diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2018-10-20 23:08:39 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2018-10-20 23:08:39 (GMT) |
commit | 03880fd134adfb470ff24cf0af43d7e45ae56530 (patch) | |
tree | f4cea4f1bce37df61bf97a6c05638d35e8eb6558 /generic | |
parent | 0a018d6ac1df162044309966c31de5f0941ebf27 (diff) | |
parent | 38f526f519657d58703e013e4415a7e4788ec33f (diff) | |
download | tk-03880fd134adfb470ff24cf0af43d7e45ae56530.zip tk-03880fd134adfb470ff24cf0af43d7e45ae56530.tar.gz tk-03880fd134adfb470ff24cf0af43d7e45ae56530.tar.bz2 |
merge trunk
Diffstat (limited to 'generic')
115 files changed, 5659 insertions, 3188 deletions
diff --git a/generic/ks_names.h b/generic/ks_names.h index 22d9fc5..9f49130 100644 --- a/generic/ks_names.h +++ b/generic/ks_names.h @@ -1,5 +1,15 @@ /* - * This file is generated from $(INCLUDESRC)/keysymdef.h. Do not edit. + * This file should be maintained in sync with xlib/X11/keysymdefs.h + * + * Note that this should be done manually only, because in some cases + * keysymdefs.h defines the same integer for multiple keysyms, e.g.: + * + * #define XK_Greek_LAMDA 0x7cb + * #define XK_Greek_LAMBDA 0x7cb + * + * #define XK_Cyrillic_DZHE 0x6bf + * #define XK_Serbian_DZE 0x6bf (deprecated) + * */ { "BackSpace", 0xFF08 }, { "Tab", 0xFF09 }, @@ -920,3 +930,10 @@ { "hebrew_shin", 0xcf9 }, { "hebrew_taf", 0xcfa }, { "Hebrew_switch", 0xFF7E }, +{ "XF86AudioLowerVolume", 0x1008FF11 }, +{ "XF86AudioMute", 0x1008FF12 }, +{ "XF86AudioRaiseVolume", 0x1008FF13 }, +{ "XF86AudioPlay", 0x1008FF14 }, +{ "XF86AudioStop", 0x1008FF15 }, +{ "XF86AudioPrev", 0x1008FF16 }, +{ "XF86AudioNext", 0x1008FF17 }, diff --git a/generic/tk.decls b/generic/tk.decls index 9ceb3af..16de241 100644 --- a/generic/tk.decls +++ b/generic/tk.decls @@ -105,7 +105,7 @@ declare 18 { 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 { @@ -146,7 +146,7 @@ declare 28 { 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 { @@ -245,7 +245,7 @@ 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) @@ -326,7 +326,7 @@ declare 75 { 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 { @@ -348,10 +348,10 @@ declare 82 { 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) } @@ -404,7 +404,7 @@ declare 97 { } 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) @@ -439,7 +439,7 @@ declare 107 { } 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, @@ -518,37 +518,37 @@ 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, @@ -561,15 +561,15 @@ declare 142 { } 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, @@ -581,13 +581,13 @@ declare 146 { 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 { @@ -744,7 +744,7 @@ 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 { @@ -774,11 +774,11 @@ declare 203 { } 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 { @@ -802,7 +802,7 @@ declare 210 { 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 { @@ -813,7 +813,7 @@ 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) @@ -943,12 +943,12 @@ declare 244 { 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, @@ -1001,22 +1001,22 @@ declare 260 { } 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) } @@ -1148,6 +1148,14 @@ 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 diff --git a/generic/tk.h b/generic/tk.h index 6abb05e..6f1c98a 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -17,17 +17,10 @@ #define _TK #include <tcl.h> -#if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION < 6) +#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 @@ -59,8 +52,8 @@ extern "C" { * 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) @@ -75,10 +68,10 @@ extern "C" { #define TK_MAJOR_VERSION 8 #define TK_MINOR_VERSION 7 #define TK_RELEASE_LEVEL TCL_ALPHA_RELEASE -#define TK_RELEASE_SERIAL 0 +#define TK_RELEASE_SERIAL 2 #define TK_VERSION "8.7" -#define TK_PATCH_LEVEL "8.7a0" +#define TK_PATCH_LEVEL "8.7a2" /* * A special definition used to allow this header file to be included from @@ -105,6 +98,10 @@ extern "C" { #ifdef BUILD_tk #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT +#else +# ifndef TCL_STORAGE_CLASS +# define TCL_STORAGE_CLASS DLLIMPORT +# endif #endif /* @@ -190,13 +187,14 @@ typedef struct Tk_OptionSpec { 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 * 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 @@ -204,6 +202,10 @@ typedef struct Tk_OptionSpec { * 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 @@ -290,7 +292,7 @@ typedef struct Tk_SavedOption { 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 @@ -306,11 +308,15 @@ typedef struct Tk_SavedOption { #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; @@ -335,8 +341,8 @@ typedef struct Tk_SavedOptions { #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 { @@ -362,19 +368,23 @@ 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 +#if TCL_MAJOR_VERSION > 8 + size_t offset; /* Where in widget record to store value; use * Tk_Offset 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 @@ -414,7 +424,9 @@ typedef enum { #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 */ @@ -423,14 +435,14 @@ typedef enum { */ 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 * depends on type. */ char *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; @@ -676,7 +688,7 @@ typedef struct { * 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 @@ -746,9 +758,10 @@ typedef XActivateDeactivateEvent XDeactivateEvent; (((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) \ @@ -814,6 +827,9 @@ typedef struct Tk_FakeWin { int minReqWidth; int minReqHeight; char *dummy20; /* geometryMaster */ +#ifdef TK_USE_INPUT_METHODS + int dummy21; +#endif /* TK_USE_INPUT_METHODS */ } Tk_FakeWin; /* @@ -915,7 +931,7 @@ typedef enum { } 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, @@ -1043,14 +1059,18 @@ typedef void (Tk_ItemDCharsProc)(Tk_Canvas canvas, Tk_Item *itemPtr, #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; @@ -1171,7 +1191,7 @@ typedef struct Tk_TSOffset { } Tk_TSOffset; /* - * Bit fields in Tk_Offset->flags: + * Bit fields in Tk_TSOffset->flags: */ #define TK_OFFSET_INDEX 1 @@ -1220,8 +1240,8 @@ 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); @@ -1245,7 +1265,7 @@ typedef int (Tk_ImagePostscriptProc) (ClientData clientData, */ 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. */ @@ -1357,7 +1377,7 @@ typedef int (Tk_ImageStringWriteProc) (Tcl_Interp *interp, Tcl_Obj *format, */ 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. */ @@ -1528,7 +1548,7 @@ 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); @@ -1556,12 +1576,13 @@ typedef int (Tk_SelectionProc) (ClientData clientData, int offset, *---------------------------------------------------------------------- * * 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 @@ -1594,6 +1615,7 @@ typedef int (Tk_SelectionProc) (ClientData clientData, int offset, # 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 diff --git a/generic/tk3d.h b/generic/tk3d.h index 891e927..f574de7 100644 --- a/generic/tk3d.h +++ b/generic/tk3d.h @@ -28,7 +28,7 @@ typedef struct TkBorder { * 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 @@ -37,7 +37,7 @@ typedef struct TkBorder { * 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). */ diff --git a/generic/tkBind.c b/generic/tkBind.c index 9cd3b7b..cc0b582 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -1260,6 +1260,16 @@ Tk_BindEvent( } } + /* + * Ignore event types which are not in flagArray and all zeroes there. + * Most notably, NoExpose events can fill the ring buffer and disturb + * (thus masking out) event sequences of interest. + */ + + if ((eventPtr->type >= TK_LASTEVENT) || !flagArray[eventPtr->type]) { + return; + } + dispPtr = ((TkWindow *) tkwin)->dispPtr; bindInfoPtr = winPtr->mainPtr->bindInfo; @@ -1728,9 +1738,10 @@ MatchPatterns( } if (psPtr->flags & PAT_NEARBY) { XEvent *firstPtr = &bindPtr->eventRing[bindPtr->curEvent]; - int timeDiff; + long timeDiff; - timeDiff = (Time) firstPtr->xkey.time - eventPtr->xkey.time; + timeDiff = ((long)firstPtr->xkey.time - + (long)eventPtr->xkey.time); if ((firstPtr->xkey.x_root < (eventPtr->xkey.x_root - NEARBY_PIXELS)) || (firstPtr->xkey.x_root @@ -1911,7 +1922,8 @@ ExpandPercents( Tcl_DString *dsPtr) /* Dynamic string in which to append new * command. */ { - int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl + size_t spaceNeeded; + int cvtFlags; /* Used to substitute string as proper Tcl * list element. */ int number, flags, length; #define NUM_SIZE 40 @@ -2493,7 +2505,7 @@ DeleteVirtualEventTable( * already defined, the new definition augments those that already exist. * * Results: - * The return value is TCL_ERROR if an error occured while creating the + * The return value is TCL_ERROR if an error occurred while creating the * virtual binding. In this case, an error message will be left in the * interp's result. If all went well then the return value is TCL_OK. * @@ -2868,7 +2880,7 @@ GetAllVirtualEvents( * Any other fields in eventPtr which are not specified by the pattern * string or the optional arguments, are set to 0. * - * The event may be handled sychronously or asynchronously, depending on + * The event may be handled synchronously or asynchronously, depending on * the value specified by the optional "-when" option. The default * setting is synchronous. * @@ -3323,9 +3335,9 @@ HandleEventGenerate( return TCL_ERROR; } if (flags & KEY_BUTTON_MOTION_CROSSING) { - event.general.xkey.time = (Time) number; + event.general.xkey.time = number; } else if (flags & PROP) { - event.general.xproperty.time = (Time) number; + event.general.xproperty.time = number; } else { goto badopt; } @@ -3456,12 +3468,23 @@ HandleEventGenerate( if ((warp != 0) && Tk_IsMapped(tkwin)) { TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display); + Tk_Window warpWindow = Tk_IdToWindow(dispPtr->display, + event.general.xmotion.window); + if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) { Tcl_DoWhenIdle(DoWarp, dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = Tk_IdToWindow(Tk_Display(mainWin), - event.general.xmotion.window); + + if (warpWindow != dispPtr->warpWindow) { + if (warpWindow) { + Tcl_Preserve(warpWindow); + } + if (dispPtr->warpWindow) { + Tcl_Release(dispPtr->warpWindow); + } + dispPtr->warpWindow = warpWindow; + } dispPtr->warpMainwin = mainWin; dispPtr->warpX = event.general.xmotion.x; dispPtr->warpY = event.general.xmotion.y; @@ -3535,8 +3558,25 @@ DoWarp( { TkDisplay *dispPtr = clientData; - TkpWarpPointer(dispPtr); - XForceScreenSaver(dispPtr->display, ScreenSaverReset); + /* + * DoWarp was scheduled only if the window was mapped. It needs to be + * still mapped at the time the present idle callback is executed. Also + * one needs to guard against window destruction in the meantime. + * Finally, the case warpWindow == NULL is special in that it means + * the whole screen. + */ + + if ((dispPtr->warpWindow == NULL) || + (Tk_IsMapped(dispPtr->warpWindow) + && (Tk_WindowId(dispPtr->warpWindow) != None))) { + TkpWarpPointer(dispPtr); + XForceScreenSaver(dispPtr->display, ScreenSaverReset); + } + + if (dispPtr->warpWindow) { + Tcl_Release(dispPtr->warpWindow); + dispPtr->warpWindow = None; + } dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } @@ -3937,7 +3977,7 @@ ParseEventDescription( p = GetField(p, field, FIELD_SIZE); } if (*field != '\0') { - if ((*field >= '1') && (*field <= '5') && (field[1] == '\0')) { + if ((*field >= '1') && (*field <= '9') && (field[1] == '\0')) { if (eventFlags == 0) { patPtr->eventType = ButtonPress; eventMask = ButtonPressMask; @@ -4278,6 +4318,33 @@ TkpGetBindingXEvent( } /* + *---------------------------------------------------------------------- + * + * TkpCancelWarp -- + * + * This function cancels an outstanding pointer warp and + * is called during tear down of the display. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpCancelWarp( + TkDisplay *dispPtr) +{ + if (dispPtr->flags & TK_DISPLAY_IN_WARP) { + Tcl_CancelIdleCall(DoWarp, dispPtr); + dispPtr->flags &= ~TK_DISPLAY_IN_WARP; + } +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 diff --git a/generic/tkBusy.c b/generic/tkBusy.c index 65248a2..8b8db66 100644 --- a/generic/tkBusy.c +++ b/generic/tkBusy.c @@ -17,16 +17,14 @@ #include "default.h" /* - * Things about the busy system that may be configured. Note that currently on - * OSX/Aqua, that's nothing at all. + * Things about the busy system that may be configured. Note that on some + * platforms this may or may not have an effect. */ static const Tk_OptionSpec busyOptionSpecs[] = { -#ifndef MAC_OSX_TK {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_BUSY_CURSOR, -1, Tk_Offset(Busy, cursor), TK_OPTION_NULL_OK, 0, 0}, -#endif {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; @@ -433,6 +431,10 @@ MakeTransparentWindowExist( TkpMakeTransparentWindowExist(tkwin, parent); + if (winPtr->window == None) { + return; /* Platform didn't make Window. */ + } + dispPtr = winPtr->dispPtr; hPtr = Tcl_CreateHashEntry(&dispPtr->winTable, (char *) winPtr->window, ¬Used); @@ -569,7 +571,7 @@ CreateBusy( busyPtr->cursor = None; 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; @@ -636,7 +638,7 @@ ConfigureBusy( { 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; } @@ -759,6 +761,9 @@ HoldBusy( } else { TkpHideBusyWindow(busyPtr); } + if (result == TCL_OK) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(busyPtr->tkBusy), -1)); + } return result; } @@ -792,11 +797,12 @@ Tk_BusyObjCmd( 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) { @@ -821,6 +827,19 @@ Tk_BusyObjCmd( 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"); @@ -831,7 +850,7 @@ Tk_BusyObjCmd( 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; @@ -852,7 +871,7 @@ Tk_BusyObjCmd( } 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) { diff --git a/generic/tkButton.c b/generic/tkButton.c index b7e314e..ddc267d 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -749,7 +749,7 @@ ButtonCreate( 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; @@ -810,7 +810,7 @@ ButtonWidgetObjCmd( 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; @@ -820,7 +820,7 @@ ButtonWidgetObjCmd( 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) { @@ -1068,7 +1068,7 @@ ConfigureButton( * 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; @@ -1611,6 +1611,19 @@ ButtonVarProc( 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. */ @@ -1692,8 +1705,8 @@ static char * ButtonTextVarProc( ClientData clientData, /* Information about button. */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Not used. */ - const char *name2, /* Not used. */ + const char *name1, /* Name of variable. */ + const char *name2, /* Second part of variable name. */ int flags) /* Information about what happened. */ { TkButton *butPtr = clientData; @@ -1704,6 +1717,19 @@ ButtonTextVarProc( } /* + * 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. */ diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c index c6470dd..609901b 100644 --- a/generic/tkCanvPs.c +++ b/generic/tkCanvPs.c @@ -491,7 +491,7 @@ TkCanvPostscriptCmd( 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", @@ -545,7 +545,7 @@ TkCanvPostscriptCmd( 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); @@ -587,7 +587,7 @@ TkCanvPostscriptCmd( 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); @@ -608,7 +608,7 @@ TkCanvPostscriptCmd( "%%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; } } @@ -825,7 +825,7 @@ Tk_PostscriptFont( fontname = Tcl_DStringValue(&ds); Tcl_AppendPrintfToObj(GetPostscriptBuffer(interp), "/%s findfont %d scalefont%s setfont\n", - fontname, TkFontGetPoints(psInfoPtr->tkwin, points), + fontname, (int)(TkFontGetPoints(psInfoPtr->tkwin, points) + 0.5), strncasecmp(fontname, "Symbol", 7) ? " ISOEncode" : ""); Tcl_CreateHashEntry(&psInfoPtr->fontTable, Tcl_DStringValue(&ds), &i); Tcl_DStringFree(&ds); diff --git a/generic/tkCanvText.c b/generic/tkCanvText.c index eb8dfe3..7c088b5 100644 --- a/generic/tkCanvText.c +++ b/generic/tkCanvText.c @@ -1006,12 +1006,13 @@ TextInsert( Tcl_Obj *obj) /* New characters to be inserted. */ { TextItem *textPtr = (TextItem *) itemPtr; - int byteIndex, byteCount, charsAdded; + int byteIndex, charsAdded; + size_t byteCount; char *newStr, *text; const char *string; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; - string = Tcl_GetStringFromObj(obj, &byteCount); + string = TkGetStringFromObj(obj, &byteCount); text = textPtr->text; @@ -1343,11 +1344,11 @@ GetTextIndex( * index. */ { TextItem *textPtr = (TextItem *) itemPtr; - int length; + size_t 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]; diff --git a/generic/tkCanvUtil.c b/generic/tkCanvUtil.c index cbbc2b4..09ce98c 100644 --- a/generic/tkCanvUtil.c +++ b/generic/tkCanvUtil.c @@ -1136,7 +1136,9 @@ Tk_ConfigOutlineGC( if (mask && (dash->number != 0)) { gcValues->line_style = LineOnOffDash; gcValues->dash_offset = outline->offset; - if (dash->number > 0) { + if ((unsigned int)ABS(dash->number) > sizeof(char *)) { + gcValues->dashes = dash->pattern.pt[0]; + } else if (dash->number != 0) { gcValues->dashes = dash->pattern.array[0]; } else { gcValues->dashes = (char) (4 * width + 0.5); @@ -1340,7 +1342,9 @@ Tk_ResetOutlineGC( if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 && (dash->pattern.array[0] != dash->pattern.array[1])) || ((dash->number == -1) && (dash->pattern.array[0] != ','))) { - if (dash->number > 0) { + if ((unsigned int)ABS(dash->number) > sizeof(char *)) { + dashList = dash->pattern.pt[0]; + } else if (dash->number != 0) { dashList = dash->pattern.array[0]; } else { dashList = (char) (4 * width + 0.5); diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c index 9c4d60a..fa7559c 100644 --- a/generic/tkCanvas.c +++ b/generic/tkCanvas.c @@ -15,9 +15,9 @@ /* #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" @@ -268,6 +268,7 @@ static int ConfigureCanvas(Tcl_Interp *interp, TkCanvas *canvasPtr, int argc, Tcl_Obj *const *argv, int flags); static void DestroyCanvas(char *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); @@ -805,6 +806,7 @@ CanvasWidgetCmd( "canvasy", "cget", "configure", "coords", "create", "dchars", "delete", "dtag", "find", "focus", "gettags", "icursor", + "image", "imove", "index", "insert", "itemcget", "itemconfigure", "lower", "move", "moveto", "postscript", @@ -817,6 +819,7 @@ CanvasWidgetCmd( 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_IMAGE, CANV_IMOVE, CANV_INDEX, CANV_INSERT, CANV_ITEMCGET, CANV_ITEMCONFIGURE, CANV_LOWER, CANV_MOVE, CANV_MOVETO, CANV_POSTSCRIPT, @@ -1186,8 +1189,8 @@ CanvasWidgetCmd( FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto doneImove) { int index; - int x1,x2,y1,y2; - int dontRedraw1,dontRedraw2; + int x1, x2, y1, y2; + int dontRedraw1, dontRedraw2; /* * The TK_MOVABLE_POINTS flag should only be set for types that @@ -1217,11 +1220,11 @@ CanvasWidgetCmd( itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; ItemDelChars(canvasPtr, itemPtr, index, index); - dontRedraw1=itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW; + dontRedraw1 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW; itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; ItemInsert(canvasPtr, itemPtr, index, tmpObj); - dontRedraw2=itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW; + dontRedraw2 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW; if (!(dontRedraw1 && dontRedraw2)) { Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, @@ -1249,8 +1252,7 @@ CanvasWidgetCmd( result = TCL_ERROR; goto done; } - arg = Tcl_GetString(objv[2]); - length = objv[2]->length; + arg = TkGetStringFromObj(objv[2], &length); c = arg[0]; /* @@ -1334,7 +1336,7 @@ CanvasWidgetCmd( } case CANV_DCHARS: { int first, last; - int x1,x2,y1,y2; + int x1, x2, y1, y2; if ((objc != 4) && (objc != 5)) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first ?last?"); @@ -1362,7 +1364,7 @@ CanvasWidgetCmd( /* * Redraw both item's old and new areas: it's possible that a * delete could result in a new area larger than the old area. - * Except if the insertProc sets the TK_ITEM_DONT_REDRAW flag, + * Except if the dCharsProc sets the TK_ITEM_DONT_REDRAW flag, * nothing more needs to be done. */ @@ -1572,7 +1574,7 @@ CanvasWidgetCmd( } case CANV_INSERT: { int beforeThis; - int x1,x2,y1,y2; + int x1, x2, y1, y2; if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId beforeThis string"); @@ -1800,7 +1802,8 @@ CanvasWidgetCmd( } case CANV_RCHARS: { int first, last; - int x1,x2,y1,y2; + int x1, x2, y1, y2; + int dontRedraw1, dontRedraw2; if (objc != 6) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first last string"); @@ -1831,12 +1834,16 @@ CanvasWidgetCmd( x1 = itemPtr->x1; y1 = itemPtr->y1; x2 = itemPtr->x2; y2 = itemPtr->y2; - itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; + itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; ItemDelChars(canvasPtr, itemPtr, first, last); + dontRedraw1 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW; + + itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; ItemInsert(canvasPtr, itemPtr, first, objv[5]); + dontRedraw2 = itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW; - if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) { + if (!(dontRedraw1 && dontRedraw2)) { Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, x1, y1, x2, y2); EventuallyRedrawItem(canvasPtr, itemPtr); @@ -2126,6 +2133,46 @@ CanvasWidgetCmd( 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: @@ -2414,6 +2461,500 @@ CanvasWorldChanged( /* *---------------------------------------------------------------------- * + * 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 -- * * This function redraws the contents of a canvas window. It is invoked diff --git a/generic/tkClipboard.c b/generic/tkClipboard.c index b902625..aa6bb93 100644 --- a/generic/tkClipboard.c +++ b/generic/tkClipboard.c @@ -449,10 +449,11 @@ Tk_ClipboardObjCmd( "-displayof", "-format", "-type", NULL }; enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE }; - int subIndex, length; + int subIndex; + size_t length; for (i = 2; i < objc - 1; i++) { - string = Tcl_GetStringFromObj(objv[i], &length); + string = TkGetStringFromObj(objv[i], &length); if (string[0] != '-') { break; } diff --git a/generic/tkCmds.c b/generic/tkCmds.c index 6196b17..81bb335 100644 --- a/generic/tkCmds.c +++ b/generic/tkCmds.c @@ -101,6 +101,7 @@ Tk_BellObjCmd( enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE }; Tk_Window tkwin = clientData; int i, index, nice = 0; + Tk_ErrorHandler handler; if (objc > 4) { wrongArgs: @@ -128,11 +129,13 @@ Tk_BellObjCmd( break; } } + handler = Tk_CreateErrorHandler(Tk_Display(tkwin), -1, -1, -1, NULL, NULL); XBell(Tk_Display(tkwin), 0); if (!nice) { XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset); } XFlush(Tk_Display(tkwin)); + Tk_DeleteErrorHandler(handler); return TCL_OK; } @@ -2068,14 +2071,14 @@ TkGetDisplayOf( * present. */ { const char *string; - int length; + size_t 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)); diff --git a/generic/tkColor.c b/generic/tkColor.c index 9abb448..9d5e157 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -480,8 +480,7 @@ Tk_FreeColor( Tcl_Panic("Tk_FreeColor called with bogus color"); } - tkColPtr->resourceRefCount--; - if (tkColPtr->resourceRefCount > 0) { + if (tkColPtr->resourceRefCount-- > 1) { return; } @@ -587,8 +586,7 @@ FreeColorObj( TkColor *tkColPtr = objPtr->internalRep.twoPtrValue.ptr1; if (tkColPtr != NULL) { - tkColPtr->objRefCount--; - if ((tkColPtr->objRefCount == 0) + if ((tkColPtr->objRefCount-- <= 1) && (tkColPtr->resourceRefCount == 0)) { ckfree(tkColPtr); } @@ -820,9 +818,9 @@ TkDebugColor( 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); } } diff --git a/generic/tkColor.h b/generic/tkColor.h index 05ef295..d5bde9d 100644 --- a/generic/tkColor.h +++ b/generic/tkColor.h @@ -38,7 +38,7 @@ typedef struct TkColor { 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 @@ -48,7 +48,7 @@ typedef struct TkColor { * 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 diff --git a/generic/tkConfig.c b/generic/tkConfig.c index 9c159e6..46300d3 100644 --- a/generic/tkConfig.c +++ b/generic/tkConfig.c @@ -91,7 +91,7 @@ typedef struct TkOption { */ 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 @@ -103,7 +103,7 @@ typedef struct OptionTable { * 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 @@ -115,14 +115,14 @@ typedef struct OptionTable { * 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, @@ -177,7 +177,7 @@ Tk_CreateOptionTable( OptionTable *tablePtr; const Tk_OptionSpec *specPtr, *specPtr2; Option *optionPtr; - int numOptions, i; + size_t numOptions, i; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -279,7 +279,7 @@ Tk_CreateOptionTable( } } 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) @@ -330,10 +330,9 @@ Tk_DeleteOptionTable( { OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; - int count; + size_t count; - tablePtr->refCount--; - if (tablePtr->refCount > 0) { + if (tablePtr->refCount-- > 1) { return; } @@ -382,7 +381,7 @@ 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. */ @@ -553,7 +552,7 @@ 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. */ @@ -569,10 +568,10 @@ DoObjConfig( * 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 @@ -585,8 +584,8 @@ DoObjConfig( */ 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; @@ -598,8 +597,8 @@ DoObjConfig( * 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; } @@ -657,14 +656,14 @@ DoObjConfig( case TK_OPTION_STRING: { char *newStr; const char *value; - int length; + size_t 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 { @@ -937,16 +936,13 @@ static int ObjectIsEmpty( Tcl_Obj *objPtr) /* Object to test. May be NULL. */ { - int length; - if (objPtr == NULL) { return 1; } - if (objPtr->bytes != NULL) { - return (objPtr->length == 0); + if (objPtr->bytes == NULL) { + Tcl_GetString(objPtr); } - (void)Tcl_GetStringFromObj(objPtr, &length); - return (length == 0); + return (objPtr->length == 0); } /* @@ -978,7 +974,7 @@ GetOption( 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 @@ -1226,7 +1222,7 @@ 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. */ @@ -1344,12 +1340,12 @@ 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; @@ -1364,7 +1360,7 @@ Tk_RestoreSavedOptions( 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; @@ -1373,13 +1369,13 @@ Tk_RestoreSavedOptions( * 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; } @@ -1394,11 +1390,11 @@ Tk_RestoreSavedOptions( * 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); @@ -1491,7 +1487,7 @@ 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) { @@ -1531,7 +1527,7 @@ Tk_FreeSavedOptions( /* 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 @@ -1539,9 +1535,9 @@ Tk_FreeConfigOptions( { 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; @@ -1552,15 +1548,15 @@ Tk_FreeConfigOptions( 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; } @@ -1597,10 +1593,10 @@ 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; @@ -1611,7 +1607,7 @@ FreeResources( * 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) { @@ -1643,8 +1639,6 @@ FreeResources( if (internalFormExists) { Tk_FreeStyle(*((Tk_Style *) internalPtr)); *((Tk_Style *) internalPtr) = NULL; - } else if (objPtr != NULL) { - Tk_FreeStyleFromObj(objPtr); } break; case TK_OPTION_BITMAP: @@ -1719,7 +1713,7 @@ 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 @@ -1733,7 +1727,7 @@ Tk_GetOptionInfo( 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 @@ -1787,7 +1781,7 @@ Tk_GetOptionInfo( 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. */ @@ -1830,8 +1824,8 @@ GetConfigList( } 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(); @@ -1865,7 +1859,7 @@ GetConfigList( 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 @@ -1873,10 +1867,10 @@ GetObjectForOption( 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: @@ -2007,7 +2001,7 @@ 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 @@ -2025,8 +2019,8 @@ Tk_GetOptionValue( 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 @@ -2096,9 +2090,9 @@ TkDebugConfig( 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)); } diff --git a/generic/tkConsole.c b/generic/tkConsole.c index 8bfbe9b..7a74344 100644 --- a/generic/tkConsole.c +++ b/generic/tkConsole.c @@ -24,7 +24,7 @@ typedef struct ConsoleInfo { Tcl_Interp *consoleInterp; /* Interpreter displaying the console. */ Tcl_Interp *interp; /* Interpreter controlled by console. */ - int refCount; + size_t refCount; } ConsoleInfo; /* @@ -223,7 +223,7 @@ Tk_InitConsoleChannels( * 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; } @@ -318,7 +318,7 @@ Tk_InitConsoleChannels( * Tk_CreateConsoleWindow -- * * Initialize the console. This code actually creates a new application - * and associated interpreter. This effectivly hides the implementation + * and associated interpreter. This effectively hides the implementation * from the main application. * * Results: @@ -344,9 +344,13 @@ Tk_CreateConsoleWindow( /* Init an interp with Tcl and Tk */ Tcl_Interp *consoleInterp = Tcl_CreateInterp(); if (Tcl_Init(consoleInterp) != TCL_OK) { + Tcl_Obj *result_obj = Tcl_GetObjResult(consoleInterp); + Tcl_SetObjResult(interp, result_obj); goto error; } if (Tk_Init(consoleInterp) != TCL_OK) { + Tcl_Obj *result_obj = Tcl_GetObjResult(consoleInterp); + Tcl_SetObjResult(interp, result_obj); goto error; } @@ -452,7 +456,7 @@ Tk_CreateConsoleWindow( if (mainWindow) { Tk_DeleteEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc, info); - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } @@ -592,7 +596,7 @@ ConsoleClose( ConsoleInfo *info = data->info; if (info) { - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { /* * Assuming the Tcl_Interp * fields must already be NULL. */ @@ -881,7 +885,7 @@ InterpDeleteProc( Tcl_DeleteThreadExitHandler(DeleteConsoleInterp, info->consoleInterp); info->consoleInterp = NULL; } - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } @@ -912,7 +916,7 @@ ConsoleDeleteProc( if (info->consoleInterp) { Tcl_DeleteInterp(info->consoleInterp); } - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } @@ -949,7 +953,7 @@ ConsoleEventProc( Tcl_EvalEx(consoleInterp, "tk::ConsoleExit", -1, TCL_EVAL_GLOBAL); } - if (--info->refCount <= 0) { + if (info->refCount-- <= 1) { ckfree(info); } } diff --git a/generic/tkCursor.c b/generic/tkCursor.c index 6b2d5f4..e337b37 100644 --- a/generic/tkCursor.c +++ b/generic/tkCursor.c @@ -463,8 +463,7 @@ FreeCursor( { TkCursor *prevPtr; - cursorPtr->resourceRefCount--; - if (cursorPtr->resourceRefCount > 0) { + if (cursorPtr->resourceRefCount-- > 1) { return; } @@ -590,8 +589,7 @@ FreeCursorObj( TkCursor *cursorPtr = objPtr->internalRep.twoPtrValue.ptr1; if (cursorPtr != NULL) { - cursorPtr->objRefCount--; - if ((cursorPtr->objRefCount == 0) + if ((cursorPtr->objRefCount-- <= 1) && (cursorPtr->resourceRefCount == 0)) { ckfree(cursorPtr); } @@ -864,9 +862,9 @@ TkDebugCursor( 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); } } diff --git a/generic/tkDecls.h b/generic/tkDecls.h index 64c32cd..eb3af95 100644 --- a/generic/tkDecls.h +++ b/generic/tkDecls.h @@ -17,6 +17,14 @@ #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 @@ -95,7 +103,7 @@ 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 */ @@ -133,7 +141,7 @@ EXTERN int Tk_ConfigureValue(Tcl_Interp *interp, /* 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, @@ -215,7 +223,7 @@ EXTERN void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection, /* 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); @@ -281,7 +289,8 @@ 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 */ @@ -298,9 +307,9 @@ EXTERN void Tk_GetAllBindings(Tcl_Interp *interp, 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 */ @@ -348,7 +357,7 @@ EXTERN Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin, /* 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 */ @@ -376,7 +385,7 @@ 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, @@ -438,28 +447,27 @@ 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); @@ -468,14 +476,16 @@ 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, @@ -486,13 +496,15 @@ EXTERN int Tk_PhotoGetImage(Tk_PhotoHandle handle, /* 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); @@ -620,7 +632,7 @@ EXTERN void Tk_FreeBitmapFromObj(Tk_Window tkwin, /* 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); @@ -642,12 +654,12 @@ 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, @@ -667,7 +679,7 @@ 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, @@ -676,7 +688,7 @@ EXTERN void Tk_MainEx(int argc, char **argv, /* 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); @@ -776,11 +788,13 @@ EXTERN void Tk_SetMinimumRequestSize(Tk_Window tkwin, 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); @@ -818,22 +832,22 @@ 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 */ @@ -895,7 +909,7 @@ typedef struct TkStubs { 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 */ @@ -905,7 +919,7 @@ typedef struct TkStubs { 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 */ @@ -931,7 +945,7 @@ typedef struct TkStubs { 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 */ @@ -953,14 +967,14 @@ typedef struct TkStubs { 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 */ @@ -974,7 +988,7 @@ typedef struct TkStubs { 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 */ @@ -984,7 +998,7 @@ typedef struct TkStubs { 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 */ @@ -1006,27 +1020,27 @@ typedef struct TkStubs { 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 */ @@ -1071,7 +1085,7 @@ typedef struct TkStubs { 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 */ @@ -1080,17 +1094,17 @@ typedef struct TkStubs { 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 */ + int (*tk_InitOptions) (Tcl_Interp *interp, void *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */ 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 */ @@ -1122,8 +1136,8 @@ typedef struct TkStubs { 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 */ @@ -1137,10 +1151,10 @@ typedef struct TkStubs { 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 */ @@ -1721,12 +1735,30 @@ extern const TkStubs *tkStubsPtr; #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 diff --git a/generic/tkEntry.c b/generic/tkEntry.c index ea8d7f1..8a69010 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.c @@ -16,8 +16,8 @@ */ #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 @@ -118,6 +118,12 @@ static const Tk_OptionSpec entryOptSpec[] = { NULL, 0, -1, 0, "-invalidcommand", 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0}, + {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder", + DEF_ENTRY_PLACEHOLDER, -1, Tk_Offset(Entry, placeholderString), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground", + "PlaceholderForeground", DEF_ENTRY_PLACEHOLDERFG, -1, + Tk_Offset(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, @@ -258,6 +264,12 @@ static const Tk_OptionSpec sbOptSpec[] = { NULL, 0, -1, 0, "-invalidcommand", 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0}, + {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder", + DEF_ENTRY_PLACEHOLDER, -1, Tk_Offset(Entry, placeholderString), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-placeholderforeground", "placeholderForeground", + "PlaceholderForeground", DEF_ENTRY_PLACEHOLDERFG, -1, + Tk_Offset(Entry, placeholderColorPtr), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground", @@ -537,6 +549,8 @@ Tk_EntryObjCmd( entryPtr->avgWidth = 1; entryPtr->validate = VALIDATE_NONE; + entryPtr->placeholderGC = None; + /* * Keep a hold of the associated tkwin until we destroy the entry, * otherwise Tk might free it while we still need it. @@ -552,7 +566,7 @@ Tk_EntryObjCmd( 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); @@ -640,7 +654,7 @@ EntryWidgetObjCmd( goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, + objPtr = Tk_GetOptionValue(interp, entryPtr, entryPtr->optionTable, objv[2], entryPtr->tkwin); if (objPtr == NULL) { goto error; @@ -650,7 +664,7 @@ EntryWidgetObjCmd( 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); @@ -887,7 +901,8 @@ EntryWidgetObjCmd( entryPtr->selectLast = index2; } if (!(entryPtr->flags & GOT_SELECTION) - && (entryPtr->exportSelection)) { + && (entryPtr->exportSelection) + && (!Tcl_IsSafe(entryPtr->interp))) { Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection, entryPtr); entryPtr->flags |= GOT_SELECTION; @@ -1122,7 +1137,7 @@ ConfigureEntry( * value. */ - oldExport = entryPtr->exportSelection; + oldExport = (entryPtr->exportSelection) && (!Tcl_IsSafe(entryPtr->interp)); if (entryPtr->type == TK_SPINBOX) { oldValues = sbPtr->valueStr; oldFormat = sbPtr->reqFormat; @@ -1136,7 +1151,7 @@ ConfigureEntry( * 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; @@ -1176,13 +1191,15 @@ ConfigureEntry( 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)) { /* @@ -1276,6 +1293,7 @@ ConfigureEntry( */ if (entryPtr->exportSelection && (!oldExport) + && (!Tcl_IsSafe(entryPtr->interp)) && (entryPtr->selectFirst != -1) && !(entryPtr->flags & GOT_SELECTION)) { Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection, @@ -1485,8 +1503,20 @@ EntryWorldChanged( } 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 != None) { + 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; @@ -1734,9 +1764,15 @@ DisplayEntry( * 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) @@ -1924,8 +1960,8 @@ EntryComputeGeometry( */ if (entryPtr->showChar != NULL) { - Tcl_UniChar ch; - char buf[TCL_UTF_MAX]; + int ch; + char buf[6]; int size; /* @@ -1935,19 +1971,72 @@ EntryComputeGeometry( * resulting string. */ - Tcl_UtfToUniChar(entryPtr->showChar, &ch); - size = Tcl_UniCharToUtf(ch, buf); + TkUtfToUniChar(entryPtr->showChar, &ch); + size = TkUniCharToUtf(ch, buf); entryPtr->numDisplayBytes = entryPtr->numChars * size; p = ckalloc(entryPtr->numDisplayBytes + 1); entryPtr->displayString = p; for (i = entryPtr->numChars; --i >= 0; ) { - p += Tcl_UniCharToUtf(ch, p); + 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, @@ -2043,9 +2132,7 @@ InsertChars( 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; @@ -2744,7 +2831,8 @@ EntrySelectTo( * Grab the selection if we don't own it already. */ - if (!(entryPtr->flags & GOT_SELECTION) && (entryPtr->exportSelection)) { + if (!(entryPtr->flags & GOT_SELECTION) && (entryPtr->exportSelection) + && (!Tcl_IsSafe(entryPtr->interp))) { Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection, entryPtr); entryPtr->flags |= GOT_SELECTION; @@ -2811,7 +2899,8 @@ EntryFetchSelection( const char *string; const char *selStart, *selEnd; - if ((entryPtr->selectFirst < 0) || !(entryPtr->exportSelection)) { + if ((entryPtr->selectFirst < 0) || (!entryPtr->exportSelection) + || Tcl_IsSafe(entryPtr->interp)) { return -1; } string = entryPtr->displayString; @@ -2864,7 +2953,8 @@ EntryLostSelection( */ if (TkpAlwaysShowSelection(entryPtr->tkwin) - && (entryPtr->selectFirst >= 0) && entryPtr->exportSelection) { + && (entryPtr->selectFirst >= 0) && entryPtr->exportSelection + && (!Tcl_IsSafe(entryPtr->interp))) { entryPtr->selectFirst = -1; entryPtr->selectLast = -1; EventuallyRedraw(entryPtr); @@ -3129,8 +3219,8 @@ static char * EntryTextVarProc( ClientData clientData, /* Information about button. */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Not used. */ - const char *name2, /* Not used. */ + const char *name1, /* Name of variable. */ + const char *name2, /* Second part of variable name. */ int flags) /* Information about what happened. */ { Entry *entryPtr = clientData; @@ -3144,6 +3234,19 @@ EntryTextVarProc( } /* + * 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. */ @@ -3245,7 +3348,7 @@ EntryValidate( * * 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 @@ -3302,7 +3405,7 @@ EntryValidateChange( /* * 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. */ @@ -3411,7 +3514,7 @@ ExpandPercents( * list element. */ int number, length; register const char *string; - Tcl_UniChar ch; + int ch; char numStorage[2*TCL_INTEGER_SPACE]; while (1) { @@ -3444,7 +3547,7 @@ ExpandPercents( before++; /* skip over % */ if (*before != '\0') { - before += Tcl_UtfToUniChar(before, &ch); + before += TkUtfToUniChar(before, &ch); } else { ch = '%'; } @@ -3464,7 +3567,7 @@ ExpandPercents( string = Tk_PathName(entryPtr->tkwin); break; default: - length = Tcl_UniCharToUtf(ch, numStorage); + length = TkUniCharToUtf(ch, numStorage); numStorage[length] = '\0'; string = numStorage; break; @@ -3524,7 +3627,7 @@ ExpandPercents( string = Tk_PathName(entryPtr->tkwin); break; default: - length = Tcl_UniCharToUtf(ch, numStorage); + length = TkUniCharToUtf(ch, numStorage); numStorage[length] = '\0'; string = numStorage; break; @@ -3639,6 +3742,8 @@ Tk_SpinboxObjCmd( sbPtr->bdRelief = TK_RELIEF_FLAT; sbPtr->buRelief = TK_RELIEF_FLAT; + entryPtr->placeholderGC = None; + /* * Keep a hold of the associated tkwin until we destroy the spinbox, * otherwise Tk might free it while we still need it. @@ -3654,7 +3759,7 @@ Tk_SpinboxObjCmd( 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; @@ -3749,7 +3854,7 @@ SpinboxWidgetObjCmd( goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, + objPtr = Tk_GetOptionValue(interp, entryPtr, entryPtr->optionTable, objv[2], entryPtr->tkwin); if (objPtr == NULL) { goto error; @@ -3759,7 +3864,7 @@ SpinboxWidgetObjCmd( 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) { @@ -4033,7 +4138,8 @@ SpinboxWidgetObjCmd( entryPtr->selectLast = index2; } if (!(entryPtr->flags & GOT_SELECTION) - && entryPtr->exportSelection) { + && entryPtr->exportSelection + && (!Tcl_IsSafe(entryPtr->interp))) { Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection, entryPtr); entryPtr->flags |= GOT_SELECTION; @@ -4278,16 +4384,17 @@ SpinboxInvoke( * there. If not, move to the first element of the list. */ - int i, listc, elemLen, length = entryPtr->numChars; + int i, listc; + size_t 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; } diff --git a/generic/tkEntry.h b/generic/tkEntry.h index 52535c8..e74b52b 100644 --- a/generic/tkEntry.h +++ b/generic/tkEntry.h @@ -129,6 +129,19 @@ typedef struct { * 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. */ @@ -221,7 +234,7 @@ typedef struct { * value that the users requests. Malloc'ed */ char *valueFormat; /* Sprintf conversion specifier used for the * value. */ - char digitFormat[10]; /* Sprintf conversion specifier computed from + char digitFormat[16]; /* Sprintf conversion specifier computed from * digits and other information; used for the * value. */ diff --git a/generic/tkError.c b/generic/tkError.c index fc223e6..5aa6d88 100644 --- a/generic/tkError.c +++ b/generic/tkError.c @@ -82,8 +82,8 @@ Tk_CreateErrorHandler( * errors. */ ClientData clientData) /* Arbitrary value to pass to errorProc. */ { - register TkErrorHandler *errorPtr; - register TkDisplay *dispPtr; + TkErrorHandler *errorPtr; + TkDisplay *dispPtr; /* * Find the display. If Tk doesn't know about this display then it's an @@ -147,8 +147,8 @@ Tk_DeleteErrorHandler( Tk_ErrorHandler handler) /* Token for handler to delete; was previous * return value from Tk_CreateErrorHandler. */ { - register TkErrorHandler *errorPtr = (TkErrorHandler *) handler; - register TkDisplay *dispPtr = errorPtr->dispPtr; + TkErrorHandler *errorPtr = (TkErrorHandler *) handler; + TkDisplay *dispPtr = errorPtr->dispPtr; errorPtr->lastRequest = NextRequest(dispPtr->display) - 1; @@ -164,19 +164,26 @@ Tk_DeleteErrorHandler( * there are many handlers that stay around forever). */ - dispPtr->deleteCount += 1; - if (dispPtr->deleteCount >= 10) { - register TkErrorHandler *prevPtr; + if (dispPtr->deleteCount++ >= 9) { + TkErrorHandler *prevPtr; TkErrorHandler *nextPtr; - int lastSerial; + 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 > lastSerial) { + XSync(dispPtr->display, False); + } dispPtr->deleteCount = 0; - lastSerial = LastKnownRequestProcessed(dispPtr->display); 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 { @@ -213,11 +220,11 @@ Tk_DeleteErrorHandler( static int ErrorProc( Display *display, /* Display for which error occurred. */ - register XErrorEvent *errEventPtr) + XErrorEvent *errEventPtr) /* Information about error. */ { - register TkDisplay *dispPtr; - register TkErrorHandler *errorPtr; + TkDisplay *dispPtr; + TkErrorHandler *errorPtr; /* * See if we know anything about the display. If not, then invoke the diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 95aeda1..d058e7c 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -356,6 +356,7 @@ CreateXIC( /* XCreateIC failed. */ return; } + winPtr->ximGeneration = dispPtr->ximGeneration; /* * Adjust the window's event mask if the IM requires it. @@ -1288,6 +1289,14 @@ Tk_HandleEvent( */ #ifdef TK_USE_INPUT_METHODS + /* + * If the XIC has been invalidated, it must be recreated. + */ + if (winPtr->dispPtr->ximGeneration != winPtr->ximGeneration) { + winPtr->flags &= ~TK_CHECKED_IC; + winPtr->inputContext = NULL; + } + if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)) { if (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) { winPtr->flags |= TK_CHECKED_IC; @@ -1295,7 +1304,9 @@ Tk_HandleEvent( CreateXIC(winPtr); } } - if (eventPtr->type == FocusIn && winPtr->inputContext != NULL) { + if ((eventPtr->type == FocusIn) && + (winPtr->dispPtr->inputMethod != NULL) && + (winPtr->inputContext != NULL)) { XSetICFocus(winPtr->inputContext); } } diff --git a/generic/tkFont.c b/generic/tkFont.c index 102fc6e..c0ff7d0 100644 --- a/generic/tkFont.c +++ b/generic/tkFont.c @@ -41,7 +41,7 @@ typedef struct TkFontInfo { */ 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. */ @@ -351,7 +351,7 @@ const Tcl_ObjType tkFontObjType = { FreeFontObjProc, /* freeIntRepProc */ DupFontObjProc, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetFontFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* @@ -497,7 +497,7 @@ Tk_FontObjCmd( const char *s; Tk_Font tkfont; Tcl_Obj *optPtr, *charPtr, *resultPtr; - Tcl_UniChar uniChar = 0; + int uniChar = 0; const TkFontAttributes *faPtr; TkFontAttributes fa; @@ -562,17 +562,19 @@ Tk_FontObjCmd( */ if (charPtr != NULL) { - if (Tcl_GetCharLength(charPtr) != 1) { + const char *string = Tcl_GetString(charPtr); + size_t len = TkUtfToUniChar(string, &uniChar); + + if (len != (size_t)charPtr->length) { resultPtr = Tcl_NewStringObj( "expected a single character but got \"", -1); - Tcl_AppendLimitedToObj(resultPtr, Tcl_GetString(charPtr), + Tcl_AppendLimitedToObj(resultPtr, string, -1, 40, "..."); Tcl_AppendToObj(resultPtr, "\"", -1); Tcl_SetObjResult(interp, resultPtr); Tcl_SetErrorCode(interp, "TK", "VALUE", "FONT_SAMPLE", NULL); return TCL_ERROR; } - uniChar = Tcl_GetUniChar(charPtr, 0); } /* @@ -710,7 +712,8 @@ Tk_FontObjCmd( case FONT_MEASURE: { const char *string; Tk_Font tkfont; - int length = 0, skip = 0; + size_t length = 0; + int skip = 0; if (objc > 4) { skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); @@ -727,7 +730,7 @@ Tk_FontObjCmd( if (tkfont == NULL) { return TCL_ERROR; } - string = Tcl_GetStringFromObj(objv[3 + skip], &length); + string = TkGetStringFromObj(objv[3 + skip], &length); Tcl_SetObjResult(interp, Tcl_NewIntObj( Tk_TextWidth(tkfont, string, length))); Tk_FreeFont(tkfont); @@ -1226,7 +1229,7 @@ Tk_AllocFontFromObj( descent = fontPtr->fm.descent; fontPtr->underlinePos = descent / 2; - fontPtr->underlineHeight = TkFontGetPixels(tkwin, fontPtr->fa.size) / 10; + fontPtr->underlineHeight = (int) (TkFontGetPixels(tkwin, fontPtr->fa.size) / 10 + 0.5); if (fontPtr->underlineHeight == 0) { fontPtr->underlineHeight = 1; } @@ -1421,8 +1424,7 @@ Tk_FreeFont( if (fontPtr == NULL) { return; } - fontPtr->resourceRefCount--; - if (fontPtr->resourceRefCount > 0) { + if (fontPtr->resourceRefCount-- > 1) { return; } if (fontPtr->namedHashPtr != NULL) { @@ -1432,8 +1434,7 @@ Tk_FreeFont( */ 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,8 +1521,7 @@ FreeFontObj( 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; @@ -1694,7 +1694,7 @@ Tk_PostscriptFontName( } else if (strcasecmp(family, "ZapfDingbats") == 0) { family = "ZapfDingbats"; } else { - Tcl_UniChar ch; + int ch; /* * Inline, capitalize the first letter of each word, lowercase the @@ -1712,14 +1712,14 @@ Tk_PostscriptFontName( src++; upper = 1; } - src += Tcl_UtfToUniChar(src, &ch); + src += TkUtfToUniChar(src, &ch); if (upper) { ch = Tcl_UniCharToUpper(ch); upper = 0; } else { ch = Tcl_UniCharToLower(ch); } - dest += Tcl_UniCharToUtf(ch, dest); + dest += TkUniCharToUtf(ch, dest); } *dest = '\0'; Tcl_DStringSetLength(dsPtr, dest - Tcl_DStringValue(dsPtr)); @@ -1794,7 +1794,7 @@ Tk_PostscriptFontName( } } - return fontPtr->fa.size; + return (int)(fontPtr->fa.size + 0.5); } /* @@ -3145,14 +3145,13 @@ TkIntersectAngledTextLayout( cy[0] = cy[1] = chunkPtr->y - fontPtr->fm.ascent; cx[1] = cx[2] = chunkPtr->x + chunkPtr->displayWidth; cy[2] = cy[3] = chunkPtr->y + fontPtr->fm.descent; - if ( !PointInQuadrilateral(cx, cy, rx[0], ry[0]) || - !PointInQuadrilateral(cx, cy, rx[1], ry[1]) || - !PointInQuadrilateral(cx, cy, rx[2], ry[2]) || - !PointInQuadrilateral(cx, cy, rx[3], ry[3])) { - goto notReverseInside; - } + if ( PointInQuadrilateral(cx, cy, rx[0], ry[0]) && + PointInQuadrilateral(cx, cy, rx[1], ry[1]) && + PointInQuadrilateral(cx, cy, rx[2], ry[2]) && + PointInQuadrilateral(cx, cy, rx[3], ry[3])) { + return 0; + } } - return 0; /* * If we're overlapping now, we must be partially in and out of at least @@ -3160,7 +3159,6 @@ TkIntersectAngledTextLayout( * rectangle that is touching or crossing a line segment of a chunk. */ - notReverseInside: chunkPtr = layoutPtr->chunks; for (i=0 ; i<layoutPtr->numChunks ; i++,chunkPtr++) { @@ -3246,10 +3244,11 @@ Tk_TextLayoutToPostscript( LayoutChunk *chunkPtr = layoutPtr->chunks; int baseline = chunkPtr->y; Tcl_Obj *psObj = Tcl_NewObj(); - int i, j, len; + int i, j; + size_t len; const char *p, *glyphname; char uindex[5], c, *ps; - Tcl_UniChar ch; + int ch; Tcl_AppendToObj(psObj, "[(", -1); for (i = 0; i < layoutPtr->numChunks; i++, chunkPtr++) { @@ -3272,7 +3271,7 @@ Tk_TextLayoutToPostscript( * international postscript fonts. */ - p += Tcl_UtfToUniChar(p, &ch); + p += TkUtfToUniChar(p, &ch); if ((ch == '(') || (ch == ')') || (ch == '\\') || (ch < 0x20)) { /* * Tricky point: the "03" is necessary in the sprintf below, @@ -3298,10 +3297,13 @@ Tk_TextLayoutToPostscript( * use the full glyph name. */ + if (ch > 0xffff) { + 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! @@ -3318,6 +3320,7 @@ Tk_TextLayoutToPostscript( * No known mapping for the character into the space of * PostScript glyphs. Ignore it. :-( */ +noMapping: ; #ifdef TK_DEBUG_POSTSCRIPT_OUTPUT fprintf(stderr, "Warning: no mapping to PostScript " @@ -3399,7 +3402,7 @@ ConfigAttributesObj( if (Tcl_GetIntFromObj(interp, valuePtr, &n) != TCL_OK) { return TCL_ERROR; } - faPtr->size = n; + faPtr->size = (double)n; break; case FONT_WEIGHT: n = TkFindStateNumObj(interp, optionPtr, weightMap, valuePtr); @@ -3490,7 +3493,11 @@ GetAttributeInfoObj( break; case FONT_SIZE: - valuePtr = Tcl_NewIntObj(faPtr->size); + if (faPtr->size >= 0.0) { + valuePtr = Tcl_NewIntObj((int)(faPtr->size + 0.5)); + } else { + valuePtr = Tcl_NewIntObj(-(int)(-faPtr->size + 0.5)); + } break; case FONT_WEIGHT: @@ -3639,7 +3646,7 @@ ParseFontNameObj( if (Tcl_GetIntFromObj(interp, objv[1], &n) != TCL_OK) { return TCL_ERROR; } - faPtr->size = n; + faPtr->size = (double)n; } i = 2; @@ -3883,7 +3890,7 @@ TkFontParseXLFD( * historical compatibility. */ - faPtr->size = 12; + faPtr->size = 12.0; if (FieldSpecified(field[XLFD_POINT_SIZE])) { if (field[XLFD_POINT_SIZE][0] == '[') { @@ -3897,10 +3904,10 @@ TkFontParseXLFD( * the purpose of, so I ignore them. */ - faPtr->size = atoi(field[XLFD_POINT_SIZE] + 1); + faPtr->size = atof(field[XLFD_POINT_SIZE] + 1); } else if (Tcl_GetInt(NULL, field[XLFD_POINT_SIZE], - &faPtr->size) == TCL_OK) { - faPtr->size /= 10; + &i) == TCL_OK) { + faPtr->size = i/10.0; } else { return TCL_ERROR; } @@ -3922,9 +3929,11 @@ TkFontParseXLFD( * ignore them. */ - faPtr->size = atoi(field[XLFD_PIXEL_SIZE] + 1); + faPtr->size = atof(field[XLFD_PIXEL_SIZE] + 1); } else if (Tcl_GetInt(NULL, field[XLFD_PIXEL_SIZE], - &faPtr->size) != TCL_OK) { + &i) == TCL_OK) { + faPtr->size = (double)i; + } else { return TCL_ERROR; } } @@ -4000,21 +4009,21 @@ FieldSpecified( *--------------------------------------------------------------------------- */ -int +double TkFontGetPixels( Tk_Window tkwin, /* For point->pixel conversion factor. */ - int size) /* Font size. */ + double size) /* Font size. */ { double d; - if (size < 0) { + if (size <= 0.0) { return -size; } d = size * 25.4 / 72.0; d *= WidthOfScreen(Tk_Screen(tkwin)); d /= WidthMMOfScreen(Tk_Screen(tkwin)); - return (int) (d + 0.5); + return d; } /* @@ -4034,21 +4043,21 @@ TkFontGetPixels( *--------------------------------------------------------------------------- */ -int +double TkFontGetPoints( Tk_Window tkwin, /* For pixel->point conversion factor. */ - int size) /* Font size. */ + double size) /* Font size. */ { double d; - if (size >= 0) { + if (size >= 0.0) { return size; } d = -size * 72.0 / 25.4; d *= WidthMMOfScreen(Tk_Screen(tkwin)); d /= WidthOfScreen(Tk_Screen(tkwin)); - return (int) (d + 0.5); + return d; } /* @@ -4195,9 +4204,9 @@ TkDebugFont( 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); } } diff --git a/generic/tkFont.h b/generic/tkFont.h index b8de885..50f79d2 100644 --- a/generic/tkFont.h +++ b/generic/tkFont.h @@ -23,7 +23,7 @@ struct TkFontAttributes { Tk_Uid family; /* Font family, or NULL to represent plaform- * specific default system font. */ - int size; /* Pointsize of font, 0 for default size, or + double size; /* Pointsize of font, 0.0 for default size, or * negative number meaning pixel size. */ int weight; /* Weight flag; see below for def'n. */ int slant; /* Slant flag; see below for def'n. */ @@ -85,7 +85,7 @@ 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 @@ -95,7 +95,7 @@ typedef struct TkFont { * 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. */ @@ -198,8 +198,8 @@ MODULE_SCOPE int TkFontParseXLFD(const char *string, TkFontAttributes *faPtr, TkXLFDAttributes *xaPtr); MODULE_SCOPE const char *const * TkFontGetAliasList(const char *faceName); MODULE_SCOPE const char *const *const * TkFontGetFallbacks(void); -MODULE_SCOPE int TkFontGetPixels(Tk_Window tkwin, int size); -MODULE_SCOPE int TkFontGetPoints(Tk_Window tkwin, int size); +MODULE_SCOPE double TkFontGetPixels(Tk_Window tkwin, double size); +MODULE_SCOPE double TkFontGetPoints(Tk_Window tkwin, double size); MODULE_SCOPE const char *const * TkFontGetGlobalClass(void); MODULE_SCOPE const char *const * TkFontGetSymbolClass(void); MODULE_SCOPE int TkCreateNamedFont(Tcl_Interp *interp, Tk_Window tkwin, diff --git a/generic/tkFrame.c b/generic/tkFrame.c index 057b4b8..53c019c 100644 --- a/generic/tkFrame.c +++ b/generic/tkFrame.c @@ -12,8 +12,8 @@ * 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. @@ -447,6 +447,29 @@ TkCreateFrame( return result; } +int +TkListCreateFrame( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + Tcl_Obj *listObj, /* List of arguments. */ + int toplevel, /* Non-zero means create a toplevel window, + * zero means create a frame. */ + Tcl_Obj *nameObj) /* Should only be non-NULL if there is no main + * window associated with the interpreter. + * Gives the base name to use for the new + * application. */ +{ + int objc; + Tcl_Obj **objv; + + if (TCL_OK != Tcl_ListObjGetElements(interp, listObj, &objc, &objv)) { + return TCL_ERROR; + } + return CreateFrame(clientData, interp, objc, objv, + toplevel ? TYPE_TOPLEVEL : TYPE_FRAME, + nameObj ? Tcl_GetString(nameObj) : NULL); +} + static int CreateFrame( ClientData clientData, /* NULL. */ @@ -465,7 +488,8 @@ CreateFrame( Tk_Window newWin; const char *className, *screenName, *visualName, *colormapName; const char *arg, *useOption; - int i, length, depth; + int i, depth; + size_t length; unsigned int mask; Colormap colormap; Visual *visual; @@ -492,24 +516,24 @@ CreateFrame( 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]); } } @@ -659,7 +683,7 @@ CreateFrame( 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; @@ -720,7 +744,8 @@ FrameWidgetObjCmd( }; register Frame *framePtr = clientData; int result = TCL_OK, index; - int c, i, length; + int c, i; + size_t length; Tcl_Obj *objPtr; if (objc < 2) { @@ -739,7 +764,7 @@ FrameWidgetObjCmd( 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; @@ -749,7 +774,7 @@ FrameWidgetObjCmd( 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) { @@ -764,7 +789,7 @@ FrameWidgetObjCmd( */ 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; @@ -937,7 +962,7 @@ ConfigureFrame( 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) { diff --git a/generic/tkGC.c b/generic/tkGC.c index 5663ede..55e5774 100644 --- a/generic/tkGC.c +++ b/generic/tkGC.c @@ -23,7 +23,7 @@ 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; @@ -312,9 +312,7 @@ Tk_FreeGC( Tcl_Panic("Tk_FreeGC received unknown gc argument"); } gcPtr = Tcl_GetHashValue(idHashPtr); - gcPtr->refCount--; - if (gcPtr->refCount == 0) { - Tk_FreeXId(gcPtr->display, (XID) XGContextFromGC(gcPtr->gc)); + if (gcPtr->refCount-- <= 1) { XFreeGC(gcPtr->display, gcPtr->gc); Tcl_DeleteHashEntry(gcPtr->valueHashPtr); Tcl_DeleteHashEntry(idHashPtr); @@ -351,12 +349,6 @@ TkGCCleanup( entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { gcPtr = Tcl_GetHashValue(entryPtr); - /* - * This call is not needed, as it is only used on Unix to restore the - * Id to the stack pool, and we don't want to use them anymore. - * Tk_FreeXId(gcPtr->display, (XID) XGContextFromGC(gcPtr->gc)); - */ - XFreeGC(gcPtr->display, gcPtr->gc); Tcl_DeleteHashEntry(gcPtr->valueHashPtr); Tcl_DeleteHashEntry(entryPtr); diff --git a/generic/tkGrab.c b/generic/tkGrab.c index 00d4511..c37b6be 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -190,7 +190,7 @@ Tk_GrabObjCmd( TkDisplay *dispPtr; const char *arg; int index; - int len; + size_t len; static const char *const optionStrings[] = { "current", "release", "set", "status", NULL }; @@ -227,7 +227,7 @@ Tk_GrabObjCmd( * 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) { diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 2a88b76..aaed30f 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -2868,17 +2868,18 @@ GridStructureProc( } } } else if (eventPtr->type == DestroyNotify) { - register Gridder *gridPtr2, *nextPtr; + register Gridder *slavePtr, *nextPtr; if (gridPtr->masterPtr != NULL) { Unlink(gridPtr); } - for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; - gridPtr2 = nextPtr) { - Tk_UnmapWindow(gridPtr2->tkwin); - gridPtr2->masterPtr = NULL; - nextPtr = gridPtr2->nextPtr; - gridPtr2->nextPtr = NULL; + for (slavePtr = gridPtr->slavePtr; slavePtr != NULL; + slavePtr = nextPtr) { + Tk_ManageGeometry(slavePtr->tkwin, NULL, NULL); + Tk_UnmapWindow(slavePtr->tkwin); + slavePtr->masterPtr = NULL; + nextPtr = slavePtr->nextPtr; + slavePtr->nextPtr = NULL; } Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable, (char *) gridPtr->tkwin)); @@ -2894,11 +2895,11 @@ GridStructureProc( Tcl_DoWhenIdle(ArrangeGrid, gridPtr); } } else if (eventPtr->type == UnmapNotify) { - register Gridder *gridPtr2; + register Gridder *slavePtr; - for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; - gridPtr2 = gridPtr2->nextPtr) { - Tk_UnmapWindow(gridPtr2->tkwin); + for (slavePtr = gridPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + Tk_UnmapWindow(slavePtr->tkwin); } } } @@ -2964,10 +2965,10 @@ ConfigureSlaves( firstChar = 0; for (numWindows=0, i=0; i < objc; i++) { - int length; + size_t length; char prevChar = firstChar; - string = Tcl_GetStringFromObj(objv[i], &length); + string = TkGetStringFromObj(objv[i], &length); firstChar = string[0]; if (firstChar == '.') { @@ -3083,7 +3084,8 @@ ConfigureSlaves( } /* - * If no -row is given, use the first unoccupied row of the master. + * If no -row is given, use the next row after the highest occupied row + * of the master. */ if (defaultRow < 0) { @@ -3314,6 +3316,9 @@ ConfigureSlaves( } if (slavePtr->masterPtr != NULL && slavePtr->masterPtr != masterPtr) { + if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { + Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); + } Unlink(slavePtr); slavePtr->masterPtr = NULL; } diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index 0906673..80b1c9c 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -49,7 +49,7 @@ typedef struct BitmapMaster { */ 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 @@ -951,8 +951,7 @@ ImgBmapFree( BitmapInstance *instancePtr = clientData; BitmapInstance *prevPtr; - instancePtr->refCount--; - if (instancePtr->refCount > 0) { + if (instancePtr->refCount-- > 1) { return; } @@ -1080,10 +1079,10 @@ 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; diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index 1c28b54..aacde56 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -55,7 +55,7 @@ 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; /* @@ -111,8 +111,8 @@ typedef struct { * 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: @@ -187,14 +187,14 @@ static int ReadImage(GIFImageConfig *gifConfPtr, * 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. @@ -757,10 +757,10 @@ StringMatchGIF( Tcl_Interp *interp) /* not used */ { unsigned char *data, header[10]; - int got, length; + size_t got, length; MFile handle; - data = Tcl_GetByteArrayFromObj(dataObj, &length); + data = TkGetByteArrayFromObj(dataObj, &length); /* * Header is a minimum of 10 bytes. @@ -826,9 +826,9 @@ StringReadGIF( int srcX, int srcY) { MFile handle, *hdlPtr = &handle; - int length; + size_t length; const char *xferFormat; - unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length); + unsigned char *data = TkGetByteArrayFromObj(dataObj, &length); mInit(data, hdlPtr, length); @@ -917,7 +917,7 @@ ReadColorMap( 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; } @@ -983,11 +983,11 @@ GetDataBlock( { 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; } @@ -1049,7 +1049,7 @@ ReadImage( * 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; @@ -1141,9 +1141,9 @@ ReadImage( * Last pass reset the decoder, so the first code we see * must be a singleton. Seed the stack with it, and set up * the old/first code pointers for insertion into the - * string table. We can't just roll this into the - * clearCode test above, because at that point we have not - * yet read the next code. + * codes table. We can't just roll this into the clearCode + * test above, because at that point we have not yet read + * the next code. */ *top++ = append[code]; @@ -1154,11 +1154,11 @@ ReadImage( inCode = code; - if (code == maxCode) { + if ((code == maxCode) && (maxCode < (1 << MAX_LWZ_BITS))) { /* * maxCode is always one bigger than our highest assigned * code. If the code we see is equal to maxCode, then we - * are about to add a new string to the table. ??? + * are about to add a new entry to the codes table. */ *top++ = firstCode; @@ -1167,7 +1167,7 @@ ReadImage( while (code > clearCode) { /* - * Populate the stack by tracing the string in the string + * Populate the stack by tracing the code in the codes * table from its tail to its head */ @@ -1176,28 +1176,24 @@ ReadImage( } firstCode = append[code]; - /* - * If there's no more room in our string table, quit. - * Otherwise, add a new string to the table - */ + /* + * Push the head of the code onto the stack. + */ - if (maxCode >= (1 << MAX_LWZ_BITS)) { - return TCL_OK; - } + *top++ = firstCode; - /* - * Push the head of the string onto the stack. - */ - - *top++ = firstCode; - - /* - * Add a new string to the string table - */ + if (maxCode < (1 << MAX_LWZ_BITS)) { + /* + * If there's still room in our codes table, add a new entry. + * Otherwise don't, and keep using the current table. + * See DEFERRED CLEAR CODE IN LZW COMPRESSION in the GIF89a + * specification. + */ - prefix[maxCode] = oldCode; - append[maxCode] = firstCode; - maxCode++; + prefix[maxCode] = oldCode; + append[maxCode] = firstCode; + maxCode++; + } /* * maxCode tells us the maximum code value we can accept. If @@ -1377,7 +1373,7 @@ 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; @@ -1403,15 +1399,15 @@ mInit( *---------------------------------------------------------------------- */ -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; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) { *dst++ = c; @@ -1552,7 +1548,7 @@ char64( *---------------------------------------------------------------------- */ -static int +static size_t Fread( GIFImageConfig *gifConfPtr, unsigned char *dst, /* where to put the result */ @@ -1566,19 +1562,20 @@ Fread( if (gifConfPtr->fromData == 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; - return (int)(hunk * count); + handle->length -= 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); } /* @@ -1657,22 +1654,22 @@ StringWriteGIF( 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); diff --git a/generic/tkImgListFormat.c b/generic/tkImgListFormat.c new file mode 100644 index 0000000..4636c41 --- /dev/null +++ b/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 "<img> 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; row<blockPtr->height; row++) { + pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] + + row * blockPtr->pitch; + Tcl_DStringInit(&line); + for (col=0; col<blockPtr->width; 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; + size_t 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: */ diff --git a/generic/tkImgPNG.c b/generic/tkImgPNG.c index 2ee515b..a620515 100644 --- a/generic/tkImgPNG.c +++ b/generic/tkImgPNG.c @@ -35,7 +35,7 @@ static const int startLine[8] = { * Chunk type flags. */ -#define PNG_CF_ANCILLARY 0x10000000L /* Non-critical chunk (can ignore). */ +#define PNG_CF_ANCILLARY 0x20000000L /* Non-critical chunk (can ignore). */ #define PNG_CF_PRIVATE 0x00100000L /* Application-specific chunk. */ #define PNG_CF_RESERVED 0x00001000L /* Not used. */ #define PNG_CF_COPYSAFE 0x00000010L /* Opaque data safe for copying. */ @@ -127,7 +127,7 @@ typedef struct { 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. */ + size_t 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. */ @@ -215,16 +215,16 @@ 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); @@ -251,9 +251,9 @@ 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); @@ -320,7 +320,7 @@ InitPNGImage( Tcl_IncrRefCount(objPtr); pngPtr->objDataPtr = objPtr; pngPtr->strDataBuf = - Tcl_GetByteArrayFromObj(objPtr, &pngPtr->strDataLen); + TkGetByteArrayFromObj(objPtr, &pngPtr->strDataLen); } /* @@ -335,7 +335,7 @@ InitPNGImage( if (Tcl_ZlibStreamInit(NULL, dir, TCL_ZLIB_FORMAT_ZLIB, TCL_ZLIB_COMPRESS_DEFAULT, NULL, &pngPtr->stream) != TCL_OK) { - if (interp) { + if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "zlib initialization failed", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "ZLIB_INIT", NULL); @@ -431,7 +431,7 @@ ReadBase64( Tcl_Interp *interp, PNGImage *pngPtr, unsigned char *destPtr, - int destSz, + size_t destSz, unsigned long *crcPtr) { static const unsigned char from64[] = { @@ -556,14 +556,14 @@ 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); @@ -571,7 +571,7 @@ ReadByteArray( } while (destSz) { - int blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ); + size_t blockSz = PNG_MIN(destSz, PNG_BLOCK_SZ); memcpy(destPtr, pngPtr->strDataBuf, blockSz); @@ -614,7 +614,7 @@ ReadData( Tcl_Interp *interp, PNGImage *pngPtr, unsigned char *destPtr, - int destSz, + size_t destSz, unsigned long *crcPtr) { if (pngPtr->base64Data) { @@ -624,10 +624,10 @@ ReadData( } 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))); @@ -859,7 +859,7 @@ static int ReadChunkHeader( Tcl_Interp *interp, PNGImage *pngPtr, - int *sizePtr, + size_t *sizePtr, unsigned long *typePtr, unsigned long *crcPtr) { @@ -984,7 +984,7 @@ ReadChunkHeader( */ Tcl_SetObjResult(interp, Tcl_NewStringObj( - "encountered an unsupported criticial chunk type", + "encountered an unsupported critical chunk type", -1)); } else { char typeString[5]; @@ -995,7 +995,7 @@ ReadChunkHeader( typeString[3] = (char) (chunkType & 255); typeString[4] = '\0'; Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "encountered an unsupported criticial chunk type" + "encountered an unsupported critical chunk type" " \"%s\"", typeString)); } Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", @@ -1240,7 +1240,7 @@ ReadIHDR( { unsigned char sigBuf[PNG_SIG_SZ]; unsigned long chunkType; - int chunkSz; + size_t chunkSz; unsigned long crc; unsigned long width, height; int mismatch; @@ -1264,7 +1264,7 @@ ReadIHDR( */ if (mismatch && pngPtr->strDataBuf) { - pngPtr->strDataBuf = Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, + pngPtr->strDataBuf = TkGetByteArrayFromObj(pngPtr->objDataPtr, &pngPtr->strDataLen); pngPtr->base64Data = pngPtr->strDataBuf; @@ -2098,7 +2098,7 @@ ReadIDAT( */ while (chunkSz && !Tcl_ZlibStreamEof(pngPtr->stream)) { - int len1, len2; + size_t len1, len2; /* * Read another block of input into the zlib stream if data remains. @@ -2147,14 +2147,14 @@ ReadIDAT( */ 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 == (size_t)pngPtr->phaseSize) { if (pngPtr->phase > 7) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra data after final scan line of final phase", @@ -2245,10 +2245,10 @@ ApplyAlpha( p += offset; if (16 == pngPtr->bitDepth) { - register int channel; + register unsigned int channel; while (p < endPtr) { - channel = (unsigned char) + channel = (unsigned int) (((p[0] << 8) | p[1]) * pngPtr->alpha); *p++ = (unsigned char) (channel >> 8); @@ -2383,7 +2383,7 @@ DecodePNG( int destY) { unsigned long chunkType; - int chunkSz; + size_t chunkSz; unsigned long crc; /* @@ -2768,7 +2768,7 @@ StringMatchPNG( 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; @@ -2846,7 +2846,7 @@ WriteData( Tcl_Interp *interp, PNGImage *pngPtr, const unsigned char *srcPtr, - int srcSz, + size_t srcSz, unsigned long *crcPtr) { if (!srcPtr || !srcSz) { @@ -2863,12 +2863,12 @@ WriteData( */ if (pngPtr->objDataPtr) { - int objSz; + size_t 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); @@ -2885,7 +2885,7 @@ WriteData( } 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; @@ -2961,7 +2961,7 @@ WriteChunk( 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; @@ -3132,9 +3132,10 @@ WriteIDAT( 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; + size_t outputSize; /* * Filter and compress each row one at a time. @@ -3226,7 +3227,7 @@ WriteIDAT( 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; diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index 6f084f0..d6ec63c 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -141,7 +141,8 @@ FileReadPPM( * 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; @@ -285,7 +286,8 @@ FileWritePPM( 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]; @@ -315,16 +317,16 @@ FileWritePPM( 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; @@ -762,10 +764,11 @@ ReadPPMStringHeader( { #define BUFFER_SIZE 1000 char buffer[BUFFER_SIZE], c; - int i, numFields, dataSize, type = 0; + int i, numFields, type = 0; + size_t dataSize; unsigned char *dataBuffer; - dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize); + dataBuffer = TkGetByteArrayFromObj(dataPtr, &dataSize); /* * Read 4 space-separated fields from the string, ignoring comments (any diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c index 666a9b0..13e6bbf 100644 --- a/generic/tkImgPhInstance.c +++ b/generic/tkImgPhInstance.c @@ -110,7 +110,7 @@ TkImgPhotoConfigureInstance( */ if (colorTablePtr != NULL) { - colorTablePtr->liveRefCount -= 1; + colorTablePtr->liveRefCount--; FreeColorTable(colorTablePtr, 0); } GetColorTable(instancePtr); @@ -404,6 +404,9 @@ TkImgPhotoGet( * * Note that Win32 pre-defines those operations that we really need. * + * Note that on MacOS, if the background comes from a Retina display + * then it will be twice as wide and twice as high as the photoimage. + * *---------------------------------------------------------------------- */ @@ -415,6 +418,13 @@ TkImgPhotoGet( (UCHAR(r) << red_shift) | \ (UCHAR(g) << green_shift) | \ (UCHAR(b) << blue_shift) )) +#ifdef MAC_OSX_TK +#define RGBA(r, g, b, a) ((unsigned)( \ + (UCHAR(r) << red_shift) | \ + (UCHAR(g) << green_shift) | \ + (UCHAR(b) << blue_shift) | \ + (UCHAR(a) << alpha_shift) )) +#endif #define RGB15(r, g, b) ((unsigned)( \ (((r) * red_mask / 255) & red_mask) | \ (((g) * green_mask / 255) & green_mask) | \ @@ -433,7 +443,16 @@ BlendComplexAlpha( unsigned long pixel; unsigned char r, g, b, alpha, unalpha, *masterPtr; unsigned char *alphaAr = iPtr->masterPtr->pix32; - +#if defined(MAC_OSX_TK) + /* Background "pixels" are actually 2^pp x 2^pp blocks of subpixels. Each + * block gets blended with the color of one image pixel. Since we iterate + * over the background subpixels, we reset the width and height to the + * subpixel dimensions of the background image we are using. + */ + int pp = bgImg->pixelpower; + width = width << pp; + height = height << pp; +#endif /* * This blending is an integer version of the Source-Over compositing rule * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH @@ -473,6 +492,13 @@ BlendComplexAlpha( while ((0x0001 & (blue_mask >> blue_shift)) == 0) { blue_shift++; } +#ifdef MAC_OSX_TK + unsigned long alpha_mask = visual->alpha_mask; + unsigned long alpha_shift = 0; + while ((0x0001 & (alpha_mask >> alpha_shift)) == 0) { + alpha_shift++; + } +#endif #endif /* !_WIN32 */ /* @@ -532,9 +558,16 @@ BlendComplexAlpha( #endif /* !_WIN32 && !MAC_OSX_TK */ for (y = 0; y < height; y++) { +# if !defined(MAC_OSX_TK) line = (y + yOffset) * iPtr->masterPtr->width; for (x = 0; x < width; x++) { masterPtr = alphaAr + ((line + x + xOffset) * 4); +#else + /* Repeat each image row and column 2^pp times. */ + line = ((y>>pp) + yOffset) * iPtr->masterPtr->width; + for (x = 0; x < width; x++) { + masterPtr = alphaAr + ((line + (x>>pp) + xOffset) * 4); +#endif alpha = masterPtr[3]; /* @@ -566,7 +599,11 @@ BlendComplexAlpha( g = ALPHA_BLEND(ga, g, alpha, unalpha); b = ALPHA_BLEND(ba, b, alpha, unalpha); } +#ifndef MAC_OSX_TK XPutPixel(bgImg, x, y, RGB(r, g, b)); +#else + XPutPixel(bgImg, x, y, RGBA(r, g, b, alpha)); +#endif } } } @@ -635,7 +672,9 @@ TkImgPhotoDisplay( (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); if (bgImg == NULL) { Tk_DeleteErrorHandler(handler); - /* We failed to get the image so draw without blending alpha. It's the best we can do */ + /* We failed to get the image, so draw without blending alpha. + * It's the best we can do. + */ goto fallBack; } @@ -700,8 +739,7 @@ TkImgPhotoFree( PhotoInstance *instancePtr = clientData; ColorTable *colorPtr; - instancePtr->refCount -= 1; - if (instancePtr->refCount > 0) { + if (instancePtr->refCount-- > 1) { return; } @@ -714,7 +752,7 @@ TkImgPhotoFree( colorPtr = instancePtr->colorTablePtr; if (colorPtr != NULL) { - colorPtr->liveRefCount -= 1; + colorPtr->liveRefCount--; } Tcl_DoWhenIdle(TkImgDisposeInstance, instancePtr); @@ -1097,8 +1135,7 @@ FreeColorTable( * longer required by an instance. */ int force) /* Force free to happen immediately. */ { - colorPtr->refCount--; - if (colorPtr->refCount > 0) { + if (colorPtr->refCount-- > 1) { return; } @@ -1241,7 +1278,7 @@ AllocateColors( } } else { /* - * Monochrome display - allocate the shades of grey we want. + * Monochrome display - allocate the shades of gray we want. */ for (i = 0; i < numColors; ++i) { diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 3e03f3d..e1d54dd 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -48,6 +48,7 @@ struct SubcommandOptions { * 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. @@ -56,18 +57,21 @@ struct SubcommandOptions { * 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 @@ -75,6 +79,7 @@ struct SubcommandOptions { */ static const char *const optionNames[] = { + "-alpha", "-background", "-compositingrule", "-format", @@ -83,6 +88,7 @@ static const char *const optionNames[] = { "-shrink", "-subsample", "-to", + "-withalpha", "-zoom", NULL }; @@ -182,9 +188,6 @@ static int ImgPhotoConfigureMaster(Tcl_Interp *interp, 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); @@ -402,14 +405,13 @@ ImgPhotoCmd( }; 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; - int imageWidth, imageHeight, matched, length, oldformat = 0; + size_t length; + int imageWidth, imageHeight, matched, oldformat = 0; Tcl_Channel chan; Tk_PhotoHandle srcHandle; ThreadSpecificData *tsdPtr = @@ -446,12 +448,12 @@ ImgPhotoCmd( Tcl_WrongNumArgs(interp, 2, objv, "option"); return TCL_ERROR; } - arg = Tcl_GetStringFromObj(objv[2], &length); - if (strncmp(arg,"-data", (unsigned) length) == 0) { + arg = TkGetStringFromObj(objv[2], &length); + if (strncmp(arg,"-data", length) == 0) { if (masterPtr->dataString) { Tcl_SetObjResult(interp, masterPtr->dataString); } - } else if (strncmp(arg,"-format", (unsigned) length) == 0) { + } else if (strncmp(arg,"-format", length) == 0) { if (masterPtr->format) { Tcl_SetObjResult(interp, masterPtr->format); } @@ -495,9 +497,9 @@ ImgPhotoCmd( return TCL_OK; } else if (objc == 3) { - const char *arg = Tcl_GetStringFromObj(objv[2], &length); + const char *arg = TkGetStringFromObj(objv[2], &length); - if (length > 1 && !strncmp(arg, "-data", (unsigned) length)) { + if (length > 1 && !strncmp(arg, "-data", length)) { Tcl_AppendResult(interp, "-data {} {} {}", NULL); if (masterPtr->dataString) { /* @@ -511,7 +513,7 @@ ImgPhotoCmd( } return TCL_OK; } else if (length > 1 && - !strncmp(arg, "-format", (unsigned) length)) { + !strncmp(arg, "-format", length)) { Tcl_AppendResult(interp, "-format {} {} {}", NULL); if (masterPtr->format) { /* @@ -573,6 +575,9 @@ ImgPhotoCmd( if ((options.fromX2 > block.width) || (options.fromY2 > block.height) || (options.fromX2 > block.width) || (options.fromY2 > block.height)) { + if (options.background) { + Tk_FreeColor(options.background); + } Tcl_SetObjResult(interp, Tcl_NewStringObj( "coordinates for -from option extend outside source image", -1)); @@ -622,35 +627,48 @@ ImgPhotoCmd( } /* + * Copy the image data over using Tk_PhotoPutZoomedBlock. + */ + + block.pixelPtr += options.fromX * block.pixelSize + + options.fromY * block.pitch; + block.width = options.fromX2 - options.fromX; + block.height = options.fromY2 - options.fromY; + result = Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr, + &block, options.toX, options.toY, options.toX2 - options.toX, + options.toY2 - options.toY, options.zoomX, options.zoomY, + options.subsampleX, options.subsampleY, + options.compositingRule); + + /* * Set the destination image size if the -shrink option was specified. + * This has to be done _after_ copying the data. Otherwise, if source + * and destination are the same image, block.pixelPtr would point to + * an invalid memory block (bug [5239fd749b]). */ if (options.options & OPT_SHRINK) { if (ImgPhotoSetSize(masterPtr, options.toX2, options.toY2) != TCL_OK) { + if (options.background) { + Tk_FreeColor(options.background); + } Tcl_SetObjResult(interp, Tcl_NewStringObj( TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); return TCL_ERROR; } } - - /* - * Copy the image data over using Tk_PhotoPutZoomedBlock. - */ - - block.pixelPtr += options.fromX * block.pixelSize - + options.fromY * block.pitch; - block.width = options.fromX2 - options.fromX; - block.height = options.fromY2 - options.fromY; - return Tk_PhotoPutZoomedBlock(interp, (Tk_PhotoHandle) masterPtr, - &block, options.toX, options.toY, options.toX2 - options.toX, - options.toY2 - options.toY, options.zoomX, options.zoomY, - options.subsampleX, options.subsampleY, - options.compositingRule); + Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, + masterPtr->width, masterPtr->height); + if (options.background) { + 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. @@ -658,7 +676,7 @@ ImgPhotoCmd( Tk_ImageStringWriteProc *stringWriteProc = NULL; - index = 2; + index = 1; memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; @@ -669,7 +687,7 @@ ImgPhotoCmd( &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; } @@ -691,50 +709,50 @@ ImgPhotoCmd( 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; - } - } - } + 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) { - 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; + } + 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; + } + } } - } else { - stringWriteProc = ImgStringWrite; + } + 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; } /* @@ -771,7 +789,22 @@ ImgPhotoCmd( 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: { @@ -779,12 +812,24 @@ ImgPhotoCmd( * photo get command - first parse and check parameters. */ - Tcl_Obj *channels[3]; - - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "x y"); + Tcl_Obj *channels[4]; + int channelCount = 3; + + 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; @@ -800,25 +845,29 @@ ImgPhotoCmd( } /* - * 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[3] = Tcl_NewIntObj(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; @@ -828,174 +877,50 @@ ImgPhotoCmd( return TCL_ERROR; } - if (MatchStringFormat(interp, options.name ? objv[2]:NULL, - options.format, &imageFormat, &imageWidth, - &imageHeight, &oldformat) == TCL_OK) { - Tcl_Obj *format, *data; + /* + * See if there's a format that can read the 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) { + if (MatchStringFormat(interp, objv[2], options.format, &imageFormat, + &imageWidth, &imageHeight, &oldformat) != 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 (!(options.options & OPT_TO) || (options.toX2 < 0)) { + options.toX2 = options.toX + imageWidth; + options.toY2 = options.toY + imageHeight; } - if (y < dataHeight || dataHeight == 0 || dataWidth == 0) { - if (block.pixelPtr != NULL) { - ckfree(block.pixelPtr); - } - if (y < dataHeight) { - return TCL_ERROR; + 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); } - return TCL_OK; + 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; + } /* - * Fill in default values for the -to option, then copy the block in - * using Tk_PhotoPutBlock. + * 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; - 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; - + return TCL_OK; + } case PHOTO_READ: { Tcl_Obj *format; @@ -1165,17 +1090,40 @@ ImgPhotoCmd( 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( @@ -1186,36 +1134,55 @@ ImgPhotoCmd( 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_NewIntObj(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( @@ -1226,38 +1193,53 @@ ImgPhotoCmd( 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, + modRegion = TkCreateRegion(); + TkUnionRectWithRegion(&setBox, modRegion, modRegion); + if (pixelPtr[3]) { + TkUnionRectWithRegion(&setBox, masterPtr->validRegion, masterPtr->validRegion); - TkDestroyRegion(clearRegion); - - /* - * Set the alpha value correctly. - */ - - pixelPtr[3] = 0; } else { - /* - * Make pixel opaque. - */ - - TkUnionRectWithRegion(&setBox, masterPtr->validRegion, + TkSubtractRegion(masterPtr->validRegion, modRegion, masterPtr->validRegion); - pixelPtr[3] = 255; } + TkDestroyRegion(modRegion); /* * Inform the generic image code that the image @@ -1459,13 +1441,18 @@ GetExtension( * * 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. * *---------------------------------------------------------------------- */ @@ -1489,7 +1476,8 @@ ParseSubcommandOptions( * TK_PHOTO_COMPOSITE_* constants. */ NULL }; - int index, c, bit, currentBit, length; + size_t length; + int index, c, bit, currentBit; int values[4], numValues, maxValues, argIndex; const char *option, *expandedOption, *needed; const char *const *listPtr; @@ -1501,7 +1489,7 @@ ParseSubcommandOptions( * optPtr->name. */ - expandedOption = option = Tcl_GetStringFromObj(objv[index], &length); + expandedOption = option = TkGetStringFromObj(objv[index], &length); if (option[0] != '-') { if (optPtr->name == NULL) { optPtr->name = objv[index]; @@ -1519,7 +1507,7 @@ ParseSubcommandOptions( currentBit = 1; for (listPtr = optionNames; *listPtr != NULL; ++listPtr) { if ((c == *listPtr[0]) - && (strncmp(option, *listPtr, (size_t) length) == 0)) { + && (strncmp(option, *listPtr, length) == 0)) { expandedOption = *listPtr; if (bit != 0) { goto unknownOrAmbiguousOption; @@ -1535,7 +1523,11 @@ ParseSubcommandOptions( */ if (!(allowedOptions & bit)) { - goto unknownOrAmbiguousOption; + if (optPtr->name != NULL) { + goto unknownOrAmbiguousOption; + } + optPtr->name = objv[index]; + continue; } /* @@ -1584,7 +1576,8 @@ ParseSubcommandOptions( 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; @@ -1765,7 +1758,8 @@ ImgPhotoConfigureMaster( const char *oldFileString, *oldPaletteString; Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL; Tcl_Obj *tempdata, *tempformat; - int length, i, j, result, imageWidth, imageHeight, oldformat; + size_t length; + int i, j, result, imageWidth, imageHeight, oldformat; double oldGamma; Tcl_Channel chan; Tk_PhotoImageFormat *imageFormat; @@ -1773,10 +1767,10 @@ ImgPhotoConfigureMaster( args = ckalloc((objc + 1) * sizeof(char *)); for (i = 0, j = 0; i < objc; i++,j++) { - args[j] = Tcl_GetStringFromObj(objv[i], &length); + args[j] = TkGetStringFromObj(objv[i], &length); if ((length > 1) && (args[j][0] == '-')) { if ((args[j][1] == 'd') && - !strncmp(args[j], "-data", (size_t) length)) { + !strncmp(args[j], "-data", length)) { if (++i < objc) { data = objv[i]; j--; @@ -1789,7 +1783,7 @@ ImgPhotoConfigureMaster( return TCL_ERROR; } } else if ((args[j][1] == 'f') && - !strncmp(args[j], "-format", (size_t) length)) { + !strncmp(args[j], "-format", length)) { if (++i < objc) { format = objv[i]; j--; @@ -1852,9 +1846,10 @@ ImgPhotoConfigureMaster( * Force into ByteArray format, which most (all) image handlers will * use anyway. Empty length means ignore the -data option. */ + size_t bytesize; - (void) Tcl_GetByteArrayFromObj(data, &length); - if (length) { + (void) TkGetByteArrayFromObj(data, &bytesize); + if (bytesize) { Tcl_IncrRefCount(data); } else { data = NULL; @@ -1870,8 +1865,8 @@ ImgPhotoConfigureMaster( * object. */ - (void) Tcl_GetStringFromObj(format, &length); - if (length) { + (void) Tcl_GetString(format); + if (format->length) { Tcl_IncrRefCount(format); } else { format = NULL; @@ -2537,7 +2532,7 @@ MatchStringFormat( 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; @@ -2553,6 +2548,16 @@ MatchStringFormat( 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) { @@ -2568,6 +2573,16 @@ MatchStringFormat( 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, @@ -2605,23 +2620,46 @@ MatchStringFormat( } } } + 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); + 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; } @@ -2686,7 +2724,7 @@ Tk_PhotoPutBlock( * messages, or NULL. */ Tk_PhotoHandle handle, /* Opaque handle for the photo image to be * updated. */ - register Tk_PhotoImageBlock *blockPtr, + Tk_PhotoImageBlock *blockPtr, /* Pointer to a structure describing the pixel * data to be copied into the image. */ int x, int y, /* Coordinates of the top-left pixel to be @@ -2697,6 +2735,8 @@ Tk_PhotoPutBlock( * transparent pixels. */ { register PhotoMaster *masterPtr = (PhotoMaster *) handle; + Tk_PhotoImageBlock sourceBlock; + unsigned char *memToFree; int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; int wLeft, hLeft, wCopy, hCopy, pitch; unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr; @@ -2724,11 +2764,43 @@ Tk_PhotoPutBlock( return TCL_OK; } + /* + * Fix for bug e4336bef5d: + * + * Make a local copy of *blockPtr, as we might have to change some + * of its fields and don't want to interfere with the caller's data. + * + * If source and destination are the same image, create a copy of the + * source data in our local sourceBlock. + * + * To find out, just comparing the pointers is not enough - they might have + * different values and still point to the same block of memory. (e.g. + * if the -from option was passed to [imageName copy]) + */ + sourceBlock = *blockPtr; + memToFree = NULL; + if (sourceBlock.pixelPtr >= masterPtr->pix32 + && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width + * masterPtr->height * 4) { + sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height + * sourceBlock.pitch); + if (sourceBlock.pixelPtr == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); + Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); + } + return TCL_ERROR; + } + memToFree = sourceBlock.pixelPtr; + memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height + * sourceBlock.pitch); + } + + xEnd = x + width; yEnd = y + height; if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) { - int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); - if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { if (interp != NULL) { @@ -2736,11 +2808,7 @@ Tk_PhotoPutBlock( TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); } - return TCL_ERROR; - } - if (sameSrc) { - blockPtr->pixelPtr = masterPtr->pix32; - blockPtr->pitch = masterPtr->width * 4; + goto errorExit; } } @@ -2759,14 +2827,14 @@ Tk_PhotoPutBlock( * components, mark it as a color image. */ - greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; - blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; - alphaOffset = blockPtr->offset[3]; - if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) { + greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0]; + blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0]; + alphaOffset = sourceBlock.offset[3]; + if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) { alphaOffset = 0; sourceIsSimplePhoto = 1; } else { - alphaOffset -= blockPtr->offset[0]; + alphaOffset -= sourceBlock.offset[0]; } if ((greenOffset != 0) || (blueOffset != 0)) { masterPtr->flags |= COLOR_IMAGE; @@ -2786,13 +2854,13 @@ Tk_PhotoPutBlock( * pixelSize == 3 and alphaOffset == 0. Maybe other cases too. */ - if ((blockPtr->pixelSize == 4) + if ((sourceBlock.pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) - && (width <= blockPtr->width) && (height <= blockPtr->height) + && (width <= sourceBlock.width) && (height <= sourceBlock.height) && ((height == 1) || ((x == 0) && (width == masterPtr->width) - && (blockPtr->pitch == pitch))) + && (sourceBlock.pitch == pitch))) && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memmove(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0], + memmove(destLinePtr, sourceBlock.pixelPtr + sourceBlock.offset[0], ((size_t)height * width * 4)); /* @@ -2808,11 +2876,11 @@ Tk_PhotoPutBlock( */ for (hLeft = height; hLeft > 0;) { - int pixelSize = blockPtr->pixelSize; + int pixelSize = sourceBlock.pixelSize; int compRuleSet = (compRule == TK_PHOTO_COMPOSITE_SET); - srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; - hCopy = MIN(hLeft, blockPtr->height); + srcLinePtr = sourceBlock.pixelPtr + sourceBlock.offset[0]; + hCopy = MIN(hLeft, sourceBlock.height); hLeft -= hCopy; for (; hCopy > 0; --hCopy) { /* @@ -2823,10 +2891,10 @@ Tk_PhotoPutBlock( if ((pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) - && (width <= blockPtr->width) + && (width <= sourceBlock.width) && compRuleSet) { memcpy(destLinePtr, srcLinePtr, ((size_t)width * 4)); - srcLinePtr += blockPtr->pitch; + srcLinePtr += sourceBlock.pitch; destLinePtr += pitch; continue; } @@ -2837,7 +2905,7 @@ Tk_PhotoPutBlock( destPtr = destLinePtr; for (wLeft = width; wLeft > 0;) { - wCopy = MIN(wLeft, blockPtr->width); + wCopy = MIN(wLeft, sourceBlock.width); wLeft -= wCopy; srcPtr = srcLinePtr; @@ -2927,7 +2995,7 @@ Tk_PhotoPutBlock( destPtr += 4; } } - srcLinePtr += blockPtr->pitch; + srcLinePtr += sourceBlock.pitch; destLinePtr += pitch; } } @@ -3043,7 +3111,15 @@ Tk_PhotoPutBlock( Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, masterPtr->height); + + if (memToFree) ckfree(memToFree); + return TCL_OK; + + errorExit: + if (memToFree) ckfree(memToFree); + + return TCL_ERROR; } /* @@ -3070,7 +3146,7 @@ Tk_PhotoPutZoomedBlock( * messages, or NULL. */ Tk_PhotoHandle handle, /* Opaque handle for the photo image to be * updated. */ - register Tk_PhotoImageBlock *blockPtr, + Tk_PhotoImageBlock *blockPtr, /* Pointer to a structure describing the pixel * data to be copied into the image. */ int x, int y, /* Coordinates of the top-left pixel to be @@ -3085,6 +3161,8 @@ Tk_PhotoPutZoomedBlock( * transparent pixels. */ { register PhotoMaster *masterPtr = (PhotoMaster *) handle; + register Tk_PhotoImageBlock sourceBlock; + unsigned char *memToFree; int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt; unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr; @@ -3121,11 +3199,41 @@ Tk_PhotoPutZoomedBlock( return TCL_OK; } + /* + * Fix for Bug e4336bef5d: + * Make a local copy of *blockPtr, as we might have to change some + * of its fields and don't want to interfere with the caller's data. + * + * If source and destination are the same image, create a copy of the + * source data in our local sourceBlock. + * + * To find out, just comparing the pointers is not enough - they might have + * different values and still point to the same block of memory. (e.g. + * if the -from option was passed to [imageName copy]) + */ + sourceBlock = *blockPtr; + memToFree = NULL; + if (sourceBlock.pixelPtr >= masterPtr->pix32 + && sourceBlock.pixelPtr <= masterPtr->pix32 + masterPtr->width + * masterPtr->height * 4) { + sourceBlock.pixelPtr = attemptckalloc(sourceBlock.height + * sourceBlock.pitch); + if (sourceBlock.pixelPtr == NULL) { + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); + Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); + } + return TCL_ERROR; + } + memToFree = sourceBlock.pixelPtr; + memcpy(sourceBlock.pixelPtr, blockPtr->pixelPtr, sourceBlock.height + * sourceBlock.pitch); + } + xEnd = x + width; yEnd = y + height; if ((xEnd > masterPtr->width) || (yEnd > masterPtr->height)) { - int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); - if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { if (interp != NULL) { @@ -3133,11 +3241,7 @@ Tk_PhotoPutZoomedBlock( TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); } - return TCL_ERROR; - } - if (sameSrc) { - blockPtr->pixelPtr = masterPtr->pix32; - blockPtr->pitch = masterPtr->width * 4; + goto errorExit; } } @@ -3156,14 +3260,14 @@ Tk_PhotoPutZoomedBlock( * components, mark it as a color image. */ - greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; - blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; - alphaOffset = blockPtr->offset[3]; - if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) { + greenOffset = sourceBlock.offset[1] - sourceBlock.offset[0]; + blueOffset = sourceBlock.offset[2] - sourceBlock.offset[0]; + alphaOffset = sourceBlock.offset[3]; + if ((alphaOffset >= sourceBlock.pixelSize) || (alphaOffset < 0)) { alphaOffset = 0; sourceIsSimplePhoto = 1; } else { - alphaOffset -= blockPtr->offset[0]; + alphaOffset -= sourceBlock.offset[0]; } if ((greenOffset != 0) || (blueOffset != 0)) { masterPtr->flags |= COLOR_IMAGE; @@ -3174,21 +3278,21 @@ Tk_PhotoPutZoomedBlock( * subsampling and zooming. */ - blockXSkip = subsampleX * blockPtr->pixelSize; - blockYSkip = subsampleY * blockPtr->pitch; + blockXSkip = subsampleX * sourceBlock.pixelSize; + blockYSkip = subsampleY * sourceBlock.pitch; if (subsampleX > 0) { - blockWid = ((blockPtr->width + subsampleX - 1) / subsampleX) * zoomX; + blockWid = ((sourceBlock.width + subsampleX - 1) / subsampleX) * zoomX; } else if (subsampleX == 0) { blockWid = width; } else { - blockWid = ((blockPtr->width - subsampleX - 1) / -subsampleX) * zoomX; + blockWid = ((sourceBlock.width - subsampleX - 1) / -subsampleX) * zoomX; } if (subsampleY > 0) { - blockHt = ((blockPtr->height + subsampleY - 1) / subsampleY) * zoomY; + blockHt = ((sourceBlock.height + subsampleY - 1) / subsampleY) * zoomY; } else if (subsampleY == 0) { blockHt = height; } else { - blockHt = ((blockPtr->height - subsampleY - 1) / -subsampleY) * zoomY; + blockHt = ((sourceBlock.height - subsampleY - 1) / -subsampleY) * zoomY; } /* @@ -3196,12 +3300,12 @@ Tk_PhotoPutZoomedBlock( */ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; - srcOrigPtr = blockPtr->pixelPtr + blockPtr->offset[0]; + srcOrigPtr = sourceBlock.pixelPtr + sourceBlock.offset[0]; if (subsampleX < 0) { - srcOrigPtr += (blockPtr->width - 1) * blockPtr->pixelSize; + srcOrigPtr += (sourceBlock.width - 1) * sourceBlock.pixelSize; } if (subsampleY < 0) { - srcOrigPtr += (blockPtr->height - 1) * blockPtr->pitch; + srcOrigPtr += (sourceBlock.height - 1) * sourceBlock.pitch; } pitch = masterPtr->width * 4; @@ -3351,7 +3455,15 @@ Tk_PhotoPutZoomedBlock( Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, masterPtr->height); + + if (memToFree) ckfree(memToFree); + return TCL_OK; + + errorExit: + if (memToFree) ckfree(memToFree); + + return TCL_ERROR; } /* @@ -3839,57 +3951,6 @@ ImgGetPhoto( /* *---------------------------------------------------------------------- * - * ImgStringWrite -- - * - * Default string write function. The data is formatted in the default - * format as accepted by the "<img> 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; row<blockPtr->height; row++) { - Tcl_Obj *line = Tcl_NewObj(); - unsigned char *pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] - + row * blockPtr->pitch; - - for (col=0; col<blockPtr->width; 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 @@ -3932,7 +3993,7 @@ Tk_PhotoGetImage( /* *-------------------------------------------------------------- * - * TkPostscriptPhoto -- + * ImgPostscriptPhoto -- * * This function is called to output the contents of a photo image in * Postscript by calling the Tk_PostscriptPhoto function. @@ -3977,7 +4038,7 @@ ImgPhotoPostscript( * *---------------------------------------------------------------------- */ - +#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 void Tk_PhotoPutBlock_NoComposite( Tk_PhotoHandle handle, @@ -4063,11 +4124,13 @@ Tk_PhotoSetSize_Panic( 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: */ diff --git a/generic/tkImgPhoto.h b/generic/tkImgPhoto.h index 36bc6cb..a84ebb3 100644 --- a/generic/tkImgPhoto.h +++ b/generic/tkImgPhoto.h @@ -93,10 +93,17 @@ struct ColorTableId { 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 @@ -201,7 +208,11 @@ struct PhotoInstance { * 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 diff --git a/generic/tkInt.decls b/generic/tkInt.decls index 586b407..04eecf6 100644 --- a/generic/tkInt.decls +++ b/generic/tkInt.decls @@ -99,7 +99,7 @@ declare 21 { 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) @@ -182,7 +182,7 @@ 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[]) @@ -389,7 +389,7 @@ declare 108 { 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) @@ -570,7 +570,7 @@ declare 169 { 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 { @@ -578,7 +578,7 @@ declare 171 { 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 { @@ -586,7 +586,7 @@ declare 173 { 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 { @@ -594,7 +594,7 @@ declare 175 { 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 { @@ -602,7 +602,7 @@ declare 177 { 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 { @@ -610,7 +610,7 @@ declare 179 { 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) } @@ -634,6 +634,13 @@ declare 184 { 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) +} + ############################################################################## @@ -983,9 +990,9 @@ declare 38 aqua { declare 39 aqua { void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid) } -declare 40 aqua { - void TkSuspendClipboard(void) -} +# +# Slot 40 unused (WAS: TkSuspendClipboard) +# declare 41 aqua { int TkMacOSXZoomToplevel(void *whichWindow, short zoomPart) } @@ -1422,28 +1429,82 @@ declare 106 win { # New in Tk 8.6 declare 107 win { - int XFlush(Display *display) + int XFlush(Display *display) } declare 108 win { - int XGrabServer(Display *display) + int XGrabServer(Display *display) } declare 109 win { - int XUngrabServer(Display *display) + int XUngrabServer(Display *display) } declare 110 win { - int XFree(void *data) + int XFree(void *data) } declare 111 win { - int XNoOp(Display *display) + int XNoOp(Display *display) } declare 112 win { - XAfterFunction XSynchronize(Display *display, Bool onoff) + XAfterFunction XSynchronize(Display *display, Bool onoff) } declare 113 win { - int XSync(Display *display, Bool discard) + int XSync(Display *display, Bool discard) } declare 114 win { - VisualID XVisualIDFromVisual(Visual *visual) + VisualID XVisualIDFromVisual(Visual *visual) +} + +# For tktreectrl +declare 120 win { + int XOffsetRegion(Region rgn, int dx, int dy) +} +declare 121 win { + int XUnionRegion(Region srca, Region srcb, Region dr_return) +} + +# For 3dcanvas +declare 122 win { + Window XCreateWindow(Display *display, Window parent, int x, int y, + unsigned int width, unsigned int height, + unsigned int border_width, int depth, unsigned int clazz, + Visual *visual, unsigned long value_mask, + XSetWindowAttributes *attributes) +} + +# Various, e.g. for stub-enabled BLT +declare 129 win { + int XLowerWindow(Display *d, Window w) +} +declare 130 win { + int XFillArcs(Display *d, Drawable dr, GC gc, XArc *a, int n) +} +declare 131 win { + int XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a, int n) +} +declare 132 win { + int XDrawRectangles(Display *d, Drawable dr, GC gc, XRectangle *r, int n) +} +declare 133 win { + int XDrawSegments(Display *d, Drawable dr, GC gc, XSegment *s, int n) +} +declare 134 win { + int XDrawPoint(Display *d, Drawable dr, GC gc, int x, int y) +} +declare 135 win { + int XDrawPoints(Display *d, Drawable dr, GC gc, XPoint *p, int n, int m) +} +declare 136 win { + int XReparentWindow(Display *d, Window w, Window p, int x, int y) +} +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) } ################################ @@ -1725,7 +1786,7 @@ declare 79 aqua { XTextProperty *text_prop_return) } declare 80 aqua { - void XDrawSegments(Display *display, Drawable d, GC gc, + int XDrawSegments(Display *display, Drawable d, GC gc, XSegment *segments, int nsegments) } declare 81 aqua { @@ -1743,10 +1804,10 @@ declare 84 aqua { void XClearWindow(Display *d, Window w) } declare 85 aqua { - void XDrawPoint(Display *display, Drawable d, GC gc, int x, int y) + int XDrawPoint(Display *display, Drawable d, GC gc, int x, int y) } declare 86 aqua { - void XDrawPoints(Display *display, Drawable d, GC gc, XPoint *points, + int XDrawPoints(Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode) } declare 87 aqua { diff --git a/generic/tkInt.h b/generic/tkInt.h index b644c5b..f903490 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -25,7 +25,6 @@ * Darwin (where configure runs only once for multiple architectures). */ -#include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif @@ -59,6 +58,14 @@ # 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 @@ -84,6 +91,10 @@ # endif #endif +#ifndef TCL_AUTO_LENGTH +# define TCL_AUTO_LENGTH (-1) +#endif + /* * Opaque type declarations: */ @@ -107,7 +118,7 @@ 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 @@ -116,7 +127,7 @@ typedef struct TkCursor { * 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. */ @@ -266,7 +277,7 @@ typedef struct TkDisplay { /* 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. */ @@ -423,6 +434,7 @@ typedef struct TkDisplay { Atom windowAtom; /* Atom for TK_WINDOW. */ Atom clipboardAtom; /* Atom for CLIPBOARD. */ Atom utf8Atom; /* Atom for UTF8_STRING. */ + Atom atomPairAtom; /* Atom for ATOM_PAIR. */ Tk_Window clipWindow; /* Window used for clipboard ownership and to * retrieve selections between processes. NULL @@ -478,7 +490,7 @@ typedef struct TkDisplay { #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 + size_t 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. */ @@ -508,6 +520,9 @@ typedef struct TkDisplay { int iconDataSize; /* Size of default iconphoto image data. */ unsigned char *iconDataPtr; /* Default iconphoto image data, if set. */ +#ifdef TK_USE_INPUT_METHODS + int ximGeneration; /* Used to invalidate XIC */ +#endif /* TK_USE_INPUT_METHODS */ } TkDisplay; /* @@ -579,7 +594,7 @@ typedef struct TkEventHandler { */ typedef struct TkMainInfo { - int refCount; /* Number of windows whose "mainPtr" fields + size_t 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 @@ -590,7 +605,11 @@ typedef struct TkMainInfo { 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. */ @@ -809,6 +828,9 @@ typedef struct TkWindow { 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 */ } TkWindow; /* @@ -817,13 +839,13 @@ typedef struct TkWindow { */ 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 + size_t charValueLen; /* Length of string in charValuePtr when that * is non-NULL. */ KeySym keysym; /* Key symbol computed after input methods * have been invoked */ @@ -837,6 +859,11 @@ typedef struct { #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 + /* * The following structure is used with TkMakeEnsemble to create ensemble * commands and optionally to create sub-ensembles. @@ -939,6 +966,7 @@ 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 TkMainInfo *tkMainWindowList; @@ -1196,7 +1224,7 @@ MODULE_SCOPE void TkUnderlineCharsInContext(Display *display, const char *string, int numBytes, int x, int y, int firstByte, int lastByte); MODULE_SCOPE void TkpGetFontAttrsForChar(Tk_Window tkwin, Tk_Font tkfont, - Tcl_UniChar c, struct TkFontAttributes *faPtr); + int c, struct TkFontAttributes *faPtr); MODULE_SCOPE Tcl_Obj * TkNewWindowObj(Tk_Window tkwin); MODULE_SCOPE void TkpShowBusyWindow(TkBusy busy); MODULE_SCOPE void TkpHideBusyWindow(TkBusy busy); @@ -1208,7 +1236,7 @@ MODULE_SCOPE void TkpCreateBusy(Tk_FakeWin *winPtr, Tk_Window tkRef, MODULE_SCOPE int TkBackgroundEvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, int flags); MODULE_SCOPE void TkSendVirtualEvent(Tk_Window tgtWin, - const char *eventName); + const char *eventName, Tcl_Obj *detail); MODULE_SCOPE Tcl_Command TkMakeEnsemble(Tcl_Interp *interp, const char *nsname, const char *name, ClientData clientData, const TkEnsemble *map); @@ -1217,6 +1245,10 @@ MODULE_SCOPE int TkInitTkCmd(Tcl_Interp *interp, MODULE_SCOPE int TkInitFontchooser(Tcl_Interp *interp, ClientData clientData); 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); #ifdef _WIN32 #define TkParseColor XParseColor @@ -1229,6 +1261,29 @@ MODULE_SCOPE Status TkParseColor (Display * display, MODULE_SCOPE void TkUnixSetXftClipRegion(TkRegion clipRegion); #endif +#if TCL_UTF_MAX > 4 +# 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 + +#ifdef TCL_TYPE_I +/* With TIP #481 available, we don't need to do anything special here */ +#define TkGetStringFromObj(objPtr, lenPtr) \ + Tcl_GetStringFromObj(objPtr, lenPtr) +#define TkGetByteArrayFromObj(objPtr, lenPtr) \ + Tcl_GetByteArrayFromObj(objPtr, lenPtr) +#else +#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); +#endif + /* * Unsupported commands. */ diff --git a/generic/tkIntDecls.h b/generic/tkIntDecls.h index b8addbd..a646779 100644 --- a/generic/tkIntDecls.h +++ b/generic/tkIntDecls.h @@ -104,7 +104,7 @@ 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); @@ -167,7 +167,7 @@ EXTERN void TkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr, /* 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[]); @@ -324,7 +324,7 @@ 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); @@ -488,7 +488,7 @@ 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 */ @@ -496,7 +496,7 @@ 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 */ @@ -504,7 +504,7 @@ 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 */ @@ -512,7 +512,7 @@ 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 */ @@ -520,7 +520,7 @@ 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 */ @@ -528,7 +528,7 @@ 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 */ @@ -550,6 +550,10 @@ 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; @@ -577,7 +581,7 @@ typedef struct TkIntStubs { 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 */ @@ -601,7 +605,7 @@ typedef struct TkIntStubs { 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 */ @@ -664,7 +668,7 @@ typedef struct TkIntStubs { 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 */ @@ -752,21 +756,22 @@ typedef struct TkIntStubs { 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; @@ -1139,6 +1144,8 @@ extern const TkIntStubs *tkIntStubsPtr; (tkIntStubsPtr->tkIntersectAngledTextLayout) /* 183 */ #define TkDrawAngledChars \ (tkIntStubsPtr->tkDrawAngledChars) /* 184 */ +#define TkDebugPhotoStringMatchDef \ + (tkIntStubsPtr->tkDebugPhotoStringMatchDef) /* 185 */ #endif /* defined(USE_TK_STUBS) */ diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h index e48e803..9bc76c0 100644 --- a/generic/tkIntPlatDecls.h +++ b/generic/tkIntPlatDecls.h @@ -224,8 +224,7 @@ EXTERN void TkMacOSXWindowOffset(void *wRef, int *xOffset, EXTERN int TkSetMacColor(unsigned long pixel, void *macColor); /* 39 */ EXTERN void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid); -/* 40 */ -EXTERN void TkSuspendClipboard(void); +/* Slot 40 is reserved */ /* 41 */ EXTERN int TkMacOSXZoomToplevel(void *whichWindow, short zoomPart); @@ -384,7 +383,7 @@ typedef struct TkIntPlatStubs { void (*tkMacOSXWindowOffset) (void *wRef, int *xOffset, int *yOffset); /* 37 */ int (*tkSetMacColor) (unsigned long pixel, void *macColor); /* 38 */ void (*tkSetWMName) (TkWindow *winPtr, Tk_Uid titleUid); /* 39 */ - void (*tkSuspendClipboard) (void); /* 40 */ + void (*reserved40)(void); int (*tkMacOSXZoomToplevel) (void *whichWindow, short zoomPart); /* 41 */ Tk_Window (*tk_TopCoordsToWindow) (Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY); /* 42 */ MacDrawable * (*tkMacOSXContainerId) (TkWindow *winPtr); /* 43 */ @@ -599,8 +598,7 @@ extern const TkIntPlatStubs *tkIntPlatStubsPtr; (tkIntPlatStubsPtr->tkSetMacColor) /* 38 */ #define TkSetWMName \ (tkIntPlatStubsPtr->tkSetWMName) /* 39 */ -#define TkSuspendClipboard \ - (tkIntPlatStubsPtr->tkSuspendClipboard) /* 40 */ +/* Slot 40 is reserved */ #define TkMacOSXZoomToplevel \ (tkIntPlatStubsPtr->tkMacOSXZoomToplevel) /* 41 */ #define Tk_TopCoordsToWindow \ @@ -666,4 +664,7 @@ extern const TkIntPlatStubs *tkIntPlatStubsPtr; #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT +#undef TkWinGetPlatformId +#define TkWinGetPlatformId() (2) /* VER_PLATFORM_WIN32_NT */ + #endif /* _TKINTPLATDECLS */ diff --git a/generic/tkIntXlibDecls.h b/generic/tkIntXlibDecls.h index 6ac7ccb..4efa241 100644 --- a/generic/tkIntXlibDecls.h +++ b/generic/tkIntXlibDecls.h @@ -23,11 +23,25 @@ # include <tcl.h> #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 #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 */ @@ -356,6 +370,61 @@ EXTERN XAfterFunction XSynchronize(Display *display, Bool onoff); EXTERN int XSync(Display *display, Bool discard); /* 114 */ EXTERN VisualID XVisualIDFromVisual(Visual *visual); +/* Slot 115 is reserved */ +/* Slot 116 is reserved */ +/* Slot 117 is reserved */ +/* Slot 118 is reserved */ +/* Slot 119 is reserved */ +/* 120 */ +EXTERN int XOffsetRegion(Region rgn, int dx, int dy); +/* 121 */ +EXTERN int XUnionRegion(Region srca, Region srcb, + Region dr_return); +/* 122 */ +EXTERN Window XCreateWindow(Display *display, Window parent, int x, + int y, unsigned int width, + unsigned int height, + unsigned int border_width, int depth, + unsigned int clazz, Visual *visual, + unsigned long value_mask, + XSetWindowAttributes *attributes); +/* Slot 123 is reserved */ +/* Slot 124 is reserved */ +/* Slot 125 is reserved */ +/* Slot 126 is reserved */ +/* Slot 127 is reserved */ +/* Slot 128 is reserved */ +/* 129 */ +EXTERN int XLowerWindow(Display *d, Window w); +/* 130 */ +EXTERN int XFillArcs(Display *d, Drawable dr, GC gc, XArc *a, + int n); +/* 131 */ +EXTERN int XDrawArcs(Display *d, Drawable dr, GC gc, XArc *a, + int n); +/* 132 */ +EXTERN int XDrawRectangles(Display *d, Drawable dr, GC gc, + XRectangle *r, int n); +/* 133 */ +EXTERN int XDrawSegments(Display *d, Drawable dr, GC gc, + XSegment *s, int n); +/* 134 */ +EXTERN int XDrawPoint(Display *d, Drawable dr, GC gc, int x, + int y); +/* 135 */ +EXTERN int XDrawPoints(Display *d, Drawable dr, GC gc, + XPoint *p, int n, int m); +/* 136 */ +EXTERN int XReparentWindow(Display *d, Window w, Window p, + 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 */ @@ -584,7 +653,7 @@ EXTERN void XSetWMClientMachine(Display *display, Window w, EXTERN Status XStringListToTextProperty(char **list, int count, XTextProperty *text_prop_return); /* 80 */ -EXTERN void XDrawSegments(Display *display, Drawable d, GC gc, +EXTERN int XDrawSegments(Display *display, Drawable d, GC gc, XSegment *segments, int nsegments); /* 81 */ EXTERN void XForceScreenSaver(Display *display, int mode); @@ -598,10 +667,10 @@ EXTERN int XFillRectangle(Display *display, Drawable d, GC gc, /* 84 */ EXTERN void XClearWindow(Display *d, Window w); /* 85 */ -EXTERN void XDrawPoint(Display *display, Drawable d, GC gc, +EXTERN int XDrawPoint(Display *display, Drawable d, GC gc, int x, int y); /* 86 */ -EXTERN void XDrawPoints(Display *display, Drawable d, GC gc, +EXTERN int XDrawPoints(Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode); /* 87 */ EXTERN int XWarpPointer(Display *display, Window src_w, @@ -742,6 +811,31 @@ typedef struct TkIntXlibStubs { XAfterFunction (*xSynchronize) (Display *display, Bool onoff); /* 112 */ int (*xSync) (Display *display, Bool discard); /* 113 */ VisualID (*xVisualIDFromVisual) (Visual *visual); /* 114 */ + void (*reserved115)(void); + void (*reserved116)(void); + void (*reserved117)(void); + void (*reserved118)(void); + void (*reserved119)(void); + int (*xOffsetRegion) (Region rgn, int dx, int dy); /* 120 */ + int (*xUnionRegion) (Region srca, Region srcb, Region dr_return); /* 121 */ + Window (*xCreateWindow) (Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long value_mask, XSetWindowAttributes *attributes); /* 122 */ + void (*reserved123)(void); + void (*reserved124)(void); + void (*reserved125)(void); + void (*reserved126)(void); + void (*reserved127)(void); + void (*reserved128)(void); + int (*xLowerWindow) (Display *d, Window w); /* 129 */ + int (*xFillArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 130 */ + int (*xDrawArcs) (Display *d, Drawable dr, GC gc, XArc *a, int n); /* 131 */ + int (*xDrawRectangles) (Display *d, Drawable dr, GC gc, XRectangle *r, int n); /* 132 */ + 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 */ @@ -824,13 +918,13 @@ typedef struct TkIntXlibStubs { XVisualInfo * (*xGetVisualInfo) (Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return); /* 77 */ void (*xSetWMClientMachine) (Display *display, Window w, XTextProperty *text_prop); /* 78 */ Status (*xStringListToTextProperty) (char **list, int count, XTextProperty *text_prop_return); /* 79 */ - void (*xDrawSegments) (Display *display, Drawable d, GC gc, XSegment *segments, int nsegments); /* 80 */ + int (*xDrawSegments) (Display *display, Drawable d, GC gc, XSegment *segments, int nsegments); /* 80 */ void (*xForceScreenSaver) (Display *display, int mode); /* 81 */ int (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 82 */ int (*xFillRectangle) (Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height); /* 83 */ void (*xClearWindow) (Display *d, Window w); /* 84 */ - void (*xDrawPoint) (Display *display, Drawable d, GC gc, int x, int y); /* 85 */ - void (*xDrawPoints) (Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode); /* 86 */ + int (*xDrawPoint) (Display *display, Drawable d, GC gc, int x, int y); /* 85 */ + int (*xDrawPoints) (Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode); /* 86 */ int (*xWarpPointer) (Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y); /* 87 */ void (*xQueryColor) (Display *display, Colormap colormap, XColor *def_in_out); /* 88 */ void (*xQueryColors) (Display *display, Colormap colormap, XColor *defs_in_out, int ncolors); /* 89 */ @@ -1081,6 +1175,45 @@ extern const TkIntXlibStubs *tkIntXlibStubsPtr; (tkIntXlibStubsPtr->xSync) /* 113 */ #define XVisualIDFromVisual \ (tkIntXlibStubsPtr->xVisualIDFromVisual) /* 114 */ +/* Slot 115 is reserved */ +/* Slot 116 is reserved */ +/* Slot 117 is reserved */ +/* Slot 118 is reserved */ +/* Slot 119 is reserved */ +#define XOffsetRegion \ + (tkIntXlibStubsPtr->xOffsetRegion) /* 120 */ +#define XUnionRegion \ + (tkIntXlibStubsPtr->xUnionRegion) /* 121 */ +#define XCreateWindow \ + (tkIntXlibStubsPtr->xCreateWindow) /* 122 */ +/* Slot 123 is reserved */ +/* Slot 124 is reserved */ +/* Slot 125 is reserved */ +/* Slot 126 is reserved */ +/* Slot 127 is reserved */ +/* Slot 128 is reserved */ +#define XLowerWindow \ + (tkIntXlibStubsPtr->xLowerWindow) /* 129 */ +#define XFillArcs \ + (tkIntXlibStubsPtr->xFillArcs) /* 130 */ +#define XDrawArcs \ + (tkIntXlibStubsPtr->xDrawArcs) /* 131 */ +#define XDrawRectangles \ + (tkIntXlibStubsPtr->xDrawRectangles) /* 132 */ +#define XDrawSegments \ + (tkIntXlibStubsPtr->xDrawSegments) /* 133 */ +#define XDrawPoint \ + (tkIntXlibStubsPtr->xDrawPoint) /* 134 */ +#define XDrawPoints \ + (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 \ diff --git a/generic/tkListbox.c b/generic/tkListbox.c index c7effdd..b3b8ce7 100644 --- a/generic/tkListbox.c +++ b/generic/tkListbox.c @@ -12,8 +12,8 @@ * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "default.h" #include "tkInt.h" +#include "default.h" #ifdef _WIN32 #include "tkWinInt.h" @@ -567,7 +567,7 @@ Tk_ListboxObjCmd( 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; @@ -682,7 +682,7 @@ ListboxWidgetObjCmd( break; } - objPtr = Tk_GetOptionValue(interp, (char *) listPtr, + objPtr = Tk_GetOptionValue(interp, listPtr, listPtr->optionTable, objv[2], listPtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; @@ -694,7 +694,7 @@ ListboxWidgetObjCmd( 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) { @@ -926,7 +926,7 @@ ListboxWidgetObjCmd( 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) { @@ -1102,7 +1102,8 @@ ListboxBboxSubCmd( 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; + size_t stringLen; Tk_FontMetrics fm; /* @@ -1114,7 +1115,7 @@ ListboxBboxSubCmd( return result; } - stringRep = Tcl_GetStringFromObj(el, &stringLen); + stringRep = TkGetStringFromObj(el, &stringLen); Tk_GetFontMetrics(listPtr->tkfont, &fm); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); @@ -1415,7 +1416,7 @@ ListboxGetItemAttributes( 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 { @@ -1565,7 +1566,7 @@ ConfigureListbox( Tcl_Obj *errorResult = NULL; int oldExport, error; - oldExport = listPtr->exportSelection; + oldExport = (listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp)); if (listPtr->listVarName != NULL) { Tcl_UntraceVar2(interp, listPtr->listVarName, NULL, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, @@ -1578,7 +1579,7 @@ ConfigureListbox( * 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; @@ -1607,10 +1608,11 @@ ConfigureListbox( /* * Claim the selection if we've suddenly started exporting it and - * there is a selection to export. + * there is a selection to export and this interp is unsafe. */ - if (listPtr->exportSelection && !oldExport + if (listPtr->exportSelection && (!oldExport) + && (!Tcl_IsSafe(listPtr->interp)) && (listPtr->numSelected != 0)) { Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection, listPtr); @@ -1723,7 +1725,7 @@ ConfigureListboxItem( { 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); @@ -1839,7 +1841,8 @@ DisplayListbox( 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; + size_t stringLen; Tk_FontMetrics fm; Tcl_Obj *curElement; Tcl_HashEntry *entry; @@ -2073,7 +2076,7 @@ DisplayListbox( */ 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); @@ -2235,7 +2238,8 @@ ListboxComputeGeometry( * Tk_UnsetGrid to update gridding for the * window. */ { - int width, height, pixelWidth, pixelHeight, textLength, i, result; + int width, height, pixelWidth, pixelHeight, i, result; + size_t textLength; Tk_FontMetrics fm; Tcl_Obj *element; const char *text; @@ -2256,7 +2260,7 @@ ListboxComputeGeometry( 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) { @@ -2322,7 +2326,8 @@ ListboxInsertSubCmd( 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; + size_t length; Tcl_Obj *newListObj; const char *stringRep; @@ -2333,7 +2338,7 @@ ListboxInsertSubCmd( * 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; @@ -2436,7 +2441,8 @@ ListboxDeleteSubCmd( 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; + size_t length; Tcl_Obj *newListObj, *element; const char *stringRep; Tcl_HashEntry *entry; @@ -2491,7 +2497,7 @@ ListboxDeleteSubCmd( 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; @@ -3079,7 +3085,8 @@ ListboxSelect( EventuallyRedrawRange(listPtr, first, last); } if ((oldCount == 0) && (listPtr->numSelected > 0) - && listPtr->exportSelection) { + && (listPtr->exportSelection) + && (!Tcl_IsSafe(listPtr->interp))) { Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection, listPtr); } @@ -3120,12 +3127,13 @@ ListboxFetchSelection( { register Listbox *listPtr = clientData; Tcl_DString selection; - int length, count, needNewline, stringLen, i; + int count, needNewline, i; + size_t length, stringLen; Tcl_Obj *curElement; const char *stringRep; Tcl_HashEntry *entry; - if (!listPtr->exportSelection) { + if ((!listPtr->exportSelection) || Tcl_IsSafe(listPtr->interp)) { return -1; } @@ -3143,7 +3151,7 @@ ListboxFetchSelection( } 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,14 +3166,14 @@ ListboxFetchSelection( * Copy the requested portion of the selection to the buffer. */ - count = length - offset; - if (count <= 0) { + if (length <= (size_t)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); @@ -3196,7 +3204,8 @@ ListboxLostSelection( { register Listbox *listPtr = clientData; - if ((listPtr->exportSelection) && (listPtr->nElements > 0)) { + if ((listPtr->exportSelection) && (!Tcl_IsSafe(listPtr->interp)) + && (listPtr->nElements > 0)) { ListboxSelect(listPtr, 0, listPtr->nElements-1, 0); GenerateListboxSelectEvent(listPtr); } @@ -3223,16 +3232,7 @@ static void GenerateListboxSelectEvent( Listbox *listPtr) /* Information about widget. */ { - union {XEvent general; XVirtualEvent virtual;} event; - - memset(&event, 0, sizeof(event)); - event.general.xany.type = VirtualEvent; - event.general.xany.serial = NextRequest(Tk_Display(listPtr->tkwin)); - event.general.xany.send_event = False; - event.general.xany.window = Tk_WindowId(listPtr->tkwin); - event.general.xany.display = Tk_Display(listPtr->tkwin); - event.virtual.name = Tk_GetUid("ListboxSelect"); - Tk_HandleEvent(&event.general); + TkSendVirtualEvent(listPtr->tkwin, "ListboxSelect", NULL); } /* @@ -3437,8 +3437,8 @@ static char * ListboxListVarProc( ClientData clientData, /* Information about button. */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* Not used. */ - const char *name2, /* Not used. */ + const char *name1, /* Name of variable. */ + const char *name2, /* Second part of variable name. */ int flags) /* Information about what happened. */ { Listbox *listPtr = clientData; @@ -3447,6 +3447,19 @@ ListboxListVarProc( 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! */ diff --git a/generic/tkMain.c b/generic/tkMain.c index 1b21223..ffcaecf 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -30,14 +30,6 @@ #endif #include "tkInt.h" -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#ifdef NO_STDLIB_H -# include "../compat/stdlib.h" -#else -# include <stdlib.h> -#endif extern int TkCygwinMainEx(int, char **, Tcl_AppInitProc *, Tcl_Interp *); @@ -196,7 +188,7 @@ Tk_MainEx( * 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 { @@ -235,7 +227,11 @@ Tk_MainEx( 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); #endif @@ -420,14 +416,15 @@ StdinProc( 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 { diff --git a/generic/tkMenu.c b/generic/tkMenu.c index d24516f..14d89cd 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -38,7 +38,7 @@ * 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 @@ -259,6 +259,9 @@ static const Tk_OptionSpec tkMenuConfigSpecs[] = { "Background", DEF_MENU_ACTIVE_FG_COLOR, Tk_Offset(TkMenu, activeFgPtr), -1, 0, (ClientData) DEF_MENU_ACTIVE_FG_MONO, 0}, + {TK_OPTION_RELIEF, "-activerelief", "activeRelief", "Relief", + DEF_MENU_ACTIVE_RELIEF, Tk_Offset(TkMenu, activeReliefPtr), + -1, 0, NULL, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0, (ClientData) DEF_MENU_BG_MONO, 0}, @@ -465,7 +468,7 @@ Tk_MenuObjCmd( 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); @@ -672,7 +675,7 @@ MenuWidgetObjCmd( 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) { @@ -692,7 +695,7 @@ MenuWidgetObjCmd( 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) { @@ -702,7 +705,7 @@ MenuWidgetObjCmd( 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) { @@ -776,7 +779,7 @@ MenuWidgetObjCmd( } 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) { @@ -802,7 +805,7 @@ MenuWidgetObjCmd( 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; @@ -811,7 +814,7 @@ MenuWidgetObjCmd( 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; @@ -1528,7 +1531,7 @@ ConfigureMenu( 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) { @@ -1700,12 +1703,12 @@ PostProcessEntry( if (mePtr->labelPtr == NULL) { mePtr->labelLength = 0; } else { - (void)Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); + (void)TkGetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); } if (mePtr->accelPtr == NULL) { mePtr->accelLength = 0; } else { - (void)Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); + (void)TkGetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); } /* @@ -1924,7 +1927,7 @@ ConfigureMenuEntry( 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; @@ -2298,7 +2301,7 @@ MenuNewEntry( 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; @@ -2495,6 +2498,22 @@ MenuVarProc( } menuPtr = mePtr->menuPtr; + + 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); /* diff --git a/generic/tkMenu.h b/generic/tkMenu.h index bac51aa..6e3c3f4 100644 --- a/generic/tkMenu.h +++ b/generic/tkMenu.h @@ -68,11 +68,15 @@ typedef struct TkMenuEntry { 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. */ +#if TK_MAJOR_VERSION > 8 + size_t labelLength; /* Number of non-NULL characters in label. */ +#else + unsigned int labelLength; /* Number of non-NULL characters in label. */ +#endif 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 None. @@ -89,8 +93,13 @@ typedef struct TkMenuEntry { 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 +#if TK_MAJOR_VERSION > 8 + size_t accelLength; /* Number of non-NULL characters in + * accelerator. */ +#else + unsigned int accelLength; /* Number of non-NULL characters in * accelerator. */ +#endif 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. */ @@ -288,6 +297,7 @@ typedef struct TkMenu { Tcl_Obj *activeBorderWidthPtr; /* Width of border around active element. */ Tcl_Obj *reliefPtr; /* 3-d effect: TK_RELIEF_RAISED, etc. */ + Tcl_Obj *activeReliefPtr; /* 3-d effect for active element. */ Tcl_Obj *fontPtr; /* Text font for menu entries. */ Tcl_Obj *fgPtr; /* Foreground color for entries. */ Tcl_Obj *disabledFgPtr; /* Foreground color when disabled. NULL means diff --git a/generic/tkMenuDraw.c b/generic/tkMenuDraw.c index 1abe1c4..3f492db 100644 --- a/generic/tkMenuDraw.c +++ b/generic/tkMenuDraw.c @@ -624,7 +624,6 @@ DisplayMenu( int width; int borderWidth; Tk_3DBorder border; - int activeBorderWidth; int relief; @@ -636,8 +635,6 @@ DisplayMenu( Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); - Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, - menuPtr->activeBorderWidthPtr, &activeBorderWidth); if (menuPtr->menuType == MENUBAR) { Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth, @@ -668,28 +665,16 @@ DisplayMenu( } mePtr->entryFlags &= ~ENTRY_NEEDS_REDISPLAY; - if (menuPtr->menuType == MENUBAR) { - width = mePtr->width; - } else { - if (mePtr->entryFlags & ENTRY_LAST_COLUMN) { - width = Tk_Width(menuPtr->tkwin) - mePtr->x - - activeBorderWidth; - } else { - width = mePtr->width + borderWidth; - } - } TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont, - &menuMetrics, mePtr->x, mePtr->y, width, + &menuMetrics, mePtr->x, mePtr->y, mePtr->width, mePtr->height, strictMotif, 1); if ((index > 0) && (menuPtr->menuType != MENUBAR) && mePtr->columnBreak) { mePtr = menuPtr->entries[index - 1]; Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, - mePtr->x, mePtr->y + mePtr->height, - mePtr->width, - Tk_Height(tkwin) - mePtr->y - mePtr->height - - activeBorderWidth, 0, - TK_RELIEF_FLAT); + mePtr->x, mePtr->y + mePtr->height, mePtr->width, + Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth, + 0, TK_RELIEF_FLAT); } } @@ -698,19 +683,18 @@ DisplayMenu( if (menuPtr->numEntries == 0) { x = y = borderWidth; - width = Tk_Width(tkwin) - 2 * activeBorderWidth; - height = Tk_Height(tkwin) - 2 * activeBorderWidth; + width = Tk_Width(tkwin) - 2 * borderWidth; + height = Tk_Height(tkwin) - 2 * borderWidth; } else { mePtr = menuPtr->entries[menuPtr->numEntries - 1]; Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, mePtr->x, mePtr->y + mePtr->height, mePtr->width, - Tk_Height(tkwin) - mePtr->y - mePtr->height - - activeBorderWidth, 0, - TK_RELIEF_FLAT); + Tk_Height(tkwin) - mePtr->y - mePtr->height - borderWidth, + 0, TK_RELIEF_FLAT); x = mePtr->x + mePtr->width; y = mePtr->y + mePtr->height; - width = Tk_Width(tkwin) - x - activeBorderWidth; - height = Tk_Height(tkwin) - y - activeBorderWidth; + width = Tk_Width(tkwin) - x - borderWidth; + height = Tk_Height(tkwin) - y - borderWidth; } Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y, width, height, 0, TK_RELIEF_FLAT); diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c index 1a4d5ae..125fe72 100644 --- a/generic/tkMenubutton.c +++ b/generic/tkMenubutton.c @@ -308,7 +308,7 @@ Tk_MenubuttonObjCmd( 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; } @@ -369,7 +369,7 @@ MenuButtonWidgetObjCmd( goto error; } - objPtr = Tk_GetOptionValue(interp, (char *) mbPtr, + objPtr = Tk_GetOptionValue(interp, mbPtr, mbPtr->optionTable, objv[2], mbPtr->tkwin); if (objPtr == NULL) { goto error; @@ -379,7 +379,7 @@ MenuButtonWidgetObjCmd( 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) { @@ -524,7 +524,7 @@ ConfigureMenuButton( * 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; @@ -882,6 +882,19 @@ MenuButtonTextVarProc( 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. */ diff --git a/generic/tkMessage.c b/generic/tkMessage.c index 2b71998..c009fe7 100644 --- a/generic/tkMessage.c +++ b/generic/tkMessage.c @@ -13,8 +13,8 @@ * 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 @@ -242,7 +242,7 @@ Tk_MessageObjCmd( 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. @@ -267,7 +267,7 @@ Tk_MessageObjCmd( 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; } @@ -331,7 +331,7 @@ MessageWidgetObjCmd( 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; @@ -343,7 +343,7 @@ MessageWidgetObjCmd( 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) { @@ -455,7 +455,7 @@ ConfigureMessage( 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; @@ -839,6 +839,19 @@ MessageTextVarProc( 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. */ diff --git a/generic/tkObj.c b/generic/tkObj.c index 7c09656..b857d98 100644 --- a/generic/tkObj.c +++ b/generic/tkObj.c @@ -73,8 +73,12 @@ typedef struct MMRep { 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; /* @@ -104,7 +108,7 @@ static const Tcl_ObjType pixelObjType = { FreePixelInternalRep, /* freeIntRepProc */ DupPixelInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetPixelFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* @@ -118,7 +122,7 @@ static const Tcl_ObjType mmObjType = { FreeMMInternalRep, /* freeIntRepProc */ DupMMInternalRep, /* dupIntRepProc */ UpdateStringOfMM, /* updateStringProc */ - SetMMFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* @@ -131,7 +135,7 @@ static const Tcl_ObjType windowObjType = { FreeWindowInternalRep, /* freeIntRepProc */ DupWindowInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetWindowFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* @@ -153,8 +157,19 @@ GetTypeCache(void) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (tsdPtr->doubleTypePtr == NULL) { - tsdPtr->doubleTypePtr = Tcl_GetObjType("double"); - tsdPtr->intTypePtr = Tcl_GetObjType("int"); + /* Smart initialization of doubleTypePtr/intTypePtr without + * hash-table lookup or creating complete Tcl_Obj's */ + Tcl_Obj obj; + obj.length = 3; + obj.bytes = (char *)"0.0"; + obj.typePtr = NULL; + Tcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue); + tsdPtr->doubleTypePtr = obj.typePtr; + obj.bytes += 2; + obj.length = 1; + obj.typePtr = NULL; + Tcl_GetLongFromObj(NULL, &obj, &obj.internalRep.longValue); + tsdPtr->intTypePtr = obj.typePtr; } return tsdPtr; } @@ -657,7 +672,7 @@ UpdateStringOfMM( { MMRep *mmPtr; char buffer[TCL_DOUBLE_SPACE]; - register int len; + size_t len; mmPtr = objPtr->internalRep.twoPtrValue.ptr1; /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */ @@ -666,7 +681,7 @@ UpdateStringOfMM( } Tcl_PrintDouble(NULL, mmPtr->value, buffer); - len = (int)strlen(buffer); + len = strlen(buffer); objPtr->bytes = ckalloc(len + 1); strcpy(objPtr->bytes, buffer); @@ -881,7 +896,7 @@ SetWindowFromAny( * Free the old internalRep before setting the new one. */ - (void)Tcl_GetString(objPtr); + Tcl_GetString(objPtr); typePtr = objPtr->typePtr; if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { typePtr->freeIntRepProc(objPtr); @@ -1112,7 +1127,7 @@ TkParsePadAmount( * None * * Side effects: - * All instances of Tcl_ObjType structues used in Tk are registered with + * All instances of Tcl_ObjType structures used in Tk are registered with * Tcl. * *---------------------------------------------------------------------- diff --git a/generic/tkOldConfig.c b/generic/tkOldConfig.c index 920d93e..4473a3e 100644 --- a/generic/tkOldConfig.c +++ b/generic/tkOldConfig.c @@ -25,20 +25,24 @@ #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); @@ -340,10 +344,10 @@ DoConfig( 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; @@ -353,7 +357,7 @@ DoConfig( } 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) { @@ -689,7 +693,7 @@ FormatConfigInfo( 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]; @@ -755,7 +759,7 @@ FormatConfigValue( 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. */ @@ -763,10 +767,11 @@ FormatConfigValue( * 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: diff --git a/generic/tkOldTest.c b/generic/tkOldTest.c index df1bb6c..f78ebba 100644 --- a/generic/tkOldTest.c +++ b/generic/tkOldTest.c @@ -172,9 +172,9 @@ ImageCreate( timPtr->interp = interp; timPtr->width = 30; timPtr->height = 15; - timPtr->imageName = ckalloc((unsigned) (strlen(name) + 1)); + timPtr->imageName = ckalloc(strlen(name) + 1); strcpy(timPtr->imageName, name); - timPtr->varName = ckalloc((unsigned) (strlen(varName) + 1)); + timPtr->varName = ckalloc(strlen(varName) + 1); strcpy(timPtr->varName, varName); Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL); *clientDataPtr = timPtr; diff --git a/generic/tkOption.c b/generic/tkOption.c index 24e7fb3..cebb86a 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.c @@ -260,7 +260,7 @@ Tk_AddOption( 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 = @@ -311,7 +311,7 @@ Tk_AddOption( 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))) { @@ -1081,7 +1081,8 @@ ReadOptionFile( { const char *realName; Tcl_Obj *buffer; - int result, bufferSize; + int result; + size_t bufferSize; Tcl_Channel chan; Tcl_DString newName; @@ -1112,7 +1113,7 @@ ReadOptionFile( 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))); diff --git a/generic/tkPack.c b/generic/tkPack.c index 88a4b2d..d7fabca 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -122,8 +122,10 @@ 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); @@ -197,11 +199,14 @@ Tk_PackObjCmd( 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; @@ -219,6 +224,7 @@ Tk_PackObjCmd( 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 @@ -228,11 +234,13 @@ Tk_PackObjCmd( 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; @@ -297,6 +305,7 @@ Tk_PackObjCmd( } return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3); } +#endif /* !TK_NO_DEPRECATED */ case PACK_CONFIGURE: if (argv2[0] != '.') { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -458,6 +467,7 @@ Tk_PackObjCmd( Tcl_SetObjResult(interp, resultObj); break; } +#ifndef TK_NO_DEPRECATED case PACK_UNPACK: { Tk_Window tkwin2; Packer *packPtr; @@ -481,6 +491,7 @@ Tk_PackObjCmd( } break; } +#endif /* !TK_NO_DEPRECATED */ } return TCL_OK; @@ -1087,6 +1098,7 @@ GetPacker( *------------------------------------------------------------------------ */ +#ifndef TK_NO_DEPRECATED static int PackAfter( Tcl_Interp *interp, /* Interpreter for error reporting. */ @@ -1169,8 +1181,8 @@ PackAfter( 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; + size_t length; + const char *curOpt = TkGetStringFromObj(curOptPtr, &length); c = curOpt[0]; @@ -1307,6 +1319,7 @@ PackAfter( } return TCL_OK; } +#endif /* !TK_NO_DEPRECATED */ /* *---------------------------------------------------------------------- @@ -1362,7 +1375,7 @@ Unlink( * handling it and should mark it as free. */ - if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) { + if ((masterPtr->slavePtr == NULL) && (masterPtr->flags & ALLOCED_MASTER)) { TkFreeGeometryMaster(masterPtr->tkwin, "pack"); masterPtr->flags &= ~ALLOCED_MASTER; } diff --git a/generic/tkPanedWindow.c b/generic/tkPanedWindow.c index 2451647..c0bbf5f 100644 --- a/generic/tkPanedWindow.c +++ b/generic/tkPanedWindow.c @@ -13,8 +13,8 @@ * 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 @@ -236,7 +236,7 @@ static void AdjustForSticky(int sticky, int cavityWidth, 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, int offset); static int PanedWindowIdentifyCoords(PanedWindow *pwPtr, Tcl_Interp *interp, int x, int y); @@ -459,7 +459,7 @@ Tk_PanedWindowObjCmd( 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; @@ -578,7 +578,7 @@ PanedWindowWidgetObjCmd( 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; @@ -590,7 +590,7 @@ PanedWindowWidgetObjCmd( 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) { @@ -669,7 +669,7 @@ PanedWindowWidgetObjCmd( 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); } } @@ -709,7 +709,7 @@ PanedWindowWidgetObjCmd( 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) { @@ -848,7 +848,7 @@ ConfigureSlaves( */ 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; @@ -925,7 +925,7 @@ ConfigureSlaves( 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) { @@ -972,9 +972,9 @@ ConfigureSlaves( 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; @@ -1249,7 +1249,7 @@ ConfigurePanedWindow( 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; @@ -1370,11 +1370,15 @@ PanedWindowEventProc( DestroyPanedWindow(pwPtr); } else if (eventPtr->type == UnmapNotify) { for (i = 0; i < pwPtr->numSlaves; i++) { - Tk_UnmapWindow(pwPtr->slaves[i]->tkwin); + if (!pwPtr->slaves[i]->hide) { + Tk_UnmapWindow(pwPtr->slaves[i]->tkwin); + } } } else if (eventPtr->type == MapNotify) { for (i = 0; i < pwPtr->numSlaves; i++) { - Tk_MapWindow(pwPtr->slaves[i]->tkwin); + if (!pwPtr->slaves[i]->hide) { + Tk_MapWindow(pwPtr->slaves[i]->tkwin); + } } } } @@ -1480,10 +1484,10 @@ DisplayPanedWindow( */ 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; } @@ -1750,7 +1754,7 @@ ArrangePanes( */ 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; @@ -1785,10 +1789,18 @@ ArrangePanes( */ if (horizontal) { - paneSize = slavePtr->paneWidth; + if (slavePtr->width > 0) { + paneSize = slavePtr->width; + } else { + paneSize = slavePtr->paneWidth; + } stretchReserve -= paneSize + (2 * slavePtr->padx); } else { - paneSize = slavePtr->paneHeight; + if (slavePtr->height > 0) { + paneSize = slavePtr->height; + } else { + paneSize = slavePtr->paneHeight; + } stretchReserve -= paneSize + (2 * slavePtr->pady); } if (IsStretchable(slavePtr->stretch,i,first,last) @@ -1838,10 +1850,18 @@ ArrangePanes( */ if (horizontal) { - paneSize = slavePtr->paneWidth; + if (slavePtr->width > 0) { + paneSize = slavePtr->width; + } else { + paneSize = slavePtr->paneWidth; + } pwSize = pwWidth; } else { - paneSize = slavePtr->paneHeight; + if (slavePtr->height > 0) { + paneSize = slavePtr->height; + } else { + paneSize = slavePtr->paneHeight; + } pwSize = pwHeight; } if (IsStretchable(slavePtr->stretch, i, first, last)) { @@ -2180,7 +2200,7 @@ ComputeGeometry( pwPtr->flags |= REQUESTED_RELAYOUT; - x = y = internalBw = Tk_InternalBorderWidth(pwPtr->tkwin); + x = y = internalBw = Tk_InternalBorderLeft(pwPtr->tkwin); reqWidth = reqHeight = 0; /* @@ -2435,7 +2455,8 @@ SetSticky( 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); @@ -2886,7 +2907,7 @@ PanedWindowProxyCommand( return TCL_ERROR; } - internalBW = Tk_InternalBorderWidth(pwPtr->tkwin); + internalBW = Tk_InternalBorderLeft(pwPtr->tkwin); if (pwPtr->orient == ORIENT_HORIZONTAL) { if (x < 0) { x = 0; @@ -2895,10 +2916,10 @@ PanedWindowProxyCommand( 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; @@ -2907,10 +2928,10 @@ PanedWindowProxyCommand( 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) { @@ -2972,16 +2993,13 @@ static int ObjectIsEmpty( Tcl_Obj *objPtr) /* Object to test. May be NULL. */ { - int length; - if (objPtr == NULL) { return 1; } - if (objPtr->bytes != NULL) { - return (objPtr->length == 0); + if (objPtr->bytes == NULL) { + Tcl_GetString(objPtr); } - (void)Tcl_GetStringFromObj(objPtr, &length); - return (length == 0); + return (objPtr->length == 0); } /* @@ -3002,13 +3020,13 @@ ObjectIsEmpty( *---------------------------------------------------------------------- */ -static char * +static void * ComputeSlotAddress( - char *recordPtr, /* Pointer to the start of a record. */ + void *recordPtr, /* Pointer to the start of a record. */ int offset) /* Offset of a slot within that record; may be < 0. */ { if (offset >= 0) { - return recordPtr + offset; + return (char *)recordPtr + offset; } else { return NULL; } @@ -3049,7 +3067,7 @@ PanedWindowIdentifyCoords( } 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; @@ -3077,7 +3095,7 @@ PanedWindowIdentifyCoords( } else { sashWidth = Tk_ReqWidth(pwPtr->tkwin); } - sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); + sashWidth -= 2 * Tk_InternalBorderLeft(pwPtr->tkwin); lpad = rpad = 0; } diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 9fa406a..e627794 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -290,7 +290,7 @@ Tk_PlaceObjCmd( 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; @@ -628,7 +628,7 @@ ConfigureSlave( 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; } diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c index 50b5f1a..4d48fe7 100644 --- a/generic/tkRectOval.c +++ b/generic/tkRectOval.c @@ -759,11 +759,103 @@ DisplayRectOval( &x1, &y1); Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3], &x2, &y2); - if (x2 <= x1) { - x2 = x1+1; - } - if (y2 <= y1) { - y2 = y1+1; + if (x2 == x1) { + + /* + * The width of the bounding box corresponds to less than one pixel + * on screen. Adjustment is needed to avoid drawing attempts with zero + * width items (which would draw nothing). The bounding box spans + * either 1 or 2 pixels. Select which pixel will be drawn. + */ + + short ix1 = (short) (rectOvalPtr->bbox[0]); + short ix2 = (short) (rectOvalPtr->bbox[2]); + + if (ix1 == ix2) { + + /* + * x1 and x2 are "within the same pixel". Use this pixel. + * Note: the degenerated case (bbox[0]==bbox[2]) of a completely + * flat box results in arbitrary selection of the pixel at the + * right (with positive coordinate) or left (with negative + * coordinate) of the box. There is no "best choice" here. + */ + + if (ix1 > 0) { + x2 += 1; + } else { + x1 -= 1; + } + } else { + + /* + * (x1,x2) span two pixels. Select the one with the larger + * covered "area". + */ + + if (ix1 > 0) { + if ((rectOvalPtr->bbox[2] - ix2) > (ix2 - rectOvalPtr->bbox[0])) { + x2 += 1; + } else { + x1 -= 1; + } + } else { + if ((rectOvalPtr->bbox[2] - ix1) > (ix1 - rectOvalPtr->bbox[0])) { + x2 += 1; + } else { + x1 -= 1; + } + } + } + } + if (y2 == y1) { + + /* + * The height of the bounding box corresponds to less than one pixel + * on screen. Adjustment is needed to avoid drawing attempts with zero + * height items (which would draw nothing). The bounding box spans + * either 1 or 2 pixels. Select which pixel will be drawn. + */ + + short iy1 = (short) (rectOvalPtr->bbox[1]); + short iy2 = (short) (rectOvalPtr->bbox[3]); + + if (iy1 == iy2) { + + /* + * y1 and y2 are "within the same pixel". Use this pixel. + * Note: the degenerated case (bbox[1]==bbox[3]) of a completely + * flat box results in arbitrary selection of the pixel below + * (with positive coordinate) or above (with negative coordinate) + * the box. There is no "best choice" here. + */ + + if (iy1 > 0) { + y2 += 1; + } else { + y1 -= 1; + } + } else { + + /* + * (y1,y2) span two pixels. Select the one with the larger + * covered "area". + */ + + if (iy1 > 0) { + if ((rectOvalPtr->bbox[3] - iy2) > (iy2 - rectOvalPtr->bbox[1])) { + y2 += 1; + } else { + y1 -= 1; + } + } else { + if ((rectOvalPtr->bbox[3] - iy1) > (iy1 - rectOvalPtr->bbox[1])) { + y2 += 1; + } else { + y1 -= 1; + } + } + } } /* diff --git a/generic/tkScale.c b/generic/tkScale.c index cc7c294..8b016a2 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -17,9 +17,13 @@ * 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 /* * The following table defines the legal values for the -orient option. It is @@ -296,13 +300,19 @@ Tk_ScaleObjCmd( 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; } + /* + * The widget was just created, no command callback must be invoked. + */ + + scalePtr->flags &= ~INVOKE_COMMAND; + Tcl_SetObjResult(interp, TkNewWindowObj(scalePtr->tkwin)); return TCL_OK; } @@ -353,7 +363,7 @@ ScaleWidgetObjCmd( 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; @@ -362,7 +372,7 @@ ScaleWidgetObjCmd( 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) { @@ -572,7 +582,7 @@ ConfigureScale( * 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; @@ -628,7 +638,7 @@ ConfigureScale( ComputeFormat(scalePtr); - scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0; + scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0; Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder); @@ -671,9 +681,9 @@ ConfigureScale( } else { char varString[TCL_DOUBLE_SPACE], scaleString[TCL_DOUBLE_SPACE]; - sprintf(varString, scalePtr->format, varValue); - sprintf(scaleString, scalePtr->format, scalePtr->value); - if (strcmp(varString, scaleString)) { + Tcl_PrintDouble(NULL, varValue, varString); + Tcl_PrintDouble(NULL, scalePtr->value, scaleString); + if (strcmp(varString, scaleString)) { ScaleSetVariable(scalePtr); } } @@ -930,10 +940,16 @@ ComputeScaleGeometry( * whichever length is longer. */ - sprintf(valueString, scalePtr->format, scalePtr->fromValue); + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + scalePtr->fromValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); - sprintf(valueString, scalePtr->format, scalePtr->toValue); + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + scalePtr->toValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1); if (valuePixels < tmp) { valuePixels = tmp; @@ -1177,6 +1193,19 @@ ScaleVarProc( 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. */ @@ -1268,7 +1297,14 @@ TkScaleSetValue( return; } scalePtr->value = value; - if (invokeCommand) { + + /* + * Schedule command callback invocation only if there is such a command + * already registered, otherwise the callback would trigger later when + * configuring the widget -command option even if the value did not change. + */ + + if ((invokeCommand) && (scalePtr->command != NULL)) { scalePtr->flags |= INVOKE_COMMAND; } TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER); @@ -1301,7 +1337,10 @@ ScaleSetVariable( if (scalePtr->varNamePtr != NULL) { char string[TCL_DOUBLE_SPACE]; - sprintf(string, scalePtr->format, scalePtr->value); + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + scalePtr->value) < 0) { + string[TCL_DOUBLE_SPACE - 1] = '\0'; + } scalePtr->flags |= SETTING_VAR; Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL, Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY); diff --git a/generic/tkScale.h b/generic/tkScale.h index 4fd9995..043d23c 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -73,7 +73,7 @@ typedef struct TkScale { * values. 0 means we get to choose the number * based on resolution and/or the range of the * scale. */ - char format[10]; /* Sprintf conversion specifier computed from + char format[16]; /* Sprintf conversion specifier computed from * digits and other information. */ double bigIncrement; /* Amount to use for large increments to scale * value. (0 means we pick a value). */ @@ -85,7 +85,11 @@ typedef struct TkScale { 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. */ +#if TK_MAJOR_VERSION > 8 + size_t labelLength; /* Number of non-NULL chars. in label. */ +#else + unsigned int labelLength; /* Number of non-NULL chars. in label. */ +#endif enum state state; /* Values are active, normal, or disabled. * Value of scale cannot be changed when * disabled. */ diff --git a/generic/tkScrollbar.c b/generic/tkScrollbar.c index 5017d30..02fb740 100644 --- a/generic/tkScrollbar.c +++ b/generic/tkScrollbar.c @@ -179,10 +179,12 @@ Tk_ScrollbarObjCmd( 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 = None; @@ -224,8 +226,8 @@ ScrollbarWidgetObjCmd( Tcl_Obj *const objv[]) /* Argument strings. */ { register TkScrollbar *scrollPtr = clientData; - int result = TCL_OK; - int length, cmdIndex; + int result = TCL_OK, cmdIndex; + size_t length; static const char *const commandNames[] = { "activate", "cget", "configure", "delta", "fraction", "get", "identify", "set", NULL @@ -269,7 +271,7 @@ ScrollbarWidgetObjCmd( 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; @@ -377,17 +379,19 @@ ScrollbarWidgetObjCmd( 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 { +#ifndef TK_NO_DEPRECATED + if (scrollPtr->flags & OLD_STYLE_COMMANDS) { resObjs[0] = Tcl_NewIntObj(scrollPtr->totalUnits); resObjs[1] = Tcl_NewIntObj(scrollPtr->windowUnits); resObjs[2] = Tcl_NewIntObj(scrollPtr->firstUnit); resObjs[3] = Tcl_NewIntObj(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: { @@ -413,8 +417,6 @@ ScrollbarWidgetObjCmd( break; } case COMMAND_SET: { - int totalUnits, windowUnits, firstUnit, lastUnit; - if (objc == 4) { double first, last; @@ -438,8 +440,10 @@ ScrollbarWidgetObjCmd( } 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; } @@ -476,11 +480,10 @@ ScrollbarWidgetObjCmd( 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); diff --git a/generic/tkScrollbar.h b/generic/tkScrollbar.h index b0cd085..99f16a4 100644 --- a/generic/tkScrollbar.h +++ b/generic/tkScrollbar.h @@ -93,21 +93,25 @@ typedef struct TkScrollbar { * 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. */ @@ -144,16 +148,18 @@ typedef struct TkScrollbar { * * 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 /* diff --git a/generic/tkSelect.c b/generic/tkSelect.c index ab9018a..02268d3 100644 --- a/generic/tkSelect.c +++ b/generic/tkSelect.c @@ -26,7 +26,7 @@ typedef struct { 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 @@ -190,8 +190,8 @@ Tk_CreateSelHandler( * should make a copy for this selPtr. */ - unsigned cmdInfoLen = Tk_Offset(CommandInfo, command) + - ((CommandInfo *)clientData)->cmdLength + 1; + unsigned cmdInfoLen = Tk_Offset(CommandInfo, command) + 1 + + ((CommandInfo *)clientData)->cmdLength; selPtr->clientData = ckalloc(cmdInfoLen); memcpy(selPtr->clientData, clientData, cmdInfoLen); @@ -831,7 +831,7 @@ Tk_SelectionObjCmd( const char *targetName = NULL; const char *formatName = NULL; register CommandInfo *cmdInfoPtr; - int cmdLength; + size_t cmdLength; static const char *const handleOptionStrings[] = { "-format", "-selection", "-type", NULL }; @@ -900,7 +900,7 @@ Tk_SelectionObjCmd( } else { format = XA_STRING; } - string = Tcl_GetStringFromObj(objs[1], &cmdLength); + string = TkGetStringFromObj(objs[1], &cmdLength); if (cmdLength == 0) { Tk_DeleteSelHandler(tkwin, selection, target); } else { @@ -1185,6 +1185,7 @@ TkSelInit( dispPtr->applicationAtom = Tk_InternAtom(tkwin, "TK_APPLICATION"); dispPtr->windowAtom = Tk_InternAtom(tkwin, "TK_WINDOW"); dispPtr->clipboardAtom = Tk_InternAtom(tkwin, "CLIPBOARD"); + dispPtr->atomPairAtom = Tk_InternAtom(tkwin, "ATOM_PAIR"); /* * Using UTF8_STRING instead of the XA_UTF8_STRING macro allows us to diff --git a/generic/tkSquare.c b/generic/tkSquare.c index 36d2d6e..2a64dbb 100644 --- a/generic/tkSquare.c +++ b/generic/tkSquare.c @@ -172,7 +172,7 @@ SquareObjCmd( squarePtr->gc = None; 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); @@ -181,7 +181,7 @@ SquareObjCmd( 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; } @@ -250,7 +250,7 @@ SquareWidgetObjCmd( 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; @@ -261,19 +261,19 @@ SquareWidgetObjCmd( 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) { diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index f08d7f4..731fa50 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -38,6 +38,43 @@ MODULE_SCOPE const TkStubs tkStubs; */ #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 @@ -62,6 +99,11 @@ TkCreateXEventSource(void) # define TkUnixContainerId 0 # 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 @@ -200,7 +242,6 @@ void TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c) # define TkWinSetForegroundWindow 0 # define TkWinDialogDebug 0 # define TkWinGetMenuSystemDefault 0 -# define TkWinGetPlatformId 0 # define TkWinSetHINSTANCE 0 # define TkWinGetPlatformTheme 0 # define TkWinChildProc 0 @@ -233,6 +274,14 @@ void TkSubtractRegion (TkRegion a, TkRegion b, TkRegion c) * 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 = { @@ -450,6 +499,7 @@ static const TkIntStubs tkIntStubs = { TkUnderlineAngledTextLayout, /* 182 */ TkIntersectAngledTextLayout, /* 183 */ TkDrawAngledChars, /* 184 */ + TkDebugPhotoStringMatchDef, /* 185 */ }; static const TkIntPlatStubs tkIntPlatStubs = { @@ -544,7 +594,7 @@ static const TkIntPlatStubs tkIntPlatStubs = { TkMacOSXWindowOffset, /* 37 */ TkSetMacColor, /* 38 */ TkSetWMName, /* 39 */ - TkSuspendClipboard, /* 40 */ + 0, /* 40 */ TkMacOSXZoomToplevel, /* 41 */ Tk_TopCoordsToWindow, /* 42 */ TkMacOSXContainerId, /* 43 */ @@ -698,6 +748,31 @@ static const TkIntXlibStubs tkIntXlibStubs = { XSynchronize, /* 112 */ XSync, /* 113 */ XVisualIDFromVisual, /* 114 */ + 0, /* 115 */ + 0, /* 116 */ + 0, /* 117 */ + 0, /* 118 */ + 0, /* 119 */ + XOffsetRegion, /* 120 */ + XUnionRegion, /* 121 */ + XCreateWindow, /* 122 */ + 0, /* 123 */ + 0, /* 124 */ + 0, /* 125 */ + 0, /* 126 */ + 0, /* 127 */ + 0, /* 128 */ + XLowerWindow, /* 129 */ + XFillArcs, /* 130 */ + XDrawArcs, /* 131 */ + XDrawRectangles, /* 132 */ + XDrawSegments, /* 133 */ + XDrawPoint, /* 134 */ + XDrawPoints, /* 135 */ + XReparentWindow, /* 136 */ + XPutImage, /* 137 */ + XPolygonRegion, /* 138 */ + XPointInRegion, /* 139 */ #endif /* WIN */ #ifdef MAC_OSX_TK /* AQUA */ XSetDashes, /* 0 */ diff --git a/generic/tkStyle.c b/generic/tkStyle.c index e7401df..508a2c4 100644 --- a/generic/tkStyle.c +++ b/generic/tkStyle.c @@ -155,7 +155,7 @@ static const Tcl_ObjType styleObjType = { FreeStyleObjProc, /* freeIntRepProc */ DupStyleObjProc, /* dupIntRepProc */ NULL, /* updateStringProc */ - SetStyleFromAny /* setFromAnyProc */ + NULL /* setFromAnyProc */ }; /* @@ -1076,7 +1076,7 @@ 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 @@ -1117,7 +1117,7 @@ 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. */ @@ -1159,7 +1159,7 @@ 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; @@ -1190,7 +1190,7 @@ 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. */ @@ -1405,62 +1405,15 @@ Tk_AllocStyleFromObj( 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); + if (SetStyleFromAny(interp, objPtr) != TCL_OK) { + return NULL; + } } - return objPtr->internalRep.twoPtrValue.ptr1; } /* - *--------------------------------------------------------------------------- - * - * Tk_FreeStyleFromObj -- - * - * No-op. Present only for stubs compatibility. - * - *--------------------------------------------------------------------------- - */ -void -Tk_FreeStyleFromObj( - Tcl_Obj *objPtr) -{ -} - -/* *---------------------------------------------------------------------- * * SetStyleFromAny -- @@ -1469,8 +1422,8 @@ Tk_FreeStyleFromObj( * 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. @@ -1485,6 +1438,7 @@ SetStyleFromAny( { const Tcl_ObjType *typePtr; const char *name; + Tk_Style style; /* * Free the old internalRep before setting the new one. @@ -1496,8 +1450,12 @@ SetStyleFromAny( 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; } diff --git a/generic/tkTest.c b/generic/tkTest.c index fa9e073..0cf1f49 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -168,7 +168,7 @@ static int TestmenubarObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); #endif -#if defined(_WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) static int TestmetricsObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]); @@ -192,6 +192,9 @@ static void CustomOptionFree(ClientData clientData, 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, @@ -203,6 +206,9 @@ static int TrivialConfigObjCmd(ClientData dummy, 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[]); /* *---------------------------------------------------------------------- @@ -227,7 +233,7 @@ Tktest_Init( { 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) { @@ -239,7 +245,7 @@ Tktest_Init( */ if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) { - return TCL_ERROR; + return TCL_ERROR; } Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL); @@ -263,20 +269,24 @@ Tktest_Init( (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) || defined(MAC_OSX_TK) +#if defined(_WIN32) Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd, (ClientData) Tk_MainWindow(interp), NULL); -#elif !defined(__CYGWIN__) +#elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK) Tcl_CreateObjCommand(interp, "testmenubar", TestmenubarObjCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testsend", TkpTestsendCmd, (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testwrapper", TestwrapperObjCmd, (ClientData) Tk_MainWindow(interp), NULL); -#endif /* _WIN32 || MAC_OSX_TK */ +#endif /* _WIN32 */ /* * Create test image type. @@ -452,7 +462,7 @@ TestcursorObjCmd( * 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. * *---------------------------------------------------------------------- @@ -665,7 +675,7 @@ TestobjconfigObjCmd( 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, @@ -673,7 +683,7 @@ TestobjconfigObjCmd( (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); @@ -708,12 +718,12 @@ TestobjconfigObjCmd( 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) { @@ -762,9 +772,9 @@ TestobjconfigObjCmd( 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); @@ -796,7 +806,7 @@ TestobjconfigObjCmd( 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); } @@ -944,7 +954,7 @@ TestobjconfigObjCmd( 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, @@ -952,7 +962,7 @@ TestobjconfigObjCmd( 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); @@ -1005,10 +1015,10 @@ TestobjconfigObjCmd( 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) { @@ -1016,7 +1026,7 @@ TestobjconfigObjCmd( Tcl_GetString(objv[2]), TrivialConfigObjCmd, (ClientData) recordPtr, TrivialCmdDeletedProc); } else { - Tk_FreeConfigOptions((char *) recordPtr, + Tk_FreeConfigOptions(recordPtr, recordPtr->header.optionTable, (Tk_Window) NULL); } } @@ -1045,8 +1055,8 @@ TestobjconfigObjCmd( 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; } @@ -1083,10 +1093,10 @@ TestobjconfigObjCmd( 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) { @@ -1097,7 +1107,7 @@ TestobjconfigObjCmd( TrivialEventProc, recordPtr); Tcl_SetObjResult(interp, objv[2]); } else { - Tk_FreeConfigOptions((char *) recordPtr, + Tk_FreeConfigOptions(recordPtr, recordPtr->header.optionTable, tkwin); } } @@ -1168,7 +1178,7 @@ TrivialConfigObjCmd( 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); @@ -1179,7 +1189,7 @@ TrivialConfigObjCmd( 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; @@ -1187,7 +1197,7 @@ TrivialConfigObjCmd( 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; @@ -1195,7 +1205,7 @@ TrivialConfigObjCmd( 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) { @@ -1204,7 +1214,7 @@ TrivialConfigObjCmd( } 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); @@ -1550,9 +1560,8 @@ ImageDisplay( TImageInstance *instPtr = (TImageInstance *) clientData; char buffer[200 + TCL_INTEGER_SPACE * 6]; - sprintf(buffer, "%s display %d %d %d %d %d %d", - instPtr->masterPtr->imageName, imageX, imageY, width, height, - drawableX, drawableY); + 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); if (width > (instPtr->masterPtr->width - imageX)) { @@ -1765,7 +1774,7 @@ TestmenubarObjCmd( *---------------------------------------------------------------------- */ -#if defined(_WIN32) || defined(MAC_OSX_TK) +#if defined(_WIN32) static int TestmetricsObjCmd( ClientData clientData, /* Main window for application. */ @@ -1776,38 +1785,15 @@ TestmetricsObjCmd( char buf[TCL_INTEGER_SPACE]; int val; -#ifdef _WIN32 if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } -#else - Tk_Window tkwin = (Tk_Window) clientData; - TkWindow *winPtr; - - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "option window"); - return TCL_ERROR; - } - - winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); - if (winPtr == NULL) { - return TCL_ERROR; - } -#endif if (strcmp(Tcl_GetString(objv[1]), "cyvscroll") == 0) { -#ifdef _WIN32 val = GetSystemMetrics(SM_CYVSCROLL); -#else - val = ((TkScrollbar *) winPtr->instanceData)->width; -#endif } else if (strcmp(Tcl_GetString(objv[1]), "cxhscroll") == 0) { -#ifdef _WIN32 val = GetSystemMetrics(SM_CXHSCROLL); -#else - val = ((TkScrollbar *) winPtr->instanceData)->width; -#endif } else { Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]), "\": must be cxhscroll or cyvscroll", NULL); @@ -1896,6 +1882,60 @@ TestpropObjCmd( 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__)) /* *---------------------------------------------------------------------- @@ -1990,7 +2030,7 @@ CustomOptionSet( objEmpty = 0; - if (internalOffset >= 0) { + if (internalOffset != -1) { internalPtr = recordPtr + internalOffset; } else { internalPtr = NULL; @@ -2066,6 +2106,54 @@ CustomOptionFree( 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_NewIntObj(width); + resultObj[1] = Tcl_NewIntObj(height); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObj)); + return TCL_OK; + } else { + return TCL_ERROR; + } +} + + /* * Local Variables: diff --git a/generic/tkText.c b/generic/tkText.c index 3079417..a08878c 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -14,9 +14,9 @@ * 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 @@ -122,7 +122,8 @@ static const Tk_ObjCustomOption lineOption = { static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators", "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1, - Tk_Offset(TkText, autoSeparators), 0, 0, 0}, + Tk_Offset(TkText, autoSeparators), + TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border), 0, DEF_TEXT_BG_MONO, 0}, @@ -193,7 +194,8 @@ static const Tk_OptionSpec optionSpecs[] = { DEF_TEXT_INSERT_WIDTH, -1, Tk_Offset(TkText, insertWidth), 0, 0, 0}, {TK_OPTION_INT, "-maxundo", "maxUndo", "MaxUndo", - DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo), 0, 0, 0}, + DEF_TEXT_MAX_UNDO, -1, Tk_Offset(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, TK_TEXT_LINE_GEOMETRY}, @@ -239,7 +241,8 @@ static const Tk_OptionSpec optionSpecs[] = { DEF_TEXT_TAKE_FOCUS, -1, Tk_Offset(TkText, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-undo", "undo", "Undo", - DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo), 0, 0 , 0}, + DEF_TEXT_UNDO, -1, Tk_Offset(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, TK_TEXT_LINE_GEOMETRY}, @@ -401,6 +404,7 @@ static Tcl_Obj * TextGetText(const TkText *textPtr, const TkTextIndex *index1, const TkTextIndex *index2, int visibleOnly); static void GenerateModifiedEvent(TkText *textPtr); +static void GenerateUndoStackEvent(TkText *textPtr); static void UpdateDirtyFlag(TkSharedText *sharedPtr); static void RunAfterSyncCmd(ClientData clientData); static void TextPushUndoAction(TkText *textPtr, @@ -543,7 +547,7 @@ CreateWidget( Tcl_InitHashTable(&sharedPtr->windowTable, TCL_STRING_KEYS); Tcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS); sharedPtr->undoStack = TkUndoInitStack(interp,0); - sharedPtr->undo = 1; + sharedPtr->undo = 0; sharedPtr->isDirty = 0; sharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; sharedPtr->autoSeparators = 1; @@ -657,7 +661,7 @@ CreateWidget( 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; @@ -760,7 +764,7 @@ TextWidgetObjCmd( 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) { @@ -823,7 +827,7 @@ TextWidgetObjCmd( } 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); @@ -860,28 +864,28 @@ TextWidgetObjCmd( } for (i = 2; i < objc-2; i++) { - int value, length; - const char *option = Tcl_GetString(objv[i]); + int value; + size_t 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, (unsigned) length)) { + if (c == 'c' && !strncmp("-chars", option, length)) { value = CountIndices(textPtr, indexFromPtr, indexToPtr, COUNT_CHARS); } else if (c == 'd' && (length > 8) - && !strncmp("-displaychars", option, (unsigned) length)) { + && !strncmp("-displaychars", option, length)) { value = CountIndices(textPtr, indexFromPtr, indexToPtr, COUNT_DISPLAY_CHARS); } else if (c == 'd' && (length > 8) - && !strncmp("-displayindices", option,(unsigned)length)) { + && !strncmp("-displayindices", option,length)) { value = CountIndices(textPtr, indexFromPtr, indexToPtr, COUNT_DISPLAY_INDICES); } else if (c == 'd' && (length > 8) - && !strncmp("-displaylines", option, (unsigned) length)) { + && !strncmp("-displaylines", option, length)) { TkTextLine *fromPtr, *lastPtr; TkTextIndex index, index2; @@ -919,43 +923,43 @@ TextWidgetObjCmd( * We're going to count up all display lines in the logical * line of 'indexFromPtr' up to, but not including the logical * line of 'indexToPtr' (except if this line is elided), and - * then subtract off what came in too much from elided lines, - * also subtract off what we didn't want from 'from' and add + * then subtract off what came in too much from elided lines, + * also subtract off what we didn't want from 'from' and add * on what we didn't count from 'to'. */ - while (TkTextIndexCmp(&index,indexToPtr) < 0) { + while (TkTextIndexCmp(&index,indexToPtr) < 0) { value += TkTextUpdateOneLine(textPtr, index.linePtr, - 0, &index, 0); + 0, &index, 0); } - index2 = index; - - /* - * Now we need to adjust the count to: - * - subtract off the number of display lines between - * indexToPtr and index2, since we might have skipped past - * indexToPtr, if we have several logical lines in a - * single display line - * - subtract off the number of display lines overcounted - * in the first logical line - * - add on the number of display lines in the last logical - * line - * This logic is still ok if both indexFromPtr and indexToPtr - * are in the same logical line. - */ - - index = *indexToPtr; - index.byteIndex = 0; - while (TkTextIndexCmp(&index,&index2) < 0) { - value -= TkTextUpdateOneLine(textPtr, index.linePtr, - 0, &index, 0); - } + index2 = index; + + /* + * Now we need to adjust the count to: + * - subtract off the number of display lines between + * indexToPtr and index2, since we might have skipped past + * indexToPtr, if we have several logical lines in a + * single display line + * - subtract off the number of display lines overcounted + * in the first logical line + * - add on the number of display lines in the last logical + * line + * This logic is still ok if both indexFromPtr and indexToPtr + * are in the same logical line. + */ + + index = *indexToPtr; + index.byteIndex = 0; + while (TkTextIndexCmp(&index,&index2) < 0) { + value -= TkTextUpdateOneLine(textPtr, index.linePtr, + 0, &index, 0); + } index.linePtr = indexFromPtr->linePtr; index.byteIndex = 0; while (1) { TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL); - if (TkTextIndexCmp(&index,indexFromPtr) >= 0) { + if (TkTextIndexCmp(&index,indexFromPtr) >= 0) { break; } TkTextIndexForwBytes(textPtr, &index, 1, &index); @@ -967,7 +971,7 @@ TextWidgetObjCmd( index.byteIndex = 0; while (1) { TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL); - if (TkTextIndexCmp(&index,indexToPtr) >= 0) { + if (TkTextIndexCmp(&index,indexToPtr) >= 0) { break; } TkTextIndexForwBytes(textPtr, &index, 1, &index); @@ -979,19 +983,19 @@ TextWidgetObjCmd( value = -value; } } else if (c == 'i' - && !strncmp("-indices", option, (unsigned) length)) { + && !strncmp("-indices", option, length)) { value = CountIndices(textPtr, indexFromPtr, indexToPtr, COUNT_INDICES); } else if (c == 'l' - && !strncmp("-lines", option, (unsigned) length)) { + && !strncmp("-lines", option, length)) { value = TkBTreeLinesTo(textPtr, indexToPtr->linePtr) - TkBTreeLinesTo(textPtr, indexFromPtr->linePtr); } else if (c == 'u' - && !strncmp("-update", option, (unsigned) length)) { + && !strncmp("-update", option, length)) { update = 1; continue; } else if (c == 'x' - && !strncmp("-xpixels", option, (unsigned) length)) { + && !strncmp("-xpixels", option, length)) { int x1, x2; TkTextIndex index; @@ -1001,7 +1005,7 @@ TextWidgetObjCmd( TkTextFindDisplayLineEnd(textPtr, &index, 0, &x2); value = x2 - x1; } else if (c == 'y' - && !strncmp("-ypixels", option, (unsigned) length)) { + && !strncmp("-ypixels", option, length)) { if (update) { TkTextUpdateLineMetrics(textPtr, TkBTreeLinesTo(textPtr, indexFromPtr->linePtr), @@ -1151,14 +1155,14 @@ TextWidgetObjCmd( objc++; } useIdx = ckalloc(objc); - memset(useIdx, 0, (unsigned) objc); + memset(useIdx, 0, objc); /* * Do a decreasing order sort so that we delete the end ranges * first to maintain index consistency. */ - qsort(indices, (unsigned) objc / 2, + qsort(indices, objc / 2, 2 * sizeof(TkTextIndex), TextIndexSortProc); lastStart = NULL; @@ -1256,7 +1260,7 @@ TextWidgetObjCmd( Tcl_Obj *objPtr = NULL; int i, found = 0, visible = 0; const char *name; - int length; + size_t length; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, @@ -1272,14 +1276,12 @@ TextWidgetObjCmd( 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, (unsigned) length) == 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++; @@ -1395,14 +1397,14 @@ TextWidgetObjCmd( result = TextPeerCmd(textPtr, interp, objc, objv); break; case TEXT_PENDINGSYNC: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - result = TCL_ERROR; - goto done; - } - Tcl_SetObjResult(interp, - Tcl_NewBooleanObj(TkTextPendingsync(textPtr))); - break; + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + result = TCL_ERROR; + goto done; + } + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(TkTextPendingsync(textPtr))); + break; } case TEXT_REPLACE: { const TkTextIndex *indexFromPtr, *indexToPtr; @@ -1461,7 +1463,7 @@ TextWidgetObjCmd( * unnecessarily. */ - int deleteInsertOffset, insertLength, j; + int deleteInsertOffset, insertLength, j, indexFromLine, indexFromByteOffset; insertLength = 0; for (j = 4; j < objc; j += 2) { @@ -1479,6 +1481,9 @@ TextWidgetObjCmd( deleteInsertOffset = insertLength; } + indexFromLine = TkBTreeLinesTo(textPtr, indexFromPtr->linePtr); + indexFromByteOffset = indexFromPtr->byteIndex; + result = TextReplaceCmd(textPtr, interp, indexFromPtr, indexToPtr, objc, objv, 0); @@ -1487,7 +1492,11 @@ TextWidgetObjCmd( * Move the insertion position to the correct place. */ - TkTextIndexForwChars(NULL, indexFromPtr, + TkTextIndex indexTmp; + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, indexFromLine, + indexFromByteOffset, &indexTmp); + TkTextIndexForwChars(NULL, &indexTmp, deleteInsertOffset, &index, COUNT_INDICES); TkBTreeUnlinkSegment(textPtr->insertMarkPtr, textPtr->insertMarkPtr->body.mark.linePtr); @@ -1535,7 +1544,7 @@ TextWidgetObjCmd( textPtr->afterSyncCmd = cmd; } else { textPtr->afterSyncCmd = cmd; - Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr); + Tcl_DoWhenIdle(RunAfterSyncCmd, (ClientData) textPtr); } break; } else if (objc != 2) { @@ -1566,8 +1575,7 @@ TextWidgetObjCmd( } done: - textPtr->refCount--; - if (textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } return result; @@ -1960,9 +1968,7 @@ DestroyText( * portion of the text widget. */ - sharedTextPtr->refCount--; - - if (sharedTextPtr->refCount > 0) { + if (sharedTextPtr->refCount-- > 1) { TkBTreeRemoveClient(sharedTextPtr->tree, textPtr); /* @@ -2038,13 +2044,12 @@ DestroyText( } textPtr->tkwin = NULL; - textPtr->refCount--; Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd); if (textPtr->afterSyncCmd){ Tcl_DecrRefCount(textPtr->afterSyncCmd); textPtr->afterSyncCmd = NULL; } - if (textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } } @@ -2077,7 +2082,7 @@ ConfigureText( Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_SavedOptions savedOptions; - int oldExport = textPtr->exportSelection; + int oldExport = (textPtr->exportSelection) && (!Tcl_IsSafe(textPtr->interp)); int mask = 0; if (Tk_SetOptions(interp, (char *) textPtr, textPtr->optionTable, @@ -2093,7 +2098,7 @@ ConfigureText( textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo; textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators; - TkUndoSetDepth(textPtr->sharedTextPtr->undoStack, + TkUndoSetMaxDepth(textPtr->sharedTextPtr->undoStack, textPtr->sharedTextPtr->maxUndo); /* @@ -2191,10 +2196,10 @@ ConfigureText( * Also, clamp the insert and current (unshared) marks to the new * -startline/-endline range limits of the widget. All other (shared) * marks are unchanged. - * The return value of TkTextMarkNameToIndex does not need to be - * checked: "insert" and "current" marks always exist, and the - * purpose of the code below precisely is to move them inside the - * -startline/-endline range. + * The return value of TkTextMarkNameToIndex does not need to be + * checked: "insert" and "current" marks always exist, and the + * purpose of the code below precisely is to move them inside the + * -startline/-endline range. */ textPtr->sharedTextPtr->stateEpoch++; @@ -2253,12 +2258,20 @@ ConfigureText( * replaced in the widget record. */ - textPtr->selTagPtr->border = textPtr->selBorder; + if (textPtr->selTagPtr->selBorder == NULL) { + textPtr->selTagPtr->border = textPtr->selBorder; + } else { + textPtr->selTagPtr->selBorder = textPtr->selBorder; + } if (textPtr->selTagPtr->borderWidthPtr != textPtr->selBorderWidthPtr) { textPtr->selTagPtr->borderWidthPtr = textPtr->selBorderWidthPtr; textPtr->selTagPtr->borderWidth = textPtr->selBorderWidth; } - textPtr->selTagPtr->fgColor = textPtr->selFgColorPtr; + if (textPtr->selTagPtr->selFgColor == NULL) { + textPtr->selTagPtr->fgColor = textPtr->selFgColorPtr; + } else { + textPtr->selTagPtr->selFgColor = textPtr->selFgColorPtr; + } textPtr->selTagPtr->affectsDisplay = 0; textPtr->selTagPtr->affectsDisplayGeometry = 0; if ((textPtr->selTagPtr->elideString != NULL) @@ -2277,12 +2290,18 @@ ConfigureText( textPtr->selTagPtr->affectsDisplayGeometry = 1; } if ((textPtr->selTagPtr->border != NULL) + || (textPtr->selTagPtr->selBorder != NULL) || (textPtr->selTagPtr->reliefString != NULL) || (textPtr->selTagPtr->bgStipple != None) || (textPtr->selTagPtr->fgColor != NULL) + || (textPtr->selTagPtr->selFgColor != NULL) || (textPtr->selTagPtr->fgStipple != None) || (textPtr->selTagPtr->overstrikeString != NULL) - || (textPtr->selTagPtr->underlineString != NULL)) { + || (textPtr->selTagPtr->overstrikeColor != NULL) + || (textPtr->selTagPtr->underlineString != NULL) + || (textPtr->selTagPtr->underlineColor != NULL) + || (textPtr->selTagPtr->lMarginColor != NULL) + || (textPtr->selTagPtr->rMarginColor != NULL)) { textPtr->selTagPtr->affectsDisplay = 1; } TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, 1); @@ -2292,7 +2311,7 @@ ConfigureText( * are tagged characters. */ - if (textPtr->exportSelection && (!oldExport)) { + if (textPtr->exportSelection && (!oldExport) && (!Tcl_IsSafe(textPtr->interp))) { TkTextSearch search; TkTextIndex first, last; @@ -2406,7 +2425,7 @@ TextWorldChanged( textPtr->charHeight = 1; } if (textPtr->charHeight != oldCharHeight) { - TkBTreeClientRangeChanged(textPtr, textPtr->charHeight); + TkBTreeClientRangeChanged(textPtr, textPtr->charHeight); } border = textPtr->borderWidth + textPtr->highlightWidth; Tk_GeometryRequest(textPtr->tkwin, @@ -2612,14 +2631,14 @@ InsertChars( * information to add to text. */ int viewUpdate) /* Update the view if set. */ { - int lineIndex, length; + int lineIndex; + size_t 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; } @@ -2711,10 +2730,14 @@ InsertChars( } /* - * Invalidate any selection retrievals in progress. + * Invalidate any selection retrievals in progress, and send an event + * that the selection changed if that is the case. */ for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + if (TkBTreeCharTagged(indexPtr, tPtr->selTagPtr)) { + TkTextSelectionEvent(tPtr); + } tPtr->abortSelections = 1; } @@ -2755,6 +2778,10 @@ TextPushUndoAction( /* Index describing second location. */ { TkUndoSubAtom *iAtom, *dAtom; + int canUndo, canRedo; + char lMarkName[20] = "tk::undoMarkL"; + char rMarkName[20] = "tk::undoMarkR"; + char stringUndoMarkId[7] = ""; /* * Create the helpers. @@ -2765,6 +2792,10 @@ TextPushUndoAction( 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. @@ -2814,6 +2845,40 @@ TextPushUndoAction( 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 @@ -2831,16 +2896,27 @@ TextPushUndoAction( 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); + canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); + canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); + /* * Depending whether the action is to insert or delete, we provide the * appropriate second and third arguments to TkUndoPushAction. (The first @@ -2852,6 +2928,10 @@ TextPushUndoAction( } else { TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom); } + + if (!canUndo || canRedo) { + GenerateUndoStackEvent(textPtr); + } } /* @@ -3016,7 +3096,7 @@ CountIndices( * If 'viewUpdate' is true, we may adjust the window contents' * y-position, and scrollbar setting. * - * If 'viewUpdate' is false, true we can guarantee that textPtr->topIndex + * If 'viewUpdate' is true we can guarantee that textPtr->topIndex * points to a valid TkTextLine after this function returns. However, if * 'viewUpdate' is false, then there is no such guarantee (since * topIndex.linePtr can be garbage). The caller is expected to take @@ -3046,6 +3126,9 @@ DeleteIndexRange( int *lineAndByteIndex; int resetViewCount; int pixels[2*PIXEL_CLIENTS]; + Tcl_HashSearch search; + Tcl_HashEntry *hPtr; + int i; if (sharedTextPtr == NULL) { sharedTextPtr = textPtr->sharedTextPtr; @@ -3075,11 +3158,16 @@ DeleteIndexRange( * The code below is ugly, but it's needed to make sure there is always a * dummy empty line at the end of the text. If the final newline of the * file (just before the dummy line) is being deleted, then back up index - * to just before the newline. Furthermore, remove any tags that are - * present on the newline that isn't going to be deleted after all (this - * simulates deleting the newline and then adding a "clean" one back - * again). Note that index1 and index2 might now be equal again which - * means that no text will be deleted but tags might be removed. + * to just before the newline. If there is a newline just before the first + * character being deleted, then back up the first index too. The idea is + * that a deletion involving a range starting at a line start and + * including the final \n (i.e. index2 is "end") is an attempt to delete + * complete lines, so the \n before the deleted block shall become the new + * final \n. Furthermore, remove any tags that are present on the newline + * that isn't going to be deleted after all (this simulates deleting the + * newline and then adding a "clean" one back again). Note that index1 and + * index2 might now be equal again which means that no text will be + * deleted but tags might be removed. */ line1 = TkBTreeLinesTo(textPtr, index1.linePtr); @@ -3092,6 +3180,10 @@ DeleteIndexRange( oldIndex2 = index2; TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES); line2--; + if ((index1.byteIndex == 0) && (line1 != 0)) { + TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES); + line1--; + } arrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize); if (arrayPtr != NULL) { for (i = 0; i < arraySize; i++) { @@ -3101,42 +3193,36 @@ DeleteIndexRange( } } - if (line1 < line2) { - /* - * We are deleting more than one line. For speed, we remove all tags - * from the range first. If we don't do this, the code below can (when - * there are many tags) grow non-linearly in execution time. - */ - - Tcl_HashSearch search; - Tcl_HashEntry *hPtr; - int i; + /* + * For speed, we remove all tags from the range first. If we don't + * do this, the code below can (when there are many tags) grow + * non-linearly in execution time. + */ - for (i=0, hPtr=Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search); - hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) { - TkTextTag *tagPtr = Tcl_GetHashValue(hPtr); + for (i=0, hPtr=Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search); + hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) { + TkTextTag *tagPtr = Tcl_GetHashValue(hPtr); - TkBTreeTag(&index1, &index2, tagPtr, 0); - } + TkBTreeTag(&index1, &index2, tagPtr, 0); + } - /* - * Special case for the sel tag which is not in the hash table. We - * need to do this once for each peer text widget. - */ + /* + * Special case for the sel tag which is not in the hash table. We + * need to do this once for each peer text widget. + */ - for (tPtr = sharedTextPtr->peers; tPtr != NULL ; - tPtr = tPtr->next) { - if (TkBTreeTag(&index1, &index2, tPtr->selTagPtr, 0)) { - /* - * Send an event that the selection changed. This is - * equivalent to: - * event generate $textWidget <<Selection>> - */ + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; + tPtr = tPtr->next) { + if (TkBTreeTag(&index1, &index2, tPtr->selTagPtr, 0)) { + /* + * Send an event that the selection changed. This is + * equivalent to: + * event generate $textWidget <<Selection>> + */ - TkTextSelectionEvent(textPtr); - tPtr->abortSelections = 1; - } - } + TkTextSelectionEvent(textPtr); + tPtr->abortSelections = 1; + } } /* @@ -3179,11 +3265,11 @@ DeleteIndexRange( resetView = 1; line = line1; byteIndex = tPtr->topIndex.byteIndex; - } else { - /* - * Deletion range starts after the top line. This peers's view - * will not need to be reset. Nothing to do. - */ + } else { + /* + * Deletion range starts after the top line. This peers's view + * will not need to be reset. Nothing to do. + */ } } else if (index2.linePtr == tPtr->topIndex.linePtr) { /* @@ -3200,11 +3286,11 @@ DeleteIndexRange( } else { byteIndex -= (index2.byteIndex - index1.byteIndex); } - } else { - /* - * Deletion range ends before the top line. This peers's view - * will not need to be reset. Nothing to do. - */ + } else { + /* + * Deletion range ends before the top line. This peers's view + * will not need to be reset. Nothing to do. + */ } if (resetView) { lineAndByteIndex[resetViewCount] = line; @@ -3249,43 +3335,43 @@ DeleteIndexRange( TkTextIndex indexTmp; if (tPtr == textPtr) { - if (viewUpdate) { - /* - * line cannot be before -startline of textPtr because - * this line corresponds to an index which is necessarily - * between "1.0" and "end" relative to textPtr. - * Therefore no need to clamp line to the -start/-end - * range. - */ + if (viewUpdate) { + /* + * line cannot be before -startline of textPtr because + * this line corresponds to an index which is necessarily + * between "1.0" and "end" relative to textPtr. + * Therefore no need to clamp line to the -start/-end + * range. + */ TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line, byteIndex, &indexTmp); TkTextSetYView(tPtr, &indexTmp, 0); } } else { - TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line, + TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line, byteIndex, &indexTmp); - /* - * line may be before -startline of tPtr and must be - * clamped to -startline before providing it to - * TkTextSetYView otherwise lines before -startline - * would be displayed. - * There is no need to worry about -endline however, - * because the view will only be reset if the deletion - * involves the TOP line of the screen - */ - - if (tPtr->start != NULL) { - int start; - TkTextIndex indexStart; - - start = TkBTreeLinesTo(NULL, tPtr->start); - TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start, + /* + * line may be before -startline of tPtr and must be + * clamped to -startline before providing it to + * TkTextSetYView otherwise lines before -startline + * would be displayed. + * There is no need to worry about -endline however, + * because the view will only be reset if the deletion + * involves the TOP line of the screen + */ + + if (tPtr->start != NULL) { + int start; + TkTextIndex indexStart; + + start = TkBTreeLinesTo(NULL, tPtr->start); + TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start, 0, &indexStart); - if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) { - indexTmp = indexStart; - } - } + if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) { + indexTmp = indexStart; + } + } TkTextSetYView(tPtr, &indexTmp, 0); } } @@ -3346,7 +3432,7 @@ TextFetchSelection( TkTextSearch search; TkTextSegment *segPtr; - if (!textPtr->exportSelection) { + if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) { return -1; } @@ -3476,7 +3562,7 @@ TkTextLostSelection( if (TkpAlwaysShowSelection(textPtr->tkwin)) { TkTextIndex start, end; - if (!textPtr->exportSelection) { + if ((!textPtr->exportSelection) || Tcl_IsSafe(textPtr->interp)) { return; } @@ -3531,16 +3617,7 @@ TkTextSelectionEvent( * event generate $textWidget <<Selection>> */ - union {XEvent general; XVirtualEvent virtual;} event; - - memset(&event, 0, sizeof(event)); - event.general.xany.type = VirtualEvent; - event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.general.xany.send_event = False; - event.general.xany.window = Tk_WindowId(textPtr->tkwin); - event.general.xany.display = Tk_Display(textPtr->tkwin); - event.virtual.name = Tk_GetUid("Selection"); - Tk_HandleEvent(&event.general); + TkSendVirtualEvent(textPtr->tkwin, "Selection", NULL); } /* @@ -3732,10 +3809,10 @@ TextSearchCmd( "-nocase", "-nolinestop", "-overlap", "-regexp", "-strictlimits", NULL }; enum SearchSwitches { - SEARCH_HIDDEN, - SEARCH_END, SEARCH_ALL, SEARCH_BACK, SEARCH_COUNT, SEARCH_ELIDE, - SEARCH_EXACT, SEARCH_FWD, SEARCH_NOCASE, - SEARCH_NOLINESTOP, SEARCH_OVERLAP, SEARCH_REGEXP, SEARCH_STRICTLIMITS + TK_TEXT_SEARCH_HIDDEN, + TK_TEXT_SEARCH_END, TK_TEXT_SEARCH_ALL, TK_TEXT_SEARCH_BACK, TK_TEXT_SEARCH_COUNT, TK_TEXT_SEARCH_ELIDE, + TK_TEXT_SEARCH_EXACT, TK_TEXT_SEARCH_FWD, TK_TEXT_SEARCH_NOCASE, + TK_TEXT_SEARCH_NOLINESTOP, TK_TEXT_SEARCH_OVERLAP, TK_TEXT_SEARCH_REGEXP, TK_TEXT_SEARCH_STRICTLIMITS }; /* @@ -3785,16 +3862,16 @@ TextSearchCmd( } switch ((enum SearchSwitches) index) { - case SEARCH_END: + case TK_TEXT_SEARCH_END: i++; goto endOfSwitchProcessing; - case SEARCH_ALL: + case TK_TEXT_SEARCH_ALL: searchSpec.all = 1; break; - case SEARCH_BACK: + case TK_TEXT_SEARCH_BACK: searchSpec.backwards = 1; break; - case SEARCH_COUNT: + case TK_TEXT_SEARCH_COUNT: if (i >= objc-1) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no value given for \"-count\" option", -1)); @@ -3810,29 +3887,29 @@ TextSearchCmd( searchSpec.varPtr = objv[i]; break; - case SEARCH_ELIDE: - case SEARCH_HIDDEN: + case TK_TEXT_SEARCH_ELIDE: + case TK_TEXT_SEARCH_HIDDEN: searchSpec.searchElide = 1; break; - case SEARCH_EXACT: + case TK_TEXT_SEARCH_EXACT: searchSpec.exact = 1; break; - case SEARCH_FWD: + case TK_TEXT_SEARCH_FWD: searchSpec.backwards = 0; break; - case SEARCH_NOCASE: + case TK_TEXT_SEARCH_NOCASE: searchSpec.noCase = 1; break; - case SEARCH_NOLINESTOP: + case TK_TEXT_SEARCH_NOLINESTOP: searchSpec.noLineStop = 1; break; - case SEARCH_OVERLAP: + case TK_TEXT_SEARCH_OVERLAP: searchSpec.overlap = 1; break; - case SEARCH_STRICTLIMITS: + case TK_TEXT_SEARCH_STRICTLIMITS: searchSpec.strictLimits = 1; break; - case SEARCH_REGEXP: + case TK_TEXT_SEARCH_REGEXP: searchSpec.exact = 0; break; default: @@ -4152,7 +4229,7 @@ TextSearchAddNextLine( if (lenPtr != NULL) { if (searchSpecPtr->exact) { - (void)Tcl_GetString(theLine); + Tcl_GetString(theLine); *lenPtr = theLine->length; } else { *lenPtr = Tcl_GetCharLength(theLine); @@ -4433,7 +4510,7 @@ TkTextGetTabs( Tcl_Obj **objv; TkTextTabArray *tabArrayPtr; TkTextTab *tabPtr; - Tcl_UniChar ch; + int ch; double prevStop, lastStop; /* * Map these strings to TkTextTabAlign values. @@ -4540,7 +4617,7 @@ TkTextGetTabs( * There may be a more efficient way of getting this. */ - Tcl_UtfToUniChar(Tcl_GetString(objv[i+1]), &ch); + TkUtfToUniChar(Tcl_GetString(objv[i+1]), &ch); if (!Tcl_UniCharIsAlpha(ch)) { continue; } @@ -4677,15 +4754,14 @@ TextDumpCmd( if (objc == arg) { TkTextIndexForwChars(NULL, &index1, 1, &index2, COUNT_INDICES); } else { - int length; + size_t 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; - if (strncmp(str, "end", (unsigned) length) == 0) { + str = TkGetStringFromObj(objv[arg], &length); + if (strncmp(str, "end", length) == 0) { atEnd = 1; } } @@ -5000,7 +5076,7 @@ DumpSegment( Tcl_DecrRefCount(tuple); return 0; } else { - int oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree); + TkSizeT oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree); Tcl_DString buf; int code; @@ -5043,6 +5119,8 @@ TextEditUndo( TkText *textPtr) /* Overall information about text widget. */ { int status; + Tcl_Obj *cmdObj; + int code; if (!textPtr->sharedTextPtr->undo) { return TCL_OK; @@ -5066,6 +5144,22 @@ TextEditUndo( } 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; } @@ -5091,6 +5185,8 @@ TextEditRedo( TkText *textPtr) /* Overall information about text widget. */ { int status; + Tcl_Obj *cmdObj; + int code; if (!textPtr->sharedTextPtr->undo) { return TCL_OK; @@ -5113,6 +5209,23 @@ TextEditRedo( 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; } @@ -5141,11 +5254,16 @@ TextEditCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int index, setModified, oldModified; + int canRedo = 0; + int canUndo = 0; + static const char *const editOptionStrings[] = { - "modified", "redo", "reset", "separator", "undo", NULL + "canundo", "canredo", "modified", "redo", "reset", "separator", + "undo", NULL }; enum editOptions { - EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, EDIT_SEPARATOR, EDIT_UNDO + EDIT_CANUNDO, EDIT_CANREDO, EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, + EDIT_SEPARATOR, EDIT_UNDO }; if (objc < 3) { @@ -5159,6 +5277,26 @@ TextEditCmd( } switch ((enum editOptions) index) { + case EDIT_CANREDO: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + if (textPtr->sharedTextPtr->undo) { + canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canRedo)); + break; + case EDIT_CANUNDO: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + if (textPtr->sharedTextPtr->undo) { + canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(canUndo)); + break; case EDIT_MODIFIED: if (objc == 3) { Tcl_SetObjResult(interp, @@ -5200,18 +5338,28 @@ TextEditCmd( Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } + canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); if (TextEditRedo(textPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to redo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_REDO", NULL); return TCL_ERROR; } + canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); + if (!canUndo || !canRedo) { + GenerateUndoStackEvent(textPtr); + } break; case EDIT_RESET: if (objc != 3) { Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } + canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); + canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); TkUndoClearStacks(textPtr->sharedTextPtr->undoStack); + if (canUndo || canRedo) { + GenerateUndoStackEvent(textPtr); + } break; case EDIT_SEPARATOR: if (objc != 3) { @@ -5225,11 +5373,16 @@ TextEditCmd( Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } + canRedo = TkUndoCanRedo(textPtr->sharedTextPtr->undoStack); if (TextEditUndo(textPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("nothing to undo", -1)); Tcl_SetErrorCode(interp, "TK", "TEXT", "NO_UNDO", NULL); return TCL_ERROR; } + canUndo = TkUndoCanUndo(textPtr->sharedTextPtr->undoStack); + if (!canRedo || !canUndo) { + GenerateUndoStackEvent(textPtr); + } break; } return TCL_OK; @@ -5324,6 +5477,7 @@ TextGetText( * * Send an event that the text was modified. This is equivalent to: * event generate $textWidget <<Modified>> + * for all peers of $textWidget. * * Results: * None @@ -5338,21 +5492,41 @@ static void GenerateModifiedEvent( TkText *textPtr) /* Information about text widget. */ { - union { - XEvent general; - XVirtualEvent virtual; - } event; - - Tk_MakeWindowExist(textPtr->tkwin); - - memset(&event, 0, sizeof(event)); - event.general.xany.type = VirtualEvent; - event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.general.xany.send_event = False; - event.general.xany.window = Tk_WindowId(textPtr->tkwin); - event.general.xany.display = Tk_Display(textPtr->tkwin); - event.virtual.name = Tk_GetUid("Modified"); - Tk_HandleEvent(&event.general); + for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL; + textPtr = textPtr->next) { + Tk_MakeWindowExist(textPtr->tkwin); + TkSendVirtualEvent(textPtr->tkwin, "Modified", NULL); + } +} + +/* + *---------------------------------------------------------------------- + * + * GenerateUndoStackEvent -- + * + * Send an event that the undo or redo stack became empty or unempty. + * This is equivalent to: + * event generate $textWidget <<UndoStack>> + * for all peers of $textWidget. + * + * Results: + * None + * + * Side effects: + * May force the text window (and all peers) into existence. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateUndoStackEvent( + TkText *textPtr) /* Information about text widget. */ +{ + for (textPtr = textPtr->sharedTextPtr->peers; textPtr != NULL; + textPtr = textPtr->next) { + Tk_MakeWindowExist(textPtr->tkwin); + TkSendVirtualEvent(textPtr->tkwin, "UndoStack", NULL); + } } /* @@ -5376,7 +5550,6 @@ UpdateDirtyFlag( TkSharedText *sharedTextPtr)/* Information about text widget. */ { int oldDirtyFlag; - TkText *textPtr; /* * If we've been forced to be dirty, we stay dirty (until explicitly @@ -5407,10 +5580,7 @@ UpdateDirtyFlag( } if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) { - for (textPtr = sharedTextPtr->peers; textPtr != NULL; - textPtr = textPtr->next) { - GenerateModifiedEvent(textPtr); - } + GenerateModifiedEvent(sharedTextPtr->peers); } } @@ -5439,21 +5609,21 @@ RunAfterSyncCmd( int code; if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { - /* - * The widget has been deleted. Don't do anything. - */ + /* + * The widget has been deleted. Don't do anything. + */ - if (--textPtr->refCount == 0) { - ckfree((char *) textPtr); - } - return; + if (textPtr->refCount-- <= 1) { + ckfree((char *) textPtr); + } + return; } 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_AddErrorInfo(textPtr->interp, "\n (text sync)"); + Tcl_BackgroundError(textPtr->interp); } Tcl_Release((ClientData) textPtr->interp); Tcl_DecrRefCount(textPtr->afterSyncCmd); @@ -5663,8 +5833,7 @@ SearchCore( * it has dual purpose. */ - pattern = Tcl_GetString(patObj); - matchLength = patObj->length; + pattern = Tcl_GetStringFromObj(patObj, &matchLength); nl = strchr(pattern, '\n'); /* @@ -5734,7 +5903,7 @@ SearchCore( firstOffset = 0; } - if (alreadySearchOffset != -1) { + if (alreadySearchOffset >= 0) { if (searchSpecPtr->backwards) { if (alreadySearchOffset < lastOffset) { lastOffset = alreadySearchOffset; @@ -5797,7 +5966,7 @@ SearchCore( CLANG_ASSERT(pattern); do { - Tcl_UniChar ch; + int ch; const char *p; int lastFullLine = lastOffset; @@ -5823,17 +5992,17 @@ SearchCore( * match. */ - const char c = pattern[0]; + const char c = matchLength ? pattern[0] : '\0'; - if (alreadySearchOffset != -1) { + if (alreadySearchOffset >= 0) { p = startOfLine + alreadySearchOffset; alreadySearchOffset = -1; } else { p = startOfLine + lastOffset -1; } while (p >= startOfLine + firstOffset) { - if (p[0] == c && !strncmp(p, pattern, - (unsigned) matchLength)) { + if (matchLength == 0 || (p[0] == c && !strncmp( + p, pattern, (size_t) matchLength))) { goto backwardsMatch; } p--; @@ -5928,7 +6097,7 @@ SearchCore( * result. */ - if (strncmp(p,pattern,(unsigned)matchLength)) { + if (strncmp(p,pattern,(size_t)matchLength)) { p = NULL; } break; @@ -5996,10 +6165,14 @@ SearchCore( if (firstNewLine != -1) { break; } else { - alreadySearchOffset -= matchLength; + alreadySearchOffset -= (matchLength ? matchLength : 1); + if (alreadySearchOffset < 0) { + break; + } } } else { - firstOffset = p - startOfLine + matchLength; + firstOffset = matchLength ? p - startOfLine + matchLength + : p - startOfLine + 1; if (firstOffset >= lastOffset) { /* * Now, we have to be careful not to find @@ -6027,7 +6200,7 @@ SearchCore( } } else { firstOffset = p - startOfLine + - Tcl_UtfToUniChar(startOfLine+matchOffset,&ch); + TkUtfToUniChar(startOfLine+matchOffset,&ch); } } } while (searchSpecPtr->all); @@ -6660,7 +6833,7 @@ SetLineStartEnd( TkText *textPtr = (TkText *) recordPtr; if (internalOffset >= 0) { - internalPtr = recordPtr + internalOffset; + internalPtr = (char *)recordPtr + internalOffset; } else { internalPtr = NULL; } @@ -6735,10 +6908,9 @@ ObjectIsEmpty( if (objPtr == NULL) { return 1; } - if (objPtr->bytes != NULL) { - return (objPtr->length == 0); + if (objPtr->bytes == NULL) { + Tcl_GetString(objPtr); } - (void)Tcl_GetString(objPtr); return (objPtr->length == 0); } diff --git a/generic/tkText.h b/generic/tkText.h index fc92644..5e84fd5 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -347,6 +347,9 @@ typedef struct TkTextTag { int lMargin2; /* Left margin for second and later display * lines of each text line, in pixels. Only * valid if lMargin2String is non-NULL. */ + Tk_3DBorder lMarginColor; /* Used for drawing background in left margins. + * This is used for both lmargin1 and lmargin2. + * NULL means no value specified here. */ char *offsetString; /* -offset option string (malloc-ed). NULL * means option not specified. */ int offset; /* Vertical offset of text's baseline from @@ -358,10 +361,18 @@ typedef struct TkTextTag { int overstrike; /* Non-zero means draw horizontal line through * middle of text. Only valid if * overstrikeString is non-NULL. */ + XColor *overstrikeColor; /* Color for the overstrike. NULL means same + * color as foreground. */ char *rMarginString; /* -rmargin option string (malloc-ed). NULL * means option not specified. */ int rMargin; /* Right margin for text, in pixels. Only * valid if rMarginString is non-NULL. */ + Tk_3DBorder rMarginColor; /* Used for drawing background in right margin. + * NULL means no value specified here. */ + Tk_3DBorder selBorder; /* Used for drawing background for selected text. + * NULL means no value specified here. */ + XColor *selFgColor; /* Foreground color for selected text. NULL means + * no value specified here. */ char *spacing1String; /* -spacing1 option string (malloc-ed). NULL * means option not specified. */ int spacing1; /* Extra spacing above first display line for @@ -389,6 +400,8 @@ typedef struct TkTextTag { int underline; /* Non-zero means draw underline underneath * text. Only valid if underlineString is * non-NULL. */ + XColor *underlineColor; /* Color for the underline. NULL means same + * color as foreground. */ TkWrapMode wrapMode; /* How to handle wrap-around for this tag. * Must be TEXT_WRAPMODE_CHAR, * TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, or @@ -519,8 +532,16 @@ typedef enum { * 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 @@ -549,7 +570,7 @@ typedef struct TkSharedText { * 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 @@ -567,6 +588,8 @@ typedef struct TkSharedText { * 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 @@ -768,7 +791,7 @@ typedef struct TkText { * 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. */ @@ -994,7 +1017,7 @@ MODULE_SCOPE void TkBTreeRemoveClient(TkTextBTree tree, 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, diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c index 0fdc280..66fa140 100644 --- a/generic/tkTextBTree.c +++ b/generic/tkTextBTree.c @@ -105,7 +105,7 @@ typedef struct BTree { 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 @@ -140,10 +140,10 @@ int tkBTreeDebug = 0; * 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) (Tk_Offset(TkTextSegment, body) \ + + 1 + (chars)) +#define TSEG_SIZE (Tk_Offset(TkTextSegment, body) \ + + sizeof(TkTextToggle)) /* * Forward declarations for functions defined in this file: @@ -501,7 +501,7 @@ TkBTreeDestroy( *---------------------------------------------------------------------- */ -int +TkSizeT TkBTreeEpoch( TkTextBTree tree) /* Tree to get epoch for. */ { @@ -799,6 +799,7 @@ RemovePixelClient( nodePtr->numPixels[treePtr->pixelReferences-1]; } if (treePtr->pixelReferences == 1) { + ckfree(nodePtr->numPixels); nodePtr->numPixels = NULL; } else { nodePtr->numPixels = ckrealloc(nodePtr->numPixels, @@ -1020,7 +1021,7 @@ TkBTreeInsertChars( * 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 @@ -1069,7 +1070,7 @@ TkBTreeInsertChars( 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') { @@ -1439,6 +1440,8 @@ TkBTreeDeleteIndexRange( prevNodePtr->nextPtr = curNodePtr->nextPtr; } parentPtr->numChildren--; + DeleteSummaries(curNodePtr->summaryPtr); + ckfree(curNodePtr->numPixels); ckfree(curNodePtr); curNodePtr = parentPtr; } @@ -4185,6 +4188,7 @@ Rebalance( treePtr->rootPtr = nodePtr->children.nodePtr; treePtr->rootPtr->parentPtr = NULL; DeleteSummaries(nodePtr->summaryPtr); + ckfree(nodePtr->numPixels); ckfree(nodePtr); } return; @@ -4274,6 +4278,7 @@ Rebalance( nodePtr->nextPtr = otherPtr->nextPtr; nodePtr->parentPtr->numChildren--; DeleteSummaries(otherPtr->summaryPtr); + ckfree(otherPtr->numPixels); ckfree(otherPtr); continue; } @@ -4558,7 +4563,7 @@ CharSplitProc( 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; diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 1eea37d..9f0d7e0 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -16,12 +16,6 @@ #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" #endif @@ -136,11 +130,15 @@ typedef struct StyleValues { * line of each text line. */ int lMargin2; /* Left margin, in pixels, for second and * later display lines of each text line. */ + Tk_3DBorder lMarginColor; /* Color of left margins (1 and 2). */ int offset; /* Offset in pixels of baseline, relative to * baseline of line. */ int overstrike; /* Non-zero means draw overstrike through * text. */ + XColor *overstrikeColor; /* Foreground color for overstrike through + * text. */ int rMargin; /* Right margin, in pixels. */ + Tk_3DBorder rMarginColor; /* Color of right margin. */ int spacing1; /* Spacing above first dline in text line. */ int spacing2; /* Spacing between lines of dline. */ int spacing3; /* Spacing below last dline in text line. */ @@ -149,6 +147,8 @@ typedef struct StyleValues { int tabStyle; /* One of TABULAR or WORDPROCESSOR. */ int underline; /* Non-zero means draw underline underneath * text. */ + XColor *underlineColor; /* Foreground color for underline underneath + * text. */ int elide; /* Zero means draw text, otherwise not. */ TkWrapMode wrapMode; /* How to handle wrap-around for this tag. * One of TEXT_WRAPMODE_CHAR, @@ -162,11 +162,13 @@ typedef struct StyleValues { */ 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. */ + GC ovGC; /* Graphics context for overstrike. */ StyleValues *sValuePtr; /* Raw information from which GCs were * derived. */ Tcl_HashEntry *hPtr; /* Pointer to entry in styleTable. Used to @@ -234,6 +236,14 @@ typedef struct DLine { int spaceBelow; /* How much extra space was added to the * bottom of the line because of spacing * options. This is included in height. */ + Tk_3DBorder lMarginColor; /* Background color of the area corresponding + * to the left margin of the display line. */ + int lMarginWidth; /* Pixel width of the area corresponding to + * the left margin. */ + Tk_3DBorder rMarginColor; /* Background color of the area corresponding + * to the right margin of the display line. */ + int rMarginWidth; /* Pixel width of the area corresponding to + * the right margin. */ int length; /* Total length of line, in pixels. */ TkTextDispChunk *chunkPtr; /* Pointer to first chunk in list of all of * those that are displayed on this line of @@ -390,7 +400,7 @@ typedef struct TextDInfo { * 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 @@ -594,7 +604,7 @@ 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: @@ -748,6 +758,7 @@ GetStyle( TextStyle *stylePtr; Tcl_HashEntry *hPtr; int numTags, isNew, i; + int isSelected; XGCValues gcValues; unsigned long mask; /* @@ -758,6 +769,7 @@ GetStyle( int fgPrio, fontPrio, fgStipplePrio; int underlinePrio, elidePrio, justifyPrio, offsetPrio; int lMargin1Prio, lMargin2Prio, rMarginPrio; + int lMarginColorPrio, rMarginColorPrio; int spacing1Prio, spacing2Prio, spacing3Prio; int overstrikePrio, tabPrio, tabStylePrio, wrapPrio; @@ -772,11 +784,14 @@ GetStyle( fgPrio = fontPrio = fgStipplePrio = -1; underlinePrio = elidePrio = justifyPrio = offsetPrio = -1; lMargin1Prio = lMargin2Prio = rMarginPrio = -1; + lMarginColorPrio = rMarginColorPrio = -1; spacing1Prio = spacing2Prio = spacing3Prio = -1; overstrikePrio = tabPrio = tabStylePrio = wrapPrio = -1; memset(&styleValues, 0, sizeof(StyleValues)); styleValues.relief = TK_RELIEF_FLAT; styleValues.fgColor = textPtr->fgColor; + styleValues.underlineColor = textPtr->fgColor; + styleValues.overstrikeColor = textPtr->fgColor; styleValues.tkfont = textPtr->tkfont; styleValues.justify = TK_JUSTIFY_LEFT; styleValues.spacing1 = textPtr->spacing1; @@ -786,12 +801,22 @@ GetStyle( styleValues.tabStyle = textPtr->tabStyle; styleValues.wrapMode = textPtr->wrapMode; styleValues.elide = 0; + isSelected = 0; + + for (i = 0 ; i < numTags; i++) { + if (textPtr->selTagPtr == tagPtrs[i]) { + isSelected = 1; + break; + } + } for (i = 0 ; i < numTags; i++) { Tk_3DBorder border; + XColor *fgColor; tagPtr = tagPtrs[i]; border = tagPtr->border; + fgColor = tagPtr->fgColor; /* * If this is the selection tag, and inactiveSelBorder is NULL (the @@ -811,6 +836,14 @@ GetStyle( border = textPtr->inactiveSelBorder; } + if ((tagPtr->selBorder != NULL) && (isSelected)) { + border = tagPtr->selBorder; + } + + if ((tagPtr->selFgColor != None) && (isSelected)) { + fgColor = tagPtr->selFgColor; + } + if ((border != NULL) && (tagPtr->priority > borderPrio)) { styleValues.border = border; borderPrio = tagPtr->priority; @@ -834,8 +867,8 @@ GetStyle( styleValues.bgStipple = tagPtr->bgStipple; bgStipplePrio = tagPtr->priority; } - if ((tagPtr->fgColor != None) && (tagPtr->priority > fgPrio)) { - styleValues.fgColor = tagPtr->fgColor; + if ((fgColor != None) && (tagPtr->priority > fgPrio)) { + styleValues.fgColor = fgColor; fgPrio = tagPtr->priority; } if ((tagPtr->tkfont != None) && (tagPtr->priority > fontPrio)) { @@ -862,6 +895,11 @@ GetStyle( styleValues.lMargin2 = tagPtr->lMargin2; lMargin2Prio = tagPtr->priority; } + if ((tagPtr->lMarginColor != NULL) + && (tagPtr->priority > lMarginColorPrio)) { + styleValues.lMarginColor = tagPtr->lMarginColor; + lMarginColorPrio = tagPtr->priority; + } if ((tagPtr->offsetString != NULL) && (tagPtr->priority > offsetPrio)) { styleValues.offset = tagPtr->offset; @@ -871,12 +909,22 @@ GetStyle( && (tagPtr->priority > overstrikePrio)) { styleValues.overstrike = tagPtr->overstrike; overstrikePrio = tagPtr->priority; + if (tagPtr->overstrikeColor != None) { + styleValues.overstrikeColor = tagPtr->overstrikeColor; + } else if (fgColor != None) { + styleValues.overstrikeColor = fgColor; + } } if ((tagPtr->rMarginString != NULL) && (tagPtr->priority > rMarginPrio)) { styleValues.rMargin = tagPtr->rMargin; rMarginPrio = tagPtr->priority; } + if ((tagPtr->rMarginColor != NULL) + && (tagPtr->priority > rMarginColorPrio)) { + styleValues.rMarginColor = tagPtr->rMarginColor; + rMarginColorPrio = tagPtr->priority; + } if ((tagPtr->spacing1String != NULL) && (tagPtr->priority > spacing1Prio)) { styleValues.spacing1 = tagPtr->spacing1; @@ -906,6 +954,11 @@ GetStyle( && (tagPtr->priority > underlinePrio)) { styleValues.underline = tagPtr->underline; underlinePrio = tagPtr->priority; + if (tagPtr->underlineColor != None) { + styleValues.underlineColor = tagPtr->underlineColor; + } else if (fgColor != None) { + styleValues.underlineColor = fgColor; + } } if ((tagPtr->elideString != NULL) && (tagPtr->priority > elidePrio)) { @@ -962,6 +1015,11 @@ GetStyle( mask |= GCStipple|GCFillStyle; } stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues); + mask = GCForeground; + gcValues.foreground = styleValues.underlineColor->pixel; + stylePtr->ulGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues); + gcValues.foreground = styleValues.overstrikeColor->pixel; + stylePtr->ovGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues); stylePtr->sValuePtr = (StyleValues *) Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr); stylePtr->hPtr = hPtr; @@ -994,14 +1052,19 @@ FreeStyle( register TextStyle *stylePtr) /* Information about style to free. */ { - stylePtr->refCount--; - if (stylePtr->refCount == 0) { + if (stylePtr->refCount-- <= 1) { if (stylePtr->bgGC != None) { Tk_FreeGC(textPtr->display, stylePtr->bgGC); } if (stylePtr->fgGC != None) { Tk_FreeGC(textPtr->display, stylePtr->fgGC); } + if (stylePtr->ulGC != None) { + Tk_FreeGC(textPtr->display, stylePtr->ulGC); + } + if (stylePtr->ovGC != None) { + Tk_FreeGC(textPtr->display, stylePtr->ovGC); + } Tcl_DeleteHashEntry(stylePtr->hPtr); ckfree(stylePtr); } @@ -1113,6 +1176,10 @@ LayoutDLine( dlPtr->nextPtr = NULL; dlPtr->flags = NEW_LAYOUT | OLD_Y_INVALID; dlPtr->logicalLinesMerged = 0; + dlPtr->lMarginColor = NULL; + dlPtr->lMarginWidth = 0; + dlPtr->rMarginColor = NULL; + dlPtr->rMarginWidth = 0; /* * This is not necessarily totally correct, where we have merged logical @@ -1387,6 +1454,7 @@ LayoutDLine( x = chunkPtr->stylePtr->sValuePtr->lMargin2; } + dlPtr->lMarginWidth = x; if (wrapMode == TEXT_WRAPMODE_NONE) { maxX = -1; } else { @@ -1698,6 +1766,11 @@ LayoutDLine( } dlPtr->height += dlPtr->spaceAbove + dlPtr->spaceBelow; dlPtr->baseline += dlPtr->spaceAbove; + dlPtr->lMarginColor = sValuePtr->lMarginColor; + dlPtr->rMarginColor = sValuePtr->rMarginColor; + if (wrapMode != TEXT_WRAPMODE_NONE) { + dlPtr->rMarginWidth = rMargin; + } /* * Recompute line length: may have changed because of justification. @@ -2384,12 +2457,26 @@ DisplayDLine( Tk_Width(textPtr->tkwin), dlPtr->height, 0, TK_RELIEF_FLAT); /* - * Next, draw background information for the whole line. + * Second, draw background information for the whole line. */ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap); /* + * Third, draw the background color of the left and right margins. + */ + if (dlPtr->lMarginColor != NULL) { + Tk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->lMarginColor, 0, y, + dlPtr->lMarginWidth + dInfoPtr->x - dInfoPtr->curXPixelOffset, + dlPtr->height, 0, TK_RELIEF_FLAT); + } + if (dlPtr->rMarginColor != NULL) { + Tk_Fill3DRectangle(textPtr->tkwin, pixmap, dlPtr->rMarginColor, + dInfoPtr->maxX - dlPtr->rMarginWidth + dInfoPtr->curXPixelOffset, + y, dlPtr->rMarginWidth, dlPtr->height, 0, TK_RELIEF_FLAT); + } + + /* * Make another pass through all of the chunks to redraw the insertion * cursor, if it is visible on this line. Must do it here rather than in * the foreground pass below because otherwise a wide insertion cursor @@ -2911,7 +2998,7 @@ AsyncUpdateLineMetrics( * The widget has been deleted, or is not mapped. Don't do anything. */ - if (--textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } return; @@ -2956,7 +3043,7 @@ AsyncUpdateLineMetrics( * 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 @@ -2986,8 +3073,7 @@ AsyncUpdateLineMetrics( GenerateWidgetViewSyncEvent(textPtr, 1); - textPtr->refCount--; - if (textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } return; @@ -3010,7 +3096,7 @@ AsyncUpdateLineMetrics( * Send the <<WidgetViewSync>> event related to the text widget * line metrics asynchronous update. * This is equivalent to: - * event generate $textWidget <<WidgetViewSync>> -detail $s + * event generate $textWidget <<WidgetViewSync>> -data $s * where $s is the sync status: true (when the widget view is in * sync with its internal data) or false (when it is not). * @@ -3026,19 +3112,10 @@ AsyncUpdateLineMetrics( static void GenerateWidgetViewSyncEvent( TkText *textPtr, /* Information about text widget. */ - Bool InSync) /* True if in sync, false otherwise */ + Bool InSync) /* true if in sync, false otherwise */ { - union {XEvent general; XVirtualEvent virtual;} event; - - memset(&event, 0, sizeof(event)); - event.general.xany.type = VirtualEvent; - event.general.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.general.xany.send_event = False; - event.general.xany.window = Tk_WindowId(textPtr->tkwin); - event.general.xany.display = Tk_Display(textPtr->tkwin); - event.virtual.name = Tk_GetUid("WidgetViewSync"); - event.virtual.user_data = Tcl_NewBooleanObj(InSync); - Tk_HandleEvent(&event.general); + TkSendVirtualEvent(textPtr->tkwin, "WidgetViewSync", + Tcl_NewBooleanObj(InSync)); } /* @@ -3116,7 +3193,7 @@ TkTextUpdateLineMetrics( * 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. */ @@ -4036,8 +4113,8 @@ DisplayText( MacDrawable *macWin = winPtr->privatePtr; if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){ dInfoPtr->flags &= ~REDRAW_PENDING; - return; - } + return; + } #endif if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { @@ -4078,7 +4155,7 @@ DisplayText( textPtr->refCount++; dInfoPtr->flags &= ~REPICK_NEEDED; TkTextPickCurrent(textPtr, &textPtr->pickEvent); - if (--textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); goto end; } @@ -4190,7 +4267,6 @@ DisplayText( } dlPtr = dlPtr->nextPtr; } - /* * Scan through the lines following the copied ones to see if we are * going to overwrite them with the copy operation. If so, mark them @@ -4215,7 +4291,6 @@ DisplayText( oldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY, damageRgn)) { TextInvalidateRegion(textPtr, damageRgn); - } numCopies++; TkDestroyRegion(damageRgn); @@ -4357,11 +4432,38 @@ DisplayText( } dlPtr->oldY = dlPtr->y; dlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID); +#ifdef MAC_OSX_TK + } else if (dlPtr->chunkPtr != NULL) { + /* + * On macOS we need to redisplay all embedded windows which + * were moved by the call to TkScrollWindows above. This is + * not necessary on Unix or Windows because XScrollWindow will + * have included the bounding rectangles of all of these + * windows in the damage region. The macosx implementation of + * TkScrollWindow does not do this. It simply generates a + * damage region which is the scroll source rectangle minus + * the scroll destination rectangle. This is because there is + * no efficient process available for iterating through the + * subwindows which meet the scrolled area. (On Unix this is + * handled by GraphicsExpose events generated by XCopyArea and + * on Windows by ScrollWindowEx. On macOS the low level + * scrolling is accomplished by calling [view scrollRect:by:]. + * This method does not provide any damage information and, in + * any case, could not be aware of Tk windows which were not + * based on NSView objects. + * + * On the other hand, this loop is already iterating through + * all embedded windows which could possibly have been moved + * by the scrolling. So it is as efficient to redisplay them + * here as it would have been if they had been redisplayed by + * the call to TextInvalidateRegion above. + */ +#else } else if (dlPtr->chunkPtr != NULL && ((dlPtr->y < 0) || (dlPtr->y + dlPtr->height > dInfoPtr->maxY))) { - register TkTextDispChunk *chunkPtr; - /* + * On platforms other than the Mac: + * * It's the first or last DLine which are also overlapping the * top or bottom of the window, but we decided above it wasn't * necessary to display them (we were able to update them by @@ -4375,6 +4477,8 @@ DisplayText( * So, we loop through all the chunks, calling the display * proc of embedded windows only. */ +#endif + register TkTextDispChunk *chunkPtr; for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL); chunkPtr = chunkPtr->nextPtr) { @@ -4397,13 +4501,18 @@ DisplayText( x = -chunkPtr->width; } + if (tkTextDebug) { + char string[TK_POS_CHARS]; + + TkTextPrintIndex(textPtr, &dlPtr->index, string); + LOG("tk_textEmbWinDisplay", string); + } TkTextEmbWinDisplayProc(textPtr, chunkPtr, x, dlPtr->spaceAbove, dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, NULL, (Drawable) None, dlPtr->y + dlPtr->spaceAbove); } - } } #ifndef TK_NO_DOUBLE_BUFFERING @@ -5973,7 +6082,7 @@ TkTextYviewCmd( TextDInfo *dInfoPtr = textPtr->dInfoPtr; int pickPlace, type; int pixels, count; - int switchLength; + size_t switchLength; double fraction; TkTextIndex index; @@ -5993,7 +6102,7 @@ TkTextYviewCmd( pickPlace = 0; if (Tcl_GetString(objv[2])[0] == '-') { register const char *switchStr = - Tcl_GetStringFromObj(objv[2], &switchLength); + TkGetStringFromObj(objv[2], &switchLength); if ((switchLength >= 2) && (strncmp(switchStr, "-pickplace", (unsigned) switchLength) == 0)) { @@ -6148,7 +6257,7 @@ TkTextPendingsync( TextDInfo *dInfoPtr = textPtr->dInfoPtr; return ( - ((dInfoPtr->metricEpoch == -1) && + ((dInfoPtr->metricEpoch == TCL_AUTO_LENGTH) && (dInfoPtr->lastMetricUpdateLine == dInfoPtr->currentMetricUpdateLine)) ? 0 : 1); } @@ -6667,7 +6776,7 @@ AsyncUpdateYScrollbar( GetYView(textPtr->interp, textPtr, 1); } - if (--textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } } @@ -6805,7 +6914,7 @@ FindDLine( static int IsStartOfNotMergedLine( TkText *textPtr, /* Widget record for text widget. */ - CONST TkTextIndex *indexPtr) /* Index to check. */ + const TkTextIndex *indexPtr) /* Index to check. */ { TkTextIndex indexPtr2; @@ -7457,6 +7566,9 @@ TkTextCharLayoutProc( * (b) at least one pixel of the character is visible, we have not * already exceeded the character limit, and the next character is a * white space character. + * In the specific case of 'word' wrapping mode however, include all space + * characters following the characters that fit in the space we've got, + * even if no pixel of them is visible. */ p = segPtr->body.chars + byteOffset; @@ -7496,8 +7608,8 @@ TkTextCharLayoutProc( if (bytesThatFit < maxBytes) { if ((bytesThatFit == 0) && noCharsYet) { - Tcl_UniChar ch; - int chLen = Tcl_UtfToUniChar(p, &ch); + int ch; + int chLen = TkUtfToUniChar(p, &ch); #if TK_LAYOUT_WITH_BASE_CHUNKS bytesThatFit = CharChunkMeasureChars(chunkPtr, line, @@ -7519,6 +7631,21 @@ TkTextCharLayoutProc( nextX = maxX; bytesThatFit++; } + if (wrapMode == TEXT_WRAPMODE_WORD) { + while (p[bytesThatFit] == ' ') { + /* + * Space characters that would go at the beginning of the + * next line are allocated to the current line. This gives + * the effect of trimming white spaces that would otherwise + * be seen at the beginning of wrapped lines. + * Note that testing for '\t' is useless here because the + * chunk always includes at most one trailing \t, see + * LayoutDLine. + */ + + bytesThatFit++; + } + } if (p[bytesThatFit] == '\n') { /* * A newline character takes up no space, so if the previous @@ -7562,7 +7689,7 @@ TkTextCharLayoutProc( chunkPtr->breakIndex = -1; #if !TK_LAYOUT_WITH_BASE_CHUNKS - ciPtr = ckalloc((Tk_Offset(CharInfo, chars) + 1) + bytesThatFit); + ciPtr = ckalloc(Tk_Offset(CharInfo, chars) + 1 + bytesThatFit); chunkPtr->clientData = ciPtr; memcpy(ciPtr->chars, p, (unsigned) bytesThatFit); #endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ @@ -7716,7 +7843,7 @@ CharChunkMeasureChars( MeasureChars(tkfont, chars, charsLen, 0, bstart, 0, -1, 0, &widthUntilStart); - xDisplacement = startX - widthUntilStart - chunkPtr->x; + xDisplacement = startX - widthUntilStart - ciPtr->baseChunkPtr->x; } fit = MeasureChars(tkfont, chars, charsLen, 0, bend, @@ -7845,7 +7972,7 @@ CharDisplayProc( y + baseline - sValuePtr->offset); if (sValuePtr->underline) { - TkUnderlineCharsInContext(display, dst, stylePtr->fgGC, + TkUnderlineCharsInContext(display, dst, stylePtr->ulGC, sValuePtr->tkfont, string, numBytes, ciPtr->baseChunkPtr->x + xDisplacement, y + baseline - sValuePtr->offset, @@ -7855,7 +7982,7 @@ CharDisplayProc( Tk_FontMetrics fm; Tk_GetFontMetrics(sValuePtr->tkfont, &fm); - TkUnderlineCharsInContext(display, dst, stylePtr->fgGC, + TkUnderlineCharsInContext(display, dst, stylePtr->ovGC, sValuePtr->tkfont, string, numBytes, ciPtr->baseChunkPtr->x + xDisplacement, y + baseline - sValuePtr->offset @@ -7872,7 +7999,7 @@ CharDisplayProc( Tk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string, numBytes, offsetX, y + baseline - sValuePtr->offset); if (sValuePtr->underline) { - Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, + Tk_UnderlineChars(display, dst, stylePtr->ulGC, sValuePtr->tkfont, string, offsetX, y + baseline - sValuePtr->offset, 0, numBytes); @@ -7882,7 +8009,7 @@ CharDisplayProc( Tk_FontMetrics fm; Tk_GetFontMetrics(sValuePtr->tkfont, &fm); - Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, + Tk_UnderlineChars(display, dst, stylePtr->ovGC, sValuePtr->tkfont, string, offsetX, y + baseline - sValuePtr->offset - fm.descent - (fm.ascent * 3) / 10, @@ -8690,7 +8817,7 @@ FinalizeBaseChunk( #if TK_DRAW_IN_CONTEXT newwidth = 0; CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1, 0, -1, 0, &newwidth); - if (newwidth != chunkPtr->width) { + if (newwidth < chunkPtr->width) { widthAdjust += newwidth - chunkPtr->width; chunkPtr->width = newwidth; } @@ -8878,13 +9005,13 @@ RemoveFromBaseChunk( bciPtr = baseCharChunkPtr->clientData; +#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS if ((ciPtr->baseOffset + ciPtr->numBytes) != Tcl_DStringLength(&bciPtr->baseChars)) { -#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS fprintf(stderr,"RemoveFromBaseChunk called with wrong chunk " "(not last)\n"); -#endif } +#endif Tcl_DStringSetLength(&bciPtr->baseChars, ciPtr->baseOffset); diff --git a/generic/tkTextImage.c b/generic/tkTextImage.c index 41dd448..defda56 100644 --- a/generic/tkTextImage.c +++ b/generic/tkTextImage.c @@ -18,7 +18,7 @@ */ #define EI_SEG_SIZE \ - ((unsigned) (Tk_Offset(TkTextSegment, body) + sizeof(TkTextEmbImage))) + (Tk_Offset(TkTextSegment, body) + sizeof(TkTextEmbImage)) /* * Prototypes for functions defined in this file: @@ -161,7 +161,7 @@ TkTextImageCmd( 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; @@ -188,7 +188,7 @@ TkTextImageCmd( } 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) { @@ -337,7 +337,7 @@ EmbImageConfigure( 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; diff --git a/generic/tkTextIndex.c b/generic/tkTextIndex.c index 8820191..2870c07 100644 --- a/generic/tkTextIndex.c +++ b/generic/tkTextIndex.c @@ -11,9 +11,9 @@ * 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): @@ -40,9 +40,9 @@ static const char * StartEnd(TkText *textPtr, const char *string, 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: @@ -64,7 +64,7 @@ static void UpdateStringOfTextIndex(Tcl_Obj *objPtr); #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 @@ -87,7 +87,7 @@ FreeTextIndexInternalRep( TkTextIndex *indexPtr = GET_TEXTINDEX(indexObjPtr); if (indexPtr->textPtr != NULL) { - if (--indexPtr->textPtr->refCount == 0) { + if (indexPtr->textPtr->refCount-- <= 1) { /* * The text widget has been deleted and we need to free it now. */ @@ -104,7 +104,7 @@ 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)); @@ -134,7 +134,7 @@ UpdateStringOfTextIndex( Tcl_Obj *objPtr) { char buffer[TK_POS_CHARS]; - register int len; + size_t len; const TkTextIndex *indexPtr = GET_TEXTINDEX(objPtr); len = TkTextPrintIndex(indexPtr->textPtr, indexPtr, buffer); @@ -206,7 +206,7 @@ TkTextGetIndexFromObj( int cache; if (objPtr->typePtr == &tkTextIndexType) { - int epoch; + TkSizeT epoch; indexPtr = GET_TEXTINDEX(objPtr); epoch = GET_INDEXEPOCH(objPtr); @@ -387,7 +387,7 @@ TkTextMakeByteIndex( TkTextSegment *segPtr; int index; const char *p, *start; - Tcl_UniChar ch; + int ch; indexPtr->tree = tree; if (lineIndex < 0) { @@ -437,7 +437,7 @@ TkTextMakeByteIndex( start = segPtr->body.chars + (byteIndex - index); p = Tcl_UtfPrev(start, segPtr->body.chars); - p += Tcl_UtfToUniChar(p, &ch); + p += TkUtfToUniChar(p, &ch); indexPtr->byteIndex += p - start; } break; @@ -480,7 +480,7 @@ TkTextMakeCharIndex( register TkTextSegment *segPtr; char *p, *start, *end; int index, offset; - Tcl_UniChar ch; + int ch; indexPtr->tree = tree; if (lineIndex < 0) { @@ -527,7 +527,7 @@ TkTextMakeCharIndex( return indexPtr; } charIndex--; - offset = Tcl_UtfToUniChar(p, &ch); + offset = TkUtfToUniChar(p, &ch); index += offset; } } else { @@ -923,7 +923,7 @@ GetIndex( } if ((string[0] == 'e') && (strncmp(string, "end", - (size_t) (endOfBase-Tcl_DStringValue(©))) == 0)) { + endOfBase-Tcl_DStringValue(©)) == 0)) { /* * Base position is end of text. */ @@ -1475,7 +1475,7 @@ TkTextIndexForwChars( TkTextElideInfo *infoPtr = NULL; int byteOffset; char *start, *end, *p; - Tcl_UniChar ch; + int ch; int elide = 0; int checkElided = (type & COUNT_DISPLAY); @@ -1574,7 +1574,7 @@ TkTextIndexForwChars( if (segPtr->typePtr == &tkTextCharType) { start = segPtr->body.chars + byteOffset; end = segPtr->body.chars + segPtr->size; - for (p = start; p < end; p += Tcl_UtfToUniChar(p, &ch)) { + for (p = start; p < end; p += TkUtfToUniChar(p, &ch)) { if (charCount == 0) { dstPtr->byteIndex += (p - start); goto forwardCharDone; @@ -1636,9 +1636,9 @@ TkTextIndexForwChars( 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); @@ -1653,11 +1653,11 @@ TkTextIndexCountBytes( 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. */ { @@ -2298,9 +2298,9 @@ StartEnd( int chSize = 1; if (segPtr->typePtr == &tkTextCharType) { - Tcl_UniChar ch; + int ch; - chSize = Tcl_UtfToUniChar(segPtr->body.chars + offset, &ch); + chSize = TkUtfToUniChar(segPtr->body.chars + offset, &ch); if (!Tcl_UniCharIsWordChar(ch)) { break; } @@ -2343,9 +2343,9 @@ StartEnd( int chSize = 1; if (segPtr->typePtr == &tkTextCharType) { - Tcl_UniChar ch; - Tcl_UtfToUniChar(segPtr->body.chars + offset, &ch); + int ch; + TkUtfToUniChar(segPtr->body.chars + offset, &ch); if (!Tcl_UniCharIsWordChar(ch)) { break; } diff --git a/generic/tkTextMark.c b/generic/tkTextMark.c index 6a41c77..da455d3 100644 --- a/generic/tkTextMark.c +++ b/generic/tkTextMark.c @@ -19,8 +19,8 @@ * Macro that determines the size of a mark segment: */ -#define MSEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \ - + sizeof(TkTextMark))) +#define MSEG_SIZE (Tk_Offset(TkTextSegment, body) \ + + sizeof(TkTextMark)) /* * Forward references for functions defined in this file: @@ -126,14 +126,14 @@ TkTextMarkCmd( switch ((enum markOptions) optionIndex) { case MARK_GRAVITY: { char c; - int length; + size_t 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")) { @@ -160,7 +160,7 @@ TkTextMarkCmd( 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)) { newTypePtr = &tkTextLeftMarkType; diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c index 3363d25..0a749c4 100644 --- a/generic/tkTextTag.c +++ b/generic/tkTextTag.c @@ -12,9 +12,9 @@ * 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 @@ -30,7 +30,7 @@ static const char *const wrapStrings[] = { /* * The 'TkTextTabStyle' enum in tkText.h is used to define a type for the * -tabstyle option of the Text widget. These values are used as indices into - * the string table below. Tags are allowed an empty wrap value, but the + * the string table below. Tags are allowed an empty tabstyle value, but the * widget as a whole is not. */ @@ -61,15 +61,26 @@ static const Tk_OptionSpec tagOptionSpecs[] = { NULL, -1, Tk_Offset(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}, + {TK_OPTION_BORDER, "-lmargincolor", NULL, NULL, + NULL, -1, Tk_Offset(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}, {TK_OPTION_STRING, "-overstrike", NULL, NULL, NULL, -1, Tk_Offset(TkTextTag, overstrikeString), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-overstrikefg", NULL, NULL, + NULL, -1, Tk_Offset(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}, {TK_OPTION_STRING, "-rmargin", NULL, NULL, NULL, -1, Tk_Offset(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}, + {TK_OPTION_BORDER, "-selectbackground", NULL, NULL, + NULL, -1, Tk_Offset(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}, {TK_OPTION_STRING, "-spacing1", NULL, NULL, NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-spacing2", NULL, NULL, @@ -84,6 +95,9 @@ static const Tk_OptionSpec tagOptionSpecs[] = { {TK_OPTION_STRING, "-underline", NULL, NULL, NULL, -1, Tk_Offset(TkTextTag, underlineString), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-underlinefg", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, underlineColor), + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL, NULL, -1, Tk_Offset(TkTextTag, wrapMode), TK_OPTION_NULL_OK, wrapStrings, 0}, @@ -229,6 +243,7 @@ TkTextTagCmd( TkTextSelectionEvent(textPtr); if (addTag && textPtr->exportSelection + && (!Tcl_IsSafe(textPtr->interp)) && !(textPtr->flags & GOT_SELECTION)) { Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY, TkTextLostSelection, textPtr); @@ -328,7 +343,7 @@ TkTextTagCmd( 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; @@ -347,7 +362,7 @@ TkTextTagCmd( } 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); @@ -359,7 +374,7 @@ TkTextTagCmd( } 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; } @@ -484,10 +499,18 @@ TkTextTagCmd( */ if (tagPtr == textPtr->selTagPtr) { - textPtr->selBorder = tagPtr->border; + if (tagPtr->selBorder == NULL) { + textPtr->selBorder = tagPtr->border; + } else { + textPtr->selBorder = tagPtr->selBorder; + } textPtr->selBorderWidth = tagPtr->borderWidth; textPtr->selBorderWidthPtr = tagPtr->borderWidthPtr; - textPtr->selFgColorPtr = tagPtr->fgColor; + if (tagPtr->selFgColor == NULL) { + textPtr->selFgColorPtr = tagPtr->fgColor; + } else { + textPtr->selFgColorPtr = tagPtr->selFgColor; + } } tagPtr->affectsDisplay = 0; @@ -509,12 +532,18 @@ TkTextTagCmd( tagPtr->affectsDisplayGeometry = 1; } if ((tagPtr->border != NULL) + || (tagPtr->selBorder != NULL) || (tagPtr->reliefString != NULL) || (tagPtr->bgStipple != None) || (tagPtr->fgColor != NULL) + || (tagPtr->selFgColor != NULL) || (tagPtr->fgStipple != None) || (tagPtr->overstrikeString != NULL) - || (tagPtr->underlineString != NULL)) { + || (tagPtr->overstrikeColor != NULL) + || (tagPtr->underlineString != NULL) + || (tagPtr->underlineColor != NULL) + || (tagPtr->lMarginColor != NULL) + || (tagPtr->rMarginColor != NULL)) { tagPtr->affectsDisplay = 1; } if (!newTag) { @@ -1011,12 +1040,17 @@ TkTextCreateTag( tagPtr->lMargin1 = 0; tagPtr->lMargin2String = NULL; tagPtr->lMargin2 = 0; + tagPtr->lMarginColor = NULL; tagPtr->offsetString = NULL; tagPtr->offset = 0; tagPtr->overstrikeString = NULL; tagPtr->overstrike = 0; + tagPtr->overstrikeColor = NULL; tagPtr->rMarginString = NULL; tagPtr->rMargin = 0; + tagPtr->rMarginColor = NULL; + tagPtr->selBorder = NULL; + tagPtr->selFgColor = NULL; tagPtr->spacing1String = NULL; tagPtr->spacing1 = 0; tagPtr->spacing2String = NULL; @@ -1028,6 +1062,7 @@ TkTextCreateTag( tagPtr->tabStyle = TK_TEXT_TABSTYLE_NONE; tagPtr->underlineString = NULL; tagPtr->underline = 0; + tagPtr->underlineColor = NULL; tagPtr->elideString = NULL; tagPtr->elide = 0; tagPtr->wrapMode = TEXT_WRAPMODE_NULL; @@ -1073,10 +1108,10 @@ FindTag( Tcl_Obj *tagName) /* Name of desired tag. */ { Tcl_HashEntry *hPtr; - int len; + size_t len; const char *str; - str = Tcl_GetStringFromObj(tagName, &len); + str = TkGetStringFromObj(tagName, &len); if (len == 3 && !strcmp(str, "sel")) { return textPtr->selTagPtr; } @@ -1224,8 +1259,7 @@ TkTextFreeTag( if (textPtr != tagPtr->textPtr) { Tcl_Panic("Tag being deleted from wrong widget"); } - textPtr->refCount--; - if (textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } tagPtr->textPtr = NULL; @@ -1488,7 +1522,7 @@ TkTextBindProc( } done: - if (--textPtr->refCount == 0) { + if (textPtr->refCount-- <= 1) { ckfree(textPtr); } } @@ -1529,7 +1563,8 @@ TkTextPickCurrent( 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; /* @@ -1622,7 +1657,7 @@ TkTextPickCurrent( 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]) { diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c index c9fc20f..79ed1a1 100644 --- a/generic/tkTextWind.c +++ b/generic/tkTextWind.c @@ -35,8 +35,8 @@ static const Tk_GeomMgr textGeomType = { * 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 (Tk_Offset(TkTextSegment, body) \ + + sizeof(TkTextEmbWindow)) /* * Prototypes for functions defined in this file: @@ -191,7 +191,7 @@ TkTextWindowCmd( 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; @@ -233,7 +233,7 @@ TkTextWindowCmd( 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) { @@ -403,7 +403,7 @@ EmbWinConfigure( } 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; diff --git a/generic/tkUndo.c b/generic/tkUndo.c index 8359e0a..c66905d 100644 --- a/generic/tkUndo.c +++ b/generic/tkUndo.c @@ -353,7 +353,7 @@ TkUndoInitStack( /* *---------------------------------------------------------------------- * - * TkUndoSetDepth -- + * TkUndoSetMaxDepth -- * * Set the maximum depth of stack. * @@ -368,7 +368,7 @@ TkUndoInitStack( */ void -TkUndoSetDepth( +TkUndoSetMaxDepth( TkUndoRedoStack *stack, /* An Undo/Redo stack */ int maxdepth) /* The maximum stack depth */ { @@ -478,6 +478,52 @@ TkUndoFreeStack( /* *---------------------------------------------------------------------- * + * TkUndoCanRedo -- + * + * Returns true if redo is possible, i.e. if the redo stack is not empty. + * + * Results: + * A boolean. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkUndoCanRedo( + TkUndoRedoStack *stack) /* An Undo/Redo stack */ +{ + return stack->redoStack != NULL; +} + +/* + *---------------------------------------------------------------------- + * + * TkUndoCanUndo -- + * + * Returns true if undo is possible, i.e. if the undo stack is not empty. + * + * Results: + * A boolean. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkUndoCanUndo( + TkUndoRedoStack *stack) /* An Undo/Redo stack */ +{ + return stack->undoStack != NULL; +} + +/* + *---------------------------------------------------------------------- + * * TkUndoInsertUndoSeparator -- * * Insert a separator on the undo stack, indicating a border for an @@ -498,7 +544,7 @@ TkUndoInsertUndoSeparator( { if (TkUndoInsertSeparator(&stack->undoStack)) { stack->depth++; - TkUndoSetDepth(stack, stack->maxdepth); + TkUndoSetMaxDepth(stack, stack->maxdepth); } } diff --git a/generic/tkUndo.h b/generic/tkUndo.h index e63aac4..490ede9 100644 --- a/generic/tkUndo.h +++ b/generic/tkUndo.h @@ -96,9 +96,11 @@ MODULE_SCOPE void TkUndoClearStack(TkUndoAtom **stack); */ MODULE_SCOPE TkUndoRedoStack *TkUndoInitStack(Tcl_Interp *interp, int maxdepth); -MODULE_SCOPE void TkUndoSetDepth(TkUndoRedoStack *stack, int maxdepth); +MODULE_SCOPE void TkUndoSetMaxDepth(TkUndoRedoStack *stack, int maxdepth); MODULE_SCOPE void TkUndoClearStacks(TkUndoRedoStack *stack); MODULE_SCOPE void TkUndoFreeStack(TkUndoRedoStack *stack); +MODULE_SCOPE int TkUndoCanRedo(TkUndoRedoStack *stack); +MODULE_SCOPE int TkUndoCanUndo(TkUndoRedoStack *stack); MODULE_SCOPE void TkUndoInsertUndoSeparator(TkUndoRedoStack *stack); MODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command, Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList); diff --git a/generic/tkUtil.c b/generic/tkUtil.c index 7ff9ecb..56d80bc 100644 --- a/generic/tkUtil.c +++ b/generic/tkUtil.c @@ -729,11 +729,11 @@ Tk_GetScrollInfoObj( 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; + size_t length; + const char *arg = TkGetStringFromObj(objv[2], &length); #define ArgPfxEq(str) \ - ((arg[0] == str[0]) && !strncmp(arg, str, (unsigned)length)) + ((arg[0] == str[0]) && !strncmp(arg, str, length)) if (ArgPfxEq("moveto")) { if (objc != 4) { @@ -753,8 +753,7 @@ Tk_GetScrollInfoObj( 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")) { @@ -1162,7 +1161,8 @@ TkMakeEnsemble( * TkSendVirtualEvent -- * * Send a virtual event notification to the specified target window. - * Equivalent to "event generate $target <<$eventName>>" + * Equivalent to: + * "event generate $target <<$eventName>> -data $detail" * * Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, so this * routine does not reenter the interpreter. @@ -1173,7 +1173,8 @@ TkMakeEnsemble( void TkSendVirtualEvent( Tk_Window target, - const char *eventName) + const char *eventName, + Tcl_Obj *detail) { union {XEvent general; XVirtualEvent virtual;} event; @@ -1184,9 +1185,114 @@ TkSendVirtualEvent( 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; + } Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL); } + +#if TCL_UTF_MAX <= 4 +/* + *--------------------------------------------------------------------------- + * + * TkUtfToUniChar -- + * + * Almost the same as Tcl_UtfToUniChar but using int instead of Tcl_UniChar. + * This function is capable of collapsing a upper/lower surrogate pair to a + * single unicode character. So, up to 6 bytes might be consumed. + * + * Results: + * *chPtr is filled with the Tcl_UniChar, and the return value is the + * number of bytes from the UTF-8 string that were consumed. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +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; + + 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 */ + size_t len2 = Tcl_UtfToUniChar(src+len, &uniChar); + if ((uniChar & 0xfc00) == 0xdc00) { + *chPtr = (((high & 0x3ff) << 10) | (uniChar & 0x3ff)) + 0x10000; + len += len2; + } else { + *chPtr = high; + } + } else { + *chPtr = uniChar; + } + return len; +} + +/* + *--------------------------------------------------------------------------- + * + * TkUniCharToUtf -- + * + * Almost the same as Tcl_UniCharToUtf but producing surrogates if + * TCL_UTF_MAX==3. So, up to 6 bytes might be produced. + * + * Results: + * *buf is filled with the UTF-8 string, and the return value is the + * number of bytes produced. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +size_t TkUniCharToUtf(int ch, char *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); + size += Tcl_UniCharToUtf(((ch & 0x3ff) | 0xdc00), buf+size); + } + return size; +} + + +#endif + +#ifndef TCL_TYPE_I +unsigned char * +TkGetByteArrayFromObj( + Tcl_Obj *objPtr, + size_t *lengthPtr +) { + int length; + + unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, &length); +#if TK_MAJOR_VERSION > 8 + if (sizeof(TCL_HASH_TYPE) > sizeof(int)) { + /* 64-bit and TIP #494 situation: */ + *lengthPtr = *(TCL_HASH_TYPE *) objPtr->internalRep.twoPtrValue.ptr1; + } else +#endif + /* 32-bit or without TIP #494 */ + *lengthPtr = (size_t) (unsigned) length; + return result; +} +#endif /* !TCL_TYPE_I */ + /* * Local Variables: * mode: c diff --git a/generic/tkVisual.c b/generic/tkVisual.c index 8b0c155..427e946 100644 --- a/generic/tkVisual.c +++ b/generic/tkVisual.c @@ -21,9 +21,9 @@ 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}, @@ -46,7 +46,7 @@ static const VisualDictionary visualNames[] = { 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 @@ -99,7 +99,7 @@ Tk_GetVisual( 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; @@ -137,7 +137,7 @@ Tk_GetVisual( for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == *colormapPtr) { - cmapPtr->refCount += 1; + cmapPtr->refCount++; break; } } @@ -195,8 +195,7 @@ Tk_GetVisual( 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; } @@ -324,7 +323,7 @@ Tk_GetVisual( cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->shareable && (cmapPtr->visual == visual)) { *colormapPtr = cmapPtr->colormap; - cmapPtr->refCount += 1; + cmapPtr->refCount++; goto done; } } @@ -427,7 +426,7 @@ Tk_GetColormap( for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == colormap) { - cmapPtr->refCount += 1; + cmapPtr->refCount++; } } return colormap; @@ -476,8 +475,7 @@ 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; @@ -534,7 +532,7 @@ Tk_PreserveColormap( for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { if (cmapPtr->colormap == colormap) { - cmapPtr->refCount += 1; + cmapPtr->refCount++; return; } } diff --git a/generic/tkWindow.c b/generic/tkWindow.c index b5cbbab..d36313b 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -54,12 +54,6 @@ typedef struct ThreadSpecificData { static Tcl_ThreadDataKey dataKey; /* - * The Mutex below is used to lock access to the Tk_Uid structs above. - */ - -TCL_DECLARE_MUTEX(windowMutex) - -/* * Default values for "changes" and "atts" fields of TkWindows. Note that Tk * always requests all events for all windows, except StructureNotify events * on internal windows: these events are generated internally. @@ -206,40 +200,6 @@ static const TkCmd commands[] = { }; /* - * The variables and table below are used to parse arguments from the "argv" - * variable in Tk_Init. - */ - -static int synchronize = 0; -static char *name = NULL; -static char *display = NULL; -static char *geometry = NULL; -static char *colormap = NULL; -static char *use = NULL; -static char *visual = NULL; -static int rest = 0; - -static const Tk_ArgvInfo argTable[] = { - {"-colormap", TK_ARGV_STRING, NULL, (char *) &colormap, - "Colormap for main window"}, - {"-display", TK_ARGV_STRING, NULL, (char *) &display, - "Display to use"}, - {"-geometry", TK_ARGV_STRING, NULL, (char *) &geometry, - "Initial geometry for window"}, - {"-name", TK_ARGV_STRING, NULL, (char *) &name, - "Name to use for application"}, - {"-sync", TK_ARGV_CONSTANT, (char *) 1, (char *) &synchronize, - "Use synchronous mode for display server"}, - {"-visual", TK_ARGV_STRING, NULL, (char *) &visual, - "Visual for main window"}, - {"-use", TK_ARGV_STRING, NULL, (char *) &use, - "Id of window in which to embed application"}, - {"--", TK_ARGV_REST, (char *) 1, (char *) &rest, - "Pass all remaining arguments through to script"}, - {NULL, TK_ARGV_END, NULL, NULL, NULL} -}; - -/* * Forward declarations to functions defined later in this file: */ @@ -279,6 +239,8 @@ TkCloseDisplay( { TkClipCleanup(dispPtr); + TkpCancelWarp(dispPtr); + if (dispPtr->name != NULL) { ckfree(dispPtr->name); } @@ -374,6 +336,7 @@ CreateTopLevelWindow( * Create built-in photo image formats. */ + Tk_CreatePhotoImageFormat(&tkImgFmtDefault); Tk_CreatePhotoImageFormat(&tkImgFmtGIF); Tk_CreatePhotoImageFormat(&tkImgFmtPNG); Tk_CreatePhotoImageFormat(&tkImgFmtPPM); @@ -395,6 +358,9 @@ CreateTopLevelWindow( * Set the flags specified in the call. */ +#ifdef TK_USE_INPUT_METHODS + winPtr->ximGeneration = 0; +#endif /*TK_USE_INPUT_METHODS*/ winPtr->flags |= flags; /* @@ -690,6 +656,7 @@ TkAllocWindow( winPtr->flags = 0; winPtr->handlerList = NULL; #ifdef TK_USE_INPUT_METHODS + winPtr->ximGeneration = 0; winPtr->inputContext = NULL; #endif /* TK_USE_INPUT_METHODS */ winPtr->tagPtr = NULL; @@ -983,7 +950,7 @@ TkCreateMainWindow( } /* - * Set variables for the intepreter. + * Set variables for the interpreter. */ Tcl_SetVar2(interp, "tk_patchLevel", NULL, TK_PATCH_LEVEL, TCL_GLOBAL_ONLY); @@ -1169,7 +1136,7 @@ Tk_CreateWindowFromPath( 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 @@ -1186,7 +1153,7 @@ Tk_CreateWindowFromPath( 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 { @@ -1196,7 +1163,7 @@ Tk_CreateWindowFromPath( *p = '.'; p[1] = '\0'; } else { - strncpy(p, pathName, (size_t) numChars); + strncpy(p, pathName, numChars); p[numChars] = '\0'; } @@ -1482,10 +1449,11 @@ Tk_DestroyWindow( UnlinkWindow(winPtr); TkEventDeadWindow(winPtr); #ifdef TK_USE_INPUT_METHODS - if (winPtr->inputContext != NULL) { + if (winPtr->inputContext != NULL && + winPtr->ximGeneration == winPtr->dispPtr->ximGeneration) { XDestroyIC(winPtr->inputContext); - winPtr->inputContext = NULL; } + winPtr->inputContext = NULL; #endif /* TK_USE_INPUT_METHODS */ if (winPtr->tagPtr != NULL) { TkFreeBindingTags(winPtr); @@ -1519,8 +1487,7 @@ Tk_DestroyWindow( winPtr->mainPtr->deletionEpoch++; } - winPtr->mainPtr->refCount--; - if (winPtr->mainPtr->refCount == 0) { + if (winPtr->mainPtr->refCount-- <= 1) { register const TkCmd *cmdPtr; /* @@ -2391,6 +2358,9 @@ Tk_IdToWindow( break; } } + if (window == None) { + return NULL; + } hPtr = Tcl_FindHashEntry(&dispPtr->winTable, (char *) window); if (hPtr == NULL) { @@ -2817,6 +2787,18 @@ DeleteWindowsExitProc( } /* + * Let error handlers catch up before actual close of displays. + * Must be done before tsdPtr->displayList is cleared, otherwise + * ErrorProc() in tkError.c cannot associate the pending X errors + * to the remaining error handlers. + */ + + for (dispPtr = tsdPtr->displayList; dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { + XSync(dispPtr->display, False); + } + + /* * Iterate destroying the displays until no more displays remain. It is * possible for displays to get recreated during exit by any code that * calls GetScreen, so we must destroy these new displays as well as the @@ -3028,22 +3010,57 @@ MODULE_SCOPE const TkStubs tkStubs; */ static int +CopyValue( + ClientData dummy, + Tcl_Obj *objPtr, + void *dstPtr) +{ + *(Tcl_Obj **)dstPtr = objPtr; + return 1; +} + +static int Initialize( Tcl_Interp *interp) /* Interpreter to initialize. */ { - char *p; - int argc, code; - const char **argv; - const char *args[20]; - const char *argString = NULL; - Tcl_DString class; + int code = TCL_OK; ThreadSpecificData *tsdPtr; + Tcl_Obj *value = NULL; + Tcl_Obj *cmd; + + Tcl_Obj *nameObj = NULL; + Tcl_Obj *classObj = NULL; + Tcl_Obj *displayObj = NULL; + Tcl_Obj *colorMapObj = NULL; + Tcl_Obj *useObj = NULL; + Tcl_Obj *visualObj = NULL; + Tcl_Obj *geometryObj = NULL; + + int sync = 0; + + const Tcl_ArgvInfo table[] = { + {TCL_ARGV_CONSTANT, "-sync", INT2PTR(1), &sync, + "Use synchronous mode for display server", NULL}, + {TCL_ARGV_FUNC, "-colormap", CopyValue, &colorMapObj, + "Colormap for main window", NULL}, + {TCL_ARGV_FUNC, "-display", CopyValue, &displayObj, + "Display to use", NULL}, + {TCL_ARGV_FUNC, "-geometry", CopyValue, &geometryObj, + "Initial geometry for window", NULL}, + {TCL_ARGV_FUNC, "-name", CopyValue, &nameObj, + "Name to use for application", NULL}, + {TCL_ARGV_FUNC, "-visual", CopyValue, &visualObj, + "Visual for main window", NULL}, + {TCL_ARGV_FUNC, "-use", CopyValue, &useObj, + "Id of window in which to embed application", NULL}, + TCL_ARGV_AUTO_REST, TCL_ARGV_AUTO_HELP, TCL_ARGV_TABLE_END + }; /* * 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; } @@ -3056,23 +3073,6 @@ Initialize( tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * Start by initializing all the static variables to default acceptable - * values so that no information is leaked from a previous run of this - * code. - */ - - Tcl_MutexLock(&windowMutex); - synchronize = 0; - name = NULL; - display = NULL; - geometry = NULL; - colormap = NULL; - use = NULL; - visual = NULL; - rest = 0; - argv = NULL; - - /* * We start by resetting the result because it might not be clean. */ @@ -3084,8 +3084,6 @@ Initialize( * master. */ - Tcl_DString ds; - /* * Step 1 : find the master and construct the interp name (could be a * function if new APIs were ok). We could also construct the path @@ -3095,18 +3093,13 @@ Initialize( Tcl_Interp *master = interp; - while (1) { + while (Tcl_IsSafe(master)) { master = Tcl_GetMaster(master); if (master == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no controlling master interpreter", -1)); Tcl_SetErrorCode(interp, "TK", "SAFE", "NO_MASTER", NULL); - code = TCL_ERROR; - goto done; - } - if (!Tcl_IsSafe(master)) { - /* Found the trusted master. */ - break; + return TCL_ERROR; } } @@ -3116,39 +3109,30 @@ Initialize( code = Tcl_GetInterpPath(master, interp); if (code != TCL_OK) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "error in Tcl_GetInterpPath", -1)); - Tcl_SetErrorCode(interp, "TK", "SAFE", "FAILED", NULL); - goto done; + Tcl_Panic("Tcl_GetInterpPath broken!"); } /* - * Build the string to eval. + * Build the command to eval in trusted master. */ - Tcl_DStringInit(&ds); - Tcl_DStringAppendElement(&ds, "::safe::TkInit"); - Tcl_DStringAppendElement(&ds, Tcl_GetString(Tcl_GetObjResult(master))); + cmd = Tcl_NewListObj(2, NULL); + Tcl_ListObjAppendElement(NULL, cmd, + Tcl_NewStringObj("::safe::TkInit", -1)); + Tcl_ListObjAppendElement(NULL, cmd, Tcl_GetObjResult(master)); /* * Step 2 : Eval in the master. The argument is the *reversed* interp * path of the slave. */ - code = Tcl_EvalEx(master, Tcl_DStringValue(&ds), -1, 0); + Tcl_IncrRefCount(cmd); + code = Tcl_EvalObjEx(master, cmd, 0); + Tcl_DecrRefCount(cmd); + Tcl_TransferResult(master, code, interp); if (code != TCL_OK) { - /* - * We might want to transfer the error message or not. We don't. - * (No API to do it and maybe security reasons). - */ - - Tcl_DStringFree(&ds); - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "not allowed to start Tk by master's safe::TkInit", -1)); - Tcl_SetErrorCode(interp, "TK", "SAFE", "FAILED", NULL); - goto done; + return code; } - Tcl_DStringFree(&ds); /* * Use the master's result as argv. Note: We don't use the Obj @@ -3156,7 +3140,7 @@ Initialize( * changing the code below. */ - argString = Tcl_GetString(Tcl_GetObjResult(master)); + value = Tcl_GetObjResult(interp); } else { /* * If there is an "argv" variable, get its value, extract out relevant @@ -3164,50 +3148,67 @@ Initialize( * that we used. */ - argString = Tcl_GetVar2(interp, "argv", NULL, TCL_GLOBAL_ONLY); + value = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY); } - if (argString != NULL) { - char buffer[TCL_INTEGER_SPACE]; - if (Tcl_SplitList(interp, argString, &argc, &argv) != TCL_OK) { - argError: + if (value) { + int objc; + Tcl_Obj **objv, **rest; + Tcl_Obj *parseList = Tcl_NewListObj(1, NULL); + + Tcl_ListObjAppendElement(NULL, parseList, Tcl_NewObj()); + + Tcl_IncrRefCount(value); + if (TCL_OK != Tcl_ListObjAppendList(interp, parseList, value) || + TCL_OK != Tcl_ListObjGetElements(NULL, parseList, &objc, &objv) || + TCL_OK != Tcl_ParseArgsObjv(interp, table, &objc, objv, &rest)) { Tcl_AddErrorInfo(interp, "\n (processing arguments in argv variable)"); code = TCL_ERROR; - goto done; } - if (Tk_ParseArgv(interp, (Tk_Window) NULL, &argc, argv, - argTable, TK_ARGV_DONT_SKIP_FIRST_ARG|TK_ARGV_NO_DEFAULTS) - != TCL_OK) { - goto argError; + 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); + ckfree(rest); + } + Tcl_DecrRefCount(parseList); + if (code != TCL_OK) { + goto done; } - p = Tcl_Merge(argc, argv); - Tcl_SetVar2(interp, "argv", NULL, p, TCL_GLOBAL_ONLY); - sprintf(buffer, "%d", argc); - Tcl_SetVar2(interp, "argc", NULL, buffer, TCL_GLOBAL_ONLY); - ckfree(p); } /* * Figure out the application's name and class. */ - Tcl_DStringInit(&class); - if (name == NULL) { - int offset; + /* + * If we got no -name argument, fetch from TkpGetAppName(). + */ - TkpGetAppName(interp, &class); - offset = Tcl_DStringLength(&class)+1; - Tcl_DStringSetLength(&class, offset); - Tcl_DStringAppend(&class, Tcl_DStringValue(&class), offset-1); - name = Tcl_DStringValue(&class) + offset; - } else { - Tcl_DStringAppend(&class, name, -1); + if (nameObj == NULL) { + Tcl_DString nameDS; + + Tcl_DStringInit(&nameDS); + TkpGetAppName(interp, &nameDS); + nameObj = Tcl_NewStringObj(Tcl_DStringValue(&nameDS), + Tcl_DStringLength(&nameDS)); + Tcl_DStringFree(&nameDS); } - p = Tcl_DStringValue(&class); - if (*p) { - Tcl_UtfToTitle(p); + /* + * The -class argument is always the ToTitle of the -name + */ + + { + size_t numBytes; + const char *bytes = TkGetStringFromObj(nameObj, &numBytes); + + classObj = Tcl_NewStringObj(bytes, numBytes); + + numBytes = Tcl_UtfToTitle(Tcl_GetString(classObj)); + Tcl_SetObjLength(classObj, numBytes); } /* @@ -3215,15 +3216,14 @@ Initialize( * information parsed from argv, if any. */ - args[0] = "toplevel"; - args[1] = "."; - args[2] = "-class"; - args[3] = Tcl_DStringValue(&class); - argc = 4; - if (display != NULL) { - args[argc] = "-screen"; - args[argc+1] = display; - argc += 2; + cmd = Tcl_NewStringObj("toplevel . -class", -1); + + Tcl_ListObjAppendElement(NULL, cmd, classObj); + classObj = NULL; + + if (displayObj) { + Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-screen", -1)); + Tcl_ListObjAppendElement(NULL, cmd, displayObj); /* * If this is the first application for this process, save the display @@ -3232,36 +3232,35 @@ Initialize( */ if (tsdPtr->numMainWindows == 0) { - Tcl_SetVar2(interp, "env", "DISPLAY", display, TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(interp, "env", "DISPLAY", displayObj, TCL_GLOBAL_ONLY); } + displayObj = NULL; } - if (colormap != NULL) { - args[argc] = "-colormap"; - args[argc+1] = colormap; - argc += 2; - colormap = NULL; + if (colorMapObj) { + Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-colormap", -1)); + Tcl_ListObjAppendElement(NULL, cmd, colorMapObj); + colorMapObj = NULL; } - if (use != NULL) { - args[argc] = "-use"; - args[argc+1] = use; - argc += 2; - use = NULL; + if (useObj) { + Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-use", -1)); + Tcl_ListObjAppendElement(NULL, cmd, useObj); + useObj = NULL; } - if (visual != NULL) { - args[argc] = "-visual"; - args[argc+1] = visual; - argc += 2; - visual = NULL; + if (visualObj) { + Tcl_ListObjAppendElement(NULL, cmd, Tcl_NewStringObj("-visual", -1)); + Tcl_ListObjAppendElement(NULL, cmd, visualObj); + visualObj = NULL; } - args[argc] = NULL; - code = TkCreateFrame(NULL, interp, argc, args, 1, name); - Tcl_DStringFree(&class); + code = TkListCreateFrame(NULL, interp, cmd, 1, nameObj); + + Tcl_DecrRefCount(cmd); + if (code != TCL_OK) { goto done; } Tcl_ResetResult(interp); - if (synchronize) { + if (sync) { XSynchronize(Tk_Display(Tk_MainWindow(interp)), True); } @@ -3270,19 +3269,19 @@ Initialize( * geometry into the "geometry" variable. */ - if (geometry != NULL) { - Tcl_DString buf; + if (geometryObj) { - Tcl_SetVar2(interp, "geometry", NULL, geometry, TCL_GLOBAL_ONLY); - Tcl_DStringInit(&buf); - Tcl_DStringAppend(&buf, "wm geometry . ", -1); - Tcl_DStringAppend(&buf, geometry, -1); - code = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0); - Tcl_DStringFree(&buf); + Tcl_SetVar2Ex(interp, "geometry", NULL, geometryObj, TCL_GLOBAL_ONLY); + + cmd = Tcl_NewStringObj("wm geometry .", -1); + Tcl_ListObjAppendElement(NULL, cmd, geometryObj); + Tcl_IncrRefCount(cmd); + code = Tcl_EvalObjEx(interp, cmd, 0); + Tcl_DecrRefCount(cmd); + geometryObj = NULL; if (code != TCL_OK) { goto done; } - geometry = NULL; } /* @@ -3319,10 +3318,6 @@ Initialize( * console window interpreter. */ - Tcl_MutexUnlock(&windowMutex); - if (argv != NULL) { - ckfree(argv); - } code = TkpInit(interp); if (code == TCL_OK) { @@ -3355,12 +3350,10 @@ tkInit", -1, 0); TkCreateThreadExitHandler(DeleteWindowsExitProc, tsdPtr); } - return code; - done: - Tcl_MutexUnlock(&windowMutex); - if (argv != NULL) { - ckfree(argv); + if (value) { + Tcl_DecrRefCount(value); + value = NULL; } return code; } diff --git a/generic/ttk/ttkBlink.c b/generic/ttk/ttkBlink.c index 706a871..7294f8b 100644 --- a/generic/ttk/ttkBlink.c +++ b/generic/ttk/ttkBlink.c @@ -14,7 +14,7 @@ * Add script-level access to configure application-wide blink rate. */ -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" diff --git a/generic/ttk/ttkButton.c b/generic/ttk/ttkButton.c index bc44f25..722e034 100644 --- a/generic/ttk/ttkButton.c +++ b/generic/ttk/ttkButton.c @@ -4,8 +4,7 @@ * label, button, checkbutton, radiobutton, and menubutton widgets. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -23,6 +22,7 @@ typedef struct * Text element resources: */ Tcl_Obj *textObj; + Tcl_Obj *justifyObj; Tcl_Obj *textVariableObj; Tcl_Obj *underlineObj; Tcl_Obj *widthObj; @@ -56,6 +56,9 @@ typedef struct static Tk_OptionSpec BaseOptionSpecs[] = { + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "left", Tk_Offset(Base,base.justifyObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-text", "text", "Text", "", Tk_Offset(Base,base.textObj), -1, 0,0,GEOMETRY_CHANGED }, @@ -136,6 +139,15 @@ BaseCleanup(void *recordPtr) TtkFreeImageSpec(basePtr->base.imageSpec); } +static void +BaseImageChanged( + ClientData clientData, int x, int y, int width, int height, + int imageWidth, int imageHeight) +{ + Base *basePtr = (Base *)clientData; + TtkResizeWidget(&basePtr->core); +} + static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask) { Base *basePtr = recordPtr; @@ -149,8 +161,8 @@ static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask) } if (basePtr->base.imageObj) { - imageSpec = TtkGetImageSpec( - interp, basePtr->core.tkwin, basePtr->base.imageObj); + imageSpec = TtkGetImageSpecEx( + interp, basePtr->core.tkwin, basePtr->base.imageObj, BaseImageChanged, basePtr); if (!imageSpec) { goto error; } @@ -480,12 +492,15 @@ static int CheckbuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask) { Checkbutton *checkPtr = recordPtr; - Ttk_TraceHandle *vt = Ttk_TraceVariable( - interp, checkPtr->checkbutton.variableObj, - CheckbuttonVariableChanged, checkPtr); - - if (!vt) { - return TCL_ERROR; + 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; + } } if (BaseConfigure(interp, recordPtr, mask) != TCL_OK){ @@ -493,7 +508,9 @@ CheckbuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask) return TCL_ERROR; } - Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace); + if (checkPtr->checkbutton.variableTrace) { + Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace); + } checkPtr->checkbutton.variableTrace = vt; return TCL_OK; @@ -539,10 +556,13 @@ CheckbuttonInvokeCommand( else newValue = checkPtr->checkbutton.onValueObj; - if (Tcl_ObjSetVar2(interp, - checkPtr->checkbutton.variableObj, NULL, newValue, - TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) - == NULL) + if (checkPtr->checkbutton.variableObj == NULL || + *Tcl_GetString(checkPtr->checkbutton.variableObj) == '\0') + CheckbuttonVariableChanged(checkPtr, Tcl_GetString(newValue)); + else if (Tcl_ObjSetVar2(interp, + checkPtr->checkbutton.variableObj, NULL, newValue, + TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) + == NULL) return TCL_ERROR; if (WidgetDestroyed(corePtr)) diff --git a/generic/ttk/ttkCache.c b/generic/ttk/ttkCache.c index 0ae2372..c29007c 100644 --- a/generic/ttk/ttkCache.c +++ b/generic/ttk/ttkCache.c @@ -28,8 +28,7 @@ * but this will be a transient effect. */ -#include <stdio.h> /* for sprintf */ -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" struct Ttk_ResourceCache_ { diff --git a/generic/ttk/ttkClamTheme.c b/generic/ttk/ttkClamTheme.c index 15ebcb7..e9bc74a 100644 --- a/generic/ttk/ttkClamTheme.c +++ b/generic/ttk/ttkClamTheme.c @@ -4,11 +4,11 @@ * "clam" theme; inspired by the XFCE family of Gnome themes. */ -#include <tk.h> +#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. */ @@ -123,8 +123,8 @@ static Ttk_ElementOptionSpec BorderElementOptions[] = { /* * <<NOTE-BORDERWIDTH>>: -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. */ @@ -402,7 +402,7 @@ typedef struct { static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = { { "-arrowsize", TK_OPTION_PIXELS, - Tk_Offset(MenuIndicatorElement,sizeObj), + Tk_Offset(MenuIndicatorElement,sizeObj), STR(MENUBUTTON_ARROW_SIZE)}, { "-arrowcolor",TK_OPTION_COLOR, Tk_Offset(MenuIndicatorElement,colorObj), @@ -630,7 +630,7 @@ static void ThumbElementDraw( 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; @@ -710,12 +710,12 @@ static void PbarElementDraw( 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); } @@ -780,8 +780,8 @@ static Ttk_ElementSpec ArrowElementSpec = { /*------------------------------------------------------------------------ * +++ 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. */ diff --git a/generic/ttk/ttkClassicTheme.c b/generic/ttk/ttkClassicTheme.c index 2fbcd76..117d928 100644 --- a/generic/ttk/ttkClassicTheme.c +++ b/generic/ttk/ttkClassicTheme.c @@ -5,7 +5,7 @@ * */ -#include <tk.h> +#include "tkInt.h" #include <X11/Xlib.h> #include <X11/Xutil.h> #include "ttkTheme.h" @@ -68,7 +68,7 @@ static Ttk_ElementSpec HighlightElementSpec = /*------------------------------------------------------------------------ * +++ Button Border element: - * + * * The Motif-style button border on X11 consists of (from outside-in): * * + focus indicator (controlled by -highlightcolor and -highlightthickness), @@ -85,13 +85,13 @@ typedef struct { static Ttk_ElementOptionSpec ButtonBorderElementOptions[] = { - { "-background", TK_OPTION_BORDER, + { "-background", TK_OPTION_BORDER, Tk_Offset(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND }, - { "-borderwidth", TK_OPTION_PIXELS, + { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, - { "-relief", TK_OPTION_RELIEF, + { "-relief", TK_OPTION_RELIEF, Tk_Offset(ButtonBorderElement,reliefObj), "flat" }, - { "-default", TK_OPTION_ANY, + { "-default", TK_OPTION_ANY, Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" }, { NULL, 0, 0, NULL } }; @@ -115,7 +115,7 @@ static void ButtonBorderElementSize( /* * (@@@ 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( @@ -281,19 +281,19 @@ static Ttk_ElementSpec ArrowElementSpec = /*------------------------------------------------------------------------ * +++ 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 { @@ -306,13 +306,13 @@ typedef struct { } SashElement; static Ttk_ElementOptionSpec SashOptions[] = { - { "-background", TK_OPTION_BORDER, + { "-background", TK_OPTION_BORDER, Tk_Offset(SashElement,borderObj), DEFAULT_BACKGROUND }, - { "-sashrelief", TK_OPTION_RELIEF, + { "-sashrelief", TK_OPTION_RELIEF, Tk_Offset(SashElement,sashReliefObj), "sunken" }, { "-sashthickness", TK_OPTION_PIXELS, Tk_Offset(SashElement,sashThicknessObj), "6" }, - { "-sashpad", TK_OPTION_PIXELS, + { "-sashpad", TK_OPTION_PIXELS, Tk_Offset(SashElement,sashPadObj), "2" }, { "-handlesize", TK_OPTION_PIXELS, Tk_Offset(SashElement,handleSizeObj), "8" }, @@ -367,10 +367,10 @@ static void SashElementDraw( 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; @@ -398,7 +398,7 @@ static void SashElementDraw( 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); } } @@ -495,7 +495,7 @@ MODULE_SCOPE int TtkClassicTheme_Init(Tcl_Interp *interp) 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]); diff --git a/generic/ttk/ttkDefaultTheme.c b/generic/ttk/ttkDefaultTheme.c index 81f8126..2118704 100644 --- a/generic/ttk/ttkDefaultTheme.c +++ b/generic/ttk/ttkDefaultTheme.c @@ -4,10 +4,7 @@ * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme */ -#include <math.h> -#include <string.h> - -#include <tkInt.h> +#include "tkInt.h" #include <X11/Xlib.h> #include <X11/Xutil.h> #include "ttkTheme.h" @@ -209,6 +206,9 @@ void TtkFillArrow( ArrowPoints(b, dir, points); XFillPolygon(display, d, gc, points, 3, Convex, CoordModeOrigin); XDrawLines(display, d, gc, points, 4, CoordModeOrigin); + + /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */ + XDrawPoint(display, d, gc, points[2].x, points[2].y); } /*public*/ @@ -218,6 +218,9 @@ void TtkDrawArrow( XPoint points[4]; ArrowPoints(b, dir, points); XDrawLines(display, d, gc, points, 4, CoordModeOrigin); + + /* Work around bug [77527326e5] - ttk artifacts on Ubuntu */ + XDrawPoint(display, d, gc, points[2].x, points[2].y); } /* @@ -680,7 +683,7 @@ typedef struct { 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 }; diff --git a/generic/ttk/ttkElements.c b/generic/ttk/ttkElements.c index 5c95dba..4dd2adb 100644 --- a/generic/ttk/ttkElements.c +++ b/generic/ttk/ttkElements.c @@ -5,9 +5,7 @@ * */ -#include <tcl.h> -#include <tk.h> -#include <string.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index f395649..e5268e7 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -8,9 +8,7 @@ * Copyright (c) 2004 Joe English */ -#include <string.h> -#include <stdio.h> -#include <tkInt.h> +#include "tkInt.h" #include <X11/Xatom.h> #include "ttkTheme.h" @@ -73,6 +71,7 @@ static const char *const validateReasonStrings[] = { /* 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 */ @@ -118,6 +117,8 @@ typedef struct { Tcl_Obj *stateObj; /* Compatibility option -- see CheckStateObj */ + Tcl_Obj *placeholderObj; /* Text to display for placeholder text */ + /* * Derived resources: */ @@ -147,12 +148,13 @@ typedef struct { /* * 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", @@ -167,6 +169,9 @@ static Tk_OptionSpec EntryOptionSpecs[] = { {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", "left", -1, Tk_Offset(Entry, entry.justify), 0, 0, GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-placeholder", "placeHolder", "PlaceHolder", + NULL, Tk_Offset(Entry, entry.placeholderObj), -1, + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-show", "show", "Show", NULL, -1, Tk_Offset(Entry, entry.showChar), TK_OPTION_NULL_OK, 0, 0}, @@ -191,11 +196,15 @@ static Tk_OptionSpec EntryOptionSpecs[] = { /* EntryStyleData options: */ + {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", + NULL, Tk_Offset(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, 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, + Tk_Offset(Entry, entry.styleData.placeholderForegroundObj), -1, TK_OPTION_NULL_OK,0,0}, WIDGET_TAKEFOCUS_TRUE, @@ -216,6 +225,7 @@ 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) @@ -227,6 +237,7 @@ static void EntryInitStyleDefaults(EntryStyleData *es) static void EntryFreeStyleDefaults(EntryStyleData *es) { + Tcl_DecrRefCount(es->placeholderForegroundObj); Tcl_DecrRefCount(es->foregroundObj); Tcl_DecrRefCount(es->selBorderObj); Tcl_DecrRefCount(es->selForegroundObj); @@ -253,6 +264,7 @@ static void EntryInitStyleData(Entry *entryPtr, EntryStyleData *es) # 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") @@ -263,6 +275,7 @@ static void EntryInitStyleData(Entry *entryPtr, EntryStyleData *es) /* 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); @@ -282,15 +295,16 @@ static char *EntryDisplayString(const char *showChar, int numChars) { char *displayString, *p; int size; - Tcl_UniChar ch; - char buf[TCL_UTF_MAX]; + int ch; + char buf[6]; - Tcl_UtfToUniChar(showChar, &ch); - size = Tcl_UniCharToUtf(ch, buf); + TkUtfToUniChar(showChar, &ch); + size = TkUniCharToUtf(ch, buf); p = displayString = ckalloc(numChars * size + 1); while (numChars--) { - p += Tcl_UniCharToUtf(ch, p); + memcpy(p, buf, size); + p += size; } *p = '\0'; @@ -303,12 +317,23 @@ static char *EntryDisplayString(const char *showChar, int numChars) */ static void EntryUpdateTextLayout(Entry *entryPtr) { + size_t 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 -- @@ -336,7 +361,8 @@ EntryFetchSelection( const char *string; const char *selStart, *selEnd; - if (entryPtr->entry.selectFirst < 0 || !entryPtr->entry.exportSelection) { + if (entryPtr->entry.selectFirst < 0 || (!entryPtr->entry.exportSelection) + || Tcl_IsSafe(entryPtr->core.interp)) { return -1; } string = entryPtr->entry.displayString; @@ -371,11 +397,12 @@ static void EntryLostSelection(ClientData clientData) /* EntryOwnSelection -- * Assert ownership of the PRIMARY selection, - * if -exportselection set and selection is present. + * if -exportselection set and selection is present and interp is unsafe. */ static void EntryOwnSelection(Entry *entryPtr) { if (entryPtr->entry.exportSelection + && (!Tcl_IsSafe(entryPtr->core.interp)) && !(entryPtr->core.flags & GOT_SELECTION)) { Tk_OwnSelection(entryPtr->core.tkwin, XA_PRIMARY, EntryLostSelection, (ClientData) entryPtr); @@ -405,7 +432,7 @@ ExpandPercents( int number, length; const char *string; int stringLength; - Tcl_UniChar ch; + int ch; char numStorage[2*TCL_INTEGER_SPACE]; while (*template) { @@ -429,7 +456,7 @@ ExpandPercents( */ ++template; /* skip over % */ if (*template != '\0') { - template += Tcl_UtfToUniChar(template, &ch); + template += TkUtfToUniChar(template, &ch); } else { ch = '%'; } @@ -479,7 +506,7 @@ ExpandPercents( string = Tk_PathName(entryPtr->core.tkwin); break; default: - length = Tcl_UniCharToUtf(ch, numStorage); + length = TkUniCharToUtf(ch, numStorage); numStorage[length] = '\0'; string = numStorage; break; @@ -558,7 +585,7 @@ static int EntryNeedsValidation(VMODE vmode, VREASON reason) * 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. @@ -998,7 +1025,8 @@ static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask) /* Claim the selection, in case we've suddenly started exporting it. */ - if (entryPtr->entry.exportSelection && entryPtr->entry.selectFirst != -1) { + if (entryPtr->entry.exportSelection && (entryPtr->entry.selectFirst != -1) + && (!Tcl_IsSafe(entryPtr->core.interp))) { EntryOwnSelection(entryPtr); } @@ -1174,6 +1202,7 @@ static void EntryDisplay(void *clientData, Drawable d) Ttk_Box textarea; TkRegion clipRegion; XRectangle rect; + Tcl_Obj *foregroundObj; EntryInitStyleData(entryPtr, &es); @@ -1240,6 +1269,7 @@ static void EntryDisplay(void *clientData, Drawable d) /* Draw cursor: */ if (showCursor) { + Ttk_Box field = Ttk_ClientRegion(entryPtr->core.layout, "field"); int cursorX = EntryCharPosition(entryPtr, entryPtr->entry.insertPos), cursorY = entryPtr->entry.layoutY, cursorHeight = entryPtr->entry.layoutHeight, @@ -1253,16 +1283,36 @@ static void EntryDisplay(void *clientData, Drawable d) /* @@@ should: maybe: SetCaretPos even when blinked off */ Tk_SetCaretPos(tkwin, cursorX, cursorY, cursorHeight); - gc = EntryGetGC(entryPtr, es.insertColorObj, clipRegion); + cursorX -= cursorWidth/2; + if (cursorX < field.x) { + cursorX = field.x; + } else if (cursorX + cursorWidth > field.x + field.width) { + cursorX = field.x + field.width - cursorWidth; + } + + gc = EntryGetGC(entryPtr, es.insertColorObj, None); XFillRectangle(Tk_Display(tkwin), d, gc, - cursorX-cursorWidth/2, cursorY, cursorWidth, cursorHeight); - XSetClipMask(Tk_Display(tkwin), gc, None); + cursorX, cursorY, cursorWidth, cursorHeight); 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, @@ -1314,8 +1364,8 @@ EntryIndex( 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; + size_t length; + const char *string = TkGetStringFromObj(indexObj, &length); if (strncmp(string, "end", length) == 0) { *indexPtr = entryPtr->entry.numChars; diff --git a/generic/ttk/ttkFrame.c b/generic/ttk/ttkFrame.c index 3e50a7f..10106eb 100644 --- a/generic/ttk/ttkFrame.c +++ b/generic/ttk/ttkFrame.c @@ -4,8 +4,7 @@ * ttk::frame and ttk::labelframe widgets. */ -#include <tk.h> - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #include "ttkManager.h" diff --git a/generic/ttk/ttkGenStubs.tcl b/generic/ttk/ttkGenStubs.tcl deleted file mode 100644 index 56ba2fa..0000000 --- a/generic/ttk/ttkGenStubs.tcl +++ /dev/null @@ -1,965 +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 <das@users.sourceforge.net> -# -# 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 -# - -package require Tcl 8.4 - -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 <name>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 <name>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 diff --git a/generic/ttk/ttkImage.c b/generic/ttk/ttkImage.c index a5a3a52..002a753 100644 --- a/generic/ttk/ttkImage.c +++ b/generic/ttk/ttkImage.c @@ -10,8 +10,7 @@ * [style map]. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -25,6 +24,8 @@ struct TtkImageSpec { int mapCount; /* #state-specific overrides */ Ttk_StateSpec *states; /* array[mapCount] of states ... */ Tk_Image *images; /* ... per-state images to use */ + Tk_ImageChangedProc *imageChanged; + ClientData imageChangedClientData; }; /* NullImageChanged -- @@ -34,15 +35,41 @@ static void NullImageChanged(ClientData clientData, int x, int y, int width, int height, int imageWidth, int imageHeight) { /* No-op */ } +/* ImageSpecImageChanged -- + * Image changes should trigger a repaint. + */ +static void ImageSpecImageChanged(ClientData clientData, + int x, int y, int width, int height, int imageWidth, int imageHeight) +{ + Ttk_ImageSpec *imageSpec = (Ttk_ImageSpec *)clientData; + if (imageSpec->imageChanged != NULL) { + imageSpec->imageChanged(imageSpec->imageChangedClientData, + x, y, width, height, + imageWidth, imageHeight); + } +} + /* TtkGetImageSpec -- * Constructs a Ttk_ImageSpec * from a Tcl_Obj *. * Result must be released using TtkFreeImageSpec. * - * TODO: Need a variant of this that takes a user-specified ImageChanged proc */ Ttk_ImageSpec * TtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr) { + return TtkGetImageSpecEx(interp, tkwin, objPtr, NULL, NULL); +} + +/* TtkGetImageSpecEx -- + * Constructs a Ttk_ImageSpec * from a Tcl_Obj *. + * Result must be released using TtkFreeImageSpec. + * imageChangedProc will be called when not NULL when + * the image changes to allow widgets to repaint. + */ +Ttk_ImageSpec * +TtkGetImageSpecEx(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, + Tk_ImageChangedProc *imageChangedProc, ClientData imageChangedClientData) +{ Ttk_ImageSpec *imageSpec = 0; int i = 0, n = 0, objc; Tcl_Obj **objv; @@ -52,6 +79,8 @@ TtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr) imageSpec->mapCount = 0; imageSpec->states = 0; imageSpec->images = 0; + imageSpec->imageChanged = imageChangedProc; + imageSpec->imageChangedClientData = imageChangedClientData; if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { goto error; @@ -74,7 +103,7 @@ TtkGetImageSpec(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr) /* Get base image: */ imageSpec->baseImage = Tk_GetImage( - interp, tkwin, Tcl_GetString(objv[0]), NullImageChanged, NULL); + interp, tkwin, Tcl_GetString(objv[0]), ImageSpecImageChanged, imageSpec); if (!imageSpec->baseImage) { goto error; } @@ -315,7 +344,7 @@ Ttk_CreateImageElement( 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 }; diff --git a/generic/ttk/ttkInit.c b/generic/ttk/ttkInit.c index dc6e994..60e3b6f 100644 --- a/generic/ttk/ttkInit.c +++ b/generic/ttk/ttkInit.c @@ -4,8 +4,7 @@ * Ttk package: initialization routine and miscellaneous utilities. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -62,7 +61,7 @@ int Ttk_GetOrientFromObj( * 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 { diff --git a/generic/ttk/ttkLabel.c b/generic/ttk/ttkLabel.c index 1037840..91be033 100644 --- a/generic/ttk/ttkLabel.c +++ b/generic/ttk/ttkLabel.c @@ -6,8 +6,7 @@ * */ -#include <tcl.h> -#include <tkInt.h> +#include "tkInt.h" #include "ttkTheme.h" /*---------------------------------------------------------------------- @@ -139,7 +138,7 @@ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin)); gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); - /* + /* * Place text according to -anchor: */ Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor); @@ -342,15 +341,15 @@ static void ImageDraw( 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 @@ -577,7 +576,7 @@ static void LabelElementSize( if (label->compound != TTK_COMPOUND_IMAGE) textReqWidth = TextReqWidth(&label->text); - switch (label->compound) + switch (label->compound) { case TTK_COMPOUND_TEXT: *widthPtr = textReqWidth; @@ -588,11 +587,11 @@ static void LabelElementSize( 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 */ diff --git a/generic/ttk/ttkLayout.c b/generic/ttk/ttkLayout.c index ba24589..795ffb5 100644 --- a/generic/ttk/ttkLayout.c +++ b/generic/ttk/ttkLayout.c @@ -6,8 +6,7 @@ * Copyright (c) 2003 Joe English. Freely redistributable. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkThemeInt.h" #define MAX(a,b) (a > b ? a : b) @@ -604,13 +603,13 @@ Ttk_InstantiateLayout(Ttk_Theme theme, Ttk_TemplateNode *op) */ /* 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; @@ -702,6 +701,8 @@ Ttk_LayoutTemplate Ttk_ParseLayoutTemplate(Tcl_Interp *interp, Tcl_Obj *objPtr) if (childSpec) { tail->child = Ttk_ParseLayoutTemplate(interp, childSpec); if (!tail->child) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("Invalid -children value")); + Tcl_SetErrorCode(interp, "TTK", "VALUE", "CHILDREN", NULL); goto error; } } diff --git a/generic/ttk/ttkManager.c b/generic/ttk/ttkManager.c index 24a0fb1..bf93699 100644 --- a/generic/ttk/ttkManager.c +++ b/generic/ttk/ttkManager.c @@ -4,8 +4,7 @@ * Support routines for geometry managers. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkManager.h" /*------------------------------------------------------------------------ @@ -320,7 +319,7 @@ void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window 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); } diff --git a/generic/ttk/ttkManager.h b/generic/ttk/ttkManager.h index d22ff98..07fcea1 100644 --- a/generic/ttk/ttkManager.h +++ b/generic/ttk/ttkManager.h @@ -22,7 +22,7 @@ typedef struct TtkManager_ Ttk_Manager; * 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. */ diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c index 81a8b64..0625af8 100644 --- a/generic/ttk/ttkNotebook.c +++ b/generic/ttk/ttkNotebook.c @@ -2,11 +2,7 @@ * Copyright (c) 2004, Joe English */ -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <tk.h> - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #include "ttkManager.h" @@ -221,7 +217,7 @@ static int ConfigureTab( 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; @@ -288,13 +284,14 @@ static void ActivateTab(Notebook *nb, int index) * TabState -- * Return the state of the specified tab, based on * notebook state, currentIndex, activeIndex, and user-specified tab state. - * The USER1 bit is set for the leftmost tab, and USER2 - * is set for the rightmost tab. + * The USER1 bit is set for the leftmost visible tab, and USER2 + * is set for the rightmost visible tab. */ static Ttk_State TabState(Notebook *nb, int index) { Ttk_State state = nb->core.state; Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index); + int i = 0; if (index == nb->notebook.currentIndex) { state |= TTK_STATE_SELECTED; @@ -305,11 +302,25 @@ static Ttk_State TabState(Notebook *nb, int index) if (index == nb->notebook.activeIndex) { state |= TTK_STATE_ACTIVE; } - if (index == 0) { - state |= TTK_STATE_USER1; + for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + if (tab->state == TAB_STATE_HIDDEN) { + continue; + } + if (index == i) { + state |= TTK_STATE_USER1; + } + break; } - if (index == Ttk_NumberSlaves(nb->notebook.mgr) - 1) { - state |= TTK_STATE_USER2; + for (i = Ttk_NumberSlaves(nb->notebook.mgr) - 1; i >= 0; --i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + if (tab->state == TAB_STATE_HIDDEN) { + continue; + } + if (index == i) { + state |= TTK_STATE_USER2; + } + break; } if (tab->state == TAB_STATE_DISABLED) { state |= TTK_STATE_DISABLED; @@ -325,6 +336,8 @@ static Ttk_State TabState(Notebook *nb, int index) /* TabrowSize -- * Compute max height and total width of all tabs (horizontal layouts) * or total height and max width (vertical layouts). + * The -mintabwidth style option is taken into account (for the width + * only). * * Side effects: * Sets width and height fields for all tabs. @@ -334,7 +347,7 @@ static Ttk_State TabState(Notebook *nb, int index) * (max height/width) but not parallel (total width/height). */ static void TabrowSize( - Notebook *nb, Ttk_Orient orient, int *widthPtr, int *heightPtr) + Notebook *nb, Ttk_Orient orient, int minTabWidth, int *widthPtr, int *heightPtr) { Ttk_Layout tabLayout = nb->notebook.tabLayout; int tabrowWidth = 0, tabrowHeight = 0; @@ -346,6 +359,7 @@ static void TabrowSize( Ttk_RebindSublayout(tabLayout, tab); Ttk_LayoutSize(tabLayout,tabState,&tab->width,&tab->height); + tab->width = MAX(tab->width, minTabWidth); if (orient == TTK_ORIENT_HORIZONTAL) { tabrowHeight = MAX(tabrowHeight, tab->height); @@ -406,7 +420,7 @@ static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr) /* Tab row: */ - TabrowSize(nb, nbstyle.tabOrient, &tabrowWidth, &tabrowHeight); + TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight); tabrowHeight += Ttk_PaddingHeight(nbstyle.tabMargins); tabrowWidth += Ttk_PaddingWidth(nbstyle.tabMargins); @@ -436,47 +450,30 @@ static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr) /* SqueezeTabs -- * Squeeze or stretch tabs to fit within the tab area parcel. + * This happens independently of the -mintabwidth style option. * - * All tabs are adjusted by an equal amount, but will not be made - * smaller than the minimum width. (If all the tabs still do - * not fit in the available space, the rightmost ones will - * be further squozen by PlaceTabs()). - * - * The algorithm does not always yield an optimal layout, but does - * have the important property that decreasing the available width - * by one pixel will cause at most one tab to shrink by one pixel; - * this means that tabs resize "smoothly" when the window shrinks - * and grows. + * All tabs are adjusted by an equal amount. * * @@@ <<NOTE-TABPOSITION>> bug: only works for horizontal orientations * @@@ <<NOTE-SQUEEZE-HIDDEN>> does not account for hidden tabs. */ static void SqueezeTabs( - Notebook *nb, int needed, int available, int minTabWidth) + Notebook *nb, int needed, int available) { int nTabs = Ttk_NumberSlaves(nb->notebook.mgr); if (nTabs > 0) { - int difference = available - needed, - delta = difference / nTabs, - remainder = difference % nTabs, - slack = 0; + int difference = available - needed; + double delta = (double)difference / needed; + double slack = 0; int i; - if (remainder < 0) { remainder += nTabs; --delta; } - for (i = 0; i < nTabs; ++i) { Tab *tab = Ttk_SlaveData(nb->notebook.mgr,i); - int adj = delta + (i < remainder) + slack; - - if (tab->width + adj >= minTabWidth) { - tab->width += adj; - slack = 0; - } else { - slack = adj - (minTabWidth - tab->width); - tab->width = minTabWidth; - } + double ad = slack + tab->width * delta; + tab->width += (int)ad; + slack = ad - (int)ad; } } } @@ -539,8 +536,13 @@ static void NotebookDoLayout(void *recordPtr) Ttk_PlaceLayout(nb->core.layout, nb->core.state, Ttk_WinBox(nbwin)); /* Place tabs: + * Note: TabrowSize() takes into account -mintabwidth, but the tabs will + * actually have this minimum size when displayed only if there is enough + * space to draw the tabs with this width. Otherwise some of the tabs can + * be squeezed to a size smaller than -mintabwidth because we prefer + * displaying all tabs than than honoring -mintabwidth for all of them. */ - TabrowSize(nb, nbstyle.tabOrient, &tabrowWidth, &tabrowHeight); + TabrowSize(nb, nbstyle.tabOrient, nbstyle.minTabWidth, &tabrowWidth, &tabrowHeight); tabrowBox = Ttk_PadBox( Ttk_PositionBox(&cavity, tabrowWidth + Ttk_PaddingWidth(nbstyle.tabMargins), @@ -548,7 +550,7 @@ static void NotebookDoLayout(void *recordPtr) nbstyle.tabPosition), nbstyle.tabMargins); - SqueezeTabs(nb, tabrowWidth, tabrowBox.width, nbstyle.minTabWidth); + SqueezeTabs(nb, tabrowWidth, tabrowBox.width); PlaceTabs(nb, tabrowBox, nbstyle.tabPlacement); /* Layout for client area frame: @@ -621,9 +623,12 @@ static void SelectTab(Notebook *nb, int index) Ttk_UnmapSlave(nb->notebook.mgr, currentIndex); } - NotebookPlaceSlave(nb, index); - + /* Must be set before calling NotebookPlaceSlave(), otherwise it may + * happen that NotebookPlaceSlaves(), triggered by an interveaning + * geometry request, will swap to old index. */ nb->notebook.currentIndex = index; + + NotebookPlaceSlave(nb, index); TtkRedisplayWidget(&nb->core); TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged"); @@ -1044,7 +1049,7 @@ static int NotebookHideCommand( 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; diff --git a/generic/ttk/ttkPanedwindow.c b/generic/ttk/ttkPanedwindow.c index adc2aef..8f8094e 100644 --- a/generic/ttk/ttkPanedwindow.c +++ b/generic/ttk/ttkPanedwindow.c @@ -6,8 +6,7 @@ * TODO: track active/pressed sash. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkManager.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -148,7 +147,7 @@ static int ConfigurePane( 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; @@ -715,7 +714,7 @@ static int PanedForgetCommand( 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; diff --git a/generic/ttk/ttkProgress.c b/generic/ttk/ttkProgress.c index 4dc50a2..b805357 100644 --- a/generic/ttk/ttkProgress.c +++ b/generic/ttk/ttkProgress.c @@ -4,9 +4,7 @@ * ttk::progressbar widget. */ -#include <math.h> -#include <tk.h> - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -23,13 +21,19 @@ static const char *const ProgressbarModeStrings[] = { }; 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 */ @@ -46,28 +50,46 @@ typedef struct { 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", Tk_Offset(Progressbar,progress.anchorObj), -1, + TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, + {TK_OPTION_FONT, "-font", "font", "Font", + DEFAULT_FONT, Tk_Offset(Progressbar,progress.fontObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", + "black", Tk_Offset(Progressbar,progress.foregroundObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "left", Tk_Offset(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, 0, 0, GEOMETRY_CHANGED }, + {TK_OPTION_DOUBLE, "-maximum", "maximum", "Maximum", + "100", Tk_Offset(Progressbar,progress.maximumObj), -1, + 0, 0, 0 }, {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, + {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", + "horizontal", Tk_Offset(Progressbar,progress.orientObj), -1, + 0, (ClientData)ttkOrientStrings, STYLE_CHANGED }, + {TK_OPTION_INT, "-phase", "phase", "Phase", + "0", Tk_Offset(Progressbar,progress.phaseObj), -1, 0, 0, 0 }, - {TK_OPTION_STRING, "-variable", "variable", "Variable", - NULL, Tk_Offset(Progressbar,progress.variableObj), -1, - TK_OPTION_NULL_OK, 0, 0 }, + {TK_OPTION_STRING, "-text", "text", "Text", "", + Tk_Offset(Progressbar,progress.textObj), -1, + 0,0,GEOMETRY_CHANGED }, {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_STRING, "-variable", "variable", "Variable", + NULL, Tk_Offset(Progressbar,progress.variableObj), -1, + TK_OPTION_NULL_OK, 0, 0 }, + {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", + "0", Tk_Offset(Progressbar, progress.wrapLengthObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED}, WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) @@ -398,7 +420,7 @@ static int ProgressbarStepCommand( { 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) { @@ -421,21 +443,23 @@ static int ProgressbarStepCommand( } 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) { - return Tcl_ObjSetVar2( - interp, pb->progress.variableObj, 0, newValueObj, - TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) - ? TCL_OK : TCL_ERROR; + int result = Tcl_ObjSetVar2( + interp, pb->progress.variableObj, 0, newValueObj, + TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) + ? TCL_OK : TCL_ERROR; + Tcl_DecrRefCount(newValueObj); + return result; } /* Otherwise, change the -value directly: */ - Tcl_IncrRefCount(newValueObj); Tcl_DecrRefCount(pb->progress.valueObj); pb->progress.valueObj = newValueObj; CheckAnimation(pb); @@ -444,7 +468,7 @@ static int ProgressbarStepCommand( } /* $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( @@ -522,7 +546,8 @@ 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 /* diff --git a/generic/ttk/ttkScale.c b/generic/ttk/ttkScale.c index 69753d1..458bccd 100644 --- a/generic/ttk/ttkScale.c +++ b/generic/ttk/ttkScale.c @@ -4,9 +4,7 @@ * ttk::scale widget. */ -#include <tk.h> -#include <string.h> -#include <stdio.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -15,6 +13,10 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) +/* Bit fields for OptionSpec mask field: + */ +#define STATE_CHANGED (0x100) /* -state option changed */ + /* * Scale widget record */ @@ -35,6 +37,11 @@ typedef struct /* internal state */ Ttk_TraceHandle *variableTrace; + /* + * Compatibility/legacy options: + */ + Tcl_Obj *stateObj; + } ScalePart; typedef struct @@ -46,14 +53,14 @@ typedef struct static Tk_OptionSpec ScaleOptionSpecs[] = { {TK_OPTION_STRING, "-command", "command", "Command", "", - Tk_Offset(Scale,scale.commandObj), -1, + Tk_Offset(Scale,scale.commandObj), -1, TK_OPTION_NULL_OK,0,0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", "", - Tk_Offset(Scale,scale.variableObj), -1, + Tk_Offset(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, + Tk_Offset(Scale,scale.orient), 0, (ClientData)ttkOrientStrings, STYLE_CHANGED }, {TK_OPTION_DOUBLE, "-from", "from", "From", "0", @@ -63,9 +70,13 @@ static Tk_OptionSpec ScaleOptionSpecs[] = {TK_OPTION_DOUBLE, "-value", "value", "Value", "0", Tk_Offset(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, Tk_Offset(Scale,scale.lengthObj), -1, 0, 0, GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-state", "state", "State", + "normal", Tk_Offset(Scale,scale.stateObj), -1, + 0,0,STATE_CHANGED}, + WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -76,7 +87,7 @@ 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) @@ -139,6 +150,10 @@ static int ScaleConfigure(Tcl_Interp *interp, void *recordPtr, int mask) } scale->scale.variableTrace = vt; + if (mask & STATE_CHANGED) { + TtkCheckStateOption(&scale->core, scale->scale.stateObj); + } + return TCL_OK; } @@ -172,7 +187,7 @@ static int ScalePostConfigure( /* ScaleGetLayout -- * getLayout hook. */ -static Ttk_Layout +static Ttk_Layout ScaleGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) { Scale *scalePtr = recordPtr; @@ -236,7 +251,7 @@ static double ScaleFraction(Scale *scalePtr, double value) } /* $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 diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c index 2bd3ddb..184f5f2 100644 --- a/generic/ttk/ttkScroll.c +++ b/generic/ttk/ttkScroll.c @@ -34,7 +34,7 @@ * TtkScrollbarUpdateRequired, which will invoke step (5) (@@@ Fix this) */ -#include <tkInt.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" diff --git a/generic/ttk/ttkScrollbar.c b/generic/ttk/ttkScrollbar.c index 5b0c212..f304ea9 100644 --- a/generic/ttk/ttkScrollbar.c +++ b/generic/ttk/ttkScrollbar.c @@ -4,8 +4,7 @@ * ttk::scrollbar widget. */ -#include <tk.h> - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -22,7 +21,7 @@ typedef struct 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; @@ -50,7 +49,7 @@ static Tk_OptionSpec ScrollbarOptionSpecs[] = * +++ Widget hooks. */ -static void +static void ScrollbarInitialize(Tcl_Interp *interp, void *recordPtr) { Scrollbar *sb = recordPtr; @@ -241,7 +240,7 @@ ScrollbarDeltaCommand( /* $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( diff --git a/generic/ttk/ttkSeparator.c b/generic/ttk/ttkSeparator.c index b52e6f4..dae6d69 100644 --- a/generic/ttk/ttkSeparator.c +++ b/generic/ttk/ttkSeparator.c @@ -4,8 +4,7 @@ * ttk::separator and ttk::sizegrip widgets. */ -#include <tk.h> - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" diff --git a/generic/ttk/ttkSquare.c b/generic/ttk/ttkSquare.c index d002f2f..5302eb7 100644 --- a/generic/ttk/ttkSquare.c +++ b/generic/ttk/ttkSquare.c @@ -3,7 +3,7 @@ * Minimal sample ttk widget. */ -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -56,24 +56,24 @@ static Tk_OptionSpec SquareOptionSpecs[] = {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground", DEFAULT_BACKGROUND, Tk_Offset(Square,square.foregroundObj), -1, 0, 0, 0}, - + {TK_OPTION_PIXELS, "-width", "width", "Width", "50", Tk_Offset(Square,square.widthObj), -1, 0, 0, GEOMETRY_CHANGED}, {TK_OPTION_PIXELS, "-height", "height", "Height", "50", Tk_Offset(Square,square.heightObj), -1, 0, 0, GEOMETRY_CHANGED}, - + {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL, - Tk_Offset(Square,square.paddingObj), -1, + Tk_Offset(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}, - + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL, Tk_Offset(Square,square.anchorObj), -1, TK_OPTION_NULL_OK, 0, 0}, - + WIDGET_TAKEFOCUS_TRUE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; @@ -138,7 +138,7 @@ static const Ttk_Ensemble SquareCommands[] = { }; /* - * 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). */ @@ -159,7 +159,7 @@ static WidgetSpec SquareWidgetSpec = TtkWidgetDisplay /* displayProc */ }; -/* ---------------------------------------------------------------------- +/* ---------------------------------------------------------------------- * Square element * * In this section we demonstrate what is required to create a new themed @@ -176,7 +176,7 @@ typedef struct Tcl_Obj *heightObj; } SquareElement; -static Ttk_ElementOptionSpec SquareElementOptions[] = +static Ttk_ElementOptionSpec SquareElementOptions[] = { { "-background", TK_OPTION_BORDER, Tk_Offset(SquareElement,borderObj), DEFAULT_BACKGROUND }, @@ -248,7 +248,7 @@ static Ttk_ElementSpec SquareElementSpec = * 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) @@ -257,12 +257,12 @@ TTK_BEGIN_LAYOUT(SquareLayout) 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 @@ -287,10 +287,10 @@ TtkSquareWidget_Init(Tcl_Interp *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); diff --git a/generic/ttk/ttkState.c b/generic/ttk/ttkState.c index c34b900..7ac6740 100644 --- a/generic/ttk/ttkState.c +++ b/generic/ttk/ttkState.c @@ -5,9 +5,7 @@ * */ -#include <string.h> - -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" /* @@ -130,7 +128,8 @@ static void StateSpecUpdateString(Tcl_Obj *objPtr) unsigned int offbits = objPtr->internalRep.longValue & 0x0000FFFF; unsigned int mask = onbits | offbits; Tcl_DString result; - int i, len; + int i; + size_t len; Tcl_DStringInit(&result); @@ -146,9 +145,9 @@ static void StateSpecUpdateString(Tcl_Obj *objPtr) len = Tcl_DStringLength(&result); if (len) { /* 'len' includes extra trailing ' ' */ - objPtr->bytes = Tcl_Alloc((unsigned)len); + objPtr->bytes = Tcl_Alloc(len); objPtr->length = len-1; - strncpy(objPtr->bytes, Tcl_DStringValue(&result), (size_t)len-1); + strncpy(objPtr->bytes, Tcl_DStringValue(&result), len-1); objPtr->bytes[len-1] = '\0'; } else { /* empty string */ diff --git a/generic/ttk/ttkStubLib.c b/generic/ttk/ttkStubLib.c index 2c07b9d..c17f1e9 100644 --- a/generic/ttk/ttkStubLib.c +++ b/generic/ttk/ttkStubLib.c @@ -67,7 +67,7 @@ error: "Error loading ", packageName, " package", " (requested version '", version, "', loaded version '", actualVersion, "'): ", - errMsg, + errMsg, NULL); return NULL; } diff --git a/generic/ttk/ttkTagSet.c b/generic/ttk/ttkTagSet.c index f2108b9..f0354d8 100644 --- a/generic/ttk/ttkTagSet.c +++ b/generic/ttk/ttkTagSet.c @@ -4,10 +4,7 @@ * Copyright (C) 2005, Joe English. Freely redistributable. */ -#include <string.h> /* for memset() */ -#include <tcl.h> -#include <tk.h> - +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -188,7 +185,7 @@ int Ttk_TagSetAdd(Ttk_TagSet tagset, Ttk_Tag 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; diff --git a/generic/ttk/ttkTheme.c b/generic/ttk/ttkTheme.c index 2f95962..f98cc26 100644 --- a/generic/ttk/ttkTheme.c +++ b/generic/ttk/ttkTheme.c @@ -10,10 +10,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include <stdlib.h> -#include <string.h> -#include <tk.h> -#include <tkInt.h> +#include "tkInt.h" #include "ttkThemeInt.h" #define PKG_ASSOC_KEY "Ttk" @@ -145,7 +142,7 @@ static const Tk_OptionSpec *TTKGetOptionSpec( /* Make sure widget option has a Tcl_Obj* entry: */ - if (optionSpec->objOffset < 0) { + if (optionSpec->objOffset == TCL_AUTO_LENGTH) { return 0; } @@ -973,12 +970,12 @@ 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; @@ -987,7 +984,7 @@ int InitializeElementRecord( int i; for (i=0; i<nResources; ++i, ++elementOption) { Tcl_Obj **dest = (Tcl_Obj **) - (elementRecord + elementOption->offset); + ((char *)elementRecord + elementOption->offset); const char *optionName = elementOption->optionName; Tcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state); Tcl_Obj *widgetValue = 0; @@ -995,7 +992,7 @@ int InitializeElementRecord( if (optionMap[i]) { widgetValue = *(Tcl_Obj **) - (widgetRecord + optionMap[i]->objOffset); + ((char *)widgetRecord + optionMap[i]->objOffset); } if (widgetValue) { @@ -1067,7 +1064,7 @@ 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 */ @@ -1097,7 +1094,7 @@ 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. */ @@ -1377,7 +1374,7 @@ 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; diff --git a/generic/ttk/ttkTheme.h b/generic/ttk/ttkTheme.h index 7bf2a7f..f087ce3 100644 --- a/generic/ttk/ttkTheme.h +++ b/generic/ttk/ttkTheme.h @@ -234,11 +234,19 @@ typedef void (Ttk_ElementSizeProc)(void *clientData, void *elementRecord, 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; @@ -372,6 +380,8 @@ MODULE_SCOPE void Ttk_RegisterNamedColor(Ttk_ResourceCache, const char *, XColor typedef struct TtkImageSpec Ttk_ImageSpec; TTKAPI Ttk_ImageSpec *TtkGetImageSpec(Tcl_Interp *, Tk_Window, Tcl_Obj *); +TTKAPI Ttk_ImageSpec *TtkGetImageSpecEx(Tcl_Interp *, Tk_Window, Tcl_Obj *, + Tk_ImageChangedProc *, ClientData); TTKAPI void TtkFreeImageSpec(Ttk_ImageSpec *); TTKAPI Tk_Image TtkSelectImage(Ttk_ImageSpec *, Ttk_State); diff --git a/generic/ttk/ttkThemeInt.h b/generic/ttk/ttkThemeInt.h index 3aaada8..25a5fdf 100644 --- a/generic/ttk/ttkThemeInt.h +++ b/generic/ttk/ttkThemeInt.h @@ -15,11 +15,11 @@ 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( diff --git a/generic/ttk/ttkTrace.c b/generic/ttk/ttkTrace.c index ba66db4..51006f8 100644 --- a/generic/ttk/ttkTrace.c +++ b/generic/ttk/ttkTrace.c @@ -3,11 +3,11 @@ * * 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 <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -26,8 +26,8 @@ static char * VarTraceProc( ClientData clientData, /* Widget record pointer */ Tcl_Interp *interp, /* Interpreter containing variable. */ - const char *name1, /* (unused) */ - const char *name2, /* (unused) */ + const char *name1, /* Name of variable. */ + const char *name2, /* Second part of variable name. */ int flags) /* Information about what happened. */ { Ttk_TraceHandle *tracePtr = clientData; @@ -38,6 +38,17 @@ VarTraceProc( 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); + return NULL; + } + name = Tcl_GetString(tracePtr->varnameObj); /* diff --git a/generic/ttk/ttkTrack.c b/generic/ttk/ttkTrack.c index 396b073..fa2a7e0 100644 --- a/generic/ttk/ttkTrack.c +++ b/generic/ttk/ttkTrack.c @@ -23,7 +23,7 @@ * TODO: Handle "chords" properly (e.g., <B1-ButtonPress-2>) */ -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index d957ad2..7aad8ae 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -4,9 +4,7 @@ * ttk::treeview widget implementation. */ -#include <string.h> -#include <stdio.h> -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -321,14 +319,14 @@ static Tk_OptionSpec HeadingOptionSpecs[] = { #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; @@ -435,7 +433,7 @@ typedef struct { #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", @@ -1131,7 +1129,7 @@ static int ConfigureItem( 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) { @@ -1211,7 +1209,7 @@ static int ConfigureColumn( 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) { @@ -1257,7 +1255,7 @@ static int ConfigureHeading( 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) { @@ -1503,7 +1501,7 @@ typedef enum { REGION_CELL } TreeRegion; -static const char *regionStrings[] = { +static const char *const regionStrings[] = { "nothing", "heading", "separator", "tree", "cell", 0 }; @@ -1825,7 +1823,7 @@ static int DrawSubtree( static int DrawForest( Treeview *tv, TreeItem *item, Drawable d, int depth, int row) { - while (item && row <= tv->tree.yscroll.last) { + while (item && row < tv->tree.yscroll.last) { row = DrawSubtree(tv, item, d, depth, row); item = item->next; } @@ -2266,7 +2264,7 @@ done: 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 }; @@ -2932,7 +2930,7 @@ static int TreeviewSelectionCommand( enum { SELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE }; - static const char *selopStrings[] = { + static const char *const selopStrings[] = { "set", "add", "remove", "toggle", NULL }; diff --git a/generic/ttk/ttkWidget.c b/generic/ttk/ttkWidget.c index c50efc5..c2f8d60 100644 --- a/generic/ttk/ttkWidget.c +++ b/generic/ttk/ttkWidget.c @@ -4,8 +4,7 @@ * Core widget utilities. */ -#include <string.h> -#include <tk.h> +#include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -757,7 +756,7 @@ int TtkWidgetIdentifyCommand( { 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) { diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h index e4dd712..798bcce 100644 --- a/generic/ttk/ttkWidget.h +++ b/generic/ttk/ttkWidget.h @@ -111,8 +111,8 @@ MODULE_SCOPE int TtkWidgetConstructorObjCmd( /* 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 \ |