diff options
Diffstat (limited to 'generic')
144 files changed, 86269 insertions, 49042 deletions
diff --git a/generic/README b/generic/README index 285127c..6ac6bb4 100644 --- a/generic/README +++ b/generic/README @@ -1,3 +1,3 @@ This directory contains Tk source files that work on all the platforms -where Tk runs (e.g. UNIX, PCs, and Macintoshes). Platform-specific -sources are in the directories ../unix, ../win, ../macosx, and ../mac. +where Tk runs (e.g. UNIX, PCs, and MacOSX). Platform-specific +sources are in the directories ../unix, ../win, and ../macosx. diff --git a/generic/default.h b/generic/default.h index dd4f609..6156f4d 100755..100644 --- a/generic/default.h +++ b/generic/default.h @@ -20,8 +20,6 @@ #else # if defined(MAC_OSX_TK) # include "tkMacOSXDefault.h" -# elif defined(MAC_TCL) -# include "tkMacDefault.h" # else # include "tkUnixDefault.h" # endif diff --git a/generic/prolog.ps b/generic/prolog.ps deleted file mode 100644 index 4076282..0000000 --- a/generic/prolog.ps +++ /dev/null @@ -1,283 +0,0 @@ -%%BeginProlog -50 dict begin - -% This is a standard prolog for Postscript generated by Tk's canvas -% widget. - -% The definitions below just define all of the variables used in -% any of the procedures here. This is needed for obscure reasons -% explained on p. 716 of the Postscript manual (Section H.2.7, -% "Initializing Variables," in the section on Encapsulated Postscript). - -/baseline 0 def -/stipimage 0 def -/height 0 def -/justify 0 def -/lineLength 0 def -/spacing 0 def -/stipple 0 def -/strings 0 def -/xoffset 0 def -/yoffset 0 def -/tmpstip null def - -% Define the array ISOLatin1Encoding (which specifies how characters are -% encoded for ISO-8859-1 fonts), if it isn't already present (Postscript -% level 2 is supposed to define it, but level 1 doesn't). - -systemdict /ISOLatin1Encoding known not { - /ISOLatin1Encoding [ - /space /space /space /space /space /space /space /space - /space /space /space /space /space /space /space /space - /space /space /space /space /space /space /space /space - /space /space /space /space /space /space /space /space - /space /exclam /quotedbl /numbersign /dollar /percent /ampersand - /quoteright - /parenleft /parenright /asterisk /plus /comma /minus /period /slash - /zero /one /two /three /four /five /six /seven - /eight /nine /colon /semicolon /less /equal /greater /question - /at /A /B /C /D /E /F /G - /H /I /J /K /L /M /N /O - /P /Q /R /S /T /U /V /W - /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore - /quoteleft /a /b /c /d /e /f /g - /h /i /j /k /l /m /n /o - /p /q /r /s /t /u /v /w - /x /y /z /braceleft /bar /braceright /asciitilde /space - /space /space /space /space /space /space /space /space - /space /space /space /space /space /space /space /space - /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent - /dieresis /space /ring /cedilla /space /hungarumlaut /ogonek /caron - /space /exclamdown /cent /sterling /currency /yen /brokenbar /section - /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen - /registered /macron - /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph - /periodcentered - /cedillar /onesuperior /ordmasculine /guillemotright /onequarter - /onehalf /threequarters /questiondown - /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla - /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex - /Idieresis - /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply - /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn - /germandbls - /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla - /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex - /idieresis - /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide - /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn - /ydieresis - ] def -} if - -% font ISOEncode font -% This procedure changes the encoding of a font from the default -% Postscript encoding to ISOLatin1. It's typically invoked just -% before invoking "setfont". The body of this procedure comes from -% Section 5.6.1 of the Postscript book. - -/ISOEncode { - dup length dict begin - {1 index /FID ne {def} {pop pop} ifelse} forall - /Encoding ISOLatin1Encoding def - currentdict - end - - % I'm not sure why it's necessary to use "definefont" on this new - % font, but it seems to be important; just use the name "Temporary" - % for the font. - - /Temporary exch definefont -} bind def - -% StrokeClip -% -% This procedure converts the current path into a clip area under -% the assumption of stroking. It's a bit tricky because some Postscript -% interpreters get errors during strokepath for dashed lines. If -% this happens then turn off dashes and try again. - -/StrokeClip { - {strokepath} stopped { - (This Postscript printer gets limitcheck overflows when) = - (stippling dashed lines; lines will be printed solid instead.) = - [] 0 setdash strokepath} if - clip -} bind def - -% desiredSize EvenPixels closestSize -% -% The procedure below is used for stippling. Given the optimal size -% of a dot in a stipple pattern in the current user coordinate system, -% compute the closest size that is an exact multiple of the device's -% pixel size. This allows stipple patterns to be displayed without -% aliasing effects. - -/EvenPixels { - % Compute exact number of device pixels per stipple dot. - dup 0 matrix currentmatrix dtransform - dup mul exch dup mul add sqrt - - % Round to an integer, make sure the number is at least 1, and compute - % user coord distance corresponding to this. - dup round dup 1 lt {pop 1} if - exch div mul -} bind def - -% width height string StippleFill -- -% -% Given a path already set up and a clipping region generated from -% it, this procedure will fill the clipping region with a stipple -% pattern. "String" contains a proper image description of the -% stipple pattern and "width" and "height" give its dimensions. Each -% stipple dot is assumed to be about one unit across in the current -% user coordinate system. This procedure trashes the graphics state. - -/StippleFill { - % The following code is needed to work around a NeWSprint bug. - - /tmpstip 1 index def - - % Change the scaling so that one user unit in user coordinates - % corresponds to the size of one stipple dot. - 1 EvenPixels dup scale - - % Compute the bounding box occupied by the path (which is now - % the clipping region), and round the lower coordinates down - % to the nearest starting point for the stipple pattern. Be - % careful about negative numbers, since the rounding works - % differently on them. - - pathbbox - 4 2 roll - 5 index div dup 0 lt {1 sub} if cvi 5 index mul 4 1 roll - 6 index div dup 0 lt {1 sub} if cvi 6 index mul 3 2 roll - - % Stack now: width height string y1 y2 x1 x2 - % Below is a doubly-nested for loop to iterate across this area - % in units of the stipple pattern size, going up columns then - % across rows, blasting out a stipple-pattern-sized rectangle at - % each position - - 6 index exch { - 2 index 5 index 3 index { - % Stack now: width height string y1 y2 x y - - gsave - 1 index exch translate - 5 index 5 index true matrix tmpstip imagemask - grestore - } for - pop - } for - pop pop pop pop pop -} bind def - -% -- AdjustColor -- -% Given a color value already set for output by the caller, adjusts -% that value to a grayscale or mono value if requested by the CL -% variable. - -/AdjustColor { - CL 2 lt { - currentgray - CL 0 eq { - .5 lt {0} {1} ifelse - } if - setgray - } if -} bind def - -% x y strings spacing xoffset yoffset justify stipple DrawText -- -% This procedure does all of the real work of drawing text. The -% color and font must already have been set by the caller, and the -% following arguments must be on the stack: -% -% x, y - Coordinates at which to draw text. -% strings - An array of strings, one for each line of the text item, -% in order from top to bottom. -% spacing - Spacing between lines. -% xoffset - Horizontal offset for text bbox relative to x and y: 0 for -% nw/w/sw anchor, -0.5 for n/center/s, and -1.0 for ne/e/se. -% yoffset - Vertical offset for text bbox relative to x and y: 0 for -% nw/n/ne anchor, +0.5 for w/center/e, and +1.0 for sw/s/se. -% justify - 0 for left justification, 0.5 for center, 1 for right justify. -% stipple - Boolean value indicating whether or not text is to be -% drawn in stippled fashion. If text is stippled, -% procedure StippleText must have been defined to call -% StippleFill in the right way. -% -% Also, when this procedure is invoked, the color and font must already -% have been set for the text. - -/DrawText { - /stipple exch def - /justify exch def - /yoffset exch def - /xoffset exch def - /spacing exch def - /strings exch def - - % First scan through all of the text to find the widest line. - - /lineLength 0 def - strings { - stringwidth pop - dup lineLength gt {/lineLength exch def} {pop} ifelse - newpath - } forall - - % Compute the baseline offset and the actual font height. - - 0 0 moveto (TXygqPZ) false charpath - pathbbox dup /baseline exch def - exch pop exch sub /height exch def pop - newpath - - % Translate coordinates first so that the origin is at the upper-left - % corner of the text's bounding box. Remember that x and y for - % positioning are still on the stack. - - translate - lineLength xoffset mul - strings length 1 sub spacing mul height add yoffset mul translate - - % Now use the baseline and justification information to translate so - % that the origin is at the baseline and positioning point for the - % first line of text. - - justify lineLength mul baseline neg translate - - % Iterate over each of the lines to output it. For each line, - % compute its width again so it can be properly justified, then - % display it. - - strings { - dup stringwidth pop - justify neg mul 0 moveto - stipple { - - % The text is stippled, so turn it into a path and print - % by calling StippledText, which in turn calls StippleFill. - % Unfortunately, many Postscript interpreters will get - % overflow errors if we try to do the whole string at - % once, so do it a character at a time. - - gsave - /char (X) def - { - char 0 3 -1 roll put - currentpoint - gsave - char true charpath clip StippleText - grestore - char stringwidth translate - moveto - } forall - grestore - } {show} ifelse - 0 spacing neg translate - } forall -} bind def - -%%EndProlog diff --git a/generic/tk.decls b/generic/tk.decls index c024cdb..65715c4 100644 --- a/generic/tk.decls +++ b/generic/tk.decls @@ -6,6 +6,7 @@ # tkStub.c, and tkPlatStub.c files. # # Copyright (c) 1998-2000 Ajuba Solutions. +# 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. @@ -163,7 +164,7 @@ declare 32 { declare 33 { unsigned long Tk_CreateBinding(Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, - const char *eventStr, const char *script, int append) + const char *eventStr, const char *command, int append) } declare 34 { Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp) @@ -495,7 +496,7 @@ declare 123 { } declare 124 { void Tk_ManageGeometry(Tk_Window tkwin, - Tk_GeomMgr *mgrPtr, ClientData clientData) + const Tk_GeomMgr *mgrPtr, ClientData clientData) } declare 125 { void Tk_MapWindow(Tk_Window tkwin) @@ -580,13 +581,13 @@ declare 147 { void Tk_PhotoBlank(Tk_PhotoHandle handle) } declare 148 { - void Tk_PhotoExpand(Tk_PhotoHandle handle, int width, int height ) + 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 { - void Tk_PhotoSetSize(Tk_PhotoHandle handle, int width, int height) + void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, int width, int height) } declare 151 { int Tk_PointToChar(Tk_TextLayout layout, int x, int y) @@ -942,12 +943,12 @@ declare 245 { void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, int height) } declare 246 { - void Tk_PhotoPutBlock(Tk_PhotoHandle handle, + void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule) } declare 247 { - void Tk_PhotoPutZoomedBlock(Tk_PhotoHandle handle, + 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) @@ -1018,6 +1019,54 @@ declare 264 { int width, int height, int state) } +# TIP#116 +declare 265 { + int Tk_PhotoExpand(Tcl_Interp *interp, Tk_PhotoHandle handle, + int width, int height) +} +declare 266 { + int Tk_PhotoPutBlock(Tcl_Interp *interp, Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, + int compRule) +} +declare 267 { + 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) +} +declare 268 { + int Tk_PhotoSetSize(Tcl_Interp *interp, Tk_PhotoHandle handle, + int width, int height) +} +# TIP#245 +declare 269 { + long Tk_GetUserInactiveTime(Display *dpy) +} +declare 270 { + void Tk_ResetUserInactiveTime(Display *dpy) +} + +# TIP #264 +declare 271 { + Tcl_Interp *Tk_Interp(Tk_Window tkwin) +} + +# Now that the Tk 8.2 -> 8.3 transition is long past, use more conventional +# means to continue support for extensions using the USE_OLD_IMAGE to +# continue use of their string-based Tcl_ImageTypes and Tcl_PhotoImageFormats. +# +# Note that this restores the usual rules for stub compatibility. Stub-enabled +# extensions compiled against 8.5 headers and linked to the 8.5 stub library +# will produce a file [load]able into an interp with Tk 8.X, for X >= 5. +# It will *not* be [load]able into interps with Tk 8.4 (or Tk 8.2!). +# Developers who need to produce a file [load]able into legacy interps must +# build against legacy sources. +declare 272 { + void Tk_CreateOldImageType(Tk_ImageType *typePtr) +} +declare 273 { + void Tk_CreateOldPhotoImageFormat(Tk_PhotoImageFormat *formatPtr) +} # Define the platform specific public Tk interface. These functions are # only available on the designated platform. @@ -1051,59 +1100,8 @@ declare 5 win { UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result) } -# Mac specific functions - -declare 0 mac { - void Tk_MacSetEmbedHandler( - Tk_MacEmbedRegisterWinProc *registerWinProcPtr, - Tk_MacEmbedGetGrafPortProc *getPortProcPtr, - Tk_MacEmbedMakeContainerExistProc *containerExistProcPtr, - Tk_MacEmbedGetClipProc *getClipProc, - Tk_MacEmbedGetOffsetInParentProc *getOffsetProc) -} - -declare 1 mac { - void Tk_MacTurnOffMenus(void) -} - -declare 2 mac { - void Tk_MacTkOwnsCursor(int tkOwnsIt) -} - -declare 3 mac { - void TkMacInitMenus(Tcl_Interp *interp) -} - -declare 4 mac { - void TkMacInitAppleEvents(Tcl_Interp *interp) -} - -declare 5 mac { - int TkMacConvertEvent(EventRecord *eventPtr) -} - -declare 6 mac { - int TkMacConvertTkEvent(EventRecord *eventPtr, Window window) -} - -declare 7 mac { - void TkGenWMConfigureEvent(Tk_Window tkwin, - int x, int y, int width, int height, int flags) -} - -declare 8 mac { - void TkMacInvalClipRgns(TkWindow *winPtr) -} - -declare 9 mac { - int TkMacHaveAppearance(void) -} - -declare 10 mac { - GWorldPtr TkMacGetDrawablePort(Drawable drawable) -} - -# Mac OS X specific functions +################################ +# Aqua specific functions declare 0 aqua { void Tk_MacOSXSetEmbedHandler( @@ -1144,6 +1142,37 @@ declare 9 aqua { declare 10 aqua { int Tk_MacOSXIsAppInFront(void) } + +############################################################################## + +# Public functions that are not accessible via the stubs table. + +export { + const char *Tk_InitStubs(Tcl_Interp *interp, const char *version, + int exact) +} +export { + const char *Tk_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, + int exact) +} + +# Global variables that need to be exported from the tcl shared library. + +export { + TkStubs *tkStubsPtr (fool checkstubs) +} +export { + TkPlatStubs *tkPlatStubsPtr (fool checkstubs) +} +export { + TkIntStubs *tkIntStubsPtr (fool checkstubs) +} +export { + TkIntPlatStubs *tkIntPlatStubsPtr (fool checkstubs) +} +export { + TkIntXlibStubs *tkIntXlibStubsPtr (fool checkstubs) +} # Local Variables: # mode: tcl diff --git a/generic/tk.h b/generic/tk.h index e777947..af7b05c 100644 --- a/generic/tk.h +++ b/generic/tk.h @@ -1,26 +1,24 @@ /* * tk.h -- * - * Declarations for Tk-related things that are visible - * outside of the Tk module itself. + * Declarations for Tk-related things that are visible outside of the Tk + * module itself. * * Copyright (c) 1989-1994 The Regents of the University of California. * Copyright (c) 1994 The Australian National University. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Ajuba Solutions. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TK #define _TK -#ifndef _TCL #include <tcl.h> -#if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION != 4) -# error Tk 8.4 must be compiled with tcl.h from Tcl 8.4 -#endif +#if (TCL_MAJOR_VERSION != 8) || (TCL_MINOR_VERSION != 5) +# error Tk 8.5 must be compiled with tcl.h from Tcl 8.5 #endif /* @@ -35,46 +33,43 @@ extern "C" { * When version numbers change here, you must also go into the following files * and update the version numbers: * - * library/tk.tcl (only if Major.minor changes, not patchlevel) + * library/tk.tcl (2 LOC patch) * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch) * win/configure.in (as above) - * win/makefile.vc (not patchlevel) * README (sections 0 and 1) - * mac/README (not patchlevel) + * macosx/Wish.xcode/project.pbxproj (not patchlevel) 1 LOC + * macosx/Wish-Common.xcconfig (not patchlevel) 1 LOC * win/README (not patchlevel) * unix/README (not patchlevel) - * unix/tk.spec (3 LOC Major/Minor, 2 LOC patch) + * unix/tk.spec (1 LOC patch) * win/tcl.m4 (not patchlevel) * - * You may also need to update some of these files when the numbers change - * for the version of Tcl that this release of Tk is compiled against. + * You may also need to update some of these files when the numbers change for + * the version of Tcl that this release of Tk is compiled against. */ -#define TK_MAJOR_VERSION 8 -#define TK_MINOR_VERSION 4 -#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE -#define TK_RELEASE_SERIAL 19 +#define TK_MAJOR_VERSION 8 +#define TK_MINOR_VERSION 5 +#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE +#define TK_RELEASE_SERIAL 11 -#define TK_VERSION "8.4" -#define TK_PATCH_LEVEL "8.4.19" +#define TK_VERSION "8.5" +#define TK_PATCH_LEVEL "8.5.11" -/* - * A special definition used to allow this header file to be included - * from windows or mac resource files so that they can obtain version - * information. RC_INVOKED is defined by default by the windows RC tool - * and manually set for macintosh. +/* + * A special definition used to allow this header file to be included from + * windows or mac resource files so that they can obtain version information. + * RC_INVOKED is defined by default by the windows RC tool and manually set + * for macintosh. * - * Resource compilers don't like all the C stuff, like typedefs and - * procedure declarations, that occur below, so block them out. + * Resource compilers don't like all the C stuff, like typedefs and procedure + * declarations, that occur below, so block them out. */ - + #ifndef RC_INVOKED - + #ifndef _XLIB_H -# if defined (MAC_TCL) -# include <Xlib.h> -# include <X.h> -# elif defined(MAC_OSX_TK) +# if defined(MAC_OSX_TK) # include <X11/Xlib.h> # include <X11/X.h> # else @@ -89,7 +84,7 @@ extern "C" { # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLEXPORT #endif - + /* * Decide whether or not to use input methods. */ @@ -122,11 +117,11 @@ typedef struct Tk_StyledElement_ *Tk_StyledElement; * Additional types exported to clients. */ -typedef CONST char *Tk_Uid; +typedef const char *Tk_Uid; /* - * The enum below defines the valid types for Tk configuration options - * as implemented by Tk_InitOptions, Tk_SetOptions, etc. + * The enum below defines the valid types for Tk configuration options as + * implemented by Tk_InitOptions, Tk_SetOptions, etc. */ typedef enum { @@ -152,56 +147,54 @@ typedef enum { } Tk_OptionType; /* - * Structures of the following type are used by widgets to specify - * their configuration options. Typically each widget has a static - * array of these structures, where each element of the array describes - * a single configuration option. The array is passed to - * Tk_CreateOptionTable. + * Structures of the following type are used by widgets to specify their + * configuration options. Typically each widget has a static array of these + * structures, where each element of the array describes a single + * configuration option. The array is passed to Tk_CreateOptionTable. */ typedef struct Tk_OptionSpec { - Tk_OptionType type; /* Type of option, such as TK_OPTION_COLOR; - * see definitions above. Last option in - * table must have type TK_OPTION_END. */ - char *optionName; /* Name used to specify option in Tcl + Tk_OptionType type; /* Type of option, such as TK_OPTION_COLOR; + * see definitions above. Last option in table + * must have type TK_OPTION_END. */ + const char *optionName; /* Name used to specify option in Tcl * commands. */ - char *dbName; /* Name for option in option database. */ - char *dbClass; /* Class for option in database. */ - char *defValue; /* Default value for option if not specified - * in command line, the option database, - * or the system. */ + const char *dbName; /* Name for option in option database. */ + const char *dbClass; /* Class for option in database. */ + const char *defValue; /* Default value for option if not specified + * in command line, the option database, or + * the system. */ int objOffset; /* Where in record to store a Tcl_Obj * that * 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. */ + * 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 * representation of the value of this option, - * such as an int or XColor *. This field - * is specified as an offset in bytes - * from the start of the record. Use the - * Tk_Offset macro to generate values for it. - * -1 means don't store the internal - * representation in the record. */ + * such as an int or XColor *. This field is + * specified as an offset in bytes from the + * start of the record. Use the Tk_Offset + * macro to generate values for it. -1 means + * don't store the internal representation in + * the record. */ int flags; /* Any combination of the values defined * below. */ ClientData clientData; /* An alternate place to put option-specific - * data. Used for the monochrome default value + * data. Used for the monochrome default value * for colors, etc. */ - int typeMask; /* An arbitrary bit mask defined by the - * class manager; typically bits correspond - * to certain kinds of options such as all - * those that require a redisplay when they - * change. Tk_SetOptions returns the bit-wise - * OR of the typeMasks of all options that - * were changed. */ + int typeMask; /* An arbitrary bit mask defined by the class + * manager; typically bits correspond to + * certain kinds of options such as all those + * that require a redisplay when they change. + * Tk_SetOptions returns the bit-wise OR of + * the typeMasks of all options that were + * changed. */ } Tk_OptionSpec; /* - * Flag values for Tk_OptionSpec structures. These flags are shared by - * Tk_ConfigSpec structures, so be sure to coordinate any changes - * carefully. + * Flag values for Tk_OptionSpec structures. These flags are shared by + * Tk_ConfigSpec structures, so be sure to coordinate any changes carefully. */ #define TK_OPTION_NULL_OK (1 << 0) @@ -222,28 +215,29 @@ typedef void (Tk_CustomOptionRestoreProc) _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *internalPtr, char *saveInternalPtr)); typedef void (Tk_CustomOptionFreeProc) _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *internalPtr)); - + typedef struct Tk_ObjCustomOption { - char *name; /* Name of the custom option. */ - Tk_CustomOptionSetProc *setProc; /* Function to use to set a record's - * option value from a Tcl_Obj */ - Tk_CustomOptionGetProc *getProc; /* Function to use to get a Tcl_Obj - * representation from an internal - * representation of an option. */ - Tk_CustomOptionRestoreProc *restoreProc; /* Function to use to restore a - * saved value for the internal - * representation. */ - Tk_CustomOptionFreeProc *freeProc; /* Function to use to free the internal - * representation of an option. */ - ClientData clientData; /* Arbitrary one-word value passed to - * the handling procs. */ + const char *name; /* Name of the custom option. */ + Tk_CustomOptionSetProc *setProc; + /* Function to use to set a record's option + * value from a Tcl_Obj */ + Tk_CustomOptionGetProc *getProc; + /* Function to use to get a Tcl_Obj + * representation from an internal + * representation of an option. */ + Tk_CustomOptionRestoreProc *restoreProc; + /* Function to use to restore a saved value + * for the internal representation. */ + Tk_CustomOptionFreeProc *freeProc; + /* Function to use to free the internal + * representation of an option. */ + ClientData clientData; /* Arbitrary one-word value passed to the + * handling procs. */ } Tk_ObjCustomOption; - /* - * Macro to use to fill in "offset" fields of the Tk_OptionSpec. - * struct. Computes number of bytes from beginning of structure - * to a given field. + * Macro to use to fill in "offset" fields of the Tk_OptionSpec structure. + * Computes number of bytes from beginning of structure to a given field. */ #ifdef offsetof @@ -253,34 +247,30 @@ typedef struct Tk_ObjCustomOption { #endif /* - * The following two structures are used for error handling. When - * configuration options are being modified, the old values are - * saved in a Tk_SavedOptions structure. If an error occurs, then the - * contents of the structure can be used to restore all of the old - * values. The contents of this structure are for the private use - * Tk. No-one outside Tk should ever read or write any of the fields - * of these structures. + * The following two structures are used for error handling. When config + * options are being modified, the old values are saved in a Tk_SavedOptions + * structure. If an error occurs, then the contents of the structure can be + * used to restore all of the old values. The contents of this structure are + * for the private use Tk. No-one outside Tk should ever read or write any of + * the fields of these structures. */ typedef struct Tk_SavedOption { - struct TkOption *optionPtr; /* Points to information that describes - * the option. */ - Tcl_Obj *valuePtr; /* The old value of the option, in - * the form of a Tcl object; may be - * NULL if the value wasn't saved as - * an object. */ - double internalForm; /* The old value of the option, in - * some internal representation such - * as an int or (XColor *). Valid - * only if optionPtr->specPtr->objOffset - * is < 0. The space must be large - * enough to accommodate a double, a - * long, or a pointer; right now it - * looks like a double is big - * enough. Also, using a double - * guarantees that the field is - * properly aligned for storing large - * values. */ + struct TkOption *optionPtr; /* Points to information that describes the + * option. */ + Tcl_Obj *valuePtr; /* The old value of the option, in the form of + * a Tcl object; may be NULL if the value was + * not saved as an object. */ + double internalForm; /* The old value of the option, in some + * internal representation such as an int or + * (XColor *). Valid only if the field + * optionPtr->specPtr->objOffset is < 0. The + * space must be large enough to accommodate a + * double, a long, or a pointer; right now it + * looks like a double (i.e., 8 bytes) is big + * enough. Also, using a double guarantees + * that the field is properly aligned for + * storing large values. */ } Tk_SavedOption; #ifdef TCL_MEM_DEBUG @@ -290,31 +280,30 @@ typedef struct Tk_SavedOption { #endif typedef struct Tk_SavedOptions { - char *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. */ + char *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. */ Tk_SavedOption items[TK_NUM_SAVED_OPTIONS]; - /* Items used to hold old values. */ - struct Tk_SavedOptions *nextPtr; /* Points to next structure in list; - * needed if too many options changed - * to hold all the old values in a - * single structure. NULL means no - * more structures. */ + /* Items used to hold old values. */ + struct Tk_SavedOptions *nextPtr; + /* Points to next structure in list; needed if + * too many options changed to hold all the + * old values in a single structure. NULL + * means no more structures. */ } Tk_SavedOptions; /* - * Structure used to describe application-specific configuration - * options: indicates procedures to call to parse an option and - * to return a text string describing an option. THESE ARE - * DEPRECATED; PLEASE USE THE NEW STRUCTURES LISTED ABOVE. + * Structure used to describe application-specific configuration options: + * indicates procedures to call to parse an option and to return a text string + * describing an option. THESE ARE DEPRECATED; PLEASE USE THE NEW STRUCTURES + * LISTED ABOVE. */ /* - * This is a temporary flag used while tkObjConfig and new widgets - * are in development. + * This is a temporary flag used while tkObjConfig and new widgets are in + * development. */ #ifndef __NO_OLD_CONFIG @@ -327,58 +316,58 @@ typedef char *(Tk_OptionPrintProc) _ANSI_ARGS_((ClientData clientData, Tcl_FreeProc **freeProcPtr)); typedef struct Tk_CustomOption { - Tk_OptionParseProc *parseProc; /* Procedure to call to parse an - * option and store it in converted - * form. */ - Tk_OptionPrintProc *printProc; /* Procedure to return a printable - * string describing an existing - * option. */ - ClientData clientData; /* Arbitrary one-word value used by - * option parser: passed to - * parseProc and printProc. */ + Tk_OptionParseProc *parseProc; + /* Procedure to call to parse an option and + * store it in converted form. */ + Tk_OptionPrintProc *printProc; + /* Procedure to return a printable string + * describing an existing option. */ + ClientData clientData; /* Arbitrary one-word value used by option + * parser: passed to parseProc and + * printProc. */ } Tk_CustomOption; /* - * Structure used to specify information for Tk_ConfigureWidget. Each - * structure gives complete information for one option, including - * how the option is specified on the command line, where it appears - * in the option database, etc. + * Structure used to specify information for Tk_ConfigureWidget. Each + * structure gives complete information for one option, including how the + * option is specified on the command line, where it appears in the option + * database, etc. */ 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. */ - char *argvName; /* Switch used to specify option in argv. - * NULL means this spec is part of a group. */ + * see definitions below. Last option in table + * must have type TK_CONFIG_END. */ + char *argvName; /* Switch used to specify option in argv. NULL + * means this spec is part of a group. */ Tk_Uid dbName; /* Name for option in option database. */ Tk_Uid dbClass; /* Class for option in database. */ - Tk_Uid defValue; /* Default value for option if not - * specified in command line or database. */ - int offset; /* Where in widget record to store value; - * use Tk_Offset macro to generate values - * for this. */ + Tk_Uid defValue; /* Default value for option if not specified + * in command line or database. */ + int offset; /* Where in widget record to store value; use + * Tk_Offset macro to generate values for + * this. */ int specFlags; /* Any combination of the values defined - * below; other bits are used internally - * by tkConfig.c. */ - 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 + * below; other bits are used internally by + * tkConfig.c. */ + Tk_CustomOption *customPtr; /* If type is TK_CONFIG_CUSTOM then this is a + * pointer to info about how to parse and + * print the option. Otherwise it is * irrelevant. */ } Tk_ConfigSpec; /* - * Type values for Tk_ConfigSpec structures. See the user - * documentation for details. + * Type values for Tk_ConfigSpec structures. See the user documentation for + * details. */ typedef enum { TK_CONFIG_BOOLEAN, TK_CONFIG_INT, TK_CONFIG_DOUBLE, TK_CONFIG_STRING, TK_CONFIG_UID, TK_CONFIG_COLOR, TK_CONFIG_FONT, TK_CONFIG_BITMAP, - TK_CONFIG_BORDER, TK_CONFIG_RELIEF, TK_CONFIG_CURSOR, - TK_CONFIG_ACTIVE_CURSOR, TK_CONFIG_JUSTIFY, TK_CONFIG_ANCHOR, + TK_CONFIG_BORDER, TK_CONFIG_RELIEF, TK_CONFIG_CURSOR, + TK_CONFIG_ACTIVE_CURSOR, TK_CONFIG_JUSTIFY, TK_CONFIG_ANCHOR, TK_CONFIG_SYNONYM, TK_CONFIG_CAP_STYLE, TK_CONFIG_JOIN_STYLE, - TK_CONFIG_PIXELS, TK_CONFIG_MM, TK_CONFIG_WINDOW, TK_CONFIG_CUSTOM, + TK_CONFIG_PIXELS, TK_CONFIG_MM, TK_CONFIG_WINDOW, TK_CONFIG_CUSTOM, TK_CONFIG_END } Tk_ConfigTypes; @@ -390,10 +379,10 @@ typedef enum { #define TK_CONFIG_OBJS 0x80 /* - * Possible flag values for Tk_ConfigSpec structures. Any bits at - * or above TK_CONFIG_USER_BIT may be used by clients for selecting - * certain entries. Before changing any values here, coordinate with - * tkOldConfig.c (internal-use-only flags are defined there). + * Possible flag values for Tk_ConfigSpec structures. Any bits at or above + * TK_CONFIG_USER_BIT may be used by clients for selecting certain entries. + * Before changing any values here, coordinate with tkOldConfig.c + * (internal-use-only flags are defined there). */ #define TK_CONFIG_NULL_OK (1 << 0) @@ -409,14 +398,15 @@ typedef enum { */ typedef struct { - 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. */ - char *help; /* Documentation message describing this option. */ + 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. */ + char *help; /* Documentation message describing this + * option. */ } Tk_ArgvInfo; /* @@ -448,8 +438,8 @@ typedef struct { #define TK_ARGV_DONT_SKIP_FIRST_ARG 0x8 /* - * Enumerated type for describing actions to be taken in response - * to a restrictProc established by Tk_RestrictEvents. + * Enumerated type for describing actions to be taken in response to a + * restrictProc established by Tk_RestrictEvents. */ typedef enum { @@ -487,10 +477,10 @@ typedef enum { #define TK_3D_DARK_GC 3 /* - * Special EnterNotify/LeaveNotify "mode" for use in events - * generated by tkShare.c. Pick a high enough value that it's - * unlikely to conflict with existing values (like NotifyNormal) - * or any new values defined in the future. + * Special EnterNotify/LeaveNotify "mode" for use in events generated by + * tkShare.c. Pick a high enough value that it's unlikely to conflict with + * existing values (like NotifyNormal) or any new values defined in the + * future. */ #define TK_NOTIFY_SHARE 20 @@ -515,7 +505,7 @@ typedef enum { /* * The following structure is used by Tk_GetFontMetrics() to return - * information about the properties of a Tk_Font. + * information about the properties of a Tk_Font. */ typedef struct Tk_FontMetrics { @@ -527,9 +517,9 @@ typedef struct Tk_FontMetrics { * letter sticks below the baseline, plus any * extra blank space added by the designer of * the font. */ - int linespace; /* The sum of the ascent and descent. How - * far apart two lines of text in the same - * font should be placed so that none of the + int linespace; /* The sum of the ascent and descent. How far + * apart two lines of text in the same font + * should be placed so that none of the * characters in one line overlap any of the * characters in the other line. */ } Tk_FontMetrics; @@ -563,13 +553,12 @@ typedef void (Tk_ClassModalProc) _ANSI_ARGS_((Tk_Window tkwin, typedef struct Tk_ClassProcs { unsigned int size; Tk_ClassWorldChangedProc *worldChangedProc; - /* Procedure to invoke when the widget needs to - * respond in some way to a change in the + /* Procedure to invoke when the widget needs + * to respond in some way to a change in the * world (font changes, etc.) */ Tk_ClassCreateProc *createProc; - /* Procedure to invoke when the - * platform-dependent window needs to be - * created. */ + /* Procedure to invoke when the platform- + * dependent window needs to be created. */ Tk_ClassModalProc *modalProc; /* Procedure to invoke after all bindings on a * widget have been triggered in order to @@ -577,8 +566,8 @@ typedef struct Tk_ClassProcs { } Tk_ClassProcs; /* - * Simple accessor for Tk_ClassProcs structure. Checks that the structure - * is not NULL, then checks the size field and returns either the requested + * Simple accessor for Tk_ClassProcs structure. Checks that the structure is + * not NULL, then checks the size field and returns either the requested * field, if present, or NULL if the structure is too small to have the field * (or NULL if the structure is NULL). * @@ -595,9 +584,9 @@ typedef struct Tk_ClassProcs { (((procs)->size <= Tk_Offset(Tk_ClassProcs, which)) ? NULL:(procs)->which)) /* - * Each geometry manager (the packer, the placer, etc.) is represented - * by a structure of the following form, which indicates procedures - * to invoke in the geometry manager to carry out certain functions. + * Each geometry manager (the packer, the placer, etc.) is represented by a + * structure of the following form, which indicates procedures to invoke in + * the geometry manager to carry out certain functions. */ typedef void (Tk_GeomRequestProc) _ANSI_ARGS_((ClientData clientData, @@ -606,17 +595,17 @@ typedef void (Tk_GeomLostSlaveProc) _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin)); typedef struct Tk_GeomMgr { - char *name; /* Name of the geometry manager (command - * used to invoke it, or name of widget - * class that allows embedded widgets). */ + const char *name; /* Name of the geometry manager (command used + * to invoke it, or name of widget class that + * allows embedded widgets). */ Tk_GeomRequestProc *requestProc; /* Procedure to invoke when a slave's * requested geometry changes. */ Tk_GeomLostSlaveProc *lostSlaveProc; - /* Procedure to invoke when a slave is - * taken away from one geometry manager - * by another. NULL means geometry manager - * doesn't care when slaves are lost. */ + /* Procedure to invoke when a slave is taken + * away from one geometry manager by another. + * NULL means geometry manager doesn't care + * when slaves are lost. */ } Tk_GeomMgr; /* @@ -648,40 +637,45 @@ typedef struct Tk_GeomMgr { /* * A virtual event shares most of its fields with the XKeyEvent and - * XButtonEvent structures. 99% of the time a virtual event will be - * an abstraction of a key or button event, so this structure provides - * the most information to the user. The only difference is the changing - * of the detail field for a virtual event so that it holds the name of the - * virtual event being triggered. + * XButtonEvent structures. 99% of the time a virtual event will be an + * abstraction of a key or button event, so this structure provides the most + * information to the user. The only difference is the changing of the detail + * field for a virtual event so that it holds the name of the virtual event + * being triggered. * - * When using this structure, if you want your code to work correctly - * in Tk 8.5 as well, you should ensure that you zero out all the + * When using this structure, you should ensure that you zero out all the * fields first using memset() or bzero(). */ typedef struct { int type; - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* True if this came from a SendEvent request */ - Display *display; /* Display the event was read from */ - Window event; /* Window on which event was requested. */ - Window root; /* root window that the event occured on */ - Window subwindow; /* child window */ - Time time; /* milliseconds */ - int x, y; /* pointer x, y coordinates in event window */ - int x_root, y_root; /* coordinates relative to root */ - unsigned int state; /* key or button mask */ - Tk_Uid name; /* Name of virtual event. */ - Bool same_screen; /* same screen flag */ - Tcl_Obj *user_data; /* not used in Tk 8.4 */ + unsigned long serial; /* # of last request processed by server. */ + Bool send_event; /* True if this came from a SendEvent + * request. */ + Display *display; /* Display the event was read from. */ + Window event; /* Window on which event was requested. */ + Window root; /* Root window that the event occured on. */ + Window subwindow; /* Child window. */ + Time time; /* Milliseconds. */ + int x, y; /* Pointer x, y coordinates in event + * window. */ + int x_root, y_root; /* Coordinates relative to root. */ + unsigned int state; /* Key or button mask */ + Tk_Uid name; /* Name of virtual event. */ + Bool same_screen; /* Same screen flag. */ + Tcl_Obj *user_data; /* Application-specific data reference; Tk + * will decrement the reference count *once* + * when it has finished processing the + * event. */ } XVirtualEvent; typedef struct { int type; - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* True if this came from a SendEvent request */ - Display *display; /* Display the event was read from */ - Window window; /* Window in which event occurred. */ + unsigned long serial; /* # of last request processed by server. */ + Bool send_event; /* True if this came from a SendEvent + * request. */ + Display *display; /* Display the event was read from. */ + Window window; /* Window in which event occurred. */ } XActivateDeactivateEvent; typedef XActivateDeactivateEvent XActivateEvent; typedef XActivateDeactivateEvent XDeactivateEvent; @@ -689,29 +683,29 @@ typedef XActivateDeactivateEvent XDeactivateEvent; /* *-------------------------------------------------------------- * - * Macros for querying Tk_Window structures. See the - * manual entries for documentation. + * Macros for querying Tk_Window structures. See the manual entries for + * documentation. * *-------------------------------------------------------------- */ -#define Tk_Display(tkwin) (((Tk_FakeWin *) (tkwin))->display) -#define Tk_ScreenNumber(tkwin) (((Tk_FakeWin *) (tkwin))->screenNum) -#define Tk_Screen(tkwin) (ScreenOfDisplay(Tk_Display(tkwin), \ - Tk_ScreenNumber(tkwin))) -#define Tk_Depth(tkwin) (((Tk_FakeWin *) (tkwin))->depth) -#define Tk_Visual(tkwin) (((Tk_FakeWin *) (tkwin))->visual) -#define Tk_WindowId(tkwin) (((Tk_FakeWin *) (tkwin))->window) -#define Tk_PathName(tkwin) (((Tk_FakeWin *) (tkwin))->pathName) -#define Tk_Name(tkwin) (((Tk_FakeWin *) (tkwin))->nameUid) -#define Tk_Class(tkwin) (((Tk_FakeWin *) (tkwin))->classUid) -#define Tk_X(tkwin) (((Tk_FakeWin *) (tkwin))->changes.x) -#define Tk_Y(tkwin) (((Tk_FakeWin *) (tkwin))->changes.y) -#define Tk_Width(tkwin) (((Tk_FakeWin *) (tkwin))->changes.width) +#define Tk_Display(tkwin) (((Tk_FakeWin *) (tkwin))->display) +#define Tk_ScreenNumber(tkwin) (((Tk_FakeWin *) (tkwin))->screenNum) +#define Tk_Screen(tkwin) \ + (ScreenOfDisplay(Tk_Display(tkwin), Tk_ScreenNumber(tkwin))) +#define Tk_Depth(tkwin) (((Tk_FakeWin *) (tkwin))->depth) +#define Tk_Visual(tkwin) (((Tk_FakeWin *) (tkwin))->visual) +#define Tk_WindowId(tkwin) (((Tk_FakeWin *) (tkwin))->window) +#define Tk_PathName(tkwin) (((Tk_FakeWin *) (tkwin))->pathName) +#define Tk_Name(tkwin) (((Tk_FakeWin *) (tkwin))->nameUid) +#define Tk_Class(tkwin) (((Tk_FakeWin *) (tkwin))->classUid) +#define Tk_X(tkwin) (((Tk_FakeWin *) (tkwin))->changes.x) +#define Tk_Y(tkwin) (((Tk_FakeWin *) (tkwin))->changes.y) +#define Tk_Width(tkwin) (((Tk_FakeWin *) (tkwin))->changes.width) #define Tk_Height(tkwin) \ (((Tk_FakeWin *) (tkwin))->changes.height) -#define Tk_Changes(tkwin) (&((Tk_FakeWin *) (tkwin))->changes) -#define Tk_Attributes(tkwin) (&((Tk_FakeWin *) (tkwin))->atts) +#define Tk_Changes(tkwin) (&((Tk_FakeWin *) (tkwin))->changes) +#define Tk_Attributes(tkwin) (&((Tk_FakeWin *) (tkwin))->atts) #define Tk_IsEmbedded(tkwin) \ (((Tk_FakeWin *) (tkwin))->flags & TK_EMBEDDED) #define Tk_IsContainer(tkwin) \ @@ -726,8 +720,10 @@ typedef XActivateDeactivateEvent XDeactivateEvent; (((Tk_FakeWin *) (tkwin))->flags & TK_WIN_MANAGED) #define Tk_TopWinHierarchy(tkwin) \ (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_HIERARCHY) -#define Tk_ReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->reqWidth) -#define Tk_ReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->reqHeight) +#define Tk_IsManageable(tkwin) \ + (((Tk_FakeWin *) (tkwin))->flags & TK_WM_MANAGEABLE) +#define Tk_ReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->reqWidth) +#define Tk_ReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->reqHeight) /* Tk_InternalBorderWidth is deprecated */ #define Tk_InternalBorderWidth(tkwin) \ (((Tk_FakeWin *) (tkwin))->internalBorderLeft) @@ -739,20 +735,19 @@ typedef XActivateDeactivateEvent XDeactivateEvent; (((Tk_FakeWin *) (tkwin))->internalBorderTop) #define Tk_InternalBorderBottom(tkwin) \ (((Tk_FakeWin *) (tkwin))->internalBorderBottom) -#define Tk_MinReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->minReqWidth) -#define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight) -#define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr) -#define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap) +#define Tk_MinReqWidth(tkwin) (((Tk_FakeWin *) (tkwin))->minReqWidth) +#define Tk_MinReqHeight(tkwin) (((Tk_FakeWin *) (tkwin))->minReqHeight) +#define Tk_Parent(tkwin) (((Tk_FakeWin *) (tkwin))->parentPtr) +#define Tk_Colormap(tkwin) (((Tk_FakeWin *) (tkwin))->atts.colormap) /* - * The structure below is needed by the macros above so that they can - * access the fields of a Tk_Window. The fields not needed by the macros - * are declared as "dummyX". The structure has its own type in order to - * prevent applications from accessing Tk_Window fields except using - * official macros. WARNING!! The structure definition must be kept - * consistent with the TkWindow structure in tkInt.h. If you change one, - * then change the other. See the declaration in tkInt.h for - * documentation on what the fields are used for internally. + * The structure below is needed by the macros above so that they can access + * the fields of a Tk_Window. The fields not needed by the macros are declared + * as "dummyX". The structure has its own type in order to prevent apps from + * accessing Tk_Window fields except using official macros. WARNING!! The + * structure definition must be kept consistent with the TkWindow structure in + * tkInt.h. If you change one, then change the other. See the declaration in + * tkInt.h for documentation on what the fields are used for internally. */ typedef struct Tk_FakeWin { @@ -807,69 +802,65 @@ typedef struct Tk_FakeWin { * TK_ALREADY_DEAD: 1 means the window is in the process of * being destroyed already. * TK_NEED_CONFIG_NOTIFY: 1 means that the window has been reconfigured - * before it was made to exist. At the time of + * before it was made to exist. At the time of * making it exist a ConfigureNotify event needs * to be generated. - * TK_GRAB_FLAG: Used to manage grabs. See tkGrab.c for - * details. + * TK_GRAB_FLAG: Used to manage grabs. See tkGrab.c for details * TK_CHECKED_IC: 1 means we've already tried to get an input - * context for this window; if the ic field - * is NULL it means that there isn't a context - * for the field. + * context for this window; if the ic field is + * NULL it means that there isn't a context for + * the field. * TK_DONT_DESTROY_WINDOW: 1 means that Tk_DestroyWindow should not * invoke XDestroyWindow to destroy this widget's - * X window. The flag is set when the window - * has already been destroyed elsewhere (e.g. - * by another application) or when it will be - * destroyed later (e.g. by destroying its - * parent). + * X window. The flag is set when the window has + * already been destroyed elsewhere (e.g. by + * another application) or when it will be + * destroyed later (e.g. by destroying its parent) * TK_WM_COLORMAP_WINDOW: 1 means that this window has at some time * appeared in the WM_COLORMAP_WINDOWS property - * for its toplevel, so we have to remove it - * from that property if the window is - * deleted and the toplevel isn't. + * for its toplevel, so we have to remove it from + * that property if the window is deleted and the + * toplevel isn't. * TK_EMBEDDED: 1 means that this window (which must be a * toplevel) is not a free-standing window but * rather is embedded in some other application. * TK_CONTAINER: 1 means that this window is a container, and - * that some other application (either in - * this process or elsewhere) may be - * embedding itself inside the window. + * that some other application (either in this + * process or elsewhere) may be embedding itself + * inside the window. * TK_BOTH_HALVES: 1 means that this window is used for - * application embedding (either as - * container or embedded application), and - * both the containing and embedded halves - * are associated with windows in this - * particular process. + * application embedding (either as container or + * embedded application), and both the containing + * and embedded halves are associated with + * windows in this particular process. * TK_DEFER_MODAL: 1 means that this window has deferred a modal * loop until all of the bindings for the current * event have been invoked. - * TK_WRAPPER: 1 means that this window is the extra - * wrapper window created around a toplevel - * to hold the menubar under Unix. See - * tkUnixWm.c for more information. + * TK_WRAPPER: 1 means that this window is the extra wrapper + * window created around a toplevel to hold the + * menubar under Unix. See tkUnixWm.c for more + * information. * TK_REPARENTED: 1 means that this window has been reparented * so that as far as the window system is - * concerned it isn't a child of its Tk - * parent. Initially this is used only for - * special Unix menubar windows. + * concerned it isn't a child of its Tk parent. + * Initially this is used only for special Unix + * menubar windows. * TK_ANONYMOUS_WINDOW: 1 means that this window has no name, and is * thus not accessible from Tk. * TK_HAS_WRAPPER 1 means that this window has a wrapper window - * TK_WIN_MANAGED 1 means that this window is a child of the - * root window, and is managed by the window - * manager. - * TK_TOP_HIERARCHY 1 means this window is at the top of a - * physical window hierarchy within this - * process, i.e. the window's parent - * either doesn't exist or is not owned by - * this Tk application. - * TK_PROP_PROPCHANGE 1 means that PropertyNotify events in - * this window's children should propagate - * up to this window. + * TK_WIN_MANAGED 1 means that this window is a child of the root + * window, and is managed by the window manager. + * TK_TOP_HIERARCHY 1 means this window is at the top of a physical + * window hierarchy within this process, i.e. the + * window's parent either doesn't exist or is not + * owned by this Tk application. + * TK_PROP_PROPCHANGE 1 means that PropertyNotify events in the + * window's children should propagate up to this + * window. + * TK_WM_MANAGEABLE 1 marks a window as capable of being converted + * into a toplevel using [wm manage]. */ - #define TK_MAPPED 1 #define TK_TOP_LEVEL 2 #define TK_ALREADY_DEAD 4 @@ -889,12 +880,12 @@ typedef struct Tk_FakeWin { #define TK_WIN_MANAGED 0x10000 #define TK_TOP_HIERARCHY 0x20000 #define TK_PROP_PROPCHANGE 0x40000 +#define TK_WM_MANAGEABLE 0x80000 /* *-------------------------------------------------------------- * - * Procedure prototypes and structures used for defining new canvas - * items: + * Procedure prototypes and structures used for defining new canvas items: * *-------------------------------------------------------------- */ @@ -915,54 +906,48 @@ typedef struct Tk_SmoothMethod { } Tk_SmoothMethod; /* - * For each item in a canvas widget there exists one record with - * the following structure. Each actual item is represented by - * a record with the following stuff at its beginning, plus additional - * type-specific stuff after that. + * For each item in a canvas widget there exists one record with the following + * structure. Each actual item is represented by a record with the following + * stuff at its beginning, plus additional type-specific stuff after that. */ #define TK_TAG_SPACE 3 -typedef struct Tk_Item { - int id; /* Unique identifier for this item - * (also serves as first tag for - * item). */ - struct Tk_Item *nextPtr; /* Next in display list of all - * items in this canvas. Later items - * in list are drawn on top of earlier - * ones. */ - Tk_Uid staticTagSpace[TK_TAG_SPACE];/* Built-in space for limited # of - * tags. */ - Tk_Uid *tagPtr; /* Pointer to array of tags. Usually - * points to staticTagSpace, but - * may point to malloc-ed space if - * there are lots of tags. */ - int tagSpace; /* Total amount of tag space available - * at tagPtr. */ - int numTags; /* Number of tag slots actually used - * at *tagPtr. */ - struct Tk_ItemType *typePtr; /* Table of procedures that implement - * this type of item. */ - int x1, y1, x2, y2; /* Bounding box for item, in integer - * canvas units. Set by item-specific - * code and guaranteed to contain every - * pixel drawn in item. Item area - * includes x1 and y1 but not x2 - * and y2. */ - struct Tk_Item *prevPtr; /* Previous in display list of all - * items in this canvas. Later items - * in list are drawn just below earlier - * ones. */ - Tk_State state; /* state of item */ - char *reserved1; /* reserved for future use */ - int redraw_flags; /* some flags used in the canvas */ +typedef struct Tk_Item { + int id; /* Unique identifier for this item (also + * serves as first tag for item). */ + struct Tk_Item *nextPtr; /* Next in display list of all items in this + * canvas. Later items in list are drawn on + * top of earlier ones. */ + Tk_Uid staticTagSpace[TK_TAG_SPACE]; + /* Built-in space for limited # of tags. */ + Tk_Uid *tagPtr; /* Pointer to array of tags. Usually points to + * staticTagSpace, but may point to malloc-ed + * space if there are lots of tags. */ + int tagSpace; /* Total amount of tag space available at + * tagPtr. */ + int numTags; /* Number of tag slots actually used at + * *tagPtr. */ + struct Tk_ItemType *typePtr;/* Table of procedures that implement this + * type of item. */ + int x1, y1, x2, y2; /* Bounding box for item, in integer canvas + * units. Set by item-specific code and + * guaranteed to contain every pixel drawn in + * item. Item area includes x1 and y1 but not + * x2 and y2. */ + struct Tk_Item *prevPtr; /* Previous in display list of all items in + * this canvas. Later items in list are drawn + * just below earlier ones. */ + Tk_State state; /* State of item. */ + char *reserved1; /* reserved for future use */ + int redraw_flags; /* Some flags used in the canvas */ /* *------------------------------------------------------------------ - * Starting here is additional type-specific stuff; see the - * declarations for individual types to see what is part of - * each type. The actual space below is determined by the - * "itemInfoSize" of the type's Tk_ItemType record. + * Starting here is additional type-specific stuff; see the declarations + * for individual types to see what is part of each type. The actual space + * below is determined by the "itemInfoSize" of the type's Tk_ItemType + * record. *------------------------------------------------------------------ */ } Tk_Item; @@ -970,20 +955,19 @@ typedef struct Tk_Item { /* * Flag bits for canvases (redraw_flags): * - * TK_ITEM_STATE_DEPENDANT - 1 means that object needs to be - * redrawn if the canvas state changes. - * TK_ITEM_DONT_REDRAW - 1 means that the object redraw is already - * been prepared, so the general canvas code - * doesn't need to do that any more. + * TK_ITEM_STATE_DEPENDANT - 1 means that object needs to be redrawn if the + * canvas state changes. + * TK_ITEM_DONT_REDRAW - 1 means that the object redraw is already been + * prepared, so the general canvas code doesn't + * need to do that any more. */ #define TK_ITEM_STATE_DEPENDANT 1 #define TK_ITEM_DONT_REDRAW 2 /* - * Records of the following type are used to describe a type of - * item (e.g. lines, circles, etc.) that can form part of a - * canvas widget. + * Records of the following type are used to describe a type of item (e.g. + * lines, circles, etc.) that can form part of a canvas widget. */ #ifdef USE_OLD_CANVAS @@ -999,13 +983,13 @@ typedef int Tk_ItemCoordProc _ANSI_ARGS_((Tcl_Interp *interp, #else typedef int Tk_ItemCreateProc _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - Tcl_Obj *CONST objv[])); + Tcl_Obj *const objv[])); typedef int Tk_ItemConfigureProc _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - Tcl_Obj *CONST objv[], int flags)); + Tcl_Obj *const objv[], int flags)); typedef int Tk_ItemCoordProc _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - Tcl_Obj *CONST argv[])); + Tcl_Obj *const argv[])); #endif typedef void Tk_ItemDeleteProc _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, Display *display)); @@ -1039,100 +1023,103 @@ typedef void Tk_ItemDCharsProc _ANSI_ARGS_((Tk_Canvas canvas, #ifndef __NO_OLD_CONFIG typedef struct Tk_ItemType { - char *name; /* The name of this type of item, such - * as "line". */ - int itemSize; /* Total amount of space needed for - * item's record. */ - Tk_ItemCreateProc *createProc; /* Procedure to create a new item of - * this type. */ - Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration - * specs for this type. Used for - * returning configuration info. */ - Tk_ItemConfigureProc *configProc; /* Procedure to call to change - * configuration options. */ - Tk_ItemCoordProc *coordProc; /* Procedure to call to get and set - * the item's coordinates. */ - Tk_ItemDeleteProc *deleteProc; /* Procedure to delete existing item of - * this type. */ - Tk_ItemDisplayProc *displayProc; /* Procedure to display items of - * this type. */ - int alwaysRedraw; /* Non-zero means displayProc should - * be called even when the item has - * been moved off-screen. */ - Tk_ItemPointProc *pointProc; /* Computes distance from item to - * a given point. */ - Tk_ItemAreaProc *areaProc; /* Computes whether item is inside, - * outside, or overlapping an area. */ + char *name; /* The name of this type of item, such as + * "line". */ + int itemSize; /* Total amount of space needed for item's + * record. */ + Tk_ItemCreateProc *createProc; + /* Procedure to create a new item of this + * type. */ + Tk_ConfigSpec *configSpecs; /* Pointer to array of configuration specs for + * this type. Used for returning configuration + * info. */ + Tk_ItemConfigureProc *configProc; + /* Procedure to call to change configuration + * options. */ + Tk_ItemCoordProc *coordProc;/* Procedure to call to get and set the item's + * coordinates. */ + Tk_ItemDeleteProc *deleteProc; + /* Procedure to delete existing item of this + * type. */ + Tk_ItemDisplayProc *displayProc; + /* Procedure to display items of this type. */ + int alwaysRedraw; /* Non-zero means displayProc should be called + * even when the item has been moved + * off-screen. */ + Tk_ItemPointProc *pointProc;/* Computes distance from item to a given + * point. */ + Tk_ItemAreaProc *areaProc; /* Computes whether item is inside, outside, + * or overlapping an area. */ Tk_ItemPostscriptProc *postscriptProc; - /* Procedure to write a Postscript - * description for items of this - * type. */ - Tk_ItemScaleProc *scaleProc; /* Procedure to rescale items of - * this type. */ - Tk_ItemTranslateProc *translateProc;/* Procedure to translate items of - * this type. */ - Tk_ItemIndexProc *indexProc; /* Procedure to determine index of - * indicated character. NULL if - * item doesn't support indexing. */ - Tk_ItemCursorProc *icursorProc; /* Procedure to set insert cursor pos. - * to just before a given position. */ - Tk_ItemSelectionProc *selectionProc;/* Procedure to return selection (in - * STRING format) when it is in this - * item. */ - Tk_ItemInsertProc *insertProc; /* Procedure to insert something into - * an item. */ - Tk_ItemDCharsProc *dCharsProc; /* Procedure to delete characters - * from an item. */ - struct Tk_ItemType *nextPtr; /* Used to link types together into - * a list. */ - char *reserved1; /* Reserved for future extension. */ - int reserved2; /* Carefully compatible with */ - char *reserved3; /* Jan Nijtmans dash patch */ + /* Procedure to write a Postscript description + * for items of this type. */ + Tk_ItemScaleProc *scaleProc;/* Procedure to rescale items of this type. */ + Tk_ItemTranslateProc *translateProc; + /* Procedure to translate items of this + * type. */ + Tk_ItemIndexProc *indexProc;/* Procedure to determine index of indicated + * character. NULL if item doesn't support + * indexing. */ + Tk_ItemCursorProc *icursorProc; + /* Procedure to set insert cursor posn to just + * before a given position. */ + Tk_ItemSelectionProc *selectionProc; + /* Procedure to return selection (in STRING + * format) when it is in this item. */ + Tk_ItemInsertProc *insertProc; + /* Procedure to insert something into an + * item. */ + Tk_ItemDCharsProc *dCharsProc; + /* Procedure to delete characters from an + * item. */ + struct Tk_ItemType *nextPtr;/* Used to link types together into a list. */ + char *reserved1; /* Reserved for future extension. */ + int reserved2; /* Carefully compatible with */ + char *reserved3; /* Jan Nijtmans dash patch */ char *reserved4; } Tk_ItemType; #endif /* - * The following structure provides information about the selection and - * the insertion cursor. It is needed by only a few items, such as - * those that display text. It is shared by the generic canvas code - * and the item-specific code, but most of the fields should be written - * only by the canvas generic code. + * The following structure provides information about the selection and the + * insertion cursor. It is needed by only a few items, such as those that + * display text. It is shared by the generic canvas code and the item-specific + * code, but most of the fields should be written only by the canvas generic + * code. */ typedef struct Tk_CanvasTextInfo { Tk_3DBorder selBorder; /* Border and background for selected - * characters. Read-only to items.*/ - int selBorderWidth; /* Width of border around selection. - * Read-only to items. */ + * characters. Read-only to items.*/ + int selBorderWidth; /* Width of border around selection. Read-only + * to items. */ XColor *selFgColorPtr; /* Foreground color for selected text. * Read-only to items. */ - Tk_Item *selItemPtr; /* Pointer to selected item. NULL means - * selection isn't in this canvas. - * Writable by items. */ + Tk_Item *selItemPtr; /* Pointer to selected item. NULL means + * selection isn't in this canvas. Writable by + * items. */ int selectFirst; /* Character index of first selected - * character. Writable by items. */ - int selectLast; /* Character index of last selected - * character. Writable by items. */ - Tk_Item *anchorItemPtr; /* Item corresponding to "selectAnchor": - * not necessarily selItemPtr. Read-only - * to items. */ - int selectAnchor; /* Character index of fixed end of - * selection (i.e. "select to" operation will - * use this as one end of the selection). + * character. Writable by items. */ + int selectLast; /* Character index of last selected character. * Writable by items. */ + Tk_Item *anchorItemPtr; /* Item corresponding to "selectAnchor": not + * necessarily selItemPtr. Read-only to + * items. */ + int selectAnchor; /* Character index of fixed end of selection + * (i.e. "select to" operation will use this + * as one end of the selection). Writable by + * items. */ Tk_3DBorder insertBorder; /* Used to draw vertical bar for insertion - * cursor. Read-only to items. */ - int insertWidth; /* Total width of insertion cursor. Read-only + * cursor. Read-only to items. */ + int insertWidth; /* Total width of insertion cursor. Read-only * to items. */ int insertBorderWidth; /* Width of 3-D border around insert cursor. * Read-only to items. */ - Tk_Item *focusItemPtr; /* Item that currently has the input focus, - * or NULL if no such item. Read-only to - * items. */ + Tk_Item *focusItemPtr; /* Item that currently has the input focus, or + * NULL if no such item. Read-only to items. */ int gotFocus; /* Non-zero means that the canvas widget has - * the input focus. Read-only to items.*/ + * the input focus. Read-only to items.*/ int cursorOn; /* Non-zero means that an insertion cursor * should be displayed in focusItemPtr. * Read-only to items.*/ @@ -1151,7 +1138,7 @@ typedef struct Tk_Dash { } Tk_Dash; typedef struct Tk_TSOffset { - int flags; /* flags; see below for possible values */ + int flags; /* Flags; see below for possible values */ int xoffset; /* x offset */ int yoffset; /* y offset */ } Tk_TSOffset; @@ -1174,22 +1161,23 @@ typedef struct Tk_Outline { double width; /* Width of outline. */ double activeWidth; /* Width of outline. */ double disabledWidth; /* Width of outline. */ - int offset; /* Dash offset */ - Tk_Dash dash; /* Dash pattern */ - Tk_Dash activeDash; /* Dash pattern if state is active*/ - Tk_Dash disabledDash; /* Dash pattern if state is disabled*/ - VOID *reserved1; /* reserved for future expansion */ + int offset; /* Dash offset. */ + Tk_Dash dash; /* Dash pattern. */ + Tk_Dash activeDash; /* Dash pattern if state is active. */ + Tk_Dash disabledDash; /* Dash pattern if state is disabled. */ + VOID *reserved1; /* Reserved for future expansion. */ VOID *reserved2; VOID *reserved3; - Tk_TSOffset tsoffset; /* stipple offset for outline*/ + Tk_TSOffset tsoffset; /* Stipple offset for outline. */ XColor *color; /* Outline color. */ XColor *activeColor; /* Outline color if state is active. */ XColor *disabledColor; /* Outline color if state is disabled. */ Pixmap stipple; /* Outline Stipple pattern. */ - Pixmap activeStipple; /* Outline Stipple pattern if state is active. */ - Pixmap disabledStipple; /* Outline Stipple pattern if state is disabled. */ + Pixmap activeStipple; /* Outline Stipple pattern if state is + * active. */ + Pixmap disabledStipple; /* Outline Stipple pattern if state is + * disabled. */ } Tk_Outline; - /* *-------------------------------------------------------------- @@ -1206,7 +1194,7 @@ typedef int (Tk_ImageCreateProc) _ANSI_ARGS_((Tcl_Interp *interp, Tk_ImageMaster master, ClientData *masterDataPtr)); #else typedef int (Tk_ImageCreateProc) _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int objc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, + char *name, int objc, Tcl_Obj *const objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, ClientData *masterDataPtr)); #endif typedef ClientData (Tk_ImageGetProc) _ANSI_ARGS_((Tk_Window tkwin, @@ -1225,39 +1213,37 @@ typedef int (Tk_ImagePostscriptProc) _ANSI_ARGS_((ClientData clientData, int x, int y, int width, int height, int prepass)); /* - * The following structure represents a particular type of image - * (bitmap, xpm image, etc.). It provides information common to - * all images of that type, such as the type name and a collection - * of procedures in the image manager that respond to various - * events. Each image manager is represented by one of these - * structures. + * The following structure represents a particular type of image (bitmap, xpm + * image, etc.). It provides information common to all images of that type, + * such as the type name and a collection of procedures in the image manager + * that respond to various events. Each image manager is represented by one of + * these structures. */ struct Tk_ImageType { char *name; /* Name of image type. */ Tk_ImageCreateProc *createProc; - /* Procedure to call to create a new image - * of this type. */ + /* Procedure to call to create a new image of + * this type. */ Tk_ImageGetProc *getProc; /* Procedure to call the first time - * Tk_GetImage is called in a new way - * (new visual or screen). */ + * Tk_GetImage is called in a new way (new + * visual or screen). */ Tk_ImageDisplayProc *displayProc; /* Call to draw image, in response to * Tk_RedrawImage calls. */ - Tk_ImageFreeProc *freeProc; /* Procedure to call whenever Tk_FreeImage - * is called to release an instance of an + Tk_ImageFreeProc *freeProc; /* Procedure to call whenever Tk_FreeImage is + * called to release an instance of an * image. */ Tk_ImageDeleteProc *deleteProc; - /* Procedure to call to delete image. It - * will not be called until after freeProc - * has been called for each instance of the - * image. */ + /* Procedure to call to delete image. It will + * not be called until after freeProc has been + * called for each instance of the image. */ Tk_ImagePostscriptProc *postscriptProc; /* Procedure to call to produce postscript * output for the image. */ struct Tk_ImageType *nextPtr; /* Next in list of all image types currently - * known. Filled in by Tk, not by image + * known. Filled in by Tk, not by image * manager. */ char *reserved; /* reserved for future expansion */ }; @@ -1271,8 +1257,8 @@ struct Tk_ImageType { */ /* - * The following type is used to identify a particular photo image - * to be manipulated: + * The following type is used to identify a particular photo image to be + * manipulated: */ typedef void *Tk_PhotoHandle; @@ -1283,29 +1269,28 @@ typedef void *Tk_PhotoHandle; typedef struct Tk_PhotoImageBlock { unsigned char *pixelPtr; /* Pointer to the first pixel. */ - int width; /* Width of block, in pixels. */ - int height; /* Height of block, in pixels. */ - int pitch; /* Address difference between corresponding + int width; /* Width of block, in pixels. */ + int height; /* Height of block, in pixels. */ + int pitch; /* Address difference between corresponding * pixels in successive lines. */ - int pixelSize; /* Address difference between successive + int pixelSize; /* Address difference between successive * pixels in the same line. */ - int offset[4]; /* Address differences between the red, green, + int offset[4]; /* Address differences between the red, green, * blue and alpha components of the pixel and * the pixel as a whole. */ } Tk_PhotoImageBlock; /* - * The following values control how blocks are combined into photo - * images when the alpha component of a pixel is not 255, a.k.a. the - * compositing rule. + * The following values control how blocks are combined into photo images when + * the alpha component of a pixel is not 255, a.k.a. the compositing rule. */ #define TK_PHOTO_COMPOSITE_OVERLAY 0 #define TK_PHOTO_COMPOSITE_SET 1 /* - * Procedure prototypes and structures used in reading and - * writing photo images: + * Procedure prototypes and structures used in reading and writing photo + * images: */ typedef struct Tk_PhotoImageFormat Tk_PhotoImageFormat; @@ -1328,68 +1313,61 @@ typedef int (Tk_ImageStringWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr)); #else typedef int (Tk_ImageFileMatchProc) _ANSI_ARGS_((Tcl_Channel chan, - CONST char *fileName, Tcl_Obj *format, int *widthPtr, + const char *fileName, Tcl_Obj *format, int *widthPtr, int *heightPtr, Tcl_Interp *interp)); typedef int (Tk_ImageStringMatchProc) _ANSI_ARGS_((Tcl_Obj *dataObj, Tcl_Obj *format, int *widthPtr, int *heightPtr, Tcl_Interp *interp)); typedef int (Tk_ImageFileReadProc) _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, CONST char *fileName, Tcl_Obj *format, + Tcl_Channel chan, const char *fileName, Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, int srcX, int srcY)); typedef int (Tk_ImageStringReadProc) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj, Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, int srcX, int srcY)); typedef int (Tk_ImageFileWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *fileName, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr)); + const char *fileName, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr)); typedef int (Tk_ImageStringWriteProc) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr)); #endif /* - * The following structure represents a particular file format for - * storing images (e.g., PPM, GIF, JPEG, etc.). It provides information - * to allow image files of that format to be recognized and read into - * a photo image. + * The following structure represents a particular file format for storing + * images (e.g., PPM, GIF, JPEG, etc.). It provides information to allow image + * files of that format to be recognized and read into a photo image. */ struct Tk_PhotoImageFormat { char *name; /* Name of image file format */ Tk_ImageFileMatchProc *fileMatchProc; - /* Procedure to call to determine whether - * an image file matches this format. */ + /* Procedure to call to determine whether an + * image file matches this format. */ Tk_ImageStringMatchProc *stringMatchProc; - /* Procedure to call to determine whether - * the data in a string matches this format. */ + /* Procedure to call to determine whether the + * data in a string matches this format. */ Tk_ImageFileReadProc *fileReadProc; - /* Procedure to call to read data from - * an image file into a photo image. */ + /* Procedure to call to read data from an + * image file into a photo image. */ Tk_ImageStringReadProc *stringReadProc; - /* Procedure to call to read data from - * a string into a photo image. */ + /* Procedure to call to read data from a + * string into a photo image. */ Tk_ImageFileWriteProc *fileWriteProc; - /* Procedure to call to write data from - * a photo image to a file. */ + /* Procedure to call to write data from a + * photo image to a file. */ Tk_ImageStringWriteProc *stringWriteProc; /* Procedure to call to obtain a string * representation of the data in a photo * image.*/ struct Tk_PhotoImageFormat *nextPtr; /* Next in list of all photo image formats - * currently known. Filled in by Tk, not - * by image format handler. */ + * currently known. Filled in by Tk, not by + * image format handler. */ }; -EXTERN void Tk_CreateOldImageType _ANSI_ARGS_(( - Tk_ImageType *typePtr)); -EXTERN void Tk_CreateOldPhotoImageFormat _ANSI_ARGS_(( - Tk_PhotoImageFormat *formatPtr)); - -#if !defined(USE_TK_STUBS) && defined(USE_OLD_IMAGE) +#ifdef USE_OLD_IMAGE #define Tk_CreateImageType Tk_CreateOldImageType #define Tk_CreatePhotoImageFormat Tk_CreateOldPhotoImageFormat #endif - /* *-------------------------------------------------------------- @@ -1402,6 +1380,7 @@ EXTERN void Tk_CreateOldPhotoImageFormat _ANSI_ARGS_(( /* * Style support version tag. */ + #define TK_STYLE_VERSION_1 0x1 #define TK_STYLE_VERSION TK_STYLE_VERSION_1 @@ -1411,16 +1390,16 @@ EXTERN void Tk_CreateOldPhotoImageFormat _ANSI_ARGS_(( */ typedef void (Tk_GetElementSizeProc) _ANSI_ARGS_((ClientData clientData, - char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin, + char *recordPtr, const Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr)); typedef void (Tk_GetElementBoxProc) _ANSI_ARGS_((ClientData clientData, - char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin, + char *recordPtr, const Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)); typedef int (Tk_GetElementBorderWidthProc) _ANSI_ARGS_((ClientData clientData, - char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin)); + char *recordPtr, const Tk_OptionSpec **optionsPtr, Tk_Window tkwin)); typedef void (Tk_DrawElementProc) _ANSI_ARGS_((ClientData clientData, - char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin, + char *recordPtr, const Tk_OptionSpec **optionsPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state)); typedef struct Tk_ElementOptionSpec { @@ -1435,22 +1414,18 @@ typedef struct Tk_ElementSpec { Tk_ElementOptionSpec *options; /* List of required options. Last one's name * must be NULL. */ - - /* - * Hooks - */ - Tk_GetElementSizeProc *getSize; - /* Compute the external (resp. internal) size of - * the element from its desired internal (resp. - * external) size. */ + /* Compute the external (resp. internal) size + * of the element from its desired internal + * (resp. external) size. */ Tk_GetElementBoxProc *getBox; /* Compute the inscribed or bounding boxes * within a given area. */ Tk_GetElementBorderWidthProc *getBorderWidth; /* Return the element's internal border width. * Mostly useful for widgets. */ - Tk_DrawElementProc *draw; /* Draw the element in the given bounding box.*/ + Tk_DrawElementProc *draw; /* Draw the element in the given bounding + * box. */ } Tk_ElementSpec; /* @@ -1465,9 +1440,9 @@ typedef struct Tk_ElementSpec { /* *-------------------------------------------------------------- * - * The definitions below provide backward compatibility for - * functions and types related to event handling that used to - * be in Tk but have moved to Tcl. + * The definitions below provide backward compatibility for functions and + * types related to event handling that used to be in Tk but have moved to + * Tcl. * *-------------------------------------------------------------- */ @@ -1510,23 +1485,20 @@ typedef struct Tk_ElementSpec { #define Tk_Main(argc, argv, proc) \ Tk_MainEx(argc, argv, proc, Tcl_CreateInterp()) -CONST char *Tk_InitStubs _ANSI_ARGS_((Tcl_Interp *interp, char *version, int exact)); +const char * Tk_InitStubs _ANSI_ARGS_((Tcl_Interp *interp, + const char *version, int exact)); +EXTERN const char * Tk_PkgInitStubsCheck _ANSI_ARGS_((Tcl_Interp *interp, + const char *version, int exact)); #ifndef USE_TK_STUBS #define Tk_InitStubs(interp, version, exact) \ - Tcl_PkgRequire(interp, "Tk", version, exact) + Tk_PkgInitStubsCheck(interp, version, exact) #endif -void Tk_InitImageArgs _ANSI_ARGS_((Tcl_Interp *interp, int argc, char ***argv)); - -#if !defined(USE_TK_STUBS) || !defined(USE_OLD_IMAGE) - #define Tk_InitImageArgs(interp, argc, argv) /**/ -#endif - /* *-------------------------------------------------------------- @@ -1552,7 +1524,6 @@ typedef Tk_RestrictAction (Tk_RestrictProc) _ANSI_ARGS_(( typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData, int offset, char *buffer, int maxBytes)); - /* *-------------------------------------------------------------- * @@ -1564,12 +1535,11 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData, #include "tkDecls.h" /* - * Allow users to say that they don't want to alter their source to - * add the extra argument to Tk_PhotoPutBlock(); DO NOT DEFINE THIS - * WHEN BUILDING TK. + * 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. * - * This goes after the inclusion of the stubbed-decls so that the - * declarations of what is actually there can be correct. + * This goes after the inclusion of the stubbed-decls so that the declarations + * of what is actually there can be correct. */ #ifdef USE_COMPOSITELESS_PHOTO_PUT_BLOCK @@ -1581,13 +1551,34 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData, # undef Tk_PhotoPutZoomedBlock # endif # define Tk_PhotoPutZoomedBlock Tk_PhotoPutZoomedBlock_NoComposite +# define USE_PANIC_ON_PHOTO_ALLOC_FAILURE +#else /* !USE_COMPOSITELESS_PHOTO_PUT_BLOCK */ +# ifdef USE_PANIC_ON_PHOTO_ALLOC_FAILURE +# ifdef Tk_PhotoPutBlock +# undef Tk_PhotoPutBlock +# endif +# define Tk_PhotoPutBlock Tk_PhotoPutBlock_Panic +# ifdef Tk_PhotoPutZoomedBlock +# undef Tk_PhotoPutZoomedBlock +# endif +# define Tk_PhotoPutZoomedBlock Tk_PhotoPutZoomedBlock_Panic +# endif /* USE_PANIC_ON_PHOTO_ALLOC_FAILURE */ #endif /* USE_COMPOSITELESS_PHOTO_PUT_BLOCK */ +#ifdef USE_PANIC_ON_PHOTO_ALLOC_FAILURE +# ifdef Tk_PhotoExpand +# undef Tk_PhotoExpand +# endif +# define Tk_PhotoExpand Tk_PhotoExpand_Panic +# ifdef Tk_PhotoSetSize +# undef Tk_PhotoSetSize +# endif +# define Tk_PhotoSetSize Tk_PhotoSetSize_Panic +#endif /* USE_PANIC_ON_PHOTO_ALLOC_FAILURE */ /* * Tcl commands exported by Tk: */ - #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT @@ -1596,9 +1587,17 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData, /* * end block for C++ */ - + #ifdef __cplusplus } #endif - + #endif /* _TK */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tk3d.c b/generic/tk3d.c index 4d9d163..caa40dd 100644 --- a/generic/tk3d.c +++ b/generic/tk3d.c @@ -1,40 +1,41 @@ -/* +/* * tk3d.c -- * - * This module provides procedures to draw borders in - * the three-dimensional Motif style. + * This module provides procedures to draw borders in the + * three-dimensional Motif style. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tk3d.h" /* - * The following table defines the string values for reliefs, which are - * used by Tk_GetReliefFromObj. + * The following table defines the string values for reliefs, which are used + * by Tk_GetReliefFromObj. */ -static CONST char *reliefStrings[] = {"flat", "groove", "raised", - "ridge", "solid", "sunken", - (char *) NULL}; +static CONST char *reliefStrings[] = { + "flat", "groove", "raised", "ridge", "solid", "sunken", NULL +}; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static void BorderInit _ANSI_ARGS_((TkDisplay *dispPtr)); -static void DupBorderObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, - Tcl_Obj *dupObjPtr)); -static void FreeBorderObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); -static int Intersect _ANSI_ARGS_((XPoint *a1Ptr, XPoint *a2Ptr, - XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr)); -static void InitBorderObj _ANSI_ARGS_((Tcl_Obj *objPtr)); -static void ShiftLine _ANSI_ARGS_((XPoint *p1Ptr, XPoint *p2Ptr, - int distance, XPoint *p3Ptr)); +static void BorderInit(TkDisplay *dispPtr); +static void DupBorderObjProc(Tcl_Obj *srcObjPtr, + Tcl_Obj *dupObjPtr); +static void FreeBorderObjProc(Tcl_Obj *objPtr); +static int Intersect(XPoint *a1Ptr, XPoint *a2Ptr, + XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr); +static void InitBorderObj(Tcl_Obj *objPtr); +static void ShiftLine(XPoint *p1Ptr, XPoint *p2Ptr, + int distance, XPoint *p3Ptr); /* * The following structure defines the implementation of the "border" Tcl @@ -57,30 +58,30 @@ Tcl_ObjType tkBorderObjType = { * * Tk_Alloc3DBorderFromObj -- * - * Given a Tcl_Obj *, map the value to a corresponding - * Tk_3DBorder structure based on the tkwin given. + * Given a Tcl_Obj *, map the value to a corresponding Tk_3DBorder + * structure based on the tkwin given. * * Results: - * The return value is a token for a data structure describing a - * 3-D border. This token may be passed to procedures such as - * Tk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented - * the border from being created then NULL is returned and an error - * message will be left in the interp's result. + * The return value is a token for a data structure describing a 3-D + * border. This token may be passed to functions such as + * Tk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented the + * border from being created then NULL is returned and an error message + * will be left in the interp's result. * * Side effects: - * The border is added to an internal database with a reference - * count. For each call to this procedure, there should eventually - * be a call to FreeBorderObjProc so that the database is - * cleaned up when borders aren't in use anymore. + * The border is added to an internal database with a reference count. + * For each call to this function, there should eventually be a call to + * FreeBorderObjProc so that the database is cleaned up when borders + * aren't in use anymore. * *---------------------------------------------------------------------- */ Tk_3DBorder -Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr) - Tcl_Interp *interp; /* Interp for error results. */ - Tk_Window tkwin; /* Need the screen the border is used on.*/ - Tcl_Obj *objPtr; /* Object giving name of color for window +Tk_Alloc3DBorderFromObj( + Tcl_Interp *interp, /* Interp for error results. */ + Tk_Window tkwin, /* Need the screen the border is used on.*/ + Tcl_Obj *objPtr) /* Object giving name of color for window * background. */ { TkBorder *borderPtr; @@ -91,15 +92,15 @@ Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr) borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1; /* - * If the object currently points to a TkBorder, see if it's the - * one we want. If so, increment its reference count and return. + * If the object currently points to a TkBorder, see if it's the one we + * want. If so, increment its reference count and return. */ if (borderPtr != NULL) { if (borderPtr->resourceRefCount == 0) { /* - * This is a stale reference: it refers to a border that's - * no longer in use. Clear the reference. + * This is a stale reference: it refers to a border that's no + * longer in use. Clear the reference. */ FreeBorderObjProc(objPtr); @@ -112,24 +113,22 @@ Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr) } /* - * The object didn't point to the border that we wanted. Search - * the list of borders with the same name to see if one of the - * others is the right one. + * The object didn't point to the border that we wanted. Search the list + * of borders with the same name to see if one of the others is the right + * one. */ /* - * If the cached value is NULL, either the object type was not a - * color going in, or the object is a color type but had - * previously been freed. + * If the cached value is NULL, either the object type was not a color + * going in, or the object is a color type but had previously been freed. * - * If the value is not NULL, the internal rep is the value - * of the color the last time this object was accessed. Check - * the screen and colormap of the last access, and if they - * match, we are done. + * If the value is not NULL, the internal rep is the value of the color + * the last time this object was accessed. Check the screen and colormap + * of the last access, and if they match, we are done. */ if (borderPtr != NULL) { - TkBorder *firstBorderPtr = + TkBorder *firstBorderPtr = (TkBorder *) Tcl_GetHashValue(borderPtr->hashPtr); FreeBorderObjProc(objPtr); for (borderPtr = firstBorderPtr ; borderPtr != NULL; @@ -138,19 +137,19 @@ Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr) && (Tk_Colormap(tkwin) == borderPtr->colormap)) { borderPtr->resourceRefCount++; borderPtr->objRefCount++; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) borderPtr; return (Tk_3DBorder) borderPtr; } } } /* - * Still no luck. Call Tk_Get3DBorder to allocate a new border. + * Still no luck. Call Tk_Get3DBorder to allocate a new border. */ borderPtr = (TkBorder *) Tk_Get3DBorder(interp, tkwin, Tcl_GetString(objPtr)); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) borderPtr; if (borderPtr != NULL) { borderPtr->objRefCount++; } @@ -165,31 +164,31 @@ Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr) * Create a data structure for displaying a 3-D border. * * Results: - * The return value is a token for a data structure describing a - * 3-D border. This token may be passed to procedures such as - * Tk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented - * the border from being created then NULL is returned and an error - * message will be left in the interp's result. + * The return value is a token for a data structure describing a 3-D + * border. This token may be passed to functions such as + * Tk_Draw3DRectangle and Tk_Free3DBorder. If an error prevented the + * border from being created then NULL is returned and an error message + * will be left in the interp's result. * * Side effects: - * Data structures, graphics contexts, etc. are allocated. - * It is the caller's responsibility to eventually call - * Tk_Free3DBorder to release the resources. + * Data structures, graphics contexts, etc. are allocated. It is the + * caller's responsibility to eventually call Tk_Free3DBorder to release + * the resources. * *-------------------------------------------------------------- */ Tk_3DBorder -Tk_Get3DBorder(interp, tkwin, colorName) - Tcl_Interp *interp; /* Place to store an error message. */ - Tk_Window tkwin; /* Token for window in which border will - * be drawn. */ - Tk_Uid colorName; /* String giving name of color - * for window background. */ +Tk_Get3DBorder( + Tcl_Interp *interp, /* Place to store an error message. */ + Tk_Window tkwin, /* Token for window in which border will be + * drawn. */ + Tk_Uid colorName) /* String giving name of color for window + * background. */ { Tcl_HashEntry *hashPtr; TkBorder *borderPtr, *existingBorderPtr; - int new; + int isNew; XGCValues gcValues; XColor *bgColorPtr; TkDisplay *dispPtr; @@ -200,8 +199,8 @@ Tk_Get3DBorder(interp, tkwin, colorName) BorderInit(dispPtr); } - hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &new); - if (!new) { + hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &isNew); + if (!isNew) { existingBorderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr); for (borderPtr = existingBorderPtr; borderPtr != NULL; borderPtr = borderPtr->nextPtr) { @@ -216,12 +215,12 @@ Tk_Get3DBorder(interp, tkwin, colorName) } /* - * No satisfactory border exists yet. Initialize a new one. + * No satisfactory border exists yet. Initialize a new one. */ bgColorPtr = Tk_GetColor(interp, tkwin, colorName); if (bgColorPtr == NULL) { - if (new) { + if (isNew) { Tcl_DeleteHashEntry(hashPtr); } return NULL; @@ -246,9 +245,8 @@ Tk_Get3DBorder(interp, tkwin, colorName) Tcl_SetHashValue(hashPtr, borderPtr); /* - * Create the information for displaying the background color, - * but delay the allocation of shadows until they are actually - * needed for drawing. + * Create the information for displaying the background color, but delay + * the allocation of shadows until they are actually needed for drawing. */ gcValues.foreground = borderPtr->bgColorPtr->pixel; @@ -267,25 +265,24 @@ Tk_Get3DBorder(interp, tkwin, colorName) * None. * * Side effects: - * A 3-D border will be drawn in the indicated drawable. - * The outside edges of the border will be determined by x, - * y, width, and height. The inside edges of the border - * will be determined by the borderWidth argument. + * A 3-D border will be drawn in the indicated drawable. The outside + * edges of the border will be determined by x, y, width, and height. The + * inside edges of the border will be determined by the borderWidth + * argument. * *-------------------------------------------------------------- */ void -Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width, height, - borderWidth, relief) - Tk_Window tkwin; /* Window for which border was allocated. */ - Drawable drawable; /* X window or pixmap in which to draw. */ - Tk_3DBorder border; /* Token for border to draw. */ - int x, y, width, height; /* Outside area of region in - * which border will be drawn. */ - int borderWidth; /* Desired width for border, in - * pixels. */ - int relief; /* Type of relief: TK_RELIEF_RAISED, +Tk_Draw3DRectangle( + Tk_Window tkwin, /* Window for which border was allocated. */ + Drawable drawable, /* X window or pixmap in which to draw. */ + Tk_3DBorder border, /* Token for border to draw. */ + int x, int y, int width, int height, + /* Outside area of region in which border will + * be drawn. */ + int borderWidth, /* Desired width for border, in pixels. */ + int relief) /* Type of relief: TK_RELIEF_RAISED, * TK_RELIEF_SUNKEN, TK_RELIEF_GROOVE, etc. */ { if (width < 2*borderWidth) { @@ -309,12 +306,11 @@ Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width, height, * * Tk_NameOf3DBorder -- * - * Given a border, return a textual string identifying the - * border's color. + * Given a border, return a textual string identifying the border's + * color. * * Results: - * The return value is the string that was used to create - * the border. + * The return value is the string that was used to create the border. * * Side effects: * None. @@ -323,8 +319,8 @@ Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width, height, */ CONST char * -Tk_NameOf3DBorder(border) - Tk_3DBorder border; /* Token for border. */ +Tk_NameOf3DBorder( + Tk_3DBorder border) /* Token for border. */ { TkBorder *borderPtr = (TkBorder *) border; @@ -336,8 +332,7 @@ Tk_NameOf3DBorder(border) * * Tk_3DBorderColor -- * - * Given a 3D border, return the X color used for the "flat" - * surfaces. + * Given a 3D border, return the X color used for the "flat" surfaces. * * Results: * Returns the color used drawing flat surfaces with the border. @@ -348,10 +343,10 @@ Tk_NameOf3DBorder(border) *-------------------------------------------------------------------- */ XColor * -Tk_3DBorderColor(border) - Tk_3DBorder border; /* Border whose color is wanted. */ +Tk_3DBorderColor( + Tk_3DBorder border) /* Border whose color is wanted. */ { - return(((TkBorder *) border)->bgColorPtr); + return ((TkBorder *) border)->bgColorPtr; } /* @@ -359,8 +354,8 @@ Tk_3DBorderColor(border) * * Tk_3DBorderGC -- * - * Given a 3D border, returns one of the graphics contexts used to - * draw the border. + * Given a 3D border, returns one of the graphics contexts used to draw + * the border. * * Results: * Returns the graphics context given by the "which" argument. @@ -371,10 +366,10 @@ Tk_3DBorderColor(border) *-------------------------------------------------------------------- */ GC -Tk_3DBorderGC(tkwin, border, which) - Tk_Window tkwin; /* Window for which border was allocated. */ - Tk_3DBorder border; /* Border whose GC is wanted. */ - int which; /* Selects one of the border's 3 GC's: +Tk_3DBorderGC( + Tk_Window tkwin, /* Window for which border was allocated. */ + Tk_3DBorder border, /* Border whose GC is wanted. */ + int which) /* Selects one of the border's 3 GC's: * TK_3D_FLAT_GC, TK_3D_LIGHT_GC, or * TK_3D_DARK_GC. */ { @@ -390,11 +385,11 @@ Tk_3DBorderGC(tkwin, border, which) } else if (which == TK_3D_DARK_GC){ return borderPtr->darkGC; } - panic("bogus \"which\" value in Tk_3DBorderGC"); + Tcl_Panic("bogus \"which\" value in Tk_3DBorderGC"); /* - * The code below will never be executed, but it's needed to - * keep compilers happy. + * The code below will never be executed, but it's needed to keep + * compilers happy. */ return (GC) None; @@ -405,10 +400,9 @@ Tk_3DBorderGC(tkwin, border, which) * * Tk_Free3DBorder -- * - * This procedure is called when a 3D border is no longer - * needed. It frees the resources associated with the - * border. After this call, the caller should never again - * use the "border" token. + * This function is called when a 3D border is no longer needed. It frees + * the resources associated with the border. After this call, the caller + * should never again use the "border" token. * * Results: * None. @@ -420,8 +414,8 @@ Tk_3DBorderGC(tkwin, border, which) */ void -Tk_Free3DBorder(border) - Tk_3DBorder border; /* Token for border to be released. */ +Tk_Free3DBorder( + Tk_3DBorder border) /* Token for border to be released. */ { TkBorder *borderPtr = (TkBorder *) border; Display *display = DisplayOfScreen(borderPtr->screen); @@ -477,27 +471,27 @@ Tk_Free3DBorder(border) * * Tk_Free3DBorderFromObj -- * - * This procedure is called to release a border allocated by - * Tk_Alloc3DBorderFromObj. It does not throw away the Tcl_Obj *; - * it only gets rid of the hash table entry for this border - * and clears the cached value that is normally stored in the object. + * This function is called to release a border allocated by + * Tk_Alloc3DBorderFromObj. It does not throw away the Tcl_Obj *; it only + * gets rid of the hash table entry for this border and clears the cached + * value that is normally stored in the object. * * Results: * None. * * Side effects: - * The reference count associated with the border represented by - * objPtr is decremented, and the border's resources are released - * to X if there are no remaining uses for it. + * The reference count associated with the border represented by objPtr + * is decremented, and the border's resources are released to X if there + * are no remaining uses for it. * *---------------------------------------------------------------------- */ void -Tk_Free3DBorderFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window this border lives in. Needed - * for the screen and colormap values. */ - Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */ +Tk_Free3DBorderFromObj( + Tk_Window tkwin, /* The window this border lives in. Needed for + * the screen and colormap values. */ + Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */ { Tk_Free3DBorder(Tk_Get3DBorderFromObj(tkwin, objPtr)); FreeBorderObjProc(objPtr); @@ -506,66 +500,65 @@ Tk_Free3DBorderFromObj(tkwin, objPtr) /* *--------------------------------------------------------------------------- * - * FreeBorderObjProc -- + * FreeBorderObjProc -- * - * This proc is called to release an object reference to a border. - * Called when the object's internal rep is released or when - * the cached borderPtr needs to be changed. + * This proc is called to release an object reference to a border. Called + * when the object's internal rep is released or when the cached + * borderPtr needs to be changed. * * Results: * None. * * Side effects: - * The object reference count is decremented. When both it - * and the hash ref count go to zero, the border's resources - * are released. + * The object reference count is decremented. When both it and the hash + * ref count go to zero, the border's resources are released. * *--------------------------------------------------------------------------- */ static void -FreeBorderObjProc(objPtr) - Tcl_Obj *objPtr; /* The object we are releasing. */ +FreeBorderObjProc( + Tcl_Obj *objPtr) /* The object we are releasing. */ { TkBorder *borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1; if (borderPtr != NULL) { borderPtr->objRefCount--; - if ((borderPtr->objRefCount == 0) + if ((borderPtr->objRefCount == 0) && (borderPtr->resourceRefCount == 0)) { ckfree((char *) borderPtr); } - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } } /* *--------------------------------------------------------------------------- * - * DupBorderObjProc -- + * DupBorderObjProc -- * - * When a cached border object is duplicated, this is called to - * update the internal reps. + * When a cached border object is duplicated, this is called to update + * the internal reps. * * Results: * None. * * Side effects: - * The border's objRefCount is incremented and the internal rep - * of the copy is set to point to it. + * The border's objRefCount is incremented and the internal rep of the + * copy is set to point to it. * *--------------------------------------------------------------------------- */ static void -DupBorderObjProc(srcObjPtr, dupObjPtr) - Tcl_Obj *srcObjPtr; /* The object we are copying from. */ - Tcl_Obj *dupObjPtr; /* The object we are copying to. */ +DupBorderObjProc( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { TkBorder *borderPtr = (TkBorder *) srcObjPtr->internalRep.twoPtrValue.ptr1; - + dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr; + dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) borderPtr; if (borderPtr != NULL) { borderPtr->objRefCount++; @@ -577,8 +570,8 @@ DupBorderObjProc(srcObjPtr, dupObjPtr) * * Tk_SetBackgroundFromBorder -- * - * Change the background of a window to one appropriate for a given - * 3-D border. + * Change the background of a window to one appropriate for a given 3-D + * border. * * Results: * None. @@ -590,9 +583,9 @@ DupBorderObjProc(srcObjPtr, dupObjPtr) */ void -Tk_SetBackgroundFromBorder(tkwin, border) - Tk_Window tkwin; /* Window whose background is to be set. */ - Tk_3DBorder border; /* Token for border. */ +Tk_SetBackgroundFromBorder( + Tk_Window tkwin, /* Window whose background is to be set. */ + Tk_3DBorder border) /* Token for border. */ { register TkBorder *borderPtr = (TkBorder *) border; @@ -618,13 +611,13 @@ Tk_SetBackgroundFromBorder(tkwin, border) */ int -Tk_GetReliefFromObj(interp, objPtr, resultPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Tcl_Obj *objPtr; /* The object we are trying to get the - * value from. */ - int *resultPtr; /* Where to place the answer. */ +Tk_GetReliefFromObj( + Tcl_Interp *interp, /* Used for error reporting. */ + Tcl_Obj *objPtr, /* The object we are trying to get the value + * from. */ + int *resultPtr) /* Where to place the answer. */ { - return Tcl_GetIndexFromObj(interp, objPtr, reliefStrings, "relief", 0, + return Tcl_GetIndexFromObj(interp, objPtr, reliefStrings, "relief", 0, resultPtr); } @@ -633,13 +626,13 @@ Tk_GetReliefFromObj(interp, objPtr, resultPtr) * * Tk_GetRelief -- * - * Parse a relief description and return the corresponding - * relief value, or an error. + * Parse a relief description and return the corresponding relief value, + * or an error. * * Results: - * A standard Tcl return value. If all goes well then - * *reliefPtr is filled in with one of the values - * TK_RELIEF_RAISED, TK_RELIEF_FLAT, or TK_RELIEF_SUNKEN. + * A standard Tcl return value. If all goes well then *reliefPtr is + * filled in with one of the values TK_RELIEF_RAISED, TK_RELIEF_FLAT, or + * TK_RELIEF_SUNKEN. * * Side effects: * None. @@ -648,10 +641,10 @@ Tk_GetReliefFromObj(interp, objPtr, resultPtr) */ int -Tk_GetRelief(interp, name, reliefPtr) - Tcl_Interp *interp; /* For error messages. */ - CONST char *name; /* Name of a relief type. */ - int *reliefPtr; /* Where to store converted relief. */ +Tk_GetRelief( + Tcl_Interp *interp, /* For error messages. */ + CONST char *name, /* Name of a relief type. */ + int *reliefPtr) /* Where to store converted relief. */ { char c; size_t length; @@ -688,12 +681,10 @@ Tk_GetRelief(interp, name, reliefPtr) * * Tk_NameOfRelief -- * - * Given a relief value, produce a string describing that - * relief value. + * Given a relief value, produce a string describing that relief value. * * Results: - * The return value is a static string that is equivalent - * to relief. + * The return value is a static string that is equivalent to relief. * * Side effects: * None. @@ -702,9 +693,9 @@ Tk_GetRelief(interp, name, reliefPtr) */ CONST char * -Tk_NameOfRelief(relief) - int relief; /* One of TK_RELIEF_FLAT, TK_RELIEF_RAISED, - * or TK_RELIEF_SUNKEN. */ +Tk_NameOfRelief( + int relief) /* One of TK_RELIEF_FLAT, TK_RELIEF_RAISED, or + * TK_RELIEF_SUNKEN. */ { if (relief == TK_RELIEF_FLAT) { return "flat"; @@ -730,39 +721,35 @@ Tk_NameOfRelief(relief) * * Tk_Draw3DPolygon -- * - * Draw a border with 3-D appearance around the edge of a - * given polygon. + * Draw a border with 3-D appearance around the edge of a given polygon. * * Results: * None. * * Side effects: - * Information is drawn in "drawable" in the form of a - * 3-D border borderWidth units width wide on the left - * of the trajectory given by pointPtr and numPoints (or - * -borderWidth units wide on the right side, if borderWidth - * is negative). + * Information is drawn in "drawable" in the form of a 3-D border + * borderWidth units width wide on the left of the trajectory given by + * pointPtr and numPoints (or -borderWidth units wide on the right side, + * if borderWidth is negative). * *-------------------------------------------------------------- */ void -Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, - borderWidth, leftRelief) - Tk_Window tkwin; /* Window for which border was allocated. */ - Drawable drawable; /* X window or pixmap in which to draw. */ - Tk_3DBorder border; /* Token for border to draw. */ - XPoint *pointPtr; /* Array of points describing - * polygon. All points must be - * absolute (CoordModeOrigin). */ - int numPoints; /* Number of points at *pointPtr. */ - int borderWidth; /* Width of border, measured in - * pixels to the left of the polygon's - * trajectory. May be negative. */ - int leftRelief; /* TK_RELIEF_RAISED or - * TK_RELIEF_SUNKEN: indicates how - * stuff to left of trajectory looks - * relative to stuff on right. */ +Tk_Draw3DPolygon( + Tk_Window tkwin, /* Window for which border was allocated. */ + Drawable drawable, /* X window or pixmap in which to draw. */ + Tk_3DBorder border, /* Token for border to draw. */ + XPoint *pointPtr, /* Array of points describing polygon. All + * points must be absolute + * (CoordModeOrigin). */ + int numPoints, /* Number of points at *pointPtr. */ + int borderWidth, /* Width of border, measured in pixels to the + * left of the polygon's trajectory. May be + * negative. */ + int leftRelief) /* TK_RELIEF_RAISED or TK_RELIEF_SUNKEN: + * indicates how stuff to left of trajectory + * looks relative to stuff on right. */ { XPoint poly[4], b1, b2, newB1, newB2; XPoint perp, c, shift1, shift2; /* Used for handling parallel lines. */ @@ -794,8 +781,8 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, } /* - * If the polygon is already closed, drop the last point from it - * (we'll close it automatically). + * If the polygon is already closed, drop the last point from it (we'll + * close it automatically). */ p1Ptr = &pointPtr[numPoints-1]; @@ -805,8 +792,8 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, } /* - * The loop below is executed once for each vertex in the polgon. - * At the beginning of each iteration things look like this: + * The loop below is executed once for each vertex in the polgon. At the + * beginning of each iteration things look like this: * * poly[1] / * * / @@ -824,23 +811,21 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, * x------------------------- * * The job of this iteration is to do the following: - * (a) Compute x (the border corner corresponding to - * pointPtr[i]) and put it in poly[2]. As part of - * this, compute a new b1 and b2 value for the next - * side of the polygon. + * (a) Compute x (the border corner corresponding to pointPtr[i]) and put + * it in poly[2]. As part of this, compute a new b1 and b2 value for + * the next side of the polygon. * (b) Put pointPtr[i] into poly[3]. * (c) Draw the polygon given by poly[0..3]. - * (d) Advance poly[0], poly[1], b1, and b2 for the - * next side of the polygon. + * (d) Advance poly[0], poly[1], b1, and b2 for the next side of the + * polygon. */ /* - * The above situation doesn't first come into existence until - * two points have been processed; the first two points are - * used to "prime the pump", so some parts of the processing - * are ommitted for these points. The variable "pointsSeen" - * keeps track of the priming process; it has to be separate - * from i in order to be able to ignore duplicate points in the + * The above situation doesn't first come into existence until two points + * have been processed; the first two points are used to "prime the pump", + * so some parts of the processing are ommitted for these points. The + * variable "pointsSeen" keeps track of the priming process; it has to be + * separate from i in order to be able to ignore duplicate points in the * polygon. */ @@ -852,9 +837,10 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, } if ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) { /* - * Ignore duplicate points (they'd cause core dumps in - * ShiftLine calls below). + * Ignore duplicate points (they'd cause core dumps in ShiftLine + * calls below). */ + continue; } ShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1); @@ -866,9 +852,8 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]); /* - * If two consecutive segments of the polygon are parallel, - * then things get more complex. Consider the following - * diagram: + * If two consecutive segments of the polygon are parallel, then + * things get more complex. Consider the following diagram: * * poly[1] * *----b1-----------b2------a @@ -880,16 +865,16 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, * --*--------*----c * newB1 newB2 * - * Instead of using x and *p1Ptr for poly[2] and poly[3], as - * in the original diagram, use a and b as above. Then instead - * of using x and *p1Ptr for the new poly[0] and poly[1], use - * b and c as above. + * Instead of using x and *p1Ptr for poly[2] and poly[3], as in + * the original diagram, use a and b as above. Then instead of + * using x and *p1Ptr for the new poly[0] and poly[1], use b and c + * as above. * * Do the computation in three stages: - * 1. Compute a point "perp" such that the line p1Ptr-perp - * is perpendicular to p1Ptr-p2Ptr. - * 2. Compute the points a and c by intersecting the lines - * b1-b2 and newB1-newB2 with p1Ptr-perp. + * 1. Compute a point "perp" such that the line p1Ptr-perp is + * perpendicular to p1Ptr-p2Ptr. + * 2. Compute the points a and c by intersecting the lines b1-b2 + * and newB1-newB2 with p1Ptr-perp. * 3. Compute b by shifting p1Ptr-perp to the right and * intersecting it with p1Ptr-p2Ptr. */ @@ -955,33 +940,34 @@ Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, */ void -Tk_Fill3DRectangle(tkwin, drawable, border, x, y, width, - height, borderWidth, relief) - Tk_Window tkwin; /* Window for which border was allocated. */ - Drawable drawable; /* X window or pixmap in which to draw. */ - Tk_3DBorder border; /* Token for border to draw. */ - int x, y, width, height; /* Outside area of rectangular region. */ - int borderWidth; /* Desired width for border, in - * pixels. Border will be *inside* region. */ - int relief; /* Indicates 3D effect: TK_RELIEF_FLAT, +Tk_Fill3DRectangle( + Tk_Window tkwin, /* Window for which border was allocated. */ + Drawable drawable, /* X window or pixmap in which to draw. */ + Tk_3DBorder border, /* Token for border to draw. */ + int x, int y, int width, int height, + /* Outside area of rectangular region. */ + int borderWidth, /* Desired width for border, in pixels. Border + * will be *inside* region. */ + int relief) /* Indicates 3D effect: TK_RELIEF_FLAT, * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */ { register TkBorder *borderPtr = (TkBorder *) border; int doubleBorder; /* - * This code is slightly tricky because it only draws the background - * in areas not covered by the 3D border. This avoids flashing - * effects on the screen for the border region. + * This code is slightly tricky because it only draws the background in + * areas not covered by the 3D border. This avoids flashing effects on the + * screen for the border region. */ - + if (relief == TK_RELIEF_FLAT) { borderWidth = 0; } else { /* - * We need to make this extra check, otherwise we will leave - * garbage in thin frames [Bug: 3596] + * We need to make this extra check, otherwise we will leave garbage + * in thin frames [Bug: 3596] */ + if (width < 2*borderWidth) { borderWidth = width/2; } @@ -1020,22 +1006,21 @@ Tk_Fill3DRectangle(tkwin, drawable, border, x, y, width, */ void -Tk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints, - borderWidth, leftRelief) - Tk_Window tkwin; /* Window for which border was allocated. */ - Drawable drawable; /* X window or pixmap in which to draw. */ - Tk_3DBorder border; /* Token for border to draw. */ - XPoint *pointPtr; /* Array of points describing - * polygon. All points must be - * absolute (CoordModeOrigin). */ - int numPoints; /* Number of points at *pointPtr. */ - int borderWidth; /* Width of border, measured in - * pixels to the left of the polygon's - * trajectory. May be negative. */ - int leftRelief; /* Indicates 3D effect of left side of +Tk_Fill3DPolygon( + Tk_Window tkwin, /* Window for which border was allocated. */ + Drawable drawable, /* X window or pixmap in which to draw. */ + Tk_3DBorder border, /* Token for border to draw. */ + XPoint *pointPtr, /* Array of points describing polygon. All + * points must be absolute + * (CoordModeOrigin). */ + int numPoints, /* Number of points at *pointPtr. */ + int borderWidth, /* Width of border, measured in pixels to the + * left of the polygon's trajectory. May be + * negative. */ + int leftRelief) /* Indicates 3D effect of left side of * trajectory relative to right: - * TK_RELIEF_FLAT, TK_RELIEF_RAISED, - * or TK_RELIEF_SUNKEN. */ + * TK_RELIEF_FLAT, TK_RELIEF_RAISED, or + * TK_RELIEF_SUNKEN. */ { register TkBorder *borderPtr = (TkBorder *) border; @@ -1064,8 +1049,8 @@ Tk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints, */ static void -BorderInit(dispPtr) - TkDisplay * dispPtr; /* Used to access thread-specific data. */ +BorderInit( + TkDisplay *dispPtr) /* Used to access thread-specific data. */ { dispPtr->borderInit = 1; Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS); @@ -1076,9 +1061,8 @@ BorderInit(dispPtr) * * ShiftLine -- * - * Given two points on a line, compute a point on a - * new line that is parallel to the given line and - * a given distance away from it. + * Given two points on a line, compute a point on a new line that is + * parallel to the given line and a given distance away from it. * * Results: * None. @@ -1090,36 +1074,31 @@ BorderInit(dispPtr) */ static void -ShiftLine(p1Ptr, p2Ptr, distance, p3Ptr) - XPoint *p1Ptr; /* First point on line. */ - XPoint *p2Ptr; /* Second point on line. */ - int distance; /* New line is to be this many - * units to the left of original - * line, when looking from p1 to - * p2. May be negative. */ - XPoint *p3Ptr; /* Store coords of point on new - * line here. */ +ShiftLine( + XPoint *p1Ptr, /* First point on line. */ + XPoint *p2Ptr, /* Second point on line. */ + int distance, /* New line is to be this many units to the + * left of original line, when looking from p1 + * to p2. May be negative. */ + XPoint *p3Ptr) /* Store coords of point on new line here. */ { int dx, dy, dxNeg, dyNeg; /* - * The table below is used for a quick approximation in - * computing the new point. An index into the table - * is 128 times the slope of the original line (the slope - * must always be between 0 and 1). The value of the table - * entry is 128 times the amount to displace the new line - * in y for each unit of perpendicular distance. In other - * words, the table maps from the tangent of an angle to - * the inverse of its cosine. If the slope of the original - * line is greater than 1, then the displacement is done in - * x rather than in y. + * The table below is used for a quick approximation in computing the new + * point. An index into the table is 128 times the slope of the original + * line (the slope must always be between 0 and 1). The value of the table + * entry is 128 times the amount to displace the new line in y for each + * unit of perpendicular distance. In other words, the table maps from the + * tangent of an angle to the inverse of its cosine. If the slope of the + * original line is greater than 1, then the displacement is done in x + * rather than in y. */ static int shiftTable[129]; /* - * Initialize the table if this is the first time it is - * used. + * Initialize the table if this is the first time it is used. */ if (shiftTable[0] == 0) { @@ -1171,10 +1150,9 @@ ShiftLine(p1Ptr, p2Ptr, distance, p3Ptr) * Find the intersection point between two lines. * * Results: - * Under normal conditions 0 is returned and the point - * at *iPtr is filled in with the intersection between - * the two lines. If the two lines are parallel, then - * -1 is returned and *iPtr isn't modified. + * Under normal conditions 0 is returned and the point at *iPtr is filled + * in with the intersection between the two lines. If the two lines are + * parallel, then -1 is returned and *iPtr isn't modified. * * Side effects: * None. @@ -1183,19 +1161,19 @@ ShiftLine(p1Ptr, p2Ptr, distance, p3Ptr) */ static int -Intersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr) - XPoint *a1Ptr; /* First point of first line. */ - XPoint *a2Ptr; /* Second point of first line. */ - XPoint *b1Ptr; /* First point of second line. */ - XPoint *b2Ptr; /* Second point of second line. */ - XPoint *iPtr; /* Filled in with intersection point. */ +Intersect( + XPoint *a1Ptr, /* First point of first line. */ + XPoint *a2Ptr, /* Second point of first line. */ + XPoint *b1Ptr, /* First point of second line. */ + XPoint *b2Ptr, /* Second point of second line. */ + XPoint *iPtr) /* Filled in with intersection point. */ { int dxadyb, dxbdya, dxadxb, dyadyb, p, q; /* - * The code below is just a straightforward manipulation of two - * equations of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve - * for the x-coordinate of intersection, then the y-coordinate. + * The code below is just a straightforward manipulation of two equations + * of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve for the + * x-coordinate of intersection, then the y-coordinate. */ dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y); @@ -1236,26 +1214,26 @@ Intersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr) * * Tk_Get3DBorderFromObj -- * - * Returns the border referred to by a Tcl object. The border must - * already have been allocated via a call to Tk_Alloc3DBorderFromObj - * or Tk_Get3DBorder. + * Returns the border referred to by a Tcl object. The border must + * already have been allocated via a call to Tk_Alloc3DBorderFromObj or + * Tk_Get3DBorder. * * Results: - * Returns the Tk_3DBorder that matches the tkwin and the string rep - * of the name of the border given in objPtr. + * Returns the Tk_3DBorder that matches the tkwin and the string rep of + * the name of the border given in objPtr. * * Side effects: - * If the object is not already a border, the conversion will free - * any old internal representation. + * If the object is not already a border, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ Tk_3DBorder -Tk_Get3DBorderFromObj(tkwin, objPtr) - Tk_Window tkwin; - Tcl_Obj *objPtr; /* The object whose string value selects - * a border. */ +Tk_Get3DBorderFromObj( + Tk_Window tkwin, + Tcl_Obj *objPtr) /* The object whose string value selects a + * border. */ { TkBorder *borderPtr = NULL; Tcl_HashEntry *hashPtr; @@ -1266,10 +1244,9 @@ Tk_Get3DBorderFromObj(tkwin, objPtr) } /* - * If we are lucky (and the user doesn't use too many different - * displays, screens, or colormaps...) then the TkBorder - * structure we need will be cached in the internal - * representation of the Tcl_Obj. Check it out... + * If we are lucky (and the user doesn't use too many different displays, + * screens, or colormaps...) then the TkBorder structure we need will be + * cached in the internal representation of the Tcl_Obj. Check it out... */ borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1; @@ -1278,22 +1255,22 @@ Tk_Get3DBorderFromObj(tkwin, objPtr) && (Tk_Screen(tkwin) == borderPtr->screen) && (Tk_Colormap(tkwin) == borderPtr->colormap)) { /* - * The object already points to the right border structure. - * Just return it. + * The object already points to the right border structure. Just + * return it. */ + return (Tk_3DBorder) borderPtr; } /* - * If we make it here, it means we aren't so lucky. Either there - * was no cached TkBorder in the Tcl_Obj, or the TkBorder that was - * there is for the wrong screen/colormap. Either way, we have - * to search for the right TkBorder. For each color name, there is - * linked list of TkBorder structures, one structure for each - * screen/colormap combination. The head of the linked list is - * recorded in a hash table (where the key is the color name) - * attached to the TkDisplay structure. Walk this list to find - * the right TkBorder structure. + * If we make it here, it means we aren't so lucky. Either there was no + * cached TkBorder in the Tcl_Obj, or the TkBorder that was there is for + * the wrong screen/colormap. Either way, we have to search for the right + * TkBorder. For each color name, there is linked list of TkBorder + * structures, one structure for each screen/colormap combination. The + * head of the linked list is recorded in a hash table (where the key is + * the color name) attached to the TkDisplay structure. Walk this list to + * find the right TkBorder structure. */ hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, Tcl_GetString(objPtr)); @@ -1305,14 +1282,14 @@ Tk_Get3DBorderFromObj(tkwin, objPtr) if ((Tk_Screen(tkwin) == borderPtr->screen) && (Tk_Colormap(tkwin) == borderPtr->colormap)) { FreeBorderObjProc(objPtr); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) borderPtr; borderPtr->objRefCount++; return (Tk_3DBorder) borderPtr; } } - error: - panic("Tk_Get3DBorderFromObj called with non-existent border!"); + error: + Tcl_Panic("Tk_Get3DBorderFromObj called with non-existent border!"); /* * The following code isn't reached; it's just there to please compilers. */ @@ -1333,20 +1310,20 @@ Tk_Get3DBorderFromObj(tkwin, objPtr) * unless "interp" is NULL. * * Side effects: - * If no error occurs, a blank internal format for a border value - * is intialized. The final form cannot be done without a Tk_Window. + * If no error occurs, a blank internal format for a border value is + * intialized. The final form cannot be done without a Tk_Window. * *---------------------------------------------------------------------- */ static void -InitBorderObj(objPtr) - Tcl_Obj *objPtr; /* The object to convert. */ +InitBorderObj( + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ Tcl_GetString(objPtr); @@ -1355,7 +1332,7 @@ InitBorderObj(objPtr) (*typePtr->freeIntRepProc)(objPtr); } objPtr->typePtr = &tkBorderObjType; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } /* @@ -1363,13 +1340,13 @@ InitBorderObj(objPtr) * * TkDebugBorder -- * - * This procedure returns debugging information about a border. + * This function returns debugging information about a border. * * Results: * The return value is a list with one sublist for each TkBorder - * corresponding to "name". Each sublist has two elements that - * contain the resourceRefCount and objRefCount fields from the - * TkBorder structure. + * corresponding to "name". Each sublist has two elements that contain + * the resourceRefCount and objRefCount fields from the TkBorder + * structure. * * Side effects: * None. @@ -1378,10 +1355,10 @@ InitBorderObj(objPtr) */ Tcl_Obj * -TkDebugBorder(tkwin, name) - Tk_Window tkwin; /* The window in which the border will be - * used (not currently used). */ - char *name; /* Name of the desired color. */ +TkDebugBorder( + Tk_Window tkwin, /* The window in which the border will be used + * (not currently used). */ + char *name) /* Name of the desired color. */ { TkBorder *borderPtr; Tcl_HashEntry *hashPtr; @@ -1393,16 +1370,24 @@ TkDebugBorder(tkwin, name) if (hashPtr != NULL) { borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr); if (borderPtr == NULL) { - panic("TkDebugBorder found empty hash table entry"); + Tcl_Panic("TkDebugBorder found empty hash table entry"); } for ( ; (borderPtr != NULL); borderPtr = borderPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(borderPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(borderPtr->objRefCount)); + Tcl_NewIntObj(borderPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tk3d.h b/generic/tk3d.h index 2905ff5..5e0a0cf 100644 --- a/generic/tk3d.h +++ b/generic/tk3d.h @@ -1,13 +1,12 @@ /* * tk3d.h -- * - * Declarations of types and functions shared by the 3d border - * module. + * Declarations of types and functions shared by the 3d border module. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TK3D @@ -22,9 +21,8 @@ /* * One of the following data structures is allocated for each 3-D border - * currently in use. Structures of this type are indexed by - * borderTable, so that a single structure can be shared for several - * uses. + * currently in use. Structures of this type are indexed by borderTable, so + * that a single structure can be shared for several uses. */ typedef struct TkBorder { @@ -38,18 +36,17 @@ typedef struct TkBorder { int resourceRefCount; /* Number of active uses of this color (each * active use corresponds to a call to * Tk_Alloc3DBorderFromObj or Tk_Get3DBorder). - * If this count is 0, then this structure - * is no longer valid and it isn't present - * in borderTable: it is being kept around - * only because there are objects referring - * to it. The structure is freed when - * resourceRefCount and objRefCount are - * both 0. */ + * If this count is 0, then this structure is + * no longer valid and it isn't present in + * borderTable: it is being kept around only + * because there are objects referring to it. + * The structure is freed when + * resourceRefCount and objRefCount are both + * 0. */ int objRefCount; /* The number of Tcl objects that reference * this structure. */ - XColor *bgColorPtr; /* Background color (intensity - * between lightColorPtr and - * darkColorPtr). */ + XColor *bgColorPtr; /* Background color (intensity between + * lightColorPtr and darkColorPtr). */ XColor *darkColorPtr; /* Color for darker areas (must free when * deleting structure). NULL means shadows * haven't been allocated yet.*/ @@ -57,28 +54,26 @@ typedef struct TkBorder { * (must free this when deleting structure). * NULL means shadows haven't been allocated * yet. */ - Pixmap shadow; /* Stipple pattern to use for drawing - * shadows areas. Used for displays with - * <= 64 colors or where colormap has filled - * up. */ - GC bgGC; /* Used (if necessary) to draw areas in - * the background color. */ - GC darkGC; /* Used to draw darker parts of the - * border. None means the shadow colors - * haven't been allocated yet.*/ - GC lightGC; /* Used to draw lighter parts of - * the border. None means the shadow colors - * haven't been allocated yet. */ - Tcl_HashEntry *hashPtr; /* Entry in borderTable (needed in - * order to delete structure). */ + Pixmap shadow; /* Stipple pattern to use for drawing shadows + * areas. Used for displays with <= 64 colors + * or where colormap has filled up. */ + GC bgGC; /* Used (if necessary) to draw areas in the + * background color. */ + GC darkGC; /* Used to draw darker parts of the border. + * None means the shadow colors haven't been + * allocated yet.*/ + GC lightGC; /* Used to draw lighter parts of the border. + * None means the shadow colors haven't been + * allocated yet. */ + Tcl_HashEntry *hashPtr; /* Entry in borderTable (needed in order to + * delete structure). */ struct TkBorder *nextPtr; /* Points to the next TkBorder structure with - * the same color name. Borders with the - * same name but different screens or - * colormaps are chained together off a - * single entry in borderTable. */ + * the same color name. Borders with the same + * name but different screens or colormaps are + * chained together off a single entry in + * borderTable. */ } TkBorder; - /* * Maximum intensity for a color: */ @@ -89,10 +84,9 @@ typedef struct TkBorder { * Declarations for platform specific interfaces used by this module. */ -EXTERN TkBorder * TkpGetBorder _ANSI_ARGS_((void)); -EXTERN void TkpGetShadows _ANSI_ARGS_((TkBorder *borderPtr, - Tk_Window tkwin)); -EXTERN void TkpFreeBorder _ANSI_ARGS_((TkBorder *borderPtr)); +MODULE_SCOPE TkBorder *TkpGetBorder(void); +MODULE_SCOPE void TkpGetShadows(TkBorder *borderPtr, Tk_Window tkwin); +MODULE_SCOPE void TkpFreeBorder(TkBorder *borderPtr); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tkArgv.c b/generic/tkArgv.c index 4821f41..a338e45 100644 --- a/generic/tkArgv.c +++ b/generic/tkArgv.c @@ -1,85 +1,81 @@ /* * tkArgv.c -- * - * This file contains a procedure that handles table-based - * argv-argc parsing. + * This file contains a function that handles table-based argv-argc + * parsing. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" -#include "tk.h" +#include "tkInt.h" /* - * Default table of argument descriptors. These are normally available - * in every application. + * Default table of argument descriptors. These are normally available in + * every application. */ static Tk_ArgvInfo defaultTable[] = { - {"-help", TK_ARGV_HELP, (char *) NULL, (char *) NULL, + {"-help", TK_ARGV_HELP, NULL, NULL, "Print summary of command-line options and abort"}, - {NULL, TK_ARGV_END, (char *) NULL, (char *) NULL, - (char *) NULL} + {NULL, TK_ARGV_END, NULL, NULL, NULL} }; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static void PrintUsage _ANSI_ARGS_((Tcl_Interp *interp, - Tk_ArgvInfo *argTable, int flags)); +static void PrintUsage(Tcl_Interp *interp, Tk_ArgvInfo *argTable, + int flags); /* *---------------------------------------------------------------------- * * Tk_ParseArgv -- * - * Process an argv array according to a table of expected - * command-line options. See the manual page for more details. + * Process an argv array according to a table of expected command-line + * options. See the manual page for more details. * * Results: - * The return value is a standard Tcl return value. If an - * error occurs then an error message is left in the interp's result. - * Under normal conditions, both *argcPtr and *argv are modified - * to return the arguments that couldn't be processed here (they - * didn't match the option table, or followed an TK_ARGV_REST - * argument). + * The return value is a standard Tcl return value. If an error occurs + * then an error message is left in the interp's result. Under normal + * conditions, both *argcPtr and *argv are modified to return the + * arguments that couldn't be processed here (they didn't match the + * option table, or followed an TK_ARGV_REST argument). * * Side effects: - * Variables may be modified, resources may be entered for tkwin, - * or procedures may be called. It all depends on the arguments - * and their entries in argTable. See the user documentation - * for details. + * Variables may be modified, resources may be entered for tkwin, or + * functions may be called. It all depends on the arguments and their + * entries in argTable. See the user documentation for details. * *---------------------------------------------------------------------- */ int -Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags) - Tcl_Interp *interp; /* Place to store error message. */ - Tk_Window tkwin; /* Window to use for setting Tk options. - * NULL means ignore Tk option specs. */ - int *argcPtr; /* Number of arguments in argv. Modified - * to hold # args left in argv at end. */ - CONST char **argv; /* Array of arguments. Modified to hold - * those that couldn't be processed here. */ - Tk_ArgvInfo *argTable; /* Array of option descriptions */ - int flags; /* Or'ed combination of various flag bits, +Tk_ParseArgv( + Tcl_Interp *interp, /* Place to store error message. */ + Tk_Window tkwin, /* Window to use for setting Tk options. NULL + * means ignore Tk option specs. */ + int *argcPtr, /* Number of arguments in argv. Modified to + * hold # args left in argv at end. */ + CONST char **argv, /* Array of arguments. Modified to hold those + * that couldn't be processed here. */ + Tk_ArgvInfo *argTable, /* Array of option descriptions */ + int flags) /* Or'ed combination of various flag bits, * such as TK_ARGV_NO_DEFAULTS. */ { register Tk_ArgvInfo *infoPtr; - /* Pointer to the current entry in the - * table of argument descriptions. */ + /* Pointer to the current entry in the table + * of argument descriptions. */ Tk_ArgvInfo *matchPtr; /* Descriptor that matches current argument. */ CONST char *curArg; /* Current argument */ register char c; /* Second character of current arg (used for - * quick check for matching; use 2nd char. - * because first char. will almost always - * be '-'). */ + * quick check for matching; use 2nd char. + * because first char. will almost always be + * '-'). */ int srcIndex; /* Location from which to read next argument * from argv. */ int dstIndex; /* Index into argv to which next unused @@ -109,9 +105,8 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags) } /* - * Loop throught the argument descriptors searching for one with - * the matching key string. If found, leave a pointer to it in - * matchPtr. + * Loop throught the argument descriptors searching for one with the + * matching key string. If found, leave a pointer to it in matchPtr. */ matchPtr = NULL; @@ -123,44 +118,43 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags) } for (; (infoPtr != NULL) && (infoPtr->type != TK_ARGV_END); infoPtr++) { - if (infoPtr->key == NULL) { - continue; - } - if ((infoPtr->key[1] != c) - || (strncmp(infoPtr->key, curArg, length) != 0)) { - continue; - } - if ((tkwin == NULL) - && ((infoPtr->type == TK_ARGV_CONST_OPTION) - || (infoPtr->type == TK_ARGV_OPTION_VALUE) - || (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) { - continue; - } - if (infoPtr->key[length] == 0) { - matchPtr = infoPtr; - goto gotMatch; - } - if (flags & TK_ARGV_NO_ABBREV) { - continue; - } - if (matchPtr != NULL) { - Tcl_AppendResult(interp, "ambiguous option \"", curArg, - "\"", (char *) NULL); - return TCL_ERROR; - } - matchPtr = infoPtr; + if (infoPtr->key == NULL) { + continue; + } + if ((infoPtr->key[1] != c) + || (strncmp(infoPtr->key, curArg, length) != 0)) { + continue; + } + if ((tkwin == NULL) + && ((infoPtr->type == TK_ARGV_CONST_OPTION) + || (infoPtr->type == TK_ARGV_OPTION_VALUE) + || (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) { + continue; + } + if (infoPtr->key[length] == 0) { + matchPtr = infoPtr; + goto gotMatch; + } + if (flags & TK_ARGV_NO_ABBREV) { + continue; + } + if (matchPtr != NULL) { + Tcl_AppendResult(interp, "ambiguous option \"", curArg, + "\"", NULL); + return TCL_ERROR; + } + matchPtr = infoPtr; } } if (matchPtr == NULL) { - /* - * Unrecognized argument. Just copy it down, unless the caller + * Unrecognized argument. Just copy it down, unless the caller * prefers an error to be registered. */ if (flags & TK_ARGV_NO_LEFTOVERS) { Tcl_AppendResult(interp, "unrecognized argument \"", - curArg, "\"", (char *) NULL); + curArg, "\"", NULL); return TCL_ERROR; } argv[dstIndex] = curArg; @@ -172,154 +166,143 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags) * Take the appropriate action based on the option type */ - gotMatch: + gotMatch: infoPtr = matchPtr; switch (infoPtr->type) { - case TK_ARGV_CONSTANT: - *((int *) infoPtr->dst) = (int) infoPtr->src; - break; - case TK_ARGV_INT: - if (argc == 0) { - goto missingArg; - } else { - char *endPtr; - - *((int *) infoPtr->dst) = - strtol(argv[srcIndex], &endPtr, 0); - if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { - Tcl_AppendResult(interp, "expected integer argument ", - "for \"", infoPtr->key, "\" but got \"", - argv[srcIndex], "\"", (char *) NULL); - return TCL_ERROR; - } - srcIndex++; - argc--; - } - break; - case TK_ARGV_STRING: - if (argc == 0) { - goto missingArg; - } else { - *((CONST char **)infoPtr->dst) = argv[srcIndex]; - srcIndex++; - argc--; - } - break; - case TK_ARGV_UID: - if (argc == 0) { - goto missingArg; - } else { - *((Tk_Uid *)infoPtr->dst) = Tk_GetUid(argv[srcIndex]); - srcIndex++; - argc--; - } - break; - case TK_ARGV_REST: - *((int *) infoPtr->dst) = dstIndex; - goto argsDone; - case TK_ARGV_FLOAT: - if (argc == 0) { - goto missingArg; - } else { - char *endPtr; - - *((double *) infoPtr->dst) = - strtod(argv[srcIndex], &endPtr); - if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { - Tcl_AppendResult(interp, "expected floating-point ", - "argument for \"", infoPtr->key, - "\" but got \"", argv[srcIndex], "\"", - (char *) NULL); - return TCL_ERROR; - } - srcIndex++; - argc--; - } - break; - case TK_ARGV_FUNC: { - typedef int (ArgvFunc) _ANSI_ARGS_ ((char *, char *, - CONST char *)); - ArgvFunc *handlerProc; + case TK_ARGV_CONSTANT: + *((int *) infoPtr->dst) = PTR2INT(infoPtr->src); + break; + case TK_ARGV_INT: + if (argc == 0) { + goto missingArg; + } else { + char *endPtr; - handlerProc = (ArgvFunc *) infoPtr->src; - if ((*handlerProc)(infoPtr->dst, infoPtr->key, - argv[srcIndex])) { - srcIndex += 1; - argc -= 1; + *((int *) infoPtr->dst) = strtol(argv[srcIndex], &endPtr, 0); + if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { + Tcl_AppendResult(interp,"expected integer argument for \"", + infoPtr->key, "\" but got \"", argv[srcIndex], + "\"", NULL); + return TCL_ERROR; } - break; + srcIndex++; + argc--; + } + break; + case TK_ARGV_STRING: + if (argc == 0) { + goto missingArg; + } + *((CONST char **)infoPtr->dst) = argv[srcIndex]; + srcIndex++; + argc--; + break; + case TK_ARGV_UID: + if (argc == 0) { + goto missingArg; } - case TK_ARGV_GENFUNC: { - typedef int (ArgvGenFunc)_ANSI_ARGS_((char *, Tcl_Interp *, - char *, int, CONST char **)); - ArgvGenFunc *handlerProc; + *((Tk_Uid *)infoPtr->dst) = Tk_GetUid(argv[srcIndex]); + srcIndex++; + argc--; + break; + case TK_ARGV_REST: + *((int *) infoPtr->dst) = dstIndex; + goto argsDone; + case TK_ARGV_FLOAT: + if (argc == 0) { + goto missingArg; + } else { + char *endPtr; - handlerProc = (ArgvGenFunc *) infoPtr->src; - argc = (*handlerProc)(infoPtr->dst, interp, infoPtr->key, - argc, argv+srcIndex); - if (argc < 0) { + *((double *) infoPtr->dst) = strtod(argv[srcIndex], &endPtr); + if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) { + Tcl_AppendResult(interp, "expected floating-point ", + "argument for \"", infoPtr->key, "\" but got \"", + argv[srcIndex], "\"", NULL); return TCL_ERROR; } - break; + srcIndex++; + argc--; } - case TK_ARGV_HELP: - PrintUsage (interp, argTable, flags); - return TCL_ERROR; - case TK_ARGV_CONST_OPTION: - Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src, - TK_INTERACTIVE_PRIO); - break; - case TK_ARGV_OPTION_VALUE: - if (argc < 1) { - goto missingArg; - } - Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex], - TK_INTERACTIVE_PRIO); + break; + case TK_ARGV_FUNC: { + typedef int (ArgvFunc)(char *, char *, CONST char *); + ArgvFunc *handlerProc = (ArgvFunc *) infoPtr->src; + + if ((*handlerProc)(infoPtr->dst, infoPtr->key, argv[srcIndex])) { srcIndex++; argc--; - break; - case TK_ARGV_OPTION_NAME_VALUE: - if (argc < 2) { - Tcl_AppendResult(interp, "\"", curArg, - "\" option requires two following arguments", - (char *) NULL); - return TCL_ERROR; - } - Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1], - TK_INTERACTIVE_PRIO); - srcIndex += 2; - argc -= 2; - break; - default: { - char buf[64 + TCL_INTEGER_SPACE]; - - sprintf(buf, "bad argument type %d in Tk_ArgvInfo", - infoPtr->type); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + break; + } + case TK_ARGV_GENFUNC: { + typedef int (ArgvGenFunc)(char *, Tcl_Interp *, char *, int, + CONST char **); + ArgvGenFunc *handlerProc = (ArgvGenFunc *) infoPtr->src; + + argc = (*handlerProc)(infoPtr->dst, interp, infoPtr->key, + argc, argv+srcIndex); + if (argc < 0) { + return TCL_ERROR; + } + break; + } + case TK_ARGV_HELP: + PrintUsage(interp, argTable, flags); + return TCL_ERROR; + case TK_ARGV_CONST_OPTION: + Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src, + TK_INTERACTIVE_PRIO); + break; + case TK_ARGV_OPTION_VALUE: + if (argc < 1) { + goto missingArg; + } + Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex], + TK_INTERACTIVE_PRIO); + srcIndex++; + argc--; + break; + case TK_ARGV_OPTION_NAME_VALUE: + if (argc < 2) { + Tcl_AppendResult(interp, "\"", curArg, + "\" option requires two following arguments", NULL); return TCL_ERROR; } + Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1], + TK_INTERACTIVE_PRIO); + srcIndex += 2; + argc -= 2; + break; + default: { + char buf[64 + TCL_INTEGER_SPACE]; + + sprintf(buf, "bad argument type %d in Tk_ArgvInfo", infoPtr->type); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_ERROR; + } } } /* - * If we broke out of the loop because of an OPT_REST argument, - * copy the remaining arguments down. + * If we broke out of the loop because of an OPT_REST argument, copy the + * remaining arguments down. */ - argsDone: + argsDone: while (argc) { argv[dstIndex] = argv[srcIndex]; srcIndex++; dstIndex++; argc--; } - argv[dstIndex] = (char *) NULL; + argv[dstIndex] = NULL; *argcPtr = dstIndex; return TCL_OK; - missingArg: + missingArg: Tcl_AppendResult(interp, "\"", curArg, - "\" option requires an additional argument", (char *) NULL); + "\" option requires an additional argument", NULL); return TCL_ERROR; } @@ -331,10 +314,9 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags) * Generate a help string describing command-line options. * * Results: - * The interp's result will be modified to hold a help string - * describing all the options in argTable, plus all those - * in the default table unless TK_ARGV_NO_DEFAULTS is - * specified in flags. + * The interp's result will be modified to hold a help string describing + * all the options in argTable, plus all those in the default table + * unless TK_ARGV_NO_DEFAULTS is specified in flags. * * Side effects: * None. @@ -343,31 +325,29 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags) */ static void -PrintUsage(interp, argTable, flags) - Tcl_Interp *interp; /* Place information in this interp's - * result area. */ - Tk_ArgvInfo *argTable; /* Array of command-specific argument +PrintUsage( + Tcl_Interp *interp, /* Place information in this interp's result + * area. */ + Tk_ArgvInfo *argTable, /* Array of command-specific argument * descriptions. */ - int flags; /* If the TK_ARGV_NO_DEFAULTS bit is set - * in this word, then don't generate - * information for default options. */ + int flags) /* If the TK_ARGV_NO_DEFAULTS bit is set in + * this word, then don't generate information + * for default options. */ { register Tk_ArgvInfo *infoPtr; - int width, i, numSpaces; -#define NUM_SPACES 20 - static char spaces[] = " "; + size_t width, i, numSpaces; char tmp[TCL_DOUBLE_SPACE]; /* - * First, compute the width of the widest option key, so that we - * can make everything line up. + * First, compute the width of the widest option key, so that we can make + * everything line up. */ width = 4; for (i = 0; i < 2; i++) { for (infoPtr = i ? defaultTable : argTable; infoPtr->type != TK_ARGV_END; infoPtr++) { - int length; + size_t length; if (infoPtr->key == NULL) { continue; } @@ -378,59 +358,54 @@ PrintUsage(interp, argTable, flags) } } - Tcl_AppendResult(interp, "Command-specific options:", (char *) NULL); + Tcl_AppendResult(interp, "Command-specific options:", NULL); for (i = 0; ; i++) { for (infoPtr = i ? defaultTable : argTable; infoPtr->type != TK_ARGV_END; infoPtr++) { if ((infoPtr->type == TK_ARGV_HELP) && (infoPtr->key == NULL)) { - Tcl_AppendResult(interp, "\n", infoPtr->help, (char *) NULL); + Tcl_AppendResult(interp, "\n", infoPtr->help, NULL); continue; } - Tcl_AppendResult(interp, "\n ", infoPtr->key, ":", (char *) NULL); + Tcl_AppendResult(interp, "\n ", infoPtr->key, ":", NULL); numSpaces = width + 1 - strlen(infoPtr->key); - while (numSpaces > 0) { - if (numSpaces >= NUM_SPACES) { - Tcl_AppendResult(interp, spaces, (char *) NULL); - } else { - Tcl_AppendResult(interp, spaces+NUM_SPACES-numSpaces, - (char *) NULL); - } - numSpaces -= NUM_SPACES; + while (numSpaces-- > 0) { + Tcl_AppendResult(interp, " ", NULL); } - Tcl_AppendResult(interp, infoPtr->help, (char *) NULL); + Tcl_AppendResult(interp, infoPtr->help, NULL); switch (infoPtr->type) { - case TK_ARGV_INT: { - sprintf(tmp, "%d", *((int *) infoPtr->dst)); - Tcl_AppendResult(interp, "\n\t\tDefault value: ", - tmp, (char *) NULL); - break; - } - case TK_ARGV_FLOAT: { - sprintf(tmp, "%g", *((double *) infoPtr->dst)); - Tcl_AppendResult(interp, "\n\t\tDefault value: ", - tmp, (char *) NULL); - break; - } - case TK_ARGV_STRING: { - char *string; + case TK_ARGV_INT: + sprintf(tmp, "%d", *((int *) infoPtr->dst)); + Tcl_AppendResult(interp, "\n\t\tDefault value: ", tmp, NULL); + break; + case TK_ARGV_FLOAT: + Tcl_PrintDouble(NULL, *((double *) infoPtr->dst), tmp); + Tcl_AppendResult(interp, "\n\t\tDefault value: ", tmp, NULL); + break; + case TK_ARGV_STRING: { + char *string = *((char **) infoPtr->dst); - string = *((char **) infoPtr->dst); - if (string != NULL) { - Tcl_AppendResult(interp, "\n\t\tDefault value: \"", - string, "\"", (char *) NULL); - } - break; - } - default: { - break; + if (string != NULL) { + Tcl_AppendResult(interp, "\n\t\tDefault value: \"", string, + "\"", NULL); } + break; + } + default: + break; } } if ((flags & TK_ARGV_NO_DEFAULTS) || (i > 0)) { break; } - Tcl_AppendResult(interp, "\nGeneric options for all commands:", - (char *) NULL); + Tcl_AppendResult(interp, "\nGeneric options for all commands:", NULL); } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkAtom.c b/generic/tkAtom.c index f94af81..54d3598 100644 --- a/generic/tkAtom.c +++ b/generic/tkAtom.c @@ -1,25 +1,23 @@ -/* +/* * tkAtom.c -- * - * This file manages a cache of X Atoms in order to avoid - * interactions with the X server. It's much like the Xmu - * routines, except it has a cleaner interface (caller - * doesn't have to provide permanent storage for atom names, - * for example). + * This file manages a cache of X Atoms in order to avoid interactions + * with the X server. It's much like the Xmu routines, except it has a + * cleaner interface (caller doesn't have to provide permanent storage + * for atom names, for example). * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* - * The following are a list of the predefined atom strings. - * They should match those found in xatom.h + * The following are a list of the predefined atom strings. They should match + * those found in xatom.h */ static char * atomNameArray[] = { @@ -46,24 +44,24 @@ static char * atomNameArray[] = { "COPYRIGHT", "NOTICE", "FONT_NAME", "FAMILY_NAME", "FULL_NAME", "CAP_HEIGHT", "WM_CLASS", "WM_TRANSIENT_FOR", - (char *) NULL + NULL }; /* - * Forward references to procedures defined in this file: + * Forward references to functions defined in this file: */ -static void AtomInit _ANSI_ARGS_((TkDisplay *dispPtr)); +static void AtomInit(TkDisplay *dispPtr); /* *-------------------------------------------------------------- * * Tk_InternAtom -- * - * Given a string, produce the equivalent X atom. This - * procedure is equivalent to XInternAtom, except that it - * keeps a local cache of atoms. Once a name is known, - * the server need not be contacted again for that name. + * Given a string, produce the equivalent X atom. This function is + * equivalent to XInternAtom, except that it keeps a local cache of + * atoms. Once a name is known, the server need not be contacted again + * for that name. * * Results: * The return value is the Atom corresponding to name. @@ -75,32 +73,31 @@ static void AtomInit _ANSI_ARGS_((TkDisplay *dispPtr)); */ Atom -Tk_InternAtom(tkwin, name) - Tk_Window tkwin; /* Window token; map name to atom - * for this window's display. */ - CONST char *name; /* Name to turn into atom. */ +Tk_InternAtom( + Tk_Window tkwin, /* Window token; map name to atom for this + * window's display. */ + CONST char *name) /* Name to turn into atom. */ { register TkDisplay *dispPtr; register Tcl_HashEntry *hPtr; - int new; + int isNew; dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->atomInit) { AtomInit(dispPtr); } - hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &new); - if (new) { + hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew); + if (isNew) { Tcl_HashEntry *hPtr2; Atom atom; atom = XInternAtom(dispPtr->display, name, False); - Tcl_SetHashValue(hPtr, atom); - hPtr2 = Tcl_CreateHashEntry(&dispPtr->atomTable, (char *) atom, - &new); + Tcl_SetHashValue(hPtr, INT2PTR(atom)); + hPtr2 = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew); Tcl_SetHashValue(hPtr2, Tcl_GetHashKey(&dispPtr->nameTable, hPtr)); } - return (Atom) Tcl_GetHashValue(hPtr); + return (Atom) PTR2INT(Tcl_GetHashValue(hPtr)); } /* @@ -108,16 +105,15 @@ Tk_InternAtom(tkwin, name) * * Tk_GetAtomName -- * - * This procedure is equivalent to XGetAtomName except that - * it uses the local atom cache to avoid contacting the - * server. + * This function is equivalent to XGetAtomName except that it uses the + * local atom cache to avoid contacting the server. * * Results: - * The return value is a character string corresponding to - * the atom given by "atom". This string's storage space - * is static: it need not be freed by the caller, and should - * not be modified by the caller. If "atom" doesn't exist - * on tkwin's display, then the string "?bad atom?" is returned. + * The return value is a character string corresponding to the atom given + * by "atom". This string's storage space is static: it need not be freed + * by the caller, and should not be modified by the caller. If "atom" + * doesn't exist on tkwin's display, then the string "?bad atom?" is + * returned. * * Side effects: * None. @@ -126,11 +122,10 @@ Tk_InternAtom(tkwin, name) */ CONST char * -Tk_GetAtomName(tkwin, atom) - Tk_Window tkwin; /* Window token; map atom to name - * relative to this window's - * display. */ - Atom atom; /* Atom whose name is wanted. */ +Tk_GetAtomName( + Tk_Window tkwin, /* Window token; map atom to name relative to + * this window's display. */ + Atom atom) /* Atom whose name is wanted. */ { register TkDisplay *dispPtr; register Tcl_HashEntry *hPtr; @@ -140,14 +135,14 @@ Tk_GetAtomName(tkwin, atom) AtomInit(dispPtr); } - hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, (char *) atom); + hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, INT2PTR(atom)); if (hPtr == NULL) { char *name; Tk_ErrorHandler handler; - int new, mustFree; + int isNew, mustFree; - handler= Tk_CreateErrorHandler(dispPtr->display, BadAtom, - -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); + handler = Tk_CreateErrorHandler(dispPtr->display, BadAtom, -1, -1, + NULL, (ClientData) NULL); name = XGetAtomName(dispPtr->display, atom); mustFree = 1; if (name == NULL) { @@ -155,15 +150,13 @@ Tk_GetAtomName(tkwin, atom) mustFree = 0; } Tk_DeleteErrorHandler(handler); - hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, (char *) name, - &new); - Tcl_SetHashValue(hPtr, atom); + hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew); + Tcl_SetHashValue(hPtr, INT2PTR(atom)); if (mustFree) { XFree(name); } name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr); - hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, (char *) atom, - &new); + hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew); Tcl_SetHashValue(hPtr, name); } return Tcl_GetHashValue(hPtr); @@ -186,8 +179,8 @@ Tk_GetAtomName(tkwin, atom) */ static void -AtomInit(dispPtr) - register TkDisplay *dispPtr; /* Display to initialize. */ +AtomInit( + register TkDisplay *dispPtr)/* Display to initialize. */ { Tcl_HashEntry *hPtr; Atom atom; @@ -197,19 +190,27 @@ AtomInit(dispPtr) Tcl_InitHashTable(&dispPtr->atomTable, TCL_ONE_WORD_KEYS); for (atom = 1; atom <= XA_LAST_PREDEFINED; atom++) { - hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, (char *) atom); - if (hPtr == NULL) { - char *name; - int new; - - name = atomNameArray[atom - 1]; - hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, (char *) name, - &new); - Tcl_SetHashValue(hPtr, atom); - name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr); - hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, (char *) atom, - &new); - Tcl_SetHashValue(hPtr, name); + char *name; + int isNew; + + hPtr = Tcl_FindHashEntry(&dispPtr->atomTable, INT2PTR(atom)); + if (hPtr != NULL) { + continue; } + + name = atomNameArray[atom - 1]; + hPtr = Tcl_CreateHashEntry(&dispPtr->nameTable, name, &isNew); + Tcl_SetHashValue(hPtr, INT2PTR(atom)); + name = Tcl_GetHashKey(&dispPtr->nameTable, hPtr); + hPtr = Tcl_CreateHashEntry(&dispPtr->atomTable, INT2PTR(atom), &isNew); + Tcl_SetHashValue(hPtr, name); } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkBind.c b/generic/tkBind.c index 3f05ccc..11b2122 100755..100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -1,29 +1,27 @@ -/* +/* * tkBind.c -- * - * This file provides procedures that associate Tcl commands - * with X events or sequences of X events. + * This file provides functions that associate Tcl commands with X events + * or sequences of X events. * * Copyright (c) 1989-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" #ifdef __WIN32__ #include "tkWinInt.h" #endif -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* UNIX */ #include "tkUnixInt.h" #endif - /* * File structure: * @@ -44,111 +42,109 @@ * Non-package-specific helpers. */ - /* - * The following union is used to hold the detail information from an - * XEvent (including Tk's XVirtualEvent extension). + * The following union is used to hold the detail information from an XEvent + * (including Tk's XVirtualEvent extension). */ + typedef union { - KeySym keySym; /* KeySym that corresponds to xkey.keycode. */ - int button; /* Button that was pressed (xbutton.button). */ - Tk_Uid name; /* Tk_Uid of virtual event. */ - ClientData clientData; /* Used when type of Detail is unknown, and to - * ensure that all bytes of Detail are initialized - * when this structure is used in a hash key. */ + KeySym keySym; /* KeySym that corresponds to xkey.keycode. */ + int button; /* Button that was pressed (xbutton.button). */ + Tk_Uid name; /* Tk_Uid of virtual event. */ + ClientData clientData; /* Used when type of Detail is unknown, and to + * ensure that all bytes of Detail are + * initialized when this structure is used in + * a hash key. */ } Detail; /* - * The structure below represents a binding table. A binding table - * represents a domain in which event bindings may occur. It includes - * a space of objects relative to which events occur (usually windows, - * but not always), a history of recent events in the domain, and - * a set of mappings that associate particular Tcl commands with sequences - * of events in the domain. Multiple binding tables may exist at once, - * either because there are multiple applications open, or because there - * are multiple domains within an application with separate event - * bindings for each (for example, each canvas widget has a separate - * binding table for associating events with the items in the canvas). - * - * Note: it is probably a bad idea to reduce EVENT_BUFFER_SIZE much - * below 30. To see this, consider a triple mouse button click while - * the Shift key is down (and auto-repeating). There may be as many - * as 3 auto-repeat events after each mouse button press or release - * (see the first large comment block within Tk_BindEvent for more on - * this), for a total of 20 events to cover the three button presses - * and two intervening releases. If you reduce EVENT_BUFFER_SIZE too - * much, shift multi-clicks will be lost. - * + * The structure below represents a binding table. A binding table represents + * a domain in which event bindings may occur. It includes a space of objects + * relative to which events occur (usually windows, but not always), a history + * of recent events in the domain, and a set of mappings that associate + * particular Tcl commands with sequences of events in the domain. Multiple + * binding tables may exist at once, either because there are multiple + * applications open, or because there are multiple domains within an + * application with separate event bindings for each (for example, each canvas + * widget has a separate binding table for associating events with the items + * in the canvas). + * + * Note: it is probably a bad idea to reduce EVENT_BUFFER_SIZE much below 30. + * To see this, consider a triple mouse button click while the Shift key is + * down (and auto-repeating). There may be as many as 3 auto-repeat events + * after each mouse button press or release (see the first large comment block + * within Tk_BindEvent for more on this), for a total of 20 events to cover + * the three button presses and two intervening releases. If you reduce + * EVENT_BUFFER_SIZE too much, shift multi-clicks will be lost. */ #define EVENT_BUFFER_SIZE 30 typedef struct BindingTable { - XEvent eventRing[EVENT_BUFFER_SIZE];/* Circular queue of recent events - * (higher indices are for more recent - * events). */ - Detail detailRing[EVENT_BUFFER_SIZE];/* "Detail" information (keySym, - * button, Tk_Uid, or 0) for each - * entry in eventRing. */ - int curEvent; /* Index in eventRing of most recent - * event. Newer events have higher - * indices. */ - Tcl_HashTable patternTable; /* Used to map from an event to a - * list of patterns that may match that - * event. Keys are PatternTableKey - * structs, values are (PatSeq *). */ - Tcl_HashTable objectTable; /* Used to map from an object to a - * list of patterns associated with - * that object. Keys are ClientData, - * values are (PatSeq *). */ - Tcl_Interp *interp; /* Interpreter in which commands are - * executed. */ + XEvent eventRing[EVENT_BUFFER_SIZE]; + /* Circular queue of recent events (higher + * indices are for more recent events). */ + Detail detailRing[EVENT_BUFFER_SIZE]; + /* "Detail" information (keySym, button, + * Tk_Uid, or 0) for each entry in + * eventRing. */ + int curEvent; /* Index in eventRing of most recent event. + * Newer events have higher indices. */ + Tcl_HashTable patternTable; /* Used to map from an event to a list of + * patterns that may match that event. Keys + * are PatternTableKey structs, values are + * (PatSeq *). */ + Tcl_HashTable objectTable; /* Used to map from an object to a list of + * patterns associated with that object. Keys + * are ClientData, values are (PatSeq *). */ + Tcl_Interp *interp; /* Interpreter in which commands are + * executed. */ } BindingTable; /* - * The following structure represents virtual event table. A virtual event - * table provides a way to map from platform-specific physical events such - * as button clicks or key presses to virtual events such as <<Paste>>, + * The following structure represents virtual event table. A virtual event + * table provides a way to map from platform-specific physical events such as + * button clicks or key presses to virtual events such as <<Paste>>, * <<Close>>, or <<ScrollWindow>>. * * A virtual event is usually never part of the event stream, but instead is - * synthesized inline by matching low-level events. However, a virtual - * event may be generated by platform-specific code or by Tcl scripts. In - * that case, no lookup of the virtual event will need to be done using - * this table, because the virtual event is actually in the event stream. + * synthesized inline by matching low-level events. However, a virtual event + * may be generated by platform-specific code or by Tcl scripts. In that case, + * no lookup of the virtual event will need to be done using this table, + * because the virtual event is actually in the event stream. */ typedef struct VirtualEventTable { - Tcl_HashTable patternTable; /* Used to map from a physical event to - * a list of patterns that may match that - * event. Keys are PatternTableKey - * structs, values are (PatSeq *). */ - Tcl_HashTable nameTable; /* Used to map a virtual event name to - * the array of physical events that can - * trigger it. Keys are the Tk_Uid names - * of the virtual events, values are - * PhysicalsOwned structs. */ + Tcl_HashTable patternTable; /* Used to map from a physical event to a list + * of patterns that may match that event. Keys + * are PatternTableKey structs, values are + * (PatSeq *). */ + Tcl_HashTable nameTable; /* Used to map a virtual event name to the + * array of physical events that can trigger + * it. Keys are the Tk_Uid names of the + * virtual events, values are PhysicalsOwned + * structs. */ } VirtualEventTable; /* - * The following structure is used as a key in a patternTable for both - * binding tables and a virtual event tables. + * The following structure is used as a key in a patternTable for both binding + * tables and a virtual event tables. * - * In a binding table, the object field corresponds to the binding tag - * for the widget whose bindings are being accessed. + * In a binding table, the object field corresponds to the binding tag for the + * widget whose bindings are being accessed. * - * In a virtual event table, the object field is always NULL. Virtual - * events are a global definiton and are not tied to a particular - * binding tag. + * In a virtual event table, the object field is always NULL. Virtual events + * are a global definiton and are not tied to a particular binding tag. * - * The same key is used for both types of pattern tables so that the - * helper functions that traverse and match patterns will work for both - * binding tables and virtual event tables. + * The same key is used for both types of pattern tables so that the helper + * functions that traverse and match patterns will work for both binding + * tables and virtual event tables. */ + typedef struct PatternTableKey { ClientData object; /* For binding table, identifies the binding * tag of the object (or class of objects) - * relative to which the event occurred. - * For virtual event table, always NULL. */ + * relative to which the event occurred. For + * virtual event table, always NULL. */ int type; /* Type of event (from X). */ Detail detail; /* Additional information, such as keysym, * button, Tk_Uid, or 0 if nothing @@ -162,37 +158,34 @@ typedef struct PatternTableKey { typedef struct Pattern { int eventType; /* Type of X event, e.g. ButtonPress. */ - int needMods; /* Mask of modifiers that must be - * present (0 means no modifiers are - * required). */ - Detail detail; /* Additional information that must - * match event. Normally this is 0, - * meaning no additional information - * must match. For KeyPress and - * KeyRelease events, a keySym may - * be specified to select a - * particular keystroke (0 means any - * keystrokes). For button events, - * specifies a particular button (0 - * means any buttons are OK). For virtual - * events, specifies the Tk_Uid of the + int needMods; /* Mask of modifiers that must be present (0 + * means no modifiers are required). */ + Detail detail; /* Additional information that must match + * event. Normally this is 0, meaning no + * additional information must match. For + * KeyPress and KeyRelease events, a keySym + * may be specified to select a particular + * keystroke (0 means any keystrokes). For + * button events, specifies a particular + * button (0 means any buttons are OK). For + * virtual events, specifies the Tk_Uid of the * virtual event name (never 0). */ } Pattern; /* * The following structure defines a pattern sequence, which consists of one - * or more patterns. In order to trigger, a pattern sequence must match - * the most recent X events (first pattern to most recent event, next - * pattern to next event, and so on). It is used as the hash value in a - * patternTable for both binding tables and virtual event tables. - * - * In a binding table, it is the sequence of physical events that make up - * a binding for an object. - * - * In a virtual event table, it is the sequence of physical events that - * define a virtual event. - * - * The same structure is used for both types of pattern tables so that the + * or more patterns. In order to trigger, a pattern sequence must match the + * most recent X events (first pattern to most recent event, next pattern to + * next event, and so on). It is used as the hash value in a patternTable for + * both binding tables and virtual event tables. + * + * In a binding table, it is the sequence of physical events that make up a + * binding for an object. + * + * In a virtual event table, it is the sequence of physical events that define + * a virtual event. + * + * The same structure is used for both types of pattern tables so that the * helper functions that traverse and match patterns will work for both * binding tables and virtual event tables. */ @@ -200,57 +193,56 @@ typedef struct Pattern { typedef struct PatSeq { int numPats; /* Number of patterns in sequence (usually * 1). */ - TkBindEvalProc *eventProc; /* The procedure that will be invoked on - * the clientData when this pattern sequence + TkBindEvalProc *eventProc; /* The function that will be invoked on the + * clientData when this pattern sequence * matches. */ - TkBindFreeProc *freeProc; /* The procedure that will be invoked to + TkBindFreeProc *freeProc; /* The function that will be invoked to * release the clientData when this pattern * sequence is freed. */ ClientData clientData; /* Arbitray data passed to eventProc and * freeProc when sequence matches. */ int flags; /* Miscellaneous flag values; see below for * definitions. */ - int refCount; /* Number of times that this binding is in - * the midst of executing. If greater than 1, - * then a recursive invocation is happening. - * Only when this is zero can the binding - * actually be freed. */ - struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences - * that have the same initial pattern. NULL - * means end of list. */ - Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the - * initial pattern. This is the head of the - * list of which nextSeqPtr forms a part. */ - struct VirtualOwners *voPtr;/* In a binding table, always NULL. In a + int refCount; /* Number of times that this binding is in the + * midst of executing. If greater than 1, then + * a recursive invocation is happening. Only + * when this is zero can the binding actually + * be freed. */ + struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that + * have the same initial pattern. NULL means + * end of list. */ + Tcl_HashEntry *hPtr; /* Pointer to hash table entry for the initial + * pattern. This is the head of the list of + * which nextSeqPtr forms a part. */ + struct VirtualOwners *voPtr;/* In a binding table, always NULL. In a * virtual event table, identifies the array * of virtual events that can be triggered by * this event. */ - struct PatSeq *nextObjPtr; /* In a binding table, next in list of all + struct PatSeq *nextObjPtr; /* In a binding table, next in list of all * pattern sequences for the same object (NULL - * for end of list). Needed to implement - * Tk_DeleteAllBindings. In a virtual event + * for end of list). Needed to implement + * Tk_DeleteAllBindings. In a virtual event * table, always NULL. */ - Pattern pats[1]; /* Array of "numPats" patterns. Only one + Pattern pats[1]; /* Array of "numPats" patterns. Only one * element is declared here but in actuality - * enough space will be allocated for "numPats" - * patterns. To match, pats[0] must match - * event n, pats[1] must match event n-1, etc. - */ + * enough space will be allocated for + * "numPats" patterns. To match, pats[0] must + * match event n, pats[1] must match event + * n-1, etc. */ } PatSeq; /* * Flag values for PatSeq structures: * - * PAT_NEARBY 1 means that all of the events matching - * this sequence must occur with nearby X - * and Y mouse coordinates and close in time. - * This is typically used to restrict multiple - * button presses. + * PAT_NEARBY 1 means that all of the events matching this sequence + * must occur with nearby X and Y mouse coordinates and + * close in time. This is typically used to restrict + * multiple button presses. * MARKED_DELETED 1 means that this binding has been marked as deleted * and removed from the binding table, but its memory - * could not be released because it was already queued for - * execution. When the binding is actually about to be - * executed, this flag will be checked and the binding + * could not be released because it was already queued + * for execution. When the binding is actually about to + * be executed, this flag will be checked and the binding * skipped if set. */ @@ -258,52 +250,49 @@ typedef struct PatSeq { #define MARKED_DELETED 0x2 /* - * Constants that define how close together two events must be - * in milliseconds or pixels to meet the PAT_NEARBY constraint: + * Constants that define how close together two events must be in milliseconds + * or pixels to meet the PAT_NEARBY constraint: */ #define NEARBY_PIXELS 5 #define NEARBY_MS 500 - /* * The following structure keeps track of all the virtual events that are - * associated with a particular physical event. It is pointed to by the - * voPtr field in a PatSeq in the patternTable of a virtual event table. + * associated with a particular physical event. It is pointed to by the voPtr + * field in a PatSeq in the patternTable of a virtual event table. */ typedef struct VirtualOwners { - int numOwners; /* Number of virtual events to trigger. */ - Tcl_HashEntry *owners[1]; /* Array of pointers to entries in - * nameTable. Enough space will - * actually be allocated for numOwners - * hash entries. */ + int numOwners; /* Number of virtual events to trigger. */ + Tcl_HashEntry *owners[1]; /* Array of pointers to entries in nameTable. + * Enough space will actually be allocated for + * numOwners hash entries. */ } VirtualOwners; /* - * The following structure is used in the nameTable of a virtual event - * table to associate a virtual event with all the physical events that can - * trigger it. + * The following structure is used in the nameTable of a virtual event table + * to associate a virtual event with all the physical events that can trigger + * it. */ typedef struct PhysicalsOwned { - int numOwned; /* Number of physical events owned. */ - PatSeq *patSeqs[1]; /* Array of pointers to physical event - * patterns. Enough space will actually - * be allocated to hold numOwned. */ + int numOwned; /* Number of physical events owned. */ + PatSeq *patSeqs[1]; /* Array of pointers to physical event + * patterns. Enough space will actually be + * allocated to hold numOwned. */ } PhysicalsOwned; /* - * One of the following structures exists for each interpreter. This - * structure keeps track of the current display and screen in the - * interpreter, so that a script can be invoked whenever the display/screen - * changes (the script does things like point tk::Priv at a display-specific - * structure). + * One of the following structures exists for each interpreter. This structure + * keeps track of the current display and screen in the interpreter, so that a + * script can be invoked whenever the display/screen changes (the script does + * things like point tk::Priv at a display-specific structure). */ typedef struct { - TkDisplay *curDispPtr; /* Display for last binding command invoked - * in this application. */ - int curScreenIndex; /* Index of screen for last binding command. */ + TkDisplay *curDispPtr; /* Display for last binding command invoked in + * this application. */ + int curScreenIndex; /* Index of screen for last binding command */ int bindingDepth; /* Number of active instances of Tk_BindEvent * in this application. */ } ScreenInfo; @@ -311,21 +300,21 @@ typedef struct { /* * The following structure is used to keep track of all the C bindings that * are awaiting invocation and whether the window they refer to has been - * destroyed. If the window is destroyed, then all pending callbacks for - * that window will be cancelled. The Tcl bindings will still all be - * invoked, however. + * destroyed. If the window is destroyed, then all pending callbacks for that + * window will be cancelled. The Tcl bindings will still all be invoked, + * however. */ typedef struct PendingBinding { struct PendingBinding *nextPtr; - /* Next in chain of pending bindings, in - * case a recursive binding evaluation is in + /* Next in chain of pending bindings, in case + * a recursive binding evaluation is in * progress. */ Tk_Window tkwin; /* The window that the following bindings * depend upon. */ - int deleted; /* Set to non-zero by window cleanup code - * if tkwin is deleted. */ - PatSeq *matchArray[5]; /* Array of pending C bindings. The actual + int deleted; /* Set to non-zero by window cleanup code if + * tkwin is deleted. */ + PatSeq *matchArray[5]; /* Array of pending C bindings. The actual * size of this depends on how many C bindings * matched the event passed to Tk_BindEvent. * THIS FIELD MUST BE THE LAST IN THE @@ -333,8 +322,8 @@ typedef struct PendingBinding { } PendingBinding; /* - * The following structure keeps track of all the information local to - * the binding package on a per interpreter basis. + * The following structure keeps track of all the information local to the + * binding package on a per interpreter basis. */ typedef struct BindInfo { @@ -342,39 +331,38 @@ typedef struct BindInfo { /* The virtual events that exist in this * interpreter. */ ScreenInfo screenInfo; /* Keeps track of the current display and - * screen, so it can be restored after - * a binding has executed. */ + * screen, so it can be restored after a + * binding has executed. */ PendingBinding *pendingList;/* The list of pending C bindings, kept in * case a C or Tcl binding causes the target * window to be deleted. */ - int deleted; /* 1 the application has been deleted but - * the structure has been preserved. */ + int deleted; /* 1 the application has been deleted but the + * structure has been preserved. */ } BindInfo; - + /* - * In X11R4 and earlier versions, XStringToKeysym is ridiculously - * slow. The data structure and hash table below, along with the - * code that uses them, implement a fast mapping from strings to - * keysyms. In X11R5 and later releases XStringToKeysym is plenty - * fast so this stuff isn't needed. The #define REDO_KEYSYM_LOOKUP - * is normally undefined, so that XStringToKeysym gets used. It - * can be set in the Makefile to enable the use of the hash table - * below. + * In X11R4 and earlier versions, XStringToKeysym is ridiculously slow. The + * data structure and hash table below, along with the code that uses them, + * implement a fast mapping from strings to keysyms. In X11R5 and later + * releases XStringToKeysym is plenty fast so this stuff isn't needed. The + * #define REDO_KEYSYM_LOOKUP is normally undefined, so that XStringToKeysym + * gets used. It can be set in the Makefile to enable the use of the hash + * table below. */ #ifdef REDO_KEYSYM_LOOKUP typedef struct { - char *name; /* Name of keysym. */ - KeySym value; /* Numeric identifier for keysym. */ + char *name; /* Name of keysym. */ + KeySym value; /* Numeric identifier for keysym. */ } KeySymInfo; static KeySymInfo keyArray[] = { #ifndef lint #include "ks_names.h" #endif - {(char *) NULL, 0} + {NULL, 0} }; -static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */ -static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */ +static Tcl_HashTable keySymTable; /* keyArray hashed by keysym value. */ +static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */ #endif /* REDO_KEYSYM_LOOKUP */ /* @@ -386,16 +374,17 @@ static int initialized = 0; TCL_DECLARE_MUTEX(bindMutex) /* - * A hash table is kept to map from the string names of event - * modifiers to information about those modifiers. The structure - * for storing this information, and the hash table built at - * initialization time, are defined below. + * A hash table is kept to map from the string names of event modifiers to + * information about those modifiers. The structure for storing this + * information, and the hash table built at initialization time, are defined + * below. */ typedef struct { char *name; /* Name of modifier. */ - int mask; /* Button/modifier mask value, * such as Button1Mask. */ - int flags; /* Various flags; see below for + int mask; /* Button/modifier mask value, such as + * Button1Mask. */ + int flags; /* Various flags; see below for * definitions. */ } ModInfo; @@ -423,6 +412,7 @@ static ModInfo modArray[] = { {"Meta", META_MASK, 0}, {"M", META_MASK, 0}, {"Alt", ALT_MASK, 0}, + {"Extended", EXTENDED_MASK, 0}, {"B1", Button1Mask, 0}, {"Button1", Button1Mask, 0}, {"B2", Button2Mask, 0}, @@ -448,32 +438,29 @@ static ModInfo modArray[] = { {"Double", 0, DOUBLE}, {"Triple", 0, TRIPLE}, {"Quadruple", 0, QUADRUPLE}, - {"Any", 0, 0}, /* Ignored: historical relic. */ + {"Any", 0, 0}, /* Ignored: historical relic */ {NULL, 0, 0} }; static Tcl_HashTable modTable; /* - * This module also keeps a hash table mapping from event names - * to information about those events. The structure, an array - * to use to initialize the hash table, and the hash table are - * all defined below. + * This module also keeps a hash table mapping from event names to information + * about those events. The structure, an array to use to initialize the hash + * table, and the hash table are all defined below. */ typedef struct { char *name; /* Name of event. */ - int type; /* Event type for X, such as - * ButtonPress. */ - int eventMask; /* Mask bits (for XSelectInput) - * for this event type. */ + int type; /* Event type for X, such as ButtonPress. */ + int eventMask; /* Mask bits (for XSelectInput) for this event + * type. */ } EventInfo; /* - * Note: some of the masks below are an OR-ed combination of - * several masks. This is necessary because X doesn't report - * up events unless you also ask for down events. Also, X - * doesn't report button state in motion events unless you've - * asked about button events. + * Note: some of the masks below are an OR-ed combination of several masks. + * This is necessary because X doesn't report up events unless you also ask + * for down events. Also, X doesn't report button state in motion events + * unless you've asked about button events. */ static EventInfo eventArray[] = { @@ -507,18 +494,18 @@ static EventInfo eventArray[] = { {"CirculateRequest", CirculateRequest, SubstructureRedirectMask}, {"ConfigureRequest", ConfigureRequest, SubstructureRedirectMask}, {"Create", CreateNotify, SubstructureNotifyMask}, - {"MapRequest", MapRequest, SubstructureRedirectMask}, + {"MapRequest", MapRequest, SubstructureRedirectMask}, {"ResizeRequest", ResizeRequest, ResizeRedirectMask}, - {(char *) NULL, 0, 0} + {NULL, 0, 0} }; static Tcl_HashTable eventTable; /* - * The defines and table below are used to classify events into - * various groups. The reason for this is that logically identical - * fields (e.g. "state") appear at different places in different - * types of events. The classification masks can be used to figure - * out quickly where to extract information from events. + * The defines and table below are used to classify events into various + * groups. The reason for this is that logically identical fields (e.g. + * "state") appear at different places in different types of events. The + * classification masks can be used to figure out quickly where to extract + * information from events. */ #define KEY 0x1 @@ -546,7 +533,7 @@ static Tcl_HashTable eventTable; #define CIRCREQ 0x400000 #define KEY_BUTTON_MOTION_VIRTUAL (KEY|BUTTON|MOTION|VIRTUAL) -#define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|CROSSING|VIRTUAL) +#define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|VIRTUAL|CROSSING) static int flagArray[TK_LASTEVENT] = { /* Not used */ 0, @@ -585,18 +572,17 @@ static int flagArray[TK_LASTEVENT] = { /* ClientMessage */ 0, /* MappingNotify */ 0, /* VirtualEvent */ VIRTUAL, - /* Activate */ ACTIVATE, + /* Activate */ ACTIVATE, /* Deactivate */ ACTIVATE, /* MouseWheel */ KEY }; /* - * The following table is used to map between the location where an - * generated event should be queued and the string used to specify the - * location. + * The following table is used to map between the location where an generated + * event should be queued and the string used to specify the location. */ - -static TkStateMap queuePosition[] = { + +static const TkStateMap queuePosition[] = { {-1, "now"}, {TCL_QUEUE_HEAD, "head"}, {TCL_QUEUE_MARK, "mark"}, @@ -605,13 +591,13 @@ static TkStateMap queuePosition[] = { }; /* - * The following tables are used as a two-way map between X's internal - * numeric values for fields in an XEvent and the strings used in Tcl. The - * tables are used both when constructing an XEvent from user input and - * when providing data from an XEvent to the user. + * The following tables are used as a two-way map between X's internal numeric + * values for fields in an XEvent and the strings used in Tcl. The tables are + * used both when constructing an XEvent from user input and when providing + * data from an XEvent to the user. */ -static TkStateMap notifyMode[] = { +static const TkStateMap notifyMode[] = { {NotifyNormal, "NotifyNormal"}, {NotifyGrab, "NotifyGrab"}, {NotifyUngrab, "NotifyUngrab"}, @@ -619,7 +605,7 @@ static TkStateMap notifyMode[] = { {-1, NULL} }; -static TkStateMap notifyDetail[] = { +static const TkStateMap notifyDetail[] = { {NotifyAncestor, "NotifyAncestor"}, {NotifyVirtual, "NotifyVirtual"}, {NotifyInferior, "NotifyInferior"}, @@ -631,20 +617,20 @@ static TkStateMap notifyDetail[] = { {-1, NULL} }; -static TkStateMap circPlace[] = { +static const TkStateMap circPlace[] = { {PlaceOnTop, "PlaceOnTop"}, {PlaceOnBottom, "PlaceOnBottom"}, {-1, NULL} }; -static TkStateMap visNotify[] = { - {VisibilityUnobscured, "VisibilityUnobscured"}, - {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"}, - {VisibilityFullyObscured, "VisibilityFullyObscured"}, +static const TkStateMap visNotify[] = { + {VisibilityUnobscured, "VisibilityUnobscured"}, + {VisibilityPartiallyObscured, "VisibilityPartiallyObscured"}, + {VisibilityFullyObscured, "VisibilityFullyObscured"}, {-1, NULL} }; -static TkStateMap configureRequestDetail[] = { +static const TkStateMap configureRequestDetail[] = { {None, "None"}, {Above, "Above"}, {Below, "Below"}, @@ -654,79 +640,71 @@ static TkStateMap configureRequestDetail[] = { {-1, NULL} }; -static TkStateMap propNotify[] = { +static const TkStateMap propNotify[] = { {PropertyNewValue, "NewValue"}, {PropertyDelete, "Delete"}, {-1, NULL} }; /* - * Prototypes for local procedures defined in this file: + * Prototypes for local functions defined in this file: */ -static void ChangeScreen _ANSI_ARGS_((Tcl_Interp *interp, - char *dispName, int screenIndex)); -static int CreateVirtualEvent _ANSI_ARGS_((Tcl_Interp *interp, +static void ChangeScreen(Tcl_Interp *interp, char *dispName, + int screenIndex); +static int CreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, char *virtString, - char *eventString)); -static int DeleteVirtualEvent _ANSI_ARGS_((Tcl_Interp *interp, + char *eventString); +static int DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, char *virtString, - char *eventString)); -static void DeleteVirtualEventTable _ANSI_ARGS_(( - VirtualEventTable *vetPtr)); -static void ExpandPercents _ANSI_ARGS_((TkWindow *winPtr, - CONST char *before, XEvent *eventPtr, KeySym keySym, - Tcl_DString *dsPtr)); -static void FreeTclBinding _ANSI_ARGS_((ClientData clientData)); -static PatSeq * FindSequence _ANSI_ARGS_((Tcl_Interp *interp, + char *eventString); +static void DeleteVirtualEventTable(VirtualEventTable *vetPtr); +static void ExpandPercents(TkWindow *winPtr, const char *before, + XEvent *eventPtr,KeySym keySym,Tcl_DString *dsPtr); +static void FreeTclBinding(ClientData clientData); +static PatSeq * FindSequence(Tcl_Interp *interp, Tcl_HashTable *patternTablePtr, ClientData object, - CONST char *eventString, int create, - int allowVirtual, unsigned long *maskPtr)); -static void GetAllVirtualEvents _ANSI_ARGS_((Tcl_Interp *interp, - VirtualEventTable *vetPtr)); -static char * GetField _ANSI_ARGS_((char *p, char *copy, int size)); -static void GetPatternString _ANSI_ARGS_((PatSeq *psPtr, - Tcl_DString *dsPtr)); -static int GetVirtualEvent _ANSI_ARGS_((Tcl_Interp *interp, - VirtualEventTable *vetPtr, char *virtString)); -static Tk_Uid GetVirtualEventUid _ANSI_ARGS_((Tcl_Interp *interp, - char *virtString)); -static int HandleEventGenerate _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window main, int objc, - Tcl_Obj *CONST objv[])); -static void InitVirtualEventTable _ANSI_ARGS_(( - VirtualEventTable *vetPtr)); -static PatSeq * MatchPatterns _ANSI_ARGS_((TkDisplay *dispPtr, + const char *eventString, int create, + int allowVirtual, unsigned long *maskPtr); +static void GetAllVirtualEvents(Tcl_Interp *interp, + VirtualEventTable *vetPtr); +static char * GetField(char *p, char *copy, int size); +static void GetPatternString(PatSeq *psPtr, Tcl_DString *dsPtr); +static int GetVirtualEvent(Tcl_Interp *interp, + VirtualEventTable *vetPtr, char *virtString); +static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp, + char *virtString); +static int HandleEventGenerate(Tcl_Interp *interp, Tk_Window main, + int objc, Tcl_Obj *const objv[]); +static void InitVirtualEventTable(VirtualEventTable *vetPtr); +static PatSeq * MatchPatterns(TkDisplay *dispPtr, BindingTable *bindPtr, PatSeq *psPtr, PatSeq *bestPtr, ClientData *objectPtr, - PatSeq **sourcePtrPtr)); -static int NameToWindow _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window main, Tcl_Obj *objPtr, - Tk_Window *tkwinPtr)); -static int ParseEventDescription _ANSI_ARGS_((Tcl_Interp *interp, - CONST char **eventStringPtr, Pattern *patPtr, - unsigned long *eventMaskPtr)); -static void DoWarp _ANSI_ARGS_((ClientData clientData)); + PatSeq **sourcePtrPtr); +static int NameToWindow(Tcl_Interp *interp, Tk_Window main, + Tcl_Obj *objPtr, Tk_Window *tkwinPtr); +static int ParseEventDescription(Tcl_Interp *interp, + const char **eventStringPtr, Pattern *patPtr, + unsigned long *eventMaskPtr); +static void DoWarp(ClientData clientData); /* - * The following define is used as a short circuit for the callback - * procedure to evaluate a TclBinding. The actual evaluation of the - * binding is handled inline, because special things have to be done - * with a Tcl binding before evaluation time. + * The following define is used as a short circuit for the callback function + * to evaluate a TclBinding. The actual evaluation of the binding is handled + * inline, because special things have to be done with a Tcl binding before + * evaluation time. */ #define EvalTclBinding ((TkBindEvalProc *) 1) - /* *--------------------------------------------------------------------------- * * TkBindInit -- * - * This procedure is called when an application is created. It - * initializes all the structures used by bindings and virtual - * events. It must be called before any other functions in this - * file are called. + * This function is called when an application is created. It initializes + * all the structures used by bindings and virtual events. It must be + * called before any other functions in this file are called. * * Results: * None. @@ -738,39 +716,37 @@ static void DoWarp _ANSI_ARGS_((ClientData clientData)); */ void -TkBindInit(mainPtr) - TkMainInfo *mainPtr; /* The newly created application. */ +TkBindInit( + TkMainInfo *mainPtr) /* The newly created application. */ { BindInfo *bindInfoPtr; if (sizeof(XEvent) < sizeof(XVirtualEvent)) { - panic("TkBindInit: virtual events can't be supported"); + Tcl_Panic("TkBindInit: virtual events can't be supported"); } /* - * Initialize the static data structures used by the binding package. - * They are only initialized once, no matter how many interps are - * created. + * Initialize the static data structures used by the binding package. They + * are only initialized once, no matter how many interps are created. */ if (!initialized) { - Tcl_MutexLock(&bindMutex); + Tcl_MutexLock(&bindMutex); if (!initialized) { Tcl_HashEntry *hPtr; ModInfo *modPtr; EventInfo *eiPtr; int newEntry; - #ifdef REDO_KEYSYM_LOOKUP KeySymInfo *kPtr; Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS); Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS); for (kPtr = keyArray; kPtr->name != NULL; kPtr++) { - hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &newEntry); + hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &newEntry); Tcl_SetHashValue(hPtr, kPtr->value); hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, - &newEntry); + &newEntry); if (newEntry) { Tcl_SetHashValue(hPtr, kPtr->name); } @@ -779,18 +755,18 @@ TkBindInit(mainPtr) Tcl_InitHashTable(&modTable, TCL_STRING_KEYS); for (modPtr = modArray; modPtr->name != NULL; modPtr++) { - hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &newEntry); + hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &newEntry); Tcl_SetHashValue(hPtr, modPtr); } - + Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS); for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) { - hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry); + hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &newEntry); Tcl_SetHashValue(hPtr, eiPtr); } initialized = 1; } - Tcl_MutexUnlock(&bindMutex); + Tcl_MutexUnlock(&bindMutex); } mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp); @@ -812,8 +788,8 @@ TkBindInit(mainPtr) * * TkBindFree -- * - * This procedure is called when an application is deleted. It - * deletes all the structures used by bindings and virtual events. + * This function is called when an application is deleted. It deletes all + * the structures used by bindings and virtual events. * * Results: * None. @@ -825,11 +801,11 @@ TkBindInit(mainPtr) */ void -TkBindFree(mainPtr) - TkMainInfo *mainPtr; /* The newly created application. */ +TkBindFree( + TkMainInfo *mainPtr) /* The newly created application. */ { BindInfo *bindInfoPtr; - + Tk_DeleteBindingTable(mainPtr->bindingTable); mainPtr->bindingTable = NULL; @@ -848,8 +824,8 @@ TkBindFree(mainPtr) * Set up a new domain in which event bindings may be created. * * Results: - * The return value is a token for the new table, which must - * be passed to procedures like Tk_CreateBinding. + * The return value is a token for the new table, which must be passed to + * functions like Tk_CreateBinding. * * Side effects: * Memory is allocated for the new table. @@ -858,9 +834,9 @@ TkBindFree(mainPtr) */ Tk_BindingTable -Tk_CreateBindingTable(interp) - Tcl_Interp *interp; /* Interpreter to associate with the binding - * table: commands are executed in this +Tk_CreateBindingTable( + Tcl_Interp *interp) /* Interpreter to associate with the binding + * table: commands are executed in this * interpreter. */ { BindingTable *bindPtr; @@ -887,9 +863,8 @@ Tk_CreateBindingTable(interp) * * Tk_DeleteBindingTable -- * - * Destroy a binding table and free up all its memory. - * The caller should not use bindingTable again after - * this procedure returns. + * Destroy a binding table and free up all its memory. The caller should + * not use bindingTable again after this function returns. * * Results: * None. @@ -901,9 +876,9 @@ Tk_CreateBindingTable(interp) */ void -Tk_DeleteBindingTable(bindingTable) - Tk_BindingTable bindingTable; /* Token for the binding table to - * destroy. */ +Tk_DeleteBindingTable( + Tk_BindingTable bindingTable) + /* Token for the binding table to destroy. */ { BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr, *nextPtr; @@ -911,8 +886,7 @@ Tk_DeleteBindingTable(bindingTable) Tcl_HashSearch search; /* - * Find and delete all of the patterns associated with the binding - * table. + * Find and delete all of the patterns associated with the binding table. */ for (hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); @@ -931,8 +905,7 @@ Tk_DeleteBindingTable(bindingTable) } /* - * Clean up the rest of the information associated with the - * binding table. + * Clean up the rest of the information associated with the binding table. */ Tcl_DeleteHashTable(&bindPtr->patternTable); @@ -945,41 +918,39 @@ Tk_DeleteBindingTable(bindingTable) * * Tk_CreateBinding -- * - * Add a binding to a binding table, so that future calls to - * Tk_BindEvent may execute the command in the binding. + * Add a binding to a binding table, so that future calls to Tk_BindEvent + * may execute the command in the binding. * * Results: - * The return value is 0 if an error occurred while setting - * up the binding. In this case, an error message will be - * left in the interp's result. If all went well then the return - * value is a mask of the event types that must be made - * available to Tk_BindEvent in order to properly detect when - * this binding triggers. This value can be used to determine + * The return value is 0 if an error occurred while setting up the + * binding. In this case, an error message will be left in the interp's + * result. If all went well then the return value is a mask of the event + * types that must be made available to Tk_BindEvent in order to properly + * detect when this binding triggers. This value can be used to determine * what events to select for in a window, for example. * * Side effects: - * An existing binding on the same event sequence may be - * replaced. - * The new binding may cause future calls to Tk_BindEvent to - * behave differently than they did previously. + * An existing binding on the same event sequence may be replaced. The + * new binding may cause future calls to Tk_BindEvent to behave + * differently than they did previously. * *-------------------------------------------------------------- */ unsigned long -Tk_CreateBinding(interp, bindingTable, object, eventString, command, append) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_BindingTable bindingTable; +Tk_CreateBinding( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_BindingTable bindingTable, /* Table in which to create binding. */ - ClientData object; /* Token for object with which binding is + ClientData object, /* Token for object with which binding is * associated. */ - CONST char *eventString; /* String describing event sequence that + const char *eventString, /* String describing event sequence that * triggers binding. */ - CONST char *command; /* Contains Tcl command to execute when + const char *command, /* Contains Tcl command to execute when * binding triggers. */ - int append; /* 0 means replace any existing binding for + int append) /* 0 means replace any existing binding for * eventString; 1 means append to that - * binding. If the existing binding is for a + * binding. If the existing binding is for a * callback function and not a Tcl command * string, the existing binding will always be * replaced. */ @@ -987,27 +958,30 @@ Tk_CreateBinding(interp, bindingTable, object, eventString, command, append) BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr; unsigned long eventMask; - char *new, *old; + char *newStr, *oldStr; + if (!*command) { + /* Silently ignore empty scripts -- see SF#3006842 */ + return 1; + } psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString, 1, 1, &eventMask); if (psPtr == NULL) { return 0; } if (psPtr->eventProc == NULL) { - int new; + int isNew; Tcl_HashEntry *hPtr; - + /* - * This pattern sequence was just created. - * Link the pattern into the list associated with the object, so - * that if the object goes away, these bindings will all - * automatically be deleted. + * This pattern sequence was just created. Link the pattern into the + * list associated with the object, so that if the object goes away, + * these bindings will all automatically be deleted. */ hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, - &new); - if (new) { + &isNew); + if (isNew) { psPtr->nextObjPtr = NULL; } else { psPtr->nextObjPtr = (PatSeq *) Tcl_GetHashValue(hPtr); @@ -1025,23 +999,23 @@ Tk_CreateBinding(interp, bindingTable, object, eventString, command, append) append = 0; } - old = (char *) psPtr->clientData; - if ((append != 0) && (old != NULL)) { - int length; + oldStr = (char *) psPtr->clientData; + if ((append != 0) && (oldStr != NULL)) { + size_t length; - length = strlen(old) + strlen(command) + 2; - new = (char *) ckalloc((unsigned) length); - sprintf(new, "%s\n%s", old, command); + length = strlen(oldStr) + strlen(command) + 2; + newStr = (char *) ckalloc((unsigned) length); + sprintf(newStr, "%s\n%s", oldStr, command); } else { - new = (char *) ckalloc((unsigned) strlen(command) + 1); - strcpy(new, command); + newStr = (char *) ckalloc((unsigned) strlen(command) + 1); + strcpy(newStr, command); } - if (old != NULL) { - ckfree(old); + if (oldStr != NULL) { + ckfree(oldStr); } psPtr->eventProc = EvalTclBinding; psPtr->freeProc = FreeTclBinding; - psPtr->clientData = (ClientData) new; + psPtr->clientData = (ClientData) newStr; return eventMask; } @@ -1051,39 +1025,37 @@ Tk_CreateBinding(interp, bindingTable, object, eventString, command, append) * TkCreateBindingProcedure -- * * Add a C binding to a binding table, so that future calls to - * Tk_BindEvent may callback the procedure in the binding. + * Tk_BindEvent may callback the function in the binding. * * Results: - * The return value is 0 if an error occurred while setting - * up the binding. In this case, an error message will be - * left in the interp's result. If all went well then the return - * value is a mask of the event types that must be made - * available to Tk_BindEvent in order to properly detect when - * this binding triggers. This value can be used to determine + + * The return value is 0 if an error occurred while setting up the + * binding. In this case, an error message will be left in the interp's + * result. If all went well then the return value is a mask of the event + * types that must be made available to Tk_BindEvent in order to properly + * detect when this binding triggers. This value can be used to determine * what events to select for in a window, for example. * * Side effects: - * Any existing binding on the same event sequence will be - * replaced. + * Any existing binding on the same event sequence will be replaced. * *--------------------------------------------------------------------------- */ unsigned long -TkCreateBindingProcedure(interp, bindingTable, object, eventString, - eventProc, freeProc, clientData) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_BindingTable bindingTable; +TkCreateBindingProcedure( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_BindingTable bindingTable, /* Table in which to create binding. */ - ClientData object; /* Token for object with which binding is + ClientData object, /* Token for object with which binding is * associated. */ - CONST char *eventString; /* String describing event sequence that + const char *eventString, /* String describing event sequence that * triggers binding. */ - TkBindEvalProc *eventProc; /* Procedure to invoke when binding - * triggers. Must not be NULL. */ - TkBindFreeProc *freeProc; /* Procedure to invoke when binding is - * freed. May be NULL for no procedure. */ - ClientData clientData; /* Arbitrary ClientData to pass to eventProc + TkBindEvalProc *eventProc, /* Function to invoke when binding triggers. + * Must not be NULL. */ + TkBindFreeProc *freeProc, /* Function to invoke when binding is freed. + * May be NULL for no function. */ + ClientData clientData) /* Arbitrary ClientData to pass to eventProc * and freeProc. */ { BindingTable *bindPtr = (BindingTable *) bindingTable; @@ -1096,26 +1068,24 @@ TkCreateBindingProcedure(interp, bindingTable, object, eventString, return 0; } if (psPtr->eventProc == NULL) { - int new; + int isNew; Tcl_HashEntry *hPtr; - + /* - * This pattern sequence was just created. - * Link the pattern into the list associated with the object, so - * that if the object goes away, these bindings will all - * automatically be deleted. + * This pattern sequence was just created. Link the pattern into the + * list associated with the object, so that if the object goes away, + * these bindings will all automatically be deleted. */ hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, - &new); - if (new) { + &isNew); + if (isNew) { psPtr->nextObjPtr = NULL; } else { psPtr->nextObjPtr = (PatSeq *) Tcl_GetHashValue(hPtr); } Tcl_SetHashValue(hPtr, psPtr); } else { - /* * Free existing callback. */ @@ -1139,24 +1109,25 @@ TkCreateBindingProcedure(interp, bindingTable, object, eventString, * Remove an event binding from a binding table. * * Results: - * The result is a standard Tcl return value. If an error - * occurs then the interp's result will contain an error message. + * The result is a standard Tcl return value. If an error occurs then the + * interp's result will contain an error message. * * Side effects: - * The binding given by object and eventString is removed - * from bindingTable. + * The binding given by object and eventString is removed from + * bindingTable. * *-------------------------------------------------------------- */ int -Tk_DeleteBinding(interp, bindingTable, object, eventString) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_BindingTable bindingTable; /* Table in which to delete binding. */ - ClientData object; /* Token for object with which binding - * is associated. */ - CONST char *eventString; /* String describing event sequence - * that triggers binding. */ +Tk_DeleteBinding( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_BindingTable bindingTable, + /* Table in which to delete binding. */ + ClientData object, /* Token for object with which binding is + * associated. */ + const char *eventString) /* String describing event sequence that + * triggers binding. */ { BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr, *prevPtr; @@ -1171,13 +1142,13 @@ Tk_DeleteBinding(interp, bindingTable, object, eventString) } /* - * Unlink the binding from the list for its object, then from the - * list for its pattern. + * Unlink the binding from the list for its object, then from the list for + * its pattern. */ hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object); if (hPtr == NULL) { - panic("Tk_DeleteBinding couldn't find object table entry"); + Tcl_Panic("Tk_DeleteBinding couldn't find object table entry"); } prevPtr = (PatSeq *) Tcl_GetHashValue(hPtr); if (prevPtr == psPtr) { @@ -1185,7 +1156,7 @@ Tk_DeleteBinding(interp, bindingTable, object, eventString) } else { for ( ; ; prevPtr = prevPtr->nextObjPtr) { if (prevPtr == NULL) { - panic("Tk_DeleteBinding couldn't find on object list"); + Tcl_Panic("Tk_DeleteBinding couldn't find on object list"); } if (prevPtr->nextObjPtr == psPtr) { prevPtr->nextObjPtr = psPtr->nextObjPtr; @@ -1203,7 +1174,7 @@ Tk_DeleteBinding(interp, bindingTable, object, eventString) } else { for ( ; ; prevPtr = prevPtr->nextSeqPtr) { if (prevPtr == NULL) { - panic("Tk_DeleteBinding couldn't find on hash chain"); + Tcl_Panic("Tk_DeleteBinding couldn't find on hash chain"); } if (prevPtr->nextSeqPtr == psPtr) { prevPtr->nextSeqPtr = psPtr->nextSeqPtr; @@ -1230,13 +1201,12 @@ Tk_DeleteBinding(interp, bindingTable, object, eventString) * Return the command associated with a given event string. * * Results: - * The return value is a pointer to the command string - * associated with eventString for object in the domain - * given by bindingTable. If there is no binding for - * eventString, or if eventString is improperly formed, - * then NULL is returned and an error message is left in - * the interp's result. The return value is semi-static: it - * will persist until the binding is changed or deleted. + * The return value is a pointer to the command string associated with + * eventString for object in the domain given by bindingTable. If there + * is no binding for eventString, or if eventString is improperly formed, + * then NULL is returned and an error message is left in the interp's + * result. The return value is semi-static: it will persist until the + * binding is changed or deleted. * * Side effects: * None. @@ -1244,15 +1214,15 @@ Tk_DeleteBinding(interp, bindingTable, object, eventString) *-------------------------------------------------------------- */ -CONST char * -Tk_GetBinding(interp, bindingTable, object, eventString) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_BindingTable bindingTable; /* Table in which to look for - * binding. */ - ClientData object; /* Token for object with which binding - * is associated. */ - CONST char *eventString; /* String describing event sequence - * that triggers binding. */ +const char * +Tk_GetBinding( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_BindingTable bindingTable, + /* Table in which to look for binding. */ + ClientData object, /* Token for object with which binding is + * associated. */ + const char *eventString) /* String describing event sequence that + * triggers binding. */ { BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr; @@ -1264,7 +1234,7 @@ Tk_GetBinding(interp, bindingTable, object, eventString) return NULL; } if (psPtr->eventProc == EvalTclBinding) { - return (CONST char *) psPtr->clientData; + return (const char *) psPtr->clientData; } return ""; } @@ -1274,14 +1244,14 @@ Tk_GetBinding(interp, bindingTable, object, eventString) * * Tk_GetAllBindings -- * - * Return a list of event strings for all the bindings - * associated with a given object. + * Return a list of event strings for all the bindings associated with a + * given object. * * Results: - * There is no return value. The interp's result is modified to - * hold a Tcl list with one entry for each binding associated - * with object in bindingTable. Each entry in the list - * contains the event string associated with one binding. + * There is no return value. The interp's result is modified to hold a + * Tcl list with one entry for each binding associated with object in + * bindingTable. Each entry in the list contains the event string + * associated with one binding. * * Side effects: * None. @@ -1290,13 +1260,11 @@ Tk_GetBinding(interp, bindingTable, object, eventString) */ void -Tk_GetAllBindings(interp, bindingTable, object) - Tcl_Interp *interp; /* Interpreter returning result or - * error. */ - Tk_BindingTable bindingTable; /* Table in which to look for - * bindings. */ - ClientData object; /* Token for object. */ - +Tk_GetAllBindings( + Tcl_Interp *interp, /* Interpreter returning result or error. */ + Tk_BindingTable bindingTable, + /* Table in which to look for bindings. */ + ClientData object) /* Token for object. */ { BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr; @@ -1310,11 +1278,11 @@ Tk_GetAllBindings(interp, bindingTable, object) Tcl_DStringInit(&ds); for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = psPtr->nextObjPtr) { - /* - * For each binding, output information about each of the - * patterns in its sequence. + /* + * For each binding, output information about each of the patterns in + * its sequence. */ - + Tcl_DStringSetLength(&ds, 0); GetPatternString(psPtr, &ds); Tcl_AppendElement(interp, Tcl_DStringValue(&ds)); @@ -1327,12 +1295,11 @@ Tk_GetAllBindings(interp, bindingTable, object) * * Tk_DeleteAllBindings -- * - * Remove all bindings associated with a given object in a - * given binding table. + * Remove all bindings associated with a given object in a given binding + * table. * * Results: - * All bindings associated with object are removed from - * bindingTable. + * All bindings associated with object are removed from bindingTable. * * Side effects: * None. @@ -1341,10 +1308,10 @@ Tk_GetAllBindings(interp, bindingTable, object) */ void -Tk_DeleteAllBindings(bindingTable, object) - Tk_BindingTable bindingTable; /* Table in which to delete - * bindings. */ - ClientData object; /* Token for object. */ +Tk_DeleteAllBindings( + Tk_BindingTable bindingTable, + /* Table in which to delete bindings. */ + ClientData object) /* Token for object. */ { BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr, *prevPtr; @@ -1357,12 +1324,12 @@ Tk_DeleteAllBindings(bindingTable, object) } for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = nextPtr) { - nextPtr = psPtr->nextObjPtr; + nextPtr = psPtr->nextObjPtr; /* - * Be sure to remove each binding from its hash chain in the - * pattern table. If this is the last pattern in the chain, - * then delete the hash entry too. + * Be sure to remove each binding from its hash chain in the pattern + * table. If this is the last pattern in the chain, then delete the + * hash entry too. */ prevPtr = (PatSeq *) Tcl_GetHashValue(psPtr->hPtr); @@ -1375,7 +1342,7 @@ Tk_DeleteAllBindings(bindingTable, object) } else { for ( ; ; prevPtr = prevPtr->nextSeqPtr) { if (prevPtr == NULL) { - panic("Tk_DeleteAllBindings couldn't find on hash chain"); + Tcl_Panic("Tk_DeleteAllBindings couldn't find on hash chain"); } if (prevPtr->nextSeqPtr == psPtr) { prevPtr->nextSeqPtr = psPtr->nextSeqPtr; @@ -1400,11 +1367,10 @@ Tk_DeleteAllBindings(bindingTable, object) * * Tk_BindEvent -- * - * This procedure is invoked to process an X event. The - * event is added to those recorded for the binding table. - * Then each of the objects at *objectPtr is checked in - * order to see if it has a binding that matches the recent - * events. If so, the most specific binding is invoked for + * This function is invoked to process an X event. The event is added to + * those recorded for the binding table. Then each of the objects at + * *objectPtr is checked in order to see if it has a binding that matches + * the recent events. If so, the most specific binding is invoked for * each object. * * Results: @@ -1413,32 +1379,32 @@ Tk_DeleteAllBindings(bindingTable, object) * Side effects: * Depends on the command associated with the matching binding. * - * All Tcl bindings scripts for each object are accumulated before - * the first binding is evaluated. If the action of a Tcl binding - * is to change or delete a binding, or delete the window associated - * with the binding, all the original Tcl binding scripts will still - * fire. Contrast this with C binding procedures. If a pending C - * binding (one that hasn't fired yet, but is queued to be fired for - * this window) is deleted, it will not be called, and if it is - * changed, then the new binding procedure will be called. If the - * window itself is deleted, no further C binding procedures will be - * called for this window. When both Tcl binding scripts and C binding - * procedures are interleaved, the above rules still apply. + * All Tcl bindings scripts for each object are accumulated before the + * first binding is evaluated. If the action of a Tcl binding is to + * change or delete a binding, or delete the window associated with the + * binding, all the original Tcl binding scripts will still fire. + * Contrast this with C binding functions. If a pending C binding (one + * that hasn't fired yet, but is queued to be fired for this window) is + * deleted, it will not be called, and if it is changed, then the new + * binding function will be called. If the window itself is deleted, no + * further C binding functions will be called for this window. When both + * Tcl binding scripts and C binding functions are interleaved, the above + * rules still apply. * *--------------------------------------------------------------------------- */ void -Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) - Tk_BindingTable bindingTable; /* Table in which to look for - * bindings. */ - XEvent *eventPtr; /* What actually happened. */ - Tk_Window tkwin; /* Window on display where event - * occurred (needed in order to - * locate display information). */ - int numObjects; /* Number of objects at *objectPtr. */ - ClientData *objectPtr; /* Array of one or more objects - * to check for a matching binding. */ +Tk_BindEvent( + Tk_BindingTable bindingTable, + /* Table in which to look for bindings. */ + XEvent *eventPtr, /* What actually happened. */ + Tk_Window tkwin, /* Window on display where event occurred + * (needed in order to locate display + * information). */ + int numObjects, /* Number of objects at *objectPtr. */ + ClientData *objectPtr) /* Array of one or more objects to check for a + * matching binding. */ { BindingTable *bindPtr; TkDisplay *dispPtr; @@ -1453,15 +1419,14 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) Tcl_DString scripts, savedResult; Detail detail; char *p, *end; - PendingBinding *pendingPtr; - PendingBinding staticPending; - TkWindow *winPtr = (TkWindow *)tkwin; + PendingBinding staticPending, *pendingPtr; + TkWindow *winPtr = (TkWindow *) tkwin; PatternTableKey key; Tk_ClassModalProc *modalProc; + /* - * Ignore events on windows that don't have names: these are windows - * like wrapper windows that shouldn't be visible to the - * application. + * Ignore events on windows that don't have names: these are windows like + * wrapper windows that shouldn't be visible to the application. */ if (winPtr->pathName == NULL) { @@ -1469,21 +1434,20 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) } /* - * Ignore the event completely if it is an Enter, Leave, FocusIn, - * or FocusOut event with detail NotifyInferior. The reason for - * ignoring these events is that we don't want transitions between - * a window and its children to visible to bindings on the parent: - * this would cause problems for mega-widgets, since the internal - * structure of a mega-widget isn't supposed to be visible to - * people watching the parent. + * Ignore the event completely if it is an Enter, Leave, FocusIn, or + * FocusOut event with detail NotifyInferior. The reason for ignoring + * these events is that we don't want transitions between a window and its + * children to visible to bindings on the parent: this would cause + * problems for mega-widgets, since the internal structure of a + * mega-widget isn't supposed to be visible to people watching the parent. */ - if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) { + if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) { if (eventPtr->xcrossing.detail == NotifyInferior) { return; } } - if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) { + if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) { if (eventPtr->xfocus.detail == NotifyInferior) { return; } @@ -1494,20 +1458,19 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo; /* - * Add the new event to the ring of saved events for the - * binding table. Two tricky points: + * Add the new event to the ring of saved events for the binding table. + * Two tricky points: * - * 1. Combine consecutive MotionNotify events. Do this by putting - * the new event *on top* of the previous event. + * 1. Combine consecutive MotionNotify events. Do this by putting the new + * event *on top* of the previous event. * 2. If a modifier key is held down, it auto-repeats to generate - * continuous KeyPress and KeyRelease events. These can flush - * the event ring so that valuable information is lost (such - * as repeated button clicks). To handle this, check for the - * special case of a modifier KeyPress arriving when the previous - * two events are a KeyRelease and KeyPress of the same key. - * If this happens, mark the most recent event (the KeyRelease) - * invalid and put the new event on top of the event before that - * (the KeyPress). + * continuous KeyPress and KeyRelease events. These can flush the event + * ring so that valuable information is lost (such as repeated button + * clicks). To handle this, check for the special case of a modifier + * KeyPress arriving when the previous two events are a KeyRelease and + * KeyPress of the same key. If this happens, mark the most recent + * event (the KeyRelease) invalid and put the new event on top of the + * event before that (the KeyPress). */ if ((eventPtr->type == MotionNotify) @@ -1517,6 +1480,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) */ } else if (eventPtr->type == KeyPress) { int i; + for (i = 0; ; i++) { if (i >= dispPtr->numModKeyCodes) { goto advanceRingPointer; @@ -1543,14 +1507,15 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) bindPtr->eventRing[bindPtr->curEvent].type = -1; bindPtr->curEvent = i; } else { - advanceRingPointer: + + advanceRingPointer: bindPtr->curEvent++; if (bindPtr->curEvent >= EVENT_BUFFER_SIZE) { bindPtr->curEvent = 0; } } ringPtr = &bindPtr->eventRing[bindPtr->curEvent]; - memcpy((VOID *) ringPtr, (VOID *) eventPtr, sizeof(XEvent)); + memcpy((void *) ringPtr, (void *) eventPtr, sizeof(XEvent)); detail.clientData = 0; flags = flagArray[ringPtr->type]; if (flags & KEY) { @@ -1575,14 +1540,12 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) memset(&key, 0, sizeof(key)); if (ringPtr->type != VirtualEvent) { - Tcl_HashTable *veptPtr; + Tcl_HashTable *veptPtr = &bindInfoPtr->virtualEventTable.patternTable; Tcl_HashEntry *hPtr; - veptPtr = &bindInfoPtr->virtualEventTable.patternTable; - - key.object = NULL; - key.type = ringPtr->type; - key.detail = detail; + key.object = NULL; + key.type = ringPtr->type; + key.detail = detail; hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key); if (hPtr != NULL) { @@ -1593,37 +1556,34 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) key.detail.clientData = 0; hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key); if (hPtr != NULL) { - vMatchNoDetailList = (PatSeq *) Tcl_GetHashValue(hPtr); + vMatchNoDetailList = (PatSeq *) Tcl_GetHashValue(hPtr); } } } /* - * Loop over all the binding tags, finding the binding script or - * callback for each one. Append all of the binding scripts, with - * %-sequences expanded, to "scripts", with null characters separating - * the scripts for each object. Append all the callbacks to the array - * of pending callbacks. + * Loop over all the binding tags, finding the binding script or callback + * for each one. Append all of the binding scripts, with %-sequences + * expanded, to "scripts", with null characters separating the scripts for + * each object. Append all the callbacks to the array of pending + * callbacks. */ - + pendingPtr = &staticPending; matchCount = 0; matchSpace = sizeof(staticPending.matchArray) / sizeof(PatSeq *); Tcl_DStringInit(&scripts); for ( ; numObjects > 0; numObjects--, objectPtr++) { - PatSeq *matchPtr, *sourcePtr; + PatSeq *matchPtr = NULL, *sourcePtr = NULL; Tcl_HashEntry *hPtr; - matchPtr = NULL; - sourcePtr = NULL; - /* * Match the new event against those recorded in the pattern table, - * saving the longest matching pattern. For events with details - * (button and key events), look for a binding for the specific - * key or button. First see if the event matches a physical event - * that the object is interested in, then look for a virtual event. + * saving the longest matching pattern. For events with details + * (button and key events), look for a binding for the specific key or + * button. First see if the event matches a physical event that the + * object is interested in, then look for a virtual event. */ key.object = *objectPtr; @@ -1631,7 +1591,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) key.detail = detail; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, + matchPtr = MatchPatterns(dispPtr, bindPtr, (PatSeq *) Tcl_GetHashValue(hPtr), matchPtr, NULL, &sourcePtr); } @@ -1643,7 +1603,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) /* * If no match was found, look for a binding for all keys or buttons - * (detail of 0). Again, first match on a virtual event. + * (detail of 0). Again, first match on a virtual event. */ if ((detail.clientData != 0) && (matchPtr == NULL)) { @@ -1656,24 +1616,24 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) } if (vMatchNoDetailList != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList, + matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList, matchPtr, objectPtr, &sourcePtr); } } - + if (matchPtr != NULL) { if (sourcePtr->eventProc == NULL) { - panic("Tk_BindEvent: missing command"); + Tcl_Panic("Tk_BindEvent: missing command"); } if (sourcePtr->eventProc == EvalTclBinding) { ExpandPercents(winPtr, (char *) sourcePtr->clientData, eventPtr, detail.keySym, &scripts); } else { if (matchCount >= matchSpace) { - PendingBinding *new; + PendingBinding *newPtr; unsigned int oldSize, newSize; - + oldSize = sizeof(staticPending) - sizeof(staticPending.matchArray) + matchSpace * sizeof(PatSeq*); @@ -1681,20 +1641,21 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) newSize = sizeof(staticPending) - sizeof(staticPending.matchArray) + matchSpace * sizeof(PatSeq*); - new = (PendingBinding *) ckalloc(newSize); - memcpy((VOID *) new, (VOID *) pendingPtr, oldSize); + newPtr = (PendingBinding *) ckalloc(newSize); + memcpy((void *) newPtr, (void *) pendingPtr, oldSize); if (pendingPtr != &staticPending) { ckfree((char *) pendingPtr); } - pendingPtr = new; + pendingPtr = newPtr; } sourcePtr->refCount++; pendingPtr->matchArray[matchCount] = sourcePtr; matchCount++; } + /* - * A "" is added to the scripts string to separate the - * various scripts that should be invoked. + * A "" is added to the scripts string to separate the various + * scripts that should be invoked. */ Tcl_DStringAppend(&scripts, "", 1); @@ -1705,29 +1666,28 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) } /* - * Now go back through and evaluate the binding for each object, - * in order, dealing with "break" and "continue" exceptions - * appropriately. + * Now go back through and evaluate the binding for each object, in order, + * dealing with "break" and "continue" exceptions appropriately. * * There are two tricks here: - * 1. Bindings can be invoked from in the middle of Tcl commands, - * where the interp's result is significant (for example, a widget - * might be deleted because of an error in creating it, so the - * result contains an error message that is eventually going to - * be returned by the creating command). To preserve the result, - * we save it in a dynamic string. - * 2. The binding's action can potentially delete the binding, - * so bindPtr may not point to anything valid once the action - * completes. Thus we have to save bindPtr->interp in a - * local variable in order to restore the result. + * 1. Bindings can be invoked from in the middle of Tcl commands, where + * the interp's result is significant (for example, a widget might be + * deleted because of an error in creating it, so the result contains + * an error message that is eventually going to be returned by the + * creating command). To preserve the result, we save it in a dynamic + * string. + * 2. The binding's action can potentially delete the binding, so bindPtr + * may not point to anything valid once the action completes. Thus we + * have to save bindPtr->interp in a local variable in order to restore + * the result. */ interp = bindPtr->interp; Tcl_DStringInit(&savedResult); /* - * Save information about the current screen, then invoke a script - * if the screen has changed. + * Save information about the current screen, then invoke a script if the + * screen has changed. */ Tcl_DStringGetResult(interp, &savedResult); @@ -1744,9 +1704,8 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) if (matchCount > 0) { /* * Remember the list of pending C binding callbacks, so we can mark - * them as deleted and not call them if the act of evaluating a C - * or Tcl binding deletes a C binding callback or even the whole - * window. + * them as deleted and not call them if the act of evaluating a C or + * Tcl binding deletes a C binding callback or even the whole window. */ pendingPtr->nextPtr = bindInfoPtr->pendingList; @@ -1754,11 +1713,11 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) pendingPtr->deleted = 0; bindInfoPtr->pendingList = pendingPtr; } - + /* - * Save the current value of the TK_DEFER_MODAL flag so we can - * restore it at the end of the loop. Clear the flag so we can - * detect any recursive requests for a modal loop. + * Save the current value of the TK_DEFER_MODAL flag so we can restore it + * at the end of the loop. Clear the flag so we can detect any recursive + * requests for a modal loop. */ flags = winPtr->flags; @@ -1769,16 +1728,15 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) i = 0; /* - * Be carefule when dereferencing screenPtr or bindInfoPtr. If we - * evaluate something that destroys ".", bindInfoPtr would have been - * freed, but we can tell that by first checking to see if - * winPtr->mainPtr == NULL. + * Be carefule when dereferencing screenPtr or bindInfoPtr. If we evaluate + * something that destroys ".", bindInfoPtr would have been freed, but we + * can tell that by first checking to see if winPtr->mainPtr == NULL. */ Tcl_Preserve((ClientData) bindInfoPtr); while (p < end) { int code; - + if (!bindInfoPtr->deleted) { screenPtr->bindingDepth++; } @@ -1786,7 +1744,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) if (*p == '\0') { PatSeq *psPtr; - + psPtr = pendingPtr->matchArray[i]; i++; code = TCL_OK; @@ -1804,6 +1762,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) } } else { int len = (int) strlen(p); + code = Tcl_EvalEx(interp, p, len, TCL_EVAL_GLOBAL); p += len; } @@ -1815,7 +1774,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) if (code != TCL_OK) { if (code == TCL_CONTINUE) { /* - * Do nothing: just go on to the next command. + * Do nothing: just go on to the next command. */ } else if (code == TCL_BREAK) { break; @@ -1829,13 +1788,13 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) if (matchCount > 0 && !pendingPtr->deleted) { /* - * Restore the original modal flag value and invoke the modal loop - * if needed. + * Restore the original modal flag value and invoke the modal loop if + * needed. */ deferModal = winPtr->flags & TK_DEFER_MODAL; - winPtr->flags = (winPtr->flags & (unsigned int) ~TK_DEFER_MODAL) - | (flags & TK_DEFER_MODAL); + winPtr->flags = (winPtr->flags & (unsigned int) ~TK_DEFER_MODAL) + | (flags & TK_DEFER_MODAL); if (deferModal) { modalProc = Tk_GetClassProc(winPtr->classProcsPtr, modalProc); if (modalProc != NULL) { @@ -1846,12 +1805,10 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) if (!bindInfoPtr->deleted && (screenPtr->bindingDepth != 0) && ((oldDispPtr != screenPtr->curDispPtr) - || (oldScreen != screenPtr->curScreenIndex))) { - + || (oldScreen != screenPtr->curScreenIndex))) { /* - * Some other binding script is currently executing, but its - * screen is no longer current. Change the current display - * back again. + * Some other binding script is currently executing, but its screen is + * no longer current. Change the current display back again. */ screenPtr->curDispPtr = oldDispPtr; @@ -1864,10 +1821,10 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) if (matchCount > 0) { if (!bindInfoPtr->deleted) { /* - * Delete the pending list from the list of pending scripts - * for this window. + * Delete the pending list from the list of pending scripts for + * this window. */ - + PendingBinding **curPtrPtr; for (curPtrPtr = &bindInfoPtr->pendingList; ; ) { @@ -1890,8 +1847,8 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) * * TkBindDeadWindow -- * - * This procedure is invoked when it is determined that a window is - * dead. It cleans up bind-related information about the window + * This function is invoked when it is determined that a window is dead. + * It cleans up bind-related information about the window * * Results: * None. @@ -1901,20 +1858,22 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr) * *--------------------------------------------------------------------------- */ - + void -TkBindDeadWindow(winPtr) - TkWindow *winPtr; /* The window that is being deleted. */ +TkBindDeadWindow( + TkWindow *winPtr) /* The window that is being deleted. */ { BindInfo *bindInfoPtr; PendingBinding *curPtr; /* - * Certain special windows like those used for send and clipboard - * have no mainPtr. + * Certain special windows like those used for send and clipboard have no + * mainPtr. */ - if (winPtr->mainPtr == NULL) - return; + + if (winPtr->mainPtr == NULL) { + return; + } bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo; curPtr = bindInfoPtr->pendingList; @@ -1931,58 +1890,59 @@ TkBindDeadWindow(winPtr) * * MatchPatterns -- * - * Given a list of pattern sequences and a list of recent events, - * return the pattern sequence that best matches the event list, - * if there is one. + * Given a list of pattern sequences and a list of recent events, return + * the pattern sequence that best matches the event list, if there is + * one. * - * This procedure is used in two different ways. In the simplest - * use, "object" is NULL and psPtr is a list of pattern sequences, - * each of which corresponds to a binding. In this case, the - * procedure finds the pattern sequences that match the event list - * and returns the most specific of those, if there is more than one. + * This function is used in two different ways. In the simplest use, + * "object" is NULL and psPtr is a list of pattern sequences, each of + * which corresponds to a binding. In this case, the function finds the + * pattern sequences that match the event list and returns the most + * specific of those, if there is more than one. * - * In the second case, psPtr is a list of pattern sequences, each - * of which corresponds to a definition for a virtual binding. - * In order for one of these sequences to "match", it must match - * the events (as above) but in addition there must be a binding - * for its associated virtual event on the current object. The - * "object" argument indicates which object the binding must be for. + * In the second case, psPtr is a list of pattern sequences, each of + * which corresponds to a definition for a virtual binding. In order for + * one of these sequences to "match", it must match the events (as above) + * but in addition there must be a binding for its associated virtual + * event on the current object. The "object" argument indicates which + * object the binding must be for. * * Results: - * The return value is NULL if bestPtr is NULL and no pattern matches - * the recent events from bindPtr. Otherwise the return value is - * the most specific pattern sequence among bestPtr and all those - * at psPtr that match the event list and object. If a pattern - * sequence other than bestPtr is returned, then *bestCommandPtr - * is filled in with a pointer to the command from the best sequence. + + * The return value is NULL if bestPtr is NULL and no pattern matches the + * recent events from bindPtr. Otherwise the return value is the most + * specific pattern sequence among bestPtr and all those at psPtr that + * match the event list and object. If a pattern sequence other than + * bestPtr is returned, then *bestCommandPtr is filled in with a pointer + * to the command from the best sequence. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ static PatSeq * -MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) - TkDisplay *dispPtr; /* Display from which the event came. */ - BindingTable *bindPtr; /* Information about binding table, such as +MatchPatterns( + TkDisplay *dispPtr, /* Display from which the event came. */ + BindingTable *bindPtr, /* Information about binding table, such as * ring of recent events. */ - PatSeq *psPtr; /* List of pattern sequences. */ - PatSeq *bestPtr; /* The best match seen so far, from a - * previous call to this procedure. NULL - * means no prior best match. */ - ClientData *objectPtr; /* If NULL, the sequences at psPtr - * correspond to "normal" bindings. If - * non-NULL, the sequences at psPtr correspond - * to virtual bindings; in order to match each - * sequence must correspond to a virtual - * binding for which a binding exists for - * object in bindPtr. */ - PatSeq **sourcePtrPtr; /* Filled with the pattern sequence that + PatSeq *psPtr, /* List of pattern sequences. */ + PatSeq *bestPtr, /* The best match seen so far, from a previous + * call to this function. NULL means no prior + * best match. */ + ClientData *objectPtr, /* If NULL, the sequences at psPtr correspond + * to "normal" bindings. If non-NULL, the + * sequences at psPtr correspond to virtual + * bindings; in order to match each sequence + * must correspond to a virtual binding for + * which a binding exists for object in + * bindPtr. */ + PatSeq **sourcePtrPtr) /* Filled with the pattern sequence that * contains the eventProc and clientData - * associated with the best match. If this + * associated with the best match. If this * differs from the return value, it is the * virtual event that most closely matched the - * return value (a physical event). Not + * return value (a physical event). Not * modified unless a result other than bestPtr * is returned. */ { @@ -1995,22 +1955,17 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) */ for ( ; psPtr != NULL; psPtr = psPtr->nextSeqPtr) { - XEvent *eventPtr; - Pattern *patPtr; - Window window; - Detail *detailPtr; - int patCount, ringCount, flags, state; - int modMask; + XEvent *eventPtr = &bindPtr->eventRing[bindPtr->curEvent]; + Detail *detailPtr = &bindPtr->detailRing[bindPtr->curEvent]; + Pattern *patPtr = psPtr->pats; + Window window = eventPtr->xany.window; + int patCount, ringCount, flags, state, modMask, i; /* - * Iterate over all the patterns in a sequence to be - * sure that they all match. + * Iterate over all the patterns in a sequence to be sure that they + * all match. */ - eventPtr = &bindPtr->eventRing[bindPtr->curEvent]; - detailPtr = &bindPtr->detailRing[bindPtr->curEvent]; - window = eventPtr->xany.window; - patPtr = psPtr->pats; patCount = psPtr->numPats; ringCount = EVENT_BUFFER_SIZE; while (patCount > 0) { @@ -2019,21 +1974,21 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) } if (eventPtr->xany.type != patPtr->eventType) { /* - * Most of the event types are considered superfluous - * in that they are ignored if they occur in the middle - * of a pattern sequence and have mismatching types. The - * only ones that cannot be ignored are ButtonPress and - * ButtonRelease events (if the next event in the pattern - * is a KeyPress or KeyRelease) and KeyPress and KeyRelease - * events (if the next pattern event is a ButtonPress or - * ButtonRelease). Here are some tricky cases to consider: + * Most of the event types are considered superfluous in that + * they are ignored if they occur in the middle of a pattern + * sequence and have mismatching types. The only ones that + * cannot be ignored are ButtonPress and ButtonRelease events + * (if the next event in the pattern is a KeyPress or + * KeyRelease) and KeyPress and KeyRelease events (if the next + * pattern event is a ButtonPress or ButtonRelease). Here are + * some tricky cases to consider: * 1. Double-Button or Double-Key events. * 2. Double-ButtonRelease or Double-KeyRelease events. - * 3. The arrival of various events like Enter and Leave - * and FocusIn and GraphicsExpose between two button - * presses or key presses. - * 4. Modifier keys like Shift and Control shouldn't - * generate conflicts with button events. + * 3. The arrival of various events like Enter and Leave and + * FocusIn and GraphicsExpose between two button presses or + * key presses. + * 4. Modifier keys like Shift and Control shouldn't generate + * conflicts with button events. */ if ((patPtr->eventType == KeyPress) @@ -2046,8 +2001,6 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) || (patPtr->eventType == ButtonRelease)) { if ((eventPtr->xany.type == KeyPress) || (eventPtr->xany.type == KeyRelease)) { - int i; - /* * Ignore key events if they are modifier keys. */ @@ -2058,6 +2011,7 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) /* * This key is a modifier key, so ignore it. */ + goto nextEvent; } } @@ -2067,32 +2021,28 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) goto nextEvent; } if (eventPtr->xany.type == CreateNotify - && eventPtr->xcreatewindow.parent != window) { + && eventPtr->xcreatewindow.parent != window) { goto nextSequence; - } else - if (eventPtr->xany.window != window) { + } else if (eventPtr->xany.window != window) { goto nextSequence; } /* - * Note: it's important for the keysym check to go before - * the modifier check, so we can ignore unwanted modifier - * keys before choking on the modifier check. + * Note: it's important for the keysym check to go before the + * modifier check, so we can ignore unwanted modifier keys before + * choking on the modifier check. */ if ((patPtr->detail.clientData != 0) && (patPtr->detail.clientData != detailPtr->clientData)) { /* - * The detail appears not to match. However, if the event - * is a KeyPress for a modifier key then just ignore the - * event. Otherwise event sequences like "aD" never match - * because the shift key goes down between the "a" and the - * "D". + * The detail appears not to match. However, if the event is a + * KeyPress for a modifier key then just ignore the event. + * Otherwise event sequences like "aD" never match because the + * shift key goes down between the "a" and the "D". */ if (eventPtr->xany.type == KeyPress) { - int i; - for (i = 0; i < dispPtr->numModKeyCodes; i++) { if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) { goto nextEvent; @@ -2102,7 +2052,7 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) goto nextSequence; } flags = flagArray[eventPtr->type]; - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { state = eventPtr->xkey.state; } else if (flags & CROSSING) { state = eventPtr->xcrossing.state; @@ -2130,10 +2080,9 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) } } if (psPtr->flags & PAT_NEARBY) { - XEvent *firstPtr; + XEvent *firstPtr = &bindPtr->eventRing[bindPtr->curEvent]; int timeDiff; - firstPtr = &bindPtr->eventRing[bindPtr->curEvent]; timeDiff = (Time) firstPtr->xkey.time - eventPtr->xkey.time; if ((firstPtr->xkey.x_root < (eventPtr->xkey.x_root - NEARBY_PIXELS)) @@ -2149,7 +2098,7 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) } patPtr++; patCount--; - nextEvent: + nextEvent: if (eventPtr == bindPtr->eventRing) { eventPtr = &bindPtr->eventRing[EVENT_BUFFER_SIZE-1]; detailPtr = &bindPtr->detailRing[EVENT_BUFFER_SIZE-1]; @@ -2169,9 +2118,9 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) PatternTableKey key; /* - * The sequence matches the physical constraints. - * Is this object interested in any of the virtual events - * that correspond to this sequence? + * The sequence matches the physical constraints. Is this object + * interested in any of the virtual events that correspond to this + * sequence? */ voPtr = psPtr->voPtr; @@ -2182,26 +2131,24 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) key.detail.clientData = 0; for (iVirt = 0; iVirt < voPtr->numOwners; iVirt++) { - Tcl_HashEntry *hPtr = voPtr->owners[iVirt]; + Tcl_HashEntry *hPtr = voPtr->owners[iVirt]; - key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, + key.detail.name = (Tk_Uid) Tcl_GetHashKey(hPtr->tablePtr, hPtr); hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr != NULL) { - /* * This tag is interested in this virtual event and its * corresponding physical event is a good match with the * virtual event's definition. */ - PatSeq *virtMatchPtr; + PatSeq *virtMatchPtr = (PatSeq *) Tcl_GetHashValue(hPtr); - virtMatchPtr = (PatSeq *) Tcl_GetHashValue(hPtr); if ((virtMatchPtr->numPats != 1) || (virtMatchPtr->nextSeqPtr != NULL)) { - panic("MatchPattern: badly constructed virtual event"); + Tcl_Panic("MatchPattern: badly constructed virtual event"); } sourcePtr = virtMatchPtr; goto match; @@ -2212,19 +2159,19 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) * The physical event matches a virtual event's definition, but * the tag isn't interested in it. */ + goto nextSequence; } - match: + match: /* - * This sequence matches. If we've already got another match, - * pick whichever is most specific. Detail is most important, - * then needMods. + * This sequence matches. If we've already got another match, pick + * whichever is most specific. Detail is most important, then + * needMods. */ if (bestPtr != NULL) { Pattern *patPtr2; - int i; if (matchPtr->numPats != bestPtr->numPats) { if (bestPtr->numPats > matchPtr->numPats) { @@ -2252,51 +2199,49 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) } } } + /* * Tie goes to current best pattern. * - * (1) For virtual vs. virtual, the least recently defined - * virtual wins, because virtuals are examined in order of - * definition. This order is _not_ guaranteed in the - * documentation. + * (1) For virtual vs. virtual, the least recently defined virtual + * wins, because virtuals are examined in order of definition. + * This order is _not_ guaranteed in the documentation. * - * (2) For virtual vs. physical, the physical wins because all - * the physicals are examined before the virtuals. This order - * is guaranteed in the documentation. + * (2) For virtual vs. physical, the physical wins because all the + * physicals are examined before the virtuals. This order is + * guaranteed in the documentation. * * (3) For physical vs. physical pattern, the most recently * defined physical wins, because physicals are examined in - * reverse order of definition. This order is guaranteed in - * the documentation. + * reverse order of definition. This order is guaranteed in the + * documentation. */ - goto nextSequence; + goto nextSequence; } - newBest: + newBest: bestPtr = matchPtr; bestSourcePtr = sourcePtr; - nextSequence: + nextSequence: continue; } *sourcePtrPtr = bestSourcePtr; return bestPtr; } - /* *-------------------------------------------------------------- * * ExpandPercents -- * - * Given a command and an event, produce a new command - * by replacing % constructs in the original command - * with information from the X event. + * Given a command and an event, produce a new command by replacing % + * constructs in the original command with information from the X event. * * Results: - * The new expanded command is appended to the dynamic string - * given by dsPtr. + * The new expanded command is appended to the dynamic string given by + * dsPtr. * * Side effects: * None. @@ -2305,23 +2250,23 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr) */ static void -ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr) - TkWindow *winPtr; /* Window where event occurred: needed to - * get input context. */ - CONST char *before; /* Command containing percent expressions - * to be replaced. */ - XEvent *eventPtr; /* X event containing information to be - * used in % replacements. */ - KeySym keySym; /* KeySym: only relevant for KeyPress and +ExpandPercents( + TkWindow *winPtr, /* Window where event occurred: needed to get + * input context. */ + const char *before, /* Command containing percent expressions to + * be replaced. */ + XEvent *eventPtr, /* X event containing information to be used + * in % replacements. */ + KeySym keySym, /* KeySym: only relevant for KeyPress and * KeyRelease events). */ - Tcl_DString *dsPtr; /* Dynamic string in which to append new + Tcl_DString *dsPtr) /* Dynamic string in which to append new * command. */ { int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl * list element. */ int number, flags, length; #define NUM_SIZE 40 - CONST char *string; + const char *string; Tcl_DString buf; char numStorage[NUM_SIZE+1]; @@ -2332,10 +2277,11 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr) } else { flags = 0; } + while (1) { /* - * Find everything up to the next % character and append it - * to the result string. + * Find everything up to the next % character and append it to the + * result string. */ for (string = before; (*string != 0) && (*string != '%'); string++) { @@ -2350,323 +2296,333 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr) } /* - * There's a percent sequence here. Process it. + * There's a percent sequence here. Process it. */ number = 0; string = "??"; switch (before[1]) { - case '#': - number = eventPtr->xany.serial; - goto doNumber; - case 'a': - if (flags & CONFIG) { - TkpPrintWindowId(numStorage, eventPtr->xconfigure.above); - string = numStorage; - } - goto doString; - case 'b': - if (flags & BUTTON) { - number = eventPtr->xbutton.button; - goto doNumber; - } - goto doString; - case 'c': - if (flags & EXPOSE) { - number = eventPtr->xexpose.count; - goto doNumber; - } - goto doString; - case 'd': - if (flags & (CROSSING|FOCUS)) { - if (flags & FOCUS) { - number = eventPtr->xfocus.detail; - } else { - number = eventPtr->xcrossing.detail; - } - string = TkFindStateString(notifyDetail, number); - } else if (flags & CONFIGREQ) { - if (eventPtr->xconfigurerequest.value_mask & CWStackMode) { - string = TkFindStateString(configureRequestDetail, - eventPtr->xconfigurerequest.detail); - } else { - string = ""; - } - } - goto doString; - case 'f': - if (flags & CROSSING) { - number = eventPtr->xcrossing.focus; - goto doNumber; - } - goto doString; - case 'h': - if (flags & EXPOSE) { - number = eventPtr->xexpose.height; - } else if (flags & (CONFIG)) { - number = eventPtr->xconfigure.height; - } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.height; - } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.height; - } else if (flags & RESIZEREQ) { - number = eventPtr->xresizerequest.height; - } else { - goto doString; - } - goto doNumber; - case 'i': - if (flags & CREATE) { - TkpPrintWindowId(numStorage, eventPtr->xcreatewindow.window); - } else if (flags & CONFIGREQ) { - TkpPrintWindowId(numStorage, eventPtr->xconfigurerequest.window); - } else if (flags & MAPREQ) { - TkpPrintWindowId(numStorage, eventPtr->xmaprequest.window); - } else { - TkpPrintWindowId(numStorage, eventPtr->xany.window); - } + case '#': + number = eventPtr->xany.serial; + goto doNumber; + case 'a': + if (flags & CONFIG) { + TkpPrintWindowId(numStorage, eventPtr->xconfigure.above); string = numStorage; - goto doString; - case 'k': - if (flags & KEY) { - number = eventPtr->xkey.keycode; - goto doNumber; - } - goto doString; - case 'm': - if (flags & CROSSING) { - number = eventPtr->xcrossing.mode; - string = TkFindStateString(notifyMode, number); - } else if (flags & FOCUS) { - number = eventPtr->xfocus.mode; - string = TkFindStateString(notifyMode, number); - } - goto doString; - case 'o': - if (flags & CREATE) { - number = eventPtr->xcreatewindow.override_redirect; - } else if (flags & MAP) { - number = eventPtr->xmap.override_redirect; - } else if (flags & REPARENT) { - number = eventPtr->xreparent.override_redirect; - } else if (flags & CONFIG) { - number = eventPtr->xconfigure.override_redirect; - } else { - goto doString; - } - goto doNumber; - case 'p': - if (flags & CIRC) { - string = TkFindStateString(circPlace, eventPtr->xcirculate.place); - } else if (flags & CIRCREQ) { - string = TkFindStateString(circPlace, eventPtr->xcirculaterequest.place); - } - goto doString; - case 's': - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { - number = eventPtr->xkey.state; - } else if (flags & CROSSING) { - number = eventPtr->xcrossing.state; - } else if (flags & PROP) { - string = TkFindStateString(propNotify, - eventPtr->xproperty.state); - goto doString; - } else if (flags & VISIBILITY) { - string = TkFindStateString(visNotify, - eventPtr->xvisibility.state); - goto doString; - } else { - goto doString; - } - goto doNumber; - case 't': - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { - number = (int) eventPtr->xkey.time; - } else if (flags & CROSSING) { - number = (int) eventPtr->xcrossing.time; - } else if (flags & PROP) { - number = (int) eventPtr->xproperty.time; - } else { - goto doString; - } + } + goto doString; + case 'b': + if (flags & BUTTON) { + number = eventPtr->xbutton.button; goto doNumber; - case 'v': - number = eventPtr->xconfigurerequest.value_mask; + } + goto doString; + case 'c': + if (flags & EXPOSE) { + number = eventPtr->xexpose.count; goto doNumber; - case 'w': - if (flags & EXPOSE) { - number = eventPtr->xexpose.width; - } else if (flags & CONFIG) { - number = eventPtr->xconfigure.width; - } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.width; - } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.width; - } else if (flags & RESIZEREQ) { - number = eventPtr->xresizerequest.width; + } + goto doString; + case 'd': + if (flags & (CROSSING|FOCUS)) { + if (flags & FOCUS) { + number = eventPtr->xfocus.detail; } else { - goto doString; + number = eventPtr->xcrossing.detail; } - goto doNumber; - case 'x': - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { - number = eventPtr->xkey.x; - } else if (flags & CROSSING) { - number = eventPtr->xcrossing.x; - } else if (flags & EXPOSE) { - number = eventPtr->xexpose.x; - } else if (flags & (CREATE|CONFIG|GRAVITY)) { - number = eventPtr->xcreatewindow.x; - } else if (flags & REPARENT) { - number = eventPtr->xreparent.x; - } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.x; - } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.x; + string = TkFindStateString(notifyDetail, number); + } else if (flags & CONFIGREQ) { + if (eventPtr->xconfigurerequest.value_mask & CWStackMode) { + string = TkFindStateString(configureRequestDetail, + eventPtr->xconfigurerequest.detail); } else { - goto doString; + string = ""; } - goto doNumber; - case 'y': - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { - number = eventPtr->xkey.y; - } else if (flags & EXPOSE) { - number = eventPtr->xexpose.y; - } else if (flags & (CREATE|CONFIG|GRAVITY)) { - number = eventPtr->xcreatewindow.y; - } else if (flags & REPARENT) { - number = eventPtr->xreparent.y; - } else if (flags & CROSSING) { - number = eventPtr->xcrossing.y; - } else if (flags & CREATE) { - number = eventPtr->xcreatewindow.y; - } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.y; + } else if (flags & VIRTUAL) { + XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr; + + if (vePtr->user_data != NULL) { + string = Tcl_GetString(vePtr->user_data); } else { - goto doString; + string = ""; } + } + goto doString; + case 'f': + if (flags & CROSSING) { + number = eventPtr->xcrossing.focus; goto doNumber; - case 'A': - if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { - Tcl_DStringFree(&buf); - string = TkpGetString(winPtr, eventPtr, &buf); - } + } + goto doString; + case 'h': + if (flags & EXPOSE) { + number = eventPtr->xexpose.height; + } else if (flags & CONFIG) { + number = eventPtr->xconfigure.height; + } else if (flags & CREATE) { + number = eventPtr->xcreatewindow.height; + } else if (flags & CONFIGREQ) { + number = eventPtr->xconfigurerequest.height; + } else if (flags & RESIZEREQ) { + number = eventPtr->xresizerequest.height; + } else { goto doString; - case 'B': - if (flags & CREATE) { - number = eventPtr->xcreatewindow.border_width; - } else if (flags & CONFIGREQ) { - number = eventPtr->xconfigurerequest.border_width; - } else if (flags & CONFIG) { - number = eventPtr->xconfigure.border_width; - } else { - goto doString; - } + } + goto doNumber; + case 'i': + if (flags & CREATE) { + TkpPrintWindowId(numStorage, eventPtr->xcreatewindow.window); + } else if (flags & CONFIGREQ) { + TkpPrintWindowId(numStorage, + eventPtr->xconfigurerequest.window); + } else if (flags & MAPREQ) { + TkpPrintWindowId(numStorage, eventPtr->xmaprequest.window); + } else { + TkpPrintWindowId(numStorage, eventPtr->xany.window); + } + string = numStorage; + goto doString; + case 'k': + if (flags & KEY) { + number = eventPtr->xkey.keycode; goto doNumber; - case 'D': - /* - * This is used only by the MouseWheel event. - */ - if (flags & KEY) { - number = eventPtr->xkey.keycode; - goto doNumber; - } + } + goto doString; + case 'm': + if (flags & CROSSING) { + number = eventPtr->xcrossing.mode; + string = TkFindStateString(notifyMode, number); + } else if (flags & FOCUS) { + number = eventPtr->xfocus.mode; + string = TkFindStateString(notifyMode, number); + } + goto doString; + case 'o': + if (flags & CREATE) { + number = eventPtr->xcreatewindow.override_redirect; + } else if (flags & MAP) { + number = eventPtr->xmap.override_redirect; + } else if (flags & REPARENT) { + number = eventPtr->xreparent.override_redirect; + } else if (flags & CONFIG) { + number = eventPtr->xconfigure.override_redirect; + } else { goto doString; - case 'E': - number = (int) eventPtr->xany.send_event; + } + goto doNumber; + case 'p': + if (flags & CIRC) { + string = TkFindStateString(circPlace, + eventPtr->xcirculate.place); + } else if (flags & CIRCREQ) { + string = TkFindStateString(circPlace, + eventPtr->xcirculaterequest.place); + } + goto doString; + case 's': + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + number = eventPtr->xkey.state; goto doNumber; - case 'K': - if (flags & KEY) { - char *name; - - name = TkKeysymToString(keySym); - if (name != NULL) { - string = name; - } - } + } else if (flags & CROSSING) { + number = eventPtr->xcrossing.state; + goto doNumber; + } else if (flags & PROP) { + string = TkFindStateString(propNotify, + eventPtr->xproperty.state); + } else if (flags & VISIBILITY) { + string = TkFindStateString(visNotify, + eventPtr->xvisibility.state); + } + goto doString; + case 't': + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + number = (int) eventPtr->xkey.time; + } else if (flags & CROSSING) { + number = (int) eventPtr->xcrossing.time; + } else if (flags & PROP) { + number = (int) eventPtr->xproperty.time; + } else { goto doString; - case 'N': - if (flags & KEY) { - number = (int) keySym; - goto doNumber; - } + } + goto doNumber; + case 'v': + number = eventPtr->xconfigurerequest.value_mask; + goto doNumber; + case 'w': + if (flags & EXPOSE) { + number = eventPtr->xexpose.width; + } else if (flags & CONFIG) { + number = eventPtr->xconfigure.width; + } else if (flags & CREATE) { + number = eventPtr->xcreatewindow.width; + } else if (flags & CONFIGREQ) { + number = eventPtr->xconfigurerequest.width; + } else if (flags & RESIZEREQ) { + number = eventPtr->xresizerequest.width; + } else { goto doString; - case 'P': - if (flags & PROP) { - string = Tk_GetAtomName((Tk_Window) winPtr, eventPtr->xproperty.atom); - } + } + goto doNumber; + case 'x': + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + number = eventPtr->xkey.x; + } else if (flags & CROSSING) { + number = eventPtr->xcrossing.x; + } else if (flags & EXPOSE) { + number = eventPtr->xexpose.x; + } else if (flags & (CREATE|CONFIG|GRAVITY)) { + number = eventPtr->xcreatewindow.x; + } else if (flags & REPARENT) { + number = eventPtr->xreparent.x; + } else if (flags & CREATE) { + number = eventPtr->xcreatewindow.x; + } else if (flags & CONFIGREQ) { + number = eventPtr->xconfigurerequest.x; + } else { goto doString; - case 'R': - if (flags & KEY_BUTTON_MOTION_CROSSING) { - TkpPrintWindowId(numStorage, eventPtr->xkey.root); - string = numStorage; - } + } + goto doNumber; + case 'y': + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + number = eventPtr->xkey.y; + } else if (flags & EXPOSE) { + number = eventPtr->xexpose.y; + } else if (flags & (CREATE|CONFIG|GRAVITY)) { + number = eventPtr->xcreatewindow.y; + } else if (flags & REPARENT) { + number = eventPtr->xreparent.y; + } else if (flags & CROSSING) { + number = eventPtr->xcrossing.y; + } else if (flags & CREATE) { + number = eventPtr->xcreatewindow.y; + } else if (flags & CONFIGREQ) { + number = eventPtr->xconfigurerequest.y; + } else { goto doString; - case 'S': - if (flags & KEY_BUTTON_MOTION_CROSSING) { - TkpPrintWindowId(numStorage, eventPtr->xkey.subwindow); - string = numStorage; - } + } + goto doNumber; + case 'A': + if ((flags & KEY) && (eventPtr->type != MouseWheelEvent)) { + Tcl_DStringFree(&buf); + string = TkpGetString(winPtr, eventPtr, &buf); + } + goto doString; + case 'B': + if (flags & CREATE) { + number = eventPtr->xcreatewindow.border_width; + } else if (flags & CONFIGREQ) { + number = eventPtr->xconfigurerequest.border_width; + } else if (flags & CONFIG) { + number = eventPtr->xconfigure.border_width; + } else { goto doString; - case 'T': - number = eventPtr->type; + } + goto doNumber; + case 'D': + /* + * This is used only by the MouseWheel event. + */ + + if (flags & KEY) { + number = eventPtr->xkey.keycode; goto doNumber; - case 'W': { + } + goto doString; + case 'E': + number = (int) eventPtr->xany.send_event; + goto doNumber; + case 'K': + if (flags & KEY) { + char *name = TkKeysymToString(keySym); + + if (name != NULL) { + string = name; + } + } + goto doString; + case 'N': + if (flags & KEY) { + number = (int) keySym; + goto doNumber; + } + goto doString; + case 'P': + if (flags & PROP) { + string = Tk_GetAtomName((Tk_Window) winPtr, + eventPtr->xproperty.atom); + } + goto doString; + case 'R': + if (flags & KEY_BUTTON_MOTION_CROSSING) { + TkpPrintWindowId(numStorage, eventPtr->xkey.root); + string = numStorage; + } + goto doString; + case 'S': + if (flags & KEY_BUTTON_MOTION_CROSSING) { + TkpPrintWindowId(numStorage, eventPtr->xkey.subwindow); + string = numStorage; + } + goto doString; + case 'T': + number = eventPtr->type; + goto doNumber; + case 'W': { + Tk_Window tkwin; + + tkwin = Tk_IdToWindow(eventPtr->xany.display, + eventPtr->xany.window); + if (tkwin != NULL) { + string = Tk_PathName(tkwin); + } else { + string = "??"; + } + goto doString; + } + case 'X': + if (flags & KEY_BUTTON_MOTION_CROSSING) { Tk_Window tkwin; + int x, y; + int width, height; + number = eventPtr->xkey.x_root; tkwin = Tk_IdToWindow(eventPtr->xany.display, eventPtr->xany.window); if (tkwin != NULL) { - string = Tk_PathName(tkwin); - } else { - string = "??"; + Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); + number -= x; } - goto doString; + goto doNumber; } - case 'X': - if (flags & KEY_BUTTON_MOTION_CROSSING) { - Tk_Window tkwin; - int x, y; - int width, height; - - number = eventPtr->xkey.x_root; - tkwin = Tk_IdToWindow(eventPtr->xany.display, - eventPtr->xany.window); - if (tkwin != NULL) { - Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - number -= x; - } - goto doNumber; - } - goto doString; - case 'Y': - if (flags & KEY_BUTTON_MOTION_CROSSING) { - Tk_Window tkwin; - int x, y; - int width, height; - - number = eventPtr->xkey.y_root; - tkwin = Tk_IdToWindow(eventPtr->xany.display, - eventPtr->xany.window); - if (tkwin != NULL) { - Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - number -= y; - } - goto doNumber; + goto doString; + case 'Y': + if (flags & KEY_BUTTON_MOTION_CROSSING) { + Tk_Window tkwin; + int x, y; + int width, height; + + number = eventPtr->xkey.y_root; + tkwin = Tk_IdToWindow(eventPtr->xany.display, + eventPtr->xany.window); + if (tkwin != NULL) { + Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); + number -= y; } - goto doString; - default: - numStorage[0] = before[1]; - numStorage[1] = '\0'; - string = numStorage; - goto doString; + goto doNumber; + } + goto doString; + default: + numStorage[0] = before[1]; + numStorage[1] = '\0'; + string = numStorage; + goto doString; } - doNumber: + doNumber: sprintf(numStorage, "%d", number); string = numStorage; - doString: + doString: spaceNeeded = Tcl_ScanElement(string, &cvtFlags); length = Tcl_DStringLength(dsPtr); Tcl_DStringSetLength(dsPtr, length + spaceNeeded); @@ -2684,28 +2640,27 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr) * * ChangeScreen -- * - * This procedure is invoked whenever the current screen changes - * in an application. It invokes a Tcl procedure named - * "tk::ScreenChanged", passing it the screen name as argument. - * tk::ScreenChanged does things like making the tk::Priv variable - * point to an array for the current display. + * This function is invoked whenever the current screen changes in an + * application. It invokes a Tcl command named "tk::ScreenChanged", + * passing it the screen name as argument. tk::ScreenChanged does things + * like making the tk::Priv variable point to an array for the current + * display. * * Results: * None. * * Side effects: - * Depends on what tk::ScreenChanged does. If an error occurs - * them bgerror will be invoked. + * Depends on what tk::ScreenChanged does. If an error occurs then + * bgerror will be invoked. * *---------------------------------------------------------------------- */ static void -ChangeScreen(interp, dispName, screenIndex) - Tcl_Interp *interp; /* Interpreter in which to invoke - * command. */ - char *dispName; /* Name of new display. */ - int screenIndex; /* Index of new screen. */ +ChangeScreen( + Tcl_Interp *interp, /* Interpreter in which to invoke command. */ + char *dispName, /* Name of new display. */ + int screenIndex) /* Index of new screen. */ { Tcl_DString cmd; int code; @@ -2718,21 +2673,21 @@ ChangeScreen(interp, dispName, screenIndex) Tcl_DStringAppend(&cmd, screen, -1); code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), TCL_EVAL_GLOBAL); + Tcl_DStringFree(&cmd); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (changing screen in event binding)"); Tcl_BackgroundError(interp); } } - /* *---------------------------------------------------------------------- * * Tk_EventCmd -- * - * This procedure is invoked to process the "event" Tcl command. - * It is used to define and generate events. + * This function is invoked to process the "event" Tcl command. It is + * used to define and generate events. * * Results: * A standard Tcl result. @@ -2744,17 +2699,17 @@ ChangeScreen(interp, dispName, screenIndex) */ int -Tk_EventObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_EventObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { int index; Tk_Window tkwin; VirtualEventTable *vetPtr; TkBindInfo bindInfo; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "add", "delete", "generate", "info", NULL }; @@ -2776,64 +2731,61 @@ Tk_EventObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case EVENT_ADD: { - int i; - char *name, *event; - - if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "virtual sequence ?sequence ...?"); - return TCL_ERROR; - } - name = Tcl_GetStringFromObj(objv[2], NULL); - for (i = 3; i < objc; i++) { - event = Tcl_GetStringFromObj(objv[i], NULL); - if (CreateVirtualEvent(interp, vetPtr, name, event) != TCL_OK) { - return TCL_ERROR; - } - } - break; + case EVENT_ADD: { + int i; + char *name, *event; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, + "virtual sequence ?sequence ...?"); + return TCL_ERROR; } - case EVENT_DELETE: { - int i; - char *name, *event; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, - "virtual ?sequence sequence ...?"); + name = Tcl_GetString(objv[2]); + for (i = 3; i < objc; i++) { + event = Tcl_GetString(objv[i]); + if (CreateVirtualEvent(interp, vetPtr, name, event) != TCL_OK) { return TCL_ERROR; } - name = Tcl_GetStringFromObj(objv[2], NULL); - if (objc == 3) { - return DeleteVirtualEvent(interp, vetPtr, name, NULL); - } - for (i = 3; i < objc; i++) { - event = Tcl_GetStringFromObj(objv[i], NULL); - if (DeleteVirtualEvent(interp, vetPtr, name, event) != TCL_OK) { - return TCL_ERROR; - } - } - break; } - case EVENT_GENERATE: { - if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, "window event ?options?"); - return TCL_ERROR; - } - return HandleEventGenerate(interp, tkwin, objc - 2, objv + 2); + break; + } + case EVENT_DELETE: { + int i; + char *name, *event; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "virtual ?sequence sequence ...?"); + return TCL_ERROR; } - case EVENT_INFO: { - if (objc == 2) { - GetAllVirtualEvents(interp, vetPtr); - return TCL_OK; - } else if (objc == 3) { - return GetVirtualEvent(interp, vetPtr, - Tcl_GetStringFromObj(objv[2], NULL)); - } else { - Tcl_WrongNumArgs(interp, 2, objv, "?virtual?"); + name = Tcl_GetString(objv[2]); + if (objc == 3) { + return DeleteVirtualEvent(interp, vetPtr, name, NULL); + } + for (i = 3; i < objc; i++) { + event = Tcl_GetString(objv[i]); + if (DeleteVirtualEvent(interp, vetPtr, name, event) != TCL_OK) { return TCL_ERROR; } } + break; + } + case EVENT_GENERATE: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window event ?options?"); + return TCL_ERROR; + } + return HandleEventGenerate(interp, tkwin, objc - 2, objv + 2); + case EVENT_INFO: + if (objc == 2) { + GetAllVirtualEvents(interp, vetPtr); + return TCL_OK; + } else if (objc == 3) { + return GetVirtualEvent(interp, vetPtr, Tcl_GetString(objv[2])); + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?virtual?"); + return TCL_ERROR; + } } return TCL_OK; } @@ -2843,8 +2795,8 @@ Tk_EventObjCmd(clientData, interp, objc, objv) * * InitVirtualEventTable -- * - * Given storage for a virtual event table, set up the fields to - * prepare a new domain in which virtual events may be defined. + * Given storage for a virtual event table, set up the fields to prepare + * a new domain in which virtual events may be defined. * * Results: * None. @@ -2856,9 +2808,9 @@ Tk_EventObjCmd(clientData, interp, objc, objv) */ static void -InitVirtualEventTable(vetPtr) - VirtualEventTable *vetPtr; /* Pointer to virtual event table. Memory - * is supplied by the caller. */ +InitVirtualEventTable( + VirtualEventTable *vetPtr) /* Pointer to virtual event table. Memory is + * supplied by the caller. */ { Tcl_InitHashTable(&vetPtr->patternTable, sizeof(PatternTableKey) / sizeof(int)); @@ -2870,7 +2822,7 @@ InitVirtualEventTable(vetPtr) * * DeleteVirtualEventTable -- * - * Delete the contents of a virtual event table. The caller is + * Delete the contents of a virtual event table. The caller is * responsible for freeing any memory used by the table itself. * * Results: @@ -2883,8 +2835,8 @@ InitVirtualEventTable(vetPtr) */ static void -DeleteVirtualEventTable(vetPtr) - VirtualEventTable *vetPtr; /* The virtual event table to delete. */ +DeleteVirtualEventTable( + VirtualEventTable *vetPtr) /* The virtual event table to delete. */ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -2903,7 +2855,7 @@ DeleteVirtualEventTable(vetPtr) hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search); for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - ckfree((char *) Tcl_GetHashValue(hPtr)); + ckfree((char *) Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(&vetPtr->nameTable); } @@ -2913,29 +2865,27 @@ DeleteVirtualEventTable(vetPtr) * * CreateVirtualEvent -- * - * Add a new definition for a virtual event. If the virtual event - * is already defined, the new definition augments those that - * already exist. + * Add a new definition for a virtual event. If the virtual event is + * already defined, the new definition augments those that already exist. * * Results: - * The return value is TCL_ERROR if an error occured 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. + * The return value is TCL_ERROR if an error occured 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. * * Side effects: - * The virtual event may cause future calls to Tk_BindEvent to - * behave differently than they did previously. + * The virtual event may cause future calls to Tk_BindEvent to behave + * differently than they did previously. * *---------------------------------------------------------------------- */ static int -CreateVirtualEvent(interp, vetPtr, virtString, eventString) - Tcl_Interp *interp; /* Used for error reporting. */ - VirtualEventTable *vetPtr;/* Table in which to augment virtual event. */ - char *virtString; /* Name of new virtual event. */ - char *eventString; /* String describing physical event that +CreateVirtualEvent( + Tcl_Interp *interp, /* Used for error reporting. */ + VirtualEventTable *vetPtr, /* Table in which to augment virtual event. */ + char *virtString, /* Name of new virtual event. */ + char *eventString) /* String describing physical event that * triggers virtual event. */ { PatSeq *psPtr; @@ -2945,10 +2895,10 @@ CreateVirtualEvent(interp, vetPtr, virtString, eventString) PhysicalsOwned *poPtr; VirtualOwners *voPtr; Tk_Uid virtUid; - + virtUid = GetVirtualEventUid(interp, virtString); if (virtUid == NULL) { - return TCL_ERROR; + return TCL_ERROR; } /* @@ -2958,7 +2908,7 @@ CreateVirtualEvent(interp, vetPtr, virtString, eventString) psPtr = FindSequence(interp, &vetPtr->patternTable, NULL, eventString, 1, 0, &eventMask); if (psPtr == NULL) { - return TCL_ERROR; + return TCL_ERROR; } /* @@ -2976,20 +2926,21 @@ CreateVirtualEvent(interp, vetPtr, virtString, eventString) poPtr = (PhysicalsOwned *) ckalloc(sizeof(PhysicalsOwned)); poPtr->numOwned = 0; } else { - /* + /* * See if this virtual event is already defined for this physical * event and just return if it is. */ int i; + for (i = 0; i < poPtr->numOwned; i++) { if (poPtr->patSeqs[i] == psPtr) { - return TCL_OK; + return TCL_OK; } } poPtr = (PhysicalsOwned *) ckrealloc((char *) poPtr, sizeof(PhysicalsOwned) + poPtr->numOwned * sizeof(PatSeq *)); - } + } Tcl_SetHashValue(vhPtr, (ClientData) poPtr); poPtr->patSeqs[poPtr->numOwned] = psPtr; poPtr->numOwned++; @@ -3000,10 +2951,10 @@ CreateVirtualEvent(interp, vetPtr, virtString, eventString) voPtr = psPtr->voPtr; if (voPtr == NULL) { - voPtr = (VirtualOwners *) ckalloc(sizeof(VirtualOwners)); + voPtr = (VirtualOwners *) ckalloc(sizeof(VirtualOwners)); voPtr->numOwners = 0; } else { - voPtr = (VirtualOwners *) ckrealloc((char *) voPtr, + voPtr = (VirtualOwners *) ckrealloc((char *) voPtr, sizeof(VirtualOwners) + voPtr->numOwners * sizeof(Tcl_HashEntry *)); } @@ -3019,31 +2970,31 @@ CreateVirtualEvent(interp, vetPtr, virtString, eventString) * * DeleteVirtualEvent -- * - * Remove the definition of a given virtual event. If the - * event string is NULL, all definitions of the virtual event - * will be removed. Otherwise, just the specified definition - * of the virtual event will be removed. + * Remove the definition of a given virtual event. If the event string is + * NULL, all definitions of the virtual event will be removed. + * Otherwise, just the specified definition of the virtual event will be + * removed. * * Results: - * The result is a standard Tcl return value. If an error - * occurs then the interp's result will contain an error message. - * It is not an error to attempt to delete a virtual event that - * does not exist or a definition that does not exist. + * The result is a standard Tcl return value. If an error occurs then the + * interp's result will contain an error message. It is not an error to + * attempt to delete a virtual event that does not exist or a definition + * that does not exist. * * Side effects: - * The virtual event given by virtString may be removed from the - * virtual event table. + * The virtual event given by virtString may be removed from the virtual + * event table. * *-------------------------------------------------------------- */ static int -DeleteVirtualEvent(interp, vetPtr, virtString, eventString) - Tcl_Interp *interp; /* Used for error reporting. */ - VirtualEventTable *vetPtr;/* Table in which to delete event. */ - char *virtString; /* String describing event sequence that +DeleteVirtualEvent( + Tcl_Interp *interp, /* Used for error reporting. */ + VirtualEventTable *vetPtr, /* Table in which to delete event. */ + char *virtString, /* String describing event sequence that * triggers binding. */ - char *eventString; /* The event sequence that should be deleted, + char *eventString) /* The event sequence that should be deleted, * or NULL to delete all event sequences for * the entire virtual event. */ { @@ -3055,12 +3006,12 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) virtUid = GetVirtualEventUid(interp, virtString); if (virtUid == NULL) { - return TCL_ERROR; + return TCL_ERROR; } - + vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid); if (vhPtr == NULL) { - return TCL_OK; + return TCL_OK; } poPtr = (PhysicalsOwned *) Tcl_GetHashValue(vhPtr); @@ -3069,28 +3020,27 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) unsigned long eventMask; /* - * Delete only the specific physical event associated with the - * virtual event. If the physical event doesn't already exist, or - * the virtual event doesn't own that physical event, return w/o - * doing anything. + * Delete only the specific physical event associated with the virtual + * event. If the physical event doesn't already exist, or the virtual + * event doesn't own that physical event, return w/o doing anything. */ eventPSPtr = FindSequence(interp, &vetPtr->patternTable, NULL, eventString, 0, 0, &eventMask); if (eventPSPtr == NULL) { - CONST char *string; + const char *string = Tcl_GetStringResult(interp); - string = Tcl_GetStringResult(interp); return (string[0] != '\0') ? TCL_ERROR : TCL_OK; } } for (iPhys = poPtr->numOwned; --iPhys >= 0; ) { PatSeq *psPtr = poPtr->patSeqs[iPhys]; + if ((eventPSPtr == NULL) || (psPtr == eventPSPtr)) { int iVirt; VirtualOwners *voPtr; - + /* * Remove association between this physical event and the given * virtual event that it triggers. @@ -3103,15 +3053,17 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) } } if (iVirt == voPtr->numOwners) { - panic("DeleteVirtualEvent: couldn't find owner"); + Tcl_Panic("DeleteVirtualEvent: couldn't find owner"); } voPtr->numOwners--; if (voPtr->numOwners == 0) { /* - * Removed last reference to this physical event, so - * remove it from physical->virtual map. + * Removed last reference to this physical event, so remove it + * from physical->virtual map. */ + PatSeq *prevPtr = (PatSeq *) Tcl_GetHashValue(psPtr->hPtr); + if (prevPtr == psPtr) { if (psPtr->nextSeqPtr == NULL) { Tcl_DeleteHashEntry(psPtr->hPtr); @@ -3122,7 +3074,7 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) } else { for ( ; ; prevPtr = prevPtr->nextSeqPtr) { if (prevPtr == NULL) { - panic("DeleteVirtualEvent couldn't find on hash chain"); + Tcl_Panic("DeleteVirtualEvent couldn't find on hash chain"); } if (prevPtr->nextSeqPtr == psPtr) { prevPtr->nextSeqPtr = psPtr->nextSeqPtr; @@ -3135,23 +3087,23 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) } else { /* * This physical event still triggers some other virtual - * event(s). Consolidate the list of virtual owners for - * this physical event so it no longer triggers the - * given virtual event. + * event(s). Consolidate the list of virtual owners for this + * physical event so it no longer triggers the given virtual + * event. */ + voPtr->owners[iVirt] = voPtr->owners[voPtr->numOwners]; } /* - * Now delete the virtual event's reference to the physical - * event. + * Now delete the virtual event's reference to the physical event. */ poPtr->numOwned--; if (eventPSPtr != NULL && poPtr->numOwned != 0) { - /* - * Just deleting this one physical event. Consolidate list - * of owned physical events and return. + /* + * Just deleting this one physical event. Consolidate list of + * owned physical events and return. */ poPtr->patSeqs[iPhys] = poPtr->patSeqs[poPtr->numOwned]; @@ -3162,10 +3114,10 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) if (poPtr->numOwned == 0) { /* - * All the physical events for this virtual event were deleted, - * either because there was only one associated physical event or - * because the caller was deleting the entire virtual event. Now - * the virtual event itself should be deleted. + * All the physical events for this virtual event were deleted, either + * because there was only one associated physical event or because the + * caller was deleting the entire virtual event. Now the virtual event + * itself should be deleted. */ ckfree((char *) poPtr); @@ -3179,16 +3131,16 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) * * GetVirtualEvent -- * - * Return the list of physical events that can invoke the - * given virtual event. + * Return the list of physical events that can invoke the given virtual + * event. * * Results: * The return value is TCL_OK and the interp's result is filled with the * string representation of the physical events associated with the * virtual event; if there are no physical events for the given virtual - * event, the interp's result is filled with and empty string. If the - * virtual event string is improperly formed, then TCL_ERROR is - * returned and an error message is left in the interp's result. + * event, the interp's result is filled with and empty string. If the + * virtual event string is improperly formed, then TCL_ERROR is returned + * and an error message is left in the interp's result. * * Side effects: * None. @@ -3197,10 +3149,10 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString) */ static int -GetVirtualEvent(interp, vetPtr, virtString) - Tcl_Interp *interp; /* Interpreter for reporting. */ - VirtualEventTable *vetPtr;/* Table in which to look for event. */ - char *virtString; /* String describing virtual event. */ +GetVirtualEvent( + Tcl_Interp *interp, /* Interpreter for reporting. */ + VirtualEventTable *vetPtr, /* Table in which to look for event. */ + char *virtString) /* String describing virtual event. */ { Tcl_HashEntry *vhPtr; Tcl_DString ds; @@ -3210,12 +3162,12 @@ GetVirtualEvent(interp, vetPtr, virtString) virtUid = GetVirtualEventUid(interp, virtString); if (virtUid == NULL) { - return TCL_ERROR; + return TCL_ERROR; } vhPtr = Tcl_FindHashEntry(&vetPtr->nameTable, virtUid); if (vhPtr == NULL) { - return TCL_OK; + return TCL_OK; } Tcl_DStringInit(&ds); @@ -3236,13 +3188,12 @@ GetVirtualEvent(interp, vetPtr, virtString) * * GetAllVirtualEvents -- * - * Return a list that contains the names of all the virtual - * event defined. + * Return a list that contains the names of all the virtual event + * defined. * * Results: - * There is no return value. The interp's result is modified to - * hold a Tcl list with one entry for each virtual event in - * nameTable. + * There is no return value. The interp's result is modified to hold a + * Tcl list with one entry for each virtual event in nameTable. * * Side effects: * None. @@ -3251,9 +3202,9 @@ GetVirtualEvent(interp, vetPtr, virtString) */ static void -GetAllVirtualEvents(interp, vetPtr) - Tcl_Interp *interp; /* Interpreter returning result. */ - VirtualEventTable *vetPtr;/* Table containing events. */ +GetAllVirtualEvents( + Tcl_Interp *interp, /* Interpreter returning result. */ + VirtualEventTable *vetPtr) /* Table containing events. */ { Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -3263,11 +3214,11 @@ GetAllVirtualEvents(interp, vetPtr) hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search); for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_DStringSetLength(&ds, 0); + Tcl_DStringSetLength(&ds, 0); Tcl_DStringAppend(&ds, "<<", 2); Tcl_DStringAppend(&ds, Tcl_GetHashKey(hPtr->tablePtr, hPtr), -1); Tcl_DStringAppend(&ds, ">>", 2); - Tcl_AppendElement(interp, Tcl_DStringValue(&ds)); + Tcl_AppendElement(interp, Tcl_DStringValue(&ds)); } Tcl_DStringFree(&ds); @@ -3278,45 +3229,45 @@ GetAllVirtualEvents(interp, vetPtr) * * HandleEventGenerate -- * - * Helper function for the "event generate" command. Generate and - * process an XEvent, constructed from information parsed from the - * event description string and its optional arguments. + * Helper function for the "event generate" command. Generate and process + * an XEvent, constructed from information parsed from the event + * description string and its optional arguments. * * argv[0] contains name of the target window. * argv[1] contains pattern string for one event (e.g, <Control-v>). - * argv[2..argc-1] contains -field/option pairs for specifying - * additional detail in the generated event. + * argv[2..argc-1] contains -field/option pairs for specifying additional + * detail in the generated event. * - * Either virtual or physical events can be generated this way. - * The event description string must contain the specification - * for only one event. + * Either virtual or physical events can be generated this way. The event + * description string must contain the specification for only one event. * * Results: * None. * * Side effects: - * When constructing the event, - * event.xany.serial is filled with the current X serial number. - * event.xany.window is filled with the target window. - * event.xany.display is filled with the target window's display. + * When constructing the event, + * event.xany.serial is filled with the current X serial number. + * event.xany.window is filled with the target window. + * event.xany.display is filled with the target window's display. * 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 value specified by the optional "-when" option. The - * default setting is synchronous. + * The event may be handled sychronously or asynchronously, depending on + * the value specified by the optional "-when" option. The default + * setting is synchronous. * *--------------------------------------------------------------------------- */ + static int -HandleEventGenerate(interp, mainWin, objc, objv) - Tcl_Interp *interp; /* Interp for errors return and name lookup. */ - Tk_Window mainWin; /* Main window associated with interp. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +HandleEventGenerate( + Tcl_Interp *interp, /* Interp for errors return and name lookup. */ + Tk_Window mainWin, /* Main window associated with interp. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - XEvent event; - CONST char *p; + union {XEvent general; XVirtualEvent virtual;} event; + const char *p; char *name, *windowName; int count, flags, synch, i, number, warp; Tcl_QueuePosition pos; @@ -3324,10 +3275,11 @@ HandleEventGenerate(interp, mainWin, objc, objv) Tk_Window tkwin, tkwin2; TkWindow *mainPtr; unsigned long eventMask; - static CONST char *fieldStrings[] = { + Tcl_Obj *userDataObj; + static const char *fieldStrings[] = { "-when", "-above", "-borderwidth", "-button", - "-count", "-delta", "-detail", "-focus", - "-height", + "-count", "-data", "-delta", "-detail", + "-focus", "-height", "-keycode", "-keysym", "-mode", "-override", "-place", "-root", "-rootx", "-rooty", "-sendevent", "-serial", "-state", "-subwindow", @@ -3336,8 +3288,8 @@ HandleEventGenerate(interp, mainWin, objc, objv) }; enum field { EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON, - EVENT_COUNT, EVENT_DELTA, EVENT_DETAIL, EVENT_FOCUS, - EVENT_HEIGHT, + EVENT_COUNT, EVENT_DATA, EVENT_DELTA, EVENT_DETAIL, + EVENT_FOCUS, EVENT_HEIGHT, EVENT_KEYCODE, EVENT_KEYSYM, EVENT_MODE, EVENT_OVERRIDE, EVENT_PLACE, EVENT_ROOT, EVENT_ROOTX, EVENT_ROOTY, EVENT_SEND, EVENT_SERIAL, EVENT_STATE, EVENT_SUBWINDOW, @@ -3345,7 +3297,7 @@ HandleEventGenerate(interp, mainWin, objc, objv) EVENT_X, EVENT_Y }; - windowName = Tcl_GetStringFromObj(objv[0], NULL); + windowName = Tcl_GetString(objv[0]); if (!windowName[0]) { tkwin = mainWin; } else if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) { @@ -3355,18 +3307,16 @@ HandleEventGenerate(interp, mainWin, objc, objv) mainPtr = (TkWindow *) mainWin; if ((tkwin == NULL) || (mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) { - char *name; - - name = Tcl_GetStringFromObj(objv[0], NULL); - Tcl_AppendResult(interp, "window id \"", name, - "\" doesn't exist in this application", (char *) NULL); + Tcl_AppendResult(interp, "window id \"", Tcl_GetString(objv[0]), + "\" doesn't exist in this application", NULL); return TCL_ERROR; } - name = Tcl_GetStringFromObj(objv[1], NULL); + name = Tcl_GetString(objv[1]); p = name; eventMask = 0; + userDataObj = NULL; count = ParseEventDescription(interp, &p, &pat, &eventMask); if (count == 0) { return TCL_ERROR; @@ -3382,48 +3332,49 @@ HandleEventGenerate(interp, mainWin, objc, objv) return TCL_ERROR; } - memset((VOID *) &event, 0, sizeof(event)); - event.xany.type = pat.eventType; - event.xany.serial = NextRequest(Tk_Display(tkwin)); - event.xany.send_event = False; + memset((void *) &event, 0, sizeof(event)); + event.general.xany.type = pat.eventType; + event.general.xany.serial = NextRequest(Tk_Display(tkwin)); + event.general.xany.send_event = False; if (windowName[0]) { - event.xany.window = Tk_WindowId(tkwin); + event.general.xany.window = Tk_WindowId(tkwin); } else { - event.xany.window = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)); + event.general.xany.window = + RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin)); } - event.xany.display = Tk_Display(tkwin); + event.general.xany.display = Tk_Display(tkwin); - flags = flagArray[event.xany.type]; + flags = flagArray[event.general.xany.type]; if (flags & DESTROY) { /* - * Event DesotryNotify should be generated by destroying - * the window. + * Event DestroyNotify should be generated by destroying the window. */ + Tk_DestroyWindow(tkwin); return TCL_OK; } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { - event.xkey.state = pat.needMods; - if ((flags & KEY) && (event.xany.type != MouseWheelEvent)) { - TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event); + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + event.general.xkey.state = pat.needMods; + if ((flags & KEY) && (event.general.xany.type != MouseWheelEvent)) { + TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event.general); } else if (flags & BUTTON) { - event.xbutton.button = pat.detail.button; + event.general.xbutton.button = pat.detail.button; } else if (flags & VIRTUAL) { - ((XVirtualEvent *) &event)->name = pat.detail.name; + event.virtual.name = pat.detail.name; } } if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) { - event.xcreatewindow.window = event.xany.window; + event.general.xcreatewindow.window = event.general.xany.window; } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.x_root = -1; - event.xkey.y_root = -1; + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.x_root = -1; + event.general.xkey.y_root = -1; } /* - * Process the remaining arguments to fill in additional fields - * of the event. + * Process the remaining arguments to fill in additional fields of the + * event. */ synch = 1; @@ -3432,7 +3383,7 @@ HandleEventGenerate(interp, mainWin, objc, objv) for (i = 2; i < objc; i += 2) { Tcl_Obj *optionPtr, *valuePtr; int index; - + optionPtr = objv[i]; valuePtr = objv[i + 1]; @@ -3442,446 +3393,451 @@ HandleEventGenerate(interp, mainWin, objc, objv) } if (objc & 1) { /* - * This test occurs after Tcl_GetIndexFromObj() so that - * "event generate <Button> -xyz" will return the error message - * that "-xyz" is a bad option, rather than that the value - * for "-xyz" is missing. + * This test occurs after Tcl_GetIndexFromObj() so that "event + * generate <Button> -xyz" will return the error message that + * "-xyz" is a bad option, rather than that the value for "-xyz" + * is missing. */ - Tcl_AppendResult(interp, "value for \"", - Tcl_GetStringFromObj(optionPtr, NULL), "\" missing", - (char *) NULL); + Tcl_AppendResult(interp, "value for \"", Tcl_GetString(optionPtr), + "\" missing", NULL); return TCL_ERROR; } switch ((enum field) index) { - case EVENT_WARP: { - if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) { - return TCL_ERROR; - } - if (!(flags & (KEY_BUTTON_MOTION_VIRTUAL))) { - goto badopt; - } - break; + case EVENT_WARP: + if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) { + return TCL_ERROR; } - case EVENT_WHEN: { - pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr, - queuePosition, valuePtr); - if ((int) pos < -1) { - return TCL_ERROR; - } - synch = 0; - if ((int) pos == -1) { - synch = 1; - } - break; + if (!(flags & KEY_BUTTON_MOTION_VIRTUAL)) { + goto badopt; } - case EVENT_ABOVE: { - if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { - return TCL_ERROR; - } - if (flags & CONFIG) { - event.xconfigure.above = Tk_WindowId(tkwin2); - } else { - goto badopt; - } - break; + break; + case EVENT_WHEN: + pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr, + queuePosition, valuePtr); + if ((int) pos < -1) { + return TCL_ERROR; } - case EVENT_BORDER: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & (CREATE|CONFIG)) { - event.xcreatewindow.border_width = number; - } else { - goto badopt; - } - break; + synch = 0; + if ((int) pos == -1) { + synch = 1; } - case EVENT_BUTTON: { - if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & BUTTON) { - event.xbutton.button = number; - } else { - goto badopt; - } - break; + break; + case EVENT_ABOVE: + if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { + return TCL_ERROR; } - case EVENT_COUNT: { - if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & EXPOSE) { - event.xexpose.count = number; - } else { - goto badopt; - } - break; + if (flags & CONFIG) { + event.general.xconfigure.above = Tk_WindowId(tkwin2); + } else { + goto badopt; } - case EVENT_DELTA: { - if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if ((flags & KEY) && (event.xkey.type == MouseWheelEvent)) { - event.xkey.keycode = number; - } else { - goto badopt; - } - break; + break; + case EVENT_BORDER: + if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { + return TCL_ERROR; } - case EVENT_DETAIL: { - number = TkFindStateNumObj(interp, optionPtr, notifyDetail, - valuePtr); - if (number < 0) { - return TCL_ERROR; - } - if (flags & FOCUS) { - event.xfocus.detail = number; - } else if (flags & CROSSING) { - event.xcrossing.detail = number; - } else { - goto badopt; - } - break; + if (flags & (CREATE|CONFIG)) { + event.general.xcreatewindow.border_width = number; + } else { + goto badopt; } - case EVENT_FOCUS: { - if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & CROSSING) { - event.xcrossing.focus = number; - } else { - goto badopt; - } - break; + break; + case EVENT_BUTTON: + if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; } - case EVENT_HEIGHT: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & EXPOSE) { - event.xexpose.height = number; - } else if (flags & CONFIG) { - event.xconfigure.height = number; - } else { - goto badopt; - } - break; + if (flags & BUTTON) { + event.general.xbutton.button = number; + } else { + goto badopt; } - case EVENT_KEYCODE: { - if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if ((flags & KEY) && (event.xkey.type != MouseWheelEvent)) { - event.xkey.keycode = number; - } else { - goto badopt; - } - break; + break; + case EVENT_COUNT: + if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & EXPOSE) { + event.general.xexpose.count = number; + } else { + goto badopt; } - case EVENT_KEYSYM: { - KeySym keysym; - char *value; + break; + case EVENT_DATA: + if (flags & VIRTUAL) { + /* + * Do not increment reference count until after parsing + * completes and we know that the event generation is really + * going to happen. + */ - value = Tcl_GetStringFromObj(valuePtr, NULL); - keysym = TkStringToKeysym(value); - if (keysym == NoSymbol) { - Tcl_AppendResult(interp, "unknown keysym \"", value, "\"", - (char *) NULL); - return TCL_ERROR; - } + userDataObj = valuePtr; + } else { + goto badopt; + } + break; + case EVENT_DELTA: + if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; + } + if ((flags & KEY) && (event.general.xkey.type == MouseWheelEvent)) { + event.general.xkey.keycode = number; + } else { + goto badopt; + } + break; + case EVENT_DETAIL: + number = TkFindStateNumObj(interp, optionPtr, notifyDetail, + valuePtr); + if (number < 0) { + return TCL_ERROR; + } + if (flags & FOCUS) { + event.general.xfocus.detail = number; + } else if (flags & CROSSING) { + event.general.xcrossing.detail = number; + } else { + goto badopt; + } + break; + case EVENT_FOCUS: + if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & CROSSING) { + event.general.xcrossing.focus = number; + } else { + goto badopt; + } + break; + case EVENT_HEIGHT: + if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, + &number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & EXPOSE) { + event.general.xexpose.height = number; + } else if (flags & CONFIG) { + event.general.xconfigure.height = number; + } else { + goto badopt; + } + break; + case EVENT_KEYCODE: + if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; + } + if ((flags & KEY) && (event.general.xkey.type != MouseWheelEvent)) { + event.general.xkey.keycode = number; + } else { + goto badopt; + } + break; + case EVENT_KEYSYM: { + KeySym keysym; + char *value; + + value = Tcl_GetString(valuePtr); + keysym = TkStringToKeysym(value); + if (keysym == NoSymbol) { + Tcl_AppendResult(interp, "unknown keysym \"", value, "\"", + NULL); + return TCL_ERROR; + } - TkpSetKeycodeAndState(tkwin, keysym, &event); - if (event.xkey.keycode == 0) { - Tcl_AppendResult(interp, "no keycode for keysym \"", value, - "\"", (char *) NULL); - return TCL_ERROR; - } - if (!(flags & KEY) || (event.xkey.type == MouseWheelEvent)) { - goto badopt; - } - break; + TkpSetKeycodeAndState(tkwin, keysym, &event.general); + if (event.general.xkey.keycode == 0) { + Tcl_AppendResult(interp, "no keycode for keysym \"", value, + "\"", NULL); + return TCL_ERROR; } - case EVENT_MODE: { - number = TkFindStateNumObj(interp, optionPtr, notifyMode, - valuePtr); - if (number < 0) { - return TCL_ERROR; - } - if (flags & CROSSING) { - event.xcrossing.mode = number; - } else if (flags & FOCUS) { - event.xfocus.mode = number; - } else { - goto badopt; - } - break; + if (!(flags & KEY) + || (event.general.xkey.type == MouseWheelEvent)) { + goto badopt; } - case EVENT_OVERRIDE: { - if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & CREATE) { - event.xcreatewindow.override_redirect = number; - } else if (flags & MAP) { - event.xmap.override_redirect = number; - } else if (flags & REPARENT) { - event.xreparent.override_redirect = number; - } else if (flags & CONFIG) { - event.xconfigure.override_redirect = number; - } else { - goto badopt; - } - break; + break; + } + case EVENT_MODE: + number = TkFindStateNumObj(interp,optionPtr,notifyMode,valuePtr); + if (number < 0) { + return TCL_ERROR; } - case EVENT_PLACE: { - number = TkFindStateNumObj(interp, optionPtr, circPlace, - valuePtr); - if (number < 0) { - return TCL_ERROR; - } - if (flags & CIRC) { - event.xcirculate.place = number; - } else { - goto badopt; - } - break; + if (flags & CROSSING) { + event.general.xcrossing.mode = number; + } else if (flags & FOCUS) { + event.general.xfocus.mode = number; + } else { + goto badopt; } - case EVENT_ROOT: { - if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { - return TCL_ERROR; - } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.root = Tk_WindowId(tkwin2); - } else { - goto badopt; - } - break; + break; + case EVENT_OVERRIDE: + if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; } - case EVENT_ROOTX: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.x_root = number; - } else { - goto badopt; - } - break; + if (flags & CREATE) { + event.general.xcreatewindow.override_redirect = number; + } else if (flags & MAP) { + event.general.xmap.override_redirect = number; + } else if (flags & REPARENT) { + event.general.xreparent.override_redirect = number; + } else if (flags & CONFIG) { + event.general.xconfigure.override_redirect = number; + } else { + goto badopt; } - case EVENT_ROOTY: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) { - return TCL_ERROR; - } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.y_root = number; - } else { - goto badopt; - } - break; + break; + case EVENT_PLACE: + number = TkFindStateNumObj(interp, optionPtr, circPlace, valuePtr); + if (number < 0) { + return TCL_ERROR; + } + if (flags & CIRC) { + event.general.xcirculate.place = number; + } else { + goto badopt; + } + break; + case EVENT_ROOT: + if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { + return TCL_ERROR; } - case EVENT_SEND: { - CONST char *value; + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.root = Tk_WindowId(tkwin2); + } else { + goto badopt; + } + break; + case EVENT_ROOTX: + if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.x_root = number; + } else { + goto badopt; + } + break; + case EVENT_ROOTY: + if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.y_root = number; + } else { + goto badopt; + } + break; + case EVENT_SEND: { + const char *value; - value = Tcl_GetStringFromObj(valuePtr, NULL); - if (isdigit(UCHAR(value[0]))) { - /* - * Allow arbitrary integer values for the field; they - * are needed by a few of the tests in the Tk test suite. - */ + value = Tcl_GetString(valuePtr); + if (isdigit(UCHAR(value[0]))) { + /* + * Allow arbitrary integer values for the field; they are + * needed by a few of the tests in the Tk test suite. + */ - if (Tcl_GetIntFromObj(interp, valuePtr, &number) - != TCL_OK) { - return TCL_ERROR; - } - } else { - if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) - != TCL_OK) { - return TCL_ERROR; - } - } - event.xany.send_event = number; - break; - } - case EVENT_SERIAL: { if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } - event.xany.serial = number; - break; - } - case EVENT_STATE: { - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - if (Tcl_GetIntFromObj(interp, valuePtr, &number) - != TCL_OK) { - return TCL_ERROR; - } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) { - event.xkey.state = number; - } else { - event.xcrossing.state = number; - } - } else if (flags & VISIBILITY) { - number = TkFindStateNumObj(interp, optionPtr, visNotify, - valuePtr); - if (number < 0) { - return TCL_ERROR; - } - event.xvisibility.state = number; - } else { - goto badopt; - } - break; - } - case EVENT_SUBWINDOW: { - if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { + } else { + if (Tcl_GetBooleanFromObj(interp,valuePtr,&number) != TCL_OK) { return TCL_ERROR; } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.subwindow = Tk_WindowId(tkwin2); - } else { - goto badopt; - } - break; } - case EVENT_TIME: { + event.general.xany.send_event = number; + break; + } + case EVENT_SERIAL: + if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; + } + event.general.xany.serial = number; + break; + case EVENT_STATE: + if (flags & KEY_BUTTON_MOTION_CROSSING) { if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { return TCL_ERROR; } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.time = (Time) number; - } else if (flags & PROP) { - event.xproperty.time = (Time) number; + if (flags & KEY_BUTTON_MOTION_VIRTUAL) { + event.general.xkey.state = number; } else { - goto badopt; + event.general.xcrossing.state = number; } - break; - } - case EVENT_WIDTH: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) - != TCL_OK) { + } else if (flags & VISIBILITY) { + number = TkFindStateNumObj(interp, optionPtr, visNotify, + valuePtr); + if (number < 0) { return TCL_ERROR; } - if (flags & EXPOSE) { - event.xexpose.width = number; - } else if (flags & (CREATE|CONFIG)) { - event.xcreatewindow.width = number; - } else { - goto badopt; - } - break; + event.general.xvisibility.state = number; + } else { + goto badopt; } - case EVENT_WINDOW: { - if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { - return TCL_ERROR; - } - if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG - |GRAVITY|CIRC)) { - event.xcreatewindow.window = Tk_WindowId(tkwin2); - } else { - goto badopt; - } - break; + break; + case EVENT_SUBWINDOW: + if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { + return TCL_ERROR; } - case EVENT_X: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) - != TCL_OK) { - return TCL_ERROR; - } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.x = number; - /* - * Only modify rootx as well if it hasn't been changed. - */ - if (event.xkey.x_root == -1) { - int rootX, rootY; + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.subwindow = Tk_WindowId(tkwin2); + } else { + goto badopt; + } + break; + case EVENT_TIME: + if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.time = (Time) number; + } else if (flags & PROP) { + event.general.xproperty.time = (Time) number; + } else { + goto badopt; + } + break; + case EVENT_WIDTH: + if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & EXPOSE) { + event.general.xexpose.width = number; + } else if (flags & (CREATE|CONFIG)) { + event.general.xcreatewindow.width = number; + } else { + goto badopt; + } + break; + case EVENT_WINDOW: + if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) { + return TCL_ERROR; + } + if (flags & (CREATE|UNMAP|MAP|REPARENT|CONFIG|GRAVITY|CIRC)) { + event.general.xcreatewindow.window = Tk_WindowId(tkwin2); + } else { + goto badopt; + } + break; + case EVENT_X: + if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { + event.general.xkey.x = number; - Tk_GetRootCoords(tkwin, &rootX, &rootY); - event.xkey.x_root = rootX + number; - } - } else if (flags & EXPOSE) { - event.xexpose.x = number; - } else if (flags & (CREATE|CONFIG|GRAVITY)) { - event.xcreatewindow.x = number; - } else if (flags & REPARENT) { - event.xreparent.x = number; - } else { - goto badopt; + /* + * Only modify rootx as well if it hasn't been changed. + */ + + if (event.general.xkey.x_root == -1) { + int rootX, rootY; + + Tk_GetRootCoords(tkwin, &rootX, &rootY); + event.general.xkey.x_root = rootX + number; } - break; + } else if (flags & EXPOSE) { + event.general.xexpose.x = number; + } else if (flags & (CREATE|CONFIG|GRAVITY)) { + event.general.xcreatewindow.x = number; + } else if (flags & REPARENT) { + event.general.xreparent.x = number; + } else { + goto badopt; } - case EVENT_Y: { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) - != TCL_OK) { - return TCL_ERROR; - } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { - event.xkey.y = number; - /* - * Only modify rooty as well if it hasn't been changed. - */ - if (event.xkey.y_root == -1) { - int rootX, rootY; + break; + case EVENT_Y: + if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { + return TCL_ERROR; + } + if (flags & KEY_BUTTON_MOTION_CROSSING) { + event.general.xkey.y = number; - Tk_GetRootCoords(tkwin, &rootX, &rootY); - event.xkey.y_root = rootY + number; - } - } else if (flags & EXPOSE) { - event.xexpose.y = number; - } else if (flags & (CREATE|CONFIG|GRAVITY)) { - event.xcreatewindow.y = number; - } else if (flags & REPARENT) { - event.xreparent.y = number; - } else { - goto badopt; + /* + * Only modify rooty as well if it hasn't been changed. + */ + + if (event.general.xkey.y_root == -1) { + int rootX, rootY; + + Tk_GetRootCoords(tkwin, &rootX, &rootY); + event.general.xkey.y_root = rootY + number; } - break; + } else if (flags & EXPOSE) { + event.general.xexpose.y = number; + } else if (flags & (CREATE|CONFIG|GRAVITY)) { + event.general.xcreatewindow.y = number; + } else if (flags & REPARENT) { + event.general.xreparent.y = number; + } else { + goto badopt; } + break; } continue; - - badopt: + + badopt: Tcl_AppendResult(interp, name, " event doesn't accept \"", - Tcl_GetStringFromObj(optionPtr, NULL), "\" option", NULL); + Tcl_GetString(optionPtr), "\" option", NULL); return TCL_ERROR; } + if (userDataObj != NULL) { + XVirtualEvent *vePtr = (XVirtualEvent *) &event; + + /* + * Must be virtual event to set that variable to non-NULL. Now we want + * to install the object into the event. Note that we must incr the + * refcount before firing it into the low-level event subsystem; the + * refcount will be decremented once the event has been processed. + */ + + vePtr->user_data = userDataObj; + Tcl_IncrRefCount(userDataObj); + } + + /* + * Now we have constructed the event, inject it into the event handling + * code. + */ + if (synch != 0) { - Tk_HandleEvent(&event); + Tk_HandleEvent(&event.general); } else { - Tk_QueueWindowEvent(&event, pos); + Tk_QueueWindowEvent(&event.general, pos); } + /* - * We only allow warping if the window is mapped + * We only allow warping if the window is mapped. */ + if ((warp != 0) && Tk_IsMapped(tkwin)) { - TkDisplay *dispPtr; - dispPtr = TkGetDisplay(event.xmotion.display); + TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display); + if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) { Tcl_DoWhenIdle(DoWarp, (ClientData) dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = event.xany.window; - dispPtr->warpX = event.xkey.x; - dispPtr->warpY = event.xkey.y; + dispPtr->warpWindow = event.general.xany.window; + dispPtr->warpX = event.general.xkey.x; + dispPtr->warpY = event.general.xkey.y; } Tcl_ResetResult(interp); return TCL_OK; - } + static int -NameToWindow(interp, mainWin, objPtr, tkwinPtr) - Tcl_Interp *interp; /* Interp for error return and name lookup. */ - Tk_Window mainWin; /* Main window of application. */ - Tcl_Obj *objPtr; /* Contains name or id string of window. */ - Tk_Window *tkwinPtr; /* Filled with token for window. */ +NameToWindow( + Tcl_Interp *interp, /* Interp for error return and name lookup. */ + Tk_Window mainWin, /* Main window of application. */ + Tcl_Obj *objPtr, /* Contains name or id string of window. */ + Tk_Window *tkwinPtr) /* Filled with token for window. */ { char *name; Tk_Window tkwin; Window id; - name = Tcl_GetStringFromObj(objPtr, NULL); + name = Tcl_GetString(objPtr); if (name[0] == '.') { tkwin = Tk_NameToWindow(interp, name, mainWin); if (tkwin == NULL) { @@ -3891,14 +3847,14 @@ NameToWindow(interp, mainWin, objPtr, tkwinPtr) } else { /* * Check for the winPtr being valid, even if it looks ok to - * TkpScanWindowId. [Bug #411307] + * TkpScanWindowId. [Bug #411307] */ if ((TkpScanWindowId(NULL, name, &id) != TCL_OK) || ((*tkwinPtr = Tk_IdToWindow(Tk_Display(mainWin), id)) == NULL)) { Tcl_AppendResult(interp, "bad window name/identifier \"", - name, "\"", (char *) NULL); + name, "\"", NULL); return TCL_ERROR; } } @@ -3921,13 +3877,13 @@ NameToWindow(interp, mainWin, objPtr, tkwinPtr) *------------------------------------------------------------------------- */ static void -DoWarp(clientData) - ClientData clientData; +DoWarp( + ClientData clientData) { TkDisplay *dispPtr = (TkDisplay *) clientData; XWarpPointer(dispPtr->display, (Window) None, (Window) dispPtr->warpWindow, - 0, 0, 0, 0, (int) dispPtr->warpX, (int) dispPtr->warpY); + 0, 0, 0, 0, (int) dispPtr->warpX, (int) dispPtr->warpY); XForceScreenSaver(dispPtr->display, ScreenSaverReset); dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } @@ -3937,35 +3893,36 @@ DoWarp(clientData) * * GetVirtualEventUid -- * - * Determine if the given string is in the proper format for a - * virtual event. + * Determine if the given string is in the proper format for a virtual + * event. * * Results: - * The return value is NULL if the virtual event string was - * not in the proper format. In this case, an error message - * will be left in the interp's result. Otherwise the return - * value is a Tk_Uid that represents the virtual event. + * The return value is NULL if the virtual event string was not in the + * proper format. In this case, an error message will be left in the + * interp's result. Otherwise the return value is a Tk_Uid that + * represents the virtual event. * * Side effects: * None. * *------------------------------------------------------------------------- */ + static Tk_Uid -GetVirtualEventUid(interp, virtString) - Tcl_Interp *interp; - char *virtString; +GetVirtualEventUid( + Tcl_Interp *interp, + char *virtString) { Tk_Uid uid; - int length; + size_t length; length = strlen(virtString); if (length < 5 || virtString[0] != '<' || virtString[1] != '<' || virtString[length - 2] != '>' || virtString[length - 1] != '>') { - Tcl_AppendResult(interp, "virtual event \"", virtString, - "\" is badly formed", (char *) NULL); - return NULL; + Tcl_AppendResult(interp, "virtual event \"", virtString, + "\" is badly formed", NULL); + return NULL; } virtString[length - 2] = '\0'; uid = Tk_GetUid(virtString + 2); @@ -3973,27 +3930,24 @@ GetVirtualEventUid(interp, virtString) return uid; } - /* *---------------------------------------------------------------------- * * FindSequence -- * - * Find the entry in the pattern table that corresponds to a - * particular pattern string, and return a pointer to that - * entry. + * Find the entry in the pattern table that corresponds to a particular + * pattern string, and return a pointer to that entry. * * Results: - * The return value is normally a pointer to the PatSeq - * in patternTable that corresponds to eventString. If an error - * was found while parsing eventString, or if "create" is 0 and - * no pattern sequence previously existed, then NULL is returned - * and the interp's result contains a message describing the problem. - * If no pattern sequence previously existed for eventString, then - * a new one is created with a NULL command field. In a successful - * return, *maskPtr is filled in with a mask of the event types - * on which the pattern sequence depends. + * The return value is normally a pointer to the PatSeq in patternTable + * that corresponds to eventString. If an error was found while parsing + * eventString, or if "create" is 0 and no pattern sequence previously + * existed, then NULL is returned and the interp's result contains a + * message describing the problem. If no pattern sequence previously + * existed for eventString, then a new one is created with a NULL command + * field. In a successful return, *maskPtr is filled in with a mask of + * the event types on which the pattern sequence depends. * * Side effects: * A new pattern sequence may be allocated. @@ -4002,45 +3956,39 @@ GetVirtualEventUid(interp, virtString) */ static PatSeq * -FindSequence(interp, patternTablePtr, object, eventString, create, - allowVirtual, maskPtr) - Tcl_Interp *interp; /* Interpreter to use for error - * reporting. */ - Tcl_HashTable *patternTablePtr; /* Table to use for lookup. */ - ClientData object; /* For binding table, token for object with - * which binding is associated. - * For virtual event table, NULL. */ - CONST char *eventString; /* String description of pattern to - * match on. See user documentation - * for details. */ - int create; /* 0 means don't create the entry if - * it doesn't already exist. Non-zero - * means create. */ - int allowVirtual; /* 0 means that virtual events are not - * allowed in the sequence. Non-zero - * otherwise. */ - unsigned long *maskPtr; /* *maskPtr is filled in with the event - * types on which this pattern sequence - * depends. */ +FindSequence( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tcl_HashTable *patternTablePtr, + /* Table to use for lookup. */ + ClientData object, /* For binding table, token for object with + * which binding is associated. For virtual + * event table, NULL. */ + const char *eventString, /* String description of pattern to match on. + * See user documentation for details. */ + int create, /* 0 means don't create the entry if it + * doesn't already exist. Non-zero means + * create. */ + int allowVirtual, /* 0 means that virtual events are not allowed + * in the sequence. Non-zero otherwise. */ + unsigned long *maskPtr) /* *maskPtr is filled in with the event types + * on which this pattern sequence depends. */ { - Pattern pats[EVENT_BUFFER_SIZE]; int numPats, virtualFound; - CONST char *p; + const char *p; Pattern *patPtr; PatSeq *psPtr; Tcl_HashEntry *hPtr; - int flags, count, new; + int flags, count, isNew; size_t sequenceSize; unsigned long eventMask; PatternTableKey key; /* *------------------------------------------------------------- - * Step 1: parse the pattern string to produce an array - * of Patterns. The array is generated backwards, so - * that the lowest-indexed pattern corresponds to the last - * event that must occur. + * Step 1: parse the pattern string to produce an array of Patterns. The + * array is generated backwards, so that the lowest-indexed pattern + * corresponds to the last event that must occur. *------------------------------------------------------------- */ @@ -4065,7 +4013,7 @@ FindSequence(interp, patternTablePtr, object, eventString, create, if (eventMask & VirtualEventMask) { if (allowVirtual == 0) { - Tcl_SetResult(interp, + Tcl_SetResult(interp, "virtual event not allowed in definition of another virtual event", TCL_STATIC); return NULL; @@ -4087,8 +4035,8 @@ FindSequence(interp, patternTablePtr, object, eventString, create, /* *------------------------------------------------------------- - * Step 2: find the sequence in the binding table if it exists, - * and add a new sequence to the table if it doesn't. + * Step 2: find the sequence in the binding table if it exists, and add a + * new sequence to the table if it doesn't. *------------------------------------------------------------- */ @@ -4101,15 +4049,15 @@ FindSequence(interp, patternTablePtr, object, eventString, create, TCL_STATIC); return NULL; } - + patPtr = &pats[EVENT_BUFFER_SIZE-numPats]; memset(&key, 0, sizeof(key)); key.object = object; key.type = patPtr->eventType; key.detail = patPtr->detail; - hPtr = Tcl_CreateHashEntry(patternTablePtr, (char *) &key, &new); + hPtr = Tcl_CreateHashEntry(patternTablePtr, (char *) &key, &isNew); sequenceSize = numPats*sizeof(Pattern); - if (!new) { + if (!isNew) { for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = psPtr->nextSeqPtr) { if ((numPats == psPtr->numPats) @@ -4121,17 +4069,18 @@ FindSequence(interp, patternTablePtr, object, eventString, create, } } if (!create) { - if (new) { + if (isNew) { Tcl_DeleteHashEntry(hPtr); } + /* - * No binding exists for the sequence, so return an empty error. - * This is a special error that the caller will check for in order - * to silently ignore this case. This is a hack that maintains - * backward compatibility for Tk_GetBinding but the various "bind" - * commands silently ignore missing bindings. + * No binding exists for the sequence, so return an empty error. This + * is a special error that the caller will check for in order to + * silently ignore this case. This is a hack that maintains backward + * compatibility for Tk_GetBinding but the various "bind" commands + * silently ignore missing bindings. */ - + return NULL; } psPtr = (PatSeq *) ckalloc((unsigned) (sizeof(PatSeq) @@ -4148,9 +4097,9 @@ FindSequence(interp, patternTablePtr, object, eventString, create, psPtr->nextObjPtr = NULL; Tcl_SetHashValue(hPtr, psPtr); - memcpy((VOID *) psPtr->pats, (VOID *) patPtr, sequenceSize); + memcpy((void *) psPtr->pats, (void *) patPtr, sequenceSize); - done: + done: *maskPtr = eventMask; return psPtr; } @@ -4160,34 +4109,31 @@ FindSequence(interp, patternTablePtr, object, eventString, create, * * ParseEventDescription -- * - * Fill Pattern buffer with information about event from - * event string. + * Fill Pattern buffer with information about event from event string. * * Results: - * Leaves error message in interp and returns 0 if there was an - * error due to a badly formed event string. Returns 1 if proper - * event was specified, 2 if Double modifier was used in event - * string, or 3 if Triple was used. + * Leaves error message in interp and returns 0 if there was an error due + * to a badly formed event string. Returns 1 if proper event was + * specified, 2 if Double modifier was used in event string, or 3 if + * Triple was used. * * Side effects: * On exit, eventStringPtr points to rest of event string (after the - * closing '>', so that this procedure can be called repeatedly to - * parse all the events in the entire sequence. + * closing '>', so that this function can be called repeatedly to parse + * all the events in the entire sequence. * *--------------------------------------------------------------------------- */ static int -ParseEventDescription(interp, eventStringPtr, patPtr, - eventMaskPtr) - Tcl_Interp *interp; /* For error messages. */ - CONST char **eventStringPtr;/* On input, holds a pointer to start of - * event string. On exit, gets pointer to - * rest of string after parsed event. */ - Pattern *patPtr; /* Filled with the pattern parsed from the +ParseEventDescription( + Tcl_Interp *interp, /* For error messages. */ + const char **eventStringPtr,/* On input, holds a pointer to start of event + * string. On exit, gets pointer to rest of + * string after parsed event. */ + Pattern *patPtr, /* Filled with the pattern parsed from the * event string. */ - unsigned long *eventMaskPtr;/* Filled with event mask of matched event. */ - + unsigned long *eventMaskPtr)/* Filled with event mask of matched event. */ { char *p; unsigned long eventMask; @@ -4206,7 +4152,7 @@ ParseEventDescription(interp, eventStringPtr, patPtr, eventMask = 0; count = 1; - + /* * Handle simple ASCII characters. */ @@ -4224,7 +4170,7 @@ ParseEventDescription(interp, eventStringPtr, patPtr, patPtr->detail.keySym = *p; } else { char buf[64]; - + sprintf(buf, "bad ASCII character 0x%x", (unsigned char) *p); Tcl_SetResult(interp, buf, TCL_VOLATILE); count = 0; @@ -4236,8 +4182,8 @@ ParseEventDescription(interp, eventStringPtr, patPtr, } /* - * A fancier event description. This can be either a virtual event - * or a physical event. + * A fancier event description. This can be either a virtual event or a + * physical event. * * A virtual event description consists of: * @@ -4248,30 +4194,30 @@ ParseEventDescription(interp, eventStringPtr, patPtr, * A physical event description consists of: * * 1. open angle bracket. - * 2. any number of modifiers, each followed by spaces - * or dashes. + * 2. any number of modifiers, each followed by spaces or dashes. * 3. an optional event name. - * 4. an option button or keysym name. Either this or - * item 3 *must* be present; if both are present - * then they are separated by spaces or dashes. + * 4. an option button or keysym name. Either this or item 3 *must* be + * present; if both are present then they are separated by spaces or + * dashes. * 5. a close angle bracket. */ p++; if (*p == '<') { /* - * This is a virtual event: soak up all the characters up to - * the next '>'. + * This is a virtual event: soak up all the characters up to the next + * '>'. */ - char *field = p + 1; + char *field = p + 1; + p = strchr(field, '>'); if (p == field) { Tcl_SetResult(interp, "virtual event \"<<>>\" is badly formed", TCL_STATIC); count = 0; goto done; - } + } if ((p == NULL) || (p[1] != '>')) { Tcl_SetResult(interp, "missing \">\" in virtual binding", TCL_STATIC); @@ -4290,13 +4236,15 @@ ParseEventDescription(interp, eventStringPtr, patPtr, while (1) { ModInfo *modPtr; + p = GetField(p, field, FIELD_SIZE); if (*p == '>') { /* * This solves the problem of, e.g., <Control-M> being - * misinterpreted as Control + Meta + missing keysym - * instead of Control + KeyPress + M. + * misinterpreted as Control + Meta + missing keysym instead of + * Control + KeyPress + M. */ + break; } hPtr = Tcl_FindHashEntry(&modTable, field); @@ -4305,10 +4253,13 @@ ParseEventDescription(interp, eventStringPtr, patPtr, } modPtr = (ModInfo *) Tcl_GetHashValue(hPtr); patPtr->needMods |= modPtr->mask; - if (modPtr->flags & (MULT_CLICKS)) { + if (modPtr->flags & MULT_CLICKS) { int i = modPtr->flags & MULT_CLICKS; + count = 2; - while (i >>= 1) count++; + while (i >>= 1) { + count++; + } } while ((*p == '-') || isspace(UCHAR(*p))) { p++; @@ -4318,8 +4269,7 @@ ParseEventDescription(interp, eventStringPtr, patPtr, eventFlags = 0; hPtr = Tcl_FindHashEntry(&eventTable, field); if (hPtr != NULL) { - EventInfo *eiPtr; - eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); + EventInfo *eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); patPtr->eventType = eiPtr->type; eventFlags = flagArray[eiPtr->type]; @@ -4338,17 +4288,18 @@ ParseEventDescription(interp, eventStringPtr, patPtr, goto getKeysym; } else if ((eventFlags & BUTTON) == 0) { Tcl_AppendResult(interp, "specified button \"", field, - "\" for non-button event", (char *) NULL); + "\" for non-button event", NULL); count = 0; goto done; } patPtr->detail.button = (*field - '0'); } else { - getKeysym: + + getKeysym: patPtr->detail.keySym = TkStringToKeysym(field); if (patPtr->detail.keySym == NoSymbol) { Tcl_AppendResult(interp, "bad event type or keysym \"", - field, "\"", (char *) NULL); + field, "\"", NULL); count = 0; goto done; } @@ -4357,7 +4308,7 @@ ParseEventDescription(interp, eventStringPtr, patPtr, eventMask = KeyPressMask; } else if ((eventFlags & KEY) == 0) { Tcl_AppendResult(interp, "specified keysym \"", field, - "\" for non-key event", (char *) NULL); + "\" for non-key event", NULL); count = 0; goto done; } @@ -4389,10 +4340,10 @@ ParseEventDescription(interp, eventStringPtr, patPtr, } p++; -end: + end: *eventStringPtr += (p - Tcl_DStringValue(©)); *eventMaskPtr |= eventMask; -done: + done: Tcl_DStringFree(©); return count; } @@ -4402,17 +4353,15 @@ done: * * GetField -- * - * Used to parse pattern descriptions. Copies up to - * size characters from p to copy, stopping at end of - * string, space, "-", ">", or whenever size is - * exceeded. + * Used to parse pattern descriptions. Copies up to size characters from + * p to copy, stopping at end of string, space, "-", ">", or whenever + * size is exceeded. * * Results: - * The return value is a pointer to the character just - * after the last one copied (usually "-" or space or - * ">", but could be anything if size was exceeded). - * Also places NULL-terminated string (up to size - * character, including NULL), at copy. + * The return value is a pointer to the character just after the last one + * copied (usually "-" or space or ">", but could be anything if size was + * exceeded). Also places NULL-terminated string (up to size character, + * including NULL), at copy. * * Side effects: * None. @@ -4421,11 +4370,10 @@ done: */ static char * -GetField(p, copy, size) - char *p; /* Pointer to part of pattern. */ - char *copy; /* Place to copy field. */ - int size; /* Maximum number of characters to - * copy. */ +GetField( + char *p, /* Pointer to part of pattern. */ + char *copy, /* Place to copy field. */ + int size) /* Maximum number of characters to copy. */ { while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '>') && (*p != '-') && (size > 1)) { @@ -4443,22 +4391,23 @@ GetField(p, copy, size) * * GetPatternString -- * - * Produce a string version of the given event, for displaying to - * the user. + * Produce a string version of the given event, for displaying to the + * user. * * Results: * The string is left in dsPtr. * * Side effects: - * It is the caller's responsibility to initialize the DString before - * and to free it after calling this procedure. + * It is the caller's responsibility to initialize the DString before and + * to free it after calling this function. * *--------------------------------------------------------------------------- */ + static void -GetPatternString(psPtr, dsPtr) - PatSeq *psPtr; - Tcl_DString *dsPtr; +GetPatternString( + PatSeq *psPtr, + Tcl_DString *dsPtr) { Pattern *patPtr; char c, buffer[TCL_INTEGER_SPACE]; @@ -4473,19 +4422,17 @@ GetPatternString(psPtr, dsPtr) for (patsLeft = psPtr->numPats, patPtr = &psPtr->pats[psPtr->numPats - 1]; patsLeft > 0; patsLeft--, patPtr--) { - /* * Check for simple case of an ASCII character. */ if ((patPtr->eventType == KeyPress) - && ((psPtr->flags & PAT_NEARBY) == 0) + && ((psPtr->flags & PAT_NEARBY) == 0) && (patPtr->needMods == 0) && (patPtr->detail.keySym < 128) && isprint(UCHAR(patPtr->detail.keySym)) && (patPtr->detail.keySym != '<') && (patPtr->detail.keySym != ' ')) { - c = (char) patPtr->detail.keySym; Tcl_DStringAppend(dsPtr, &c, 1); continue; @@ -4503,12 +4450,13 @@ GetPatternString(psPtr, dsPtr) } /* - * It's a more general event specification. First check - * for "Double", "Triple", "Quadruple", then modifiers, - * then event type, then keysym or button detail. + * It's a more general event specification. First check for "Double", + * "Triple", "Quadruple", then modifiers, then event type, then keysym + * or button detail. */ Tcl_DStringAppend(dsPtr, "<", 1); + if ((psPtr->flags & PAT_NEARBY) && (patsLeft > 1) && (memcmp((char *) patPtr, (char *) (patPtr-1), sizeof(Pattern)) == 0)) { @@ -4530,6 +4478,7 @@ GetPatternString(psPtr, dsPtr) Tcl_DStringAppend(dsPtr, "Double-", 7); } } + for (needMods = patPtr->needMods, modPtr = modArray; needMods != 0; modPtr++) { if (modPtr->mask & needMods) { @@ -4538,6 +4487,7 @@ GetPatternString(psPtr, dsPtr) Tcl_DStringAppend(dsPtr, "-", 1); } } + for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) { if (eiPtr->type == patPtr->eventType) { Tcl_DStringAppend(dsPtr, eiPtr->name, -1); @@ -4551,9 +4501,7 @@ GetPatternString(psPtr, dsPtr) if (patPtr->detail.clientData != 0) { if ((patPtr->eventType == KeyPress) || (patPtr->eventType == KeyRelease)) { - char *string; - - string = TkKeysymToString(patPtr->detail.keySym); + char *string = TkKeysymToString(patPtr->detail.keySym); if (string != NULL) { Tcl_DStringAppend(dsPtr, string, -1); } @@ -4562,6 +4510,7 @@ GetPatternString(psPtr, dsPtr) Tcl_DStringAppend(dsPtr, buffer, -1); } } + Tcl_DStringAppend(dsPtr, ">", 1); } } @@ -4571,8 +4520,8 @@ GetPatternString(psPtr, dsPtr) * * EvalTclBinding -- * - * The procedure that is invoked by Tk_BindEvent when a Tcl binding - * is fired. + * The function that is invoked by Tk_BindEvent when a Tcl binding is + * fired. * * Results: * A standard Tcl result code, the result of globally evaluating the @@ -4585,8 +4534,8 @@ GetPatternString(psPtr, dsPtr) */ static void -FreeTclBinding(clientData) - ClientData clientData; +FreeTclBinding( + ClientData clientData) { ckfree((char *) clientData); } @@ -4596,12 +4545,11 @@ FreeTclBinding(clientData) * * TkStringToKeysym -- * - * This procedure finds the keysym associated with a given keysym - * name. + * This function finds the keysym associated with a given keysym name. * * Results: - * The return value is the keysym that corresponds to name, or - * NoSymbol if there is no such keysym. + * The return value is the keysym that corresponds to name, or NoSymbol + * if there is no such keysym. * * Side effects: * None. @@ -4610,19 +4558,18 @@ FreeTclBinding(clientData) */ KeySym -TkStringToKeysym(name) - char *name; /* Name of a keysym. */ +TkStringToKeysym( + char *name) /* Name of a keysym. */ { #ifdef REDO_KEYSYM_LOOKUP - Tcl_HashEntry *hPtr; - KeySym keysym; + Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&keySymTable, name); - hPtr = Tcl_FindHashEntry(&keySymTable, name); if (hPtr != NULL) { return (KeySym) Tcl_GetHashValue(hPtr); } if (strlen(name) == 1) { - keysym = (KeySym) (unsigned char) name[0]; + KeySym keysym = (KeySym) (unsigned char) name[0]; + if (TkKeysymToString(keysym) != NULL) { return keysym; } @@ -4636,12 +4583,11 @@ TkStringToKeysym(name) * * TkKeysymToString -- * - * This procedure finds the keysym name associated with a given - * keysym. + * This function finds the keysym name associated with a given keysym. * * Results: - * The return value is a pointer to a static string containing - * the name of the given keysym, or NULL if there is no known name. + * The return value is a pointer to a static string containing the name + * of the given keysym, or NULL if there is no known name. * * Side effects: * None. @@ -4650,17 +4596,17 @@ TkStringToKeysym(name) */ char * -TkKeysymToString(keysym) - KeySym keysym; +TkKeysymToString( + KeySym keysym) { #ifdef REDO_KEYSYM_LOOKUP - Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&nameTable, (char *)keysym); - hPtr = Tcl_FindHashEntry(&nameTable, (char *)keysym); if (hPtr != NULL) { return (char *) Tcl_GetHashValue(hPtr); } #endif /* REDO_KEYSYM_LOOKUP */ + return XKeysymToString(keysym); } @@ -4669,25 +4615,24 @@ TkKeysymToString(keysym) * * TkCopyAndGlobalEval -- * - * This procedure makes a copy of a script then passes to Tcl - * to evaluate it. It's used in situations where the execution of - * a command may cause the original command string to be reallocated. + * This function makes a copy of a script then calls Tcl_GlobalEval to + * evaluate it. It's used in situations where the execution of a command + * may cause the original command string to be reallocated. * * Results: - * Returns the result of evaluating script, including both a standard - * Tcl completion code and a string in the interp's result. + * Returns the result of evaluating script, including both a standard Tcl + * completion code and a string in the interp's result. * * Side effects: - * None. + * Any; depends on script. * *---------------------------------------------------------------------- */ int -TkCopyAndGlobalEval(interp, script) - Tcl_Interp *interp; /* Interpreter in which to evaluate - * script. */ - char *script; /* Script to evaluate. */ +TkCopyAndGlobalEval( + Tcl_Interp *interp, /* Interpreter in which to evaluate script. */ + char *script) /* Script to evaluate. */ { Tcl_DString buffer; int code; @@ -4699,5 +4644,40 @@ TkCopyAndGlobalEval(interp, script) Tcl_DStringFree(&buffer); return code; } + +/* + *---------------------------------------------------------------------- + * + * TkpGetBindingXEvent -- + * + * This function returns the XEvent associated with the currently + * executing binding. This function can only be invoked while a binding + * is executing. + * + * Results: + * Returns a pointer to the XEvent that caused the current binding code + * to be run. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +XEvent * +TkpGetBindingXEvent( + Tcl_Interp *interp) /* Interpreter. */ +{ + TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp); + BindingTable *bindPtr = (BindingTable *) winPtr->mainPtr->bindingTable; + return &(bindPtr->eventRing[bindPtr->curEvent]); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkBitmap.c b/generic/tkBitmap.c index 5c8a9fc..09545d6 100644 --- a/generic/tkBitmap.c +++ b/generic/tkBitmap.c @@ -1,43 +1,42 @@ -/* +/* * tkBitmap.c -- * * This file maintains a database of read-only bitmaps for the Tk - * toolkit. This allows bitmaps to be shared between widgets and - * also avoids interactions with the X server. + * toolkit. This allows bitmaps to be shared between widgets and also + * avoids interactions with the X server. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* * The includes below are for pre-defined bitmaps. * - * Platform-specific issue: Windows complains when the bitmaps are - * included, because an array of characters is being initialized with - * integers as elements. For lint purposes, the following pragmas - * temporarily turn off that warning message. + * Platform-specific issue: Windows complains when the bitmaps are included, + * because an array of characters is being initialized with integers as + * elements. For lint purposes, the following pragmas temporarily turn off + * that warning message. */ #if defined(_MSC_VER) #pragma warning (disable : 4305) #endif -#include "error.bmp" -#include "gray12.bmp" -#include "gray25.bmp" -#include "gray50.bmp" -#include "gray75.bmp" -#include "hourglass.bmp" -#include "info.bmp" -#include "questhead.bmp" -#include "question.bmp" -#include "warning.bmp" +#include "error.xbm" +#include "gray12.xbm" +#include "gray25.xbm" +#include "gray50.xbm" +#include "gray75.xbm" +#include "hourglass.xbm" +#include "info.xbm" +#include "questhead.xbm" +#include "question.xbm" +#include "warning.xbm" #if defined(_MSC_VER) #pragma warning (default : 4305) @@ -45,82 +44,80 @@ /* * One of the following data structures exists for each bitmap that is - * currently in use. Each structure is indexed with both "idTable" and + * currently in use. Each structure is indexed with both "idTable" and * "nameTable". */ typedef struct TkBitmap { - Pixmap bitmap; /* X identifier for bitmap. None means this - * bitmap was created by Tk_DefineBitmap - * and it isn't currently in use. */ + Pixmap bitmap; /* X identifier for bitmap. None means this + * bitmap was created by Tk_DefineBitmap and + * it isn't currently in use. */ int width, height; /* Dimensions of bitmap. */ Display *display; /* Display for which bitmap is valid. */ - int screenNum; /* Screen on which bitmap is valid */ + int screenNum; /* Screen on which bitmap is valid. */ int resourceRefCount; /* Number of active uses of this bitmap (each * active use corresponds to a call to - * Tk_AllocBitmapFromObj or Tk_GetBitmap). - * If this count is 0, then this TkBitmap + * Tk_AllocBitmapFromObj or Tk_GetBitmap). If + * this count is 0, then this TkBitmap * structure is no longer valid and it isn't * present in nameTable: it is being kept * around only because there are objects - * referring to it. The structure is freed - * when resourceRefCount and objRefCount - * are both 0. */ - int objRefCount; /* Number of Tcl_Obj's that reference - * this structure. */ + * referring to it. The structure is freed + * when resourceRefCount and objRefCount are + * both 0. */ + int objRefCount; /* Number of Tcl_Obj's that reference this + * structure. */ Tcl_HashEntry *nameHashPtr; /* Entry in nameTable for this structure * (needed when deleting). */ - Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure - * (needed when deleting). */ + Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure (needed + * when deleting). */ struct TkBitmap *nextPtr; /* Points to the next TkBitmap structure with - * the same name. All bitmaps with the - * same name (but different displays or - * screens) are chained together off a - * single entry in nameTable. */ + * the same name. All bitmaps with the same + * name (but different displays or screens) + * are chained together off a single entry in + * nameTable. */ } TkBitmap; -/* - * Used in bitmapDataTable, stored in the TkDisplay structure, to map - * between in-core data about a bitmap to its TkBitmap structure. +/* + * Used in bitmapDataTable, stored in the TkDisplay structure, to map between + * in-core data about a bitmap to its TkBitmap structure. */ typedef struct { - CONST char *source; /* Bitmap bits. */ + const char *source; /* Bitmap bits. */ int width, height; /* Dimensions of bitmap. */ } DataKey; typedef struct ThreadSpecificData { - int initialized; /* 0 means table below needs initializing. */ + int initialized; /* 0 means table below needs initializing. */ Tcl_HashTable predefBitmapTable; - /* Hash table created by Tk_DefineBitmap - * to map from a name to a collection - * of in-core data about a bitmap. The - * table is indexed by the address of the - * data for the bitmap, and the entries - * contain pointers to TkPredefBitmap - * structures. */ + /* Hash table created by Tk_DefineBitmap to + * map from a name to a collection of in-core + * data about a bitmap. The table is indexed + * by the address of the data for the bitmap, + * and the entries contain pointers to + * TkPredefBitmap structures. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static void BitmapInit _ANSI_ARGS_((TkDisplay *dispPtr)); -static void DupBitmapObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, - Tcl_Obj *dupObjPtr)); -static void FreeBitmap _ANSI_ARGS_((TkBitmap *bitmapPtr)); -static void FreeBitmapObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); -static TkBitmap * GetBitmap _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *name)); -static TkBitmap * GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); -static void InitBitmapObj _ANSI_ARGS_((Tcl_Obj *objPtr)); +static void BitmapInit(TkDisplay *dispPtr); +static void DupBitmapObjProc(Tcl_Obj *srcObjPtr, + Tcl_Obj *dupObjPtr); +static void FreeBitmap(TkBitmap *bitmapPtr); +static void FreeBitmapObjProc(Tcl_Obj *objPtr); +static TkBitmap * GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, + const char *name); +static TkBitmap * GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +static void InitBitmapObj(Tcl_Obj *objPtr); /* * The following structure defines the implementation of the "bitmap" Tcl - * object, which maps a string bitmap name to a TkBitmap object. The - * ptr1 field of the Tcl_Obj points to a TkBitmap object. + * object, which maps a string bitmap name to a TkBitmap object. The ptr1 + * field of the Tcl_Obj points to a TkBitmap object. */ Tcl_ObjType tkBitmapObjType = { @@ -136,33 +133,33 @@ Tcl_ObjType tkBitmapObjType = { * * Tk_AllocBitmapFromObj -- * - * Given a Tcl_Obj *, map the value to a corresponding - * Pixmap structure based on the tkwin given. + * Given a Tcl_Obj *, map the value to a corresponding Pixmap structure + * based on the tkwin given. * * Results: - * The return value is the X identifer for the desired bitmap - * (i.e. a Pixmap with a single plane), unless string couldn't be - * parsed correctly. In this case, None is returned and an error - * message is left in the interp's result. The caller should never - * modify the bitmap that is returned, and should eventually call - * Tk_FreeBitmapFromObj when the bitmap is no longer needed. + * The return value is the X identifer for the desired bitmap (i.e. a + * Pixmap with a single plane), unless string couldn't be parsed + * correctly. In this case, None is returned and an error message is left + * in the interp's result. The caller should never modify the bitmap that + * is returned, and should eventually call Tk_FreeBitmapFromObj when the + * bitmap is no longer needed. * * Side effects: * The bitmap is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeBitmapFromObj, so that the database can be cleaned up - * when bitmaps aren't needed anymore. + * For each call to this function, there should eventually be a call to + * Tk_FreeBitmapFromObj, so that the database can be cleaned up when + * bitmaps aren't needed anymore. * *---------------------------------------------------------------------- */ Pixmap -Tk_AllocBitmapFromObj(interp, tkwin, objPtr) - Tcl_Interp *interp; /* Interp for error results. This may - * be NULL. */ - Tk_Window tkwin; /* Need the screen the bitmap is used on.*/ - Tcl_Obj *objPtr; /* Object describing bitmap; see manual - * entry for legal syntax of string value. */ +Tk_AllocBitmapFromObj( + Tcl_Interp *interp, /* Interp for error results. This may be + * NULL. */ + Tk_Window tkwin, /* Need the screen the bitmap is used on.*/ + Tcl_Obj *objPtr) /* Object describing bitmap; see manual entry + * for legal syntax of string value. */ { TkBitmap *bitmapPtr; @@ -172,54 +169,54 @@ Tk_AllocBitmapFromObj(interp, tkwin, objPtr) bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1; /* - * If the object currently points to a TkBitmap, see if it's the - * one we want. If so, increment its reference count and return. + * If the object currently points to a TkBitmap, see if it's the one we + * want. If so, increment its reference count and return. */ if (bitmapPtr != NULL) { if (bitmapPtr->resourceRefCount == 0) { /* - * This is a stale reference: it refers to a TkBitmap that's - * no longer in use. Clear the reference. + * This is a stale reference: it refers to a TkBitmap that's no + * longer in use. Clear the reference. */ FreeBitmapObjProc(objPtr); bitmapPtr = NULL; - } else if ( (Tk_Display(tkwin) == bitmapPtr->display) - && (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum) ) { + } else if ((Tk_Display(tkwin) == bitmapPtr->display) + && (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) { bitmapPtr->resourceRefCount++; return bitmapPtr->bitmap; } } /* - * The object didn't point to the TkBitmap that we wanted. Search - * the list of TkBitmaps with the same name to see if one of the - * others is the right one. + * The object didn't point to the TkBitmap that we wanted. Search the list + * of TkBitmaps with the same name to see if one of the others is the + * right one. */ if (bitmapPtr != NULL) { - TkBitmap *firstBitmapPtr = - (TkBitmap *) Tcl_GetHashValue(bitmapPtr->nameHashPtr); + TkBitmap *firstBitmapPtr = (TkBitmap *) + Tcl_GetHashValue(bitmapPtr->nameHashPtr); FreeBitmapObjProc(objPtr); for (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL; bitmapPtr = bitmapPtr->nextPtr) { - if ( (Tk_Display(tkwin) == bitmapPtr->display) && - (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum) ) { + if ((Tk_Display(tkwin) == bitmapPtr->display) && + (Tk_ScreenNumber(tkwin) == bitmapPtr->screenNum)) { bitmapPtr->resourceRefCount++; bitmapPtr->objRefCount++; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; return bitmapPtr->bitmap; } } } /* - * Still no luck. Call GetBitmap to allocate a new TkBitmap object. + * Still no luck. Call GetBitmap to allocate a new TkBitmap object. */ bitmapPtr = GetBitmap(interp, tkwin, Tcl_GetString(objPtr)); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; if (bitmapPtr == NULL) { return None; } @@ -232,35 +229,36 @@ Tk_AllocBitmapFromObj(interp, tkwin, objPtr) * * Tk_GetBitmap -- * - * Given a string describing a bitmap, locate (or create if necessary) - * a bitmap that fits the description. + * Given a string describing a bitmap, locate (or create if necessary) a + * bitmap that fits the description. * * Results: - * The return value is the X identifer for the desired bitmap - * (i.e. a Pixmap with a single plane), unless string couldn't be - * parsed correctly. In this case, None is returned and an error - * message is left in the interp's result. The caller should never - * modify the bitmap that is returned, and should eventually call - * Tk_FreeBitmap when the bitmap is no longer needed. + * The return value is the X identifer for the desired bitmap (i.e. a + * Pixmap with a single plane), unless string couldn't be parsed + * correctly. In this case, None is returned and an error message is left + * in the interp's result. The caller should never modify the bitmap that + * is returned, and should eventually call Tk_FreeBitmap when the bitmap + * is no longer needed. * * Side effects: * The bitmap is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps + * For each call to this function, there should eventually be a call to + * Tk_FreeBitmap, so that the database can be cleaned up when bitmaps * aren't needed anymore. * *---------------------------------------------------------------------- */ Pixmap -Tk_GetBitmap(interp, tkwin, string) - Tcl_Interp *interp; /* Interpreter to use for error reporting, +Tk_GetBitmap( + Tcl_Interp *interp, /* Interpreter to use for error reporting, * this may be NULL. */ - Tk_Window tkwin; /* Window in which bitmap will be used. */ - CONST char *string; /* Description of bitmap. See manual entry - * for details on legal syntax. */ + Tk_Window tkwin, /* Window in which bitmap will be used. */ + const char *string) /* Description of bitmap. See manual entry for + * details on legal syntax. */ { TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string); + if (bitmapPtr == NULL) { return None; } @@ -272,53 +270,52 @@ Tk_GetBitmap(interp, tkwin, string) * * GetBitmap -- * - * Given a string describing a bitmap, locate (or create if necessary) - * a bitmap that fits the description. This routine returns the - * internal data structure for the bitmap. This avoids extra - * hash table lookups in Tk_AllocBitmapFromObj. + * Given a string describing a bitmap, locate (or create if necessary) a + * bitmap that fits the description. This routine returns the internal + * data structure for the bitmap. This avoids extra hash table lookups in + * Tk_AllocBitmapFromObj. * * Results: - * The return value is the X identifer for the desired bitmap - * (i.e. a Pixmap with a single plane), unless string couldn't be - * parsed correctly. In this case, None is returned and an error - * message is left in the interp's result. The caller should never - * modify the bitmap that is returned, and should eventually call - * Tk_FreeBitmap when the bitmap is no longer needed. + * The return value is the X identifer for the desired bitmap (i.e. a + * Pixmap with a single plane), unless string couldn't be parsed + * correctly. In this case, None is returned and an error message is left + * in the interp's result. The caller should never modify the bitmap that + * is returned, and should eventually call Tk_FreeBitmap when the bitmap + * is no longer needed. * * Side effects: * The bitmap is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeBitmap or Tk_FreeBitmapFromObj, so that the database can - * be cleaned up when bitmaps aren't needed anymore. + * For each call to this function, there should eventually be a call to + * Tk_FreeBitmap or Tk_FreeBitmapFromObj, so that the database can be + * cleaned up when bitmaps aren't needed anymore. * *---------------------------------------------------------------------- */ static TkBitmap * -GetBitmap(interp, tkwin, string) - Tcl_Interp *interp; /* Interpreter to use for error reporting, +GetBitmap( + Tcl_Interp *interp, /* Interpreter to use for error reporting, * this may be NULL. */ - Tk_Window tkwin; /* Window in which bitmap will be used. */ - CONST char *string; /* Description of bitmap. See manual entry - * for details on legal syntax. */ + Tk_Window tkwin, /* Window in which bitmap will be used. */ + const char *string) /* Description of bitmap. See manual entry for + * details on legal syntax. */ { Tcl_HashEntry *nameHashPtr, *predefHashPtr; TkBitmap *bitmapPtr, *existingBitmapPtr; TkPredefBitmap *predefPtr; - int new; Pixmap bitmap; - int width, height; - int dummy2; + int isNew, width, height, dummy2; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!dispPtr->bitmapInit) { BitmapInit(dispPtr); } - nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string, &new); - if (!new) { + nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string, + &isNew); + if (!isNew) { existingBitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr); for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL; bitmapPtr = bitmapPtr->nextPtr) { @@ -333,26 +330,25 @@ GetBitmap(interp, tkwin, string) } /* - * No suitable bitmap exists. Create a new bitmap from the - * information contained in the string. If the string starts - * with "@" then the rest of the string is a file name containing - * the bitmap. Otherwise the string must refer to a bitmap - * defined by a call to Tk_DefineBitmap. + * No suitable bitmap exists. Create a new bitmap from the information + * contained in the string. If the string starts with "@" then the rest of + * the string is a file name containing the bitmap. Otherwise the string + * must refer to a bitmap defined by a call to Tk_DefineBitmap. */ if (*string == '@') { /* INTL: ISO char */ Tcl_DString buffer; int result; - if (Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't specify bitmap with '@' in a", - " safe interpreter", (char *) NULL); - goto error; - } + if (Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't specify bitmap with '@' in a", + " safe interpreter", NULL); + goto error; + } /* - * Note that we need to cast away the CONST from the string because - * Tcl_TranslateFileName is non const, even though it doesn't modify + * Note that we need to cast away the const from the string because + * Tcl_TranslateFileName is non-const, even though it doesn't modify * the string. */ @@ -366,29 +362,29 @@ GetBitmap(interp, tkwin, string) &bitmap, &dummy2, &dummy2); if (result != BitmapSuccess) { if (interp != NULL) { - Tcl_AppendResult(interp, "error reading bitmap file \"", string, - "\"", (char *) NULL); + Tcl_AppendResult(interp, "error reading bitmap file \"", + string, "\"", NULL); } Tcl_DStringFree(&buffer); goto error; } Tcl_DStringFree(&buffer); } else { - predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable, - string); + predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable, string); if (predefHashPtr == NULL) { /* - * The following platform specific call allows the user to - * define bitmaps that may only exist during run time. If - * it returns None nothing was found and we return the error. + * The following platform specific call allows the user to define + * bitmaps that may only exist during run time. If it returns None + * nothing was found and we return the error. */ + bitmap = TkpGetNativeAppBitmap(Tk_Display(tkwin), string, &width, &height); - + if (bitmap == None) { if (interp != NULL) { Tcl_AppendResult(interp, "bitmap \"", string, - "\" not defined", (char *) NULL); + "\" not defined", NULL); } goto error; } @@ -400,13 +396,12 @@ GetBitmap(interp, tkwin, string) bitmap = TkpCreateNativeBitmap(Tk_Display(tkwin), predefPtr->source); if (bitmap == None) { - panic("native bitmap creation failed"); + Tcl_Panic("native bitmap creation failed"); } } else { bitmap = XCreateBitmapFromData(Tk_Display(tkwin), - RootWindowOfScreen(Tk_Screen(tkwin)), - predefPtr->source, - (unsigned) width, (unsigned) height); + RootWindowOfScreen(Tk_Screen(tkwin)), + predefPtr->source, (unsigned)width, (unsigned)height); } } } @@ -424,18 +419,18 @@ GetBitmap(interp, tkwin, string) bitmapPtr->resourceRefCount = 1; bitmapPtr->objRefCount = 0; bitmapPtr->nameHashPtr = nameHashPtr; - bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable, - (char *) bitmap, &new); - if (!new) { - panic("bitmap already registered in Tk_GetBitmap"); + bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable, + (char *) bitmap, &isNew); + if (!isNew) { + Tcl_Panic("bitmap already registered in Tk_GetBitmap"); } bitmapPtr->nextPtr = existingBitmapPtr; Tcl_SetHashValue(nameHashPtr, bitmapPtr); Tcl_SetHashValue(bitmapPtr->idHashPtr, bitmapPtr); return bitmapPtr; - error: - if (new) { + error: + if (isNew) { Tcl_DeleteHashEntry(nameHashPtr); } return NULL; @@ -446,53 +441,53 @@ GetBitmap(interp, tkwin, string) * * Tk_DefineBitmap -- * - * This procedure associates a textual name with a binary bitmap - * description, so that the name may be used to refer to the - * bitmap in future calls to Tk_GetBitmap. + * This function associates a textual name with a binary bitmap + * description, so that the name may be used to refer to the bitmap in + * future calls to Tk_GetBitmap. * * Results: - * A standard Tcl result. If an error occurs then TCL_ERROR is - * returned and a message is left in the interp's result. + * A standard Tcl result. If an error occurs then TCL_ERROR is returned + * and a message is left in the interp's result. * * Side effects: - * "Name" is entered into the bitmap table and may be used from - * here on to refer to the given bitmap. + * "Name" is entered into the bitmap table and may be used from here on + * to refer to the given bitmap. * *---------------------------------------------------------------------- */ int -Tk_DefineBitmap(interp, name, source, width, height) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - CONST char *name; /* Name to use for bitmap. Must not already - * be defined as a bitmap. */ - CONST char *source; /* Address of bits for bitmap. */ - int width; /* Width of bitmap. */ - int height; /* Height of bitmap. */ +Tk_DefineBitmap( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + const char *name, /* Name to use for bitmap. Must not already be + * defined as a bitmap. */ + const char *source, /* Address of bits for bitmap. */ + int width, /* Width of bitmap. */ + int height) /* Height of bitmap. */ { - int new; + int isNew; Tcl_HashEntry *predefHashPtr; TkPredefBitmap *predefPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - /* + /* * Initialize the Bitmap module if not initialized already for this - * thread. Since the current TkDisplay structure cannot be - * introspected from here, pass a NULL pointer to BitmapInit, - * which will know to initialize only the data in the - * ThreadSpecificData structure for the current thread. - */ + * thread. Since the current TkDisplay structure cannot be introspected + * from here, pass a NULL pointer to BitmapInit, which will know to + * initialize only the data in the ThreadSpecificData structure for the + * current thread. + */ if (!tsdPtr->initialized) { - BitmapInit((TkDisplay *) NULL); + BitmapInit(NULL); } - predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable, - name, &new); - if (!new) { - Tcl_AppendResult(interp, "bitmap \"", name, - "\" is already defined", (char *) NULL); + predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable, + name, &isNew); + if (!isNew) { + Tcl_AppendResult(interp, "bitmap \"", name, "\" is already defined", + NULL); return TCL_ERROR; } predefPtr = (TkPredefBitmap *) ckalloc(sizeof(TkPredefBitmap)); @@ -509,8 +504,7 @@ Tk_DefineBitmap(interp, name, source, width, height) * * Tk_NameOfBitmap -- * - * Given a bitmap, return a textual string identifying the - * bitmap. + * Given a bitmap, return a textual string identifying the bitmap. * * Results: * The return value is the string name associated with bitmap. @@ -521,19 +515,18 @@ Tk_DefineBitmap(interp, name, source, width, height) *-------------------------------------------------------------- */ -CONST char * -Tk_NameOfBitmap(display, bitmap) - Display *display; /* Display for which bitmap was - * allocated. */ - Pixmap bitmap; /* Bitmap whose name is wanted. */ +const char * +Tk_NameOfBitmap( + Display *display, /* Display for which bitmap was allocated. */ + Pixmap bitmap) /* Bitmap whose name is wanted. */ { Tcl_HashEntry *idHashPtr; TkBitmap *bitmapPtr; TkDisplay *dispPtr = TkGetDisplay(display); if (dispPtr == NULL || !dispPtr->bitmapInit) { - unknown: - panic("Tk_NameOfBitmap received unknown bitmap argument"); + unknown: + Tcl_Panic("Tk_NameOfBitmap received unknown bitmap argument"); } idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); @@ -549,35 +542,33 @@ Tk_NameOfBitmap(display, bitmap) * * Tk_SizeOfBitmap -- * - * Given a bitmap managed by this module, returns the width - * and height of the bitmap. + * Given a bitmap managed by this module, returns the width and height of + * the bitmap. * * Results: - * The words at *widthPtr and *heightPtr are filled in with - * the dimenstions of bitmap. + * The words at *widthPtr and *heightPtr are filled in with the + * dimenstions of bitmap. * * Side effects: - * If bitmap isn't managed by this module then the procedure - * panics.. + * If bitmap isn't managed by this module then the function panics.. * *-------------------------------------------------------------- */ void -Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr) - Display *display; /* Display for which bitmap was - * allocated. */ - Pixmap bitmap; /* Bitmap whose size is wanted. */ - int *widthPtr; /* Store bitmap width here. */ - int *heightPtr; /* Store bitmap height here. */ +Tk_SizeOfBitmap( + Display *display, /* Display for which bitmap was allocated. */ + Pixmap bitmap, /* Bitmap whose size is wanted. */ + int *widthPtr, /* Store bitmap width here. */ + int *heightPtr) /* Store bitmap height here. */ { Tcl_HashEntry *idHashPtr; TkBitmap *bitmapPtr; TkDisplay *dispPtr = TkGetDisplay(display); if (!dispPtr->bitmapInit) { - unknownBitmap: - panic("Tk_SizeOfBitmap received unknown bitmap argument"); + unknownBitmap: + Tcl_Panic("Tk_SizeOfBitmap received unknown bitmap argument"); } idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); @@ -594,23 +585,23 @@ Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr) * * FreeBitmap -- * - * This procedure does all the work of releasing a bitmap allocated by - * Tk_GetBitmap or TkGetBitmapFromData. It is invoked by both + * This function does all the work of releasing a bitmap allocated by + * Tk_GetBitmap or TkGetBitmapFromData. It is invoked by both * Tk_FreeBitmap and Tk_FreeBitmapFromObj * * Results: * None. * * Side effects: - * The reference count associated with bitmap is decremented, and - * it is officially deallocated if no-one is using it anymore. + * The reference count associated with bitmap is decremented, and it is + * officially deallocated if no-one is using it anymore. * *---------------------------------------------------------------------- */ static void -FreeBitmap(bitmapPtr) - TkBitmap *bitmapPtr; /* Bitmap to be released. */ +FreeBitmap( + TkBitmap *bitmapPtr) /* Bitmap to be released. */ { TkBitmap *prevPtr; @@ -644,35 +635,34 @@ FreeBitmap(bitmapPtr) * * Tk_FreeBitmap -- * - * This procedure is called to release a bitmap allocated by - * Tk_GetBitmap or TkGetBitmapFromData. + * This function is called to release a bitmap allocated by Tk_GetBitmap + * or TkGetBitmapFromData. * * Results: * None. * * Side effects: - * The reference count associated with bitmap is decremented, and - * it is officially deallocated if no-one is using it anymore. + * The reference count associated with bitmap is decremented, and it is + * officially deallocated if no-one is using it anymore. * *---------------------------------------------------------------------- */ void -Tk_FreeBitmap(display, bitmap) - Display *display; /* Display for which bitmap was - * allocated. */ - Pixmap bitmap; /* Bitmap to be released. */ +Tk_FreeBitmap( + Display *display, /* Display for which bitmap was allocated. */ + Pixmap bitmap) /* Bitmap to be released. */ { Tcl_HashEntry *idHashPtr; TkDisplay *dispPtr = TkGetDisplay(display); if (!dispPtr->bitmapInit) { - panic("Tk_FreeBitmap called before Tk_GetBitmap"); + Tcl_Panic("Tk_FreeBitmap called before Tk_GetBitmap"); } idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); if (idHashPtr == NULL) { - panic("Tk_FreeBitmap received unknown bitmap argument"); + Tcl_Panic("Tk_FreeBitmap received unknown bitmap argument"); } FreeBitmap((TkBitmap *) Tcl_GetHashValue(idHashPtr)); } @@ -682,27 +672,27 @@ Tk_FreeBitmap(display, bitmap) * * Tk_FreeBitmapFromObj -- * - * This procedure is called to release a bitmap allocated by - * Tk_AllocBitmapFromObj. It does not throw away the Tcl_Obj *; - * it only gets rid of the hash table entry for this bitmap - * and clears the cached value that is normally stored in the object. + * This function is called to release a bitmap allocated by + * Tk_AllocBitmapFromObj. It does not throw away the Tcl_Obj *; it only + * gets rid of the hash table entry for this bitmap and clears the cached + * value that is normally stored in the object. * * Results: * None. * * Side effects: - * The reference count associated with the bitmap represented by - * objPtr is decremented, and the bitmap is released to X if there are - * no remaining uses for it. + * The reference count associated with the bitmap represented by objPtr + * is decremented, and the bitmap is released to X if there are no + * remaining uses for it. * *---------------------------------------------------------------------- */ void -Tk_FreeBitmapFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window this bitmap lives in. Needed - * for the display value. */ - Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */ +Tk_FreeBitmapFromObj( + Tk_Window tkwin, /* The window this bitmap lives in. Needed for + * the display value. */ + Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */ { FreeBitmap(GetBitmapFromObj(tkwin, objPtr)); } @@ -710,26 +700,25 @@ Tk_FreeBitmapFromObj(tkwin, objPtr) /* *--------------------------------------------------------------------------- * - * FreeBitmapObjProc -- + * FreeBitmapObjProc -- * * This proc is called to release an object reference to a bitmap. - * Called when the object's internal rep is released or when - * the cached bitmapPtr needs to be changed. + * Called when the object's internal rep is released or when the cached + * bitmapPtr needs to be changed. * * Results: * None. * * Side effects: - * The object reference count is decremented. When both it - * and the hash ref count go to zero, the color's resources - * are released. + * The object reference count is decremented. When both it and the hash + * ref count go to zero, the color's resources are released. * *--------------------------------------------------------------------------- */ static void -FreeBitmapObjProc(objPtr) - Tcl_Obj *objPtr; /* The object we are releasing. */ +FreeBitmapObjProc( + Tcl_Obj *objPtr) /* The object we are releasing. */ { TkBitmap *bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1; @@ -739,37 +728,37 @@ FreeBitmapObjProc(objPtr) && (bitmapPtr->resourceRefCount == 0)) { ckfree((char *) bitmapPtr); } - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } } /* *--------------------------------------------------------------------------- * - * DupBitmapObjProc -- + * DupBitmapObjProc -- * - * When a cached bitmap object is duplicated, this is called to - * update the internal reps. + * When a cached bitmap object is duplicated, this is called to update + * the internal reps. * * Results: * None. * * Side effects: - * The color's objRefCount is incremented and the internal rep - * of the copy is set to point to it. + * The color's objRefCount is incremented and the internal rep of the + * copy is set to point to it. * *--------------------------------------------------------------------------- */ static void -DupBitmapObjProc(srcObjPtr, dupObjPtr) - Tcl_Obj *srcObjPtr; /* The object we are copying from. */ - Tcl_Obj *dupObjPtr; /* The object we are copying to. */ +DupBitmapObjProc( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { TkBitmap *bitmapPtr = (TkBitmap *) srcObjPtr->internalRep.twoPtrValue.ptr1; - + dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr; + dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; if (bitmapPtr != NULL) { bitmapPtr->objRefCount++; @@ -781,22 +770,22 @@ DupBitmapObjProc(srcObjPtr, dupObjPtr) * * Tk_GetBitmapFromData -- * - * Given a description of the bits for a bitmap, make a bitmap that - * has the given properties. *** NOTE: this procedure is obsolete - * and really shouldn't be used anymore. *** + * Given a description of the bits for a bitmap, make a bitmap that has + * the given properties. *** NOTE: this function is obsolete and really + * shouldn't be used anymore. *** * * Results: - * The return value is the X identifer for the desired bitmap - * (a one-plane Pixmap), unless it couldn't be created properly. - * In this case, None is returned and an error message is left in - * the interp's result. The caller should never modify the bitmap that - * is returned, and should eventually call Tk_FreeBitmap when the - * bitmap is no longer needed. + * The return value is the X identifer for the desired bitmap (a + * one-plane Pixmap), unless it couldn't be created properly. In this + * case, None is returned and an error message is left in the interp's + * result. The caller should never modify the bitmap that is returned, + * and should eventually call Tk_FreeBitmap when the bitmap is no longer + * needed. * * Side effects: * The bitmap is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeBitmap, so that the database can be cleaned up when bitmaps + * For each call to this function, there should eventually be a call to + * Tk_FreeBitmap, so that the database can be cleaned up when bitmaps * aren't needed anymore. * *---------------------------------------------------------------------- @@ -804,15 +793,15 @@ DupBitmapObjProc(srcObjPtr, dupObjPtr) /* ARGSUSED */ Pixmap -Tk_GetBitmapFromData(interp, tkwin, source, width, height) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tk_Window tkwin; /* Window in which bitmap will be used. */ - CONST char *source; /* Bitmap data for bitmap shape. */ - int width, height; /* Dimensions of bitmap. */ +Tk_GetBitmapFromData( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which bitmap will be used. */ + const char *source, /* Bitmap data for bitmap shape. */ + int width, int height) /* Dimensions of bitmap. */ { DataKey nameKey; Tcl_HashEntry *dataHashPtr; - int new; + int isNew; char string[16 + TCL_INTEGER_SPACE]; char *name; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -826,9 +815,9 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height) nameKey.source = source; nameKey.width = width; nameKey.height = height; - dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable, - (char *) &nameKey, &new); - if (!new) { + dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable, + (char *) &nameKey, &isNew); + if (!isNew) { name = (char *) Tcl_GetHashValue(dataHashPtr); } else { dispPtr->bitmapAutoNumber++; @@ -848,27 +837,28 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height) * * Tk_GetBitmapFromObj -- * - * Returns the bitmap referred to by a Tcl object. The bitmap must - * already have been allocated via a call to Tk_AllocBitmapFromObj - * or Tk_GetBitmap. + * Returns the bitmap referred to by a Tcl object. The bitmap must + * already have been allocated via a call to Tk_AllocBitmapFromObj or + * Tk_GetBitmap. * * Results: - * Returns the Pixmap that matches the tkwin and the string rep - * of objPtr. + * Returns the Pixmap that matches the tkwin and the string rep of + * objPtr. * * Side effects: - * If the object is not already a bitmap, the conversion will free - * any old internal representation. + * If the object is not already a bitmap, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ Pixmap -Tk_GetBitmapFromObj(tkwin, objPtr) - Tk_Window tkwin; - Tcl_Obj *objPtr; /* The object from which to get pixels. */ +Tk_GetBitmapFromObj( + Tk_Window tkwin, + Tcl_Obj *objPtr) /* The object from which to get pixels. */ { TkBitmap *bitmapPtr = GetBitmapFromObj(tkwin, objPtr); + return bitmapPtr->bitmap; } @@ -877,28 +867,28 @@ Tk_GetBitmapFromObj(tkwin, objPtr) * * GetBitmapFromObj -- * - * Returns the bitmap referred to by a Tcl object. The bitmap must - * already have been allocated via a call to Tk_AllocBitmapFromObj - * or Tk_GetBitmap. + * Returns the bitmap referred to by a Tcl object. The bitmap must + * already have been allocated via a call to Tk_AllocBitmapFromObj or + * Tk_GetBitmap. * * Results: - * Returns the TkBitmap * that matches the tkwin and the string rep - * of objPtr. + * Returns the TkBitmap * that matches the tkwin and the string rep of + * objPtr. * * Side effects: - * If the object is not already a bitmap, the conversion will free - * any old internal representation. + * If the object is not already a bitmap, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ static TkBitmap * -GetBitmapFromObj(tkwin, objPtr) - Tk_Window tkwin; /* Window in which the bitmap will be used. */ - Tcl_Obj *objPtr; /* The object that describes the desired +GetBitmapFromObj( + Tk_Window tkwin, /* Window in which the bitmap will be used. */ + Tcl_Obj *objPtr) /* The object that describes the desired * bitmap. */ { - TkBitmap *bitmapPtr; + TkBitmap *bitmapPtr; Tcl_HashEntry *hashPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -907,7 +897,7 @@ GetBitmapFromObj(tkwin, objPtr) } bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1; - if (bitmapPtr != NULL) { + if (bitmapPtr != NULL) { if ((bitmapPtr->resourceRefCount > 0) && (Tk_Display(tkwin) == bitmapPtr->display)) { return bitmapPtr; @@ -915,29 +905,29 @@ GetBitmapFromObj(tkwin, objPtr) hashPtr = bitmapPtr->nameHashPtr; FreeBitmapObjProc(objPtr); } else { - hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, - Tcl_GetString(objPtr)); + hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, + Tcl_GetString(objPtr)); if (hashPtr == NULL) { goto error; } - } + } /* - * At this point we've got a hash table entry, off of which hang - * one or more TkBitmap structures. See if any of them will work. + * At this point we've got a hash table entry, off of which hang one or + * more TkBitmap structures. See if any of them will work. */ for (bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr); bitmapPtr != NULL; bitmapPtr = bitmapPtr->nextPtr) { if (Tk_Display(tkwin) == bitmapPtr->display) { - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) bitmapPtr; bitmapPtr->objRefCount++; return bitmapPtr; } } - error: - panic("GetBitmapFromObj called with non-existent bitmap!"); + error: + Tcl_Panic("GetBitmapFromObj called with non-existent bitmap!"); /* * The following code isn't reached; it's just there to please compilers. */ @@ -949,27 +939,27 @@ GetBitmapFromObj(tkwin, objPtr) * * InitBitmapObj -- * - * Bookeeping procedure to change an objPtr to a bitmap type. + * Bookeeping function to change an objPtr to a bitmap type. * * Results: * None. * * Side effects: - * The old internal rep of the object is freed. The internal - * rep is cleared. The final form of the object is set - * by either Tk_AllocBitmapFromObj or GetBitmapFromObj. + * The old internal rep of the object is freed. The internal rep is + * cleared. The final form of the object is set by either + * Tk_AllocBitmapFromObj or GetBitmapFromObj. * *---------------------------------------------------------------------- */ static void -InitBitmapObj(objPtr) - Tcl_Obj *objPtr; /* The object to convert. */ +InitBitmapObj( + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ Tcl_GetString(objPtr); @@ -978,21 +968,22 @@ InitBitmapObj(objPtr) (*typePtr->freeIntRepProc)(objPtr); } objPtr->typePtr = &tkBitmapObjType; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } /* *---------------------------------------------------------------------- * * BitmapInit -- - * Initializes hash tables used by this module. Initializes - * tables stored in TkDisplay structure if a TkDisplay pointer - * is passed in. Iinitializes the thread-local data - * in the current thread's ThreadSpecificData structure. + * + * Initializes hash tables used by this module. Initializes tables stored + * in TkDisplay structure if a TkDisplay pointer is passed in. Also + * initializes the thread-local data in the current thread's + * ThreadSpecificData structure. * * Results: - * None. - * + * None. + * * Side effects: * Read the code. * @@ -1000,70 +991,70 @@ InitBitmapObj(objPtr) */ static void -BitmapInit(dispPtr) - TkDisplay *dispPtr; /* TkDisplay structure encapsulating - * thread-specific data used by this - * module, or NULL if unavailable. */ +BitmapInit( + TkDisplay *dispPtr) /* TkDisplay structure encapsulating + * thread-specific data used by this module, + * or NULL if unavailable. */ { Tcl_Interp *dummy; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - /* - * First initialize the data in the ThreadSpecificData strucuture, - * if needed. + /* + * First initialize the data in the ThreadSpecificData strucuture, if + * needed. */ if (!tsdPtr->initialized) { tsdPtr->initialized = 1; - dummy = Tcl_CreateInterp(); + dummy = Tcl_CreateInterp(); Tcl_InitHashTable(&tsdPtr->predefBitmapTable, TCL_STRING_KEYS); - Tk_DefineBitmap(dummy, "error", (char *) error_bits, + Tk_DefineBitmap(dummy, "error", (char *) error_bits, error_width, error_height); - Tk_DefineBitmap(dummy, "gray75", (char *) gray75_bits, - gray75_width, gray75_height); - Tk_DefineBitmap(dummy, "gray50", (char *) gray50_bits, - gray50_width, gray50_height); - Tk_DefineBitmap(dummy, "gray25", (char *) gray25_bits, - gray25_width, gray25_height); - Tk_DefineBitmap(dummy, "gray12", (char *) gray12_bits, - gray12_width, gray12_height); - Tk_DefineBitmap(dummy, "hourglass", (char *) hourglass_bits, - hourglass_width, hourglass_height); - Tk_DefineBitmap(dummy, "info", (char *) info_bits, - info_width, info_height); - Tk_DefineBitmap(dummy, "questhead", (char *) questhead_bits, - questhead_width, questhead_height); - Tk_DefineBitmap(dummy, "question", (char *) question_bits, - question_width, question_height); - Tk_DefineBitmap(dummy, "warning", (char *) warning_bits, - warning_width, warning_height); - - TkpDefineNativeBitmaps(); - Tcl_DeleteInterp(dummy); + Tk_DefineBitmap(dummy, "gray75", (char *) gray75_bits, + gray75_width, gray75_height); + Tk_DefineBitmap(dummy, "gray50", (char *) gray50_bits, + gray50_width, gray50_height); + Tk_DefineBitmap(dummy, "gray25", (char *) gray25_bits, + gray25_width, gray25_height); + Tk_DefineBitmap(dummy, "gray12", (char *) gray12_bits, + gray12_width, gray12_height); + Tk_DefineBitmap(dummy, "hourglass", (char *) hourglass_bits, + hourglass_width, hourglass_height); + Tk_DefineBitmap(dummy, "info", (char *) info_bits, + info_width, info_height); + Tk_DefineBitmap(dummy, "questhead", (char *) questhead_bits, + questhead_width, questhead_height); + Tk_DefineBitmap(dummy, "question", (char *) question_bits, + question_width, question_height); + Tk_DefineBitmap(dummy, "warning", (char *) warning_bits, + warning_width, warning_height); + + TkpDefineNativeBitmaps(); + Tcl_DeleteInterp(dummy); } /* - * Was a valid TkDisplay pointer passed? If so, initialize the - * Bitmap module tables in that structure. + * Was a valid TkDisplay pointer passed? If so, initialize the Bitmap + * module tables in that structure. */ if (dispPtr != NULL) { - dispPtr->bitmapInit = 1; + dispPtr->bitmapInit = 1; Tcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&dispPtr->bitmapDataTable, sizeof(DataKey) - /sizeof(int)); + Tcl_InitHashTable(&dispPtr->bitmapDataTable, + sizeof(DataKey) / sizeof(int)); /* - * The call below is tricky: can't use sizeof(IdKey) because it - * gets padded with extra unpredictable bytes on some 64-bit - * machines. + * The call below is tricky: can't use sizeof(IdKey) because it gets + * padded with extra unpredictable bytes on some 64-bit machines. */ /* * The comment above doesn't make sense... */ + Tcl_InitHashTable(&dispPtr->bitmapIdTable, TCL_ONE_WORD_KEYS); } } @@ -1073,8 +1064,8 @@ BitmapInit(dispPtr) * * TkReadBitmapFile -- * - * Loads a bitmap image in X bitmap format into the specified - * drawable. This is equivelent to the XReadBitmapFile in X. + * Loads a bitmap image in X bitmap format into the specified drawable. + * This is equivelent to the XReadBitmapFile in X. * * Results: * Sets the size, hotspot, and bitmap on success. @@ -1086,16 +1077,15 @@ BitmapInit(dispPtr) */ int -TkReadBitmapFile(display, d, filename, width_return, height_return, - bitmap_return, x_hot_return, y_hot_return) - Display* display; - Drawable d; - CONST char* filename; - unsigned int* width_return; - unsigned int* height_return; - Pixmap* bitmap_return; - int* x_hot_return; - int* y_hot_return; +TkReadBitmapFile( + Display *display, + Drawable d, + const char *filename, + unsigned int *width_return, + unsigned int *height_return, + Pixmap *bitmap_return, + int *x_hot_return, + int *y_hot_return) { char *data; @@ -1108,23 +1098,22 @@ TkReadBitmapFile(display, d, filename, width_return, height_return, *bitmap_return = XCreateBitmapFromData(display, d, data, *width_return, *height_return); - ckfree(data); return BitmapSuccess; - } +} /* *---------------------------------------------------------------------- * * TkDebugBitmap -- * - * This procedure returns debugging information about a bitmap. + * This function returns debugging information about a bitmap. * * Results: * The return value is a list with one sublist for each TkBitmap - * corresponding to "name". Each sublist has two elements that - * contain the resourceRefCount and objRefCount fields from the - * TkBitmap structure. + * corresponding to "name". Each sublist has two elements that contain + * the resourceRefCount and objRefCount fields from the TkBitmap + * structure. * * Side effects: * None. @@ -1133,10 +1122,10 @@ TkReadBitmapFile(display, d, filename, width_return, height_return, */ Tcl_Obj * -TkDebugBitmap(tkwin, name) - Tk_Window tkwin; /* The window in which the bitmap will be - * used (not currently used). */ - char *name; /* Name of the desired color. */ +TkDebugBitmap( + Tk_Window tkwin, /* The window in which the bitmap will be used + * (not currently used). */ + char *name) /* Name of the desired color. */ { TkBitmap *bitmapPtr; Tcl_HashEntry *hashPtr; @@ -1148,45 +1137,54 @@ TkDebugBitmap(tkwin, name) if (hashPtr != NULL) { bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr); if (bitmapPtr == NULL) { - panic("TkDebugBitmap found empty hash table entry"); + Tcl_Panic("TkDebugBitmap found empty hash table entry"); } for ( ; (bitmapPtr != NULL); bitmapPtr = bitmapPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(bitmapPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(bitmapPtr->objRefCount)); + Tcl_NewIntObj(bitmapPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } - /* *---------------------------------------------------------------------- * * TkGetBitmapPredefTable -- - * This procedure is used by tkMacBitmap.c to access the thread- - * specific predefBitmap table that maps from the names of - * the predefined bitmaps to data associated with those - * bitmaps. It is required because the table is allocated in - * thread-local storage and is not visible outside this file. + * + * This function is used by tkMacBitmap.c to access the thread-specific + * predefBitmap table that maps from the names of the predefined bitmaps + * to data associated with those bitmaps. It is required because the + * table is allocated in thread-local storage and is not visible outside + * this file. * Results: - * Returns a pointer to the predefined bitmap hash table for - * the current thread. + * Returns a pointer to the predefined bitmap hash table for the current + * thread. * * Side effects: * None. * *---------------------------------------------------------------------- */ + Tcl_HashTable * -TkGetBitmapPredefTable() +TkGetBitmapPredefTable(void) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); return &tsdPtr->predefBitmapTable; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkButton.c b/generic/tkButton.c index 3783985..4e3c06c 100644 --- a/generic/tkButton.c +++ b/generic/tkButton.c @@ -1,39 +1,40 @@ -/* +/* * tkButton.c -- * - * This module implements a collection of button-like - * widgets for the Tk toolkit. The widgets implemented - * include labels, buttons, checkbuttons, and radiobuttons. + * This module implements a collection of button-like widgets for the Tk + * toolkit. The widgets implemented include buttons, checkbuttons, + * radiobuttons, and labels. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkButton.h" #include "default.h" -typedef struct ThreadSpecificData { +typedef struct ThreadSpecificData { int defaultsInitialized; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Class names for buttons, indexed by one of the type values defined - * in tkButton.h. + * Class names for buttons, indexed by one of the type values defined in + * tkButton.h. */ -static char *classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"}; +static const char *classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"}; /* - * The following table defines the legal values for the -default option. - * It is used together with the "enum defaultValue" declaration in tkButton.h. + * The following table defines the legal values for the -default option. It is + * used together with the "enum defaultValue" declaration in tkButton.h. */ -static char *defaultStrings[] = { - "active", "disabled", "normal", (char *) NULL +static const char *defaultStrings[] = { + "active", "disabled", "normal", NULL }; /* @@ -41,8 +42,8 @@ static char *defaultStrings[] = { * It is used together with the "enum state" declaration in tkButton.h. */ -static char *stateStrings[] = { - "active", "disabled", "normal", (char *) NULL +static const char *stateStrings[] = { + "active", "disabled", "normal", NULL }; /* @@ -50,8 +51,8 @@ static char *stateStrings[] = { * It is used with the "enum compound" declaration in tkButton.h */ -static char *compoundStrings[] = { - "bottom", "center", "left", "none", "right", "top", (char *) NULL +static const char *compoundStrings[] = { + "bottom", "center", "left", "none", "right", "top", NULL }; char tkDefButtonBorderWidth[TCL_INTEGER_SPACE] = DEF_BUTTON_BORDER_WIDTH; @@ -73,10 +74,10 @@ static Tk_OptionSpec labelOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), 0, (ClientData) DEF_BUTTON_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, @@ -93,8 +94,8 @@ static Tk_OptionSpec labelOptionSpecs[] = { "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", @@ -143,8 +144,7 @@ static Tk_OptionSpec labelOptionSpecs[] = { {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), Tk_Offset(TkButton, wrapLength), 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0} }; static Tk_OptionSpec buttonOptionSpecs[] = { @@ -159,10 +159,10 @@ static Tk_OptionSpec buttonOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), 0, (ClientData) DEF_BUTTON_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, @@ -185,8 +185,8 @@ static Tk_OptionSpec buttonOptionSpecs[] = { "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", @@ -245,8 +245,7 @@ static Tk_OptionSpec buttonOptionSpecs[] = { {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), Tk_Offset(TkButton, wrapLength), 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; static Tk_OptionSpec checkbuttonOptionSpecs[] = { @@ -261,10 +260,10 @@ static Tk_OptionSpec checkbuttonOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), 0, (ClientData) DEF_BUTTON_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, @@ -284,8 +283,8 @@ static Tk_OptionSpec checkbuttonOptionSpecs[] = { "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", @@ -344,6 +343,11 @@ static Tk_OptionSpec checkbuttonOptionSpecs[] = { {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage", + DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1, + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue", + DEF_BUTTON_TRISTATE_VALUE, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", @@ -354,8 +358,7 @@ static Tk_OptionSpec checkbuttonOptionSpecs[] = { {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), Tk_Offset(TkButton, wrapLength), 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; static Tk_OptionSpec radiobuttonOptionSpecs[] = { @@ -370,10 +373,10 @@ static Tk_OptionSpec radiobuttonOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_BUTTON_BG_COLOR, -1, Tk_Offset(TkButton, normalBorder), 0, (ClientData) DEF_BUTTON_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, @@ -393,8 +396,8 @@ static Tk_OptionSpec radiobuttonOptionSpecs[] = { "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR, -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", @@ -450,6 +453,11 @@ static Tk_OptionSpec radiobuttonOptionSpecs[] = { {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage", + DEF_BUTTON_IMAGE, Tk_Offset(TkButton, tristateImagePtr), -1, + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue", + DEF_BUTTON_TRISTATE_VALUE, Tk_Offset(TkButton, tristateValuePtr), -1, 0, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0}, {TK_OPTION_STRING, "-value", "value", "Value", @@ -462,17 +470,15 @@ static Tk_OptionSpec radiobuttonOptionSpecs[] = { {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr), Tk_Offset(TkButton, wrapLength), 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* - * The following table maps from one of the type values defined in - * tkButton.h, such as TYPE_LABEL, to the option template for that - * class of widgets. + * The following table maps from one of the type values defined in tkButton.h, + * such as TYPE_LABEL, to the option template for that class of widgets. */ -static Tk_OptionSpec *optionSpecs[] = { +static Tk_OptionSpec * const optionSpecs[] = { labelOptionSpecs, buttonOptionSpecs, checkbuttonOptionSpecs, @@ -480,18 +486,17 @@ static Tk_OptionSpec *optionSpecs[] = { }; /* - * The following tables define the widget commands supported by - * each of the classes, and map the indexes into the string tables - * into a single enumerated type used to dispatch the widget command. + * The following tables define the widget commands supported by each of the + * classes, and map the indexes into the string tables into a single + * enumerated type used to dispatch the widget command. */ -static CONST char *commandNames[][8] = { - {"cget", "configure", (char *) NULL}, - {"cget", "configure", "flash", "invoke", (char *) NULL}, - {"cget", "configure", "deselect", "flash", "invoke", "select", - "toggle", (char *) NULL}, +static const char *commandNames[][8] = { + {"cget", "configure", NULL}, + {"cget", "configure", "flash", "invoke", NULL}, {"cget", "configure", "deselect", "flash", "invoke", "select", - (char *) NULL} + "toggle", NULL}, + {"cget", "configure", "deselect", "flash", "invoke", "select", NULL} }; enum command { COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH, @@ -507,91 +512,92 @@ static enum command map[][8] = { }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void ButtonCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static int ButtonCreate _ANSI_ARGS_((ClientData clientData, +static void ButtonCmdDeletedProc(ClientData clientData); +static int ButtonCreate(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[], int type)); -static void ButtonEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void ButtonImageProc _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[], int type); +static void ButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void ButtonImageProc(ClientData clientData, int x, int y, int width, int height, - int imgWidth, int imgHeight)); -static void ButtonSelectImageProc _ANSI_ARGS_(( - ClientData clientData, int x, int y, int width, - int height, int imgWidth, int imgHeight)); -static char * ButtonTextVarProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static char * ButtonVarProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static int ButtonWidgetObjCmd _ANSI_ARGS_((ClientData clientData, + int imgWidth, int imgHeight); +static void ButtonSelectImageProc(ClientData clientData, + int x, int y, int width, int height, + int imgWidth, int imgHeight); +static void ButtonTristateImageProc(ClientData clientData, + int x, int y, int width, int height, + int imgWidth, int imgHeight); +static char * ButtonTextVarProc(ClientData clientData, + Tcl_Interp *interp, const char *name1, + const char *name2, int flags); +static char * ButtonVarProc(ClientData clientData, + Tcl_Interp *interp, const char *name1, + const char *name2, int flags); +static int ButtonWidgetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static int ConfigureButton _ANSI_ARGS_((Tcl_Interp *interp, - TkButton *butPtr, int objc, - Tcl_Obj *CONST objv[])); -static void DestroyButton _ANSI_ARGS_((TkButton *butPtr)); + Tcl_Obj *const objv[]); +static int ConfigureButton(Tcl_Interp *interp, TkButton *butPtr, + int objc, Tcl_Obj *const objv[]); +static void DestroyButton(TkButton *butPtr); /* *-------------------------------------------------------------- * * Tk_ButtonCmd, Tk_CheckbuttonCmd, Tk_LabelCmd, Tk_RadiobuttonCmd -- * - * These procedures are invoked to process the "button", "label", - * "radiobutton", and "checkbutton" Tcl commands. See the - * user documentation for details on what they do. + * These functions are invoked to process the "button", "label", + * "radiobutton", and "checkbutton" Tcl commands. See the user + * documentation for details on what they do. * * Results: * A standard Tcl result. * * Side effects: - * See the user documentation. These procedures are just wrappers; - * they call ButtonCreate to do all of the real work. + * See the user documentation. These functions are just wrappers; they + * call ButtonCreate to do all of the real work. * *-------------------------------------------------------------- */ int -Tk_ButtonObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +Tk_ButtonObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument values. */ { return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON); } int -Tk_CheckbuttonObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +Tk_CheckbuttonObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument values. */ { return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON); } int -Tk_LabelObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +Tk_LabelObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument values. */ { return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL); } int -Tk_RadiobuttonObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +Tk_RadiobuttonObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument values. */ { return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON); } @@ -601,9 +607,9 @@ Tk_RadiobuttonObjCmd(clientData, interp, objc, objv) * * ButtonCreate -- * - * This procedure does all the real work of implementing the - * "button", "label", "radiobutton", and "checkbutton" Tcl - * commands. See the user documentation for details on what it does. + * This function does all the real work of implementing the "button", + * "label", "radiobutton", and "checkbutton" Tcl commands. See the user + * documentation for details on what it does. * * Results: * A standard Tcl result. @@ -615,20 +621,20 @@ Tk_RadiobuttonObjCmd(clientData, interp, objc, objv) */ static int -ButtonCreate(clientData, interp, objc, objv, type) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ - int type; /* Type of button to create: TYPE_LABEL, +ButtonCreate( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[], /* Argument values. */ + int type) /* Type of button to create: TYPE_LABEL, * TYPE_BUTTON, TYPE_CHECK_BUTTON, or * TYPE_RADIO_BUTTON. */ { TkButton *butPtr; Tk_OptionTable optionTable; Tk_Window tkwin; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->defaultsInitialized) { TkpButtonSetDefaults(optionSpecs[type]); @@ -645,14 +651,14 @@ ButtonCreate(clientData, interp, objc, objv, type) */ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, the cached pointer will be returned. + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]); @@ -681,6 +687,8 @@ ButtonCreate(clientData, interp, objc, objv, type) butPtr->image = NULL; butPtr->selectImagePtr = NULL; butPtr->selectImage = NULL; + butPtr->tristateImagePtr = NULL; + butPtr->tristateImage = NULL; butPtr->state = STATE_NORMAL; butPtr->normalBorder = NULL; butPtr->activeBorder = NULL; @@ -725,6 +733,7 @@ ButtonCreate(clientData, interp, objc, objv, type) butPtr->selVarNamePtr = NULL; butPtr->onValuePtr = NULL; butPtr->offValuePtr = NULL; + butPtr->tristateValuePtr = NULL; butPtr->cursor = None; butPtr->takeFocusPtr = NULL; butPtr->commandPtr = NULL; @@ -754,9 +763,9 @@ ButtonCreate(clientData, interp, objc, objv, type) * * ButtonWidgetCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -768,11 +777,11 @@ ButtonCreate(clientData, interp, objc, objv, type) */ static int -ButtonWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about button widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +ButtonWidgetObjCmd( + ClientData clientData, /* Information about button widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument values. */ { TkButton *butPtr = (TkButton *) clientData; int index; @@ -791,137 +800,126 @@ ButtonWidgetObjCmd(clientData, interp, objc, objv) Tcl_Preserve((ClientData) butPtr); switch (map[butPtr->type][index]) { - case COMMAND_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "cget option"); - goto error; - } - objPtr = Tk_GetOptionValue(interp, (char *) butPtr, - butPtr->optionTable, objv[2], butPtr->tkwin); + case COMMAND_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "cget option"); + goto error; + } + objPtr = Tk_GetOptionValue(interp, (char *) butPtr, + butPtr->optionTable, objv[2], butPtr->tkwin); + if (objPtr == NULL) { + goto error; + } else { + Tcl_SetObjResult(interp, objPtr); + } + break; + + case COMMAND_CONFIGURE: + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) butPtr, + butPtr->optionTable, (objc == 3) ? objv[2] : NULL, + butPtr->tkwin); if (objPtr == NULL) { - goto error; + goto error; } else { Tcl_SetObjResult(interp, objPtr); } - break; + } else { + result = ConfigureButton(interp, butPtr, objc-2, objv+2); } + break; - case COMMAND_CONFIGURE: { - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) butPtr, - butPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - butPtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } - } else { - result = ConfigureButton(interp, butPtr, objc-2, objv+2); - } - break; + case COMMAND_DESELECT: + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "deselect"); + goto error; } - - case COMMAND_DESELECT: { - if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "deselect"); + if (butPtr->type == TYPE_CHECK_BUTTON) { + if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, + butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) + == NULL) { goto error; } - if (butPtr->type == TYPE_CHECK_BUTTON) { - if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, - butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) - == NULL) { - goto error; - } - } else if (butPtr->flags & SELECTED) { - if (Tcl_ObjSetVar2(interp, - butPtr->selVarNamePtr, NULL, Tcl_NewObj(), - TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) - == NULL) { - goto error; - } + } else if (butPtr->flags & SELECTED) { + if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, + Tcl_NewObj(), TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL){ + goto error; } - break; } + break; - case COMMAND_FLASH: { + case COMMAND_FLASH: + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "flash"); + goto error; + } + if (butPtr->state != STATE_DISABLED) { int i; - if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "flash"); - goto error; - } - if (butPtr->state != STATE_DISABLED) { - for (i = 0; i < 4; i++) { - if (butPtr->state == STATE_NORMAL) { - butPtr->state = STATE_ACTIVE; - Tk_SetBackgroundFromBorder(butPtr->tkwin, - butPtr->activeBorder); - } else { - butPtr->state = STATE_NORMAL; - Tk_SetBackgroundFromBorder(butPtr->tkwin, - butPtr->normalBorder); - } - TkpDisplayButton((ClientData) butPtr); - - /* - * Special note: must cancel any existing idle handler - * for TkpDisplayButton; it's no longer needed, and - * TkpDisplayButton cleared the REDRAW_PENDING flag. - */ - - Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr); - XFlush(butPtr->display); - Tcl_Sleep(50); + for (i = 0; i < 4; i++) { + if (butPtr->state == STATE_NORMAL) { + butPtr->state = STATE_ACTIVE; + Tk_SetBackgroundFromBorder(butPtr->tkwin, + butPtr->activeBorder); + } else { + butPtr->state = STATE_NORMAL; + Tk_SetBackgroundFromBorder(butPtr->tkwin, + butPtr->normalBorder); } + TkpDisplayButton((ClientData) butPtr); + + /* + * Special note: must cancel any existing idle handler for + * TkpDisplayButton; it's no longer needed, and + * TkpDisplayButton cleared the REDRAW_PENDING flag. + */ + + Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr); + XFlush(butPtr->display); + Tcl_Sleep(50); } - break; } + break; - case COMMAND_INVOKE: { - if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "invoke"); - goto error; - } - if (butPtr->state != STATE_DISABLED) { - result = TkInvokeButton(butPtr); - } - break; + case COMMAND_INVOKE: + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "invoke"); + goto error; + } + if (butPtr->state != STATE_DISABLED) { + result = TkInvokeButton(butPtr); } + break; - case COMMAND_SELECT: { - if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "select"); - goto error; - } - if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, - butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) - == NULL) { - goto error; - } - break; + case COMMAND_SELECT: + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "select"); + goto error; } + if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, + butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) + == NULL) { + goto error; + } + break; - case COMMAND_TOGGLE: { - if (objc > 2) { - Tcl_WrongNumArgs(interp, 1, objv, "toggle"); - goto error; - } - if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, - (butPtr->flags & SELECTED) ? butPtr->offValuePtr - : butPtr->onValuePtr, - TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) - == NULL) { - goto error; - } - break; + case COMMAND_TOGGLE: + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "toggle"); + goto error; + } + if (Tcl_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL, + (butPtr->flags & SELECTED) ? butPtr->offValuePtr + : butPtr->onValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) + == NULL) { + goto error; } + break; } Tcl_Release((ClientData) butPtr); return result; - error: + error: Tcl_Release((ClientData) butPtr); return TCL_ERROR; } @@ -931,8 +929,8 @@ ButtonWidgetObjCmd(clientData, interp, objc, objv) * * DestroyButton -- * - * This procedure is invoked by ButtonEventProc to free all the - * resources of a button and clean up its state. + * This function is invoked by ButtonEventProc to free all the resources + * of a button and clean up its state. * * Results: * None. @@ -944,8 +942,8 @@ ButtonWidgetObjCmd(clientData, interp, objc, objv) */ static void -DestroyButton(butPtr) - TkButton *butPtr; /* Info about button widget. */ +DestroyButton( + TkButton *butPtr) /* Info about button widget. */ { butPtr->flags |= BUTTON_DELETED; TkpDestroyButton(butPtr); @@ -955,9 +953,8 @@ DestroyButton(butPtr) } /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd); @@ -972,6 +969,9 @@ DestroyButton(butPtr) if (butPtr->selectImage != NULL) { Tk_FreeImage(butPtr->selectImage); } + if (butPtr->tristateImage != NULL) { + Tk_FreeImage(butPtr->tristateImage); + } if (butPtr->normalTextGC != None) { Tk_FreeGC(butPtr->display, butPtr->normalTextGC); } @@ -1009,28 +1009,28 @@ DestroyButton(butPtr) * * ConfigureButton -- * - * This procedure is called to process an objc/objv list to set + * This function is called to process an objc/objv list to set * configuration options for a button widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then an error message is left in interp's result. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then an error message is left in interp's result. * * Side effects: - * Configuration information, such as text string, colors, font, - * etc. get set for butPtr; old resources get freed, if there - * were any. The button is redisplayed. + * Configuration information, such as text string, colors, font, etc. get + * set for butPtr; old resources get freed, if there were any. The button + * is redisplayed. * *---------------------------------------------------------------------- */ static int -ConfigureButton(interp, butPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - register TkButton *butPtr; /* Information about widget; may or may +ConfigureButton( + Tcl_Interp *interp, /* Used for error reporting. */ + register TkButton *butPtr, /* Information about widget; may or may * not already have values for some fields. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument values. */ { Tk_SavedOptions savedOptions; Tcl_Obj *errorResult = NULL; @@ -1042,21 +1042,21 @@ ConfigureButton(interp, butPtr, objc, objv) */ if (butPtr->textVarNamePtr != NULL) { - Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr), + Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr), TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, (ClientData) butPtr); } if (butPtr->selVarNamePtr != NULL) { - Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr), + Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr), TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, (ClientData) butPtr); } /* - * The following loop is potentially executed twice. During the - * first pass configuration options get set to their new values. - * If there is an error in this pass, we execute a second pass - * to restore all the options to their previous values. + * The following loop is potentially executed twice. During the first pass + * configuration options get set to their new values. If there is an error + * in this pass, we execute a second pass to restore all the options to + * their previous values. */ for (error = 0; error <= 1; error++) { @@ -1067,7 +1067,7 @@ ConfigureButton(interp, butPtr, objc, objv) if (Tk_SetOptions(interp, (char *) butPtr, butPtr->optionTable, objc, objv, - butPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { + butPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -1089,8 +1089,8 @@ ConfigureButton(interp, butPtr, objc, objv) /* * A few options need special processing, such as setting the - * background from a 3-D border, or filling in complicated - * defaults that couldn't be specified to Tk_SetOptions. + * background from a 3-D border, or filling in complicated defaults + * that couldn't be specified to Tk_SetOptions. */ if ((butPtr->state == STATE_ACTIVE) @@ -1114,28 +1114,43 @@ ConfigureButton(interp, butPtr, objc, objv) if (butPtr->type >= TYPE_CHECK_BUTTON) { Tcl_Obj *valuePtr, *namePtr; - + if (butPtr->selVarNamePtr == NULL) { butPtr->selVarNamePtr = Tcl_NewStringObj( Tk_Name(butPtr->tkwin), -1); Tcl_IncrRefCount(butPtr->selVarNamePtr); } namePtr = butPtr->selVarNamePtr; - + /* * Select the button if the associated variable has the - * appropriate value, initialize the variable if it doesn't - * exist, then set a trace on the variable to monitor future - * changes to its value. + * appropriate value, initialize the variable if it doesn't exist, + * then set a trace on the variable to monitor future changes to + * its value. */ - + valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY); butPtr->flags &= ~SELECTED; + butPtr->flags &= ~TRISTATED; if (valuePtr != NULL) { - if (strcmp(Tcl_GetString(valuePtr), - Tcl_GetString(butPtr->onValuePtr)) == 0) { + const char *value = Tcl_GetString(valuePtr); + if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) { butPtr->flags |= SELECTED; - } + } else if (strcmp(value, + Tcl_GetString(butPtr->tristateValuePtr)) == 0) { + butPtr->flags |= TRISTATED; + + /* + * For checkbuttons if the tristate value is the + * same as the offvalue then prefer off to tristate + */ + + if (butPtr->offValuePtr + && strcmp(value, + Tcl_GetString(butPtr->offValuePtr)) == 0) { + butPtr->flags &= ~TRISTATED; + } + } } else { if (Tcl_ObjSetVar2(interp, namePtr, NULL, (butPtr->type == TYPE_CHECK_BUTTON) @@ -1146,8 +1161,8 @@ ConfigureButton(interp, butPtr, objc, objv) } /* - * If a radiobutton has the empty string as value - * it should be selected. + * If a radiobutton has the empty string as value it should be + * selected. */ if ((butPtr->type == TYPE_RADIO_BUTTON) && @@ -1158,11 +1173,11 @@ ConfigureButton(interp, butPtr, objc, objv) } /* - * Get the images for the widget, if there are any. Allocate the - * new images before freeing the old ones, so that the reference - * counts don't go to zero and cause image data to be discarded. + * Get the images for the widget, if there are any. Allocate the new + * images before freeing the old ones, so that the reference counts + * don't go to zero and cause image data to be discarded. */ - + if (butPtr->imagePtr != NULL) { image = Tk_GetImage(butPtr->interp, butPtr->tkwin, Tcl_GetString(butPtr->imagePtr), ButtonImageProc, @@ -1191,6 +1206,20 @@ ConfigureButton(interp, butPtr, objc, objv) Tk_FreeImage(butPtr->selectImage); } butPtr->selectImage = image; + if (butPtr->tristateImagePtr != NULL) { + image = Tk_GetImage(butPtr->interp, butPtr->tkwin, + Tcl_GetString(butPtr->tristateImagePtr), + ButtonTristateImageProc, (ClientData) butPtr); + if (image == NULL) { + continue; + } + } else { + image = NULL; + } + if (butPtr->tristateImage != NULL) { + Tk_FreeImage(butPtr->tristateImage); + } + butPtr->tristateImage = image; haveImage = 0; if (butPtr->imagePtr != NULL || butPtr->bitmap != None) { @@ -1203,7 +1232,7 @@ ConfigureButton(interp, butPtr, objc, objv) * on the variable's value, create the variable if it doesn't * exist, and fetch its current value. */ - + Tcl_Obj *valuePtr, *namePtr; namePtr = butPtr->textVarNamePtr; @@ -1222,22 +1251,21 @@ ConfigureButton(interp, butPtr, objc, objv) Tcl_IncrRefCount(butPtr->textPtr); } } - + if ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) { /* - * The button must display the contents of an image or - * bitmap. + * The button must display the contents of an image or bitmap. */ if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthPtr, &butPtr->width) != TCL_OK) { - widthError: + widthError: Tcl_AddErrorInfo(interp, "\n (processing -width option)"); continue; } if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightPtr, &butPtr->height) != TCL_OK) { - heightError: + heightError: Tcl_AddErrorInfo(interp, "\n (processing -height option)"); continue; } @@ -1275,7 +1303,7 @@ ConfigureButton(interp, butPtr, objc, objv) TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonVarProc, (ClientData) butPtr); } - + TkButtonWorldChanged((ClientData) butPtr); if (error) { Tcl_SetObjResult(interp, errorResult); @@ -1291,9 +1319,9 @@ ConfigureButton(interp, butPtr, objc, objv) * * TkButtonWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: * None. @@ -1303,10 +1331,10 @@ ConfigureButton(interp, butPtr, objc, objv) * *--------------------------------------------------------------------------- */ - + void -TkButtonWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +TkButtonWorldChanged( + ClientData instanceData) /* Information about widget. */ { XGCValues gcValues; GC newGC; @@ -1322,7 +1350,7 @@ TkButtonWorldChanged(instanceData) gcValues.font = Tk_FontId(butPtr->tkfont); gcValues.foreground = butPtr->normalFg->pixel; gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel; - + /* * Note: GraphicsExpose events are disabled in normalTextGC because it's * used to copy stuff from an off-screen pixmap onto the screen (we know @@ -1369,8 +1397,8 @@ TkButtonWorldChanged(instanceData) } /* - * Allocate the disabled graphics context, for drawing text in - * its disabled state. + * Allocate the disabled graphics context, for drawing text in its + * disabled state. */ mask = GCForeground | GCBackground | GCFont; @@ -1406,31 +1434,31 @@ TkButtonWorldChanged(instanceData) * * ButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This function is invoked by the Tk dispatcher for various events on + * buttons. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -ButtonEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +ButtonEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkButton *butPtr = (TkButton *) clientData; if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) { goto redraw; } else if (eventPtr->type == ConfigureNotify) { /* - * Must redraw after size changes, since layout could have changed - * and borders will need to be redrawn. + * Must redraw after size changes, since layout could have changed and + * borders will need to be redrawn. */ goto redraw; @@ -1453,7 +1481,7 @@ ButtonEventProc(clientData, eventPtr) } return; - redraw: + redraw: if ((butPtr->tkwin != NULL) && !(butPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr); butPtr->flags |= REDRAW_PENDING; @@ -1465,9 +1493,9 @@ ButtonEventProc(clientData, eventPtr) * * ButtonCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -1479,16 +1507,16 @@ ButtonEventProc(clientData, eventPtr) */ static void -ButtonCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +ButtonCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkButton *butPtr = (TkButton *) clientData; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted or because the command - * was deleted, and then this procedure destroys the widget. The - * BUTTON_DELETED flag distinguishes these cases. + * This function could be invoked either because the window was destroyed + * and the command was then deleted or because the command was deleted, + * and then this function destroys the widget. The BUTTON_DELETED flag + * distinguishes these cases. */ if (!(butPtr->flags & BUTTON_DELETED)) { @@ -1501,14 +1529,14 @@ ButtonCmdDeletedProc(clientData) * * TkInvokeButton -- * - * This procedure is called to carry out the actions associated - * with a button, such as invoking a Tcl command or setting a - * variable. This procedure is invoked, for example, when the - * button is invoked via the mouse. + * This function is called to carry out the actions associated with a + * button, such as invoking a Tcl command or setting a variable. This + * function is invoked, for example, when the button is invoked via the + * mouse. * * Results: - * A standard Tcl return value. Information is also left in - * the interp's result. + * A standard Tcl return value. Information is also left in the interp's + * result. * * Side effects: * Depends on the button and its associated command. @@ -1517,8 +1545,8 @@ ButtonCmdDeletedProc(clientData) */ int -TkInvokeButton(butPtr) - TkButton *butPtr; /* Information about button. */ +TkInvokeButton( + TkButton *butPtr) /* Information about button. */ { Tcl_Obj *namePtr = butPtr->selVarNamePtr; @@ -1555,10 +1583,9 @@ TkInvokeButton(butPtr) * * ButtonVarProc -- * - * This procedure is invoked when someone changes the - * state variable associated with a radio button. Depending - * on the new value of the button's variable, the button - * may be selected or deselected. + * This function is invoked when someone changes the state variable + * associated with a radio button. Depending on the new value of the + * button's variable, the button may be selected or deselected. * * Results: * NULL is always returned. @@ -1571,12 +1598,12 @@ TkInvokeButton(butPtr) /* ARGSUSED */ static char * -ButtonVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about button. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Name of variable. */ - CONST char *name2; /* Second part of variable name. */ - int flags; /* Information about what happened. */ +ButtonVarProc( + ClientData clientData, /* Information about button. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + const char *name1, /* Name of variable. */ + const char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ { register TkButton *butPtr = (TkButton *) clientData; char *name, *value; @@ -1585,12 +1612,13 @@ ButtonVarProc(clientData, interp, name1, name2, flags) name = Tcl_GetString(butPtr->selVarNamePtr); /* - * If the variable is being unset, then just re-establish the - * trace unless the whole interpreter is going away. + * If the variable is being unset, then just re-establish the trace unless + * the whole interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { butPtr->flags &= ~SELECTED; + butPtr->flags &= ~TRISTATED; if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { Tcl_TraceVar(interp, name, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, @@ -1600,34 +1628,47 @@ ButtonVarProc(clientData, interp, name1, name2, flags) } /* - * Use the value of the variable to update the selected status of - * the button. + * Use the value of the variable to update the selected status of the + * button. */ valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY); if (valuePtr == NULL) { - value = ""; + value = Tcl_GetString(butPtr->tristateValuePtr); } else { value = Tcl_GetString(valuePtr); } if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) { if (butPtr->flags & SELECTED) { - return (char *) NULL; + return NULL; } butPtr->flags |= SELECTED; - } else if (butPtr->flags & SELECTED) { - butPtr->flags &= ~SELECTED; + butPtr->flags &= ~TRISTATED; + } else if (butPtr->offValuePtr + && strcmp(value, Tcl_GetString(butPtr->offValuePtr)) == 0) { + if (!(butPtr->flags & (SELECTED | TRISTATED))) { + return NULL; + } + butPtr->flags &= ~(SELECTED | TRISTATED); + } else if (strcmp(value, Tcl_GetString(butPtr->tristateValuePtr)) == 0) { + if (butPtr->flags & TRISTATED) { + return NULL; + } + butPtr->flags |= TRISTATED; + butPtr->flags &= ~SELECTED; + } else if (butPtr->flags & (SELECTED | TRISTATED)) { + butPtr->flags &= ~(SELECTED | TRISTATED); } else { - return (char *) NULL; + return NULL; } - redisplay: + redisplay: if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin) && !(butPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr); butPtr->flags |= REDRAW_PENDING; } - return (char *) NULL; + return NULL; } /* @@ -1635,52 +1676,51 @@ ButtonVarProc(clientData, interp, name1, name2, flags) * * ButtonTextVarProc -- * - * This procedure is invoked when someone changes the variable - * whose contents are to be displayed in a button. + * This function is invoked when someone changes the variable whose + * contents are to be displayed in a button. * * Results: * NULL is always returned. * * Side effects: - * The text displayed in the button will change to match the - * variable. + * The text displayed in the button will change to match the variable. * *-------------------------------------------------------------- */ /* ARGSUSED */ static char * -ButtonTextVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about button. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Not used. */ - CONST char *name2; /* Not used. */ - int flags; /* Information about what happened. */ +ButtonTextVarProc( + ClientData clientData, /* Information about button. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + const char *name1, /* Not used. */ + const char *name2, /* Not used. */ + int flags) /* Information about what happened. */ { TkButton *butPtr = (TkButton *) clientData; char *name; Tcl_Obj *valuePtr; if (butPtr->flags & BUTTON_DELETED) { - return (char *) NULL; + return NULL; } name = Tcl_GetString(butPtr->textVarNamePtr); /* - * If the variable is unset, then immediately recreate it unless - * the whole interpreter is going away. + * If the variable is unset, then immediately recreate it unless the whole + * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_SetVar2Ex(interp, name, NULL, butPtr->textPtr, + Tcl_SetVar2Ex(interp, name, NULL, butPtr->textPtr, TCL_GLOBAL_ONLY); Tcl_TraceVar(interp, name, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ButtonTextVarProc, clientData); } - return (char *) NULL; + return NULL; } valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY); @@ -1697,7 +1737,7 @@ ButtonTextVarProc(clientData, interp, name1, name2, flags) Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr); butPtr->flags |= REDRAW_PENDING; } - return (char *) NULL; + return NULL; } /* @@ -1705,9 +1745,9 @@ ButtonTextVarProc(clientData, interp, name1, name2, flags) * * ButtonImageProc -- * - * This procedure is invoked by the image code whenever the manager - * for an image does something that affects the size or contents - * of an image displayed in a button. + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size or contents of an image + * displayed in a button. * * Results: * None. @@ -1719,13 +1759,13 @@ ButtonTextVarProc(clientData, interp, name1, name2, flags) */ static void -ButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight) - ClientData clientData; /* Pointer to widget record. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +ButtonImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (might be + * <= 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { register TkButton *butPtr = (TkButton *) clientData; @@ -1743,9 +1783,9 @@ ButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight) * * ButtonSelectImageProc -- * - * This procedure is invoked by the image code whenever the manager - * for an image does something that affects the size or contents - * of the image displayed in a button when it is selected. + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size or contents of the image + * displayed in a button when it is selected. * * Results: * None. @@ -1757,18 +1797,18 @@ ButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight) */ static void -ButtonSelectImageProc(clientData, x, y, width, height, imgWidth, imgHeight) - ClientData clientData; /* Pointer to widget record. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +ButtonSelectImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (might be + * <= 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { register TkButton *butPtr = (TkButton *) clientData; /* - * Don't recompute geometry: it's controlled by the primary image. + * Don't recompute geometry: it's controlled by the primary image. */ if ((butPtr->flags & SELECTED) && (butPtr->tkwin != NULL) @@ -1778,3 +1818,52 @@ ButtonSelectImageProc(clientData, x, y, width, height, imgWidth, imgHeight) butPtr->flags |= REDRAW_PENDING; } } + +/* + *---------------------------------------------------------------------- + * + * ButtonTristateImageProc -- + * + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size or contents of the image + * displayed in a button when it is selected. + * + * Results: + * None. + * + * Side effects: + * May arrange for the button to get redisplayed. + * + *---------------------------------------------------------------------- + */ + +static void +ButtonTristateImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (might be + * <= 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ +{ + register TkButton *butPtr = (TkButton *) clientData; + + /* + * Don't recompute geometry: it's controlled by the primary image. + */ + + if ((butPtr->flags & TRISTATED) && (butPtr->tkwin != NULL) + && Tk_IsMapped(butPtr->tkwin) + && !(butPtr->flags & REDRAW_PENDING)) { + Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) butPtr); + butPtr->flags |= REDRAW_PENDING; + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkButton.h b/generic/tkButton.h index 9547c9a..4fde4c1 100644 --- a/generic/tkButton.h +++ b/generic/tkButton.h @@ -1,13 +1,13 @@ /* * tkButton.h -- * - * Declarations of types and functions used to implement - * button-like widgets. + * Declarations of types and functions used to implement button-like + * widgets. * * Copyright (c) 1996-1998 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKBUTTON @@ -48,20 +48,20 @@ enum defaultState { }; /* - * A data structure of the following type is kept for each - * widget managed by this file: + * A data structure of the following type is kept for each widget managed by + * this file: */ typedef struct { - Tk_Window tkwin; /* Window that embodies the button. NULL - * means that the window has been destroyed. */ - Display *display; /* Display containing widget. Needed to - * free up resources after tkwin is gone. */ + Tk_Window tkwin; /* Window that embodies the button. NULL means + * that the window has been destroyed. */ + Display *display; /* Display containing widget. Needed to free + * up resources after tkwin is gone. */ Tcl_Interp *interp; /* Interpreter associated with button. */ Tcl_Command widgetCmd; /* Token for button's widget command. */ int type; /* Type of widget, such as TYPE_LABEL: * restricts operations that may be performed - * on widget. See below for legal values. */ + * on widget. See below for legal values. */ Tk_OptionTable optionTable; /* Table that defines configuration options * available for this widget. */ @@ -71,96 +71,102 @@ typedef struct { Tcl_Obj *textPtr; /* Value of -text option: specifies text to * display in button. */ - int underline; /* Value of -underline option: specifies - * index of character to underline. < 0 means - * don't underline anything. */ + int underline; /* Value of -underline option: specifies index + * of character to underline. < 0 means don't + * underline anything. */ Tcl_Obj *textVarNamePtr; /* Value of -textvariable option: specifies - * name of variable or NULL. If non-NULL, + * name of variable or NULL. If non-NULL, * button displays the contents of this * variable. */ - Pixmap bitmap; /* Value of -bitmap option. If not None, + Pixmap bitmap; /* Value of -bitmap option. If not None, * specifies bitmap to display and text and * textVar are ignored. */ - Tcl_Obj *imagePtr; /* Value of -image option: specifies image - * to display in window, or NULL if none. - * If non-NULL, bitmap, text, and textVarName - * are ignored.*/ + Tcl_Obj *imagePtr; /* Value of -image option: specifies image to + * display in window, or NULL if none. If + * non-NULL, bitmap, text, and textVarName are + * ignored.*/ Tk_Image image; /* Derived from imagePtr by calling - * Tk_GetImage, or NULL if imagePtr is NULL. */ + * Tk_GetImage, or NULL if imagePtr is + * NULL. */ Tcl_Obj *selectImagePtr; /* Value of -selectimage option: specifies * image to display in window when selected, - * or NULL if none. Ignored if imagePtr is + * or NULL if none. Ignored if imagePtr is * NULL. */ Tk_Image selectImage; /* Derived from selectImagePtr by calling - * Tk_GetImage, or NULL if selectImagePtr - * is NULL. */ + * Tk_GetImage, or NULL if selectImagePtr is + * NULL. */ + Tcl_Obj *tristateImagePtr; /* Value of -tristateimage option: specifies + * image to display in window when selected, + * or NULL if none. Ignored if imagePtr is + * NULL. */ + Tk_Image tristateImage; /* Derived from tristateImagePtr by calling + * Tk_GetImage, or NULL if tristateImagePtr is + * NULL. */ /* * Information used when displaying widget: */ - enum state state; /* Value of -state option: specifies - * state of button for display purposes.*/ + enum state state; /* Value of -state option: specifies state of + * button for display purposes.*/ Tk_3DBorder normalBorder; /* Value of -background option: specifies * color for background (and border) when * window isn't active. */ - Tk_3DBorder activeBorder; /* Value of -activebackground option: - * this is the color used to draw 3-D border - * and background when widget is active. */ + Tk_3DBorder activeBorder; /* Value of -activebackground option: this is + * the color used to draw 3-D border and + * background when widget is active. */ Tcl_Obj *borderWidthPtr; /* Value of -borderWidth option: specifies * width of border in pixels. */ int borderWidth; /* Integer value corresponding to - * borderWidthPtr. Always >= 0. */ + * borderWidthPtr. Always >= 0. */ int relief; /* Value of -relief option: specifies 3-d * effect for border, such as * TK_RELIEF_RAISED. */ - int overRelief; /* Value of -overrelief option: specifies a 3-d - * effect for the border, such as + int overRelief; /* Value of -overrelief option: specifies a + * 3-d effect for the border, such as * TK_RELIEF_RAISED, to be used when the mouse * is over the button. */ int offRelief; /* Value of -offrelief option: specifies a 3-d * effect for the border, such as * TK_RELIEF_RAISED, to be used when a - * checkbutton or radiobutton without - * indicator is off */ + * checkbutton or radiobutton without + * indicator is off. */ Tcl_Obj *highlightWidthPtr; /* Value of -highlightthickness option: * specifies width in pixels of highlight to * draw around widget when it has the focus. * <= 0 means don't draw a highlight. */ int highlightWidth; /* Integer value corresponding to - * highlightWidthPtr. Always >= 0. */ + * highlightWidthPtr. Always >= 0. */ Tk_3DBorder highlightBorder;/* Value of -highlightbackground option: * specifies background with which to draw 3-D * default ring and focus highlight area when * highlight is off. */ - XColor *highlightColorPtr; /* Value of -highlightcolor option: - * specifies color for drawing traversal - * highlight. */ + XColor *highlightColorPtr; /* Value of -highlightcolor option: specifies + * color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. - * Indicates how much interior stuff must - * be offset from outside edges to leave - * room for borders. */ - Tk_Font tkfont; /* Value of -font option: specifies font - * to use for display text. */ + * Indicates how much interior stuff must be + * offset from outside edges to leave room for + * borders. */ + Tk_Font tkfont; /* Value of -font option: specifies font to + * use for display text. */ XColor *normalFg; /* Value of -font option: specifies foreground * color in normal mode. */ XColor *activeFg; /* Value of -activeforeground option: - * foreground color in active mode. NULL - * means use -foreground instead. */ + * foreground color in active mode. NULL means + * use -foreground instead. */ XColor *disabledFg; /* Value of -disabledforeground option: - * foreground color when disabled. NULL - * means use normalFg with a 50% stipple - * instead. */ - GC normalTextGC; /* GC for drawing text in normal mode. Also + * foreground color when disabled. NULL means + * use normalFg with a 50% stipple instead. */ + GC normalTextGC; /* GC for drawing text in normal mode. Also * used to copy from off-screen pixmap onto * screen. */ GC activeTextGC; /* GC for drawing text in active mode (NULL * means use normalTextGC). */ GC disabledGC; /* Used to produce disabled effect for text * and check/radio marks. */ - GC stippleGC; /* Used to produce disabled stipple effect - * for images when disabled. */ + GC stippleGC; /* Used to produce disabled stipple effect for + * images when disabled. */ Pixmap gray; /* Pixmap for displaying disabled text if * disabledFg is NULL. */ GC copyGC; /* Used for copying information from an @@ -169,33 +175,34 @@ typedef struct { int width; /* Integer value corresponding to widthPtr. */ Tcl_Obj *heightPtr; /* Value of -height option. */ int height; /* Integer value corresponding to heightPtr. */ - Tcl_Obj *wrapLengthPtr; /* Value of -wraplength option: specifies - * line length (in pixels) at which to wrap - * onto next line. <= 0 means don't wrap - * except at newlines. */ + Tcl_Obj *wrapLengthPtr; /* Value of -wraplength option: specifies line + * length (in pixels) at which to wrap onto + * next line. <= 0 means don't wrap except at + * newlines. */ int wrapLength; /* Integer value corresponding to * wrapLengthPtr. */ Tcl_Obj *padXPtr; /* Value of -padx option: specifies how many * pixels of extra space to leave on left and - * right of text. Ignored for bitmaps and + * right of text. Ignored for bitmaps and * images. */ int padX; /* Integer value corresponding to padXPtr. */ Tcl_Obj *padYPtr; /* Value of -padx option: specifies how many * pixels of extra space to leave above and - * below text. Ignored for bitmaps and + * below text. Ignored for bitmaps and * images. */ int padY; /* Integer value corresponding to padYPtr. */ Tk_Anchor anchor; /* Value of -anchor option: specifies where * text/bitmap should be displayed inside * button region. */ - Tk_Justify justify; /* Value of -justify option: specifies how - * to align lines of multi-line text. */ - int indicatorOn; /* Value of -indicatoron option: 1 means - * draw indicator in checkbuttons and - * radiobuttons, 0 means don't draw it. */ + Tk_Justify justify; /* Value of -justify option: specifies how to + * align lines of multi-line text. */ + int indicatorOn; /* Value of -indicatoron option: 1 means draw + * indicator in checkbuttons and radiobuttons, + * 0 means don't draw it. */ Tk_3DBorder selectBorder; /* Value of -selectcolor option: specifies * color for drawing indicator background, or - * perhaps widget background, when selected. */ + * perhaps widget background, when + * selected. */ int textWidth; /* Width needed to display text as requested, * in pixels. */ int textHeight; /* Height needed to display text as requested, @@ -206,26 +213,28 @@ typedef struct { int indicatorDiameter; /* Diameter of indicator, in pixels. */ enum defaultState defaultState; /* Value of -default option, such as - * DEFAULT_NORMAL: specifies state - * of default ring for buttons (normal, - * active, or disabled). NULL for other - * classes. */ + * DEFAULT_NORMAL: specifies state of default + * ring for buttons (normal, active, or + * disabled). NULL for other classes. */ /* - * For check and radio buttons, the fields below are used - * to manage the variable indicating the button's state. + * For check and radio buttons, the fields below are used to manage the + * variable indicating the button's state. */ Tcl_Obj *selVarNamePtr; /* Value of -variable option: specifies name - * of variable used to control selected - * state of button. */ + * of variable used to control selected state + * of button. */ Tcl_Obj *onValuePtr; /* Value of -offvalue option: specifies value * to store in variable when this button is * selected. */ Tcl_Obj *offValuePtr; /* Value of -offvalue option: specifies value - * to store in variable when this button - * isn't selected. Used only by - * checkbuttons. */ + * to store in variable when this button isn't + * selected. Used only by checkbuttons. */ + Tcl_Obj *tristateValuePtr; /* Value of -tristatevalue option: specifies + * value to display Tristate or Multivalue + * mode when variable matches this value. + * Used by check- buttons. */ /* * Miscellaneous information: @@ -233,31 +242,30 @@ typedef struct { Tk_Cursor cursor; /* Value of -cursor option: if not None, * specifies current cursor for window. */ - Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal + Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal * scripts. */ - Tcl_Obj *commandPtr; /* Value of -command option: specifies script - * to execute when button is invoked. If - * widget is label or has no command, this - * is NULL. */ - int compound; /* Value of -compound option; specifies whether - * the button should show both an image and - * text, and, if so, how. */ - int repeatDelay; /* Value of -repeatdelay option; specifies - * the number of ms after which the button will + Tcl_Obj *commandPtr; /* Value of -command option: specifies script + * to execute when button is invoked. If + * widget is label or has no command, this is + * NULL. */ + int compound; /* Value of -compound option; specifies + * whether the button should show both an + * image and text, and, if so, how. */ + int repeatDelay; /* Value of -repeatdelay option; specifies the + * number of ms after which the button will * start to auto-repeat its command. */ int repeatInterval; /* Value of -repeatinterval option; specifies * the number of ms between auto-repeat * invocataions of the button command. */ - int flags; /* Various flags; see below for + int flags; /* Various flags; see below for * definitions. */ } TkButton; /* - * Possible "type" values for buttons. These are the kinds of - * widgets supported by this file. The ordering of the type - * numbers is significant: greater means more features and is - * used in the code. + * Possible "type" values for buttons. These are the kinds of widgets + * supported by this file. The ordering of the type numbers is significant: + * greater means more features and is used in the code. */ #define TYPE_LABEL 0 @@ -268,51 +276,46 @@ typedef struct { /* * Flag bits for buttons: * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler - * has already been queued to redraw - * this window. - * SELECTED: Non-zero means this button is selected, - * so special highlight should be drawn. - * GOT_FOCUS: Non-zero means this button currently - * has the input focus. + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has + * already been queued to redraw this window. + * SELECTED: Non-zero means this button is selected, so + * special highlight should be drawn. + * GOT_FOCUS: Non-zero means this button currently has the + * input focus. * BUTTON_DELETED: Non-zero needs that this button has been - * deleted, or is in the process of being - * deleted. + * deleted, or is in the process of being deleted */ #define REDRAW_PENDING (1 << 0) #define SELECTED (1 << 1) #define GOT_FOCUS (1 << 2) #define BUTTON_DELETED (1 << 3) +#define TRISTATED (1 << 4) + /* - * Declaration of button class functions structure - * and button/label defaults, for use in optionSpecs. + * Declaration of variables shared between the files in the button module. */ -extern Tk_ClassProcs tkpButtonProcs; -extern char tkDefButtonBorderWidth[TCL_INTEGER_SPACE]; +MODULE_SCOPE Tk_ClassProcs tkpButtonProcs; +MODULE_SCOPE char tkDefButtonBorderWidth[TCL_INTEGER_SPACE]; /* - * Declaration of procedures used in the implementation of the button - * widget. + * Declaration of functions used in the implementation of the button widget. */ #ifndef TkpButtonSetDefaults -EXTERN void TkpButtonSetDefaults _ANSI_ARGS_(( - Tk_OptionSpec *specPtr)); +MODULE_SCOPE void TkpButtonSetDefaults(Tk_OptionSpec *specPtr); #endif -EXTERN void TkButtonWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -EXTERN void TkpComputeButtonGeometry _ANSI_ARGS_(( - TkButton *butPtr)); -EXTERN TkButton * TkpCreateButton _ANSI_ARGS_((Tk_Window tkwin)); +MODULE_SCOPE void TkButtonWorldChanged(ClientData instanceData); +MODULE_SCOPE void TkpComputeButtonGeometry(TkButton *butPtr); +MODULE_SCOPE TkButton *TkpCreateButton(Tk_Window tkwin); #ifndef TkpDestroyButton -EXTERN void TkpDestroyButton _ANSI_ARGS_((TkButton *butPtr)); +MODULE_SCOPE void TkpDestroyButton(TkButton *butPtr); #endif #ifndef TkpDisplayButton -EXTERN void TkpDisplayButton _ANSI_ARGS_((ClientData clientData)); +MODULE_SCOPE void TkpDisplayButton(ClientData clientData); #endif -EXTERN int TkInvokeButton _ANSI_ARGS_((TkButton *butPtr)); +MODULE_SCOPE int TkInvokeButton(TkButton *butPtr); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tkCanvArc.c b/generic/tkCanvArc.c index 9bee1ef..ecd57b8 100644 --- a/generic/tkCanvArc.c +++ b/generic/tkCanvArc.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvArc.c -- * * This file implements arc items for canvas widgets. @@ -6,14 +6,14 @@ * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> -#include "tkPort.h" #include "tkInt.h" #include "tkCanvas.h" + /* * The structure below defines the record for each arc item. */ @@ -22,41 +22,42 @@ typedef enum { PIESLICE_STYLE, CHORD_STYLE, ARC_STYLE } Style; -typedef struct ArcItem { +typedef struct ArcItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ Tk_Outline outline; /* Outline structure */ double bbox[4]; /* Coordinates (x1, y1, x2, y2) of bounding * box for oval of which arc is a piece. */ double start; /* Angle at which arc begins, in degrees * between 0 and 360. */ - double extent; /* Extent of arc (angular distance from - * start to end of arc) in degrees between - * -360 and 360. */ - double *outlinePtr; /* Points to (x,y) coordinates for points - * that define one or two closed polygons + double extent; /* Extent of arc (angular distance from start + * to end of arc) in degrees between -360 and + * 360. */ + double *outlinePtr; /* Points to (x,y) coordinates for points that + * define one or two closed polygons * representing the portion of the outline - * that isn't part of the arc (the V-shape - * for a pie slice or a line-like segment - * for a chord). Malloc'ed. */ - int numOutlinePoints; /* Number of points at outlinePtr. Zero - * means no space allocated. */ + * that isn't part of the arc (the V-shape for + * a pie slice or a line-like segment for a + * chord). Malloc'ed. */ + int numOutlinePoints; /* Number of points at outlinePtr. Zero means + * no space allocated. */ Tk_TSOffset tsoffset; XColor *fillColor; /* Color for filling arc (used for drawing - * outline too when style is "arc"). NULL + * outline too when style is "arc"). NULL * means don't fill arc. */ XColor *activeFillColor; /* Color for filling arc (used for drawing * outline too when style is "arc" and state - * is "active"). NULL means use fillColor. */ + * is "active"). NULL means use fillColor. */ XColor *disabledFillColor; /* Color for filling arc (used for drawing * outline too when style is "arc" and state * is "disabled". NULL means use fillColor */ Pixmap fillStipple; /* Stipple bitmap for filling item. */ - Pixmap activeFillStipple; /* Stipple bitmap for filling item if state - * is active. */ - Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state - * is disabled. */ - Style style; /* How to draw arc: arc, chord, or pieslice. */ + Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is + * active. */ + Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is + * disabled. */ + Style style; /* How to draw arc: arc, chord, or + * pieslice. */ GC fillGC; /* Graphics context for filling item. */ double center1[2]; /* Coordinates of center of arc outline at * start (see ComputeArcOutline). */ @@ -65,8 +66,8 @@ typedef struct ArcItem { } ArcItem; /* - * The definitions below define the sizes of the polygons used to - * display outline information for various styles of arcs: + * The definitions below define the sizes of the polygons used to display + * outline information for various styles of arcs: */ #define CHORD_OUTLINE_PTS 7 @@ -77,14 +78,11 @@ typedef struct ArcItem { * Information used for parsing configuration specs: */ -static int StyleParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, +static int StyleParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, CONST char *value, - char *widgRec, int offset)); -static char * StylePrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); + char *widgRec, int offset); +static char * StylePrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); static Tk_CustomOption stateOption = { (Tk_OptionParseProc *) TkStateParseProc, @@ -112,169 +110,152 @@ static Tk_CustomOption pixelOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.activeDash), + {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, activeFillColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.activeColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.activeStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, activeFillStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-activefill", NULL, NULL, + NULL, Tk_Offset(ArcItem, activeFillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.activeColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.activeStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, + NULL, Tk_Offset(ArcItem, activeFillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, "0.0", Tk_Offset(ArcItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.dash), + {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, "0", Tk_Offset(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.disabledDash), + {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, disabledFillColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.disabledColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.disabledStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, disabledFillStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, + NULL, Tk_Offset(ArcItem, disabledFillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.disabledColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.disabledStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, + NULL, Tk_Offset(ArcItem, disabledFillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL, "0.0", Tk_Offset(ArcItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_DOUBLE, "-extent", (char *) NULL, (char *) NULL, + {TK_CONFIG_DOUBLE, "-extent", NULL, NULL, "90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-fill", NULL, NULL, + NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, "0,0", Tk_Offset(ArcItem, tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, - {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-outline", NULL, NULL, "black", Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL, "0,0", Tk_Offset(ArcItem, outline.tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, - {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, outline.stipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_DOUBLE, "-start", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL, + NULL, Tk_Offset(ArcItem, outline.stipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_DOUBLE, "-start", NULL, NULL, "0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-style", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, + NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-style", NULL, NULL, + NULL, Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT, &styleOption}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_CUSTOM, "-width", NULL, NULL, "1.0", Tk_Offset(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static void ComputeArcBbox _ANSI_ARGS_((Tk_Canvas canvas, - ArcItem *arcPtr)); -static int ConfigureArc _ANSI_ARGS_((Tcl_Interp *interp, +static void ComputeArcBbox(Tk_Canvas canvas, ArcItem *arcPtr); +static int ConfigureArc(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static int CreateArc _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[], int flags); +static int CreateArc(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeleteArc _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayArc _ANSI_ARGS_((Tk_Canvas canvas, + int objc, Tcl_Obj *CONST objv[]); +static void DeleteArc(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayArc(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static int ArcCoords _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[])); -static int ArcToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static double ArcToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *coordPtr)); -static int ArcToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static void ScaleArc _ANSI_ARGS_((Tk_Canvas canvas, + int x, int y, int width, int height); +static int ArcCoords(Tcl_Interp *interp, Tk_Canvas canvas, + Tk_Item *itemPtr, int objc, Tcl_Obj *CONST objv[]); +static int ArcToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static double ArcToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *coordPtr); +static int ArcToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void ScaleArc(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslateArc _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); -static int AngleInRange _ANSI_ARGS_((double x, double y, - double start, double extent)); -static void ComputeArcOutline _ANSI_ARGS_((Tk_Canvas canvas, - ArcItem *arcPtr)); -static int HorizLineToArc _ANSI_ARGS_((double x1, double x2, + double scaleX, double scaleY); +static void TranslateArc(Tk_Canvas canvas, + Tk_Item *itemPtr, double deltaX, double deltaY); +static int AngleInRange(double x, double y, + double start, double extent); +static void ComputeArcOutline(Tk_Canvas canvas, ArcItem *arcPtr); +static int HorizLineToArc(double x1, double x2, double y, double rx, double ry, - double start, double extent)); -static int VertLineToArc _ANSI_ARGS_((double x, double y1, + double start, double extent); +static int VertLineToArc(double x, double y1, double y2, double rx, double ry, - double start, double extent)); + double start, double extent); /* - * The structures below defines the arc item types by means of procedures - * that can be invoked by generic item code. + * The structures below defines the arc item types by means of functions that + * can be invoked by generic item code. */ Tk_ItemType tkArcType = { - "arc", /* name */ - sizeof(ArcItem), /* itemSize */ - CreateArc, /* createProc */ - configSpecs, /* configSpecs */ - ConfigureArc, /* configureProc */ - ArcCoords, /* coordProc */ - DeleteArc, /* deleteProc */ - DisplayArc, /* displayProc */ - TK_CONFIG_OBJS, /* flags */ - ArcToPoint, /* pointProc */ - ArcToArea, /* areaProc */ - ArcToPostscript, /* postscriptProc */ - ScaleArc, /* scaleProc */ - TranslateArc, /* translateProc */ - (Tk_ItemIndexProc *) NULL, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* icursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ - (Tk_ItemInsertProc *) NULL, /* insertProc */ - (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + "arc", /* name */ + sizeof(ArcItem), /* itemSize */ + CreateArc, /* createProc */ + configSpecs, /* configSpecs */ + ConfigureArc, /* configureProc */ + ArcCoords, /* coordProc */ + DeleteArc, /* deleteProc */ + DisplayArc, /* displayProc */ + TK_CONFIG_OBJS, /* flags */ + ArcToPoint, /* pointProc */ + ArcToArea, /* areaProc */ + ArcToPostscript, /* postscriptProc */ + ScaleArc, /* scaleProc */ + TranslateArc, /* translateProc */ + NULL, /* indexProc */ + NULL, /* icursorProc */ + NULL, /* selectionProc */ + NULL, /* insertProc */ + NULL, /* dTextProc */ + NULL, /* nextPtr */ }; #ifndef PI -# define PI 3.14159265358979323846 +#define PI 3.14159265358979323846 #endif - /* *-------------------------------------------------------------- * * CreateArc -- * - * This procedure is invoked to create a new arc item in - * a canvas. + * This function is invoked to create a new arc item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is - * left uninitialized, so it can be safely freed by the + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the * caller. * * Side effects: @@ -284,24 +265,24 @@ Tk_ItemType tkArcType = { */ static int -CreateArc(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing arc. */ +CreateArc( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing arc. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* - * Carry out initialization that is needed in order to clean - * up after errors during the the remainder of this procedure. + * Carry out initialization that is needed in order to clean up after + * errors during the the remainder of this function. */ Tk_CreateOutline(&(arcPtr->outline)); @@ -327,6 +308,7 @@ CreateArc(interp, canvas, itemPtr, objc, objv) for (i = 1; i < objc; i++) { char *arg = Tcl_GetString(objv[i]); + if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { break; } @@ -337,7 +319,8 @@ CreateArc(interp, canvas, itemPtr, objc, objv) if (ConfigureArc(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) { return TCL_OK; } - error: + + error: DeleteArc(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -347,9 +330,8 @@ CreateArc(interp, canvas, itemPtr, objc, objv) * * ArcCoords -- * - * This procedure is invoked to process the "coords" widget - * command on arcs. See the user documentation for details - * on what it does. + * This function is invoked to process the "coords" widget command on + * arcs. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -361,21 +343,20 @@ CreateArc(interp, canvas, itemPtr, objc, objv) */ static int -ArcCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +ArcCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { ArcItem *arcPtr = (ArcItem *) itemPtr; if (objc == 0) { Tcl_Obj *obj = Tcl_NewObj(); Tcl_Obj *subobj = Tcl_NewDoubleObj(arcPtr->bbox[0]); + Tcl_ListObjAppendElement(interp, obj, subobj); subobj = Tcl_NewDoubleObj(arcPtr->bbox[1]); Tcl_ListObjAppendElement(interp, obj, subobj); @@ -391,7 +372,7 @@ ArcCoords(interp, canvas, itemPtr, objc, objv) return TCL_ERROR; } else if (objc != 4) { char buf[64 + TCL_INTEGER_SPACE]; - + sprintf(buf, "wrong # coordinates: expected 4, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -410,7 +391,7 @@ ArcCoords(interp, canvas, itemPtr, objc, objv) ComputeArcBbox(canvas, arcPtr); } else { char buf[64 + TCL_INTEGER_SPACE]; - + sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -423,28 +404,28 @@ ArcCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureArc -- * - * This procedure is invoked to configure various aspects - * of a arc item, such as its outline and fill colors. + * This function is invoked to configure various aspects of a arc item, + * such as its outline and fill colors. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: - * Configuration information, such as colors and stipple - * patterns, may be set for itemPtr. + * Configuration information, such as colors and stipple patterns, may be + * set for itemPtr. * *-------------------------------------------------------------- */ static int -ConfigureArc(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Arc item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureArc( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Arc item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; XGCValues gcValues; @@ -466,8 +447,8 @@ ConfigureArc(interp, canvas, itemPtr, objc, objv, flags) state = itemPtr->state; /* - * A few of the options require additional processing, such as - * style and graphics contexts. + * A few of the options require additional processing, such as style and + * graphics contexts. */ if (arcPtr->outline.activeWidth > arcPtr->outline.width || @@ -506,8 +487,7 @@ ConfigureArc(interp, canvas, itemPtr, objc, objv, flags) i = (int) (arcPtr->extent/360.0); arcPtr->extent -= i*360.0; - mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, - &(arcPtr->outline)); + mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(arcPtr->outline)); if (mask) { gcValues.cap_style = CapButt; mask |= GCCapStyle; @@ -596,8 +576,8 @@ ConfigureArc(interp, canvas, itemPtr, objc, objv, flags) * * DeleteArc -- * - * This procedure is called to clean up the data structure - * associated with a arc item. + * This function is called to clean up the data structure associated with + * an arc item. * * Results: * None. @@ -609,11 +589,10 @@ ConfigureArc(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteArc(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall canvas. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeleteArc( + Tk_Canvas canvas, /* Info about overall canvas. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; @@ -649,31 +628,29 @@ DeleteArc(canvas, itemPtr, display) * * ComputeArcBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of an arc. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of an arc. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -ComputeArcBbox(canvas, arcPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - ArcItem *arcPtr; /* Item whose bbox is to be - * recomputed. */ +ComputeArcBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + ArcItem *arcPtr) /* Item whose bbox is to be recomputed. */ { double tmp, center[2], point[2]; double width; Tk_State state = arcPtr->header.state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -700,14 +677,14 @@ ComputeArcBbox(canvas, arcPtr) */ if (arcPtr->bbox[1] > arcPtr->bbox[3]) { - double tmp; - tmp = arcPtr->bbox[3]; + double tmp = arcPtr->bbox[3]; + arcPtr->bbox[3] = arcPtr->bbox[1]; arcPtr->bbox[1] = tmp; } if (arcPtr->bbox[0] > arcPtr->bbox[2]) { - double tmp; - tmp = arcPtr->bbox[2]; + double tmp = arcPtr->bbox[2]; + arcPtr->bbox[2] = arcPtr->bbox[0]; arcPtr->bbox[0] = tmp; } @@ -715,10 +692,10 @@ ComputeArcBbox(canvas, arcPtr) ComputeArcOutline(canvas,arcPtr); /* - * To compute the bounding box, start with the the bbox formed - * by the two endpoints of the arc. Then add in the center of - * the arc's oval (if relevant) and the 3-o'clock, 6-o'clock, - * 9-o'clock, and 12-o'clock positions, if they are relevant. + * To compute the bounding box, start with the the bbox formed by the two + * endpoints of the arc. Then add in the center of the arc's oval (if + * relevant) and the 3-o'clock, 6-o'clock, 9-o'clock, and 12-o'clock + * positions, if they are relevant. */ arcPtr->header.x1 = arcPtr->header.x2 = (int) arcPtr->center1[0]; @@ -768,8 +745,8 @@ ComputeArcBbox(canvas, arcPtr) } /* - * Lastly, expand by the width of the arc (if the arc's outline is - * being drawn) and add one extra pixel just for safety. + * Lastly, expand by the width of the arc (if the arc's outline is being + * drawn) and add one extra pixel just for safety. */ if (arcPtr->outline.gc == None) { @@ -788,28 +765,26 @@ ComputeArcBbox(canvas, arcPtr) * * DisplayArc -- * - * This procedure is invoked to draw an arc item in a given - * drawable. + * This function is invoked to draw an arc item in a given drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int x, y, width, height; /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayArc( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, /* Describes region of canvas that must be */ + int width, int height) /* redisplayed (not used). */ { ArcItem *arcPtr = (ArcItem *) itemPtr; short x1, y1, x2, y2; @@ -818,7 +793,7 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) Tk_State state = itemPtr->state; Pixmap stipple; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } lineWidth = arcPtr->outline.width; @@ -837,7 +812,7 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) if (arcPtr->activeFillStipple != None) { stipple = arcPtr->activeFillStipple; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (arcPtr->outline.disabledWidth > 0) { lineWidth = arcPtr->outline.disabledWidth; } @@ -850,8 +825,8 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) } /* - * Compute the screen coordinates of the bounding box for the item, - * plus integer values for the angles. + * Compute the screen coordinates of the bounding box for the item, plus + * integer values for the angles. */ Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[0], arcPtr->bbox[1], @@ -868,16 +843,18 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) extent = (int) ((64*arcPtr->extent) + 0.5); /* - * Display filled arc first (if wanted), then outline. If the extent - * is zero then don't invoke XFillArc or XDrawArc, since this causes - * some window servers to crash and should be a no-op anyway. + * Display filled arc first (if wanted), then outline. If the extent is + * zero then don't invoke XFillArc or XDrawArc, since this causes some + * window servers to crash and should be a no-op anyway. */ if ((arcPtr->fillGC != None) && (extent != 0)) { if (stipple != None) { - int w=0; int h=0; + int w = 0; + int h = 0; Tk_TSOffset *tsoffset = &arcPtr->tsoffset; int flags = tsoffset->flags; + if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) { Tk_SizeOfBitmap(display, stipple, &w, &h); if (flags & TK_OFFSET_CENTER) { @@ -914,10 +891,10 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) } /* - * If the outline width is very thin, don't use polygons to draw - * the linear parts of the outline (this often results in nothing - * being displayed); just draw lines instead. The same is done if - * the outline is dashed, because then polygons don't work. + * If the outline width is very thin, don't use polygons to draw the + * linear parts of the outline (this often results in nothing being + * displayed); just draw lines instead. The same is done if the + * outline is dashed, because then polygons don't work. */ if (lineWidth < 1.5 || dashnumber != 0) { @@ -948,8 +925,8 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) TkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS, display, drawable, arcPtr->outline.gc, None); TkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, - PIE_OUTLINE2_PTS, display, drawable, arcPtr->outline.gc, - None); + PIE_OUTLINE2_PTS, display, drawable, + arcPtr->outline.gc, None); } } @@ -962,17 +939,16 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) * * ArcToPoint -- * - * Computes the distance from a given point to a given - * arc, in canvas units. + * Computes the distance from a given point to a given arc, in canvas + * units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are coordPtr[0] and coordPtr[1] is inside the arc. If the - * point isn't inside the arc then the return value is the - * distance from the point to the arc. If itemPtr is filled, - * then anywhere in the interior is considered "inside"; if - * itemPtr isn't filled, then "inside" means only the area - * occupied by the outline. + * The return value is 0 if the point whose x and y coordinates are + * coordPtr[0] and coordPtr[1] is inside the arc. If the point isn't + * inside the arc then the return value is the distance from the point to + * the arc. If itemPtr is filled, then anywhere in the interior is + * considered "inside"; if itemPtr isn't filled, then "inside" means only + * the area occupied by the outline. * * Side effects: * None. @@ -982,10 +958,10 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height) /* ARGSUSED */ static double -ArcToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +ArcToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; double vertex[2], pointAngle, diff, dist, newDist; @@ -993,7 +969,7 @@ ArcToPoint(canvas, itemPtr, pointPtr) int filled, angleInRange; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -1009,10 +985,9 @@ ArcToPoint(canvas, itemPtr, pointPtr) } /* - * See if the point is within the angular range of the arc. - * Remember, X angles are backwards from the way we'd normally - * think of them. Also, compensate for any eccentricity of - * the oval. + * See if the point is within the angular range of the arc. Remember, X + * angles are backwards from the way we'd normally think of them. Also, + * compensate for any eccentricity of the oval. */ vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0; @@ -1039,14 +1014,13 @@ ArcToPoint(canvas, itemPtr, pointPtr) ((arcPtr->extent < 0) && ((diff - 360.0) >= arcPtr->extent)); /* - * Now perform different tests depending on what kind of arc - * we're dealing with. + * Now perform different tests depending on what kind of arc we're dealing + * with. */ if (arcPtr->style == ARC_STYLE) { if (angleInRange) { - return TkOvalToPoint(arcPtr->bbox, width, - 0, pointPtr); + return TkOvalToPoint(arcPtr->bbox, width, 0, pointPtr); } dist = hypot(pointPtr[0] - arcPtr->center1[0], pointPtr[1] - arcPtr->center1[1]); @@ -1072,7 +1046,7 @@ ArcToPoint(canvas, itemPtr, pointPtr) dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS, pointPtr); newDist = TkPolygonToPoint(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, - PIE_OUTLINE2_PTS, pointPtr); + PIE_OUTLINE2_PTS, pointPtr); } else { dist = TkLineToPoint(vertex, arcPtr->center1, pointPtr); newDist = TkLineToPoint(vertex, arcPtr->center2, pointPtr); @@ -1090,17 +1064,16 @@ ArcToPoint(canvas, itemPtr, pointPtr) } /* - * This is a chord-style arc. We have to deal specially with the - * triangular piece that represents the difference between a - * chord-style arc and a pie-slice arc (for small angles this piece - * is excluded here where it would be included for pie slices; - * for large angles the piece is included here but would be - * excluded for pie slices). + * This is a chord-style arc. We have to deal specially with the + * triangular piece that represents the difference between a chord-style + * arc and a pie-slice arc (for small angles this piece is excluded here + * where it would be included for pie slices; for large angles the piece + * is included here but would be excluded for pie slices). */ if (width > 1.0) { dist = TkPolygonToPoint(arcPtr->outlinePtr, CHORD_OUTLINE_PTS, - pointPtr); + pointPtr); } else { dist = TkLineToPoint(arcPtr->center1, arcPtr->center2, pointPtr); } @@ -1134,14 +1107,13 @@ ArcToPoint(canvas, itemPtr, pointPtr) * * ArcToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given area. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given area. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -1151,26 +1123,25 @@ ArcToPoint(canvas, itemPtr, pointPtr) /* ARGSUSED */ static int -ArcToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against arc. */ - double *rectPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +ArcToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against arc. */ + double *rectPtr) /* Pointer to array of four coordinates (x1, + * y1, x2, y2) describing rectangular area. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; - double rx, ry; /* Radii for transformed oval: these define - * an oval centered at the origin. */ - double tRect[4]; /* Transformed version of x1, y1, x2, y2, - * for coord. system where arc is centered - * on the origin. */ + double rx, ry; /* Radii for transformed oval: these define an + * oval centered at the origin. */ + double tRect[4]; /* Transformed version of x1, y1, x2, y2, for + * coord. system where arc is centered on the + * origin. */ double center[2], width, angle, tmp; double points[20], *pointPtr; int numPoints, filled; int inside; /* Non-zero means every test so far suggests - * that arc is inside rectangle. 0 means - * every test so far shows arc to be outside - * of rectangle. */ + * that arc is inside rectangle. 0 means every + * test so far shows arc to be outside of + * rectangle. */ int newInside; Tk_State state = itemPtr->state; @@ -1182,7 +1153,7 @@ ArcToArea(canvas, itemPtr, rectPtr) if (arcPtr->outline.activeWidth>width) { width = (double) arcPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (arcPtr->outline.disabledWidth>0) { width = (double) arcPtr->outline.disabledWidth; } @@ -1198,8 +1169,8 @@ ArcToArea(canvas, itemPtr, rectPtr) } /* - * Transform both the arc and the rectangle so that the arc's oval - * is centered on the origin. + * Transform both the arc and the rectangle so that the arc's oval is + * centered on the origin. */ center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0; @@ -1212,17 +1183,16 @@ ArcToArea(canvas, itemPtr, rectPtr) ry = arcPtr->bbox[3] - center[1] + width/2.0; /* - * Find the extreme points of the arc and see whether these are all - * inside the rectangle (in which case we're done), partly in and - * partly out (in which case we're done), or all outside (in which - * case we have more work to do). The extreme points include the - * following, which are checked in order: + * Find the extreme points of the arc and see whether these are all inside + * the rectangle (in which case we're done), partly in and partly out (in + * which case we're done), or all outside (in which case we have more work + * to do). The extreme points include the following, which are checked in + * order: * - * 1. The outside points of the arc, corresponding to start and - * extent. + * 1. The outside points of the arc, corresponding to start and extent. * 2. The center of the arc (but only in pie-slice mode). - * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc - * includes those angles). + * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc includes + * those angles). */ pointPtr = points; @@ -1283,8 +1253,8 @@ ArcToArea(canvas, itemPtr, rectPtr) } /* - * Now that we've located the extreme points, loop through them all - * to see which are inside the rectangle. + * Now that we've located the extreme points, loop through them all to see + * which are inside the rectangle. */ inside = (points[0] > tRect[0]) && (points[0] < tRect[2]) @@ -1302,17 +1272,17 @@ ArcToArea(canvas, itemPtr, rectPtr) } /* - * So far, oval appears to be outside rectangle, but can't yet tell - * for sure. Next, test each of the four sides of the rectangle - * against the bounding region for the arc. If any intersections - * are found, then return "overlapping". First, test against the - * polygon(s) forming the sides of a chord or pie-slice. + * So far, oval appears to be outside rectangle, but can't yet tell for + * sure. Next, test each of the four sides of the rectangle against the + * bounding region for the arc. If any intersections are found, then + * return "overlapping". First, test against the polygon(s) forming the + * sides of a chord or pie-slice. */ if (arcPtr->style == PIESLICE_STYLE) { if (width >= 1.0) { if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS, - rectPtr) != -1) { + rectPtr) != -1) { return 0; } if (TkPolygonToArea(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, @@ -1340,9 +1310,9 @@ ArcToArea(canvas, itemPtr, rectPtr) } /* - * Next check for overlap between each of the four sides and the - * outer perimiter of the arc. If the arc isn't filled, then also - * check the inner perimeter of the arc. + * Next check for overlap between each of the four sides and the outer + * perimiter of the arc. If the arc isn't filled, then also check the + * inner perimeter of the arc. */ if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start, @@ -1371,11 +1341,11 @@ ArcToArea(canvas, itemPtr, rectPtr) } /* - * The arc still appears to be totally disjoint from the rectangle, - * but it's also possible that the rectangle is totally inside the arc. - * Do one last check, which is to check one point of the rectangle - * to see if it's inside the arc. If it is, we've got overlap. If - * it isn't, the arc's really outside the rectangle. + * The arc still appears to be totally disjoint from the rectangle, but + * it's also possible that the rectangle is totally inside the arc. Do one + * last check, which is to check one point of the rectangle to see if it's + * inside the arc. If it is, we've got overlap. If it isn't, the arc's + * really outside the rectangle. */ if (ArcToPoint(canvas, itemPtr, rectPtr) == 0.0) { @@ -1389,15 +1359,14 @@ ArcToArea(canvas, itemPtr, rectPtr) * * ScaleArc -- * - * This procedure is invoked to rescale an arc item. + * This function is invoked to rescale an arc item. * * Results: * None. * * Side effects: - * The arc referred to by itemPtr is rescaled so that the - * following transformation is applied to all point - * coordinates: + * The arc referred to by itemPtr is rescaled so that the following + * transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -1405,12 +1374,13 @@ ArcToArea(canvas, itemPtr, rectPtr) */ static void -ScaleArc(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing arc. */ - Tk_Item *itemPtr; /* Arc to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleArc( + Tk_Canvas canvas, /* Canvas containing arc. */ + Tk_Item *itemPtr, /* Arc to be scaled. */ + double originX, /* Origin about which to scale rect. */ + double originY, + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; @@ -1426,25 +1396,24 @@ ScaleArc(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateArc -- * - * This procedure is called to move an arc by a given amount. + * This function is called to move an arc by a given amount. * * Results: * None. * * Side effects: - * The position of the arc is offset by (xDelta, yDelta), and - * the bounding box is updated in the generic part of the item - * structure. + * The position of the arc is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslateArc(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslateArc( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, /* Amount by which item is to be moved. */ + double deltaY) { ArcItem *arcPtr = (ArcItem *) itemPtr; @@ -1460,26 +1429,25 @@ TranslateArc(canvas, itemPtr, deltaX, deltaY) * * ComputeArcOutline -- * - * This procedure creates a polygon describing everything in - * the outline for an arc except what's in the curved part. - * For a "pie slice" arc this is a V-shaped chunk, and for - * a "chord" arc this is a linear chunk (with cutaway corners). - * For "arc" arcs, this stuff isn't relevant. + * This function creates a polygon describing everything in the outline + * for an arc except what's in the curved part. For a "pie slice" arc + * this is a V-shaped chunk, and for a "chord" arc this is a linear chunk + * (with cutaway corners). For "arc" arcs, this stuff isn't relevant. * * Results: * None. * * Side effects: - * The information at arcPtr->outlinePtr gets modified, and - * storage for arcPtr->outlinePtr may be allocated or freed. + * The information at arcPtr->outlinePtr gets modified, and storage for + * arcPtr->outlinePtr may be allocated or freed. * *-------------------------------------------------------------- */ static void -ComputeArcOutline(canvas,arcPtr) - Tk_Canvas canvas; /* Information about overall canvas. */ - ArcItem *arcPtr; /* Information about arc. */ +ComputeArcOutline( + Tk_Canvas canvas, /* Information about overall canvas. */ + ArcItem *arcPtr) /* Information about arc. */ { double sin1, cos1, sin2, cos2, angle, width, halfWidth; double boxWidth, boxHeight; @@ -1487,10 +1455,9 @@ ComputeArcOutline(canvas,arcPtr) double *outlinePtr; Tk_State state = arcPtr->header.state; - /* - * Make sure that the outlinePtr array is large enough to hold - * either a chord or pie-slice outline. + * Make sure that the outlinePtr array is large enough to hold either a + * chord or pie-slice outline. */ if (arcPtr->numOutlinePoints == 0) { @@ -1500,14 +1467,13 @@ ComputeArcOutline(canvas,arcPtr) } outlinePtr = arcPtr->outlinePtr; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } /* - * First compute the two points that lie at the centers of - * the ends of the curved arc segment, which are marked with - * X's in the figure below: + * First compute the two points that lie at the centers of the ends of the + * curved arc segment, which are marked with X's in the figure below: * * * * * * @@ -1517,13 +1483,13 @@ ComputeArcOutline(canvas,arcPtr) * * * * * * X * * X * - * The code is tricky because the arc can be ovular in shape. - * It computes the position for a unit circle, and then - * scales to fit the shape of the arc's bounding box. + * The code is tricky because the arc can be ovular in shape. It computes + * the position for a unit circle, and then scales to fit the shape of the + * arc's bounding box. * - * Also, watch out because angles go counter-clockwise like you - * might expect, but the y-coordinate system is inverted. To - * handle this, just negate the angles in all the computations. + * Also, watch out because angles go counter-clockwise like you might + * expect, but the y-coordinate system is inverted. To handle this, just + * negate the angles in all the computations. */ boxWidth = arcPtr->bbox[2] - arcPtr->bbox[0]; @@ -1542,8 +1508,8 @@ ComputeArcOutline(canvas,arcPtr) arcPtr->center2[1] = vertex[1] + sin2*boxHeight/2.0; /* - * Next compute the "outermost corners" of the arc, which are - * marked with X's in the figure below: + * Next compute the "outermost corners" of the arc, which are marked with + * X's in the figure below: * * * * * * * * @@ -1552,12 +1518,11 @@ ComputeArcOutline(canvas,arcPtr) * X * * X * * * * - * The code below is tricky because it has to handle eccentricity - * in the shape of the oval. The key in the code below is to - * realize that the slope of the line from arcPtr->center1 to corner1 - * is (boxWidth*sin1)/(boxHeight*cos1), and similarly for arcPtr->center2 - * and corner2. These formulas can be computed from the formula for - * the oval. + * The code below is tricky because it has to handle eccentricity in the + * shape of the oval. The key in the code below is to realize that the + * slope of the line from arcPtr->center1 to corner1 is (boxWidth*sin1) + * divided by (boxHeight*cos1), and similarly for arcPtr->center2 and + * corner2. These formulas can be computed from the formula for the oval. */ width = arcPtr->outline.width; @@ -1565,7 +1530,7 @@ ComputeArcOutline(canvas,arcPtr) if (arcPtr->outline.activeWidth>arcPtr->outline.width) { width = arcPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (arcPtr->outline.disabledWidth>arcPtr->outline.width) { width = arcPtr->outline.disabledWidth; } @@ -1588,10 +1553,10 @@ ComputeArcOutline(canvas,arcPtr) corner2[1] = arcPtr->center2[1] + sin(angle)*halfWidth; /* - * For a chord outline, generate a six-sided polygon with three - * points for each end of the chord. The first and third points - * for each end are butt points generated on either side of the - * center point. The second point is the corner point. + * For a chord outline, generate a six-sided polygon with three points for + * each end of the chord. The first and third points for each end are butt + * points generated on either side of the center point. The second point + * is the corner point. */ if (arcPtr->style == CHORD_STYLE) { @@ -1611,10 +1576,9 @@ ComputeArcOutline(canvas,arcPtr) - arcPtr->center1[1]; } else if (arcPtr->style == PIESLICE_STYLE) { /* - * For pie slices, generate two polygons, one for each side - * of the pie slice. The first arm has a shape like this, - * where the center of the oval is X, arcPtr->center1 is at Y, and - * corner1 is at Z: + * For pie slices, generate two polygons, one for each side of the pie + * slice. The first arm has a shape like this, where the center of the + * oval is X, arcPtr->center1 is at Y, and corner1 is at Z: * * _____________________ * | \ @@ -1622,7 +1586,6 @@ ComputeArcOutline(canvas,arcPtr) * X Y Z * | / * |_____________________/ - * */ TkGetButtPoints(arcPtr->center1, vertex, width, 0, @@ -1639,7 +1602,6 @@ ComputeArcOutline(canvas,arcPtr) /* * The second arm has a shape like this: * - * * ______________________ * / \ * / \ @@ -1648,10 +1610,10 @@ ComputeArcOutline(canvas,arcPtr) * \______________________/ * * Similar to above X is the center of the oval/circle, Y is - * arcPtr->center2, and Z is corner2. The extra jog out to the left - * of X is needed in or to produce a butted joint with the - * first arm; the corner to the right of X is one of the - * first two points of the first arm, depending on extent. + * arcPtr->center2, and Z is corner2. The extra jog out to the left of + * X is needed in or to produce a butted joint with the first arm; the + * corner to the right of X is one of the first two points of the + * first arm, depending on extent. */ TkGetButtPoints(arcPtr->center2, vertex, width, 0, @@ -1680,15 +1642,13 @@ ComputeArcOutline(canvas,arcPtr) * * HorizLineToArc -- * - * Determines whether a horizontal line segment intersects - * a given arc. + * Determines whether a horizontal line segment intersects a given arc. * * Results: - * The return value is 1 if the given line intersects the - * infinitely-thin arc section defined by rx, ry, start, - * and extent, and 0 otherwise. Only the perimeter of the - * arc is checked: interior areas (e.g. pie-slice or chord) - * are not checked. + * The return value is 1 if the given line intersects the infinitely-thin + * arc section defined by rx, ry, start, and extent, and 0 otherwise. + * Only the perimeter of the arc is checked: interior areas (e.g. chord + * or pie-slice) are not checked. * * Side effects: * None. @@ -1697,25 +1657,24 @@ ComputeArcOutline(canvas,arcPtr) */ static int -HorizLineToArc(x1, x2, y, rx, ry, start, extent) - double x1, x2; /* X-coords of endpoints of line segment. - * X1 must be <= x2. */ - double y; /* Y-coordinate of line segment. */ - double rx, ry; /* These x- and y-radii define an oval +HorizLineToArc( + double x1, double x2, /* X-coords of endpoints of line segment. X1 + * must be <= x2. */ + double y, /* Y-coordinate of line segment. */ + double rx, double ry, /* These x- and y-radii define an oval * centered at the origin. */ - double start, extent; /* Angles that define extent of arc, in - * the standard fashion for this module. */ + double start, double extent)/* Angles that define extent of arc, in the + * standard fashion for this module. */ { - double tmp; + double tmp, x; double tx, ty; /* Coordinates of intersection point in * transformed coordinate system. */ - double x; /* - * Compute the x-coordinate of one possible intersection point - * between the arc and the line. Use a transformed coordinate - * system where the oval is a unit circle centered at the origin. - * Then scale back to get actual x-coordinate. + * Compute the x-coordinate of one possible intersection point between the + * arc and the line. Use a transformed coordinate system where the oval is + * a unit circle centered at the origin. Then scale back to get actual + * x-coordinate. */ ty = y/ry; @@ -1744,15 +1703,13 @@ HorizLineToArc(x1, x2, y, rx, ry, start, extent) * * VertLineToArc -- * - * Determines whether a vertical line segment intersects - * a given arc. + * Determines whether a vertical line segment intersects a given arc. * * Results: - * The return value is 1 if the given line intersects the - * infinitely-thin arc section defined by rx, ry, start, - * and extent, and 0 otherwise. Only the perimeter of the - * arc is checked: interior areas (e.g. pie-slice or chord) - * are not checked. + * The return value is 1 if the given line intersects the infinitely-thin + * arc section defined by rx, ry, start, and extent, and 0 otherwise. + * Only the perimeter of the arc is checked: interior areas (e.g. chord + * or pie-slice) are not checked. * * Side effects: * None. @@ -1761,25 +1718,24 @@ HorizLineToArc(x1, x2, y, rx, ry, start, extent) */ static int -VertLineToArc(x, y1, y2, rx, ry, start, extent) - double x; /* X-coordinate of line segment. */ - double y1, y2; /* Y-coords of endpoints of line segment. - * Y1 must be <= y2. */ - double rx, ry; /* These x- and y-radii define an oval +VertLineToArc( + double x, /* X-coordinate of line segment. */ + double y1, double y2, /* Y-coords of endpoints of line segment. Y1 + * must be <= y2. */ + double rx, double ry, /* These x- and y-radii define an oval * centered at the origin. */ - double start, extent; /* Angles that define extent of arc, in - * the standard fashion for this module. */ + double start, double extent)/* Angles that define extent of arc, in the + * standard fashion for this module. */ { - double tmp; + double tmp, y; double tx, ty; /* Coordinates of intersection point in * transformed coordinate system. */ - double y; /* - * Compute the y-coordinate of one possible intersection point - * between the arc and the line. Use a transformed coordinate - * system where the oval is a unit circle centered at the origin. - * Then scale back to get actual y-coordinate. + * Compute the y-coordinate of one possible intersection point between the + * arc and the line. Use a transformed coordinate system where the oval is + * a unit circle centered at the origin. Then scale back to get actual + * y-coordinate. */ tx = x/rx; @@ -1808,15 +1764,14 @@ VertLineToArc(x, y1, y2, rx, ry, start, extent) * * AngleInRange -- * - * Determine whether the angle from the origin to a given - * point is within a given range. + * Determine whether the angle from the origin to a given point is within + * a given range. * * Results: - * The return value is 1 if the angle from (0,0) to (x,y) - * is in the range given by start and extent, where angles - * are interpreted in the standard way for ovals (meaning - * backwards from normal interpretation). Otherwise the - * return value is 0. + * The return value is 1 if the angle from (0,0) to (x,y) is in the range + * given by start and extent, where angles are interpreted in the + * standard way for ovals (meaning backwards from normal interpretation). + * Otherwise the return value is 0. * * Side effects: * None. @@ -1825,11 +1780,11 @@ VertLineToArc(x, y1, y2, rx, ry, start, extent) */ static int -AngleInRange(x, y, start, extent) - double x, y; /* Coordinate of point; angle measured - * from origin to here, relative to x-axis. */ - double start; /* First angle, degrees, >=0, <=360. */ - double extent; /* Size of arc in degrees >=-360, <=360. */ +AngleInRange( + double x, double y, /* Coordinate of point; angle measured from + * origin to here, relative to x-axis. */ + double start, /* First angle, degrees, >=0, <=360. */ + double extent) /* Size of arc in degrees >=-360, <=360. */ { double diff; @@ -1855,15 +1810,13 @@ AngleInRange(x, y, start, extent) * * ArcToPostscript -- * - * This procedure is called to generate Postscript for - * arc items. + * This function is called to generate Postscript for arc items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used - * to be there. If no error occurs, then Postscript for the - * item is appended to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -1872,15 +1825,13 @@ AngleInRange(x, y, start, extent) */ static int -ArcToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created. */ +ArcToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { ArcItem *arcPtr = (ArcItem *) itemPtr; char buffer[400]; @@ -1900,7 +1851,7 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) ang2 = arcPtr->start; } - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } color = arcPtr->outline.color; @@ -1920,7 +1871,7 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) if (arcPtr->activeFillStipple!=None) { fillStipple = arcPtr->activeFillStipple; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (arcPtr->outline.disabledColor!=NULL) { color = arcPtr->outline.disabledColor; } @@ -1936,15 +1887,15 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) } /* - * If the arc is filled, output Postscript for the interior region - * of the arc. + * If the arc is filled, output Postscript for the interior region of the + * arc. */ if (arcPtr->fillGC != None) { sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n", (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2, (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); if (arcPtr->style == CHORD_STYLE) { sprintf(buffer, "0 0 1 %.15g %.15g arc closepath\nsetmatrix\n", ang1, ang2); @@ -1953,21 +1904,20 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) "0 0 moveto 0 0 1 %.15g %.15g arc closepath\nsetmatrix\n", ang1, ang2); } - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) { return TCL_ERROR; - }; + } if (fillStipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); - if (Tk_CanvasPsStipple(interp, canvas, fillStipple) - != TCL_OK) { + Tcl_AppendResult(interp, "clip ", NULL); + if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) { return TCL_ERROR; } if (arcPtr->outline.gc != None) { - Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } } @@ -1979,16 +1929,15 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n", (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2, (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); sprintf(buffer, "0 0 1 %.15g %.15g", ang1, ang2); Tcl_AppendResult(interp, buffer, - " arc\nsetmatrix\n0 setlinecap\n", (char *) NULL); - if (Tk_CanvasPsOutline(canvas, itemPtr, - &(arcPtr->outline)) != TCL_OK) { + " arc\nsetmatrix\n0 setlinecap\n", NULL); + if (Tk_CanvasPsOutline(canvas, itemPtr, &(arcPtr->outline)) != TCL_OK){ return TCL_ERROR; } if (arcPtr->style != ARC_STYLE) { - Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); if (arcPtr->style == CHORD_STYLE) { Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS); @@ -2000,15 +1949,14 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) return TCL_ERROR; } if (stipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); - if (Tk_CanvasPsStipple(interp, canvas, - stipple) != TCL_OK) { + Tcl_AppendResult(interp, "clip ", NULL); + if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK){ return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } - Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, PIE_OUTLINE2_PTS); @@ -2018,13 +1966,12 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) return TCL_ERROR; } if (stipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); - if (Tk_CanvasPsStipple(interp, canvas, - stipple) != TCL_OK) { + Tcl_AppendResult(interp, "clip ", NULL); + if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } } } @@ -2037,34 +1984,34 @@ ArcToPostscript(interp, canvas, itemPtr, prepass) * * StyleParseProc -- * - * This procedure is invoked during option processing to handle - * the "-style" option. + * This function is invoked during option processing to handle the + * "-style" option. * * Results: * A standard Tcl return value. * * Side effects: - * The state for a given item gets replaced by the state - * indicated in the value argument. + * The state for a given item gets replaced by the state indicated in the + * value argument. * *-------------------------------------------------------------- */ static int -StyleParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* some flags.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ +StyleParseProc( + ClientData clientData, /* some flags.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + CONST char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item. */ { int c; size_t length; register Style *stylePtr = (Style *) (widgRec + offset); - if(value == NULL || *value == 0) { + if (value == NULL || *value == 0) { *stylePtr = PIESLICE_STYLE; return TCL_OK; } @@ -2085,9 +2032,8 @@ StyleParseProc(clientData, interp, tkwin, value, widgRec, offset) return TCL_OK; } - Tcl_AppendResult(interp, "bad -style option \"", - value, "\": must be arc, chord, or pieslice", - (char *) NULL); + Tcl_AppendResult(interp, "bad -style option \"", value, + "\": must be arc, chord, or pieslice", NULL); *stylePtr = PIESLICE_STYLE; return TCL_ERROR; } @@ -2097,16 +2043,15 @@ StyleParseProc(clientData, interp, tkwin, value, widgRec, offset) * * StylePrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-style" - * configuration option. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-style" configuration option. * * Results: - * The return value is a string describing the state for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). + * The return value is a string describing the state for the item + * referred to by "widgRec". In addition, *freeProcPtr is filled in with + * the address of a function to call to free the result string when it's + * no longer needed (or NULL to indicate that the string doesn't need to + * be freed). * * Side effects: * None. @@ -2115,22 +2060,30 @@ StyleParseProc(clientData, interp, tkwin, value, widgRec, offset) */ static char * -StylePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Ignored. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +StylePrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Ignored. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Offset into item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { register Style *stylePtr = (Style *) (widgRec + offset); - if (*stylePtr==ARC_STYLE) { + if (*stylePtr == ARC_STYLE) { return "arc"; - } else if (*stylePtr==CHORD_STYLE) { + } else if (*stylePtr == CHORD_STYLE) { return "chord"; } else { return "pieslice"; } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvBmap.c b/generic/tkCanvBmap.c index f308c52..30aa429 100644 --- a/generic/tkCanvBmap.c +++ b/generic/tkCanvBmap.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvBmap.c -- * * This file implements bitmap items for canvas widgets. @@ -6,13 +6,12 @@ * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" /* @@ -21,11 +20,10 @@ typedef struct BitmapItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ double x, y; /* Coordinates of positioning point for * bitmap. */ - Tk_Anchor anchor; /* Where to anchor bitmap relative to - * (x,y). */ + Tk_Anchor anchor; /* Where to anchor bitmap relative to (x,y) */ Pixmap bitmap; /* Bitmap to display in window. */ Pixmap activeBitmap; /* Bitmap to display in window. */ Pixmap disabledBitmap; /* Bitmap to display in window. */ @@ -35,8 +33,8 @@ typedef struct BitmapItem { XColor *bgColor; /* Background color to use for bitmap. */ XColor *activeBgColor; /* Background color to use for bitmap. */ XColor *disabledBgColor; /* Background color to use for bitmap. */ - GC gc; /* Graphics context to use for drawing - * bitmap on screen. */ + GC gc; /* Graphics context to use for drawing bitmap + * on screen. */ } BitmapItem; /* @@ -53,96 +51,95 @@ static Tk_CustomOption tagsOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_COLOR, "-activebackground", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activebitmap", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-activebackground", NULL, NULL, + NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activebitmap", NULL, NULL, + NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-activeforeground", NULL, NULL, + NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_COLOR, "-background", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-disabledbackground", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, disabledBgColor), + {TK_CONFIG_COLOR, "-background", NULL, NULL, + NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-bitmap", NULL, NULL, + NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-disabledbackground", NULL, NULL, + NULL, Tk_Offset(BitmapItem, disabledBgColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledbitmap", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, disabledBitmap), + {TK_CONFIG_BITMAP, "-disabledbitmap", NULL, NULL, + NULL, Tk_Offset(BitmapItem, disabledBitmap), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-disabledforeground", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapItem, disabledFgColor), + {TK_CONFIG_COLOR, "-disabledforeground", NULL, NULL, + NULL, Tk_Offset(BitmapItem, disabledFgColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-foreground", NULL, NULL, "black", Tk_Offset(BitmapItem, fgColor), 0}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static int BitmapCoords _ANSI_ARGS_((Tcl_Interp *interp, +static int BitmapCoords(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[])); -static int BitmapToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static double BitmapToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *coordPtr)); -static int BitmapToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static void ComputeBitmapBbox _ANSI_ARGS_((Tk_Canvas canvas, - BitmapItem *bmapPtr)); -static int ConfigureBitmap _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[]); +static int BitmapToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static double BitmapToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *coordPtr); +static int BitmapToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void ComputeBitmapBbox(Tk_Canvas canvas, + BitmapItem *bmapPtr); +static int ConfigureBitmap(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static int TkcCreateBitmap _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[], int flags); +static int TkcCreateBitmap(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeleteBitmap _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayBitmap _ANSI_ARGS_((Tk_Canvas canvas, + int objc, Tcl_Obj *CONST objv[]); +static void DeleteBitmap(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static void ScaleBitmap _ANSI_ARGS_((Tk_Canvas canvas, + int x, int y, int width, int height); +static void ScaleBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslateBitmap _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); + double scaleX, double scaleY); +static void TranslateBitmap(Tk_Canvas canvas, Tk_Item *itemPtr, + double deltaX, double deltaY); /* - * The structures below defines the bitmap item type in terms of - * procedures that can be invoked by generic item code. + * The structures below defines the bitmap item type in terms of functions + * that can be invoked by generic item code. */ Tk_ItemType tkBitmapType = { - "bitmap", /* name */ - sizeof(BitmapItem), /* itemSize */ - TkcCreateBitmap, /* createProc */ - configSpecs, /* configSpecs */ - ConfigureBitmap, /* configureProc */ - BitmapCoords, /* coordProc */ - DeleteBitmap, /* deleteProc */ - DisplayBitmap, /* displayProc */ - TK_CONFIG_OBJS, /* flags */ - BitmapToPoint, /* pointProc */ - BitmapToArea, /* areaProc */ - BitmapToPostscript, /* postscriptProc */ - ScaleBitmap, /* scaleProc */ - TranslateBitmap, /* translateProc */ - (Tk_ItemIndexProc *) NULL, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* icursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ - (Tk_ItemInsertProc *) NULL, /* insertProc */ - (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + "bitmap", /* name */ + sizeof(BitmapItem), /* itemSize */ + TkcCreateBitmap, /* createProc */ + configSpecs, /* configSpecs */ + ConfigureBitmap, /* configureProc */ + BitmapCoords, /* coordProc */ + DeleteBitmap, /* deleteProc */ + DisplayBitmap, /* displayProc */ + TK_CONFIG_OBJS, /* flags */ + BitmapToPoint, /* pointProc */ + BitmapToArea, /* areaProc */ + BitmapToPostscript, /* postscriptProc */ + ScaleBitmap, /* scaleProc */ + TranslateBitmap, /* translateProc */ + NULL, /* indexProc */ + NULL, /* icursorProc */ + NULL, /* selectionProc */ + NULL, /* insertProc */ + NULL, /* dTextProc */ + NULL, /* nextPtr */ }; /* @@ -150,14 +147,13 @@ Tk_ItemType tkBitmapType = { * * TkcCreateBitmap -- * - * This procedure is invoked to create a new bitmap - * item in a canvas. + * This function is invoked to create a new bitmap item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is left uninitialized, - * so it can be safely freed by the caller. + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the + * caller. * * Side effects: * A new bitmap item is created. @@ -166,13 +162,13 @@ Tk_ItemType tkBitmapType = { */ static int -TkcCreateBitmap(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing rectangle. */ +TkcCreateBitmap( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing rectangle. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; int i; @@ -198,8 +194,8 @@ TkcCreateBitmap(interp, canvas, itemPtr, objc, objv) bmapPtr->gc = None; /* - * Process the arguments to fill in the item record. - * Only 1 (list) or 2 (x y) coords are allowed. + * Process the arguments to fill in the item record. Only 1 (list) or 2 (x + * y) coords are allowed. */ if (objc == 1) { @@ -219,7 +215,7 @@ TkcCreateBitmap(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -229,9 +225,8 @@ TkcCreateBitmap(interp, canvas, itemPtr, objc, objv) * * BitmapCoords -- * - * This procedure is invoked to process the "coords" widget - * command on bitmap items. See the user documentation for - * details on what it does. + * This function is invoked to process the "coords" widget command on + * bitmap items. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -243,20 +238,19 @@ TkcCreateBitmap(interp, canvas, itemPtr, objc, objv) */ static int -BitmapCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +BitmapCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; if (objc == 0) { Tcl_Obj *obj = Tcl_NewObj(); + Tcl_Obj *subobj = Tcl_NewDoubleObj(bmapPtr->x); Tcl_ListObjAppendElement(interp, obj, subobj); subobj = Tcl_NewDoubleObj(bmapPtr->y); @@ -297,12 +291,12 @@ BitmapCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureBitmap -- * - * This procedure is invoked to configure various aspects - * of a bitmap item, such as its anchor position. + * This function is invoked to configure various aspects of a bitmap + * item, such as its anchor position. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: * Configuration information may be set for itemPtr. @@ -311,13 +305,13 @@ BitmapCoords(interp, canvas, itemPtr, objc, objv) */ static int -ConfigureBitmap(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Bitmap item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureBitmap( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Bitmap item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; XGCValues gcValues; @@ -336,8 +330,8 @@ ConfigureBitmap(interp, canvas, itemPtr, objc, objv, flags) } /* - * A few of the options require additional processing, such as those - * that determine the graphics context. + * A few of the options require additional processing, such as those that + * determine the graphics context. */ state = itemPtr->state; @@ -410,8 +404,8 @@ ConfigureBitmap(interp, canvas, itemPtr, objc, objv, flags) * * DeleteBitmap -- * - * This procedure is called to clean up the data structure - * associated with a bitmap item. + * This function is called to clean up the data structure associated with + * a bitmap item. * * Results: * None. @@ -423,11 +417,10 @@ ConfigureBitmap(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteBitmap(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall canvas widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeleteBitmap( + Tk_Canvas canvas, /* Info about overall canvas widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; @@ -468,27 +461,24 @@ DeleteBitmap(canvas, itemPtr, display) * * ComputeBitmapBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a bitmap item. - * This procedure is where the child bitmap's placement is - * computed. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a bitmap item. This function is where the + * child bitmap's placement is computed. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -ComputeBitmapBbox(canvas, bmapPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - BitmapItem *bmapPtr; /* Item whose bbox is to be - * recomputed. */ +ComputeBitmapBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + BitmapItem *bmapPtr) /* Item whose bbox is to be recomputed. */ { int width, height; int x, y; @@ -525,36 +515,36 @@ ComputeBitmapBbox(canvas, bmapPtr) Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &width, &height); switch (bmapPtr->anchor) { - case TK_ANCHOR_N: - x -= width/2; - break; - case TK_ANCHOR_NE: - x -= width; - break; - case TK_ANCHOR_E: - x -= width; - y -= height/2; - break; - case TK_ANCHOR_SE: - x -= width; - y -= height; - break; - case TK_ANCHOR_S: - x -= width/2; - y -= height; - break; - case TK_ANCHOR_SW: - y -= height; - break; - case TK_ANCHOR_W: - y -= height/2; - break; - case TK_ANCHOR_NW: - break; - case TK_ANCHOR_CENTER: - x -= width/2; - y -= height/2; - break; + case TK_ANCHOR_N: + x -= width/2; + break; + case TK_ANCHOR_NE: + x -= width; + break; + case TK_ANCHOR_E: + x -= width; + y -= height/2; + break; + case TK_ANCHOR_SE: + x -= width; + y -= height; + break; + case TK_ANCHOR_S: + x -= width/2; + y -= height; + break; + case TK_ANCHOR_SW: + y -= height; + break; + case TK_ANCHOR_W: + y -= height/2; + break; + case TK_ANCHOR_NW: + break; + case TK_ANCHOR_CENTER: + x -= width/2; + y -= height/2; + break; } /* @@ -572,28 +562,27 @@ ComputeBitmapBbox(canvas, bmapPtr) * * DisplayBitmap -- * - * This procedure is invoked to draw a bitmap item in a given - * drawable. + * This function is invoked to draw a bitmap item in a given drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int x, y, width, height; /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayBitmap( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, int width, int height) + /* Describes region of canvas that must be + * redisplayed (not used). */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; int bmapX, bmapY, bmapWidth, bmapHeight; @@ -602,9 +591,8 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height) Tk_State state = itemPtr->state; /* - * If the area being displayed doesn't cover the whole bitmap, - * then only redisplay the part of the bitmap that needs - * redisplay. + * If the area being displayed doesn't cover the whole bitmap, then only + * redisplay the part of the bitmap that needs redisplay. */ if (state == TK_STATE_NULL) { @@ -650,9 +638,9 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height) &drawableX, &drawableY); /* - * Must modify the mask origin within the graphics context - * to line up with the bitmap's origin (in order to make - * bitmaps with "-background {}" work right). + * Must modify the mask origin within the graphics context to line up + * with the bitmap's origin (in order to make bitmaps with + * "-background {}" work right). */ XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX, @@ -669,14 +657,14 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height) * * BitmapToPoint -- * - * Computes the distance from a given point to a given - * rectangle, in canvas units. + * Computes the distance from a given point to a given rectangle, in + * canvas units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are coordPtr[0] and coordPtr[1] is inside the bitmap. If the - * point isn't inside the bitmap then the return value is the - * distance from the point to the bitmap. + * The return value is 0 if the point whose x and y coordinates are + * coordPtr[0] and coordPtr[1] is inside the bitmap. If the point isn't + * inside the bitmap then the return value is the distance from the point + * to the bitmap. * * Side effects: * None. @@ -686,10 +674,10 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height) /* ARGSUSED */ static double -BitmapToPoint(canvas, itemPtr, coordPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *coordPtr; /* Pointer to x and y coordinates. */ +BitmapToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *coordPtr) /* Pointer to x and y coordinates. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; double x1, x2, y1, y2, xDiff, yDiff; @@ -727,14 +715,13 @@ BitmapToPoint(canvas, itemPtr, coordPtr) * * BitmapToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangle. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangle. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -744,12 +731,12 @@ BitmapToPoint(canvas, itemPtr, coordPtr) /* ARGSUSED */ static int -BitmapToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against rectangle. */ - double *rectPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +BitmapToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against rectangle. */ + double *rectPtr) /* Pointer to array of four coordinates + * (x1,y1,x2,y2) describing rectangular + * area. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; @@ -773,16 +760,16 @@ BitmapToArea(canvas, itemPtr, rectPtr) * * ScaleBitmap -- * - * This procedure is invoked to rescale a bitmap item in a - * canvas. It is one of the standard item procedures for - * bitmap items, and is invoked by the generic canvas code. + * This function is invoked to rescale a bitmap item in a canvas. It is + * one of the standard item functions for bitmap items, and is invoked by + * the generic canvas code. * * Results: * None. * * Side effects: - * The item referred to by itemPtr is rescaled so that the - * following transformation is applied to all point coordinates: + * The item referred to by itemPtr is rescaled so that the following + * transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -790,12 +777,13 @@ BitmapToArea(canvas, itemPtr, rectPtr) */ static void -ScaleBitmap(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing rectangle. */ - Tk_Item *itemPtr; /* Rectangle to be scaled. */ - double originX, originY; /* Origin about which to scale item. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleBitmap( + Tk_Canvas canvas, /* Canvas containing rectangle. */ + Tk_Item *itemPtr, /* Rectangle to be scaled. */ + double originX, double originY, + /* Origin about which to scale item. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; @@ -809,25 +797,24 @@ ScaleBitmap(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateBitmap -- * - * This procedure is called to move an item by a given amount. + * This function is called to move an item by a given amount. * * Results: * None. * * Side effects: - * The position of the item is offset by (xDelta, yDelta), and - * the bounding box is updated in the generic part of the item - * structure. + * The position of the item is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslateBitmap(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslateBitmap( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; @@ -841,15 +828,13 @@ TranslateBitmap(canvas, itemPtr, deltaX, deltaY) * * BitmapToPostscript -- * - * This procedure is called to generate Postscript for - * bitmap items. + * This function is called to generate Postscript for bitmap items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used to be there. - * If no error occurs, then Postscript for the item is appended - * to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -858,15 +843,13 @@ TranslateBitmap(canvas, itemPtr, deltaX, deltaY) */ static int -BitmapToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created. */ +BitmapToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; double x, y; @@ -911,8 +894,8 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass) } /* - * Compute the coordinates of the lower-left corner of the bitmap, - * taking into account the anchor position for the bitmp. + * Compute the coordinates of the lower-left corner of the bitmap, taking + * into account the anchor position for the bitmp. */ x = bmapPtr->x; @@ -920,15 +903,15 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass) Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &width, &height); switch (bmapPtr->anchor) { - case TK_ANCHOR_NW: y -= height; break; - case TK_ANCHOR_N: x -= width/2.0; y -= height; break; - case TK_ANCHOR_NE: x -= width; y -= height; break; - case TK_ANCHOR_E: x -= width; y -= height/2.0; break; - case TK_ANCHOR_SE: x -= width; break; - case TK_ANCHOR_S: x -= width/2.0; break; - case TK_ANCHOR_SW: break; - case TK_ANCHOR_W: y -= height/2.0; break; - case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; + case TK_ANCHOR_NW: y -= height; break; + case TK_ANCHOR_N: x -= width/2.0; y -= height; break; + case TK_ANCHOR_NE: x -= width; y -= height; break; + case TK_ANCHOR_E: x -= width; y -= height/2.0; break; + case TK_ANCHOR_SE: x -= width; break; + case TK_ANCHOR_S: x -= width/2.0; break; + case TK_ANCHOR_SW: break; + case TK_ANCHOR_W: y -= height/2.0; break; + case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; } /* @@ -939,18 +922,18 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass) sprintf(buffer, "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %s\n", x, y, width, height, -width, "0 rlineto closepath"); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) { return TCL_ERROR; } - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } /* - * Draw the bitmap, if there is a foreground color. If the bitmap - * is very large, then chop it up into multiple bitmaps, each - * consisting of one or more rows. This is needed because Postscript - * can't handle single strings longer than 64 KBytes long. + * Draw the bitmap, if there is a foreground color. If the bitmap is very + * large, then chop it up into multiple bitmaps, each consisting of one or + * more rows. This is needed because Postscript can't handle single + * strings longer than 64 KBytes long. */ if (fgColor != NULL) { @@ -960,8 +943,7 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass) if (width > 60000) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "can't generate Postscript", - " for bitmaps more than 60000 pixels wide", - (char *) NULL); + " for bitmaps more than 60000 pixels wide", NULL); return TCL_ERROR; } rowsAtOnce = 60000/width; @@ -969,7 +951,7 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass) rowsAtOnce = 1; } sprintf(buffer, "%.15g %.15g translate\n", x, y+height); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); for (curRow = 0; curRow < height; curRow += rowsAtOnce) { rowsThisTime = rowsAtOnce; if (rowsThisTime > (height - curRow)) { @@ -977,13 +959,21 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass) } sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n", (double) rowsThisTime, width, rowsThisTime); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); if (Tk_CanvasPsBitmap(interp, canvas, bitmap, 0, curRow, width, rowsThisTime) != TCL_OK) { return TCL_ERROR; } - Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL); + Tcl_AppendResult(interp, "\n} imagemask\n", NULL); } } return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvImg.c b/generic/tkCanvImg.c index ba85b4f..9e928c7 100644 --- a/generic/tkCanvImg.c +++ b/generic/tkCanvImg.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvImg.c -- * * This file implements image items for canvas widgets. @@ -6,13 +6,12 @@ * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" /* @@ -21,24 +20,24 @@ typedef struct ImageItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ Tk_Canvas canvas; /* Canvas containing the image. */ double x, y; /* Coordinates of positioning point for * image. */ - Tk_Anchor anchor; /* Where to anchor image relative to - * (x,y). */ - char *imageString; /* String describing -image option (malloc-ed). - * NULL means no image right now. */ + Tk_Anchor anchor; /* Where to anchor image relative to (x,y). */ + char *imageString; /* String describing -image option + * (malloc-ed). NULL means no image right + * now. */ char *activeImageString; /* String describing -activeimage option. * NULL means no image right now. */ char *disabledImageString; /* String describing -disabledimage option. * NULL means no image right now. */ - Tk_Image image; /* Image to display in window, or NULL if - * no image at present. */ - Tk_Image activeImage; /* Image to display in window, or NULL if - * no image at present. */ - Tk_Image disabledImage; /* Image to display in window, or NULL if - * no image at present. */ + Tk_Image image; /* Image to display in window, or NULL if no + * image at present. */ + Tk_Image activeImage; /* Image to display in window, or NULL if no + * image at present. */ + Tk_Image disabledImage; /* Image to display in window, or NULL if no + * image at present. */ } ImageItem; /* @@ -55,86 +54,81 @@ static Tk_CustomOption tagsOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_STRING, "-activeimage", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ImageItem, activeImageString), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-activeimage", NULL, NULL, + NULL, Tk_Offset(ImageItem, activeImageString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, "center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_STRING, "-disabledimage", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ImageItem, disabledImageString), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_STRING, "-disabledimage", NULL, NULL, + NULL, Tk_Offset(ImageItem, disabledImageString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_STRING, "-image", NULL, NULL, + NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static void ImageChangedProc _ANSI_ARGS_((ClientData clientData, +static void ImageChangedProc(ClientData clientData, int x, int y, int width, int height, int imgWidth, - int imgHeight)); -static int ImageCoords _ANSI_ARGS_((Tcl_Interp *interp, + int imgHeight); +static int ImageCoords(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - Tcl_Obj *CONST argv[])); -static int ImageToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static double ImageToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *coordPtr)); -static int ImageToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static void ComputeImageBbox _ANSI_ARGS_((Tk_Canvas canvas, - ImageItem *imgPtr)); -static int ConfigureImage _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST argv[]); +static int ImageToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static double ImageToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *coordPtr); +static int ImageToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void ComputeImageBbox(Tk_Canvas canvas, ImageItem *imgPtr); +static int ConfigureImage(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - Tcl_Obj *CONST argv[], int flags)); -static int CreateImage _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST argv[], int flags); +static int CreateImage(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int argc, Tcl_Obj *CONST argv[])); -static void DeleteImage _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayImage _ANSI_ARGS_((Tk_Canvas canvas, + int argc, Tcl_Obj *CONST argv[]); +static void DeleteImage(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayImage(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static void ScaleImage _ANSI_ARGS_((Tk_Canvas canvas, + int x, int y, int width, int height); +static void ScaleImage(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslateImage _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); + double scaleX, double scaleY); +static void TranslateImage(Tk_Canvas canvas, + Tk_Item *itemPtr, double deltaX, double deltaY); /* - * The structures below defines the image item type in terms of - * procedures that can be invoked by generic item code. + * The structures below defines the image item type in terms of functions that + * can be invoked by generic item code. */ Tk_ItemType tkImageType = { - "image", /* name */ - sizeof(ImageItem), /* itemSize */ - CreateImage, /* createProc */ - configSpecs, /* configSpecs */ - ConfigureImage, /* configureProc */ - ImageCoords, /* coordProc */ - DeleteImage, /* deleteProc */ - DisplayImage, /* displayProc */ - TK_CONFIG_OBJS, /* flags */ - ImageToPoint, /* pointProc */ - ImageToArea, /* areaProc */ - ImageToPostscript, /* postscriptProc */ - ScaleImage, /* scaleProc */ - TranslateImage, /* translateProc */ - (Tk_ItemIndexProc *) NULL, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* icursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ - (Tk_ItemInsertProc *) NULL, /* insertProc */ - (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + "image", /* name */ + sizeof(ImageItem), /* itemSize */ + CreateImage, /* createProc */ + configSpecs, /* configSpecs */ + ConfigureImage, /* configureProc */ + ImageCoords, /* coordProc */ + DeleteImage, /* deleteProc */ + DisplayImage, /* displayProc */ + TK_CONFIG_OBJS, /* flags */ + ImageToPoint, /* pointProc */ + ImageToArea, /* areaProc */ + ImageToPostscript, /* postscriptProc */ + ScaleImage, /* scaleProc */ + TranslateImage, /* translateProc */ + NULL, /* indexProc */ + NULL, /* icursorProc */ + NULL, /* selectionProc */ + NULL, /* insertProc */ + NULL, /* dTextProc */ + NULL, /* nextPtr */ }; /* @@ -142,14 +136,13 @@ Tk_ItemType tkImageType = { * * CreateImage -- * - * This procedure is invoked to create a new image - * item in a canvas. + * This function is invoked to create a new image item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is left uninitialized, - * so it can be safely freed by the caller. + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the + * caller. * * Side effects: * A new image item is created. @@ -158,19 +151,19 @@ Tk_ItemType tkImageType = { */ static int -CreateImage(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing rectangle. */ +CreateImage( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing rectangle. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* @@ -187,8 +180,8 @@ CreateImage(interp, canvas, itemPtr, objc, objv) imgPtr->disabledImage = NULL; /* - * Process the arguments to fill in the item record. - * Only 1 (list) or 2 (x y) coords are allowed. + * Process the arguments to fill in the item record. Only 1 (list) or 2 (x + * y) coords are allowed. */ if (objc == 1) { @@ -207,7 +200,7 @@ CreateImage(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -217,9 +210,8 @@ CreateImage(interp, canvas, itemPtr, objc, objv) * * ImageCoords -- * - * This procedure is invoked to process the "coords" widget - * command on image items. See the user documentation for - * details on what it does. + * This function is invoked to process the "coords" widget command on + * image items. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -231,20 +223,19 @@ CreateImage(interp, canvas, itemPtr, objc, objv) */ static int -ImageCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +ImageCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { ImageItem *imgPtr = (ImageItem *) itemPtr; if (objc == 0) { Tcl_Obj *obj = Tcl_NewObj(); + Tcl_Obj *subobj = Tcl_NewDoubleObj(imgPtr->x); Tcl_ListObjAppendElement(interp, obj, subobj); subobj = Tcl_NewDoubleObj(imgPtr->y); @@ -271,7 +262,7 @@ ImageCoords(interp, canvas, itemPtr, objc, objv) ComputeImageBbox(canvas, imgPtr); } else { char buf[64]; - + sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -284,12 +275,12 @@ ImageCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureImage -- * - * This procedure is invoked to configure various aspects - * of an image item, such as its anchor position. + * This function is invoked to configure various aspects of an image + * item, such as its anchor position. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: * Configuration information may be set for itemPtr. @@ -298,13 +289,13 @@ ImageCoords(interp, canvas, itemPtr, objc, objv) */ static int -ConfigureImage(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Image item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureImage( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Image item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; Tk_Window tkwin; @@ -317,10 +308,10 @@ ConfigureImage(interp, canvas, itemPtr, objc, objv, flags) } /* - * Create the image. Save the old image around and don't free it - * until after the new one is allocated. This keeps the reference - * count from going to zero so the image doesn't have to be recreated - * if it hasn't changed. + * Create the image. Save the old image around and don't free it until + * after the new one is allocated. This keeps the reference count from + * going to zero so the image doesn't have to be recreated if it hasn't + * changed. */ if (imgPtr->activeImageString != NULL) { @@ -376,8 +367,8 @@ ConfigureImage(interp, canvas, itemPtr, objc, objv, flags) * * DeleteImage -- * - * This procedure is called to clean up the data structure - * associated with a image item. + * This function is called to clean up the data structure associated with + * a image item. * * Results: * None. @@ -389,11 +380,10 @@ ConfigureImage(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteImage(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall canvas widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeleteImage( + Tk_Canvas canvas, /* Info about overall canvas widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; @@ -422,27 +412,24 @@ DeleteImage(canvas, itemPtr, display) * * ComputeImageBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a image item. - * This procedure is where the child image's placement is - * computed. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a image item. This function is where the + * child image's placement is computed. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -ComputeImageBbox(canvas, imgPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - ImageItem *imgPtr; /* Item whose bbox is to be - * recomputed. */ +ComputeImageBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + ImageItem *imgPtr) /* Item whose bbox is to be recomputed. */ { int width, height; int x, y; @@ -478,36 +465,36 @@ ComputeImageBbox(canvas, imgPtr) Tk_SizeOfImage(image, &width, &height); switch (imgPtr->anchor) { - case TK_ANCHOR_N: - x -= width/2; - break; - case TK_ANCHOR_NE: - x -= width; - break; - case TK_ANCHOR_E: - x -= width; - y -= height/2; - break; - case TK_ANCHOR_SE: - x -= width; - y -= height; - break; - case TK_ANCHOR_S: - x -= width/2; - y -= height; - break; - case TK_ANCHOR_SW: - y -= height; - break; - case TK_ANCHOR_W: - y -= height/2; - break; - case TK_ANCHOR_NW: - break; - case TK_ANCHOR_CENTER: - x -= width/2; - y -= height/2; - break; + case TK_ANCHOR_N: + x -= width/2; + break; + case TK_ANCHOR_NE: + x -= width; + break; + case TK_ANCHOR_E: + x -= width; + y -= height/2; + break; + case TK_ANCHOR_SE: + x -= width; + y -= height; + break; + case TK_ANCHOR_S: + x -= width/2; + y -= height; + break; + case TK_ANCHOR_SW: + y -= height; + break; + case TK_ANCHOR_W: + y -= height/2; + break; + case TK_ANCHOR_NW: + break; + case TK_ANCHOR_CENTER: + x -= width/2; + y -= height/2; + break; } /* @@ -525,35 +512,34 @@ ComputeImageBbox(canvas, imgPtr) * * DisplayImage -- * - * This procedure is invoked to draw a image item in a given - * drawable. + * This function is invoked to draw a image item in a given drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int x, y, width, height; /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayImage( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, int width, int height) + /* Describes region of canvas that must be + * redisplayed (not used). */ { ImageItem *imgPtr = (ImageItem *) itemPtr; short drawableX, drawableY; Tk_Image image; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -587,14 +573,14 @@ DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height) * * ImageToPoint -- * - * Computes the distance from a given point to a given - * rectangle, in canvas units. + * Computes the distance from a given point to a given rectangle, in + * canvas units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are coordPtr[0] and coordPtr[1] is inside the image. If the - * point isn't inside the image then the return value is the - * distance from the point to the image. + * The return value is 0 if the point whose x and y coordinates are + * coordPtr[0] and coordPtr[1] is inside the image. If the point isn't + * inside the image then the return value is the distance from the point + * to the image. * * Side effects: * None. @@ -603,10 +589,10 @@ DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height) */ static double -ImageToPoint(canvas, itemPtr, coordPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *coordPtr; /* Pointer to x and y coordinates. */ +ImageToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *coordPtr) /* Pointer to x and y coordinates. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; double x1, x2, y1, y2, xDiff, yDiff; @@ -644,14 +630,13 @@ ImageToPoint(canvas, itemPtr, coordPtr) * * ImageToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangle. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangle. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -660,12 +645,12 @@ ImageToPoint(canvas, itemPtr, coordPtr) */ static int -ImageToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against rectangle. */ - double *rectPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +ImageToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against rectangle. */ + double *rectPtr) /* Pointer to array of four coordinates + * (x1,y1,x2,y2) describing rectangular + * area. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; @@ -689,15 +674,13 @@ ImageToArea(canvas, itemPtr, rectPtr) * * ImageToPostscript -- * - * This procedure is called to generate Postscript for - * image items. + * This function is called to generate Postscript for image items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in interp->result, replacing whatever used to be there. - * If no error occurs, then Postscript for the item is appended - * to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in interp->result, + * replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -706,15 +689,13 @@ ImageToArea(canvas, itemPtr, rectPtr) */ static int -ImageToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created.*/ +ImageToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created.*/ { ImageItem *imgPtr = (ImageItem *)itemPtr; Tk_Window canvasWin = Tk_CanvasTkwin(canvas); @@ -725,7 +706,7 @@ ImageToPostscript(interp, canvas, itemPtr, prepass) Tk_Image image; Tk_State state = itemPtr->state; - if (state == TK_STATE_NULL) { + if(state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -743,33 +724,34 @@ ImageToPostscript(interp, canvas, itemPtr, prepass) /* * Image item without actual image specified. */ - return TCL_OK; + + return TCL_OK; } Tk_SizeOfImage(image, &width, &height); /* - * Compute the coordinates of the lower-left corner of the image, - * taking into account the anchor position for the image. + * Compute the coordinates of the lower-left corner of the image, taking + * into account the anchor position for the image. */ x = imgPtr->x; y = Tk_CanvasPsY(canvas, imgPtr->y); switch (imgPtr->anchor) { - case TK_ANCHOR_NW: y -= height; break; - case TK_ANCHOR_N: x -= width/2.0; y -= height; break; - case TK_ANCHOR_NE: x -= width; y -= height; break; - case TK_ANCHOR_E: x -= width; y -= height/2.0; break; - case TK_ANCHOR_SE: x -= width; break; - case TK_ANCHOR_S: x -= width/2.0; break; - case TK_ANCHOR_SW: break; - case TK_ANCHOR_W: y -= height/2.0; break; - case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; + case TK_ANCHOR_NW: y -= height; break; + case TK_ANCHOR_N: x -= width/2.0; y -= height; break; + case TK_ANCHOR_NE: x -= width; y -= height; break; + case TK_ANCHOR_E: x -= width; y -= height/2.0; break; + case TK_ANCHOR_SE: x -= width; break; + case TK_ANCHOR_S: x -= width/2.0; break; + case TK_ANCHOR_SW: break; + case TK_ANCHOR_W: y -= height/2.0; break; + case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; } if (!prepass) { sprintf(buffer, "%.15g %.15g", x, y); - Tcl_AppendResult(interp, buffer, " translate\n", (char *) NULL); + Tcl_AppendResult(interp, buffer, " translate\n", NULL); } return Tk_PostscriptImage(image, interp, canvasWin, @@ -781,14 +763,14 @@ ImageToPostscript(interp, canvas, itemPtr, prepass) * * ScaleImage -- * - * This procedure is invoked to rescale an item. + * This function is invoked to rescale an item. * * Results: * None. * * Side effects: - * The item referred to by itemPtr is rescaled so that the - * following transformation is applied to all point coordinates: + * The item referred to by itemPtr is rescaled so that the following + * transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -796,12 +778,13 @@ ImageToPostscript(interp, canvas, itemPtr, prepass) */ static void -ScaleImage(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing rectangle. */ - Tk_Item *itemPtr; /* Rectangle to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleImage( + Tk_Canvas canvas, /* Canvas containing rectangle. */ + Tk_Item *itemPtr, /* Rectangle to be scaled. */ + double originX, double originY, + /* Origin about which to scale rect. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; @@ -815,25 +798,24 @@ ScaleImage(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateImage -- * - * This procedure is called to move an item by a given amount. + * This function is called to move an item by a given amount. * * Results: * None. * * Side effects: - * The position of the item is offset by (xDelta, yDelta), and - * the bounding box is updated in the generic part of the item - * structure. + * The position of the item is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslateImage(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslateImage( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; @@ -847,9 +829,9 @@ TranslateImage(canvas, itemPtr, deltaX, deltaY) * * ImageChangedProc -- * - * This procedure is invoked by the image code whenever the manager - * for an image does something that affects the image's size or - * how it is displayed. + * This function is invoked by the image code whenever the manager for an + * image does something that affects the image's size or how it is + * displayed. * * Results: * None. @@ -861,21 +843,21 @@ TranslateImage(canvas, itemPtr, deltaX, deltaY) */ static void -ImageChangedProc(clientData, x, y, width, height, imgWidth, imgHeight) - ClientData clientData; /* Pointer to canvas item for image. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +ImageChangedProc( + ClientData clientData, /* Pointer to canvas item for image. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (may be <= + * 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { ImageItem *imgPtr = (ImageItem *) clientData; /* - * If the image's size changed and it's not anchored at its - * northwest corner then just redisplay the entire area of the - * image. This is a bit over-conservative, but we need to do - * something because a size change also means a position change. + * If the image's size changed and it's not anchored at its northwest + * corner then just redisplay the entire area of the image. This is a bit + * over-conservative, but we need to do something because a size change + * also means a position change. */ if (((imgPtr->header.x2 - imgPtr->header.x1) != imgWidth) @@ -885,9 +867,17 @@ ImageChangedProc(clientData, x, y, width, height, imgWidth, imgHeight) height = imgHeight; Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1, imgPtr->header.y1, imgPtr->header.x2, imgPtr->header.y2); - } + } ComputeImageBbox(imgPtr->canvas, imgPtr); Tk_CanvasEventuallyRedraw(imgPtr->canvas, imgPtr->header.x1 + x, imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width), (int) (imgPtr->header.y1 + y + height)); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c index 4c7b9be..cce3460 100644 --- a/generic/tkCanvLine.c +++ b/generic/tkCanvLine.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvLine.c -- * * This file implements line items for canvas widgets. @@ -7,13 +7,12 @@ * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" /* @@ -26,21 +25,21 @@ typedef enum { typedef struct LineItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ Tk_Outline outline; /* Outline structure */ - Tk_Canvas canvas; /* Canvas containing item. Needed for - * parsing arrow shapes. */ + Tk_Canvas canvas; /* Canvas containing item. Needed for parsing + * arrow shapes. */ int numPoints; /* Number of points in line (always >= 0). */ - double *coordPtr; /* Pointer to malloc-ed array containing - * x- and y-coords of all points in line. + double *coordPtr; /* Pointer to malloc-ed array containing x- + * and y-coords of all points in line. * X-coords are even-valued indices, y-coords * are corresponding odd-valued indices. If - * the line has arrowheads then the first - * and last points have been adjusted to refer - * to the necks of the arrowheads rather than - * their tips. The actual endpoints are - * stored in the *firstArrowPtr and - * *lastArrowPtr, if they exist. */ + * the line has arrowheads then the first and + * last points have been adjusted to refer to + * the necks of the arrowheads rather than + * their tips. The actual endpoints are stored + * in the *firstArrowPtr and *lastArrowPtr, if + * they exist. */ int capStyle; /* Cap style for line. */ int joinStyle; /* Join style for line. */ GC arrowGC; /* Graphics context for drawing arrowheads. */ @@ -53,13 +52,13 @@ typedef struct LineItem { * edge of shaft. */ double *firstArrowPtr; /* Points to array of PTS_IN_ARROW points * describing polygon for arrowhead at first - * point in line. First point of arrowhead - * is tip. Malloc'ed. NULL means no arrowhead - * at first point. */ + * point in line. First point of arrowhead is + * tip. Malloc'ed. NULL means no arrowhead at + * first point. */ double *lastArrowPtr; /* Points to polygon for arrowhead at last * point in line (PTS_IN_ARROW points, first - * of which is tip). Malloc'ed. NULL means - * no arrowhead at last point. */ + * of which is tip). Malloc'ed. NULL means no + * arrowhead at last point. */ Tk_SmoothMethod *smooth; /* Non-zero means draw line smoothed (i.e. * with Bezier splines). */ int splineSteps; /* Number of steps in each spline segment. */ @@ -72,65 +71,63 @@ typedef struct LineItem { #define PTS_IN_ARROW 6 /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static int ArrowheadPostscript _ANSI_ARGS_((Tcl_Interp *interp, +static int ArrowheadPostscript(Tcl_Interp *interp, Tk_Canvas canvas, LineItem *linePtr, - double *arrowPtr)); -static void ComputeLineBbox _ANSI_ARGS_((Tk_Canvas canvas, - LineItem *linePtr)); -static int ConfigureLine _ANSI_ARGS_((Tcl_Interp *interp, + double *arrowPtr); +static void ComputeLineBbox(Tk_Canvas canvas, LineItem *linePtr); +static int ConfigureLine(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static int ConfigureArrows _ANSI_ARGS_((Tk_Canvas canvas, - LineItem *linePtr)); -static int CreateLine _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[], int flags); +static int ConfigureArrows(Tk_Canvas canvas, LineItem *linePtr); +static int CreateLine(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeleteLine _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayLine _ANSI_ARGS_((Tk_Canvas canvas, + int objc, Tcl_Obj *CONST objv[]); +static void DeleteLine(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayLine(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static int GetLineIndex _ANSI_ARGS_((Tcl_Interp *interp, + int x, int y, int width, int height); +static int GetLineIndex(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, - Tcl_Obj *obj, int *indexPtr)); -static int LineCoords _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *obj, int *indexPtr); +static int LineCoords(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void LineDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int first, int last)); -static void LineInsert _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj)); -static int LineToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static double LineToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *coordPtr)); -static int LineToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static int ArrowParseProc _ANSI_ARGS_((ClientData clientData, + int objc, Tcl_Obj *CONST objv[]); +static void LineDeleteCoords(Tk_Canvas canvas, + Tk_Item *itemPtr, int first, int last); +static void LineInsert(Tk_Canvas canvas, + Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj); +static int LineToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static double LineToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *coordPtr); +static int LineToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static int ArrowParseProc(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, - CONST char *value, char *recordPtr, int offset)); -static char * ArrowPrintProc _ANSI_ARGS_((ClientData clientData, + CONST char *value, char *recordPtr, int offset); +static char * ArrowPrintProc(ClientData clientData, Tk_Window tkwin, char *recordPtr, int offset, - Tcl_FreeProc **freeProcPtr)); -static int ParseArrowShape _ANSI_ARGS_((ClientData clientData, + Tcl_FreeProc **freeProcPtr); +static int ParseArrowShape(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, - CONST char *value, char *recordPtr, int offset)); -static char * PrintArrowShape _ANSI_ARGS_((ClientData clientData, + CONST char *value, char *recordPtr, int offset); +static char * PrintArrowShape(ClientData clientData, Tk_Window tkwin, char *recordPtr, int offset, - Tcl_FreeProc **freeProcPtr)); -static void ScaleLine _ANSI_ARGS_((Tk_Canvas canvas, + Tcl_FreeProc **freeProcPtr); +static void ScaleLine(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslateLine _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); + double scaleX, double scaleY); +static void TranslateLine(Tk_Canvas canvas, + Tk_Item *itemPtr, double deltaX, double deltaY); /* - * Information used for parsing configuration specs. If you change any - * of the default strings, be sure to change the corresponding default - * values in CreateLine. + * Information used for parsing configuration specs. If you change any of the + * default strings, be sure to change the corresponding default values in + * CreateLine. */ static Tk_CustomOption arrowShapeOption = { @@ -168,73 +165,65 @@ static Tk_CustomOption pixelOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.activeDash), + {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.activeColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.activeStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-activefill", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.activeColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.activeStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, "0.0", Tk_Offset(LineItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_CUSTOM, "-arrow", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-arrow", NULL, NULL, "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT, &arrowOption}, - {TK_CONFIG_CUSTOM, "-arrowshape", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-arrowshape", NULL, NULL, "8 10 3", Tk_Offset(LineItem, arrowShapeA), TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption}, - {TK_CONFIG_CAP_STYLE, "-capstyle", (char *) NULL, (char *) NULL, + {TK_CONFIG_CAP_STYLE, "-capstyle", NULL, NULL, "butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-fill", NULL, NULL, "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.dash), + {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL, - "0", Tk_Offset(LineItem, outline.offset), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.disabledDash), + {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, + "0", Tk_Offset(LineItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT}, + {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.disabledColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.disabledStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.disabledColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.disabledStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL, "0.0", Tk_Offset(LineItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL, + {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL, "round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, "0,0", Tk_Offset(LineItem, outline.tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, - {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL, "0", Tk_Offset(LineItem, smooth), TK_CONFIG_DONT_SET_DEFAULT, &smoothOption}, - {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-splinesteps", NULL, NULL, "12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(LineItem, outline.stipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, + NULL, Tk_Offset(LineItem, outline.stipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_CUSTOM, "-width", NULL, NULL, "1.0", Tk_Offset(LineItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * The structures below defines the line item type by means - * of procedures that can be invoked by generic item code. + * The structures below defines the line item type by means of functions that + * can be invoked by generic item code. */ Tk_ItemType tkLineType = { @@ -253,17 +242,17 @@ Tk_ItemType tkLineType = { ScaleLine, /* scaleProc */ TranslateLine, /* translateProc */ (Tk_ItemIndexProc *) GetLineIndex, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* icursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ + NULL, /* icursorProc */ + NULL, /* selectionProc */ (Tk_ItemInsertProc *) LineInsert, /* insertProc */ LineDeleteCoords, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + NULL, /* nextPtr */ }; /* - * The definition below determines how large are static arrays - * used to hold spline points (splines larger than this have to - * have their arrays malloc-ed). + * The definition below determines how large are static arrays used to hold + * spline points (splines larger than this have to have their arrays + * malloc-ed). */ #define MAX_STATIC_POINTS 200 @@ -273,14 +262,13 @@ Tk_ItemType tkLineType = { * * CreateLine -- * - * This procedure is invoked to create a new line item in - * a canvas. + * This function is invoked to create a new line item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is left uninitialized, - * so it can be safely freed by the caller. + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the + * caller. * * Side effects: * A new line item is created. @@ -289,25 +277,24 @@ Tk_ItemType tkLineType = { */ static int -CreateLine(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing line. */ +CreateLine( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing line. */ { LineItem *linePtr = (LineItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* - * Carry out initialization that is needed to set defaults and to - * allow proper cleanup after errors during the the remainder of - * this procedure. + * Carry out initialization that is needed to set defaults and to allow + * proper cleanup after errors during the the remainder of this function. */ Tk_CreateOutline(&(linePtr->outline)); @@ -323,17 +310,18 @@ CreateLine(interp, canvas, itemPtr, objc, objv) linePtr->arrowShapeC = (float)3.0; linePtr->firstArrowPtr = NULL; linePtr->lastArrowPtr = NULL; - linePtr->smooth = (Tk_SmoothMethod *) NULL; + linePtr->smooth = NULL; linePtr->splineSteps = 12; /* - * Count the number of points and then parse them into a point - * array. Leading arguments are assumed to be points if they - * start with a digit or a minus sign followed by a digit. + * Count the number of points and then parse them into a point array. + * Leading arguments are assumed to be points if they start with a digit + * or a minus sign followed by a digit. */ for (i = 1; i < objc; i++) { char *arg = Tcl_GetString(objv[i]); + if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { break; } @@ -345,7 +333,7 @@ CreateLine(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeleteLine(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -355,9 +343,8 @@ CreateLine(interp, canvas, itemPtr, objc, objv) * * LineCoords -- * - * This procedure is invoked to process the "coords" widget - * command on lines. See the user documentation for details - * on what it does. + * This function is invoked to process the "coords" widget command on + * lines. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -369,15 +356,13 @@ CreateLine(interp, canvas, itemPtr, objc, objv) */ static int -LineCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +LineCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { LineItem *linePtr = (LineItem *) itemPtr; int i, numPoints; @@ -414,20 +399,22 @@ LineCoords(interp, canvas, itemPtr, objc, objv) } if (objc & 1) { char buf[64 + TCL_INTEGER_SPACE]; + sprintf(buf, "wrong # coordinates: expected an even number, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; } else if (objc < 4) { char buf[64 + TCL_INTEGER_SPACE]; + sprintf(buf, "wrong # coordinates: expected at least 4, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; } else { numPoints = objc/2; if (linePtr->numPoints != numPoints) { - coordPtr = (double *) ckalloc((unsigned) - (sizeof(double) * objc)); + coordPtr = (double *) + ckalloc((unsigned) (sizeof(double) * objc)); if (linePtr->coordPtr != NULL) { ckfree((char *) linePtr->coordPtr); } @@ -468,28 +455,28 @@ LineCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureLine -- * - * This procedure is invoked to configure various aspects - * of a line item such as its background color. + * This function is invoked to configure various aspects of a line item + * such as its background color. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: - * Configuration information, such as colors and stipple - * patterns, may be set for itemPtr. + * Configuration information, such as colors and stipple patterns, may be + * set for itemPtr. * *-------------------------------------------------------------- */ static int -ConfigureLine(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Line item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureLine( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Line item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { LineItem *linePtr = (LineItem *) itemPtr; XGCValues gcValues; @@ -505,8 +492,8 @@ ConfigureLine(interp, canvas, itemPtr, objc, objv, flags) } /* - * A few of the options require additional processing, such as - * graphics contexts. + * A few of the options require additional processing, such as graphics + * contexts. */ state = itemPtr->state; @@ -571,9 +558,8 @@ ConfigureLine(interp, canvas, itemPtr, objc, objv, flags) } /* - * Setup arrowheads, if needed. If arrowheads are turned off, - * restore the line's endpoints (they were shortened when the - * arrowheads were added). + * Setup arrowheads, if needed. If arrowheads are turned off, restore the + * line's endpoints (they were shortened when the arrowheads were added). */ if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST) @@ -611,8 +597,8 @@ ConfigureLine(interp, canvas, itemPtr, objc, objv, flags) * * DeleteLine -- * - * This procedure is called to clean up the data structure - * associated with a line item. + * This function is called to clean up the data structure associated with + * a line item. * * Results: * None. @@ -624,11 +610,10 @@ ConfigureLine(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteLine(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall canvas widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeleteLine( + Tk_Canvas canvas, /* Info about overall canvas widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { LineItem *linePtr = (LineItem *) itemPtr; @@ -652,24 +637,22 @@ DeleteLine(canvas, itemPtr, display) * * ComputeLineBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a line. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a line. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ static void -ComputeLineBbox(canvas, linePtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - LineItem *linePtr; /* Item whose bbos is to be - * recomputed. */ +ComputeLineBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + LineItem *linePtr) /* Item whose bbos is to be recomputed. */ { double *coordPtr; int i, intWidth; @@ -705,13 +688,12 @@ ComputeLineBbox(canvas, linePtr) linePtr->header.y1 = linePtr->header.y2 = (int) coordPtr[1]; /* - * Compute the bounding box of all the points in the line, - * then expand in all directions by the line's width to take - * care of butting or rounded corners and projecting or - * rounded caps. This expansion is an overestimate (worst-case - * is square root of two over two) but it's simple. Don't do - * anything special for curves. This causes an additional - * overestimate in the bounding box, but is faster. + * Compute the bounding box of all the points in the line, then expand in + * all directions by the line's width to take care of butting or rounded + * corners and projecting or rounded caps. This expansion is an + * overestimate (worst-case is square root of two over two) but it's + * simple. eDon't do anything special for curves. This causes an + * additional overestimate in the bounding box, but is faster. */ for (i = 1, coordPtr = linePtr->coordPtr+2; i < linePtr->numPoints; @@ -780,9 +762,9 @@ ComputeLineBbox(canvas, linePtr) } /* - * For mitered lines, make a second pass through all the points. - * Compute the locations of the two miter vertex points and add - * those into the bounding box. + * For mitered lines, make a second pass through all the points. Compute + * the locations of the two miter vertex points and add those into the + * bounding box. */ if (linePtr->joinStyle == JoinMiter) { @@ -790,7 +772,7 @@ ComputeLineBbox(canvas, linePtr) i--, coordPtr += 2) { double miter[4]; int j; - + if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width, miter, miter+2)) { for (j = 0; j < 4; j += 2) { @@ -820,8 +802,8 @@ ComputeLineBbox(canvas, linePtr) } /* - * Add one more pixel of fudge factor just to be safe (e.g. - * X may round differently than we do). + * Add one more pixel of fudge factor just to be safe (e.g. X may round + * differently than we do). */ linePtr->header.x1 -= 1; @@ -835,28 +817,27 @@ ComputeLineBbox(canvas, linePtr) * * DisplayLine -- * - * This procedure is invoked to draw a line item in a given - * drawable. + * This function is invoked to draw a line item in a given drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int x, y, width, height; /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayLine( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, int width, int height) + /* Describes region of canvas that must be + * redisplayed (not used). */ { LineItem *linePtr = (LineItem *) itemPtr; XPoint staticPoints[MAX_STATIC_POINTS*3]; @@ -883,16 +864,15 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height) } } /* - * Build up an array of points in screen coordinates. Use a - * static array unless the line has an enormous number of points; - * in this case, dynamically allocate an array. For smoothed lines, - * generate the curve points on each redisplay. + * Build up an array of points in screen coordinates. Use a static array + * unless the line has an enormous number of points; in this case, + * dynamically allocate an array. For smoothed lines, generate the curve + * points on each redisplay. */ if ((linePtr->smooth) && (linePtr->numPoints > 2)) { - numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = linePtr->smooth->coordProc(canvas, NULL, + linePtr->numPoints, linePtr->splineSteps, NULL, NULL); } else { numPoints = linePtr->numPoints; } @@ -905,18 +885,17 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height) if ((linePtr->smooth) && (linePtr->numPoints > 2)) { numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr, - linePtr->numPoints, linePtr->splineSteps, pointPtr, - (double *) NULL); + linePtr->numPoints, linePtr->splineSteps, pointPtr, NULL); } else { numPoints = TkCanvTranslatePath((TkCanvas*)canvas, numPoints, linePtr->coordPtr, 0, pointPtr); } /* - * Display line, the free up line storage if it was dynamically - * allocated. If we're stippling, then modify the stipple offset - * in the GC. Be sure to reset the offset when done, since the - * GC is supposed to be read-only. + * Display line, the free up line storage if it was dynamically allocated. + * If we're stippling, then modify the stipple offset in the GC. Be sure + * to reset the offset when done, since the GC is supposed to be + * read-only. */ if (Tk_ChangeOutlineGC(canvas, itemPtr, &(linePtr->outline))) { @@ -972,24 +951,24 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height) */ static void -LineInsert(canvas, itemPtr, beforeThis, obj) - Tk_Canvas canvas; /* Canvas containing text item. */ - Tk_Item *itemPtr; /* Line item to be modified. */ - int beforeThis; /* Index before which new coordinates - * are to be inserted. */ - Tcl_Obj *obj; /* New coordinates to be inserted. */ +LineInsert( + Tk_Canvas canvas, /* Canvas containing text item. */ + Tk_Item *itemPtr, /* Line item to be modified. */ + int beforeThis, /* Index before which new coordinates are to + * be inserted. */ + Tcl_Obj *obj) /* New coordinates to be inserted. */ { LineItem *linePtr = (LineItem *) itemPtr; int length, objc, i; - double *new, *coordPtr; + double *newCoordPtr, *coordPtr; Tk_State state = itemPtr->state; Tcl_Obj **objv; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } - if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &objc, &objv) != TCL_OK) + if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK) || !objc || objc&1) { return; } @@ -1008,38 +987,40 @@ LineInsert(canvas, itemPtr, beforeThis, obj) linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0]; linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1]; } - new = (double *) ckalloc((unsigned)(sizeof(double) * (length + objc))); - for(i=0; i<beforeThis; i++) { - new[i] = linePtr->coordPtr[i]; + newCoordPtr = (double *) + ckalloc(sizeof(double) * (unsigned)(length + objc)); + for (i=0; i<beforeThis; i++) { + newCoordPtr[i] = linePtr->coordPtr[i]; } - for(i=0; i<objc; i++) { - if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i], - new+(i+beforeThis))!=TCL_OK) { + for (i=0; i<objc; i++) { + if (Tcl_GetDoubleFromObj(NULL, objv[i], + &newCoordPtr[i + beforeThis]) != TCL_OK) { Tcl_ResetResult(((TkCanvas *)canvas)->interp); - ckfree((char *) new); + ckfree((char *) newCoordPtr); return; } } - for(i=beforeThis; i<length; i++) { - new[i+objc] = linePtr->coordPtr[i]; + for (i=beforeThis; i<length; i++) { + newCoordPtr[i+objc] = linePtr->coordPtr[i]; } if (linePtr->coordPtr) { ckfree((char *) linePtr->coordPtr); } - linePtr->coordPtr = new; + linePtr->coordPtr = newCoordPtr; length += objc; linePtr->numPoints = length / 2; if ((length>3) && (state != TK_STATE_HIDDEN)) { /* - * This is some optimizing code that will result that only the part - * of the polygon that changed (and the objects that are overlapping - * with that part) need to be redrawn. A special flag is set that - * instructs the general canvas code not to redraw the whole - * object. If this flag is not set, the canvas will do the redrawing, - * otherwise I have to do it here. + * This is some optimizing code that will result that only the part of + * the polygon that changed (and the objects that are overlapping with + * that part) need to be redrawn. A special flag is set that instructs + * the general canvas code not to redraw the whole object. If this + * flag is not set, the canvas will do the redrawing, otherwise I have + * to do it here. */ + itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW; if (beforeThis>0) {beforeThis -= 2; objc+=2; } @@ -1055,23 +1036,29 @@ LineInsert(canvas, itemPtr, beforeThis, obj) itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis]; itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1]; if ((linePtr->firstArrowPtr != NULL) && (beforeThis<1)) { - /* include old first arrow */ + /* + * Include old first arrow. + */ + for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); } } if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+objc)>=length)) { - /* include old last arrow */ + /* + * Include old last arrow. + */ + for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); } } coordPtr = linePtr->coordPtr+beforeThis+2; - for(i=2; i<objc; i+=2) { + for (i=2; i<objc; i+=2) { TkIncludePoint(itemPtr, coordPtr); - coordPtr+=2; + coordPtr+=2; } } if (linePtr->firstArrowPtr != NULL) { @@ -1083,21 +1070,28 @@ LineInsert(canvas, itemPtr, beforeThis, obj) linePtr->lastArrowPtr = NULL; } if (linePtr->arrow != ARROWS_NONE) { - ConfigureArrows(canvas, linePtr); + ConfigureArrows(canvas, linePtr); } - if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) { + if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) { double width; int intWidth; + if ((linePtr->firstArrowPtr != NULL) && (beforeThis>2)) { - /* include new first arrow */ + /* + * Include new first arrow. + */ + for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); } } - if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+objc)<(length-2))) { - /* include new right arrow */ + if ((linePtr->lastArrowPtr != NULL) && (beforeThis+objc < length-2)) { + /* + * Include new right arrow. + */ + for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); @@ -1105,13 +1099,13 @@ LineInsert(canvas, itemPtr, beforeThis, obj) } width = linePtr->outline.width; if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { - if (linePtr->outline.activeWidth>width) { - width = linePtr->outline.activeWidth; - } + if (linePtr->outline.activeWidth>width) { + width = linePtr->outline.activeWidth; + } } else if (state==TK_STATE_DISABLED) { - if (linePtr->outline.disabledWidth>0) { - width = linePtr->outline.disabledWidth; - } + if (linePtr->outline.disabledWidth>0) { + width = linePtr->outline.disabledWidth; + } } intWidth = (int) (width + 0.5); if (intWidth < 1) { @@ -1137,18 +1131,18 @@ LineInsert(canvas, itemPtr, beforeThis, obj) * None. * * Side effects: - * Characters between "first" and "last", inclusive, get - * deleted from itemPtr. + * Characters between "first" and "last", inclusive, get deleted from + * itemPtr. * *-------------------------------------------------------------- */ static void -LineDeleteCoords(canvas, itemPtr, first, last) - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Item in which to delete characters. */ - int first; /* Index of first character to delete. */ - int last; /* Index of last character to delete. */ +LineDeleteCoords( + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Item in which to delete characters. */ + int first, /* Index of first character to delete. */ + int last) /* Index of last character to delete. */ { LineItem *linePtr = (LineItem *) itemPtr; int count, i, first1, last1; @@ -1156,7 +1150,7 @@ LineDeleteCoords(canvas, itemPtr, first, last) double *coordPtr; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -1180,36 +1174,51 @@ LineDeleteCoords(canvas, itemPtr, first, last) linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0]; linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1]; } - first1 = first; last1 = last; - if(first1>0) first1 -= 2; - if(last1<length-2) last1 += 2; + first1 = first; + last1 = last; + if (first1 > 0) { + first1 -= 2; + } + if (last1 < length-2) { + last1 += 2; + } if (linePtr->smooth) { - if(first1>0) first1 -= 2; - if(last1<length-2) last1 += 2; + if (first1 > 0) { + first1 -= 2; + } + if (last1 < length-2) { + last1 += 2; + } } - if((first1<2) && (last1 >= length-2)) { + if (!(first1 < 2) && (last1 >= length-2)) { /* - * This is some optimizing code that will result that only the part - * of the line that changed (and the objects that are overlapping - * with that part) need to be redrawn. A special flag is set that - * instructs the general canvas code not to redraw the whole - * object. If this flag is set, the redrawing has to be done here, - * otherwise the general Canvas code will take care of it. + * This is some optimizing code that will result that only the part of + * the line that changed (and the objects that are overlapping with + * that part) need to be redrawn. A special flag is set that instructs + * the general canvas code not to redraw the whole object. If this + * flag is set, the redrawing has to be done here, otherwise the + * general Canvas code will take care of it. */ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW; itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1]; itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1]; - if ((linePtr->firstArrowPtr != NULL) && (first1<2)) { - /* include old first arrow */ + if ((linePtr->firstArrowPtr != NULL) && (first1 < 2)) { + /* + * Include old first arrow. + */ + for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); } } - if ((linePtr->lastArrowPtr != NULL) && (last1>=length-2)) { - /* include old last arrow */ + if ((linePtr->lastArrowPtr != NULL) && (last1 >= length-2)) { + /* + * Include old last arrow. + */ + for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); @@ -1218,7 +1227,7 @@ LineDeleteCoords(canvas, itemPtr, first, last) coordPtr = linePtr->coordPtr+first1+2; for (i=first1+2; i<=last1; i+=2) { TkIncludePoint(itemPtr, coordPtr); - coordPtr+=2; + coordPtr += 2; } } @@ -1236,20 +1245,27 @@ LineDeleteCoords(canvas, itemPtr, first, last) linePtr->lastArrowPtr = NULL; } if (linePtr->arrow != ARROWS_NONE) { - ConfigureArrows(canvas, linePtr); + ConfigureArrows(canvas, linePtr); } - if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) { + if (itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) { double width; int intWidth; - if ((linePtr->firstArrowPtr != NULL) && (first1<4)) { - /* include new first arrow */ + + if ((linePtr->firstArrowPtr != NULL) && (first1 < 4)) { + /* + * Include new first arrow. + */ + for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); } } - if ((linePtr->lastArrowPtr != NULL) && (last1>(length-4))) { - /* include new right arrow */ + if ((linePtr->lastArrowPtr != NULL) && (last1 > length-4)) { + /* + * Include new right arrow. + */ + for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint(itemPtr, coordPtr); @@ -1257,20 +1273,22 @@ LineDeleteCoords(canvas, itemPtr, first, last) } width = linePtr->outline.width; if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { - if (linePtr->outline.activeWidth>width) { - width = linePtr->outline.activeWidth; - } + if (linePtr->outline.activeWidth > width) { + width = linePtr->outline.activeWidth; + } } else if (state==TK_STATE_DISABLED) { - if (linePtr->outline.disabledWidth>0) { - width = linePtr->outline.disabledWidth; - } + if (linePtr->outline.disabledWidth > 0) { + width = linePtr->outline.disabledWidth; + } } intWidth = (int) (width + 0.5); if (intWidth < 1) { intWidth = 1; } - itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth; - itemPtr->x2 += intWidth; itemPtr->y2 += intWidth; + itemPtr->x1 -= intWidth; + itemPtr->y1 -= intWidth; + itemPtr->x2 += intWidth; + itemPtr->y2 += intWidth; Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2); } @@ -1282,14 +1300,14 @@ LineDeleteCoords(canvas, itemPtr, first, last) * * LineToPoint -- * - * Computes the distance from a given point to a given - * line, in canvas units. + * Computes the distance from a given point to a given line, in canvas + * units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are pointPtr[0] and pointPtr[1] is inside the line. If the - * point isn't inside the line then the return value is the - * distance from the point to the line. + * The return value is 0 if the point whose x and y coordinates are + * pointPtr[0] and pointPtr[1] is inside the line. If the point isn't + * inside the line then the return value is the distance from the point + * to the line. * * Side effects: * None. @@ -1299,10 +1317,10 @@ LineDeleteCoords(canvas, itemPtr, first, last) /* ARGSUSED */ static double -LineToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +LineToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { Tk_State state = itemPtr->state; LineItem *linePtr = (LineItem *) itemPtr; @@ -1311,15 +1329,15 @@ LineToPoint(canvas, itemPtr, pointPtr) double poly[10]; double bestDist, dist, width; int numPoints, count; - int changedMiterToBevel; /* Non-zero means that a mitered corner - * had to be treated as beveled after all - * because the angle was < 11 degrees. */ + int changedMiterToBevel; /* Non-zero means that a mitered corner had to + * be treated as beveled after all because the + * angle was < 11 degrees. */ bestDist = 1.0e36; /* - * Handle smoothed lines by generating an expanded set of points - * against which to do the check. + * Handle smoothed lines by generating an expanded set of points against + * which to do the check. */ if(state == TK_STATE_NULL) { @@ -1338,9 +1356,8 @@ LineToPoint(canvas, itemPtr, pointPtr) } if ((linePtr->smooth) && (linePtr->numPoints > 2)) { - numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = linePtr->smooth->coordProc(canvas, NULL, + linePtr->numPoints, linePtr->splineSteps, NULL, NULL); if (numPoints <= MAX_STATIC_POINTS) { linePoints = staticSpace; } else { @@ -1348,8 +1365,7 @@ LineToPoint(canvas, itemPtr, pointPtr) (2*numPoints*sizeof(double))); } numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - linePoints); + linePtr->numPoints, linePtr->splineSteps, NULL, linePoints); } else { numPoints = linePtr->numPoints; linePoints = linePtr->coordPtr; @@ -1362,26 +1378,25 @@ LineToPoint(canvas, itemPtr, pointPtr) if (!numPoints || itemPtr->state==TK_STATE_HIDDEN) { return bestDist; } else if (numPoints == 1) { - bestDist = hypot(linePoints[0] - pointPtr[0], linePoints[1] - pointPtr[1]) - - width/2.0; + bestDist = hypot(linePoints[0]-pointPtr[0], linePoints[1]-pointPtr[1]) + - width/2.0; if (bestDist < 0) bestDist = 0; return bestDist; } /* - * The overall idea is to iterate through all of the edges of - * the line, computing a polygon for each edge and testing the - * point against that polygon. In addition, there are additional - * tests to deal with rounded joints and caps. + * The overall idea is to iterate through all of the edges of the line, + * computing a polygon for each edge and testing the point against that + * polygon. In addition, there are additional tests to deal with rounded + * joints and caps. */ changedMiterToBevel = 0; for (count = numPoints, coordPtr = linePoints; count >= 2; count--, coordPtr += 2) { - /* - * If rounding is done around the first point then compute - * the distance between the point and the point. + * If rounding is done around the first point then compute the + * distance between the point and the point. */ if (((linePtr->capStyle == CapRound) && (count == numPoints)) @@ -1398,9 +1413,9 @@ LineToPoint(canvas, itemPtr, pointPtr) } /* - * Compute the polygonal shape corresponding to this edge, - * consisting of two points for the first point of the edge - * and two points for the last point of the edge. + * Compute the polygonal shape corresponding to this edge, consisting + * of two points for the first point of the edge and two points for + * the last point of the edge. */ if (count == numPoints) { @@ -1412,14 +1427,13 @@ LineToPoint(canvas, itemPtr, pointPtr) poly[2] = poly[4]; poly[3] = poly[5]; } else { - TkGetButtPoints(coordPtr+2, coordPtr, width, 0, - poly, poly+2); + TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2); /* - * If this line uses beveled joints, then check the distance - * to a polygon comprising the last two points of the previous - * polygon and the first two from this polygon; this checks - * the wedges that fill the mitered joint. + * If this line uses beveled joints, then check the distance to a + * polygon comprising the last two points of the previous polygon + * and the first two from this polygon; this checks the wedges + * that fill the mitered joint. */ if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) { @@ -1442,8 +1456,8 @@ LineToPoint(canvas, itemPtr, pointPtr) if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width, poly+4, poly+6) == 0) { changedMiterToBevel = 1; - TkGetButtPoints(coordPtr, coordPtr+2, width, - 0, poly+4, poly+6); + TkGetButtPoints(coordPtr, coordPtr+2, width, 0, + poly+4, poly+6); } } else { TkGetButtPoints(coordPtr, coordPtr+2, width, 0, @@ -1461,8 +1475,8 @@ LineToPoint(canvas, itemPtr, pointPtr) } /* - * If caps are rounded, check the distance to the cap around the - * final end point of the line. + * If caps are rounded, check the distance to the cap around the final end + * point of the line. */ if (linePtr->capStyle == CapRound) { @@ -1503,7 +1517,7 @@ LineToPoint(canvas, itemPtr, pointPtr) } } - done: + done: if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) { ckfree((char *) linePoints); } @@ -1515,14 +1529,12 @@ LineToPoint(canvas, itemPtr, pointPtr) * * LineToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangular area. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangular area. * * Results: - * -1 is returned if the item is entirely outside the - * area, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area, 0 if it + * overlaps, and 1 if it is entirely inside the given area. * * Side effects: * None. @@ -1532,10 +1544,10 @@ LineToPoint(canvas, itemPtr, pointPtr) /* ARGSUSED */ static int -LineToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against line. */ - double *rectPtr; +LineToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against line. */ + double *rectPtr) { LineItem *linePtr = (LineItem *) itemPtr; double staticSpace[2*MAX_STATIC_POINTS]; @@ -1564,6 +1576,7 @@ LineToArea(canvas, itemPtr, rectPtr) return -1; } else if (linePtr->numPoints == 1) { double oval[4]; + oval[0] = linePtr->coordPtr[0]-radius; oval[1] = linePtr->coordPtr[1]-radius; oval[2] = linePtr->coordPtr[0]+radius; @@ -1572,14 +1585,13 @@ LineToArea(canvas, itemPtr, rectPtr) } /* - * Handle smoothed lines by generating an expanded set of points - * against which to do the check. + * Handle smoothed lines by generating an expanded set of points against + * which to do the check. */ if ((linePtr->smooth) && (linePtr->numPoints > 2)) { - numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = linePtr->smooth->coordProc(canvas, NULL, + linePtr->numPoints, linePtr->splineSteps, NULL, NULL); if (numPoints <= MAX_STATIC_POINTS) { linePoints = staticSpace; } else { @@ -1587,8 +1599,7 @@ LineToArea(canvas, itemPtr, rectPtr) (2*numPoints*sizeof(double))); } numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - linePoints); + linePtr->numPoints, linePtr->splineSteps, NULL, linePoints); } else { numPoints = linePtr->numPoints; linePoints = linePtr->coordPtr; @@ -1602,7 +1613,7 @@ LineToArea(canvas, itemPtr, rectPtr) width = 1.0; } - result = TkThickPolyLineToArea(linePoints, numPoints, + result = TkThickPolyLineToArea(linePoints, numPoints, width, linePtr->capStyle, linePtr->joinStyle, rectPtr); if (result == 0) { @@ -1630,7 +1641,7 @@ LineToArea(canvas, itemPtr, rectPtr) } } - done: + done: if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) { ckfree((char *) linePoints); } @@ -1642,15 +1653,14 @@ LineToArea(canvas, itemPtr, rectPtr) * * ScaleLine -- * - * This procedure is invoked to rescale a line item. + * This function is invoked to rescale a line item. * * Results: * None. * * Side effects: - * The line referred to by itemPtr is rescaled so that the - * following transformation is applied to all point - * coordinates: + * The line referred to by itemPtr is rescaled so that the following + * transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -1658,20 +1668,21 @@ LineToArea(canvas, itemPtr, rectPtr) */ static void -ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing line. */ - Tk_Item *itemPtr; /* Line to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleLine( + Tk_Canvas canvas, /* Canvas containing line. */ + Tk_Item *itemPtr, /* Line to be scaled. */ + double originX, double originY, + /* Origin about which to scale rect. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { LineItem *linePtr = (LineItem *) itemPtr; double *coordPtr; int i; /* - * Delete any arrowheads before scaling all the points (so that - * the end-points of the line get restored). + * Delete any arrowheads before scaling all the points (so that the + * end-points of the line get restored). */ if (linePtr->firstArrowPtr != NULL) { @@ -1705,14 +1716,13 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY) * * GetLineIndex -- * - * Parse an index into a line item and return either its value - * or an error. + * Parse an index into a line item and return either its value or an + * error. * * Results: - * A standard Tcl result. If all went well, then *indexPtr is - * filled in with the index (into itemPtr) corresponding to - * string. Otherwise an error message is left in - * interp->result. + * A standard Tcl result. If all went well, then *indexPtr is filled in + * with the index (into itemPtr) corresponding to string. Otherwise an + * error message is left in interp->result. * * Side effects: * None. @@ -1721,14 +1731,14 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY) */ static int -GetLineIndex(interp, canvas, itemPtr, obj, indexPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item for which the index is being +GetLineIndex( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item for which the index is being * specified. */ - Tcl_Obj *obj; /* Specification of a particular coord - * in itemPtr's line. */ - int *indexPtr; /* Where to store converted index. */ + Tcl_Obj *obj, /* Specification of a particular coord in + * itemPtr's line. */ + int *indexPtr) /* Where to store converted index. */ { LineItem *linePtr = (LineItem *) itemPtr; int length; @@ -1738,16 +1748,14 @@ GetLineIndex(interp, canvas, itemPtr, obj, indexPtr) if (strncmp(string, "end", (unsigned) length) == 0) { *indexPtr = 2*linePtr->numPoints; } else { - badIndex: - /* - * Some of the paths here leave messages in interp->result, - * so we have to clear it out before storing our own message. + * Some of the paths here leave messages in interp->result, so we + * have to clear it out before storing our own message. */ - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); - Tcl_AppendResult(interp, "bad index \"", string, "\"", - (char *) NULL); + badIndex: + Tcl_SetResult(interp, NULL, TCL_STATIC); + Tcl_AppendResult(interp, "bad index \"", string, "\"", NULL); return TCL_ERROR; } } else if (string[0] == '@') { @@ -1780,7 +1788,7 @@ GetLineIndex(interp, canvas, itemPtr, obj, indexPtr) if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) { goto badIndex; } - *indexPtr &= -2; /* if index is odd, make it even */ + *indexPtr &= -2; /* if index is odd, make it even */ if (*indexPtr < 0){ *indexPtr = 0; } else if (*indexPtr > (2*linePtr->numPoints)) { @@ -1795,25 +1803,24 @@ GetLineIndex(interp, canvas, itemPtr, obj, indexPtr) * * TranslateLine -- * - * This procedure is called to move a line by a given amount. + * This function is called to move a line by a given amount. * * Results: * None. * * Side effects: - * The position of the line is offset by (xDelta, yDelta), and - * the bounding box is updated in the generic part of the item - * structure. + * The position of the line is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslateLine(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslateLine( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { LineItem *linePtr = (LineItem *) itemPtr; double *coordPtr; @@ -1846,13 +1853,13 @@ TranslateLine(canvas, itemPtr, deltaX, deltaY) * * ParseArrowShape -- * - * This procedure is called back during option parsing to - * parse arrow shape information. + * This function is called back during option parsing to parse arrow + * shape information. * * Results: - * The return value is a standard Tcl result: TCL_OK means - * that the arrow shape information was parsed ok, and - * TCL_ERROR means it couldn't be parsed. + * The return value is a standard Tcl result: TCL_OK means that the arrow + * shape information was parsed ok, and TCL_ERROR means it couldn't be + * parsed. * * Side effects: * Arrow information in recordPtr is updated. @@ -1862,14 +1869,14 @@ TranslateLine(canvas, itemPtr, deltaX, deltaY) /* ARGSUSED */ static int -ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset) - ClientData clientData; /* Not used. */ - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Window tkwin; /* Not used. */ - CONST char *value; /* Textual specification of arrow shape. */ - char *recordPtr; /* Pointer to item record in which to - * store arrow information. */ - int offset; /* Offset of shape information in widget +ParseArrowShape( + ClientData clientData, /* Not used. */ + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Window tkwin, /* Not used. */ + CONST char *value, /* Textual specification of arrow shape. */ + char *recordPtr, /* Pointer to item record in which to store + * arrow information. */ + int offset) /* Offset of shape information in widget * record. */ { LineItem *linePtr = (LineItem *) recordPtr; @@ -1878,14 +1885,14 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset) CONST char **argv = NULL; if (offset != Tk_Offset(LineItem, arrowShapeA)) { - panic("ParseArrowShape received bogus offset"); + Tcl_Panic("ParseArrowShape received bogus offset"); } if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) { syntaxError: Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad arrow shape \"", value, - "\": must be list with three numbers", (char *) NULL); + "\": must be list with three numbers", NULL); if (argv != NULL) { ckfree((char *) argv); } @@ -1913,8 +1920,8 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset) * * PrintArrowShape -- * - * This procedure is a callback invoked by the configuration - * code to return a printable value describing an arrow shape. + * This function is a callback invoked by the configuration code to + * return a printable value describing an arrow shape. * * Results: * None. @@ -1927,14 +1934,14 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset) /* ARGSUSED */ static char * -PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr) - ClientData clientData; /* Not used. */ - Tk_Window tkwin; /* Window associated with linePtr's widget. */ - char *recordPtr; /* Pointer to item record containing current +PrintArrowShape( + ClientData clientData, /* Not used. */ + Tk_Window tkwin, /* Window associated with linePtr's widget. */ + char *recordPtr, /* Pointer to item record containing current * shape information. */ - int offset; /* Offset of arrow information in record. */ - Tcl_FreeProc **freeProcPtr; /* Store address of procedure to call to - * free string here. */ + int offset, /* Offset of arrow information in record. */ + Tcl_FreeProc **freeProcPtr) /* Store address of function to call to free + * string here. */ { LineItem *linePtr = (LineItem *) recordPtr; char *buffer; @@ -1952,27 +1959,27 @@ PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr) * * ArrowParseProc -- * - * This procedure is invoked during option processing to handle - * the "-arrow" option. + * This function is invoked during option processing to handle the + * "-arrow" option. * * Results: * A standard Tcl return value. * * Side effects: - * The arrow for a given item gets replaced by the arrow - * indicated in the value argument. + * The arrow for a given item gets replaced by the arrow indicated in the + * value argument. * *-------------------------------------------------------------- */ static int -ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* some flags.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ +ArrowParseProc( + ClientData clientData, /* some flags.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + CONST char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item. */ { int c; size_t length; @@ -2004,9 +2011,8 @@ ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset) return TCL_OK; } - Tcl_AppendResult(interp, "bad arrow spec \"", value, - "\": must be none, first, last, or both", - (char *) NULL); + Tcl_AppendResult(interp, "bad arrow spec \"", value, + "\": must be none, first, last, or both", NULL); *arrowPtr = ARROWS_NONE; return TCL_ERROR; } @@ -2016,16 +2022,15 @@ ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset) * * ArrowPrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-arrow" - * configuration option. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-arrow" configuration option. * * Results: - * The return value is a string describing the arrows for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). + * The return value is a string describing the arrows for the item + * referred to by "widgRec". In addition, *freeProcPtr is filled in with + * the address of a function to call to free the result string when it's + * no longer needed (or NULL to indicate that the string doesn't need to + * be freed). * * Side effects: * None. @@ -2034,25 +2039,25 @@ ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset) */ static char * -ArrowPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +ArrowPrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Offset into item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { register Arrows *arrowPtr = (Arrows *) (widgRec + offset); switch (*arrowPtr) { - case ARROWS_FIRST: + case ARROWS_FIRST: return "first"; - case ARROWS_LAST: + case ARROWS_LAST: return "last"; - case ARROWS_BOTH: + case ARROWS_BOTH: return "both"; - default: + default: return "none"; } } @@ -2062,40 +2067,38 @@ ArrowPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) * * ConfigureArrows -- * - * If arrowheads have been requested for a line, this - * procedure makes arrangements for the arrowheads. + * If arrowheads have been requested for a line, this function makes + * arrangements for the arrowheads. * * Results: * Always returns TCL_OK. * * Side effects: - * Information in linePtr is set up for one or two arrowheads. - * the firstArrowPtr and lastArrowPtr polygons are allocated - * and initialized, if need be, and the end points of the line - * are adjusted so that a thick line doesn't stick out past - * the arrowheads. + * Information in linePtr is set up for one or two arrowheads. The + * firstArrowPtr and lastArrowPtr polygons are allocated and initialized, + * if need be, and the end points of the line are adjusted so that a + * thick line doesn't stick out past the arrowheads. * *-------------------------------------------------------------- */ /* ARGSUSED */ static int -ConfigureArrows(canvas, linePtr) - Tk_Canvas canvas; /* Canvas in which arrows will be - * displayed (interp and tkwin - * fields are needed). */ - LineItem *linePtr; /* Item to configure for arrows. */ +ConfigureArrows( + Tk_Canvas canvas, /* Canvas in which arrows will be displayed + * (interp and tkwin fields are needed). */ + LineItem *linePtr) /* Item to configure for arrows. */ { double *poly, *coordPtr; double dx, dy, length, sinTheta, cosTheta, temp; - double fracHeight; /* Line width as fraction of - * arrowhead width. */ - double backup; /* Distance to backup end points - * so the line ends in the middle - * of the arrowhead. */ - double vertX, vertY; /* Position of arrowhead vertex. */ - double shapeA, shapeB, shapeC; /* Adjusted coordinates (see - * explanation below). */ + double fracHeight; /* Line width as fraction of arrowhead + * width. */ + double backup; /* Distance to backup end points so the line + * ends in the middle of the arrowhead. */ + double vertX, vertY; /* Position of arrowhead vertex. */ + double shapeA, shapeB, shapeC; + /* Adjusted coordinates (see explanation + * below). */ double width; Tk_State state = linePtr->header.state; @@ -2119,10 +2122,10 @@ ConfigureArrows(canvas, linePtr) } /* - * The code below makes a tiny increase in the shape parameters - * for the line. This is a bit of a hack, but it seems to result - * in displays that more closely approximate the specified parameters. - * Without the adjustment, the arrows come out smaller than expected. + * The code below makes a tiny increase in the shape parameters for the + * line. This is a bit of a hack, but it seems to result in displays that + * more closely approximate the specified parameters. Without the + * adjustment, the arrows come out smaller than expected. */ shapeA = linePtr->arrowShapeA + 0.001; @@ -2130,9 +2133,9 @@ ConfigureArrows(canvas, linePtr) shapeC = linePtr->arrowShapeC + width/2.0 + 0.001; /* - * If there's an arrowhead on the first point of the line, compute - * its polygon and adjust the first point of the line so that the - * line doesn't stick out past the leading edge of the arrowhead. + * If there's an arrowhead on the first point of the line, compute its + * polygon and adjust the first point of the line so that the line doesn't + * stick out past the leading edge of the arrowhead. */ fracHeight = (width/2.0)/shapeC; @@ -2169,9 +2172,8 @@ ConfigureArrows(canvas, linePtr) poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight); /* - * Polygon done. Now move the first point towards the second so - * that the corners at the end of the line are inside the - * arrowhead. + * Polygon done. Now move the first point towards the second so that + * the corners at the end of the line are inside the arrowhead. */ linePtr->coordPtr[0] = poly[0] - backup*cosTheta; @@ -2186,8 +2188,8 @@ ConfigureArrows(canvas, linePtr) coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2); poly = linePtr->lastArrowPtr; if (poly == NULL) { - poly = (double *) ckalloc((unsigned) - (2*PTS_IN_ARROW*sizeof(double))); + poly = (double *) + ckalloc((unsigned) (2*PTS_IN_ARROW*sizeof(double))); poly[0] = poly[10] = coordPtr[2]; poly[1] = poly[11] = coordPtr[3]; linePtr->lastArrowPtr = poly; @@ -2203,10 +2205,10 @@ ConfigureArrows(canvas, linePtr) } vertX = poly[0] - shapeA*cosTheta; vertY = poly[1] - shapeA*sinTheta; - temp = shapeC*sinTheta; + temp = shapeC * sinTheta; poly[2] = poly[0] - shapeB*cosTheta + temp; poly[8] = poly[2] - 2*temp; - temp = shapeC*cosTheta; + temp = shapeC * cosTheta; poly[3] = poly[1] - shapeB*sinTheta - temp; poly[9] = poly[3] + 2*temp; poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight); @@ -2225,15 +2227,13 @@ ConfigureArrows(canvas, linePtr) * * LineToPostscript -- * - * This procedure is called to generate Postscript for - * line items. + * This function is called to generate Postscript for line items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used - * to be there. If no error occurs, then Postscript for the - * item is appended to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -2242,15 +2242,13 @@ ConfigureArrows(canvas, linePtr) */ static int -LineToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created. */ +LineToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { LineItem *linePtr = (LineItem *) itemPtr; char buffer[64 + TCL_INTEGER_SPACE]; @@ -2299,24 +2297,23 @@ LineToPostscript(interp, canvas, itemPtr, prepass) linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]), width/2.0, width/2.0); Tcl_AppendResult(interp, "matrix currentmatrix\n",buffer, - " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL); - if (Tk_CanvasPsColor(interp, canvas, color) - != TCL_OK) { + " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", NULL); + if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) { return TCL_ERROR; } if (stipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); + Tcl_AppendResult(interp, "clip ", NULL); if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } return TCL_OK; } /* - * Generate a path for the line's center-line (do this differently - * for straight lines and smoothed lines). + * Generate a path for the line's center-line (do this differently for + * straight lines and smoothed lines). */ if ((!linePtr->smooth) || (linePtr->numPoints < 3)) { @@ -2327,29 +2324,27 @@ LineToPostscript(interp, canvas, itemPtr, prepass) linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps); } else { /* - * Special hack: Postscript printers don't appear to be able - * to turn a path drawn with "curveto"s into a clipping path - * without exceeding resource limits, so TkMakeBezierPostscript - * won't work for stippled curves. Instead, generate all of - * the intermediate points here and output them into the - * Postscript file with "lineto"s instead. + * Special hack: Postscript printers don't appear to be able to + * turn a path drawn with "curveto"s into a clipping path without + * exceeding resource limits, so TkMakeBezierPostscript won't work + * for stippled curves. Instead, generate all of the intermediate + * points here and output them into the Postscript file with + * "lineto"s instead. */ double staticPoints[2*MAX_STATIC_POINTS]; double *pointPtr; int numPoints; - numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = linePtr->smooth->coordProc(canvas, NULL, + linePtr->numPoints, linePtr->splineSteps, NULL, NULL); pointPtr = staticPoints; if (numPoints > MAX_STATIC_POINTS) { pointPtr = (double *) ckalloc((unsigned) (numPoints * 2 * sizeof(double))); } numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr, - linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, - pointPtr); + linePtr->numPoints, linePtr->splineSteps, NULL, pointPtr); Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints); if (pointPtr != staticPoints) { ckfree((char *) pointPtr); @@ -2367,17 +2362,16 @@ LineToPostscript(interp, canvas, itemPtr, prepass) } else if (linePtr->capStyle == CapProjecting) { style = "2 setlinecap\n"; } - Tcl_AppendResult(interp, style, (char *) NULL); + Tcl_AppendResult(interp, style, NULL); style = "0 setlinejoin\n"; if (linePtr->joinStyle == JoinRound) { style = "1 setlinejoin\n"; } else if (linePtr->joinStyle == JoinBevel) { style = "2 setlinejoin\n"; } - Tcl_AppendResult(interp, style, (char *) NULL); + Tcl_AppendResult(interp, style, NULL); - if (Tk_CanvasPsOutline(canvas, itemPtr, - &(linePtr->outline)) != TCL_OK) { + if (Tk_CanvasPsOutline(canvas, itemPtr, &(linePtr->outline)) != TCL_OK) { return TCL_ERROR; } @@ -2387,8 +2381,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass) if (linePtr->firstArrowPtr != NULL) { if (stipple != None) { - Tcl_AppendResult(interp, "grestore gsave\n", - (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); } if (ArrowheadPostscript(interp, canvas, linePtr, linePtr->firstArrowPtr) != TCL_OK) { @@ -2397,7 +2390,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass) } if (linePtr->lastArrowPtr != NULL) { if (stipple != None) { - Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); } if (ArrowheadPostscript(interp, canvas, linePtr, linePtr->lastArrowPtr) != TCL_OK) { @@ -2412,15 +2405,14 @@ LineToPostscript(interp, canvas, itemPtr, prepass) * * ArrowheadPostscript -- * - * This procedure is called to generate Postscript for - * an arrowhead for a line item. + * This function is called to generate Postscript for an arrowhead for a + * line item. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used - * to be there. If no error occurs, then Postscript for the - * arrowhead is appended to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the arrowhead is appended to the result. * * Side effects: * None. @@ -2429,14 +2421,13 @@ LineToPostscript(interp, canvas, itemPtr, prepass) */ static int -ArrowheadPostscript(interp, canvas, linePtr, arrowPtr) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - LineItem *linePtr; /* Line item for which Postscript is - * being generated. */ - double *arrowPtr; /* Pointer to first of five points - * describing arrowhead polygon. */ +ArrowheadPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + LineItem *linePtr, /* Line item for which Postscript is being + * generated. */ + double *arrowPtr) /* Pointer to first of five points describing + * arrowhead polygon. */ { Pixmap stipple; Tk_State state = linePtr->header.state; @@ -2458,13 +2449,20 @@ ArrowheadPostscript(interp, canvas, linePtr, arrowPtr) Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW); if (stipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); - if (Tk_CanvasPsStipple(interp, canvas, stipple) - != TCL_OK) { + Tcl_AppendResult(interp, "clip ", NULL); + if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvPoly.c b/generic/tkCanvPoly.c index 3027c88..b86bc63 100644 --- a/generic/tkCanvPoly.c +++ b/generic/tkCanvPoly.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvPoly.c -- * * This file implements polygon items for canvas widgets. @@ -7,13 +7,12 @@ * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Ajuba Solutions. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" /* @@ -22,24 +21,28 @@ typedef struct PolygonItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ Tk_Outline outline; /* Outline structure */ - int numPoints; /* Number of points in polygon. - * Polygon is always closed. */ + int numPoints; /* Number of points in polygon. Polygon is + * always closed. */ int pointsAllocated; /* Number of points for which space is * allocated at *coordPtr. */ - double *coordPtr; /* Pointer to malloc-ed array containing - * x- and y-coords of all points in polygon. + double *coordPtr; /* Pointer to malloc-ed array containing x- + * and y-coords of all points in polygon. * X-coords are even-valued indices, y-coords * are corresponding odd-valued indices. */ int joinStyle; /* Join style for outline */ Tk_TSOffset tsoffset; XColor *fillColor; /* Foreground color for polygon. */ - XColor *activeFillColor; /* Foreground color for polygon if state is active. */ - XColor *disabledFillColor; /* Foreground color for polygon if state is disabled. */ + XColor *activeFillColor; /* Foreground color for polygon if state is + * active. */ + XColor *disabledFillColor; /* Foreground color for polygon if state is + * disabled. */ Pixmap fillStipple; /* Stipple bitmap for filling polygon. */ - Pixmap activeFillStipple; /* Stipple bitmap for filling polygon if state is active. */ - Pixmap disabledFillStipple; /* Stipple bitmap for filling polygon if state is disabled. */ + Pixmap activeFillStipple; /* Stipple bitmap for filling polygon if state + * is active. */ + Pixmap disabledFillStipple; /* Stipple bitmap for filling polygon if state + * is disabled. */ GC fillGC; /* Graphics context for filling polygon. */ Tk_SmoothMethod *smooth; /* Non-zero means draw shape smoothed (i.e. * with Bezier splines). */ @@ -79,125 +82,116 @@ static Tk_CustomOption pixelOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.activeDash), + {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, activeFillColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.activeColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.activeStipple), + {TK_CONFIG_COLOR, "-activefill", NULL, NULL, + NULL, Tk_Offset(PolygonItem, activeFillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.activeColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.activeStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, activeFillStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, + NULL, Tk_Offset(PolygonItem, activeFillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, "0.0", Tk_Offset(PolygonItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.dash), + {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, "0", Tk_Offset(PolygonItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.disabledDash), + {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, disabledFillColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.disabledColor), + {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, + NULL, Tk_Offset(PolygonItem, disabledFillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.disabledColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.disabledStipple), + {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.disabledStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, disabledFillStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, + NULL, Tk_Offset(PolygonItem, disabledFillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL, "0.0", Tk_Offset(PolygonItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-fill", NULL, NULL, "black", Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL, + {TK_CONFIG_JOIN_STYLE, "-joinstyle", NULL, NULL, "round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, "0,0", Tk_Offset(PolygonItem, tsoffset), TK_CONFIG_NULL_OK, &offsetOption}, - {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.color), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-outline", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.color), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL, "0,0", Tk_Offset(PolygonItem, outline.tsoffset), TK_CONFIG_NULL_OK, &offsetOption}, - {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, outline.stipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL, + NULL, Tk_Offset(PolygonItem, outline.stipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-smooth", NULL, NULL, "0", Tk_Offset(PolygonItem, smooth), TK_CONFIG_DONT_SET_DEFAULT, &smoothOption}, - {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-splinesteps", NULL, NULL, "12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, + NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_CUSTOM, "-width", NULL, NULL, "1.0", Tk_Offset(PolygonItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static void ComputePolygonBbox _ANSI_ARGS_((Tk_Canvas canvas, - PolygonItem *polyPtr)); -static int ConfigurePolygon _ANSI_ARGS_((Tcl_Interp *interp, +static void ComputePolygonBbox(Tk_Canvas canvas, + PolygonItem *polyPtr); +static int ConfigurePolygon(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static int CreatePolygon _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[], int flags); +static int CreatePolygon(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeletePolygon _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayPolygon _ANSI_ARGS_((Tk_Canvas canvas, + int objc, Tcl_Obj *CONST objv[]); +static void DeletePolygon(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayPolygon(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static int GetPolygonIndex _ANSI_ARGS_((Tcl_Interp *interp, + int x, int y, int width, int height); +static int GetPolygonIndex(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, - Tcl_Obj *obj, int *indexPtr)); -static int PolygonCoords _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *obj, int *indexPtr); +static int PolygonCoords(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void PolygonDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int first, int last)); -static void PolygonInsert _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj)); -static int PolygonToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static double PolygonToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *pointPtr)); -static int PolygonToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static void ScalePolygon _ANSI_ARGS_((Tk_Canvas canvas, + int objc, Tcl_Obj *CONST objv[]); +static void PolygonDeleteCoords(Tk_Canvas canvas, + Tk_Item *itemPtr, int first, int last); +static void PolygonInsert(Tk_Canvas canvas, + Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj); +static int PolygonToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static double PolygonToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *pointPtr); +static int PolygonToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void ScalePolygon(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslatePolygon _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); + double scaleX, double scaleY); +static void TranslatePolygon(Tk_Canvas canvas, + Tk_Item *itemPtr, double deltaX, double deltaY); /* - * The structures below defines the polygon item type by means - * of procedures that can be invoked by generic item code. + * The structures below defines the polygon item type by means of functions + * that can be invoked by generic item code. */ Tk_ItemType tkPolygonType = { @@ -216,17 +210,17 @@ Tk_ItemType tkPolygonType = { ScalePolygon, /* scaleProc */ TranslatePolygon, /* translateProc */ (Tk_ItemIndexProc *) GetPolygonIndex,/* indexProc */ - (Tk_ItemCursorProc *) NULL, /* icursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ + NULL, /* icursorProc */ + NULL, /* selectionProc */ (Tk_ItemInsertProc *) PolygonInsert,/* insertProc */ PolygonDeleteCoords, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + NULL, /* nextPtr */ }; /* - * The definition below determines how large are static arrays - * used to hold spline points (splines larger than this have to - * have their arrays malloc-ed). + * The definition below determines how large are static arrays used to hold + * spline points (splines larger than this have to have their arrays + * malloc-ed). */ #define MAX_STATIC_POINTS 200 @@ -236,14 +230,12 @@ Tk_ItemType tkPolygonType = { * * CreatePolygon -- * - * This procedure is invoked to create a new polygon item in - * a canvas. + * This function is invoked to create a new polygon item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is - * left uninitialized, so it can be safely freed by the + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the * caller. * * Side effects: @@ -253,24 +245,24 @@ Tk_ItemType tkPolygonType = { */ static int -CreatePolygon(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing polygon. */ +CreatePolygon( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing polygon. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* - * Carry out initialization that is needed in order to clean - * up after errors during the the remainder of this procedure. + * Carry out initialization that is needed in order to clean up after + * errors during the the remainder of this function. */ Tk_CreateOutline(&(polyPtr->outline)); @@ -288,14 +280,14 @@ CreatePolygon(interp, canvas, itemPtr, objc, objv) polyPtr->activeFillStipple = None; polyPtr->disabledFillStipple = None; polyPtr->fillGC = None; - polyPtr->smooth = (Tk_SmoothMethod *) NULL; + polyPtr->smooth = NULL; polyPtr->splineSteps = 12; polyPtr->autoClosed = 0; /* - * Count the number of points and then parse them into a point - * array. Leading arguments are assumed to be points if they - * start with a digit or a minus sign followed by a digit. + * Count the number of points and then parse them into a point array. + * Leading arguments are assumed to be points if they start with a digit + * or a minus sign followed by a digit. */ for (i = 0; i < objc; i++) { @@ -313,7 +305,7 @@ CreatePolygon(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeletePolygon(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -323,9 +315,8 @@ CreatePolygon(interp, canvas, itemPtr, objc, objv) * * PolygonCoords -- * - * This procedure is invoked to process the "coords" widget - * command on polygons. See the user documentation for details - * on what it does. + * This function is invoked to process the "coords" widget command on + * polygons. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -337,25 +328,25 @@ CreatePolygon(interp, canvas, itemPtr, objc, objv) */ static int -PolygonCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +PolygonCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; int i, numPoints; if (objc == 0) { /* - * Print the coords used to create the polygon. If we auto - * closed the polygon then we don't report the last point. + * Print the coords used to create the polygon. If we auto closed the + * polygon then we don't report the last point. */ + Tcl_Obj *subobj, *obj = Tcl_NewObj(); + for (i = 0; i < 2*(polyPtr->numPoints - polyPtr->autoClosed); i++) { subobj = Tcl_NewDoubleObj(polyPtr->coordPtr[i]); Tcl_ListObjAppendElement(interp, obj, subobj); @@ -371,6 +362,7 @@ PolygonCoords(interp, canvas, itemPtr, objc, objv) } if (objc & 1) { char buf[64 + TCL_INTEGER_SPACE]; + sprintf(buf, "wrong # coordinates: expected an even number, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); @@ -383,8 +375,8 @@ PolygonCoords(interp, canvas, itemPtr, objc, objv) } /* - * One extra point gets allocated here, because we always - * add another point to close the polygon. + * One extra point gets allocated here, because we always add + * another point to close the polygon. */ polyPtr->coordPtr = (double *) ckalloc((unsigned) @@ -403,7 +395,7 @@ PolygonCoords(interp, canvas, itemPtr, objc, objv) /* * Close the polygon if it isn't already closed. */ - + if (objc>2 && ((polyPtr->coordPtr[objc-2] != polyPtr->coordPtr[0]) || (polyPtr->coordPtr[objc-1] != polyPtr->coordPtr[1]))) { polyPtr->autoClosed = 1; @@ -421,28 +413,28 @@ PolygonCoords(interp, canvas, itemPtr, objc, objv) * * ConfigurePolygon -- * - * This procedure is invoked to configure various aspects - * of a polygon item such as its background color. + * This function is invoked to configure various aspects of a polygon + * item such as its background color. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: - * Configuration information, such as colors and stipple - * patterns, may be set for itemPtr. + * Configuration information, such as colors and stipple patterns, may be + * set for itemPtr. * *-------------------------------------------------------------- */ static int -ConfigurePolygon(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Polygon item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigurePolygon( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Polygon item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; XGCValues gcValues; @@ -460,8 +452,8 @@ ConfigurePolygon(interp, canvas, itemPtr, objc, objv, flags) } /* - * A few of the options require additional processing, such as - * graphics contexts. + * A few of the options require additional processing, such as graphics + * contexts. */ state = itemPtr->state; @@ -562,8 +554,8 @@ ConfigurePolygon(interp, canvas, itemPtr, objc, objv, flags) * * DeletePolygon -- * - * This procedure is called to clean up the data structure - * associated with a polygon item. + * This function is called to clean up the data structure associated with + * a polygon item. * * Results: * None. @@ -575,11 +567,10 @@ ConfigurePolygon(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeletePolygon(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall canvas widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeletePolygon( + Tk_Canvas canvas, /* Info about overall canvas widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; @@ -615,24 +606,22 @@ DeletePolygon(canvas, itemPtr, display) * * ComputePolygonBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a polygon. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a polygon. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ static void -ComputePolygonBbox(canvas, polyPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - PolygonItem *polyPtr; /* Item whose bbox is to be - * recomputed. */ +ComputePolygonBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + PolygonItem *polyPtr) /* Item whose bbox is to be recomputed. */ { double *coordPtr; int i; @@ -664,12 +653,11 @@ ComputePolygonBbox(canvas, polyPtr) polyPtr->header.y1 = polyPtr->header.y2 = (int) coordPtr[1]; /* - * Compute the bounding box of all the points in the polygon, - * then expand in all directions by the outline's width to take - * care of butting or rounded corners and projecting or - * rounded caps. This expansion is an overestimate (worst-case - * is square root of two over two) but it's simple. Don't do - * anything special for curves. This causes an additional + * Compute the bounding box of all the points in the polygon, then expand + * in all directions by the outline's width to take care of butting or + * rounded corners and projecting or rounded caps. This expansion is an + * overestimate (worst-case is square root of two over two) but it's + * simple. Don't do anything special for curves. This causes an additional * overestimate in the bounding box, but is faster. */ @@ -715,6 +703,7 @@ ComputePolygonBbox(canvas, polyPtr) if (tsoffset) { if (tsoffset->flags & TK_OFFSET_INDEX) { int index = tsoffset->flags & ~TK_OFFSET_INDEX; + if (tsoffset->flags == INT_MAX) { index = (polyPtr->numPoints - 1) * 2; } @@ -750,13 +739,14 @@ ComputePolygonBbox(canvas, polyPtr) /* * For mitered lines, make a second pass through all the points. - * Compute the locations of the two miter vertex points and add - * those into the bounding box. + * Compute the locations of the two miter vertex points and add those + * into the bounding box. */ if (polyPtr->joinStyle == JoinMiter) { double miter[4]; int j; + coordPtr = polyPtr->coordPtr; if (polyPtr->numPoints>3) { if (TkGetMiterPoints(coordPtr+2*(polyPtr->numPoints-2), @@ -767,9 +757,8 @@ ComputePolygonBbox(canvas, polyPtr) } } } - for (i = polyPtr->numPoints ; i >= 3; - i--, coordPtr += 2) { - + for (i = polyPtr->numPoints ; i >= 3; i--, coordPtr += 2) { + if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width, miter, miter+2)) { for (j = 0; j < 4; j += 2) { @@ -781,8 +770,8 @@ ComputePolygonBbox(canvas, polyPtr) } /* - * Add one more pixel of fudge factor just to be safe (e.g. - * X may round differently than we do). + * Add one more pixel of fudge factor just to be safe (e.g. X may round + * differently than we do). */ polyPtr->header.x1 -= 1; @@ -796,34 +785,33 @@ ComputePolygonBbox(canvas, polyPtr) * * TkFillPolygon -- * - * This procedure is invoked to convert a polygon to screen - * coordinates and display it using a particular GC. + * This function is invoked to convert a polygon to screen coordinates + * and display it using a particular GC. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ void -TkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC) - Tk_Canvas canvas; /* Canvas whose coordinate system - * is to be used for drawing. */ - double *coordPtr; /* Array of coordinates for polygon: - * x1, y1, x2, y2, .... */ - int numPoints; /* Twice this many coordinates are - * present at *coordPtr. */ - Display *display; /* Display on which to draw polygon. */ - Drawable drawable; /* Pixmap or window in which to draw - * polygon. */ - GC gc; /* Graphics context for drawing. */ - GC outlineGC; /* If not None, use this to draw an - * outline around the polygon after - * filling it. */ +TkFillPolygon( + Tk_Canvas canvas, /* Canvas whose coordinate system is to be + * used for drawing. */ + double *coordPtr, /* Array of coordinates for polygon: x1, y1, + * x2, y2, .... */ + int numPoints, /* Twice this many coordinates are present at + * *coordPtr. */ + Display *display, /* Display on which to draw polygon. */ + Drawable drawable, /* Pixmap or window in which to draw + * polygon. */ + GC gc, /* Graphics context for drawing. */ + GC outlineGC) /* If not None, use this to draw an outline + * around the polygon after filling it. */ { XPoint staticPoints[MAX_STATIC_POINTS]; XPoint *pointPtr; @@ -831,9 +819,9 @@ TkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC) int i; /* - * Build up an array of points in screen coordinates. Use a - * static array unless the polygon has an enormous number of points; - * in this case, dynamically allocate an array. + * Build up an array of points in screen coordinates. Use a static array + * unless the polygon has an enormous number of points; in this case, + * dynamically allocate an array. */ if (numPoints <= MAX_STATIC_POINTS) { @@ -842,7 +830,7 @@ TkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC) pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint))); } - for (i = 0, pPtr = pointPtr; i < numPoints; i += 1, coordPtr += 2, pPtr++) { + for (i=0, pPtr=pointPtr ; i<numPoints; i+=1, coordPtr+=2, pPtr++) { Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x, &pPtr->y); } @@ -870,28 +858,27 @@ TkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC) * * DisplayPolygon -- * - * This procedure is invoked to draw a polygon item in a given - * drawable. + * This function is invoked to draw a polygon item in a given drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int x, y, width, height; /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayPolygon( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, int width, int height) + /* Describes region of canvas that must be + * redisplayed (not used). */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; Tk_State state = itemPtr->state; @@ -904,7 +891,7 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) return; } - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { @@ -922,16 +909,17 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) stipple = polyPtr->disabledFillStipple; } } + /* - * If we're stippling then modify the stipple offset in the GC. Be - * sure to reset the offset when done, since the GC is supposed to be - * read-only. + * If we're stippling then modify the stipple offset in the GC. Be sure to + * reset the offset when done, since the GC is supposed to be read-only. */ if ((stipple != None) && (polyPtr->fillGC != None)) { Tk_TSOffset *tsoffset = &polyPtr->tsoffset; int w=0; int h=0; int flags = tsoffset->flags; + if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) { Tk_SizeOfBitmap(display, stipple, &w, &h); if (flags & TK_OFFSET_CENTER) { @@ -956,6 +944,7 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) if(polyPtr->numPoints < 3) { short x,y; int intLineWidth = (int) (linewidth + 0.5); + if (intLineWidth < 1) { intLineWidth = 1; } @@ -974,13 +963,12 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) XPoint *pointPtr; /* - * This is a smoothed polygon. Display using a set of generated - * spline points rather than the original points. + * This is a smoothed polygon. Display using a set of generated spline + * points rather than the original points. */ - numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL, - polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = polyPtr->smooth->coordProc(canvas, NULL, + polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL); if (numPoints <= MAX_STATIC_POINTS) { pointPtr = staticPoints; } else { @@ -988,8 +976,7 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) (numPoints * sizeof(XPoint))); } numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr, - polyPtr->numPoints, polyPtr->splineSteps, pointPtr, - (double *) NULL); + polyPtr->numPoints, polyPtr->splineSteps, pointPtr, NULL); if (polyPtr->fillGC != None) { XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr, numPoints, Complex, CoordModeOrigin); @@ -1025,118 +1012,134 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height) */ static void -PolygonInsert(canvas, itemPtr, beforeThis, obj) - Tk_Canvas canvas; /* Canvas containing text item. */ - Tk_Item *itemPtr; /* Line item to be modified. */ - int beforeThis; /* Index before which new coordinates - * are to be inserted. */ - Tcl_Obj *obj; /* New coordinates to be inserted. */ +PolygonInsert( + Tk_Canvas canvas, /* Canvas containing text item. */ + Tk_Item *itemPtr, /* Line item to be modified. */ + int beforeThis, /* Index before which new coordinates are to + * be inserted. */ + Tcl_Obj *obj) /* New coordinates to be inserted. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; int length, objc, i; Tcl_Obj **objv; - double *new; + double *newCoordPtr; Tk_State state = itemPtr->state; if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } - if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &objc, &objv) != TCL_OK) + if (!obj || (Tcl_ListObjGetElements(NULL, obj, &objc, &objv) != TCL_OK) || !objc || objc&1) { return; } length = 2*(polyPtr->numPoints - polyPtr->autoClosed); - while(beforeThis>length) beforeThis-=length; - while(beforeThis<0) beforeThis+=length; - new = (double *) ckalloc((unsigned)(sizeof(double) * (length + 2 + objc))); + while (beforeThis>length) { + beforeThis -= length; + } + while (beforeThis<0) { + beforeThis += length; + } + newCoordPtr = (double *) + ckalloc(sizeof(double) * (unsigned)(length + 2 + objc)); for (i=0; i<beforeThis; i++) { - new[i] = polyPtr->coordPtr[i]; + newCoordPtr[i] = polyPtr->coordPtr[i]; } for (i=0; i<objc; i++) { - if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i], - new+(i+beforeThis))!=TCL_OK) { - ckfree((char *) new); + if (Tcl_GetDoubleFromObj(NULL, objv[i], + &newCoordPtr[i+beforeThis]) != TCL_OK){ + ckfree((char *) newCoordPtr); return; } } - for(i=beforeThis; i<length; i++) { - new[i+objc] = polyPtr->coordPtr[i]; + for (i=beforeThis; i<length; i++) { + newCoordPtr[i+objc] = polyPtr->coordPtr[i]; } - if(polyPtr->coordPtr) ckfree((char *) polyPtr->coordPtr); - length+=objc; - polyPtr->coordPtr = new; + if (polyPtr->coordPtr) { + ckfree((char *) polyPtr->coordPtr); + } + length += objc; + polyPtr->coordPtr = newCoordPtr; polyPtr->numPoints = (length/2) + polyPtr->autoClosed; /* - * Close the polygon if it isn't already closed, or remove autoclosing - * if the user's coordinates are now closed. + * Close the polygon if it isn't already closed, or remove autoclosing if + * the user's coordinates are now closed. */ if (polyPtr->autoClosed) { - if ((new[length-2] == new[0]) && (new[length-1] == new[1])) { + if ((newCoordPtr[length-2] == newCoordPtr[0]) + && (newCoordPtr[length-1] == newCoordPtr[1])) { polyPtr->autoClosed = 0; polyPtr->numPoints--; } - } - else { - if ((new[length-2] != new[0]) || (new[length-1] != new[1])) { + } else { + if ((newCoordPtr[length-2] != newCoordPtr[0]) + || (newCoordPtr[length-1] != newCoordPtr[1])) { polyPtr->autoClosed = 1; polyPtr->numPoints++; } } - new[length] = new[0]; - new[length+1] = new[1]; + newCoordPtr[length] = newCoordPtr[0]; + newCoordPtr[length+1] = newCoordPtr[1]; if (((length-objc)>3) && (state != TK_STATE_HIDDEN)) { /* - * This is some optimizing code that will result that only the part - * of the polygon that changed (and the objects that are overlapping - * with that part) need to be redrawn. A special flag is set that - * instructs the general canvas code not to redraw the whole - * object. If this flag is not set, the canvas will do the redrawing, - * otherwise I have to do it here. + * This is some optimizing code that will result that only the part of + * the polygon that changed (and the objects that are overlapping with + * that part) need to be redrawn. A special flag is set that instructs + * the general canvas code not to redraw the whole object. If this + * flag is not set, the canvas will do the redrawing, otherwise I have + * to do it here. */ + double width; int j; itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW; /* - * The header elements that normally are used for the - * bounding box, are now used to calculate the bounding - * box for only the part that has to be redrawn. That - * doesn't matter, because afterwards the bounding - * box has to be re-calculated anyway. + * The header elements that normally are used for the bounding box, + * are now used to calculate the bounding box for only the part that + * has to be redrawn. That doesn't matter, because afterwards the + * bounding box has to be re-calculated anyway. */ itemPtr->x1 = itemPtr->x2 = (int) polyPtr->coordPtr[beforeThis]; itemPtr->y1 = itemPtr->y2 = (int) polyPtr->coordPtr[beforeThis+1]; beforeThis-=2; objc+=4; - if(polyPtr->smooth) { - beforeThis-=2; objc+=4; - } /* be carefull; beforeThis could now be negative */ - for(i=beforeThis; i<beforeThis+objc; i+=2) { - j=i; - if(j<0) j+=length; - if(j>=length) j-=length; - TkIncludePoint(itemPtr, polyPtr->coordPtr+j); + if (polyPtr->smooth) { + beforeThis-=2; + objc+=4; + } + + /* + * Be careful; beforeThis could now be negative + */ + + for (i=beforeThis; i<beforeThis+objc; i+=2) { + j = i; + if (j<0) { + j += length; + } else if (j>=length) { + j -= length; + } + TkIncludePoint(itemPtr, polyPtr->coordPtr+j); } width = polyPtr->outline.width; if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) { - if (polyPtr->outline.activeWidth>width) { - width = polyPtr->outline.activeWidth; - } + if (polyPtr->outline.activeWidth > width) { + width = polyPtr->outline.activeWidth; + } } else if (state==TK_STATE_DISABLED) { - if (polyPtr->outline.disabledWidth>0.0) { - width = polyPtr->outline.disabledWidth; - } + if (polyPtr->outline.disabledWidth > 0.0) { + width = polyPtr->outline.disabledWidth; + } } itemPtr->x1 -= (int) width; itemPtr->y1 -= (int) width; itemPtr->x2 += (int) width; itemPtr->y2 += (int) width; Tk_CanvasEventuallyRedraw(canvas, - itemPtr->x1, itemPtr->y1, - itemPtr->x2, itemPtr->y2); + itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2); } ComputePolygonBbox(canvas, polyPtr); @@ -1153,37 +1156,47 @@ PolygonInsert(canvas, itemPtr, beforeThis, obj) * None. * * Side effects: - * Characters between "first" and "last", inclusive, get - * deleted from itemPtr. + * Characters between "first" and "last", inclusive, get deleted from + * itemPtr. * *-------------------------------------------------------------- */ static void -PolygonDeleteCoords(canvas, itemPtr, first, last) - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Item in which to delete characters. */ - int first; /* Index of first character to delete. */ - int last; /* Index of last character to delete. */ +PolygonDeleteCoords( + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Item in which to delete characters. */ + int first, /* Index of first character to delete. */ + int last) /* Index of last character to delete. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; int count, i; int length = 2*(polyPtr->numPoints - polyPtr->autoClosed); - while(first>=length) first-=length; - while(first<0) first+=length; - while(last>=length) last-=length; - while(last<0) last+=length; + while (first>=length) { + first -= length; + } + while (first<0) { + first += length; + } + while (last>=length) { + last -= length; + } + while (last<0) { + last += length; + } first &= -2; last &= -2; count = last + 2 - first; - if(count<=0) count +=length; + if (count<=0) { + count += length; + } - if(count >= length) { + if (count >= length) { polyPtr->numPoints = 0; - if(polyPtr->coordPtr != NULL) { + if (polyPtr->coordPtr != NULL) { ckfree((char *) polyPtr->coordPtr); polyPtr->coordPtr = NULL; } @@ -1191,7 +1204,7 @@ PolygonDeleteCoords(canvas, itemPtr, first, last) return; } - if(last>=first) { + if (last>=first) { for(i=last+2; i<length; i++) { polyPtr->coordPtr[i-count] = polyPtr->coordPtr[i]; } @@ -1211,14 +1224,14 @@ PolygonDeleteCoords(canvas, itemPtr, first, last) * * PolygonToPoint -- * - * Computes the distance from a given point to a given - * polygon, in canvas units. + * Computes the distance from a given point to a given polygon, in canvas + * units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are pointPtr[0] and pointPtr[1] is inside the polygon. If the - * point isn't inside the polygon then the return value is the - * distance from the point to the polygon. + * The return value is 0 if the point whose x and y coordinates are + * pointPtr[0] and pointPtr[1] is inside the polygon. If the point isn't + * inside the polygon then the return value is the distance from the + * point to the polygon. * * Side effects: * None. @@ -1228,10 +1241,10 @@ PolygonDeleteCoords(canvas, itemPtr, first, last) /* ARGSUSED */ static double -PolygonToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +PolygonToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr, *polyPoints; @@ -1240,15 +1253,15 @@ PolygonToPoint(canvas, itemPtr, pointPtr) double radius; double bestDist, dist; int numPoints, count; - int changedMiterToBevel; /* Non-zero means that a mitered corner - * had to be treated as beveled after all - * because the angle was < 11 degrees. */ + int changedMiterToBevel; /* Non-zero means that a mitered corner had to + * be treated as beveled after all because the + * angle was < 11 degrees. */ double width; Tk_State state = itemPtr->state; bestDist = 1.0e36; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } width = polyPtr->outline.width; @@ -1269,9 +1282,9 @@ PolygonToPoint(canvas, itemPtr, pointPtr) */ if ((polyPtr->smooth) && (polyPtr->numPoints>2)) { - numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL, - polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = polyPtr->smooth->coordProc(canvas, NULL, + polyPtr->numPoints, polyPtr->splineSteps, NULL, + NULL); if (numPoints <= MAX_STATIC_POINTS) { polyPoints = staticSpace; } else { @@ -1279,7 +1292,7 @@ PolygonToPoint(canvas, itemPtr, pointPtr) (2*numPoints*sizeof(double))); } numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr, - polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, + polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints); } else { numPoints = polyPtr->numPoints; @@ -1300,22 +1313,23 @@ PolygonToPoint(canvas, itemPtr, pointPtr) } } - if ((polyPtr->outline.gc == None) || (width <= 1)) goto donepoint; + if ((polyPtr->outline.gc == None) || (width <= 1)) { + goto donepoint; + } /* - * The overall idea is to iterate through all of the edges of - * the line, computing a polygon for each edge and testing the - * point against that polygon. In addition, there are additional - * tests to deal with rounded joints and caps. + * The overall idea is to iterate through all of the edges of the line, + * computing a polygon for each edge and testing the point against that + * polygon. In addition, there are additional tests to deal with rounded + * joints and caps. */ changedMiterToBevel = 0; for (count = numPoints, coordPtr = polyPoints; count >= 2; count--, coordPtr += 2) { - /* - * If rounding is done around the first point then compute - * the distance between the point and the point. + * If rounding is done around the first point then compute the + * distance between the point and the point. */ if (polyPtr->joinStyle == JoinRound) { @@ -1330,9 +1344,9 @@ PolygonToPoint(canvas, itemPtr, pointPtr) } /* - * Compute the polygonal shape corresponding to this edge, - * consisting of two points for the first point of the edge - * and two points for the last point of the edge. + * Compute the polygonal shape corresponding to this edge, consisting + * of two points for the first point of the edge and two points for + * the last point of the edge. */ if (count == numPoints) { @@ -1348,10 +1362,10 @@ PolygonToPoint(canvas, itemPtr, pointPtr) poly, poly+2); /* - * If this line uses beveled joints, then check the distance - * to a polygon comprising the last two points of the previous - * polygon and the first two from this polygon; this checks - * the wedges that fill the mitered joint. + * If this line uses beveled joints, then check the distance to a + * polygon comprising the last two points of the previous polygon + * and the first two from this polygon; this checks the wedges + * that fill the mitered joint. */ if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) { @@ -1374,8 +1388,8 @@ PolygonToPoint(canvas, itemPtr, pointPtr) if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, (double) width, poly+4, poly+6) == 0) { changedMiterToBevel = 1; - TkGetButtPoints(coordPtr, coordPtr+2, (double) width, - 0, poly+4, poly+6); + TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0, + poly+4, poly+6); } } else { TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0, @@ -1392,7 +1406,7 @@ PolygonToPoint(canvas, itemPtr, pointPtr) } } - donepoint: + donepoint: if ((polyPoints != staticSpace) && polyPoints != polyPtr->coordPtr) { ckfree((char *) polyPoints); } @@ -1404,14 +1418,13 @@ PolygonToPoint(canvas, itemPtr, pointPtr) * * PolygonToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangular area. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangular area. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -1421,12 +1434,12 @@ PolygonToPoint(canvas, itemPtr, pointPtr) /* ARGSUSED */ static int -PolygonToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against polygon. */ - double *rectPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +PolygonToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against polygon. */ + double *rectPtr) /* Pointer to array of four coordinates + * (x1,y1,x2,y2) describing rectangular + * area. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr; @@ -1434,19 +1447,18 @@ PolygonToArea(canvas, itemPtr, rectPtr) double *polyPoints, poly[10]; double radius; int numPoints, count; - int changedMiterToBevel; /* Non-zero means that a mitered corner - * had to be treated as beveled after all - * because the angle was < 11 degrees. */ - int inside; /* Tentative guess about what to return, - * based on all points seen so far: one - * means everything seen so far was - * inside the area; -1 means everything - * was outside the area. 0 means overlap - * has been found. */ + int changedMiterToBevel; /* Non-zero means that a mitered corner had to + * be treated as beveled after all because the + * angle was < 11 degrees. */ + int inside; /* Tentative guess about what to return, based + * on all points seen so far: one means + * everything seen so far was inside the area; + * -1 means everything was outside the area. 0 + * means overlap has been found. */ double width; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -1468,60 +1480,62 @@ PolygonToArea(canvas, itemPtr, rectPtr) return -1; } else if (polyPtr->numPoints <3) { double oval[4]; + oval[0] = polyPtr->coordPtr[0]-radius; oval[1] = polyPtr->coordPtr[1]-radius; oval[2] = polyPtr->coordPtr[0]+radius; oval[3] = polyPtr->coordPtr[1]+radius; return TkOvalToArea(oval, rectPtr); } + /* * Handle smoothed polygons by generating an expanded set of points * against which to do the check. */ if (polyPtr->smooth) { - numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL, - polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, - (double *) NULL); + numPoints = polyPtr->smooth->coordProc(canvas, NULL, + polyPtr->numPoints, polyPtr->splineSteps, NULL, NULL); if (numPoints <= MAX_STATIC_POINTS) { polyPoints = staticSpace; } else { - polyPoints = (double *) ckalloc((unsigned) - (2*numPoints*sizeof(double))); + polyPoints = (double *) + ckalloc((unsigned) (2*numPoints*sizeof(double))); } numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr, - polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, - polyPoints); + polyPtr->numPoints, polyPtr->splineSteps, NULL, polyPoints); } else { numPoints = polyPtr->numPoints; polyPoints = polyPtr->coordPtr; } /* - * Simple test to see if we are in the polygon. Polygons are - * different from othe canvas items in that they register points - * being inside even if it isn't filled. + * Simple test to see if we are in the polygon. Polygons are different + * from othe canvas items in that they register points being inside even + * if it isn't filled. */ + inside = TkPolygonToArea(polyPoints, numPoints, rectPtr); - if (inside==0) goto donearea; + if (inside==0) { + goto donearea; + } - if (polyPtr->outline.gc == None) goto donearea ; + if (polyPtr->outline.gc == None) { + goto donearea; + } /* - * Iterate through all of the edges of the line, computing a polygon - * for each edge and testing the area against that polygon. In - * addition, there are additional tests to deal with rounded joints - * and caps. + * Iterate through all of the edges of the line, computing a polygon for + * each edge and testing the area against that polygon. In addition, there + * are additional tests to deal with rounded joints and caps. */ changedMiterToBevel = 0; for (count = numPoints, coordPtr = polyPoints; count >= 2; count--, coordPtr += 2) { - /* - * If rounding is done around the first point of the edge - * then test a circular region around the point with the - * area. + * If rounding is done around the first point of the edge then test a + * circular region around the point with the area. */ if (polyPtr->joinStyle == JoinRound) { @@ -1536,28 +1550,26 @@ PolygonToArea(canvas, itemPtr, rectPtr) } /* - * Compute the polygonal shape corresponding to this edge, - * consisting of two points for the first point of the edge - * and two points for the last point of the edge. + * Compute the polygonal shape corresponding to this edge, consisting + * of two points for the first point of the edge and two points for + * the last point of the edge. */ if (count == numPoints) { - TkGetButtPoints(coordPtr+2, coordPtr, width, - 0, poly, poly+2); + TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2); } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) { poly[0] = poly[6]; poly[1] = poly[7]; poly[2] = poly[4]; poly[3] = poly[5]; } else { - TkGetButtPoints(coordPtr+2, coordPtr, width, 0, - poly, poly+2); + TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2); /* - * If the last joint was beveled, then also check a - * polygon comprising the last two points of the previous - * polygon and the first two from this polygon; this checks - * the wedges that fill the beveled joint. + * If the last joint was beveled, then also check a polygon + * comprising the last two points of the previous polygon and the + * first two from this polygon; this checks the wedges that fill + * the beveled joint. */ if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) { @@ -1571,18 +1583,15 @@ PolygonToArea(canvas, itemPtr, rectPtr) } } if (count == 2) { - TkGetButtPoints(coordPtr, coordPtr+2, width, - 0, poly+4, poly+6); + TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6); } else if (polyPtr->joinStyle == JoinMiter) { if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, width, poly+4, poly+6) == 0) { changedMiterToBevel = 1; - TkGetButtPoints(coordPtr, coordPtr+2, width, - 0, poly+4, poly+6); + TkGetButtPoints(coordPtr, coordPtr+2, width,0, poly+4, poly+6); } } else { - TkGetButtPoints(coordPtr, coordPtr+2, width, 0, - poly+4, poly+6); + TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6); } poly[8] = poly[0]; poly[9] = poly[1]; @@ -1592,7 +1601,7 @@ PolygonToArea(canvas, itemPtr, rectPtr) } } - donearea: + donearea: if ((polyPoints != staticSpace) && (polyPoints != polyPtr->coordPtr)) { ckfree((char *) polyPoints); } @@ -1604,15 +1613,14 @@ PolygonToArea(canvas, itemPtr, rectPtr) * * ScalePolygon -- * - * This procedure is invoked to rescale a polygon item. + * This function is invoked to rescale a polygon item. * * Results: * None. * * Side effects: - * The polygon referred to by itemPtr is rescaled so that the - * following transformation is applied to all point - * coordinates: + * The polygon referred to by itemPtr is rescaled so that the following + * transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -1620,12 +1628,13 @@ PolygonToArea(canvas, itemPtr, rectPtr) */ static void -ScalePolygon(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing polygon. */ - Tk_Item *itemPtr; /* Polygon to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScalePolygon( + Tk_Canvas canvas, /* Canvas containing polygon. */ + Tk_Item *itemPtr, /* Polygon to be scaled. */ + double originX, double originY, + /* Origin about which to scale rect. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr; @@ -1644,14 +1653,13 @@ ScalePolygon(canvas, itemPtr, originX, originY, scaleX, scaleY) * * GetPolygonIndex -- * - * Parse an index into a polygon item and return either its value - * or an error. + * Parse an index into a polygon item and return either its value or an + * error. * * Results: - * A standard Tcl result. If all went well, then *indexPtr is - * filled in with the index (into itemPtr) corresponding to - * string. Otherwise an error message is left in - * interp->result. + * A standard Tcl result. If all went well, then *indexPtr is filled in + * with the index (into itemPtr) corresponding to string. Otherwise an + * error message is left in interp->result. * * Side effects: * None. @@ -1660,33 +1668,31 @@ ScalePolygon(canvas, itemPtr, originX, originY, scaleX, scaleY) */ static int -GetPolygonIndex(interp, canvas, itemPtr, obj, indexPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item for which the index is being +GetPolygonIndex( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item for which the index is being * specified. */ - Tcl_Obj *obj; /* Specification of a particular coord - * in itemPtr's line. */ - int *indexPtr; /* Where to store converted index. */ + Tcl_Obj *obj, /* Specification of a particular coord in + * itemPtr's line. */ + int *indexPtr) /* Where to store converted index. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; int length; char *string = Tcl_GetStringFromObj(obj, &length); if (string[0] == 'e') { - if (strncmp(string, "end", (unsigned) length) == 0) { + if (strncmp(string, "end", (unsigned)length) == 0) { *indexPtr = 2*(polyPtr->numPoints - polyPtr->autoClosed); } else { - badIndex: - /* - * Some of the paths here leave messages in interp->result, - * so we have to clear it out before storing our own message. + * Some of the paths here leave messages in interp->result, so we + * have to clear it out before storing our own message. */ - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); - Tcl_AppendResult(interp, "bad index \"", string, "\"", - (char *) NULL); + badIndex: + Tcl_SetResult(interp, NULL, TCL_STATIC); + Tcl_AppendResult(interp, "bad index \"", string, "\"", NULL); return TCL_ERROR; } } else if (string[0] == '@') { @@ -1717,6 +1723,7 @@ GetPolygonIndex(interp, canvas, itemPtr, obj, indexPtr) } } else { int count = 2*(polyPtr->numPoints - polyPtr->autoClosed); + if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) { goto badIndex; } @@ -1739,26 +1746,24 @@ GetPolygonIndex(interp, canvas, itemPtr, obj, indexPtr) * * TranslatePolygon -- * - * This procedure is called to move a polygon by a given - * amount. + * This function is called to move a polygon by a given amount. * * Results: * None. * * Side effects: - * The position of the polygon is offset by (xDelta, yDelta), - * and the bounding box is updated in the generic part of the - * item structure. + * The position of the polygon is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslatePolygon(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslatePolygon( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr; @@ -1777,15 +1782,13 @@ TranslatePolygon(canvas, itemPtr, deltaX, deltaY) * * PolygonToPostscript -- * - * This procedure is called to generate Postscript for - * polygon items. + * This function is called to generate Postscript for polygon items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used - * to be there. If no error occurs, then Postscript for the - * item is appended to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -1794,15 +1797,13 @@ TranslatePolygon(canvas, itemPtr, deltaX, deltaY) */ static int -PolygonToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created. */ +PolygonToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { PolygonItem *polyPtr = (PolygonItem *) itemPtr; char *style; @@ -1868,17 +1869,17 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass) polyPtr->coordPtr[0], Tk_CanvasPsY(canvas, polyPtr->coordPtr[1]), width/2.0, width/2.0); Tcl_AppendResult(interp, "matrix currentmatrix\n",string, - " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL); + " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", NULL); if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) { return TCL_ERROR; } if (stipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); + Tcl_AppendResult(interp, "clip ", NULL); if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } return TCL_OK; } @@ -1899,16 +1900,15 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass) return TCL_ERROR; } if (fillStipple != None) { - Tcl_AppendResult(interp, "eoclip ", (char *) NULL); - if (Tk_CanvasPsStipple(interp, canvas, fillStipple) - != TCL_OK) { + Tcl_AppendResult(interp, "eoclip ", NULL); + if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) { return TCL_ERROR; } if (color != NULL) { - Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); } } else { - Tcl_AppendResult(interp, "eofill\n", (char *) NULL); + Tcl_AppendResult(interp, "eofill\n", NULL); } } @@ -1917,13 +1917,12 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass) */ if (color != NULL) { - if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) { Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr, - polyPtr->numPoints); + polyPtr->numPoints); } else { polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr, - polyPtr->numPoints, polyPtr->splineSteps); + polyPtr->numPoints, polyPtr->splineSteps); } if (polyPtr->joinStyle == JoinRound) { @@ -1933,8 +1932,7 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass) } else { style = "0"; } - Tcl_AppendResult(interp, style," setlinejoin 1 setlinecap\n", - (char *) NULL); + Tcl_AppendResult(interp, style," setlinejoin 1 setlinecap\n", NULL); if (Tk_CanvasPsOutline(canvas, itemPtr, &(polyPtr->outline)) != TCL_OK) { return TCL_ERROR; @@ -1942,3 +1940,11 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass) } return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c index 88e106a..ac8f105 100644 --- a/generic/tkCanvPs.c +++ b/generic/tkCanvPs.c @@ -1,28 +1,28 @@ -/* +/* * tkCanvPs.c -- * - * This module provides Postscript output support for canvases, - * including the "postscript" widget command plus a few utility - * procedures used for generating Postscript. + * This module provides Postscript output support for canvases, including + * the "postscript" widget command plus a few utility functions used for + * generating Postscript. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkCanvas.h" -#include "tkPort.h" +#include "tkFont.h" /* * See tkCanvas.h for key data structures used to implement canvases. */ /* - * The following definition is used in generating postscript for images - * and windows. + * The following definition is used in generating postscript for images and + * windows. */ typedef struct TkColormapData { /* Hold color information for a window */ @@ -36,11 +36,12 @@ typedef struct TkColormapData { /* Hold color information for a window */ /* * One of the following structures is created to keep track of Postscript - * output being generated. It consists mostly of information provided on - * the widget command line. + * output being generated. It consists mostly of information provided on the + * widget command line. */ typedef struct TkPostscriptInfo { + Tk_Window tkwin; /* The canvas being printed. */ int x, y, width, height; /* Area to print, in canvas pixel * coordinates. */ int x2, y2; /* x+width and y+height. */ @@ -55,93 +56,90 @@ typedef struct TkPostscriptInfo { double scale; /* Scale factor for conversion: each pixel * maps into this many points. */ Tk_Anchor pageAnchor; /* How to anchor bbox on Postscript page. */ - int rotate; /* Non-zero means output should be rotated - * on page (landscape mode). */ + int rotate; /* Non-zero means output should be rotated on + * page (landscape mode). */ char *fontVar; /* If non-NULL, gives name of global variable * containing font mapping information. * Malloc'ed. */ char *colorVar; /* If non-NULL, give name of global variable * containing color mapping information. * Malloc'ed. */ - char *colorMode; /* Mode for handling colors: "monochrome", + char *colorMode; /* Mode for handling colors: "monochrome", * "gray", or "color". Malloc'ed. */ - int colorLevel; /* Numeric value corresponding to colorMode: - * 0 for mono, 1 for gray, 2 for color. */ + int colorLevel; /* Numeric value corresponding to colorMode: 0 + * for mono, 1 for gray, 2 for color. */ char *fileName; /* Name of file in which to write Postscript; * NULL means return Postscript info as * result. Malloc'ed. */ - char *channelName; /* If -channel is specified, the name of - * the channel to use. */ + char *channelName; /* If -channel is specified, the name of the + * channel to use. */ Tcl_Channel chan; /* Open channel corresponding to fileName. */ Tcl_HashTable fontTable; /* Hash table containing names of all font - * families used in output. The hash table + * families used in output. The hash table * values are not used. */ - int prepass; /* Non-zero means that we're currently in - * the pre-pass that collects font information, - * so the Postscript generated isn't - * relevant. */ - int prolog; /* Non-zero means output should contain - the file prolog.ps in the header. */ + int prepass; /* Non-zero means that we're currently in the + * pre-pass that collects font information, so + * the Postscript generated isn't relevant. */ + int prolog; /* Non-zero means output should contain the + * prolog definitions in the header. */ } TkPostscriptInfo; /* - * The table below provides a template that's used to process arguments - * to the canvas "postscript" command and fill in TkPostscriptInfo - * structures. + * The table below provides a template that's used to process arguments to the + * canvas "postscript" command and fill in TkPostscriptInfo structures. */ static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_STRING, "-colormap", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-colormap", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, colorVar), 0}, - {TK_CONFIG_STRING, "-colormode", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-colormode", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, colorMode), 0}, - {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-file", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, fileName), 0}, - {TK_CONFIG_STRING, "-channel", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-channel", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, channelName), 0}, - {TK_CONFIG_STRING, "-fontmap", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-fontmap", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, fontVar), 0}, - {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-height", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, height), 0}, - {TK_CONFIG_ANCHOR, "-pageanchor", (char *) NULL, (char *) NULL, + {TK_CONFIG_ANCHOR, "-pageanchor", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, pageAnchor), 0}, - {TK_CONFIG_STRING, "-pageheight", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-pageheight", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, pageHeightString), 0}, - {TK_CONFIG_STRING, "-pagewidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-pagewidth", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, pageWidthString), 0}, - {TK_CONFIG_STRING, "-pagex", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-pagex", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, pageXString), 0}, - {TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-pagey", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, pageYString), 0}, - {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL, + {TK_CONFIG_BOOLEAN, "-prolog", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, prolog), 0}, - {TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL, + {TK_CONFIG_BOOLEAN, "-rotate", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, rotate), 0}, - {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-width", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, width), 0}, - {TK_CONFIG_PIXELS, "-x", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-x", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, x), 0}, - {TK_CONFIG_PIXELS, "-y", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-y", NULL, NULL, "", Tk_Offset(TkPostscriptInfo, y), 0}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int GetPostscriptPoints _ANSI_ARGS_((Tcl_Interp *interp, - char *string, double *doublePtr)); +static int GetPostscriptPoints(Tcl_Interp *interp, + char *string, double *doublePtr); /* *-------------------------------------------------------------- * * TkCanvPostscriptCmd -- * - * This procedure is invoked to process the "postscript" options - * of the widget command for canvas widgets. See the user - * documentation for details on what it does. + * This function is invoked to process the "postscript" options of the + * widget command for canvas widgets. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -154,16 +152,15 @@ static int GetPostscriptPoints _ANSI_ARGS_((Tcl_Interp *interp, /* ARGSUSED */ int -TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) - TkCanvas *canvasPtr; /* Information about canvas widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Caller has - * already parsed this command enough - * to know that argv[1] is - * "postscript". */ +TkCanvPostscriptCmd( + TkCanvas *canvasPtr, /* Information about canvas widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. Caller has already parsed + * this command enough to know that argv[1] is + * "postscript". */ { - TkPostscriptInfo psInfo; + TkPostscriptInfo psInfo, *psInfoPtr = &psInfo; Tk_PostscriptInfo oldInfoPtr; int result; Tk_Item *itemPtr; @@ -173,30 +170,28 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) time_t now; size_t length; Tk_Window tkwin = canvasPtr->tkwin; - int deltaX = 0, deltaY = 0; /* Offset of lower-left corner of - * area to be marked up, measured - * in canvas units from the positioning - * point on the page (reflects - * anchor position). Initial values - * needed only to stop compiler - * warnings. */ Tcl_HashSearch search; Tcl_HashEntry *hPtr; Tcl_DString buffer; - char psenccmd[]="::tk::ensure_psenc_is_loaded"; + char psenccmd[] = "::tk::ensure_psenc_is_loaded"; + int deltaX = 0, deltaY = 0; /* Offset of lower-left corner of area to be + * marked up, measured in canvas units from + * the positioning point on the page (reflects + * anchor position). Initial values needed + * only to stop compiler warnings. */ /* - *---------------------------------------------------------------- - * Initialize the data structure describing Postscript generation, - * then process all the arguments to fill the data structure in. - *---------------------------------------------------------------- + * Initialize the data structure describing Postscript generation, then + * process all the arguments to fill the data structure in. */ + result = Tcl_EvalEx(interp,psenccmd,-1,TCL_EVAL_GLOBAL); if (result != TCL_OK) { return result; } oldInfoPtr = canvasPtr->psInfo; - canvasPtr->psInfo = (Tk_PostscriptInfo) &psInfo; + canvasPtr->psInfo = (Tk_PostscriptInfo) psInfoPtr; + psInfo.tkwin = canvasPtr->tkwin; psInfo.x = canvasPtr->xOrigin; psInfo.y = canvasPtr->yOrigin; psInfo.width = -1; @@ -220,9 +215,8 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) psInfo.prepass = 0; psInfo.prolog = 1; Tcl_InitHashTable(&psInfo.fontTable, TCL_STRING_KEYS); - result = Tk_ConfigureWidget(interp, tkwin, - configSpecs, argc-2, argv+2, (char *) &psInfo, - TK_CONFIG_ARGV_ONLY); + result = Tk_ConfigureWidget(interp, tkwin, configSpecs, argc-2, argv+2, + (char *) &psInfo, TK_CONFIG_ARGV_ONLY); if (result != TCL_OK) { goto cleanup; } @@ -265,38 +259,38 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) psInfo.scale /= WidthOfScreen(Tk_Screen(tkwin)); } switch (psInfo.pageAnchor) { - case TK_ANCHOR_NW: - case TK_ANCHOR_W: - case TK_ANCHOR_SW: - deltaX = 0; - break; - case TK_ANCHOR_N: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_S: - deltaX = -psInfo.width/2; - break; - case TK_ANCHOR_NE: - case TK_ANCHOR_E: - case TK_ANCHOR_SE: - deltaX = -psInfo.width; - break; + case TK_ANCHOR_NW: + case TK_ANCHOR_W: + case TK_ANCHOR_SW: + deltaX = 0; + break; + case TK_ANCHOR_N: + case TK_ANCHOR_CENTER: + case TK_ANCHOR_S: + deltaX = -psInfo.width/2; + break; + case TK_ANCHOR_NE: + case TK_ANCHOR_E: + case TK_ANCHOR_SE: + deltaX = -psInfo.width; + break; } switch (psInfo.pageAnchor) { - case TK_ANCHOR_NW: - case TK_ANCHOR_N: - case TK_ANCHOR_NE: - deltaY = - psInfo.height; - break; - case TK_ANCHOR_W: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_E: - deltaY = -psInfo.height/2; - break; - case TK_ANCHOR_SW: - case TK_ANCHOR_S: - case TK_ANCHOR_SE: - deltaY = 0; - break; + case TK_ANCHOR_NW: + case TK_ANCHOR_N: + case TK_ANCHOR_NE: + deltaY = - psInfo.height; + break; + case TK_ANCHOR_W: + case TK_ANCHOR_CENTER: + case TK_ANCHOR_E: + deltaY = -psInfo.height/2; + break; + case TK_ANCHOR_SW: + case TK_ANCHOR_S: + case TK_ANCHOR_SE: + deltaY = 0; + break; } if (psInfo.colorMode == NULL) { @@ -310,22 +304,20 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) } else if (strncmp(psInfo.colorMode, "color", length) == 0) { psInfo.colorLevel = 2; } else { - Tcl_AppendResult(interp, "bad color mode \"", - psInfo.colorMode, "\": must be monochrome, ", - "gray, or color", (char *) NULL); + Tcl_AppendResult(interp, "bad color mode \"", psInfo.colorMode, + "\": must be monochrome, gray, or color", NULL); goto cleanup; } } if (psInfo.fileName != NULL) { - /* * Check that -file and -channel are not both specified. */ if (psInfo.channelName != NULL) { Tcl_AppendResult(interp, "can't specify both -file", - " and -channel", (char *) NULL); + " and -channel", NULL); result = TCL_ERROR; goto cleanup; } @@ -337,11 +329,11 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) if (Tcl_IsSafe(interp)) { Tcl_AppendResult(interp, "can't specify -file in a", - " safe interpreter", (char *) NULL); + " safe interpreter", NULL); result = TCL_ERROR; goto cleanup; } - + p = Tcl_TranslateFileName(interp, psInfo.fileName, &buffer); if (p == NULL) { goto cleanup; @@ -355,35 +347,31 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) if (psInfo.channelName != NULL) { int mode; - + /* - * Check that the channel is found in this interpreter and that it - * is open for writing. + * Check that the channel is found in this interpreter and that it is + * open for writing. */ - psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, - &mode); + psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName, &mode); if (psInfo.chan == (Tcl_Channel) NULL) { result = TCL_ERROR; goto cleanup; } if ((mode & TCL_WRITABLE) == 0) { - Tcl_AppendResult(interp, "channel \"", - psInfo.channelName, "\" wasn't opened for writing", - (char *) NULL); + Tcl_AppendResult(interp, "channel \"", psInfo.channelName, + "\" wasn't opened for writing", NULL); result = TCL_ERROR; goto cleanup; } } - + /* - *-------------------------------------------------------- - * Make a pre-pass over all of the items, generating Postscript - * and then throwing it away. The purpose of this pass is just - * to collect information about all the fonts in use, so that - * we can output font information in the proper form required - * by the Document Structuring Conventions. - *-------------------------------------------------------- + * Make a pre-pass over all of the items, generating Postscript and then + * throwing it away. The purpose of this pass is just to collect + * information about all the fonts in use, so that we can output font + * information in the proper form required by the Document Structuring + * Conventions. */ psInfo.prepass = 1; @@ -401,11 +389,10 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) Tcl_ResetResult(interp); if (result != TCL_OK) { /* - * An error just occurred. Just skip out of this loop. - * There's no need to report the error now; it can be - * reported later (errors can happen later that don't - * happen now, so we still have to check for errors later - * anyway). + * An error just occurred. Just skip out of this loop. There's no + * need to report the error now; it can be reported later (errors + * can happen later that don't happen now, so we still have to + * check for errors later anyway). */ break; } @@ -413,117 +400,109 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) psInfo.prepass = 0; /* - *-------------------------------------------------------- * Generate the header and prolog for the Postscript. - *-------------------------------------------------------- */ if (psInfo.prolog) { - Tcl_AppendResult(interp, "%!PS-Adobe-3.0 EPSF-3.0\n", - "%%Creator: Tk Canvas Widget\n", (char *) NULL); + Tcl_AppendResult(interp, "%!PS-Adobe-3.0 EPSF-3.0\n", + "%%Creator: Tk Canvas Widget\n", NULL); #ifdef HAVE_PW_GECOS - if (!Tcl_IsSafe(interp)) { - struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */ - Tcl_AppendResult(interp, "%%For: ", - (pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n", - (char *) NULL); - endpwent(); - } + if (!Tcl_IsSafe(interp)) { + struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */ + + Tcl_AppendResult(interp, "%%For: ", + (pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n", NULL); + endpwent(); + } #endif /* HAVE_PW_GECOS */ - Tcl_AppendResult(interp, "%%Title: Window ", - Tk_PathName(tkwin), "\n", (char *) NULL); - time(&now); - Tcl_AppendResult(interp, "%%CreationDate: ", - ctime(&now), (char *) NULL); /* INTL: Native. */ - if (!psInfo.rotate) { - sprintf(string, "%d %d %d %d", - (int) (psInfo.pageX + psInfo.scale*deltaX), - (int) (psInfo.pageY + psInfo.scale*deltaY), - (int) (psInfo.pageX + psInfo.scale*(deltaX + psInfo.width) - + 1.0), - (int) (psInfo.pageY + psInfo.scale*(deltaY + psInfo.height) - + 1.0)); - } else { - sprintf(string, "%d %d %d %d", - (int) (psInfo.pageX - psInfo.scale*(deltaY + psInfo.height)), - (int) (psInfo.pageY + psInfo.scale*deltaX), - (int) (psInfo.pageX - psInfo.scale*deltaY + 1.0), - (int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width) - + 1.0)); - } - Tcl_AppendResult(interp, "%%BoundingBox: ", string, - "\n", (char *) NULL); - Tcl_AppendResult(interp, "%%Pages: 1\n", - "%%DocumentData: Clean7Bit\n", (char *) NULL); - Tcl_AppendResult(interp, "%%Orientation: ", - psInfo.rotate ? "Landscape\n" : "Portrait\n", (char *) NULL); - p = "%%DocumentNeededResources: font "; - for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_AppendResult(interp, p, - Tcl_GetHashKey(&psInfo.fontTable, hPtr), - "\n", (char *) NULL); - p = "%%+ font "; - } - Tcl_AppendResult(interp, "%%EndComments\n\n", (char *) NULL); + Tcl_AppendResult(interp, "%%Title: Window ", Tk_PathName(tkwin), "\n", + NULL); + time(&now); + Tcl_AppendResult(interp, "%%CreationDate: ", + ctime(&now), NULL); /* INTL: Native. */ + if (!psInfo.rotate) { + sprintf(string, "%d %d %d %d", + (int) (psInfo.pageX + psInfo.scale*deltaX), + (int) (psInfo.pageY + psInfo.scale*deltaY), + (int) (psInfo.pageX + psInfo.scale*(deltaX + psInfo.width) + + 1.0), + (int) (psInfo.pageY + psInfo.scale*(deltaY + psInfo.height) + + 1.0)); + } else { + sprintf(string, "%d %d %d %d", + (int) (psInfo.pageX - psInfo.scale*(deltaY+psInfo.height)), + (int) (psInfo.pageY + psInfo.scale*deltaX), + (int) (psInfo.pageX - psInfo.scale*deltaY + 1.0), + (int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width) + + 1.0)); + } + Tcl_AppendResult(interp, "%%BoundingBox: ", string, "\n", NULL); + Tcl_AppendResult(interp, "%%Pages: 1\n", + "%%DocumentData: Clean7Bit\n", NULL); + Tcl_AppendResult(interp, "%%Orientation: ", + psInfo.rotate ? "Landscape\n" : "Portrait\n", NULL); + p = "%%DocumentNeededResources: font "; + for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + Tcl_AppendResult(interp, p, + Tcl_GetHashKey(&psInfo.fontTable, hPtr), "\n", NULL); + p = "%%+ font "; + } + Tcl_AppendResult(interp, "%%EndComments\n\n", NULL); - /* - * Insert the prolog - */ - Tcl_AppendResult(interp, Tcl_GetVar(interp,"::tk::ps_preamable", - TCL_GLOBAL_ONLY), (char *) NULL); + /* + * Insert the prolog + */ - if (psInfo.chan != NULL) { - Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); - Tcl_ResetResult(canvasPtr->interp); - } + Tcl_AppendResult(interp, Tcl_GetVar(interp,"::tk::ps_preamable", + TCL_GLOBAL_ONLY), NULL); - /* - *----------------------------------------------------------- - * Document setup: set the color level and include fonts. - *----------------------------------------------------------- - */ + if (psInfo.chan != NULL) { + Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); + Tcl_ResetResult(canvasPtr->interp); + } - sprintf(string, "/CL %d def\n", psInfo.colorLevel); - Tcl_AppendResult(interp, "%%BeginSetup\n", string, - (char *) NULL); - for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_AppendResult(interp, "%%IncludeResource: font ", - Tcl_GetHashKey(&psInfo.fontTable, hPtr), "\n", (char *) NULL); - } - Tcl_AppendResult(interp, "%%EndSetup\n\n", (char *) NULL); + /* + * Document setup: set the color level and include fonts. + */ - /* - *----------------------------------------------------------- - * Page setup: move to page positioning point, rotate if - * needed, set scale factor, offset for proper anchor position, - * and set clip region. - *----------------------------------------------------------- - */ + sprintf(string, "/CL %d def\n", psInfo.colorLevel); + Tcl_AppendResult(interp, "%%BeginSetup\n", string, NULL); + for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + Tcl_AppendResult(interp, "%%IncludeResource: font ", + Tcl_GetHashKey(&psInfo.fontTable, hPtr), "\n", NULL); + } + Tcl_AppendResult(interp, "%%EndSetup\n\n", NULL); - Tcl_AppendResult(interp, "%%Page: 1 1\n", "save\n", - (char *) NULL); - sprintf(string, "%.1f %.1f translate\n", psInfo.pageX, psInfo.pageY); - Tcl_AppendResult(interp, string, (char *) NULL); - if (psInfo.rotate) { - Tcl_AppendResult(interp, "90 rotate\n", (char *) NULL); - } - sprintf(string, "%.4g %.4g scale\n", psInfo.scale, psInfo.scale); - Tcl_AppendResult(interp, string, (char *) NULL); - sprintf(string, "%d %d translate\n", deltaX - psInfo.x, deltaY); - Tcl_AppendResult(interp, string, (char *) NULL); - sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g", - psInfo.x, - Tk_PostscriptY((double) psInfo.y, (Tk_PostscriptInfo) &psInfo), - psInfo.x2, - Tk_PostscriptY((double) psInfo.y, (Tk_PostscriptInfo) &psInfo), - psInfo.x2, - Tk_PostscriptY((double) psInfo.y2, (Tk_PostscriptInfo) &psInfo), - psInfo.x, - Tk_PostscriptY((double) psInfo.y2, (Tk_PostscriptInfo) &psInfo)); - Tcl_AppendResult(interp, string, - " lineto closepath clip newpath\n", (char *) NULL); + /* + * Page setup: move to page positioning point, rotate if needed, set + * scale factor, offset for proper anchor position, and set clip + * region. + */ + + Tcl_AppendResult(interp, "%%Page: 1 1\n", "save\n", NULL); + sprintf(string, "%.1f %.1f translate\n", psInfo.pageX, psInfo.pageY); + Tcl_AppendResult(interp, string, NULL); + if (psInfo.rotate) { + Tcl_AppendResult(interp, "90 rotate\n", NULL); + } + sprintf(string, "%.4g %.4g scale\n", psInfo.scale, psInfo.scale); + Tcl_AppendResult(interp, string, NULL); + sprintf(string, "%d %d translate\n", deltaX - psInfo.x, deltaY); + Tcl_AppendResult(interp, string, NULL); + sprintf(string, + "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g", + psInfo.x, Tk_PostscriptY((double)psInfo.y, + (Tk_PostscriptInfo)psInfoPtr), + psInfo.x2, Tk_PostscriptY((double)psInfo.y, + (Tk_PostscriptInfo)psInfoPtr), + psInfo.x2, Tk_PostscriptY((double)psInfo.y2, + (Tk_PostscriptInfo)psInfoPtr), + psInfo.x, Tk_PostscriptY((double)psInfo.y2, + (Tk_PostscriptInfo)psInfoPtr)); + Tcl_AppendResult(interp, string, + " lineto closepath clip newpath\n", NULL); } if (psInfo.chan != NULL) { Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); @@ -531,10 +510,8 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) } /* - *--------------------------------------------------------------------- * Iterate through all the items, having each relevant one draw itself. * Quit if any of the items returns an error. - *--------------------------------------------------------------------- */ result = TCL_OK; @@ -550,7 +527,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) if (itemPtr->state == TK_STATE_HIDDEN) { continue; } - Tcl_AppendResult(interp, "gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "gsave\n", NULL); result = (*itemPtr->typePtr->postscriptProc)(interp, (Tk_Canvas) canvasPtr, itemPtr, 0); if (result != TCL_OK) { @@ -561,7 +538,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) Tcl_AddErrorInfo(interp, msg); goto cleanup; } - Tcl_AppendResult(interp, "grestore\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore\n", NULL); if (psInfo.chan != NULL) { Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); Tcl_ResetResult(interp); @@ -569,15 +546,13 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) } /* - *--------------------------------------------------------------------- - * Output page-end information, such as commands to print the page - * and document trailer stuff. - *--------------------------------------------------------------------- + * Output page-end information, such as commands to print the page and + * document trailer stuff. */ if (psInfo.prolog) { - Tcl_AppendResult(interp, "restore showpage\n\n", - "%%Trailer\nend\n%%EOF\n", (char *) NULL); + Tcl_AppendResult(interp, "restore showpage\n\n", + "%%Trailer\nend\n%%EOF\n", NULL); } if (psInfo.chan != NULL) { Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1); @@ -588,7 +563,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) * Clean up psInfo to release malloc'ed stuff. */ - cleanup: + cleanup: if (psInfo.pageXString != NULL) { ckfree(psInfo.pageXString); } @@ -629,16 +604,15 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) * * Tk_PostscriptColor -- * - * This procedure is called by individual canvas items when - * they want to set a color value for output. Given information - * about an X color, this procedure will generate Postscript - * commands to set up an appropriate color in Postscript. + * This function is called by individual canvas items when they want to + * set a color value for output. Given information about an X color, this + * function will generate Postscript commands to set up an appropriate + * color in Postscript. * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in the interp's result. - * If no error occurs, then additional Postscript will be - * appended to the interp's result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in the interp's result. If no error occurs, then + * additional Postscript will be appended to the interp's result. * * Side effects: * None. @@ -647,10 +621,10 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv) */ int -Tk_PostscriptColor(interp, psInfo, colorPtr) - Tcl_Interp *interp; - Tk_PostscriptInfo psInfo; /* Postscript info. */ - XColor *colorPtr; /* Information about color. */ +Tk_PostscriptColor( + Tcl_Interp *interp, + Tk_PostscriptInfo psInfo, /* Postscript info. */ + XColor *colorPtr) /* Information about color. */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; int tmp; @@ -662,9 +636,8 @@ Tk_PostscriptColor(interp, psInfo, colorPtr) } /* - * If there is a color map defined, then look up the color's name - * in the map and use the Postscript commands found there, if there - * are any. + * If there is a color map defined, then look up the color's name in the + * map and use the Postscript commands found there, if there are any. */ if (psInfoPtr->colorVar != NULL) { @@ -673,22 +646,21 @@ Tk_PostscriptColor(interp, psInfo, colorPtr) cmdString = Tcl_GetVar2(interp, psInfoPtr->colorVar, Tk_NameOfColor(colorPtr), 0); if (cmdString != NULL) { - Tcl_AppendResult(interp, cmdString, "\n", (char *) NULL); + Tcl_AppendResult(interp, cmdString, "\n", NULL); return TCL_OK; } } /* - * No color map entry for this color. Grab the color's intensities - * and output Postscript commands for them. Special note: X uses - * a range of 0-65535 for intensities, but most displays only use - * a range of 0-255, which maps to (0, 256, 512, ... 65280) in the - * X scale. This means that there's no way to get perfect white, - * since the highest intensity is only 65280 out of 65535. To - * work around this problem, rescale the X intensity to a 0-255 - * scale and use that as the basis for the Postscript colors. This - * scheme still won't work if the display only uses 4 bits per color, - * but most diplays use at least 8 bits. + * No color map entry for this color. Grab the color's intensities and + * output Postscript commands for them. Special note: X uses a range of + * 0-65535 for intensities, but most displays only use a range of 0-255, + * which maps to (0, 256, 512, ... 65280) in the X scale. This means that + * there's no way to get perfect white, since the highest intensity is + * only 65280 out of 65535. To work around this problem, rescale the X + * intensity to a 0-255 scale and use that as the basis for the Postscript + * colors. This scheme still won't work if the display only uses 4 bits + * per color, but most diplays use at least 8 bits. */ tmp = colorPtr->red; @@ -699,7 +671,7 @@ Tk_PostscriptColor(interp, psInfo, colorPtr) blue = ((double) (tmp >> 8))/255.0; sprintf(string, "%.3f %.3f %.3f setrgbcolor AdjustColor\n", red, green, blue); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); return TCL_OK; } @@ -708,88 +680,89 @@ Tk_PostscriptColor(interp, psInfo, colorPtr) * * Tk_PostscriptFont -- * - * This procedure is called by individual canvas items when - * they want to output text. Given information about an X - * font, this procedure will generate Postscript commands - * to set up an appropriate font in Postscript. + * This function is called by individual canvas items when they want to + * output text. Given information about an X font, this function will + * generate Postscript commands to set up an appropriate font in + * Postscript. * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in the interp's result. - * If no error occurs, then additional Postscript will be - * appended to the interp's result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in the interp's result. If no error occurs, then + * additional Postscript will be appended to the interp's result. * * Side effects: - * The Postscript font name is entered into psInfoPtr->fontTable - * if it wasn't already there. + * The Postscript font name is entered into psInfoPtr->fontTable if it + * wasn't already there. * *-------------------------------------------------------------- */ int -Tk_PostscriptFont(interp, psInfo, tkfont) - Tcl_Interp *interp; - Tk_PostscriptInfo psInfo; /* Postscript Info. */ - Tk_Font tkfont; /* Information about font in which text - * is to be printed. */ +Tk_PostscriptFont( + Tcl_Interp *interp, + Tk_PostscriptInfo psInfo, /* Postscript Info. */ + Tk_Font tkfont) /* Information about font in which text is to + * be printed. */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; - char *end; char pointString[TCL_INTEGER_SPACE]; Tcl_DString ds; int i, points; /* - * First, look up the font's name in the font map, if there is one. - * If there is an entry for this font, it consists of a list - * containing font name and size. Use this information. + * First, look up the font's name in the font map, if there is one. If + * there is an entry for this font, it consists of a list containing font + * name and size. Use this information. */ - Tcl_DStringInit(&ds); - if (psInfoPtr->fontVar != NULL) { - CONST char *list; - int argc; + CONST char *name = Tk_NameOfFont(tkfont); + Tcl_Obj **objv; + int objc; double size; - CONST char **argv; - CONST char *name; + Tcl_Obj *list = Tcl_GetVar2Ex(interp, psInfoPtr->fontVar, name, 0); - name = Tk_NameOfFont(tkfont); - list = Tcl_GetVar2(interp, psInfoPtr->fontVar, name, 0); if (list != NULL) { - if (Tcl_SplitList(interp, list, &argc, &argv) != TCL_OK) { - badMapEntry: + CONST char *fontname; + + if (Tcl_ListObjGetElements(interp, list, &objc, &objv) != TCL_OK + || objc != 2 + || Tcl_GetString(objv[0])[0]=='\0' + || Tcl_GetDoubleFromObj(interp, objv[1], &size) != TCL_OK + || size <= 0) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad font map entry for \"", name, - "\": \"", list, "\"", (char *) NULL); + "\": \"", Tcl_GetString(list), "\"", NULL); return TCL_ERROR; } - if (argc != 2) { - goto badMapEntry; - } - size = strtod(argv[1], &end); - if ((size <= 0) || (*end != 0)) { - goto badMapEntry; - } - Tcl_DStringAppend(&ds, argv[0], -1); - points = (int) size; - - ckfree((char *) argv); - goto findfont; + fontname = Tcl_GetString(objv[0]); + sprintf(pointString, "%d", (int)size); + + Tcl_AppendResult(interp, "/", fontname, " findfont ", + pointString, " scalefont ", NULL); + if (strncasecmp(fontname, "Symbol", 7) != 0) { + Tcl_AppendResult(interp, "ISOEncode ", NULL); + } + Tcl_AppendResult(interp, "setfont\n", NULL); + Tcl_CreateHashEntry(&psInfoPtr->fontTable, fontname, &i); + return TCL_OK; } - } + } - points = Tk_PostscriptFontName(tkfont, &ds); + /* + * Nothing in the font map, so fall back to the old guessing technique. + */ - findfont: - sprintf(pointString, "%d", points); + Tcl_DStringInit(&ds); + points = Tk_PostscriptFontName(tkfont, &ds); + sprintf(pointString, "%d", TkFontGetPoints(psInfoPtr->tkwin, points)); Tcl_AppendResult(interp, "/", Tcl_DStringValue(&ds), " findfont ", - pointString, " scalefont ", (char *) NULL); + pointString, " scalefont ", NULL); if (strncasecmp(Tcl_DStringValue(&ds), "Symbol", 7) != 0) { - Tcl_AppendResult(interp, "ISOEncode ", (char *) NULL); + Tcl_AppendResult(interp, "ISOEncode ", NULL); } - Tcl_AppendResult(interp, "setfont\n", (char *) NULL); + Tcl_AppendResult(interp, "setfont\n", NULL); Tcl_CreateHashEntry(&psInfoPtr->fontTable, Tcl_DStringValue(&ds), &i); Tcl_DStringFree(&ds); @@ -801,16 +774,14 @@ Tk_PostscriptFont(interp, psInfo, tkfont) * * Tk_PostscriptBitmap -- * - * This procedure is called to output the contents of a - * sub-region of a bitmap in proper image data format for - * Postscript (i.e. data between angle brackets, one bit - * per pixel). + * This function is called to output the contents of a sub-region of a + * bitmap in proper image data format for Postscript (i.e. data between + * angle brackets, one bit per pixel). * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in the interp's result. - * If no error occurs, then additional Postscript will be - * appended to the interp's result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in the interp's result. If no error occurs, then + * additional Postscript will be appended to the interp's result. * * Side effects: * None. @@ -819,16 +790,14 @@ Tk_PostscriptFont(interp, psInfo, tkfont) */ int -Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, - height) - Tcl_Interp *interp; - Tk_Window tkwin; - Tk_PostscriptInfo psInfo; /* Postscript info. */ - Pixmap bitmap; /* Bitmap for which to generate - * Postscript. */ - int startX, startY; /* Coordinates of upper-left corner - * of rectangular region to output. */ - int width, height; /* Height of rectangular region. */ +Tk_PostscriptBitmap( + Tcl_Interp *interp, + Tk_Window tkwin, + Tk_PostscriptInfo psInfo, /* Postscript info. */ + Pixmap bitmap, /* Bitmap for which to generate Postscript. */ + int startX, int startY, /* Coordinates of upper-left corner of + * rectangular region to output. */ + int width, int height) /* Height of rectangular region. */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; XImage *imagePtr; @@ -845,10 +814,10 @@ Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, /* * The following call should probably be a call to Tk_SizeOfBitmap - * instead, but it seems that we are occasionally invoked by custom - * item types that create their own bitmaps without registering them - * with Tk. XGetGeometry is a bit slower than Tk_SizeOfBitmap, but - * it shouldn't matter here. + * instead, but it seems that we are occasionally invoked by custom item + * types that create their own bitmaps without registering them with Tk. + * XGetGeometry is a bit slower than Tk_SizeOfBitmap, but it shouldn't + * matter here. */ XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot, @@ -856,7 +825,7 @@ Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, (unsigned int *) &totalHeight, &dummyBorderwidth, &dummyDepth); imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0, totalWidth, totalHeight, 1, XYPixmap); - Tcl_AppendResult(interp, "<", (char *) NULL); + Tcl_AppendResult(interp, "<", NULL); mask = 0x80; value = 0; charsInLine = 0; @@ -870,25 +839,25 @@ Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, mask >>= 1; if (mask == 0) { sprintf(string, "%02x", value); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); mask = 0x80; value = 0; charsInLine += 2; if (charsInLine >= 60) { - Tcl_AppendResult(interp, "\n", (char *) NULL); + Tcl_AppendResult(interp, "\n", NULL); charsInLine = 0; } } } if (mask != 0x80) { sprintf(string, "%02x", value); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); mask = 0x80; value = 0; charsInLine += 2; } } - Tcl_AppendResult(interp, ">", (char *) NULL); + Tcl_AppendResult(interp, ">", NULL); XDestroyImage(imagePtr); return TCL_OK; } @@ -898,18 +867,16 @@ Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, * * Tk_PostscriptStipple -- * - * This procedure is called by individual canvas items when - * they have created a path that they'd like to be filled with - * a stipple pattern. Given information about an X bitmap, - * this procedure will generate Postscript commands to fill - * the current clip region using a stipple pattern defined by the - * bitmap. + * This function is called by individual canvas items when they have + * created a path that they'd like to be filled with a stipple pattern. + * Given information about an X bitmap, this function will generate + * Postscript commands to fill the current clip region using a stipple + * pattern defined by the bitmap. * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in the interp's result. - * If no error occurs, then additional Postscript will be - * appended to the interp's result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in the interp's result. If no error occurs, then + * additional Postscript will be appended to the interp's result. * * Side effects: * None. @@ -918,12 +885,12 @@ Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width, */ int -Tk_PostscriptStipple(interp, tkwin, psInfo, bitmap) - Tcl_Interp *interp; - Tk_Window tkwin; - Tk_PostscriptInfo psInfo; /* Interpreter for returning Postscript - * or error message. */ - Pixmap bitmap; /* Bitmap to use for stippling. */ +Tk_PostscriptStipple( + Tcl_Interp *interp, + Tk_Window tkwin, + Tk_PostscriptInfo psInfo, /* Interpreter for returning Postscript or + * error message. */ + Pixmap bitmap) /* Bitmap to use for stippling. */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; int width, height; @@ -938,22 +905,22 @@ Tk_PostscriptStipple(interp, tkwin, psInfo, bitmap) /* * The following call should probably be a call to Tk_SizeOfBitmap - * instead, but it seems that we are occasionally invoked by custom - * item types that create their own bitmaps without registering them - * with Tk. XGetGeometry is a bit slower than Tk_SizeOfBitmap, but - * it shouldn't matter here. + * instead, but it seems that we are occasionally invoked by custom item + * types that create their own bitmaps without registering them with Tk. + * XGetGeometry is a bit slower than Tk_SizeOfBitmap, but it shouldn't + * matter here. */ XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot, (int *) &dummyX, (int *) &dummyY, (unsigned *) &width, (unsigned *) &height, &dummyBorderwidth, &dummyDepth); sprintf(string, "%d %d ", width, height); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); if (Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, 0, 0, width, height) != TCL_OK) { return TCL_ERROR; } - Tcl_AppendResult(interp, " StippleFill\n", (char *) NULL); + Tcl_AppendResult(interp, " StippleFill\n", NULL); return TCL_OK; } @@ -962,12 +929,13 @@ Tk_PostscriptStipple(interp, tkwin, psInfo, bitmap) * * Tk_PostscriptY -- * - * Given a y-coordinate in local coordinates, this procedure - * returns a y-coordinate to use for Postscript output. + * Given a y-coordinate in local coordinates, this function returns a + * y-coordinate to use for Postscript output. Required because canvases + * have their origin in the top-left, but postscript pages have their + * origin in the bottom left. * * Results: - * Returns the Postscript coordinate that corresponds to - * "y". + * Returns the Postscript coordinate that corresponds to "y". * * Side effects: * None. @@ -976,9 +944,9 @@ Tk_PostscriptStipple(interp, tkwin, psInfo, bitmap) */ double -Tk_PostscriptY(y, psInfo) - double y; /* Y-coordinate in canvas coords. */ - Tk_PostscriptInfo psInfo; /* Postscript info */ +Tk_PostscriptY( + double y, /* Y-coordinate in canvas coords. */ + Tk_PostscriptInfo psInfo) /* Postscript info */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; @@ -990,8 +958,8 @@ Tk_PostscriptY(y, psInfo) * * Tk_PostscriptPath -- * - * Given an array of points for a path, generate Postscript - * commands to create the path. + * Given an array of points for a path, generate Postscript commands to + * create the path. * * Results: * Postscript commands get appended to what's in the interp's result. @@ -1003,14 +971,13 @@ Tk_PostscriptY(y, psInfo) */ void -Tk_PostscriptPath(interp, psInfo, coordPtr, numPoints) - Tcl_Interp *interp; - Tk_PostscriptInfo psInfo; /* Canvas on whose behalf Postscript - * is being generated. */ - double *coordPtr; /* Pointer to first in array of - * 2*numPoints coordinates giving - * points for path. */ - int numPoints; /* Number of points at *coordPtr. */ +Tk_PostscriptPath( + Tcl_Interp *interp, + Tk_PostscriptInfo psInfo, /* Canvas on whose behalf Postscript is being + * generated. */ + double *coordPtr, /* Pointer to first in array of 2*numPoints + * coordinates giving points for path. */ + int numPoints) /* Number of points at *coordPtr. */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; char buffer[200]; @@ -1020,12 +987,12 @@ Tk_PostscriptPath(interp, psInfo, coordPtr, numPoints) } sprintf(buffer, "%.15g %.15g moveto\n", coordPtr[0], Tk_PostscriptY(coordPtr[1], psInfo)); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); for (numPoints--, coordPtr += 2; numPoints > 0; numPoints--, coordPtr += 2) { sprintf(buffer, "%.15g %.15g lineto\n", coordPtr[0], Tk_PostscriptY(coordPtr[1], psInfo)); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); } } @@ -1034,15 +1001,14 @@ Tk_PostscriptPath(interp, psInfo, coordPtr, numPoints) * * GetPostscriptPoints -- * - * Given a string, returns the number of Postscript points - * corresponding to that string. + * Given a string, returns the number of Postscript points corresponding + * to that string. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * screen distance is stored at *doublePtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the screen distance is stored + * at *doublePtr; otherwise TCL_ERROR is returned and an error message is + * left in the interp's result. * * Side effects: * None. @@ -1051,44 +1017,41 @@ Tk_PostscriptPath(interp, psInfo, coordPtr, numPoints) */ static int -GetPostscriptPoints(interp, string, doublePtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - char *string; /* String describing a screen distance. */ - double *doublePtr; /* Place to store converted result. */ +GetPostscriptPoints( + Tcl_Interp *interp, /* Use this for error reporting. */ + char *string, /* String describing a screen distance. */ + double *doublePtr) /* Place to store converted result. */ { char *end; double d; d = strtod(string, &end); if (end == string) { - error: - Tcl_AppendResult(interp, "bad distance \"", string, - "\"", (char *) NULL); - return TCL_ERROR; + goto error; } while ((*end != '\0') && isspace(UCHAR(*end))) { end++; } switch (*end) { - case 'c': - d *= 72.0/2.54; - end++; - break; - case 'i': - d *= 72.0; - end++; - break; - case 'm': - d *= 72.0/25.4; - end++; - break; - case 0: - break; - case 'p': - end++; - break; - default: - goto error; + case 'c': + d *= 72.0/2.54; + end++; + break; + case 'i': + d *= 72.0; + end++; + break; + case 'm': + d *= 72.0/25.4; + end++; + break; + case 0: + break; + case 'p': + end++; + break; + default: + goto error; } while ((*end != '\0') && isspace(UCHAR(*end))) { end++; @@ -1098,34 +1061,37 @@ GetPostscriptPoints(interp, string, doublePtr) } *doublePtr = d; return TCL_OK; -} + error: + Tcl_AppendResult(interp, "bad distance \"", string, "\"", NULL); + return TCL_ERROR; +} + /* *-------------------------------------------------------------- * * TkImageGetColor -- * - * This procedure converts a pixel value to three floating - * point numbers, representing the amount of red, green, and - * blue in that pixel on the screen. It makes use of colormap - * data passed as an argument, and should work for all Visual - * types. + * This function converts a pixel value to three floating point numbers, + * representing the amount of red, green, and blue in that pixel on the + * screen. It makes use of colormap data passed as an argument, and + * should work for all Visual types. * - * This implementation is bogus on Windows because the colormap - * data is never filled in. Instead all postscript generated - * data coming through here is expected to be RGB color data. - * To handle lower bit-depth images properly, XQueryColors - * must be implemented for Windows. + * This implementation is bogus on Windows because the colormap data is + * never filled in. Instead all postscript generated data coming through + * here is expected to be RGB color data. To handle lower bit-depth + * images properly, XQueryColors must be implemented for Windows. * * Results: - * Returns red, green, and blue color values in the range - * 0 to 1. There are no error returns. + * Returns red, green, and blue color values in the range 0 to 1. There + * are no error returns. * * Side effects: * None. * *-------------------------------------------------------------- */ + #ifdef WIN32 #include <windows.h> @@ -1134,35 +1100,41 @@ GetPostscriptPoints(interp, string, doublePtr) #define GetRValue(rgb) ((BYTE)(rgb)) #define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8)) #define GetBValue(rgb) ((BYTE)((rgb)>>16)) -*/ -#else + */ + +#else /* !WIN32 */ + #define GetRValue(rgb) ((rgb & cdata->red_mask) >> cdata->red_shift) #define GetGValue(rgb) ((rgb & cdata->green_mask) >> cdata->green_shift) #define GetBValue(rgb) ((rgb & cdata->blue_mask) >> cdata->blue_shift) -#endif + +#endif /* WIN32 */ #if defined(WIN32) || defined(MAC_OSX_TK) static void -TkImageGetColor(cdata, pixel, red, green, blue) - TkColormapData *cdata; /* Colormap data */ - unsigned long pixel; /* Pixel value to look up */ - double *red, *green, *blue; /* Color data to return */ +TkImageGetColor( + TkColormapData *cdata, /* Colormap data */ + unsigned long pixel, /* Pixel value to look up */ + double *red, double *green, double *blue) + /* Color data to return */ { *red = (double) GetRValue(pixel) / 255.0; *green = (double) GetGValue(pixel) / 255.0; *blue = (double) GetBValue(pixel) / 255.0; } -#else +#else /* ! (WIN32 || MAC_OSX_TK) */ static void -TkImageGetColor(cdata, pixel, red, green, blue) - TkColormapData *cdata; /* Colormap data */ - unsigned long pixel; /* Pixel value to look up */ - double *red, *green, *blue; /* Color data to return */ +TkImageGetColor( + TkColormapData *cdata, /* Colormap data */ + unsigned long pixel, /* Pixel value to look up */ + double *red, double *green, double *blue) + /* Color data to return */ { if (cdata->separated) { int r = GetRValue(pixel); int g = GetGValue(pixel); int b = GetBValue(pixel); + *red = cdata->colors[r].red / 65535.0; *green = cdata->colors[g].green / 65535.0; *blue = cdata->colors[b].blue / 65535.0; @@ -1172,24 +1144,22 @@ TkImageGetColor(cdata, pixel, red, green, blue) *blue = cdata->colors[pixel].blue / 65535.0; } } -#endif - +#endif /* WIN32 || MAC_OSX_TK */ + /* *-------------------------------------------------------------- * * TkPostscriptImage -- * - * This procedure is called to output the contents of an - * image in Postscript, using a format appropriate for the - * current color mode (i.e. one bit per pixel in monochrome, - * one byte per pixel in gray, and three bytes per pixel in - * color). + * This function is called to output the contents of an image in + * Postscript, using a format appropriate for the current color mode + * (i.e. one bit per pixel in monochrome, one byte per pixel in gray, and + * three bytes per pixel in color). * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in interp->result. - * If no error occurs, then additional Postscript will be - * appended to interp->result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in interp->result. If no error occurs, then + * additional Postscript will be appended to interp->result. * * Side effects: * None. @@ -1198,13 +1168,13 @@ TkImageGetColor(cdata, pixel, red, green, blue) */ int -TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) - Tcl_Interp *interp; - Tk_Window tkwin; - Tk_PostscriptInfo psInfo; /* postscript info */ - XImage *ximage; /* Image to draw */ - int x, y; /* First pixel to output */ - int width, height; /* Width and height of area */ +TkPostscriptImage( + Tcl_Interp *interp, + Tk_Window tkwin, + Tk_PostscriptInfo psInfo, /* postscript info */ + XImage *ximage, /* Image to draw */ + int x, int y, /* First pixel to output */ + int width, int height) /* Width and height of area */ { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; char buffer[256]; @@ -1225,9 +1195,8 @@ TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) visual = Tk_Visual(tkwin); /* - * Obtain information about the colormap, ie the mapping between - * pixel values and RGB values. The code below should work - * for all Visual types. + * Obtain information about the colormap, ie the mapping between pixel + * values and RGB values. The code below should work for all Visual types. */ ncolors = visual->map_entries; @@ -1242,33 +1211,42 @@ TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) cdata.red_shift = 0; cdata.green_shift = 0; cdata.blue_shift = 0; - while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) + + while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) { cdata.red_shift ++; - while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) + } + while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) { cdata.green_shift ++; - while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) + } + while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) { cdata.blue_shift ++; - for (i = 0; i < ncolors; i ++) + } + + for (i = 0; i < ncolors; i ++) { cdata.colors[i].pixel = - ((i << cdata.red_shift) & cdata.red_mask) | - ((i << cdata.green_shift) & cdata.green_mask) | - ((i << cdata.blue_shift) & cdata.blue_mask); + ((i << cdata.red_shift) & cdata.red_mask) | + ((i << cdata.green_shift) & cdata.green_mask) | + ((i << cdata.blue_shift) & cdata.blue_mask); + } } else { cdata.separated=0; - for (i = 0; i < ncolors; i ++) + for (i = 0; i < ncolors; i ++) { cdata.colors[i].pixel = i; + } } - if (visual->class == StaticGray || visual->class == GrayScale) + + if (visual->class == StaticGray || visual->class == GrayScale) { cdata.color = 0; - else + } else { cdata.color = 1; + } XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors); /* - * Figure out which color level to use (possibly lower than the - * one specified by the user). For example, if the user specifies - * color with monochrome screen, use gray or monochrome mode instead. + * Figure out which color level to use (possibly lower than the one + * specified by the user). For example, if the user specifies color with + * monochrome screen, use gray or monochrome mode instead. */ if (!cdata.color && level == 2) { @@ -1280,15 +1258,15 @@ TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) } /* - * Check that at least one row of the image can be represented - * with a string less than 64 KB long (this is a limit in the - * Postscript interpreter). + * Check that at least one row of the image can be represented with a + * string less than 64 KB long (this is a limit in the Postscript + * interpreter). */ switch (level) { - case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break; - case 1: bytesPerLine = width; maxWidth = 60000; break; - case 2: bytesPerLine = 3 * width; maxWidth = 20000; break; + case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break; + case 1: bytesPerLine = width; maxWidth = 60000; break; + case 2: bytesPerLine = 3 * width; maxWidth = 20000; break; } if (bytesPerLine > 60000) { @@ -1296,7 +1274,7 @@ TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide", maxWidth); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); ckfree((char *) cdata.colors); return TCL_ERROR; } @@ -1306,107 +1284,110 @@ TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) for (band = height-1; band >= 0; band -= maxRows) { int rows = (band >= maxRows) ? maxRows : band + 1; int lineLen = 0; + switch (level) { - case 0: - sprintf(buffer, "%d %d 1 matrix {\n<", width, rows); - Tcl_AppendResult(interp, buffer, (char *) NULL); - break; - case 1: - sprintf(buffer, "%d %d 8 matrix {\n<", width, rows); - Tcl_AppendResult(interp, buffer, (char *) NULL); - break; - case 2: - sprintf(buffer, "%d %d 8 matrix {\n<", - width, rows); - Tcl_AppendResult(interp, buffer, (char *) NULL); - break; + case 0: + sprintf(buffer, "%d %d 1 matrix {\n<", width, rows); + Tcl_AppendResult(interp, buffer, NULL); + break; + case 1: + sprintf(buffer, "%d %d 8 matrix {\n<", width, rows); + Tcl_AppendResult(interp, buffer, NULL); + break; + case 2: + sprintf(buffer, "%d %d 8 matrix {\n<", width, rows); + Tcl_AppendResult(interp, buffer, NULL); + break; } for (yy = band; yy > band - rows; yy--) { switch (level) { - case 0: { - /* - * Generate data for image in monochrome mode. - * No attempt at dithering is made--instead, just - * set a threshold. - */ - unsigned char mask=0x80; - unsigned char data=0x00; - for (xx = x; xx< x+width; xx++) { - TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), - &red, &green, &blue); - if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5) - data |= mask; - mask >>= 1; - if (mask == 0) { - sprintf(buffer, "%02X", data); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 2; - if (lineLen > 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } - mask=0x80; - data=0x00; - } - } - if ((width % 8) != 0) { - sprintf(buffer, "%02X", data); - Tcl_AppendResult(interp, buffer, (char *) NULL); - mask=0x80; - data=0x00; + case 0: { + /* + * Generate data for image in monochrome mode. No attempt at + * dithering is made--instead, just set a threshold. + */ + + unsigned char mask = 0x80; + unsigned char data = 0x00; + + for (xx = x; xx< x+width; xx++) { + TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), + &red, &green, &blue); + if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5) { + data |= mask; } - break; - } - case 1: { - /* - * Generate data in gray mode--in this case, take a - * weighted sum of the red, green, and blue values. - */ - for (xx = x; xx < x+width; xx ++) { - TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), - &red, &green, &blue); - sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 * - (0.30 * red + 0.59 * green + 0.11 * blue))); - Tcl_AppendResult(interp, buffer, (char *) NULL); + mask >>= 1; + if (mask == 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, NULL); lineLen += 2; if (lineLen > 60) { lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); + Tcl_AppendResult(interp, "\n", NULL); } + mask=0x80; + data=0x00; } - break; } - case 2: { - /* - * Finally, color mode. Here, just output the red, green, - * and blue values directly. - */ - for (xx = x; xx < x+width; xx++) { - TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), - &red, &green, &blue); - sprintf(buffer, "%02X%02X%02X", - (int) floor(0.5 + 255.0 * red), - (int) floor(0.5 + 255.0 * green), - (int) floor(0.5 + 255.0 * blue)); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 6; - if (lineLen > 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } + if ((width % 8) != 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, NULL); + mask=0x80; + data=0x00; + } + break; + } + case 1: + /* + * Generate data in gray mode; in this case, take a weighted + * sum of the red, green, and blue values. + */ + + for (xx = x; xx < x+width; xx ++) { + TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), + &red, &green, &blue); + sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 * + (0.30 * red + 0.59 * green + 0.11 * blue))); + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 2; + if (lineLen > 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); + } + } + break; + case 2: + /* + * Finally, color mode. Here, just output the red, green, and + * blue values directly. + */ + + for (xx = x; xx < x+width; xx++) { + TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy), + &red, &green, &blue); + sprintf(buffer, "%02X%02X%02X", + (int) floor(0.5 + 255.0 * red), + (int) floor(0.5 + 255.0 * green), + (int) floor(0.5 + 255.0 * blue)); + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 6; + if (lineLen > 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); } - break; } + break; } } switch (level) { - case 0: sprintf(buffer, ">\n} image\n"); break; - case 1: sprintf(buffer, ">\n} image\n"); break; - case 2: sprintf(buffer, ">\n} false 3 colorimage\n"); break; + case 0: case 1: + sprintf(buffer, ">\n} image\n"); break; + case 2: + sprintf(buffer, ">\n} false 3 colorimage\n"); break; } - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); sprintf(buffer, "0 %d translate\n", rows); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); } ckfree((char *) cdata.colors); return TCL_OK; @@ -1417,28 +1398,28 @@ TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height) * * Tk_PostscriptPhoto -- * - * This procedure is called to output the contents of a - * photo image in Postscript, using a format appropriate for - * the requested postscript color mode (i.e. one byte per pixel - * in gray, and three bytes per pixel in color). + * This function is called to output the contents of a photo image in + * Postscript, using a format appropriate for the requested postscript + * color mode (i.e. one byte per pixel in gray, and three bytes per pixel + * in color). * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in interp->result. - * If no error occurs, then additional Postscript will be - * appended to the interpreter's result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in interp->result. If no error occurs, then + * additional Postscript will be appended to the interpreter's result. * * Side effects: * None. * *-------------------------------------------------------------- */ + int -Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height) - Tcl_Interp *interp; - Tk_PhotoImageBlock *blockPtr; - Tk_PostscriptInfo psInfo; - int width, height; +Tk_PostscriptPhoto( + Tcl_Interp *interp, + Tk_PhotoImageBlock *blockPtr, + Tk_PostscriptInfo psInfo, + int width, int height) { TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo; int colorLevel = psInfoPtr->colorLevel; @@ -1462,20 +1443,20 @@ Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height) } /* - * Define the "TkPhoto" function, which is a modified version - * of the original "transparentimage" function posted - * by ian@five-d.com (Ian Kemmish) to comp.lang.postscript. - * For a monochrome colorLevel this is a slightly different - * version that uses the imagemask command instead of image. + * Define the "TkPhoto" function, which is a modified version of the + * original "transparentimage" function posted by ian@five-d.com (Ian + * Kemmish) to comp.lang.postscript. For a monochrome colorLevel this is a + * slightly different version that uses the imagemask command instead of + * image. */ - if( !codeIncluded && (colorLevel != 0) ) { + if (!codeIncluded && (colorLevel != 0)) { /* * Color and gray-scale code. */ codeIncluded = !0; - Tcl_AppendResult( interp, + Tcl_AppendResult(interp, "/TkPhoto { \n", " gsave \n", " 32 dict begin \n", @@ -1544,14 +1525,14 @@ Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height) " } for \n", " end \n", " grestore \n", - "} bind def \n\n\n", (char *) NULL); - } else if( !codeIncluded && (colorLevel == 0) ) { + "} bind def \n\n\n", NULL); + } else if (!codeIncluded && (colorLevel == 0)) { /* * Monochrome-only code */ codeIncluded = !0; - Tcl_AppendResult( interp, + Tcl_AppendResult(interp, "/TkPhoto { \n", " gsave \n", " 32 dict begin \n", @@ -1588,27 +1569,26 @@ Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height) " } for \n", " end \n", " grestore \n", - "} bind def \n\n\n", (char *) NULL); + "} bind def \n\n\n", NULL); } /* - * Check that at least one row of the image can be represented - * with a string less than 64 KB long (this is a limit in the - * Postscript interpreter). + * Check that at least one row of the image can be represented with a + * string less than 64 KB long (this is a limit in the Postscript + * interpreter). */ - switch (colorLevel) - { - case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break; - case 1: bytesPerLine = width; maxWidth = 60000; break; - case 2: bytesPerLine = 3 * width; maxWidth = 20000; break; - } + switch (colorLevel) { + case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break; + case 1: bytesPerLine = width; maxWidth = 60000; break; + case 2: bytesPerLine = 3 * width; maxWidth = 20000; break; + } if (bytesPerLine > 60000) { Tcl_ResetResult(interp); sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide", maxWidth); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); return TCL_ERROR; } @@ -1617,45 +1597,37 @@ Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height) */ switch (colorLevel) { - case 0: - strcpy( cspace, "/DeviceGray"); - strcpy( decode, "[1 0]"); - bpc = 1; - break; - case 1: - strcpy( cspace, "/DeviceGray"); - strcpy( decode, "[0 1]"); - bpc = 8; - break; - default: - strcpy( cspace, "/DeviceRGB"); - strcpy( decode, "[0 1 0 1 0 1]"); - bpc = 8; - break; + case 0: + strcpy(cspace, "/DeviceGray"); + strcpy(decode, "[1 0]"); + bpc = 1; + break; + case 1: + strcpy(cspace, "/DeviceGray"); + strcpy(decode, "[0 1]"); + bpc = 8; + break; + default: + strcpy(cspace, "/DeviceRGB"); + strcpy(decode, "[0 1 0 1 0 1]"); + bpc = 8; + break; } - Tcl_AppendResult(interp, - cspace, " setcolorspace\n\n", (char *) NULL); + Tcl_AppendResult(interp, cspace, " setcolorspace\n\n", NULL); - sprintf(buffer, - " /Width %d\n /Height %d\n /BitsPerComponent %d\n", + sprintf(buffer, " /Width %d\n /Height %d\n /BitsPerComponent %d\n", width, height, bpc); - Tcl_AppendResult(interp, - "<<\n /ImageType 1\n", buffer, - " /DataSource currentfile", - " /ASCIIHexDecode filter\n", (char *) NULL); - - - sprintf(buffer, - " /ImageMatrix [1 0 0 -1 0 %d]\n", height); - Tcl_AppendResult(interp, buffer, - " /Decode ", decode, "\n>>\n1 TkPhoto\n", (char *) NULL); + Tcl_AppendResult(interp, "<<\n /ImageType 1\n", buffer, + " /DataSource currentfile /ASCIIHexDecode filter\n", NULL); + sprintf(buffer, " /ImageMatrix [1 0 0 -1 0 %d]\n", height); + Tcl_AppendResult(interp, buffer, " /Decode ", decode, + "\n>>\n1 TkPhoto\n", NULL); /* - * Check the PhotoImageBlock information. - * We assume that: + * Check the PhotoImageBlock information. We assume that: * if pixelSize is 1,2 or 4, the image is R,G,B,A; * if pixelSize is 3, the image is R,G,B and offset[3] is bogus. */ @@ -1678,198 +1650,192 @@ Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height) alphaOffset = blockPtr->offset[3]; } - for (yy = 0, lineLen=0; yy < height; yy++) { switch (colorLevel) { - case 0: { - /* - * Generate data for image in monochrome mode. - * No attempt at dithering is made--instead, just - * set a threshold. - * To handle transparecies we need to output two lines: - * one for the black pixels, one for the white ones. - */ + case 0: { + /* + * Generate data for image in monochrome mode. No attempt at + * dithering is made--instead, just set a threshold. To handle + * transparecies we need to output two lines: one for the black + * pixels, one for the white ones. + */ - unsigned char mask=0x80; - unsigned char data=0x00; - for (xx = 0; xx< width; xx ++) { - pixelPtr = blockPtr->pixelPtr - + (yy * blockPtr->pitch) + unsigned char mask = 0x80; + unsigned char data = 0x00; + + for (xx = 0; xx< width; xx ++) { + pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize); - red = pixelPtr[blockPtr->offset[0]]; - green = pixelPtr[blockPtr->offset[1]]; - blue = pixelPtr[blockPtr->offset[2]]; + red = pixelPtr[blockPtr->offset[0]]; + green = pixelPtr[blockPtr->offset[1]]; + blue = pixelPtr[blockPtr->offset[2]]; - alpha = *(alphaPtr + (yy * alphaPitch) - + (xx * alphaIncr) + alphaOffset); + alpha = *(alphaPtr + (yy * alphaPitch) + + (xx * alphaIncr) + alphaOffset); - /* - * If pixel is less than threshold, then it is black. - */ + /* + * If pixel is less than threshold, then it is black. + */ - if ((alpha != 0) && - ( 0.3086 * red - + 0.6094 * green - + 0.082 * blue < 128)) { - data |= mask; - } - mask >>= 1; - if (mask == 0) { - sprintf(buffer, "%02X", data); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 2; - if (lineLen >= 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } - mask=0x80; - data=0x00; - } + if ((alpha != 0) && + (0.3086*red + 0.6094*green + 0.082*blue < 128)) { + data |= mask; } - if ((width % 8) != 0) { + mask >>= 1; + if (mask == 0) { sprintf(buffer, "%02X", data); - Tcl_AppendResult(interp, buffer, (char *) NULL); - mask=0x80; - data=0x00; + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 2; + if (lineLen >= 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); + } + mask = 0x80; + data = 0x00; } + } + if ((width % 8) != 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, NULL); + mask = 0x80; + data = 0x00; + } - mask=0x80; - data=0x00; - for (xx = 0; xx< width; xx ++) { - pixelPtr = blockPtr->pixelPtr - + (yy * blockPtr->pitch) + mask = 0x80; + data = 0x00; + for (xx=0 ; xx<width ; xx++) { + pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize); - red = pixelPtr[blockPtr->offset[0]]; - green = pixelPtr[blockPtr->offset[1]]; - blue = pixelPtr[blockPtr->offset[2]]; - - alpha = *(alphaPtr + (yy * alphaPitch) - + (xx * alphaIncr) + alphaOffset); - - /* - * If pixel is greater than threshold, then it is white. - */ - - if ((alpha != 0) && - ( 0.3086 * red - + 0.6094 * green - + 0.082 * blue >= 128)) { - data |= mask; - } - mask >>= 1; - if (mask == 0) { - sprintf(buffer, "%02X", data); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 2; - if (lineLen >= 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } - mask=0x80; - data=0x00; - } - } - if ((width % 8) != 0) { - sprintf(buffer, "%02X", data); - Tcl_AppendResult(interp, buffer, (char *) NULL); - mask=0x80; - data=0x00; - } - break; - } - case 1: { + red = pixelPtr[blockPtr->offset[0]]; + green = pixelPtr[blockPtr->offset[1]]; + blue = pixelPtr[blockPtr->offset[2]]; + + alpha = *(alphaPtr + (yy * alphaPitch) + + (xx * alphaIncr) + alphaOffset); + /* - * Generate transparency data. - * We must prevent a transparent value of 0 - * because of a bug in some HP printers. + * If pixel is greater than threshold, then it is white. */ - for (xx = 0; xx < width; xx ++) { - alpha = *(alphaPtr + (yy * alphaPitch) - + (xx * alphaIncr) + alphaOffset); - sprintf(buffer, "%02X", alpha | 0x01); - Tcl_AppendResult(interp, buffer, (char *) NULL); + if ((alpha != 0) && + (0.3086*red + 0.6094*green + 0.082*blue >= 128)) { + data |= mask; + } + mask >>= 1; + if (mask == 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, NULL); lineLen += 2; if (lineLen >= 60) { lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); + Tcl_AppendResult(interp, "\n", NULL); } + mask = 0x80; + data = 0x00; } + } + if ((width % 8) != 0) { + sprintf(buffer, "%02X", data); + Tcl_AppendResult(interp, buffer, NULL); + mask = 0x80; + data = 0x00; + } + break; + } + case 1: { + /* + * Generate transparency data. We must prevent a transparent value + * of 0 because of a bug in some HP printers. + */ + for (xx = 0; xx < width; xx ++) { + alpha = *(alphaPtr + (yy * alphaPitch) + + (xx * alphaIncr) + alphaOffset); + sprintf(buffer, "%02X", alpha | 0x01); + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 2; + if (lineLen >= 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); + } + } - /* - * Generate data in gray mode--in this case, take a - * weighted sum of the red, green, and blue values. - */ + /* + * Generate data in gray mode; in this case, take a weighted sum + * of the red, green, and blue values. + */ - for (xx = 0; xx < width; xx ++) { - pixelPtr = blockPtr->pixelPtr - + (yy * blockPtr->pitch) + for (xx = 0; xx < width; xx ++) { + pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize); - red = pixelPtr[blockPtr->offset[0]]; - green = pixelPtr[blockPtr->offset[1]]; - blue = pixelPtr[blockPtr->offset[2]]; - - sprintf(buffer, "%02X", (int) floor(0.5 + - ( 0.3086 * red + 0.6094 * green + 0.0820 * blue))); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 2; - if (lineLen >= 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } + red = pixelPtr[blockPtr->offset[0]]; + green = pixelPtr[blockPtr->offset[1]]; + blue = pixelPtr[blockPtr->offset[2]]; + + sprintf(buffer, "%02X", (int) floor(0.5 + + ( 0.3086 * red + 0.6094 * green + 0.0820 * blue))); + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 2; + if (lineLen >= 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); } - break; } - default: { - /* - * Generate transparency data. - * We must prevent a transparent value of 0 - * because of a bug in some HP printers. - */ + break; + } + default: + /* + * Generate transparency data. We must prevent a transparent value + * of 0 because of a bug in some HP printers. + */ - for (xx = 0; xx < width; xx ++) { - alpha = *(alphaPtr + (yy * alphaPitch) - + (xx * alphaIncr) + alphaOffset); - sprintf(buffer, "%02X", alpha | 0x01); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 2; - if (lineLen >= 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } + for (xx = 0; xx < width; xx ++) { + alpha = *(alphaPtr + (yy * alphaPitch) + + (xx * alphaIncr) + alphaOffset); + sprintf(buffer, "%02X", alpha | 0x01); + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 2; + if (lineLen >= 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); } + } + /* + * Finally, color mode. Here, just output the red, green, and blue + * values directly. + */ - /* - * Finally, color mode. Here, just output the red, green, - * and blue values directly. - */ - - for (xx = 0; xx < width; xx ++) { - pixelPtr = blockPtr->pixelPtr - + (yy * blockPtr->pitch) - + (xx *blockPtr->pixelSize); - - sprintf(buffer, "%02X%02X%02X", - pixelPtr[blockPtr->offset[0]], - pixelPtr[blockPtr->offset[1]], - pixelPtr[blockPtr->offset[2]]); - Tcl_AppendResult(interp, buffer, (char *) NULL); - lineLen += 6; - if (lineLen >= 60) { - lineLen = 0; - Tcl_AppendResult(interp, "\n", (char *) NULL); - } + for (xx = 0; xx < width; xx ++) { + pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + + (xx * blockPtr->pixelSize); + + sprintf(buffer, "%02X%02X%02X", + pixelPtr[blockPtr->offset[0]], + pixelPtr[blockPtr->offset[1]], + pixelPtr[blockPtr->offset[2]]); + Tcl_AppendResult(interp, buffer, NULL); + lineLen += 6; + if (lineLen >= 60) { + lineLen = 0; + Tcl_AppendResult(interp, "\n", NULL); } - break; } + break; } } - Tcl_AppendResult(interp, ">\n", (char *) NULL); + Tcl_AppendResult(interp, ">\n", NULL); return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvText.c b/generic/tkCanvText.c index 282482f..24c3c7f 100644 --- a/generic/tkCanvText.c +++ b/generic/tkCanvText.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvText.c -- * * This file implements text items for canvas widgets. @@ -6,33 +6,32 @@ * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" #include "tkCanvas.h" -#include "tkPort.h" #include "default.h" /* * The structure below defines the record for each text item. */ -typedef struct TextItem { +typedef struct TextItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ Tk_CanvasTextInfo *textInfoPtr; /* Pointer to a structure containing * information about the selection and - * insertion cursor. The structure is owned - * by (and shared with) the generic canvas + * insertion cursor. The structure is owned by + * (and shared with) the generic canvas * code. */ /* * Fields that are set by widget commands other than "configure". */ - + double x, y; /* Positioning point for text. */ int insertPos; /* Character index of character just before * which the insertion cursor is displayed. */ @@ -52,8 +51,10 @@ typedef struct TextItem { Pixmap activeStipple; /* Stipple bitmap for text, or None. */ Pixmap disabledStipple; /* Stipple bitmap for text, or None. */ char *text; /* Text for item (malloc-ed). */ - int width; /* Width of lines for word-wrap, pixels. - * Zero means no word-wrap. */ + int width; /* Width of lines for word-wrap, pixels. Zero + * means no word-wrap. */ + int underline; /* Index of character to put underline beneath + * or -1 for no underlining. */ /* * Fields whose values are derived from the current values of the @@ -63,18 +64,18 @@ typedef struct TextItem { int numChars; /* Length of text in characters. */ int numBytes; /* Length of text in bytes. */ Tk_TextLayout textLayout; /* Cached text layout information. */ - int leftEdge; /* Pixel location of the left edge of the - * text item; where the left border of the - * text layout is drawn. */ - int rightEdge; /* Pixel just to right of right edge of - * area of text item. Used for selecting up - * to end of line. */ + int leftEdge; /* Pixel location of the left edge of the text + * item; where the left border of the text + * layout is drawn. */ + int rightEdge; /* Pixel just to right of right edge of area + * of text item. Used for selecting up to end + * of line. */ GC gc; /* Graphics context for drawing text. */ GC selTextGC; /* Graphics context for selected text. */ GC cursorOffGC; /* If not None, this gives a graphics context * to use to draw the insertion cursor when - * it's off. Used if the selection and - * insertion cursor colors are the same. */ + * it's off. Used if the selection and + * insertion cursor colors are the same. */ } TextItem; /* @@ -95,89 +96,86 @@ static Tk_CustomOption offsetOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, - "center", Tk_Offset(TextItem, anchor), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-activefill", NULL, NULL, + NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, + NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, + "center", Tk_Offset(TextItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, + {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, + NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, + NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-fill", NULL, NULL, "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK}, - {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL, + {TK_CONFIG_FONT, "-font", NULL, NULL, DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0}, - {TK_CONFIG_JUSTIFY, "-justify", (char *) NULL, (char *) NULL, - "left", Tk_Offset(TextItem, justify), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL, + {TK_CONFIG_JUSTIFY, "-justify", NULL, NULL, + "left", Tk_Offset(TextItem, justify), TK_CONFIG_DONT_SET_DEFAULT}, + {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, "0,0", Tk_Offset(TextItem, tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_STRING, "-text", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, + NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_STRING, "-text", NULL, NULL, "", Tk_Offset(TextItem, text), 0}, - {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-underline", NULL, NULL, + "-1", Tk_Offset(TextItem, underline), 0}, + {TK_CONFIG_PIXELS, "-width", NULL, NULL, "0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static void ComputeTextBbox _ANSI_ARGS_((Tk_Canvas canvas, - TextItem *textPtr)); -static int ConfigureText _ANSI_ARGS_((Tcl_Interp *interp, +static void ComputeTextBbox(Tk_Canvas canvas, TextItem *textPtr); +static int ConfigureText(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - Tcl_Obj *CONST objv[], int flags)); -static int CreateText _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[], int flags); +static int CreateText(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int argc, Tcl_Obj *CONST objv[])); -static void DeleteText _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayCanvText _ANSI_ARGS_((Tk_Canvas canvas, + int argc, Tcl_Obj *CONST objv[]); +static void DeleteText(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayCanvText(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static int GetSelText _ANSI_ARGS_((Tk_Canvas canvas, + int x, int y, int width, int height); +static int GetSelText(Tk_Canvas canvas, Tk_Item *itemPtr, int offset, char *buffer, - int maxBytes)); -static int GetTextIndex _ANSI_ARGS_((Tcl_Interp *interp, + int maxBytes); +static int GetTextIndex(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, - Tcl_Obj *obj, int *indexPtr)); -static void ScaleText _ANSI_ARGS_((Tk_Canvas canvas, + Tcl_Obj *obj, int *indexPtr); +static void ScaleText(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void SetTextCursor _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int index)); -static int TextCoords _ANSI_ARGS_((Tcl_Interp *interp, + double scaleX, double scaleY); +static void SetTextCursor(Tk_Canvas canvas, + Tk_Item *itemPtr, int index); +static int TextCoords(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, - int argc, Tcl_Obj *CONST objv[])); -static void TextDeleteChars _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int first, int last)); -static void TextInsert _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, int beforeThis, char *string)); -static int TextToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static double TextToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *pointPtr)); -static int TextToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static void TranslateText _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); + int argc, Tcl_Obj *CONST objv[]); +static void TextDeleteChars(Tk_Canvas canvas, + Tk_Item *itemPtr, int first, int last); +static void TextInsert(Tk_Canvas canvas, + Tk_Item *itemPtr, int beforeThis, char *string); +static int TextToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static double TextToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *pointPtr); +static int TextToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static void TranslateText(Tk_Canvas canvas, + Tk_Item *itemPtr, double deltaX, double deltaY); /* - * The structures below defines the rectangle and oval item types - * by means of procedures that can be invoked by generic item code. + * The structures below defines the rectangle and oval item types by means of + * functions that can be invoked by generic item code. */ Tk_ItemType tkTextType = { @@ -200,7 +198,7 @@ Tk_ItemType tkTextType = { GetSelText, /* selectionProc */ TextInsert, /* insertProc */ TextDeleteChars, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + NULL, /* nextPtr */ }; /* @@ -208,14 +206,12 @@ Tk_ItemType tkTextType = { * * CreateText -- * - * This procedure is invoked to create a new text item - * in a canvas. + * This function is invoked to create a new text item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item then an error message is left in - * the interp's result; in this case itemPtr is left uninitialized - * so it can be safely freed by the caller. + * A standard Tcl return value. If an error occurred in creating the item + * then an error message is left in the interp's result; in this case + * itemPtr is left uninitialized so it can be safely freed by the caller. * * Side effects: * A new text item is created. @@ -224,24 +220,24 @@ Tk_ItemType tkTextType = { */ static int -CreateText(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header has been +CreateText( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been * initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing rectangle. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing rectangle. */ { TextItem *textPtr = (TextItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* * Carry out initialization that is needed in order to clean up after - * errors during the the remainder of this procedure. + * errors during the the remainder of this function. */ textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas); @@ -262,6 +258,7 @@ CreateText(interp, canvas, itemPtr, objc, objv) textPtr->disabledStipple = None; textPtr->text = NULL; textPtr->width = 0; + textPtr->underline = -1; textPtr->numChars = 0; textPtr->numBytes = 0; @@ -273,14 +270,15 @@ CreateText(interp, canvas, itemPtr, objc, objv) textPtr->cursorOffGC = None; /* - * Process the arguments to fill in the item record. - * Only 1 (list) or 2 (x y) coords are allowed. + * Process the arguments to fill in the item record. Only 1 (list) or 2 (x + * y) coords are allowed. */ if (objc == 1) { i = 1; } else { char *arg = Tcl_GetString(objv[1]); + i = 2; if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { i = 1; @@ -293,7 +291,7 @@ CreateText(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -303,9 +301,8 @@ CreateText(interp, canvas, itemPtr, objc, objv) * * TextCoords -- * - * This procedure is invoked to process the "coords" widget - * command on text items. See the user documentation for - * details on what it does. + * This function is invoked to process the "coords" widget command on + * text items. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -317,18 +314,19 @@ CreateText(interp, canvas, itemPtr, objc, objv) */ static int -TextCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be read or +TextCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or * modified. */ - int objc; /* Number of coordinates supplied in objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, x2, y2, ... */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { TextItem *textPtr = (TextItem *) itemPtr; if (objc == 0) { Tcl_Obj *obj = Tcl_NewObj(); + Tcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x); Tcl_ListObjAppendElement(interp, obj, subobj); subobj = Tcl_NewDoubleObj(textPtr->y); @@ -347,15 +345,16 @@ TextCoords(interp, canvas, itemPtr, objc, objv) return TCL_ERROR; } } - if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], &textPtr->x) != TCL_OK) + if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], + &textPtr->x) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1], - &textPtr->y) != TCL_OK)) { + &textPtr->y) != TCL_OK)) { return TCL_ERROR; } ComputeTextBbox(canvas, textPtr); } else { char buf[64 + TCL_INTEGER_SPACE]; - + sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -368,28 +367,28 @@ TextCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureText -- * - * This procedure is invoked to configure various aspects - * of a text item, such as its border and background colors. + * This function is invoked to configure various aspects of a text item, + * such as its border and background colors. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: - * Configuration information, such as colors and stipple - * patterns, may be set for itemPtr. + * Configuration information, such as colors and stipple patterns, may be + * set for itemPtr. * *-------------------------------------------------------------- */ static int -ConfigureText(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Rectangle item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureText( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Rectangle item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { TextItem *textPtr = (TextItem *) itemPtr; XGCValues gcValues; @@ -409,14 +408,13 @@ ConfigureText(interp, canvas, itemPtr, objc, objv, flags) } /* - * A few of the options require additional processing, such as - * graphics contexts. + * A few of the options require additional processing, such as graphics + * contexts. */ state = itemPtr->state; - if (textPtr->activeColor != NULL || - textPtr->activeStipple != None) { + if (textPtr->activeColor != NULL || textPtr->activeStipple != None) { itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; } else { itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; @@ -497,14 +495,14 @@ ConfigureText(interp, canvas, itemPtr, objc, objv, flags) /* - * If the text was changed, move the selection and insertion indices - * to keep them inside the item. + * If the text was changed, move the selection and insertion indices to + * keep them inside the item. */ textPtr->numBytes = strlen(textPtr->text); textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes); if (textInfoPtr->selItemPtr == itemPtr) { - + if (textInfoPtr->selectFirst >= textPtr->numChars) { textInfoPtr->selItemPtr = NULL; } else { @@ -530,8 +528,8 @@ ConfigureText(interp, canvas, itemPtr, objc, objv, flags) * * DeleteText -- * - * This procedure is called to clean up the data structure - * associated with a text item. + * This function is called to clean up the data structure associated with + * a text item. * * Results: * None. @@ -543,10 +541,10 @@ ConfigureText(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteText(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall canvas widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for canvas. */ +DeleteText( + Tk_Canvas canvas, /* Info about overall canvas widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { TextItem *textPtr = (TextItem *) itemPtr; @@ -590,26 +588,25 @@ DeleteText(canvas, itemPtr, display) * * ComputeTextBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a text item. - * In addition, it recomputes all of the geometry information - * used to display a text item or check for mouse hits. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a text item. In addition, it recomputes + * all of the geometry information used to display a text item or check + * for mouse hits. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr, and the linePtr structure is regenerated - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr, + * and the linePtr structure is regenerated for itemPtr. * *-------------------------------------------------------------- */ static void -ComputeTextBbox(canvas, textPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - TextItem *textPtr; /* Item whose bbox is to be recomputed. */ +ComputeTextBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + TextItem *textPtr) /* Item whose bbox is to be recomputed. */ { Tk_CanvasTextInfo *textInfoPtr; int leftX, topY, width, height, fudge; @@ -629,57 +626,56 @@ ComputeTextBbox(canvas, textPtr) } /* - * Use overall geometry information to compute the top-left corner - * of the bounding box for the text item. + * Use overall geometry information to compute the top-left corner of the + * bounding box for the text item. */ leftX = (int) floor(textPtr->x + 0.5); topY = (int) floor(textPtr->y + 0.5); switch (textPtr->anchor) { - case TK_ANCHOR_NW: - case TK_ANCHOR_N: - case TK_ANCHOR_NE: - break; - - case TK_ANCHOR_W: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_E: - topY -= height / 2; - break; - - case TK_ANCHOR_SW: - case TK_ANCHOR_S: - case TK_ANCHOR_SE: - topY -= height; - break; + case TK_ANCHOR_NW: + case TK_ANCHOR_N: + case TK_ANCHOR_NE: + break; + + case TK_ANCHOR_W: + case TK_ANCHOR_CENTER: + case TK_ANCHOR_E: + topY -= height / 2; + break; + + case TK_ANCHOR_SW: + case TK_ANCHOR_S: + case TK_ANCHOR_SE: + topY -= height; + break; } switch (textPtr->anchor) { - case TK_ANCHOR_NW: - case TK_ANCHOR_W: - case TK_ANCHOR_SW: - break; + case TK_ANCHOR_NW: + case TK_ANCHOR_W: + case TK_ANCHOR_SW: + break; - case TK_ANCHOR_N: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_S: - leftX -= width / 2; - break; + case TK_ANCHOR_N: + case TK_ANCHOR_CENTER: + case TK_ANCHOR_S: + leftX -= width / 2; + break; - case TK_ANCHOR_NE: - case TK_ANCHOR_E: - case TK_ANCHOR_SE: - leftX -= width; - break; + case TK_ANCHOR_NE: + case TK_ANCHOR_E: + case TK_ANCHOR_SE: + leftX -= width; + break; } - textPtr->leftEdge = leftX; + textPtr->leftEdge = leftX; textPtr->rightEdge = leftX + width; /* - * Last of all, update the bounding box for the item. The item's - * bounding box includes the bounding box of all its lines, plus - * an extra fudge factor for the cursor border (which could - * potentially be quite large). + * Last of all, update the bounding box for the item. The item's bounding + * box includes the bounding box of all its lines, plus an extra fudge + * factor for the cursor border (which could potentially be quite large). */ textInfoPtr = textPtr->textInfoPtr; @@ -698,26 +694,26 @@ ComputeTextBbox(canvas, textPtr) * * DisplayCanvText -- * - * This procedure is invoked to draw a text item in a given - * drawable. + * This function is invoked to draw a text item in a given drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw item. */ - int x, y, width, height; /* Describes region of canvas that must be +DisplayCanvText( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, int width, int height) + /* Describes region of canvas that must be * redisplayed (not used). */ { TextItem *textPtr; @@ -749,8 +745,8 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) } /* - * If we're stippling, then modify the stipple offset in the GC. Be - * sure to reset the offset when done, since the GC is supposed to be + * If we're stippling, then modify the stipple offset in the GC. Be sure + * to reset the offset when done, since the GC is supposed to be * read-only. */ @@ -792,7 +788,7 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) for (y = yFirst ; y <= yLast; y += height) { if (y == yLast) { width = xLast + wLast - x; - } else { + } else { width = textPtr->rightEdge - textPtr->leftEdge - x; } Tk_CanvasDrawableCoords(canvas, @@ -811,11 +807,11 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) /* * If the insertion point should be displayed, then draw a special - * background for the cursor before drawing the text. Note: if - * we're the cursor item but the cursor is turned off, then redraw - * background over the area of the cursor. This guarantees that - * the selection won't make the cursor invisible on mono displays, - * where both are drawn in the same color. + * background for the cursor before drawing the text. Note: if we're the + * cursor item but the cursor is turned off, then redraw background over + * the area of the cursor. This guarantees that the selection won't make + * the cursor invisible on mono displays, where both are drawn in the same + * color. */ if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) { @@ -836,11 +832,10 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED); } else if (textPtr->cursorOffGC != None) { /* - * Redraw the background over the area of the cursor, - * even though the cursor is turned off. This - * guarantees that the selection won't make the cursor - * invisible on mono displays, where both may be drawn - * in the same color. + * Redraw the background over the area of the cursor, even + * though the cursor is turned off. This guarantees that the + * selection won't make the cursor invisible on mono displays, + * where both may be drawn in the same color. */ XFillRectangle(display, drawable, textPtr->cursorOffGC, @@ -851,16 +846,14 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) } } - /* - * If there is no selected text or the selected text foreground - * is the same as the regular text foreground, then draw one - * text string. If there is selected text and the foregrounds - * differ, draw the regular text up to the selection, draw - * the selection, then draw the rest of the regular text. - * Drawing the regular text and then the selected text over - * it would causes problems with anti-aliased text because the - * two anti-aliasing colors would blend together. + * If there is no selected text or the selected text foreground is the + * same as the regular text foreground, then draw one text string. If + * there is selected text and the foregrounds differ, draw the regular + * text up to the selection, draw the selection, then draw the rest of the + * regular text. Drawing the regular text and then the selected text over + * it would causes problems with anti-aliased text because the two + * anti-aliasing colors would blend together. */ Tk_CanvasDrawableCoords(canvas, (double) textPtr->leftEdge, @@ -878,6 +871,8 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout, drawableX, drawableY, 0, -1); } + Tk_UnderlineTextLayout(display, drawable, textPtr->gc, textPtr->textLayout, + drawableX, drawableY, textPtr->underline); if (stipple != None) { XSetTSOrigin(display, textPtr->gc, 0, 0); @@ -895,24 +890,23 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height) * None. * * Side effects: - * The text in the given item is modified. The cursor and - * selection positions are also modified to reflect the - * insertion. + * The text in the given item is modified. The cursor and selection + * positions are also modified to reflect the insertion. * *-------------------------------------------------------------- */ static void -TextInsert(canvas, itemPtr, index, string) - Tk_Canvas canvas; /* Canvas containing text item. */ - Tk_Item *itemPtr; /* Text item to be modified. */ - int index; /* Character index before which string is - * to be inserted. */ - char *string; /* New characters to be inserted. */ +TextInsert( + Tk_Canvas canvas, /* Canvas containing text item. */ + Tk_Item *itemPtr, /* Text item to be modified. */ + int index, /* Character index before which string is to + * be inserted. */ + char *string) /* New characters to be inserted. */ { TextItem *textPtr = (TextItem *) itemPtr; int byteIndex, byteCount, charsAdded; - char *new, *text; + char *newStr, *text; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; string = Tcl_GetStringFromObj((Tcl_Obj *) string, &byteCount); @@ -931,20 +925,20 @@ TextInsert(canvas, itemPtr, index, string) return; } - new = (char *) ckalloc((unsigned) textPtr->numBytes + byteCount + 1); - memcpy(new, text, (size_t) byteIndex); - strcpy(new + byteIndex, string); - strcpy(new + byteIndex + byteCount, text + byteIndex); + newStr = (char *) ckalloc((unsigned) textPtr->numBytes + byteCount + 1); + memcpy(newStr, text, (size_t) byteIndex); + strcpy(newStr + byteIndex, string); + strcpy(newStr + byteIndex + byteCount, text + byteIndex); ckfree(text); - textPtr->text = new; + textPtr->text = newStr; charsAdded = Tcl_NumUtfChars(string, byteCount); textPtr->numChars += charsAdded; textPtr->numBytes += byteCount; /* * Inserting characters invalidates indices such as those for the - * selection and cursor. Update the indices appropriately. + * selection and cursor. Update the indices appropriately. */ if (textInfoPtr->selItemPtr == itemPtr) { @@ -976,25 +970,24 @@ TextInsert(canvas, itemPtr, index, string) * None. * * Side effects: - * Characters between "first" and "last", inclusive, get - * deleted from itemPtr, and things like the selection - * position get updated. + * Characters between "first" and "last", inclusive, get deleted from + * itemPtr, and things like the selection position get updated. * *-------------------------------------------------------------- */ static void -TextDeleteChars(canvas, itemPtr, first, last) - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Item in which to delete characters. */ - int first; /* Character index of first character to +TextDeleteChars( + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Item in which to delete characters. */ + int first, /* Character index of first character to * delete. */ - int last; /* Character index of last character to - * delete (inclusive). */ + int last) /* Character index of last character to delete + * (inclusive). */ { TextItem *textPtr = (TextItem *) itemPtr; int byteIndex, byteCount, charsRemoved; - char *new, *text; + char *newStr, *text; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; text = textPtr->text; @@ -1012,19 +1005,19 @@ TextDeleteChars(canvas, itemPtr, first, last) byteIndex = Tcl_UtfAtIndex(text, first) - text; byteCount = Tcl_UtfAtIndex(text + byteIndex, charsRemoved) - (text + byteIndex); - - new = (char *) ckalloc((unsigned) (textPtr->numBytes + 1 - byteCount)); - memcpy(new, text, (size_t) byteIndex); - strcpy(new + byteIndex, text + byteIndex + byteCount); + + newStr = (char *) ckalloc((unsigned) (textPtr->numBytes + 1 - byteCount)); + memcpy(newStr, text, (size_t) byteIndex); + strcpy(newStr + byteIndex, text + byteIndex + byteCount); ckfree(text); - textPtr->text = new; + textPtr->text = newStr; textPtr->numChars -= charsRemoved; textPtr->numBytes -= byteCount; /* - * Update indexes for the selection and cursor to reflect the - * renumbering of the remaining characters. + * Update indexes for the selection and cursor to reflect the renumbering + * of the remaining characters. */ if (textInfoPtr->selItemPtr == itemPtr) { @@ -1066,14 +1059,14 @@ TextDeleteChars(canvas, itemPtr, first, last) * * TextToPoint -- * - * Computes the distance from a given point to a given - * text item, in canvas units. + * Computes the distance from a given point to a given text item, in + * canvas units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are pointPtr[0] and pointPtr[1] is inside the text item. If - * the point isn't inside the text item then the return value - * is the distance from the point to the text item. + * The return value is 0 if the point whose x and y coordinates are + * pointPtr[0] and pointPtr[1] is inside the text item. If the point + * isn't inside the text item then the return value is the distance from + * the point to the text item. * * Side effects: * None. @@ -1082,10 +1075,10 @@ TextDeleteChars(canvas, itemPtr, first, last) */ static double -TextToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +TextToPoint( + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { TextItem *textPtr; Tk_State state = itemPtr->state; @@ -1095,7 +1088,7 @@ TextToPoint(canvas, itemPtr, pointPtr) state = ((TkCanvas *)canvas)->canvas_state; } textPtr = (TextItem *) itemPtr; - value = (double) Tk_DistanceToTextLayout(textPtr->textLayout, + value = (double) Tk_DistanceToTextLayout(textPtr->textLayout, (int) pointPtr[0] - textPtr->leftEdge, (int) pointPtr[1] - textPtr->header.y1); @@ -1111,14 +1104,13 @@ TextToPoint(canvas, itemPtr, pointPtr) * * TextToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangle. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangle. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -1127,12 +1119,12 @@ TextToPoint(canvas, itemPtr, pointPtr) */ static int -TextToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Item to check against rectangle. */ - double *rectPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +TextToArea( + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Item to check against rectangle. */ + double *rectPtr) /* Pointer to array of four coordinates + * (x1,y1,x2,y2) describing rectangular + * area. */ { TextItem *textPtr; Tk_State state = itemPtr->state; @@ -1154,26 +1146,27 @@ TextToArea(canvas, itemPtr, rectPtr) * * ScaleText -- * - * This procedure is invoked to rescale a text item. + * This function is invoked to rescale a text item. * * Results: * None. * * Side effects: - * Scales the position of the text, but not the size - * of the font for the text. + * Scales the position of the text, but not the size of the font for the + * text. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -ScaleText(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing rectangle. */ - Tk_Item *itemPtr; /* Rectangle to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleText( + Tk_Canvas canvas, /* Canvas containing rectangle. */ + Tk_Item *itemPtr, /* Rectangle to be scaled. */ + double originX, double originY, + /* Origin about which to scale rect. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { TextItem *textPtr = (TextItem *) itemPtr; @@ -1188,25 +1181,24 @@ ScaleText(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateText -- * - * This procedure is called to move a text item by a - * given amount. + * This function is called to move a text item by a given amount. * * Results: * None. * * Side effects: - * The position of the text item is offset by (xDelta, yDelta), - * and the bounding box is updated in the generic part of the - * item structure. + * The position of the text item is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslateText(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be moved. */ +TranslateText( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { TextItem *textPtr = (TextItem *) itemPtr; @@ -1220,14 +1212,13 @@ TranslateText(canvas, itemPtr, deltaX, deltaY) * * GetTextIndex -- * - * Parse an index into a text item and return either its value - * or an error. + * Parse an index into a text item and return either its value or an + * error. * * Results: - * A standard Tcl result. If all went well, then *indexPtr is - * filled in with the index (into itemPtr) corresponding to - * string. Otherwise an error message is left in - * the interp's result. + * A standard Tcl result. If all went well, then *indexPtr is filled in + * with the index (into itemPtr) corresponding to string. Otherwise an + * error message is left in the interp's result. * * Side effects: * None. @@ -1236,18 +1227,19 @@ TranslateText(canvas, itemPtr, deltaX, deltaY) */ static int -GetTextIndex(interp, canvas, itemPtr, obj, indexPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item for which the index is being +GetTextIndex( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item for which the index is being * specified. */ - Tcl_Obj *obj; /* Specification of a particular character - * in itemPtr's text. */ - int *indexPtr; /* Where to store converted character + Tcl_Obj *obj, /* Specification of a particular character in + * itemPtr's text. */ + int *indexPtr) /* Where to store converted character * index. */ { TextItem *textPtr = (TextItem *) itemPtr; - int c, length; + int length; + int c; TkCanvas *canvasPtr = (TkCanvas *) canvas; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; char *string = Tcl_GetStringFromObj(obj, &length); @@ -1256,17 +1248,18 @@ GetTextIndex(interp, canvas, itemPtr, obj, indexPtr) if ((c == 'e') && (strncmp(string, "end", (unsigned) length) == 0)) { *indexPtr = textPtr->numChars; - } else if ((c=='i') && (strncmp(string, "insert", (unsigned) length)==0)) { + } else if ((c == 'i') + && (strncmp(string, "insert", (unsigned) length) == 0)) { *indexPtr = textPtr->insertPos; - } else if ((c=='s') && (strncmp(string, "sel.first", (unsigned) length)==0) - && (length >= 5)) { + } else if ((c == 's') && (length >= 5) + && (strncmp(string, "sel.first", (unsigned) length) == 0)) { if (textInfoPtr->selItemPtr != itemPtr) { Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC); return TCL_ERROR; } *indexPtr = textInfoPtr->selectFirst; - } else if ((c=='s') && (strncmp(string, "sel.last", (unsigned) length)==0) - && (length >= 5)) { + } else if ((c == 's') && (length >= 5) + && (strncmp(string, "sel.last", (unsigned) length) == 0)) { if (textInfoPtr->selItemPtr != itemPtr) { Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC); return TCL_ERROR; @@ -1292,7 +1285,7 @@ GetTextIndex(interp, canvas, itemPtr, obj, indexPtr) *indexPtr = Tk_PointToChar(textPtr->textLayout, x + canvasPtr->scrollX1 - textPtr->leftEdge, y + canvasPtr->scrollY1 - textPtr->header.y1); - } else if (Tcl_GetIntFromObj((Tcl_Interp *)NULL, obj, indexPtr) == TCL_OK) { + } else if (Tcl_GetIntFromObj(NULL, obj, indexPtr) == TCL_OK) { if (*indexPtr < 0){ *indexPtr = 0; } else if (*indexPtr > textPtr->numChars) { @@ -1300,14 +1293,13 @@ GetTextIndex(interp, canvas, itemPtr, obj, indexPtr) } } else { /* - * Some of the paths here leave messages in the interp's result, - * so we have to clear it out before storing our own message. + * Some of the paths here leave messages in the interp's result, so we + * have to clear it out before storing our own message. */ - badIndex: - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); - Tcl_AppendResult(interp, "bad index \"", string, "\"", - (char *) NULL); + badIndex: + Tcl_SetResult(interp, NULL, TCL_STATIC); + Tcl_AppendResult(interp, "bad index \"", string, "\"", NULL); return TCL_ERROR; } return TCL_OK; @@ -1331,18 +1323,18 @@ GetTextIndex(interp, canvas, itemPtr, obj, indexPtr) /* ARGSUSED */ static void -SetTextCursor(canvas, itemPtr, index) - Tk_Canvas canvas; /* Record describing canvas widget. */ - Tk_Item *itemPtr; /* Text item in which cursor position is to - * be set. */ - int index; /* Character index of character just before +SetTextCursor( + Tk_Canvas canvas, /* Record describing canvas widget. */ + Tk_Item *itemPtr, /* Text item in which cursor position is to be + * set. */ + int index) /* Character index of character just before * which cursor is to be positioned. */ { TextItem *textPtr = (TextItem *) itemPtr; if (index < 0) { textPtr->insertPos = 0; - } else if (index > textPtr->numChars) { + } else if (index > textPtr->numChars) { textPtr->insertPos = textPtr->numChars; } else { textPtr->insertPos = index; @@ -1354,15 +1346,14 @@ SetTextCursor(canvas, itemPtr, index) * * GetSelText -- * - * This procedure is invoked to return the selected portion - * of a text item. It is only called when this item has - * the selection. + * This function is invoked to return the selected portion of a text + * item. It is only called when this item has the selection. * * Results: - * The return value is the number of non-NULL bytes stored - * at buffer. Buffer is filled (or partially filled) with a - * NULL-terminated string containing part or all of the selection, - * as given by offset and maxBytes. + * The return value is the number of non-NULL bytes stored at buffer. + * Buffer is filled (or partially filled) with a NULL-terminated string + * containing part or all of the selection, as given by offset and + * maxBytes. * * Side effects: * None. @@ -1371,18 +1362,18 @@ SetTextCursor(canvas, itemPtr, index) */ static int -GetSelText(canvas, itemPtr, offset, buffer, maxBytes) - Tk_Canvas canvas; /* Canvas containing selection. */ - Tk_Item *itemPtr; /* Text item containing selection. */ - int offset; /* Byte offset within selection of first +GetSelText( + Tk_Canvas canvas, /* Canvas containing selection. */ + Tk_Item *itemPtr, /* Text item containing selection. */ + int offset, /* Byte offset within selection of first * character to be returned. */ - char *buffer; /* Location in which to place selection. */ - int maxBytes; /* Maximum number of bytes to place at - * buffer, not including terminating NULL + char *buffer, /* Location in which to place selection. */ + int maxBytes) /* Maximum number of bytes to place at buffer, + * not including terminating NULL * character. */ { TextItem *textPtr = (TextItem *) itemPtr; - int byteCount; + int byteCount; char *text; CONST char *selStart, *selEnd; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; @@ -1412,15 +1403,13 @@ GetSelText(canvas, itemPtr, offset, buffer, maxBytes) * * TextToPostscript -- * - * This procedure is called to generate Postscript for - * text items. + * This function is called to generate Postscript for text items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used - * to be there. If no error occurs, then Postscript for the - * item is appended to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -1429,13 +1418,13 @@ GetSelText(canvas, itemPtr, offset, buffer, maxBytes) */ static int -TextToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is wanted. */ - int prepass; /* 1 means this is a prepass to collect - * font information; 0 means final Postscript - * is being created. */ +TextToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { TextItem *textPtr = (TextItem *) itemPtr; int x, y; @@ -1446,7 +1435,7 @@ TextToPostscript(interp, canvas, itemPtr, prepass) Pixmap stipple; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } color = textPtr->color; @@ -1480,41 +1469,53 @@ TextToPostscript(interp, canvas, itemPtr, prepass) return TCL_ERROR; } if (stipple != None) { - Tcl_AppendResult(interp, "/StippleText {\n ", - (char *) NULL); + Tcl_AppendResult(interp, "/StippleText {\n ", NULL); Tk_CanvasPsStipple(interp, canvas, stipple); - Tcl_AppendResult(interp, "} bind def\n", (char *) NULL); + Tcl_AppendResult(interp, "} bind def\n", NULL); } sprintf(buffer, "%.15g %.15g [\n", textPtr->x, Tk_CanvasPsY(canvas, textPtr->y)); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); Tk_TextLayoutToPostscript(interp, textPtr->textLayout); x = 0; y = 0; justify = NULL; /* lint. */ switch (textPtr->anchor) { - case TK_ANCHOR_NW: x = 0; y = 0; break; - case TK_ANCHOR_N: x = 1; y = 0; break; - case TK_ANCHOR_NE: x = 2; y = 0; break; - case TK_ANCHOR_E: x = 2; y = 1; break; - case TK_ANCHOR_SE: x = 2; y = 2; break; - case TK_ANCHOR_S: x = 1; y = 2; break; - case TK_ANCHOR_SW: x = 0; y = 2; break; - case TK_ANCHOR_W: x = 0; y = 1; break; - case TK_ANCHOR_CENTER: x = 1; y = 1; break; + case TK_ANCHOR_NW: x = 0; y = 0; break; + case TK_ANCHOR_N: x = 1; y = 0; break; + case TK_ANCHOR_NE: x = 2; y = 0; break; + case TK_ANCHOR_E: x = 2; y = 1; break; + case TK_ANCHOR_SE: x = 2; y = 2; break; + case TK_ANCHOR_S: x = 1; y = 2; break; + case TK_ANCHOR_SW: x = 0; y = 2; break; + case TK_ANCHOR_W: x = 0; y = 1; break; + case TK_ANCHOR_CENTER: x = 1; y = 1; break; } switch (textPtr->justify) { - case TK_JUSTIFY_LEFT: justify = "0"; break; - case TK_JUSTIFY_CENTER: justify = "0.5";break; - case TK_JUSTIFY_RIGHT: justify = "1"; break; + case TK_JUSTIFY_LEFT: justify = "0"; break; + case TK_JUSTIFY_CENTER: justify = "0.5"; break; + case TK_JUSTIFY_RIGHT: justify = "1"; break; } Tk_GetFontMetrics(textPtr->tkfont, &fm); - sprintf(buffer, "] %d %g %g %s %s DrawText\n", - fm.linespace, x / -2.0, y / 2.0, justify, - ((stipple == None) ? "false" : "true")); - Tcl_AppendResult(interp, buffer, (char *) NULL); + sprintf(buffer, "] %d ", fm.linespace); + Tcl_AppendResult(interp, buffer, NULL); + Tcl_PrintDouble(NULL, x / -2.0, buffer); + Tcl_AppendResult(interp, buffer, NULL); + Tcl_PrintDouble(NULL, y / 2.0, buffer); + Tcl_AppendResult(interp, " ", buffer, NULL); + sprintf(buffer, " %s %s DrawText\n", + justify, ((stipple == None) ? "false" : "true")); + Tcl_AppendResult(interp, buffer, NULL); return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvUtil.c b/generic/tkCanvUtil.c index 8ad3b5c..eca3789 100644 --- a/generic/tkCanvUtil.c +++ b/generic/tkCanvUtil.c @@ -1,29 +1,64 @@ -/* +/* * tkCanvUtil.c -- * - * This procedure contains a collection of utility procedures - * used by the implementations of various canvas item types. + * This file contains a collection of utility functions used by the + * implementations of various canvas item types. * * Copyright (c) 1994 Sun Microsystems, Inc. - * Copyright (c) 1994 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkCanvas.h" -#include "tkPort.h" #include <assert.h> +/* + * Structures defined only in this file. + */ + +typedef struct SmoothAssocData { + struct SmoothAssocData *nextPtr; + /* Pointer to next SmoothAssocData. */ + Tk_SmoothMethod smooth; /* Name and functions associated with this + * option. */ +} SmoothAssocData; + +Tk_SmoothMethod tkBezierSmoothMethod = { + "true", + TkMakeBezierCurve, + (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, + int numPoints, int numSteps)) TkMakeBezierPostscript, +}; +static Tk_SmoothMethod tkRawSmoothMethod = { + "raw", + TkMakeRawCurve, + (void (*) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, + int numPoints, int numSteps)) TkMakeRawCurvePostscript, +}; + +/* + * Function forward-declarations. + */ + +static void SmoothMethodCleanupProc(ClientData clientData, + Tcl_Interp *interp); +static SmoothAssocData *InitSmoothMethods(Tcl_Interp *interp); +static int DashConvert(char *l, CONST char *p, int n, + double width); +static void TranslateAndAppendCoords(TkCanvas *canvPtr, + double x, double y, XPoint *outArr, int numOut); + +#define ABS(a) ((a>=0)?(a):(-(a))) /* *---------------------------------------------------------------------- * * Tk_CanvasTkwin -- * - * Given a token for a canvas, this procedure returns the - * widget that represents the canvas. + * Given a token for a canvas, this function returns the widget that + * represents the canvas. * * Results: * The return value is a handle for the widget. @@ -35,8 +70,8 @@ */ Tk_Window -Tk_CanvasTkwin(canvas) - Tk_Canvas canvas; /* Token for the canvas. */ +Tk_CanvasTkwin( + Tk_Canvas canvas) /* Token for the canvas. */ { TkCanvas *canvasPtr = (TkCanvas *) canvas; return canvasPtr->tkwin; @@ -47,16 +82,15 @@ Tk_CanvasTkwin(canvas) * * Tk_CanvasDrawableCoords -- * - * Given an (x,y) coordinate pair within a canvas, this procedure + * Given an (x,y) coordinate pair within a canvas, this function * returns the corresponding coordinates at which the point should * be drawn in the drawable used for display. * * Results: - * There is no return value. The values at *drawableXPtr and - * *drawableYPtr are filled in with the coordinates at which - * x and y should be drawn. These coordinates are clipped - * to fit within a "short", since this is what X uses in - * most cases for drawing. + * There is no return value. The values at *drawableXPtr and + * *drawableYPtr are filled in with the coordinates at which x and y + * should be drawn. These coordinates are clipped to fit within a + * "short", since this is what X uses in most cases for drawing. * * Side effects: * None. @@ -65,11 +99,12 @@ Tk_CanvasTkwin(canvas) */ void -Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr) - Tk_Canvas canvas; /* Token for the canvas. */ - double x, y; /* Coordinates in canvas space. */ - short *drawableXPtr, *drawableYPtr; /* Screen coordinates are stored - * here. */ +Tk_CanvasDrawableCoords( + Tk_Canvas canvas, /* Token for the canvas. */ + double x, /* Coordinates in canvas space. */ + double y, + short *drawableXPtr, /* Screen coordinates are stored here. */ + short *drawableYPtr) { TkCanvas *canvasPtr = (TkCanvas *) canvas; double tmp; @@ -88,7 +123,7 @@ Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr) *drawableXPtr = (short) tmp; } - tmp = y - canvasPtr->drawableYOrigin; + tmp = y - canvasPtr->drawableYOrigin; if (tmp > 0) { tmp += 0.5; } else { @@ -108,15 +143,14 @@ Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr) * * Tk_CanvasWindowCoords -- * - * Given an (x,y) coordinate pair within a canvas, this procedure - * returns the corresponding coordinates in the canvas's window. + * Given an (x,y) coordinate pair within a canvas, this function returns + * the corresponding coordinates in the canvas's window. * * Results: - * There is no return value. The values at *screenXPtr and - * *screenYPtr are filled in with the coordinates at which - * (x,y) appears in the canvas's window. These coordinates - * are clipped to fit within a "short", since this is what X - * uses in most cases for drawing. + * There is no return value. The values at *screenXPtr and *screenYPtr + * are filled in with the coordinates at which (x,y) appears in the + * canvas's window. These coordinates are clipped to fit within a + * "short", since this is what X uses in most cases for drawing. * * Side effects: * None. @@ -125,11 +159,12 @@ Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr) */ void -Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr) - Tk_Canvas canvas; /* Token for the canvas. */ - double x, y; /* Coordinates in canvas space. */ - short *screenXPtr, *screenYPtr; /* Screen coordinates are stored - * here. */ +Tk_CanvasWindowCoords( + Tk_Canvas canvas, /* Token for the canvas. */ + double x, /* Coordinates in canvas space. */ + double y, + short *screenXPtr, /* Screen coordinates are stored here. */ + short *screenYPtr) { TkCanvas *canvasPtr = (TkCanvas *) canvas; double tmp; @@ -148,7 +183,7 @@ Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr) *screenXPtr = (short) tmp; } - tmp = y - canvasPtr->yOrigin; + tmp = y - canvasPtr->yOrigin; if (tmp > 0) { tmp += 0.5; } else { @@ -172,11 +207,10 @@ Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr) * corresponding to that string. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * canvas coordinate is stored at *doublePtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the canvas coordinate is + * stored at *doublePtr; otherwise TCL_ERROR is returned and an error + * message is left in the interp's result. * * Side effects: * None. @@ -185,14 +219,15 @@ Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr) */ int -Tk_CanvasGetCoord(interp, canvas, string, doublePtr) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to which coordinate applies. */ - CONST char *string; /* Describes coordinate (any screen - * coordinate form may be used here). */ - double *doublePtr; /* Place to store converted coordinate. */ +Tk_CanvasGetCoord( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to which coordinate applies. */ + CONST char *string, /* Describes coordinate (any screen coordinate + * form may be used here). */ + double *doublePtr) /* Place to store converted coordinate. */ { TkCanvas *canvasPtr = (TkCanvas *) canvas; + if (Tk_GetScreenMM(canvasPtr->interp, canvasPtr->tkwin, string, doublePtr) != TCL_OK) { return TCL_ERROR; @@ -210,11 +245,10 @@ Tk_CanvasGetCoord(interp, canvas, string, doublePtr) * corresponding to that string. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * canvas coordinate is stored at *doublePtr; otherwise - * TCL_ERROR is returned and an error message is left in - * interp->result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the canvas coordinate is + * stored at *doublePtr; otherwise TCL_ERROR is returned and an error + * message is left in interp->result. * * Side effects: * None. @@ -223,20 +257,16 @@ Tk_CanvasGetCoord(interp, canvas, string, doublePtr) */ int -Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to which coordinate applies. */ - Tcl_Obj *obj; /* Describes coordinate (any screen - * coordinate form may be used here). */ - double *doublePtr; /* Place to store converted coordinate. */ +Tk_CanvasGetCoordFromObj( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to which coordinate applies. */ + Tcl_Obj *obj, /* Describes coordinate (any screen coordinate + * form may be used here). */ + double *doublePtr) /* Place to store converted coordinate. */ { TkCanvas *canvasPtr = (TkCanvas *) canvas; - if (Tk_GetMMFromObj(canvasPtr->interp, canvasPtr->tkwin, obj, - doublePtr) != TCL_OK) { - return TCL_ERROR; - } - *doublePtr *= canvasPtr->pixelsPerMM; - return TCL_OK; + + return Tk_GetDoublePixelsFromObj(canvasPtr->interp, canvasPtr->tkwin, obj, doublePtr); } /* @@ -244,9 +274,9 @@ Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr) * * Tk_CanvasSetStippleOrigin -- * - * This procedure sets the stipple origin in a graphics context - * so that stipples drawn with the GC will line up with other - * stipples previously drawn in the canvas. + * This function sets the stipple origin in a graphics context so that + * stipples drawn with the GC will line up with other stipples previously + * drawn in the canvas. * * Results: * None. @@ -258,12 +288,11 @@ Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr) */ void -Tk_CanvasSetStippleOrigin(canvas, gc) - Tk_Canvas canvas; /* Token for a canvas. */ - GC gc; /* Graphics context that is about to be - * used to draw a stippled pattern as - * part of redisplaying the canvas. */ - +Tk_CanvasSetStippleOrigin( + Tk_Canvas canvas, /* Token for a canvas. */ + GC gc) /* Graphics context that is about to be used + * to draw a stippled pattern as part of + * redisplaying the canvas. */ { TkCanvas *canvasPtr = (TkCanvas *) canvas; @@ -276,9 +305,9 @@ Tk_CanvasSetStippleOrigin(canvas, gc) * * Tk_CanvasSetOffset-- * - * This procedure sets the stipple offset in a graphics - * context so that stipples drawn with the GC will - * line up with other stipples with the same offset. + * This function sets the stipple offset in a graphics context so that + * stipples drawn with the GC will line up with other stipples with the + * same offset. * * Results: * None. @@ -290,12 +319,12 @@ Tk_CanvasSetStippleOrigin(canvas, gc) */ void -Tk_CanvasSetOffset(canvas, gc, offset) - Tk_Canvas canvas; /* Token for a canvas. */ - GC gc; /* Graphics context that is about to be - * used to draw a stippled pattern as - * part of redisplaying the canvas. */ - Tk_TSOffset *offset; /* offset (may be NULL pointer)*/ +Tk_CanvasSetOffset( + Tk_Canvas canvas, /* Token for a canvas. */ + GC gc, /* Graphics context that is about to be used + * to draw a stippled pattern as part of + * redisplaying the canvas. */ + Tk_TSOffset *offset) /* Offset (may be NULL pointer)*/ { TkCanvas *canvasPtr = (TkCanvas *) canvas; int flags = 0; @@ -320,17 +349,16 @@ Tk_CanvasSetOffset(canvas, gc, offset) * * Tk_CanvasGetTextInfo -- * - * This procedure returns a pointer to a structure containing - * information about the selection and insertion cursor for - * a canvas widget. Items such as text items save the pointer - * and use it to share access to the information with the generic - * canvas code. + * This function returns a pointer to a structure containing information + * about the selection and insertion cursor for a canvas widget. Items + * such as text items save the pointer and use it to share access to the + * information with the generic canvas code. * * Results: * The return value is a pointer to the structure holding text - * information for the canvas. Most of the fields should not - * be modified outside the generic canvas code; see the user - * documentation for details. + * information for the canvas. Most of the fields should not be modified + * outside the generic canvas code; see the user documentation for + * details. * * Side effects: * None. @@ -339,8 +367,8 @@ Tk_CanvasSetOffset(canvas, gc, offset) */ Tk_CanvasTextInfo * -Tk_CanvasGetTextInfo(canvas) - Tk_Canvas canvas; /* Token for the canvas widget. */ +Tk_CanvasGetTextInfo( + Tk_Canvas canvas) /* Token for the canvas widget. */ { return &((TkCanvas *) canvas)->textInfo; } @@ -350,28 +378,27 @@ Tk_CanvasGetTextInfo(canvas) * * Tk_CanvasTagsParseProc -- * - * This procedure is invoked during option processing to handle - * "-tags" options for canvas items. + * This function is invoked during option processing to handle "-tags" + * options for canvas items. * * Results: * A standard Tcl return value. * * Side effects: - * The tags for a given item get replaced by those indicated - * in the value argument. + * The tags for a given item get replaced by those indicated in the value + * argument. * *-------------------------------------------------------------- */ int -Tk_CanvasTagsParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* Not used.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option (list of tag - * names). */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item (ignored). */ +Tk_CanvasTagsParseProc( + ClientData clientData, /* Not used.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + CONST char *value, /* Value of option (list of tag names). */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item (ignored). */ { register Tk_Item *itemPtr = (Tk_Item *) widgRec; int argc, i; @@ -387,8 +414,7 @@ Tk_CanvasTagsParseProc(clientData, interp, tkwin, value, widgRec, offset) } /* - * Make sure that there's enough space in the item to hold the - * tag names. + * Make sure that there's enough space in the item to hold the tag names. */ if (itemPtr->tagSpace < argc) { @@ -415,16 +441,16 @@ Tk_CanvasTagsParseProc(clientData, interp, tkwin, value, widgRec, offset) * * Tk_CanvasTagsPrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-tags" configuration - * option for canvas items. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-tags" configuration option for canvas + * items. * * Results: - * The return value is a string describing all the tags for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). + * The return value is a string describing all the tags for the item + * referred to by "widgRec". In addition, *freeProcPtr is filled in with + * the address of a function to call to free the result string when it's + * no longer needed (or NULL to indicate that the string doesn't need to + * be freed). * * Side effects: * None. @@ -433,61 +459,55 @@ Tk_CanvasTagsParseProc(clientData, interp, tkwin, value, widgRec, offset) */ char * -Tk_CanvasTagsPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Ignored. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +Tk_CanvasTagsPrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Ignored. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { register Tk_Item *itemPtr = (Tk_Item *) widgRec; if (itemPtr->numTags == 0) { - *freeProcPtr = (Tcl_FreeProc *) NULL; + *freeProcPtr = NULL; return ""; } if (itemPtr->numTags == 1) { - *freeProcPtr = (Tcl_FreeProc *) NULL; + *freeProcPtr = NULL; return (char *) itemPtr->tagPtr[0]; } *freeProcPtr = TCL_DYNAMIC; return Tcl_Merge(itemPtr->numTags, (CONST char **) itemPtr->tagPtr); } - -static int DashConvert _ANSI_ARGS_((char *l, CONST char *p, - int n, double width)); -#define ABS(a) ((a>=0)?(a):(-(a))) - /* *-------------------------------------------------------------- * * TkCanvasDashParseProc -- * - * This procedure is invoked during option processing to handle - * "-dash", "-activedash" and "-disableddash" options for canvas - * objects. + * This function is invoked during option processing to handle "-dash", + * "-activedash" and "-disableddash" options for canvas objects. * * Results: * A standard Tcl return value. * * Side effects: - * The dash list for a given canvas object gets replaced by - * those indicated in the value argument. + * The dash list for a given canvas object gets replaced by those + * indicated in the value argument. * *-------------------------------------------------------------- */ int -TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* Not used.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ +TkCanvasDashParseProc( + ClientData clientData, /* Not used.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + CONST char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item. */ { return Tk_GetDash(interp, value, (Tk_Dash *)(widgRec+offset)); } @@ -497,16 +517,16 @@ TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset) * * TkCanvasDashPrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-dash", "-activedash" - * and "-disableddash" configuration options for canvas items. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-dash", "-activedash" and "-disableddash" + * configuration options for canvas items. * * Results: - * The return value is a string describing all the dash list for - * the item referred to by "widgRec"and "offset". In addition, - * *freeProcPtr is filled in with the address of a procedure to - * call to free the result string when it's no longer needed (or - * NULL to indicate that the string doesn't need to be freed). + * The return value is a string describing all the dash list for the item + * referred to by "widgRec"and "offset". In addition, *freeProcPtr is + * filled in with the address of a function to call to free the result + * string when it's no longer needed (or NULL to indicate that the string + * doesn't need to be freed). * * Side effects: * None. @@ -515,14 +535,14 @@ TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset) */ char * -TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset in record for item. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +TkCanvasDashPrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Offset in record for item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { Tk_Dash *dash = (Tk_Dash *) (widgRec+offset); char *buffer; @@ -533,18 +553,18 @@ TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) i = -i; *freeProcPtr = TCL_DYNAMIC; buffer = (char *) ckalloc((unsigned int) (i+1)); - p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; + p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; memcpy(buffer, p, (unsigned int) i); buffer[i] = 0; return buffer; } else if (!i) { - *freeProcPtr = (Tcl_FreeProc *) NULL; + *freeProcPtr = NULL; return ""; } buffer = (char *)ckalloc((unsigned int) (4*i)); *freeProcPtr = TCL_DYNAMIC; - p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; + p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; sprintf(buffer, "%d", *p++ & 0xff); while(--i) { sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff); @@ -555,46 +575,80 @@ TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) /* *-------------------------------------------------------------- * - * Tk_CreateSmoothMethod -- + * InitSmoothMethods -- * - * This procedure is invoked to add additional values - * for the "-smooth" option to the list. + * This function is invoked to set up the initial state of the list of + * "-smooth" methods. It should only be called when the list installed + * in the interpreter is NULL. * * Results: - * A standard Tcl return value. + * Pointer to the start of the list of default smooth methods. * * Side effects: - * In the future "-smooth <name>" will be accepted as - * smooth method for the line and polygon. + * A linked list of smooth methods is created and attached to the + * interpreter's association key "smoothMethod" * *-------------------------------------------------------------- */ -Tk_SmoothMethod tkBezierSmoothMethod = { - "bezier", - TkMakeBezierCurve, - (void (*) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, - double *coordPtr, int numPoints, int numSteps))) - TkMakeBezierPostscript, -}; +static SmoothAssocData * +InitSmoothMethods( + Tcl_Interp *interp) +{ + SmoothAssocData *methods, *ptr; -static void SmoothMethodCleanupProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp)); + methods = (SmoothAssocData *) ckalloc(sizeof(SmoothAssocData)); + methods->smooth.name = tkRawSmoothMethod.name; + methods->smooth.coordProc = tkRawSmoothMethod.coordProc; + methods->smooth.postscriptProc = tkRawSmoothMethod.postscriptProc; -typedef struct SmoothAssocData { - struct SmoothAssocData *nextPtr; /* pointer to next SmoothAssocData */ - Tk_SmoothMethod smooth; /* name and functions associated with this - * option */ -} SmoothAssocData; + methods->nextPtr = (SmoothAssocData *) ckalloc(sizeof(SmoothAssocData)); + + ptr = methods->nextPtr; + ptr->smooth.name = tkBezierSmoothMethod.name; + ptr->smooth.coordProc = tkBezierSmoothMethod.coordProc; + ptr->smooth.postscriptProc = tkBezierSmoothMethod.postscriptProc; + ptr->nextPtr = NULL; + + Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc, + (ClientData) methods); + return methods; +} + +/* + *-------------------------------------------------------------- + * + * Tk_CreateSmoothMethod -- + * + * This function is invoked to add additional values for the "-smooth" + * option to the list. + * + * Results: + * A standard Tcl return value. + * + * Side effects: + * In the future "-smooth <name>" will be accepted as smooth method for + * the line and polygon. + * + *-------------------------------------------------------------- + */ void -Tk_CreateSmoothMethod(interp, smooth) - Tcl_Interp *interp; - Tk_SmoothMethod *smooth; +Tk_CreateSmoothMethod( + Tcl_Interp *interp, + Tk_SmoothMethod *smooth) { SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr; methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod", - (Tcl_InterpDeleteProc **) NULL); + NULL); + + /* + * Initialize if we were not previously initialized. + */ + + if (methods == NULL) { + methods = InitSmoothMethods(interp); + } /* * If there's already a smooth method with the given name, remove it. @@ -618,15 +672,16 @@ Tk_CreateSmoothMethod(interp, smooth) ptr->smooth.postscriptProc = smooth->postscriptProc; ptr->nextPtr = methods; Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc, - (ClientData) ptr); + (ClientData) ptr); } + /* *---------------------------------------------------------------------- * * SmoothMethodCleanupProc -- * - * This procedure is invoked whenever an interpreter is deleted - * to cleanup the smooth methods. + * This function is invoked whenever an interpreter is deleted to + * cleanup the smooth methods. * * Results: * None. @@ -638,10 +693,10 @@ Tk_CreateSmoothMethod(interp, smooth) */ static void -SmoothMethodCleanupProc(clientData, interp) - ClientData clientData; /* Points to "smoothMethod" AssocData - * for the interpreter. */ - Tcl_Interp *interp; /* Interpreter that is being deleted. */ +SmoothMethodCleanupProc( + ClientData clientData, /* Points to "smoothMethod" AssocData for the + * interpreter. */ + Tcl_Interp *interp) /* Interpreter that is being deleted. */ { SmoothAssocData *ptr, *methods = (SmoothAssocData *) clientData; @@ -655,8 +710,8 @@ SmoothMethodCleanupProc(clientData, interp) * * TkSmoothParseProc -- * - * This procedure is invoked during option processing to handle - * the "-smooth" option. + * This function is invoked during option processing to handle the + * "-smooth" option. * * Results: * A standard Tcl return value. @@ -669,33 +724,54 @@ SmoothMethodCleanupProc(clientData, interp) */ int -TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* some flags.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ +TkSmoothParseProc( + ClientData clientData, /* some flags.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + CONST char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item. */ { register Tk_SmoothMethod **smoothPtr = - (Tk_SmoothMethod **) (widgRec + offset); + (Tk_SmoothMethod **) (widgRec + offset); Tk_SmoothMethod *smooth = NULL; int b; size_t length; SmoothAssocData *methods; if (value == NULL || *value == 0) { - *smoothPtr = (Tk_SmoothMethod *) NULL; + *smoothPtr = NULL; return TCL_OK; } length = strlen(value); methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod", - (Tcl_InterpDeleteProc **) NULL); - while (methods != (SmoothAssocData *) NULL) { + NULL); + + /* + * Not initialized yet; fix that now. + */ + + if (methods == NULL) { + methods = InitSmoothMethods(interp); + } + + /* + * Backward compatability hack. + */ + + if (strncmp(value, "bezier", length) == 0) { + smooth = &tkBezierSmoothMethod; + } + + /* + * Search the list of installed smooth methods. + */ + + while (methods != NULL) { if (strncmp(value, methods->smooth.name, length) == 0) { - if (smooth != (Tk_SmoothMethod *) NULL) { - Tcl_AppendResult(interp, "ambigeous smooth method \"", value, - "\"", (char *) NULL); + if (smooth != NULL) { + Tcl_AppendResult(interp, "ambiguous smooth method \"", value, + "\"", NULL); return TCL_ERROR; } smooth = &methods->smooth; @@ -705,19 +781,16 @@ TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset) if (smooth) { *smoothPtr = smooth; return TCL_OK; - } else if (strncmp(value, tkBezierSmoothMethod.name, length) == 0) { - /* - * We need to do handle the built-in bezier method. - */ - *smoothPtr = &tkBezierSmoothMethod; - return TCL_OK; } + /* + * Did not find it. Try parsing as a boolean instead. + */ if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) { return TCL_ERROR; } - *smoothPtr = b ? &tkBezierSmoothMethod : (Tk_SmoothMethod*) NULL; + *smoothPtr = b ? &tkBezierSmoothMethod : NULL; return TCL_OK; } /* @@ -725,16 +798,15 @@ TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset) * * TkSmoothPrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-smooth" - * configuration option. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-smooth" configuration option. * * Results: - * The return value is a string describing the smooth option for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). + * The return value is a string describing the smooth option for the item + * referred to by "widgRec". In addition, *freeProcPtr is filled in with + * the address of a function to call to free the result string when it's + * no longer needed (or NULL to indicate that the string doesn't need to + * be freed). * * Side effects: * None. @@ -743,16 +815,17 @@ TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset) */ char * -TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +TkSmoothPrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Offset into item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { - register Tk_SmoothMethod **smoothPtr = (Tk_SmoothMethod **) (widgRec + offset); + register Tk_SmoothMethod **smoothPtr = + (Tk_SmoothMethod **) (widgRec + offset); return (*smoothPtr) ? (*smoothPtr)->name : "0"; } @@ -761,13 +834,12 @@ TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) * * Tk_GetDash * - * This procedure is used to parse a string, assuming - * it is dash information. + * This function is used to parse a string, assuming it is dash + * information. * * Results: - * The return value is a standard Tcl result: TCL_OK means - * that the dash information was parsed ok, and - * TCL_ERROR means it couldn't be parsed. + * The return value is a standard Tcl result: TCL_OK means that the dash + * information was parsed ok, and TCL_ERROR means it couldn't be parsed. * * Side effects: * Dash information in the dash structure is updated. @@ -776,29 +848,34 @@ TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) */ int -Tk_GetDash(interp, value, dash) - Tcl_Interp *interp; /* Used for error reporting. */ - CONST char *value; /* Textual specification of dash list. */ - Tk_Dash *dash; /* Pointer to record in which to - * store dash information. */ +Tk_GetDash( + Tcl_Interp *interp, /* Used for error reporting. */ + CONST char *value, /* Textual specification of dash list. */ + Tk_Dash *dash) /* Pointer to record in which to store dash + * information. */ { int argc, i; CONST char **largv, **argv = NULL; char *pt; - if ((value==(char *) NULL) || (*value==0) ) { + if ((value==NULL) || (*value==0) ) { dash->number = 0; return TCL_OK; } - if ((*value == '.') || (*value == ',') || - (*value == '-') || (*value == '_')) { - i = DashConvert((char *) NULL, value, -1, 0.0); + + /* + * switch is usually compiled more efficiently than a chain of conditions. + */ + + switch (*value) { + case '.': case ',': case '-': case '_': + i = DashConvert(NULL, value, -1, 0.0); if (i>0) { i = strlen(value); } else { goto badDashList; } - if (i > sizeof(char *)) { + if (i > (int)sizeof(char *)) { dash->pattern.pt = pt = (char *) ckalloc(strlen(value)); } else { pt = dash->pattern.array; @@ -807,26 +884,16 @@ Tk_GetDash(interp, value, dash) dash->number = -i; return TCL_OK; } + if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) { Tcl_ResetResult(interp); - badDashList: - Tcl_AppendResult(interp, "bad dash list \"", value, - "\": must be a list of integers or a format like \"-..\"", - (char *) NULL); - syntaxError: - if (argv != NULL) { - ckfree((char *) argv); - } - if (ABS(dash->number) > sizeof(char *)) - ckfree((char *) dash->pattern.pt); - dash->number = 0; - return TCL_ERROR; + goto badDashList; } - if (ABS(dash->number) > sizeof(char *)) { + if ((unsigned int)ABS(dash->number) > sizeof(char *)) { ckfree((char *) dash->pattern.pt); } - if (argc > sizeof(char *)) { + if (argc > (int)sizeof(char *)) { dash->pattern.pt = pt = (char *) ckalloc((unsigned int) argc); } else { pt = dash->pattern.array; @@ -834,23 +901,41 @@ Tk_GetDash(interp, value, dash) dash->number = argc; largv = argv; - while(argc>0) { - if (Tcl_GetInt(interp, *largv, &i) != TCL_OK || - i < 1 || i>255) { + while (argc>0) { + if (Tcl_GetInt(interp, *largv, &i) != TCL_OK || i < 1 || i>255) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "expected integer in the range 1..255 but got \"", - *largv, "\"", (char *) NULL); + Tcl_AppendResult(interp, + "expected integer in the range 1..255 but got \"", + *largv, "\"", NULL); goto syntaxError; } *pt++ = i; - argc--; largv++; + argc--; + largv++; } - + if (argv != NULL) { ckfree((char *) argv); } - return TCL_OK; + + /* + * Something went wrong. Generate error message, clean up and return. + */ + + badDashList: + Tcl_AppendResult(interp, "bad dash list \"", value, + "\": must be a list of integers or a format like \"-..\"", + NULL); + syntaxError: + if (argv != NULL) { + ckfree((char *) argv); + } + if ((unsigned int)ABS(dash->number) > sizeof(char *)) { + ckfree((char *) dash->pattern.pt); + } + dash->number = 0; + return TCL_ERROR; } /* @@ -858,8 +943,8 @@ Tk_GetDash(interp, value, dash) * * Tk_CreateOutline * - * This procedure initializes the Tk_Outline structure - * with default values. + * This function initializes the Tk_Outline structure with default + * values. * * Results: * None @@ -870,8 +955,9 @@ Tk_GetDash(interp, value, dash) *-------------------------------------------------------------- */ -void Tk_CreateOutline(outline) - Tk_Outline *outline; +void +Tk_CreateOutline( + Tk_Outline *outline) /* Outline structure to be filled in. */ { outline->gc = None; outline->width = 1.0; @@ -897,8 +983,8 @@ void Tk_CreateOutline(outline) * * Tk_DeleteOutline * - * This procedure frees all memory that might be - * allocated and referenced in the Tk_Outline structure. + * This function frees all memory that might be allocated and referenced + * in the Tk_Outline structure. * * Results: * None @@ -909,20 +995,21 @@ void Tk_CreateOutline(outline) *-------------------------------------------------------------- */ -void Tk_DeleteOutline(display, outline) - Display *display; /* Display containing window */ - Tk_Outline *outline; +void +Tk_DeleteOutline( + Display *display, /* Display containing window. */ + Tk_Outline *outline) { if (outline->gc != None) { Tk_FreeGC(display, outline->gc); } - if (ABS(outline->dash.number) > sizeof(char *)) { + if ((unsigned int)ABS(outline->dash.number) > sizeof(char *)) { ckfree((char *) outline->dash.pattern.pt); } - if (ABS(outline->activeDash.number) > sizeof(char *)) { + if ((unsigned int)ABS(outline->activeDash.number) > sizeof(char *)) { ckfree((char *) outline->activeDash.pattern.pt); } - if (ABS(outline->disabledDash.number) > sizeof(char *)) { + if ((unsigned int)ABS(outline->disabledDash.number) > sizeof(char *)) { ckfree((char *) outline->disabledDash.pattern.pt); } if (outline->color != NULL) { @@ -950,15 +1037,14 @@ void Tk_DeleteOutline(display, outline) * * Tk_ConfigOutlineGC * - * This procedure should be called in the canvas object - * during the configure command. The graphics context - * description in gcValues is updated according to the - * information in the dash structure, as far as possible. + * This function should be called in the canvas object during the + * configure command. The graphics context description in gcValues is + * updated according to the information in the dash structure, as far as + * possible. * * Results: - * The return-value is a mask, indicating which - * elements of gcValues have been updated. - * 0 means there is no outline. + * The return-value is a mask, indicating which elements of gcValues have + * been updated. 0 means there is no outline. * * Side effects: * GC information in gcValues is updated. @@ -966,11 +1052,12 @@ void Tk_DeleteOutline(display, outline) *-------------------------------------------------------------- */ -int Tk_ConfigOutlineGC(gcValues, canvas, item, outline) - XGCValues *gcValues; - Tk_Canvas canvas; - Tk_Item *item; - Tk_Outline *outline; +int +Tk_ConfigOutlineGC( + XGCValues *gcValues, + Tk_Canvas canvas, + Tk_Item *item, + Tk_Outline *outline) { int mask = 0; double width; @@ -1015,7 +1102,7 @@ int Tk_ConfigOutlineGC(gcValues, canvas, item, outline) if (outline->activeStipple!=None) { stipple = outline->activeStipple; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (outline->disabledWidth>0) { width = outline->disabledWidth; } @@ -1047,12 +1134,10 @@ int Tk_ConfigOutlineGC(gcValues, canvas, item, outline) if (mask && (dash->number != 0)) { gcValues->line_style = LineOnOffDash; gcValues->dash_offset = outline->offset; - if (dash->number >= 2) { - gcValues->dashes = 4; - } else if (dash->number > 0) { + if (dash->number > 0) { gcValues->dashes = dash->pattern.array[0]; } else { - gcValues->dashes = (char) (4 * width); + gcValues->dashes = (char) (4 * width + 0.5); } mask |= GCLineStyle|GCDashList|GCDashOffset; } @@ -1064,15 +1149,12 @@ int Tk_ConfigOutlineGC(gcValues, canvas, item, outline) * * Tk_ChangeOutlineGC * - * Updates the GC to represent the full information of - * the dash structure. Partly this is already done in - * Tk_ConfigOutlineGC(). - * This function should be called just before drawing - * the dashed item. + * Updates the GC to represent the full information of the dash + * structure. Partly this is already done in Tk_ConfigOutlineGC(). This + * function should be called just before drawing the dashed item. * * Results: - * 1 if there is a stipple pattern. - * 0 otherwise. + * 1 if there is a stipple pattern, and 0 otherwise. * * Side effects: * GC is updated. @@ -1081,10 +1163,10 @@ int Tk_ConfigOutlineGC(gcValues, canvas, item, outline) */ int -Tk_ChangeOutlineGC(canvas, item, outline) - Tk_Canvas canvas; - Tk_Item *item; - Tk_Outline *outline; +Tk_ChangeOutlineGC( + Tk_Canvas canvas, + Tk_Item *item, + Tk_Outline *outline) { CONST char *p; double width; @@ -1134,25 +1216,30 @@ Tk_ChangeOutlineGC(canvas, item, outline) return 0; } - if ((dash->number<-1) || ((dash->number == -1) && (dash->pattern.array[1]!=','))) { + if ((dash->number<-1) || + ((dash->number == -1) && (dash->pattern.array[0] != ','))) { char *q; int i = -dash->number; - p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; + p = (i > (int)sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; q = (char *) ckalloc(2*(unsigned int)i); i = DashConvert(q, p, i, width); - XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, q, i); + XSetDashes(((TkCanvas *)canvas)->display, outline->gc, + outline->offset, q, i); ckfree(q); - } else if ( dash->number>2 || (dash->number==2 && - (dash->pattern.array[0]!=dash->pattern.array[1]))) { - p = (char *) (dash->number > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array; - XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, p, dash->number); + } else if (dash->number>2 || (dash->number==2 && + (dash->pattern.array[0]!=dash->pattern.array[1]))) { + p = (dash->number > (int)sizeof(char *)) + ? dash->pattern.pt : dash->pattern.array; + XSetDashes(((TkCanvas *)canvas)->display, outline->gc, + outline->offset, p, dash->number); } if (stipple!=None) { int w=0; int h=0; Tk_TSOffset *tsoffset = &outline->tsoffset; int flags = tsoffset->flags; - if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) { + if (!(flags & TK_OFFSET_INDEX) && + (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) { Tk_SizeOfBitmap(((TkCanvas *)canvas)->display, stipple, &w, &h); if (flags & TK_OFFSET_CENTER) { w /= 2; @@ -1181,26 +1268,24 @@ Tk_ChangeOutlineGC(canvas, item, outline) * * Tk_ResetOutlineGC * - * Restores the GC to the situation before - * Tk_ChangeDashGC() was called. - * This function should be called just after the dashed - * item is drawn, because the GC is supposed to be - * read-only. + * Restores the GC to the situation before Tk_ChangeDashGC() was called. + * This function should be called just after the dashed item is drawn, + * because the GC is supposed to be read-only. * * Results: - * 1 if there is a stipple pattern. - * 0 otherwise. + * 1 if there is a stipple pattern, and 0 otherwise. * * Side effects: * GC is updated. * *-------------------------------------------------------------- */ + int -Tk_ResetOutlineGC(canvas, item, outline) - Tk_Canvas canvas; - Tk_Item *item; - Tk_Outline *outline; +Tk_ResetOutlineGC( + Tk_Canvas canvas, + Tk_Item *item, + Tk_Outline *outline) { char dashList; double width; @@ -1232,7 +1317,7 @@ Tk_ResetOutlineGC(canvas, item, outline) if (outline->activeStipple!=None) { stipple = outline->activeStipple; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (outline->disabledWidth>width) { width = outline->disabledWidth; } @@ -1251,14 +1336,12 @@ Tk_ResetOutlineGC(canvas, item, outline) } if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 && - (dash->pattern.array[0] != dash->pattern.array[1])) || - ((dash->number == -1) && (dash->pattern.array[1] != ','))) { - if (dash->number < 0) { - dashList = (int) (4 * width + 0.5); - } else if (dash->number<3) { + (dash->pattern.array[0] != dash->pattern.array[1])) || + ((dash->number == -1) && (dash->pattern.array[0] != ','))) { + if (dash->number > 0) { dashList = dash->pattern.array[0]; } else { - dashList = 4; + dashList = (char) (4 * width + 0.5); } XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, &dashList , 1); @@ -1269,30 +1352,30 @@ Tk_ResetOutlineGC(canvas, item, outline) } return 0; } - /* *-------------------------------------------------------------- * * Tk_CanvasPsOutline * - * Creates the postscript command for the correct - * Outline-information (width, dash, color and stipple). + * Creates the postscript command for the correct Outline-information + * (width, dash, color and stipple). * * Results: * TCL_OK if succeeded, otherwise TCL_ERROR. * * Side effects: - * canvas->interp->result contains the postscript string, - * or an error message if the result was TCL_ERROR. + * canvas->interp->result contains the postscript string, or an error + * message if the result was TCL_ERROR. * *-------------------------------------------------------------- */ + int -Tk_CanvasPsOutline(canvas, item, outline) - Tk_Canvas canvas; - Tk_Item *item; - Tk_Outline *outline; +Tk_CanvasPsOutline( + Tk_Canvas canvas, + Tk_Item *item, + Tk_Outline *outline) { char string[41]; char pattern[11]; @@ -1314,6 +1397,7 @@ Tk_CanvasPsOutline(canvas, item, outline) if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } + if (((TkCanvas *)canvas)->currentItemPtr == item) { if (outline->activeWidth > width) { width = outline->activeWidth; @@ -1342,7 +1426,7 @@ Tk_CanvasPsOutline(canvas, item, outline) } } sprintf(string, "%.15g setlinewidth\n", width); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); if (dash->number > 10) { str = (char *)ckalloc((unsigned int) (1 + 4*dash->number)); @@ -1350,38 +1434,40 @@ Tk_CanvasPsOutline(canvas, item, outline) str = (char *)ckalloc((unsigned int) (1 - 8*dash->number)); lptr = (char *)ckalloc((unsigned int) (1 - 2*dash->number)); } - ptr = (char *) ((ABS(dash->number) > sizeof(char *)) ) ? - dash->pattern.pt : dash->pattern.array; + ptr = ((unsigned int)ABS(dash->number) > sizeof(char *)) ? + dash->pattern.pt : dash->pattern.array; if (dash->number > 0) { char *ptr0 = ptr; + sprintf(str, "[%d", *ptr++ & 0xff); i = dash->number-1; while (i--) { sprintf(str+strlen(str), " %d", *ptr++ & 0xff); } - Tcl_AppendResult(interp, str, (char *)NULL); + Tcl_AppendResult(interp, str, NULL); if (dash->number&1) { - Tcl_AppendResult(interp, " ", str+1, (char *)NULL); + Tcl_AppendResult(interp, " ", str+1, NULL); } sprintf(str, "] %d setdash\n", outline->offset); - Tcl_AppendResult(interp, str, (char *)NULL); + Tcl_AppendResult(interp, str, NULL); ptr = ptr0; } else if (dash->number < 0) { if ((i = DashConvert(lptr, ptr, -dash->number, width)) != 0) { char *lptr0 = lptr; + sprintf(str, "[%d", *lptr++ & 0xff); while (--i) { sprintf(str+strlen(str), " %d", *lptr++ & 0xff); } - Tcl_AppendResult(interp, str, (char *)NULL); + Tcl_AppendResult(interp, str, NULL); sprintf(str, "] %d setdash\n", outline->offset); - Tcl_AppendResult(interp, str, (char *)NULL); + Tcl_AppendResult(interp, str, NULL); lptr = lptr0; } else { - Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL); + Tcl_AppendResult(interp, "[] 0 setdash\n", NULL); } } else { - Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL); + Tcl_AppendResult(interp, "[] 0 setdash\n", NULL); } if (str != string) { ckfree(str); @@ -1393,32 +1479,28 @@ Tk_CanvasPsOutline(canvas, item, outline) return TCL_ERROR; } if (stipple != None) { - Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL); + Tcl_AppendResult(interp, "StrokeClip ", NULL); if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) { return TCL_ERROR; } } else { - Tcl_AppendResult(interp, "stroke\n", (char *) NULL); + Tcl_AppendResult(interp, "stroke\n", NULL); } return TCL_OK; } - /* *-------------------------------------------------------------- * * DashConvert * - * Converts a character-like dash-list (e.g. "-..") - * into an X11-style. l must point to a string that - * holds room to at least 2*n characters. if - * l == NULL, this function can be used for - * syntax checking only. + * Converts a character-like dash-list (e.g. "-..") into an X11-style. l + * must point to a string that holds room to at least 2*n characters. If + * l == NULL, this function can be used for syntax checking only. * * Results: - * The length of the resulting X11 compatible - * dash-list. -1 if failed. + * The length of the resulting X11 compatible dash-list. -1 if failed. * * Side effects: * None @@ -1427,11 +1509,13 @@ Tk_CanvasPsOutline(canvas, item, outline) */ static int -DashConvert (l, p, n, width) - char *l; - CONST char *p; - int n; - double width; +DashConvert( + char *l, /* Must be at least 2*n chars long, or NULL to + * indicate "just check syntax". */ + CONST char *p, /* String to parse. */ + int n, /* Length of string to parse, or -1 to + * indicate that strlen() should be used. */ + double width) /* Width of line. */ { int result = 0; int size, intWidth; @@ -1445,30 +1529,28 @@ DashConvert (l, p, n, width) } while (n-- && *p) { switch (*p++) { - case ' ': - if (result) { - if (l) { - l[-1] += intWidth + 1; - } - continue; - } else { - return 0; + case ' ': + if (result) { + if (l) { + l[-1] += intWidth + 1; } - break; - case '_': - size = 8; - break; - case '-': - size = 6; - break; - case ',': - size = 4; - break; - case '.': - size = 2; - break; - default: - return -1; + continue; + } + return 0; + case '_': + size = 8; + break; + case '-': + size = 6; + break; + case ',': + size = 4; + break; + case '.': + size = 2; + break; + default: + return -1; } if (l) { *l++ = size * intWidth; @@ -1482,14 +1564,14 @@ DashConvert (l, p, n, width) /* *---------------------------------------------------------------------- * - * translateAndAppendCoords -- + * TranslateAndAppendCoords -- * * This is a helper routine for TkCanvTranslatePath() below. * - * Given an (x,y) coordinate pair within a canvas, this procedure - * computes the corresponding coordinates at which the point should - * be drawn in the drawable used for display. Those coordinates are - * then written into outArr[numOut*2] and outArr[numOut*2+1]. + * Given an (x,y) coordinate pair within a canvas, this function computes + * the corresponding coordinates at which the point should be drawn in + * the drawable used for display. Those coordinates are then written into + * outArr[numOut*2] and outArr[numOut*2+1]. * * Results: * There is no return value. @@ -1501,11 +1583,12 @@ DashConvert (l, p, n, width) */ static void -translateAndAppendCoords(canvPtr, x, y, outArr, numOut) - TkCanvas *canvPtr; /* The canvas. */ - double x, y; /* Coordinates in canvas space. */ - XPoint *outArr; /* Write results into this array */ - int numOut; /* Num of prior entries in outArr[] */ +TranslateAndAppendCoords( + TkCanvas *canvPtr, /* The canvas. */ + double x, /* Coordinates in canvas space. */ + double y, + XPoint *outArr, /* Write results into this array */ + int numOut) /* Num of prior entries in outArr[] */ { double tmp; @@ -1517,7 +1600,7 @@ translateAndAppendCoords(canvPtr, x, y, outArr, numOut) } outArr[numOut].x = (short) tmp; - tmp = y - canvPtr->drawableYOrigin; + tmp = y - canvPtr->drawableYOrigin; if (tmp > 0) { tmp += 0.5; } else { @@ -1531,225 +1614,262 @@ translateAndAppendCoords(canvPtr, x, y, outArr, numOut) * * TkCanvTranslatePath * - * Translate a line or polygon path so that all vertices are - * within a rectangle that is 1000 pixels larger than the total - * size of the canvas window. This will prevent pixel coordinates - * from overflowing the 16-bit integer size limitation imposed by - * most windowing systems. - * - * coordPtr must point to an array of doubles, two doubles per - * vertex. There are a total of numVertex vertices, or 2*numVertex - * entries in coordPtr. The result vertices written into outArr - * have their coordinate origin shifted to canvPtr->drawableXOrigin - * by canvPtr->drawableYOrigin. There might be as many as 3 times - * more output vertices than there are input vertices. The calling - * function should allocate space accordingly. - * - * This routine limits the width and height of a canvas window - * to 31767 pixels. At the highest resolution display devices - * available today (210 ppi in Jan 2003) that's a window that is - * over 13 feet wide and tall. Should be enough for the near - * future. + * Translate a line or polygon path so that all vertices are within a + * rectangle that is 1000 pixels larger than the total size of the canvas + * window. This will prevent pixel coordinates from overflowing the + * 16-bit integer size limitation imposed by most windowing systems. + * + * coordPtr must point to an array of doubles, two doubles per vertex. + * There are a total of numVertex vertices, or 2*numVertex entries in + * coordPtr. The result vertices written into outArr have their + * coordinate origin shifted to canvPtr->drawableXOrigin by + * canvPtr->drawableYOrigin. There might be as many as 3 times more + * output vertices than there are input vertices. The calling function + * should allocate space accordingly. + * + * This routine limits the width and height of a canvas window to 31767 + * pixels. At the highest resolution display devices available today (210 + * ppi in Jan 2003) that's a window that is over 13 feet wide and tall. + * Should be enough for the near future. * * Results: - * Clipped and translated path vertices are written into outArr[]. - * There might be as many as twice the vertices in outArr[] as there - * are in coordPtr[]. The return value is the number of vertices - * actually written into outArr[]. + * Clipped and translated path vertices are written into outArr[]. There + * might be as many as twice the vertices in outArr[] as there are in + * coordPtr[]. The return value is the number of vertices actually + * written into outArr[]. * * Side effects: * None * *-------------------------------------------------------------- */ + int -TkCanvTranslatePath (canvPtr, numVertex, coordArr, closedPath, outArr) - TkCanvas *canvPtr; /* The canvas */ - int numVertex; /* Number of vertices specified by coordArr[] */ - double *coordArr; /* X and Y coordinates for each vertex */ - int closedPath; /* True if this is a closed polygon */ - XPoint *outArr; /* Write results here, if not NULL */ +TkCanvTranslatePath( + TkCanvas *canvPtr, /* The canvas */ + int numVertex, /* Number of vertices specified by + * coordArr[] */ + double *coordArr, /* X and Y coordinates for each vertex */ + int closedPath, /* True if this is a closed polygon */ + XPoint *outArr) /* Write results here, if not NULL */ { - int numOutput = 0; /* Number of output coordinates */ - double lft, rgh; /* Left and right sides of the bounding box */ - double top, btm; /* Top and bottom sizes of the bounding box */ - double *tempArr; /* Temporary storage used by the clipper */ - double *a, *b, *t; /* Pointers to parts of the temporary storage */ - int i, j; /* Loop counters */ - int maxOutput; /* Maximum number of outputs that we will allow */ - double limit[4]; /* Boundries at which clipping occurs */ - double staticSpace[480]; /* Temp space from the stack */ + int numOutput = 0; /* Number of output coordinates */ + double lft, rgh; /* Left and right sides of the bounding box */ + double top, btm; /* Top and bottom sizes of the bounding box */ + double *tempArr; /* Temporary storage used by the clipper */ + double *a, *b, *t; /* Pointers to parts of the temporary + * storage */ + int i, j; /* Loop counters */ + int maxOutput; /* Maximum number of outputs that we will + * allow */ + double limit[4]; /* Boundries at which clipping occurs */ + double staticSpace[480]; /* Temp space from the stack */ /* - ** Constrain all vertices of the path to be within a box that is no - ** larger than 32000 pixels wide or height. The top-left corner of - ** this clipping box is 1000 pixels above and to the left of the top - ** left corner of the window on which the canvas is displayed. - ** - ** This means that a canvas will not display properly on a canvas - ** window that is larger than 31000 pixels wide or high. That is not - ** a problem today, but might someday become a factor for ultra-high - ** resolutions displays. - ** - ** The X11 protocol allows us (in theory) to expand the size of the - ** clipping box to 32767 pixels. But we have found experimentally that - ** XFree86 sometimes fails to draw lines correctly if they are longer - ** than about 32500 pixels. So we have left a little margin in the - ** size to mask that bug. - */ + * Constrain all vertices of the path to be within a box that is no larger + * than 32000 pixels wide or height. The top-left corner of this clipping + * box is 1000 pixels above and to the left of the top left corner of the + * window on which the canvas is displayed. + * + * This means that a canvas will not display properly on a canvas window + * that is larger than 31000 pixels wide or high. That is not a problem + * today, but might someday become a factor for ultra-high resolutions + * displays. + * + * The X11 protocol allows us (in theory) to expand the size of the + * clipping box to 32767 pixels. But we have found experimentally that + * XFree86 sometimes fails to draw lines correctly if they are longer than + * about 32500 pixels. So we have left a little margin in the size to mask + * that bug. + */ + lft = canvPtr->xOrigin - 1000.0; top = canvPtr->yOrigin - 1000.0; rgh = lft + 32000.0; btm = top + 32000.0; - /* Try the common case first - no clipping. Loop over the input - ** coordinates and translate them into appropriate output coordinates. - ** But if a vertex outside of the bounding box is seen, break out of - ** the loop. - ** - ** Most of the time, no clipping is needed, so this one loop is - ** sufficient to do the translation. - */ - for(i=0; i<numVertex; i++){ - double x, y; - x = coordArr[i*2]; - y = coordArr[i*2+1]; - if( x<lft || x>rgh || y<top || y>btm ) break; - translateAndAppendCoords(canvPtr, x, y, outArr, numOutput++); - } - if( i==numVertex ){ - assert( numOutput==numVertex ); - return numOutput; - } - - /* If we reach this point, it means that some clipping is required. - ** Begin by allocating some working storage - at least 6 times as much space - ** as coordArr[] requires. Divide this space into two separate arrays - ** a[] and b[]. Initialize a[] to be equal to coordArr[]. - */ - if( numVertex*12 <= sizeof(staticSpace)/sizeof(staticSpace[0]) ){ - tempArr = staticSpace; + /* + * Try the common case first - no clipping. Loop over the input + * coordinates and translate them into appropriate output coordinates. + * But if a vertex outside of the bounding box is seen, break out of the + * loop. + * + * Most of the time, no clipping is needed, so this one loop is sufficient + * to do the translation. + */ + + for (i=0; i<numVertex; i++){ + double x, y; + + x = coordArr[i*2]; + y = coordArr[i*2+1]; + if (x<lft || x>rgh || y<top || y>btm) { + break; + } + TranslateAndAppendCoords(canvPtr, x, y, outArr, numOutput++); + } + if (i == numVertex){ + assert(numOutput == numVertex); + return numOutput; + } + + /* + * If we reach this point, it means that some clipping is required. Begin + * by allocating some working storage - at least 6 times as much space as + * coordArr[] requires. Divide this space into two separate arrays a[] and + * b[]. Initialize a[] to be equal to coordArr[]. + */ + + if (numVertex*12 <= (int)(sizeof(staticSpace)/sizeof(staticSpace[0]))) { + tempArr = staticSpace; } else { - tempArr = (double*)ckalloc( numVertex*12*sizeof(tempArr[0]) ); + tempArr = (double *)ckalloc(numVertex*12*sizeof(tempArr[0])); } - for(i=0; i<numVertex*2; i++){ - tempArr[i] = coordArr[i]; + for (i=0; i<numVertex*2; i++){ + tempArr[i] = coordArr[i]; } a = tempArr; b = &tempArr[numVertex*6]; - /* We will make four passes through the input data. On each pass, - ** we copy the contents of a[] over into b[]. As we copy, we clip - ** any line segments that extend to the right past xClip then we - ** rotate the coordinate system 90 degrees clockwise. After each - ** pass is complete, we interchange a[] and b[] in preparation for - ** the next pass. - ** - ** Each pass clips line segments that extend beyond a single side - ** of the bounding box, and four passes rotate the coordinate system - ** back to its original value. I'm not an expert on graphics - ** algorithms, but I think this is called Cohen-Sutherland polygon - ** clipping. - ** - ** The limit[] array contains the xClip value used for each of the - ** four passes. - */ + /* + * We will make four passes through the input data. On each pass, we copy + * the contents of a[] over into b[]. As we copy, we clip any line + * segments that extend to the right past xClip then we rotate the + * coordinate system 90 degrees clockwise. After each pass is complete, we + * interchange a[] and b[] in preparation for the next pass. + * + * Each pass clips line segments that extend beyond a single side of the + * bounding box, and four passes rotate the coordinate system back to its + * original value. I'm not an expert on graphics algorithms, but I think + * this is called Cohen-Sutherland polygon clipping. + * + * The limit[] array contains the xClip value used for each of the four + * passes. + */ + limit[0] = rgh; limit[1] = -top; limit[2] = -lft; limit[3] = btm; - /* This is the loop that makes the four passes through the data. - */ + /* + * This is the loop that makes the four passes through the data. + */ + maxOutput = numVertex*3; - for(j=0; j<4; j++){ - double xClip = limit[j]; - int inside = a[0]<xClip; - double priorY = a[1]; - numOutput = 0; - - /* Clip everything to the right of xClip. Store the results in - ** b[] rotated by 90 degrees clockwise. - */ - for(i=0; i<numVertex; i++){ - double x = a[i*2]; - double y = a[i*2+1]; - if( x>=xClip ){ - /* The current vertex is to the right of xClip. - */ - if( inside ){ - /* If the current vertex is to the right of xClip but - ** the previous vertex was left of xClip, then draw a - ** line segment from the previous vertex to until it - ** intersects the vertical at xClip. - */ - double x0, y0, yN; - assert( i>0 ); - x0 = a[i*2-2]; - y0 = a[i*2-1]; - yN = y0 + (y - y0)*(xClip-x0)/(x-x0); - b[numOutput*2] = -yN; - b[numOutput*2+1] = xClip; - numOutput++; - assert( numOutput<=maxOutput ); - priorY = yN; - inside = 0; - }else if( i==0 ){ - /* If the first vertex is to the right of xClip, add - ** a vertex that is the projection of the first vertex - ** onto the vertical xClip line. - */ - b[0] = -y; - b[1] = xClip; - numOutput = 1; - priorY = y; - } - }else{ - /* The current vertex is to the left of xClip - */ - if( !inside ){ - /* If the current vertex is on the left of xClip and - ** one or more prior vertices where to the right, then - ** we have to draw a line segment along xClip that extends - ** from the spot where we first crossed from left to right - ** to the spot where we cross back from right to left. - */ - double x0, y0, yN; - assert( i>0 ); - x0 = a[i*2-2]; - y0 = a[i*2-1]; - yN = y0 + (y - y0)*(xClip-x0)/(x-x0); - if( yN!=priorY ){ - b[numOutput*2] = -yN; - b[numOutput*2+1] = xClip; - numOutput++; - assert( numOutput<=maxOutput ); - } - inside = 1; - } - b[numOutput*2] = -y; - b[numOutput*2+1] = x; - numOutput++; - assert( numOutput<=maxOutput ); - } - } - - /* Interchange a[] and b[] in preparation for the next pass. - */ - t = a; - a = b; - b = t; - numVertex = numOutput; - } - - /* All clipping is now finished. Convert the coordinates from doubles - ** into XPoints and translate the origin for the drawable. - */ - for(i=0; i<numVertex; i++){ - translateAndAppendCoords(canvPtr, a[i*2], a[i*2+1], outArr, i); - } - if( tempArr!=staticSpace ){ - ckfree((char *) tempArr); + for (j=0; j<4; j++){ + double xClip = limit[j]; + int inside = a[0]<xClip; + double priorY = a[1]; + numOutput = 0; + + /* + * Clip everything to the right of xClip. Store the results in b[] + * rotated by 90 degrees clockwise. + */ + + for (i=0; i<numVertex; i++){ + double x = a[i*2]; + double y = a[i*2+1]; + + if (x >= xClip) { + /* + * The current vertex is to the right of xClip. + */ + + if (inside) { + /* + * If the current vertex is to the right of xClip but the + * previous vertex was left of xClip, then draw a line + * segment from the previous vertex to until it intersects + * the vertical at xClip. + */ + + double x0, y0, yN; + + assert(i > 0); + x0 = a[i*2-2]; + y0 = a[i*2-1]; + yN = y0 + (y - y0)*(xClip-x0)/(x-x0); + b[numOutput*2] = -yN; + b[numOutput*2+1] = xClip; + numOutput++; + assert(numOutput <= maxOutput); + priorY = yN; + inside = 0; + } else if (i == 0) { + /* + * If the first vertex is to the right of xClip, add a + * vertex that is the projection of the first vertex onto + * the vertical xClip line. + */ + + b[0] = -y; + b[1] = xClip; + numOutput = 1; + priorY = y; + } + } else { + /* + * The current vertex is to the left of xClip + */ + if (!inside) { + /* If the current vertex is on the left of xClip and one + * or more prior vertices where to the right, then we have + * to draw a line segment along xClip that extends from + * the spot where we first crossed from left to right to + * the spot where we cross back from right to left. + */ + + double x0, y0, yN; + + assert(i > 0); + x0 = a[i*2-2]; + y0 = a[i*2-1]; + yN = y0 + (y - y0)*(xClip-x0)/(x-x0); + if (yN != priorY) { + b[numOutput*2] = -yN; + b[numOutput*2+1] = xClip; + numOutput++; + assert(numOutput <= maxOutput); + } + inside = 1; + } + b[numOutput*2] = -y; + b[numOutput*2+1] = x; + numOutput++; + assert(numOutput <= maxOutput); + } + } + + /* + * Interchange a[] and b[] in preparation for the next pass. + */ + + t = a; + a = b; + b = t; + numVertex = numOutput; + } + + /* + * All clipping is now finished. Convert the coordinates from doubles into + * XPoints and translate the origin for the drawable. + */ + + for (i=0; i<numVertex; i++){ + TranslateAndAppendCoords(canvPtr, a[i*2], a[i*2+1], outArr, i); + } + if (tempArr != staticSpace) { + ckfree((char *) tempArr); } return numOutput; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvWind.c b/generic/tkCanvWind.c index 96fcadd..b62859c 100644 --- a/generic/tkCanvWind.c +++ b/generic/tkCanvWind.c @@ -1,4 +1,4 @@ -/* +/* * tkCanvWind.c -- * * This file implements window items for canvas widgets. @@ -6,13 +6,12 @@ * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" /* @@ -49,103 +48,99 @@ static Tk_CustomOption tagsOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL, + {TK_CONFIG_ANCHOR, "-anchor", NULL, NULL, "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-height", NULL, NULL, "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_PIXELS, "-width", NULL, NULL, "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_WINDOW, "-window", NULL, NULL, + NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK}, + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas, - WindowItem *winItemPtr)); -static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp, +static void ComputeWindowBbox(Tk_Canvas canvas, + WindowItem *winItemPtr); +static int ConfigureWinItem(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *CONST objv[], int flags); +static int CreateWinItem(Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas, + int objc, Tcl_Obj *CONST objv[]); +static void DeleteWinItem(Tk_Canvas canvas, + Tk_Item *itemPtr, Display *display); +static void DisplayWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static void ScaleWinItem _ANSI_ARGS_((Tk_Canvas canvas, + int x, int y, int width, int height); +static void ScaleWinItem(Tk_Canvas canvas, Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); -static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp, + double scaleX, double scaleY); +static void TranslateWinItem(Tk_Canvas canvas, + Tk_Item *itemPtr, double deltaX, double deltaY); +static int WinItemCoords(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[])); -static void WinItemLostSlaveProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin)); -static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void WinItemStructureProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *rectPtr)); -static int WinItemToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *pointPtr)); + Tcl_Obj *CONST objv[]); +static void WinItemLostSlaveProc(ClientData clientData, + Tk_Window tkwin); +static void WinItemRequestProc(ClientData clientData, + Tk_Window tkwin); +static void WinItemStructureProc(ClientData clientData, + XEvent *eventPtr); +static int WinItemToArea(Tk_Canvas canvas, + Tk_Item *itemPtr, double *rectPtr); +static int WinItemToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static double WinItemToPoint(Tk_Canvas canvas, + Tk_Item *itemPtr, double *pointPtr); #ifdef X_GetImage -static int xerrorhandler _ANSI_ARGS_((ClientData clientData, - XErrorEvent *e)); +static int xerrorhandler(ClientData clientData, XErrorEvent *e); #endif -static int CanvasPsWindow _ANSI_ARGS_((Tcl_Interp *interp, +static int CanvasPsWindow(Tcl_Interp *interp, Tk_Window tkwin, Tk_Canvas canvas, double x, - double y, int width, int height)); + double y, int width, int height); /* - * The structure below defines the window item type by means of procedures + * The structure below defines the window item type by means of functions * that can be invoked by generic item code. */ Tk_ItemType tkWindowType = { - "window", /* name */ - sizeof(WindowItem), /* itemSize */ - CreateWinItem, /* createProc */ - configSpecs, /* configSpecs */ - ConfigureWinItem, /* configureProc */ - WinItemCoords, /* coordProc */ - DeleteWinItem, /* deleteProc */ - DisplayWinItem, /* displayProc */ - 1|TK_CONFIG_OBJS, /* flags */ - WinItemToPoint, /* pointProc */ - WinItemToArea, /* areaProc */ - WinItemToPostscript, /* postscriptProc */ - ScaleWinItem, /* scaleProc */ - TranslateWinItem, /* translateProc */ - (Tk_ItemIndexProc *) NULL, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* cursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ - (Tk_ItemInsertProc *) NULL, /* insertProc */ - (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + "window", /* name */ + sizeof(WindowItem), /* itemSize */ + CreateWinItem, /* createProc */ + configSpecs, /* configSpecs */ + ConfigureWinItem, /* configureProc */ + WinItemCoords, /* coordProc */ + DeleteWinItem, /* deleteProc */ + DisplayWinItem, /* displayProc */ + 1|TK_CONFIG_OBJS, /* flags */ + WinItemToPoint, /* pointProc */ + WinItemToArea, /* areaProc */ + WinItemToPostscript, /* postscriptProc */ + ScaleWinItem, /* scaleProc */ + TranslateWinItem, /* translateProc */ + NULL, /* indexProc */ + NULL, /* cursorProc */ + NULL, /* selectionProc */ + NULL, /* insertProc */ + NULL, /* dTextProc */ + NULL, /* nextPtr */ }; - /* - * The structure below defines the official type record for the - * placer: + * The structure below defines the official type record for the canvas (as + * geometry manager): */ -static Tk_GeomMgr canvasGeomType = { +static const Tk_GeomMgr canvasGeomType = { "canvas", /* name */ WinItemRequestProc, /* requestProc */ WinItemLostSlaveProc, /* lostSlaveProc */ @@ -156,14 +151,12 @@ static Tk_GeomMgr canvasGeomType = { * * CreateWinItem -- * - * This procedure is invoked to create a new window - * item in a canvas. + * This function is invoked to create a new window item in a canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is - * left uninitialized, so it can be safely freed by the + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the * caller. * * Side effects: @@ -173,19 +166,19 @@ static Tk_GeomMgr canvasGeomType = { */ static int -CreateWinItem(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing window. */ +CreateWinItem( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing window. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* @@ -199,8 +192,8 @@ CreateWinItem(interp, canvas, itemPtr, objc, objv) winItemPtr->canvas = canvas; /* - * Process the arguments to fill in the item record. - * Only 1 (list) or 2 (x y) coords are allowed. + * Process the arguments to fill in the item record. Only 1 (list) or 2 (x + * y) coords are allowed. */ if (objc == 1) { @@ -220,7 +213,7 @@ CreateWinItem(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -230,9 +223,8 @@ CreateWinItem(interp, canvas, itemPtr, objc, objv) * * WinItemCoords -- * - * This procedure is invoked to process the "coords" widget - * command on window items. See the user documentation for - * details on what it does. + * This function is invoked to process the "coords" widget command on + * window items. See the user documentation for details on what it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -244,15 +236,13 @@ CreateWinItem(interp, canvas, itemPtr, objc, objv) */ static int -WinItemCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +WinItemCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1, y1, x2, y2, ... */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; @@ -297,12 +287,12 @@ WinItemCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureWinItem -- * - * This procedure is invoked to configure various aspects - * of a window item, such as its anchor position. + * This function is invoked to configure various aspects of a window + * item, such as its anchor position. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: * Configuration information may be set for itemPtr. @@ -311,13 +301,13 @@ WinItemCoords(interp, canvas, itemPtr, objc, objv) */ static int -ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Window item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureWinItem( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Window item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window oldWindow; @@ -338,8 +328,7 @@ ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags) if (oldWindow != NULL) { Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, WinItemStructureProc, (ClientData) winItemPtr); - Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL, - (ClientData) NULL); + Tk_ManageGeometry(oldWindow, NULL, (ClientData) NULL); Tk_UnmaintainGeometry(oldWindow, canvasTkwin); Tk_UnmapWindow(oldWindow); } @@ -347,10 +336,10 @@ ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags) Tk_Window ancestor, parent; /* - * Make sure that the canvas is either the parent of the - * window associated with the item or a descendant of that - * parent. Also, don't allow a top-of-hierarchy window to be - * managed inside a canvas. + * Make sure that the canvas is either the parent of the window + * associated with the item or a descendant of that parent. Also, + * don't allow a top-of-hierarchy window to be managed inside a + * canvas. */ parent = Tk_Parent(winItemPtr->tkwin); @@ -360,10 +349,10 @@ ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags) break; } if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) { - badWindow: + badWindow: Tcl_AppendResult(interp, "can't use ", Tk_PathName(winItemPtr->tkwin), - " in a window item of this canvas", (char *) NULL); + " in a window item of this canvas", NULL); winItemPtr->tkwin = NULL; return TCL_ERROR; } @@ -399,8 +388,8 @@ ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags) * * DeleteWinItem -- * - * This procedure is called to clean up the data structure - * associated with a window item. + * This function is called to clean up the data structure associated with + * a window item. * * Results: * None. @@ -412,11 +401,10 @@ ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteWinItem(canvas, itemPtr, display) - Tk_Canvas canvas; /* Overall info about widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeleteWinItem( + Tk_Canvas canvas, /* Overall info about widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas); @@ -424,7 +412,7 @@ DeleteWinItem(canvas, itemPtr, display) if (winItemPtr->tkwin != NULL) { Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, (ClientData) winItemPtr); - Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL, + Tk_ManageGeometry(winItemPtr->tkwin, NULL, (ClientData) NULL); if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); @@ -438,26 +426,23 @@ DeleteWinItem(canvas, itemPtr, display) * * ComputeWindowBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a window item. - * This procedure is where the child window's placement is - * computed. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a window item. This function is where the + * child window's placement is computed. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ static void -ComputeWindowBbox(canvas, winItemPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - WindowItem *winItemPtr; /* Item whose bbox is to be - * recomputed. */ +ComputeWindowBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + WindowItem *winItemPtr) /* Item whose bbox is to be recomputed. */ { int width, height, x, y; Tk_State state = winItemPtr->header.state; @@ -470,10 +455,10 @@ ComputeWindowBbox(canvas, winItemPtr) } if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) { /* - * There is no window for this item yet. Just give it a 1x1 - * bounding box. Don't give it a 0x0 bounding box; there are - * strange cases where this bounding box might be used as the - * dimensions of the window, and 0x0 causes problems under X. + * There is no window for this item yet. Just give it a 1x1 bounding + * box. Don't give it a 0x0 bounding box; there are strange cases + * where this bounding box might be used as the dimensions of the + * window, and 0x0 causes problems under X. */ winItemPtr->header.x1 = x; @@ -507,36 +492,36 @@ ComputeWindowBbox(canvas, winItemPtr) */ switch (winItemPtr->anchor) { - case TK_ANCHOR_N: - x -= width/2; - break; - case TK_ANCHOR_NE: - x -= width; - break; - case TK_ANCHOR_E: - x -= width; - y -= height/2; - break; - case TK_ANCHOR_SE: - x -= width; - y -= height; - break; - case TK_ANCHOR_S: - x -= width/2; - y -= height; - break; - case TK_ANCHOR_SW: - y -= height; - break; - case TK_ANCHOR_W: - y -= height/2; - break; - case TK_ANCHOR_NW: - break; - case TK_ANCHOR_CENTER: - x -= width/2; - y -= height/2; - break; + case TK_ANCHOR_N: + x -= width/2; + break; + case TK_ANCHOR_NE: + x -= width; + break; + case TK_ANCHOR_E: + x -= width; + y -= height/2; + break; + case TK_ANCHOR_SE: + x -= width; + y -= height; + break; + case TK_ANCHOR_S: + x -= width/2; + y -= height; + break; + case TK_ANCHOR_SW: + y -= height; + break; + case TK_ANCHOR_W: + y -= height/2; + break; + case TK_ANCHOR_NW: + break; + case TK_ANCHOR_CENTER: + x -= width/2; + y -= height/2; + break; } /* @@ -554,36 +539,32 @@ ComputeWindowBbox(canvas, winItemPtr) * * DisplayWinItem -- * - * This procedure is invoked to "draw" a window item in a given - * drawable. Since the window draws itself, we needn't do any - * actual redisplay here. However, this procedure takes care - * of actually repositioning the child window so that it occupies - * the correct screen position. + * This function is invoked to "draw" a window item in a given drawable. + * Since the window draws itself, we needn't do any actual redisplay + * here. However, this function takes care of actually repositioning the + * child window so that it occupies the correct screen position. * * Results: * None. * * Side effects: - * The child window's position may get changed. Note: this - * procedure gets called both when a window needs to be displayed - * and when it ceases to be visible on the screen (e.g. it was - * scrolled or moved off-screen or the enclosing canvas is - * unmapped). + * The child window's position may get changed. Note: this function gets + * called both when a window needs to be displayed and when it ceases to + * be visible on the screen (e.g. it was scrolled or moved off-screen or + * the enclosing canvas is unmapped). * *-------------------------------------------------------------- */ static void -DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, - regionWidth, regionHeight) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int regionX, regionY, regionWidth, regionHeight; - /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayWinItem( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int regionX, int regionY, int regionWidth, int regionHeight) + /* Describes region of canvas that must be + * redisplayed (not used). */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; int width, height; @@ -616,16 +597,16 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, height = winItemPtr->header.y2 - winItemPtr->header.y1; /* - * If the window is completely out of the visible area of the canvas - * then unmap it. This code used not to be present (why unmap the - * window if it isn't visible anyway?) but this could cause the - * window to suddenly reappear if the canvas window got resized. + * If the window is completely out of the visible area of the canvas then + * unmap it. This code used not to be present (why unmap the window if it + * isn't visible anyway?) but this could cause the window to suddenly + * reappear if the canvas window got resized. */ if (((x + width) <= 0) || ((y + height) <= 0) || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) { if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { - Tk_UnmapWindow(winItemPtr->tkwin); + Tk_UnmapWindow(winItemPtr->tkwin); } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } @@ -633,8 +614,8 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, } /* - * Reposition and map the window (but in different ways depending - * on whether the canvas is the window's parent). + * Reposition and map the window (but in different ways depending on + * whether the canvas is the window's parent). */ if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { @@ -655,14 +636,14 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, * * WinItemToPoint -- * - * Computes the distance from a given point to a given - * window, in canvas units. + * Computes the distance from a given point to a given window, in canvas + * units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are coordPtr[0] and coordPtr[1] is inside the window. If the - * point isn't inside the window then the return value is the - * distance from the point to the window. + * The return value is 0 if the point whose x and y coordinates are + * coordPtr[0] and coordPtr[1] is inside the window. If the point isn't + * inside the window then the return value is the distance from the point + * to the window. * * Side effects: * None. @@ -671,10 +652,10 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, */ static double -WinItemToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +WinItemToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; double x1, x2, y1, y2, xDiff, yDiff; @@ -712,14 +693,13 @@ WinItemToPoint(canvas, itemPtr, pointPtr) * * WinItemToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangle. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangle. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -728,11 +708,11 @@ WinItemToPoint(canvas, itemPtr, pointPtr) */ static int -WinItemToArea(canvas, itemPtr, rectPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against rectangle. */ - double *rectPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular +WinItemToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against rectangle. */ + double *rectPtr) /* Pointer to array of four coordinates + * (x1,y1,x2,y2) describing rectangular * area. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; @@ -757,8 +737,8 @@ WinItemToArea(canvas, itemPtr, rectPtr) * * xerrorhandler -- * - * This is a dummy function to catch X11 errors during an - * attempt to print a canvas window. + * This is a dummy function to catch X11 errors during an attempt to + * print a canvas window. * * Results: * None. @@ -771,11 +751,11 @@ WinItemToArea(canvas, itemPtr, rectPtr) #ifdef X_GetImage static int -xerrorhandler(clientData, e) - ClientData clientData; - XErrorEvent *e; +xerrorhandler( + ClientData clientData, + XErrorEvent *e) { - return 0; + return 0; } #endif @@ -785,15 +765,13 @@ xerrorhandler(clientData, e) * * WinItemToPostscript -- * - * This procedure is called to generate Postscript for - * window items. + * This function is called to generate Postscript for window items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in interp->result, replacing whatever used to be there. - * If no error occurs, then Postscript for the item is appended - * to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in interp->result, + * replacing whatever used to be there. If no error occurs, then + * Postscript for the item is appended to the result. * * Side effects: * None. @@ -802,15 +780,13 @@ xerrorhandler(clientData, e) */ static int -WinItemToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created.*/ +WinItemToPostscript( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { WindowItem *winItemPtr = (WindowItem *)itemPtr; @@ -821,80 +797,75 @@ WinItemToPostscript(interp, canvas, itemPtr, prepass) if (prepass || winItemPtr->tkwin == NULL) { return TCL_OK; } - + width = Tk_Width(tkwin); height = Tk_Height(tkwin); /* - * Compute the coordinates of the lower-left corner of the window, - * taking into account the anchor position for the window. + * Compute the coordinates of the lower-left corner of the window, taking + * into account the anchor position for the window. */ x = winItemPtr->x; y = Tk_CanvasPsY(canvas, winItemPtr->y); - + switch (winItemPtr->anchor) { - case TK_ANCHOR_NW: y -= height; break; - case TK_ANCHOR_N: x -= width/2.0; y -= height; break; - case TK_ANCHOR_NE: x -= width; y -= height; break; - case TK_ANCHOR_E: x -= width; y -= height/2.0; break; - case TK_ANCHOR_SE: x -= width; break; - case TK_ANCHOR_S: x -= width/2.0; break; - case TK_ANCHOR_SW: break; - case TK_ANCHOR_W: y -= height/2.0; break; - case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; + case TK_ANCHOR_NW: y -= height; break; + case TK_ANCHOR_N: x -= width/2.0; y -= height; break; + case TK_ANCHOR_NE: x -= width; y -= height; break; + case TK_ANCHOR_E: x -= width; y -= height/2.0; break; + case TK_ANCHOR_SE: x -= width; break; + case TK_ANCHOR_S: x -= width/2.0; break; + case TK_ANCHOR_SW: break; + case TK_ANCHOR_W: y -= height/2.0; break; + case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; } return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height); } - + static int -CanvasPsWindow(interp, tkwin, canvas, x, y, width, height) - Tcl_Interp *interp; /* Leave Postscript or error message - * here. */ - Tk_Window tkwin; /* window to be printed */ - Tk_Canvas canvas; /* Information about overall canvas. */ - double x, y; /* origin of window. */ - int width, height; /* width/height of window. */ +CanvasPsWindow( + Tcl_Interp *interp, /* Leave Postscript or error message here. */ + Tk_Window tkwin, /* window to be printed */ + Tk_Canvas canvas, /* Information about overall canvas. */ + double x, double y, /* origin of window. */ + int width, int height) /* width/height of window. */ { char buffer[256]; XImage *ximage; int result; Tcl_DString buffer1, buffer2; #ifdef X_GetImage - Tk_ErrorHandler handle; + Tk_ErrorHandler handle; #endif sprintf(buffer, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n", Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); - /* first try if the widget has its own "postscript" command. If it - * exists, this will produce much better postscript than - * when a pixmap is used. + /* + * First try if the widget has its own "postscript" command. If it exists, + * this will produce much better postscript than when a pixmap is used. */ Tcl_DStringInit(&buffer1); Tcl_DStringInit(&buffer2); Tcl_DStringGetResult(interp, &buffer2); - sprintf (buffer, "%s postscript -prolog 0\n", Tk_PathName(tkwin)); + sprintf(buffer, "%s postscript -prolog 0\n", Tk_PathName(tkwin)); result = Tcl_Eval(interp, buffer); Tcl_DStringGetResult(interp, &buffer1); Tcl_DStringResult(interp, &buffer2); Tcl_DStringFree(&buffer2); if (result == TCL_OK) { - Tcl_AppendResult(interp, - "50 dict begin\nsave\ngsave\n", - (char *) NULL); - sprintf (buffer, - "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d", + Tcl_AppendResult(interp, "50 dict begin\nsave\ngsave\n", NULL); + sprintf(buffer, "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d", height, width, height, width); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); Tcl_AppendResult(interp, " 0 rlineto closepath\n", "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n", - Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n", - (char *) NULL); + Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n", NULL); Tcl_DStringFree(&buffer1); return result; @@ -902,17 +873,18 @@ CanvasPsWindow(interp, tkwin, canvas, x, y, width, height) Tcl_DStringFree(&buffer1); /* - * If the window is off the screen it will generate an BadMatch/XError - * We catch any BadMatch errors here + * If the window is off the screen it will generate a BadMatch/XError. We + * catch any BadMatch errors here */ + #ifdef X_GetImage handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch, X_GetImage, -1, xerrorhandler, (ClientData) tkwin); #endif /* - * Generate an XImage from the window. We can then read pixel - * values out of the XImage. + * Generate an XImage from the window. We can then read pixel values out + * of the XImage. */ ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0, @@ -922,7 +894,7 @@ CanvasPsWindow(interp, tkwin, canvas, x, y, width, height) Tk_DeleteErrorHandler(handle); #endif - if (ximage == (XImage*) NULL) { + if (ximage == NULL) { return TCL_OK; } @@ -938,15 +910,14 @@ CanvasPsWindow(interp, tkwin, canvas, x, y, width, height) * * ScaleWinItem -- * - * This procedure is invoked to rescale a window item. + * This function is invoked to rescale a window item. * * Results: * None. * * Side effects: - * The window referred to by itemPtr is rescaled - * so that the following transformation is applied to all - * point coordinates: + * The window referred to by itemPtr is rescaled so that the following + * transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -954,12 +925,13 @@ CanvasPsWindow(interp, tkwin, canvas, x, y, width, height) */ static void -ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing window. */ - Tk_Item *itemPtr; /* Window to be scaled. */ - double originX, originY; /* Origin about which to scale window. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleWinItem( + Tk_Canvas canvas, /* Canvas containing window. */ + Tk_Item *itemPtr, /* Window to be scaled. */ + double originX, double originY, + /* Origin about which to scale window. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; @@ -979,25 +951,24 @@ ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateWinItem -- * - * This procedure is called to move a window by a given amount. + * This function is called to move a window by a given amount. * * Results: * None. * * Side effects: - * The position of the window is offset by (xDelta, yDelta), - * and the bounding box is updated in the generic part of the - * item structure. + * The position of the window is offset by (xDelta, yDelta), and the + * bounding box is updated in the generic part of the item structure. * *-------------------------------------------------------------- */ static void -TranslateWinItem(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslateWinItem( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; @@ -1011,25 +982,23 @@ TranslateWinItem(canvas, itemPtr, deltaX, deltaY) * * WinItemStructureProc -- * - * This procedure is invoked whenever StructureNotify events - * occur for a window that's managed as part of a canvas window - * item. This procudure's only purpose is to clean up when - * windows are deleted. + * This function is invoked whenever StructureNotify events occur for a + * window that's managed as part of a canvas window item. This function's + * only purpose is to clean up when windows are deleted. * * Results: * None. * * Side effects: - * The window is disassociated from the window item when it is - * deleted. + * The window is disassociated from the window item when it is deleted. * *-------------------------------------------------------------- */ static void -WinItemStructureProc(clientData, eventPtr) - ClientData clientData; /* Pointer to record describing window item. */ - XEvent *eventPtr; /* Describes what just happened. */ +WinItemStructureProc( + ClientData clientData, /* Pointer to record describing window item. */ + XEvent *eventPtr) /* Describes what just happened. */ { WindowItem *winItemPtr = (WindowItem *) clientData; @@ -1043,8 +1012,8 @@ WinItemStructureProc(clientData, eventPtr) * * WinItemRequestProc -- * - * This procedure is invoked whenever a window that's associated - * with a window canvas item changes its requested dimensions. + * This function is invoked whenever a window that's associated with a + * window canvas item changes its requested dimensions. * * Results: * None. @@ -1057,10 +1026,9 @@ WinItemStructureProc(clientData, eventPtr) */ static void -WinItemRequestProc(clientData, tkwin) - ClientData clientData; /* Pointer to record for window item. */ - Tk_Window tkwin; /* Window that changed its desired - * size. */ +WinItemRequestProc( + ClientData clientData, /* Pointer to record for window item. */ + Tk_Window tkwin) /* Window that changed its desired size. */ { WindowItem *winItemPtr = (WindowItem *) clientData; @@ -1080,8 +1048,8 @@ WinItemRequestProc(clientData, tkwin) * * WinItemLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This function is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. @@ -1094,10 +1062,10 @@ WinItemRequestProc(clientData, tkwin) /* ARGSUSED */ static void -WinItemLostSlaveProc(clientData, tkwin) - ClientData clientData; /* WindowItem structure for slave window that +WinItemLostSlaveProc( + ClientData clientData, /* WindowItem structure for slave window that * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { WindowItem *winItemPtr = (WindowItem *) clientData; Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas); @@ -1110,3 +1078,11 @@ WinItemLostSlaveProc(clientData, tkwin) Tk_UnmapWindow(winItemPtr->tkwin); winItemPtr->tkwin = NULL; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c index 8f9641f..14fe1ab 100644 --- a/generic/tkCanvas.c +++ b/generic/tkCanvas.c @@ -1,23 +1,22 @@ -/* +/* * tkCanvas.c -- * - * This module implements canvas widgets for the Tk toolkit. - * A canvas displays a background and a collection of graphical - * objects such as rectangles, lines, and texts. + * This module implements canvas widgets for the Tk toolkit. A canvas + * displays a background and a collection of graphical objects such as + * rectangles, lines, and texts. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* #define USE_OLD_TAG_SEARCH 1 */ #include "default.h" #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" #ifdef TK_NO_DOUBLE_BUFFERING #ifdef MAC_OSX_TK @@ -31,32 +30,29 @@ #ifdef USE_OLD_TAG_SEARCH /* - * The structure defined below is used to keep track of a tag search - * in progress. No field should be accessed by anyone other than - * StartTagSearch and NextItem. + * The structure defined below is used to keep track of a tag search in + * progress. No field should be accessed by anyone other than StartTagSearch + * and NextItem. */ typedef struct TagSearch { TkCanvas *canvasPtr; /* Canvas widget being searched. */ - Tk_Uid tag; /* Tag to search for. 0 means return - * all items. */ + Tk_Uid tag; /* Tag to search for. 0 means return all + * items. */ Tk_Item *currentPtr; /* Pointer to last item returned. */ - Tk_Item *lastPtr; /* The item right before the currentPtr - * is tracked so if the currentPtr is - * deleted we don't have to start from the - * beginning. */ + Tk_Item *lastPtr; /* The item right before the currentPtr is + * tracked so if the currentPtr is deleted we + * don't have to start from the beginning. */ int searchOver; /* Non-zero means NextItem should always * return NULL. */ } TagSearch; #else /* USE_OLD_TAG_SEARCH */ /* - * The structure defined below is used to keep track of a tag search - * in progress. No field should be accessed by anyone other than - * TagSearchScan, TagSearchFirst, TagSearchNext, - * TagSearchScanExpr, TagSearchEvalExpr, - * TagSearchExprInit, TagSearchExprDestroy, - * TagSearchDestroy. + * The structure defined below is used to keep track of a tag search in + * progress. No field should be accessed by anyone other than TagSearchScan, + * TagSearchFirst, TagSearchNext, TagSearchScanExpr, TagSearchEvalExpr, + * TagSearchExprInit, TagSearchExprDestroy, TagSearchDestroy. * ( * Not quite accurate: the TagSearch structure is also accessed from: * CanvasWidgetCmd, FindItems, RelinkItems @@ -72,24 +68,32 @@ typedef struct TagSearch { typedef struct TagSearch { TkCanvas *canvasPtr; /* Canvas widget being searched. */ Tk_Item *currentPtr; /* Pointer to last item returned. */ - Tk_Item *lastPtr; /* The item right before the currentPtr - * is tracked so if the currentPtr is - * deleted we don't have to start from the - * beginning. */ + Tk_Item *lastPtr; /* The item right before the currentPtr is + * tracked so if the currentPtr is deleted we + * don't have to start from the beginning. */ int searchOver; /* Non-zero means NextItem should always * return NULL. */ - int type; /* search type */ - int id; /* item id for searches by id */ + int type; /* Search type (see #defs below) */ + int id; /* Item id for searches by id */ + char *string; /* Tag expression string */ + int stringIndex; /* Current position in string scan */ + int stringLength; /* Length of tag expression string */ + char *rewritebuffer; /* Tag string (after removing escapes) */ + unsigned int rewritebufferAllocated; + /* Available space for rewrites. */ + TagSearchExpr *expr; /* Compiled tag expression. */ +} TagSearch; - char *string; /* tag expression string */ - int stringIndex; /* current position in string scan */ - int stringLength; /* length of tag expression string */ +/* + * Values for the TagSearch type field. + */ - char *rewritebuffer; /* tag string (after removing escapes) */ - unsigned int rewritebufferAllocated; /* available space for rewrites */ +#define SEARCH_TYPE_EMPTY 0 /* Looking for empty tag */ +#define SEARCH_TYPE_ID 1 /* Looking for an item by id */ +#define SEARCH_TYPE_ALL 2 /* Looking for all items */ +#define SEARCH_TYPE_TAG 3 /* Looking for an item by simple tag */ +#define SEARCH_TYPE_EXPR 4 /* Compound search */ - TagSearchExpr *expr; /* compiled tag expression */ -} TagSearch; #endif /* USE_OLD_TAG_SEARCH */ /* @@ -119,10 +123,8 @@ static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_CANVAS_BG_MONO, Tk_Offset(TkCanvas, bgBorder), TK_CONFIG_MONO_ONLY}, - {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, - (char *) NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0}, {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_CANVAS_BORDER_WIDTH, Tk_Offset(TkCanvas, borderWidth), 0}, {TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough", @@ -203,13 +205,12 @@ static Tk_ConfigSpec configSpecs[] = { "ScrollIncrement", DEF_CANVAS_Y_SCROLL_INCREMENT, Tk_Offset(TkCanvas, yScrollIncrement), 0}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * List of all the item types known at present. This is *global* and - * is protected by typeListMutex. + * List of all the item types known at present. This is *global* and is + * protected by typeListMutex. */ static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't @@ -218,9 +219,10 @@ TCL_DECLARE_MUTEX(typeListMutex) #ifndef USE_OLD_TAG_SEARCH /* - * Uids for operands in compiled advanced tag search expressions + * Uids for operands in compiled advanced tag search expressions. * Initialization is done by GetStaticUids() */ + typedef struct { Tk_Uid allUid; Tk_Uid currentUid; @@ -235,107 +237,89 @@ typedef struct { } SearchUids; static Tcl_ThreadDataKey dataKey; -static SearchUids *GetStaticUids _ANSI_ARGS_((void)); +static SearchUids * GetStaticUids(void); #endif /* USE_OLD_TAG_SEARCH */ /* - * Standard item types provided by Tk: + * Prototypes for functions defined later in this file: */ -extern Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType; -extern Tk_ItemType tkOvalType, tkPolygonType; -extern Tk_ItemType tkRectangleType, tkTextType, tkWindowType; - -/* - * Prototypes for procedures defined later in this file: - */ - -static void CanvasBindProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void CanvasBlinkProc _ANSI_ARGS_((ClientData clientData)); -static void CanvasCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void CanvasDoEvent _ANSI_ARGS_((TkCanvas *canvasPtr, - XEvent *eventPtr)); -static void CanvasEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int CanvasFetchSelection _ANSI_ARGS_(( - ClientData clientData, int offset, - char *buffer, int maxBytes)); -static Tk_Item * CanvasFindClosest _ANSI_ARGS_((TkCanvas *canvasPtr, - double coords[2])); -static void CanvasFocusProc _ANSI_ARGS_((TkCanvas *canvasPtr, - int gotFocus)); -static void CanvasLostSelection _ANSI_ARGS_(( - ClientData clientData)); -static void CanvasSelectTo _ANSI_ARGS_((TkCanvas *canvasPtr, - Tk_Item *itemPtr, int index)); -static void CanvasSetOrigin _ANSI_ARGS_((TkCanvas *canvasPtr, - int xOrigin, int yOrigin)); -static void CanvasUpdateScrollbars _ANSI_ARGS_(( - TkCanvas *canvasPtr)); -static int CanvasWidgetCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, Tcl_Obj *CONST *argv)); -static void CanvasWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static int ConfigureCanvas _ANSI_ARGS_((Tcl_Interp *interp, - TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv, - int flags)); -static void DestroyCanvas _ANSI_ARGS_((char *memPtr)); -static void DisplayCanvas _ANSI_ARGS_((ClientData clientData)); -static void DoItem _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Item *itemPtr, Tk_Uid tag)); -static void EventuallyRedrawItem _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr)); +static void CanvasBindProc(ClientData clientData, + XEvent *eventPtr); +static void CanvasBlinkProc(ClientData clientData); +static void CanvasCmdDeletedProc(ClientData clientData); +static void CanvasDoEvent(TkCanvas *canvasPtr, XEvent *eventPtr); +static void CanvasEventProc(ClientData clientData, + XEvent *eventPtr); +static int CanvasFetchSelection(ClientData clientData, int offset, + char *buffer, int maxBytes); +static Tk_Item * CanvasFindClosest(TkCanvas *canvasPtr, + double coords[2]); +static void CanvasFocusProc(TkCanvas *canvasPtr, int gotFocus); +static void CanvasLostSelection(ClientData clientData); +static void CanvasSelectTo(TkCanvas *canvasPtr, + Tk_Item *itemPtr, int index); +static void CanvasSetOrigin(TkCanvas *canvasPtr, + int xOrigin, int yOrigin); +static void CanvasUpdateScrollbars(TkCanvas *canvasPtr); +static int CanvasWidgetCmd(ClientData clientData, + Tcl_Interp *interp, int argc, + Tcl_Obj *CONST *argv); +static void CanvasWorldChanged( + ClientData instanceData); +static int ConfigureCanvas(Tcl_Interp *interp, + TkCanvas *canvasPtr, int argc, + Tcl_Obj *CONST *argv, int flags); +static void DestroyCanvas(char *memPtr); +static void DisplayCanvas(ClientData clientData); +static void DoItem(Tcl_Interp *interp, + Tk_Item *itemPtr, Tk_Uid tag); +static void EventuallyRedrawItem(Tk_Canvas canvas, + Tk_Item *itemPtr); #ifdef USE_OLD_TAG_SEARCH -static int FindItems _ANSI_ARGS_((Tcl_Interp *interp, - TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv, - Tcl_Obj *newTagObj, int first)); +static int FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr, + int argc, Tcl_Obj *CONST *argv, + Tcl_Obj *newTagObj, int first); #else /* USE_OLD_TAG_SEARCH */ -static int FindItems _ANSI_ARGS_((Tcl_Interp *interp, - TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv, +static int FindItems(Tcl_Interp *interp, TkCanvas *canvasPtr, + int argc, Tcl_Obj *CONST *argv, Tcl_Obj *newTagObj, int first, - TagSearch **searchPtrPtr)); + TagSearch **searchPtrPtr); #endif /* USE_OLD_TAG_SEARCH */ -static int FindArea _ANSI_ARGS_((Tcl_Interp *interp, - TkCanvas *canvasPtr, Tcl_Obj *CONST *argv, Tk_Uid uid, - int enclosed)); -static double GridAlign _ANSI_ARGS_((double coord, double spacing)); -static CONST char** GetStringsFromObjs _ANSI_ARGS_((int argc, - Tcl_Obj *CONST *objv)); -static void InitCanvas _ANSI_ARGS_((void)); +static int FindArea(Tcl_Interp *interp, TkCanvas *canvasPtr, + Tcl_Obj *CONST *argv, Tk_Uid uid, int enclosed); +static double GridAlign(double coord, double spacing); +static CONST char** TkGetStringsFromObjs(int argc, Tcl_Obj *CONST *objv); +static void InitCanvas(void); #ifdef USE_OLD_TAG_SEARCH -static Tk_Item * NextItem _ANSI_ARGS_((TagSearch *searchPtr)); +static Tk_Item * NextItem(TagSearch *searchPtr); #endif /* USE_OLD_TAG_SEARCH */ -static void PickCurrentItem _ANSI_ARGS_((TkCanvas *canvasPtr, - XEvent *eventPtr)); -static Tcl_Obj * ScrollFractions _ANSI_ARGS_((int screen1, - int screen2, int object1, int object2)); +static void PickCurrentItem(TkCanvas *canvasPtr, XEvent *eventPtr); +static Tcl_Obj * ScrollFractions(int screen1, + int screen2, int object1, int object2); #ifdef USE_OLD_TAG_SEARCH -static void RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr, - Tcl_Obj *tag, Tk_Item *prevPtr)); -static Tk_Item * StartTagSearch _ANSI_ARGS_((TkCanvas *canvasPtr, - Tcl_Obj *tag, TagSearch *searchPtr)); +static void RelinkItems(TkCanvas *canvasPtr, + Tcl_Obj *tag, Tk_Item *prevPtr); +static Tk_Item * StartTagSearch(TkCanvas *canvasPtr, + Tcl_Obj *tag, TagSearch *searchPtr); #else /* USE_OLD_TAG_SEARCH */ -static int RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr, - Tcl_Obj *tag, Tk_Item *prevPtr, - TagSearch **searchPtrPtr)); -static void TagSearchExprInit _ANSI_ARGS_ (( - TagSearchExpr **exprPtrPtr)); -static void TagSearchExprDestroy _ANSI_ARGS_((TagSearchExpr *expr)); -static void TagSearchDestroy _ANSI_ARGS_((TagSearch *searchPtr)); -static int TagSearchScan _ANSI_ARGS_((TkCanvas *canvasPtr, - Tcl_Obj *tag, TagSearch **searchPtrPtr)); -static int TagSearchScanExpr _ANSI_ARGS_((Tcl_Interp *interp, - TagSearch *searchPtr, TagSearchExpr *expr)); -static int TagSearchEvalExpr _ANSI_ARGS_((TagSearchExpr *expr, - Tk_Item *itemPtr)); -static Tk_Item * TagSearchFirst _ANSI_ARGS_((TagSearch *searchPtr)); -static Tk_Item * TagSearchNext _ANSI_ARGS_((TagSearch *searchPtr)); +static int RelinkItems(TkCanvas *canvasPtr, Tcl_Obj *tag, + Tk_Item *prevPtr, TagSearch **searchPtrPtr); +static void TagSearchExprInit(TagSearchExpr **exprPtrPtr); +static void TagSearchExprDestroy(TagSearchExpr *expr); +static void TagSearchDestroy(TagSearch *searchPtr); +static int TagSearchScan(TkCanvas *canvasPtr, + Tcl_Obj *tag, TagSearch **searchPtrPtr); +static int TagSearchScanExpr(Tcl_Interp *interp, + TagSearch *searchPtr, TagSearchExpr *expr); +static int TagSearchEvalExpr(TagSearchExpr *expr, + Tk_Item *itemPtr); +static Tk_Item * TagSearchFirst(TagSearch *searchPtr); +static Tk_Item * TagSearchNext(TagSearch *searchPtr); #endif /* USE_OLD_TAG_SEARCH */ /* - * The structure below defines canvas class behavior by means of procedures + * The structure below defines canvas class behavior by means of functions * that can be invoked from generic window code. */ @@ -344,15 +328,38 @@ static Tk_ClassProcs canvasClass = { CanvasWorldChanged, /* worldChangedProc */ }; +/* + * Macros that significantly simplify all code that finds items. + */ + +#ifdef USE_OLD_TAG_SEARCH +#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ + (itemPtr) = StartTagSearch(canvasPtr,(objPtr),&search) +#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ + for ((itemPtr) = StartTagSearch(canvasPtr, (objPtr), &search); \ + (itemPtr) != NULL; (itemPtr) = NextItem(&search)) +#else /* USE_OLD_TAG_SEARCH */ +#define FIRST_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ + if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \ + errorExitClause; \ + } \ + itemPtr = TagSearchFirst(*(searchPtrPtr)); +#define FOR_EVERY_CANVAS_ITEM_MATCHING(objPtr,searchPtrPtr,errorExitClause) \ + if ((result=TagSearchScan(canvasPtr,(objPtr),(searchPtrPtr))) != TCL_OK){ \ + errorExitClause; \ + } \ + for (itemPtr = TagSearchFirst(*(searchPtrPtr)); \ + itemPtr != NULL; itemPtr = TagSearchNext(*(searchPtrPtr))) +#endif /* USE_OLD_TAG_SEARCH */ + /* *-------------------------------------------------------------- * * Tk_CanvasObjCmd -- * - * This procedure is invoked to process the "canvas" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "canvas" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -364,16 +371,15 @@ static Tk_ClassProcs canvasClass = { */ int -Tk_CanvasObjCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - Tcl_Obj *CONST argv[]; /* Argument objects. */ +Tk_CanvasObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + Tcl_Obj *CONST argv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; TkCanvas *canvasPtr; - Tk_Window new; + Tk_Window newWin; if (typeList == NULL) { InitCanvas(); @@ -384,21 +390,20 @@ Tk_CanvasObjCmd(clientData, interp, argc, argv) return TCL_ERROR; } - new = Tk_CreateWindowFromPath(interp, tkwin, - Tcl_GetString(argv[1]), (char *) NULL); - if (new == NULL) { + newWin = Tk_CreateWindowFromPath(interp,tkwin,Tcl_GetString(argv[1]),NULL); + if (newWin == NULL) { return TCL_ERROR; } /* - * Initialize fields that won't be initialized by ConfigureCanvas, - * or which ConfigureCanvas expects to have reasonable values - * (e.g. resource pointers). + * Initialize fields that won't be initialized by ConfigureCanvas, or + * which ConfigureCanvas expects to have reasonable values (e.g. resource + * pointers). */ canvasPtr = (TkCanvas *) ckalloc(sizeof(TkCanvas)); - canvasPtr->tkwin = new; - canvasPtr->display = Tk_Display(new); + canvasPtr->tkwin = newWin; + canvasPtr->display = Tk_Display(newWin); canvasPtr->interp = interp; canvasPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd, @@ -460,8 +465,8 @@ Tk_CanvasObjCmd(clientData, interp, argc, argv) canvasPtr->hotPrevPtr = NULL; canvasPtr->cursor = None; canvasPtr->takeFocus = NULL; - canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(new)); - canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(new)); + canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(newWin)); + canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(newWin)); canvasPtr->flags = 0; canvasPtr->nextId = 1; canvasPtr->psInfo = NULL; @@ -492,7 +497,7 @@ Tk_CanvasObjCmd(clientData, interp, argc, argv) Tcl_SetResult(interp, Tk_PathName(canvasPtr->tkwin), TCL_STATIC); return TCL_OK; - error: + error: Tk_DestroyWindow(canvasPtr->tkwin); return TCL_ERROR; } @@ -502,9 +507,9 @@ Tk_CanvasObjCmd(clientData, interp, argc, argv) * * CanvasWidgetCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -516,22 +521,21 @@ Tk_CanvasObjCmd(clientData, interp, argc, argv) */ static int -CanvasWidgetCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about canvas - * widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +CanvasWidgetCmd( + ClientData clientData, /* Information about canvas widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; - int c, length, result; - Tk_Item *itemPtr = NULL; /* Initialization needed only to - * prevent compiler warning. */ + int c, result; + Tk_Item *itemPtr = NULL; /* Initialization needed only to prevent + * compiler warning. */ #ifdef USE_OLD_TAG_SEARCH TagSearch search; #else /* USE_OLD_TAG_SEARCH */ - TagSearch *searchPtr = NULL; /* Allocated by first TagSearchScan - * Freed by TagSearchDestroy */ + TagSearch *searchPtr = NULL;/* Allocated by first TagSearchScan, freed by + * TagSearchDestroy */ #endif /* USE_OLD_TAG_SEARCH */ int index; @@ -569,7 +573,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_OK; switch ((enum options) index) { - case CANV_ADDTAG: { + case CANV_ADDTAG: if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "tag searchCommand ?arg arg ...?"); result = TCL_ERROR; @@ -581,13 +585,12 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = FindItems(interp, canvasPtr, objc, objv, objv[2], 3, &searchPtr); #endif /* USE_OLD_TAG_SEARCH */ break; - } - case CANV_BBOX: { + case CANV_BBOX: { int i, gotAny; - int x1 = 0, y1 = 0, x2 = 0, y2 = 0; /* Initializations needed - * only to prevent compiler - * warnings. */ + int x1 = 0, y1 = 0, x2 = 0, y2 = 0; /* Initializations needed only + * to prevent overcautious + * compiler warnings. */ if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?tagOrId ...?"); @@ -596,17 +599,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } gotAny = 0; for (i = 2; i < objc; i++) { -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[i], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[i], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ - + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[i], &searchPtr, goto done) { if ((itemPtr->x1 >= itemPtr->x2) || (itemPtr->y1 >= itemPtr->y2)) { continue; @@ -635,13 +628,13 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } if (gotAny) { char buf[TCL_INTEGER_SPACE * 4]; - + sprintf(buf, "%d %d %d %d", x1, y1, x2, y2); Tcl_SetResult(interp, buf, TCL_VOLATILE); } break; - } - case CANV_BIND: { + } + case CANV_BIND: { ClientData object; if ((objc < 3) || (objc > 5)) { @@ -651,8 +644,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } /* - * Figure out what object to use for the binding (individual - * item vs. tag). + * Figure out what object to use for the binding (individual item vs. + * tag). */ object = 0; @@ -674,7 +667,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) if (object == 0) { Tcl_AppendResult(interp, "item \"", Tcl_GetString(objv[2]), - "\" doesn't exist", (char *) NULL); + "\" doesn't exist", NULL); result = TCL_ERROR; goto done; } @@ -683,13 +676,15 @@ CanvasWidgetCmd(clientData, interp, objc, objv) object = (ClientData) Tk_GetUid(Tcl_GetString(objv[2])); } #else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { + result = TagSearchScan(canvasPtr, objv[2], &searchPtr); + if (result != TCL_OK) { goto done; } - if (searchPtr->type == 1) { + if (searchPtr->type == SEARCH_TYPE_ID) { Tcl_HashEntry *entryPtr; - entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) searchPtr->id); + entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, + (char *) INT2PTR(searchPtr->id)); if (entryPtr != NULL) { itemPtr = (Tk_Item *) Tcl_GetHashValue(entryPtr); object = (ClientData) itemPtr; @@ -697,7 +692,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) if (object == 0) { Tcl_AppendResult(interp, "item \"", Tcl_GetString(objv[2]), - "\" doesn't exist", (char *) NULL); + "\" doesn't exist", NULL); result = TCL_ERROR; goto done; } @@ -707,8 +702,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) #endif /* USE_OLD_TAG_SEARCH */ /* - * Make a binding table if the canvas doesn't already have - * one. + * Make a binding table if the canvas doesn't already have one. */ if (canvasPtr->bindingTable == NULL) { @@ -718,18 +712,19 @@ CanvasWidgetCmd(clientData, interp, objc, objv) if (objc == 5) { int append = 0; unsigned long mask; - char* argv4 = Tcl_GetStringFromObj(objv[4],NULL); + char* argv4 = Tcl_GetString(objv[4]); if (argv4[0] == 0) { result = Tk_DeleteBinding(interp, canvasPtr->bindingTable, - object, Tcl_GetStringFromObj(objv[3], NULL)); + object, Tcl_GetString(objv[3])); goto done; } #ifndef USE_OLD_TAG_SEARCH - if (searchPtr->type == 4) { - /* - * if new tag expression, then insert in linked list - */ + if (searchPtr->type == SEARCH_TYPE_EXPR) { + /* + * If new tag expression, then insert in linked list. + */ + TagSearchExpr *expr, **lastPtr; lastPtr = &(canvasPtr->bindTagExprs); @@ -741,25 +736,27 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } if (!expr) { /* - * transfer ownership of expr to bindTagExprs list + * Transfer ownership of expr to bindTagExprs list. */ + *lastPtr = searchPtr->expr; searchPtr->expr->next = NULL; /* - * flag in TagSearch that expr has changed ownership - * so that TagSearchDestroy doesn't try to free it + * Flag in TagSearch that expr has changed ownership so + * that TagSearchDestroy doesn't try to free it. */ + searchPtr->expr = NULL; } - } + } #endif /* not USE_OLD_TAG_SEARCH */ if (argv4[0] == '+') { argv4++; append = 1; } mask = Tk_CreateBinding(interp, canvasPtr->bindingTable, - object, Tcl_GetStringFromObj(objv[3],NULL), argv4, append); + object, Tcl_GetString(objv[3]), argv4, append); if (mask == 0) { result = TCL_ERROR; goto done; @@ -770,27 +767,28 @@ CanvasWidgetCmd(clientData, interp, objc, objv) |EnterWindowMask|LeaveWindowMask|KeyPressMask |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) { Tk_DeleteBinding(interp, canvasPtr->bindingTable, - object, Tcl_GetStringFromObj(objv[3], NULL)); + object, Tcl_GetString(objv[3])); Tcl_ResetResult(interp); Tcl_AppendResult(interp, "requested illegal events; ", "only key, button, motion, enter, leave, and virtual ", - "events may be used", (char *) NULL); + "events may be used", NULL); result = TCL_ERROR; goto done; } } else if (objc == 4) { CONST char *command; - + command = Tk_GetBinding(interp, canvasPtr->bindingTable, - object, Tcl_GetStringFromObj(objv[3], NULL)); + object, Tcl_GetString(objv[3])); if (command == NULL) { CONST char *string; - string = Tcl_GetStringResult(interp); + string = Tcl_GetStringResult(interp); + /* - * Ignore missing binding errors. This is a special hack - * that relies on the error message returned by FindSequence - * in tkBind.c. + * Ignore missing binding errors. This is a special hack that + * relies on the error message returned by FindSequence in + * tkBind.c. */ if (string[0] != '\0') { @@ -806,8 +804,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) Tk_GetAllBindings(interp, canvasPtr->bindingTable, object); } break; - } - case CANV_CANVASX: { + } + case CANV_CANVASX: { int x; double grid; char buf[TCL_DOUBLE_SPACE]; @@ -834,8 +832,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) Tcl_PrintDouble(interp, GridAlign((double) x, grid), buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; - } - case CANV_CANVASY: { + } + case CANV_CANVASY: { int y; double grid; char buf[TCL_DOUBLE_SPACE]; @@ -862,8 +860,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) Tcl_PrintDouble(interp, GridAlign((double) y, grid), buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; - } - case CANV_CGET: { + } + case CANV_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; @@ -872,11 +870,10 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = Tk_ConfigureValue(interp, canvasPtr->tkwin, configSpecs, (char *) canvasPtr, Tcl_GetString(objv[2]), 0); break; - } - case CANV_CONFIGURE: { + case CANV_CONFIGURE: if (objc == 2) { result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs, - (char *) canvasPtr, (char *) NULL, 0); + (char *) canvasPtr, NULL, 0); } else if (objc == 3) { result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs, (char *) canvasPtr, Tcl_GetString(objv[2]), 0); @@ -885,43 +882,37 @@ CanvasWidgetCmd(clientData, interp, objc, objv) TK_CONFIG_ARGV_ONLY); } break; - } - case CANV_COORDS: { + case CANV_COORDS: if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?x y x y ...?"); result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, objv[2], &search); -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - itemPtr = TagSearchFirst(searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ + FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done); if (itemPtr != NULL) { if (objc != 3) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); } if (itemPtr->typePtr->coordProc != NULL) { - if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = (*itemPtr->typePtr->coordProc)(interp, - (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3); - } else { - CONST char **args = GetStringsFromObjs(objc-3, objv+3); - result = (*itemPtr->typePtr->coordProc)(interp, - (Tk_Canvas) canvasPtr, itemPtr, objc-3, (Tcl_Obj **) args); - if (args) ckfree((char *) args); - } + if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { + result = (*itemPtr->typePtr->coordProc)(interp, + (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3); + } else { + CONST char **args = TkGetStringsFromObjs(objc-3, objv+3); + result = (*itemPtr->typePtr->coordProc)(interp, + (Tk_Canvas) canvasPtr, itemPtr, objc-3, + (Tcl_Obj **) args); + if (args != NULL) { + ckfree((char *) args); + } + } } if (objc != 3) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); } } break; - } - case CANV_CREATE: { + case CANV_CREATE: { Tk_ItemType *typePtr; Tk_ItemType *matchPtr = NULL; Tk_Item *itemPtr; @@ -929,6 +920,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) int isNew = 0; Tcl_HashEntry *entryPtr; char *arg; + int length; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg arg ...?"); @@ -940,13 +932,12 @@ CanvasWidgetCmd(clientData, interp, objc, objv) Tcl_MutexLock(&typeListMutex); for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->nextPtr) { if ((c == typePtr->name[0]) - && (strncmp(arg, typePtr->name, (unsigned) length) == 0)) { + && (strncmp(arg, typePtr->name, (unsigned)length) == 0)) { if (matchPtr != NULL) { Tcl_MutexUnlock(&typeListMutex); - badType: + badType: Tcl_AppendResult(interp, - "unknown or ambiguous item type \"", - arg, "\"", (char *) NULL); + "unknown or ambiguous item type \"",arg,"\"",NULL); result = TCL_ERROR; goto done; } @@ -984,10 +975,12 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = (*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3); } else { - CONST char **args = GetStringsFromObjs(objc-3, objv+3); + CONST char **args = TkGetStringsFromObjs(objc-3, objv+3); result = (*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr, itemPtr, objc-3, (Tcl_Obj **) args); - if (args) ckfree((char *) args); + if (args != NULL) { + ckfree((char *) args); + } } if (result != TCL_OK) { ckfree((char *) itemPtr); @@ -996,7 +989,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } itemPtr->nextPtr = NULL; entryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable, - (char *) itemPtr->id, &isNew); + (char *) INT2PTR(itemPtr->id), &isNew); Tcl_SetHashValue(entryPtr, itemPtr); itemPtr->prevPtr = canvasPtr->lastItemPtr; canvasPtr->hotPtr = itemPtr; @@ -1013,8 +1006,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) sprintf(buf, "%d", itemPtr->id); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; - } - case CANV_DCHARS: { + } + case CANV_DCHARS: { int first, last; int x1,x2,y1,y2; @@ -1023,37 +1016,32 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { if ((itemPtr->typePtr->indexProc == NULL) || (itemPtr->typePtr->dCharsProc == NULL)) { continue; } if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, (char *) objv[3], &first); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, (char *) objv[3], + &first); } else { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, Tcl_GetStringFromObj(objv[3], NULL), &first); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, Tcl_GetString(objv[3]), + &first); } if (result != TCL_OK) { goto done; } if (objc == 5) { if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, (char *) objv[4], &last); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, (char *) objv[4], + &last); } else { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, Tcl_GetStringFromObj(objv[4], NULL), &last); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, + Tcl_GetString(objv[4]), &last); } if (result != TCL_OK) { goto done; @@ -1063,10 +1051,10 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } /* - * 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, nothing more needs to be done. + * 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, + * nothing more needs to be done. */ x1 = itemPtr->x1; y1 = itemPtr->y1; @@ -1082,22 +1070,13 @@ CanvasWidgetCmd(clientData, interp, objc, objv) itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; } break; - } - case CANV_DELETE: { + } + case CANV_DELETE: { int i; Tcl_HashEntry *entryPtr; for (i = 2; i < objc; i++) { -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[i], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[i], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[i], &searchPtr, goto done) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); if (canvasPtr->bindingTable != NULL) { Tk_DeleteAllBindings(canvasPtr->bindingTable, @@ -1109,7 +1088,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) ckfree((char *) itemPtr->tagPtr); } entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, - (char *) itemPtr->id); + (char *) INT2PTR(itemPtr->id)); Tcl_DeleteHashEntry(entryPtr); if (itemPtr->nextPtr != NULL) { itemPtr->nextPtr->prevPtr = itemPtr->prevPtr; @@ -1148,8 +1127,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } } break; - } - case CANV_DTAG: { + } + case CANV_DTAG: { Tk_Uid tag; int i; @@ -1159,20 +1138,11 @@ CanvasWidgetCmd(clientData, interp, objc, objv) goto done; } if (objc == 4) { - tag = Tk_GetUid(Tcl_GetStringFromObj(objv[3], NULL)); + tag = Tk_GetUid(Tcl_GetString(objv[3])); } else { - tag = Tk_GetUid(Tcl_GetStringFromObj(objv[2], NULL)); + tag = Tk_GetUid(Tcl_GetString(objv[2])); } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { for (i = itemPtr->numTags-1; i >= 0; i--) { if (itemPtr->tagPtr[i] == tag) { itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1]; @@ -1181,22 +1151,21 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } } break; - } - case CANV_FIND: { + } + case CANV_FIND: if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "searchCommand ?arg arg ...?"); result = TCL_ERROR; goto done; } #ifdef USE_OLD_TAG_SEARCH - result = FindItems(interp, canvasPtr, objc, objv, (Tcl_Obj *) NULL, 2); + result = FindItems(interp, canvasPtr, objc, objv, NULL, 2); #else /* USE_OLD_TAG_SEARCH */ - result = FindItems(interp, canvasPtr, objc, objv, - (Tcl_Obj *) NULL, 2, &searchPtr); + result = FindItems(interp, canvasPtr, objc, objv, NULL, 2, + &searchPtr); #endif /* USE_OLD_TAG_SEARCH */ break; - } - case CANV_FOCUS: { + case CANV_FOCUS: if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?tagOrId?"); result = TCL_ERROR; @@ -1206,7 +1175,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) if (objc == 2) { if (itemPtr != NULL) { char buf[TCL_INTEGER_SPACE]; - + sprintf(buf, "%d", itemPtr->id); Tcl_SetResult(interp, buf, TCL_VOLATILE); } @@ -1215,20 +1184,11 @@ CanvasWidgetCmd(clientData, interp, objc, objv) if ((itemPtr != NULL) && (canvasPtr->textInfo.gotFocus)) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); } - if (Tcl_GetStringFromObj(objv[2], NULL)[0] == 0) { + if (Tcl_GetString(objv[2])[0] == 0) { canvasPtr->textInfo.focusItemPtr = NULL; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { if (itemPtr->typePtr->icursorProc != NULL) { break; } @@ -1241,21 +1201,13 @@ CanvasWidgetCmd(clientData, interp, objc, objv) EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); } break; - } - case CANV_GETTAGS: { + case CANV_GETTAGS: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId"); result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, objv[2], &search); -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - itemPtr = TagSearchFirst(searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ + FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done); if (itemPtr != NULL) { int i; for (i = 0; i < itemPtr->numTags; i++) { @@ -1263,8 +1215,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } } break; - } - case CANV_ICURSOR: { + case CANV_ICURSOR: { int index; if (objc != 4) { @@ -1272,26 +1223,19 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { if ((itemPtr->typePtr->indexProc == NULL) || (itemPtr->typePtr->icursorProc == NULL)) { goto done; } if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, (char *) objv[3], &index); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, (char *) objv[3], + &index); } else { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, Tcl_GetStringFromObj(objv[3], NULL), &index); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, Tcl_GetString(objv[3]), + &index); } if (result != TCL_OK) { goto done; @@ -1304,9 +1248,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } } break; - } - case CANV_INDEX: { - + } + case CANV_INDEX: { int index; char buf[TCL_INTEGER_SPACE]; @@ -1315,23 +1258,14 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { if (itemPtr->typePtr->indexProc != NULL) { break; } } if (itemPtr == NULL) { Tcl_AppendResult(interp, "can't find an indexable item \"", - Tcl_GetStringFromObj(objv[2], NULL), "\"", (char *) NULL); + Tcl_GetString(objv[2]), "\"", NULL); result = TCL_ERROR; goto done; } @@ -1340,7 +1274,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) itemPtr, (char *) objv[3], &index); } else { result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, Tcl_GetStringFromObj(objv[3], NULL), &index); + itemPtr, Tcl_GetString(objv[3]), &index); } if (result != TCL_OK) { goto done; @@ -1348,8 +1282,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) sprintf(buf, "%d", index); Tcl_SetResult(interp, buf, TCL_VOLATILE); break; - } - case CANV_INSERT: { + } + case CANV_INSERT: { int beforeThis; int x1,x2,y1,y2; @@ -1358,37 +1292,29 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { if ((itemPtr->typePtr->indexProc == NULL) || (itemPtr->typePtr->insertProc == NULL)) { continue; } if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, (char *) objv[3], &beforeThis); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, (char *) objv[3], + &beforeThis); } else { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, Tcl_GetStringFromObj(objv[3], NULL), &beforeThis); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, Tcl_GetString(objv[3]), + &beforeThis); } if (result != TCL_OK) { goto done; } /* - * Redraw both item's old and new areas: it's possible - * that an insertion could result in a new area either - * larger or smaller than the old area. Except if the - * insertProc sets the TK_ITEM_DONT_REDRAW flag, nothing - * more needs to be done. + * Redraw both item's old and new areas: it's possible that an + * insertion could result in a new area either larger or smaller + * than the old area. Except if the insertProc sets the + * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done. */ x1 = itemPtr->x1; y1 = itemPtr->y1; @@ -1399,7 +1325,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) itemPtr, beforeThis, (char *) objv[4]); } else { (*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr, - itemPtr, beforeThis, Tcl_GetStringFromObj(objv[4], NULL)); + itemPtr, beforeThis, Tcl_GetString(objv[4])); } if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) { Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, @@ -1409,48 +1335,31 @@ CanvasWidgetCmd(clientData, interp, objc, objv) itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW; } break; - } - case CANV_ITEMCGET: { + } + case CANV_ITEMCGET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId option"); result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, objv[2], &search); -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - itemPtr = TagSearchFirst(searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ + FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done); if (itemPtr != NULL) { result = Tk_ConfigureValue(canvasPtr->interp, canvasPtr->tkwin, itemPtr->typePtr->configSpecs, (char *) itemPtr, - Tcl_GetStringFromObj(objv[3], NULL), 0); + Tcl_GetString(objv[3]), 0); } break; - } - case CANV_ITEMCONFIGURE: { + case CANV_ITEMCONFIGURE: if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?option value ...?"); result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { if (objc == 3) { result = Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin, itemPtr->typePtr->configSpecs, (char *) itemPtr, - (char *) NULL, 0); + NULL, 0); } else if (objc == 4) { result = Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin, itemPtr->typePtr->configSpecs, (char *) itemPtr, @@ -1458,15 +1367,17 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } else { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = (*itemPtr->typePtr->configProc)(interp, - (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3, - TK_CONFIG_ARGV_ONLY); + result = (*itemPtr->typePtr->configProc)(interp, + (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3, + TK_CONFIG_ARGV_ONLY); } else { - CONST char **args = GetStringsFromObjs(objc-3, objv+3); - result = (*itemPtr->typePtr->configProc)(interp, - (Tk_Canvas) canvasPtr, itemPtr, objc-3, (Tcl_Obj **) args, - TK_CONFIG_ARGV_ONLY); - if (args) ckfree((char *) args); + CONST char **args = TkGetStringsFromObjs(objc-3, objv+3); + result = (*itemPtr->typePtr->configProc)(interp, + (Tk_Canvas) canvasPtr, itemPtr, objc-3, + (Tcl_Obj **) args, TK_CONFIG_ARGV_ONLY); + if (args != NULL) { + ckfree((char *) args); + } } EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); canvasPtr->flags |= REPICK_NEEDED; @@ -1476,8 +1387,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } } break; - } - case CANV_LOWER: { + case CANV_LOWER: { Tk_Item *itemPtr; if ((objc != 3) && (objc != 4)) { @@ -1487,24 +1397,16 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } /* - * First find the item just after which we'll insert the - * named items. + * First find the item just after which we'll insert the named items. */ if (objc == 3) { itemPtr = NULL; } else { -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, objv[3], &search); -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[3], &searchPtr)) != TCL_OK) { - goto done; - } - itemPtr = TagSearchFirst(searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ + FIRST_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done); if (itemPtr == NULL) { Tcl_AppendResult(interp, "tag \"", Tcl_GetString(objv[3]), - "\" doesn't match any items", (char *) NULL); + "\" doesn't match any items", NULL); result = TCL_ERROR; goto done; } @@ -1513,13 +1415,11 @@ CanvasWidgetCmd(clientData, interp, objc, objv) #ifdef USE_OLD_TAG_SEARCH RelinkItems(canvasPtr, objv[2], itemPtr); #else /* USE_OLD_TAG_SEARCH */ - if ((result = RelinkItems(canvasPtr, objv[2], itemPtr, &searchPtr)) != TCL_OK) { - goto done; - } + result = RelinkItems(canvasPtr, objv[2], itemPtr, &searchPtr); #endif /* USE_OLD_TAG_SEARCH */ break; - } - case CANV_MOVE: { + } + case CANV_MOVE: { double xAmount, yAmount; if (objc != 5) { @@ -1533,16 +1433,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); (void) (*itemPtr->typePtr->translateProc)((Tk_Canvas) canvasPtr, itemPtr, xAmount, yAmount); @@ -1550,14 +1441,17 @@ CanvasWidgetCmd(clientData, interp, objc, objv) canvasPtr->flags |= REPICK_NEEDED; } break; - } - case CANV_POSTSCRIPT: { - CONST char **args = GetStringsFromObjs(objc, objv); + } + case CANV_POSTSCRIPT: { + CONST char **args = TkGetStringsFromObjs(objc, objv); + result = TkCanvPostscriptCmd(canvasPtr, interp, objc, args); - if (args) ckfree((char *) args); + if (args != NULL) { + ckfree((char *) args); + } break; - } - case CANV_RAISE: { + } + case CANV_RAISE: { Tk_Item *prevPtr; if ((objc != 3) && (objc != 4)) { @@ -1567,29 +1461,19 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } /* - * First find the item just after which we'll insert the - * named items. + * First find the item just after which we'll insert the named items. */ if (objc == 3) { prevPtr = canvasPtr->lastItemPtr; } else { prevPtr = NULL; -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[3], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[3], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) { prevPtr = itemPtr; } if (prevPtr == NULL) { - Tcl_AppendResult(interp, "tagOrId \"", Tcl_GetStringFromObj(objv[3], NULL), - "\" doesn't match any items", (char *) NULL); + Tcl_AppendResult(interp, "tagOrId \"", Tcl_GetString(objv[3]), + "\" doesn't match any items", NULL); result = TCL_ERROR; goto done; } @@ -1597,14 +1481,11 @@ CanvasWidgetCmd(clientData, interp, objc, objv) #ifdef USE_OLD_TAG_SEARCH RelinkItems(canvasPtr, objv[2], prevPtr); #else /* USE_OLD_TAG_SEARCH */ - result = RelinkItems(canvasPtr, objv[2], prevPtr, &searchPtr); - if (result != TCL_OK) { - goto done; - } + result = RelinkItems(canvasPtr, objv[2], prevPtr, &searchPtr); #endif /* USE_OLD_TAG_SEARCH */ break; - } - case CANV_SCALE: { + } + case CANV_SCALE: { double xOrigin, yOrigin, xScale, yScale; if (objc != 7) { @@ -1626,16 +1507,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr); (void) (*itemPtr->typePtr->scaleProc)((Tk_Canvas) canvasPtr, itemPtr, xOrigin, yOrigin, xScale, yScale); @@ -1643,9 +1515,9 @@ CanvasWidgetCmd(clientData, interp, objc, objv) canvasPtr->flags |= REPICK_NEEDED; } break; - } - case CANV_SCAN: { - int x, y, gain=10; + } + case CANV_SCAN: { + int x, y, gain = 10; static CONST char *optionStrings[] = { "mark", "dragto", NULL }; @@ -1687,8 +1559,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) CanvasSetOrigin(canvasPtr, newXOrigin, newYOrigin); } break; - } - case CANV_SELECT: { + } + case CANV_SELECT: { int index, optionindex; static CONST char *optionStrings[] = { "adjust", "clear", "from", "item", "to", NULL @@ -1703,16 +1575,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) goto done; } if (objc >= 4) { -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, objv[3], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[3], &searchPtr)) != TCL_OK) { - goto done; - } - for (itemPtr = TagSearchFirst(searchPtr); - itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[3], &searchPtr, goto done) { if ((itemPtr->typePtr->indexProc != NULL) && (itemPtr->typePtr->selectionProc != NULL)){ break; @@ -1721,30 +1584,32 @@ CanvasWidgetCmd(clientData, interp, objc, objv) if (itemPtr == NULL) { Tcl_AppendResult(interp, "can't find an indexable and selectable item \"", - Tcl_GetStringFromObj(objv[3], NULL), "\"", (char *) NULL); + Tcl_GetString(objv[3]), "\"", NULL); result = TCL_ERROR; goto done; } } if (objc == 5) { if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, (char *) objv[4], &index); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, (char *) objv[4], + &index); } else { - result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr, - itemPtr, Tcl_GetStringFromObj(objv[4], NULL), &index); + result = itemPtr->typePtr->indexProc(interp, + (Tk_Canvas) canvasPtr, itemPtr, Tcl_GetString(objv[4]), + &index); } if (result != TCL_OK) { goto done; } } - if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, "select option", 0, - &optionindex) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, + "select option", 0, &optionindex) != TCL_OK) { result = TCL_ERROR; goto done; } switch ((enum options) optionindex) { - case CANV_ADJUST: { + case CANV_ADJUST: if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index"); result = TCL_ERROR; @@ -1762,10 +1627,9 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } CanvasSelectTo(canvasPtr, itemPtr, index); break; - } - case CANV_CLEAR: { + case CANV_CLEAR: if (objc != 3) { - Tcl_AppendResult(interp, 3, objv, (char *) NULL); + Tcl_WrongNumArgs(interp, 3, objv, NULL); result = TCL_ERROR; goto done; } @@ -1776,8 +1640,7 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } goto done; break; - } - case CANV_FROM: { + case CANV_FROM: if (objc != 5) { Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index"); result = TCL_ERROR; @@ -1786,22 +1649,18 @@ CanvasWidgetCmd(clientData, interp, objc, objv) canvasPtr->textInfo.anchorItemPtr = itemPtr; canvasPtr->textInfo.selectAnchor = index; break; - } - case CANV_ITEM: { + case CANV_ITEM: if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); + Tcl_WrongNumArgs(interp, 3, objv, NULL); result = TCL_ERROR; goto done; } if (canvasPtr->textInfo.selItemPtr != NULL) { - char buf[TCL_INTEGER_SPACE]; - - sprintf(buf, "%d", canvasPtr->textInfo.selItemPtr->id); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_SetObjResult(interp, + Tcl_NewIntObj(canvasPtr->textInfo.selItemPtr->id)); } break; - } - case CANV_TO: { + case CANV_TO: if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index"); result = TCL_ERROR; @@ -1809,30 +1668,21 @@ CanvasWidgetCmd(clientData, interp, objc, objv) } CanvasSelectTo(canvasPtr, itemPtr, index); break; - } } break; - } - case CANV_TYPE: { + } + case CANV_TYPE: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "tag"); result = TCL_ERROR; goto done; } -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, objv[2], &search); -#else /* USE_OLD_TAG_SEARCH */ - if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) { - goto done; - } - itemPtr = TagSearchFirst(searchPtr); -#endif /* USE_OLD_TAG_SEARCH */ + FIRST_CANVAS_ITEM_MATCHING(objv[2], &searchPtr, goto done); if (itemPtr != NULL) { Tcl_SetResult(interp, itemPtr->typePtr->name, TCL_STATIC); } break; - } - case CANV_XVIEW: { + case CANV_XVIEW: { int count, type; int newX = 0; /* Initialization needed only to prevent * gcc warnings. */ @@ -1845,84 +1695,89 @@ CanvasWidgetCmd(clientData, interp, objc, objv) - canvasPtr->inset, canvasPtr->scrollX1, canvasPtr->scrollX2)); } else { - CONST char **args = GetStringsFromObjs(objc, objv); + CONST char **args = TkGetStringsFromObjs(objc, objv); type = Tk_GetScrollInfo(interp, objc, args, &fraction, &count); - if (args) ckfree((char *) args); + if (args != NULL) { + ckfree((char *) args); + } switch (type) { - case TK_SCROLL_ERROR: - result = TCL_ERROR; - goto done; - case TK_SCROLL_MOVETO: - newX = canvasPtr->scrollX1 - canvasPtr->inset - + (int) (fraction * (canvasPtr->scrollX2 - - canvasPtr->scrollX1) + 0.5); - break; - case TK_SCROLL_PAGES: - newX = (int) (canvasPtr->xOrigin + count * .9 - * (Tk_Width(canvasPtr->tkwin) - 2*canvasPtr->inset)); - break; - case TK_SCROLL_UNITS: - if (canvasPtr->xScrollIncrement > 0) { - newX = canvasPtr->xOrigin - + count*canvasPtr->xScrollIncrement; - } else { - newX = (int) (canvasPtr->xOrigin + count * .1 - * (Tk_Width(canvasPtr->tkwin) - - 2*canvasPtr->inset)); - } - break; + case TK_SCROLL_ERROR: + result = TCL_ERROR; + goto done; + case TK_SCROLL_MOVETO: + newX = canvasPtr->scrollX1 - canvasPtr->inset + + (int) (fraction * (canvasPtr->scrollX2 + - canvasPtr->scrollX1) + 0.5); + break; + case TK_SCROLL_PAGES: + newX = (int) (canvasPtr->xOrigin + count * .9 + * (Tk_Width(canvasPtr->tkwin) - 2*canvasPtr->inset)); + break; + case TK_SCROLL_UNITS: + if (canvasPtr->xScrollIncrement > 0) { + newX = canvasPtr->xOrigin + + count*canvasPtr->xScrollIncrement; + } else { + newX = (int) (canvasPtr->xOrigin + count * .1 + * (Tk_Width(canvasPtr->tkwin) + - 2*canvasPtr->inset)); + } + break; } CanvasSetOrigin(canvasPtr, newX, canvasPtr->yOrigin); } break; - } - case CANV_YVIEW: { + } + case CANV_YVIEW: { int count, type; int newY = 0; /* Initialization needed only to prevent * gcc warnings. */ double fraction; if (objc == 2) { - Tcl_SetObjResult(interp,ScrollFractions(\ + Tcl_SetObjResult(interp, ScrollFractions( canvasPtr->yOrigin + canvasPtr->inset, canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin) - - canvasPtr->inset, canvasPtr->scrollY1, - canvasPtr->scrollY2)); + - canvasPtr->inset, + canvasPtr->scrollY1, canvasPtr->scrollY2)); } else { - CONST char **args = GetStringsFromObjs(objc, objv); + CONST char **args = TkGetStringsFromObjs(objc, objv); type = Tk_GetScrollInfo(interp, objc, args, &fraction, &count); - if (args) ckfree((char *) args); + if (args != NULL) { + ckfree((char *) args); + } switch (type) { - case TK_SCROLL_ERROR: - result = TCL_ERROR; - goto done; - case TK_SCROLL_MOVETO: - newY = canvasPtr->scrollY1 - canvasPtr->inset - + (int) (fraction*(canvasPtr->scrollY2 - - canvasPtr->scrollY1) + 0.5); - break; - case TK_SCROLL_PAGES: - newY = (int) (canvasPtr->yOrigin + count * .9 + case TK_SCROLL_ERROR: + result = TCL_ERROR; + goto done; + case TK_SCROLL_MOVETO: + newY = canvasPtr->scrollY1 - canvasPtr->inset + + (int) (fraction*(canvasPtr->scrollY2 + - canvasPtr->scrollY1) + 0.5); + break; + case TK_SCROLL_PAGES: + newY = (int) (canvasPtr->yOrigin + count * .9 + * (Tk_Height(canvasPtr->tkwin) + - 2*canvasPtr->inset)); + break; + case TK_SCROLL_UNITS: + if (canvasPtr->yScrollIncrement > 0) { + newY = canvasPtr->yOrigin + + count*canvasPtr->yScrollIncrement; + } else { + newY = (int) (canvasPtr->yOrigin + count * .1 * (Tk_Height(canvasPtr->tkwin) - 2*canvasPtr->inset)); - break; - case TK_SCROLL_UNITS: - if (canvasPtr->yScrollIncrement > 0) { - newY = canvasPtr->yOrigin - + count*canvasPtr->yScrollIncrement; - } else { - newY = (int) (canvasPtr->yOrigin + count * .1 - * (Tk_Height(canvasPtr->tkwin) - - 2*canvasPtr->inset)); - } - break; + } + break; } CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY); } break; - } } - done: + } + + done: #ifndef USE_OLD_TAG_SEARCH TagSearchDestroy(searchPtr); #endif /* not USE_OLD_TAG_SEARCH */ @@ -1935,9 +1790,9 @@ CanvasWidgetCmd(clientData, interp, objc, objv) * * DestroyCanvas -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a canvas at a safe time - * (when no-one is using it anymore). + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of a canvas at a safe time (when no-one is + * using it anymore). * * Results: * None. @@ -1949,8 +1804,8 @@ CanvasWidgetCmd(clientData, interp, objc, objv) */ static void -DestroyCanvas(memPtr) - char *memPtr; /* Info about canvas widget. */ +DestroyCanvas( + char *memPtr) /* Info about canvas widget. */ { TkCanvas *canvasPtr = (TkCanvas *) memPtr; Tk_Item *itemPtr; @@ -1974,9 +1829,8 @@ DestroyCanvas(memPtr) } /* - * Free up all the stuff that requires special handling, - * then let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ Tcl_DeleteHashTable(&canvasPtr->idTable); @@ -1990,7 +1844,7 @@ DestroyCanvas(memPtr) TagSearchExprDestroy(expr); expr = next; } -#endif +#endif /* USE_OLD_TAG_SEARCH */ Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler); if (canvasPtr->bindingTable != NULL) { Tk_DeleteBindingTable(canvasPtr->bindingTable); @@ -2005,33 +1859,33 @@ DestroyCanvas(memPtr) * * ConfigureCanvas -- * - * This procedure is called to process an objv/objc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a canvas widget. + * This function is called to process an objv/objc list, plus the Tk + * option database, in order to configure (or reconfigure) a canvas + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for canvasPtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for canvasPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureCanvas(interp, canvasPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - TkCanvas *canvasPtr; /* Information about widget; may or may - * not already have values for some fields. */ - int objc; /* Number of valid entries in objv. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureCanvas( + Tcl_Interp *interp, /* Used for error reporting. */ + TkCanvas *canvasPtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in objv. */ + Tcl_Obj *CONST objv[], /* Argument objects. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { XGCValues gcValues; - GC new; + GC newGC; + Tk_State old_canvas_state=canvasPtr->canvas_state; if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs, objc, (CONST char **) objv, (char *) canvasPtr, @@ -2040,9 +1894,8 @@ ConfigureCanvas(interp, canvasPtr, objc, objv, flags) } /* - * A few options need special processing, such as setting the - * background from a 3-D border and creating a GC for copying - * bits to the screen. + * A few options need special processing, such as setting the background + * from a 3-D border and creating a GC for copying bits to the screen. */ Tk_SetBackgroundFromBorder(canvasPtr->tkwin, canvasPtr->bgBorder); @@ -2055,12 +1908,33 @@ ConfigureCanvas(interp, canvasPtr, objc, objv, flags) gcValues.function = GXcopy; gcValues.graphics_exposures = False; gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel; - new = Tk_GetGC(canvasPtr->tkwin, + newGC = Tk_GetGC(canvasPtr->tkwin, GCFunction|GCGraphicsExposures|GCForeground, &gcValues); if (canvasPtr->pixmapGC != None) { Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC); } - canvasPtr->pixmapGC = new; + canvasPtr->pixmapGC = newGC; + + /* + * Reconfigure items to reflect changed state disabled/normal. + */ + + if ( old_canvas_state != canvasPtr->canvas_state ) { + Tk_Item *itemPtr; + int result; + + for ( itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; + itemPtr = itemPtr->nextPtr) { + if ( itemPtr->state == TK_STATE_NULL ) { + result = (*itemPtr->typePtr->configProc)(canvasPtr->interp, + (Tk_Canvas) canvasPtr, itemPtr, 0, NULL, + TK_CONFIG_ARGV_ONLY); + if (result != TCL_OK) { + Tcl_ResetResult(canvasPtr->interp); + } + } + } + } /* * Reset the desired dimensions for the window. @@ -2070,8 +1944,8 @@ ConfigureCanvas(interp, canvasPtr, objc, objv, flags) canvasPtr->height + 2*canvasPtr->inset); /* - * Restart the cursor timing sequence in case the on-time or off-time - * just changed. + * Restart the cursor timing sequence in case the on-time or off-time just + * changed. */ if (canvasPtr->textInfo.gotFocus) { @@ -2096,7 +1970,7 @@ ConfigureCanvas(interp, canvasPtr, objc, objv, flags) } if (argc2 != 4) { Tcl_AppendResult(interp, "bad scrollRegion \"", - canvasPtr->regionString, "\"", (char *) NULL); + canvasPtr->regionString, "\"", NULL); badRegion: ckfree(canvasPtr->regionString); ckfree((char *) argv2); @@ -2133,8 +2007,8 @@ ConfigureCanvas(interp, canvasPtr, objc, objv, flags) } /* - * Reset the canvas's origin (this is a no-op unless confine - * mode has just been turned on or the scroll region has changed). + * Reset the canvas's origin (this is a no-op unless confine mode has just + * been turned on or the scroll region has changed). */ CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin); @@ -2151,24 +2025,24 @@ ConfigureCanvas(interp, canvasPtr, objc, objv, flags) * * CanvasWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: - * None. + * None. * * Side effects: - * Configures all items in the canvas with a empty argc/argv, for - * the side effect of causing all the items to recompute their - * geometry and to be redisplayed. + * Configures all items in the canvas with a empty argc/argv, for the + * side effect of causing all the items to recompute their geometry and + * to be redisplayed. * *--------------------------------------------------------------------------- */ - + static void -CanvasWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +CanvasWorldChanged( + ClientData instanceData) /* Information about widget. */ { TkCanvas *canvasPtr; Tk_Item *itemPtr; @@ -2196,9 +2070,9 @@ CanvasWorldChanged(instanceData) * * DisplayCanvas -- * - * This procedure redraws the contents of a canvas window. - * It is invoked as a do-when-idle handler, so it only runs - * when there's nothing else for the application to do. + * This function redraws the contents of a canvas window. It is invoked + * as a do-when-idle handler, so it only runs when there's nothing else + * for the application to do. * * Results: * None. @@ -2210,8 +2084,8 @@ CanvasWorldChanged(instanceData) */ static void -DisplayCanvas(clientData) - ClientData clientData; /* Information about widget. */ +DisplayCanvas( + ClientData clientData) /* Information about widget. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; Tk_Window tkwin = canvasPtr->tkwin; @@ -2228,8 +2102,8 @@ DisplayCanvas(clientData) } /* - * Choose a new current item if that is needed (this could cause - * event handlers to be invoked). + * Choose a new current item if that is needed (this could cause event + * handlers to be invoked). */ while (canvasPtr->flags & REPICK_NEEDED) { @@ -2244,9 +2118,9 @@ DisplayCanvas(clientData) } /* - * 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. + * 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; @@ -2258,8 +2132,8 @@ DisplayCanvas(clientData) } } /* - * Compute the intersection between the area that needs redrawing - * and the area that's visible on the screen. + * Compute the intersection between the area that needs redrawing and the + * area that's visible on the screen. */ if ((canvasPtr->redrawX1 < canvasPtr->redrawX2) @@ -2283,43 +2157,39 @@ DisplayCanvas(clientData) if ((screenX1 >= screenX2) || (screenY1 >= screenY2)) { goto borders; } - + width = screenX2 - screenX1; height = screenY2 - screenY1; #ifndef TK_NO_DOUBLE_BUFFERING /* - * Redrawing is done in a temporary pixmap that is allocated - * here and freed at the end of the procedure. All drawing - * is done to the pixmap, and the pixmap is copied to the - * screen at the end of the procedure. The temporary pixmap - * serves two purposes: + * Redrawing is done in a temporary pixmap that is allocated here and + * freed at the end of the function. All drawing is done to the + * pixmap, and the pixmap is copied to the screen at the end of the + * function. The temporary pixmap serves two purposes: * - * 1. It provides a smoother visual effect (no clearing and - * gradual redraw will be visible to users). - * 2. It allows us to redraw only the objects that overlap - * the redraw area. Otherwise incorrect results could - * occur from redrawing things that stick outside of - * the redraw area (we'd have to redraw everything in - * order to make the overlaps look right). + * 1. It provides a smoother visual effect (no clearing and gradual + * redraw will be visible to users). + * 2. It allows us to redraw only the objects that overlap the redraw + * area. Otherwise incorrect results could occur from redrawing + * things that stick outside of the redraw area (we'd have to + * redraw everything in order to make the overlaps look right). * * Some tricky points about the pixmap: * - * 1. We only allocate a large enough pixmap to hold the - * area that has to be redisplayed. This saves time in - * in the X server for large objects that cover much - * more than the area being redisplayed: only the area - * of the pixmap will actually have to be redrawn. - * 2. Some X servers (e.g. the one for DECstations) have troubles - * with characters that overlap an edge of the pixmap (on the - * DEC servers, as of 8/18/92, such characters are drawn one - * pixel too far to the right). To handle this problem, - * make the pixmap a bit larger than is absolutely needed - * so that for normal-sized fonts the characters that overlap - * the edge of the pixmap will be outside the area we care - * about. + * 1. We only allocate a large enough pixmap to hold the area that has + * to be redisplayed. This saves time in in the X server for large + * objects that cover much more than the area being redisplayed: + * only the area of the pixmap will actually have to be redrawn. + * 2. Some X servers (e.g. the one for DECstations) have troubles with + * with characters that overlap an edge of the pixmap (on the DEC + * servers, as of 8/18/92, such characters are drawn one pixel too + * far to the right). To handle this problem, make the pixmap a bit + * larger than is absolutely needed so that for normal-sized fonts + * the characters that overlap the edge of the pixmap will be + * outside the area we care about. */ - + canvasPtr->drawableXOrigin = screenX1 - 30; canvasPtr->drawableYOrigin = screenY1 - 30; pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), @@ -2334,24 +2204,24 @@ DisplayCanvas(clientData) screenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin, width, height); #endif /* TK_NO_DOUBLE_BUFFERING */ - + /* * Clear the area to be redrawn. */ - + XFillRectangle(Tk_Display(tkwin), pixmap, canvasPtr->pixmapGC, screenX1 - canvasPtr->drawableXOrigin, screenY1 - canvasPtr->drawableYOrigin, (unsigned int) width, (unsigned int) height); - + /* - * Scan through the item list, redrawing those items that need it. - * An item must be redraw if either (a) it intersects the smaller + * Scan through the item list, redrawing those items that need it. An + * item must be redraw if either (a) it intersects the smaller * on-screen area or (b) it intersects the full canvas area and its - * type requests that it be redrawn always (e.g. so subwindows can - * be unmapped when they move off-screen). + * type requests that it be redrawn always (e.g. so subwindows can be + * unmapped when they move off-screen). */ - + for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; itemPtr = itemPtr->nextPtr) { if ((itemPtr->x1 >= screenX2) @@ -2375,13 +2245,13 @@ DisplayCanvas(clientData) canvasPtr->display, pixmap, screenX1, screenY1, width, height); } - + #ifndef TK_NO_DOUBLE_BUFFERING /* - * Copy from the temporary pixmap to the screen, then free up - * the temporary pixmap. + * Copy from the temporary pixmap to the screen, then free up the + * temporary pixmap. */ - + XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), canvasPtr->pixmapGC, screenX1 - canvasPtr->drawableXOrigin, @@ -2398,7 +2268,7 @@ DisplayCanvas(clientData) * Draw the window borders, if needed. */ - borders: + borders: if (canvasPtr->flags & REDRAW_BORDERS) { canvasPtr->flags &= ~REDRAW_BORDERS; if (canvasPtr->borderWidth > 0) { @@ -2426,7 +2296,7 @@ DisplayCanvas(clientData) } } - done: + done: canvasPtr->flags &= ~(REDRAW_PENDING|BBOX_NOT_EMPTY); canvasPtr->redrawX1 = canvasPtr->redrawX2 = 0; canvasPtr->redrawY1 = canvasPtr->redrawY2 = 0; @@ -2440,23 +2310,23 @@ DisplayCanvas(clientData) * * CanvasEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on canvases. + * This function is invoked by the Tk dispatcher for various events on + * canvases. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -CanvasEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +CanvasEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; @@ -2491,8 +2361,8 @@ CanvasEventProc(clientData, eventPtr) canvasPtr->flags |= UPDATE_SCROLLBARS; /* - * The call below is needed in order to recenter the canvas if - * it's confined and its scroll region is smaller than the window. + * The call below is needed in order to recenter the canvas if it's + * confined and its scroll region is smaller than the window. */ CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin); @@ -2513,9 +2383,9 @@ CanvasEventProc(clientData, eventPtr) Tk_Item *itemPtr; /* - * Special hack: if the canvas is unmapped, then must notify - * all items with "alwaysRedraw" set, so that they know that - * they are no longer displayed. + * Special hack: if the canvas is unmapped, then must notify all items + * with "alwaysRedraw" set, so that they know that they are no longer + * displayed. */ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; @@ -2533,9 +2403,9 @@ CanvasEventProc(clientData, eventPtr) * * CanvasCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -2547,17 +2417,17 @@ CanvasEventProc(clientData, eventPtr) */ static void -CanvasCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +CanvasCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; Tk_Window tkwin = canvasPtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (tkwin != NULL) { @@ -2571,8 +2441,8 @@ CanvasCmdDeletedProc(clientData) * * Tk_CanvasEventuallyRedraw -- * - * Arrange for part or all of a canvas widget to redrawn at - * some convenient time in the future. + * Arrange for part or all of a canvas widget to redrawn at some + * convenient time in the future. * * Results: * None. @@ -2584,18 +2454,20 @@ CanvasCmdDeletedProc(clientData) */ void -Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2) - Tk_Canvas canvas; /* Information about widget. */ - int x1, y1; /* Upper left corner of area to redraw. - * Pixels on edge are redrawn. */ - int x2, y2; /* Lower right corner of area to redraw. +Tk_CanvasEventuallyRedraw( + Tk_Canvas canvas, /* Information about widget. */ + int x1, int y1, /* Upper left corner of area to redraw. Pixels + * on edge are redrawn. */ + int x2, int y2) /* Lower right corner of area to redraw. * Pixels on edge are not redrawn. */ { TkCanvas *canvasPtr = (TkCanvas *) canvas; + /* * If tkwin is NULL, the canvas has been destroyed, so we can't really * redraw it. */ + if (canvasPtr->tkwin == NULL) { return; } @@ -2637,8 +2509,8 @@ Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2) * * EventuallyRedrawItem -- * - * Arrange for part or all of a canvas widget to redrawn at - * some convenient time in the future. + * Arrange for part or all of a canvas widget to redrawn at some + * convenient time in the future. * * Results: * None. @@ -2650,9 +2522,9 @@ Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2) */ static void -EventuallyRedrawItem(canvas, itemPtr) - Tk_Canvas canvas; /* Information about widget. */ - Tk_Item *itemPtr; /* item to be redrawn. */ +EventuallyRedrawItem( + Tk_Canvas canvas, /* Information about widget. */ + Tk_Item *itemPtr) /* Item to be redrawn. */ { TkCanvas *canvasPtr = (TkCanvas *) canvas; if ((itemPtr->x1 >= itemPtr->x2) || (itemPtr->y1 >= itemPtr->y2) || @@ -2698,27 +2570,26 @@ EventuallyRedrawItem(canvas, itemPtr) * * Tk_CreateItemType -- * - * This procedure may be invoked to add a new kind of canvas - * element to the core item types supported by Tk. + * This function may be invoked to add a new kind of canvas element to + * the core item types supported by Tk. * * Results: * None. * * Side effects: - * From now on, the new item type will be useable in canvas - * widgets (e.g. typePtr->name can be used as the item type - * in "create" widget commands). If there was already a - * type with the same name as in typePtr, it is replaced with - * the new type. + * From now on, the new item type will be useable in canvas widgets + * (e.g. typePtr->name can be used as the item type in "create" widget + * commands). If there was already a type with the same name as in + * typePtr, it is replaced with the new type. * *-------------------------------------------------------------- */ void -Tk_CreateItemType(typePtr) - Tk_ItemType *typePtr; /* Information about item type; - * storage must be statically - * allocated (must live forever). */ +Tk_CreateItemType( + Tk_ItemType *typePtr) /* Information about item type; storage must + * be statically allocated (must live + * forever). */ { Tk_ItemType *typePtr2, *prevPtr; @@ -2752,14 +2623,14 @@ Tk_CreateItemType(typePtr) * * Tk_GetItemTypes -- * - * This procedure returns a pointer to the list of all item - * types. Note that this is inherently thread-unsafe, but since - * item types are only ever registered very rarely this is - * unlikely to be a problem in practice. + * This function returns a pointer to the list of all item types. Note + * that this is inherently thread-unsafe, but since item types are only + * ever registered very rarely this is unlikely to be a problem in + * practice. * * Results: - * The return value is a pointer to the first in the list - * of item types currently supported by canvases. + * The return value is a pointer to the first in the list of item types + * currently supported by canvases. * * Side effects: * None. @@ -2768,7 +2639,7 @@ Tk_CreateItemType(typePtr) */ Tk_ItemType * -Tk_GetItemTypes() +Tk_GetItemTypes(void) { if (typeList == NULL) { InitCanvas(); @@ -2777,13 +2648,12 @@ Tk_GetItemTypes() } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * InitCanvas -- * - * This procedure is invoked to perform once-only-ever - * initialization for the module, such as setting up the type - * table. + * This function is invoked to perform once-only-ever initialization for + * the module, such as setting up the type table. * * Results: * None. @@ -2791,11 +2661,11 @@ Tk_GetItemTypes() * Side effects: * None. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -InitCanvas() +InitCanvas(void) { Tcl_MutexLock(&typeListMutex); if (typeList != NULL) { @@ -2821,33 +2691,30 @@ InitCanvas() * * StartTagSearch -- * - * This procedure is called to initiate an enumeration of - * all items in a given canvas that contain a given tag. + * This function is called to initiate an enumeration of all items in a + * given canvas that contain a given tag. * * Results: - * The return value is a pointer to the first item in - * canvasPtr that matches tag, or NULL if there is no - * such item. The information at *searchPtr is initialized - * such that successive calls to NextItem will return - * successive items that match tag. + * The return value is a pointer to the first item in canvasPtr that + * matches tag, or NULL if there is no such item. The information at + * *searchPtr is initialized such that successive calls to NextItem will + * return successive items that match tag. * * Side effects: - * SearchPtr is linked into a list of searches in progress - * on canvasPtr, so that elements can safely be deleted - * while the search is in progress. EndTagSearch must be - * called at the end of the search to unlink searchPtr from - * this list. + * SearchPtr is linked into a list of searches in progress on canvasPtr, + * so that elements can safely be deleted while the search is in + * progress. EndTagSearch must be called at the end of the search to + * unlink searchPtr from this list. * *-------------------------------------------------------------- */ static Tk_Item * -StartTagSearch(canvasPtr, tagObj, searchPtr) - TkCanvas *canvasPtr; /* Canvas whose items are to be - * searched. */ - Tcl_Obj *tagObj; /* Object giving tag value. */ - TagSearch *searchPtr; /* Record describing tag search; - * will be initialized here. */ +StartTagSearch( + TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */ + Tcl_Obj *tagObj, /* Object giving tag value. */ + TagSearch *searchPtr) /* Record describing tag search; will be + * initialized here. */ { int id; Tk_Item *itemPtr, *lastPtr; @@ -2869,10 +2736,10 @@ StartTagSearch(canvasPtr, tagObj, searchPtr) searchPtr->searchOver = 0; /* - * Find the first matching item in one of several ways. If the tag - * is a number then it selects the single item with the matching - * identifier. In this case see if the item being requested is the - * hot item, in which case the search can be skipped. + * Find the first matching item in one of several ways. If the tag is a + * number then it selects the single item with the matching identifier. + * In this case see if the item being requested is the hot item, in which + * case the search can be skipped. */ if (isdigit(UCHAR(*tag))) { @@ -2883,7 +2750,7 @@ StartTagSearch(canvasPtr, tagObj, searchPtr) id = strtoul(tag, &end, 0); if (*end == 0) { itemPtr = canvasPtr->hotPtr; - lastPtr = canvasPtr->hotPrevPtr; + lastPtr = canvasPtr->hotPrevPtr; if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) { dispPtr->numSlowSearches++; @@ -2916,7 +2783,7 @@ StartTagSearch(canvasPtr, tagObj, searchPtr) } /* - * None of the above. Search for an item with a matching tag. + * None of the above. Search for an item with a matching tag. */ for (lastPtr = NULL, itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; @@ -2940,15 +2807,15 @@ StartTagSearch(canvasPtr, tagObj, searchPtr) * * NextItem -- * - * This procedure returns successive items that match a given - * tag; it should be called only after StartTagSearch has been - * used to begin a search. + * This function returns successive items that match a given tag; it + * should be called only after StartTagSearch has been used to begin a + * search. * * Results: - * The return value is a pointer to the next item that matches - * the tag specified to StartTagSearch, or NULL if no such - * item exists. *SearchPtr is updated so that the next call - * to this procedure will return the next item. + * The return value is a pointer to the next item that matches the tag + * specified to StartTagSearch, or NULL if no such item exists. + * *SearchPtr is updated so that the next call to this function will + * return the next item. * * Side effects: * None. @@ -2957,9 +2824,8 @@ StartTagSearch(canvasPtr, tagObj, searchPtr) */ static Tk_Item * -NextItem(searchPtr) - TagSearch *searchPtr; /* Record describing search in - * progress. */ +NextItem( + TagSearch *searchPtr) /* Record describing search in progress. */ { Tk_Item *itemPtr, *lastPtr; int count; @@ -2967,8 +2833,8 @@ NextItem(searchPtr) Tk_Uid *tagPtr; /* - * Find next item in list (this may not actually be a suitable - * one to return), and return if there are no items left. + * Find next item in list (this may not actually be a suitable one to + * return), and return if there are no items left. */ lastPtr = searchPtr->lastPtr; @@ -2983,10 +2849,10 @@ NextItem(searchPtr) } if (itemPtr != searchPtr->currentPtr) { /* - * The structure of the list has changed. Probably the - * previously-returned item was removed from the list. - * In this case, don't advance lastPtr; just return - * its new successor (i.e. do nothing here). + * The structure of the list has changed. Probably the previously- + * returned item was removed from the list. In this case, don't + * advance lastPtr; just return its new successor (i.e. do nothing + * here). */ } else { lastPtr = itemPtr; @@ -3023,29 +2889,28 @@ NextItem(searchPtr) return NULL; } -#else /* USE_OLD_TAG_SEARCH */ +#else /* !USE_OLD_TAG_SEARCH */ /* *---------------------------------------------------------------------- * * GetStaticUids -- * - *This procedure is invoked to return a structure filled with - *the Uids used when doing tag searching. If it was never before - *called in the current thread, it initializes the structure for - *that thread (uids are only ever local to one thread [Bug - *1114977]). + * This function is invoked to return a structure filled with the Uids + * used when doing tag searching. If it was never before called in the + * current thread, it initializes the structure for that thread (uids are + * only ever local to one thread [Bug 1114977]). * * Results: - *None. + * None. * * Side effects: - *None. + * None. * *---------------------------------------------------------------------- */ static SearchUids * -GetStaticUids() +GetStaticUids(void) { SearchUids *searchUids = (SearchUids *) Tcl_GetThreadData(&dataKey, sizeof(SearchUids)); @@ -3070,7 +2935,7 @@ GetStaticUids() * * TagSearchExprInit -- * - * This procedure allocates and initializes one TagSearchExpr struct. + * This function allocates and initializes one TagSearchExpr struct. * * Results: * @@ -3080,8 +2945,8 @@ GetStaticUids() */ static void -TagSearchExprInit(exprPtrPtr) - TagSearchExpr **exprPtrPtr; +TagSearchExprInit( + TagSearchExpr **exprPtrPtr) { TagSearchExpr* expr = *exprPtrPtr; @@ -3096,67 +2961,63 @@ TagSearchExprInit(exprPtrPtr) expr->length = 0; *exprPtrPtr = expr; } - + /* *-------------------------------------------------------------- * * TagSearchExprDestroy -- * - * This procedure destroys one TagSearchExpr structure. + * This function destroys one TagSearchExpr structure. * * Results: * * Side effects: * *-------------------------------------------------------------- - */ + */ static void -TagSearchExprDestroy(expr) - TagSearchExpr *expr; +TagSearchExprDestroy( + TagSearchExpr *expr) { if (expr) { if (expr->uids) { - ckfree((char *)expr->uids); + ckfree((char *)expr->uids); } - ckfree((char *)expr); + ckfree((char *)expr); } } - + /* *-------------------------------------------------------------- * * TagSearchScan -- * - * This procedure is called to initiate an enumeration of - * all items in a given canvas that contain a tag that matches - * the tagOrId expression. + * This function is called to initiate an enumeration of all items in a + * given canvas that contain a tag that matches the tagOrId expression. * * Results: - * The return value indicates if the tagOrId expression - * was successfully scanned (syntax). - * The information at *searchPtr is initialized - * such that a call to TagSearchFirst, followed by - * successive calls to TagSearchNext will return items - * that match tag. + * The return value indicates if the tagOrId expression was successfully + * scanned (syntax). The information at *searchPtr is initialized such + * that a call to TagSearchFirst, followed by successive calls to + * TagSearchNext will return items that match tag. * * Side effects: - * SearchPtr is linked into a list of searches in progress - * on canvasPtr, so that elements can safely be deleted - * while the search is in progress. + * SearchPtr is linked into a list of searches in progress on canvasPtr, + * so that elements can safely be deleted while the search is in + * progress. * *-------------------------------------------------------------- */ static int -TagSearchScan(canvasPtr, tagObj, searchPtrPtr) - TkCanvas *canvasPtr; /* Canvas whose items are to be - * searched. */ - Tcl_Obj *tagObj; /* Object giving tag value. */ - TagSearch **searchPtrPtr; /* Record describing tag search; - * will be initialized here. */ +TagSearchScan( + TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */ + Tcl_Obj *tagObj, /* Object giving tag value. */ + TagSearch **searchPtrPtr) /* Record describing tag search; will be + * initialized here. */ { - char *tag = Tcl_GetStringFromObj(tagObj,NULL); + char *tag = Tcl_GetString(tagObj); int i; TagSearch *searchPtr; @@ -3165,61 +3026,78 @@ TagSearchScan(canvasPtr, tagObj, searchPtrPtr) */ if (*searchPtrPtr) { - searchPtr = *searchPtrPtr; + searchPtr = *searchPtrPtr; } else { - /* Allocate primary search struct on first call */ - *searchPtrPtr = searchPtr = (TagSearch *) ckalloc(sizeof(TagSearch)); + /* + * Allocate primary search struct on first call. + */ + + *searchPtrPtr = searchPtr = (TagSearch *) ckalloc(sizeof(TagSearch)); searchPtr->expr = NULL; - /* Allocate buffer for rewritten tags (after de-escaping) */ - searchPtr->rewritebufferAllocated = 100; - searchPtr->rewritebuffer = - ckalloc(searchPtr->rewritebufferAllocated); + /* + * Allocate buffer for rewritten tags (after de-escaping). + */ + + searchPtr->rewritebufferAllocated = 100; + searchPtr->rewritebuffer = ckalloc(searchPtr->rewritebufferAllocated); } TagSearchExprInit(&(searchPtr->expr)); - /* How long is the tagOrId ? */ + /* + * How long is the tagOrId? + */ + searchPtr->stringLength = strlen(tag); - /* Make sure there is enough buffer to hold rewritten tags */ + /* + * Make sure there is enough buffer to hold rewritten tags. + */ + if ((unsigned int)searchPtr->stringLength >= searchPtr->rewritebufferAllocated) { - searchPtr->rewritebufferAllocated = searchPtr->stringLength + 100; - searchPtr->rewritebuffer = - ckrealloc(searchPtr->rewritebuffer, - searchPtr->rewritebufferAllocated); + searchPtr->rewritebufferAllocated = searchPtr->stringLength + 100; + searchPtr->rewritebuffer = + ckrealloc(searchPtr->rewritebuffer, + searchPtr->rewritebufferAllocated); } - /* Initialize search */ + /* + * Initialize search. + */ + searchPtr->canvasPtr = canvasPtr; searchPtr->searchOver = 0; - searchPtr->type = 0; + searchPtr->type = SEARCH_TYPE_EMPTY; /* - * Find the first matching item in one of several ways. If the tag - * is a number then it selects the single item with the matching - * identifier. In this case see if the item being requested is the - * hot item, in which case the search can be skipped. + * Find the first matching item in one of several ways. If the tag is a + * number then it selects the single item with the matching identifier. + * In this case see if the item being requested is the hot item, in which + * case the search can be skipped. */ if (searchPtr->stringLength && isdigit(UCHAR(*tag))) { - char *end; + char *end; - searchPtr->id = strtoul(tag, &end, 0); - if (*end == 0) { - searchPtr->type = 1; - return TCL_OK; + searchPtr->id = strtoul(tag, &end, 0); + if (*end == 0) { + searchPtr->type = SEARCH_TYPE_ID; + return TCL_OK; } } /* - * For all other tags and tag expressions convert to a UID. - * This UID is kept forever, but this should be thought of - * as a cache rather than as a memory leak. + * For all other tags and tag expressions convert to a UID. This UID is + * kept forever, but this should be thought of as a cache rather than as a + * memory leak. */ searchPtr->expr->uid = Tk_GetUid(tag); - /* short circuit impossible searches for null tags */ + /* + * Short circuit impossible searches for null tags. + */ + if (searchPtr->stringLength == 0) { return TCL_OK; } @@ -3228,55 +3106,58 @@ TagSearchScan(canvasPtr, tagObj, searchPtrPtr) * Pre-scan tag for at least one unquoted "&&" "||" "^" "!" * if not found then use string as simple tag */ + for (i = 0; i < searchPtr->stringLength ; i++) { - if (tag[i] == '"') { - i++; - for ( ; i < searchPtr->stringLength; i++) { - if (tag[i] == '\\') { - i++; - continue; - } - if (tag[i] == '"') { - break; - } - } - } else { - if ((tag[i] == '&' && tag[i+1] == '&') - || (tag[i] == '|' && tag[i+1] == '|') - || (tag[i] == '^') - || (tag[i] == '!')) { - searchPtr->type = 4; - break; - } - } + if (tag[i] == '"') { + i++; + for ( ; i < searchPtr->stringLength; i++) { + if (tag[i] == '\\') { + i++; + continue; + } + if (tag[i] == '"') { + break; + } + } + } else if ((tag[i] == '&' && tag[i+1] == '&') + || (tag[i] == '|' && tag[i+1] == '|') + || (tag[i] == '^') + || (tag[i] == '!')) { + searchPtr->type = SEARCH_TYPE_EXPR; + break; + } } searchPtr->string = tag; searchPtr->stringIndex = 0; - if (searchPtr->type == 4) { - /* - * an operator was found in the prescan, so - * now compile the tag expression into array of Tk_Uid - * flagging any syntax errors found - */ - if (TagSearchScanExpr(canvasPtr->interp, searchPtr, searchPtr->expr) != TCL_OK) { - /* Syntax error in tag expression */ - /* Result message set by TagSearchScanExpr */ + if (searchPtr->type == SEARCH_TYPE_EXPR) { + /* + * An operator was found in the prescan, so now compile the tag + * expression into array of Tk_Uid flagging any syntax errors found. + */ + + if (TagSearchScanExpr(canvasPtr->interp, searchPtr, + searchPtr->expr) != TCL_OK) { + /* + * Syntax error in tag expression. The result message was set by + * TagSearchScanExpr. + */ + return TCL_ERROR; } searchPtr->expr->length = searchPtr->expr->index; + } else if (searchPtr->expr->uid == GetStaticUids()->allUid) { + /* + * All items match. + */ + + searchPtr->type = SEARCH_TYPE_ALL; } else { - if (searchPtr->expr->uid == GetStaticUids()->allUid) { - /* - * All items match. - */ - searchPtr->type = 2; - } else { - /* - * Optimized single-tag search - */ - searchPtr->type = 3; - } + /* + * Optimized single-tag search + */ + + searchPtr->type = SEARCH_TYPE_TAG; } return TCL_OK; } @@ -3286,24 +3167,26 @@ TagSearchScan(canvasPtr, tagObj, searchPtrPtr) * * TagSearchDestroy -- * - * This procedure destroys any dynamic structures that - * may have been allocated by TagSearchScan. + * This function destroys any dynamic structures that may have been + * allocated by TagSearchScan. * * Results: + * None * * Side effects: + * Deallocates memory. * *-------------------------------------------------------------- */ static void -TagSearchDestroy(searchPtr) - TagSearch *searchPtr; /* Record describing tag search */ +TagSearchDestroy( + TagSearch *searchPtr) /* Record describing tag search */ { if (searchPtr) { - TagSearchExprDestroy(searchPtr->expr); - ckfree((char *)searchPtr->rewritebuffer); - ckfree((char *)searchPtr); + TagSearchExprDestroy(searchPtr->expr); + ckfree((char *)searchPtr->rewritebuffer); + ckfree((char *)searchPtr); } } @@ -3312,16 +3195,14 @@ TagSearchDestroy(searchPtr) * * TagSearchScanExpr -- * - * This recursive procedure is called to scan a tag expression - * and compile it into an array of Tk_Uids. + * This recursive function is called to scan a tag expression and compile + * it into an array of Tk_Uids. * * Results: - * The return value indicates if the tagOrId expression - * was successfully scanned (syntax). - * The information at *searchPtr is initialized - * such that a call to TagSearchFirst, followed by - * successive calls to TagSearchNext will return items - * that match tag. + * The return value indicates if the tagOrId expression was successfully + * scanned (syntax). The information at *searchPtr is initialized such + * that a call to TagSearchFirst, followed by successive calls to + * TagSearchNext will return items that match tag. * * Side effects: * @@ -3329,216 +3210,233 @@ TagSearchDestroy(searchPtr) */ static int -TagSearchScanExpr(interp, searchPtr, expr) - Tcl_Interp *interp; /* Current interpreter. */ - TagSearch *searchPtr; /* Search data */ - TagSearchExpr *expr; /* compiled expression result */ +TagSearchScanExpr( + Tcl_Interp *interp, /* Current interpreter. */ + TagSearch *searchPtr, /* Search data */ + TagSearchExpr *expr) /* compiled expression result */ { - int looking_for_tag; /* When true, scanner expects - * next char(s) to be a tag, - * else operand expected */ - int found_tag; /* One or more tags found */ - int found_endquote; /* For quoted tag string parsing */ - int negate_result; /* Pending negation of next tag value */ - char *tag; /* tag from tag expression string */ + int looking_for_tag; /* When true, scanner expects next char(s) to + * be a tag, else operand expected */ + int found_tag; /* One or more tags found */ + int found_endquote; /* For quoted tag string parsing */ + int negate_result; /* Pending negation of next tag value */ + char *tag; /* Tag from tag expression string */ char c; SearchUids *searchUids; /* Collection of uids for basic search * expression terms. */ - + searchUids = GetStaticUids(); negate_result = 0; found_tag = 0; looking_for_tag = 1; while (searchPtr->stringIndex < searchPtr->stringLength) { - c = searchPtr->string[searchPtr->stringIndex++]; + c = searchPtr->string[searchPtr->stringIndex++]; - if (expr->allocated == expr->index) { - expr->allocated += 15; + /* + * Need two slots free at this point, not one. [Bug 2931374] + */ + + if (expr->index >= expr->allocated-1) { + expr->allocated += 15; if (expr->uids) { - expr->uids = - (Tk_Uid *) ckrealloc((char *)(expr->uids), - (expr->allocated)*sizeof(Tk_Uid)); + expr->uids = (Tk_Uid *) + ckrealloc((char *)(expr->uids), + (expr->allocated)*sizeof(Tk_Uid)); } else { - expr->uids = - (Tk_Uid *) ckalloc((expr->allocated)*sizeof(Tk_Uid)); + expr->uids = (Tk_Uid *) + ckalloc((expr->allocated)*sizeof(Tk_Uid)); } - } - - if (looking_for_tag) { - - switch (c) { - case ' ' : /* ignore unquoted whitespace */ - case '\t' : - case '\n' : - case '\r' : - break; - - case '!' : /* negate next tag or subexpr */ - if (looking_for_tag > 1) { - Tcl_AppendResult(interp, - "Too many '!' in tag search expression", - (char *) NULL); - return TCL_ERROR; - } - looking_for_tag++; - negate_result = 1; - break; - - case '(' : /* scan (negated) subexpr recursively */ - if (negate_result) { - expr->uids[expr->index++] = searchUids->negparenUid; - negate_result = 0; - } else { - expr->uids[expr->index++] = searchUids->parenUid; + } + + if (looking_for_tag) { + + switch (c) { + case ' ': /* ignore unquoted whitespace */ + case '\t': + case '\n': + case '\r': + break; + + case '!': /* negate next tag or subexpr */ + if (looking_for_tag > 1) { + Tcl_AppendResult(interp, + "Too many '!' in tag search expression", + NULL); + return TCL_ERROR; + } + looking_for_tag++; + negate_result = 1; + break; + + case '(': /* scan (negated) subexpr recursively */ + if (negate_result) { + expr->uids[expr->index++] = searchUids->negparenUid; + negate_result = 0; + } else { + expr->uids[expr->index++] = searchUids->parenUid; + } + if (TagSearchScanExpr(interp, searchPtr, expr) != TCL_OK) { + /* + * Result string should be already set by nested call to + * tag_expr_scan() + */ + + return TCL_ERROR; + } + looking_for_tag = 0; + found_tag = 1; + break; + + case '"': /* quoted tag string */ + if (negate_result) { + expr->uids[expr->index++] = searchUids->negtagvalUid; + negate_result = 0; + } else { + expr->uids[expr->index++] = searchUids->tagvalUid; + } + tag = searchPtr->rewritebuffer; + found_endquote = 0; + while (searchPtr->stringIndex < searchPtr->stringLength) { + c = searchPtr->string[searchPtr->stringIndex++]; + if (c == '\\') { + c = searchPtr->string[searchPtr->stringIndex++]; } - if (TagSearchScanExpr(interp, searchPtr, expr) != TCL_OK) { - /* Result string should be already set - * by nested call to tag_expr_scan() */ - return TCL_ERROR; + if (c == '"') { + found_endquote = 1; + break; } - looking_for_tag = 0; - found_tag = 1; - break; - - case '"' : /* quoted tag string */ - if (negate_result) { - expr->uids[expr->index++] = searchUids->negtagvalUid; - negate_result = 0; - } else { - expr->uids[expr->index++] = searchUids->tagvalUid; + *tag++ = c; + } + if (! found_endquote) { + Tcl_AppendResult(interp, + "Missing endquote in tag search expression", + NULL); + return TCL_ERROR; + } + if (! (tag - searchPtr->rewritebuffer)) { + Tcl_AppendResult(interp, + "Null quoted tag string in tag search expression", + NULL); + return TCL_ERROR; + } + *tag++ = '\0'; + expr->uids[expr->index++] = + Tk_GetUid(searchPtr->rewritebuffer); + looking_for_tag = 0; + found_tag = 1; + break; + + case '&': /* illegal chars when looking for tag */ + case '|': + case '^': + case ')': + Tcl_AppendResult(interp, + "Unexpected operator in tag search expression", + NULL); + return TCL_ERROR; + + default: /* unquoted tag string */ + if (negate_result) { + expr->uids[expr->index++] = searchUids->negtagvalUid; + negate_result = 0; + } else { + expr->uids[expr->index++] = searchUids->tagvalUid; + } + tag = searchPtr->rewritebuffer; + *tag++ = c; + + /* + * Copy rest of tag, including any embedded whitespace. + */ + + while (searchPtr->stringIndex < searchPtr->stringLength) { + c = searchPtr->string[searchPtr->stringIndex]; + if (c == '!' || c == '&' || c == '|' || c == '^' + || c == '(' || c == ')' || c == '"') { + break; } - tag = searchPtr->rewritebuffer; - found_endquote = 0; - while (searchPtr->stringIndex < searchPtr->stringLength) { - c = searchPtr->string[searchPtr->stringIndex++]; - if (c == '\\') { - c = searchPtr->string[searchPtr->stringIndex++]; - } - if (c == '"') { - found_endquote = 1; - break; - } - *tag++ = c; - } - if (! found_endquote) { - Tcl_AppendResult(interp, - "Missing endquote in tag search expression", - (char *) NULL); - return TCL_ERROR; - } - if (! (tag - searchPtr->rewritebuffer)) { - Tcl_AppendResult(interp, - "Null quoted tag string in tag search expression", - (char *) NULL); - return TCL_ERROR; - } - *tag++ = '\0'; - expr->uids[expr->index++] = - Tk_GetUid(searchPtr->rewritebuffer); - looking_for_tag = 0; - found_tag = 1; - break; - - case '&' : /* illegal chars when looking for tag */ - case '|' : - case '^' : - case ')' : - Tcl_AppendResult(interp, - "Unexpected operator in tag search expression", - (char *) NULL); - return TCL_ERROR; - - default : /* unquoted tag string */ - if (negate_result) { - expr->uids[expr->index++] = searchUids->negtagvalUid; - negate_result = 0; - } else { - expr->uids[expr->index++] = searchUids->tagvalUid; - } - tag = searchPtr->rewritebuffer; - *tag++ = c; - /* copy rest of tag, including any embedded whitespace */ - while (searchPtr->stringIndex < searchPtr->stringLength) { - c = searchPtr->string[searchPtr->stringIndex]; - if (c == '!' || c == '&' || c == '|' || c == '^' - || c == '(' || c == ')' || c == '"') { - break; - } - *tag++ = c; - searchPtr->stringIndex++; - } - /* remove trailing whitespace */ - while (1) { - c = *--tag; - /* there must have been one non-whitespace char, - * so this will terminate */ - if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { - break; - } - } - *++tag = '\0'; - expr->uids[expr->index++] = - Tk_GetUid(searchPtr->rewritebuffer); - looking_for_tag = 0; - found_tag = 1; - } - - } else { /* ! looking_for_tag */ - - switch (c) { - case ' ' : /* ignore whitespace */ - case '\t' : - case '\n' : - case '\r' : - break; - - case '&' : /* AND operator */ - c = searchPtr->string[searchPtr->stringIndex++]; - if (c != '&') { - Tcl_AppendResult(interp, - "Singleton '&' in tag search expression", - (char *) NULL); - return TCL_ERROR; - } - expr->uids[expr->index++] = searchUids->andUid; - looking_for_tag = 1; - break; - - case '|' : /* OR operator */ - c = searchPtr->string[searchPtr->stringIndex++]; - if (c != '|') { - Tcl_AppendResult(interp, - "Singleton '|' in tag search expression", - (char *) NULL); - return TCL_ERROR; - } - expr->uids[expr->index++] = searchUids->orUid; - looking_for_tag = 1; - break; - - case '^' : /* XOR operator */ - expr->uids[expr->index++] = searchUids->xorUid; - looking_for_tag = 1; - break; - - case ')' : /* end subexpression */ - expr->uids[expr->index++] = searchUids->endparenUid; - goto breakwhile; - - default : /* syntax error */ - Tcl_AppendResult(interp, - "Invalid boolean operator in tag search expression", - (char *) NULL); - return TCL_ERROR; - } - } - } - breakwhile: + *tag++ = c; + searchPtr->stringIndex++; + } + + /* + * Remove trailing whitespace. + */ + + while (1) { + c = *--tag; + + /* + * There must have been one non-whitespace char, so this + * will terminate. + */ + + if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { + break; + } + } + *++tag = '\0'; + expr->uids[expr->index++] = + Tk_GetUid(searchPtr->rewritebuffer); + looking_for_tag = 0; + found_tag = 1; + } + + } else { /* ! looking_for_tag */ + switch (c) { + case ' ': /* ignore whitespace */ + case '\t': + case '\n': + case '\r': + break; + + case '&': /* AND operator */ + c = searchPtr->string[searchPtr->stringIndex++]; + if (c != '&') { + Tcl_AppendResult(interp, + "Singleton '&' in tag search expression", + NULL); + return TCL_ERROR; + } + expr->uids[expr->index++] = searchUids->andUid; + looking_for_tag = 1; + break; + + case '|': /* OR operator */ + c = searchPtr->string[searchPtr->stringIndex++]; + if (c != '|') { + Tcl_AppendResult(interp, + "Singleton '|' in tag search expression", + NULL); + return TCL_ERROR; + } + expr->uids[expr->index++] = searchUids->orUid; + looking_for_tag = 1; + break; + + case '^' : /* XOR operator */ + expr->uids[expr->index++] = searchUids->xorUid; + looking_for_tag = 1; + break; + + case ')' : /* end subexpression */ + expr->uids[expr->index++] = searchUids->endparenUid; + goto breakwhile; + + default: /* syntax error */ + Tcl_AppendResult(interp, + "Invalid boolean operator in tag search expression", + NULL); + return TCL_ERROR; + } + } + } + + breakwhile: if (found_tag && ! looking_for_tag) { - return TCL_OK; + return TCL_OK; } - Tcl_AppendResult(interp, "Missing tag in tag search expression", - (char *) NULL); + Tcl_AppendResult(interp, "Missing tag in tag search expression", NULL); return TCL_ERROR; } @@ -3547,11 +3445,11 @@ TagSearchScanExpr(interp, searchPtr, expr) * * TagSearchEvalExpr -- * - * This recursive procedure is called to eval a tag expression. + * This recursive function is called to eval a tag expression. * * Results: - * The return value indicates if the tagOrId expression - * successfully matched the tags of the current item. + * The return value indicates if the tagOrId expression successfully + * matched the tags of the current item. * * Side effects: * @@ -3559,18 +3457,17 @@ TagSearchScanExpr(interp, searchPtr, expr) */ static int -TagSearchEvalExpr(expr, itemPtr) - TagSearchExpr *expr; /* Search expression */ - Tk_Item *itemPtr; /* Item being test for match */ +TagSearchEvalExpr( + TagSearchExpr *expr, /* Search expression */ + Tk_Item *itemPtr) /* Item being test for match */ { - int looking_for_tag; /* When true, scanner expects - * next char(s) to be a tag, - * else operand expected */ - int negate_result; /* Pending negation of next tag value */ + int looking_for_tag; /* When true, scanner expects next char(s) to + * be a tag, else operand expected. */ + int negate_result; /* Pending negation of next tag value */ Tk_Uid uid; Tk_Uid *tagPtr; int count; - int result; /* Value of expr so far */ + int result; /* Value of expr so far */ int parendepth; SearchUids *searchUids; /* Collection of uids for basic search * expression terms. */ @@ -3581,77 +3478,84 @@ TagSearchEvalExpr(expr, itemPtr) negate_result = 0; looking_for_tag = 1; while (expr->index < expr->length) { - uid = expr->uids[expr->index++]; - if (looking_for_tag) { - if (uid == searchUids->tagvalUid) { + uid = expr->uids[expr->index++]; + if (looking_for_tag) { + if (uid == searchUids->tagvalUid) { /* - * assert(expr->index < expr->length); + * assert(expr->index < expr->length); */ - uid = expr->uids[expr->index++]; - result = 0; - /* - * set result 1 if tag is found in item's tags - */ - for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; - count > 0; tagPtr++, count--) { - if (*tagPtr == uid) { - result = 1; - break; - } - } - - } else if (uid == searchUids->negtagvalUid) { - negate_result = ! negate_result; + uid = expr->uids[expr->index++]; + result = 0; + + /* + * set result 1 if tag is found in item's tags + */ + + for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; + count > 0; tagPtr++, count--) { + if (*tagPtr == uid) { + result = 1; + break; + } + } + + } else if (uid == searchUids->negtagvalUid) { + negate_result = ! negate_result; /* - * assert(expr->index < expr->length); + * assert(expr->index < expr->length); */ - uid = expr->uids[expr->index++]; - result = 0; - /* - * set result 1 if tag is found in item's tags - */ - for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; - count > 0; tagPtr++, count--) { - if (*tagPtr == uid) { - result = 1; - break; - } - } - - } else if (uid == searchUids->parenUid) { - /* - * evaluate subexpressions with recursion - */ - result = TagSearchEvalExpr(expr, itemPtr); - - } else if (uid == searchUids->negparenUid) { - negate_result = ! negate_result; - /* - * evaluate subexpressions with recursion - */ - result = TagSearchEvalExpr(expr, itemPtr); + uid = expr->uids[expr->index++]; + result = 0; + + /* + * set result 1 if tag is found in item's tags + */ + + for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; + count > 0; tagPtr++, count--) { + if (*tagPtr == uid) { + result = 1; + break; + } + } + + } else if (uid == searchUids->parenUid) { + /* + * Evaluate subexpressions with recursion + */ + + result = TagSearchEvalExpr(expr, itemPtr); + + } else if (uid == searchUids->negparenUid) { + negate_result = ! negate_result; + + /* + * Evaluate subexpressions with recursion + */ + + result = TagSearchEvalExpr(expr, itemPtr); /* - * } else { - * assert(0); + * } else { + * assert(0); */ - } - if (negate_result) { - result = ! result; - negate_result = 0; - } - looking_for_tag = 0; - } else { /* ! looking_for_tag */ - if (((uid == searchUids->andUid) && (!result)) || + } + if (negate_result) { + result = ! result; + negate_result = 0; + } + looking_for_tag = 0; + } else { /* ! looking_for_tag */ + if (((uid == searchUids->andUid) && (!result)) || ((uid == searchUids->orUid) && result)) { - /* - * short circuit expression evaluation - * - * if result before && is 0, or result before || is 1, - * then the expression is decided and no further - * evaluation is needed. - */ - - parendepth = 0; + /* + * Short circuit expression evaluation. + * + * if result before && is 0, or result before || is 1, then + * the expression is decided and no further evaluation is + * needed. + */ + + parendepth = 0; while (expr->index < expr->length) { uid = expr->uids[expr->index++]; if (uid == searchUids->tagvalUid || @@ -3663,7 +3567,7 @@ TagSearchEvalExpr(expr, itemPtr) uid == searchUids->negparenUid) { parendepth++; continue; - } + } if (uid == searchUids->endparenUid) { parendepth--; if (parendepth < 0) { @@ -3671,24 +3575,24 @@ TagSearchEvalExpr(expr, itemPtr) } } } - return result; + return result; - } else if (uid == searchUids->xorUid) { - /* - * if the previous result was 1 - * then negate the next result - */ - negate_result = result; + } else if (uid == searchUids->xorUid) { + /* + * If the previous result was 1 then negate the next result. + */ - } else if (uid == searchUids->endparenUid) { - return result; + negate_result = result; + + } else if (uid == searchUids->endparenUid) { + return result; /* - * } else { - * assert(0); + * } else { + * assert(0); */ - } - looking_for_tag = 1; - } + } + looking_for_tag = 1; + } } /* * assert(! looking_for_tag); @@ -3701,104 +3605,103 @@ TagSearchEvalExpr(expr, itemPtr) * * TagSearchFirst -- * - * This procedure is called to get the first item - * item that matches a preestablished search predicate - * that was set by TagSearchScan. + * This function is called to get the first item item that matches a + * preestablished search predicate that was set by TagSearchScan. * * Results: - * The return value is a pointer to the first item, or NULL - * if there is no such item. The information at *searchPtr - * is updated such that successive calls to TagSearchNext - * will return successive items. + * The return value is a pointer to the first item, or NULL if there is + * no such item. The information at *searchPtr is updated such that + * successive calls to TagSearchNext will return successive items. * * Side effects: - * SearchPtr is linked into a list of searches in progress - * on canvasPtr, so that elements can safely be deleted - * while the search is in progress. + * SearchPtr is linked into a list of searches in progress on canvasPtr, + * so that elements can safely be deleted while the search is in + * progress. * *-------------------------------------------------------------- */ static Tk_Item * -TagSearchFirst(searchPtr) - TagSearch *searchPtr; /* Record describing tag search */ +TagSearchFirst( + TagSearch *searchPtr) /* Record describing tag search */ { Tk_Item *itemPtr, *lastPtr; Tk_Uid uid, *tagPtr; int count; - /* short circuit impossible searches for null tags */ + /* + * Short circuit impossible searches for null tags. + */ + if (searchPtr->stringLength == 0) { - return NULL; + return NULL; } /* - * Find the first matching item in one of several ways. If the tag - * is a number then it selects the single item with the matching - * identifier. In this case see if the item being requested is the - * hot item, in which case the search can be skipped. + * Find the first matching item in one of several ways. If the tag is a + * number then it selects the single item with the matching identifier. + * In this case see if the item being requested is the hot item, in which + * case the search can be skipped. */ - if (searchPtr->type == 1) { - Tcl_HashEntry *entryPtr; - - itemPtr = searchPtr->canvasPtr->hotPtr; - lastPtr = searchPtr->canvasPtr->hotPrevPtr; - if ((itemPtr == NULL) || (itemPtr->id != searchPtr->id) || - (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) { - entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable, - (char *) searchPtr->id); - if (entryPtr != NULL) { - itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr); - lastPtr = itemPtr->prevPtr; - } else { - lastPtr = itemPtr = NULL; - } - } - searchPtr->lastPtr = lastPtr; - searchPtr->searchOver = 1; - searchPtr->canvasPtr->hotPtr = itemPtr; - searchPtr->canvasPtr->hotPrevPtr = lastPtr; - return itemPtr; - } - - if (searchPtr->type == 2) { - - /* - * All items match. - */ - - searchPtr->lastPtr = NULL; - searchPtr->currentPtr = searchPtr->canvasPtr->firstItemPtr; - return searchPtr->canvasPtr->firstItemPtr; - } - - if (searchPtr->type == 3) { - - /* - * Optimized single-tag search - */ - - uid = searchPtr->expr->uid; - for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr; - itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { - for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; - count > 0; tagPtr++, count--) { - if (*tagPtr == uid) { - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; - } - } - } + if (searchPtr->type == SEARCH_TYPE_ID) { + Tcl_HashEntry *entryPtr; + + itemPtr = searchPtr->canvasPtr->hotPtr; + lastPtr = searchPtr->canvasPtr->hotPrevPtr; + if ((itemPtr == NULL) || (itemPtr->id != searchPtr->id) + || (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) { + entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable, + (char *) INT2PTR(searchPtr->id)); + if (entryPtr != NULL) { + itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr); + lastPtr = itemPtr->prevPtr; + } else { + lastPtr = itemPtr = NULL; + } + } + searchPtr->lastPtr = lastPtr; + searchPtr->searchOver = 1; + searchPtr->canvasPtr->hotPtr = itemPtr; + searchPtr->canvasPtr->hotPrevPtr = lastPtr; + return itemPtr; + } + + if (searchPtr->type == SEARCH_TYPE_ALL) { + /* + * All items match. + */ + + searchPtr->lastPtr = NULL; + searchPtr->currentPtr = searchPtr->canvasPtr->firstItemPtr; + return searchPtr->canvasPtr->firstItemPtr; + } + + if (searchPtr->type == SEARCH_TYPE_TAG) { + /* + * Optimized single-tag search + */ + + uid = searchPtr->expr->uid; + for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr; + itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { + for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; + count > 0; tagPtr++, count--) { + if (*tagPtr == uid) { + searchPtr->lastPtr = lastPtr; + searchPtr->currentPtr = itemPtr; + return itemPtr; + } + } + } } else { /* - * None of the above. Search for an item matching the tag expression. + * None of the above. Search for an item matching the tag expression. */ for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr; - itemPtr != NULL; lastPtr=itemPtr, itemPtr=itemPtr->nextPtr) { + itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { searchPtr->expr->index = 0; if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) { searchPtr->lastPtr = lastPtr; @@ -3817,89 +3720,86 @@ TagSearchFirst(searchPtr) * * TagSearchNext -- * - * This procedure returns successive items that match a given - * tag; it should be called only after TagSearchFirst has been - * used to begin a search. + * This function returns successive items that match a given tag; it + * should be called only after TagSearchFirst has been used to begin a + * search. * * Results: - * The return value is a pointer to the next item that matches - * the tag expr specified to TagSearchScan, or NULL if no such - * item exists. *SearchPtr is updated so that the next call - * to this procedure will return the next item. + * The return value is a pointer to the next item that matches the tag + * expr specified to TagSearchScan, or NULL if no such item exists. + * *SearchPtr is updated so that the next call to this function will + * return the next item. * * Side effects: - * None. + * None. * *-------------------------------------------------------------- */ static Tk_Item * -TagSearchNext(searchPtr) - TagSearch *searchPtr; /* Record describing search in - * progress. */ +TagSearchNext( + TagSearch *searchPtr) /* Record describing search in progress. */ { Tk_Item *itemPtr, *lastPtr; Tk_Uid uid, *tagPtr; int count; /* - * Find next item in list (this may not actually be a suitable - * one to return), and return if there are no items left. + * Find next item in list (this may not actually be a suitable one to + * return), and return if there are no items left. */ lastPtr = searchPtr->lastPtr; if (lastPtr == NULL) { - itemPtr = searchPtr->canvasPtr->firstItemPtr; + itemPtr = searchPtr->canvasPtr->firstItemPtr; } else { - itemPtr = lastPtr->nextPtr; + itemPtr = lastPtr->nextPtr; } if ((itemPtr == NULL) || (searchPtr->searchOver)) { - searchPtr->searchOver = 1; - return NULL; + searchPtr->searchOver = 1; + return NULL; } if (itemPtr != searchPtr->currentPtr) { - /* - * The structure of the list has changed. Probably the - * previously-returned item was removed from the list. - * In this case, don't advance lastPtr; just return - * its new successor (i.e. do nothing here). - */ + /* + * The structure of the list has changed. Probably the previously- + * returned item was removed from the list. In this case, don't + * advance lastPtr; just return its new successor (i.e. do nothing + * here). + */ } else { - lastPtr = itemPtr; - itemPtr = lastPtr->nextPtr; + lastPtr = itemPtr; + itemPtr = lastPtr->nextPtr; } - if (searchPtr->type == 2) { - - /* - * All items match. - */ + if (searchPtr->type == SEARCH_TYPE_ALL) { + /* + * All items match. + */ - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; + searchPtr->lastPtr = lastPtr; + searchPtr->currentPtr = itemPtr; + return itemPtr; } - if (searchPtr->type == 3) { - - /* - * Optimized single-tag search - */ + if (searchPtr->type == SEARCH_TYPE_TAG) { + /* + * Optimized single-tag search + */ - uid = searchPtr->expr->uid; - for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { - for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; - count > 0; tagPtr++, count--) { - if (*tagPtr == uid) { - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; - } - } - } - searchPtr->lastPtr = lastPtr; - searchPtr->searchOver = 1; - return NULL; + uid = searchPtr->expr->uid; + for (; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { + for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; + count > 0; tagPtr++, count--) { + if (*tagPtr == uid) { + searchPtr->lastPtr = lastPtr; + searchPtr->currentPtr = itemPtr; + return itemPtr; + } + } + } + searchPtr->lastPtr = lastPtr; + searchPtr->searchOver = 1; + return NULL; } /* @@ -3907,12 +3807,12 @@ TagSearchNext(searchPtr) */ for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) { - searchPtr->expr->index = 0; - if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) { - searchPtr->lastPtr = lastPtr; - searchPtr->currentPtr = itemPtr; - return itemPtr; - } + searchPtr->expr->index = 0; + if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) { + searchPtr->lastPtr = lastPtr; + searchPtr->currentPtr = itemPtr; + return itemPtr; + } } searchPtr->lastPtr = lastPtr; searchPtr->searchOver = 1; @@ -3925,29 +3825,27 @@ TagSearchNext(searchPtr) * * DoItem -- * - * This is a utility procedure called by FindItems. It - * either adds itemPtr's id to the result forming in interp, - * or it adds a new tag to itemPtr, depending on the value - * of tag. + * This is a utility function called by FindItems. It either adds + * itemPtr's id to the result forming in interp, or it adds a new tag to + * itemPtr, depending on the value of tag. * * Results: * None. * * Side effects: - * If tag is NULL then itemPtr's id is added as a list element - * to the interp's result; otherwise tag is added to itemPtr's - * list of tags. + * If tag is NULL then itemPtr's id is added as a list element to the + * interp's result; otherwise tag is added to itemPtr's list of tags. * *-------------------------------------------------------------- */ static void -DoItem(interp, itemPtr, tag) - Tcl_Interp *interp; /* Interpreter in which to (possibly) - * record item id. */ - Tk_Item *itemPtr; /* Item to (possibly) modify. */ - Tk_Uid tag; /* Tag to add to those already - * present for item, or NULL. */ +DoItem( + Tcl_Interp *interp, /* Interpreter in which to (possibly) record + * item id. */ + Tk_Item *itemPtr, /* Item to (possibly) modify. */ + Tk_Uid tag) /* Tag to add to those already present for + * item, or NULL. */ { Tk_Uid *tagPtr; int count; @@ -3972,18 +3870,17 @@ DoItem(interp, itemPtr, tag) } /* - * Grow the tag space if there's no more room left in the current - * block. + * Grow the tag space if there's no more room left in the current block. */ if (itemPtr->tagSpace == itemPtr->numTags) { Tk_Uid *newTagPtr; itemPtr->tagSpace += 5; - newTagPtr = (Tk_Uid *) ckalloc((unsigned) - (itemPtr->tagSpace * sizeof(Tk_Uid))); - memcpy((VOID *) newTagPtr, (VOID *) itemPtr->tagPtr, - (itemPtr->numTags * sizeof(Tk_Uid))); + newTagPtr = (Tk_Uid *) + ckalloc((unsigned) (itemPtr->tagSpace * sizeof(Tk_Uid))); + memcpy((void *) newTagPtr, itemPtr->tagPtr, + itemPtr->numTags * sizeof(Tk_Uid)); if (itemPtr->tagPtr != itemPtr->staticTagSpace) { ckfree((char *) itemPtr->tagPtr); } @@ -4004,57 +3901,51 @@ DoItem(interp, itemPtr, tag) * * FindItems -- * - * This procedure does all the work of implementing the - * "find" and "addtag" options of the canvas widget command, - * which locate items that have certain features (location, - * tags, position in display list, etc.). + * This function does all the work of implementing the "find" and + * "addtag" options of the canvas widget command, which locate items that + * have certain features (location, tags, position in display list, etc.) * * Results: - * A standard Tcl return value. If newTag is NULL, then a - * list of ids from all the items that match argc/argv is - * returned in the interp's result. If newTag is NULL, then - * the normal the interp's result is an empty string. If an error - * occurs, then the interp's result will hold an error message. + * A standard Tcl return value. If newTag is NULL, then a list of ids + * from all the items that match objc/objv is returned in the interp's + * result. If newTag is NULL, then the normal the interp's result is an + * empty string. If an error occurs, then the interp's result will hold + * an error message. * * Side effects: - * If newTag is non-NULL, then all the items that match the - * information in argc/argv have that tag added to their - * lists of tags. + * If newTag is non-NULL, then all the items that match the information + * in objc/objv have that tag added to their lists of tags. * *-------------------------------------------------------------- */ static int -#ifdef USE_OLD_TAG_SEARCH -FindItems(interp, canvasPtr, argc, argv, newTag, first) -#else /* USE_OLD_TAG_SEARCH */ -FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) -#endif /* USE_OLD_TAG_SEARCH */ - Tcl_Interp *interp; /* Interpreter for error reporting. */ - TkCanvas *canvasPtr; /* Canvas whose items are to be - * searched. */ - int argc; /* Number of entries in argv. Must be - * greater than zero. */ - Tcl_Obj *CONST *argv; /* Arguments that describe what items - * to search for (see user doc on - * "find" and "addtag" options). */ - Tcl_Obj *newTag; /* If non-NULL, gives new tag to set - * on all found items; if NULL, then - * ids of found items are returned - * in the interp's result. */ - int first; /* For error messages: gives number - * of elements of argv which are already - * handled. */ +FindItems( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */ + int objc, /* Number of entries in argv. Must be greater + * than zero. */ + Tcl_Obj *CONST *objv, /* Arguments that describe what items to + * search for (see user doc on "find" and + * "addtag" options). */ + Tcl_Obj *newTag, /* If non-NULL, gives new tag to set on all + * found items; if NULL, then ids of found + * items are returned in the interp's + * result. */ + int first /* For error messages: gives number of + * elements of objv which are already + * handled. */ #ifndef USE_OLD_TAG_SEARCH - TagSearch **searchPtrPtr; /* From CanvasWidgetCmd local vars*/ + ,TagSearch **searchPtrPtr /* From CanvasWidgetCmd local vars*/ #endif /* not USE_OLD_TAG_SEARCH */ + ) { #ifdef USE_OLD_TAG_SEARCH TagSearch search; #endif /* USE_OLD_TAG_SEARCH */ Tk_Item *itemPtr; Tk_Uid uid; - int index; + int index, result; static CONST char *optionStrings[] = { "above", "all", "below", "closest", "enclosed", "overlapping", "withtag", NULL @@ -4065,41 +3956,34 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) }; if (newTag != NULL) { - uid = Tk_GetUid(Tcl_GetStringFromObj(newTag, NULL)); + uid = Tk_GetUid(Tcl_GetString(newTag)); } else { uid = NULL; } - if (Tcl_GetIndexFromObj(interp, argv[first], optionStrings, "search command", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[first], optionStrings, + "search command", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { - case CANV_ABOVE: { + case CANV_ABOVE: { Tk_Item *lastPtr = NULL; - if (argc != first+2) { - Tcl_WrongNumArgs(interp, first+1, argv, "tagOrId"); + + if (objc != first+2) { + Tcl_WrongNumArgs(interp, first+1, objv, "tagOrId"); return TCL_ERROR; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, argv[first+1], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if (TagSearchScan(canvasPtr, argv[first+1], searchPtrPtr) != TCL_OK) { - return TCL_ERROR; - } - for (itemPtr = TagSearchFirst(*searchPtrPtr); - itemPtr != NULL; itemPtr = TagSearchNext(*searchPtrPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr, + return TCL_ERROR) { lastPtr = itemPtr; } if ((lastPtr != NULL) && (lastPtr->nextPtr != NULL)) { DoItem(interp, lastPtr->nextPtr, uid); } break; - } - case CANV_ALL: { - if (argc != first+1) { - Tcl_WrongNumArgs(interp, first+1, argv, (char *) NULL); + } + case CANV_ALL: + if (objc != first+1) { + Tcl_WrongNumArgs(interp, first+1, objv, NULL); return TCL_ERROR; } @@ -4108,52 +3992,43 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) DoItem(interp, itemPtr, uid); } break; - } - case CANV_BELOW: { - Tk_Item *itemPtr; - if (argc != first+2) { - Tcl_WrongNumArgs(interp, first+1, argv, "tagOrId"); + case CANV_BELOW: + if (objc != first+2) { + Tcl_WrongNumArgs(interp, first+1, objv, "tagOrId"); return TCL_ERROR; } -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, argv[first+1], &search); -#else /* USE_OLD_TAG_SEARCH */ - if (TagSearchScan(canvasPtr, argv[first+1], searchPtrPtr) != TCL_OK) { - return TCL_ERROR; - } - itemPtr = TagSearchFirst(*searchPtrPtr); -#endif /* USE_OLD_TAG_SEARCH */ + FIRST_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr, + return TCL_ERROR); if (itemPtr != NULL) { if (itemPtr->prevPtr != NULL) { DoItem(interp, itemPtr->prevPtr, uid); } } break; - } - case CANV_CLOSEST: { + case CANV_CLOSEST: { double closestDist; Tk_Item *startPtr, *closestPtr; double coords[2], halo; int x1, y1, x2, y2; - if ((argc < first+3) || (argc > first+5)) { - Tcl_WrongNumArgs(interp, first+1, argv, "x y ?halo? ?start?"); + if ((objc < first+3) || (objc > first+5)) { + Tcl_WrongNumArgs(interp, first+1, objv, "x y ?halo? ?start?"); return TCL_ERROR; } - if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[first+1], + if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[first+1], &coords[0]) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, - (Tk_Canvas) canvasPtr, argv[first+2], &coords[1]) != TCL_OK)) { + (Tk_Canvas) canvasPtr, objv[first+2], &coords[1]) != TCL_OK)) { return TCL_ERROR; } - if (argc > first+3) { - if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[first+3], + if (objc > first+3) { + if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[first+3], &halo) != TCL_OK) { return TCL_ERROR; } if (halo < 0.0) { Tcl_AppendResult(interp, "can't have negative halo value \"", - Tcl_GetString(argv[3]), "\"", (char *) NULL); + Tcl_GetString(objv[3]), "\"", NULL); return TCL_ERROR; } } else { @@ -4165,31 +4040,26 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) */ startPtr = canvasPtr->firstItemPtr; - if (argc == first+5) { -#ifdef USE_OLD_TAG_SEARCH - itemPtr = StartTagSearch(canvasPtr, argv[first+4], &search); -#else /* USE_OLD_TAG_SEARCH */ - if (TagSearchScan(canvasPtr, argv[first+4], searchPtrPtr) != TCL_OK) { - return TCL_ERROR; - } - itemPtr = TagSearchFirst(*searchPtrPtr); -#endif /* USE_OLD_TAG_SEARCH */ + if (objc == first+5) { + FIRST_CANVAS_ITEM_MATCHING(objv[first+4], searchPtrPtr, + return TCL_ERROR); if (itemPtr != NULL) { startPtr = itemPtr; } } /* - * The code below is optimized so that it can eliminate most - * items without having to call their item-specific procedures. - * This is done by keeping a bounding box (x1, y1, x2, y2) that - * an item's bbox must overlap if the item is to have any - * chance of being closer than the closest so far. + * The code below is optimized so that it can eliminate most items + * without having to call their item-specific functions. This is done + * by keeping a bounding box (x1, y1, x2, y2) that an item's bbox must + * overlap if the item is to have any chance of being closer than the + * closest so far. */ itemPtr = startPtr; while(itemPtr && (itemPtr->state == TK_STATE_HIDDEN || - (itemPtr->state == TK_STATE_NULL && canvasPtr->canvas_state == TK_STATE_HIDDEN))) { + (itemPtr->state == TK_STATE_NULL && + canvasPtr->canvas_state == TK_STATE_HIDDEN))) { itemPtr = itemPtr->nextPtr; } if (itemPtr == NULL) { @@ -4204,8 +4074,8 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) double newDist; /* - * Update the bounding box using itemPtr, which is the - * new closest item. + * Update the bounding box using itemPtr, which is the new closest + * item. */ x1 = (int) (coords[0] - closestDist - halo - 1); @@ -4215,9 +4085,9 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) closestPtr = itemPtr; /* - * Search for an item that beats the current closest one. - * Work circularly through the canvas's item list until - * getting back to the starting item. + * Search for an item that beats the current closest one. Work + * circularly through the canvas's item list until getting back to + * the starting item. */ while (1) { @@ -4229,7 +4099,8 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) DoItem(interp, closestPtr, uid); return TCL_OK; } - if (itemPtr->state == TK_STATE_HIDDEN || (itemPtr->state == TK_STATE_NULL && + if (itemPtr->state == TK_STATE_HIDDEN || + (itemPtr->state == TK_STATE_NULL && canvasPtr->canvas_state == TK_STATE_HIDDEN)) { continue; } @@ -4249,39 +4120,28 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) } } break; - } - case CANV_ENCLOSED: { - if (argc != first+5) { - Tcl_WrongNumArgs(interp, first+1, argv, "x1 y1 x2 y2"); + } + case CANV_ENCLOSED: + if (objc != first+5) { + Tcl_WrongNumArgs(interp, first+1, objv, "x1 y1 x2 y2"); return TCL_ERROR; } - return FindArea(interp, canvasPtr, argv+first+1, uid, 1); - } - case CANV_OVERLAPPING: { - if (argc != first+5) { - Tcl_WrongNumArgs(interp, first+1, argv, "x1 y1 x2 y2"); + return FindArea(interp, canvasPtr, objv+first+1, uid, 1); + case CANV_OVERLAPPING: + if (objc != first+5) { + Tcl_WrongNumArgs(interp, first+1, objv, "x1 y1 x2 y2"); return TCL_ERROR; } - return FindArea(interp, canvasPtr, argv+first+1, uid, 0); - } - case CANV_WITHTAG: { - if (argc != first+2) { - Tcl_WrongNumArgs(interp, first+1, argv, "tagOrId"); + return FindArea(interp, canvasPtr, objv+first+1, uid, 0); + case CANV_WITHTAG: + if (objc != first+2) { + Tcl_WrongNumArgs(interp, first+1, objv, "tagOrId"); return TCL_ERROR; } -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, argv[first+1], &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if (TagSearchScan(canvasPtr, argv[first+1], searchPtrPtr) != TCL_OK) { - return TCL_ERROR; - } - for (itemPtr = TagSearchFirst(*searchPtrPtr); - itemPtr != NULL; itemPtr = TagSearchNext(*searchPtrPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(objv[first+1], searchPtrPtr, + return TCL_ERROR) { DoItem(interp, itemPtr, uid); } - } } return TCL_OK; } @@ -4291,53 +4151,49 @@ FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr) * * FindArea -- * - * This procedure implements area searches for the "find" - * and "addtag" options. + * This function implements area searches for the "find" and "addtag" + * options. * * Results: - * A standard Tcl return value. If newTag is NULL, then a - * list of ids from all the items overlapping or enclosed - * by the rectangle given by argc is returned in the interp's result. - * If newTag is NULL, then the normal the interp's result is an - * empty string. If an error occurs, then the interp's result will - * hold an error message. + * A standard Tcl return value. If newTag is NULL, then a list of ids + * from all the items overlapping or enclosed by the rectangle given by + * objc is returned in the interp's result. If newTag is NULL, then the + * normal the interp's result is an empty string. If an error occurs, + * then the interp's result will hold an error message. * * Side effects: - * If uid is non-NULL, then all the items overlapping - * or enclosed by the area in argv have that tag added to - * their lists of tags. + * If uid is non-NULL, then all the items overlapping or enclosed by the + * area in objv have that tag added to their lists of tags. * *-------------------------------------------------------------- */ static int -FindArea(interp, canvasPtr, argv, uid, enclosed) - Tcl_Interp *interp; /* Interpreter for error reporting - * and result storing. */ - TkCanvas *canvasPtr; /* Canvas whose items are to be - * searched. */ - Tcl_Obj *CONST *argv; /* Array of four arguments that - * give the coordinates of the - * rectangular area to search. */ - Tk_Uid uid; /* If non-NULL, gives new tag to set - * on all found items; if NULL, then - * ids of found items are returned - * in the interp's result. */ - int enclosed; /* 0 means overlapping or enclosed - * items are OK, 1 means only enclosed - * items are OK. */ +FindArea( + Tcl_Interp *interp, /* Interpreter for error reporting and result + * storing. */ + TkCanvas *canvasPtr, /* Canvas whose items are to be searched. */ + Tcl_Obj *CONST *objv, /* Array of four arguments that give the + * coordinates of the rectangular area to + * search. */ + Tk_Uid uid, /* If non-NULL, gives new tag to set on all + * found items; if NULL, then ids of found + * items are returned in the interp's + * result. */ + int enclosed) /* 0 means overlapping or enclosed items are + * OK, 1 means only enclosed items are OK. */ { double rect[4], tmp; int x1, y1, x2, y2; Tk_Item *itemPtr; - if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[0], + if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[0], &rect[0]) != TCL_OK) - || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[1], + || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[1], &rect[1]) != TCL_OK) - || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[2], + || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[2], &rect[2]) != TCL_OK) - || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[3], + || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[3], &rect[3]) != TCL_OK)) { return TCL_ERROR; } @@ -4349,8 +4205,8 @@ FindArea(interp, canvasPtr, argv, uid, enclosed) } /* - * Use an integer bounding box for a quick test, to avoid - * calling item-specific code except for items that are close. + * Use an integer bounding box for a quick test, to avoid calling + * item-specific code except for items that are close. */ x1 = (int) (rect[0]-1.0); @@ -4380,65 +4236,60 @@ FindArea(interp, canvasPtr, argv, uid, enclosed) * * RelinkItems -- * - * Move one or more items to a different place in the - * display order for a canvas. + * Move one or more items to a different place in the display order for a + * canvas. * * Results: * None. * * Side effects: - * The items identified by "tag" are moved so that they - * are all together in the display list and immediately - * after prevPtr. The order of the moved items relative - * to each other is not changed. + * The items identified by "tag" are moved so that they are all together + * in the display list and immediately after prevPtr. The order of the + * moved items relative to each other is not changed. * *-------------------------------------------------------------- */ #ifdef USE_OLD_TAG_SEARCH static void -RelinkItems(canvasPtr, tag, prevPtr) +RelinkItems( + TkCanvas *canvasPtr, /* Canvas to be modified. */ + Tcl_Obj *tag, /* Tag identifying items to be moved in the + * redisplay list. */ + Tk_Item *prevPtr) /* Reposition the items so that they go just + * after this item (NULL means put at + * beginning of list). */ #else /* USE_OLD_TAG_SEARCH */ static int -RelinkItems(canvasPtr, tag, prevPtr, searchPtrPtr) +RelinkItems( + TkCanvas *canvasPtr, /* Canvas to be modified. */ + Tcl_Obj *tag, /* Tag identifying items to be moved in the + * redisplay list. */ + Tk_Item *prevPtr, /* Reposition the items so that they go just + * after this item (NULL means put at + * beginning of list). */ + TagSearch **searchPtrPtr) /* From CanvasWidgetCmd local vars */ #endif /* USE_OLD_TAG_SEARCH */ - TkCanvas *canvasPtr; /* Canvas to be modified. */ - Tcl_Obj *tag; /* Tag identifying items to be moved - * in the redisplay list. */ - Tk_Item *prevPtr; /* Reposition the items so that they - * go just after this item (NULL means - * put at beginning of list). */ -#ifndef USE_OLD_TAG_SEARCH - TagSearch **searchPtrPtr; /* From CanvasWidgetCmd local vars */ -#endif /* not USE_OLD_TAG_SEARCH */ { Tk_Item *itemPtr; #ifdef USE_OLD_TAG_SEARCH TagSearch search; #endif /* USE_OLD_TAG_SEARCH */ Tk_Item *firstMovePtr, *lastMovePtr; + int result; /* - * Find all of the items to be moved and remove them from - * the list, making an auxiliary list running from firstMovePtr - * to lastMovePtr. Record their areas for redisplay. + * Find all of the items to be moved and remove them from the list, making + * an auxiliary list running from firstMovePtr to lastMovePtr. Record + * their areas for redisplay. */ firstMovePtr = lastMovePtr = NULL; -#ifdef USE_OLD_TAG_SEARCH - for (itemPtr = StartTagSearch(canvasPtr, tag, &search); - itemPtr != NULL; itemPtr = NextItem(&search)) { -#else /* USE_OLD_TAG_SEARCH */ - if (TagSearchScan(canvasPtr, tag, searchPtrPtr) != TCL_OK) { - return TCL_ERROR; - } - for (itemPtr = TagSearchFirst(*searchPtrPtr); - itemPtr != NULL; itemPtr = TagSearchNext(*searchPtrPtr)) { -#endif /* USE_OLD_TAG_SEARCH */ + FOR_EVERY_CANVAS_ITEM_MATCHING(tag, searchPtrPtr, return TCL_ERROR) { if (itemPtr == prevPtr) { /* - * Item after which insertion is to occur is being - * moved! Switch to insert after its predecessor. + * Item after which insertion is to occur is being moved! Switch + * to insert after its predecessor. */ prevPtr = prevPtr->prevPtr; @@ -4470,15 +4321,15 @@ RelinkItems(canvasPtr, tag, prevPtr, searchPtrPtr) } /* - * Insert the list of to-be-moved items back into the canvas's - * at the desired position. + * Insert the list of to-be-moved items back into the canvas's at the + * desired position. */ if (firstMovePtr == NULL) { #ifdef USE_OLD_TAG_SEARCH return; #else /* USE_OLD_TAG_SEARCH */ - return TCL_OK; + return TCL_OK; #endif /* USE_OLD_TAG_SEARCH */ } if (prevPtr == NULL) { @@ -4510,24 +4361,23 @@ RelinkItems(canvasPtr, tag, prevPtr, searchPtrPtr) * * CanvasBindProc -- * - * This procedure is invoked by the Tk dispatcher to handle - * events associated with bindings on items. + * This function is invoked by the Tk dispatcher to handle events + * associated with bindings on items. * * Results: * None. * * Side effects: - * Depends on the command invoked as part of the binding - * (if there was any). + * Depends on the command invoked as part of the binding (if there was + * any). * *-------------------------------------------------------------- */ static void -CanvasBindProc(clientData, eventPtr) - ClientData clientData; /* Pointer to canvas structure. */ - XEvent *eventPtr; /* Pointer to X event that just - * happened. */ +CanvasBindProc( + ClientData clientData, /* Pointer to canvas structure. */ + XEvent *eventPtr) /* Pointer to X event that just happened. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; @@ -4535,47 +4385,46 @@ CanvasBindProc(clientData, eventPtr) /* * This code below keeps track of the current modifier state in - * canvasPtr>state. This information is used to defer repicks of - * the current item while buttons are down. + * canvasPtr>state. This information is used to defer repicks of the + * current item while buttons are down. */ if ((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease)) { int mask; switch (eventPtr->xbutton.button) { - case Button1: - mask = Button1Mask; - break; - case Button2: - mask = Button2Mask; - break; - case Button3: - mask = Button3Mask; - break; - case Button4: - mask = Button4Mask; - break; - case Button5: - mask = Button5Mask; - break; - default: - mask = 0; - break; + case Button1: + mask = Button1Mask; + break; + case Button2: + mask = Button2Mask; + break; + case Button3: + mask = Button3Mask; + break; + case Button4: + mask = Button4Mask; + break; + case Button5: + mask = Button5Mask; + break; + default: + mask = 0; + break; } /* - * For button press events, repick the current item using the - * button state before the event, then process the event. For - * button release events, first process the event, then repick - * the current item using the button state *after* the event - * (the button has logically gone up before we change the - * current item). + * For button press events, repick the current item using the button + * state before the event, then process the event. For button release + * events, first process the event, then repick the current item using + * the button state *after* the event (the button has logically gone + * up before we change the current item). */ if (eventPtr->type == ButtonPress) { /* - * On a button press, first repick the current item using - * the button state before the event, the process the event. + * On a button press, first repick the current item using the + * button state before the event, the process the event. */ canvasPtr->state = eventPtr->xbutton.state; @@ -4584,9 +4433,9 @@ CanvasBindProc(clientData, eventPtr) CanvasDoEvent(canvasPtr, eventPtr); } else { /* - * Button release: first process the event, with the button - * still considered to be down. Then repick the current - * item under the assumption that the button is no longer down. + * Button release: first process the event, with the button still + * considered to be down. Then repick the current item under the + * assumption that the button is no longer down. */ canvasPtr->state = eventPtr->xbutton.state; @@ -4608,7 +4457,7 @@ CanvasBindProc(clientData, eventPtr) } CanvasDoEvent(canvasPtr, eventPtr); - done: + done: Tcl_Release((ClientData) canvasPtr); } @@ -4617,34 +4466,31 @@ CanvasBindProc(clientData, eventPtr) * * PickCurrentItem -- * - * Find the topmost item in a canvas that contains a given - * location and mark the the current item. If the current - * item has changed, generate a fake exit event on the old - * current item, a fake enter event on the new current item - * item and force a redraw of the two items. Canvas items - * that are hidden or disabled are ignored. + * Find the topmost item in a canvas that contains a given location and + * mark the the current item. If the current item has changed, generate a + * fake exit event on the old current item, a fake enter event on the new + * current item item and force a redraw of the two items. Canvas items + * that are hidden or disabled are ignored. * * Results: * None. * * Side effects: - * The current item for canvasPtr may change. If it does, - * then the commands associated with item entry and exit - * could do just about anything. A binding script could - * delete the canvas, so callers should protect themselves - * with Tcl_Preserve and Tcl_Release. + * The current item for canvasPtr may change. If it does, then the + * commands associated with item entry and exit could do just about + * anything. A binding script could delete the canvas, so callers should + * protect themselves with Tcl_Preserve and Tcl_Release. * *-------------------------------------------------------------- */ static void -PickCurrentItem(canvasPtr, eventPtr) - TkCanvas *canvasPtr; /* Canvas widget in which to select - * current item. */ - XEvent *eventPtr; /* Event describing location of - * mouse cursor. Must be EnterWindow, - * LeaveWindow, ButtonRelease, or - * MotionNotify. */ +PickCurrentItem( + TkCanvas *canvasPtr, /* Canvas widget in which to select current + * item. */ + XEvent *eventPtr) /* Event describing location of mouse cursor. + * Must be EnterWindow, LeaveWindow, + * ButtonRelease, or MotionNotify. */ { double coords[2]; int buttonDown; @@ -4654,23 +4500,24 @@ PickCurrentItem(canvasPtr, eventPtr) #endif /* - * Check whether or not a button is down. If so, we'll log entry - * and exit into and out of the current item, but not entry into - * any other item. This implements a form of grabbing equivalent - * to what the X server does for windows. + * Check whether or not a button is down. If so, we'll log entry and exit + * into and out of the current item, but not entry into any other item. + * This implements a form of grabbing equivalent to what the X server does + * for windows. */ buttonDown = canvasPtr->state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask); /* - * Save information about this event in the canvas. The event in - * the canvas is used for two purposes: + * Save information about this event in the canvas. The event in the + * canvas is used for two purposes: * * 1. Event bindings: if the current item changes, fake events are * generated to allow item-enter and item-leave bindings to trigger. - * 2. Reselection: if the current item gets deleted, can use the - * saved event to find a new current item. + * 2. Reselection: if the current item gets deleted, can use the saved + * event to find a new current item. + * * Translate MotionNotify events into EnterNotify events, since that's * what gets reported to item handlers. */ @@ -4703,10 +4550,10 @@ PickCurrentItem(canvasPtr, eventPtr) } /* - * If this is a recursive call (there's already a partially completed - * call pending on the stack; it's in the middle of processing a - * Leave event handler for the old current item) then just return; - * the pending call will do everything that's needed. + * If this is a recursive call (there's already a partially completed call + * pending on the stack; it's in the middle of processing a Leave event + * handler for the old current item) then just return; the pending call + * will do everything that's needed. */ if (canvasPtr->flags & REPICK_IN_PROGRESS) { @@ -4714,8 +4561,8 @@ PickCurrentItem(canvasPtr, eventPtr) } /* - * A LeaveNotify event automatically means that there's no current - * object, so the check for closest item can be skipped. + * A LeaveNotify event automatically means that there's no current object, + * so the check for closest item can be skipped. */ coords[0] = canvasPtr->pickEvent.xcrossing.x + canvasPtr->xOrigin; @@ -4738,12 +4585,11 @@ PickCurrentItem(canvasPtr, eventPtr) if (!buttonDown) { canvasPtr->flags &= ~LEFT_GRABBED_ITEM; } - + /* - * Simulate a LeaveNotify event on the previous current item and - * an EnterNotify event on the new current item. Remove the "current" - * tag from the previous current item and place it on the new current - * item. + * Simulate a LeaveNotify event on the previous current item and an + * EnterNotify event on the new current item. Remove the "current" tag + * from the previous current item and place it on the new current item. */ if ((canvasPtr->newCurrentPtr != canvasPtr->currentItemPtr) @@ -4757,9 +4603,9 @@ PickCurrentItem(canvasPtr, eventPtr) event.type = LeaveNotify; /* - * If the event's detail happens to be NotifyInferior the - * binding mechanism will discard the event. To be consistent, - * always use NotifyAncestor. + * If the event's detail happens to be NotifyInferior the binding + * mechanism will discard the event. To be consistent, always use + * NotifyAncestor. */ event.xcrossing.detail = NotifyAncestor; @@ -4768,28 +4614,29 @@ PickCurrentItem(canvasPtr, eventPtr) canvasPtr->flags &= ~REPICK_IN_PROGRESS; /* - * The check below is needed because there could be an event - * handler for <LeaveNotify> that deletes the current item. + * The check below is needed because there could be an event handler + * for <LeaveNotify> that deletes the current item. */ if ((itemPtr == canvasPtr->currentItemPtr) && !buttonDown) { for (i = itemPtr->numTags-1; i >= 0; i--) { #ifdef USE_OLD_TAG_SEARCH - if (itemPtr->tagPtr[i] == Tk_GetUid("current")) { + if (itemPtr->tagPtr[i] == Tk_GetUid("current")) #else /* USE_OLD_TAG_SEARCH */ - if (itemPtr->tagPtr[i] == searchUids->currentUid) { + if (itemPtr->tagPtr[i] == searchUids->currentUid) #endif /* USE_OLD_TAG_SEARCH */ + /* then */ { itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1]; itemPtr->numTags--; break; } } } - + /* - * Note: during CanvasDoEvent above, it's possible that - * canvasPtr->newCurrentPtr got reset to NULL because the - * item was deleted. + * Note: during CanvasDoEvent above, it's possible that + * canvasPtr->newCurrentPtr got reset to NULL because the item was + * deleted. */ } if ((canvasPtr->newCurrentPtr != canvasPtr->currentItemPtr) && buttonDown) { @@ -4798,9 +4645,9 @@ PickCurrentItem(canvasPtr, eventPtr) } /* - * Special note: it's possible that canvasPtr->newCurrentPtr == - * canvasPtr->currentItemPtr here. This can happen, for example, - * if LEFT_GRABBED_ITEM was set. + * Special note: it's possible that canvasPtr->newCurrentPtr == + * canvasPtr->currentItemPtr here. This can happen, for example, if + * LEFT_GRABBED_ITEM was set. */ prevItemPtr = canvasPtr->currentItemPtr; @@ -4810,23 +4657,21 @@ PickCurrentItem(canvasPtr, eventPtr) (prevItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT)) { EventuallyRedrawItem((Tk_Canvas) canvasPtr, prevItemPtr); (*prevItemPtr->typePtr->configProc)(canvasPtr->interp, - (Tk_Canvas) canvasPtr, prevItemPtr, 0, (Tcl_Obj **) NULL, + (Tk_Canvas) canvasPtr, prevItemPtr, 0, NULL, TK_CONFIG_ARGV_ONLY); } if (canvasPtr->currentItemPtr != NULL) { XEvent event; #ifdef USE_OLD_TAG_SEARCH - DoItem((Tcl_Interp *) NULL, canvasPtr->currentItemPtr, - Tk_GetUid("current")); + DoItem(NULL, canvasPtr->currentItemPtr, Tk_GetUid("current")); #else /* USE_OLD_TAG_SEARCH */ - DoItem((Tcl_Interp *) NULL, canvasPtr->currentItemPtr, - searchUids->currentUid); + DoItem(NULL, canvasPtr->currentItemPtr, searchUids->currentUid); #endif /* USE_OLD_TAG_SEA */ if ((canvasPtr->currentItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT && prevItemPtr != canvasPtr->currentItemPtr)) { (*canvasPtr->currentItemPtr->typePtr->configProc)(canvasPtr->interp, - (Tk_Canvas) canvasPtr, canvasPtr->currentItemPtr, 0, (Tcl_Obj **) NULL, + (Tk_Canvas) canvasPtr, canvasPtr->currentItemPtr, 0, NULL, TK_CONFIG_ARGV_ONLY); EventuallyRedrawItem((Tk_Canvas) canvasPtr, canvasPtr->currentItemPtr); @@ -4843,13 +4688,13 @@ PickCurrentItem(canvasPtr, eventPtr) * * CanvasFindClosest -- * - * Given x and y coordinates, find the topmost canvas item that - * is "close" to the coordinates. Canvas items that are hidden - * or disabled are ignored. + * Given x and y coordinates, find the topmost canvas item that is + * "close" to the coordinates. Canvas items that are hidden or disabled + * are ignored. * * Results: - * The return value is a pointer to the topmost item that is - * close to (x,y), or NULL if no item is close. + * The return value is a pointer to the topmost item that is close to + * (x,y), or NULL if no item is close. * * Side effects: * None. @@ -4858,10 +4703,10 @@ PickCurrentItem(canvasPtr, eventPtr) */ static Tk_Item * -CanvasFindClosest(canvasPtr, coords) - TkCanvas *canvasPtr; /* Canvas widget to search. */ - double coords[2]; /* Desired x,y position in canvas, - * not screen, coordinates.) */ +CanvasFindClosest( + TkCanvas *canvasPtr, /* Canvas widget to search. */ + double coords[2]) /* Desired x,y position in canvas, not screen, + * coordinates.) */ { Tk_Item *itemPtr; Tk_Item *bestPtr; @@ -4897,27 +4742,25 @@ CanvasFindClosest(canvasPtr, coords) * * CanvasDoEvent -- * - * This procedure is called to invoke binding processing - * for a new event that is associated with the current item - * for a canvas. + * This function is called to invoke binding processing for a new event + * that is associated with the current item for a canvas. * * Results: * None. * * Side effects: - * Depends on the bindings for the canvas. A binding script - * could delete the canvas, so callers should protect themselves - * with Tcl_Preserve and Tcl_Release. + * Depends on the bindings for the canvas. A binding script could delete + * the canvas, so callers should protect themselves with Tcl_Preserve and + * Tcl_Release. * *-------------------------------------------------------------- */ static void -CanvasDoEvent(canvasPtr, eventPtr) - TkCanvas *canvasPtr; /* Canvas widget in which event - * occurred. */ - XEvent *eventPtr; /* Real or simulated X event that - * is to be processed. */ +CanvasDoEvent( + TkCanvas *canvasPtr, /* Canvas widget in which event occurred. */ + XEvent *eventPtr) /* Real or simulated X event that is to be + * processed. */ { #define NUM_STATIC 3 ClientData staticObjects[NUM_STATIC]; @@ -4944,30 +4787,30 @@ CanvasDoEvent(canvasPtr, eventPtr) #ifdef USE_OLD_TAG_SEARCH /* - * Set up an array with all the relevant objects for processing - * this event. The relevant objects are (a) the event's item, - * (b) the tags associated with the event's item, and (c) the - * tag "all". If there are a lot of tags then malloc an array - * to hold all of the objects. + * Set up an array with all the relevant objects for processing this + * event. The relevant objects are (a) the event's item, (b) the tags + * associated with the event's item, and (c) the tag "all". If there are a + * lot of tags then malloc an array to hold all of the objects. */ numObjects = itemPtr->numTags + 2; #else /* USE_OLD_TAG_SEARCH */ /* - * Set up an array with all the relevant objects for processing - * this event. The relevant objects are: + * Set up an array with all the relevant objects for processing this + * event. The relevant objects are: * (a) the event's item, - * (b) the tags associated with the event's item, + * (b) the tags associated with the event's item, * (c) the expressions that are true for the event's item's tags, and - * (d) the tag "all". + * (d) the tag "all". * - * If there are a lot of tags then malloc an array to hold all of - * the objects. + * If there are a lot of tags then malloc an array to hold all of the + * objects. */ /* - * flag and count all expressions that match item's tags + * Flag and count all expressions that match item's tags. */ + numExprs = 0; expr = canvasPtr->bindTagExprs; while (expr) { @@ -4984,8 +4827,8 @@ CanvasDoEvent(canvasPtr, eventPtr) if (numObjects <= NUM_STATIC) { objectPtr = staticObjects; } else { - objectPtr = (ClientData *) - ckalloc((unsigned) (numObjects * sizeof(ClientData))); + objectPtr = (ClientData *) ckalloc((unsigned) + (numObjects * sizeof(ClientData))); } #ifdef USE_OLD_TAG_SEARCH objectPtr[0] = (ClientData) Tk_GetUid("all"); @@ -4996,10 +4839,12 @@ CanvasDoEvent(canvasPtr, eventPtr) objectPtr[i+1] = (ClientData) itemPtr->tagPtr[i]; } objectPtr[itemPtr->numTags+1] = (ClientData) itemPtr; + #ifndef USE_OLD_TAG_SEARCH /* - * copy uids of matching expressions into object array + * Copy uids of matching expressions into object array */ + i = itemPtr->numTags+2; expr = canvasPtr->bindTagExprs; while (expr) { @@ -5011,8 +4856,8 @@ CanvasDoEvent(canvasPtr, eventPtr) #endif /* not USE_OLD_TAG_SEARCH */ /* - * Invoke the binding system, then free up the object array if - * it was malloc-ed. + * Invoke the binding system, then free up the object array if it was + * malloc-ed. */ if (canvasPtr->tkwin != NULL) { @@ -5029,22 +4874,22 @@ CanvasDoEvent(canvasPtr, eventPtr) * * CanvasBlinkProc -- * - * This procedure is called as a timer handler to blink the - * insertion cursor off and on. + * This function is called as a timer handler to blink the insertion + * cursor off and on. * * Results: * None. * * Side effects: - * The cursor gets turned on or off, redisplay gets invoked, - * and this procedure reschedules itself. + * The cursor gets turned on or off, redisplay gets invoked, and this + * function reschedules itself. * *---------------------------------------------------------------------- */ static void -CanvasBlinkProc(clientData) - ClientData clientData; /* Pointer to record describing entry. */ +CanvasBlinkProc( + ClientData clientData) /* Pointer to record describing entry. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; @@ -5073,9 +4918,9 @@ CanvasBlinkProc(clientData) * * CanvasFocusProc -- * - * This procedure is called whenever a canvas gets or loses the - * input focus. It's also called whenever the window is - * reconfigured while it has the focus. + * This function is called whenever a canvas gets or loses the input + * focus. It's also called whenever the window is reconfigured while it + * has the focus. * * Results: * None. @@ -5087,9 +4932,9 @@ CanvasBlinkProc(clientData) */ static void -CanvasFocusProc(canvasPtr, gotFocus) - TkCanvas *canvasPtr; /* Canvas that just got or lost focus. */ - int gotFocus; /* 1 means window is getting focus, 0 means +CanvasFocusProc( + TkCanvas *canvasPtr, /* Canvas that just got or lost focus. */ + int gotFocus) /* 1 means window is getting focus, 0 means * it's losing it. */ { Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler); @@ -5124,8 +4969,8 @@ CanvasFocusProc(canvasPtr, gotFocus) * * CanvasSelectTo -- * - * Modify the selection by moving its un-anchored end. This could - * make the selection either larger or smaller. + * Modify the selection by moving its un-anchored end. This could make + * the selection either larger or smaller. * * Results: * None. @@ -5137,10 +4982,10 @@ CanvasFocusProc(canvasPtr, gotFocus) */ static void -CanvasSelectTo(canvasPtr, itemPtr, index) - TkCanvas *canvasPtr; /* Information about widget. */ - Tk_Item *itemPtr; /* Item that is to hold selection. */ - int index; /* Index of element that is to become the +CanvasSelectTo( + TkCanvas *canvasPtr, /* Information about widget. */ + Tk_Item *itemPtr, /* Item that is to hold selection. */ + int index) /* Index of element that is to become the * "other" end of the selection. */ { int oldFirst, oldLast; @@ -5186,15 +5031,15 @@ CanvasSelectTo(canvasPtr, itemPtr, index) * * CanvasFetchSelection -- * - * This procedure is invoked by Tk to return part or all of - * the selection, when the selection is in a canvas widget. - * This procedure always returns the selection as a STRING. + * This function is invoked by Tk to return part or all of the selection, + * when the selection is in a canvas widget. This function always returns + * the selection as a STRING. * * Results: - * The return value is the number of non-NULL bytes stored - * at buffer. Buffer is filled (or partially filled) with a - * NULL-terminated string containing part or all of the selection, - * as given by offset and maxBytes. + * The return value is the number of non-NULL bytes stored at buffer. + * Buffer is filled (or partially filled) with a NULL-terminated string + * containing part or all of the selection, as given by offset and + * maxBytes. * * Side effects: * None. @@ -5203,15 +5048,14 @@ CanvasSelectTo(canvasPtr, itemPtr, index) */ static int -CanvasFetchSelection(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Information about canvas widget. */ - int offset; /* Offset within selection of first - * character to be returned. */ - char *buffer; /* Location in which to place - * selection. */ - int maxBytes; /* Maximum number of bytes to place - * at buffer, not including terminating - * NULL character. */ +CanvasFetchSelection( + ClientData clientData, /* Information about canvas widget. */ + int offset, /* Offset within selection of first character + * to be returned. */ + char *buffer, /* Location in which to place selection. */ + int maxBytes) /* Maximum number of bytes to place at buffer, + * not including terminating NULL + * character. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; @@ -5231,22 +5075,22 @@ CanvasFetchSelection(clientData, offset, buffer, maxBytes) * * CanvasLostSelection -- * - * This procedure is called back by Tk when the selection is - * grabbed away from a canvas widget. + * This function is called back by Tk when the selection is grabbed away + * from a canvas widget. * * Results: * None. * * Side effects: - * The existing selection is unhighlighted, and the window is - * marked as not containing a selection. + * The existing selection is unhighlighted, and the window is marked as + * not containing a selection. * *---------------------------------------------------------------------- */ static void -CanvasLostSelection(clientData) - ClientData clientData; /* Information about entry widget. */ +CanvasLostSelection( + ClientData clientData) /* Information about entry widget. */ { TkCanvas *canvasPtr = (TkCanvas *) clientData; @@ -5262,13 +5106,11 @@ CanvasLostSelection(clientData) * * GridAlign -- * - * Given a coordinate and a grid spacing, this procedure - * computes the location of the nearest grid line to the - * coordinate. + * Given a coordinate and a grid spacing, this function computes the + * location of the nearest grid line to the coordinate. * * Results: - * The return value is the location of the grid line nearest - * to coord. + * The return value is the location of the grid line nearest to coord. * * Side effects: * None. @@ -5277,10 +5119,10 @@ CanvasLostSelection(clientData) */ static double -GridAlign(coord, spacing) - double coord; /* Coordinate to grid-align. */ - double spacing; /* Spacing between grid lines. If <= 0 - * then no alignment is done. */ +GridAlign( + double coord, /* Coordinate to grid-align. */ + double spacing) /* Spacing between grid lines. If <= 0 then no + * alignment is done. */ { if (spacing <= 0.0) { return coord; @@ -5296,15 +5138,14 @@ GridAlign(coord, spacing) * * ScrollFractions -- * - * Given the range that's visible in the window and the "100% - * range" for what's in the canvas, return a list of two - * doubles representing the scroll fractions. This procedure - * is used for both x and y scrolling. + * Given the range that's visible in the window and the "100% range" for + * what's in the canvas, return a list of two doubles representing the + * scroll fractions. This function is used for both x and y scrolling. * * Results: - * The memory pointed to by string is modified to hold - * two real numbers containing the scroll fractions (between - * 0 and 1) corresponding to the other arguments. + * A List Tcl_Obj with two real numbers (Double Tcl_Objs) containing the + * scroll fractions (between 0 and 1) corresponding to the other + * arguments. * * Side effects: * None. @@ -5313,14 +5154,14 @@ GridAlign(coord, spacing) */ static Tcl_Obj * -ScrollFractions(screen1, screen2, object1, object2) - int screen1; /* Lowest coordinate visible in the window. */ - int screen2; /* Highest coordinate visible in the window. */ - int object1; /* Lowest coordinate in the object. */ - int object2; /* Highest coordinate in the object. */ +ScrollFractions( + int screen1, /* Lowest coordinate visible in the window. */ + int screen2, /* Highest coordinate visible in the window. */ + int object1, /* Lowest coordinate in the object. */ + int object2) /* Highest coordinate in the object. */ { + Tcl_Obj *buffer[2]; double range, f1, f2; - char buffer[2*TCL_DOUBLE_SPACE+2]; range = object2 - object1; if (range <= 0) { @@ -5339,8 +5180,9 @@ ScrollFractions(screen1, screen2, object1, object2) f2 = f1; } } - sprintf(buffer, "%g %g", f1, f2); - return Tcl_NewStringObj(buffer, -1); + buffer[0] = Tcl_NewDoubleObj(f1); + buffer[1] = Tcl_NewDoubleObj(f2); + return Tcl_NewListObj(2, buffer); } /* @@ -5348,46 +5190,45 @@ ScrollFractions(screen1, screen2, object1, object2) * * CanvasUpdateScrollbars -- * - * This procedure is invoked whenever a canvas has changed in - * a way that requires scrollbars to be redisplayed (e.g. the - * view in the canvas has changed). + * This function is invoked whenever a canvas has changed in a way that + * requires scrollbars to be redisplayed (e.g. the view in the canvas has + * changed). * * Results: * None. * * Side effects: - * If there are scrollbars associated with the canvas, then - * their scrolling commands are invoked to cause them to - * redisplay. If errors occur, additional Tcl commands may - * be invoked to process the errors. + * If there are scrollbars associated with the canvas, then their + * scrolling commands are invoked to cause them to redisplay. If errors + * occur, additional Tcl commands may be invoked to process the errors. * *-------------------------------------------------------------- */ static void -CanvasUpdateScrollbars(canvasPtr) - TkCanvas *canvasPtr; /* Information about canvas. */ +CanvasUpdateScrollbars( + TkCanvas *canvasPtr) /* Information about canvas. */ { int result; Tcl_Interp *interp; - int xOrigin, yOrigin, inset, width, height, scrollX1, scrollX2, - scrollY1, scrollY2; + int xOrigin, yOrigin, inset, width, height; + int scrollX1, scrollX2, scrollY1, scrollY2; char *xScrollCmd, *yScrollCmd; /* * Save all the relevant values from the canvasPtr, because it might be * deleted as part of either of the two calls to Tcl_VarEval below. */ - + interp = canvasPtr->interp; Tcl_Preserve((ClientData) interp); xScrollCmd = canvasPtr->xScrollCmd; - if (xScrollCmd != (char *) NULL) { - Tcl_Preserve((ClientData) xScrollCmd); + if (xScrollCmd != NULL) { + Tcl_Preserve((ClientData) xScrollCmd); } yScrollCmd = canvasPtr->yScrollCmd; - if (yScrollCmd != (char *) NULL) { - Tcl_Preserve((ClientData) yScrollCmd); + if (yScrollCmd != NULL) { + Tcl_Preserve((ClientData) yScrollCmd); } xOrigin = canvasPtr->xOrigin; yOrigin = canvasPtr->yOrigin; @@ -5402,27 +5243,27 @@ CanvasUpdateScrollbars(canvasPtr) if (canvasPtr->xScrollCmd != NULL) { Tcl_Obj *fractions = ScrollFractions(xOrigin + inset, xOrigin + width - inset, scrollX1, scrollX2); - result = Tcl_VarEval(interp, xScrollCmd, " ", - Tcl_GetString(fractions), (char *) NULL); + result = Tcl_VarEval(interp, xScrollCmd, " ", Tcl_GetString(fractions), + NULL); Tcl_DecrRefCount(fractions); if (result != TCL_OK) { Tcl_BackgroundError(interp); } Tcl_ResetResult(interp); - Tcl_Release((ClientData) xScrollCmd); + Tcl_Release((ClientData) xScrollCmd); } if (yScrollCmd != NULL) { Tcl_Obj *fractions = ScrollFractions(yOrigin + inset, yOrigin + height - inset, scrollY1, scrollY2); - result = Tcl_VarEval(interp, yScrollCmd, " ", - Tcl_GetString(fractions), (char *) NULL); + result = Tcl_VarEval(interp, yScrollCmd, " ", Tcl_GetString(fractions), + NULL); Tcl_DecrRefCount(fractions); if (result != TCL_OK) { Tcl_BackgroundError(interp); } Tcl_ResetResult(interp); - Tcl_Release((ClientData) yScrollCmd); + Tcl_Release((ClientData) yScrollCmd); } Tcl_Release((ClientData) interp); } @@ -5432,38 +5273,35 @@ CanvasUpdateScrollbars(canvasPtr) * * CanvasSetOrigin -- * - * This procedure is invoked to change the mapping between - * canvas coordinates and screen coordinates in the canvas - * window. + * This function is invoked to change the mapping between canvas + * coordinates and screen coordinates in the canvas window. * * Results: * None. * * Side effects: - * The canvas will be redisplayed to reflect the change in - * view. In addition, scrollbars will be updated if there - * are any. + * The canvas will be redisplayed to reflect the change in view. In + * addition, scrollbars will be updated if there are any. * *-------------------------------------------------------------- */ static void -CanvasSetOrigin(canvasPtr, xOrigin, yOrigin) - TkCanvas *canvasPtr; /* Information about canvas. */ - int xOrigin; /* New X origin for canvas (canvas x-coord +CanvasSetOrigin( + TkCanvas *canvasPtr, /* Information about canvas. */ + int xOrigin, /* New X origin for canvas (canvas x-coord * corresponding to left edge of canvas * window). */ - int yOrigin; /* New Y origin for canvas (canvas y-coord + int yOrigin) /* New Y origin for canvas (canvas y-coord * corresponding to top edge of canvas * window). */ { int left, right, top, bottom, delta; /* - * If scroll increments have been set, round the window origin - * to the nearest multiple of the increments. Remember, the - * origin is the place just inside the borders, not the upper - * left corner. + * If scroll increments have been set, round the window origin to the + * nearest multiple of the increments. Remember, the origin is the place + * just inside the borders, not the upper left corner. */ if (canvasPtr->xScrollIncrement > 0) { @@ -5491,13 +5329,13 @@ CanvasSetOrigin(canvasPtr, xOrigin, yOrigin) /* * Adjust the origin if necessary to keep as much as possible of the - * canvas in the view. The variables left, right, etc. keep track of - * how much extra space there is on each side of the view before it - * will stick out past the scroll region. If one side sticks out past - * the edge of the scroll region, adjust the view to bring that side - * back to the edge of the scrollregion (but don't move it so much that - * the other side sticks out now). If scroll increments are in effect, - * be sure to adjust only by full increments. + * canvas in the view. The variables left, right, etc. keep track of how + * much extra space there is on each side of the view before it will stick + * out past the scroll region. If one side sticks out past the edge of + * the scroll region, adjust the view to bring that side back to the edge + * of the scrollregion (but don't move it so much that the other side + * sticks out now). If scroll increments are in effect, be sure to adjust + * only by full increments. */ if ((canvasPtr->confine) && (canvasPtr->regionString != NULL)) { @@ -5540,11 +5378,11 @@ CanvasSetOrigin(canvasPtr, xOrigin, yOrigin) } /* - * Tricky point: must redisplay not only everything that's visible - * in the window's final configuration, but also everything that was - * visible in the initial configuration. This is needed because some - * item types, like windows, need to know when they move off-screen - * so they can explicitly undisplay themselves. + * Tricky point: must redisplay not only everything that's visible in the + * window's final configuration, but also everything that was visible in + * the initial configuration. This is needed because some item types, like + * windows, need to know when they move off-screen so they can explicitly + * undisplay themselves. */ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, @@ -5559,37 +5397,38 @@ CanvasSetOrigin(canvasPtr, xOrigin, yOrigin) canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin), canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin)); } - + /* *---------------------------------------------------------------------- * - * GetStringsFromObjs + * TkGetStringsFromObjs -- * * Results: * Converts object list into string list. * * Side effects: - * Memory is allocated for the argv array, which must - * be freed using ckfree() when no longer needed. + * Memory is allocated for the objv array, which must be freed using + * ckfree() when no longer needed. * *---------------------------------------------------------------------- */ + /* ARGSUSED */ static CONST char ** -GetStringsFromObjs(argc, objv) - int argc; - Tcl_Obj *CONST objv[]; +TkGetStringsFromObjs( + int objc, + Tcl_Obj *CONST objv[]) { register int i; CONST char **argv; - if (argc <= 0) { + if (objc <= 0) { return NULL; } - argv = (CONST char **) ckalloc((argc+1) * sizeof(char *)); - for (i = 0; i < argc; i++) { - argv[i] = Tcl_GetStringFromObj(objv[i], NULL); + argv = (CONST char **) ckalloc((objc+1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + argv[i] = Tcl_GetString(objv[i]); } - argv[argc] = 0; + argv[objc] = 0; return argv; } @@ -5598,16 +5437,15 @@ GetStringsFromObjs(argc, objv) * * Tk_CanvasPsColor -- * - * This procedure is called by individual canvas items when - * they want to set a color value for output. Given information - * about an X color, this procedure will generate Postscript - * commands to set up an appropriate color in Postscript. + * This function is called by individual canvas items when they want to + * set a color value for output. Given information about an X color, this + * function will generate Postscript commands to set up an appropriate + * color in Postscript. * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in interp->result. - * If no error occurs, then additional Postscript will be - * appended to interp->result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in interp->result. If no error occurs, then + * additional Postscript will be appended to interp->result. * * Side effects: * None. @@ -5616,11 +5454,11 @@ GetStringsFromObjs(argc, objv) */ int -Tk_CanvasPsColor(interp, canvas, colorPtr) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ - XColor *colorPtr; /* Information about color. */ +Tk_CanvasPsColor( + Tcl_Interp *interp, /* Interpreter for returning Postscript or + * error message. */ + Tk_Canvas canvas, /* Information about canvas. */ + XColor *colorPtr) /* Information about color. */ { return Tk_PostscriptColor(interp, ((TkCanvas *) canvas)->psInfo, colorPtr); @@ -5631,31 +5469,30 @@ Tk_CanvasPsColor(interp, canvas, colorPtr) * * Tk_CanvasPsFont -- * - * This procedure is called by individual canvas items when - * they want to output text. Given information about an X - * font, this procedure will generate Postscript commands - * to set up an appropriate font in Postscript. + * This function is called by individual canvas items when they want to + * output text. Given information about an X font, this function will + * generate Postscript commands to set up an appropriate font in + * Postscript. * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in interp->result. - * If no error occurs, then additional Postscript will be - * appended to the interp->result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in interp->result. If no error occurs, then + * additional Postscript will be appended to the interp->result. * * Side effects: - * The Postscript font name is entered into psInfoPtr->fontTable - * if it wasn't already there. + * The Postscript font name is entered into psInfoPtr->fontTable if it + * wasn't already there. * *-------------------------------------------------------------- */ int -Tk_CanvasPsFont(interp, canvas, tkfont) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ - Tk_Font tkfont; /* Information about font in which text - * is to be printed. */ +Tk_CanvasPsFont( + Tcl_Interp *interp, /* Interpreter for returning Postscript or + * error message. */ + Tk_Canvas canvas, /* Information about canvas. */ + Tk_Font tkfont) /* Information about font in which text is to + * be printed. */ { return Tk_PostscriptFont(interp, ((TkCanvas *) canvas)->psInfo, tkfont); } @@ -5665,16 +5502,14 @@ Tk_CanvasPsFont(interp, canvas, tkfont) * * Tk_CanvasPsBitmap -- * - * This procedure is called to output the contents of a - * sub-region of a bitmap in proper image data format for - * Postscript (i.e. data between angle brackets, one bit - * per pixel). + * This function is called to output the contents of a sub-region of a + * bitmap in proper image data format for Postscript (i.e. data between + * angle brackets, one bit per pixel). * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in interp->result. - * If no error occurs, then additional Postscript will be - * appended to interp->result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in interp->result. If no error occurs, then + * additional Postscript will be appended to interp->result. * * Side effects: * None. @@ -5683,15 +5518,14 @@ Tk_CanvasPsFont(interp, canvas, tkfont) */ int -Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ - Pixmap bitmap; /* Bitmap for which to generate - * Postscript. */ - int startX, startY; /* Coordinates of upper-left corner - * of rectangular region to output. */ - int width, height; /* Height of rectangular region. */ +Tk_CanvasPsBitmap( + Tcl_Interp *interp, /* Interpreter for returning Postscript or + * error message. */ + Tk_Canvas canvas, /* Information about canvas. */ + Pixmap bitmap, /* Bitmap for which to generate Postscript. */ + int startX, int startY, /* Coordinates of upper-left corner of + * rectangular region to output. */ + int width, int height) /* Size of rectangular region. */ { return Tk_PostscriptBitmap(interp, ((TkCanvas *) canvas)->tkwin, ((TkCanvas *) canvas)->psInfo, bitmap, startX, startY, @@ -5703,18 +5537,16 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) * * Tk_CanvasPsStipple -- * - * This procedure is called by individual canvas items when - * they have created a path that they'd like to be filled with - * a stipple pattern. Given information about an X bitmap, - * this procedure will generate Postscript commands to fill - * the current clip region using a stipple pattern defined by the - * bitmap. + * This function is called by individual canvas items when they have + * created a path that they'd like to be filled with a stipple pattern. + * Given information about an X bitmap, this function will generate + * Postscript commands to fill the current clip region using a stipple + * pattern defined by the bitmap. * * Results: - * Returns a standard Tcl return value. If an error occurs - * then an error message will be left in interp->result. - * If no error occurs, then additional Postscript will be - * appended to interp->result. + * Returns a standard Tcl return value. If an error occurs then an error + * message will be left in interp->result. If no error occurs, then + * additional Postscript will be appended to interp->result. * * Side effects: * None. @@ -5723,11 +5555,11 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height) */ int -Tk_CanvasPsStipple(interp, canvas, bitmap) - Tcl_Interp *interp; /* Interpreter for returning Postscript - * or error message. */ - Tk_Canvas canvas; /* Information about canvas. */ - Pixmap bitmap; /* Bitmap to use for stippling. */ +Tk_CanvasPsStipple( + Tcl_Interp *interp, /* Interpreter for returning Postscript or + * error message. */ + Tk_Canvas canvas, /* Information about canvas. */ + Pixmap bitmap) /* Bitmap to use for stippling. */ { return Tk_PostscriptStipple(interp, ((TkCanvas *) canvas)->tkwin, ((TkCanvas *) canvas)->psInfo, bitmap); @@ -5738,12 +5570,11 @@ Tk_CanvasPsStipple(interp, canvas, bitmap) * * Tk_CanvasPsY -- * - * Given a y-coordinate in canvas coordinates, this procedure - * returns a y-coordinate to use for Postscript output. + * Given a y-coordinate in canvas coordinates, this function returns a + * y-coordinate to use for Postscript output. * * Results: - * Returns the Postscript coordinate that corresponds to - * "y". + * Returns the Postscript coordinate that corresponds to "y". * * Side effects: * None. @@ -5752,10 +5583,10 @@ Tk_CanvasPsStipple(interp, canvas, bitmap) */ double -Tk_CanvasPsY(canvas, y) - Tk_Canvas canvas; /* Token for canvas on whose behalf - * Postscript is being generated. */ - double y; /* Y-coordinate in canvas coords. */ +Tk_CanvasPsY( + Tk_Canvas canvas, /* Token for canvas on whose behalf Postscript + * is being generated. */ + double y) /* Y-coordinate in canvas coords. */ { return Tk_PostscriptY(y, ((TkCanvas *) canvas)->psInfo); } @@ -5765,8 +5596,8 @@ Tk_CanvasPsY(canvas, y) * * Tk_CanvasPsPath -- * - * Given an array of points for a path, generate Postscript - * commands to create the path. + * Given an array of points for a path, generate Postscript commands to + * create the path. * * Results: * Postscript commands get appended to what's in interp->result. @@ -5778,16 +5609,23 @@ Tk_CanvasPsY(canvas, y) */ void -Tk_CanvasPsPath(interp, canvas, coordPtr, numPoints) - Tcl_Interp *interp; /* Put generated Postscript in this - * interpreter's result field. */ - Tk_Canvas canvas; /* Canvas on whose behalf Postscript - * is being generated. */ - double *coordPtr; /* Pointer to first in array of - * 2*numPoints coordinates giving - * points for path. */ - int numPoints; /* Number of points at *coordPtr. */ +Tk_CanvasPsPath( + Tcl_Interp *interp, /* Put generated Postscript in this + * interpreter's result field. */ + Tk_Canvas canvas, /* Canvas on whose behalf Postscript is being + * generated. */ + double *coordPtr, /* Pointer to first in array of 2*numPoints + * coordinates giving points for path. */ + int numPoints) /* Number of points at *coordPtr. */ { Tk_PostscriptPath(interp, ((TkCanvas *) canvas)->psInfo, coordPtr, numPoints); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCanvas.h b/generic/tkCanvas.h index ad6c555..d009cfa 100644 --- a/generic/tkCanvas.h +++ b/generic/tkCanvas.h @@ -1,15 +1,14 @@ /* * tkCanvas.h -- * - * Declarations shared among all the files that implement - * canvas widgets. + * Declarations shared among all the files that implement canvas widgets. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * Copyright (c) 1998 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKCANVAS @@ -23,36 +22,39 @@ typedef struct TagSearchExpr_s TagSearchExpr; struct TagSearchExpr_s { - TagSearchExpr *next; /* for linked lists of expressions - used in bindings */ - Tk_Uid uid; /* the uid of the whole expression */ - Tk_Uid *uids; /* expresion compiled to an array of uids */ - int allocated; /* available space for array of uids */ - int length; /* length of expression */ - int index; /* current position in expression evaluation */ - int match; /* this expression matches event's item's tags*/ + TagSearchExpr *next; /* For linked lists of expressions - used in + * bindings. */ + Tk_Uid uid; /* The uid of the whole expression. */ + Tk_Uid *uids; /* Expresion compiled to an array of uids. */ + int allocated; /* Available space for array of uids. */ + int length; /* Length of expression. */ + int index; /* Current position in expression + * evaluation. */ + int match; /* This expression matches event's item's + * tags. */ }; #endif /* not USE_OLD_TAG_SEARCH */ /* - * The record below describes a canvas widget. It is made available - * to the item procedures so they can access certain shared fields such - * as the overall displacement and scale factor for the canvas. + * The record below describes a canvas widget. It is made available to the + * item functions so they can access certain shared fields such as the overall + * displacement and scale factor for the canvas. */ typedef struct TkCanvas { - Tk_Window tkwin; /* Window that embodies the canvas. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display containing widget; needed, among + Tk_Window tkwin; /* Window that embodies the canvas. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up.*/ + Display *display; /* Display containing widget; needed, among * other things, to release resources after * tkwin has already gone away. */ Tcl_Interp *interp; /* Interpreter associated with canvas. */ Tcl_Command widgetCmd; /* Token for canvas's widget command. */ - Tk_Item *firstItemPtr; /* First in list of all items in canvas, - * or NULL if canvas empty. */ - Tk_Item *lastItemPtr; /* Last in list of all items in canvas, - * or NULL if canvas empty. */ + Tk_Item *firstItemPtr; /* First in list of all items in canvas, or + * NULL if canvas empty. */ + Tk_Item *lastItemPtr; /* Last in list of all items in canvas, or + * NULL if canvas empty. */ /* * Information used when displaying widget: @@ -62,39 +64,39 @@ typedef struct TkCanvas { Tk_3DBorder bgBorder; /* Used for canvas background. */ int relief; /* Indicates whether window as a whole is * raised, sunken, or flat. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ XColor *highlightBgColorPtr; - /* Color for drawing traversal highlight - * area when highlight is off. */ + /* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. - * Indicates how much interior stuff must - * be offset from outside edges to leave - * room for borders. */ + * Indicates how much interior stuff must be + * offset from outside edges to leave room for + * borders. */ GC pixmapGC; /* Used to copy bits from a pixmap to the * screen and also to clear the pixmap. */ int width, height; /* Dimensions to request for canvas window, * specified in pixels. */ - int redrawX1, redrawY1; /* Upper left corner of area to redraw, - * in pixel coordinates. Border pixels - * are included. Only valid if - * REDRAW_PENDING flag is set. */ - int redrawX2, redrawY2; /* Lower right corner of area to redraw, - * in integer canvas coordinates. Border - * pixels will *not* be redrawn. */ - int confine; /* Non-zero means constrain view to keep - * as much of canvas visible as possible. */ + int redrawX1, redrawY1; /* Upper left corner of area to redraw, in + * pixel coordinates. Border pixels are + * included. Only valid if REDRAW_PENDING flag + * is set. */ + int redrawX2, redrawY2; /* Lower right corner of area to redraw, in + * integer canvas coordinates. Border pixels + * will *not* be redrawn. */ + int confine; /* Non-zero means constrain view to keep as + * much of canvas visible as possible. */ /* * Information used to manage the selection and insertion cursor: */ - Tk_CanvasTextInfo textInfo; /* Contains lots of fields; see tk.h for - * details. This structure is shared with - * the code that implements individual items. */ + Tk_CanvasTextInfo textInfo; /* Contains lots of fields; see tk.h for + * details. This structure is shared with the + * code that implements individual items. */ int insertOnTime; /* Number of milliseconds cursor should spend * in "on" state for each blink. */ int insertOffTime; /* Number of milliseconds cursor should spend @@ -104,7 +106,7 @@ typedef struct TkCanvas { * off. */ /* - * Transformation applied to canvas as a whole: to compute screen + * Transformation applied to canvas as a whole: to compute screen * coordinates (X,Y) from canvas coordinates (x,y), do the following: * * X = x - xOrigin; @@ -116,65 +118,63 @@ typedef struct TkCanvas { * canvas pixel units. */ int drawableXOrigin, drawableYOrigin; /* During redisplay, these fields give the - * canvas coordinates corresponding to - * the upper-left corner of the drawable - * where items are actually being drawn - * (typically a pixmap smaller than the - * whole window). */ + * canvas coordinates corresponding to the + * upper-left corner of the drawable where + * items are actually being drawn (typically a + * pixmap smaller than the whole window). */ /* * Information used for event bindings associated with items. */ Tk_BindingTable bindingTable; - /* Table of all bindings currently defined - * for this canvas. NULL means that no - * bindings exist, so the table hasn't been - * created. Each "object" used for this - * table is either a Tk_Uid for a tag or - * the address of an item named by id. */ + /* Table of all bindings currently defined for + * this canvas. NULL means that no bindings + * exist, so the table hasn't been created. + * Each "object" used for this table is either + * a Tk_Uid for a tag or the address of an + * item named by id. */ Tk_Item *currentItemPtr; /* The item currently containing the mouse * pointer, or NULL if none. */ Tk_Item *newCurrentPtr; /* The item that is about to become the - * current one, or NULL. This field is - * used to detect deletions of the new - * current item pointer that occur during - * Leave processing of the previous current - * item. */ - double closeEnough; /* The mouse is assumed to be inside an - * item if it is this close to it. */ - XEvent pickEvent; /* The event upon which the current choice - * of currentItem is based. Must be saved - * so that if the currentItem is deleted, - * can pick another. */ - int state; /* Last known modifier state. Used to - * defer picking a new current object - * while buttons are down. */ + * current one, or NULL. This field is used to + * detect deletions of the new current item + * pointer that occur during Leave processing + * of the previous current item. */ + double closeEnough; /* The mouse is assumed to be inside an item + * if it is this close to it. */ + XEvent pickEvent; /* The event upon which the current choice of + * currentItem is based. Must be saved so that + * if the currentItem is deleted, can pick + * another. */ + int state; /* Last known modifier state. Used to defer + * picking a new current object while buttons + * are down. */ /* * Information used for managing scrollbars: */ char *xScrollCmd; /* Command prefix for communicating with - * horizontal scrollbar. NULL means no - * horizontal scrollbar. Malloc'ed*/ + * horizontal scrollbar. NULL means no + * horizontal scrollbar. Malloc'ed. */ char *yScrollCmd; /* Command prefix for communicating with - * vertical scrollbar. NULL means no - * vertical scrollbar. Malloc'ed*/ + * vertical scrollbar. NULL means no vertical + * scrollbar. Malloc'ed. */ int scrollX1, scrollY1, scrollX2, scrollY2; /* These four coordinates define the region * that is the 100% area for scrolling (i.e. * these numbers determine the size and * location of the sliders on scrollbars). * Units are pixels in canvas coords. */ - char *regionString; /* The option string from which scrollX1 - * etc. are derived. Malloc'ed. */ + char *regionString; /* The option string from which scrollX1 etc. + * are derived. Malloc'ed. */ int xScrollIncrement; /* If >0, defines a grid for horizontal - * scrolling. This is the size of the "unit", + * scrolling. This is the size of the "unit", * and the left edge of the screen will always * lie on an even unit boundary. */ int yScrollIncrement; /* If >0, defines a grid for horizontal - * scrolling. This is the size of the "unit", + * scrolling. This is the size of the "unit", * and the left edge of the screen will always * lie on an even unit boundary. */ @@ -195,11 +195,11 @@ typedef struct TkCanvas { */ Tk_Item *hotPtr; /* Pointer to "hot" item (one that's been - * recently used. NULL means there's no - * hot item. */ + * recently used. NULL means there's no hot + * item. */ Tk_Item *hotPrevPtr; /* Pointer to predecessor to hotPtr (NULL - * means item is first in list). This is - * only a hint and may not really be hotPtr's + * means item is first in list). This is only + * a hint and may not really be hotPtr's * predecessor. */ /* @@ -207,61 +207,61 @@ typedef struct TkCanvas { */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ - double pixelsPerMM; /* Scale factor between MM and pixels; - * used when converting coordinates. */ - int flags; /* Various flags; see below for + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + double pixelsPerMM; /* Scale factor between MM and pixels; used + * when converting coordinates. */ + int flags; /* Various flags; see below for * definitions. */ - int nextId; /* Number to use as id for next item - * created in widget. */ - Tk_PostscriptInfo psInfo; - /* Pointer to information used for generating - * Postscript for the canvas. NULL means - * no Postscript is currently being - * generated. */ + int nextId; /* Number to use as id for next item created + * in widget. */ + Tk_PostscriptInfo psInfo; /* Pointer to information used for generating + * Postscript for the canvas. NULL means no + * Postscript is currently being generated. */ Tcl_HashTable idTable; /* Table of integer indices. */ + /* * Additional information, added by the 'dash'-patch */ - VOID *reserved1; - Tk_State canvas_state; /* state of canvas */ - VOID *reserved2; - VOID *reserved3; + + void *reserved1; + Tk_State canvas_state; /* State of canvas. */ + void *reserved2; + void *reserved3; Tk_TSOffset tsoffset; #ifndef USE_OLD_TAG_SEARCH - TagSearchExpr *bindTagExprs; /* linked list of tag expressions used in bindings */ + TagSearchExpr *bindTagExprs;/* Linked list of tag expressions used in + * bindings. */ #endif } TkCanvas; /* * Flag bits for canvases: * - * REDRAW_PENDING - 1 means a DoWhenIdle handler has already - * been created to redraw some or all of the - * canvas. + * REDRAW_PENDING - 1 means a DoWhenIdle handler has already been + * created to redraw some or all of the canvas. * REDRAW_BORDERS - 1 means that the borders need to be redrawn * during the next redisplay operation. * REPICK_NEEDED - 1 means DisplayCanvas should pick a new * current item before redrawing the canvas. - * GOT_FOCUS - 1 means the focus is currently in this - * widget, so should draw the insertion cursor - * and traversal highlight. + * GOT_FOCUS - 1 means the focus is currently in this widget, + * so should draw the insertion cursor and + * traversal highlight. * CURSOR_ON - 1 means the insertion cursor is in the "on" - * phase of its blink cycle. 0 means either - * we don't have the focus or the cursor is in - * the "off" phase of its cycle. - * UPDATE_SCROLLBARS - 1 means the scrollbars should get updated - * as part of the next display operation. - * LEFT_GRABBED_ITEM - 1 means that the mouse left the current - * item while a grab was in effect, so we - * didn't change canvasPtr->currentItemPtr. + * phase of its blink cycle. 0 means either we + * don't have the focus or the cursor is in the + * "off" phase of its cycle. + * UPDATE_SCROLLBARS - 1 means the scrollbars should get updated as + * part of the next display operation. + * LEFT_GRABBED_ITEM - 1 means that the mouse left the current item + * while a grab was in effect, so we didn't + * change canvasPtr->currentItemPtr. * REPICK_IN_PROGRESS - 1 means PickCurrentItem is currently - * executing. If it should be called recursively, + * executing. If it should be called recursively, * it should simply return immediately. - * BBOX_NOT_EMPTY - 1 means that the bounding box of the area - * that should be redrawn is not empty. + * BBOX_NOT_EMPTY - 1 means that the bounding box of the area that + * should be redrawn is not empty. */ #define REDRAW_PENDING 1 @@ -277,8 +277,8 @@ typedef struct TkCanvas { /* * Flag bits for canvas items (redraw_flags): * - * FORCE_REDRAW - 1 means that the new coordinates of some - * item are not yet registered using + * FORCE_REDRAW - 1 means that the new coordinates of some item + * are not yet registered using * Tk_CanvasEventuallyRedraw(). It should still * be done by the general canvas code. */ @@ -286,20 +286,21 @@ typedef struct TkCanvas { #define FORCE_REDRAW 8 /* - * Canvas-related procedures that are shared among Tk modules but not - * exported to the outside world: + * Canvas-related functions that are shared among Tk modules but not exported + * to the outside world: */ -extern int TkCanvPostscriptCmd _ANSI_ARGS_((TkCanvas *canvasPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); - +MODULE_SCOPE int TkCanvPostscriptCmd(TkCanvas *canvasPtr, + Tcl_Interp *interp, int argc, CONST char **argv); +MODULE_SCOPE int TkCanvTranslatePath(TkCanvas *canvPtr, + int numVertex, double *coordPtr, int closed, + XPoint *outPtr); /* - * Other procedures that are shared among Tk canvas modules but not exported - * to the outside world: + * Standard item types provided by Tk: */ -extern int TkCanvTranslatePath _ANSI_ARGS_((TkCanvas *canvPtr, - int numVertex, double *coordPtr, int closed, - XPoint *outPtr)); +MODULE_SCOPE Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType; +MODULE_SCOPE Tk_ItemType tkOvalType, tkPolygonType; +MODULE_SCOPE Tk_ItemType tkRectangleType, tkTextType, tkWindowType; #endif /* _TKCANVAS */ diff --git a/generic/tkClipboard.c b/generic/tkClipboard.c index 8c37f09..9428894 100644 --- a/generic/tkClipboard.c +++ b/generic/tkClipboard.c @@ -1,48 +1,46 @@ /* * tkClipboard.c -- * - * This file manages the clipboard for the Tk toolkit, - * maintaining a collection of data buffers that will be - * supplied on demand to requesting applications. + * This file manages the clipboard for the Tk toolkit, maintaining a + * collection of data buffers that will be supplied on demand to + * requesting applications. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" #include "tkSelect.h" /* - * Prototypes for procedures used only in this file: + * Prototypes for functions used only in this file: */ -static int ClipboardAppHandler _ANSI_ARGS_((ClientData clientData, - int offset, char *buffer, int maxBytes)); -static int ClipboardHandler _ANSI_ARGS_((ClientData clientData, - int offset, char *buffer, int maxBytes)); -static int ClipboardWindowHandler _ANSI_ARGS_(( - ClientData clientData, int offset, char *buffer, - int maxBytes)); -static void ClipboardLostSel _ANSI_ARGS_((ClientData clientData)); -static int ClipboardGetProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, char *portion)); +static int ClipboardAppHandler(ClientData clientData, + int offset, char *buffer, int maxBytes); +static int ClipboardHandler(ClientData clientData, + int offset, char *buffer, int maxBytes); +static int ClipboardWindowHandler(ClientData clientData, + int offset, char *buffer, int maxBytes); +static void ClipboardLostSel(ClientData clientData); +static int ClipboardGetProc(ClientData clientData, + Tcl_Interp *interp, char *portion); /* *---------------------------------------------------------------------- * * ClipboardHandler -- * - * This procedure acts as selection handler for the - * clipboard manager. It extracts the required chunk of - * data from the buffer chain for a given selection target. + * This function acts as selection handler for the clipboard manager. It + * extracts the required chunk of data from the buffer chain for a given + * selection target. * * Results: - * The return value is a count of the number of bytes - * actually stored at buffer. + * The return value is a count of the number of bytes actually stored at + * buffer. * * Side effects: * None. @@ -51,17 +49,17 @@ static int ClipboardGetProc _ANSI_ARGS_((ClientData clientData, */ static int -ClipboardHandler(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Information about data to fetch. */ - int offset; /* Return selection bytes starting at this +ClipboardHandler( + ClientData clientData, /* Information about data to fetch. */ + int offset, /* Return selection bytes starting at this * offset. */ - char *buffer; /* Place to store converted selection. */ - int maxBytes; /* Maximum # of bytes to store at buffer. */ + char *buffer, /* Place to store converted selection. */ + int maxBytes) /* Maximum # of bytes to store at buffer. */ { TkClipboardTarget *targetPtr = (TkClipboardTarget*) clientData; TkClipboardBuffer *cbPtr; char *srcPtr, *destPtr; - int count = 0; + size_t count = 0; int scanned = 0; size_t length, freeCount; @@ -104,7 +102,7 @@ ClipboardHandler(clientData, offset, buffer, maxBytes) srcPtr = cbPtr->buffer; length = cbPtr->length; } - return count; + return (int)count; } /* @@ -112,16 +110,15 @@ ClipboardHandler(clientData, offset, buffer, maxBytes) * * ClipboardAppHandler -- * - * This procedure acts as selection handler for retrievals of type - * TK_APPLICATION. It returns the name of the application that - * owns the clipboard. Note: we can't use the default Tk - * selection handler for this selection type, because the clipboard - * window isn't a "real" window and doesn't have the necessary - * information. + * This function acts as selection handler for retrievals of type + * TK_APPLICATION. It returns the name of the application that owns the + * clipboard. Note: we can't use the default Tk selection handler for + * this selection type, because the clipboard window isn't a "real" + * window and doesn't have the necessary information. * * Results: - * The return value is a count of the number of bytes - * actually stored at buffer. + * The return value is a count of the number of bytes actually stored at + * buffer. * * Side effects: * None. @@ -130,12 +127,12 @@ ClipboardHandler(clientData, offset, buffer, maxBytes) */ static int -ClipboardAppHandler(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Pointer to TkDisplay structure. */ - int offset; /* Return selection bytes starting at this +ClipboardAppHandler( + ClientData clientData, /* Pointer to TkDisplay structure. */ + int offset, /* Return selection bytes starting at this * offset. */ - char *buffer; /* Place to store converted selection. */ - int maxBytes; /* Maximum # of bytes to store at buffer. */ + char *buffer, /* Place to store converted selection. */ + int maxBytes) /* Maximum # of bytes to store at buffer. */ { TkDisplay *dispPtr = (TkDisplay *) clientData; size_t length; @@ -151,7 +148,7 @@ ClipboardAppHandler(clientData, offset, buffer, maxBytes) length = maxBytes; } strncpy(buffer, p, length); - return length; + return (int)length; } /* @@ -159,15 +156,13 @@ ClipboardAppHandler(clientData, offset, buffer, maxBytes) * * ClipboardWindowHandler -- * - * This procedure acts as selection handler for retrievals of - * type TK_WINDOW. Since the clipboard doesn't correspond to - * any particular window, we just return ".". We can't use Tk's - * default handler for this selection type, because the clipboard - * window isn't a valid window. + * This function acts as selection handler for retrievals of type + * TK_WINDOW. Since the clipboard doesn't correspond to any particular + * window, we just return ".". We can't use Tk's default handler for this + * selection type, because the clipboard window isn't a valid window. * * Results: - * The return value is 1, the number of non-null bytes stored - * at buffer. + * The return value is 1, the number of non-null bytes stored at buffer. * * Side effects: * None. @@ -176,12 +171,12 @@ ClipboardAppHandler(clientData, offset, buffer, maxBytes) */ static int -ClipboardWindowHandler(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Not used. */ - int offset; /* Return selection bytes starting at this +ClipboardWindowHandler( + ClientData clientData, /* Not used. */ + int offset, /* Return selection bytes starting at this * offset. */ - char *buffer; /* Place to store converted selection. */ - int maxBytes; /* Maximum # of bytes to store at buffer. */ + char *buffer, /* Place to store converted selection. */ + int maxBytes) /* Maximum # of bytes to store at buffer. */ { buffer[0] = '.'; buffer[1] = 0; @@ -193,9 +188,9 @@ ClipboardWindowHandler(clientData, offset, buffer, maxBytes) * * ClipboardLostSel -- * - * This procedure is invoked whenever clipboard ownership is - * claimed by another window. It just sets a flag so that we - * know the clipboard was taken away. + * This function is invoked whenever clipboard ownership is claimed by + * another window. It just sets a flag so that we know the clipboard was + * taken away. * * Results: * None. @@ -207,8 +202,8 @@ ClipboardWindowHandler(clientData, offset, buffer, maxBytes) */ static void -ClipboardLostSel(clientData) - ClientData clientData; /* Pointer to TkDisplay structure. */ +ClipboardLostSel( + ClientData clientData) /* Pointer to TkDisplay structure. */ { TkDisplay *dispPtr = (TkDisplay*) clientData; @@ -220,33 +215,31 @@ ClipboardLostSel(clientData) * * Tk_ClipboardClear -- * - * Take control of the clipboard and clear out the previous - * contents. This procedure must be invoked before any - * calls to Tk_ClipboardAppend. + * Take control of the clipboard and clear out the previous contents. + * This function must be invoked before any calls to Tk_ClipboardAppend. * * Results: - * A standard Tcl result. If an error occurs, an error message is - * left in the interp's result. + * A standard Tcl result. If an error occurs, an error message is left in + * the interp's result. * * Side effects: - * From now on, requests for the CLIPBOARD selection will be - * directed to the clipboard manager routines associated with - * clipWindow for the display of tkwin. In order to guarantee - * atomicity, no event handling should occur between - * Tk_ClipboardClear and the following Tk_ClipboardAppend - * calls. This procedure may cause a user-defined LostSel command - * to be invoked when the CLIPBOARD is claimed, so any calling - * function should be reentrant at the point Tk_ClipboardClear is + * From now on, requests for the CLIPBOARD selection will be directed to + * the clipboard manager routines associated with clipWindow for the + * display of tkwin. In order to guarantee atomicity, no event handling + * should occur between Tk_ClipboardClear and the following + * Tk_ClipboardAppend calls. This function may cause a user-defined + * LostSel command to be invoked when the CLIPBOARD is claimed, so any + * calling function should be reentrant at the point Tk_ClipboardClear is * invoked. * *---------------------------------------------------------------------- */ int -Tk_ClipboardClear(interp, tkwin) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tk_Window tkwin; /* Window in application that is clearing - * clipboard; identifies application and +Tk_ClipboardClear( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin) /* Window in application that is clearing + * clipboard; identifies application and * display. */ { TkWindow *winPtr = (TkWindow *) tkwin; @@ -264,8 +257,8 @@ Tk_ClipboardClear(interp, tkwin) } /* - * Discard any existing clipboard data and delete the selection - * handler(s) associated with that data. + * Discard any existing clipboard data and delete the selection handler(s) + * associated with that data. */ for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL; @@ -301,38 +294,37 @@ Tk_ClipboardClear(interp, tkwin) * * Tk_ClipboardAppend -- * - * Append a buffer of data to the clipboard. The first buffer of - * a given type determines the format for that type. Any successive - * appends to that type must have the same format or an error will - * be returned. Tk_ClipboardClear must be called before a sequence - * of Tk_ClipboardAppend calls can be issued. In order to guarantee + * Append a buffer of data to the clipboard. The first buffer of a given + * type determines the format for that type. Any successive appends to + * that type must have the same format or an error will be returned. + * Tk_ClipboardClear must be called before a sequence of + * Tk_ClipboardAppend calls can be issued. In order to guarantee * atomicity, no event handling should occur between Tk_ClipboardClear * and the following Tk_ClipboardAppend calls. * * Results: - * A standard Tcl result. If an error is returned, an error message - * is left in the interp's result. + * A standard Tcl result. If an error is returned, an error message is + * left in the interp's result. * * Side effects: - * The specified buffer will be copied onto the end of the clipboard. - * The clipboard maintains a list of buffers which will be used to - * supply the data for a selection get request. The first time a given - * type is appended, Tk_ClipboardAppend will register a selection - * handler of the appropriate type. + * The specified buffer will be copied onto the end of the clipboard. + * The clipboard maintains a list of buffers which will be used to supply + * the data for a selection get request. The first time a given type is + * appended, Tk_ClipboardAppend will register a selection handler of the + * appropriate type. * *---------------------------------------------------------------------- */ int -Tk_ClipboardAppend(interp, tkwin, type, format, buffer) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Window tkwin; /* Window that selects a display. */ - Atom type; /* The desired conversion type for this +Tk_ClipboardAppend( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Window tkwin, /* Window that selects a display. */ + Atom type, /* The desired conversion type for this * clipboard item, e.g. STRING or LENGTH. */ - Atom format; /* Format in which the selection - * information should be returned to - * the requestor. */ - char* buffer; /* NULL terminated string containing the data + Atom format, /* Format in which the selection information + * should be returned to the requestor. */ + char* buffer) /* NULL terminated string containing the data * to be added to the clipboard. */ { TkWindow *winPtr = (TkWindow *) tkwin; @@ -341,8 +333,8 @@ Tk_ClipboardAppend(interp, tkwin, type, format, buffer) TkClipboardBuffer *cbPtr; /* - * If this application doesn't already own the clipboard, clear - * the clipboard. If we don't own the clipboard selection, claim it. + * If this application doesn't already own the clipboard, clear the + * clipboard. If we don't own the clipboard selection, claim it. */ if (dispPtr->clipboardAppPtr != winPtr->mainPtr) { @@ -355,14 +347,15 @@ Tk_ClipboardAppend(interp, tkwin, type, format, buffer) /* * Check to see if the specified target is already present on the - * clipboard. If it isn't, we need to create a new target; otherwise, - * we just append the new buffer to the clipboard list. + * clipboard. If it isn't, we need to create a new target; otherwise, we + * just append the new buffer to the clipboard list. */ for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL; targetPtr = targetPtr->nextPtr) { - if (targetPtr->type == type) + if (targetPtr->type == type) { break; + } } if (targetPtr == NULL) { targetPtr = (TkClipboardTarget*) ckalloc(sizeof(TkClipboardTarget)); @@ -377,7 +370,7 @@ Tk_ClipboardAppend(interp, tkwin, type, format, buffer) Tcl_AppendResult(interp, "format \"", Tk_GetAtomName(tkwin, format), "\" does not match current format \"", Tk_GetAtomName(tkwin, targetPtr->format),"\" for ", - Tk_GetAtomName(tkwin, type), (char *) NULL); + Tk_GetAtomName(tkwin, type), NULL); return TCL_ERROR; } @@ -408,9 +401,8 @@ Tk_ClipboardAppend(interp, tkwin, type, format, buffer) * * Tk_ClipboardObjCmd -- * - * This procedure is invoked to process the "clipboard" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "clipboard" Tcl command. See + * the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -422,12 +414,11 @@ Tk_ClipboardAppend(interp, tkwin, type, format, buffer) */ int -Tk_ClipboardObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +Tk_ClipboardObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { Tk_Window tkwin = (Tk_Window) clientData; char *path = NULL; @@ -447,173 +438,173 @@ Tk_ClipboardObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case CLIPBOARD_APPEND: { - Atom target, format; - char *targetName = NULL; - char *formatName = NULL; - char *string; - static CONST char *appendOptionStrings[] = { - "-displayof", "-format", "-type", NULL - }; - enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, - APPEND_TYPE }; - int subIndex, length; - - for (i = 2; i < objc - 1; i++) { - string = Tcl_GetStringFromObj(objv[i], &length); - if (string[0] != '-') { - break; - } - - /* - * If the argument is "--", it signifies the end of arguments. - */ - if (string[1] == '-' && length == 2) { - i++; - break; - } - if (Tcl_GetIndexFromObj(interp, objv[i], appendOptionStrings, - "option", 0, &subIndex) != TCL_OK) { - return TCL_ERROR; - } - - /* - * Increment i so that it points to the value for the flag - * instead of the flag itself. - */ + case CLIPBOARD_APPEND: { + Atom target, format; + char *targetName = NULL; + char *formatName = NULL; + char *string; + static CONST char *appendOptionStrings[] = { + "-displayof", "-format", "-type", NULL + }; + enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE }; + int subIndex, length; + + for (i = 2; i < objc - 1; i++) { + string = Tcl_GetStringFromObj(objv[i], &length); + if (string[0] != '-') { + break; + } + /* + * If the argument is "--", it signifies the end of arguments. + */ + if (string[1] == '-' && length == 2) { i++; - if (i >= objc) { - Tcl_AppendResult(interp, "value for \"", string, - "\" missing", (char *) NULL); - return TCL_ERROR; - } - switch ((enum appendOptions) subIndex) { - case APPEND_DISPLAYOF: - path = Tcl_GetString(objv[i]); - break; - case APPEND_FORMAT: - formatName = Tcl_GetString(objv[i]); - break; - case APPEND_TYPE: - targetName = Tcl_GetString(objv[i]); - break; - } + break; } - if (objc - i != 1) { - Tcl_WrongNumArgs(interp, 2, objv, "?options? data"); + if (Tcl_GetIndexFromObj(interp, objv[i], appendOptionStrings, + "option", 0, &subIndex) != TCL_OK) { return TCL_ERROR; } - if (path != NULL) { - tkwin = Tk_NameToWindow(interp, path, tkwin); - } - if (tkwin == NULL) { + + /* + * Increment i so that it points to the value for the flag instead + * of the flag itself. + */ + + i++; + if (i >= objc) { + Tcl_AppendResult(interp, "value for \"", string, + "\" missing", NULL); return TCL_ERROR; } - if (targetName != NULL) { - target = Tk_InternAtom(tkwin, targetName); - } else { - target = XA_STRING; - } - if (formatName != NULL) { - format = Tk_InternAtom(tkwin, formatName); - } else { - format = XA_STRING; + switch ((enum appendOptions) subIndex) { + case APPEND_DISPLAYOF: + path = Tcl_GetString(objv[i]); + break; + case APPEND_FORMAT: + formatName = Tcl_GetString(objv[i]); + break; + case APPEND_TYPE: + targetName = Tcl_GetString(objv[i]); + break; } - return Tk_ClipboardAppend(interp, tkwin, target, format, - Tcl_GetString(objv[i])); } - case CLIPBOARD_CLEAR: { - static CONST char *clearOptionStrings[] = { "-displayof", NULL }; - enum clearOptions { CLEAR_DISPLAYOF }; - int subIndex; - if (objc != 2 && objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?"); - return TCL_ERROR; - } + if (objc - i != 1) { + Tcl_WrongNumArgs(interp, 2, objv, "?options? data"); + return TCL_ERROR; + } + if (path != NULL) { + tkwin = Tk_NameToWindow(interp, path, tkwin); + } + if (tkwin == NULL) { + return TCL_ERROR; + } + if (targetName != NULL) { + target = Tk_InternAtom(tkwin, targetName); + } else { + target = XA_STRING; + } + if (formatName != NULL) { + format = Tk_InternAtom(tkwin, formatName); + } else { + format = XA_STRING; + } + return Tk_ClipboardAppend(interp, tkwin, target, format, + Tcl_GetString(objv[i])); + } + case CLIPBOARD_CLEAR: { + static CONST char *clearOptionStrings[] = { "-displayof", NULL }; + enum clearOptions { CLEAR_DISPLAYOF }; + int subIndex; + + if (objc != 2 && objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?"); + return TCL_ERROR; + } - if (objc == 4) { - if (Tcl_GetIndexFromObj(interp, objv[2], clearOptionStrings, - "option", 0, &subIndex) != TCL_OK) { - return TCL_ERROR; - } - if ((enum clearOptions) subIndex == CLEAR_DISPLAYOF) { - path = Tcl_GetString(objv[3]); - } - } - if (path != NULL) { - tkwin = Tk_NameToWindow(interp, path, tkwin); - } - if (tkwin == NULL) { + if (objc == 4) { + if (Tcl_GetIndexFromObj(interp, objv[2], clearOptionStrings, + "option", 0, &subIndex) != TCL_OK) { return TCL_ERROR; } - return Tk_ClipboardClear(interp, tkwin); - } - case CLIPBOARD_GET: { - Atom target; - char *targetName = NULL; - Tcl_DString selBytes; - int result; - char *string; - static CONST char *getOptionStrings[] = { - "-displayof", "-type", NULL - }; - enum getOptions { APPEND_DISPLAYOF, APPEND_TYPE }; - int subIndex; - - for (i = 2; i < objc; i++) { - string = Tcl_GetString(objv[i]); - if (string[0] != '-') { - break; - } - if (Tcl_GetIndexFromObj(interp, objv[i], getOptionStrings, - "option", 0, &subIndex) != TCL_OK) { - return TCL_ERROR; - } - i++; - if (i >= objc) { - Tcl_AppendResult(interp, "value for \"", string, - "\" missing", (char *) NULL); - return TCL_ERROR; - } - switch ((enum getOptions) subIndex) { - case APPEND_DISPLAYOF: - path = Tcl_GetString(objv[i]); - break; - case APPEND_TYPE: - targetName = Tcl_GetString(objv[i]); - break; - } + if ((enum clearOptions) subIndex == CLEAR_DISPLAYOF) { + path = Tcl_GetString(objv[3]); } - if (path != NULL) { - tkwin = Tk_NameToWindow(interp, path, tkwin); + } + if (path != NULL) { + tkwin = Tk_NameToWindow(interp, path, tkwin); + } + if (tkwin == NULL) { + return TCL_ERROR; + } + return Tk_ClipboardClear(interp, tkwin); + } + case CLIPBOARD_GET: { + Atom target; + char *targetName = NULL; + Tcl_DString selBytes; + int result; + char *string; + static CONST char *getOptionStrings[] = { + "-displayof", "-type", NULL + }; + enum getOptions { APPEND_DISPLAYOF, APPEND_TYPE }; + int subIndex; + + for (i = 2; i < objc; i++) { + string = Tcl_GetString(objv[i]); + if (string[0] != '-') { + break; } - if (tkwin == NULL) { + if (Tcl_GetIndexFromObj(interp, objv[i], getOptionStrings, + "option", 0, &subIndex) != TCL_OK) { return TCL_ERROR; } - selection = Tk_InternAtom(tkwin, "CLIPBOARD"); - - if (objc - i > 1) { - Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + i++; + if (i >= objc) { + Tcl_AppendResult(interp, "value for \"", string, + "\" missing", NULL); return TCL_ERROR; - } else if (objc - i == 1) { - target = Tk_InternAtom(tkwin, Tcl_GetString(objv[i])); - } else if (targetName != NULL) { - target = Tk_InternAtom(tkwin, targetName); - } else { - target = XA_STRING; } - - Tcl_DStringInit(&selBytes); - result = Tk_GetSelection(interp, tkwin, selection, target, - ClipboardGetProc, (ClientData) &selBytes); - if (result == TCL_OK) { - Tcl_DStringResult(interp, &selBytes); - } else { - Tcl_DStringFree(&selBytes); + switch ((enum getOptions) subIndex) { + case APPEND_DISPLAYOF: + path = Tcl_GetString(objv[i]); + break; + case APPEND_TYPE: + targetName = Tcl_GetString(objv[i]); + break; } - return result; } + if (path != NULL) { + tkwin = Tk_NameToWindow(interp, path, tkwin); + } + if (tkwin == NULL) { + return TCL_ERROR; + } + selection = Tk_InternAtom(tkwin, "CLIPBOARD"); + + if (objc - i > 1) { + Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + return TCL_ERROR; + } else if (objc - i == 1) { + target = Tk_InternAtom(tkwin, Tcl_GetString(objv[i])); + } else if (targetName != NULL) { + target = Tk_InternAtom(tkwin, targetName); + } else { + target = XA_STRING; + } + + Tcl_DStringInit(&selBytes); + result = Tk_GetSelection(interp, tkwin, selection, target, + ClipboardGetProc, (ClientData) &selBytes); + if (result == TCL_OK) { + Tcl_DStringResult(interp, &selBytes); + } else { + Tcl_DStringFree(&selBytes); + } + return result; + } } return TCL_OK; } @@ -623,8 +614,8 @@ Tk_ClipboardObjCmd(clientData, interp, objc, objv) * * TkClipInit -- * - * This procedure is called to initialize the window for claiming - * clipboard ownership and for receiving selection get results. This + * This function is called to initialize the window for claiming + * clipboard ownership and for receiving selection get results. This * function is called from tkSelect.c as well as tkClipboard.c. * * Results: @@ -639,17 +630,16 @@ Tk_ClipboardObjCmd(clientData, interp, objc, objv) */ int -TkClipInit(interp, dispPtr) - Tcl_Interp *interp; /* Interpreter to use for error - * reporting. */ - register TkDisplay *dispPtr;/* Display to initialize. */ +TkClipInit( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + register TkDisplay *dispPtr)/* Display to initialize. */ { XSetWindowAttributes atts; dispPtr->clipTargetPtr = NULL; dispPtr->clipboardActive = 0; dispPtr->clipboardAppPtr = NULL; - + /* * Create the window used for clipboard ownership and selection retrieval, * and set up an event handler for it. @@ -667,17 +657,17 @@ TkClipInit(interp, dispPtr) if (dispPtr->multipleAtom == None) { /* - * Need to invoke selection initialization to make sure that - * atoms we depend on below are defined. + * Need to invoke selection initialization to make sure that atoms we + * depend on below are defined. */ TkSelInit(dispPtr->clipWindow); } /* - * Create selection handlers for types TK_APPLICATION and TK_WINDOW - * on this window. Can't use the default handlers for these types - * because this isn't a full-fledged window. + * Create selection handlers for types TK_APPLICATION and TK_WINDOW on + * this window. Can't use the default handlers for these types because + * this isn't a full-fledged window. */ Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom, @@ -694,29 +684,37 @@ TkClipInit(interp, dispPtr) * * ClipboardGetProc -- * - * This procedure is invoked to process pieces of the selection - * as they arrive during "clipboard get" commands. + * This function is invoked to process pieces of the selection as they + * arrive during "clipboard get" commands. * * Results: * Always returns TCL_OK. * * Side effects: - * Bytes get appended to the dynamic string pointed to by the - * clientData argument. + * Bytes get appended to the dynamic string pointed to by the clientData + * argument. * *-------------------------------------------------------------- */ /* ARGSUSED */ static int -ClipboardGetProc(clientData, interp, portion) - ClientData clientData; /* Dynamic string holding partially - * assembled selection. */ - Tcl_Interp *interp; /* Interpreter used for error - * reporting (not used). */ - char *portion; /* New information to be appended. */ +ClipboardGetProc( + ClientData clientData, /* Dynamic string holding partially assembled + * selection. */ + Tcl_Interp *interp, /* Interpreter used for error reporting (not + * used). */ + char *portion) /* New information to be appended. */ { Tcl_DStringAppend((Tcl_DString *) clientData, portion, -1); return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCmds.c b/generic/tkCmds.c index 16cfd8d..a86ef84 100644 --- a/generic/tkCmds.c +++ b/generic/tkCmds.c @@ -1,50 +1,47 @@ -/* +/* * tkCmds.c -- * - * This file contains a collection of Tk-related Tcl commands - * that didn't fit in any particular file of the toolkit. + * This file contains a collection of Tk-related Tcl commands that didn't + * fit in any particular file of the toolkit. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 2000 Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" #if defined(WIN32) #include "tkWinInt.h" -#elif defined(MAC_TCL) -#include "tkMacInt.h" -#elif defined(MAC_OSX_TK) +#elif defined(MAC_OSX_TK) #include "tkMacOSXInt.h" #else #include "tkUnixInt.h" #endif /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static TkWindow * GetToplevel _ANSI_ARGS_((Tk_Window tkwin)); -static char * WaitVariableProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static void WaitVisibilityProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void WaitWindowProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); +static TkWindow * GetTopHierarchy(Tk_Window tkwin); +static char * WaitVariableProc(ClientData clientData, + Tcl_Interp *interp, const char *name1, + const char *name2, int flags); +static void WaitVisibilityProc(ClientData clientData, + XEvent *eventPtr); +static void WaitWindowProc(ClientData clientData, + XEvent *eventPtr); /* *---------------------------------------------------------------------- * * Tk_BellObjCmd -- * - * This procedure is invoked to process the "bell" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "bell" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -56,18 +53,21 @@ static void WaitWindowProc _ANSI_ARGS_((ClientData clientData, */ int -Tk_BellObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_BellObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - static CONST char *bellOptions[] = {"-displayof", "-nice", (char *) NULL}; + static const char *bellOptions[] = { + "-displayof", "-nice", NULL + }; enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE }; Tk_Window tkwin = (Tk_Window) clientData; int i, index, nice = 0; if (objc > 4) { + wrongArgs: Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window? ?-nice?"); return TCL_ERROR; } @@ -78,20 +78,18 @@ Tk_BellObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } switch ((enum options) index) { - case TK_BELL_DISPLAYOF: - if (++i >= objc) { - Tcl_WrongNumArgs(interp, 1, objv, - "?-displayof window? ?-nice?"); - return TCL_ERROR; - } - tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin); - if (tkwin == NULL) { - return TCL_ERROR; - } - break; - case TK_BELL_NICE: - nice = 1; - break; + case TK_BELL_DISPLAYOF: + if (++i >= objc) { + goto wrongArgs; + } + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + break; + case TK_BELL_NICE: + nice = 1; + break; } } XBell(Tk_Display(tkwin), 0); @@ -107,8 +105,8 @@ Tk_BellObjCmd(clientData, interp, objc, objv) * * Tk_BindObjCmd -- * - * This procedure is invoked to process the "bind" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "bind" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -120,23 +118,23 @@ Tk_BellObjCmd(clientData, interp, objc, objv) */ int -Tk_BindObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_BindObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; TkWindow *winPtr; ClientData object; char *string; - + if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "window ?pattern? ?command?"); return TCL_ERROR; } string = Tcl_GetString(objv[1]); - + /* * Bind tags either a window name or a tag name for the first argument. * If the argument starts with ".", assume it is a window; otherwise, it @@ -155,8 +153,8 @@ Tk_BindObjCmd(clientData, interp, objc, objv) } /* - * If there are four arguments, the command is modifying a binding. If - * there are three arguments, the command is querying a binding. If there + * If there are four arguments, the command is modifying a binding. If + * there are three arguments, the command is querying a binding. If there * are only two arguments, the command is querying all the bindings for * the given tag/window. */ @@ -167,7 +165,7 @@ Tk_BindObjCmd(clientData, interp, objc, objv) char *sequence, *script; sequence = Tcl_GetString(objv[2]); script = Tcl_GetString(objv[3]); - + /* * If the script is null, just delete the binding. */ @@ -181,7 +179,7 @@ Tk_BindObjCmd(clientData, interp, objc, objv) * If the script begins with "+", append this script to the existing * binding. */ - + if (script[0] == '+') { script++; append = 1; @@ -192,7 +190,7 @@ Tk_BindObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } } else if (objc == 3) { - CONST char *command; + const char *command; command = Tk_GetBinding(interp, winPtr->mainPtr->bindingTable, object, Tcl_GetString(objv[2])); @@ -212,8 +210,8 @@ Tk_BindObjCmd(clientData, interp, objc, objv) * * TkBindEventProc -- * - * This procedure is invoked by Tk_HandleEvent for each event; it - * causes any appropriate bindings for that event to be invoked. + * This function is invoked by Tk_HandleEvent for each event; it causes + * any appropriate bindings for that event to be invoked. * * Results: * None. @@ -226,9 +224,9 @@ Tk_BindObjCmd(clientData, interp, objc, objv) */ void -TkBindEventProc(winPtr, eventPtr) - TkWindow *winPtr; /* Pointer to info about window. */ - XEvent *eventPtr; /* Information about event. */ +TkBindEventProc( + TkWindow *winPtr, /* Pointer to info about window. */ + XEvent *eventPtr) /* Information about event. */ { #define MAX_OBJS 20 ClientData objects[MAX_OBJS], *objPtr; @@ -244,8 +242,8 @@ TkBindEventProc(winPtr, eventPtr) objPtr = objects; if (winPtr->numTags != 0) { /* - * Make a copy of the tags for the window, replacing window names - * with pointers to the pathName from the appropriate window. + * Make a copy of the tags for the window, replacing window names with + * pointers to the pathName from the appropriate window. */ if (winPtr->numTags > MAX_OBJS) { @@ -293,8 +291,8 @@ TkBindEventProc(winPtr, eventPtr) * * Tk_BindtagsObjCmd -- * - * This procedure is invoked to process the "bindtags" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "bindtags" Tcl command. See + * the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -306,18 +304,18 @@ TkBindEventProc(winPtr, eventPtr) */ int -Tk_BindtagsObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_BindtagsObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; TkWindow *winPtr, *winPtr2; int i, length; char *p; Tcl_Obj *listPtr, **tags; - + if ((objc < 2) || (objc > 3)) { Tcl_WrongNumArgs(interp, 1, objv, "window ?taglist?"); return TCL_ERROR; @@ -375,9 +373,9 @@ Tk_BindtagsObjCmd(clientData, interp, objc, objv) /* * Handle names starting with "." specially: store a malloc'ed - * string, rather than a Uid; at event time we'll look up the - * name in the window table and use the corresponding window, - * if there is one. + * string, rather than a Uid; at event time we'll look up the name + * in the window table and use the corresponding window, if there + * is one. */ copy = (char *) ckalloc((unsigned) (strlen(p) + 1)); @@ -395,9 +393,9 @@ Tk_BindtagsObjCmd(clientData, interp, objc, objv) * * TkFreeBindingTags -- * - * This procedure is called to free all of the binding tags - * associated with a window; typically it is only invoked where - * there are window-specific tags. + * This function is called to free all of the binding tags associated + * with a window; typically it is only invoked where there are + * window-specific tags. * * Results: * None. @@ -409,8 +407,8 @@ Tk_BindtagsObjCmd(clientData, interp, objc, objv) */ void -TkFreeBindingTags(winPtr) - TkWindow *winPtr; /* Window whose tags are to be released. */ +TkFreeBindingTags( + TkWindow *winPtr) /* Window whose tags are to be released. */ { int i; char *p; @@ -419,10 +417,10 @@ TkFreeBindingTags(winPtr) p = (char *) (winPtr->tagPtr[i]); if (*p == '.') { /* - * Names starting with "." are malloced rather than Uids, so - * they have to be freed. + * Names starting with "." are malloced rather than Uids, so they + * have to be freed. */ - + ckfree(p); } } @@ -436,8 +434,8 @@ TkFreeBindingTags(winPtr) * * Tk_DestroyObjCmd -- * - * This procedure is invoked to process the "destroy" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "destroy" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -449,12 +447,11 @@ TkFreeBindingTags(winPtr) */ int -Tk_DestroyObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_DestroyObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window window; Tk_Window tkwin = (Tk_Window) clientData; @@ -469,13 +466,12 @@ Tk_DestroyObjCmd(clientData, interp, objc, objv) Tk_DestroyWindow(window); if (window == tkwin) { /* - * We just deleted the main window for the application! This - * makes it impossible to do anything more (tkwin isn't - * valid anymore). + * We just deleted the main window for the application! This makes + * it impossible to do anything more (tkwin isn't valid anymore). */ break; - } + } } return TCL_OK; } @@ -485,8 +481,8 @@ Tk_DestroyObjCmd(clientData, interp, objc, objv) * * Tk_LowerObjCmd -- * - * This procedure is invoked to process the "lower" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "lower" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -499,12 +495,11 @@ Tk_DestroyObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ int -Tk_LowerObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_LowerObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window mainwin = (Tk_Window) clientData; Tk_Window tkwin, other; @@ -529,7 +524,7 @@ Tk_LowerObjCmd(clientData, interp, objc, objv) if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) { Tcl_AppendResult(interp, "can't lower \"", Tcl_GetString(objv[1]), "\" below \"", (other ? Tcl_GetString(objv[2]) : ""), - "\"", (char *) NULL); + "\"", NULL); return TCL_ERROR; } return TCL_OK; @@ -540,8 +535,8 @@ Tk_LowerObjCmd(clientData, interp, objc, objv) * * Tk_RaiseObjCmd -- * - * This procedure is invoked to process the "raise" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "raise" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -554,12 +549,11 @@ Tk_LowerObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ int -Tk_RaiseObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_RaiseObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window mainwin = (Tk_Window) clientData; Tk_Window tkwin, other; @@ -584,7 +578,7 @@ Tk_RaiseObjCmd(clientData, interp, objc, objv) if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) { Tcl_AppendResult(interp, "can't raise \"", Tcl_GetString(objv[1]), "\" above \"", (other ? Tcl_GetString(objv[2]) : ""), - "\"", (char *) NULL); + "\"", NULL); return TCL_ERROR; } return TCL_OK; @@ -595,8 +589,8 @@ Tk_RaiseObjCmd(clientData, interp, objc, objv) * * Tk_TkObjCmd -- * - * This procedure is invoked to process the "tk" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "tk" Tcl command. See the user + * documentation for details on what it does. * * Results: * A standard Tcl result. @@ -608,21 +602,21 @@ Tk_RaiseObjCmd(clientData, interp, objc, objv) */ int -Tk_TkObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_TkObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { int index; Tk_Window tkwin; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "appname", "caret", "scaling", "useinputmethods", - "windowingsystem", NULL + "windowingsystem", "inactive", NULL }; enum options { TK_APPNAME, TK_CARET, TK_SCALING, TK_USE_IM, - TK_WINDOWINGSYSTEM + TK_WINDOWINGSYSTEM, TK_INACTIVE }; tkwin = (Tk_Window) clientData; @@ -637,216 +631,257 @@ Tk_TkObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case TK_APPNAME: { - TkWindow *winPtr; - char *string; - - if (Tcl_IsSafe(interp)) { - Tcl_SetResult(interp, - "appname not accessible in a safe interpreter", - TCL_STATIC); - return TCL_ERROR; - } + case TK_APPNAME: { + TkWindow *winPtr; + char *string; + + if (Tcl_IsSafe(interp)) { + Tcl_SetResult(interp, + "appname not accessible in a safe interpreter", + TCL_STATIC); + return TCL_ERROR; + } - winPtr = (TkWindow *) tkwin; + winPtr = (TkWindow *) tkwin; - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?newName?"); - return TCL_ERROR; - } - if (objc == 3) { - string = Tcl_GetStringFromObj(objv[2], NULL); - winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string)); - } - Tcl_AppendResult(interp, winPtr->nameUid, NULL); - break; + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?newName?"); + return TCL_ERROR; + } + if (objc == 3) { + string = Tcl_GetString(objv[2]); + winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string)); + } + Tcl_AppendResult(interp, winPtr->nameUid, NULL); + break; + } + case TK_CARET: { + Tcl_Obj *objPtr; + TkCaret *caretPtr; + Tk_Window window; + static const char *caretStrings[] = { + "-x", "-y", "-height", NULL + }; + enum caretOptions { + TK_CARET_X, TK_CARET_Y, TK_CARET_HEIGHT + }; + + if ((objc < 3) || ((objc > 4) && !(objc & 1))) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?-x x? ?-y y? ?-height height?"); + return TCL_ERROR; } - case TK_CARET: { - Tcl_Obj *objPtr; - TkCaret *caretPtr; - Tk_Window window; - static CONST char *caretStrings[] - = { "-x", "-y", "-height", NULL }; - enum caretOptions - { TK_CARET_X, TK_CARET_Y, TK_CARET_HEIGHT }; - - if ((objc < 3) || ((objc > 4) && !(objc & 1))) { - Tcl_WrongNumArgs(interp, 2, objv, - "window ?-x x? ?-y y? ?-height height?"); + window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); + if (window == NULL) { + return TCL_ERROR; + } + caretPtr = &(((TkWindow *) window)->dispPtr->caret); + if (objc == 3) { + /* + * Return all the current values + */ + + objPtr = Tcl_NewObj(); + Tcl_ListObjAppendElement(interp, objPtr, + Tcl_NewStringObj("-height", 7)); + Tcl_ListObjAppendElement(interp, objPtr, + Tcl_NewIntObj(caretPtr->height)); + Tcl_ListObjAppendElement(interp, objPtr, + Tcl_NewStringObj("-x", 2)); + Tcl_ListObjAppendElement(interp, objPtr, + Tcl_NewIntObj(caretPtr->x)); + Tcl_ListObjAppendElement(interp, objPtr, + Tcl_NewStringObj("-y", 2)); + Tcl_ListObjAppendElement(interp, objPtr, + Tcl_NewIntObj(caretPtr->y)); + Tcl_SetObjResult(interp, objPtr); + } else if (objc == 4) { + int value; + + /* + * Return the current value of the selected option + */ + + if (Tcl_GetIndexFromObj(interp, objv[3], caretStrings, + "caret option", 0, &index) != TCL_OK) { return TCL_ERROR; } - window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); - if (window == NULL) { - return TCL_ERROR; + if (index == TK_CARET_X) { + value = caretPtr->x; + } else if (index == TK_CARET_Y) { + value = caretPtr->y; + } else /* if (index == TK_CARET_HEIGHT) -- last case */ { + value = caretPtr->height; } - caretPtr = &(((TkWindow *) window)->dispPtr->caret); - if (objc == 3) { - /* - * Return all the current values - */ - objPtr = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewStringObj("-height", 7)); - Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewIntObj(caretPtr->height)); - Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewStringObj("-x", 2)); - Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewIntObj(caretPtr->x)); - Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewStringObj("-y", 2)); - Tcl_ListObjAppendElement(interp, objPtr, - Tcl_NewIntObj(caretPtr->y)); - Tcl_SetObjResult(interp, objPtr); - } else if (objc == 4) { - int value; - /* - * Return the current value of the selected option - */ - if (Tcl_GetIndexFromObj(interp, objv[3], caretStrings, - "caret option", 0, &index) != TCL_OK) { + Tcl_SetIntObj(Tcl_GetObjResult(interp), value); + } else { + int i, value, x = 0, y = 0, height = -1; + + for (i = 3; i < objc; i += 2) { + if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings, + "caret option", 0, &index) != TCL_OK) || + Tcl_GetIntFromObj(interp,objv[i+1],&value) != TCL_OK) { return TCL_ERROR; } if (index == TK_CARET_X) { - value = caretPtr->x; + x = value; } else if (index == TK_CARET_Y) { - value = caretPtr->y; + y = value; } else /* if (index == TK_CARET_HEIGHT) -- last case */ { - value = caretPtr->height; - } - Tcl_SetIntObj(Tcl_GetObjResult(interp), value); - } else { - int i, value, x = 0, y = 0, height = -1; - - for (i = 3; i < objc; i += 2) { - if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings, - "caret option", 0, &index) != TCL_OK) || - (Tcl_GetIntFromObj(interp, objv[i+1], &value) - != TCL_OK)) { - return TCL_ERROR; - } - if (index == TK_CARET_X) { - x = value; - } else if (index == TK_CARET_Y) { - y = value; - } else /* if (index == TK_CARET_HEIGHT) -- last case */ { - height = value; - } - } - if (height < 0) { - height = Tk_Height(window); + height = value; } - Tk_SetCaretPos(window, x, y, height); } - break; + if (height < 0) { + height = Tk_Height(window); + } + Tk_SetCaretPos(window, x, y, height); + } + break; + } + case TK_SCALING: { + Screen *screenPtr; + int skip, width, height; + double d; + + if (Tcl_IsSafe(interp)) { + Tcl_SetResult(interp, + "scaling not accessible in a safe interpreter", + TCL_STATIC); + return TCL_ERROR; } - case TK_SCALING: { - Screen *screenPtr; - int skip, width, height; - double d; - if (Tcl_IsSafe(interp)) { - Tcl_SetResult(interp, - "scaling not accessible in a safe interpreter", - TCL_STATIC); + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; + } + screenPtr = Tk_Screen(tkwin); + if (objc - skip == 2) { + d = 25.4 / 72; + d *= WidthOfScreen(screenPtr); + d /= WidthMMOfScreen(screenPtr); + Tcl_SetDoubleObj(Tcl_GetObjResult(interp), d); + } else if (objc - skip == 3) { + if (Tcl_GetDoubleFromObj(interp, objv[2+skip], &d) != TCL_OK) { return TCL_ERROR; } - - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; + d = (25.4 / 72) / d; + width = (int) (d * WidthOfScreen(screenPtr) + 0.5); + if (width <= 0) { + width = 1; } - screenPtr = Tk_Screen(tkwin); - if (objc - skip == 2) { - d = 25.4 / 72; - d *= WidthOfScreen(screenPtr); - d /= WidthMMOfScreen(screenPtr); - Tcl_SetDoubleObj(Tcl_GetObjResult(interp), d); - } else if (objc - skip == 3) { - if (Tcl_GetDoubleFromObj(interp, objv[2+skip], &d) != TCL_OK) { - return TCL_ERROR; - } - d = (25.4 / 72) / d; - width = (int) (d * WidthOfScreen(screenPtr) + 0.5); - if (width <= 0) { - width = 1; - } - height = (int) (d * HeightOfScreen(screenPtr) + 0.5); - if (height <= 0) { - height = 1; - } - WidthMMOfScreen(screenPtr) = width; - HeightMMOfScreen(screenPtr) = height; - } else { - Tcl_WrongNumArgs(interp, 2, objv, - "?-displayof window? ?factor?"); - return TCL_ERROR; + height = (int) (d * HeightOfScreen(screenPtr) + 0.5); + if (height <= 0) { + height = 1; } - break; + WidthMMOfScreen(screenPtr) = width; + HeightMMOfScreen(screenPtr) = height; + } else { + Tcl_WrongNumArgs(interp, 2, objv, + "?-displayof window? ?factor?"); + return TCL_ERROR; + } + break; + } + case TK_USE_IM: { + TkDisplay *dispPtr; + int skip; + + if (Tcl_IsSafe(interp)) { + Tcl_SetResult(interp, + "useinputmethods not accessible in a safe interpreter", + TCL_STATIC); + return TCL_ERROR; } - case TK_USE_IM: { - TkDisplay *dispPtr; - int skip; - if (Tcl_IsSafe(interp)) { - Tcl_SetResult(interp, - "useinputmethods not accessible in a safe interpreter", - TCL_STATIC); - return TCL_ERROR; - } + skip = TkGetDisplayOf(interp, objc-2, objv+2, &tkwin); + if (skip < 0) { + return TCL_ERROR; + } + dispPtr = ((TkWindow *) tkwin)->dispPtr; + if ((objc - skip) == 3) { + /* + * In the case where TK_USE_INPUT_METHODS is not defined, this + * will be ignored and we will always return 0. That will indicate + * to the user that input methods are just not available. + */ - skip = TkGetDisplayOf(interp, objc-2, objv+2, &tkwin); - if (skip < 0) { + int boolVal; + + if (Tcl_GetBooleanFromObj(interp, objv[2+skip], + &boolVal) != TCL_OK) { return TCL_ERROR; } - dispPtr = ((TkWindow *) tkwin)->dispPtr; - if ((objc - skip) == 3) { - /* - * In the case where TK_USE_INPUT_METHODS is not defined, - * this will be ignored and we will always return 0. - * That will indicate to the user that input methods - * are just not available. - */ - int boolVal; - if (Tcl_GetBooleanFromObj(interp, objv[2+skip], &boolVal) - != TCL_OK) { - return TCL_ERROR; - } #ifdef TK_USE_INPUT_METHODS - if (boolVal) { - dispPtr->flags |= TK_DISPLAY_USE_IM; - } else { - dispPtr->flags &= ~TK_DISPLAY_USE_IM; - } -#endif /* TK_USE_INPUT_METHODS */ - } else if ((objc - skip) != 2) { - Tcl_WrongNumArgs(interp, 2, objv, - "?-displayof window? ?boolean?"); - return TCL_ERROR; + if (boolVal) { + dispPtr->flags |= TK_DISPLAY_USE_IM; + } else { + dispPtr->flags &= ~TK_DISPLAY_USE_IM; } - Tcl_SetBooleanObj(Tcl_GetObjResult(interp), - (int) (dispPtr->flags & TK_DISPLAY_USE_IM)); - break; +#endif /* TK_USE_INPUT_METHODS */ + } else if ((objc - skip) != 2) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-displayof window? ?boolean?"); + return TCL_ERROR; + } + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), + (int) (dispPtr->flags & TK_DISPLAY_USE_IM)); + break; + } + case TK_WINDOWINGSYSTEM: { + const char *windowingsystem; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; } - case TK_WINDOWINGSYSTEM: { - CONST char *windowingsystem; - - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } #if defined(WIN32) - windowingsystem = "win32"; -#elif defined(MAC_TCL) - windowingsystem = "classic"; + windowingsystem = "win32"; #elif defined(MAC_OSX_TK) - windowingsystem = "aqua"; + windowingsystem = "aqua"; #else - windowingsystem = "x11"; + windowingsystem = "x11"; #endif - Tcl_SetStringObj(Tcl_GetObjResult(interp), windowingsystem, -1); - break; + Tcl_SetStringObj(Tcl_GetObjResult(interp), windowingsystem, -1); + break; + } + case TK_INACTIVE: { + int skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + + if (skip < 0) { + return TCL_ERROR; + } + if (objc - skip == 2) { + long inactive; + + inactive = (Tcl_IsSafe(interp) ? -1 : + Tk_GetUserInactiveTime(Tk_Display(tkwin))); + Tcl_SetObjResult(interp, Tcl_NewLongObj(inactive)); + + } else if (objc - skip == 3) { + char *string; + + string = Tcl_GetString(objv[objc-1]); + if (strcmp(string, "reset") != 0) { + Tcl_Obj *msg = Tcl_NewStringObj("bad option \"", -1); + + Tcl_AppendStringsToObj(msg, string, "\": must be reset", NULL); + Tcl_SetObjResult(interp, msg); + return TCL_ERROR; + } + if (Tcl_IsSafe(interp)) { + Tcl_SetResult(interp, + "resetting the user inactivity timer " + "is not allowed in a safe interpreter", TCL_STATIC); + return TCL_ERROR; + } + Tk_ResetUserInactiveTime(Tk_Display(tkwin)); + Tcl_ResetResult(interp); + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? ?reset?"); + return TCL_ERROR; } + break; + } } return TCL_OK; } @@ -856,8 +891,8 @@ Tk_TkObjCmd(clientData, interp, objc, objv) * * Tk_TkwaitObjCmd -- * - * This procedure is invoked to process the "tkwait" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "tkwait" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -870,19 +905,21 @@ Tk_TkObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ int -Tk_TkwaitObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_TkwaitObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; int done, index; - static CONST char *optionStrings[] = { "variable", "visibility", "window", - (char *) NULL }; - enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW }; - + static const char *optionStrings[] = { + "variable", "visibility", "window", NULL + }; + enum options { + TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW + }; + if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name"); return TCL_ERROR; @@ -894,78 +931,78 @@ Tk_TkwaitObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case TKWAIT_VARIABLE: { - if (Tcl_TraceVar(interp, Tcl_GetString(objv[2]), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - WaitVariableProc, (ClientData) &done) != TCL_OK) { - return TCL_ERROR; - } - done = 0; - while (!done) { - Tcl_DoOneEvent(0); - } - Tcl_UntraceVar(interp, Tcl_GetString(objv[2]), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - WaitVariableProc, (ClientData) &done); - break; + case TKWAIT_VARIABLE: + if (Tcl_TraceVar(interp, Tcl_GetString(objv[2]), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + WaitVariableProc, (ClientData) &done) != TCL_OK) { + return TCL_ERROR; + } + done = 0; + while (!done) { + Tcl_DoOneEvent(0); } - - case TKWAIT_VISIBILITY: { - Tk_Window window; + Tcl_UntraceVar(interp, Tcl_GetString(objv[2]), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + WaitVariableProc, (ClientData) &done); + break; - window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); - if (window == NULL) { - return TCL_ERROR; - } - Tk_CreateEventHandler(window, - VisibilityChangeMask|StructureNotifyMask, - WaitVisibilityProc, (ClientData) &done); - done = 0; - while (!done) { - Tcl_DoOneEvent(0); - } - if (done != 1) { - /* - * Note that we do not delete the event handler because it - * was deleted automatically when the window was destroyed. - */ - - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "window \"", Tcl_GetString(objv[2]), - "\" was deleted before its visibility changed", - (char *) NULL); - return TCL_ERROR; - } - Tk_DeleteEventHandler(window, - VisibilityChangeMask|StructureNotifyMask, - WaitVisibilityProc, (ClientData) &done); - break; + case TKWAIT_VISIBILITY: { + Tk_Window window; + + window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); + if (window == NULL) { + return TCL_ERROR; } - - case TKWAIT_WINDOW: { - Tk_Window window; - - window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); - if (window == NULL) { - return TCL_ERROR; - } - Tk_CreateEventHandler(window, StructureNotifyMask, - WaitWindowProc, (ClientData) &done); - done = 0; - while (!done) { - Tcl_DoOneEvent(0); - } + Tk_CreateEventHandler(window, + VisibilityChangeMask|StructureNotifyMask, + WaitVisibilityProc, (ClientData) &done); + done = 0; + while (!done) { + Tcl_DoOneEvent(0); + } + if (done != 1) { /* - * Note: there's no need to delete the event handler. It was + * Note that we do not delete the event handler because it was * deleted automatically when the window was destroyed. */ - break; + + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "window \"", Tcl_GetString(objv[2]), + "\" was deleted before its visibility changed", NULL); + return TCL_ERROR; } + Tk_DeleteEventHandler(window, + VisibilityChangeMask|StructureNotifyMask, + WaitVisibilityProc, (ClientData) &done); + break; + } + + case TKWAIT_WINDOW: { + Tk_Window window; + + window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); + if (window == NULL) { + return TCL_ERROR; + } + Tk_CreateEventHandler(window, StructureNotifyMask, + WaitWindowProc, (ClientData) &done); + done = 0; + while (!done) { + Tcl_DoOneEvent(0); + } + + /* + * Note: there's no need to delete the event handler. It was deleted + * automatically when the window was destroyed. + */ + + break; + } } /* - * Clear out the interpreter's result, since it may have been set - * by event handlers. + * Clear out the interpreter's result, since it may have been set by event + * handlers. */ Tcl_ResetResult(interp); @@ -974,24 +1011,24 @@ Tk_TkwaitObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ static char * -WaitVariableProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Pointer to integer to set to 1. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Name of variable. */ - CONST char *name2; /* Second part of variable name. */ - int flags; /* Information about what happened. */ +WaitVariableProc( + ClientData clientData, /* Pointer to integer to set to 1. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + const char *name1, /* Name of variable. */ + const char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ { int *donePtr = (int *) clientData; *donePtr = 1; - return (char *) NULL; + return NULL; } /*ARGSUSED*/ static void -WaitVisibilityProc(clientData, eventPtr) - ClientData clientData; /* Pointer to integer to set to 1. */ - XEvent *eventPtr; /* Information about event (not used). */ +WaitVisibilityProc( + ClientData clientData, /* Pointer to integer to set to 1. */ + XEvent *eventPtr) /* Information about event (not used). */ { int *donePtr = (int *) clientData; @@ -1004,9 +1041,9 @@ WaitVisibilityProc(clientData, eventPtr) } static void -WaitWindowProc(clientData, eventPtr) - ClientData clientData; /* Pointer to integer to set to 1. */ - XEvent *eventPtr; /* Information about event. */ +WaitWindowProc( + ClientData clientData, /* Pointer to integer to set to 1. */ + XEvent *eventPtr) /* Information about event. */ { int *donePtr = (int *) clientData; @@ -1020,8 +1057,8 @@ WaitWindowProc(clientData, eventPtr) * * Tk_UpdateObjCmd -- * - * This procedure is invoked to process the "update" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "update" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -1034,14 +1071,13 @@ WaitWindowProc(clientData, eventPtr) /* ARGSUSED */ int -Tk_UpdateObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_UpdateObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - static CONST char *updateOptions[] = {"idletasks", (char *) NULL}; + static const char *updateOptions[] = {"idletasks", NULL}; int flags, index; TkDisplay *dispPtr; @@ -1054,19 +1090,18 @@ Tk_UpdateObjCmd(clientData, interp, objc, objv) } flags = TCL_IDLE_EVENTS; } else { - Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?"); + Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?"); return TCL_ERROR; } /* - * Handle all pending events, sync all displays, and repeat over - * and over again until all pending events have been handled. - * Special note: it's possible that the entire application could - * be destroyed by an event handler that occurs during the update. - * Thus, don't use any information from tkwin after calling - * Tcl_DoOneEvent. + * Handle all pending events, sync all displays, and repeat over and over + * again until all pending events have been handled. Special note: it's + * possible that the entire application could be destroyed by an event + * handler that occurs during the update. Thus, don't use any information + * from tkwin after calling Tcl_DoOneEvent. */ - + while (1) { while (Tcl_DoOneEvent(flags) != 0) { /* Empty loop body */ @@ -1081,8 +1116,8 @@ Tk_UpdateObjCmd(clientData, interp, objc, objv) } /* - * Must clear the interpreter's result because event handlers could - * have executed commands. + * Must clear the interpreter's result because event handlers could have + * executed commands. */ Tcl_ResetResult(interp); @@ -1094,8 +1129,8 @@ Tk_UpdateObjCmd(clientData, interp, objc, objv) * * Tk_WinfoObjCmd -- * - * This procedure is invoked to process the "winfo" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "winfo" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -1107,12 +1142,11 @@ Tk_UpdateObjCmd(clientData, interp, objc, objv) */ int -Tk_WinfoObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_WinfoObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { int index, x, y, width, height, useX, useY, class, skip; char *string; @@ -1120,7 +1154,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) Tk_Window tkwin; Tcl_Obj *resultPtr; - static TkStateMap visualMap[] = { + static const TkStateMap visualMap[] = { {PseudoColor, "pseudocolor"}, {GrayScale, "grayscale"}, {DirectColor, "directcolor"}, @@ -1129,7 +1163,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) {StaticGray, "staticgray"}, {-1, NULL} }; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "cells", "children", "class", "colormapfull", "depth", "geometry", "height", "id", "ismapped", "manager", "name", "parent", @@ -1140,7 +1174,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) "toplevel", "viewable", "visual", "visualid", "vrootheight", "vrootwidth", "vrootx", "vrooty", "width", "x", "y", - + "atom", "atomname", "containing", "interps", "pathname", @@ -1160,7 +1194,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) WIN_TOPLEVEL, WIN_VIEWABLE, WIN_VISUAL, WIN_VISUALID, WIN_VROOTHEIGHT,WIN_VROOTWIDTH, WIN_VROOTX, WIN_VROOTY, WIN_WIDTH, WIN_X, WIN_Y, - + WIN_ATOM, WIN_ATOMNAME, WIN_CONTAINING, WIN_INTERPS, WIN_PATHNAME, @@ -1169,7 +1203,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) }; tkwin = (Tk_Window) clientData; - + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); return TCL_ERROR; @@ -1184,7 +1218,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; } - string = Tcl_GetStringFromObj(objv[2], NULL); + string = Tcl_GetString(objv[2]); tkwin = Tk_NameToWindow(interp, string, tkwin); if (tkwin == NULL) { return TCL_ERROR; @@ -1194,502 +1228,468 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) resultPtr = Tcl_GetObjResult(interp); switch ((enum options) index) { - case WIN_CELLS: { - Tcl_SetIntObj(resultPtr, Tk_Visual(tkwin)->map_entries); - break; - } - case WIN_CHILDREN: { - Tcl_Obj *strPtr; - - winPtr = winPtr->childList; - for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) { - if (!(winPtr->flags & TK_ANONYMOUS_WINDOW)) { - strPtr = Tcl_NewStringObj(winPtr->pathName, -1); - Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); - } + case WIN_CELLS: + Tcl_SetIntObj(resultPtr, Tk_Visual(tkwin)->map_entries); + break; + case WIN_CHILDREN: { + Tcl_Obj *strPtr; + + winPtr = winPtr->childList; + for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) { + if (!(winPtr->flags & TK_ANONYMOUS_WINDOW)) { + strPtr = Tcl_NewStringObj(winPtr->pathName, -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); } - break; - } - case WIN_CLASS: { - Tcl_SetStringObj(resultPtr, Tk_Class(tkwin), -1); - break; - } - case WIN_COLORMAPFULL: { - Tcl_SetBooleanObj(resultPtr, - TkpCmapStressed(tkwin, Tk_Colormap(tkwin))); - break; } - case WIN_DEPTH: { - Tcl_SetIntObj(resultPtr, Tk_Depth(tkwin)); - break; - } - case WIN_GEOMETRY: { - char buf[16 + TCL_INTEGER_SPACE * 4]; + break; + } + case WIN_CLASS: + Tcl_SetStringObj(resultPtr, Tk_Class(tkwin), -1); + break; + case WIN_COLORMAPFULL: + Tcl_SetBooleanObj(resultPtr, + TkpCmapStressed(tkwin, Tk_Colormap(tkwin))); + break; + case WIN_DEPTH: + Tcl_SetIntObj(resultPtr, Tk_Depth(tkwin)); + break; + case WIN_GEOMETRY: { + char buf[16 + TCL_INTEGER_SPACE * 4]; + + sprintf(buf, "%dx%d+%d+%d", Tk_Width(tkwin), Tk_Height(tkwin), + Tk_X(tkwin), Tk_Y(tkwin)); + Tcl_SetStringObj(resultPtr, buf, -1); + break; + } + case WIN_HEIGHT: + Tcl_SetIntObj(resultPtr, Tk_Height(tkwin)); + break; + case WIN_ID: { + char buf[TCL_INTEGER_SPACE]; - sprintf(buf, "%dx%d+%d+%d", Tk_Width(tkwin), Tk_Height(tkwin), - Tk_X(tkwin), Tk_Y(tkwin)); - Tcl_SetStringObj(resultPtr, buf, -1); - break; - } - case WIN_HEIGHT: { - Tcl_SetIntObj(resultPtr, Tk_Height(tkwin)); - break; + Tk_MakeWindowExist(tkwin); + TkpPrintWindowId(buf, Tk_WindowId(tkwin)); + + /* + * interp result may have changed, refetch it + */ + + resultPtr = Tcl_GetObjResult(interp); + Tcl_SetStringObj(resultPtr, buf, -1); + break; + } + case WIN_ISMAPPED: + Tcl_SetBooleanObj(resultPtr, (int) Tk_IsMapped(tkwin)); + break; + case WIN_MANAGER: + if (winPtr->geomMgrPtr != NULL) { + Tcl_SetStringObj(resultPtr, winPtr->geomMgrPtr->name, -1); + } + break; + case WIN_NAME: + Tcl_SetStringObj(resultPtr, Tk_Name(tkwin), -1); + break; + case WIN_PARENT: + if (winPtr->parentPtr != NULL) { + Tcl_SetStringObj(resultPtr, winPtr->parentPtr->pathName, -1); + } + break; + case WIN_POINTERX: + useX = 1; + useY = 0; + goto pointerxy; + case WIN_POINTERY: + useX = 0; + useY = 1; + goto pointerxy; + case WIN_POINTERXY: + useX = 1; + useY = 1; + + pointerxy: + winPtr = GetTopHierarchy(tkwin); + if (winPtr == NULL) { + x = -1; + y = -1; + } else { + TkGetPointerCoords((Tk_Window) winPtr, &x, &y); } - case WIN_ID: { - char buf[TCL_INTEGER_SPACE]; - - Tk_MakeWindowExist(tkwin); - TkpPrintWindowId(buf, Tk_WindowId(tkwin)); - /* - * interp result may have changed, refetch it - */ - resultPtr = Tcl_GetObjResult(interp); + if (useX & useY) { + char buf[TCL_INTEGER_SPACE * 2]; + + sprintf(buf, "%d %d", x, y); Tcl_SetStringObj(resultPtr, buf, -1); - break; - } - case WIN_ISMAPPED: { - Tcl_SetBooleanObj(resultPtr, (int) Tk_IsMapped(tkwin)); - break; - } - case WIN_MANAGER: { - if (winPtr->geomMgrPtr != NULL) { - Tcl_SetStringObj(resultPtr, winPtr->geomMgrPtr->name, -1); - } - break; - } - case WIN_NAME: { - Tcl_SetStringObj(resultPtr, Tk_Name(tkwin), -1); - break; - } - case WIN_PARENT: { - if (winPtr->parentPtr != NULL) { - Tcl_SetStringObj(resultPtr, winPtr->parentPtr->pathName, -1); - } - break; + } else if (useX) { + Tcl_SetIntObj(resultPtr, x); + } else { + Tcl_SetIntObj(resultPtr, y); } - case WIN_POINTERX: { - useX = 1; - useY = 0; - goto pointerxy; - } - case WIN_POINTERY: { - useX = 0; - useY = 1; - goto pointerxy; - } - case WIN_POINTERXY: { - useX = 1; - useY = 1; - - pointerxy: - winPtr = GetToplevel(tkwin); - if (winPtr == NULL) { - x = -1; - y = -1; - } else { - TkGetPointerCoords((Tk_Window) winPtr, &x, &y); + break; + case WIN_REQHEIGHT: + Tcl_SetIntObj(resultPtr, Tk_ReqHeight(tkwin)); + break; + case WIN_REQWIDTH: + Tcl_SetIntObj(resultPtr, Tk_ReqWidth(tkwin)); + break; + case WIN_ROOTX: + Tk_GetRootCoords(tkwin, &x, &y); + Tcl_SetIntObj(resultPtr, x); + break; + case WIN_ROOTY: + Tk_GetRootCoords(tkwin, &x, &y); + Tcl_SetIntObj(resultPtr, y); + break; + case WIN_SCREEN: { + char buf[TCL_INTEGER_SPACE]; + + sprintf(buf, "%d", Tk_ScreenNumber(tkwin)); + Tcl_AppendStringsToObj(resultPtr, Tk_DisplayName(tkwin),".",buf, NULL); + break; + } + case WIN_SCREENCELLS: + Tcl_SetIntObj(resultPtr, CellsOfScreen(Tk_Screen(tkwin))); + break; + case WIN_SCREENDEPTH: + Tcl_SetIntObj(resultPtr, DefaultDepthOfScreen(Tk_Screen(tkwin))); + break; + case WIN_SCREENHEIGHT: + Tcl_SetIntObj(resultPtr, HeightOfScreen(Tk_Screen(tkwin))); + break; + case WIN_SCREENWIDTH: + Tcl_SetIntObj(resultPtr, WidthOfScreen(Tk_Screen(tkwin))); + break; + case WIN_SCREENMMHEIGHT: + Tcl_SetIntObj(resultPtr, HeightMMOfScreen(Tk_Screen(tkwin))); + break; + case WIN_SCREENMMWIDTH: + Tcl_SetIntObj(resultPtr, WidthMMOfScreen(Tk_Screen(tkwin))); + break; + case WIN_SCREENVISUAL: + class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class; + goto visual; + case WIN_SERVER: + TkGetServerInfo(interp, tkwin); + break; + case WIN_TOPLEVEL: + winPtr = GetTopHierarchy(tkwin); + if (winPtr != NULL) { + Tcl_SetStringObj(resultPtr, winPtr->pathName, -1); + } + break; + case WIN_VIEWABLE: { + int viewable = 0; + + for ( ; ; winPtr = winPtr->parentPtr) { + if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) { + break; } - if (useX & useY) { - char buf[TCL_INTEGER_SPACE * 2]; - - sprintf(buf, "%d %d", x, y); - Tcl_SetStringObj(resultPtr, buf, -1); - } else if (useX) { - Tcl_SetIntObj(resultPtr, x); - } else { - Tcl_SetIntObj(resultPtr, y); + if (winPtr->flags & TK_TOP_HIERARCHY) { + viewable = 1; + break; } - break; } - case WIN_REQHEIGHT: { - Tcl_SetIntObj(resultPtr, Tk_ReqHeight(tkwin)); - break; - } - case WIN_REQWIDTH: { - Tcl_SetIntObj(resultPtr, Tk_ReqWidth(tkwin)); - break; - } - case WIN_ROOTX: { - Tk_GetRootCoords(tkwin, &x, &y); - Tcl_SetIntObj(resultPtr, x); - break; - } - case WIN_ROOTY: { - Tk_GetRootCoords(tkwin, &x, &y); - Tcl_SetIntObj(resultPtr, y); - break; + + Tcl_SetBooleanObj(resultPtr, viewable); + break; + } + case WIN_VISUAL: + class = Tk_Visual(tkwin)->class; + + visual: + string = TkFindStateString(visualMap, class); + if (string == NULL) { + string = "unknown"; + } + Tcl_SetStringObj(resultPtr, string, -1); + break; + case WIN_VISUALID: { + char buf[TCL_INTEGER_SPACE]; + + sprintf(buf, "0x%x", + (unsigned int) XVisualIDFromVisual(Tk_Visual(tkwin))); + Tcl_SetStringObj(resultPtr, buf, -1); + break; + } + case WIN_VROOTHEIGHT: + Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); + Tcl_SetIntObj(resultPtr, height); + break; + case WIN_VROOTWIDTH: + Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); + Tcl_SetIntObj(resultPtr, width); + break; + case WIN_VROOTX: + Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); + Tcl_SetIntObj(resultPtr, x); + break; + case WIN_VROOTY: + Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); + Tcl_SetIntObj(resultPtr, y); + break; + case WIN_WIDTH: + Tcl_SetIntObj(resultPtr, Tk_Width(tkwin)); + break; + case WIN_X: + Tcl_SetIntObj(resultPtr, Tk_X(tkwin)); + break; + case WIN_Y: + Tcl_SetIntObj(resultPtr, Tk_Y(tkwin)); + break; + + /* + * Uses -displayof. + */ + + case WIN_ATOM: + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case WIN_SCREEN: { - char buf[TCL_INTEGER_SPACE]; - - sprintf(buf, "%d", Tk_ScreenNumber(tkwin)); - Tcl_AppendStringsToObj(resultPtr, Tk_DisplayName(tkwin), ".", - buf, NULL); - break; + if (objc - skip != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? name"); + return TCL_ERROR; } - case WIN_SCREENCELLS: { - Tcl_SetIntObj(resultPtr, CellsOfScreen(Tk_Screen(tkwin))); - break; + objv += skip; + string = Tcl_GetString(objv[2]); + Tcl_SetLongObj(resultPtr, (long) Tk_InternAtom(tkwin, string)); + break; + case WIN_ATOMNAME: { + const char *name; + long id; + + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case WIN_SCREENDEPTH: { - Tcl_SetIntObj(resultPtr, DefaultDepthOfScreen(Tk_Screen(tkwin))); - break; + if (objc - skip != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id"); + return TCL_ERROR; } - case WIN_SCREENHEIGHT: { - Tcl_SetIntObj(resultPtr, HeightOfScreen(Tk_Screen(tkwin))); - break; + objv += skip; + if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) { + return TCL_ERROR; } - case WIN_SCREENWIDTH: { - Tcl_SetIntObj(resultPtr, WidthOfScreen(Tk_Screen(tkwin))); - break; + name = Tk_GetAtomName(tkwin, (Atom) id); + if (strcmp(name, "?bad atom?") == 0) { + string = Tcl_GetString(objv[2]); + Tcl_AppendStringsToObj(resultPtr, + "no atom exists with id \"", string, "\"", NULL); + return TCL_ERROR; } - case WIN_SCREENMMHEIGHT: { - Tcl_SetIntObj(resultPtr, HeightMMOfScreen(Tk_Screen(tkwin))); - break; + Tcl_SetStringObj(resultPtr, name, -1); + break; + } + case WIN_CONTAINING: + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case WIN_SCREENMMWIDTH: { - Tcl_SetIntObj(resultPtr, WidthMMOfScreen(Tk_Screen(tkwin))); - break; + if (objc - skip != 4) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-displayof window? rootX rootY"); + return TCL_ERROR; } - case WIN_SCREENVISUAL: { - class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class; - goto visual; + objv += skip; + string = Tcl_GetString(objv[2]); + if (Tk_GetPixels(interp, tkwin, string, &x) != TCL_OK) { + return TCL_ERROR; } - case WIN_SERVER: { - TkGetServerInfo(interp, tkwin); - break; + string = Tcl_GetString(objv[3]); + if (Tk_GetPixels(interp, tkwin, string, &y) != TCL_OK) { + return TCL_ERROR; } - case WIN_TOPLEVEL: { - winPtr = GetToplevel(tkwin); - if (winPtr != NULL) { - Tcl_SetStringObj(resultPtr, winPtr->pathName, -1); - } - break; + tkwin = Tk_CoordsToWindow(x, y, tkwin); + if (tkwin != NULL) { + Tcl_SetStringObj(resultPtr, Tk_PathName(tkwin), -1); } - case WIN_VIEWABLE: { - int viewable = 0; - for ( ; ; winPtr = winPtr->parentPtr) { - if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) { - break; - } - if (winPtr->flags & TK_TOP_HIERARCHY) { - viewable = 1; - break; - } - } + break; + case WIN_INTERPS: { + int result; - Tcl_SetBooleanObj(resultPtr, viewable); - break; + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case WIN_VISUAL: { - class = Tk_Visual(tkwin)->class; - - visual: - string = TkFindStateString(visualMap, class); - if (string == NULL) { - string = "unknown"; - } - Tcl_SetStringObj(resultPtr, string, -1); - break; + if (objc - skip != 2) { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?"); + return TCL_ERROR; } - case WIN_VISUALID: { - char buf[TCL_INTEGER_SPACE]; + result = TkGetInterpNames(interp, tkwin); + return result; + } + case WIN_PATHNAME: { + Window id; - sprintf(buf, "0x%x", - (unsigned int) XVisualIDFromVisual(Tk_Visual(tkwin))); - Tcl_SetStringObj(resultPtr, buf, -1); - break; - } - case WIN_VROOTHEIGHT: { - Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetIntObj(resultPtr, height); - break; - } - case WIN_VROOTWIDTH: { - Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetIntObj(resultPtr, width); - break; - } - case WIN_VROOTX: { - Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetIntObj(resultPtr, x); - break; - } - case WIN_VROOTY: { - Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height); - Tcl_SetIntObj(resultPtr, y); - break; + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case WIN_WIDTH: { - Tcl_SetIntObj(resultPtr, Tk_Width(tkwin)); - break; + if (objc - skip != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id"); + return TCL_ERROR; } - case WIN_X: { - Tcl_SetIntObj(resultPtr, Tk_X(tkwin)); - break; + string = Tcl_GetString(objv[2 + skip]); + if (TkpScanWindowId(interp, string, &id) != TCL_OK) { + return TCL_ERROR; } - case WIN_Y: { - Tcl_SetIntObj(resultPtr, Tk_Y(tkwin)); - break; + winPtr = (TkWindow *)Tk_IdToWindow(Tk_Display(tkwin), id); + if ((winPtr == NULL) || + (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) { + Tcl_AppendStringsToObj(resultPtr, "window id \"", string, + "\" doesn't exist in this application", NULL); + return TCL_ERROR; } /* - * Uses -displayof. + * If the window is a utility window with no associated path (such as + * a wrapper window or send communication window), just return an + * empty string. */ - - case WIN_ATOM: { - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? name"); - return TCL_ERROR; - } - objv += skip; - string = Tcl_GetStringFromObj(objv[2], NULL); - Tcl_SetLongObj(resultPtr, (long) Tk_InternAtom(tkwin, string)); - break; - } - case WIN_ATOMNAME: { - CONST char *name; - long id; - - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id"); - return TCL_ERROR; - } - objv += skip; - if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) { - return TCL_ERROR; - } - name = Tk_GetAtomName(tkwin, (Atom) id); - if (strcmp(name, "?bad atom?") == 0) { - string = Tcl_GetStringFromObj(objv[2], NULL); - Tcl_AppendStringsToObj(resultPtr, - "no atom exists with id \"", string, "\"", NULL); - return TCL_ERROR; - } - Tcl_SetStringObj(resultPtr, name, -1); - break; - } - case WIN_CONTAINING: { - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "?-displayof window? rootX rootY"); - return TCL_ERROR; - } - objv += skip; - string = Tcl_GetStringFromObj(objv[2], NULL); - if (Tk_GetPixels(interp, tkwin, string, &x) != TCL_OK) { - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[3], NULL); - if (Tk_GetPixels(interp, tkwin, string, &y) != TCL_OK) { - return TCL_ERROR; - } - tkwin = Tk_CoordsToWindow(x, y, tkwin); - if (tkwin != NULL) { - Tcl_SetStringObj(resultPtr, Tk_PathName(tkwin), -1); - } - break; - } - case WIN_INTERPS: { - int result; - - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 2) { - Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?"); - return TCL_ERROR; - } - result = TkGetInterpNames(interp, tkwin); - return result; - } - case WIN_PATHNAME: { - Window id; - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id"); - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[2 + skip], NULL); - if (TkpScanWindowId(interp, string, &id) != TCL_OK) { - return TCL_ERROR; - } - winPtr = (TkWindow *)Tk_IdToWindow(Tk_Display(tkwin), id); - if ((winPtr == NULL) || - (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) { - Tcl_AppendStringsToObj(resultPtr, "window id \"", string, - "\" doesn't exist in this application", (char *) NULL); - return TCL_ERROR; - } - - /* - * If the window is a utility window with no associated path - * (such as a wrapper window or send communication window), just - * return an empty string. - */ - - tkwin = (Tk_Window) winPtr; - if (Tk_PathName(tkwin) != NULL) { - Tcl_SetStringObj(resultPtr, Tk_PathName(tkwin), -1); - } - break; + tkwin = (Tk_Window) winPtr; + if (Tk_PathName(tkwin) != NULL) { + Tcl_SetStringObj(resultPtr, Tk_PathName(tkwin), -1); } + break; + } /* * objv[3] is window. */ - case WIN_EXISTS: { - int alive; + case WIN_EXISTS: { + int alive; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "window"); - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[2], NULL); - winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin); - Tcl_ResetResult(interp); - resultPtr = Tcl_GetObjResult(interp); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + string = Tcl_GetString(objv[2]); + winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin); + Tcl_ResetResult(interp); + resultPtr = Tcl_GetObjResult(interp); - alive = 1; - if ((winPtr == NULL) || (winPtr->flags & TK_ALREADY_DEAD)) { - alive = 0; - } - Tcl_SetBooleanObj(resultPtr, alive); - break; + alive = 1; + if ((winPtr == NULL) || (winPtr->flags & TK_ALREADY_DEAD)) { + alive = 0; } - case WIN_FPIXELS: { - double mm, pixels; + Tcl_SetBooleanObj(resultPtr, alive); + break; + } + case WIN_FPIXELS: { + double mm, pixels; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "window number"); - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[2], NULL); - tkwin = Tk_NameToWindow(interp, string, tkwin); - if (tkwin == NULL) { - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[3], NULL); - if (Tk_GetScreenMM(interp, tkwin, string, &mm) != TCL_OK) { - return TCL_ERROR; - } - pixels = mm * WidthOfScreen(Tk_Screen(tkwin)) - / WidthMMOfScreen(Tk_Screen(tkwin)); - Tcl_SetDoubleObj(resultPtr, pixels); - break; + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window number"); + return TCL_ERROR; } - case WIN_PIXELS: { - int pixels; - - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "window number"); - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[2], NULL); - tkwin = Tk_NameToWindow(interp, string, tkwin); - if (tkwin == NULL) { - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[3], NULL); - if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) { - return TCL_ERROR; - } - Tcl_SetIntObj(resultPtr, pixels); - break; + string = Tcl_GetString(objv[2]); + tkwin = Tk_NameToWindow(interp, string, tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + string = Tcl_GetString(objv[3]); + if (Tk_GetScreenMM(interp, tkwin, string, &mm) != TCL_OK) { + return TCL_ERROR; } - case WIN_RGB: { - XColor *colorPtr; - char buf[TCL_INTEGER_SPACE * 3]; + pixels = mm * WidthOfScreen(Tk_Screen(tkwin)) + / WidthMMOfScreen(Tk_Screen(tkwin)); + Tcl_SetDoubleObj(resultPtr, pixels); + break; + } + case WIN_PIXELS: { + int pixels; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "window colorName"); - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[2], NULL); - tkwin = Tk_NameToWindow(interp, string, tkwin); - if (tkwin == NULL) { - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[3], NULL); - colorPtr = Tk_GetColor(interp, tkwin, string); - if (colorPtr == NULL) { - return TCL_ERROR; - } - sprintf(buf, "%d %d %d", colorPtr->red, colorPtr->green, - colorPtr->blue); - Tk_FreeColor(colorPtr); - Tcl_SetStringObj(resultPtr, buf, -1); - break; + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window number"); + return TCL_ERROR; } - case WIN_VISUALSAVAILABLE: { - XVisualInfo template, *visInfoPtr; - int count, i; - int includeVisualId; - Tcl_Obj *strPtr; - char buf[16 + TCL_INTEGER_SPACE]; - char visualIdString[TCL_INTEGER_SPACE]; - - if (objc == 3) { - includeVisualId = 0; - } else if ((objc == 4) - && (strcmp(Tcl_GetStringFromObj(objv[3], NULL), - "includeids") == 0)) { - includeVisualId = 1; - } else { - Tcl_WrongNumArgs(interp, 2, objv, "window ?includeids?"); - return TCL_ERROR; - } + string = Tcl_GetString(objv[2]); + tkwin = Tk_NameToWindow(interp, string, tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + string = Tcl_GetString(objv[3]); + if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetIntObj(resultPtr, pixels); + break; + } + case WIN_RGB: { + XColor *colorPtr; + char buf[TCL_INTEGER_SPACE * 3]; - string = Tcl_GetStringFromObj(objv[2], NULL); - tkwin = Tk_NameToWindow(interp, string, tkwin); - if (tkwin == NULL) { - return TCL_ERROR; - } + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window colorName"); + return TCL_ERROR; + } + string = Tcl_GetString(objv[2]); + tkwin = Tk_NameToWindow(interp, string, tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + string = Tcl_GetString(objv[3]); + colorPtr = Tk_GetColor(interp, tkwin, string); + if (colorPtr == NULL) { + return TCL_ERROR; + } + sprintf(buf, "%d %d %d", colorPtr->red, colorPtr->green, + colorPtr->blue); + Tk_FreeColor(colorPtr); + Tcl_SetStringObj(resultPtr, buf, -1); + break; + } + case WIN_VISUALSAVAILABLE: { + XVisualInfo template, *visInfoPtr; + int count, i; + int includeVisualId; + Tcl_Obj *strPtr; + char buf[16 + TCL_INTEGER_SPACE]; + char visualIdString[TCL_INTEGER_SPACE]; + + if (objc == 3) { + includeVisualId = 0; + } else if ((objc == 4) + && (strcmp(Tcl_GetString(objv[3]), "includeids") == 0)) { + includeVisualId = 1; + } else { + Tcl_WrongNumArgs(interp, 2, objv, "window ?includeids?"); + return TCL_ERROR; + } - template.screen = Tk_ScreenNumber(tkwin); - visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask, - &template, &count); - if (visInfoPtr == NULL) { - Tcl_SetStringObj(resultPtr, - "can't find any visuals for screen", -1); - return TCL_ERROR; + string = Tcl_GetString(objv[2]); + tkwin = Tk_NameToWindow(interp, string, tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + + template.screen = Tk_ScreenNumber(tkwin); + visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask, + &template, &count); + if (visInfoPtr == NULL) { + Tcl_SetStringObj(resultPtr, + "can't find any visuals for screen", -1); + return TCL_ERROR; + } + for (i = 0; i < count; i++) { + string = TkFindStateString(visualMap, visInfoPtr[i].class); + if (string == NULL) { + strcpy(buf, "unknown"); + } else { + sprintf(buf, "%s %d", string, visInfoPtr[i].depth); } - for (i = 0; i < count; i++) { - string = TkFindStateString(visualMap, visInfoPtr[i].class); - if (string == NULL) { - strcpy(buf, "unknown"); - } else { - sprintf(buf, "%s %d", string, visInfoPtr[i].depth); - } - if (includeVisualId) { - sprintf(visualIdString, " 0x%x", - (unsigned int) visInfoPtr[i].visualid); - strcat(buf, visualIdString); - } - strPtr = Tcl_NewStringObj(buf, -1); - Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); + if (includeVisualId) { + sprintf(visualIdString, " 0x%x", + (unsigned int) visInfoPtr[i].visualid); + strcat(buf, visualIdString); } - XFree((char *) visInfoPtr); - break; + strPtr = Tcl_NewStringObj(buf, -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); } + XFree((char *) visInfoPtr); + break; + } } return TCL_OK; } @@ -1700,8 +1700,8 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) * * Tk_WmObjCmd -- * - * This procedure is invoked to process the "wm" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "wm" Tcl command. See the user + * documentation for details on what it does. * * Results: * A standard Tcl result. @@ -1714,24 +1714,23 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ int -Tk_WmObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_WmObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window tkwin; TkWindow *winPtr; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "aspect", "client", "command", "deiconify", "focusmodel", "frame", "geometry", "grid", "group", "iconbitmap", "iconify", "iconmask", "iconname", "iconposition", "iconwindow", "maxsize", "minsize", "overrideredirect", "positionfrom", "protocol", "resizable", "sizefrom", "state", "title", - "tracing", "transient", "withdraw", (char *) NULL + "tracing", "transient", "withdraw", NULL }; enum options { TKWM_ASPECT, TKWM_CLIENT, TKWM_COMMAND, TKWM_DEICONIFY, @@ -1790,127 +1789,119 @@ Tk_WmObjCmd(clientData, interp, objc, objv) } if (!(winPtr->flags & TK_TOP_LEVEL)) { Tcl_AppendResult(interp, "window \"", winPtr->pathName, - "\" isn't a top-level window", (char *) NULL); + "\" isn't a top-level window", NULL); return TCL_ERROR; } switch ((enum options) index) { - case TKWM_ASPECT: { - TkpWmAspectCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_CLIENT: { - TkpWmClientCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_COMMAND: { - TkpWmCommandCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_DEICONIFY: { - TkpWmDeiconifyCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_FOCUSMOD: { - TkpWmFocusmodCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_FRAME: { - TkpWmFrameCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_GEOMETRY: { - TkpWmGeometryCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_GRID: { - TkpWmGridCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_GROUP: { - TkpWmGroupCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_ICONBMP: { - TkpWmIconbitmapCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_ICONIFY: { - TkpWmIconifyCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_ICONMASK: { - TkpWmIconmaskCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_ICONNAME: { - /* slight Unix variation */ - TkpWmIconnameCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_ICONPOS: { - /* nearly same - 1 line more on Unix */ - TkpWmIconpositionCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_ICONWIN: { - TkpWmIconwindowCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_MAXSIZE: { - /* nearly same, win diffs */ - TkpWmMaxsizeCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_MINSIZE: { - /* nearly same, win diffs */ - TkpWmMinsizeCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_OVERRIDE: { - /* almost same */ - TkpWmOverrideCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_POSFROM: { - /* Equal across platforms */ - TkpWmPositionfromCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_PROTOCOL: { - /* Equal across platforms */ - TkpWmProtocolCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_RESIZABLE: { - /* almost same */ - TkpWmResizableCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_SIZEFROM: { - /* Equal across platforms */ - TkpWmSizefromCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_STATE: { - TkpWmStateCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_TITLE: { - TkpWmTitleCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_TRANSIENT: { - TkpWmTransientCmd(interp, tkwin, winPtr, objc, objv); - break; - } - case TKWM_WITHDRAW: { - TkpWmWithdrawCmd(interp, tkwin, winPtr, objc, objv); - break; - } + case TKWM_ASPECT: + TkpWmAspectCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_CLIENT: + TkpWmClientCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_COMMAND: + TkpWmCommandCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_DEICONIFY: + TkpWmDeiconifyCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_FOCUSMOD: + TkpWmFocusmodCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_FRAME: + TkpWmFrameCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_GEOMETRY: + TkpWmGeometryCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_GRID: + TkpWmGridCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_GROUP: + TkpWmGroupCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_ICONBMP: + TkpWmIconbitmapCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_ICONIFY: + TkpWmIconifyCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_ICONMASK: + TkpWmIconmaskCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_ICONNAME: + /* + * Slight Unix variation. + */ + TkpWmIconnameCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_ICONPOS: + /* + * nearly same - 1 line more on Unix. + */ + TkpWmIconpositionCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_ICONWIN: + TkpWmIconwindowCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_MAXSIZE: + /* + * Nearly same, win diffs. + */ + TkpWmMaxsizeCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_MINSIZE: + /* + * Nearly same, win diffs + */ + TkpWmMinsizeCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_OVERRIDE: + /* + * Almost same. + */ + TkpWmOverrideCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_POSFROM: + /* + * Equal across platforms + */ + TkpWmPositionfromCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_PROTOCOL: + /* + * Equal across platforms + */ + TkpWmProtocolCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_RESIZABLE: + /* + * Almost same + */ + TkpWmResizableCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_SIZEFROM: + /* + * Equal across platforms + */ + TkpWmSizefromCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_STATE: + TkpWmStateCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_TITLE: + TkpWmTitleCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_TRANSIENT: + TkpWmTransientCmd(interp, tkwin, winPtr, objc, objv); + break; + case TKWM_WITHDRAW: + TkpWmWithdrawCmd(interp, tkwin, winPtr, objc, objv); + break; } - updateGeom: + updateGeom: if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); wmPtr->flags |= WM_UPDATE_PENDING; @@ -1924,21 +1915,20 @@ Tk_WmObjCmd(clientData, interp, objc, objv) * * TkGetDisplayOf -- * - * Parses a "-displayof window" option for various commands. If - * present, the literal "-displayof" should be in objv[0] and the - * window name in objv[1]. + * Parses a "-displayof window" option for various commands. If present, + * the literal "-displayof" should be in objv[0] and the window name in + * objv[1]. * * Results: - * The return value is 0 if the argument strings did not contain - * the "-displayof" option. The return value is 2 if the - * argument strings contained both the "-displayof" option and - * a valid window name. Otherwise, the return value is -1 if - * the window name was missing or did not specify a valid window. + * The return value is 0 if the argument strings did not contain the + * "-displayof" option. The return value is 2 if the argument strings + * contained both the "-displayof" option and a valid window name. + * Otherwise, the return value is -1 if the window name was missing or + * did not specify a valid window. * - * If the return value was 2, *tkwinPtr is filled with the - * token for the window specified on the command line. If the - * return value was -1, an error message is left in interp's - * result object. + * If the return value was 2, *tkwinPtr is filled with the token for the + * window specified on the command line. If the return value was -1, an + * error message is left in interp's result object. * * Side effects: * None. @@ -1947,14 +1937,14 @@ Tk_WmObjCmd(clientData, interp, objc, objv) */ int -TkGetDisplayOf(interp, objc, objv, tkwinPtr) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. If it is present, +TkGetDisplayOf( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[], /* Argument objects. If it is present, * "-displayof" should be in objv[0] and * objv[1] the name of a window. */ - Tk_Window *tkwinPtr; /* On input, contains main window of - * application associated with interp. On + Tk_Window *tkwinPtr) /* On input, contains main window of + * application associated with interp. On * output, filled with window specified as * option to "-displayof" argument, or * unmodified if "-displayof" argument was not @@ -1962,7 +1952,7 @@ TkGetDisplayOf(interp, objc, objv, tkwinPtr) { char *string; int length; - + if (objc < 1) { return 0; } @@ -1974,8 +1964,7 @@ TkGetDisplayOf(interp, objc, objv, tkwinPtr) "value for \"-displayof\" missing", -1); return -1; } - string = Tcl_GetStringFromObj(objv[1], NULL); - *tkwinPtr = Tk_NameToWindow(interp, string, *tkwinPtr); + *tkwinPtr = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), *tkwinPtr); if (*tkwinPtr == NULL) { return -1; } @@ -1990,11 +1979,11 @@ TkGetDisplayOf(interp, objc, objv, tkwinPtr) * TkDeadAppCmd -- * * If an application has been deleted then all Tk commands will be - * re-bound to this procedure. + * re-bound to this function. * * Results: - * A standard Tcl error is reported to let the user know that - * the application is dead. + * A standard Tcl error is reported to let the user know that the + * application is dead. * * Side effects: * See the user documentation. @@ -2004,28 +1993,28 @@ TkGetDisplayOf(interp, objc, objv, tkwinPtr) /* ARGSUSED */ int -TkDeadAppCmd(clientData, interp, argc, argv) - ClientData clientData; /* Dummy. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TkDeadAppCmd( + ClientData clientData, /* Dummy. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + const char **argv) /* Argument strings. */ { Tcl_AppendResult(interp, "can't invoke \"", argv[0], - "\" command: application has been destroyed", (char *) NULL); + "\" command: application has been destroyed", NULL); return TCL_ERROR; } /* *---------------------------------------------------------------------- * - * GetToplevel -- + * GetTopHierarchy -- * - * Retrieves the toplevel window which is the nearest ancestor of - * of the specified window. + * Retrieves the top-of-hierarchy window which is the nearest ancestor of + * the specified window. * * Results: - * Returns the toplevel window or NULL if the window has no - * ancestor which is a toplevel. + * Returns the top-of-hierarchy window, or NULL if the window has no + * ancestor which is at the top of a physical window hierarchy. * * Side effects: * None. @@ -2034,17 +2023,22 @@ TkDeadAppCmd(clientData, interp, argc, argv) */ static TkWindow * -GetToplevel(tkwin) - Tk_Window tkwin; /* Window for which the toplevel should be - * deterined. */ +GetTopHierarchy( + Tk_Window tkwin) /* Window for which the top-of-hierarchy + * ancestor should be deterined. */ { - TkWindow *winPtr = (TkWindow *) tkwin; - - while (!(winPtr->flags & TK_TOP_LEVEL)) { - winPtr = winPtr->parentPtr; - if (winPtr == NULL) { - return NULL; - } - } - return winPtr; + TkWindow *winPtr = (TkWindow *) tkwin; + + while ((winPtr != NULL) && !(winPtr->flags & TK_TOP_HIERARCHY)) { + winPtr = winPtr->parentPtr; + } + return winPtr; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkColor.c b/generic/tkColor.c index a5a1136..1111c51 100755..100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -1,21 +1,22 @@ -/* +/* * tkColor.c -- * - * This file maintains a database of color values for the Tk - * toolkit, in order to avoid round-trips to the server to - * map color names to pixel values. + * This file maintains a database of color values for the Tk toolkit, in + * order to avoid round-trips to the server to map color names to pixel + * values. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkColor.h" /* - * Structures of the following following type are used as keys for + * Structures of the following following type are used as keys for * colorValueTable (in TkDisplay). */ @@ -26,30 +27,28 @@ typedef struct { Display *display; /* Display for colormap. */ } ValueKey; - /* - * The structure below is used to allocate thread-local data. + * The structure below is used to allocate thread-local data. */ typedef struct ThreadSpecificData { - char rgbString[20]; /* */ + char rgbString[20]; /* */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static void ColorInit _ANSI_ARGS_((TkDisplay *dispPtr)); -static void DupColorObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, - Tcl_Obj *dupObjPtr)); -static void FreeColorObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); -static void InitColorObj _ANSI_ARGS_((Tcl_Obj *objPtr)); +static void ColorInit(TkDisplay *dispPtr); +static void DupColorObjProc(Tcl_Obj *srcObjPtr,Tcl_Obj *dupObjPtr); +static void FreeColorObjProc(Tcl_Obj *objPtr); +static void InitColorObj(Tcl_Obj *objPtr); /* * The following structure defines the implementation of the "color" Tcl - * object, which maps a string color name to a TkColor object. The - * ptr1 field of the Tcl_Obj points to a TkColor object. + * object, which maps a string color name to a TkColor object. The ptr1 field + * of the Tcl_Obj points to a TkColor object. */ Tcl_ObjType tkColorObjType = { @@ -65,32 +64,31 @@ Tcl_ObjType tkColorObjType = { * * Tk_AllocColorFromObj -- * - * Given a Tcl_Obj *, map the value to a corresponding - * XColor structure based on the tkwin given. + * Given a Tcl_Obj *, map the value to a corresponding XColor structure + * based on the tkwin given. * * Results: - * The return value is a pointer to an XColor structure that - * indicates the red, blue, and green intensities for the color - * given by the string in objPtr, and also specifies a pixel value - * to use to draw in that color. If an error occurs, NULL is - * returned and an error message will be left in interp's result - * (unless interp is NULL). + * The return value is a pointer to an XColor structure that indicates + * the red, blue, and green intensities for the color given by the string + * in objPtr, and also specifies a pixel value to use to draw in that + * color. If an error occurs, NULL is returned and an error message will + * be left in interp's result (unless interp is NULL). * * Side effects: - * The color is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeColorFromObj so that the database is cleaned up when colors + * The color is added to an internal database with a reference count. For + * each call to this function, there should eventually be a call to + * Tk_FreeColorFromObj so that the database is cleaned up when colors * aren't in use anymore. * *---------------------------------------------------------------------- */ XColor * -Tk_AllocColorFromObj(interp, tkwin, objPtr) - Tcl_Interp *interp; /* Used only for error reporting. If NULL, +Tk_AllocColorFromObj( + Tcl_Interp *interp, /* Used only for error reporting. If NULL, * then no messages are provided. */ - Tk_Window tkwin; /* Window in which the color will be used.*/ - Tcl_Obj *objPtr; /* Object that describes the color; string + Tk_Window tkwin, /* Window in which the color will be used.*/ + Tcl_Obj *objPtr) /* Object that describes the color; string * value is a color name such as "red" or * "#ff0000".*/ { @@ -102,15 +100,15 @@ Tk_AllocColorFromObj(interp, tkwin, objPtr) tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1; /* - * If the object currently points to a TkColor, see if it's the - * one we want. If so, increment its reference count and return. + * If the object currently points to a TkColor, see if it's the one we + * want. If so, increment its reference count and return. */ if (tkColPtr != NULL) { if (tkColPtr->resourceRefCount == 0) { /* - * This is a stale reference: it refers to a TkColor that's - * no longer in use. Clear the reference. + * This is a stale reference: it refers to a TkColor that's no + * longer in use. Clear the reference. */ FreeColorObjProc(objPtr); @@ -123,14 +121,14 @@ Tk_AllocColorFromObj(interp, tkwin, objPtr) } /* - * The object didn't point to the TkColor that we wanted. Search - * the list of TkColors with the same name to see if one of the - * other TkColors is the right one. + * The object didn't point to the TkColor that we wanted. Search the list + * of TkColors with the same name to see if one of the other TkColors is + * the right one. */ if (tkColPtr != NULL) { - TkColor *firstColorPtr = - (TkColor *) Tcl_GetHashValue(tkColPtr->hashPtr); + TkColor *firstColorPtr = Tcl_GetHashValue(tkColPtr->hashPtr); + FreeColorObjProc(objPtr); for (tkColPtr = firstColorPtr; tkColPtr != NULL; tkColPtr = tkColPtr->nextPtr) { @@ -138,18 +136,18 @@ Tk_AllocColorFromObj(interp, tkwin, objPtr) && (Tk_Colormap(tkwin) == tkColPtr->colormap)) { tkColPtr->resourceRefCount++; tkColPtr->objRefCount++; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) tkColPtr; return (XColor *) tkColPtr; } } } /* - * Still no luck. Call Tk_GetColor to allocate a new TkColor object. + * Still no luck. Call Tk_GetColor to allocate a new TkColor object. */ tkColPtr = (TkColor *) Tk_GetColor(interp, tkwin, Tcl_GetString(objPtr)); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) tkColPtr; if (tkColPtr != NULL) { tkColPtr->objRefCount++; } @@ -165,31 +163,31 @@ Tk_AllocColorFromObj(interp, tkwin, objPtr) * XColor structure. * * Results: - * The return value is a pointer to an XColor structure that - * indicates the red, blue, and green intensities for the color - * given by "name", and also specifies a pixel value to use to - * draw in that color. If an error occurs, NULL is returned and - * an error message will be left in the interp's result. + * The return value is a pointer to an XColor structure that indicates + * the red, blue, and green intensities for the color given by "name", + * and also specifies a pixel value to use to draw in that color. If an + * error occurs, NULL is returned and an error message will be left in + * the interp's result. * * Side effects: - * The color is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeColor so that the database is cleaned up when colors - * aren't in use anymore. + * The color is added to an internal database with a reference count. For + * each call to this function, there should eventually be a call to + * Tk_FreeColor so that the database is cleaned up when colors aren't in + * use anymore. * *---------------------------------------------------------------------- */ XColor * -Tk_GetColor(interp, tkwin, name) - Tcl_Interp *interp; /* Place to leave error message if - * color can't be found. */ - Tk_Window tkwin; /* Window in which color will be used. */ - Tk_Uid name; /* Name of color to be allocated (in form +Tk_GetColor( + Tcl_Interp *interp, /* Place to leave error message if color can't + * be found. */ + Tk_Window tkwin, /* Window in which color will be used. */ + Tk_Uid name) /* Name of color to be allocated (in form * suitable for passing to XParseColor). */ { Tcl_HashEntry *nameHashPtr; - int new; + int isNew; TkColor *tkColPtr; TkColor *existingColPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -199,14 +197,13 @@ Tk_GetColor(interp, tkwin, name) } /* - * First, check to see if there's already a mapping for this color - * name. + * First, check to see if there's already a mapping for this color name. */ - nameHashPtr = Tcl_CreateHashEntry(&dispPtr->colorNameTable, name, &new); - if (!new) { - existingColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr); - for (tkColPtr = existingColPtr; tkColPtr != NULL; + nameHashPtr = Tcl_CreateHashEntry(&dispPtr->colorNameTable, name, &isNew); + if (!isNew) { + existingColPtr = Tcl_GetHashValue(nameHashPtr); + for (tkColPtr = existingColPtr; tkColPtr != NULL; tkColPtr = tkColPtr->nextPtr) { if ((tkColPtr->screen == Tk_Screen(tkwin)) && (Tk_Colormap(tkwin) == tkColPtr->colormap)) { @@ -219,8 +216,7 @@ Tk_GetColor(interp, tkwin, name) } /* - * The name isn't currently known. Map from the name to a pixel - * value. + * The name isn't currently known. Map from the name to a pixel value. */ tkColPtr = TkpGetColor(tkwin, name); @@ -228,28 +224,28 @@ Tk_GetColor(interp, tkwin, name) if (interp != NULL) { if (*name == '#') { Tcl_AppendResult(interp, "invalid color name \"", name, - "\"", (char *) NULL); + "\"", NULL); } else { Tcl_AppendResult(interp, "unknown color name \"", name, - "\"", (char *) NULL); + "\"", NULL); } } - if (new) { + if (isNew) { Tcl_DeleteHashEntry(nameHashPtr); } - return (XColor *) NULL; + return NULL; } /* - * Now create a new TkColor structure and add it to colorNameTable - * (in TkDisplay). + * Now create a new TkColor structure and add it to colorNameTable (in + * TkDisplay). */ tkColPtr->magic = COLOR_MAGIC; tkColPtr->gc = None; tkColPtr->screen = Tk_Screen(tkwin); tkColPtr->colormap = Tk_Colormap(tkwin); - tkColPtr->visual = Tk_Visual(tkwin); + tkColPtr->visual = Tk_Visual(tkwin); tkColPtr->resourceRefCount = 1; tkColPtr->objRefCount = 0; tkColPtr->type = TK_COLOR_BY_NAME; @@ -265,34 +261,33 @@ Tk_GetColor(interp, tkwin, name) * * Tk_GetColorByValue -- * - * Given a desired set of red-green-blue intensities for a color, - * locate a pixel value to use to draw that color in a given - * window. + * Given a desired set of red-green-blue intensities for a color, locate + * a pixel value to use to draw that color in a given window. * * Results: - * The return value is a pointer to an XColor structure that - * indicates the closest red, blue, and green intensities available - * to those specified in colorPtr, and also specifies a pixel - * value to use to draw in that color. + * The return value is a pointer to an XColor structure that indicates + * the closest red, blue, and green intensities available to those + * specified in colorPtr, and also specifies a pixel value to use to draw + * in that color. * * Side effects: - * The color is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeColor, so that the database is cleaned up when colors - * aren't in use anymore. + * The color is added to an internal database with a reference count. For + * each call to this function, there should eventually be a call to + * Tk_FreeColor, so that the database is cleaned up when colors aren't in + * use anymore. * *---------------------------------------------------------------------- */ XColor * -Tk_GetColorByValue(tkwin, colorPtr) - Tk_Window tkwin; /* Window where color will be used. */ - XColor *colorPtr; /* Red, green, and blue fields indicate +Tk_GetColorByValue( + Tk_Window tkwin, /* Window where color will be used. */ + XColor *colorPtr) /* Red, green, and blue fields indicate * desired color. */ { ValueKey valueKey; Tcl_HashEntry *valueHashPtr; - int new; + int isNew; TkColor *tkColPtr; Display *display = Tk_Display(tkwin); TkDisplay *dispPtr = TkGetDisplay(display); @@ -302,26 +297,28 @@ Tk_GetColorByValue(tkwin, colorPtr) } /* - * First, check to see if there's already a mapping for this color - * name. + * First, check to see if there's already a mapping for this color name. + * Must clear the structure first; it's not tightly packed on 64-bit + * systems. [Bug 2911570] */ + memset(&valueKey, 0, sizeof(ValueKey)); valueKey.red = colorPtr->red; valueKey.green = colorPtr->green; valueKey.blue = colorPtr->blue; valueKey.colormap = Tk_Colormap(tkwin); valueKey.display = display; - valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable, - (char *) &valueKey, &new); - if (!new) { - tkColPtr = (TkColor *) Tcl_GetHashValue(valueHashPtr); + valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable, + (char *) &valueKey, &isNew); + if (!isNew) { + tkColPtr = Tcl_GetHashValue(valueHashPtr); tkColPtr->resourceRefCount++; return &tkColPtr->color; } /* - * The name isn't currently known. Find a pixel value for this - * color and add a new structure to colorValueTable (in TkDisplay). + * The name isn't currently known. Find a pixel value for this color and + * add a new structure to colorValueTable (in TkDisplay). */ tkColPtr = TkpGetColorByValue(tkwin, colorPtr); @@ -329,7 +326,7 @@ Tk_GetColorByValue(tkwin, colorPtr) tkColPtr->gc = None; tkColPtr->screen = Tk_Screen(tkwin); tkColPtr->colormap = valueKey.colormap; - tkColPtr->visual = Tk_Visual(tkwin); + tkColPtr->visual = Tk_Visual(tkwin); tkColPtr->resourceRefCount = 1; tkColPtr->objRefCount = 0; tkColPtr->type = TK_COLOR_BY_VALUE; @@ -344,16 +341,14 @@ Tk_GetColorByValue(tkwin, colorPtr) * * Tk_NameOfColor -- * - * Given a color, return a textual string identifying - * the color. + * Given a color, return a textual string identifying the color. * * Results: - * If colorPtr was created by Tk_GetColor, then the return - * value is the "string" that was used to create it. - * Otherwise the return value is a string that could have - * been passed to Tk_GetColor to allocate that color. The - * storage for the returned string is only guaranteed to - * persist up until the next call to this procedure. + * If colorPtr was created by Tk_GetColor, then the return value is the + * "string" that was used to create it. Otherwise the return value is a + * string that could have been passed to Tk_GetColor to allocate that + * color. The storage for the returned string is only guaranteed to + * persist up until the next call to this function. * * Side effects: * None. @@ -362,18 +357,18 @@ Tk_GetColorByValue(tkwin, colorPtr) */ CONST char * -Tk_NameOfColor(colorPtr) - XColor *colorPtr; /* Color whose name is desired. */ +Tk_NameOfColor( + XColor *colorPtr) /* Color whose name is desired. */ { register TkColor *tkColPtr = (TkColor *) colorPtr; - - if ((tkColPtr->magic == COLOR_MAGIC) && - (tkColPtr->type == TK_COLOR_BY_NAME)) { + + if (tkColPtr->magic==COLOR_MAGIC && tkColPtr->type==TK_COLOR_BY_NAME) { return tkColPtr->hashPtr->key.string; } else { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red, + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red, colorPtr->green, colorPtr->blue); return tsdPtr->rgbString; } @@ -384,15 +379,14 @@ Tk_NameOfColor(colorPtr) * * Tk_GCForColor -- * - * Given a color allocated from this module, this procedure - * returns a GC that can be used for simple drawing with that - * color. + * Given a color allocated from this module, this function returns a GC + * that can be used for simple drawing with that color. * * Results: - * The return value is a GC with color set as its foreground - * color and all other fields defaulted. This GC is only valid - * as long as the color exists; it is freed automatically when - * the last reference to the color is freed. + * The return value is a GC with color set as its foreground color and + * all other fields defaulted. This GC is only valid as long as the color + * exists; it is freed automatically when the last reference to the color + * is freed. * * Side effects: * None. @@ -401,24 +395,23 @@ Tk_NameOfColor(colorPtr) */ GC -Tk_GCForColor(colorPtr, drawable) - XColor *colorPtr; /* Color for which a GC is desired. Must - * have been allocated by Tk_GetColor. */ - Drawable drawable; /* Drawable in which the color will be - * used (must have same screen and depth - * as the one for which the color was - * allocated). */ +Tk_GCForColor( + XColor *colorPtr, /* Color for which a GC is desired. Must have + * been allocated by Tk_GetColor. */ + Drawable drawable) /* Drawable in which the color will be used + * (must have same screen and depth as the one + * for which the color was allocated). */ { TkColor *tkColPtr = (TkColor *) colorPtr; XGCValues gcValues; /* - * Do a quick sanity check to make sure this color was really - * allocated by Tk_GetColor. + * Do a quick sanity check to make sure this color was really allocated by + * Tk_GetColor. */ if (tkColPtr->magic != COLOR_MAGIC) { - panic("Tk_GCForColor called with bogus color"); + Tcl_Panic("Tk_GCForColor called with bogus color"); } if (tkColPtr->gc == None) { @@ -434,23 +427,21 @@ Tk_GCForColor(colorPtr, drawable) * * Tk_FreeColor -- * - * This procedure is called to release a color allocated by - * Tk_GetColor. + * This function is called to release a color allocated by Tk_GetColor. * * Results: * None. * * Side effects: - * The reference count associated with colorPtr is deleted, and - * the color is released to X if there are no remaining uses - * for it. + * The reference count associated with colorPtr is deleted, and the color + * is released to X if there are no remaining uses for it. * *---------------------------------------------------------------------- */ void -Tk_FreeColor(colorPtr) - XColor *colorPtr; /* Color to be released. Must have been +Tk_FreeColor( + XColor *colorPtr) /* Color to be released. Must have been * allocated by Tk_GetColor or * Tk_GetColorByValue. */ { @@ -459,12 +450,12 @@ Tk_FreeColor(colorPtr) TkColor *prevPtr; /* - * Do a quick sanity check to make sure this color was really - * allocated by Tk_GetColor. + * Do a quick sanity check to make sure this color was really allocated by + * Tk_GetColor. */ if (tkColPtr->magic != COLOR_MAGIC) { - panic("Tk_FreeColor called with bogus color"); + Tcl_Panic("Tk_FreeColor called with bogus color"); } tkColPtr->resourceRefCount--; @@ -474,8 +465,8 @@ Tk_FreeColor(colorPtr) /* * This color is no longer being actively used, so free the color - * resources associated with it and remove it from the hash table. - * no longer any objects referencing it. + * resources associated with it and remove it from the hash table. No + * longer any objects referencing it. */ if (tkColPtr->gc != None) { @@ -484,11 +475,11 @@ Tk_FreeColor(colorPtr) } TkpFreeColor(tkColPtr); - prevPtr = (TkColor *) Tcl_GetHashValue(tkColPtr->hashPtr); + prevPtr = Tcl_GetHashValue(tkColPtr->hashPtr); if (prevPtr == tkColPtr) { if (tkColPtr->nextPtr == NULL) { Tcl_DeleteHashEntry(tkColPtr->hashPtr); - } else { + } else { Tcl_SetHashValue(tkColPtr->hashPtr, tkColPtr->nextPtr); } } else { @@ -499,10 +490,9 @@ Tk_FreeColor(colorPtr) } /* - * Free the TkColor structure if there are no objects referencing - * it. However, if there are objects referencing it then keep the - * structure around; it will get freed when the last reference is - * cleared + * Free the TkColor structure if there are no objects referencing it. + * However, if there are objects referencing it then keep the structure + * around; it will get freed when the last reference is cleared */ if (tkColPtr->objRefCount == 0) { @@ -515,27 +505,27 @@ Tk_FreeColor(colorPtr) * * Tk_FreeColorFromObj -- * - * This procedure is called to release a color allocated by - * Tk_AllocColorFromObj. It does not throw away the Tcl_Obj *; - * it only gets rid of the hash table entry for this color - * and clears the cached value that is normally stored in the object. + * This function is called to release a color allocated by + * Tk_AllocColorFromObj. It does not throw away the Tcl_Obj *; it only + * gets rid of the hash table entry for this color and clears the cached + * value that is normally stored in the object. * * Results: * None. * * Side effects: - * The reference count associated with the color represented by - * objPtr is decremented, and the color is released to X if there are - * no remaining uses for it. + * The reference count associated with the color represented by objPtr is + * decremented, and the color is released to X if there are no remaining + * uses for it. * *---------------------------------------------------------------------- */ void -Tk_FreeColorFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window this color lives in. Needed - * for the screen and colormap values. */ - Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */ +Tk_FreeColorFromObj( + Tk_Window tkwin, /* The window this color lives in. Needed for + * the screen and colormap values. */ + Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */ { Tk_FreeColor(Tk_GetColorFromObj(tkwin, objPtr)); FreeColorObjProc(objPtr); @@ -544,66 +534,65 @@ Tk_FreeColorFromObj(tkwin, objPtr) /* *--------------------------------------------------------------------------- * - * FreeColorObjProc -- + * FreeColorObjProc -- * - * This proc is called to release an object reference to a color. - * Called when the object's internal rep is released or when - * the cached tkColPtr needs to be changed. + * This proc is called to release an object reference to a color. Called + * when the object's internal rep is released or when the cached tkColPtr + * needs to be changed. * * Results: * None. * * Side effects: - * The object reference count is decremented. When both it - * and the hash ref count go to zero, the color's resources - * are released. + * The object reference count is decremented. When both it and the hash + * ref count go to zero, the color's resources are released. * *--------------------------------------------------------------------------- */ static void -FreeColorObjProc(objPtr) - Tcl_Obj *objPtr; /* The object we are releasing. */ +FreeColorObjProc( + Tcl_Obj *objPtr) /* The object we are releasing. */ { TkColor *tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1; if (tkColPtr != NULL) { tkColPtr->objRefCount--; - if ((tkColPtr->objRefCount == 0) + if ((tkColPtr->objRefCount == 0) && (tkColPtr->resourceRefCount == 0)) { ckfree((char *) tkColPtr); } - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } } /* *--------------------------------------------------------------------------- * - * DupColorObjProc -- + * DupColorObjProc -- * - * When a cached color object is duplicated, this is called to - * update the internal reps. + * When a cached color object is duplicated, this is called to update the + * internal reps. * * Results: * None. * * Side effects: - * The color's objRefCount is incremented and the internal rep - * of the copy is set to point to it. + * The color's objRefCount is incremented and the internal rep of the + * copy is set to point to it. * *--------------------------------------------------------------------------- */ static void -DupColorObjProc(srcObjPtr, dupObjPtr) - Tcl_Obj *srcObjPtr; /* The object we are copying from. */ - Tcl_Obj *dupObjPtr; /* The object we are copying to. */ +DupColorObjProc( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { TkColor *tkColPtr = (TkColor *) srcObjPtr->internalRep.twoPtrValue.ptr1; - + dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr; + dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) tkColPtr; if (tkColPtr != NULL) { tkColPtr->objRefCount++; @@ -615,26 +604,25 @@ DupColorObjProc(srcObjPtr, dupObjPtr) * * Tk_GetColorFromObj -- * - * Returns the color referred to by a Tcl object. The color must - * already have been allocated via a call to Tk_AllocColorFromObj - * or Tk_GetColor. + * Returns the color referred to by a Tcl object. The color must already + * have been allocated via a call to Tk_AllocColorFromObj or Tk_GetColor. * * Results: - * Returns the XColor * that matches the tkwin and the string rep - * of objPtr. + * Returns the XColor * that matches the tkwin and the string rep of + * objPtr. * * Side effects: - * If the object is not already a color, the conversion will free - * any old internal representation. + * If the object is not already a color, the conversion will free any old + * internal representation. * *---------------------------------------------------------------------- */ XColor * -Tk_GetColorFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window in which the color will be +Tk_GetColorFromObj( + Tk_Window tkwin, /* The window in which the color will be * used. */ - Tcl_Obj *objPtr; /* String value contains the name of the + Tcl_Obj *objPtr) /* String value contains the name of the * desired color. */ { TkColor *tkColPtr; @@ -644,51 +632,52 @@ Tk_GetColorFromObj(tkwin, objPtr) if (objPtr->typePtr != &tkColorObjType) { InitColorObj(objPtr); } - + /* - * First check to see if the internal representation of the object - * is defined and is a color that is valid for the current screen - * and color map. If it is, we are done. + * First check to see if the internal representation of the object is + * defined and is a color that is valid for the current screen and color + * map. If it is, we are done. */ + tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1; if ((tkColPtr != NULL) && (tkColPtr->resourceRefCount > 0) && (Tk_Screen(tkwin) == tkColPtr->screen) && (Tk_Colormap(tkwin) == tkColPtr->colormap)) { /* - * The object already points to the right TkColor structure. - * Just return it. + * The object already points to the right TkColor structure. Just + * return it. */ return (XColor *) tkColPtr; } /* - * If we reach this point, it means that the TkColor structure - * that we have cached in the internal representation is not valid - * for the current screen and colormap. But there is a list of - * other TkColor structures attached to the TkDisplay. Walk this - * list looking for the right TkColor structure. + * If we reach this point, it means that the TkColor structure that we + * have cached in the internal representation is not valid for the current + * screen and colormap. But there is a list of other TkColor structures + * attached to the TkDisplay. Walk this list looking for the right TkColor + * structure. */ - hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, + hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, Tcl_GetString(objPtr)); if (hashPtr == NULL) { goto error; } - for (tkColPtr = (TkColor *) Tcl_GetHashValue(hashPtr); + for (tkColPtr = Tcl_GetHashValue(hashPtr); (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) { if ((Tk_Screen(tkwin) == tkColPtr->screen) && (Tk_Colormap(tkwin) == tkColPtr->colormap)) { FreeColorObjProc(objPtr); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) tkColPtr; tkColPtr->objRefCount++; return (XColor *) tkColPtr; } } - error: - panic(" Tk_GetColorFromObj called with non-existent color!"); + error: + Tcl_Panic("Tk_GetColorFromObj called with non-existent color!"); /* * The following code isn't reached; it's just there to please compilers. */ @@ -700,28 +689,27 @@ Tk_GetColorFromObj(tkwin, objPtr) * * InitColorObj -- * - * Bookeeping procedure to change an objPtr to a color type. + * Bookeeping function to change an objPtr to a color type. * * Results: * None. * * Side effects: - * The old internal rep of the object is freed. The object's - * type is set to color with a NULL TkColor pointer (the pointer - * will be set later by either Tk_AllocColorFromObj or - * Tk_GetColorFromObj). + * The old internal rep of the object is freed. The object's type is set + * to color with a NULL TkColor pointer (the pointer will be set later by + * either Tk_AllocColorFromObj or Tk_GetColorFromObj). * *---------------------------------------------------------------------- */ static void -InitColorObj(objPtr) - Tcl_Obj *objPtr; /* The object to convert. */ +InitColorObj( + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ Tcl_GetString(objPtr); @@ -730,7 +718,7 @@ InitColorObj(objPtr) (*typePtr->freeIntRepProc)(objPtr); } objPtr->typePtr = &tkColorObjType; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } /* @@ -750,14 +738,14 @@ InitColorObj(objPtr) */ static void -ColorInit(dispPtr) - TkDisplay *dispPtr; +ColorInit( + TkDisplay *dispPtr) { if (!dispPtr->colorInit) { - dispPtr->colorInit = 1; + dispPtr->colorInit = 1; Tcl_InitHashTable(&dispPtr->colorNameTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&dispPtr->colorValueTable, - sizeof(ValueKey)/sizeof(int)); + Tcl_InitHashTable(&dispPtr->colorValueTable, + sizeof(ValueKey)/sizeof(int)); } } @@ -766,13 +754,13 @@ ColorInit(dispPtr) * * TkDebugColor -- * - * This procedure returns debugging information about a color. + * This function returns debugging information about a color. * * Results: * The return value is a list with one sublist for each TkColor - * corresponding to "name". Each sublist has two elements that - * contain the resourceRefCount and objRefCount fields from the - * TkColor structure. + * corresponding to "name". Each sublist has two elements that contain + * the resourceRefCount and objRefCount fields from the TkColor + * structure. * * Side effects: * None. @@ -781,29 +769,30 @@ ColorInit(dispPtr) */ Tcl_Obj * -TkDebugColor(tkwin, name) - Tk_Window tkwin; /* The window in which the color will be - * used (not currently used). */ - char *name; /* Name of the desired color. */ +TkDebugColor( + Tk_Window tkwin, /* The window in which the color will be used + * (not currently used). */ + char *name) /* Name of the desired color. */ { - TkColor *tkColPtr; Tcl_HashEntry *hashPtr; - Tcl_Obj *resultPtr, *objPtr; + Tcl_Obj *resultPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; resultPtr = Tcl_NewObj(); hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, name); if (hashPtr != NULL) { - tkColPtr = (TkColor *) Tcl_GetHashValue(hashPtr); + TkColor *tkColPtr = Tcl_GetHashValue(hashPtr); + if (tkColPtr == NULL) { - panic("TkDebugColor found empty hash table entry"); + Tcl_Panic("TkDebugColor found empty hash table entry"); } for ( ; (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) { - objPtr = Tcl_NewObj(); + Tcl_Obj *objPtr = Tcl_NewObj(); + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(tkColPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(tkColPtr->objRefCount)); + Tcl_NewIntObj(tkColPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } @@ -814,11 +803,11 @@ TkDebugColor(tkwin, name) /* This function is not necessary for Win32, * since XParseColor already does the right thing */ Status -TkParseColor(display, map, name, color) - Display * display; /* The display */ - Colormap map; /* Color map */ - CONST char* name; /* String to be parsed */ - XColor * color; +TkParseColor( + Display *display, /* The display */ + Colormap map, /* Color map */ + const char *name, /* String to be parsed */ + XColor *color) { char buf[14]; if (*name == '#') { @@ -874,3 +863,10 @@ TkParseColor(display, map, name, color) return XParseColor(display, map, name, color); } #endif /* __WIN32__ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkColor.h b/generic/tkColor.h index 2a59e05..d4679cf 100644 --- a/generic/tkColor.h +++ b/generic/tkColor.h @@ -1,13 +1,12 @@ /* * tkColor.h -- * - * Declarations of data types and functions used by the - * Tk color module. + * Declarations of data types and functions used by the Tk color module. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKCOLOR @@ -16,14 +15,14 @@ #include <tkInt.h> #ifdef BUILD_tk -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLEXPORT +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT #endif /* - * One of the following data structures is used to keep track of - * each color that is being used by the application; typically there - * is a colormap entry allocated for each of these colors. + * One of the following data structures is used to keep track of each color + * that is being used by the application; typically there is a colormap entry + * allocated for each of these colors. */ #define TK_COLOR_BY_NAME 1 @@ -34,39 +33,38 @@ typedef struct TkColor { XColor color; /* Information about this color. */ unsigned int magic; /* Used for quick integrity check on this - * structure. Must always have the - * value COLOR_MAGIC. */ + * structure. Must always have the value + * COLOR_MAGIC. */ GC gc; /* Simple gc with this color as foreground - * color and all other fields defaulted. - * May be None. */ - Screen *screen; /* Screen where this color is valid. Used - * to delete it, and to find its display. */ + * color and all other fields defaulted. May + * be None. */ + Screen *screen; /* Screen where this color is valid. Used to + * delete it, and to find its display. */ Colormap colormap; /* Colormap from which this entry was * allocated. */ - Visual *visual; /* Visual associated with colormap. */ + Visual *visual; /* Visual associated with colormap. */ int 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 + * Tk_AllocColorFromObj or Tk_GetColor). If + * this count is 0, then this TkColor * structure is no longer valid and it isn't - * present in a hash table: it is being - * kept around only because there are objects - * referring to it. The structure is freed - * when resourceRefCount and objRefCount - * are both 0. */ + * present in a hash table: it is being kept + * around only because there are objects + * referring to it. The structure is freed + * when resourceRefCount and objRefCount are + * both 0. */ int objRefCount; /* The number of Tcl objects that reference * this structure. */ - int type; /* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE */ + int type; /* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE. */ Tcl_HashEntry *hashPtr; /* Pointer to hash table entry for this * structure. (for use in deleting entry). */ struct TkColor *nextPtr; /* Points to the next TkColor structure with - * the same color name. Colors with the - * same name but different screens or - * colormaps are chained together off a - * single entry in nameTable. For colors in - * valueTable (those allocated by - * Tk_GetColorByValue) this field is always - * NULL. */ + * the same color name. Colors with the same + * name but different screens or colormaps are + * chained together off a single entry in + * nameTable. For colors in valueTable (those + * allocated by Tk_GetColorByValue) this field + * is always NULL. */ } TkColor; /* @@ -74,14 +72,12 @@ typedef struct TkColor { */ #ifndef TkpFreeColor -EXTERN void TkpFreeColor _ANSI_ARGS_((TkColor *tkColPtr)); +MODULE_SCOPE void TkpFreeColor(TkColor *tkColPtr); #endif -EXTERN TkColor * TkpGetColor _ANSI_ARGS_((Tk_Window tkwin, - Tk_Uid name)); -EXTERN TkColor * TkpGetColorByValue _ANSI_ARGS_((Tk_Window tkwin, - XColor *colorPtr)); +MODULE_SCOPE TkColor * TkpGetColor(Tk_Window tkwin, Tk_Uid name); +MODULE_SCOPE TkColor * TkpGetColorByValue(Tk_Window tkwin, XColor *colorPtr); -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLIMPORT +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TKCOLOR */ diff --git a/generic/tkConfig.c b/generic/tkConfig.c index 1e66af0..ed47210 100644 --- a/generic/tkConfig.c +++ b/generic/tkConfig.c @@ -1,13 +1,13 @@ -/* +/* * tkConfig.c -- * - * This file contains procedures that manage configuration options - * for widgets and other things. + * This file contains functions that manage configuration options for + * widgets and other things. * * Copyright (c) 1997-1998 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* @@ -23,129 +23,123 @@ #define __NO_OLD_CONFIG #endif -#include "tk.h" #include "tkInt.h" -#include "tkPort.h" #include "tkFont.h" /* - * The following definition is an AssocData key used to keep track of - * all of the option tables that have been created for an interpreter. + * The following definition is an AssocData key used to keep track of all of + * the option tables that have been created for an interpreter. */ #define OPTION_HASH_KEY "TkOptionTable" /* - * The following two structures are used along with Tk_OptionSpec - * structures to manage configuration options. Tk_OptionSpec is - * static templates that are compiled into the code of a widget - * or other object manager. However, to look up options efficiently - * we need to supplement the static information with additional - * dynamic information, and this dynamic information may be different - * for each application. Thus we create structures of the following - * two types to hold all of the dynamic information; this is done - * by Tk_CreateOptionTable. - * - * One of the following structures corresponds to each Tk_OptionSpec. - * These structures exist as arrays inside TkOptionTable structures. + * The following two structures are used along with Tk_OptionSpec structures + * to manage configuration options. Tk_OptionSpec is static templates that are + * compiled into the code of a widget or other object manager. However, to + * look up options efficiently we need to supplement the static information + * with additional dynamic information, and this dynamic information may be + * different for each application. Thus we create structures of the following + * two types to hold all of the dynamic information; this is done by + * Tk_CreateOptionTable. + * + * One of the following structures corresponds to each Tk_OptionSpec. These + * structures exist as arrays inside TkOptionTable structures. */ typedef struct TkOption { - CONST Tk_OptionSpec *specPtr; /* The original spec from the template - * passed to Tk_CreateOptionTable.*/ - Tk_Uid dbNameUID; /* The Uid form of the option database - * name. */ - Tk_Uid dbClassUID; /* The Uid form of the option database - * class name. */ - Tcl_Obj *defaultPtr; /* Default value for this option. */ + CONST Tk_OptionSpec *specPtr; + /* The original spec from the template passed + * to Tk_CreateOptionTable.*/ + Tk_Uid dbNameUID; /* The Uid form of the option database + * name. */ + Tk_Uid dbClassUID; /* The Uid form of the option database class + * name. */ + Tcl_Obj *defaultPtr; /* Default value for this option. */ union { - Tcl_Obj *monoColorPtr; /* For color and border options, this - * is an alternate default value to - * use on monochrome displays. */ - struct TkOption *synonymPtr; /* For synonym options, this points to - * the master entry. */ - struct Tk_ObjCustomOption *custom; /* For TK_OPTION_CUSTOM. */ + Tcl_Obj *monoColorPtr; /* For color and border options, this is an + * alternate default value to use on + * monochrome displays. */ + struct TkOption *synonymPtr; + /* For synonym options, this points to the + * master entry. */ + struct Tk_ObjCustomOption *custom; + /* For TK_OPTION_CUSTOM. */ } extra; - int flags; /* Miscellaneous flag values; see - * below for definitions. */ + int flags; /* Miscellaneous flag values; see below for + * definitions. */ } Option; /* * Flag bits defined for Option structures: * - * OPTION_NEEDS_FREEING - 1 means that FreeResources must be - * invoke to free resources associated with - * the option when it is no longer needed. + * OPTION_NEEDS_FREEING - 1 means that FreeResources must be invoked to + * free resources associated with the option when + * it is no longer needed. */ #define OPTION_NEEDS_FREEING 1 /* - * One of the following exists for each Tk_OptionSpec array that has - * been passed to Tk_CreateOptionTable. + * One of the following exists for each Tk_OptionSpec array that has been + * passed to Tk_CreateOptionTable. */ typedef struct OptionTable { - int refCount; /* Counts the number of uses of this - * table (the number of times - * Tk_CreateOptionTable has returned - * it). This can be greater than 1 if - * it is shared along several option - * table chains, or if the same table - * is used for multiple purposes. */ - Tcl_HashEntry *hashEntryPtr; /* Hash table entry that refers to this - * table; used to delete the entry. */ - struct OptionTable *nextPtr; /* If templatePtr was part of a chain - * of templates, this points to the - * table corresponding to the next - * template in the chain. */ - int numOptions; /* The number of items in the options - * array below. */ - Option options[1]; /* Information about the individual - * options in the table. This must be - * the last field in the structure: - * the actual size of the array will - * be numOptions, not 1. */ + int refCount; /* Counts the number of uses of this table + * (the number of times Tk_CreateOptionTable + * has returned it). This can be greater than + * 1 if it is shared along several option + * table chains, or if the same table is used + * for multiple purposes. */ + Tcl_HashEntry *hashEntryPtr;/* Hash table entry that refers to this table; + * used to delete the entry. */ + struct OptionTable *nextPtr;/* If templatePtr was part of a chain of + * templates, this points to the table + * corresponding to the next template in the + * chain. */ + int numOptions; /* The number of items in the options array + * below. */ + Option options[1]; /* Information about the individual options in + * the table. This must be the last field in + * the structure: the actual size of the array + * will be numOptions, not 1. */ } OptionTable; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int DoObjConfig _ANSI_ARGS_((Tcl_Interp *interp, - char *recordPtr, Option *optionPtr, - Tcl_Obj *valuePtr, Tk_Window tkwin, - Tk_SavedOption *savePtr)); -static void DestroyOptionHashTable _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); -static void FreeResources _ANSI_ARGS_((Option *optionPtr, - Tcl_Obj *objPtr, char *internalPtr, - Tk_Window tkwin)); -static Tcl_Obj * GetConfigList _ANSI_ARGS_((char *recordPtr, - Option *optionPtr, Tk_Window tkwin)); -static Tcl_Obj * GetObjectForOption _ANSI_ARGS_((char *recordPtr, - Option *optionPtr, Tk_Window tkwin)); -static Option * GetOption _ANSI_ARGS_((CONST char *name, - OptionTable *tablePtr)); -static Option * GetOptionFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, OptionTable *tablePtr)); -static int ObjectIsEmpty _ANSI_ARGS_((Tcl_Obj *objPtr)); -static int SetOptionFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); +static int DoObjConfig(Tcl_Interp *interp, char *recordPtr, + Option *optionPtr, Tcl_Obj *valuePtr, + Tk_Window tkwin, Tk_SavedOption *savePtr); +static void DestroyOptionHashTable(ClientData clientData, + Tcl_Interp *interp); +static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr, + char *internalPtr, Tk_Window tkwin); +static Tcl_Obj * GetConfigList(char *recordPtr, + Option *optionPtr, Tk_Window tkwin); +static Tcl_Obj * GetObjectForOption(char *recordPtr, + Option *optionPtr, Tk_Window tkwin); +static Option * GetOption(CONST char *name, OptionTable *tablePtr); +static Option * GetOptionFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, OptionTable *tablePtr); +static int ObjectIsEmpty(Tcl_Obj *objPtr); +static int SetOptionFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* - * The structure below defines an object type that is used to cache the - * result of looking up an option name. If an object has this type, then - * its internalPtr1 field points to the OptionTable in which it was looked up, - * and the internalPtr2 field points to the entry that matched. + * The structure below defines an object type that is used to cache the result + * of looking up an option name. If an object has this type, then its + * internalPtr1 field points to the OptionTable in which it was looked up, and + * the internalPtr2 field points to the entry that matched. */ Tcl_ObjType tkOptionObjType = { - "option", /* name */ - (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ - (Tcl_UpdateStringProc *) NULL, /* updateStringProc */ - SetOptionFromAny /* setFromAnyProc */ + "option", /* name */ + NULL, /* freeIntRepProc */ + NULL, /* dupIntRepProc */ + NULL, /* updateStringProc */ + SetOptionFromAny /* setFromAnyProc */ }; /* @@ -153,12 +147,12 @@ Tcl_ObjType tkOptionObjType = { * * Tk_CreateOptionTable -- * - * Given a template for configuration options, this procedure - * creates a table that may be used to look up options efficiently. + * Given a template for configuration options, this function creates a + * table that may be used to look up options efficiently. * * Results: - * Returns a token to a structure that can be passed to procedures - * such as Tk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions. + * Returns a token to a structure that can be passed to functions such as + * Tk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions. * * Side effects: * Storage is allocated. @@ -167,12 +161,12 @@ Tcl_ObjType tkOptionObjType = { */ Tk_OptionTable -Tk_CreateOptionTable(interp, templatePtr) - Tcl_Interp *interp; /* Interpreter associated with the - * application in which this table - * will be used. */ - CONST Tk_OptionSpec *templatePtr; /* Static information about the - * configuration options. */ +Tk_CreateOptionTable( + Tcl_Interp *interp, /* Interpreter associated with the application + * in which this table will be used. */ + CONST Tk_OptionSpec *templatePtr) + /* Static information about the configuration + * options. */ { Tcl_HashTable *hashTablePtr; Tcl_HashEntry *hashEntryPtr; @@ -183,13 +177,13 @@ Tk_CreateOptionTable(interp, templatePtr) int numOptions, i; /* - * We use an AssocData value in the interpreter to keep a hash - * table of all the option tables we've created for this application. - * This is used for two purposes. First, it allows us to share the - * tables (e.g. in several chains) and second, we use the deletion - * callback for the AssocData to delete all the option tables when - * the interpreter is deleted. The code below finds the hash table - * or creates a new one if it doesn't already exist. + * We use an AssocData value in the interpreter to keep a hash table of + * all the option tables we've created for this application. This is used + * for two purposes. First, it allows us to share the tables (e.g. in + * several chains) and second, we use the deletion callback for the + * AssocData to delete all the option tables when the interpreter is + * deleted. The code below finds the hash table or creates a new one if it + * doesn't already exist. */ hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY, @@ -202,8 +196,8 @@ Tk_CreateOptionTable(interp, templatePtr) } /* - * See if a table has already been created for this template. If - * so, just reuse the existing table. + * See if a table has already been created for this template. If so, just + * reuse the existing table. */ hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr, @@ -215,8 +209,8 @@ Tk_CreateOptionTable(interp, templatePtr) } /* - * Count the number of options in the template, then create the - * table structure. + * Count the number of options in the template, then create the table + * structure. */ numOptions = 0; @@ -245,14 +239,13 @@ Tk_CreateOptionTable(interp, templatePtr) if (specPtr->type == TK_OPTION_SYNONYM) { /* - * This is a synonym option; find the master option that it - * refers to and create a pointer from the synonym to the - * master. + * This is a synonym option; find the master option that it refers + * to and create a pointer from the synonym to the master. */ for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) { if (specPtr2->type == TK_OPTION_END) { - panic("Tk_CreateOptionTable couldn't find synonym"); + Tcl_Panic("Tk_CreateOptionTable couldn't find synonym"); } if (strcmp(specPtr2->optionName, (char *) specPtr->clientData) == 0) { @@ -265,12 +258,10 @@ Tk_CreateOptionTable(interp, templatePtr) optionPtr->dbNameUID = Tk_GetUid(specPtr->dbName); } if (specPtr->dbClass != NULL) { - optionPtr->dbClassUID = - Tk_GetUid(specPtr->dbClass); + optionPtr->dbClassUID = Tk_GetUid(specPtr->dbClass); } if (specPtr->defValue != NULL) { - optionPtr->defaultPtr = - Tcl_NewStringObj(specPtr->defValue, -1); + optionPtr->defaultPtr = Tcl_NewStringObj(specPtr->defValue,-1); Tcl_IncrRefCount(optionPtr->defaultPtr); } if (((specPtr->type == TK_OPTION_COLOR) @@ -286,7 +277,7 @@ Tk_CreateOptionTable(interp, templatePtr) * Get the custom parsing, etc., functions. */ optionPtr->extra.custom = - (Tk_ObjCustomOption *)specPtr->clientData; + (Tk_ObjCustomOption *) specPtr->clientData; } } if (((specPtr->type == TK_OPTION_STRING) @@ -304,9 +295,9 @@ Tk_CreateOptionTable(interp, templatePtr) Tcl_SetHashValue(hashEntryPtr, tablePtr); /* - * Finally, check to see if this template chains to another template - * with additional options. If so, call ourselves recursively to - * create the next table(s). + * Finally, check to see if this template chains to another template with + * additional options. If so, call ourselves recursively to create the + * next table(s). */ if (specPtr->clientData != NULL) { @@ -322,22 +313,22 @@ Tk_CreateOptionTable(interp, templatePtr) * * Tk_DeleteOptionTable -- * - * Called to release resources used by an option table when - * the table is no longer needed. + * Called to release resources used by an option table when the table is + * no longer needed. * * Results: * None. * * Side effects: - * The option table and associated resources (such as additional - * option tables chained off it) are destroyed. + * The option table and associated resources (such as additional option + * tables chained off it) are destroyed. * *---------------------------------------------------------------------- */ void -Tk_DeleteOptionTable(optionTable) - Tk_OptionTable optionTable; /* The option table to delete. */ +Tk_DeleteOptionTable( + Tk_OptionTable optionTable) /* The option table to delete. */ { OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; @@ -372,25 +363,25 @@ Tk_DeleteOptionTable(optionTable) * * DestroyOptionHashTable -- * - * This procedure is the deletion callback associated with the - * AssocData entry created by Tk_CreateOptionTable. It is - * invoked when an interpreter is deleted, and deletes all of - * the option tables associated with that interpreter. + * This function is the deletion callback associated with the AssocData + * entry created by Tk_CreateOptionTable. It is invoked when an + * interpreter is deleted, and deletes all of the option tables + * associated with that interpreter. * * Results: * None. * * Side effects: - * The option hash table is destroyed along with all of the - * OptionTable structures that it refers to. + * The option hash table is destroyed along with all of the OptionTable + * structures that it refers to. * *---------------------------------------------------------------------- */ static void -DestroyOptionHashTable(clientData, interp) - ClientData clientData; /* The hash table we are destroying */ - Tcl_Interp *interp; /* The interpreter we are destroying */ +DestroyOptionHashTable( + ClientData clientData, /* The hash table we are destroying */ + Tcl_Interp *interp) /* The interpreter we are destroying */ { Tcl_HashTable *hashTablePtr = (Tcl_HashTable *) clientData; Tcl_HashSearch search; @@ -404,13 +395,12 @@ DestroyOptionHashTable(clientData, interp) /* * The following statements do two tricky things: - * 1. They ensure that the option table is deleted, even if - * there are outstanding references to it. - * 2. They ensure that Tk_DeleteOptionTable doesn't delete - * other tables chained from this one; we'll do it when - * we come across the hash table entry for the chained - * table (in fact, the chained table may already have - * been deleted). + * 1. They ensure that the option table is deleted, even if there are + * outstanding references to it. + * 2. They ensure that Tk_DeleteOptionTable doesn't delete other + * tables chained from this one; we'll do it when we come across + * the hash table entry for the chained table (in fact, the chained + * table may already have been deleted). */ tablePtr->refCount = 1; @@ -426,16 +416,16 @@ DestroyOptionHashTable(clientData, interp) * * Tk_InitOptions -- * - * This procedure is invoked when an object such as a widget - * is created. It supplies an initial value for each configuration - * option (the value may come from the option database, a system - * default, or the default in the option table). + * This function is invoked when an object such as a widget is created. + * It supplies an initial value for each configuration option (the value + * may come from the option database, a system default, or the default in + * the option table). * * Results: - * The return value is TCL_OK if the procedure completed - * successfully, and TCL_ERROR if one of the initial values was - * bogus. If an error occurs and interp isn't NULL, then an - * error message will be left in its result. + * The return value is TCL_OK if the function completed successfully, and + * TCL_ERROR if one of the initial values was bogus. If an error occurs + * and interp isn't NULL, then an error message will be left in its + * result. * * Side effects: * Fields of recordPtr are filled in with initial values. @@ -444,21 +434,21 @@ DestroyOptionHashTable(clientData, interp) */ int -Tk_InitOptions(interp, recordPtr, optionTable, tkwin) - Tcl_Interp *interp; /* Interpreter for error reporting. NULL - * means don't leave an error message. */ - char *recordPtr; /* Pointer to the record to configure. - * Note: the caller should have properly - * initialized the record with NULL - * pointers for each option value. */ - Tk_OptionTable optionTable; /* The token which matches the config - * specs for the widget in question. */ - Tk_Window tkwin; /* Certain options types (such as - * TK_OPTION_COLOR) need fields out - * of the window they are used in to - * be able to calculate their values. - * Not needed unless one of these - * options is in the configSpecs record. */ +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: + * the caller should have properly initialized + * the record with NULL pointers for each + * option value. */ + Tk_OptionTable optionTable, /* The token which matches the config specs + * for the widget in question. */ + Tk_Window tkwin) /* Certain options types (such as + * TK_OPTION_COLOR) need fields out of the + * window they are used in to be able to + * calculate their values. Not needed unless + * one of these options is in the configSpecs + * record. */ { OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; @@ -471,8 +461,8 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) /* * If this table chains to other tables, handle their initialization - * first. That way, if both tables refer to the same field of the - * record, the value in the first table will win. + * first. That way, if both tables refer to the same field of the record, + * the value in the first table will win. */ if (tablePtr->nextPtr != NULL) { @@ -489,11 +479,11 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) for (optionPtr = tablePtr->options, count = tablePtr->numOptions; count > 0; optionPtr++, count--) { - /* * If we specify TK_OPTION_DONT_SET_DEFAULT, then the user has * processed and set a default for this already. */ + if ((optionPtr->specPtr->type == TK_OPTION_SYNONYM) || (optionPtr->specPtr->flags & TK_OPTION_DONT_SET_DEFAULT)) { continue; @@ -502,12 +492,12 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) /* * We look in three places for the initial value, using the first - * non-NULL value that we find. First, check the option database. + * non-NULL value that we find. First, check the option database. */ valuePtr = NULL; if (optionPtr->dbNameUID != NULL) { - value = Tk_GetOption(tkwin, optionPtr->dbNameUID, + value = Tk_GetOption(tkwin, optionPtr->dbNameUID, optionPtr->dbClassUID); if (value != NULL) { valuePtr = Tcl_NewStringObj(value, -1); @@ -518,6 +508,7 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) /* * Second, check for a system-specific default value. */ + if ((valuePtr == NULL) && (optionPtr->dbNameUID != NULL)) { valuePtr = TkpGetSystemDefault(tkwin, optionPtr->dbNameUID, @@ -528,16 +519,16 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) } /* - * Third and last, use the default value supplied by the option - * table. In the case of color objects, we pick one of two - * values depending on whether the screen is mono or color. + * Third and last, use the default value supplied by the option table. + * In the case of color objects, we pick one of two values depending + * on whether the screen is mono or color. */ if (valuePtr == NULL) { - if ((tkwin != NULL) + if ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR) || (optionPtr->specPtr->type == TK_OPTION_BORDER)) - && (Tk_Depth(tkwin) <= 1) + && (Tk_Depth(tkwin) <= 1) && (optionPtr->extra.monoColorPtr != NULL)) { valuePtr = optionPtr->extra.monoColorPtr; } else { @@ -554,25 +545,26 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) * referenced here, and will be properly free'd when finished, * regardless of what DoObjConfig does. */ + Tcl_IncrRefCount(valuePtr); - + if (DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, - (Tk_SavedOption *) NULL) != TCL_OK) { + NULL) != TCL_OK) { if (interp != NULL) { char msg[200]; - + switch (source) { - case OPTION_DATABASE: - sprintf(msg, "\n (database entry for \"%.50s\")", - optionPtr->specPtr->optionName); - break; - case SYSTEM_DEFAULT: - sprintf(msg, "\n (system default for \"%.50s\")", - optionPtr->specPtr->optionName); - break; - case TABLE_DEFAULT: - sprintf(msg, "\n (default value for \"%.50s\")", - optionPtr->specPtr->optionName); + case OPTION_DATABASE: + sprintf(msg, "\n (database entry for \"%.50s\")", + optionPtr->specPtr->optionName); + break; + case SYSTEM_DEFAULT: + sprintf(msg, "\n (system default for \"%.50s\")", + optionPtr->specPtr->optionName); + break; + case TABLE_DEFAULT: + sprintf(msg, "\n (default value for \"%.50s\")", + optionPtr->specPtr->optionName); } if (tkwin != NULL) { sprintf(msg + strlen(msg) - 1, " in widget \"%.50s\")", @@ -593,40 +585,38 @@ Tk_InitOptions(interp, recordPtr, optionTable, tkwin) * * DoObjConfig -- * - * This procedure applies a new value for a configuration option - * to the record being configured. + * This function applies a new value for a configuration option to the + * record being configured. * * Results: - * The return value is TCL_OK if the procedure completed - * successfully. If an error occurred then TCL_ERROR is - * returned and an error message is left in interp's result, if - * interp isn't NULL. In addition, if oldValuePtrPtr isn't - * NULL then it *oldValuePtrPtr is filled in with a pointer - * to the option's old value. + * The return value is TCL_OK if the function completed successfully. If + * an error occurred then TCL_ERROR is returned and an error message is + * left in interp's result, if interp isn't NULL. In addition, if + * oldValuePtrPtr isn't NULL then it *oldValuePtrPtr is filled in with a + * pointer to the option's old value. * * Side effects: - * RecordPtr gets modified to hold the new value in the form of - * a Tcl_Obj, an internal representation, or both. The old - * value is freed if oldValuePtrPtr is NULL. + * RecordPtr gets modified to hold the new value in the form of a + * Tcl_Obj, an internal representation, or both. The old value is freed + * if oldValuePtrPtr is NULL. * *-------------------------------------------------------------- */ static int -DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr) - Tcl_Interp *interp; /* Interpreter for error reporting. If - * NULL, then no message is left if an error +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 value. */ - Option *optionPtr; /* Pointer to information about the - * option. */ - Tcl_Obj *valuePtr; /* New value for option. */ - Tk_Window tkwin; /* Window in which option will be used (needed + char *recordPtr, /* The record to modify to hold the new option + * value. */ + Option *optionPtr, /* Pointer to information about the option. */ + Tcl_Obj *valuePtr, /* New value for option. */ + Tk_Window tkwin, /* Window in which option will be used (needed * to allocate resources for some options). - * May be NULL if the option doesn't - * require window-related resources. */ - Tk_SavedOption *savedOptionPtr; + * May be NULL if the option doesn't require + * window-related resources. */ + Tk_SavedOption *savedOptionPtr) /* If NULL, the old value for the option will * be freed. If non-NULL, the old value will * be stored here, and it becomes the property @@ -634,13 +624,14 @@ DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr) * free the old value). */ { Tcl_Obj **slotPtrPtr, *oldPtr; - char *internalPtr; /* Points to location in record where - * internal representation of value should - * be stored, or NULL. */ + char *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 * internal representation of value. */ - Tk_SavedOption internal; /* Used to save the old internal representation - * of the value if savedOptionPtr is NULL. */ + Tk_SavedOption internal; /* Used to save the old internal + * representation of the value if + * savedOptionPtr is NULL. */ CONST Tk_OptionSpec *specPtr; int nullOK; @@ -658,8 +649,8 @@ DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr) } /* - * Apply the new value in a type-specific way. Also remember the - * old object and internal forms, if they exist. + * Apply the new value in a type-specific way. Also remember the old + * object and internal forms, if they exist. */ if (specPtr->internalOffset >= 0) { @@ -676,296 +667,293 @@ DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr) } nullOK = (optionPtr->specPtr->flags & TK_OPTION_NULL_OK); switch (optionPtr->specPtr->type) { - case TK_OPTION_BOOLEAN: { - int new; + case TK_OPTION_BOOLEAN: { + int newBool; - if (Tcl_GetBooleanFromObj(interp, valuePtr, &new) - != TCL_OK) { - return TCL_ERROR; - } - if (internalPtr != NULL) { - *((int *) oldInternalPtr) = *((int *) internalPtr); - *((int *) internalPtr) = new; - } - break; + if (Tcl_GetBooleanFromObj(interp, valuePtr, &newBool) != TCL_OK) { + return TCL_ERROR; } - case TK_OPTION_INT: { - int new; - - if (Tcl_GetIntFromObj(interp, valuePtr, &new) != TCL_OK) { - return TCL_ERROR; - } - if (internalPtr != NULL) { - *((int *) oldInternalPtr) = *((int *) internalPtr); - *((int *) internalPtr) = new; - } - break; + if (internalPtr != NULL) { + *((int *) oldInternalPtr) = *((int *) internalPtr); + *((int *) internalPtr) = newBool; } - case TK_OPTION_DOUBLE: { - double new; - - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = 0; - } else { - if (Tcl_GetDoubleFromObj(interp, valuePtr, &new) != TCL_OK) { - return TCL_ERROR; - } - } + break; + } + case TK_OPTION_INT: { + int newInt; - if (internalPtr != NULL) { - *((double *) oldInternalPtr) = *((double *) internalPtr); - *((double *) internalPtr) = new; - } - break; + if (Tcl_GetIntFromObj(interp, valuePtr, &newInt) != TCL_OK) { + return TCL_ERROR; } - case TK_OPTION_STRING: { - char *new, *value; - int length; - - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - } - if (internalPtr != NULL) { - if (valuePtr != NULL) { - value = Tcl_GetStringFromObj(valuePtr, &length); - new = ckalloc((unsigned) (length + 1)); - strcpy(new, value); - } else { - new = NULL; - } - *((char **) oldInternalPtr) = *((char **) internalPtr); - *((char **) internalPtr) = new; - } - break; + if (internalPtr != NULL) { + *((int *) oldInternalPtr) = *((int *) internalPtr); + *((int *) internalPtr) = newInt; } - case TK_OPTION_STRING_TABLE: { - int new; + break; + } + case TK_OPTION_DOUBLE: { + double newDbl; - if (Tcl_GetIndexFromObj(interp, valuePtr, - (CONST char **) optionPtr->specPtr->clientData, - optionPtr->specPtr->optionName+1, 0, &new) != TCL_OK) { + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newDbl = 0; + } else { + if (Tcl_GetDoubleFromObj(interp, valuePtr, &newDbl) != TCL_OK) { return TCL_ERROR; } - if (internalPtr != NULL) { - *((int *) oldInternalPtr) = *((int *) internalPtr); - *((int *) internalPtr) = new; - } - break; } - case TK_OPTION_COLOR: { - XColor *newPtr; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - newPtr = NULL; - } else { - newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr); - if (newPtr == NULL) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((XColor **) oldInternalPtr) = *((XColor **) internalPtr); - *((XColor **) internalPtr) = newPtr; - } - break; + if (internalPtr != NULL) { + *((double *) oldInternalPtr) = *((double *) internalPtr); + *((double *) internalPtr) = newDbl; } - case TK_OPTION_FONT: { - Tk_Font new; + break; + } + case TK_OPTION_STRING: { + char *newStr, *value; + int length; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = NULL; + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + } + if (internalPtr != NULL) { + if (valuePtr != NULL) { + value = Tcl_GetStringFromObj(valuePtr, &length); + newStr = ckalloc((unsigned) (length + 1)); + strcpy(newStr, value); } else { - new = Tk_AllocFontFromObj(interp, tkwin, valuePtr); - if (new == NULL) { - return TCL_ERROR; - } + newStr = NULL; } - if (internalPtr != NULL) { - *((Tk_Font *) oldInternalPtr) = *((Tk_Font *) internalPtr); - *((Tk_Font *) internalPtr) = new; - } - break; + *((char **) oldInternalPtr) = *((char **) internalPtr); + *((char **) internalPtr) = newStr; } - case TK_OPTION_STYLE: { - Tk_Style new; + break; + } + case TK_OPTION_STRING_TABLE: { + int newValue; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = NULL; - } else { - new = Tk_AllocStyleFromObj(interp, valuePtr); - if (new == NULL) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((Tk_Style *) oldInternalPtr) = *((Tk_Style *) internalPtr); - *((Tk_Style *) internalPtr) = new; - } - break; + if (Tcl_GetIndexFromObj(interp, valuePtr, + (CONST char **) optionPtr->specPtr->clientData, + optionPtr->specPtr->optionName+1, 0, &newValue) != TCL_OK) { + return TCL_ERROR; + } + if (internalPtr != NULL) { + *((int *) oldInternalPtr) = *((int *) internalPtr); + *((int *) internalPtr) = newValue; } - case TK_OPTION_BITMAP: { - Pixmap new; + break; + } + case TK_OPTION_COLOR: { + XColor *newPtr; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = None; - } else { - new = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr); - if (new == None) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((Pixmap *) oldInternalPtr) = *((Pixmap *) internalPtr); - *((Pixmap *) internalPtr) = new; + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newPtr = NULL; + } else { + newPtr = Tk_AllocColorFromObj(interp, tkwin, valuePtr); + if (newPtr == NULL) { + return TCL_ERROR; } - break; } - case TK_OPTION_BORDER: { - Tk_3DBorder new; + if (internalPtr != NULL) { + *((XColor **) oldInternalPtr) = *((XColor **) internalPtr); + *((XColor **) internalPtr) = newPtr; + } + break; + } + case TK_OPTION_FONT: { + Tk_Font newFont; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = NULL; - } else { - new = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr); - if (new == NULL) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((Tk_3DBorder *) oldInternalPtr) = - *((Tk_3DBorder *) internalPtr); - *((Tk_3DBorder *) internalPtr) = new; + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newFont = NULL; + } else { + newFont = Tk_AllocFontFromObj(interp, tkwin, valuePtr); + if (newFont == NULL) { + return TCL_ERROR; } - break; } - case TK_OPTION_RELIEF: { - int new; + if (internalPtr != NULL) { + *((Tk_Font *) oldInternalPtr) = *((Tk_Font *) internalPtr); + *((Tk_Font *) internalPtr) = newFont; + } + break; + } + case TK_OPTION_STYLE: { + Tk_Style newStyle; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = TK_RELIEF_NULL; - } else { - if (Tk_GetReliefFromObj(interp, valuePtr, &new) != TCL_OK) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((int *) oldInternalPtr) = *((int *) internalPtr); - *((int *) internalPtr) = new; + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newStyle = NULL; + } else { + newStyle = Tk_AllocStyleFromObj(interp, valuePtr); + if (newStyle == NULL) { + return TCL_ERROR; } - break; } - case TK_OPTION_CURSOR: { - Tk_Cursor new; + if (internalPtr != NULL) { + *((Tk_Style *) oldInternalPtr) = *((Tk_Style *) internalPtr); + *((Tk_Style *) internalPtr) = newStyle; + } + break; + } + case TK_OPTION_BITMAP: { + Pixmap newBitmap; - if (nullOK && ObjectIsEmpty(valuePtr)) { - new = None; - valuePtr = NULL; - } else { - new = Tk_AllocCursorFromObj(interp, tkwin, valuePtr); - if (new == None) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((Tk_Cursor *) oldInternalPtr) = *((Tk_Cursor *) internalPtr); - *((Tk_Cursor *) internalPtr) = new; + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newBitmap = None; + } else { + newBitmap = Tk_AllocBitmapFromObj(interp, tkwin, valuePtr); + if (newBitmap == None) { + return TCL_ERROR; } - Tk_DefineCursor(tkwin, new); - break; } - case TK_OPTION_JUSTIFY: { - Tk_Justify new; + if (internalPtr != NULL) { + *((Pixmap *) oldInternalPtr) = *((Pixmap *) internalPtr); + *((Pixmap *) internalPtr) = newBitmap; + } + break; + } + case TK_OPTION_BORDER: { + Tk_3DBorder newBorder; - if (Tk_GetJustifyFromObj(interp, valuePtr, &new) != TCL_OK) { + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newBorder = NULL; + } else { + newBorder = Tk_Alloc3DBorderFromObj(interp, tkwin, valuePtr); + if (newBorder == NULL) { return TCL_ERROR; } - if (internalPtr != NULL) { - *((Tk_Justify *) oldInternalPtr) - = *((Tk_Justify *) internalPtr); - *((Tk_Justify *) internalPtr) = new; - } - break; } - case TK_OPTION_ANCHOR: { - Tk_Anchor new; + if (internalPtr != NULL) { + *((Tk_3DBorder *) oldInternalPtr) = *((Tk_3DBorder *) internalPtr); + *((Tk_3DBorder *) internalPtr) = newBorder; + } + break; + } + case TK_OPTION_RELIEF: { + int newRelief; - if (Tk_GetAnchorFromObj(interp, valuePtr, &new) != TCL_OK) { + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newRelief = TK_RELIEF_NULL; + } else { + if (Tk_GetReliefFromObj(interp, valuePtr, &newRelief) != TCL_OK) { return TCL_ERROR; } - if (internalPtr != NULL) { - *((Tk_Anchor *) oldInternalPtr) - = *((Tk_Anchor *) internalPtr); - *((Tk_Anchor *) internalPtr) = new; - } - break; } - case TK_OPTION_PIXELS: { - int new; + if (internalPtr != NULL) { + *((int *) oldInternalPtr) = *((int *) internalPtr); + *((int *) internalPtr) = newRelief; + } + break; + } + case TK_OPTION_CURSOR: { + Tk_Cursor newCursor; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = 0; - } else { - if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, - &new) != TCL_OK) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((int *) oldInternalPtr) = *((int *) internalPtr); - *((int *) internalPtr) = new; + if (nullOK && ObjectIsEmpty(valuePtr)) { + newCursor = None; + valuePtr = NULL; + } else { + newCursor = Tk_AllocCursorFromObj(interp, tkwin, valuePtr); + if (newCursor == None) { + return TCL_ERROR; } - break; } - case TK_OPTION_WINDOW: { - Tk_Window new; + if (internalPtr != NULL) { + *((Tk_Cursor *) oldInternalPtr) = *((Tk_Cursor *) internalPtr); + *((Tk_Cursor *) internalPtr) = newCursor; + } + Tk_DefineCursor(tkwin, newCursor); + break; + } + case TK_OPTION_JUSTIFY: { + Tk_Justify newJustify; - if (nullOK && ObjectIsEmpty(valuePtr)) { - valuePtr = NULL; - new = None; - } else { - if (TkGetWindowFromObj(interp, tkwin, valuePtr, &new) - != TCL_OK) { - return TCL_ERROR; - } - } - if (internalPtr != NULL) { - *((Tk_Window *) oldInternalPtr) = *((Tk_Window *) internalPtr); - *((Tk_Window *) internalPtr) = new; + if (Tk_GetJustifyFromObj(interp, valuePtr, &newJustify) != TCL_OK) { + return TCL_ERROR; + } + if (internalPtr != NULL) { + *((Tk_Justify *) oldInternalPtr) = *((Tk_Justify *) internalPtr); + *((Tk_Justify *) internalPtr) = newJustify; + } + break; + } + case TK_OPTION_ANCHOR: { + Tk_Anchor newAnchor; + + if (Tk_GetAnchorFromObj(interp, valuePtr, &newAnchor) != TCL_OK) { + return TCL_ERROR; + } + if (internalPtr != NULL) { + *((Tk_Anchor *) oldInternalPtr) = *((Tk_Anchor *) internalPtr); + *((Tk_Anchor *) internalPtr) = newAnchor; + } + break; + } + case TK_OPTION_PIXELS: { + int newPixels; + + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newPixels = 0; + } else { + if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, + &newPixels) != TCL_OK) { + return TCL_ERROR; } - break; } - case TK_OPTION_CUSTOM: { - Tk_ObjCustomOption *custom = optionPtr->extra.custom; - if (custom->setProc(custom->clientData, interp, tkwin, - &valuePtr, recordPtr, optionPtr->specPtr->internalOffset, - (char *)oldInternalPtr, - optionPtr->specPtr->flags) != TCL_OK) { + if (internalPtr != NULL) { + *((int *) oldInternalPtr) = *((int *) internalPtr); + *((int *) internalPtr) = newPixels; + } + break; + } + case TK_OPTION_WINDOW: { + Tk_Window newWin; + + if (nullOK && ObjectIsEmpty(valuePtr)) { + valuePtr = NULL; + newWin = None; + } else { + if (TkGetWindowFromObj(interp, tkwin, valuePtr, + &newWin) != TCL_OK) { return TCL_ERROR; } - break; } - - default: { - char buf[40+TCL_INTEGER_SPACE]; - sprintf(buf, "bad config table: unknown type %d", - optionPtr->specPtr->type); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + if (internalPtr != NULL) { + *((Tk_Window *) oldInternalPtr) = *((Tk_Window *) internalPtr); + *((Tk_Window *) internalPtr) = newWin; + } + break; + } + case TK_OPTION_CUSTOM: { + Tk_ObjCustomOption *custom = optionPtr->extra.custom; + + if (custom->setProc(custom->clientData, interp, tkwin, + &valuePtr, recordPtr, optionPtr->specPtr->internalOffset, + (char *)oldInternalPtr, optionPtr->specPtr->flags) != TCL_OK) { return TCL_ERROR; } + break; + } + + { + char buf[40+TCL_INTEGER_SPACE]; + + default: + sprintf(buf, "bad config table: unknown type %d", + optionPtr->specPtr->type); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_ERROR; + } } /* - * Release resources associated with the old value, if we're not - * returning it to the caller, then install the new object value into - * the record. + * Release resources associated with the old value, if we're not returning + * it to the caller, then install the new object value into the record. */ if (savedOptionPtr == NULL) { @@ -990,12 +978,11 @@ DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr) * * ObjectIsEmpty -- * - * This procedure tests whether the string value of an object is - * empty. + * This function tests whether the string value of an object is empty. * * Results: - * The return value is 1 if the string value of objPtr has length - * zero, and 0 otherwise. + * The return value is 1 if the string value of objPtr has length zero, + * and 0 otherwise. * * Side effects: * None. @@ -1004,8 +991,8 @@ DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin, savedOptionPtr) */ static int -ObjectIsEmpty(objPtr) - Tcl_Obj *objPtr; /* Object to test. May be NULL. */ +ObjectIsEmpty( + Tcl_Obj *objPtr) /* Object to test. May be NULL. */ { int length; @@ -1024,15 +1011,14 @@ ObjectIsEmpty(objPtr) * * GetOption -- * - * This procedure searches through a chained option table to find - * the entry for a particular option name. + * This function searches through a chained option table to find the + * entry for a particular option name. * * Results: - * The return value is a pointer to the matching entry, or NULL - * if no matching entry could be found. - * Note: if the matching entry is a synonym then this procedure - * returns a pointer to the synonym entry, *not* the "real" entry - * that the synonym refers to. + * The return value is a pointer to the matching entry, or NULL if no + * matching entry could be found. Note: if the matching entry is a + * synonym then this function returns a pointer to the synonym entry, + * *not* the "real" entry that the synonym refers to. * * Side effects: * None. @@ -1041,10 +1027,10 @@ ObjectIsEmpty(objPtr) */ static Option * -GetOption(name, tablePtr) - CONST char *name; /* String balue to be looked up in the - * option table. */ - OptionTable *tablePtr; /* Table in which to look up name. */ +GetOption( + CONST char *name, /* String balue to be looked up in the option + * table. */ + OptionTable *tablePtr) /* Table in which to look up name. */ { Option *bestPtr, *optionPtr; OptionTable *tablePtr2; @@ -1052,14 +1038,13 @@ GetOption(name, tablePtr) int count; /* - * Search through all of the option tables in the chain to find the - * best match. Some tricky aspects: + * Search through all of the option tables in the chain to find the best + * match. Some tricky aspects: * * 1. We have to accept unique abbreviations. - * 2. The same name could appear in different tables in the chain. - * If this happens, we use the entry from the first table. We - * have to be careful to distinguish this case from an ambiguous - * abbreviation. + * 2. The same name could appear in different tables in the chain. If this + * happens, we use the entry from the first table. We have to be + * careful to distinguish this case from an ambiguous abbreviation. */ bestPtr = NULL; @@ -1071,40 +1056,38 @@ GetOption(name, tablePtr) *p1 == *p2; p1++, p2++) { if (*p1 == 0) { /* - * This is an exact match. We're done. + * This is an exact match. We're done. */ - bestPtr = optionPtr; - goto done; + return optionPtr; } } if (*p1 == 0) { /* - * The name is an abbreviation for this option. Keep - * to make sure that the abbreviation only matches one - * option name. If we've already found a match in the - * past, then it is an error unless the full names for - * the two options are identical; in this case, the first - * option overrides the second. + * The name is an abbreviation for this option. Keep to make + * sure that the abbreviation only matches one option name. + * If we've already found a match in the past, then it is an + * error unless the full names for the two options are + * identical; in this case, the first option overrides the + * second. */ if (bestPtr == NULL) { bestPtr = optionPtr; - } else { - if (strcmp(bestPtr->specPtr->optionName, - optionPtr->specPtr->optionName) != 0) { - goto error; - } + } else if (strcmp(bestPtr->specPtr->optionName, + optionPtr->specPtr->optionName) != 0) { + return NULL; } } } } - done: - return bestPtr; + /* + * Return whatever we have found, which could be NULL if nothing + * matched. The multiple-matching case is handled above. + */ - error: - return NULL; + return bestPtr; } /* @@ -1112,32 +1095,30 @@ GetOption(name, tablePtr) * * GetOptionFromObj -- * - * This procedure searches through a chained option table to find - * the entry for a particular option name. + * This function searches through a chained option table to find the + * entry for a particular option name. * * Results: - * The return value is a pointer to the matching entry, or NULL - * if no matching entry could be found. If NULL is returned and - * interp is not NULL than an error message is left in its result. - * Note: if the matching entry is a synonym then this procedure - * returns a pointer to the synonym entry, *not* the "real" entry - * that the synonym refers to. + * The return value is a pointer to the matching entry, or NULL if no + * matching entry could be found. If NULL is returned and interp is not + * NULL than an error message is left in its result. Note: if the + * matching entry is a synonym then this function returns a pointer to + * the synonym entry, *not* the "real" entry that the synonym refers to. * * Side effects: - * Information about the matching entry is cached in the object - * containing the name, so that future lookups can proceed more - * quickly. + * Information about the matching entry is cached in the object + * containing the name, so that future lookups can proceed more quickly. * *---------------------------------------------------------------------- */ static Option * -GetOptionFromObj(interp, objPtr, tablePtr) - Tcl_Interp *interp; /* Used only for error reporting; if NULL - * no message is left after an error. */ - Tcl_Obj *objPtr; /* Object whose string value is to be - * looked up in the option table. */ - OptionTable *tablePtr; /* Table in which to look up objPtr. */ +GetOptionFromObj( + Tcl_Interp *interp, /* Used only for error reporting; if NULL no + * message is left after an error. */ + Tcl_Obj *objPtr, /* Object whose string value is to be looked + * up in the option table. */ + OptionTable *tablePtr) /* Table in which to look up objPtr. */ { Option *bestPtr; char *name; @@ -1147,16 +1128,16 @@ GetOptionFromObj(interp, objPtr, tablePtr) */ if (objPtr->typePtr == &tkOptionObjType) { - if (objPtr->internalRep.twoPtrValue.ptr1 == (VOID *) tablePtr) { - return (Option *) objPtr->internalRep.twoPtrValue.ptr2; - } + if (objPtr->internalRep.twoPtrValue.ptr1 == (void *) tablePtr) { + return (Option *) objPtr->internalRep.twoPtrValue.ptr2; + } } /* * The answer isn't cached. */ - name = Tcl_GetStringFromObj(objPtr, NULL); + name = Tcl_GetString(objPtr); bestPtr = GetOption(name, tablePtr); if (bestPtr == NULL) { goto error; @@ -1166,15 +1147,14 @@ GetOptionFromObj(interp, objPtr, tablePtr) && (objPtr->typePtr->freeIntRepProc != NULL)) { objPtr->typePtr->freeIntRepProc(objPtr); } - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tablePtr; - objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) bestPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr; + objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr; objPtr->typePtr = &tkOptionObjType; return bestPtr; - error: + error: if (interp != NULL) { - Tcl_AppendResult(interp, "unknown option \"", name, - "\"", (char *) NULL); + Tcl_AppendResult(interp, "unknown option \"", name, "\"", NULL); } return NULL; } @@ -1184,29 +1164,28 @@ GetOptionFromObj(interp, objPtr, tablePtr) * * TkGetOptionSpec -- * - * This procedure searches through a chained option table to find - * the option spec for a particular option name. + * This function searches through a chained option table to find the + * option spec for a particular option name. * * Results: - * The return value is a pointer to the option spec of the matching - * entry, or NULL if no matching entry could be found. - * Note: if the matching entry is a synonym then this procedure - * returns a pointer to the option spec of the synonym entry, *not* - * the "real" entry that the synonym refers to. - * Note: this call is primarily used by the style management code - * (tkStyle.c) to look up an element's option spec into a widget's - * option table. + * The return value is a pointer to the option spec of the matching + * entry, or NULL if no matching entry could be found. Note: if the + * matching entry is a synonym then this function returns a pointer to + * the option spec of the synonym entry, *not* the "real" entry that the + * synonym refers to. Note: this call is primarily used by the style + * management code (tkStyle.c) to look up an element's option spec into a + * widget's option table. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ CONST Tk_OptionSpec * -TkGetOptionSpec(name, optionTable) - CONST char *name; /* String value to be looked up. */ - Tk_OptionTable optionTable; /* Table in which to look up name. */ +TkGetOptionSpec( + CONST char *name, /* String value to be looked up. */ + Tk_OptionTable optionTable) /* Table in which to look up name. */ { Option *optionPtr; @@ -1222,14 +1201,14 @@ TkGetOptionSpec(name, optionTable) * * SetOptionFromAny -- * - * This procedure is called to convert a Tcl object to option - * internal form. However, this doesn't make sense (need to have a - * table of options in order to do the conversion) so the - * procedure always generates an error. + * This function is called to convert a Tcl object to option internal + * form. However, this doesn't make sense (need to have a table of + * options in order to do the conversion) so the function always + * generates an error. * * Results: - * The return value is always TCL_ERROR, and an error message is - * left in interp's result if interp isn't NULL. + * The return value is always TCL_ERROR, and an error message is left in + * interp's result if interp isn't NULL. * * Side effects: * None. @@ -1238,9 +1217,9 @@ TkGetOptionSpec(name, optionTable) */ static int -SetOptionFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr; /* The object to convert. */ +SetOptionFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + register Tcl_Obj *objPtr) /* The object to convert. */ { Tcl_AppendToObj(Tcl_GetObjResult(interp), "can't convert value to option except via GetOptionFromObj API", @@ -1253,53 +1232,47 @@ SetOptionFromAny(interp, objPtr) * * Tk_SetOptions -- * - * Process one or more name-value pairs for configuration options - * and fill in fields of a record with new values. + * Process one or more name-value pairs for configuration options and + * fill in fields of a record with new values. * * Results: - * If all goes well then TCL_OK is returned and the old values of - * any modified objects are saved in *savePtr, if it isn't NULL (the - * caller must eventually call Tk_RestoreSavedOptions or - * Tk_FreeSavedOptions to free the contents of *savePtr). In - * addition, if maskPtr isn't NULL then *maskPtr is filled in with - * the OR of the typeMask bits from all modified options. If an - * error occurs then TCL_ERROR is returned and a message - * is left in interp's result unless interp is NULL; nothing is + * If all goes well then TCL_OK is returned and the old values of any + * modified objects are saved in *savePtr, if it isn't NULL (the caller + * must eventually call Tk_RestoreSavedOptions or Tk_FreeSavedOptions to + * free the contents of *savePtr). In addition, if maskPtr isn't NULL + * then *maskPtr is filled in with the OR of the typeMask bits from all + * modified options. If an error occurs then TCL_ERROR is returned and a + * message is left in interp's result unless interp is NULL; nothing is * saved in *savePtr or *maskPtr in this case. * * Side effects: - * The fields of recordPtr get filled in with object pointers - * from objc/objv. Old information in widgRec's fields gets - * recycled. Information may be left at *savePtr. + * The fields of recordPtr get filled in with object pointers from + * objc/objv. Old information in widgRec's fields gets recycled. + * Information may be left at *savePtr. * *-------------------------------------------------------------- */ int -Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr, - maskPtr) - Tcl_Interp *interp; /* Interpreter for error reporting. - * If NULL, then no error message is - * returned.*/ - char *recordPtr; /* The record to configure. */ - Tk_OptionTable optionTable; /* Describes valid options. */ - int objc; /* The number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Contains one or more name-value - * pairs. */ - Tk_Window tkwin; /* Window associated with the thing - * being configured; needed for some - * options (such as colors). */ - Tk_SavedOptions *savePtr; /* If non-NULL, the old values of - * modified options are saved here - * so that they can be restored - * after an error. */ - int *maskPtr; /* It non-NULL, this word is modified - * on a successful return to hold the - * bit-wise OR of the typeMask fields - * of all options that were modified - * by this call. Used by the caller - * to figure out which options - * actually changed. */ +Tk_SetOptions( + Tcl_Interp *interp, /* Interpreter for error reporting. If NULL, + * then no error message is returned.*/ + char *recordPtr, /* The record to configure. */ + Tk_OptionTable optionTable, /* Describes valid options. */ + int objc, /* The number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Contains one or more name-value pairs. */ + Tk_Window tkwin, /* Window associated with the thing being + * configured; needed for some options (such + * as colors). */ + Tk_SavedOptions *savePtr, /* If non-NULL, the old values of modified + * options are saved here so that they can be + * restored after an error. */ + int *maskPtr) /* It non-NULL, this word is modified on a + * successful return to hold the bit-wise OR + * of the typeMask fields of all options that + * were modified by this call. Used by the + * caller to figure out which options actually + * changed. */ { OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; @@ -1315,8 +1288,8 @@ Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr, lastSavePtr = savePtr; /* - * Scan through all of the arguments, processing those - * that match entries in the option table. + * Scan through all of the arguments, processing those that match entries + * in the option table. */ mask = 0; @@ -1333,19 +1306,18 @@ Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr, if (interp != NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "value for \"", Tcl_GetStringFromObj(*objv, NULL), - "\" missing", (char *) NULL); + "\" missing", NULL); goto error; } } if ((savePtr != NULL) && (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) { /* - * We've run out of space for saving old option values. Allocate + * We've run out of space for saving old option values. Allocate * more space. */ - newSavePtr = (Tk_SavedOptions *) ckalloc(sizeof( - Tk_SavedOptions)); + newSavePtr = (Tk_SavedOptions *) ckalloc(sizeof(Tk_SavedOptions)); newSavePtr->recordPtr = recordPtr; newSavePtr->tkwin = tkwin; newSavePtr->numItems = 0; @@ -1355,7 +1327,7 @@ Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr, } if (DoObjConfig(interp, recordPtr, optionPtr, objv[1], tkwin, (savePtr != NULL) ? &lastSavePtr->items[lastSavePtr->numItems] - : (Tk_SavedOption *) NULL) != TCL_OK) { + : NULL) != TCL_OK) { char msg[100]; sprintf(msg, "\n (processing \"%.40s\" option)", @@ -1373,7 +1345,7 @@ Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr, } return TCL_OK; - error: + error: if (savePtr != NULL) { Tk_RestoreSavedOptions(savePtr); } @@ -1385,38 +1357,38 @@ Tk_SetOptions(interp, recordPtr, optionTable, objc, objv, tkwin, savePtr, * * Tk_RestoreSavedOptions -- * - * This procedure undoes the effect of a previous call to - * Tk_SetOptions by restoring all of the options to their value - * before the call to Tk_SetOptions. + * This function undoes the effect of a previous call to Tk_SetOptions by + * restoring all of the options to their value before the call to + * Tk_SetOptions. * * Results: * None. * * Side effects: - * The configutation record is restored and all the information - * stored in savePtr is freed. + * The configutation record is restored and all the information stored in + * savePtr is freed. * *---------------------------------------------------------------------- */ void -Tk_RestoreSavedOptions(savePtr) - Tk_SavedOptions *savePtr; /* Holds saved option information; must - * have been passed to Tk_SetOptions. */ +Tk_RestoreSavedOptions( + Tk_SavedOptions *savePtr) /* Holds saved option information; must have + * been passed to Tk_SetOptions. */ { int i; Option *optionPtr; Tcl_Obj *newPtr; /* New object value of option, which we - * replace with old value and free. Taken - * from record. */ + * replace with old value and free. Taken from + * record. */ char *internalPtr; /* Points to internal value of option in * record. */ CONST Tk_OptionSpec *specPtr; /* - * Be sure to restore the options in the opposite order they were - * set. This is important because it's possible that the same - * option name was used twice in a single call to Tk_SetOptions. + * Be sure to restore the options in the opposite order they were set. + * This is important because it's possible that the same option name was + * used twice in a single call to Tk_SetOptions. */ if (savePtr->nextPtr != NULL) { @@ -1429,8 +1401,8 @@ Tk_RestoreSavedOptions(savePtr) specPtr = optionPtr->specPtr; /* - * First free the new value of the option, which is currently - * in the record. + * First free the new value of the option, which is currently in the + * record. */ if (specPtr->objOffset >= 0) { @@ -1459,101 +1431,69 @@ Tk_RestoreSavedOptions(savePtr) = savePtr->items[i].valuePtr; } if (specPtr->internalOffset >= 0) { + register char *ptr = (char *) &savePtr->items[i].internalForm; + switch (specPtr->type) { - case TK_OPTION_BOOLEAN: { - *((int *) internalPtr) - = *((int *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_INT: { - *((int *) internalPtr) - = *((int *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_DOUBLE: { - *((double *) internalPtr) - = *((double *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_STRING: { - *((char **) internalPtr) - = *((char **) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_STRING_TABLE: { - *((int *) internalPtr) - = *((int *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_COLOR: { - *((XColor **) internalPtr) - = *((XColor **) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_FONT: { - *((Tk_Font *) internalPtr) - = *((Tk_Font *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_STYLE: { - *((Tk_Style *) internalPtr) - = *((Tk_Style *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_BITMAP: { - *((Pixmap *) internalPtr) - = *((Pixmap *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_BORDER: { - *((Tk_3DBorder *) internalPtr) - = *((Tk_3DBorder *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_RELIEF: { - *((int *) internalPtr) - = *((int *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_CURSOR: { - *((Tk_Cursor *) internalPtr) - = *((Tk_Cursor *) &savePtr->items[i].internalForm); - Tk_DefineCursor(savePtr->tkwin, - *((Tk_Cursor *) internalPtr)); - break; - } - case TK_OPTION_JUSTIFY: { - *((Tk_Justify *) internalPtr) - = *((Tk_Justify *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_ANCHOR: { - *((Tk_Anchor *) internalPtr) - = *((Tk_Anchor *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_PIXELS: { - *((int *) internalPtr) - = *((int *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_WINDOW: { - *((Tk_Window *) internalPtr) - = *((Tk_Window *) &savePtr->items[i].internalForm); - break; - } - case TK_OPTION_CUSTOM: { - Tk_ObjCustomOption *custom = optionPtr->extra.custom; - if (custom->restoreProc != NULL) { - custom->restoreProc(custom->clientData, savePtr->tkwin, - internalPtr, - (char *)&savePtr->items[i].internalForm); - } - break; - } - default: { - panic("bad option type in Tk_RestoreSavedOptions"); + case TK_OPTION_BOOLEAN: + *((int *) internalPtr) = *((int *) ptr); + break; + case TK_OPTION_INT: + *((int *) internalPtr) = *((int *) ptr); + break; + case TK_OPTION_DOUBLE: + *((double *) internalPtr) = *((double *) ptr); + break; + case TK_OPTION_STRING: + *((char **) internalPtr) = *((char **) ptr); + break; + case TK_OPTION_STRING_TABLE: + *((int *) internalPtr) = *((int *) ptr); + break; + case TK_OPTION_COLOR: + *((XColor **) internalPtr) = *((XColor **) ptr); + break; + case TK_OPTION_FONT: + *((Tk_Font *) internalPtr) = *((Tk_Font *) ptr); + break; + case TK_OPTION_STYLE: + *((Tk_Style *) internalPtr) = *((Tk_Style *) ptr); + break; + case TK_OPTION_BITMAP: + *((Pixmap *) internalPtr) = *((Pixmap *) ptr); + break; + case TK_OPTION_BORDER: + *((Tk_3DBorder *) internalPtr) = *((Tk_3DBorder *) ptr); + break; + case TK_OPTION_RELIEF: + *((int *) internalPtr) = *((int *) ptr); + break; + case TK_OPTION_CURSOR: + *((Tk_Cursor *) internalPtr) = *((Tk_Cursor *) ptr); + Tk_DefineCursor(savePtr->tkwin, *((Tk_Cursor *) internalPtr)); + break; + case TK_OPTION_JUSTIFY: + *((Tk_Justify *) internalPtr) = *((Tk_Justify *) ptr); + break; + case TK_OPTION_ANCHOR: + *((Tk_Anchor *) internalPtr) = *((Tk_Anchor *) ptr); + break; + case TK_OPTION_PIXELS: + *((int *) internalPtr) = *((int *) ptr); + break; + case TK_OPTION_WINDOW: + *((Tk_Window *) internalPtr) = *((Tk_Window *) ptr); + break; + case TK_OPTION_CUSTOM: { + Tk_ObjCustomOption *custom = optionPtr->extra.custom; + + if (custom->restoreProc != NULL) { + custom->restoreProc(custom->clientData, savePtr->tkwin, + internalPtr, ptr); } + break; + } + default: + Tcl_Panic("bad option type in Tk_RestoreSavedOptions"); } } } @@ -1565,8 +1505,8 @@ Tk_RestoreSavedOptions(savePtr) * * Tk_FreeSavedOptions -- * - * Free all of the saved configuration option values from a - * previous call to Tk_SetOptions. + * Free all of the saved configuration option values from a previous call + * to Tk_SetOptions. * * Results: * None. @@ -1578,9 +1518,9 @@ Tk_RestoreSavedOptions(savePtr) */ void -Tk_FreeSavedOptions(savePtr) - Tk_SavedOptions *savePtr; /* Contains options saved in a previous - * call to Tk_SetOptions. */ +Tk_FreeSavedOptions( + Tk_SavedOptions *savePtr) /* Contains options saved in a previous call + * to Tk_SetOptions. */ { int count; Tk_SavedOption *savedOptionPtr; @@ -1613,25 +1553,25 @@ Tk_FreeSavedOptions(savePtr) * None. * * Side effects: - * All of the Tcl_Obj's in recordPtr that are controlled by - * configuration options in optionTable are freed. + * All of the Tcl_Obj's in recordPtr that are controlled by configuration + * options in optionTable are freed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ void -Tk_FreeConfigOptions(recordPtr, optionTable, tkwin) - char *recordPtr; /* Record whose fields contain current - * values for options. */ - Tk_OptionTable optionTable; /* Describes legal options. */ - Tk_Window tkwin; /* Window associated with recordPtr; needed +Tk_FreeConfigOptions( + char *recordPtr, /* Record whose fields contain current values + * for options. */ + Tk_OptionTable optionTable, /* Describes legal options. */ + Tk_Window tkwin) /* Window associated with recordPtr; needed * for freeing some options. */ { OptionTable *tablePtr; Option *optionPtr; int count; - Tcl_Obj **oldPtrPtr, *oldPtr; + Tcl_Obj **oldPtrPtr, *oldPtr; char *oldInternalPtr; CONST Tk_OptionSpec *specPtr; @@ -1670,114 +1610,113 @@ Tk_FreeConfigOptions(recordPtr, optionTable, tkwin) * * FreeResources -- * - * Free system resources associated with a configuration option, - * such as colors or fonts. + * Free system resources associated with a configuration option, such as + * colors or fonts. * * Results: * None. * * Side effects: - * Any system resources associated with objPtr are released. However, + * Any system resources associated with objPtr are released. However, * objPtr itself is not freed. * *---------------------------------------------------------------------- */ static void -FreeResources(optionPtr, objPtr, internalPtr, tkwin) - Option *optionPtr; /* Description of the configuration option. */ - Tcl_Obj *objPtr; /* The current value of the option, specified +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 + char *internalPtr, /* A pointer to an internal representation for * the option's value, such as an int or - * (XColor *). Only valid if + * (XColor *). Only valid if * optionPtr->specPtr->internalOffset >= 0. */ - Tk_Window tkwin; /* The window in which this option is used. */ + Tk_Window tkwin) /* The window in which this option is used. */ { int internalFormExists; /* * If there exists an internal form for the value, use it to free - * resources (also zero out the internal form). If there is no - * internal form, then use the object form. + * resources (also zero out the internal form). If there is no internal + * form, then use the object form. */ internalFormExists = optionPtr->specPtr->internalOffset >= 0; switch (optionPtr->specPtr->type) { - case TK_OPTION_STRING: - if (internalFormExists) { - if (*((char **) internalPtr) != NULL) { - ckfree(*((char **) internalPtr)); - *((char **) internalPtr) = NULL; - } - } - break; - case TK_OPTION_COLOR: - if (internalFormExists) { - if (*((XColor **) internalPtr) != NULL) { - Tk_FreeColor(*((XColor **) internalPtr)); - *((XColor **) internalPtr) = NULL; - } - } else if (objPtr != NULL) { - Tk_FreeColorFromObj(tkwin, objPtr); - } - break; - case TK_OPTION_FONT: - if (internalFormExists) { - Tk_FreeFont(*((Tk_Font *) internalPtr)); - *((Tk_Font *) internalPtr) = NULL; - } else if (objPtr != NULL) { - Tk_FreeFontFromObj(tkwin, objPtr); - } - break; - case TK_OPTION_STYLE: - if (internalFormExists) { - Tk_FreeStyle(*((Tk_Style *) internalPtr)); - *((Tk_Style *) internalPtr) = NULL; - } else if (objPtr != NULL) { - Tk_FreeStyleFromObj(objPtr); - } - break; - case TK_OPTION_BITMAP: - if (internalFormExists) { - if (*((Pixmap *) internalPtr) != None) { - Tk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *) internalPtr)); - *((Pixmap *) internalPtr) = None; - } - } else if (objPtr != NULL) { - Tk_FreeBitmapFromObj(tkwin, objPtr); - } - break; - case TK_OPTION_BORDER: - if (internalFormExists) { - if (*((Tk_3DBorder *) internalPtr) != NULL) { - Tk_Free3DBorder(*((Tk_3DBorder *) internalPtr)); - *((Tk_3DBorder *) internalPtr) = NULL; - } - } else if (objPtr != NULL) { - Tk_Free3DBorderFromObj(tkwin, objPtr); - } - break; - case TK_OPTION_CURSOR: - if (internalFormExists) { - if (*((Tk_Cursor *) internalPtr) != None) { - Tk_FreeCursor(Tk_Display(tkwin), - *((Tk_Cursor *) internalPtr)); - *((Tk_Cursor *) internalPtr) = None; - } - } else if (objPtr != NULL) { - Tk_FreeCursorFromObj(tkwin, objPtr); - } - break; - case TK_OPTION_CUSTOM: { - Tk_ObjCustomOption *custom = optionPtr->extra.custom; - if (internalFormExists && custom->freeProc != NULL) { - custom->freeProc(custom->clientData, tkwin, internalPtr); - } - break; - } - default: - break; + case TK_OPTION_STRING: + if (internalFormExists) { + if (*((char **) internalPtr) != NULL) { + ckfree(*((char **) internalPtr)); + *((char **) internalPtr) = NULL; + } + } + break; + case TK_OPTION_COLOR: + if (internalFormExists) { + if (*((XColor **) internalPtr) != NULL) { + Tk_FreeColor(*((XColor **) internalPtr)); + *((XColor **) internalPtr) = NULL; + } + } else if (objPtr != NULL) { + Tk_FreeColorFromObj(tkwin, objPtr); + } + break; + case TK_OPTION_FONT: + if (internalFormExists) { + Tk_FreeFont(*((Tk_Font *) internalPtr)); + *((Tk_Font *) internalPtr) = NULL; + } else if (objPtr != NULL) { + Tk_FreeFontFromObj(tkwin, objPtr); + } + break; + case TK_OPTION_STYLE: + if (internalFormExists) { + Tk_FreeStyle(*((Tk_Style *) internalPtr)); + *((Tk_Style *) internalPtr) = NULL; + } else if (objPtr != NULL) { + Tk_FreeStyleFromObj(objPtr); + } + break; + case TK_OPTION_BITMAP: + if (internalFormExists) { + if (*((Pixmap *) internalPtr) != None) { + Tk_FreeBitmap(Tk_Display(tkwin), *((Pixmap *) internalPtr)); + *((Pixmap *) internalPtr) = None; + } + } else if (objPtr != NULL) { + Tk_FreeBitmapFromObj(tkwin, objPtr); + } + break; + case TK_OPTION_BORDER: + if (internalFormExists) { + if (*((Tk_3DBorder *) internalPtr) != NULL) { + Tk_Free3DBorder(*((Tk_3DBorder *) internalPtr)); + *((Tk_3DBorder *) internalPtr) = NULL; + } + } else if (objPtr != NULL) { + Tk_Free3DBorderFromObj(tkwin, objPtr); + } + break; + case TK_OPTION_CURSOR: + if (internalFormExists) { + if (*((Tk_Cursor *) internalPtr) != None) { + Tk_FreeCursor(Tk_Display(tkwin), *((Tk_Cursor *) internalPtr)); + *((Tk_Cursor *) internalPtr) = None; + } + } else if (objPtr != NULL) { + Tk_FreeCursorFromObj(tkwin, objPtr); + } + break; + case TK_OPTION_CUSTOM: { + Tk_ObjCustomOption *custom = optionPtr->extra.custom; + if (internalFormExists && custom->freeProc != NULL) { + custom->freeProc(custom->clientData, tkwin, internalPtr); + } + break; + } + default: + break; } } @@ -1786,23 +1725,21 @@ FreeResources(optionPtr, objPtr, internalPtr, tkwin) * * Tk_GetOptionInfo -- * - * Returns a list object containing complete information about - * either a single option or all the configuration options in a - * table. + * Returns a list object containing complete information about either a + * single option or all the configuration options in a table. * * Results: - * This procedure normally returns a pointer to an object. - * If namePtr isn't NULL, then the result object is a list with - * five elements: the option's name, its database name, database - * class, default value, and current value. If the option is a - * synonym then the list will contain only two values: the option - * name and the name of the option it refers to. If namePtr is - * NULL, then information is returned for every option in the - * option table: the result will have one sub-list (in the form - * described above) for each option in the table. If an error - * occurs (e.g. because namePtr isn't valid) then NULL is returned - * and an error message will be left in interp's result unless - * interp is NULL. + + * This function normally returns a pointer to an object. If namePtr + * isn't NULL, then the result object is a list with five elements: the + * option's name, its database name, database class, default value, and + * current value. If the option is a synonym then the list will contain + * only two values: the option name and the name of the option it refers + * to. If namePtr is NULL, then information is returned for every option + * in the option table: the result will have one sub-list (in the form + * described above) for each option in the table. If an error occurs + * (e.g. because namePtr isn't valid) then NULL is returned and an error + * message will be left in interp's result unless interp is NULL. * * Side effects: * None. @@ -1811,18 +1748,18 @@ FreeResources(optionPtr, objPtr, internalPtr, tkwin) */ Tcl_Obj * -Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin) - Tcl_Interp *interp; /* Interpreter for error reporting. If - * NULL, then no error message is created. */ - char *recordPtr; /* Record whose fields contain current - * values for options. */ - Tk_OptionTable optionTable; /* Describes all the legal options. */ - Tcl_Obj *namePtr; /* If non-NULL, the string value selects - * a single option whose info is to be - * returned. Otherwise info is returned for - * all options in optionTable. */ - Tk_Window tkwin; /* Window associated with recordPtr; needed - * to compute correct default value for some +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 + * for options. */ + Tk_OptionTable optionTable, /* Describes all the legal options. */ + Tcl_Obj *namePtr, /* If non-NULL, the string value selects a + * single option whose info is to be returned. + * Otherwise info is returned for all options + * in optionTable. */ + Tk_Window tkwin) /* Window associated with recordPtr; needed to + * compute correct default value for some * options. */ { Tcl_Obj *resultPtr; @@ -1831,14 +1768,14 @@ Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin) int count; /* - * If information is only wanted for a single configuration - * spec, then handle that one spec specially. + * If information is only wanted for a single configuration spec, then + * handle that one spec specially. */ if (namePtr != NULL) { optionPtr = GetOptionFromObj(interp, namePtr, tablePtr); if (optionPtr == NULL) { - return (Tcl_Obj *) NULL; + return NULL; } if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) { optionPtr = optionPtr->extra.synonymPtr; @@ -1847,11 +1784,11 @@ Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin) } /* - * Loop through all the specs, creating a big list with all - * their information. + * Loop through all the specs, creating a big list with all their + * information. */ - resultPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); + resultPtr = Tcl_NewListObj(0, NULL); for (; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { for (optionPtr = tablePtr->options, count = tablePtr->numOptions; count > 0; optionPtr++, count--) { @@ -1867,12 +1804,12 @@ Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin) * * GetConfigList -- * - * Create a valid Tcl list holding the configuration information - * for a single configuration option. + * Create a valid Tcl list holding the configuration information for a + * single configuration option. * * Results: - * A Tcl list, dynamically allocated. The caller is expected to - * arrange for this list to be freed eventually. + * A Tcl list, dynamically allocated. The caller is expected to arrange + * for this list to be freed eventually. * * Side effects: * Memory is allocated. @@ -1881,37 +1818,37 @@ Tk_GetOptionInfo(interp, recordPtr, optionTable, namePtr, tkwin) */ static Tcl_Obj * -GetConfigList(recordPtr, optionPtr, tkwin) - char *recordPtr; /* Pointer to record holding current - * values of configuration options. */ - Option *optionPtr; /* Pointer to information describing a +GetConfigList( + char *recordPtr, /* Pointer to record holding current values of + * configuration options. */ + Option *optionPtr, /* Pointer to information describing a * particular option. */ - Tk_Window tkwin; /* Window corresponding to recordPtr. */ + Tk_Window tkwin) /* Window corresponding to recordPtr. */ { Tcl_Obj *listPtr, *elementPtr; - listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, + listPtr = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj(optionPtr->specPtr->optionName, -1)); if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) { elementPtr = Tcl_NewStringObj( optionPtr->extra.synonymPtr->specPtr->optionName, -1); - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr); + Tcl_ListObjAppendElement(NULL, listPtr, elementPtr); } else { if (optionPtr->dbNameUID == NULL) { elementPtr = Tcl_NewObj(); } else { elementPtr = Tcl_NewStringObj(optionPtr->dbNameUID, -1); } - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr); + Tcl_ListObjAppendElement(NULL, listPtr, elementPtr); if (optionPtr->dbClassUID == NULL) { elementPtr = Tcl_NewObj(); } else { elementPtr = Tcl_NewStringObj(optionPtr->dbClassUID, -1); } - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr); + Tcl_ListObjAppendElement(NULL, listPtr, elementPtr); if ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR) || (optionPtr->specPtr->type == TK_OPTION_BORDER)) @@ -1923,7 +1860,7 @@ GetConfigList(recordPtr, optionPtr, tkwin) } else { elementPtr = Tcl_NewObj(); } - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr); + Tcl_ListObjAppendElement(NULL, listPtr, elementPtr); if (optionPtr->specPtr->objOffset >= 0) { elementPtr = *((Tcl_Obj **) (recordPtr @@ -1934,7 +1871,7 @@ GetConfigList(recordPtr, optionPtr, tkwin) } else { elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin); } - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr); + Tcl_ListObjAppendElement(NULL, listPtr, elementPtr); } return listPtr; } @@ -1944,14 +1881,13 @@ GetConfigList(recordPtr, optionPtr, tkwin) * * GetObjectForOption -- * - * This procedure is called to create an object that contains the - * value for an option. It is invoked by GetConfigList and - * Tk_GetOptionValue when only the internal form of an option is - * stored in the record. + * This function is called to create an object that contains the value + * for an option. It is invoked by GetConfigList and Tk_GetOptionValue + * when only the internal form of an option is stored in the record. * * Results: - * The return value is a pointer to a Tcl object. The caller - * must call Tcl_IncrRefCount on this object to preserve it. + * The return value is a pointer to a Tcl object. The caller must call + * Tcl_IncrRefCount on this object to preserve it. * * Side effects: * None. @@ -1960,13 +1896,13 @@ GetConfigList(recordPtr, optionPtr, tkwin) */ static Tcl_Obj * -GetObjectForOption(recordPtr, optionPtr, tkwin) - char *recordPtr; /* Pointer to record holding current - * values of configuration options. */ - Option *optionPtr; /* Pointer to information describing an - * option whose internal value is stored - * in *recordPtr. */ - Tk_Window tkwin; /* Window corresponding to recordPtr. */ +GetObjectForOption( + char *recordPtr, /* Pointer to record holding current values of + * configuration options. */ + Option *optionPtr, /* Pointer to information describing an option + * whose internal value is stored in + * *recordPtr. */ + Tk_Window tkwin) /* Window corresponding to recordPtr. */ { Tcl_Obj *objPtr; char *internalPtr; /* Points to internal value of option in @@ -1975,107 +1911,103 @@ GetObjectForOption(recordPtr, optionPtr, tkwin) internalPtr = recordPtr + optionPtr->specPtr->internalOffset; objPtr = NULL; switch (optionPtr->specPtr->type) { - case TK_OPTION_BOOLEAN: { - objPtr = Tcl_NewIntObj(*((int *) internalPtr)); - break; - } - case TK_OPTION_INT: { - objPtr = Tcl_NewIntObj(*((int *) internalPtr)); - break; - } - case TK_OPTION_DOUBLE: { - objPtr = Tcl_NewDoubleObj(*((double *) internalPtr)); - break; + case TK_OPTION_BOOLEAN: + objPtr = Tcl_NewIntObj(*((int *) internalPtr)); + break; + case TK_OPTION_INT: + objPtr = Tcl_NewIntObj(*((int *) internalPtr)); + break; + case TK_OPTION_DOUBLE: + objPtr = Tcl_NewDoubleObj(*((double *) internalPtr)); + break; + case TK_OPTION_STRING: + objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1); + break; + case TK_OPTION_STRING_TABLE: + objPtr = Tcl_NewStringObj(((char **) optionPtr->specPtr->clientData)[ + *((int *) internalPtr)], -1); + break; + case TK_OPTION_COLOR: { + XColor *colorPtr = *((XColor **) internalPtr); + + if (colorPtr != NULL) { + objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1); + } + break; + } + case TK_OPTION_FONT: { + Tk_Font tkfont = *((Tk_Font *) internalPtr); + + if (tkfont != NULL) { + objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1); } - case TK_OPTION_STRING: { - objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1); - break; + break; + } + case TK_OPTION_STYLE: { + Tk_Style style = *((Tk_Style *) internalPtr); + + if (style != NULL) { + objPtr = Tcl_NewStringObj(Tk_NameOfStyle(style), -1); } - case TK_OPTION_STRING_TABLE: { + break; + } + case TK_OPTION_BITMAP: { + Pixmap pixmap = *((Pixmap *) internalPtr); + + if (pixmap != None) { objPtr = Tcl_NewStringObj( - ((char **) optionPtr->specPtr->clientData)[ - *((int *) internalPtr)], -1); - break; - } - case TK_OPTION_COLOR: { - XColor *colorPtr = *((XColor **) internalPtr); - if (colorPtr != NULL) { - objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1); - } - break; - } - case TK_OPTION_FONT: { - Tk_Font tkfont = *((Tk_Font *) internalPtr); - if (tkfont != NULL) { - objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1); - } - break; - } - case TK_OPTION_STYLE: { - Tk_Style style = *((Tk_Style *) internalPtr); - if (style != NULL) { - objPtr = Tcl_NewStringObj(Tk_NameOfStyle(style), -1); - } - break; - } - case TK_OPTION_BITMAP: { - Pixmap pixmap = *((Pixmap *) internalPtr); - if (pixmap != None) { - objPtr = Tcl_NewStringObj(Tk_NameOfBitmap(Tk_Display(tkwin), - pixmap), -1); - } - break; - } - case TK_OPTION_BORDER: { - Tk_3DBorder border = *((Tk_3DBorder *) internalPtr); - if (border != NULL) { - objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1); - } - break; - } - case TK_OPTION_RELIEF: { - objPtr = Tcl_NewStringObj(Tk_NameOfRelief( - *((int *) internalPtr)), -1); - break; - } - case TK_OPTION_CURSOR: { - Tk_Cursor cursor = *((Tk_Cursor *) internalPtr); - if (cursor != None) { - objPtr = Tcl_NewStringObj( - Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1); - } - break; + Tk_NameOfBitmap(Tk_Display(tkwin), pixmap), -1); } - case TK_OPTION_JUSTIFY: { - objPtr = Tcl_NewStringObj(Tk_NameOfJustify( - *((Tk_Justify *) internalPtr)), -1); - break; - } - case TK_OPTION_ANCHOR: { - objPtr = Tcl_NewStringObj(Tk_NameOfAnchor( - *((Tk_Anchor *) internalPtr)), -1); - break; - } - case TK_OPTION_PIXELS: { - objPtr = Tcl_NewIntObj(*((int *) internalPtr)); - break; - } - case TK_OPTION_WINDOW: { - Tk_Window tkwin = *((Tk_Window *) internalPtr); - if (tkwin != NULL) { - objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1); - } - break; - } - case TK_OPTION_CUSTOM: { - Tk_ObjCustomOption *custom = optionPtr->extra.custom; - objPtr = custom->getProc(custom->clientData, tkwin, recordPtr, - optionPtr->specPtr->internalOffset); - break; + break; + } + case TK_OPTION_BORDER: { + Tk_3DBorder border = *((Tk_3DBorder *) internalPtr); + + if (border != NULL) { + objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1); } - default: { - panic("bad option type in GetObjectForOption"); + break; + } + case TK_OPTION_RELIEF: + objPtr = Tcl_NewStringObj(Tk_NameOfRelief(*((int *) internalPtr)), -1); + break; + case TK_OPTION_CURSOR: { + Tk_Cursor cursor = *((Tk_Cursor *) internalPtr); + + if (cursor != None) { + objPtr = Tcl_NewStringObj( + Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1); } + break; + } + case TK_OPTION_JUSTIFY: + objPtr = Tcl_NewStringObj(Tk_NameOfJustify( + *((Tk_Justify *) internalPtr)), -1); + break; + case TK_OPTION_ANCHOR: + objPtr = Tcl_NewStringObj(Tk_NameOfAnchor( + *((Tk_Anchor *) internalPtr)), -1); + break; + case TK_OPTION_PIXELS: + objPtr = Tcl_NewIntObj(*((int *) internalPtr)); + break; + case TK_OPTION_WINDOW: { + Tk_Window tkwin = *((Tk_Window *) internalPtr); + + if (tkwin != NULL) { + objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1); + } + break; + } + case TK_OPTION_CUSTOM: { + Tk_ObjCustomOption *custom = optionPtr->extra.custom; + + objPtr = custom->getProc(custom->clientData, tkwin, recordPtr, + optionPtr->specPtr->internalOffset); + break; + } + default: + Tcl_Panic("bad option type in GetObjectForOption"); } if (objPtr == NULL) { objPtr = Tcl_NewObj(); @@ -2088,14 +2020,13 @@ GetObjectForOption(recordPtr, optionPtr, tkwin) * * Tk_GetOptionValue -- * - * This procedure returns the current value of a configuration - * option. + * This function returns the current value of a configuration option. * * Results: - * The return value is the object holding the current value of - * the option given by namePtr. If no such option exists, then - * the return value is NULL and an error message is left in - * interp's result (if interp isn't NULL). + * The return value is the object holding the current value of the option + * given by namePtr. If no such option exists, then the return value is + * NULL and an error message is left in interp's result (if interp isn't + * NULL). * * Side effects: * None. @@ -2104,16 +2035,16 @@ GetObjectForOption(recordPtr, optionPtr, tkwin) */ Tcl_Obj * -Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin) - Tcl_Interp *interp; /* Interpreter for error reporting. If - * NULL then no messages are provided for +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 for options. */ - Tk_OptionTable optionTable; /* Describes legal options. */ - Tcl_Obj *namePtr; /* Gives the command-line name for the - * option whose value is to be returned. */ - Tk_Window tkwin; /* Window corresponding to recordPtr. */ + char *recordPtr, /* Record whose fields contain current values + * for options. */ + Tk_OptionTable optionTable, /* Describes legal options. */ + Tcl_Obj *namePtr, /* Gives the command-line name for the option + * whose value is to be returned. */ + Tk_Window tkwin) /* Window corresponding to recordPtr. */ { OptionTable *tablePtr = (OptionTable *) optionTable; Option *optionPtr; @@ -2127,16 +2058,16 @@ Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin) optionPtr = optionPtr->extra.synonymPtr; } if (optionPtr->specPtr->objOffset >= 0) { - resultPtr = *((Tcl_Obj **) (recordPtr + optionPtr->specPtr->objOffset)); + resultPtr = *((Tcl_Obj **) (recordPtr+optionPtr->specPtr->objOffset)); if (resultPtr == NULL) { /* * This option has a null value and is represented by a null - * object pointer. We can't return the null pointer, since that - * would indicate an error. Instead, return a new empty object. + * object pointer. We can't return the null pointer, since that + * would indicate an error. Instead, return a new empty object. */ - + resultPtr = Tcl_NewObj(); - } + } } else { resultPtr = GetObjectForOption(recordPtr, optionPtr, tkwin); } @@ -2148,19 +2079,17 @@ Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin) * * TkDebugConfig -- * - * This is a debugging procedure that returns information about - * one of the configuration tables that currently exists for an - * interpreter. + * This is a debugging function that returns information about one of the + * configuration tables that currently exists for an interpreter. * * Results: - * If the specified table exists in the given interpreter, then a - * list is returned describing the table and any other tables that - * it chains to: for each table there will be three list elements - * giving the reference count for the table, the number of elements - * in the table, and the command-line name for the first option - * in the table. If the table doesn't exist in the interpreter - * then an empty object is returned. The reference count for the - * returned object is 0. + * If the specified table exists in the given interpreter, then a list is + * returned describing the table and any other tables that it chains to: + * for each table there will be three list elements giving the reference + * count for the table, the number of elements in the table, and the + * command-line name for the first option in the table. If the table + * doesn't exist in the interpreter then an empty object is returned. + * The reference count for the returned object is 0. * * Side effects: * None. @@ -2169,12 +2098,12 @@ Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin) */ Tcl_Obj * -TkDebugConfig(interp, table) - Tcl_Interp *interp; /* Interpreter in which the table is - * defined. */ - Tk_OptionTable table; /* Table about which information is to - * be returned. May not necessarily - * exist in the interpreter anymore. */ +TkDebugConfig( + Tcl_Interp *interp, /* Interpreter in which the table is + * defined. */ + Tk_OptionTable table) /* Table about which information is to be + * returned. May not necessarily exist in the + * interpreter anymore. */ { OptionTable *tablePtr = (OptionTable *) table; Tcl_HashTable *hashTablePtr; @@ -2190,8 +2119,8 @@ TkDebugConfig(interp, table) } /* - * Scan all the tables for this interpreter to make sure that the - * one we want still is valid. + * Scan all the tables for this interpreter to make sure that the one we + * want still is valid. */ for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); @@ -2199,17 +2128,23 @@ TkDebugConfig(interp, table) hashEntryPtr = Tcl_NextHashEntry(&search)) { if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) { for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(tablePtr->refCount)); - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(tablePtr->numOptions)); - Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr, - Tcl_NewStringObj( - tablePtr->options[0].specPtr->optionName, - -1)); + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewStringObj( + tablePtr->options[0].specPtr->optionName, -1)); } break; } } return objPtr; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkConsole.c b/generic/tkConsole.c index 307b9b5..b10aaaf 100644 --- a/generic/tkConsole.c +++ b/generic/tkConsole.c @@ -1,15 +1,14 @@ -/* +/* * tkConsole.c -- * - * This file implements a Tcl console for systems that may not - * otherwise have access to a console. It uses the Text widget - * and provides special access via a console command. + * This file implements a Tcl console for systems that may not otherwise + * have access to a console. It uses the Text widget and provides special + * access via a console command. * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tk.h" @@ -23,8 +22,8 @@ */ typedef struct ConsoleInfo { - Tcl_Interp *consoleInterp; /* Interpreter displaying the console. */ - Tcl_Interp *interp; /* Interpreter controlled by console. */ + Tcl_Interp *consoleInterp; /* Interpreter displaying the console. */ + Tcl_Interp *interp; /* Interpreter controlled by console. */ int refCount; } ConsoleInfo; @@ -40,30 +39,26 @@ typedef struct ChannelData { int type; /* TCL_STDOUT or TCL_STDERR */ } ChannelData; -/* +/* * Prototypes for local procedures defined in this file: */ -static int ConsoleClose _ANSI_ARGS_((ClientData instanceData, - Tcl_Interp *interp)); -static void ConsoleDeleteProc _ANSI_ARGS_((ClientData clientData)); -static void ConsoleEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int ConsoleHandle _ANSI_ARGS_((ClientData instandeData, - int direction, ClientData *handlePtr)); -static int ConsoleInput _ANSI_ARGS_((ClientData instanceData, - char *buf, int toRead, int *errorCode)); -static int ConsoleObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int ConsoleOutput _ANSI_ARGS_((ClientData instanceData, - CONST char *buf, int toWrite, int *errorCode)); -static void ConsoleWatch _ANSI_ARGS_((ClientData instanceData, - int mask)); -static void DeleteConsoleInterp _ANSI_ARGS_((ClientData clientData)); -static void InterpDeleteProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp)); -static int InterpreterObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); +static int ConsoleClose(ClientData instanceData, Tcl_Interp *interp); +static void ConsoleDeleteProc(ClientData clientData); +static void ConsoleEventProc(ClientData clientData, XEvent *eventPtr); +static int ConsoleHandle(ClientData instanceData, + int direction, ClientData *handlePtr); +static int ConsoleInput(ClientData instanceData, + char *buf, int toRead, int *errorCode); +static int ConsoleObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int ConsoleOutput(ClientData instanceData, + CONST char *buf, int toWrite, int *errorCode); +static void ConsoleWatch(ClientData instanceData, int mask); +static void DeleteConsoleInterp(ClientData clientData); +static void InterpDeleteProc(ClientData clientData, Tcl_Interp *interp); +static int InterpreterObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); /* * This structure describes the channel type structure for file based IO: @@ -84,13 +79,12 @@ static Tcl_ChannelType consoleChannelType = { NULL, /* Always non-blocking.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ - NULL, /* wide seek proc */ - NULL, /* thread action proc */ + NULL, /* wide seek proc */ + NULL, /* thread action proc */ + NULL }; - #ifdef __WIN32__ - #include <windows.h> /* @@ -98,20 +92,21 @@ static Tcl_ChannelType consoleChannelType = { * * ShouldUseConsoleChannel * - * Check to see if console window should be used for a given - * standard channel + * Check to see if console window should be used for a given standard + * channel. * * Results: * None. * * Side effects: - * Creates the console channel and installs it as the standard - * channels. + * Creates the console channel and installs it as the standard channels. * *---------------------------------------------------------------------- */ -static int ShouldUseConsoleChannel(type) - int type; + +static int +ShouldUseConsoleChannel( + int type) { DWORD handleId; /* Standard handle to retrieve. */ DCB dcb; @@ -120,18 +115,18 @@ static int ShouldUseConsoleChannel(type) HANDLE handle; switch (type) { - case TCL_STDIN: - handleId = STD_INPUT_HANDLE; - break; - case TCL_STDOUT: - handleId = STD_OUTPUT_HANDLE; - break; - case TCL_STDERR: - handleId = STD_ERROR_HANDLE; - break; - default: - return 0; - break; + case TCL_STDIN: + handleId = STD_INPUT_HANDLE; + break; + case TCL_STDOUT: + handleId = STD_OUTPUT_HANDLE; + break; + case TCL_STDERR: + handleId = STD_ERROR_HANDLE; + break; + default: + return 0; + break; } handle = GetStdHandle(handleId); @@ -139,7 +134,7 @@ static int ShouldUseConsoleChannel(type) /* * Note that we need to check for 0 because Windows will return 0 if this * is not a console mode application, even though this is not a valid - * handle. + * handle. */ if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) { @@ -147,27 +142,27 @@ static int ShouldUseConsoleChannel(type) } /* - * Win2K BUG: GetStdHandle(STD_OUTPUT_HANDLE) can return what appears - * to be a valid handle. See TclpGetDefaultStdChannel() for this change - * implemented. We didn't change it here because GetFileType() [below] - * will catch this with FILE_TYPE_UNKNOWN and appropriately return a - * value of 1, anyways. + * Win2K BUG: GetStdHandle(STD_OUTPUT_HANDLE) can return what appears to + * be a valid handle. See TclpGetDefaultStdChannel() for this change + * implemented. We didn't change it here because GetFileType() [below] + * will catch this with FILE_TYPE_UNKNOWN and appropriately return a value + * of 1, anyways. * * char dummyBuff[1]; * DWORD dummyWritten; * * if ((type == TCL_STDOUT) - * && !WriteFile(handle, dummyBuff, 0, &dummyWritten, NULL)) { - * return 1; + * && !WriteFile(handle, dummyBuff, 0, &dummyWritten, NULL)) { + * return 1; * } */ fileType = GetFileType(handle); /* - * If the file is a character device, we need to try to figure out - * whether it is a serial port, a console, or something else. We - * test for the console case first because this is more common. + * If the file is a character device, we need to try to figure out whether + * it is a serial port, a console, or something else. We test for the + * console case first because this is more common. */ if (fileType == FILE_TYPE_CHAR) { @@ -175,10 +170,10 @@ static int ShouldUseConsoleChannel(type) if (!GetConsoleMode(handle, &consoleParams) && !GetCommState(handle, &dcb)) { /* - * Don't use a CHAR type channel for stdio, otherwise Tk - * runs into trouble with the MS DevStudio debugger. + * Don't use a CHAR type channel for stdio, otherwise Tk runs into + * trouble with the MS DevStudio debugger. */ - + return 1; } } else if (fileType == FILE_TYPE_UNKNOWN) { @@ -202,23 +197,22 @@ static int ShouldUseConsoleChannel(type) * * Tk_InitConsoleChannels -- * - * Create the console channels and install them as the standard - * channels. All I/O will be discarded until Tk_CreateConsoleWindow - * is called to attach the console to a text widget. + * Create the console channels and install them as the standard channels. + * All I/O will be discarded until Tk_CreateConsoleWindow is called to + * attach the console to a text widget. * * Results: * None. * * Side effects: - * Creates the console channel and installs it as the standard - * channels. + * Creates the console channel and installs it as the standard channels. * *---------------------------------------------------------------------- */ void -Tk_InitConsoleChannels(interp) - Tcl_Interp *interp; +Tk_InitConsoleChannels( + Tcl_Interp *interp) { static Tcl_ThreadDataKey consoleInitKey; int *consoleInitPtr, doIn, doOut, doErr; @@ -226,11 +220,11 @@ Tk_InitConsoleChannels(interp) Tcl_Channel consoleChannel; /* - * Ensure that we are getting the matching version of Tcl. This is - * really only an issue when Tk is loaded dynamically. + * Ensure that we are getting the matching version of Tcl. This is really + * only an issue when Tk is loaded dynamically. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) { + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { return; } @@ -326,9 +320,9 @@ Tk_InitConsoleChannels(interp) * * Tk_CreateConsoleWindow -- * - * Initialize the console. This code actually creates a new - * application and associated interpreter. This effectivly hides - * the implementation from the main application. + * Initialize the console. This code actually creates a new application + * and associated interpreter. This effectivly hides the implementation + * from the main application. * * Results: * None. @@ -339,9 +333,9 @@ Tk_InitConsoleChannels(interp) *---------------------------------------------------------------------- */ -int -Tk_CreateConsoleWindow(interp) - Tcl_Interp *interp; /* Interpreter to use for prompting. */ +int +Tk_CreateConsoleWindow( + Tcl_Interp *interp) /* Interpreter to use for prompting. */ { Tcl_Channel chan; ConsoleInfo *info; @@ -350,32 +344,26 @@ Tk_CreateConsoleWindow(interp) int result = TCL_OK; int haveConsoleChannel = 1; -#ifdef MAC_TCL - static const char *initCmd = "if {[catch {source $tk_library:console.tcl}]} {source -rsrc console}"; -#else - static const char *initCmd = "source $tk_library/console.tcl"; -#endif - /* Init an interp with Tcl and Tk */ Tcl_Interp *consoleInterp = Tcl_CreateInterp(); if (Tcl_Init(consoleInterp) != TCL_OK) { - goto error; + goto error; } if (Tk_Init(consoleInterp) != TCL_OK) { goto error; } - + /* * Fetch the instance data from whatever std channel is a * console channel. If none, create fresh instance data. */ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN)) - == &consoleChannelType) { + == &consoleChannelType) { } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT)) - == &consoleChannelType) { + == &consoleChannelType) { } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR)) - == &consoleChannelType) { + == &consoleChannelType) { } else { haveConsoleChannel = 0; } @@ -422,14 +410,14 @@ Tk_CreateConsoleWindow(interp) Tcl_CallWhenDeleted(consoleInterp, InterpDeleteProc, (ClientData) info); info->refCount++; Tcl_CreateThreadExitHandler(DeleteConsoleInterp, - (ClientData) consoleInterp); - - /* - * Add console commands to the interp + (ClientData) consoleInterp); + + /* + * Add console commands to the interp */ token = Tcl_CreateObjCommand(interp, "console", ConsoleObjCmd, - (ClientData) info, ConsoleDeleteProc); + (ClientData) info, ConsoleDeleteProc); info->refCount++; /* @@ -448,22 +436,10 @@ Tk_CreateConsoleWindow(interp) } Tcl_Preserve((ClientData) consoleInterp); - result = Tcl_GlobalEval(consoleInterp, initCmd); + result = Tcl_GlobalEval(consoleInterp, "source $tk_library/console.tcl"); if (result == TCL_ERROR) { - Tcl_Obj *objPtr = Tcl_GetVar2Ex(consoleInterp, "errorCode", NULL, - TCL_GLOBAL_ONLY); - Tcl_ResetResult(interp); - if (objPtr) { - Tcl_SetObjErrorCode(interp, objPtr); - } - - objPtr = Tcl_GetVar2Ex(consoleInterp, "errorInfo", NULL, - TCL_GLOBAL_ONLY); - if (objPtr) { - int numBytes; - CONST char *message = Tcl_GetStringFromObj(objPtr, &numBytes); - Tcl_AddObjErrorInfo(interp, message, numBytes); - } + Tcl_SetReturnOptions(interp, + Tcl_GetReturnOptions(consoleInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp)); } Tcl_Release((ClientData) consoleInterp); @@ -480,7 +456,7 @@ Tk_CreateConsoleWindow(interp) goto error; } return TCL_OK; - + error: Tcl_AddErrorInfo(interp, "\n (creating console window)"); if (!Tcl_InterpDeleted(consoleInterp)) { @@ -494,12 +470,12 @@ Tk_CreateConsoleWindow(interp) * * ConsoleOutput-- * - * Writes the given output on the IO channel. Returns count of how - * many characters were actually written, and an error indication. + * Writes the given output on the IO channel. Returns count of how many + * characters were actually written, and an error indication. * * Results: - * A count of how many characters were written is returned and an - * error indication is returned in an output argument. + * A count of how many characters were written is returned and an error + * indication is returned in an output argument. * * Side effects: * Writes output on the actual channel. @@ -508,11 +484,11 @@ Tk_CreateConsoleWindow(interp) */ static int -ConsoleOutput(instanceData, buf, toWrite, errorCode) - ClientData instanceData; /* Indicates which device to use. */ - CONST char *buf; /* The data buffer. */ - int toWrite; /* How many bytes to write? */ - int *errorCode; /* Where to store error code. */ +ConsoleOutput( + ClientData instanceData, /* Indicates which device to use. */ + CONST char *buf, /* The data buffer. */ + int toWrite, /* How many bytes to write? */ + int *errorCode) /* Where to store error code. */ { ChannelData *data = (ChannelData *)instanceData; ConsoleInfo *info = data->info; @@ -564,7 +540,7 @@ ConsoleOutput(instanceData, buf, toWrite, errorCode) * * ConsoleInput -- * - * Read input from the console. Not currently implemented. + * Read input from the console. Not currently implemented. * * Results: * Always returns EOF. @@ -577,12 +553,12 @@ ConsoleOutput(instanceData, buf, toWrite, errorCode) /* ARGSUSED */ static int -ConsoleInput(instanceData, buf, bufSize, errorCode) - ClientData instanceData; /* Unused. */ - char *buf; /* Where to store data read. */ - int bufSize; /* How much space is available - * in the buffer? */ - int *errorCode; /* Where to store error code. */ +ConsoleInput( + ClientData instanceData, /* Unused. */ + char *buf, /* Where to store data read. */ + int bufSize, /* How much space is available in the + * buffer? */ + int *errorCode) /* Where to store error code. */ { return 0; /* Always return EOF. */ } @@ -605,9 +581,9 @@ ConsoleInput(instanceData, buf, bufSize, errorCode) /* ARGSUSED */ static int -ConsoleClose(instanceData, interp) - ClientData instanceData; /* Unused. */ - Tcl_Interp *interp; /* Unused. */ +ConsoleClose( + ClientData instanceData, /* Unused. */ + Tcl_Interp *interp) /* Unused. */ { ChannelData *data = (ChannelData *)instanceData; ConsoleInfo *info = data->info; @@ -627,9 +603,9 @@ ConsoleClose(instanceData, interp) * * ConsoleWatch -- * - * Called by the notifier to set up the console device so that - * events will be noticed. Since there are no events on the - * console, this routine just returns without doing anything. + * Called by the notifier to set up the console device so that events + * will be noticed. Since there are no events on the console, this + * routine just returns without doing anything. * * Results: * None. @@ -642,12 +618,11 @@ ConsoleClose(instanceData, interp) /* ARGSUSED */ static void -ConsoleWatch(instanceData, mask) - ClientData instanceData; /* Device ID for the channel. */ - int mask; /* OR-ed combination of - * TCL_READABLE, TCL_WRITABLE and - * TCL_EXCEPTION, for the events - * we are interested in. */ +ConsoleWatch( + ClientData instanceData, /* Device ID for the channel. */ + int mask) /* OR-ed combination of TCL_READABLE, + * TCL_WRITABLE and TCL_EXCEPTION, for the + * events we are interested in. */ { } @@ -657,8 +632,7 @@ ConsoleWatch(instanceData, mask) * ConsoleHandle -- * * Invoked by the generic IO layer to get a handle from a channel. - * Because console channels are not devices, this function always - * fails. + * Because console channels are not devices, this function always fails. * * Results: * Always returns TCL_ERROR. @@ -671,12 +645,12 @@ ConsoleWatch(instanceData, mask) /* ARGSUSED */ static int -ConsoleHandle(instanceData, direction, handlePtr) - ClientData instanceData; /* Device ID for the channel. */ - int direction; /* TCL_READABLE or TCL_WRITABLE to indicate +ConsoleHandle( + ClientData instanceData, /* Device ID for the channel. */ + int direction, /* TCL_READABLE or TCL_WRITABLE to indicate * which direction of the channel is being * requested. */ - ClientData *handlePtr; /* Where to store handle */ + ClientData *handlePtr) /* Where to store handle */ { return TCL_ERROR; } @@ -699,11 +673,11 @@ ConsoleHandle(instanceData, direction, handlePtr) */ static int -ConsoleObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Access to the console interp */ - Tcl_Interp *interp; /* Current interpreter */ - int objc; /* Number of arguments */ - Tcl_Obj *CONST objv[]; /* Argument objects */ +ConsoleObjCmd( + ClientData clientData, /* Access to the console interp */ + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[]) /* Argument objects */ { int index, result; static CONST char *options[] = {"eval", "hide", "show", "title", NULL}; @@ -759,22 +733,8 @@ ConsoleObjCmd(clientData, interp, objc, objv) if (consoleInterp && !Tcl_InterpDeleted(consoleInterp)) { Tcl_Preserve((ClientData) consoleInterp); result = Tcl_GlobalEvalObj(consoleInterp, cmd); - if (result == TCL_ERROR) { - Tcl_Obj *objPtr = Tcl_GetVar2Ex(consoleInterp, "errorCode", - NULL, TCL_GLOBAL_ONLY); - Tcl_ResetResult(interp); - if (objPtr) { - Tcl_SetObjErrorCode(interp, objPtr); - } - - objPtr = Tcl_GetVar2Ex(consoleInterp, "errorInfo", - NULL, TCL_GLOBAL_ONLY); - if (objPtr) { - int numBytes; - CONST char *message = Tcl_GetStringFromObj(objPtr, &numBytes); - Tcl_AddObjErrorInfo(interp, message, numBytes); - } - } + Tcl_SetReturnOptions(interp, + Tcl_GetReturnOptions(consoleInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp)); Tcl_Release((ClientData) consoleInterp); } else { @@ -790,8 +750,8 @@ ConsoleObjCmd(clientData, interp, objc, objv) * * InterpreterObjCmd -- * - * This command allows the console interp to communicate with the - * main interpreter. + * This command allows the console interp to communicate with the main + * interpreter. * * Results: * A standard Tcl result. @@ -800,11 +760,11 @@ ConsoleObjCmd(clientData, interp, objc, objv) */ static int -InterpreterObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Not used */ - Tcl_Interp *interp; /* Current interpreter */ - int objc; /* Number of arguments */ - Tcl_Obj *CONST objv[]; /* Argument objects */ +InterpreterObjCmd( + ClientData clientData, /* */ + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[]) /* Argument objects */ { int index, result = TCL_OK; static CONST char *options[] = {"eval", "record", NULL}; @@ -817,7 +777,7 @@ InterpreterObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) - != TCL_OK) { + != TCL_OK) { return TCL_ERROR; } @@ -834,30 +794,16 @@ InterpreterObjCmd(clientData, interp, objc, objv) Tcl_Preserve((ClientData) otherInterp); switch ((enum option) index) { case OTHER_EVAL: - result = Tcl_GlobalEvalObj(otherInterp, objv[2]); + result = Tcl_GlobalEvalObj(otherInterp, objv[2]); /* * TODO: Should exceptions be filtered here? */ - if (result == TCL_ERROR) { - Tcl_Obj *objPtr = Tcl_GetVar2Ex(otherInterp, "errorCode", - NULL, TCL_GLOBAL_ONLY); - Tcl_ResetResult(interp); - if (objPtr) { - Tcl_SetObjErrorCode(interp, objPtr); - } - - objPtr = Tcl_GetVar2Ex(otherInterp, "errorInfo", - NULL, TCL_GLOBAL_ONLY); - if (objPtr) { - int numBytes; - CONST char *message = Tcl_GetStringFromObj(objPtr, &numBytes); - Tcl_AddObjErrorInfo(interp, message, numBytes); - } - } + Tcl_SetReturnOptions(interp, + Tcl_GetReturnOptions(otherInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(otherInterp)); break; case OTHER_RECORD: - Tcl_RecordAndEvalObj(otherInterp, objv[2], TCL_EVAL_GLOBAL); + Tcl_RecordAndEvalObj(otherInterp, objv[2], TCL_EVAL_GLOBAL); /* * By not setting result, we discard any exceptions or errors here * and always return TCL_OK. All the caller wants is the @@ -882,8 +828,8 @@ InterpreterObjCmd(clientData, interp, objc, objv) */ static void -DeleteConsoleInterp(clientData) - ClientData clientData; +DeleteConsoleInterp( + ClientData clientData) { Tcl_Interp *interp = (Tcl_Interp *)clientData; Tcl_DeleteInterp(interp); @@ -894,23 +840,28 @@ DeleteConsoleInterp(clientData) * * InterpDeleteProc -- * - * React when the interp in which the console is displayed is deleted - * for any reason. + * React when the interp in which the console is displayed is deleted + * for any reason. * * Results: * None. + * + * Side effects: + * A new console it created. + * + *---------------------------------------------------------------------- */ static void -InterpDeleteProc(clientData, interp) - ClientData clientData; - Tcl_Interp *interp; +InterpDeleteProc( + ClientData clientData, + Tcl_Interp *interp) { ConsoleInfo *info = (ConsoleInfo *) clientData; - if(info->consoleInterp == interp) { + if (info->consoleInterp == interp) { Tcl_DeleteThreadExitHandler(DeleteConsoleInterp, - (ClientData) info-> consoleInterp); + (ClientData) info->consoleInterp); info->consoleInterp = NULL; } if (--info->refCount <= 0) { @@ -924,20 +875,20 @@ InterpDeleteProc(clientData, interp) * ConsoleDeleteProc -- * * If the console command is deleted we destroy the console window and - * all associated data structures. - + * all associated data structures. + * * Results: * None. * * Side effects: - * A new console is created. + * A new console it created. * *---------------------------------------------------------------------- */ static void -ConsoleDeleteProc(clientData) - ClientData clientData; +ConsoleDeleteProc( + ClientData clientData) { ConsoleInfo *info = (ConsoleInfo *) clientData; @@ -954,10 +905,11 @@ ConsoleDeleteProc(clientData) * * ConsoleEventProc -- * - * This event function is registered on the main window of the slave - * interpreter. If the user or a running script causes the main window to - * be destroyed, then we need to inform the console interpreter by + * This event function is registered on the main window of the slave + * interpreter. If the user or a running script causes the main window to + * be destroyed, then we need to inform the console interpreter by * invoking "::tk::ConsoleExit". + * * Results: * None. * @@ -968,9 +920,9 @@ ConsoleDeleteProc(clientData) */ static void -ConsoleEventProc(clientData, eventPtr) - ClientData clientData; - XEvent *eventPtr; +ConsoleEventProc( + ClientData clientData, + XEvent *eventPtr) { if (eventPtr->type == DestroyNotify) { ConsoleInfo *info = (ConsoleInfo *) clientData; @@ -985,3 +937,11 @@ ConsoleEventProc(clientData, eventPtr) } } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkCursor.c b/generic/tkCursor.c index f599083..410aea9 100644 --- a/generic/tkCursor.c +++ b/generic/tkCursor.c @@ -1,52 +1,50 @@ -/* +/* * tkCursor.c -- * * This file maintains a database of read-only cursors for the Tk - * toolkit. This allows cursors to be shared between widgets and - * also avoids round-trips to the X server. + * toolkit. This allows cursors to be shared between widgets and also + * avoids round-trips to the X server. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* - * A TkCursor structure exists for each cursor that is currently - * active. Each structure is indexed with two hash tables defined - * below. One of the tables is cursorIdTable, and the other is either - * cursorNameTable or cursorDataTable, each of which are stored in the - * TkDisplay structure for the current thread. + * A TkCursor structure exists for each cursor that is currently active. Each + * structure is indexed with two hash tables defined below. One of the tables + * is cursorIdTable, and the other is either cursorNameTable or + * cursorDataTable, each of which are stored in the TkDisplay structure for + * the current thread. */ typedef struct { CONST char *source; /* Cursor bits. */ CONST char *mask; /* Mask bits. */ - int width, height; /* Dimensions of cursor (and data - * and mask). */ + int width, height; /* Dimensions of cursor (and data and + * mask). */ int xHot, yHot; /* Location of cursor hot-spot. */ Tk_Uid fg, bg; /* Colors for cursor. */ Display *display; /* Display on which cursor will be used. */ } DataKey; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static void CursorInit _ANSI_ARGS_((TkDisplay *dispPtr)); -static void DupCursorObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, - Tcl_Obj *dupObjPtr)); -static void FreeCursor _ANSI_ARGS_((TkCursor *cursorPtr)); -static void FreeCursorObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); -static TkCursor * TkcGetCursor _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *name)); -static TkCursor * GetCursorFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); -static void InitCursorObj _ANSI_ARGS_((Tcl_Obj *objPtr)); +static void CursorInit(TkDisplay *dispPtr); +static void DupCursorObjProc(Tcl_Obj *srcObjPtr, + Tcl_Obj *dupObjPtr); +static void FreeCursor(TkCursor *cursorPtr); +static void FreeCursorObjProc(Tcl_Obj *objPtr); +static TkCursor * TkcGetCursor(Tcl_Interp *interp, + Tk_Window tkwin, CONST char *name); +static TkCursor * GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +static void InitCursorObj(Tcl_Obj *objPtr); /* * The following structure defines the implementation of the "cursor" Tcl @@ -69,33 +67,32 @@ Tcl_ObjType tkCursorObjType = { * * Tk_AllocCursorFromObj -- * - * Given a Tcl_Obj *, map the value to a corresponding - * Tk_Cursor structure based on the tkwin given. + * Given a Tcl_Obj *, map the value to a corresponding Tk_Cursor + * structure based on the tkwin given. * * Results: - * The return value is the X identifer for the desired cursor, - * unless objPtr couldn't be parsed correctly. In this case, - * None is returned and an error message is left in the interp's result. - * The caller should never modify the cursor that is returned, and - * should eventually call Tk_FreeCursorFromObj when the cursor is no - * longer needed. + * The return value is the X identifer for the desired cursor, unless + * objPtr couldn't be parsed correctly. In this case, None is returned + * and an error message is left in the interp's result. The caller should + * never modify the cursor that is returned, and should eventually call + * Tk_FreeCursorFromObj when the cursor is no longer needed. * * Side effects: * The cursor is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeCursorFromObj, so that the database can be cleaned up - * when cursors aren't needed anymore. + * For each call to this function, there should eventually be a call to + * Tk_FreeCursorFromObj, so that the database can be cleaned up when + * cursors aren't needed anymore. * *---------------------------------------------------------------------- */ Tk_Cursor -Tk_AllocCursorFromObj(interp, tkwin, objPtr) - Tcl_Interp *interp; /* Interp for error results. */ - Tk_Window tkwin; /* Window in which the cursor will be used.*/ - Tcl_Obj *objPtr; /* Object describing cursor; see manual - * entry for description of legal - * syntax of this obj's string rep. */ +Tk_AllocCursorFromObj( + Tcl_Interp *interp, /* Interp for error results. */ + Tk_Window tkwin, /* Window in which the cursor will be used.*/ + Tcl_Obj *objPtr) /* Object describing cursor; see manual entry + * for description of legal syntax of this + * obj's string rep. */ { TkCursor *cursorPtr; @@ -105,16 +102,17 @@ Tk_AllocCursorFromObj(interp, tkwin, objPtr) cursorPtr = (TkCursor *) objPtr->internalRep.twoPtrValue.ptr1; /* - * If the object currently points to a TkCursor, see if it's the - * one we want. If so, increment its reference count and return. + * If the object currently points to a TkCursor, see if it's the one we + * want. If so, increment its reference count and return. */ if (cursorPtr != NULL) { if (cursorPtr->resourceRefCount == 0) { /* - * This is a stale reference: it refers to a TkCursor that's - * no longer in use. Clear the reference. + * This is a stale reference: it refers to a TkCursor that's no + * longer in use. Clear the reference. */ + FreeCursorObjProc(objPtr); cursorPtr = NULL; } else if (Tk_Display(tkwin) == cursorPtr->display) { @@ -124,38 +122,37 @@ Tk_AllocCursorFromObj(interp, tkwin, objPtr) } /* - * The object didn't point to the TkCursor that we wanted. Search - * the list of TkCursors with the same name to see if one of the - * other TkCursors is the right one. + * The object didn't point to the TkCursor that we wanted. Search the list + * of TkCursors with the same name to see if one of the other TkCursors is + * the right one. */ if (cursorPtr != NULL) { - TkCursor *firstCursorPtr = - (TkCursor *) Tcl_GetHashValue(cursorPtr->hashPtr); + TkCursor *firstCursorPtr = (TkCursor *) + Tcl_GetHashValue(cursorPtr->hashPtr); FreeCursorObjProc(objPtr); for (cursorPtr = firstCursorPtr; cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) { if (Tk_Display(tkwin) == cursorPtr->display) { cursorPtr->resourceRefCount++; cursorPtr->objRefCount++; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) cursorPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) cursorPtr; return cursorPtr->cursor; } } } /* - * Still no luck. Call TkcGetCursor to allocate a new TkCursor object. + * Still no luck. Call TkcGetCursor to allocate a new TkCursor object. */ cursorPtr = TkcGetCursor(interp, tkwin, Tcl_GetString(objPtr)); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) cursorPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) cursorPtr; if (cursorPtr == NULL) { return None; - } else { - cursorPtr->objRefCount++; - return cursorPtr->cursor; } + cursorPtr->objRefCount++; + return cursorPtr->cursor; } /* @@ -163,32 +160,31 @@ Tk_AllocCursorFromObj(interp, tkwin, objPtr) * * Tk_GetCursor -- * - * Given a string describing a cursor, locate (or create if necessary) - * a cursor that fits the description. + * Given a string describing a cursor, locate (or create if necessary) a + * cursor that fits the description. * * Results: - * The return value is the X identifer for the desired cursor, - * unless string couldn't be parsed correctly. In this case, - * None is returned and an error message is left in the interp's result. - * The caller should never modify the cursor that is returned, and - * should eventually call Tk_FreeCursor when the cursor is no longer - * needed. + * The return value is the X identifer for the desired cursor, unless + * string couldn't be parsed correctly. In this case, None is returned + * and an error message is left in the interp's result. The caller should + * never modify the cursor that is returned, and should eventually call + * Tk_FreeCursor when the cursor is no longer needed. * * Side effects: * The cursor is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeCursor, so that the database can be cleaned up when cursors + * For each call to this function, there should eventually be a call to + * Tk_FreeCursor, so that the database can be cleaned up when cursors * aren't needed anymore. * *---------------------------------------------------------------------- */ Tk_Cursor -Tk_GetCursor(interp, tkwin, string) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tk_Window tkwin; /* Window in which cursor will be used. */ - Tk_Uid string; /* Description of cursor. See manual entry - * for details on legal syntax. */ +Tk_GetCursor( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + Tk_Uid string) /* Description of cursor. See manual entry for + * details on legal syntax. */ { TkCursor *cursorPtr = TkcGetCursor(interp, tkwin, string); if (cursorPtr == NULL) { @@ -202,48 +198,47 @@ Tk_GetCursor(interp, tkwin, string) * * TkcGetCursor -- * - * Given a string describing a cursor, locate (or create if necessary) - * a cursor that fits the description. This routine returns the - * internal data structure for the cursor, which avoids extra - * hash table lookups in Tk_AllocCursorFromObj. + * Given a string describing a cursor, locate (or create if necessary) a + * cursor that fits the description. This routine returns the internal + * data structure for the cursor, which avoids extra hash table lookups + * in Tk_AllocCursorFromObj. * * Results: - * The return value is a pointer to the TkCursor for the desired - * cursor, unless string couldn't be parsed correctly. In this - * case, NULL is returned and an error message is left in the - * interp's result. The caller should never modify the cursor that - * is returned, and should eventually call Tk_FreeCursor when the - * cursor is no longer needed. + * The return value is a pointer to the TkCursor for the desired cursor, + * unless string couldn't be parsed correctly. In this case, NULL is + * returned and an error message is left in the interp's result. The + * caller should never modify the cursor that is returned, and should + * eventually call Tk_FreeCursor when the cursor is no longer needed. * * Side effects: * The cursor is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeCursor, so that the database can be cleaned up when cursors + * For each call to this function, there should eventually be a call to + * Tk_FreeCursor, so that the database can be cleaned up when cursors * aren't needed anymore. * *---------------------------------------------------------------------- */ static TkCursor * -TkcGetCursor(interp, tkwin, string) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tk_Window tkwin; /* Window in which cursor will be used. */ - CONST char *string; /* Description of cursor. See manual entry - * for details on legal syntax. */ +TkcGetCursor( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + CONST char *string) /* Description of cursor. See manual entry for + * details on legal syntax. */ { Tcl_HashEntry *nameHashPtr; register TkCursor *cursorPtr; TkCursor *existingCursorPtr = NULL; - int new; + int isNew; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->cursorInit) { CursorInit(dispPtr); } - nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable, - string, &new); - if (!new) { + nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable, + string, &isNew); + if (!isNew) { existingCursorPtr = (TkCursor *) Tcl_GetHashValue(nameHashPtr); for (cursorPtr = existingCursorPtr; cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) { @@ -259,7 +254,7 @@ TkcGetCursor(interp, tkwin, string) cursorPtr = TkGetCursorByName(interp, tkwin, string); if (cursorPtr == NULL) { - if (new) { + if (isNew) { Tcl_DeleteHashEntry(nameHashPtr); } return NULL; @@ -275,10 +270,10 @@ TkcGetCursor(interp, tkwin, string) cursorPtr->otherTable = &dispPtr->cursorNameTable; cursorPtr->hashPtr = nameHashPtr; cursorPtr->nextPtr = existingCursorPtr; - cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable, - (char *) cursorPtr->cursor, &new); - if (!new) { - panic("cursor already registered in Tk_GetCursor"); + cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable, + (char *) cursorPtr->cursor, &isNew); + if (!isNew) { + Tcl_Panic("cursor already registered in Tk_GetCursor"); } Tcl_SetHashValue(nameHashPtr, cursorPtr); Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr); @@ -291,46 +286,43 @@ TkcGetCursor(interp, tkwin, string) * * Tk_GetCursorFromData -- * - * Given a description of the bits and colors for a cursor, - * make a cursor that has the given properties. + * Given a description of the bits and colors for a cursor, make a cursor + * that has the given properties. * * Results: - * The return value is the X identifer for the desired cursor, - * unless it couldn't be created properly. In this case, None is - * returned and an error message is left in the interp's result. The - * caller should never modify the cursor that is returned, and - * should eventually call Tk_FreeCursor when the cursor is no - * longer needed. + * The return value is the X identifer for the desired cursor, unless it + * couldn't be created properly. In this case, None is returned and an + * error message is left in the interp's result. The caller should never + * modify the cursor that is returned, and should eventually call + * Tk_FreeCursor when the cursor is no longer needed. * * Side effects: * The cursor is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeCursor, so that the database can be cleaned up when cursors + * For each call to this function, there should eventually be a call to + * Tk_FreeCursor, so that the database can be cleaned up when cursors * aren't needed anymore. * *---------------------------------------------------------------------- */ Tk_Cursor -Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, - xHot, yHot, fg, bg) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tk_Window tkwin; /* Window in which cursor will be used. */ - CONST char *source; /* Bitmap data for cursor shape. */ - CONST char *mask; /* Bitmap data for cursor mask. */ - int width, height; /* Dimensions of cursor. */ - int xHot, yHot; /* Location of hot-spot in cursor. */ - Tk_Uid fg; /* Foreground color for cursor. */ - Tk_Uid bg; /* Background color for cursor. */ +Tk_GetCursorFromData( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + CONST char *source, /* Bitmap data for cursor shape. */ + CONST char *mask, /* Bitmap data for cursor mask. */ + int width, int height, /* Dimensions of cursor. */ + int xHot, int yHot, /* Location of hot-spot in cursor. */ + Tk_Uid fg, /* Foreground color for cursor. */ + Tk_Uid bg) /* Background color for cursor. */ { DataKey dataKey; Tcl_HashEntry *dataHashPtr; register TkCursor *cursorPtr; - int new; + int isNew; XColor fgColor, bgColor; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!dispPtr->cursorInit) { CursorInit(dispPtr); } @@ -344,27 +336,25 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, dataKey.fg = fg; dataKey.bg = bg; dataKey.display = Tk_Display(tkwin); - dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable, - (char *) &dataKey, &new); - if (!new) { + dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable, + (char *) &dataKey, &isNew); + if (!isNew) { cursorPtr = (TkCursor *) Tcl_GetHashValue(dataHashPtr); cursorPtr->resourceRefCount++; return cursorPtr->cursor; } /* - * No suitable cursor exists yet. Make one using the data - * available and add it to the database. + * No suitable cursor exists yet. Make one using the data available and + * add it to the database. */ if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) { - Tcl_AppendResult(interp, "invalid color name \"", fg, "\"", - (char *) NULL); + Tcl_AppendResult(interp, "invalid color name \"", fg, "\"", NULL); goto error; } if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) { - Tcl_AppendResult(interp, "invalid color name \"", bg, "\"", - (char *) NULL); + Tcl_AppendResult(interp, "invalid color name \"", bg, "\"", NULL); goto error; } @@ -379,18 +369,18 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, cursorPtr->otherTable = &dispPtr->cursorDataTable; cursorPtr->hashPtr = dataHashPtr; cursorPtr->objRefCount = 0; - cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable, - (char *) cursorPtr->cursor, &new); + cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable, + (char *) cursorPtr->cursor, &isNew); cursorPtr->nextPtr = NULL; - if (!new) { - panic("cursor already registered in Tk_GetCursorFromData"); + if (!isNew) { + Tcl_Panic("cursor already registered in Tk_GetCursorFromData"); } Tcl_SetHashValue(dataHashPtr, cursorPtr); Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr); return cursorPtr->cursor; - error: + error: Tcl_DeleteHashEntry(dataHashPtr); return None; } @@ -403,12 +393,11 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, * Given a cursor, return a textual string identifying it. * * Results: - * If cursor was created by Tk_GetCursor, then the return - * value is the "string" that was used to create it. - * Otherwise the return value is a string giving the X - * identifier for the cursor. The storage for the returned - * string is only guaranteed to persist up until the next - * call to this procedure. + * If cursor was created by Tk_GetCursor, then the return value is the + * "string" that was used to create it. Otherwise the return value is a + * string giving the X identifier for the cursor. The storage for the + * returned string is only guaranteed to persist up until the next call + * to this function. * * Side effects: * None. @@ -417,9 +406,9 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, */ CONST char * -Tk_NameOfCursor(display, cursor) - Display *display; /* Display for which cursor was allocated. */ - Tk_Cursor cursor; /* Identifier for cursor whose name is +Tk_NameOfCursor( + Display *display, /* Display for which cursor was allocated. */ + Tk_Cursor cursor) /* Identifier for cursor whose name is * wanted. */ { Tcl_HashEntry *idHashPtr; @@ -429,9 +418,8 @@ Tk_NameOfCursor(display, cursor) dispPtr = TkGetDisplay(display); if (!dispPtr->cursorInit) { - printid: - sprintf(dispPtr->cursorString, "cursor id 0x%x", - (unsigned int) cursor); + printid: + sprintf(dispPtr->cursorString, "cursor id %p", cursor); return dispPtr->cursorString; } idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor); @@ -450,23 +438,22 @@ Tk_NameOfCursor(display, cursor) * * FreeCursor -- * - * This procedure is invoked by both Tk_FreeCursor and - * Tk_FreeCursorFromObj; it does all the real work of deallocating - * a cursor. + * This function is invoked by both Tk_FreeCursorFromObj and + * Tk_FreeCursor; it does all the real work of deallocating a cursor. * * Results: * None. * * Side effects: - * The reference count associated with cursor is decremented, and - * it is officially deallocated if no-one is using it anymore. + * The reference count associated with cursor is decremented, and it is + * officially deallocated if no-one is using it anymore. * *---------------------------------------------------------------------- */ static void -FreeCursor(cursorPtr) - TkCursor *cursorPtr; /* Cursor to be released. */ +FreeCursor( + TkCursor *cursorPtr) /* Cursor to be released. */ { TkCursor *prevPtr; @@ -500,34 +487,34 @@ FreeCursor(cursorPtr) * * Tk_FreeCursor -- * - * This procedure is called to release a cursor allocated by - * Tk_GetCursor or TkGetCursorFromData. + * This function is called to release a cursor allocated by Tk_GetCursor + * or TkGetCursorFromData. * * Results: * None. * * Side effects: - * The reference count associated with cursor is decremented, and - * it is officially deallocated if no-one is using it anymore. + * The reference count associated with cursor is decremented, and it is + * officially deallocated if no-one is using it anymore. * *---------------------------------------------------------------------- */ void -Tk_FreeCursor(display, cursor) - Display *display; /* Display for which cursor was allocated. */ - Tk_Cursor cursor; /* Identifier for cursor to be released. */ +Tk_FreeCursor( + Display *display, /* Display for which cursor was allocated. */ + Tk_Cursor cursor) /* Identifier for cursor to be released. */ { Tcl_HashEntry *idHashPtr; TkDisplay *dispPtr = TkGetDisplay(display); if (!dispPtr->cursorInit) { - panic("Tk_FreeCursor called before Tk_GetCursor"); + Tcl_Panic("Tk_FreeCursor called before Tk_GetCursor"); } idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor); if (idHashPtr == NULL) { - panic("Tk_FreeCursor received unknown cursor argument"); + Tcl_Panic("Tk_FreeCursor received unknown cursor argument"); } FreeCursor((TkCursor *) Tcl_GetHashValue(idHashPtr)); } @@ -537,27 +524,27 @@ Tk_FreeCursor(display, cursor) * * Tk_FreeCursorFromObj -- * - * This procedure is called to release a cursor allocated by - * Tk_AllocCursorFromObj. It does not throw away the Tcl_Obj *; - * it only gets rid of the hash table entry for this cursor - * and clears the cached value that is normally stored in the object. + * This function is called to release a cursor allocated by + * Tk_AllocCursorFromObj. It does not throw away the Tcl_Obj *; it only + * gets rid of the hash table entry for this cursor and clears the cached + * value that is normally stored in the object. * * Results: * None. * * Side effects: - * The reference count associated with the cursor represented by - * objPtr is decremented, and the cursor is released to X if there are - * no remaining uses for it. + * The reference count associated with the cursor represented by objPtr + * is decremented, and the cursor is released to X if there are no + * remaining uses for it. * *---------------------------------------------------------------------- */ void -Tk_FreeCursorFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window this cursor lives in. Needed - * for the display value. */ - Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */ +Tk_FreeCursorFromObj( + Tk_Window tkwin, /* The window this cursor lives in. Needed for + * the display value. */ + Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */ { FreeCursor(GetCursorFromObj(tkwin, objPtr)); FreeCursorObjProc(objPtr); @@ -566,66 +553,65 @@ Tk_FreeCursorFromObj(tkwin, objPtr) /* *--------------------------------------------------------------------------- * - * FreeCursorFromObjProc -- + * FreeCursorFromObjProc -- * * This proc is called to release an object reference to a cursor. - * Called when the object's internal rep is released or when - * the cached tkColPtr needs to be changed. + * Called when the object's internal rep is released or when the cached + * tkColPtr needs to be changed. * * Results: * None. * * Side effects: - * The object reference count is decremented. When both it - * and the hash ref count go to zero, the color's resources - * are released. + * The object reference count is decremented. When both it and the hash + * ref count go to zero, the color's resources are released. * *--------------------------------------------------------------------------- */ static void -FreeCursorObjProc(objPtr) - Tcl_Obj *objPtr; /* The object we are releasing. */ +FreeCursorObjProc( + Tcl_Obj *objPtr) /* The object we are releasing. */ { TkCursor *cursorPtr = (TkCursor *) objPtr->internalRep.twoPtrValue.ptr1; if (cursorPtr != NULL) { cursorPtr->objRefCount--; - if ((cursorPtr->objRefCount == 0) + if ((cursorPtr->objRefCount == 0) && (cursorPtr->resourceRefCount == 0)) { ckfree((char *) cursorPtr); } - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } } /* *--------------------------------------------------------------------------- * - * DupCursorObjProc -- + * DupCursorObjProc -- * - * When a cached cursor object is duplicated, this is called to - * update the internal reps. + * When a cached cursor object is duplicated, this is called to update + * the internal reps. * * Results: * None. * * Side effects: - * The color's objRefCount is incremented and the internal rep - * of the copy is set to point to it. + * The color's objRefCount is incremented and the internal rep of the + * copy is set to point to it. * *--------------------------------------------------------------------------- */ static void -DupCursorObjProc(srcObjPtr, dupObjPtr) - Tcl_Obj *srcObjPtr; /* The object we are copying from. */ - Tcl_Obj *dupObjPtr; /* The object we are copying to. */ +DupCursorObjProc( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { TkCursor *cursorPtr = (TkCursor *) srcObjPtr->internalRep.twoPtrValue.ptr1; - + dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) cursorPtr; + dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) cursorPtr; if (cursorPtr != NULL) { cursorPtr->objRefCount++; @@ -638,27 +624,31 @@ DupCursorObjProc(srcObjPtr, dupObjPtr) * Tk_GetCursorFromObj -- * * Returns the cursor referred to buy a Tcl object. The cursor must - * already have been allocated via a call to Tk_AllocCursorFromObj or + * already have been allocated via a call to Tk_AllocCursorFromObj or * Tk_GetCursor. * * Results: - * Returns the Tk_Cursor that matches the tkwin and the string rep - * of the name of the cursor given in objPtr. + * Returns the Tk_Cursor that matches the tkwin and the string rep of the + * name of the cursor given in objPtr. * * Side effects: - * If the object is not already a cursor, the conversion will free - * any old internal representation. + * If the object is not already a cursor, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ Tk_Cursor -Tk_GetCursorFromObj(tkwin, objPtr) - Tk_Window tkwin; - Tcl_Obj *objPtr; /* The object from which to get pixels. */ +Tk_GetCursorFromObj( + Tk_Window tkwin, + Tcl_Obj *objPtr) /* The object from which to get pixels. */ { TkCursor *cursorPtr = GetCursorFromObj(tkwin, objPtr); - /* GetCursorFromObj should never return NULL */ + + /* + * GetCursorFromObj should never return NULL + */ + return cursorPtr->cursor; } @@ -667,25 +657,25 @@ Tk_GetCursorFromObj(tkwin, objPtr) * * GetCursorFromObj -- * - * Returns the cursor referred to by a Tcl object. The cursor must - * already have been allocated via a call to Tk_AllocCursorFromObj - * or Tk_GetCursor. + * Returns the cursor referred to by a Tcl object. The cursor must + * already have been allocated via a call to Tk_AllocCursorFromObj or + * Tk_GetCursor. * * Results: - * Returns the TkCursor * that matches the tkwin and the string rep - * of the name of the cursor given in objPtr. + * Returns the TkCursor * that matches the tkwin and the string rep of + * the name of the cursor given in objPtr. * * Side effects: - * If the object is not already a cursor, the conversion will free - * any old internal representation. + * If the object is not already a cursor, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ static TkCursor * -GetCursorFromObj(tkwin, objPtr) - Tk_Window tkwin; /* Window in which the cursor will be used. */ - Tcl_Obj *objPtr; /* The object that describes the desired +GetCursorFromObj( + Tk_Window tkwin, /* Window in which the cursor will be used. */ + Tcl_Obj *objPtr) /* The object that describes the desired * cursor. */ { TkCursor *cursorPtr; @@ -697,11 +687,12 @@ GetCursorFromObj(tkwin, objPtr) } /* - * The internal representation is a cache of the last cursor used - * with the given name. But there can be lots different cursors - * for each cursor name; one cursor for each display. Check to - * see if the cursor we have cached is the one that is needed. + * The internal representation is a cache of the last cursor used with the + * given name. But there can be lots different cursors for each cursor + * name; one cursor for each display. Check to see if the cursor we have + * cached is the one that is needed. */ + cursorPtr = (TkCursor *) objPtr->internalRep.twoPtrValue.ptr1; if ((cursorPtr != NULL) && (Tk_Display(tkwin) == cursorPtr->display)) { return cursorPtr; @@ -721,14 +712,14 @@ GetCursorFromObj(tkwin, objPtr) cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) { if (Tk_Display(tkwin) == cursorPtr->display) { FreeCursorObjProc(objPtr); - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) cursorPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) cursorPtr; cursorPtr->objRefCount++; return cursorPtr; } } - error: - panic("GetCursorFromObj called with non-existent cursor!"); + error: + Tcl_Panic("GetCursorFromObj called with non-existent cursor!"); /* * The following code isn't reached; it's just there to please compilers. */ @@ -740,27 +731,27 @@ GetCursorFromObj(tkwin, objPtr) * * InitCursorObj -- * - * Bookeeping procedure to change an objPtr to a cursor type. + * Bookeeping function to change an objPtr to a cursor type. * * Results: * None. * * Side effects: - * The old internal rep of the object is freed. The internal - * rep is cleared. The final form of the object is set - * by either Tk_AllocCursorFromObj or GetCursorFromObj. + * The old internal rep of the object is freed. The internal rep is + * cleared. The final form of the object is set by either + * Tk_AllocCursorFromObj or GetCursorFromObj. * *---------------------------------------------------------------------- */ static void -InitCursorObj(objPtr) - Tcl_Obj *objPtr; /* The object to convert. */ +InitCursorObj( + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ Tcl_GetString(objPtr); @@ -769,7 +760,7 @@ InitCursorObj(objPtr) (*typePtr->freeIntRepProc)(objPtr); } objPtr->typePtr = &tkCursorObjType; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; } /* @@ -789,26 +780,26 @@ InitCursorObj(objPtr) */ static void -CursorInit(dispPtr) - TkDisplay *dispPtr; /* Display used to store thread-specific data. */ +CursorInit( + TkDisplay *dispPtr) /* Display used to store thread-specific + * data. */ { Tcl_InitHashTable(&dispPtr->cursorNameTable, TCL_STRING_KEYS); Tcl_InitHashTable(&dispPtr->cursorDataTable, sizeof(DataKey)/sizeof(int)); /* - * The call below is tricky: can't use sizeof(IdKey) because it - * gets padded with extra unpredictable bytes on some 64-bit - * machines. + * The call below is tricky: can't use sizeof(IdKey) because it gets + * padded with extra unpredictable bytes on some 64-bit machines. */ - /* - * Old code.... - * Tcl_InitHashTable(&dispPtr->cursorIdTable, sizeof(Display *) + /* + * Old code.... + * Tcl_InitHashTable(&dispPtr->cursorIdTable, sizeof(Display *) * /sizeof(int)); * - * The comment above doesn't make sense. - * However, XIDs should only be 32 bits, by the definition of X, - * so the code above causes Tk to crash. Here is the real code: + * The comment above doesn't make sense. However, XIDs should only be 32 + * bits, by the definition of X, so the code above causes Tk to crash. + * Here is the real code: */ Tcl_InitHashTable(&dispPtr->cursorIdTable, TCL_ONE_WORD_KEYS); @@ -821,13 +812,13 @@ CursorInit(dispPtr) * * TkDebugCursor -- * - * This procedure returns debugging information about a cursor. + * This function returns debugging information about a cursor. * * Results: * The return value is a list with one sublist for each TkCursor - * corresponding to "name". Each sublist has two elements that - * contain the resourceRefCount and objRefCount fields from the - * TkCursor structure. + * corresponding to "name". Each sublist has two elements that contain + * the resourceRefCount and objRefCount fields from the TkCursor + * structure. * * Side effects: * None. @@ -836,10 +827,10 @@ CursorInit(dispPtr) */ Tcl_Obj * -TkDebugCursor(tkwin, name) - Tk_Window tkwin; /* The window in which the cursor will be - * used (not currently used). */ - char *name; /* Name of the desired color. */ +TkDebugCursor( + Tk_Window tkwin, /* The window in which the cursor will be used + * (not currently used). */ + char *name) /* Name of the desired color. */ { TkCursor *cursorPtr; Tcl_HashEntry *hashPtr; @@ -854,16 +845,24 @@ TkDebugCursor(tkwin, name) if (hashPtr != NULL) { cursorPtr = (TkCursor *) Tcl_GetHashValue(hashPtr); if (cursorPtr == NULL) { - panic("TkDebugCursor found empty hash table entry"); + Tcl_Panic("TkDebugCursor found empty hash table entry"); } for ( ; (cursorPtr != NULL); cursorPtr = cursorPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(cursorPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(cursorPtr->objRefCount)); + Tcl_NewIntObj(cursorPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } return resultPtr; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkDecls.h b/generic/tkDecls.h index 81871a2..d06df4b 100644 --- a/generic/tkDecls.h +++ b/generic/tkDecls.h @@ -29,882 +29,1651 @@ * Exported function declarations: */ +#ifndef Tk_MainLoop_TCL_DECLARED +#define Tk_MainLoop_TCL_DECLARED /* 0 */ -EXTERN void Tk_MainLoop _ANSI_ARGS_((void)); +EXTERN void Tk_MainLoop(void); +#endif +#ifndef Tk_3DBorderColor_TCL_DECLARED +#define Tk_3DBorderColor_TCL_DECLARED /* 1 */ -EXTERN XColor * Tk_3DBorderColor _ANSI_ARGS_((Tk_3DBorder border)); +EXTERN XColor * Tk_3DBorderColor(Tk_3DBorder border); +#endif +#ifndef Tk_3DBorderGC_TCL_DECLARED +#define Tk_3DBorderGC_TCL_DECLARED /* 2 */ -EXTERN GC Tk_3DBorderGC _ANSI_ARGS_((Tk_Window tkwin, - Tk_3DBorder border, int which)); +EXTERN GC Tk_3DBorderGC(Tk_Window tkwin, Tk_3DBorder border, + int which); +#endif +#ifndef Tk_3DHorizontalBevel_TCL_DECLARED +#define Tk_3DHorizontalBevel_TCL_DECLARED /* 3 */ -EXTERN void Tk_3DHorizontalBevel _ANSI_ARGS_((Tk_Window tkwin, +EXTERN void Tk_3DHorizontalBevel(Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftIn, - int rightIn, int topBevel, int relief)); + int rightIn, int topBevel, int relief); +#endif +#ifndef Tk_3DVerticalBevel_TCL_DECLARED +#define Tk_3DVerticalBevel_TCL_DECLARED /* 4 */ -EXTERN void Tk_3DVerticalBevel _ANSI_ARGS_((Tk_Window tkwin, +EXTERN void Tk_3DVerticalBevel(Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftBevel, - int relief)); + int relief); +#endif +#ifndef Tk_AddOption_TCL_DECLARED +#define Tk_AddOption_TCL_DECLARED /* 5 */ -EXTERN void Tk_AddOption _ANSI_ARGS_((Tk_Window tkwin, - CONST char *name, CONST char *value, - int priority)); +EXTERN void Tk_AddOption(Tk_Window tkwin, CONST char *name, + CONST char *value, int priority); +#endif +#ifndef Tk_BindEvent_TCL_DECLARED +#define Tk_BindEvent_TCL_DECLARED /* 6 */ -EXTERN void Tk_BindEvent _ANSI_ARGS_(( - Tk_BindingTable bindingTable, +EXTERN void Tk_BindEvent(Tk_BindingTable bindingTable, XEvent *eventPtr, Tk_Window tkwin, - int numObjects, ClientData *objectPtr)); + int numObjects, ClientData *objectPtr); +#endif +#ifndef Tk_CanvasDrawableCoords_TCL_DECLARED +#define Tk_CanvasDrawableCoords_TCL_DECLARED /* 7 */ -EXTERN void Tk_CanvasDrawableCoords _ANSI_ARGS_(( - Tk_Canvas canvas, double x, double y, - short *drawableXPtr, short *drawableYPtr)); +EXTERN void Tk_CanvasDrawableCoords(Tk_Canvas canvas, double x, + double y, short *drawableXPtr, + short *drawableYPtr); +#endif +#ifndef Tk_CanvasEventuallyRedraw_TCL_DECLARED +#define Tk_CanvasEventuallyRedraw_TCL_DECLARED /* 8 */ -EXTERN void Tk_CanvasEventuallyRedraw _ANSI_ARGS_(( - Tk_Canvas canvas, int x1, int y1, int x2, - int y2)); +EXTERN void Tk_CanvasEventuallyRedraw(Tk_Canvas canvas, int x1, + int y1, int x2, int y2); +#endif +#ifndef Tk_CanvasGetCoord_TCL_DECLARED +#define Tk_CanvasGetCoord_TCL_DECLARED /* 9 */ -EXTERN int Tk_CanvasGetCoord _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_CanvasGetCoord(Tcl_Interp *interp, Tk_Canvas canvas, CONST char *str, - double *doublePtr)); + double *doublePtr); +#endif +#ifndef Tk_CanvasGetTextInfo_TCL_DECLARED +#define Tk_CanvasGetTextInfo_TCL_DECLARED /* 10 */ -EXTERN Tk_CanvasTextInfo * Tk_CanvasGetTextInfo _ANSI_ARGS_(( - Tk_Canvas canvas)); +EXTERN Tk_CanvasTextInfo * Tk_CanvasGetTextInfo(Tk_Canvas canvas); +#endif +#ifndef Tk_CanvasPsBitmap_TCL_DECLARED +#define Tk_CanvasPsBitmap_TCL_DECLARED /* 11 */ -EXTERN int Tk_CanvasPsBitmap _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_CanvasPsBitmap(Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap, int x, - int y, int width, int height)); + int y, int width, int height); +#endif +#ifndef Tk_CanvasPsColor_TCL_DECLARED +#define Tk_CanvasPsColor_TCL_DECLARED /* 12 */ -EXTERN int Tk_CanvasPsColor _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, XColor *colorPtr)); +EXTERN int Tk_CanvasPsColor(Tcl_Interp *interp, + Tk_Canvas canvas, XColor *colorPtr); +#endif +#ifndef Tk_CanvasPsFont_TCL_DECLARED +#define Tk_CanvasPsFont_TCL_DECLARED /* 13 */ -EXTERN int Tk_CanvasPsFont _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Font font)); +EXTERN int Tk_CanvasPsFont(Tcl_Interp *interp, Tk_Canvas canvas, + Tk_Font font); +#endif +#ifndef Tk_CanvasPsPath_TCL_DECLARED +#define Tk_CanvasPsPath_TCL_DECLARED /* 14 */ -EXTERN void Tk_CanvasPsPath _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, double *coordPtr, - int numPoints)); +EXTERN void Tk_CanvasPsPath(Tcl_Interp *interp, Tk_Canvas canvas, + double *coordPtr, int numPoints); +#endif +#ifndef Tk_CanvasPsStipple_TCL_DECLARED +#define Tk_CanvasPsStipple_TCL_DECLARED /* 15 */ -EXTERN int Tk_CanvasPsStipple _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Pixmap bitmap)); +EXTERN int Tk_CanvasPsStipple(Tcl_Interp *interp, + Tk_Canvas canvas, Pixmap bitmap); +#endif +#ifndef Tk_CanvasPsY_TCL_DECLARED +#define Tk_CanvasPsY_TCL_DECLARED /* 16 */ -EXTERN double Tk_CanvasPsY _ANSI_ARGS_((Tk_Canvas canvas, double y)); +EXTERN double Tk_CanvasPsY(Tk_Canvas canvas, double y); +#endif +#ifndef Tk_CanvasSetStippleOrigin_TCL_DECLARED +#define Tk_CanvasSetStippleOrigin_TCL_DECLARED /* 17 */ -EXTERN void Tk_CanvasSetStippleOrigin _ANSI_ARGS_(( - Tk_Canvas canvas, GC gc)); +EXTERN void Tk_CanvasSetStippleOrigin(Tk_Canvas canvas, GC gc); +#endif +#ifndef Tk_CanvasTagsParseProc_TCL_DECLARED +#define Tk_CanvasTagsParseProc_TCL_DECLARED /* 18 */ -EXTERN int Tk_CanvasTagsParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, - char *widgRec, int offset)); +EXTERN int Tk_CanvasTagsParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef Tk_CanvasTagsPrintProc_TCL_DECLARED +#define Tk_CanvasTagsPrintProc_TCL_DECLARED /* 19 */ -EXTERN char * Tk_CanvasTagsPrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); +EXTERN char * Tk_CanvasTagsPrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif +#ifndef Tk_CanvasTkwin_TCL_DECLARED +#define Tk_CanvasTkwin_TCL_DECLARED /* 20 */ -EXTERN Tk_Window Tk_CanvasTkwin _ANSI_ARGS_((Tk_Canvas canvas)); +EXTERN Tk_Window Tk_CanvasTkwin(Tk_Canvas canvas); +#endif +#ifndef Tk_CanvasWindowCoords_TCL_DECLARED +#define Tk_CanvasWindowCoords_TCL_DECLARED /* 21 */ -EXTERN void Tk_CanvasWindowCoords _ANSI_ARGS_((Tk_Canvas canvas, - double x, double y, short *screenXPtr, - short *screenYPtr)); +EXTERN void Tk_CanvasWindowCoords(Tk_Canvas canvas, double x, + double y, short *screenXPtr, + short *screenYPtr); +#endif +#ifndef Tk_ChangeWindowAttributes_TCL_DECLARED +#define Tk_ChangeWindowAttributes_TCL_DECLARED /* 22 */ -EXTERN void Tk_ChangeWindowAttributes _ANSI_ARGS_(( - Tk_Window tkwin, unsigned long valueMask, - XSetWindowAttributes *attsPtr)); +EXTERN void Tk_ChangeWindowAttributes(Tk_Window tkwin, + unsigned long valueMask, + XSetWindowAttributes *attsPtr); +#endif +#ifndef Tk_CharBbox_TCL_DECLARED +#define Tk_CharBbox_TCL_DECLARED /* 23 */ -EXTERN int Tk_CharBbox _ANSI_ARGS_((Tk_TextLayout layout, - int index, int *xPtr, int *yPtr, - int *widthPtr, int *heightPtr)); +EXTERN int Tk_CharBbox(Tk_TextLayout layout, int index, + int *xPtr, int *yPtr, int *widthPtr, + int *heightPtr); +#endif +#ifndef Tk_ClearSelection_TCL_DECLARED +#define Tk_ClearSelection_TCL_DECLARED /* 24 */ -EXTERN void Tk_ClearSelection _ANSI_ARGS_((Tk_Window tkwin, - Atom selection)); +EXTERN void Tk_ClearSelection(Tk_Window tkwin, Atom selection); +#endif +#ifndef Tk_ClipboardAppend_TCL_DECLARED +#define Tk_ClipboardAppend_TCL_DECLARED /* 25 */ -EXTERN int Tk_ClipboardAppend _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_ClipboardAppend(Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, - char *buffer)); + char *buffer); +#endif +#ifndef Tk_ClipboardClear_TCL_DECLARED +#define Tk_ClipboardClear_TCL_DECLARED /* 26 */ -EXTERN int Tk_ClipboardClear _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin)); +EXTERN int Tk_ClipboardClear(Tcl_Interp *interp, + Tk_Window tkwin); +#endif +#ifndef Tk_ConfigureInfo_TCL_DECLARED +#define Tk_ConfigureInfo_TCL_DECLARED /* 27 */ -EXTERN int Tk_ConfigureInfo _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_ConfigSpec *specs, - char *widgRec, CONST char *argvName, - int flags)); +EXTERN int Tk_ConfigureInfo(Tcl_Interp *interp, Tk_Window tkwin, + Tk_ConfigSpec *specs, char *widgRec, + CONST char *argvName, int flags); +#endif +#ifndef Tk_ConfigureValue_TCL_DECLARED +#define Tk_ConfigureValue_TCL_DECLARED /* 28 */ -EXTERN int Tk_ConfigureValue _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_ConfigureValue(Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, char *widgRec, CONST char *argvName, - int flags)); + int flags); +#endif +#ifndef Tk_ConfigureWidget_TCL_DECLARED +#define Tk_ConfigureWidget_TCL_DECLARED /* 29 */ -EXTERN int Tk_ConfigureWidget _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_ConfigureWidget(Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, - int flags)); + int flags); +#endif +#ifndef Tk_ConfigureWindow_TCL_DECLARED +#define Tk_ConfigureWindow_TCL_DECLARED /* 30 */ -EXTERN void Tk_ConfigureWindow _ANSI_ARGS_((Tk_Window tkwin, +EXTERN void Tk_ConfigureWindow(Tk_Window tkwin, unsigned int valueMask, - XWindowChanges *valuePtr)); + XWindowChanges *valuePtr); +#endif +#ifndef Tk_ComputeTextLayout_TCL_DECLARED +#define Tk_ComputeTextLayout_TCL_DECLARED /* 31 */ -EXTERN Tk_TextLayout Tk_ComputeTextLayout _ANSI_ARGS_((Tk_Font font, - CONST char *str, int numChars, - int wrapLength, Tk_Justify justify, - int flags, int *widthPtr, int *heightPtr)); +EXTERN Tk_TextLayout Tk_ComputeTextLayout(Tk_Font font, CONST char *str, + int numChars, int wrapLength, + Tk_Justify justify, int flags, int *widthPtr, + int *heightPtr); +#endif +#ifndef Tk_CoordsToWindow_TCL_DECLARED +#define Tk_CoordsToWindow_TCL_DECLARED /* 32 */ -EXTERN Tk_Window Tk_CoordsToWindow _ANSI_ARGS_((int rootX, int rootY, - Tk_Window tkwin)); +EXTERN Tk_Window Tk_CoordsToWindow(int rootX, int rootY, + Tk_Window tkwin); +#endif +#ifndef Tk_CreateBinding_TCL_DECLARED +#define Tk_CreateBinding_TCL_DECLARED /* 33 */ -EXTERN unsigned long Tk_CreateBinding _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN unsigned long Tk_CreateBinding(Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventStr, - CONST char *script, int append)); + CONST char *command, int append); +#endif +#ifndef Tk_CreateBindingTable_TCL_DECLARED +#define Tk_CreateBindingTable_TCL_DECLARED /* 34 */ -EXTERN Tk_BindingTable Tk_CreateBindingTable _ANSI_ARGS_(( - Tcl_Interp *interp)); +EXTERN Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp); +#endif +#ifndef Tk_CreateErrorHandler_TCL_DECLARED +#define Tk_CreateErrorHandler_TCL_DECLARED /* 35 */ -EXTERN Tk_ErrorHandler Tk_CreateErrorHandler _ANSI_ARGS_((Display *display, - int errNum, int request, int minorCode, +EXTERN Tk_ErrorHandler Tk_CreateErrorHandler(Display *display, int errNum, + int request, int minorCode, Tk_ErrorProc *errorProc, - ClientData clientData)); + ClientData clientData); +#endif +#ifndef Tk_CreateEventHandler_TCL_DECLARED +#define Tk_CreateEventHandler_TCL_DECLARED /* 36 */ -EXTERN void Tk_CreateEventHandler _ANSI_ARGS_((Tk_Window token, +EXTERN void Tk_CreateEventHandler(Tk_Window token, unsigned long mask, Tk_EventProc *proc, - ClientData clientData)); + ClientData clientData); +#endif +#ifndef Tk_CreateGenericHandler_TCL_DECLARED +#define Tk_CreateGenericHandler_TCL_DECLARED /* 37 */ -EXTERN void Tk_CreateGenericHandler _ANSI_ARGS_(( - Tk_GenericProc *proc, ClientData clientData)); +EXTERN void Tk_CreateGenericHandler(Tk_GenericProc *proc, + ClientData clientData); +#endif +#ifndef Tk_CreateImageType_TCL_DECLARED +#define Tk_CreateImageType_TCL_DECLARED /* 38 */ -EXTERN void Tk_CreateImageType _ANSI_ARGS_(( - Tk_ImageType *typePtr)); +EXTERN void Tk_CreateImageType(Tk_ImageType *typePtr); +#endif +#ifndef Tk_CreateItemType_TCL_DECLARED +#define Tk_CreateItemType_TCL_DECLARED /* 39 */ -EXTERN void Tk_CreateItemType _ANSI_ARGS_((Tk_ItemType *typePtr)); +EXTERN void Tk_CreateItemType(Tk_ItemType *typePtr); +#endif +#ifndef Tk_CreatePhotoImageFormat_TCL_DECLARED +#define Tk_CreatePhotoImageFormat_TCL_DECLARED /* 40 */ -EXTERN void Tk_CreatePhotoImageFormat _ANSI_ARGS_(( - Tk_PhotoImageFormat *formatPtr)); +EXTERN void Tk_CreatePhotoImageFormat( + Tk_PhotoImageFormat *formatPtr); +#endif +#ifndef Tk_CreateSelHandler_TCL_DECLARED +#define Tk_CreateSelHandler_TCL_DECLARED /* 41 */ -EXTERN void Tk_CreateSelHandler _ANSI_ARGS_((Tk_Window tkwin, - Atom selection, Atom target, - Tk_SelectionProc *proc, - ClientData clientData, Atom format)); +EXTERN void Tk_CreateSelHandler(Tk_Window tkwin, Atom selection, + Atom target, Tk_SelectionProc *proc, + ClientData clientData, Atom format); +#endif +#ifndef Tk_CreateWindow_TCL_DECLARED +#define Tk_CreateWindow_TCL_DECLARED /* 42 */ -EXTERN Tk_Window Tk_CreateWindow _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window parent, CONST char *name, - CONST char *screenName)); +EXTERN Tk_Window Tk_CreateWindow(Tcl_Interp *interp, Tk_Window parent, + CONST char *name, CONST char *screenName); +#endif +#ifndef Tk_CreateWindowFromPath_TCL_DECLARED +#define Tk_CreateWindowFromPath_TCL_DECLARED /* 43 */ -EXTERN Tk_Window Tk_CreateWindowFromPath _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Window tkwin, - CONST char *pathName, CONST char *screenName)); +EXTERN Tk_Window Tk_CreateWindowFromPath(Tcl_Interp *interp, + Tk_Window tkwin, CONST char *pathName, + CONST char *screenName); +#endif +#ifndef Tk_DefineBitmap_TCL_DECLARED +#define Tk_DefineBitmap_TCL_DECLARED /* 44 */ -EXTERN int Tk_DefineBitmap _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *name, CONST char *source, - int width, int height)); +EXTERN int Tk_DefineBitmap(Tcl_Interp *interp, CONST char *name, + CONST char *source, int width, int height); +#endif +#ifndef Tk_DefineCursor_TCL_DECLARED +#define Tk_DefineCursor_TCL_DECLARED /* 45 */ -EXTERN void Tk_DefineCursor _ANSI_ARGS_((Tk_Window window, - Tk_Cursor cursor)); +EXTERN void Tk_DefineCursor(Tk_Window window, Tk_Cursor cursor); +#endif +#ifndef Tk_DeleteAllBindings_TCL_DECLARED +#define Tk_DeleteAllBindings_TCL_DECLARED /* 46 */ -EXTERN void Tk_DeleteAllBindings _ANSI_ARGS_(( - Tk_BindingTable bindingTable, - ClientData object)); +EXTERN void Tk_DeleteAllBindings(Tk_BindingTable bindingTable, + ClientData object); +#endif +#ifndef Tk_DeleteBinding_TCL_DECLARED +#define Tk_DeleteBinding_TCL_DECLARED /* 47 */ -EXTERN int Tk_DeleteBinding _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_DeleteBinding(Tcl_Interp *interp, Tk_BindingTable bindingTable, - ClientData object, CONST char *eventStr)); + ClientData object, CONST char *eventStr); +#endif +#ifndef Tk_DeleteBindingTable_TCL_DECLARED +#define Tk_DeleteBindingTable_TCL_DECLARED /* 48 */ -EXTERN void Tk_DeleteBindingTable _ANSI_ARGS_(( - Tk_BindingTable bindingTable)); +EXTERN void Tk_DeleteBindingTable(Tk_BindingTable bindingTable); +#endif +#ifndef Tk_DeleteErrorHandler_TCL_DECLARED +#define Tk_DeleteErrorHandler_TCL_DECLARED /* 49 */ -EXTERN void Tk_DeleteErrorHandler _ANSI_ARGS_(( - Tk_ErrorHandler handler)); +EXTERN void Tk_DeleteErrorHandler(Tk_ErrorHandler handler); +#endif +#ifndef Tk_DeleteEventHandler_TCL_DECLARED +#define Tk_DeleteEventHandler_TCL_DECLARED /* 50 */ -EXTERN void Tk_DeleteEventHandler _ANSI_ARGS_((Tk_Window token, +EXTERN void Tk_DeleteEventHandler(Tk_Window token, unsigned long mask, Tk_EventProc *proc, - ClientData clientData)); + ClientData clientData); +#endif +#ifndef Tk_DeleteGenericHandler_TCL_DECLARED +#define Tk_DeleteGenericHandler_TCL_DECLARED /* 51 */ -EXTERN void Tk_DeleteGenericHandler _ANSI_ARGS_(( - Tk_GenericProc *proc, ClientData clientData)); +EXTERN void Tk_DeleteGenericHandler(Tk_GenericProc *proc, + ClientData clientData); +#endif +#ifndef Tk_DeleteImage_TCL_DECLARED +#define Tk_DeleteImage_TCL_DECLARED /* 52 */ -EXTERN void Tk_DeleteImage _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *name)); +EXTERN void Tk_DeleteImage(Tcl_Interp *interp, CONST char *name); +#endif +#ifndef Tk_DeleteSelHandler_TCL_DECLARED +#define Tk_DeleteSelHandler_TCL_DECLARED /* 53 */ -EXTERN void Tk_DeleteSelHandler _ANSI_ARGS_((Tk_Window tkwin, - Atom selection, Atom target)); +EXTERN void Tk_DeleteSelHandler(Tk_Window tkwin, Atom selection, + Atom target); +#endif +#ifndef Tk_DestroyWindow_TCL_DECLARED +#define Tk_DestroyWindow_TCL_DECLARED /* 54 */ -EXTERN void Tk_DestroyWindow _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void Tk_DestroyWindow(Tk_Window tkwin); +#endif +#ifndef Tk_DisplayName_TCL_DECLARED +#define Tk_DisplayName_TCL_DECLARED /* 55 */ -EXTERN CONST84_RETURN char * Tk_DisplayName _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN CONST84_RETURN char * Tk_DisplayName(Tk_Window tkwin); +#endif +#ifndef Tk_DistanceToTextLayout_TCL_DECLARED +#define Tk_DistanceToTextLayout_TCL_DECLARED /* 56 */ -EXTERN int Tk_DistanceToTextLayout _ANSI_ARGS_(( - Tk_TextLayout layout, int x, int y)); +EXTERN int Tk_DistanceToTextLayout(Tk_TextLayout layout, int x, + int y); +#endif +#ifndef Tk_Draw3DPolygon_TCL_DECLARED +#define Tk_Draw3DPolygon_TCL_DECLARED /* 57 */ -EXTERN void Tk_Draw3DPolygon _ANSI_ARGS_((Tk_Window tkwin, - Drawable drawable, Tk_3DBorder border, - XPoint *pointPtr, int numPoints, - int borderWidth, int leftRelief)); +EXTERN void Tk_Draw3DPolygon(Tk_Window tkwin, Drawable drawable, + Tk_3DBorder border, XPoint *pointPtr, + int numPoints, int borderWidth, + int leftRelief); +#endif +#ifndef Tk_Draw3DRectangle_TCL_DECLARED +#define Tk_Draw3DRectangle_TCL_DECLARED /* 58 */ -EXTERN void Tk_Draw3DRectangle _ANSI_ARGS_((Tk_Window tkwin, +EXTERN void Tk_Draw3DRectangle(Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, - int borderWidth, int relief)); + int borderWidth, int relief); +#endif +#ifndef Tk_DrawChars_TCL_DECLARED +#define Tk_DrawChars_TCL_DECLARED /* 59 */ -EXTERN void Tk_DrawChars _ANSI_ARGS_((Display *display, - Drawable drawable, GC gc, Tk_Font tkfont, - CONST char *source, int numBytes, int x, - int y)); +EXTERN void Tk_DrawChars(Display *display, Drawable drawable, + GC gc, Tk_Font tkfont, CONST char *source, + int numBytes, int x, int y); +#endif +#ifndef Tk_DrawFocusHighlight_TCL_DECLARED +#define Tk_DrawFocusHighlight_TCL_DECLARED /* 60 */ -EXTERN void Tk_DrawFocusHighlight _ANSI_ARGS_((Tk_Window tkwin, - GC gc, int width, Drawable drawable)); +EXTERN void Tk_DrawFocusHighlight(Tk_Window tkwin, GC gc, + int width, Drawable drawable); +#endif +#ifndef Tk_DrawTextLayout_TCL_DECLARED +#define Tk_DrawTextLayout_TCL_DECLARED /* 61 */ -EXTERN void Tk_DrawTextLayout _ANSI_ARGS_((Display *display, +EXTERN void Tk_DrawTextLayout(Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, - int firstChar, int lastChar)); + int firstChar, int lastChar); +#endif +#ifndef Tk_Fill3DPolygon_TCL_DECLARED +#define Tk_Fill3DPolygon_TCL_DECLARED /* 62 */ -EXTERN void Tk_Fill3DPolygon _ANSI_ARGS_((Tk_Window tkwin, - Drawable drawable, Tk_3DBorder border, - XPoint *pointPtr, int numPoints, - int borderWidth, int leftRelief)); +EXTERN void Tk_Fill3DPolygon(Tk_Window tkwin, Drawable drawable, + Tk_3DBorder border, XPoint *pointPtr, + int numPoints, int borderWidth, + int leftRelief); +#endif +#ifndef Tk_Fill3DRectangle_TCL_DECLARED +#define Tk_Fill3DRectangle_TCL_DECLARED /* 63 */ -EXTERN void Tk_Fill3DRectangle _ANSI_ARGS_((Tk_Window tkwin, +EXTERN void Tk_Fill3DRectangle(Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, - int borderWidth, int relief)); + int borderWidth, int relief); +#endif +#ifndef Tk_FindPhoto_TCL_DECLARED +#define Tk_FindPhoto_TCL_DECLARED /* 64 */ -EXTERN Tk_PhotoHandle Tk_FindPhoto _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *imageName)); +EXTERN Tk_PhotoHandle Tk_FindPhoto(Tcl_Interp *interp, + CONST char *imageName); +#endif +#ifndef Tk_FontId_TCL_DECLARED +#define Tk_FontId_TCL_DECLARED /* 65 */ -EXTERN Font Tk_FontId _ANSI_ARGS_((Tk_Font font)); +EXTERN Font Tk_FontId(Tk_Font font); +#endif +#ifndef Tk_Free3DBorder_TCL_DECLARED +#define Tk_Free3DBorder_TCL_DECLARED /* 66 */ -EXTERN void Tk_Free3DBorder _ANSI_ARGS_((Tk_3DBorder border)); +EXTERN void Tk_Free3DBorder(Tk_3DBorder border); +#endif +#ifndef Tk_FreeBitmap_TCL_DECLARED +#define Tk_FreeBitmap_TCL_DECLARED /* 67 */ -EXTERN void Tk_FreeBitmap _ANSI_ARGS_((Display *display, - Pixmap bitmap)); +EXTERN void Tk_FreeBitmap(Display *display, Pixmap bitmap); +#endif +#ifndef Tk_FreeColor_TCL_DECLARED +#define Tk_FreeColor_TCL_DECLARED /* 68 */ -EXTERN void Tk_FreeColor _ANSI_ARGS_((XColor *colorPtr)); +EXTERN void Tk_FreeColor(XColor *colorPtr); +#endif +#ifndef Tk_FreeColormap_TCL_DECLARED +#define Tk_FreeColormap_TCL_DECLARED /* 69 */ -EXTERN void Tk_FreeColormap _ANSI_ARGS_((Display *display, - Colormap colormap)); +EXTERN void Tk_FreeColormap(Display *display, Colormap colormap); +#endif +#ifndef Tk_FreeCursor_TCL_DECLARED +#define Tk_FreeCursor_TCL_DECLARED /* 70 */ -EXTERN void Tk_FreeCursor _ANSI_ARGS_((Display *display, - Tk_Cursor cursor)); +EXTERN void Tk_FreeCursor(Display *display, Tk_Cursor cursor); +#endif +#ifndef Tk_FreeFont_TCL_DECLARED +#define Tk_FreeFont_TCL_DECLARED /* 71 */ -EXTERN void Tk_FreeFont _ANSI_ARGS_((Tk_Font f)); +EXTERN void Tk_FreeFont(Tk_Font f); +#endif +#ifndef Tk_FreeGC_TCL_DECLARED +#define Tk_FreeGC_TCL_DECLARED /* 72 */ -EXTERN void Tk_FreeGC _ANSI_ARGS_((Display *display, GC gc)); +EXTERN void Tk_FreeGC(Display *display, GC gc); +#endif +#ifndef Tk_FreeImage_TCL_DECLARED +#define Tk_FreeImage_TCL_DECLARED /* 73 */ -EXTERN void Tk_FreeImage _ANSI_ARGS_((Tk_Image image)); +EXTERN void Tk_FreeImage(Tk_Image image); +#endif +#ifndef Tk_FreeOptions_TCL_DECLARED +#define Tk_FreeOptions_TCL_DECLARED /* 74 */ -EXTERN void Tk_FreeOptions _ANSI_ARGS_((Tk_ConfigSpec *specs, - char *widgRec, Display *display, - int needFlags)); +EXTERN void Tk_FreeOptions(Tk_ConfigSpec *specs, char *widgRec, + Display *display, int needFlags); +#endif +#ifndef Tk_FreePixmap_TCL_DECLARED +#define Tk_FreePixmap_TCL_DECLARED /* 75 */ -EXTERN void Tk_FreePixmap _ANSI_ARGS_((Display *display, - Pixmap pixmap)); +EXTERN void Tk_FreePixmap(Display *display, Pixmap pixmap); +#endif +#ifndef Tk_FreeTextLayout_TCL_DECLARED +#define Tk_FreeTextLayout_TCL_DECLARED /* 76 */ -EXTERN void Tk_FreeTextLayout _ANSI_ARGS_(( - Tk_TextLayout textLayout)); +EXTERN void Tk_FreeTextLayout(Tk_TextLayout textLayout); +#endif +#ifndef Tk_FreeXId_TCL_DECLARED +#define Tk_FreeXId_TCL_DECLARED /* 77 */ -EXTERN void Tk_FreeXId _ANSI_ARGS_((Display *display, XID xid)); +EXTERN void Tk_FreeXId(Display *display, XID xid); +#endif +#ifndef Tk_GCForColor_TCL_DECLARED +#define Tk_GCForColor_TCL_DECLARED /* 78 */ -EXTERN GC Tk_GCForColor _ANSI_ARGS_((XColor *colorPtr, - Drawable drawable)); +EXTERN GC Tk_GCForColor(XColor *colorPtr, Drawable drawable); +#endif +#ifndef Tk_GeometryRequest_TCL_DECLARED +#define Tk_GeometryRequest_TCL_DECLARED /* 79 */ -EXTERN void Tk_GeometryRequest _ANSI_ARGS_((Tk_Window tkwin, - int reqWidth, int reqHeight)); +EXTERN void Tk_GeometryRequest(Tk_Window tkwin, int reqWidth, + int reqHeight); +#endif +#ifndef Tk_Get3DBorder_TCL_DECLARED +#define Tk_Get3DBorder_TCL_DECLARED /* 80 */ -EXTERN Tk_3DBorder Tk_Get3DBorder _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_Uid colorName)); +EXTERN Tk_3DBorder Tk_Get3DBorder(Tcl_Interp *interp, Tk_Window tkwin, + Tk_Uid colorName); +#endif +#ifndef Tk_GetAllBindings_TCL_DECLARED +#define Tk_GetAllBindings_TCL_DECLARED /* 81 */ -EXTERN void Tk_GetAllBindings _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN void Tk_GetAllBindings(Tcl_Interp *interp, Tk_BindingTable bindingTable, - ClientData object)); + ClientData object); +#endif +#ifndef Tk_GetAnchor_TCL_DECLARED +#define Tk_GetAnchor_TCL_DECLARED /* 82 */ -EXTERN int Tk_GetAnchor _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *str, Tk_Anchor *anchorPtr)); +EXTERN int Tk_GetAnchor(Tcl_Interp *interp, CONST char *str, + Tk_Anchor *anchorPtr); +#endif +#ifndef Tk_GetAtomName_TCL_DECLARED +#define Tk_GetAtomName_TCL_DECLARED /* 83 */ -EXTERN CONST84_RETURN char * Tk_GetAtomName _ANSI_ARGS_((Tk_Window tkwin, - Atom atom)); +EXTERN CONST84_RETURN char * Tk_GetAtomName(Tk_Window tkwin, Atom atom); +#endif +#ifndef Tk_GetBinding_TCL_DECLARED +#define Tk_GetBinding_TCL_DECLARED /* 84 */ -EXTERN CONST84_RETURN char * Tk_GetBinding _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN CONST84_RETURN char * Tk_GetBinding(Tcl_Interp *interp, Tk_BindingTable bindingTable, - ClientData object, CONST char *eventStr)); + ClientData object, CONST char *eventStr); +#endif +#ifndef Tk_GetBitmap_TCL_DECLARED +#define Tk_GetBitmap_TCL_DECLARED /* 85 */ -EXTERN Pixmap Tk_GetBitmap _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *str)); +EXTERN Pixmap Tk_GetBitmap(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *str); +#endif +#ifndef Tk_GetBitmapFromData_TCL_DECLARED +#define Tk_GetBitmapFromData_TCL_DECLARED /* 86 */ -EXTERN Pixmap Tk_GetBitmapFromData _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN Pixmap Tk_GetBitmapFromData(Tcl_Interp *interp, Tk_Window tkwin, CONST char *source, - int width, int height)); + int width, int height); +#endif +#ifndef Tk_GetCapStyle_TCL_DECLARED +#define Tk_GetCapStyle_TCL_DECLARED /* 87 */ -EXTERN int Tk_GetCapStyle _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *str, int *capPtr)); +EXTERN int Tk_GetCapStyle(Tcl_Interp *interp, CONST char *str, + int *capPtr); +#endif +#ifndef Tk_GetColor_TCL_DECLARED +#define Tk_GetColor_TCL_DECLARED /* 88 */ -EXTERN XColor * Tk_GetColor _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_Uid name)); +EXTERN XColor * Tk_GetColor(Tcl_Interp *interp, Tk_Window tkwin, + Tk_Uid name); +#endif +#ifndef Tk_GetColorByValue_TCL_DECLARED +#define Tk_GetColorByValue_TCL_DECLARED /* 89 */ -EXTERN XColor * Tk_GetColorByValue _ANSI_ARGS_((Tk_Window tkwin, - XColor *colorPtr)); +EXTERN XColor * Tk_GetColorByValue(Tk_Window tkwin, XColor *colorPtr); +#endif +#ifndef Tk_GetColormap_TCL_DECLARED +#define Tk_GetColormap_TCL_DECLARED /* 90 */ -EXTERN Colormap Tk_GetColormap _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *str)); +EXTERN Colormap Tk_GetColormap(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *str); +#endif +#ifndef Tk_GetCursor_TCL_DECLARED +#define Tk_GetCursor_TCL_DECLARED /* 91 */ -EXTERN Tk_Cursor Tk_GetCursor _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_Uid str)); +EXTERN Tk_Cursor Tk_GetCursor(Tcl_Interp *interp, Tk_Window tkwin, + Tk_Uid str); +#endif +#ifndef Tk_GetCursorFromData_TCL_DECLARED +#define Tk_GetCursorFromData_TCL_DECLARED /* 92 */ -EXTERN Tk_Cursor Tk_GetCursorFromData _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN Tk_Cursor Tk_GetCursorFromData(Tcl_Interp *interp, Tk_Window tkwin, CONST char *source, CONST char *mask, int width, int height, - int xHot, int yHot, Tk_Uid fg, Tk_Uid bg)); + int xHot, int yHot, Tk_Uid fg, Tk_Uid bg); +#endif +#ifndef Tk_GetFont_TCL_DECLARED +#define Tk_GetFont_TCL_DECLARED /* 93 */ -EXTERN Tk_Font Tk_GetFont _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *str)); +EXTERN Tk_Font Tk_GetFont(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *str); +#endif +#ifndef Tk_GetFontFromObj_TCL_DECLARED +#define Tk_GetFontFromObj_TCL_DECLARED /* 94 */ -EXTERN Tk_Font Tk_GetFontFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Tk_Font Tk_GetFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetFontMetrics_TCL_DECLARED +#define Tk_GetFontMetrics_TCL_DECLARED /* 95 */ -EXTERN void Tk_GetFontMetrics _ANSI_ARGS_((Tk_Font font, - Tk_FontMetrics *fmPtr)); +EXTERN void Tk_GetFontMetrics(Tk_Font font, + Tk_FontMetrics *fmPtr); +#endif +#ifndef Tk_GetGC_TCL_DECLARED +#define Tk_GetGC_TCL_DECLARED /* 96 */ -EXTERN GC Tk_GetGC _ANSI_ARGS_((Tk_Window tkwin, - unsigned long valueMask, XGCValues *valuePtr)); +EXTERN GC Tk_GetGC(Tk_Window tkwin, unsigned long valueMask, + XGCValues *valuePtr); +#endif +#ifndef Tk_GetImage_TCL_DECLARED +#define Tk_GetImage_TCL_DECLARED /* 97 */ -EXTERN Tk_Image Tk_GetImage _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *name, +EXTERN Tk_Image Tk_GetImage(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *name, Tk_ImageChangedProc *changeProc, - ClientData clientData)); + ClientData clientData); +#endif +#ifndef Tk_GetImageMasterData_TCL_DECLARED +#define Tk_GetImageMasterData_TCL_DECLARED /* 98 */ -EXTERN ClientData Tk_GetImageMasterData _ANSI_ARGS_(( - Tcl_Interp *interp, CONST char *name, - Tk_ImageType **typePtrPtr)); +EXTERN ClientData Tk_GetImageMasterData(Tcl_Interp *interp, + CONST char *name, Tk_ImageType **typePtrPtr); +#endif +#ifndef Tk_GetItemTypes_TCL_DECLARED +#define Tk_GetItemTypes_TCL_DECLARED /* 99 */ -EXTERN Tk_ItemType * Tk_GetItemTypes _ANSI_ARGS_((void)); +EXTERN Tk_ItemType * Tk_GetItemTypes(void); +#endif +#ifndef Tk_GetJoinStyle_TCL_DECLARED +#define Tk_GetJoinStyle_TCL_DECLARED /* 100 */ -EXTERN int Tk_GetJoinStyle _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *str, int *joinPtr)); +EXTERN int Tk_GetJoinStyle(Tcl_Interp *interp, CONST char *str, + int *joinPtr); +#endif +#ifndef Tk_GetJustify_TCL_DECLARED +#define Tk_GetJustify_TCL_DECLARED /* 101 */ -EXTERN int Tk_GetJustify _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *str, Tk_Justify *justifyPtr)); +EXTERN int Tk_GetJustify(Tcl_Interp *interp, CONST char *str, + Tk_Justify *justifyPtr); +#endif +#ifndef Tk_GetNumMainWindows_TCL_DECLARED +#define Tk_GetNumMainWindows_TCL_DECLARED /* 102 */ -EXTERN int Tk_GetNumMainWindows _ANSI_ARGS_((void)); +EXTERN int Tk_GetNumMainWindows(void); +#endif +#ifndef Tk_GetOption_TCL_DECLARED +#define Tk_GetOption_TCL_DECLARED /* 103 */ -EXTERN Tk_Uid Tk_GetOption _ANSI_ARGS_((Tk_Window tkwin, - CONST char *name, CONST char *className)); +EXTERN Tk_Uid Tk_GetOption(Tk_Window tkwin, CONST char *name, + CONST char *className); +#endif +#ifndef Tk_GetPixels_TCL_DECLARED +#define Tk_GetPixels_TCL_DECLARED /* 104 */ -EXTERN int Tk_GetPixels _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *str, - int *intPtr)); +EXTERN int Tk_GetPixels(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *str, int *intPtr); +#endif +#ifndef Tk_GetPixmap_TCL_DECLARED +#define Tk_GetPixmap_TCL_DECLARED /* 105 */ -EXTERN Pixmap Tk_GetPixmap _ANSI_ARGS_((Display *display, - Drawable d, int width, int height, int depth)); +EXTERN Pixmap Tk_GetPixmap(Display *display, Drawable d, int width, + int height, int depth); +#endif +#ifndef Tk_GetRelief_TCL_DECLARED +#define Tk_GetRelief_TCL_DECLARED /* 106 */ -EXTERN int Tk_GetRelief _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *name, int *reliefPtr)); +EXTERN int Tk_GetRelief(Tcl_Interp *interp, CONST char *name, + int *reliefPtr); +#endif +#ifndef Tk_GetRootCoords_TCL_DECLARED +#define Tk_GetRootCoords_TCL_DECLARED /* 107 */ -EXTERN void Tk_GetRootCoords _ANSI_ARGS_((Tk_Window tkwin, - int *xPtr, int *yPtr)); +EXTERN void Tk_GetRootCoords(Tk_Window tkwin, int *xPtr, + int *yPtr); +#endif +#ifndef Tk_GetScrollInfo_TCL_DECLARED +#define Tk_GetScrollInfo_TCL_DECLARED /* 108 */ -EXTERN int Tk_GetScrollInfo _ANSI_ARGS_((Tcl_Interp *interp, - int argc, CONST84 char **argv, - double *dblPtr, int *intPtr)); +EXTERN int Tk_GetScrollInfo(Tcl_Interp *interp, int argc, + CONST84 char **argv, double *dblPtr, + int *intPtr); +#endif +#ifndef Tk_GetScreenMM_TCL_DECLARED +#define Tk_GetScreenMM_TCL_DECLARED /* 109 */ -EXTERN int Tk_GetScreenMM _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *str, - double *doublePtr)); +EXTERN int Tk_GetScreenMM(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *str, double *doublePtr); +#endif +#ifndef Tk_GetSelection_TCL_DECLARED +#define Tk_GetSelection_TCL_DECLARED /* 110 */ -EXTERN int Tk_GetSelection _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Atom selection, Atom target, - Tk_GetSelProc *proc, ClientData clientData)); +EXTERN int Tk_GetSelection(Tcl_Interp *interp, Tk_Window tkwin, + Atom selection, Atom target, + Tk_GetSelProc *proc, ClientData clientData); +#endif +#ifndef Tk_GetUid_TCL_DECLARED +#define Tk_GetUid_TCL_DECLARED /* 111 */ -EXTERN Tk_Uid Tk_GetUid _ANSI_ARGS_((CONST char *str)); +EXTERN Tk_Uid Tk_GetUid(CONST char *str); +#endif +#ifndef Tk_GetVisual_TCL_DECLARED +#define Tk_GetVisual_TCL_DECLARED /* 112 */ -EXTERN Visual * Tk_GetVisual _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *str, - int *depthPtr, Colormap *colormapPtr)); +EXTERN Visual * Tk_GetVisual(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *str, int *depthPtr, + Colormap *colormapPtr); +#endif +#ifndef Tk_GetVRootGeometry_TCL_DECLARED +#define Tk_GetVRootGeometry_TCL_DECLARED /* 113 */ -EXTERN void Tk_GetVRootGeometry _ANSI_ARGS_((Tk_Window tkwin, - int *xPtr, int *yPtr, int *widthPtr, - int *heightPtr)); +EXTERN void Tk_GetVRootGeometry(Tk_Window tkwin, int *xPtr, + int *yPtr, int *widthPtr, int *heightPtr); +#endif +#ifndef Tk_Grab_TCL_DECLARED +#define Tk_Grab_TCL_DECLARED /* 114 */ -EXTERN int Tk_Grab _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, int grabGlobal)); +EXTERN int Tk_Grab(Tcl_Interp *interp, Tk_Window tkwin, + int grabGlobal); +#endif +#ifndef Tk_HandleEvent_TCL_DECLARED +#define Tk_HandleEvent_TCL_DECLARED /* 115 */ -EXTERN void Tk_HandleEvent _ANSI_ARGS_((XEvent *eventPtr)); +EXTERN void Tk_HandleEvent(XEvent *eventPtr); +#endif +#ifndef Tk_IdToWindow_TCL_DECLARED +#define Tk_IdToWindow_TCL_DECLARED /* 116 */ -EXTERN Tk_Window Tk_IdToWindow _ANSI_ARGS_((Display *display, - Window window)); +EXTERN Tk_Window Tk_IdToWindow(Display *display, Window window); +#endif +#ifndef Tk_ImageChanged_TCL_DECLARED +#define Tk_ImageChanged_TCL_DECLARED /* 117 */ -EXTERN void Tk_ImageChanged _ANSI_ARGS_((Tk_ImageMaster master, - int x, int y, int width, int height, - int imageWidth, int imageHeight)); +EXTERN void Tk_ImageChanged(Tk_ImageMaster master, int x, int y, + int width, int height, int imageWidth, + int imageHeight); +#endif +#ifndef Tk_Init_TCL_DECLARED +#define Tk_Init_TCL_DECLARED /* 118 */ -EXTERN int Tk_Init _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int Tk_Init(Tcl_Interp *interp); +#endif +#ifndef Tk_InternAtom_TCL_DECLARED +#define Tk_InternAtom_TCL_DECLARED /* 119 */ -EXTERN Atom Tk_InternAtom _ANSI_ARGS_((Tk_Window tkwin, - CONST char *name)); +EXTERN Atom Tk_InternAtom(Tk_Window tkwin, CONST char *name); +#endif +#ifndef Tk_IntersectTextLayout_TCL_DECLARED +#define Tk_IntersectTextLayout_TCL_DECLARED /* 120 */ -EXTERN int Tk_IntersectTextLayout _ANSI_ARGS_(( - Tk_TextLayout layout, int x, int y, - int width, int height)); +EXTERN int Tk_IntersectTextLayout(Tk_TextLayout layout, int x, + int y, int width, int height); +#endif +#ifndef Tk_MaintainGeometry_TCL_DECLARED +#define Tk_MaintainGeometry_TCL_DECLARED /* 121 */ -EXTERN void Tk_MaintainGeometry _ANSI_ARGS_((Tk_Window slave, +EXTERN void Tk_MaintainGeometry(Tk_Window slave, Tk_Window master, int x, int y, int width, - int height)); + int height); +#endif +#ifndef Tk_MainWindow_TCL_DECLARED +#define Tk_MainWindow_TCL_DECLARED /* 122 */ -EXTERN Tk_Window Tk_MainWindow _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN Tk_Window Tk_MainWindow(Tcl_Interp *interp); +#endif +#ifndef Tk_MakeWindowExist_TCL_DECLARED +#define Tk_MakeWindowExist_TCL_DECLARED /* 123 */ -EXTERN void Tk_MakeWindowExist _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void Tk_MakeWindowExist(Tk_Window tkwin); +#endif +#ifndef Tk_ManageGeometry_TCL_DECLARED +#define Tk_ManageGeometry_TCL_DECLARED /* 124 */ -EXTERN void Tk_ManageGeometry _ANSI_ARGS_((Tk_Window tkwin, - Tk_GeomMgr *mgrPtr, ClientData clientData)); +EXTERN void Tk_ManageGeometry(Tk_Window tkwin, + CONST Tk_GeomMgr *mgrPtr, + ClientData clientData); +#endif +#ifndef Tk_MapWindow_TCL_DECLARED +#define Tk_MapWindow_TCL_DECLARED /* 125 */ -EXTERN void Tk_MapWindow _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void Tk_MapWindow(Tk_Window tkwin); +#endif +#ifndef Tk_MeasureChars_TCL_DECLARED +#define Tk_MeasureChars_TCL_DECLARED /* 126 */ -EXTERN int Tk_MeasureChars _ANSI_ARGS_((Tk_Font tkfont, - CONST char *source, int numBytes, - int maxPixels, int flags, int *lengthPtr)); +EXTERN int Tk_MeasureChars(Tk_Font tkfont, CONST char *source, + int numBytes, int maxPixels, int flags, + int *lengthPtr); +#endif +#ifndef Tk_MoveResizeWindow_TCL_DECLARED +#define Tk_MoveResizeWindow_TCL_DECLARED /* 127 */ -EXTERN void Tk_MoveResizeWindow _ANSI_ARGS_((Tk_Window tkwin, - int x, int y, int width, int height)); +EXTERN void Tk_MoveResizeWindow(Tk_Window tkwin, int x, int y, + int width, int height); +#endif +#ifndef Tk_MoveWindow_TCL_DECLARED +#define Tk_MoveWindow_TCL_DECLARED /* 128 */ -EXTERN void Tk_MoveWindow _ANSI_ARGS_((Tk_Window tkwin, int x, - int y)); +EXTERN void Tk_MoveWindow(Tk_Window tkwin, int x, int y); +#endif +#ifndef Tk_MoveToplevelWindow_TCL_DECLARED +#define Tk_MoveToplevelWindow_TCL_DECLARED /* 129 */ -EXTERN void Tk_MoveToplevelWindow _ANSI_ARGS_((Tk_Window tkwin, - int x, int y)); +EXTERN void Tk_MoveToplevelWindow(Tk_Window tkwin, int x, int y); +#endif +#ifndef Tk_NameOf3DBorder_TCL_DECLARED +#define Tk_NameOf3DBorder_TCL_DECLARED /* 130 */ -EXTERN CONST84_RETURN char * Tk_NameOf3DBorder _ANSI_ARGS_(( - Tk_3DBorder border)); +EXTERN CONST84_RETURN char * Tk_NameOf3DBorder(Tk_3DBorder border); +#endif +#ifndef Tk_NameOfAnchor_TCL_DECLARED +#define Tk_NameOfAnchor_TCL_DECLARED /* 131 */ -EXTERN CONST84_RETURN char * Tk_NameOfAnchor _ANSI_ARGS_((Tk_Anchor anchor)); +EXTERN CONST84_RETURN char * Tk_NameOfAnchor(Tk_Anchor anchor); +#endif +#ifndef Tk_NameOfBitmap_TCL_DECLARED +#define Tk_NameOfBitmap_TCL_DECLARED /* 132 */ -EXTERN CONST84_RETURN char * Tk_NameOfBitmap _ANSI_ARGS_((Display *display, - Pixmap bitmap)); +EXTERN CONST84_RETURN char * Tk_NameOfBitmap(Display *display, Pixmap bitmap); +#endif +#ifndef Tk_NameOfCapStyle_TCL_DECLARED +#define Tk_NameOfCapStyle_TCL_DECLARED /* 133 */ -EXTERN CONST84_RETURN char * Tk_NameOfCapStyle _ANSI_ARGS_((int cap)); +EXTERN CONST84_RETURN char * Tk_NameOfCapStyle(int cap); +#endif +#ifndef Tk_NameOfColor_TCL_DECLARED +#define Tk_NameOfColor_TCL_DECLARED /* 134 */ -EXTERN CONST84_RETURN char * Tk_NameOfColor _ANSI_ARGS_((XColor *colorPtr)); +EXTERN CONST84_RETURN char * Tk_NameOfColor(XColor *colorPtr); +#endif +#ifndef Tk_NameOfCursor_TCL_DECLARED +#define Tk_NameOfCursor_TCL_DECLARED /* 135 */ -EXTERN CONST84_RETURN char * Tk_NameOfCursor _ANSI_ARGS_((Display *display, - Tk_Cursor cursor)); +EXTERN CONST84_RETURN char * Tk_NameOfCursor(Display *display, + Tk_Cursor cursor); +#endif +#ifndef Tk_NameOfFont_TCL_DECLARED +#define Tk_NameOfFont_TCL_DECLARED /* 136 */ -EXTERN CONST84_RETURN char * Tk_NameOfFont _ANSI_ARGS_((Tk_Font font)); +EXTERN CONST84_RETURN char * Tk_NameOfFont(Tk_Font font); +#endif +#ifndef Tk_NameOfImage_TCL_DECLARED +#define Tk_NameOfImage_TCL_DECLARED /* 137 */ -EXTERN CONST84_RETURN char * Tk_NameOfImage _ANSI_ARGS_(( - Tk_ImageMaster imageMaster)); +EXTERN CONST84_RETURN char * Tk_NameOfImage(Tk_ImageMaster imageMaster); +#endif +#ifndef Tk_NameOfJoinStyle_TCL_DECLARED +#define Tk_NameOfJoinStyle_TCL_DECLARED /* 138 */ -EXTERN CONST84_RETURN char * Tk_NameOfJoinStyle _ANSI_ARGS_((int join)); +EXTERN CONST84_RETURN char * Tk_NameOfJoinStyle(int join); +#endif +#ifndef Tk_NameOfJustify_TCL_DECLARED +#define Tk_NameOfJustify_TCL_DECLARED /* 139 */ -EXTERN CONST84_RETURN char * Tk_NameOfJustify _ANSI_ARGS_(( - Tk_Justify justify)); +EXTERN CONST84_RETURN char * Tk_NameOfJustify(Tk_Justify justify); +#endif +#ifndef Tk_NameOfRelief_TCL_DECLARED +#define Tk_NameOfRelief_TCL_DECLARED /* 140 */ -EXTERN CONST84_RETURN char * Tk_NameOfRelief _ANSI_ARGS_((int relief)); +EXTERN CONST84_RETURN char * Tk_NameOfRelief(int relief); +#endif +#ifndef Tk_NameToWindow_TCL_DECLARED +#define Tk_NameToWindow_TCL_DECLARED /* 141 */ -EXTERN Tk_Window Tk_NameToWindow _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *pathName, Tk_Window tkwin)); +EXTERN Tk_Window Tk_NameToWindow(Tcl_Interp *interp, + CONST char *pathName, Tk_Window tkwin); +#endif +#ifndef Tk_OwnSelection_TCL_DECLARED +#define Tk_OwnSelection_TCL_DECLARED /* 142 */ -EXTERN void Tk_OwnSelection _ANSI_ARGS_((Tk_Window tkwin, - Atom selection, Tk_LostSelProc *proc, - ClientData clientData)); +EXTERN void Tk_OwnSelection(Tk_Window tkwin, Atom selection, + Tk_LostSelProc *proc, ClientData clientData); +#endif +#ifndef Tk_ParseArgv_TCL_DECLARED +#define Tk_ParseArgv_TCL_DECLARED /* 143 */ -EXTERN int Tk_ParseArgv _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, int *argcPtr, - CONST84 char **argv, Tk_ArgvInfo *argTable, - int flags)); +EXTERN int Tk_ParseArgv(Tcl_Interp *interp, Tk_Window tkwin, + int *argcPtr, CONST84 char **argv, + Tk_ArgvInfo *argTable, int flags); +#endif +#ifndef Tk_PhotoPutBlock_NoComposite_TCL_DECLARED +#define Tk_PhotoPutBlock_NoComposite_TCL_DECLARED /* 144 */ -EXTERN void Tk_PhotoPutBlock_NoComposite _ANSI_ARGS_(( - Tk_PhotoHandle handle, +EXTERN void Tk_PhotoPutBlock_NoComposite(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, - int width, int height)); + int width, int height); +#endif +#ifndef Tk_PhotoPutZoomedBlock_NoComposite_TCL_DECLARED +#define Tk_PhotoPutZoomedBlock_NoComposite_TCL_DECLARED /* 145 */ -EXTERN void Tk_PhotoPutZoomedBlock_NoComposite _ANSI_ARGS_(( +EXTERN 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)); + int subsampleX, int subsampleY); +#endif +#ifndef Tk_PhotoGetImage_TCL_DECLARED +#define Tk_PhotoGetImage_TCL_DECLARED /* 146 */ -EXTERN int Tk_PhotoGetImage _ANSI_ARGS_((Tk_PhotoHandle handle, - Tk_PhotoImageBlock *blockPtr)); +EXTERN int Tk_PhotoGetImage(Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr); +#endif +#ifndef Tk_PhotoBlank_TCL_DECLARED +#define Tk_PhotoBlank_TCL_DECLARED /* 147 */ -EXTERN void Tk_PhotoBlank _ANSI_ARGS_((Tk_PhotoHandle handle)); +EXTERN void Tk_PhotoBlank(Tk_PhotoHandle handle); +#endif +#ifndef Tk_PhotoExpand_Panic_TCL_DECLARED +#define Tk_PhotoExpand_Panic_TCL_DECLARED /* 148 */ -EXTERN void Tk_PhotoExpand _ANSI_ARGS_((Tk_PhotoHandle handle, - int width, int height)); +EXTERN void Tk_PhotoExpand_Panic(Tk_PhotoHandle handle, + int width, int height); +#endif +#ifndef Tk_PhotoGetSize_TCL_DECLARED +#define Tk_PhotoGetSize_TCL_DECLARED /* 149 */ -EXTERN void Tk_PhotoGetSize _ANSI_ARGS_((Tk_PhotoHandle handle, - int *widthPtr, int *heightPtr)); +EXTERN void Tk_PhotoGetSize(Tk_PhotoHandle handle, int *widthPtr, + int *heightPtr); +#endif +#ifndef Tk_PhotoSetSize_Panic_TCL_DECLARED +#define Tk_PhotoSetSize_Panic_TCL_DECLARED /* 150 */ -EXTERN void Tk_PhotoSetSize _ANSI_ARGS_((Tk_PhotoHandle handle, - int width, int height)); +EXTERN void Tk_PhotoSetSize_Panic(Tk_PhotoHandle handle, + int width, int height); +#endif +#ifndef Tk_PointToChar_TCL_DECLARED +#define Tk_PointToChar_TCL_DECLARED /* 151 */ -EXTERN int Tk_PointToChar _ANSI_ARGS_((Tk_TextLayout layout, - int x, int y)); +EXTERN int Tk_PointToChar(Tk_TextLayout layout, int x, int y); +#endif +#ifndef Tk_PostscriptFontName_TCL_DECLARED +#define Tk_PostscriptFontName_TCL_DECLARED /* 152 */ -EXTERN int Tk_PostscriptFontName _ANSI_ARGS_((Tk_Font tkfont, - Tcl_DString *dsPtr)); +EXTERN int Tk_PostscriptFontName(Tk_Font tkfont, + Tcl_DString *dsPtr); +#endif +#ifndef Tk_PreserveColormap_TCL_DECLARED +#define Tk_PreserveColormap_TCL_DECLARED /* 153 */ -EXTERN void Tk_PreserveColormap _ANSI_ARGS_((Display *display, - Colormap colormap)); +EXTERN void Tk_PreserveColormap(Display *display, + Colormap colormap); +#endif +#ifndef Tk_QueueWindowEvent_TCL_DECLARED +#define Tk_QueueWindowEvent_TCL_DECLARED /* 154 */ -EXTERN void Tk_QueueWindowEvent _ANSI_ARGS_((XEvent *eventPtr, - Tcl_QueuePosition position)); +EXTERN void Tk_QueueWindowEvent(XEvent *eventPtr, + Tcl_QueuePosition position); +#endif +#ifndef Tk_RedrawImage_TCL_DECLARED +#define Tk_RedrawImage_TCL_DECLARED /* 155 */ -EXTERN void Tk_RedrawImage _ANSI_ARGS_((Tk_Image image, - int imageX, int imageY, int width, - int height, Drawable drawable, int drawableX, - int drawableY)); +EXTERN void Tk_RedrawImage(Tk_Image image, int imageX, + int imageY, int width, int height, + Drawable drawable, int drawableX, + int drawableY); +#endif +#ifndef Tk_ResizeWindow_TCL_DECLARED +#define Tk_ResizeWindow_TCL_DECLARED /* 156 */ -EXTERN void Tk_ResizeWindow _ANSI_ARGS_((Tk_Window tkwin, - int width, int height)); +EXTERN void Tk_ResizeWindow(Tk_Window tkwin, int width, + int height); +#endif +#ifndef Tk_RestackWindow_TCL_DECLARED +#define Tk_RestackWindow_TCL_DECLARED /* 157 */ -EXTERN int Tk_RestackWindow _ANSI_ARGS_((Tk_Window tkwin, - int aboveBelow, Tk_Window other)); +EXTERN int Tk_RestackWindow(Tk_Window tkwin, int aboveBelow, + Tk_Window other); +#endif +#ifndef Tk_RestrictEvents_TCL_DECLARED +#define Tk_RestrictEvents_TCL_DECLARED /* 158 */ -EXTERN Tk_RestrictProc * Tk_RestrictEvents _ANSI_ARGS_(( - Tk_RestrictProc *proc, ClientData arg, - ClientData *prevArgPtr)); +EXTERN Tk_RestrictProc * Tk_RestrictEvents(Tk_RestrictProc *proc, + ClientData arg, ClientData *prevArgPtr); +#endif +#ifndef Tk_SafeInit_TCL_DECLARED +#define Tk_SafeInit_TCL_DECLARED /* 159 */ -EXTERN int Tk_SafeInit _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int Tk_SafeInit(Tcl_Interp *interp); +#endif +#ifndef Tk_SetAppName_TCL_DECLARED +#define Tk_SetAppName_TCL_DECLARED /* 160 */ -EXTERN CONST char * Tk_SetAppName _ANSI_ARGS_((Tk_Window tkwin, - CONST char *name)); +EXTERN CONST char * Tk_SetAppName(Tk_Window tkwin, CONST char *name); +#endif +#ifndef Tk_SetBackgroundFromBorder_TCL_DECLARED +#define Tk_SetBackgroundFromBorder_TCL_DECLARED /* 161 */ -EXTERN void Tk_SetBackgroundFromBorder _ANSI_ARGS_(( - Tk_Window tkwin, Tk_3DBorder border)); +EXTERN void Tk_SetBackgroundFromBorder(Tk_Window tkwin, + Tk_3DBorder border); +#endif +#ifndef Tk_SetClass_TCL_DECLARED +#define Tk_SetClass_TCL_DECLARED /* 162 */ -EXTERN void Tk_SetClass _ANSI_ARGS_((Tk_Window tkwin, - CONST char *className)); +EXTERN void Tk_SetClass(Tk_Window tkwin, CONST char *className); +#endif +#ifndef Tk_SetGrid_TCL_DECLARED +#define Tk_SetGrid_TCL_DECLARED /* 163 */ -EXTERN void Tk_SetGrid _ANSI_ARGS_((Tk_Window tkwin, - int reqWidth, int reqHeight, int gridWidth, - int gridHeight)); +EXTERN void Tk_SetGrid(Tk_Window tkwin, int reqWidth, + int reqHeight, int gridWidth, int gridHeight); +#endif +#ifndef Tk_SetInternalBorder_TCL_DECLARED +#define Tk_SetInternalBorder_TCL_DECLARED /* 164 */ -EXTERN void Tk_SetInternalBorder _ANSI_ARGS_((Tk_Window tkwin, - int width)); +EXTERN void Tk_SetInternalBorder(Tk_Window tkwin, int width); +#endif +#ifndef Tk_SetWindowBackground_TCL_DECLARED +#define Tk_SetWindowBackground_TCL_DECLARED /* 165 */ -EXTERN void Tk_SetWindowBackground _ANSI_ARGS_((Tk_Window tkwin, - unsigned long pixel)); +EXTERN void Tk_SetWindowBackground(Tk_Window tkwin, + unsigned long pixel); +#endif +#ifndef Tk_SetWindowBackgroundPixmap_TCL_DECLARED +#define Tk_SetWindowBackgroundPixmap_TCL_DECLARED /* 166 */ -EXTERN void Tk_SetWindowBackgroundPixmap _ANSI_ARGS_(( - Tk_Window tkwin, Pixmap pixmap)); +EXTERN void Tk_SetWindowBackgroundPixmap(Tk_Window tkwin, + Pixmap pixmap); +#endif +#ifndef Tk_SetWindowBorder_TCL_DECLARED +#define Tk_SetWindowBorder_TCL_DECLARED /* 167 */ -EXTERN void Tk_SetWindowBorder _ANSI_ARGS_((Tk_Window tkwin, - unsigned long pixel)); +EXTERN void Tk_SetWindowBorder(Tk_Window tkwin, + unsigned long pixel); +#endif +#ifndef Tk_SetWindowBorderWidth_TCL_DECLARED +#define Tk_SetWindowBorderWidth_TCL_DECLARED /* 168 */ -EXTERN void Tk_SetWindowBorderWidth _ANSI_ARGS_((Tk_Window tkwin, - int width)); +EXTERN void Tk_SetWindowBorderWidth(Tk_Window tkwin, int width); +#endif +#ifndef Tk_SetWindowBorderPixmap_TCL_DECLARED +#define Tk_SetWindowBorderPixmap_TCL_DECLARED /* 169 */ -EXTERN void Tk_SetWindowBorderPixmap _ANSI_ARGS_(( - Tk_Window tkwin, Pixmap pixmap)); +EXTERN void Tk_SetWindowBorderPixmap(Tk_Window tkwin, + Pixmap pixmap); +#endif +#ifndef Tk_SetWindowColormap_TCL_DECLARED +#define Tk_SetWindowColormap_TCL_DECLARED /* 170 */ -EXTERN void Tk_SetWindowColormap _ANSI_ARGS_((Tk_Window tkwin, - Colormap colormap)); +EXTERN void Tk_SetWindowColormap(Tk_Window tkwin, + Colormap colormap); +#endif +#ifndef Tk_SetWindowVisual_TCL_DECLARED +#define Tk_SetWindowVisual_TCL_DECLARED /* 171 */ -EXTERN int Tk_SetWindowVisual _ANSI_ARGS_((Tk_Window tkwin, - Visual *visual, int depth, Colormap colormap)); +EXTERN int Tk_SetWindowVisual(Tk_Window tkwin, Visual *visual, + int depth, Colormap colormap); +#endif +#ifndef Tk_SizeOfBitmap_TCL_DECLARED +#define Tk_SizeOfBitmap_TCL_DECLARED /* 172 */ -EXTERN void Tk_SizeOfBitmap _ANSI_ARGS_((Display *display, - Pixmap bitmap, int *widthPtr, int *heightPtr)); +EXTERN void Tk_SizeOfBitmap(Display *display, Pixmap bitmap, + int *widthPtr, int *heightPtr); +#endif +#ifndef Tk_SizeOfImage_TCL_DECLARED +#define Tk_SizeOfImage_TCL_DECLARED /* 173 */ -EXTERN void Tk_SizeOfImage _ANSI_ARGS_((Tk_Image image, - int *widthPtr, int *heightPtr)); +EXTERN void Tk_SizeOfImage(Tk_Image image, int *widthPtr, + int *heightPtr); +#endif +#ifndef Tk_StrictMotif_TCL_DECLARED +#define Tk_StrictMotif_TCL_DECLARED /* 174 */ -EXTERN int Tk_StrictMotif _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN int Tk_StrictMotif(Tk_Window tkwin); +#endif +#ifndef Tk_TextLayoutToPostscript_TCL_DECLARED +#define Tk_TextLayoutToPostscript_TCL_DECLARED /* 175 */ -EXTERN void Tk_TextLayoutToPostscript _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_TextLayout layout)); +EXTERN void Tk_TextLayoutToPostscript(Tcl_Interp *interp, + Tk_TextLayout layout); +#endif +#ifndef Tk_TextWidth_TCL_DECLARED +#define Tk_TextWidth_TCL_DECLARED /* 176 */ -EXTERN int Tk_TextWidth _ANSI_ARGS_((Tk_Font font, - CONST char *str, int numBytes)); +EXTERN int Tk_TextWidth(Tk_Font font, CONST char *str, + int numBytes); +#endif +#ifndef Tk_UndefineCursor_TCL_DECLARED +#define Tk_UndefineCursor_TCL_DECLARED /* 177 */ -EXTERN void Tk_UndefineCursor _ANSI_ARGS_((Tk_Window window)); +EXTERN void Tk_UndefineCursor(Tk_Window window); +#endif +#ifndef Tk_UnderlineChars_TCL_DECLARED +#define Tk_UnderlineChars_TCL_DECLARED /* 178 */ -EXTERN void Tk_UnderlineChars _ANSI_ARGS_((Display *display, +EXTERN void Tk_UnderlineChars(Display *display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char *source, int x, int y, - int firstByte, int lastByte)); + int firstByte, int lastByte); +#endif +#ifndef Tk_UnderlineTextLayout_TCL_DECLARED +#define Tk_UnderlineTextLayout_TCL_DECLARED /* 179 */ -EXTERN void Tk_UnderlineTextLayout _ANSI_ARGS_((Display *display, +EXTERN void Tk_UnderlineTextLayout(Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, - int underline)); + int underline); +#endif +#ifndef Tk_Ungrab_TCL_DECLARED +#define Tk_Ungrab_TCL_DECLARED /* 180 */ -EXTERN void Tk_Ungrab _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void Tk_Ungrab(Tk_Window tkwin); +#endif +#ifndef Tk_UnmaintainGeometry_TCL_DECLARED +#define Tk_UnmaintainGeometry_TCL_DECLARED /* 181 */ -EXTERN void Tk_UnmaintainGeometry _ANSI_ARGS_((Tk_Window slave, - Tk_Window master)); +EXTERN void Tk_UnmaintainGeometry(Tk_Window slave, + Tk_Window master); +#endif +#ifndef Tk_UnmapWindow_TCL_DECLARED +#define Tk_UnmapWindow_TCL_DECLARED /* 182 */ -EXTERN void Tk_UnmapWindow _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void Tk_UnmapWindow(Tk_Window tkwin); +#endif +#ifndef Tk_UnsetGrid_TCL_DECLARED +#define Tk_UnsetGrid_TCL_DECLARED /* 183 */ -EXTERN void Tk_UnsetGrid _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void Tk_UnsetGrid(Tk_Window tkwin); +#endif +#ifndef Tk_UpdatePointer_TCL_DECLARED +#define Tk_UpdatePointer_TCL_DECLARED /* 184 */ -EXTERN void Tk_UpdatePointer _ANSI_ARGS_((Tk_Window tkwin, int x, - int y, int state)); +EXTERN void Tk_UpdatePointer(Tk_Window tkwin, int x, int y, + int state); +#endif +#ifndef Tk_AllocBitmapFromObj_TCL_DECLARED +#define Tk_AllocBitmapFromObj_TCL_DECLARED /* 185 */ -EXTERN Pixmap Tk_AllocBitmapFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Pixmap Tk_AllocBitmapFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_Alloc3DBorderFromObj_TCL_DECLARED +#define Tk_Alloc3DBorderFromObj_TCL_DECLARED /* 186 */ -EXTERN Tk_3DBorder Tk_Alloc3DBorderFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Tk_3DBorder Tk_Alloc3DBorderFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_AllocColorFromObj_TCL_DECLARED +#define Tk_AllocColorFromObj_TCL_DECLARED /* 187 */ -EXTERN XColor * Tk_AllocColorFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *objPtr)); +EXTERN XColor * Tk_AllocColorFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_AllocCursorFromObj_TCL_DECLARED +#define Tk_AllocCursorFromObj_TCL_DECLARED /* 188 */ -EXTERN Tk_Cursor Tk_AllocCursorFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Tk_Cursor Tk_AllocCursorFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_AllocFontFromObj_TCL_DECLARED +#define Tk_AllocFontFromObj_TCL_DECLARED /* 189 */ -EXTERN Tk_Font Tk_AllocFontFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *objPtr)); +EXTERN Tk_Font Tk_AllocFontFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_CreateOptionTable_TCL_DECLARED +#define Tk_CreateOptionTable_TCL_DECLARED /* 190 */ -EXTERN Tk_OptionTable Tk_CreateOptionTable _ANSI_ARGS_((Tcl_Interp *interp, - CONST Tk_OptionSpec *templatePtr)); +EXTERN Tk_OptionTable Tk_CreateOptionTable(Tcl_Interp *interp, + CONST Tk_OptionSpec *templatePtr); +#endif +#ifndef Tk_DeleteOptionTable_TCL_DECLARED +#define Tk_DeleteOptionTable_TCL_DECLARED /* 191 */ -EXTERN void Tk_DeleteOptionTable _ANSI_ARGS_(( - Tk_OptionTable optionTable)); +EXTERN void Tk_DeleteOptionTable(Tk_OptionTable optionTable); +#endif +#ifndef Tk_Free3DBorderFromObj_TCL_DECLARED +#define Tk_Free3DBorderFromObj_TCL_DECLARED /* 192 */ -EXTERN void Tk_Free3DBorderFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN void Tk_Free3DBorderFromObj(Tk_Window tkwin, + Tcl_Obj *objPtr); +#endif +#ifndef Tk_FreeBitmapFromObj_TCL_DECLARED +#define Tk_FreeBitmapFromObj_TCL_DECLARED /* 193 */ -EXTERN void Tk_FreeBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN void Tk_FreeBitmapFromObj(Tk_Window tkwin, + Tcl_Obj *objPtr); +#endif +#ifndef Tk_FreeColorFromObj_TCL_DECLARED +#define Tk_FreeColorFromObj_TCL_DECLARED /* 194 */ -EXTERN void Tk_FreeColorFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN void Tk_FreeColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_FreeConfigOptions_TCL_DECLARED +#define Tk_FreeConfigOptions_TCL_DECLARED /* 195 */ -EXTERN void Tk_FreeConfigOptions _ANSI_ARGS_((char *recordPtr, - Tk_OptionTable optionToken, Tk_Window tkwin)); +EXTERN void Tk_FreeConfigOptions(char *recordPtr, + Tk_OptionTable optionToken, Tk_Window tkwin); +#endif +#ifndef Tk_FreeSavedOptions_TCL_DECLARED +#define Tk_FreeSavedOptions_TCL_DECLARED /* 196 */ -EXTERN void Tk_FreeSavedOptions _ANSI_ARGS_(( - Tk_SavedOptions *savePtr)); +EXTERN void Tk_FreeSavedOptions(Tk_SavedOptions *savePtr); +#endif +#ifndef Tk_FreeCursorFromObj_TCL_DECLARED +#define Tk_FreeCursorFromObj_TCL_DECLARED /* 197 */ -EXTERN void Tk_FreeCursorFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN void Tk_FreeCursorFromObj(Tk_Window tkwin, + Tcl_Obj *objPtr); +#endif +#ifndef Tk_FreeFontFromObj_TCL_DECLARED +#define Tk_FreeFontFromObj_TCL_DECLARED /* 198 */ -EXTERN void Tk_FreeFontFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN void Tk_FreeFontFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_Get3DBorderFromObj_TCL_DECLARED +#define Tk_Get3DBorderFromObj_TCL_DECLARED /* 199 */ -EXTERN Tk_3DBorder Tk_Get3DBorderFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Tk_3DBorder Tk_Get3DBorderFromObj(Tk_Window tkwin, + Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetAnchorFromObj_TCL_DECLARED +#define Tk_GetAnchorFromObj_TCL_DECLARED /* 200 */ -EXTERN int Tk_GetAnchorFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, Tk_Anchor *anchorPtr)); +EXTERN int Tk_GetAnchorFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Tk_Anchor *anchorPtr); +#endif +#ifndef Tk_GetBitmapFromObj_TCL_DECLARED +#define Tk_GetBitmapFromObj_TCL_DECLARED /* 201 */ -EXTERN Pixmap Tk_GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Pixmap Tk_GetBitmapFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetColorFromObj_TCL_DECLARED +#define Tk_GetColorFromObj_TCL_DECLARED /* 202 */ -EXTERN XColor * Tk_GetColorFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN XColor * Tk_GetColorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetCursorFromObj_TCL_DECLARED +#define Tk_GetCursorFromObj_TCL_DECLARED /* 203 */ -EXTERN Tk_Cursor Tk_GetCursorFromObj _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Obj *objPtr)); +EXTERN Tk_Cursor Tk_GetCursorFromObj(Tk_Window tkwin, Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetOptionInfo_TCL_DECLARED +#define Tk_GetOptionInfo_TCL_DECLARED /* 204 */ -EXTERN Tcl_Obj * Tk_GetOptionInfo _ANSI_ARGS_((Tcl_Interp *interp, - char *recordPtr, Tk_OptionTable optionTable, - Tcl_Obj *namePtr, Tk_Window tkwin)); +EXTERN Tcl_Obj * Tk_GetOptionInfo(Tcl_Interp *interp, char *recordPtr, + Tk_OptionTable optionTable, Tcl_Obj *namePtr, + Tk_Window tkwin); +#endif +#ifndef Tk_GetOptionValue_TCL_DECLARED +#define Tk_GetOptionValue_TCL_DECLARED /* 205 */ -EXTERN Tcl_Obj * Tk_GetOptionValue _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN Tcl_Obj * Tk_GetOptionValue(Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, - Tcl_Obj *namePtr, Tk_Window tkwin)); + Tcl_Obj *namePtr, Tk_Window tkwin); +#endif +#ifndef Tk_GetJustifyFromObj_TCL_DECLARED +#define Tk_GetJustifyFromObj_TCL_DECLARED /* 206 */ -EXTERN int Tk_GetJustifyFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, Tk_Justify *justifyPtr)); +EXTERN int Tk_GetJustifyFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Tk_Justify *justifyPtr); +#endif +#ifndef Tk_GetMMFromObj_TCL_DECLARED +#define Tk_GetMMFromObj_TCL_DECLARED /* 207 */ -EXTERN int Tk_GetMMFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *objPtr, - double *doublePtr)); +EXTERN int Tk_GetMMFromObj(Tcl_Interp *interp, Tk_Window tkwin, + Tcl_Obj *objPtr, double *doublePtr); +#endif +#ifndef Tk_GetPixelsFromObj_TCL_DECLARED +#define Tk_GetPixelsFromObj_TCL_DECLARED /* 208 */ -EXTERN int Tk_GetPixelsFromObj _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_GetPixelsFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, - int *intPtr)); + int *intPtr); +#endif +#ifndef Tk_GetReliefFromObj_TCL_DECLARED +#define Tk_GetReliefFromObj_TCL_DECLARED /* 209 */ -EXTERN int Tk_GetReliefFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr, int *resultPtr)); +EXTERN int Tk_GetReliefFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, int *resultPtr); +#endif +#ifndef Tk_GetScrollInfoObj_TCL_DECLARED +#define Tk_GetScrollInfoObj_TCL_DECLARED /* 210 */ -EXTERN int Tk_GetScrollInfoObj _ANSI_ARGS_((Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[], - double *dblPtr, int *intPtr)); +EXTERN int Tk_GetScrollInfoObj(Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[], double *dblPtr, + int *intPtr); +#endif +#ifndef Tk_InitOptions_TCL_DECLARED +#define Tk_InitOptions_TCL_DECLARED /* 211 */ -EXTERN int Tk_InitOptions _ANSI_ARGS_((Tcl_Interp *interp, - char *recordPtr, Tk_OptionTable optionToken, - Tk_Window tkwin)); +EXTERN int Tk_InitOptions(Tcl_Interp *interp, char *recordPtr, + Tk_OptionTable optionToken, Tk_Window tkwin); +#endif +#ifndef Tk_MainEx_TCL_DECLARED +#define Tk_MainEx_TCL_DECLARED /* 212 */ -EXTERN void Tk_MainEx _ANSI_ARGS_((int argc, char **argv, +EXTERN void Tk_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, - Tcl_Interp *interp)); + Tcl_Interp *interp); +#endif +#ifndef Tk_RestoreSavedOptions_TCL_DECLARED +#define Tk_RestoreSavedOptions_TCL_DECLARED /* 213 */ -EXTERN void Tk_RestoreSavedOptions _ANSI_ARGS_(( - Tk_SavedOptions *savePtr)); +EXTERN void Tk_RestoreSavedOptions(Tk_SavedOptions *savePtr); +#endif +#ifndef Tk_SetOptions_TCL_DECLARED +#define Tk_SetOptions_TCL_DECLARED /* 214 */ -EXTERN int Tk_SetOptions _ANSI_ARGS_((Tcl_Interp *interp, - char *recordPtr, Tk_OptionTable optionTable, - int objc, Tcl_Obj *CONST objv[], - Tk_Window tkwin, Tk_SavedOptions *savePtr, - int *maskPtr)); +EXTERN 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); +#endif +#ifndef Tk_InitConsoleChannels_TCL_DECLARED +#define Tk_InitConsoleChannels_TCL_DECLARED /* 215 */ -EXTERN void Tk_InitConsoleChannels _ANSI_ARGS_(( - Tcl_Interp *interp)); +EXTERN void Tk_InitConsoleChannels(Tcl_Interp *interp); +#endif +#ifndef Tk_CreateConsoleWindow_TCL_DECLARED +#define Tk_CreateConsoleWindow_TCL_DECLARED /* 216 */ -EXTERN int Tk_CreateConsoleWindow _ANSI_ARGS_(( - Tcl_Interp *interp)); +EXTERN int Tk_CreateConsoleWindow(Tcl_Interp *interp); +#endif +#ifndef Tk_CreateSmoothMethod_TCL_DECLARED +#define Tk_CreateSmoothMethod_TCL_DECLARED /* 217 */ -EXTERN void Tk_CreateSmoothMethod _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_SmoothMethod *method)); +EXTERN void Tk_CreateSmoothMethod(Tcl_Interp *interp, + Tk_SmoothMethod *method); +#endif /* Slot 218 is reserved */ /* Slot 219 is reserved */ +#ifndef Tk_GetDash_TCL_DECLARED +#define Tk_GetDash_TCL_DECLARED /* 220 */ -EXTERN int Tk_GetDash _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *value, Tk_Dash *dash)); +EXTERN int Tk_GetDash(Tcl_Interp *interp, CONST char *value, + Tk_Dash *dash); +#endif +#ifndef Tk_CreateOutline_TCL_DECLARED +#define Tk_CreateOutline_TCL_DECLARED /* 221 */ -EXTERN void Tk_CreateOutline _ANSI_ARGS_((Tk_Outline *outline)); +EXTERN void Tk_CreateOutline(Tk_Outline *outline); +#endif +#ifndef Tk_DeleteOutline_TCL_DECLARED +#define Tk_DeleteOutline_TCL_DECLARED /* 222 */ -EXTERN void Tk_DeleteOutline _ANSI_ARGS_((Display *display, - Tk_Outline *outline)); +EXTERN void Tk_DeleteOutline(Display *display, + Tk_Outline *outline); +#endif +#ifndef Tk_ConfigOutlineGC_TCL_DECLARED +#define Tk_ConfigOutlineGC_TCL_DECLARED /* 223 */ -EXTERN int Tk_ConfigOutlineGC _ANSI_ARGS_((XGCValues *gcValues, +EXTERN int Tk_ConfigOutlineGC(XGCValues *gcValues, Tk_Canvas canvas, Tk_Item *item, - Tk_Outline *outline)); + Tk_Outline *outline); +#endif +#ifndef Tk_ChangeOutlineGC_TCL_DECLARED +#define Tk_ChangeOutlineGC_TCL_DECLARED /* 224 */ -EXTERN int Tk_ChangeOutlineGC _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *item, Tk_Outline *outline)); +EXTERN int Tk_ChangeOutlineGC(Tk_Canvas canvas, Tk_Item *item, + Tk_Outline *outline); +#endif +#ifndef Tk_ResetOutlineGC_TCL_DECLARED +#define Tk_ResetOutlineGC_TCL_DECLARED /* 225 */ -EXTERN int Tk_ResetOutlineGC _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *item, Tk_Outline *outline)); +EXTERN int Tk_ResetOutlineGC(Tk_Canvas canvas, Tk_Item *item, + Tk_Outline *outline); +#endif +#ifndef Tk_CanvasPsOutline_TCL_DECLARED +#define Tk_CanvasPsOutline_TCL_DECLARED /* 226 */ -EXTERN int Tk_CanvasPsOutline _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *item, Tk_Outline *outline)); +EXTERN int Tk_CanvasPsOutline(Tk_Canvas canvas, Tk_Item *item, + Tk_Outline *outline); +#endif +#ifndef Tk_SetTSOrigin_TCL_DECLARED +#define Tk_SetTSOrigin_TCL_DECLARED /* 227 */ -EXTERN void Tk_SetTSOrigin _ANSI_ARGS_((Tk_Window tkwin, GC gc, - int x, int y)); +EXTERN void Tk_SetTSOrigin(Tk_Window tkwin, GC gc, int x, int y); +#endif +#ifndef Tk_CanvasGetCoordFromObj_TCL_DECLARED +#define Tk_CanvasGetCoordFromObj_TCL_DECLARED /* 228 */ -EXTERN int Tk_CanvasGetCoordFromObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Canvas canvas, - Tcl_Obj *obj, double *doublePtr)); +EXTERN int Tk_CanvasGetCoordFromObj(Tcl_Interp *interp, + Tk_Canvas canvas, Tcl_Obj *obj, + double *doublePtr); +#endif +#ifndef Tk_CanvasSetOffset_TCL_DECLARED +#define Tk_CanvasSetOffset_TCL_DECLARED /* 229 */ -EXTERN void Tk_CanvasSetOffset _ANSI_ARGS_((Tk_Canvas canvas, - GC gc, Tk_TSOffset *offset)); +EXTERN void Tk_CanvasSetOffset(Tk_Canvas canvas, GC gc, + Tk_TSOffset *offset); +#endif +#ifndef Tk_DitherPhoto_TCL_DECLARED +#define Tk_DitherPhoto_TCL_DECLARED /* 230 */ -EXTERN void Tk_DitherPhoto _ANSI_ARGS_((Tk_PhotoHandle handle, - int x, int y, int width, int height)); +EXTERN void Tk_DitherPhoto(Tk_PhotoHandle handle, int x, int y, + int width, int height); +#endif +#ifndef Tk_PostscriptBitmap_TCL_DECLARED +#define Tk_PostscriptBitmap_TCL_DECLARED /* 231 */ -EXTERN int Tk_PostscriptBitmap _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_PostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, int startY, - int width, int height)); + int width, int height); +#endif +#ifndef Tk_PostscriptColor_TCL_DECLARED +#define Tk_PostscriptColor_TCL_DECLARED /* 232 */ -EXTERN int Tk_PostscriptColor _ANSI_ARGS_((Tcl_Interp *interp, - Tk_PostscriptInfo psInfo, XColor *colorPtr)); +EXTERN int Tk_PostscriptColor(Tcl_Interp *interp, + Tk_PostscriptInfo psInfo, XColor *colorPtr); +#endif +#ifndef Tk_PostscriptFont_TCL_DECLARED +#define Tk_PostscriptFont_TCL_DECLARED /* 233 */ -EXTERN int Tk_PostscriptFont _ANSI_ARGS_((Tcl_Interp *interp, - Tk_PostscriptInfo psInfo, Tk_Font font)); +EXTERN int Tk_PostscriptFont(Tcl_Interp *interp, + Tk_PostscriptInfo psInfo, Tk_Font font); +#endif +#ifndef Tk_PostscriptImage_TCL_DECLARED +#define Tk_PostscriptImage_TCL_DECLARED /* 234 */ -EXTERN int Tk_PostscriptImage _ANSI_ARGS_((Tk_Image image, +EXTERN int Tk_PostscriptImage(Tk_Image image, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, - int width, int height, int prepass)); + int width, int height, int prepass); +#endif +#ifndef Tk_PostscriptPath_TCL_DECLARED +#define Tk_PostscriptPath_TCL_DECLARED /* 235 */ -EXTERN void Tk_PostscriptPath _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN void Tk_PostscriptPath(Tcl_Interp *interp, Tk_PostscriptInfo psInfo, double *coordPtr, - int numPoints)); + int numPoints); +#endif +#ifndef Tk_PostscriptStipple_TCL_DECLARED +#define Tk_PostscriptStipple_TCL_DECLARED /* 236 */ -EXTERN int Tk_PostscriptStipple _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_PostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, - Pixmap bitmap)); + Pixmap bitmap); +#endif +#ifndef Tk_PostscriptY_TCL_DECLARED +#define Tk_PostscriptY_TCL_DECLARED /* 237 */ -EXTERN double Tk_PostscriptY _ANSI_ARGS_((double y, - Tk_PostscriptInfo psInfo)); +EXTERN double Tk_PostscriptY(double y, Tk_PostscriptInfo psInfo); +#endif +#ifndef Tk_PostscriptPhoto_TCL_DECLARED +#define Tk_PostscriptPhoto_TCL_DECLARED /* 238 */ -EXTERN int Tk_PostscriptPhoto _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int Tk_PostscriptPhoto(Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo, int width, - int height)); + int height); +#endif +#ifndef Tk_CreateClientMessageHandler_TCL_DECLARED +#define Tk_CreateClientMessageHandler_TCL_DECLARED /* 239 */ -EXTERN void Tk_CreateClientMessageHandler _ANSI_ARGS_(( - Tk_ClientMessageProc *proc)); +EXTERN void Tk_CreateClientMessageHandler( + Tk_ClientMessageProc *proc); +#endif +#ifndef Tk_DeleteClientMessageHandler_TCL_DECLARED +#define Tk_DeleteClientMessageHandler_TCL_DECLARED /* 240 */ -EXTERN void Tk_DeleteClientMessageHandler _ANSI_ARGS_(( - Tk_ClientMessageProc *proc)); +EXTERN void Tk_DeleteClientMessageHandler( + Tk_ClientMessageProc *proc); +#endif +#ifndef Tk_CreateAnonymousWindow_TCL_DECLARED +#define Tk_CreateAnonymousWindow_TCL_DECLARED /* 241 */ -EXTERN Tk_Window Tk_CreateAnonymousWindow _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Window parent, - CONST char *screenName)); +EXTERN Tk_Window Tk_CreateAnonymousWindow(Tcl_Interp *interp, + Tk_Window parent, CONST char *screenName); +#endif +#ifndef Tk_SetClassProcs_TCL_DECLARED +#define Tk_SetClassProcs_TCL_DECLARED /* 242 */ -EXTERN void Tk_SetClassProcs _ANSI_ARGS_((Tk_Window tkwin, +EXTERN void Tk_SetClassProcs(Tk_Window tkwin, Tk_ClassProcs *procs, - ClientData instanceData)); + ClientData instanceData); +#endif +#ifndef Tk_SetInternalBorderEx_TCL_DECLARED +#define Tk_SetInternalBorderEx_TCL_DECLARED /* 243 */ -EXTERN void Tk_SetInternalBorderEx _ANSI_ARGS_((Tk_Window tkwin, - int left, int right, int top, int bottom)); +EXTERN void Tk_SetInternalBorderEx(Tk_Window tkwin, int left, + int right, int top, int bottom); +#endif +#ifndef Tk_SetMinimumRequestSize_TCL_DECLARED +#define Tk_SetMinimumRequestSize_TCL_DECLARED /* 244 */ -EXTERN void Tk_SetMinimumRequestSize _ANSI_ARGS_(( - Tk_Window tkwin, int minWidth, int minHeight)); +EXTERN void Tk_SetMinimumRequestSize(Tk_Window tkwin, + int minWidth, int minHeight); +#endif +#ifndef Tk_SetCaretPos_TCL_DECLARED +#define Tk_SetCaretPos_TCL_DECLARED /* 245 */ -EXTERN void Tk_SetCaretPos _ANSI_ARGS_((Tk_Window tkwin, int x, - int y, int height)); +EXTERN void Tk_SetCaretPos(Tk_Window tkwin, int x, int y, + int height); +#endif +#ifndef Tk_PhotoPutBlock_Panic_TCL_DECLARED +#define Tk_PhotoPutBlock_Panic_TCL_DECLARED /* 246 */ -EXTERN void Tk_PhotoPutBlock _ANSI_ARGS_((Tk_PhotoHandle handle, +EXTERN void Tk_PhotoPutBlock_Panic(Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, - int width, int height, int compRule)); + int width, int height, int compRule); +#endif +#ifndef Tk_PhotoPutZoomedBlock_Panic_TCL_DECLARED +#define Tk_PhotoPutZoomedBlock_Panic_TCL_DECLARED /* 247 */ -EXTERN void Tk_PhotoPutZoomedBlock _ANSI_ARGS_(( - Tk_PhotoHandle handle, +EXTERN 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)); + int subsampleX, int subsampleY, int compRule); +#endif +#ifndef Tk_CollapseMotionEvents_TCL_DECLARED +#define Tk_CollapseMotionEvents_TCL_DECLARED /* 248 */ -EXTERN int Tk_CollapseMotionEvents _ANSI_ARGS_(( - Display *display, int collapse)); +EXTERN int Tk_CollapseMotionEvents(Display *display, + int collapse); +#endif +#ifndef Tk_RegisterStyleEngine_TCL_DECLARED +#define Tk_RegisterStyleEngine_TCL_DECLARED /* 249 */ -EXTERN Tk_StyleEngine Tk_RegisterStyleEngine _ANSI_ARGS_((CONST char *name, - Tk_StyleEngine parent)); +EXTERN Tk_StyleEngine Tk_RegisterStyleEngine(CONST char *name, + Tk_StyleEngine parent); +#endif +#ifndef Tk_GetStyleEngine_TCL_DECLARED +#define Tk_GetStyleEngine_TCL_DECLARED /* 250 */ -EXTERN Tk_StyleEngine Tk_GetStyleEngine _ANSI_ARGS_((CONST char *name)); +EXTERN Tk_StyleEngine Tk_GetStyleEngine(CONST char *name); +#endif +#ifndef Tk_RegisterStyledElement_TCL_DECLARED +#define Tk_RegisterStyledElement_TCL_DECLARED /* 251 */ -EXTERN int Tk_RegisterStyledElement _ANSI_ARGS_(( - Tk_StyleEngine engine, - Tk_ElementSpec *templatePtr)); +EXTERN int Tk_RegisterStyledElement(Tk_StyleEngine engine, + Tk_ElementSpec *templatePtr); +#endif +#ifndef Tk_GetElementId_TCL_DECLARED +#define Tk_GetElementId_TCL_DECLARED /* 252 */ -EXTERN int Tk_GetElementId _ANSI_ARGS_((CONST char *name)); +EXTERN int Tk_GetElementId(CONST char *name); +#endif +#ifndef Tk_CreateStyle_TCL_DECLARED +#define Tk_CreateStyle_TCL_DECLARED /* 253 */ -EXTERN Tk_Style Tk_CreateStyle _ANSI_ARGS_((CONST char *name, - Tk_StyleEngine engine, ClientData clientData)); +EXTERN Tk_Style Tk_CreateStyle(CONST char *name, + Tk_StyleEngine engine, ClientData clientData); +#endif +#ifndef Tk_GetStyle_TCL_DECLARED +#define Tk_GetStyle_TCL_DECLARED /* 254 */ -EXTERN Tk_Style Tk_GetStyle _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *name)); +EXTERN Tk_Style Tk_GetStyle(Tcl_Interp *interp, CONST char *name); +#endif +#ifndef Tk_FreeStyle_TCL_DECLARED +#define Tk_FreeStyle_TCL_DECLARED /* 255 */ -EXTERN void Tk_FreeStyle _ANSI_ARGS_((Tk_Style style)); +EXTERN void Tk_FreeStyle(Tk_Style style); +#endif +#ifndef Tk_NameOfStyle_TCL_DECLARED +#define Tk_NameOfStyle_TCL_DECLARED /* 256 */ -EXTERN CONST char * Tk_NameOfStyle _ANSI_ARGS_((Tk_Style style)); +EXTERN CONST char * Tk_NameOfStyle(Tk_Style style); +#endif +#ifndef Tk_AllocStyleFromObj_TCL_DECLARED +#define Tk_AllocStyleFromObj_TCL_DECLARED /* 257 */ -EXTERN Tk_Style Tk_AllocStyleFromObj _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); +EXTERN Tk_Style Tk_AllocStyleFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetStyleFromObj_TCL_DECLARED +#define Tk_GetStyleFromObj_TCL_DECLARED /* 258 */ -EXTERN Tk_Style Tk_GetStyleFromObj _ANSI_ARGS_((Tcl_Obj *objPtr)); +EXTERN Tk_Style Tk_GetStyleFromObj(Tcl_Obj *objPtr); +#endif +#ifndef Tk_FreeStyleFromObj_TCL_DECLARED +#define Tk_FreeStyleFromObj_TCL_DECLARED /* 259 */ -EXTERN void Tk_FreeStyleFromObj _ANSI_ARGS_((Tcl_Obj *objPtr)); +EXTERN void Tk_FreeStyleFromObj(Tcl_Obj *objPtr); +#endif +#ifndef Tk_GetStyledElement_TCL_DECLARED +#define Tk_GetStyledElement_TCL_DECLARED /* 260 */ -EXTERN Tk_StyledElement Tk_GetStyledElement _ANSI_ARGS_((Tk_Style style, - int elementId, Tk_OptionTable optionTable)); +EXTERN Tk_StyledElement Tk_GetStyledElement(Tk_Style style, int elementId, + Tk_OptionTable optionTable); +#endif +#ifndef Tk_GetElementSize_TCL_DECLARED +#define Tk_GetElementSize_TCL_DECLARED /* 261 */ -EXTERN void Tk_GetElementSize _ANSI_ARGS_((Tk_Style style, +EXTERN void Tk_GetElementSize(Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int width, int height, - int inner, int *widthPtr, int *heightPtr)); + int inner, int *widthPtr, int *heightPtr); +#endif +#ifndef Tk_GetElementBox_TCL_DECLARED +#define Tk_GetElementBox_TCL_DECLARED /* 262 */ -EXTERN void Tk_GetElementBox _ANSI_ARGS_((Tk_Style style, +EXTERN 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)); + int *widthPtr, int *heightPtr); +#endif +#ifndef Tk_GetElementBorderWidth_TCL_DECLARED +#define Tk_GetElementBorderWidth_TCL_DECLARED /* 263 */ -EXTERN int Tk_GetElementBorderWidth _ANSI_ARGS_((Tk_Style style, +EXTERN int Tk_GetElementBorderWidth(Tk_Style style, Tk_StyledElement element, char *recordPtr, - Tk_Window tkwin)); + Tk_Window tkwin); +#endif +#ifndef Tk_DrawElement_TCL_DECLARED +#define Tk_DrawElement_TCL_DECLARED /* 264 */ -EXTERN void Tk_DrawElement _ANSI_ARGS_((Tk_Style style, +EXTERN 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)); + int width, int height, int state); +#endif +#ifndef Tk_PhotoExpand_TCL_DECLARED +#define Tk_PhotoExpand_TCL_DECLARED +/* 265 */ +EXTERN int Tk_PhotoExpand(Tcl_Interp *interp, + Tk_PhotoHandle handle, int width, int height); +#endif +#ifndef Tk_PhotoPutBlock_TCL_DECLARED +#define Tk_PhotoPutBlock_TCL_DECLARED +/* 266 */ +EXTERN int Tk_PhotoPutBlock(Tcl_Interp *interp, + Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, int x, int y, + int width, int height, int compRule); +#endif +#ifndef Tk_PhotoPutZoomedBlock_TCL_DECLARED +#define Tk_PhotoPutZoomedBlock_TCL_DECLARED +/* 267 */ +EXTERN 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); +#endif +#ifndef Tk_PhotoSetSize_TCL_DECLARED +#define Tk_PhotoSetSize_TCL_DECLARED +/* 268 */ +EXTERN int Tk_PhotoSetSize(Tcl_Interp *interp, + Tk_PhotoHandle handle, int width, int height); +#endif +#ifndef Tk_GetUserInactiveTime_TCL_DECLARED +#define Tk_GetUserInactiveTime_TCL_DECLARED +/* 269 */ +EXTERN long Tk_GetUserInactiveTime(Display *dpy); +#endif +#ifndef Tk_ResetUserInactiveTime_TCL_DECLARED +#define Tk_ResetUserInactiveTime_TCL_DECLARED +/* 270 */ +EXTERN void Tk_ResetUserInactiveTime(Display *dpy); +#endif +#ifndef Tk_Interp_TCL_DECLARED +#define Tk_Interp_TCL_DECLARED +/* 271 */ +EXTERN Tcl_Interp * Tk_Interp(Tk_Window tkwin); +#endif +#ifndef Tk_CreateOldImageType_TCL_DECLARED +#define Tk_CreateOldImageType_TCL_DECLARED +/* 272 */ +EXTERN void Tk_CreateOldImageType(Tk_ImageType *typePtr); +#endif +#ifndef Tk_CreateOldPhotoImageFormat_TCL_DECLARED +#define Tk_CreateOldPhotoImageFormat_TCL_DECLARED +/* 273 */ +EXTERN void Tk_CreateOldPhotoImageFormat( + Tk_PhotoImageFormat *formatPtr); +#endif typedef struct TkStubHooks { struct TkPlatStubs *tkPlatStubs; @@ -917,271 +1686,280 @@ typedef struct TkStubs { int magic; struct TkStubHooks *hooks; - void (*tk_MainLoop) _ANSI_ARGS_((void)); /* 0 */ - XColor * (*tk_3DBorderColor) _ANSI_ARGS_((Tk_3DBorder border)); /* 1 */ - GC (*tk_3DBorderGC) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 2 */ - void (*tk_3DHorizontalBevel) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftIn, int rightIn, int topBevel, int relief)); /* 3 */ - void (*tk_3DVerticalBevel) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftBevel, int relief)); /* 4 */ - void (*tk_AddOption) _ANSI_ARGS_((Tk_Window tkwin, CONST char *name, CONST char *value, int priority)); /* 5 */ - void (*tk_BindEvent) _ANSI_ARGS_((Tk_BindingTable bindingTable, XEvent *eventPtr, Tk_Window tkwin, int numObjects, ClientData *objectPtr)); /* 6 */ - void (*tk_CanvasDrawableCoords) _ANSI_ARGS_((Tk_Canvas canvas, double x, double y, short *drawableXPtr, short *drawableYPtr)); /* 7 */ - void (*tk_CanvasEventuallyRedraw) _ANSI_ARGS_((Tk_Canvas canvas, int x1, int y1, int x2, int y2)); /* 8 */ - int (*tk_CanvasGetCoord) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, CONST char *str, double *doublePtr)); /* 9 */ - Tk_CanvasTextInfo * (*tk_CanvasGetTextInfo) _ANSI_ARGS_((Tk_Canvas canvas)); /* 10 */ - int (*tk_CanvasPsBitmap) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap, int x, int y, int width, int height)); /* 11 */ - int (*tk_CanvasPsColor) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, XColor *colorPtr)); /* 12 */ - int (*tk_CanvasPsFont) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Font font)); /* 13 */ - void (*tk_CanvasPsPath) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, int numPoints)); /* 14 */ - int (*tk_CanvasPsStipple) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap)); /* 15 */ - double (*tk_CanvasPsY) _ANSI_ARGS_((Tk_Canvas canvas, double y)); /* 16 */ - void (*tk_CanvasSetStippleOrigin) _ANSI_ARGS_((Tk_Canvas canvas, GC gc)); /* 17 */ - int (*tk_CanvasTagsParseProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, CONST char *value, char *widgRec, int offset)); /* 18 */ - char * (*tk_CanvasTagsPrintProc) _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)); /* 19 */ - Tk_Window (*tk_CanvasTkwin) _ANSI_ARGS_((Tk_Canvas canvas)); /* 20 */ - void (*tk_CanvasWindowCoords) _ANSI_ARGS_((Tk_Canvas canvas, double x, double y, short *screenXPtr, short *screenYPtr)); /* 21 */ - void (*tk_ChangeWindowAttributes) _ANSI_ARGS_((Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes *attsPtr)); /* 22 */ - int (*tk_CharBbox) _ANSI_ARGS_((Tk_TextLayout layout, int index, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)); /* 23 */ - void (*tk_ClearSelection) _ANSI_ARGS_((Tk_Window tkwin, Atom selection)); /* 24 */ - int (*tk_ClipboardAppend) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, char *buffer)); /* 25 */ - int (*tk_ClipboardClear) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin)); /* 26 */ - int (*tk_ConfigureInfo) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, char *widgRec, CONST char *argvName, int flags)); /* 27 */ - int (*tk_ConfigureValue) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, char *widgRec, CONST char *argvName, int flags)); /* 28 */ - int (*tk_ConfigureWidget) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags)); /* 29 */ - void (*tk_ConfigureWindow) _ANSI_ARGS_((Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr)); /* 30 */ - Tk_TextLayout (*tk_ComputeTextLayout) _ANSI_ARGS_((Tk_Font font, CONST char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr)); /* 31 */ - Tk_Window (*tk_CoordsToWindow) _ANSI_ARGS_((int rootX, int rootY, Tk_Window tkwin)); /* 32 */ - unsigned long (*tk_CreateBinding) _ANSI_ARGS_((Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventStr, CONST char *script, int append)); /* 33 */ - Tk_BindingTable (*tk_CreateBindingTable) _ANSI_ARGS_((Tcl_Interp *interp)); /* 34 */ - Tk_ErrorHandler (*tk_CreateErrorHandler) _ANSI_ARGS_((Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, ClientData clientData)); /* 35 */ - void (*tk_CreateEventHandler) _ANSI_ARGS_((Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData)); /* 36 */ - void (*tk_CreateGenericHandler) _ANSI_ARGS_((Tk_GenericProc *proc, ClientData clientData)); /* 37 */ - void (*tk_CreateImageType) _ANSI_ARGS_((Tk_ImageType *typePtr)); /* 38 */ - void (*tk_CreateItemType) _ANSI_ARGS_((Tk_ItemType *typePtr)); /* 39 */ - void (*tk_CreatePhotoImageFormat) _ANSI_ARGS_((Tk_PhotoImageFormat *formatPtr)); /* 40 */ - void (*tk_CreateSelHandler) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Atom target, Tk_SelectionProc *proc, ClientData clientData, Atom format)); /* 41 */ - Tk_Window (*tk_CreateWindow) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window parent, CONST char *name, CONST char *screenName)); /* 42 */ - Tk_Window (*tk_CreateWindowFromPath) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *pathName, CONST char *screenName)); /* 43 */ - int (*tk_DefineBitmap) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *name, CONST char *source, int width, int height)); /* 44 */ - void (*tk_DefineCursor) _ANSI_ARGS_((Tk_Window window, Tk_Cursor cursor)); /* 45 */ - void (*tk_DeleteAllBindings) _ANSI_ARGS_((Tk_BindingTable bindingTable, ClientData object)); /* 46 */ - int (*tk_DeleteBinding) _ANSI_ARGS_((Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventStr)); /* 47 */ - void (*tk_DeleteBindingTable) _ANSI_ARGS_((Tk_BindingTable bindingTable)); /* 48 */ - void (*tk_DeleteErrorHandler) _ANSI_ARGS_((Tk_ErrorHandler handler)); /* 49 */ - void (*tk_DeleteEventHandler) _ANSI_ARGS_((Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData)); /* 50 */ - void (*tk_DeleteGenericHandler) _ANSI_ARGS_((Tk_GenericProc *proc, ClientData clientData)); /* 51 */ - void (*tk_DeleteImage) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *name)); /* 52 */ - void (*tk_DeleteSelHandler) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Atom target)); /* 53 */ - void (*tk_DestroyWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 54 */ - CONST84_RETURN char * (*tk_DisplayName) _ANSI_ARGS_((Tk_Window tkwin)); /* 55 */ - int (*tk_DistanceToTextLayout) _ANSI_ARGS_((Tk_TextLayout layout, int x, int y)); /* 56 */ - void (*tk_Draw3DPolygon) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief)); /* 57 */ - void (*tk_Draw3DRectangle) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief)); /* 58 */ - void (*tk_DrawChars) _ANSI_ARGS_((Display *display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char *source, int numBytes, int x, int y)); /* 59 */ - void (*tk_DrawFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable)); /* 60 */ - void (*tk_DrawTextLayout) _ANSI_ARGS_((Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int firstChar, int lastChar)); /* 61 */ - void (*tk_Fill3DPolygon) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief)); /* 62 */ - void (*tk_Fill3DRectangle) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief)); /* 63 */ - Tk_PhotoHandle (*tk_FindPhoto) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *imageName)); /* 64 */ - Font (*tk_FontId) _ANSI_ARGS_((Tk_Font font)); /* 65 */ - void (*tk_Free3DBorder) _ANSI_ARGS_((Tk_3DBorder border)); /* 66 */ - void (*tk_FreeBitmap) _ANSI_ARGS_((Display *display, Pixmap bitmap)); /* 67 */ - void (*tk_FreeColor) _ANSI_ARGS_((XColor *colorPtr)); /* 68 */ - void (*tk_FreeColormap) _ANSI_ARGS_((Display *display, Colormap colormap)); /* 69 */ - void (*tk_FreeCursor) _ANSI_ARGS_((Display *display, Tk_Cursor cursor)); /* 70 */ - void (*tk_FreeFont) _ANSI_ARGS_((Tk_Font f)); /* 71 */ - void (*tk_FreeGC) _ANSI_ARGS_((Display *display, GC gc)); /* 72 */ - void (*tk_FreeImage) _ANSI_ARGS_((Tk_Image image)); /* 73 */ - void (*tk_FreeOptions) _ANSI_ARGS_((Tk_ConfigSpec *specs, char *widgRec, Display *display, int needFlags)); /* 74 */ - void (*tk_FreePixmap) _ANSI_ARGS_((Display *display, Pixmap pixmap)); /* 75 */ - void (*tk_FreeTextLayout) _ANSI_ARGS_((Tk_TextLayout textLayout)); /* 76 */ - void (*tk_FreeXId) _ANSI_ARGS_((Display *display, XID xid)); /* 77 */ - GC (*tk_GCForColor) _ANSI_ARGS_((XColor *colorPtr, Drawable drawable)); /* 78 */ - void (*tk_GeometryRequest) _ANSI_ARGS_((Tk_Window tkwin, int reqWidth, int reqHeight)); /* 79 */ - Tk_3DBorder (*tk_Get3DBorder) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid colorName)); /* 80 */ - void (*tk_GetAllBindings) _ANSI_ARGS_((Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object)); /* 81 */ - int (*tk_GetAnchor) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *str, Tk_Anchor *anchorPtr)); /* 82 */ - CONST84_RETURN char * (*tk_GetAtomName) _ANSI_ARGS_((Tk_Window tkwin, Atom atom)); /* 83 */ - CONST84_RETURN char * (*tk_GetBinding) _ANSI_ARGS_((Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventStr)); /* 84 */ - Pixmap (*tk_GetBitmap) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *str)); /* 85 */ - Pixmap (*tk_GetBitmapFromData) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *source, int width, int height)); /* 86 */ - int (*tk_GetCapStyle) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *str, int *capPtr)); /* 87 */ - XColor * (*tk_GetColor) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name)); /* 88 */ - XColor * (*tk_GetColorByValue) _ANSI_ARGS_((Tk_Window tkwin, XColor *colorPtr)); /* 89 */ - Colormap (*tk_GetColormap) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *str)); /* 90 */ - Tk_Cursor (*tk_GetCursor) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid str)); /* 91 */ - Tk_Cursor (*tk_GetCursorFromData) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *source, CONST char *mask, int width, int height, int xHot, int yHot, Tk_Uid fg, Tk_Uid bg)); /* 92 */ - Tk_Font (*tk_GetFont) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *str)); /* 93 */ - Tk_Font (*tk_GetFontFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 94 */ - void (*tk_GetFontMetrics) _ANSI_ARGS_((Tk_Font font, Tk_FontMetrics *fmPtr)); /* 95 */ - GC (*tk_GetGC) _ANSI_ARGS_((Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr)); /* 96 */ - Tk_Image (*tk_GetImage) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *name, Tk_ImageChangedProc *changeProc, ClientData clientData)); /* 97 */ - ClientData (*tk_GetImageMasterData) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *name, Tk_ImageType **typePtrPtr)); /* 98 */ - Tk_ItemType * (*tk_GetItemTypes) _ANSI_ARGS_((void)); /* 99 */ - int (*tk_GetJoinStyle) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *str, int *joinPtr)); /* 100 */ - int (*tk_GetJustify) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *str, Tk_Justify *justifyPtr)); /* 101 */ - int (*tk_GetNumMainWindows) _ANSI_ARGS_((void)); /* 102 */ - Tk_Uid (*tk_GetOption) _ANSI_ARGS_((Tk_Window tkwin, CONST char *name, CONST char *className)); /* 103 */ - int (*tk_GetPixels) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *str, int *intPtr)); /* 104 */ - Pixmap (*tk_GetPixmap) _ANSI_ARGS_((Display *display, Drawable d, int width, int height, int depth)); /* 105 */ - int (*tk_GetRelief) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *name, int *reliefPtr)); /* 106 */ - void (*tk_GetRootCoords) _ANSI_ARGS_((Tk_Window tkwin, int *xPtr, int *yPtr)); /* 107 */ - int (*tk_GetScrollInfo) _ANSI_ARGS_((Tcl_Interp *interp, int argc, CONST84 char **argv, double *dblPtr, int *intPtr)); /* 108 */ - int (*tk_GetScreenMM) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *str, double *doublePtr)); /* 109 */ - int (*tk_GetSelection) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData)); /* 110 */ - Tk_Uid (*tk_GetUid) _ANSI_ARGS_((CONST char *str)); /* 111 */ - Visual * (*tk_GetVisual) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *str, int *depthPtr, Colormap *colormapPtr)); /* 112 */ - void (*tk_GetVRootGeometry) _ANSI_ARGS_((Tk_Window tkwin, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)); /* 113 */ - int (*tk_Grab) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal)); /* 114 */ - void (*tk_HandleEvent) _ANSI_ARGS_((XEvent *eventPtr)); /* 115 */ - Tk_Window (*tk_IdToWindow) _ANSI_ARGS_((Display *display, Window window)); /* 116 */ - void (*tk_ImageChanged) _ANSI_ARGS_((Tk_ImageMaster master, int x, int y, int width, int height, int imageWidth, int imageHeight)); /* 117 */ - int (*tk_Init) _ANSI_ARGS_((Tcl_Interp *interp)); /* 118 */ - Atom (*tk_InternAtom) _ANSI_ARGS_((Tk_Window tkwin, CONST char *name)); /* 119 */ - int (*tk_IntersectTextLayout) _ANSI_ARGS_((Tk_TextLayout layout, int x, int y, int width, int height)); /* 120 */ - void (*tk_MaintainGeometry) _ANSI_ARGS_((Tk_Window slave, Tk_Window master, int x, int y, int width, int height)); /* 121 */ - Tk_Window (*tk_MainWindow) _ANSI_ARGS_((Tcl_Interp *interp)); /* 122 */ - void (*tk_MakeWindowExist) _ANSI_ARGS_((Tk_Window tkwin)); /* 123 */ - void (*tk_ManageGeometry) _ANSI_ARGS_((Tk_Window tkwin, Tk_GeomMgr *mgrPtr, ClientData clientData)); /* 124 */ - void (*tk_MapWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 125 */ - int (*tk_MeasureChars) _ANSI_ARGS_((Tk_Font tkfont, CONST char *source, int numBytes, int maxPixels, int flags, int *lengthPtr)); /* 126 */ - void (*tk_MoveResizeWindow) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height)); /* 127 */ - void (*tk_MoveWindow) _ANSI_ARGS_((Tk_Window tkwin, int x, int y)); /* 128 */ - void (*tk_MoveToplevelWindow) _ANSI_ARGS_((Tk_Window tkwin, int x, int y)); /* 129 */ - CONST84_RETURN char * (*tk_NameOf3DBorder) _ANSI_ARGS_((Tk_3DBorder border)); /* 130 */ - CONST84_RETURN char * (*tk_NameOfAnchor) _ANSI_ARGS_((Tk_Anchor anchor)); /* 131 */ - CONST84_RETURN char * (*tk_NameOfBitmap) _ANSI_ARGS_((Display *display, Pixmap bitmap)); /* 132 */ - CONST84_RETURN char * (*tk_NameOfCapStyle) _ANSI_ARGS_((int cap)); /* 133 */ - CONST84_RETURN char * (*tk_NameOfColor) _ANSI_ARGS_((XColor *colorPtr)); /* 134 */ - CONST84_RETURN char * (*tk_NameOfCursor) _ANSI_ARGS_((Display *display, Tk_Cursor cursor)); /* 135 */ - CONST84_RETURN char * (*tk_NameOfFont) _ANSI_ARGS_((Tk_Font font)); /* 136 */ - CONST84_RETURN char * (*tk_NameOfImage) _ANSI_ARGS_((Tk_ImageMaster imageMaster)); /* 137 */ - CONST84_RETURN char * (*tk_NameOfJoinStyle) _ANSI_ARGS_((int join)); /* 138 */ - CONST84_RETURN char * (*tk_NameOfJustify) _ANSI_ARGS_((Tk_Justify justify)); /* 139 */ - CONST84_RETURN char * (*tk_NameOfRelief) _ANSI_ARGS_((int relief)); /* 140 */ - Tk_Window (*tk_NameToWindow) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *pathName, Tk_Window tkwin)); /* 141 */ - void (*tk_OwnSelection) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Tk_LostSelProc *proc, ClientData clientData)); /* 142 */ - int (*tk_ParseArgv) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, int *argcPtr, CONST84 char **argv, Tk_ArgvInfo *argTable, int flags)); /* 143 */ - void (*tk_PhotoPutBlock_NoComposite) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height)); /* 144 */ - void (*tk_PhotoPutZoomedBlock_NoComposite) _ANSI_ARGS_((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) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr)); /* 146 */ - void (*tk_PhotoBlank) _ANSI_ARGS_((Tk_PhotoHandle handle)); /* 147 */ - void (*tk_PhotoExpand) _ANSI_ARGS_((Tk_PhotoHandle handle, int width, int height)); /* 148 */ - void (*tk_PhotoGetSize) _ANSI_ARGS_((Tk_PhotoHandle handle, int *widthPtr, int *heightPtr)); /* 149 */ - void (*tk_PhotoSetSize) _ANSI_ARGS_((Tk_PhotoHandle handle, int width, int height)); /* 150 */ - int (*tk_PointToChar) _ANSI_ARGS_((Tk_TextLayout layout, int x, int y)); /* 151 */ - int (*tk_PostscriptFontName) _ANSI_ARGS_((Tk_Font tkfont, Tcl_DString *dsPtr)); /* 152 */ - void (*tk_PreserveColormap) _ANSI_ARGS_((Display *display, Colormap colormap)); /* 153 */ - void (*tk_QueueWindowEvent) _ANSI_ARGS_((XEvent *eventPtr, Tcl_QueuePosition position)); /* 154 */ - void (*tk_RedrawImage) _ANSI_ARGS_((Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY)); /* 155 */ - void (*tk_ResizeWindow) _ANSI_ARGS_((Tk_Window tkwin, int width, int height)); /* 156 */ - int (*tk_RestackWindow) _ANSI_ARGS_((Tk_Window tkwin, int aboveBelow, Tk_Window other)); /* 157 */ - Tk_RestrictProc * (*tk_RestrictEvents) _ANSI_ARGS_((Tk_RestrictProc *proc, ClientData arg, ClientData *prevArgPtr)); /* 158 */ - int (*tk_SafeInit) _ANSI_ARGS_((Tcl_Interp *interp)); /* 159 */ - CONST char * (*tk_SetAppName) _ANSI_ARGS_((Tk_Window tkwin, CONST char *name)); /* 160 */ - void (*tk_SetBackgroundFromBorder) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border)); /* 161 */ - void (*tk_SetClass) _ANSI_ARGS_((Tk_Window tkwin, CONST char *className)); /* 162 */ - void (*tk_SetGrid) _ANSI_ARGS_((Tk_Window tkwin, int reqWidth, int reqHeight, int gridWidth, int gridHeight)); /* 163 */ - void (*tk_SetInternalBorder) _ANSI_ARGS_((Tk_Window tkwin, int width)); /* 164 */ - void (*tk_SetWindowBackground) _ANSI_ARGS_((Tk_Window tkwin, unsigned long pixel)); /* 165 */ - void (*tk_SetWindowBackgroundPixmap) _ANSI_ARGS_((Tk_Window tkwin, Pixmap pixmap)); /* 166 */ - void (*tk_SetWindowBorder) _ANSI_ARGS_((Tk_Window tkwin, unsigned long pixel)); /* 167 */ - void (*tk_SetWindowBorderWidth) _ANSI_ARGS_((Tk_Window tkwin, int width)); /* 168 */ - void (*tk_SetWindowBorderPixmap) _ANSI_ARGS_((Tk_Window tkwin, Pixmap pixmap)); /* 169 */ - void (*tk_SetWindowColormap) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 170 */ - int (*tk_SetWindowVisual) _ANSI_ARGS_((Tk_Window tkwin, Visual *visual, int depth, Colormap colormap)); /* 171 */ - void (*tk_SizeOfBitmap) _ANSI_ARGS_((Display *display, Pixmap bitmap, int *widthPtr, int *heightPtr)); /* 172 */ - void (*tk_SizeOfImage) _ANSI_ARGS_((Tk_Image image, int *widthPtr, int *heightPtr)); /* 173 */ - int (*tk_StrictMotif) _ANSI_ARGS_((Tk_Window tkwin)); /* 174 */ - void (*tk_TextLayoutToPostscript) _ANSI_ARGS_((Tcl_Interp *interp, Tk_TextLayout layout)); /* 175 */ - int (*tk_TextWidth) _ANSI_ARGS_((Tk_Font font, CONST char *str, int numBytes)); /* 176 */ - void (*tk_UndefineCursor) _ANSI_ARGS_((Tk_Window window)); /* 177 */ - void (*tk_UnderlineChars) _ANSI_ARGS_((Display *display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char *source, int x, int y, int firstByte, int lastByte)); /* 178 */ - void (*tk_UnderlineTextLayout) _ANSI_ARGS_((Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int underline)); /* 179 */ - void (*tk_Ungrab) _ANSI_ARGS_((Tk_Window tkwin)); /* 180 */ - void (*tk_UnmaintainGeometry) _ANSI_ARGS_((Tk_Window slave, Tk_Window master)); /* 181 */ - void (*tk_UnmapWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 182 */ - void (*tk_UnsetGrid) _ANSI_ARGS_((Tk_Window tkwin)); /* 183 */ - void (*tk_UpdatePointer) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int state)); /* 184 */ - Pixmap (*tk_AllocBitmapFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)); /* 185 */ - Tk_3DBorder (*tk_Alloc3DBorderFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)); /* 186 */ - XColor * (*tk_AllocColorFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)); /* 187 */ - Tk_Cursor (*tk_AllocCursorFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)); /* 188 */ - Tk_Font (*tk_AllocFontFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)); /* 189 */ - Tk_OptionTable (*tk_CreateOptionTable) _ANSI_ARGS_((Tcl_Interp *interp, CONST Tk_OptionSpec *templatePtr)); /* 190 */ - void (*tk_DeleteOptionTable) _ANSI_ARGS_((Tk_OptionTable optionTable)); /* 191 */ - void (*tk_Free3DBorderFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 192 */ - void (*tk_FreeBitmapFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 193 */ - void (*tk_FreeColorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 194 */ - void (*tk_FreeConfigOptions) _ANSI_ARGS_((char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin)); /* 195 */ - void (*tk_FreeSavedOptions) _ANSI_ARGS_((Tk_SavedOptions *savePtr)); /* 196 */ - void (*tk_FreeCursorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 197 */ - void (*tk_FreeFontFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 198 */ - Tk_3DBorder (*tk_Get3DBorderFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 199 */ - int (*tk_GetAnchorFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Anchor *anchorPtr)); /* 200 */ - Pixmap (*tk_GetBitmapFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 201 */ - XColor * (*tk_GetColorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 202 */ - Tk_Cursor (*tk_GetCursorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj *objPtr)); /* 203 */ - Tcl_Obj * (*tk_GetOptionInfo) _ANSI_ARGS_((Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin)); /* 204 */ - Tcl_Obj * (*tk_GetOptionValue) _ANSI_ARGS_((Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin)); /* 205 */ - int (*tk_GetJustifyFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr)); /* 206 */ - int (*tk_GetMMFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr)); /* 207 */ - int (*tk_GetPixelsFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr)); /* 208 */ - int (*tk_GetReliefFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr)); /* 209 */ - int (*tk_GetScrollInfoObj) _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], double *dblPtr, int *intPtr)); /* 210 */ - int (*tk_InitOptions) _ANSI_ARGS_((Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin)); /* 211 */ - void (*tk_MainEx) _ANSI_ARGS_((int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp)); /* 212 */ - void (*tk_RestoreSavedOptions) _ANSI_ARGS_((Tk_SavedOptions *savePtr)); /* 213 */ - int (*tk_SetOptions) _ANSI_ARGS_((Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *CONST objv[], Tk_Window tkwin, Tk_SavedOptions *savePtr, int *maskPtr)); /* 214 */ - void (*tk_InitConsoleChannels) _ANSI_ARGS_((Tcl_Interp *interp)); /* 215 */ - int (*tk_CreateConsoleWindow) _ANSI_ARGS_((Tcl_Interp *interp)); /* 216 */ - void (*tk_CreateSmoothMethod) _ANSI_ARGS_((Tcl_Interp *interp, Tk_SmoothMethod *method)); /* 217 */ + void (*tk_MainLoop) (void); /* 0 */ + XColor * (*tk_3DBorderColor) (Tk_3DBorder border); /* 1 */ + GC (*tk_3DBorderGC) (Tk_Window tkwin, Tk_3DBorder border, int which); /* 2 */ + void (*tk_3DHorizontalBevel) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftIn, int rightIn, int topBevel, int relief); /* 3 */ + void (*tk_3DVerticalBevel) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftBevel, int relief); /* 4 */ + void (*tk_AddOption) (Tk_Window tkwin, CONST char *name, CONST char *value, int priority); /* 5 */ + void (*tk_BindEvent) (Tk_BindingTable bindingTable, XEvent *eventPtr, Tk_Window tkwin, int numObjects, ClientData *objectPtr); /* 6 */ + void (*tk_CanvasDrawableCoords) (Tk_Canvas canvas, double x, double y, short *drawableXPtr, short *drawableYPtr); /* 7 */ + void (*tk_CanvasEventuallyRedraw) (Tk_Canvas canvas, int x1, int y1, int x2, int y2); /* 8 */ + int (*tk_CanvasGetCoord) (Tcl_Interp *interp, Tk_Canvas canvas, CONST char *str, double *doublePtr); /* 9 */ + Tk_CanvasTextInfo * (*tk_CanvasGetTextInfo) (Tk_Canvas canvas); /* 10 */ + int (*tk_CanvasPsBitmap) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap, int x, int y, int width, int height); /* 11 */ + int (*tk_CanvasPsColor) (Tcl_Interp *interp, Tk_Canvas canvas, XColor *colorPtr); /* 12 */ + int (*tk_CanvasPsFont) (Tcl_Interp *interp, Tk_Canvas canvas, Tk_Font font); /* 13 */ + void (*tk_CanvasPsPath) (Tcl_Interp *interp, Tk_Canvas canvas, double *coordPtr, int numPoints); /* 14 */ + int (*tk_CanvasPsStipple) (Tcl_Interp *interp, Tk_Canvas canvas, Pixmap bitmap); /* 15 */ + double (*tk_CanvasPsY) (Tk_Canvas canvas, double y); /* 16 */ + void (*tk_CanvasSetStippleOrigin) (Tk_Canvas canvas, GC gc); /* 17 */ + int (*tk_CanvasTagsParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, CONST char *value, char *widgRec, int offset); /* 18 */ + char * (*tk_CanvasTagsPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 19 */ + Tk_Window (*tk_CanvasTkwin) (Tk_Canvas canvas); /* 20 */ + void (*tk_CanvasWindowCoords) (Tk_Canvas canvas, double x, double y, short *screenXPtr, short *screenYPtr); /* 21 */ + void (*tk_ChangeWindowAttributes) (Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes *attsPtr); /* 22 */ + int (*tk_CharBbox) (Tk_TextLayout layout, int index, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 23 */ + void (*tk_ClearSelection) (Tk_Window tkwin, Atom selection); /* 24 */ + int (*tk_ClipboardAppend) (Tcl_Interp *interp, Tk_Window tkwin, Atom target, Atom format, char *buffer); /* 25 */ + int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */ + int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, char *widgRec, CONST char *argvName, int flags); /* 27 */ + int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, char *widgRec, CONST char *argvName, int flags); /* 28 */ + int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags); /* 29 */ + void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */ + Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, CONST char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */ + Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */ + unsigned long (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventStr, CONST char *command, int append); /* 33 */ + Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */ + Tk_ErrorHandler (*tk_CreateErrorHandler) (Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, ClientData clientData); /* 35 */ + void (*tk_CreateEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 36 */ + void (*tk_CreateGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 37 */ + void (*tk_CreateImageType) (Tk_ImageType *typePtr); /* 38 */ + void (*tk_CreateItemType) (Tk_ItemType *typePtr); /* 39 */ + void (*tk_CreatePhotoImageFormat) (Tk_PhotoImageFormat *formatPtr); /* 40 */ + void (*tk_CreateSelHandler) (Tk_Window tkwin, Atom selection, Atom target, Tk_SelectionProc *proc, ClientData clientData, Atom format); /* 41 */ + Tk_Window (*tk_CreateWindow) (Tcl_Interp *interp, Tk_Window parent, CONST char *name, CONST char *screenName); /* 42 */ + Tk_Window (*tk_CreateWindowFromPath) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *pathName, CONST char *screenName); /* 43 */ + int (*tk_DefineBitmap) (Tcl_Interp *interp, CONST char *name, CONST char *source, int width, int height); /* 44 */ + void (*tk_DefineCursor) (Tk_Window window, Tk_Cursor cursor); /* 45 */ + void (*tk_DeleteAllBindings) (Tk_BindingTable bindingTable, ClientData object); /* 46 */ + int (*tk_DeleteBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventStr); /* 47 */ + void (*tk_DeleteBindingTable) (Tk_BindingTable bindingTable); /* 48 */ + void (*tk_DeleteErrorHandler) (Tk_ErrorHandler handler); /* 49 */ + void (*tk_DeleteEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 50 */ + void (*tk_DeleteGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 51 */ + void (*tk_DeleteImage) (Tcl_Interp *interp, CONST char *name); /* 52 */ + void (*tk_DeleteSelHandler) (Tk_Window tkwin, Atom selection, Atom target); /* 53 */ + void (*tk_DestroyWindow) (Tk_Window tkwin); /* 54 */ + CONST84_RETURN char * (*tk_DisplayName) (Tk_Window tkwin); /* 55 */ + int (*tk_DistanceToTextLayout) (Tk_TextLayout layout, int x, int y); /* 56 */ + void (*tk_Draw3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 57 */ + void (*tk_Draw3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 58 */ + void (*tk_DrawChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char *source, int numBytes, int x, int y); /* 59 */ + void (*tk_DrawFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable); /* 60 */ + void (*tk_DrawTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int firstChar, int lastChar); /* 61 */ + void (*tk_Fill3DPolygon) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint *pointPtr, int numPoints, int borderWidth, int leftRelief); /* 62 */ + void (*tk_Fill3DRectangle) (Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief); /* 63 */ + Tk_PhotoHandle (*tk_FindPhoto) (Tcl_Interp *interp, CONST char *imageName); /* 64 */ + Font (*tk_FontId) (Tk_Font font); /* 65 */ + void (*tk_Free3DBorder) (Tk_3DBorder border); /* 66 */ + void (*tk_FreeBitmap) (Display *display, Pixmap bitmap); /* 67 */ + void (*tk_FreeColor) (XColor *colorPtr); /* 68 */ + void (*tk_FreeColormap) (Display *display, Colormap colormap); /* 69 */ + void (*tk_FreeCursor) (Display *display, Tk_Cursor cursor); /* 70 */ + void (*tk_FreeFont) (Tk_Font f); /* 71 */ + void (*tk_FreeGC) (Display *display, GC gc); /* 72 */ + void (*tk_FreeImage) (Tk_Image image); /* 73 */ + void (*tk_FreeOptions) (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 */ + 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 */ + Pixmap (*tk_GetBitmap) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *str); /* 85 */ + Pixmap (*tk_GetBitmapFromData) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *source, int width, int height); /* 86 */ + int (*tk_GetCapStyle) (Tcl_Interp *interp, CONST char *str, int *capPtr); /* 87 */ + XColor * (*tk_GetColor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name); /* 88 */ + XColor * (*tk_GetColorByValue) (Tk_Window tkwin, XColor *colorPtr); /* 89 */ + Colormap (*tk_GetColormap) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *str); /* 90 */ + Tk_Cursor (*tk_GetCursor) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid str); /* 91 */ + Tk_Cursor (*tk_GetCursorFromData) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *source, CONST char *mask, int width, int height, int xHot, int yHot, Tk_Uid fg, Tk_Uid bg); /* 92 */ + Tk_Font (*tk_GetFont) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *str); /* 93 */ + Tk_Font (*tk_GetFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 94 */ + void (*tk_GetFontMetrics) (Tk_Font font, Tk_FontMetrics *fmPtr); /* 95 */ + GC (*tk_GetGC) (Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr); /* 96 */ + Tk_Image (*tk_GetImage) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *name, Tk_ImageChangedProc *changeProc, ClientData clientData); /* 97 */ + ClientData (*tk_GetImageMasterData) (Tcl_Interp *interp, CONST char *name, Tk_ImageType **typePtrPtr); /* 98 */ + Tk_ItemType * (*tk_GetItemTypes) (void); /* 99 */ + int (*tk_GetJoinStyle) (Tcl_Interp *interp, CONST char *str, int *joinPtr); /* 100 */ + int (*tk_GetJustify) (Tcl_Interp *interp, CONST char *str, Tk_Justify *justifyPtr); /* 101 */ + int (*tk_GetNumMainWindows) (void); /* 102 */ + Tk_Uid (*tk_GetOption) (Tk_Window tkwin, CONST char *name, CONST char *className); /* 103 */ + int (*tk_GetPixels) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *str, int *intPtr); /* 104 */ + Pixmap (*tk_GetPixmap) (Display *display, Drawable d, int width, int height, int depth); /* 105 */ + int (*tk_GetRelief) (Tcl_Interp *interp, CONST char *name, int *reliefPtr); /* 106 */ + void (*tk_GetRootCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 107 */ + int (*tk_GetScrollInfo) (Tcl_Interp *interp, int argc, CONST84 char **argv, double *dblPtr, int *intPtr); /* 108 */ + int (*tk_GetScreenMM) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *str, double *doublePtr); /* 109 */ + int (*tk_GetSelection) (Tcl_Interp *interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc *proc, ClientData clientData); /* 110 */ + Tk_Uid (*tk_GetUid) (CONST char *str); /* 111 */ + Visual * (*tk_GetVisual) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *str, int *depthPtr, Colormap *colormapPtr); /* 112 */ + void (*tk_GetVRootGeometry) (Tk_Window tkwin, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 113 */ + int (*tk_Grab) (Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal); /* 114 */ + void (*tk_HandleEvent) (XEvent *eventPtr); /* 115 */ + Tk_Window (*tk_IdToWindow) (Display *display, Window window); /* 116 */ + void (*tk_ImageChanged) (Tk_ImageMaster master, int x, int y, int width, int height, int imageWidth, int imageHeight); /* 117 */ + int (*tk_Init) (Tcl_Interp *interp); /* 118 */ + Atom (*tk_InternAtom) (Tk_Window tkwin, CONST char *name); /* 119 */ + int (*tk_IntersectTextLayout) (Tk_TextLayout layout, int x, int y, int width, int height); /* 120 */ + void (*tk_MaintainGeometry) (Tk_Window slave, Tk_Window master, int x, int y, int width, int height); /* 121 */ + Tk_Window (*tk_MainWindow) (Tcl_Interp *interp); /* 122 */ + void (*tk_MakeWindowExist) (Tk_Window tkwin); /* 123 */ + void (*tk_ManageGeometry) (Tk_Window tkwin, CONST Tk_GeomMgr *mgrPtr, ClientData clientData); /* 124 */ + void (*tk_MapWindow) (Tk_Window tkwin); /* 125 */ + int (*tk_MeasureChars) (Tk_Font tkfont, CONST char *source, int numBytes, int maxPixels, int flags, int *lengthPtr); /* 126 */ + void (*tk_MoveResizeWindow) (Tk_Window tkwin, int x, int y, int width, int height); /* 127 */ + void (*tk_MoveWindow) (Tk_Window tkwin, int x, int y); /* 128 */ + void (*tk_MoveToplevelWindow) (Tk_Window tkwin, int x, int y); /* 129 */ + CONST84_RETURN char * (*tk_NameOf3DBorder) (Tk_3DBorder border); /* 130 */ + CONST84_RETURN char * (*tk_NameOfAnchor) (Tk_Anchor anchor); /* 131 */ + CONST84_RETURN char * (*tk_NameOfBitmap) (Display *display, Pixmap bitmap); /* 132 */ + CONST84_RETURN char * (*tk_NameOfCapStyle) (int cap); /* 133 */ + CONST84_RETURN char * (*tk_NameOfColor) (XColor *colorPtr); /* 134 */ + CONST84_RETURN char * (*tk_NameOfCursor) (Display *display, Tk_Cursor cursor); /* 135 */ + CONST84_RETURN char * (*tk_NameOfFont) (Tk_Font font); /* 136 */ + CONST84_RETURN char * (*tk_NameOfImage) (Tk_ImageMaster imageMaster); /* 137 */ + CONST84_RETURN char * (*tk_NameOfJoinStyle) (int join); /* 138 */ + CONST84_RETURN char * (*tk_NameOfJustify) (Tk_Justify justify); /* 139 */ + CONST84_RETURN char * (*tk_NameOfRelief) (int relief); /* 140 */ + 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, 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_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 */ + void (*tk_PhotoGetSize) (Tk_PhotoHandle handle, int *widthPtr, int *heightPtr); /* 149 */ + void (*tk_PhotoSetSize_Panic) (Tk_PhotoHandle handle, int width, int height); /* 150 */ + int (*tk_PointToChar) (Tk_TextLayout layout, int x, int y); /* 151 */ + int (*tk_PostscriptFontName) (Tk_Font tkfont, Tcl_DString *dsPtr); /* 152 */ + void (*tk_PreserveColormap) (Display *display, Colormap colormap); /* 153 */ + void (*tk_QueueWindowEvent) (XEvent *eventPtr, Tcl_QueuePosition position); /* 154 */ + void (*tk_RedrawImage) (Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY); /* 155 */ + void (*tk_ResizeWindow) (Tk_Window tkwin, int width, int height); /* 156 */ + int (*tk_RestackWindow) (Tk_Window tkwin, int aboveBelow, Tk_Window other); /* 157 */ + Tk_RestrictProc * (*tk_RestrictEvents) (Tk_RestrictProc *proc, ClientData arg, ClientData *prevArgPtr); /* 158 */ + int (*tk_SafeInit) (Tcl_Interp *interp); /* 159 */ + CONST char * (*tk_SetAppName) (Tk_Window tkwin, CONST char *name); /* 160 */ + void (*tk_SetBackgroundFromBorder) (Tk_Window tkwin, Tk_3DBorder border); /* 161 */ + void (*tk_SetClass) (Tk_Window tkwin, CONST char *className); /* 162 */ + void (*tk_SetGrid) (Tk_Window tkwin, int reqWidth, int reqHeight, int gridWidth, int gridHeight); /* 163 */ + void (*tk_SetInternalBorder) (Tk_Window tkwin, int width); /* 164 */ + void (*tk_SetWindowBackground) (Tk_Window tkwin, unsigned long pixel); /* 165 */ + void (*tk_SetWindowBackgroundPixmap) (Tk_Window tkwin, Pixmap pixmap); /* 166 */ + void (*tk_SetWindowBorder) (Tk_Window tkwin, unsigned long pixel); /* 167 */ + void (*tk_SetWindowBorderWidth) (Tk_Window tkwin, int width); /* 168 */ + void (*tk_SetWindowBorderPixmap) (Tk_Window tkwin, Pixmap pixmap); /* 169 */ + void (*tk_SetWindowColormap) (Tk_Window tkwin, Colormap colormap); /* 170 */ + int (*tk_SetWindowVisual) (Tk_Window tkwin, Visual *visual, int depth, Colormap colormap); /* 171 */ + void (*tk_SizeOfBitmap) (Display *display, Pixmap bitmap, int *widthPtr, int *heightPtr); /* 172 */ + void (*tk_SizeOfImage) (Tk_Image image, int *widthPtr, int *heightPtr); /* 173 */ + int (*tk_StrictMotif) (Tk_Window tkwin); /* 174 */ + void (*tk_TextLayoutToPostscript) (Tcl_Interp *interp, Tk_TextLayout layout); /* 175 */ + int (*tk_TextWidth) (Tk_Font font, CONST char *str, int numBytes); /* 176 */ + void (*tk_UndefineCursor) (Tk_Window window); /* 177 */ + void (*tk_UnderlineChars) (Display *display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char *source, int x, int y, int firstByte, int lastByte); /* 178 */ + void (*tk_UnderlineTextLayout) (Display *display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int underline); /* 179 */ + void (*tk_Ungrab) (Tk_Window tkwin); /* 180 */ + void (*tk_UnmaintainGeometry) (Tk_Window slave, Tk_Window master); /* 181 */ + void (*tk_UnmapWindow) (Tk_Window tkwin); /* 182 */ + void (*tk_UnsetGrid) (Tk_Window tkwin); /* 183 */ + void (*tk_UpdatePointer) (Tk_Window tkwin, int x, int y, int state); /* 184 */ + Pixmap (*tk_AllocBitmapFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 185 */ + Tk_3DBorder (*tk_Alloc3DBorderFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 186 */ + XColor * (*tk_AllocColorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 187 */ + Tk_Cursor (*tk_AllocCursorFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 188 */ + Tk_Font (*tk_AllocFontFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr); /* 189 */ + Tk_OptionTable (*tk_CreateOptionTable) (Tcl_Interp *interp, CONST Tk_OptionSpec *templatePtr); /* 190 */ + void (*tk_DeleteOptionTable) (Tk_OptionTable optionTable); /* 191 */ + void (*tk_Free3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 192 */ + void (*tk_FreeBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 193 */ + void (*tk_FreeColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 194 */ + void (*tk_FreeConfigOptions) (char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 195 */ + void (*tk_FreeSavedOptions) (Tk_SavedOptions *savePtr); /* 196 */ + void (*tk_FreeCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 197 */ + void (*tk_FreeFontFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 198 */ + Tk_3DBorder (*tk_Get3DBorderFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 199 */ + int (*tk_GetAnchorFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Anchor *anchorPtr); /* 200 */ + Pixmap (*tk_GetBitmapFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 201 */ + XColor * (*tk_GetColorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 202 */ + Tk_Cursor (*tk_GetCursorFromObj) (Tk_Window tkwin, Tcl_Obj *objPtr); /* 203 */ + Tcl_Obj * (*tk_GetOptionInfo) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 204 */ + Tcl_Obj * (*tk_GetOptionValue) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin); /* 205 */ + int (*tk_GetJustifyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tk_Justify *justifyPtr); /* 206 */ + int (*tk_GetMMFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 207 */ + int (*tk_GetPixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr); /* 208 */ + int (*tk_GetReliefFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr); /* 209 */ + int (*tk_GetScrollInfoObj) (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], double *dblPtr, int *intPtr); /* 210 */ + int (*tk_InitOptions) (Tcl_Interp *interp, char *recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin); /* 211 */ + void (*tk_MainEx) (int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); /* 212 */ + 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 */ + void (*tk_InitConsoleChannels) (Tcl_Interp *interp); /* 215 */ + int (*tk_CreateConsoleWindow) (Tcl_Interp *interp); /* 216 */ + void (*tk_CreateSmoothMethod) (Tcl_Interp *interp, Tk_SmoothMethod *method); /* 217 */ VOID *reserved218; VOID *reserved219; - int (*tk_GetDash) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *value, Tk_Dash *dash)); /* 220 */ - void (*tk_CreateOutline) _ANSI_ARGS_((Tk_Outline *outline)); /* 221 */ - void (*tk_DeleteOutline) _ANSI_ARGS_((Display *display, Tk_Outline *outline)); /* 222 */ - int (*tk_ConfigOutlineGC) _ANSI_ARGS_((XGCValues *gcValues, Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline)); /* 223 */ - int (*tk_ChangeOutlineGC) _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline)); /* 224 */ - int (*tk_ResetOutlineGC) _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline)); /* 225 */ - int (*tk_CanvasPsOutline) _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline)); /* 226 */ - void (*tk_SetTSOrigin) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y)); /* 227 */ - int (*tk_CanvasGetCoordFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, double *doublePtr)); /* 228 */ - void (*tk_CanvasSetOffset) _ANSI_ARGS_((Tk_Canvas canvas, GC gc, Tk_TSOffset *offset)); /* 229 */ - void (*tk_DitherPhoto) _ANSI_ARGS_((Tk_PhotoHandle handle, int x, int y, int width, int height)); /* 230 */ - int (*tk_PostscriptBitmap) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, int startY, int width, int height)); /* 231 */ - int (*tk_PostscriptColor) _ANSI_ARGS_((Tcl_Interp *interp, Tk_PostscriptInfo psInfo, XColor *colorPtr)); /* 232 */ - int (*tk_PostscriptFont) _ANSI_ARGS_((Tcl_Interp *interp, Tk_PostscriptInfo psInfo, Tk_Font font)); /* 233 */ - int (*tk_PostscriptImage) _ANSI_ARGS_((Tk_Image image, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, int width, int height, int prepass)); /* 234 */ - void (*tk_PostscriptPath) _ANSI_ARGS_((Tcl_Interp *interp, Tk_PostscriptInfo psInfo, double *coordPtr, int numPoints)); /* 235 */ - int (*tk_PostscriptStipple) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap)); /* 236 */ - double (*tk_PostscriptY) _ANSI_ARGS_((double y, Tk_PostscriptInfo psInfo)); /* 237 */ - int (*tk_PostscriptPhoto) _ANSI_ARGS_((Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo, int width, int height)); /* 238 */ - void (*tk_CreateClientMessageHandler) _ANSI_ARGS_((Tk_ClientMessageProc *proc)); /* 239 */ - void (*tk_DeleteClientMessageHandler) _ANSI_ARGS_((Tk_ClientMessageProc *proc)); /* 240 */ - Tk_Window (*tk_CreateAnonymousWindow) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window parent, CONST char *screenName)); /* 241 */ - void (*tk_SetClassProcs) _ANSI_ARGS_((Tk_Window tkwin, Tk_ClassProcs *procs, ClientData instanceData)); /* 242 */ - void (*tk_SetInternalBorderEx) _ANSI_ARGS_((Tk_Window tkwin, int left, int right, int top, int bottom)); /* 243 */ - void (*tk_SetMinimumRequestSize) _ANSI_ARGS_((Tk_Window tkwin, int minWidth, int minHeight)); /* 244 */ - void (*tk_SetCaretPos) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int height)); /* 245 */ - void (*tk_PhotoPutBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule)); /* 246 */ - void (*tk_PhotoPutZoomedBlock) _ANSI_ARGS_((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) _ANSI_ARGS_((Display *display, int collapse)); /* 248 */ - Tk_StyleEngine (*tk_RegisterStyleEngine) _ANSI_ARGS_((CONST char *name, Tk_StyleEngine parent)); /* 249 */ - Tk_StyleEngine (*tk_GetStyleEngine) _ANSI_ARGS_((CONST char *name)); /* 250 */ - int (*tk_RegisterStyledElement) _ANSI_ARGS_((Tk_StyleEngine engine, Tk_ElementSpec *templatePtr)); /* 251 */ - int (*tk_GetElementId) _ANSI_ARGS_((CONST char *name)); /* 252 */ - Tk_Style (*tk_CreateStyle) _ANSI_ARGS_((CONST char *name, Tk_StyleEngine engine, ClientData clientData)); /* 253 */ - Tk_Style (*tk_GetStyle) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *name)); /* 254 */ - void (*tk_FreeStyle) _ANSI_ARGS_((Tk_Style style)); /* 255 */ - CONST char * (*tk_NameOfStyle) _ANSI_ARGS_((Tk_Style style)); /* 256 */ - Tk_Style (*tk_AllocStyleFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *objPtr)); /* 257 */ - Tk_Style (*tk_GetStyleFromObj) _ANSI_ARGS_((Tcl_Obj *objPtr)); /* 258 */ - void (*tk_FreeStyleFromObj) _ANSI_ARGS_((Tcl_Obj *objPtr)); /* 259 */ - Tk_StyledElement (*tk_GetStyledElement) _ANSI_ARGS_((Tk_Style style, int elementId, Tk_OptionTable optionTable)); /* 260 */ - void (*tk_GetElementSize) _ANSI_ARGS_((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) _ANSI_ARGS_((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) _ANSI_ARGS_((Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin)); /* 263 */ - void (*tk_DrawElement) _ANSI_ARGS_((Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state)); /* 264 */ + int (*tk_GetDash) (Tcl_Interp *interp, CONST char *value, Tk_Dash *dash); /* 220 */ + void (*tk_CreateOutline) (Tk_Outline *outline); /* 221 */ + void (*tk_DeleteOutline) (Display *display, Tk_Outline *outline); /* 222 */ + int (*tk_ConfigOutlineGC) (XGCValues *gcValues, Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 223 */ + int (*tk_ChangeOutlineGC) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 224 */ + int (*tk_ResetOutlineGC) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 225 */ + int (*tk_CanvasPsOutline) (Tk_Canvas canvas, Tk_Item *item, Tk_Outline *outline); /* 226 */ + void (*tk_SetTSOrigin) (Tk_Window tkwin, GC gc, int x, int y); /* 227 */ + int (*tk_CanvasGetCoordFromObj) (Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, double *doublePtr); /* 228 */ + void (*tk_CanvasSetOffset) (Tk_Canvas canvas, GC gc, Tk_TSOffset *offset); /* 229 */ + void (*tk_DitherPhoto) (Tk_PhotoHandle handle, int x, int y, int width, int height); /* 230 */ + int (*tk_PostscriptBitmap) (Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, int startY, int width, int height); /* 231 */ + int (*tk_PostscriptColor) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, XColor *colorPtr); /* 232 */ + int (*tk_PostscriptFont) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, Tk_Font font); /* 233 */ + int (*tk_PostscriptImage) (Tk_Image image, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, int width, int height, int prepass); /* 234 */ + void (*tk_PostscriptPath) (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, double *coordPtr, int numPoints); /* 235 */ + int (*tk_PostscriptStipple) (Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap); /* 236 */ + double (*tk_PostscriptY) (double y, Tk_PostscriptInfo psInfo); /* 237 */ + int (*tk_PostscriptPhoto) (Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo, int width, int height); /* 238 */ + void (*tk_CreateClientMessageHandler) (Tk_ClientMessageProc *proc); /* 239 */ + void (*tk_DeleteClientMessageHandler) (Tk_ClientMessageProc *proc); /* 240 */ + Tk_Window (*tk_CreateAnonymousWindow) (Tcl_Interp *interp, Tk_Window parent, CONST char *screenName); /* 241 */ + void (*tk_SetClassProcs) (Tk_Window tkwin, Tk_ClassProcs *procs, ClientData instanceData); /* 242 */ + void (*tk_SetInternalBorderEx) (Tk_Window tkwin, int left, int right, int top, int bottom); /* 243 */ + void (*tk_SetMinimumRequestSize) (Tk_Window tkwin, int minWidth, int minHeight); /* 244 */ + void (*tk_SetCaretPos) (Tk_Window tkwin, int x, int y, int height); /* 245 */ + void (*tk_PhotoPutBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 246 */ + void (*tk_PhotoPutZoomedBlock_Panic) (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 247 */ + int (*tk_CollapseMotionEvents) (Display *display, int collapse); /* 248 */ + Tk_StyleEngine (*tk_RegisterStyleEngine) (CONST char *name, Tk_StyleEngine parent); /* 249 */ + Tk_StyleEngine (*tk_GetStyleEngine) (CONST char *name); /* 250 */ + int (*tk_RegisterStyledElement) (Tk_StyleEngine engine, Tk_ElementSpec *templatePtr); /* 251 */ + int (*tk_GetElementId) (CONST char *name); /* 252 */ + Tk_Style (*tk_CreateStyle) (CONST char *name, Tk_StyleEngine engine, ClientData clientData); /* 253 */ + Tk_Style (*tk_GetStyle) (Tcl_Interp *interp, CONST char *name); /* 254 */ + void (*tk_FreeStyle) (Tk_Style style); /* 255 */ + CONST char * (*tk_NameOfStyle) (Tk_Style style); /* 256 */ + Tk_Style (*tk_AllocStyleFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 257 */ + Tk_Style (*tk_GetStyleFromObj) (Tcl_Obj *objPtr); /* 258 */ + void (*tk_FreeStyleFromObj) (Tcl_Obj *objPtr); /* 259 */ + Tk_StyledElement (*tk_GetStyledElement) (Tk_Style style, int elementId, Tk_OptionTable optionTable); /* 260 */ + void (*tk_GetElementSize) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr); /* 261 */ + void (*tk_GetElementBox) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr); /* 262 */ + int (*tk_GetElementBorderWidth) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin); /* 263 */ + void (*tk_DrawElement) (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state); /* 264 */ + int (*tk_PhotoExpand) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 265 */ + int (*tk_PhotoPutBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule); /* 266 */ + int (*tk_PhotoPutZoomedBlock) (Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule); /* 267 */ + int (*tk_PhotoSetSize) (Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height); /* 268 */ + long (*tk_GetUserInactiveTime) (Display *dpy); /* 269 */ + void (*tk_ResetUserInactiveTime) (Display *dpy); /* 270 */ + Tcl_Interp * (*tk_Interp) (Tk_Window tkwin); /* 271 */ + void (*tk_CreateOldImageType) (Tk_ImageType *typePtr); /* 272 */ + void (*tk_CreateOldPhotoImageFormat) (Tk_PhotoImageFormat *formatPtr); /* 273 */ } TkStubs; #ifdef __cplusplus @@ -1790,17 +2568,17 @@ extern TkStubs *tkStubsPtr; #define Tk_PhotoBlank \ (tkStubsPtr->tk_PhotoBlank) /* 147 */ #endif -#ifndef Tk_PhotoExpand -#define Tk_PhotoExpand \ - (tkStubsPtr->tk_PhotoExpand) /* 148 */ +#ifndef Tk_PhotoExpand_Panic +#define Tk_PhotoExpand_Panic \ + (tkStubsPtr->tk_PhotoExpand_Panic) /* 148 */ #endif #ifndef Tk_PhotoGetSize #define Tk_PhotoGetSize \ (tkStubsPtr->tk_PhotoGetSize) /* 149 */ #endif -#ifndef Tk_PhotoSetSize -#define Tk_PhotoSetSize \ - (tkStubsPtr->tk_PhotoSetSize) /* 150 */ +#ifndef Tk_PhotoSetSize_Panic +#define Tk_PhotoSetSize_Panic \ + (tkStubsPtr->tk_PhotoSetSize_Panic) /* 150 */ #endif #ifndef Tk_PointToChar #define Tk_PointToChar \ @@ -2176,13 +2954,13 @@ extern TkStubs *tkStubsPtr; #define Tk_SetCaretPos \ (tkStubsPtr->tk_SetCaretPos) /* 245 */ #endif -#ifndef Tk_PhotoPutBlock -#define Tk_PhotoPutBlock \ - (tkStubsPtr->tk_PhotoPutBlock) /* 246 */ +#ifndef Tk_PhotoPutBlock_Panic +#define Tk_PhotoPutBlock_Panic \ + (tkStubsPtr->tk_PhotoPutBlock_Panic) /* 246 */ #endif -#ifndef Tk_PhotoPutZoomedBlock -#define Tk_PhotoPutZoomedBlock \ - (tkStubsPtr->tk_PhotoPutZoomedBlock) /* 247 */ +#ifndef Tk_PhotoPutZoomedBlock_Panic +#define Tk_PhotoPutZoomedBlock_Panic \ + (tkStubsPtr->tk_PhotoPutZoomedBlock_Panic) /* 247 */ #endif #ifndef Tk_CollapseMotionEvents #define Tk_CollapseMotionEvents \ @@ -2252,6 +3030,42 @@ extern TkStubs *tkStubsPtr; #define Tk_DrawElement \ (tkStubsPtr->tk_DrawElement) /* 264 */ #endif +#ifndef Tk_PhotoExpand +#define Tk_PhotoExpand \ + (tkStubsPtr->tk_PhotoExpand) /* 265 */ +#endif +#ifndef Tk_PhotoPutBlock +#define Tk_PhotoPutBlock \ + (tkStubsPtr->tk_PhotoPutBlock) /* 266 */ +#endif +#ifndef Tk_PhotoPutZoomedBlock +#define Tk_PhotoPutZoomedBlock \ + (tkStubsPtr->tk_PhotoPutZoomedBlock) /* 267 */ +#endif +#ifndef Tk_PhotoSetSize +#define Tk_PhotoSetSize \ + (tkStubsPtr->tk_PhotoSetSize) /* 268 */ +#endif +#ifndef Tk_GetUserInactiveTime +#define Tk_GetUserInactiveTime \ + (tkStubsPtr->tk_GetUserInactiveTime) /* 269 */ +#endif +#ifndef Tk_ResetUserInactiveTime +#define Tk_ResetUserInactiveTime \ + (tkStubsPtr->tk_ResetUserInactiveTime) /* 270 */ +#endif +#ifndef Tk_Interp +#define Tk_Interp \ + (tkStubsPtr->tk_Interp) /* 271 */ +#endif +#ifndef Tk_CreateOldImageType +#define Tk_CreateOldImageType \ + (tkStubsPtr->tk_CreateOldImageType) /* 272 */ +#endif +#ifndef Tk_CreateOldPhotoImageFormat +#define Tk_CreateOldPhotoImageFormat \ + (tkStubsPtr->tk_CreateOldPhotoImageFormat) /* 273 */ +#endif #endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ diff --git a/generic/tkEntry.c b/generic/tkEntry.c index afd6b15..8f181cd 100644 --- a/generic/tkEntry.c +++ b/generic/tkEntry.c @@ -1,9 +1,9 @@ -/* - * Entry.c -- +/* + * tkEntry.c -- * * This module implements entry and spinbox widgets for the Tk toolkit. - * An entry displays a string and allows the string to be edited. - * A spinbox expands on the entry by adding up/down buttons that control + * An entry displays a string and allows the string to be edited. A + * spinbox expands on the entry by adding up/down buttons that control * the value of the entry widget. * * Copyright (c) 1990-1994 The Regents of the University of California. @@ -11,32 +11,32 @@ * Copyright (c) 2000 Ajuba Solutions. * Copyright (c) 2002 ActiveState Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "default.h" #include "tkEntry.h" - /* - * The following macro defines how many extra pixels to leave on each - * side of the text in the entry. + * The following macro defines how many extra pixels to leave on each side of + * the text in the entry. */ #define XPAD 1 #define YPAD 1 /* - * A comparison function for double values. For Spinboxes. + * A comparison function for double values. For Spinboxes. */ + #define MIN_DBL_VAL 1E-9 #define DOUBLES_EQ(d1, d2) (fabs((d1) - (d2)) < MIN_DBL_VAL) static char *stateStrings[] = { - "disabled", "normal", "readonly", (char *) NULL + "disabled", "normal", "readonly", NULL }; /* @@ -44,7 +44,7 @@ static char *stateStrings[] = { */ static char *validateStrings[] = { - "all", "key", "focus", "focusin", "focusout", "none", (char *) NULL + "all", "key", "focus", "focusin", "focusout", "none", NULL }; enum validateType { VALIDATE_ALL, VALIDATE_KEY, VALIDATE_FOCUS, @@ -61,115 +61,104 @@ enum validateType { * Information used for Entry objv parsing. */ -static Tk_OptionSpec entryOptSpec[] = { +static const Tk_OptionSpec entryOptSpec[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder), 0, (ClientData) DEF_ENTRY_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), - 0, 0, 0}, + DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground", - "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1, - Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK, - (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0}, + "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1, + Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK, + (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", - "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1, - Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, + "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1, + Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", - "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1, - Tk_Offset(Entry, exportSelection), 0, 0, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1, + Tk_Offset(Entry, exportSelection), 0, 0, 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, - 0, 0}, + DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG, - -1, Tk_Offset(Entry, highlightBgColorPtr), - 0, 0, 0}, + -1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), - 0, 0, 0}, + DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", - "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1, + "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1, Tk_Offset(Entry, highlightWidth), 0, 0, 0}, {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground", - DEF_ENTRY_INSERT_BG, - -1, Tk_Offset(Entry, insertBorder), - 0, 0, 0}, - {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", - "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1, - Tk_Offset(Entry, insertBorderWidth), 0, - (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0}, + DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0}, + {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", + "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1, + Tk_Offset(Entry, insertBorderWidth), 0, + (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0}, {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime), - 0, 0, 0}, + DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime), + 0, 0, 0}, {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), - 0, 0, 0}, + DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), - 0, 0, 0}, + DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0}, {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand", DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_SYNONYM, "-invcmd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0}, + {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0}, {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground", - "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1, - Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK, - (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0}, + "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1, + Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK, + (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), - 0, 0, 0}, + DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder), - 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0}, - {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", - "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1, - Tk_Offset(Entry, selBorderWidth), - 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0}, + DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder), + 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0}, + {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", + "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1, + Tk_Offset(Entry, selBorderWidth), + 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr), TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0}, {TK_OPTION_STRING, "-show", "show", "Show", - DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar), - TK_OPTION_NULL_OK, 0, 0}, + DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar), + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), - 0, (ClientData) stateStrings, 0}, + DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), + 0, (ClientData) stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), - TK_OPTION_NULL_OK, 0, 0}, + DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), + TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", - DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), - 0, (ClientData) validateStrings, 0}, - {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand", - (char *) NULL, -1, Tk_Offset(Entry, validateCmd), - TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_SYNONYM, "-vcmd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-validatecommand", 0}, + DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), + 0, (ClientData) validateStrings, 0}, + {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand", + NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-validatecommand", 0}, {TK_OPTION_INT, "-width", "width", "Width", DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0}, {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* @@ -189,20 +178,19 @@ static Tk_OptionSpec entryOptSpec[] = { #define DEF_SPINBOX_VALUES "" #define DEF_SPINBOX_WRAP "0" -static Tk_OptionSpec sbOptSpec[] = { +static const Tk_OptionSpec sbOptSpec[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Background", DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(Spinbox, activeBorder), 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder), 0, (ClientData) DEF_ENTRY_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), - 0, 0, 0}, + DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth), 0, 0, 0}, {TK_OPTION_BORDER, "-buttonbackground", "Button.background", "Background", DEF_BUTTON_BG_COLOR, -1, Tk_Offset(Spinbox, buttonBorder), 0, (ClientData) DEF_BUTTON_BG_MONO, 0}, @@ -210,11 +198,9 @@ static Tk_OptionSpec sbOptSpec[] = { DEF_BUTTON_CURSOR, -1, Tk_Offset(Spinbox, bCursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-buttondownrelief", "Button.relief", "Relief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, bdRelief), - 0, 0, 0}, + DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, bdRelief), 0, 0, 0}, {TK_OPTION_RELIEF, "-buttonuprelief", "Button.relief", "Relief", - DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, buRelief), - 0, 0, 0}, + DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, buRelief), 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", DEF_SPINBOX_CMD, -1, Tk_Offset(Spinbox, command), TK_OPTION_NULL_OK, 0, 0}, @@ -222,22 +208,21 @@ static Tk_OptionSpec sbOptSpec[] = { DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground", - "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1, - Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK, - (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0}, + "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1, + Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK, + (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", - "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1, - Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, + "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1, + Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", - "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1, - Tk_Offset(Entry, exportSelection), 0, 0, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1, + Tk_Offset(Entry, exportSelection), 0, 0, 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, - 0, 0}, + DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0, 0, 0}, {TK_OPTION_STRING, "-format", "format", "Format", DEF_SPINBOX_FORMAT, -1, Tk_Offset(Spinbox, reqFormat), TK_OPTION_NULL_OK, 0, 0}, @@ -245,84 +230,77 @@ static Tk_OptionSpec sbOptSpec[] = { DEF_SPINBOX_FROM, -1, Tk_Offset(Spinbox, fromValue), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG, - -1, Tk_Offset(Entry, highlightBgColorPtr), - 0, 0, 0}, + -1, Tk_Offset(Entry, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), - 0, 0, 0}, + DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", - "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1, + "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1, Tk_Offset(Entry, highlightWidth), 0, 0, 0}, {TK_OPTION_DOUBLE, "-increment", "increment", "Increment", DEF_SPINBOX_INCREMENT, -1, Tk_Offset(Spinbox, increment), 0, 0, 0}, {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground", - DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), - 0, 0, 0}, - {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", - "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1, - Tk_Offset(Entry, insertBorderWidth), 0, - (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0}, + DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder), 0, 0, 0}, + {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", + "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1, + Tk_Offset(Entry, insertBorderWidth), 0, + (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0}, {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime), - 0, 0, 0}, + DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime), + 0, 0, 0}, {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), - 0, 0, 0}, + DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime), 0, 0, 0}, {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), - 0, 0, 0}, + DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth), 0, 0, 0}, {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand", DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_SYNONYM, "-invcmd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0}, + {TK_OPTION_SYNONYM, "-invcmd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), - 0, 0, 0}, + DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief), 0, 0, 0}, {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground", - "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1, - Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK, - (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0}, + "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1, + Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK, + (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0}, {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay", - DEF_SPINBOX_REPEAT_DELAY, -1, Tk_Offset(Spinbox, repeatDelay), - 0, 0, 0}, + DEF_SPINBOX_REPEAT_DELAY, -1, Tk_Offset(Spinbox, repeatDelay), + 0, 0, 0}, {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval", - DEF_SPINBOX_REPEAT_INTERVAL, -1, Tk_Offset(Spinbox, repeatInterval), - 0, 0, 0}, + DEF_SPINBOX_REPEAT_INTERVAL, -1, Tk_Offset(Spinbox, repeatInterval), + 0, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder), - 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0}, - {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", - "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1, - Tk_Offset(Entry, selBorderWidth), - 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0}, + DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder), + 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0}, + {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", + "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1, + Tk_Offset(Entry, selBorderWidth), + 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr), TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), - 0, (ClientData) stateStrings, 0}, + DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state), + 0, (ClientData) stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), - TK_CONFIG_NULL_OK, 0, 0}, + DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus), + TK_CONFIG_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName), TK_CONFIG_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-to", "to", "To", DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", - DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), - 0, (ClientData) validateStrings, 0}, - {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand", - (char *) NULL, -1, Tk_Offset(Entry, validateCmd), - TK_CONFIG_NULL_OK, 0, 0}, + DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate), + 0, (ClientData) validateStrings, 0}, + {TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand", + NULL, -1, Tk_Offset(Entry, validateCmd), TK_CONFIG_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-values", "values", "Values", - DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr), - TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_SYNONYM, "-vcmd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-validatecommand", 0}, + DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_SYNONYM, "-vcmd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-validatecommand", 0}, {TK_OPTION_INT, "-width", "width", "Width", DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0}, {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap", @@ -330,29 +308,28 @@ static Tk_OptionSpec sbOptSpec[] = { {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd), TK_CONFIG_NULL_OK, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* - * The following tables define the entry widget commands (and sub- - * commands) and map the indexes into the string tables into - * enumerated types used to dispatch the entry widget command. + * The following tables define the entry widget commands (and sub-commands) + * and map the indexes into the string tables into enumerated types used to + * dispatch the entry widget command. */ static CONST char *entryCmdNames[] = { - "bbox", "cget", "configure", "delete", "get", "icursor", "index", - "insert", "scan", "selection", "validate", "xview", (char *) NULL + "bbox", "cget", "configure", "delete", "get", "icursor", "index", + "insert", "scan", "selection", "validate", "xview", NULL }; enum entryCmd { - COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE, - COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT, + COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE, + COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT, COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW }; static CONST char *selCmdNames[] = { - "adjust", "clear", "from", "present", "range", "to", (char *) NULL + "adjust", "clear", "from", "present", "range", "to", NULL }; enum selCmd { @@ -361,31 +338,30 @@ enum selCmd { }; /* - * The following tables define the spinbox widget commands (and sub- - * commands) and map the indexes into the string tables into - * enumerated types used to dispatch the spinbox widget command. + * The following tables define the spinbox widget commands (and sub-commands) + * and map the indexes into the string tables into enumerated types used to + * dispatch the spinbox widget command. */ static CONST char *sbCmdNames[] = { "bbox", "cget", "configure", "delete", "get", "icursor", "identify", "index", "insert", "invoke", "scan", "selection", "set", - "validate", "xview", (char *) NULL + "validate", "xview", NULL }; enum sbCmd { - SB_CMD_BBOX, SB_CMD_CGET, SB_CMD_CONFIGURE, SB_CMD_DELETE, + SB_CMD_BBOX, SB_CMD_CGET, SB_CMD_CONFIGURE, SB_CMD_DELETE, SB_CMD_GET, SB_CMD_ICURSOR, SB_CMD_IDENTIFY, SB_CMD_INDEX, SB_CMD_INSERT, SB_CMD_INVOKE, SB_CMD_SCAN, SB_CMD_SELECTION, SB_CMD_SET, SB_CMD_VALIDATE, SB_CMD_XVIEW }; static CONST char *sbSelCmdNames[] = { - "adjust", "clear", "element", "from", "present", "range", "to", - (char *) NULL + "adjust", "clear", "element", "from", "present", "range", "to", NULL }; enum sbselCmd { - SB_SEL_ADJUST, SB_SEL_CLEAR, SB_SEL_ELEMENT, SB_SEL_FROM, + SB_SEL_ADJUST, SB_SEL_CLEAR, SB_SEL_ELEMENT, SB_SEL_FROM, SB_SEL_PRESENT, SB_SEL_RANGE, SB_SEL_TO }; @@ -393,91 +369,80 @@ enum sbselCmd { * Extra for selection of elements */ -/* - * This is the string array corresponding to the enum in selelement. - * If you modify them, you must modify the strings here. +/* + * This is the string array corresponding to the enum in selelement. If you + * modify them, you must modify the strings here. */ - + static CONST char *selElementNames[] = { - "none", "buttondown", "buttonup", (char *) NULL, "entry" + "none", "buttondown", "buttonup", NULL, "entry" }; + /* - * Flags for GetEntryIndex procedure: + * Flags for GetEntryIndex function: */ #define ZERO_OK 1 #define LAST_PLUS_ONE_OK 2 /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int ConfigureEntry _ANSI_ARGS_((Tcl_Interp *interp, - Entry *entryPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static void DeleteChars _ANSI_ARGS_((Entry *entryPtr, int index, - int count)); -static void DestroyEntry _ANSI_ARGS_((char *memPtr)); -static void DisplayEntry _ANSI_ARGS_((ClientData clientData)); -static void EntryBlinkProc _ANSI_ARGS_((ClientData clientData)); -static void EntryCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void EntryComputeGeometry _ANSI_ARGS_((Entry *entryPtr)); -static void EntryEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void EntryFocusProc _ANSI_ARGS_ ((Entry *entryPtr, - int gotFocus)); -static int EntryFetchSelection _ANSI_ARGS_((ClientData clientData, - int offset, char *buffer, int maxBytes)); -static void EntryLostSelection _ANSI_ARGS_(( - ClientData clientData)); -static void EventuallyRedraw _ANSI_ARGS_((Entry *entryPtr)); -static void EntryScanTo _ANSI_ARGS_((Entry *entryPtr, int y)); -static void EntrySetValue _ANSI_ARGS_((Entry *entryPtr, - CONST char *value)); -static void EntrySelectTo _ANSI_ARGS_(( - Entry *entryPtr, int index)); -static char * EntryTextVarProc _ANSI_ARGS_((ClientData clientData, +static int ConfigureEntry(Tcl_Interp *interp, Entry *entryPtr, + int objc, Tcl_Obj *CONST objv[], int flags); +static void DeleteChars(Entry *entryPtr, int index, int count); +static void DestroyEntry(char *memPtr); +static void DisplayEntry(ClientData clientData); +static void EntryBlinkProc(ClientData clientData); +static void EntryCmdDeletedProc(ClientData clientData); +static void EntryComputeGeometry(Entry *entryPtr); +static void EntryEventProc(ClientData clientData, + XEvent *eventPtr); +static void EntryFocusProc(Entry *entryPtr, int gotFocus); +static int EntryFetchSelection(ClientData clientData, int offset, + char *buffer, int maxBytes); +static void EntryLostSelection(ClientData clientData); +static void EventuallyRedraw(Entry *entryPtr); +static void EntryScanTo(Entry *entryPtr, int y); +static void EntrySetValue(Entry *entryPtr, CONST char *value); +static void EntrySelectTo(Entry *entryPtr, int index); +static char * EntryTextVarProc(ClientData clientData, Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static void EntryUpdateScrollbar _ANSI_ARGS_((Entry *entryPtr)); -static int EntryValidate _ANSI_ARGS_((Entry *entryPtr, - char *cmd)); -static int EntryValidateChange _ANSI_ARGS_((Entry *entryPtr, - char *change, CONST char *new, int index, - int type)); -static void ExpandPercents _ANSI_ARGS_((Entry *entryPtr, - CONST char *before, char *change, CONST char *new, - int index, int type, Tcl_DString *dsPtr)); -static void EntryValueChanged _ANSI_ARGS_((Entry *entryPtr, - CONST char *newValue)); -static void EntryVisibleRange _ANSI_ARGS_((Entry *entryPtr, - double *firstPtr, double *lastPtr)); -static int EntryWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static void EntryWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static int GetEntryIndex _ANSI_ARGS_((Tcl_Interp *interp, - Entry *entryPtr, char *string, int *indexPtr)); -static void InsertChars _ANSI_ARGS_((Entry *entryPtr, int index, - char *string)); + CONST char *name2, int flags); +static void EntryUpdateScrollbar(Entry *entryPtr); +static int EntryValidate(Entry *entryPtr, char *cmd); +static int EntryValidateChange(Entry *entryPtr, char *change, + CONST char *newStr, int index, int type); +static void ExpandPercents(Entry *entryPtr, CONST char *before, + CONST char *change, CONST char *newStr, int index, + int type, Tcl_DString *dsPtr); +static void EntryValueChanged(Entry *entryPtr, + CONST char *newValue); +static void EntryVisibleRange(Entry *entryPtr, + double *firstPtr, double *lastPtr); +static int EntryWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static void EntryWorldChanged(ClientData instanceData); +static int GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr, + char *string, int *indexPtr); +static void InsertChars(Entry *entryPtr, int index, char *string); /* * These forward declarations are the spinbox specific ones: */ -static int SpinboxWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static int GetSpinboxElement _ANSI_ARGS_((Spinbox *sbPtr, - int x, int y)); -static int SpinboxInvoke _ANSI_ARGS_((Tcl_Interp *interp, - Spinbox *sbPtr, int element)); -static int ComputeFormat _ANSI_ARGS_((Spinbox *sbPtr)); +static int SpinboxWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GetSpinboxElement(Spinbox *sbPtr, int x, int y); +static int SpinboxInvoke(Tcl_Interp *interp, Spinbox *sbPtr, + int element); +static int ComputeFormat(Spinbox *sbPtr); /* - * The structure below defines widget class behavior by means of procedures + * The structure below defines widget class behavior by means of functions * that can be invoked from generic window code. */ @@ -492,9 +457,8 @@ static Tk_ClassProcs entryClass = { * * Tk_EntryObjCmd -- * - * This procedure is invoked to process the "entry" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "entry" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -506,11 +470,11 @@ static Tk_ClassProcs entryClass = { */ int -Tk_EntryObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_EntryObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register Entry *entryPtr; Tk_OptionTable optionTable; @@ -523,27 +487,27 @@ Tk_EntryObjCmd(clientData, interp, objc, objv) } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, Tk will return the cached value. + * Create the option table for this widget class. If it has already been + * created, Tk will return the cached value. */ optionTable = Tk_CreateOptionTable(interp, entryOptSpec); /* - * Initialize the fields of the structure that won't be initialized - * by ConfigureEntry, or that ConfigureEntry requires to be - * initialized already (e.g. resource pointers). Only the non-NULL/0 - * data must be initialized as memset covers the rest. + * Initialize the fields of the structure that won't be initialized by + * ConfigureEntry, or that ConfigureEntry requires to be initialized + * already (e.g. resource pointers). Only the non-NULL/0 data must be + * initialized as memset covers the rest. */ entryPtr = (Entry *) ckalloc(sizeof(Entry)); - memset((VOID *) entryPtr, 0, sizeof(Entry)); + memset(entryPtr, 0, sizeof(Entry)); entryPtr->tkwin = tkwin; entryPtr->display = Tk_Display(tkwin); @@ -573,7 +537,7 @@ Tk_EntryObjCmd(clientData, interp, objc, objv) entryPtr->validate = VALIDATE_NONE; /* - * Keep a hold of the associated tkwin until we destroy the listbox, + * Keep a hold of the associated tkwin until we destroy the entry, * otherwise Tk might free it while we still need it. */ @@ -603,9 +567,9 @@ Tk_EntryObjCmd(clientData, interp, objc, objv) * * EntryWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -617,11 +581,11 @@ Tk_EntryObjCmd(clientData, interp, objc, objv) */ static int -EntryWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about entry widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +EntryWidgetObjCmd( + ClientData clientData, /* Information about entry widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Entry *entryPtr = (Entry *) clientData; int cmdIndex, selIndex, result; @@ -632,9 +596,9 @@ EntryWidgetObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } - /* - * Parse the widget command by looking up the second token in - * the list of valid command names. + /* + * Parse the widget command by looking up the second token in the list of + * valid command names. */ result = Tcl_GetIndexFromObj(interp, objv[1], entryCmdNames, @@ -645,398 +609,381 @@ EntryWidgetObjCmd(clientData, interp, objc, objv) Tcl_Preserve((ClientData) entryPtr); switch ((enum entryCmd) cmdIndex) { - case COMMAND_BBOX: { - int index, x, y, width, height; - char buf[TCL_INTEGER_SPACE * 4]; + case COMMAND_BBOX: { + int index, x, y, width, height; + char buf[TCL_INTEGER_SPACE * 4]; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; - } - if ((index == entryPtr->numChars) && (index > 0)) { - index--; - } - Tk_CharBbox(entryPtr->textLayout, index, &x, &y, - &width, &height); - sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX, - y + entryPtr->layoutY, width, height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - break; - } - - case COMMAND_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); - goto error; - } - - objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, - entryPtr->optionTable, objv[2], entryPtr->tkwin); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { + goto error; + } + if ((index == entryPtr->numChars) && (index > 0)) { + index--; + } + Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height); + sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX, + y + entryPtr->layoutY, width, height); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + break; + } + + case COMMAND_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + goto error; + } + + objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, + entryPtr->optionTable, objv[2], entryPtr->tkwin); + if (objPtr == NULL) { + goto error; + } else { + Tcl_SetObjResult(interp, objPtr); + } + break; + + case COMMAND_CONFIGURE: + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr, + entryPtr->optionTable, + (objc == 3) ? objv[2] : NULL, + entryPtr->tkwin); if (objPtr == NULL) { - goto error; + goto error; } else { Tcl_SetObjResult(interp, objPtr); } - break; + } else { + result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0); } + break; - case COMMAND_CONFIGURE: { - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr, - entryPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - entryPtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } - } else { - result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0); - } - break; + case COMMAND_DELETE: { + int first, last; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &first) != TCL_OK) { + goto error; + } + if (objc == 3) { + last = first + 1; + } else if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]), + &last) != TCL_OK) { + goto error; } + if ((last >= first) && (entryPtr->state == STATE_NORMAL)) { + DeleteChars(entryPtr, first, last - first); + } + break; + } - case COMMAND_DELETE: { - int first, last; + case COMMAND_GET: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + goto error; + } + Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1); + break; - if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &first) != TCL_OK) { - goto error; - } - if (objc == 3) { - last = first + 1; - } else { - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]), - &last) != TCL_OK) { - goto error; - } - } - if ((last >= first) && (entryPtr->state == STATE_NORMAL)) { - DeleteChars(entryPtr, first, last - first); - } - break; + case COMMAND_ICURSOR: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "pos"); + goto error; } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &entryPtr->insertPos) != TCL_OK) { + goto error; + } + EventuallyRedraw(entryPtr); + break; - case COMMAND_GET: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); - goto error; - } - Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1); - break; + case COMMAND_INDEX: { + int index; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "string"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { + goto error; } + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + break; + } - case COMMAND_ICURSOR: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "pos"); + case COMMAND_INSERT: { + int index; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "index text"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { + goto error; + } + if (entryPtr->state == STATE_NORMAL) { + InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + } + break; + } + + case COMMAND_SCAN: { + int x; + char *minorCmd; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x"); + goto error; + } + if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { + goto error; + } + + minorCmd = Tcl_GetString(objv[2]); + if (minorCmd[0] == 'm' + && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) { + entryPtr->scanMarkX = x; + entryPtr->scanMarkIndex = entryPtr->leftIndex; + } else if ((minorCmd[0] == 'd') + && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) { + EntryScanTo(entryPtr, x); + } else { + Tcl_AppendResult(interp, "bad scan option \"", + Tcl_GetString(objv[2]), "\": must be mark or dragto", + NULL); + goto error; + } + break; + } + + case COMMAND_SELECTION: { + int index, index2; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?index?"); + goto error; + } + + /* + * Parse the selection sub-command, using the command table + * "selCmdNames" defined above. + */ + + result = Tcl_GetIndexFromObj(interp, objv[2], selCmdNames, + "selection option", 0, &selIndex); + if (result != TCL_OK) { + goto error; + } + + /* + * Disabled entries don't allow the selection to be modified, but + * 'selection present' must return a boolean. + */ + + if ((entryPtr->state == STATE_DISABLED) + && (selIndex != SELECTION_PRESENT)) { + goto done; + } + + switch (selIndex) { + case SELECTION_ADJUST: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); goto error; } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &entryPtr->insertPos) != TCL_OK) { - goto error; + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { + goto error; } - EventuallyRedraw(entryPtr); + if (entryPtr->selectFirst >= 0) { + int half1, half2; + + half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2; + half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2; + if (index < half1) { + entryPtr->selectAnchor = entryPtr->selectLast; + } else if (index > half2) { + entryPtr->selectAnchor = entryPtr->selectFirst; + } else { + /* + * We're at about the halfway point in the selection; just + * keep the existing anchor. + */ + } + } + EntrySelectTo(entryPtr, index); break; - } - - case COMMAND_INDEX: { - int index; + case SELECTION_CLEAR: if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "string"); + Tcl_WrongNumArgs(interp, 3, objv, NULL); goto error; } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; + if (entryPtr->selectFirst >= 0) { + entryPtr->selectFirst = -1; + entryPtr->selectLast = -1; + EventuallyRedraw(entryPtr); } - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); - break; - } - - case COMMAND_INSERT: { - int index; + goto done; + case SELECTION_FROM: if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "index text"); + Tcl_WrongNumArgs(interp, 3, objv, "index"); goto error; } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; - } - if (entryPtr->state == STATE_NORMAL) { - InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { + goto error; } + entryPtr->selectAnchor = index; break; - } - case COMMAND_SCAN: { - int x; - char *minorCmd; + case SELECTION_PRESENT: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + goto error; + } + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj((entryPtr->selectFirst >= 0))); + goto done; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x"); + case SELECTION_RANGE: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "start end"); goto error; } - if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { - goto error; + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]), + &index) != TCL_OK) { + goto error; } - - minorCmd = Tcl_GetString(objv[2]); - if (minorCmd[0] == 'm' - && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) { - entryPtr->scanMarkX = x; - entryPtr->scanMarkIndex = entryPtr->leftIndex; - } else if ((minorCmd[0] == 'd') - && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) { - EntryScanTo(entryPtr, x); - } else { - Tcl_AppendResult(interp, "bad scan option \"", - Tcl_GetString(objv[2]), "\": must be mark or dragto", - (char *) NULL); + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[4]), + &index2) != TCL_OK) { goto error; } + if (index >= index2) { + entryPtr->selectFirst = -1; + entryPtr->selectLast = -1; + } else { + entryPtr->selectFirst = index; + entryPtr->selectLast = index2; + } + if (!(entryPtr->flags & GOT_SELECTION) + && (entryPtr->exportSelection)) { + Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, + EntryLostSelection, (ClientData) entryPtr); + entryPtr->flags |= GOT_SELECTION; + } + EventuallyRedraw(entryPtr); break; - } - - case COMMAND_SELECTION: { - int index, index2; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option ?index?"); + case SELECTION_TO: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); goto error; } - - /* - * Parse the selection sub-command, using the command - * table "selCmdNames" defined above. - */ - - result = Tcl_GetIndexFromObj(interp, objv[2], selCmdNames, - "selection option", 0, &selIndex); - if (result != TCL_OK) { + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { goto error; } + EntrySelectTo(entryPtr, index); + break; + } + break; + } - /* - * Disabled entries don't allow the selection to be modified, - * but 'selection present' must return a boolean. - */ - - if ((entryPtr->state == STATE_DISABLED) - && (selIndex != SELECTION_PRESENT)) { - goto done; - } - - switch (selIndex) { - case SELECTION_ADJUST: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - if (entryPtr->selectFirst >= 0) { - int half1, half2; - - half1 = (entryPtr->selectFirst - + entryPtr->selectLast)/2; - half2 = (entryPtr->selectFirst - + entryPtr->selectLast + 1)/2; - if (index < half1) { - entryPtr->selectAnchor = entryPtr->selectLast; - } else if (index > half2) { - entryPtr->selectAnchor = entryPtr->selectFirst; - } else { - /* - * We're at about the halfway point in the - * selection; just keep the existing anchor. - */ - } - } - EntrySelectTo(entryPtr, index); - break; - } - - case SELECTION_CLEAR: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); - goto error; - } - if (entryPtr->selectFirst >= 0) { - entryPtr->selectFirst = -1; - entryPtr->selectLast = -1; - EventuallyRedraw(entryPtr); - } - goto done; - } - - case SELECTION_FROM: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - entryPtr->selectAnchor = index; - break; - } - - case SELECTION_PRESENT: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); - goto error; - } - Tcl_SetObjResult(interp, - Tcl_NewBooleanObj((entryPtr->selectFirst >= 0))); - goto done; - } + case COMMAND_VALIDATE: { + int code; - case SELECTION_RANGE: { - if (objc != 5) { - Tcl_WrongNumArgs(interp, 3, objv, "start end"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[4]),& index2) != TCL_OK) { - goto error; - } - if (index >= index2) { - entryPtr->selectFirst = -1; - entryPtr->selectLast = -1; - } else { - entryPtr->selectFirst = index; - entryPtr->selectLast = index2; - } - if (!(entryPtr->flags & GOT_SELECTION) - && (entryPtr->exportSelection)) { - Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, - EntryLostSelection, (ClientData) entryPtr); - entryPtr->flags |= GOT_SELECTION; - } - EventuallyRedraw(entryPtr); - break; - } - - case SELECTION_TO: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - EntrySelectTo(entryPtr, index); - break; - } - } - break; + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + goto error; + } + selIndex = entryPtr->validate; + entryPtr->validate = VALIDATE_ALL; + code = EntryValidateChange(entryPtr, NULL, entryPtr->string, + -1, VALIDATE_FORCED); + if (entryPtr->validate != VALIDATE_NONE) { + entryPtr->validate = selIndex; } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj((code == TCL_OK))); + break; + } - case COMMAND_VALIDATE: { - int code; + case COMMAND_XVIEW: { + int index; - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + if (objc == 2) { + double first, last; + char buf[TCL_DOUBLE_SPACE]; + + EntryVisibleRange(entryPtr, &first, &last); + Tcl_PrintDouble(NULL, first, buf); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_PrintDouble(NULL, last, buf); + Tcl_AppendResult(interp, " ", buf, NULL); + goto done; + } else if (objc == 3) { + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { goto error; } - selIndex = entryPtr->validate; - entryPtr->validate = VALIDATE_ALL; - code = EntryValidateChange(entryPtr, (char *) NULL, - entryPtr->string, -1, VALIDATE_FORCED); - if (entryPtr->validate != VALIDATE_NONE) { - entryPtr->validate = selIndex; - } - Tcl_SetObjResult(interp, Tcl_NewBooleanObj((code == TCL_OK))); - break; - } + } else { + double fraction; + int count; - case COMMAND_XVIEW: { - int index; - - if (objc == 2) { - double first, last; - char buf[TCL_DOUBLE_SPACE * 2]; - - EntryVisibleRange(entryPtr, &first, &last); - sprintf(buf, "%g %g", first, last); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - goto done; - } else if (objc == 3) { - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; - } - } else { - double fraction; - int count; - - index = entryPtr->leftIndex; - switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, - &count)) { - case TK_SCROLL_ERROR: { - goto error; - } - case TK_SCROLL_MOVETO: { - index = (int) ((fraction * entryPtr->numChars) + 0.5); - break; - } - case TK_SCROLL_PAGES: { - int charsPerPage; - - charsPerPage = ((Tk_Width(entryPtr->tkwin) - - 2 * entryPtr->inset) - / entryPtr->avgWidth) - 2; - if (charsPerPage < 1) { - charsPerPage = 1; - } - index += count * charsPerPage; - break; - } - case TK_SCROLL_UNITS: { - index += count; - break; - } + index = entryPtr->leftIndex; + switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, + &count)) { + case TK_SCROLL_ERROR: + goto error; + case TK_SCROLL_MOVETO: + index = (int) ((fraction * entryPtr->numChars) + 0.5); + break; + case TK_SCROLL_PAGES: { + int charsPerPage; + + charsPerPage = ((Tk_Width(entryPtr->tkwin) + - 2 * entryPtr->inset) / entryPtr->avgWidth) - 2; + if (charsPerPage < 1) { + charsPerPage = 1; } + index += count * charsPerPage; + break; } - if (index >= entryPtr->numChars) { - index = entryPtr->numChars - 1; - } - if (index < 0) { - index = 0; + case TK_SCROLL_UNITS: + index += count; + break; } - entryPtr->leftIndex = index; - entryPtr->flags |= UPDATE_SCROLLBAR; - EntryComputeGeometry(entryPtr); - EventuallyRedraw(entryPtr); - break; } + if (index >= entryPtr->numChars) { + index = entryPtr->numChars - 1; + } + if (index < 0) { + index = 0; + } + entryPtr->leftIndex = index; + entryPtr->flags |= UPDATE_SCROLLBAR; + EntryComputeGeometry(entryPtr); + EventuallyRedraw(entryPtr); + break; + } } - done: + done: Tcl_Release((ClientData) entryPtr); return result; - error: + error: Tcl_Release((ClientData) entryPtr); return TCL_ERROR; } @@ -1046,9 +993,9 @@ EntryWidgetObjCmd(clientData, interp, objc, objv) * * DestroyEntry -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of an entry at a safe time - * (when no-one is using it anymore). + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of an entry at a safe time (when no-one is + * using it anymore). * * Results: * None. @@ -1060,15 +1007,14 @@ EntryWidgetObjCmd(clientData, interp, objc, objv) */ static void -DestroyEntry(memPtr) - char *memPtr; /* Info about entry widget. */ +DestroyEntry( + char *memPtr) /* Info about entry widget. */ { Entry *entryPtr = (Entry *) memPtr; /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ ckfree((char *)entryPtr->string); @@ -1113,43 +1059,43 @@ DestroyEntry(memPtr) * * ConfigureEntry -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or reconfigure) - * an entry widget. + * This function is called to process an argv/argc list, plus the Tk + * option database, in order to configure (or reconfigure) an entry + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for entryPtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for entryPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureEntry(interp, entryPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Entry *entryPtr; /* Information about widget; may or may not +ConfigureEntry( + Tcl_Interp *interp, /* Used for error reporting. */ + Entry *entryPtr, /* Information about widget; may or may not * already have values for some fields. */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *CONST objv[], /* Argument objects. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { Tk_SavedOptions savedOptions; Tk_3DBorder border; Tcl_Obj *errorResult = NULL; - Spinbox *sbPtr = (Spinbox *) entryPtr; /* Only used when this widget - * is of type TK_SPINBOX */ - char *oldValues = NULL; /* lint initialization */ - char *oldFormat = NULL; /* lint initialization */ + Spinbox *sbPtr = (Spinbox *) entryPtr; + /* Only used when this widget is of type + * TK_SPINBOX */ + char *oldValues = NULL; /* lint initialization */ + char *oldFormat = NULL; /* lint initialization */ int error; - int oldExport = 0; /* lint initialization */ - int valuesChanged = 0; /* lint initialization */ - double oldFrom = 0.0; /* lint initialization */ - double oldTo = 0.0; /* lint initialization */ + int oldExport = 0; /* lint initialization */ + int valuesChanged = 0; /* lint initialization */ + double oldFrom = 0.0; /* lint initialization */ + double oldTo = 0.0; /* lint initialization */ /* * Eliminate any existing trace on a variable monitored by the entry. @@ -1157,16 +1103,17 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) if ((entryPtr->textVarName != NULL) && (entryPtr->flags & ENTRY_VAR_TRACED)) { - Tcl_UntraceVar(interp, entryPtr->textVarName, + Tcl_UntraceVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, EntryTextVarProc, (ClientData) entryPtr); entryPtr->flags &= ~ENTRY_VAR_TRACED; } /* - * Store old values that we need to effect certain behavior if - * they change value + * Store old values that we need to effect certain behavior if they change + * value. */ + oldExport = entryPtr->exportSelection; if (entryPtr->type == TK_SPINBOX) { oldValues = sbPtr->valueStr; @@ -1183,7 +1130,7 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) if (Tk_SetOptions(interp, (char *) entryPtr, entryPtr->optionTable, objc, objv, - entryPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { + entryPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -1233,6 +1180,7 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) * calculate the minimum space we'll need for the values as * strings. */ + int min, max; size_t formatLen, formatSpace = TCL_DOUBLE_SPACE; char fbuf[4], *fmt = sbPtr->reqFormat; @@ -1241,7 +1189,7 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) if ((fmt[0] != '%') || (fmt[formatLen-1] != 'f')) { badFormatOpt: Tcl_AppendResult(interp, "bad spinbox format specifier \"", - sbPtr->reqFormat, "\"", (char *) NULL); + sbPtr->reqFormat, "\"", NULL); continue; } if ((sscanf(fmt, "%%%d.%d%[f]", &min, &max, fbuf) == 3) @@ -1259,16 +1207,19 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) formatSpace = TCL_DOUBLE_SPACE; } sbPtr->formatBuf = ckrealloc(sbPtr->formatBuf, formatSpace); + /* - * We perturb the value of oldFrom to allow us to go into - * the branch below that will reformat the displayed value. + * We perturb the value of oldFrom to allow us to go into the + * branch below that will reformat the displayed value. */ + oldFrom = sbPtr->fromValue - 1; } /* - * See if we have to rearrange our listObj data + * See if we have to rearrange our listObj data. */ + if (oldValues != sbPtr->valueStr) { if (sbPtr->listObj != NULL) { Tcl_DecrRefCount(sbPtr->listObj); @@ -1294,13 +1245,14 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) } /* - * Restart the cursor timing sequence in case the on-time or - * off-time just changed. Set validate temporarily to none, - * so the configure doesn't cause it to be triggered. + * Restart the cursor timing sequence in case the on-time or off-time + * just changed. Set validate temporarily to none, so the configure + * doesn't cause it to be triggered. */ if (entryPtr->flags & GOT_FOCUS) { int validate = entryPtr->validate; + entryPtr->validate = VALIDATE_NONE; EntryFocusProc(entryPtr, 1); entryPtr->validate = validate; @@ -1311,8 +1263,8 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) */ if (entryPtr->exportSelection && (!oldExport) - && (entryPtr->selectFirst != -1) - && !(entryPtr->flags & GOT_SELECTION)) { + && (entryPtr->selectFirst != -1) + && !(entryPtr->flags & GOT_SELECTION)) { Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection, (ClientData) entryPtr); entryPtr->flags |= GOT_SELECTION; @@ -1324,12 +1276,12 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) */ Tk_SetInternalBorder(entryPtr->tkwin, - entryPtr->borderWidth + entryPtr->highlightWidth); + entryPtr->borderWidth + entryPtr->highlightWidth); if (entryPtr->highlightWidth <= 0) { entryPtr->highlightWidth = 0; } - entryPtr->inset = entryPtr->highlightWidth - + entryPtr->borderWidth + XPAD; + entryPtr->inset = entryPtr->highlightWidth + + entryPtr->borderWidth + XPAD; break; } if (!error) { @@ -1359,9 +1311,10 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) Tcl_Obj *objPtr; /* - * No check for error return, because there shouldn't be one - * given the check for valid list above + * No check for error return, because there shouldn't be one given + * the check for valid list above. */ + Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr); EntryValueChanged(entryPtr, Tcl_GetString(objPtr)); } else if ((sbPtr->valueStr == NULL) @@ -1370,15 +1323,15 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) || !DOUBLES_EQ(sbPtr->toValue, oldTo))) { /* * If the valueStr is empty and -from && -to are specified, check - * to see if the current string is within the range. If not, - * it will be constrained to the nearest edge. If the current - * string isn't a double value, we set it to -from. + * to see if the current string is within the range. If not, it + * will be constrained to the nearest edge. If the current string + * isn't a double value, we set it to -from. */ - int code; + double dvalue; - code = Tcl_GetDouble(NULL, entryPtr->string, &dvalue); - if (code != TCL_OK) { + if (sscanf(entryPtr->string, "%lf", &dvalue) == 0) { + /* Scan failure */ dvalue = sbPtr->fromValue; } else { if (dvalue > sbPtr->toValue) { @@ -1393,8 +1346,8 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) } /* - * Set up a trace on the variable's value after we've possibly - * constrained the value according to new -from/-to values. + * Set up a trace on the variable's value after we've possibly constrained + * the value according to new -from/-to values. */ if ((entryPtr->textVarName != NULL) @@ -1407,11 +1360,11 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) EntryWorldChanged((ClientData) entryPtr); if (error) { - Tcl_SetObjResult(interp, errorResult); + Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } else { - return TCL_OK; + return TCL_OK; } } @@ -1420,22 +1373,22 @@ ConfigureEntry(interp, entryPtr, objc, objv, flags) * * EntryWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: - * None. + * None. * * Side effects: - * Entry will be relayed out and redisplayed. + * Entry will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ - + static void -EntryWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +EntryWorldChanged( + ClientData instanceData) /* Information about widget. */ { XGCValues gcValues; GC gc = None; @@ -1461,27 +1414,27 @@ EntryWorldChanged(instanceData) } /* - * Default background and foreground are from the normal state. - * In a disabled state, both of those may be overridden; in the readonly - * state, the background may be overridden. + * Default background and foreground are from the normal state. In a + * disabled state, both of those may be overridden; in the readonly state, + * the background may be overridden. */ border = entryPtr->normalBorder; colorPtr = entryPtr->fgColorPtr; switch (entryPtr->state) { - case STATE_DISABLED: - if (entryPtr->disabledBorder != NULL) { - border = entryPtr->disabledBorder; - } - if (entryPtr->dfgColorPtr != NULL) { - colorPtr = entryPtr->dfgColorPtr; - } - break; - case STATE_READONLY: - if (entryPtr->readonlyBorder != NULL) { - border = entryPtr->readonlyBorder; - } - break; + case STATE_DISABLED: + if (entryPtr->disabledBorder != NULL) { + border = entryPtr->disabledBorder; + } + if (entryPtr->dfgColorPtr != NULL) { + colorPtr = entryPtr->dfgColorPtr; + } + break; + case STATE_READONLY: + if (entryPtr->readonlyBorder != NULL) { + border = entryPtr->readonlyBorder; + } + break; } Tk_SetBackgroundFromBorder(entryPtr->tkwin, border); @@ -1507,8 +1460,7 @@ EntryWorldChanged(instanceData) entryPtr->selTextGC = gc; /* - * Recompute the window's geometry and arrange for it to be - * redisplayed. + * Recompute the window's geometry and arrange for it to be redisplayed. */ EntryComputeGeometry(entryPtr); @@ -1516,18 +1468,17 @@ EntryWorldChanged(instanceData) EventuallyRedraw(entryPtr); } -#ifndef MAC_OSX_TK +#ifndef MAC_OSX_TK /* *-------------------------------------------------------------- * * TkpDrawEntryBorderAndFocus -- * - * This procedure redraws the border of an entry widget. - * It overrides the generic border drawing code if the - * entry widget parameters are such that the native widget - * drawing is a good fit. - * This version just returns o, so platforms that don't - * do special native drawing don't have to implement it. + * This function redraws the border of an entry widget. It overrides the + * generic border drawing code if the entry widget parameters are such + * that the native widget drawing is a good fit. This version just + * returns 0, so platforms that don't do special native drawing don't + * have to implement it. * * Results: * 1 if it has drawn the border, 0 if not. @@ -1539,26 +1490,24 @@ EntryWorldChanged(instanceData) */ int -TkpDrawEntryBorderAndFocus(entryPtr, pixmap, isSpinbox) - Entry *entryPtr; - Drawable pixmap; - int isSpinbox; +TkpDrawEntryBorderAndFocus( + Entry *entryPtr, + Drawable pixmap, + int isSpinbox) { return 0; } - - + /* *-------------------------------------------------------------- * * TkpDrawSpinboxButtons -- * - * This procedure redraws the buttons of an spinbox widget. - * It overrides the generic button drawing code if the - * spinbox widget parameters are such that the native widget - * drawing is a good fit. - * This version just returns 0, so platforms that don't - * do special native drawing don't have to implement it. + * This function redraws the buttons of an spinbox widget. It overrides + * the generic button drawing code if the spinbox widget parameters are + * such that the native widget drawing is a good fit. This version just + * returns 0, so platforms that don't do special native drawing don't + * have to implement it. * * Results: * 1 if it has drawn the border, 0 if not. @@ -1570,20 +1519,20 @@ TkpDrawEntryBorderAndFocus(entryPtr, pixmap, isSpinbox) */ int -TkpDrawSpinboxButtons(sbPtr, pixmap) - Spinbox *sbPtr; - Pixmap pixmap; +TkpDrawSpinboxButtons( + Spinbox *sbPtr, + Pixmap pixmap) { return 0; } #endif /* Not MAC_OSX_TK */ - + /* *-------------------------------------------------------------- * * DisplayEntry -- * - * This procedure redraws the contents of an entry window. + * This function redraws the contents of an entry window. * * Results: * None. @@ -1595,8 +1544,8 @@ TkpDrawSpinboxButtons(sbPtr, pixmap) */ static void -DisplayEntry(clientData) - ClientData clientData; /* Information about window. */ +DisplayEntry( + ClientData clientData) /* Information about window. */ { Entry *entryPtr = (Entry *) clientData; Tk_Window tkwin = entryPtr->tkwin; @@ -1620,9 +1569,9 @@ DisplayEntry(clientData) if (entryPtr->flags & UPDATE_SCROLLBAR) { entryPtr->flags &= ~UPDATE_SCROLLBAR; - /* - * Preserve/Release because updating the scrollbar can have - * the side-effect of destroying or unmapping the entry widget. + /* + * Preserve/Release because updating the scrollbar can have the + * side-effect of destroying or unmapping the entry widget. */ Tcl_Preserve((ClientData) entryPtr); @@ -1637,10 +1586,10 @@ DisplayEntry(clientData) #ifndef TK_NO_DOUBLE_BUFFERING /* - * In order to avoid screen flashes, this procedure redraws the - * textual area of the entry into off-screen memory, then copies - * it back on-screen in a single operation. This means there's - * no point in time where the on-screen image has been cleared. + * In order to avoid screen flashes, this function redraws the textual + * area of the entry into off-screen memory, then copies it back on-screen + * in a single operation. This means there's no point in time where the + * on-screen image has been cleared. */ pixmap = Tk_GetPixmap(entryPtr->display, Tk_WindowId(tkwin), @@ -1650,18 +1599,17 @@ DisplayEntry(clientData) #endif /* TK_NO_DOUBLE_BUFFERING */ /* - * Compute x-coordinate of the pixel just after last visible - * one, plus vertical position of baseline of text. + * Compute x-coordinate of the pixel just after last visible one, plus + * vertical position of baseline of text. */ xBound = Tk_Width(tkwin) - entryPtr->inset - entryPtr->xWidth; baseY = (Tk_Height(tkwin) + fm.ascent - fm.descent) / 2; /* - * On Windows and Mac, we need to hide the selection whenever we - * don't have the focus. + * Hide the selection whenever we don't have the focus, unless we + * always want to show selection. */ - if (TkpAlwaysShowSelection(entryPtr->tkwin)) { showSelection = 1; } else { @@ -1669,9 +1617,9 @@ DisplayEntry(clientData) } /* - * Draw the background in three layers. From bottom to top the - * layers are: normal background, selection background, and - * insertion cursor background. + * Draw the background in three layers. From bottom to top the layers are: + * normal background, selection background, and insertion cursor + * background. */ if ((entryPtr->state == STATE_DISABLED) && @@ -1711,16 +1659,16 @@ DisplayEntry(clientData) MAC_OSX_ENTRY_SELECT_RELIEF #endif ); - } + } } /* - * Draw a special background for the insertion cursor, overriding - * even the selection background. As a special hack to keep the - * cursor visible when the insertion cursor color is the same as - * the color for selected text (e.g., on mono displays), write - * background in the cursor area (instead of nothing) when the - * cursor isn't on. Otherwise the selection would hide the cursor. + * Draw a special background for the insertion cursor, overriding even the + * selection background. As a special hack to keep the cursor visible when + * the insertion cursor color is the same as the color for selected text + * (e.g., on mono displays), write background in the cursor area (instead + * of nothing) when the cursor isn't on. Otherwise the selection would + * hide the cursor. */ if ((entryPtr->state == STATE_NORMAL) && (entryPtr->flags & GOT_FOCUS)) { @@ -1730,25 +1678,22 @@ DisplayEntry(clientData) cursorX -= (entryPtr->insertWidth)/2; Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent, fm.ascent + fm.descent); - if (entryPtr->insertPos >= entryPtr->leftIndex) { - if (cursorX < xBound) { - if (entryPtr->flags & CURSOR_ON) { - Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->insertBorder, - cursorX, baseY - fm.ascent, entryPtr->insertWidth, - fm.ascent + fm.descent, - entryPtr->insertBorderWidth, - TK_RELIEF_RAISED); - } else if (entryPtr->insertBorder == entryPtr->selBorder) { - Tk_Fill3DRectangle(tkwin, pixmap, border, - cursorX, baseY - fm.ascent, entryPtr->insertWidth, - fm.ascent + fm.descent, 0, TK_RELIEF_FLAT); - } + if (entryPtr->insertPos >= entryPtr->leftIndex && cursorX < xBound) { + if (entryPtr->flags & CURSOR_ON) { + Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->insertBorder, + cursorX, baseY - fm.ascent, entryPtr->insertWidth, + fm.ascent + fm.descent, entryPtr->insertBorderWidth, + TK_RELIEF_RAISED); + } else if (entryPtr->insertBorder == entryPtr->selBorder) { + Tk_Fill3DRectangle(tkwin, pixmap, border, cursorX, + baseY - fm.ascent, entryPtr->insertWidth, + fm.ascent + fm.descent, 0, TK_RELIEF_FLAT); } } } /* - * Draw the text in two pieces: first the unselected portion, then the + * Draw the text in two pieces: first the unselected portion, then the * selected portion on top of it. */ @@ -1778,17 +1723,18 @@ DisplayEntry(clientData) /* * Draw the spin button controls. */ - if (TkpDrawSpinboxButtons(sbPtr, pixmap) == 0) { - xWidth = entryPtr->xWidth; - pad = XPAD + 1; - inset = entryPtr->inset - XPAD; - startx = Tk_Width(tkwin) - (xWidth + inset); - height = (Tk_Height(tkwin) - 2*inset)/2; + + if (TkpDrawSpinboxButtons(sbPtr, pixmap) == 0) { + xWidth = entryPtr->xWidth; + pad = XPAD + 1; + inset = entryPtr->inset - XPAD; + startx = Tk_Width(tkwin) - (xWidth + inset); + height = (Tk_Height(tkwin) - 2*inset)/2; #if 0 - Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder, - startx, inset, xWidth, height, 1, sbPtr->buRelief); - Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder, - startx, inset+height, xWidth, height, 1, sbPtr->bdRelief); + Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder, + startx, inset, xWidth, height, 1, sbPtr->buRelief); + Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder, + startx, inset+height, xWidth, height, 1, sbPtr->bdRelief); #else Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder, startx, inset, xWidth, height, 1, @@ -1799,90 +1745,97 @@ DisplayEntry(clientData) (sbPtr->selElement == SEL_BUTTONDOWN) ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED); #endif - - xWidth -= 2*pad; - /* - * Only draw the triangles if we have enough display space - */ - if ((xWidth > 1)) { - XPoint points[3]; - int starty, space, offset; - - space = height - 2*pad; - /* - * Ensure width of triangle is odd to guarantee a sharp tip - */ - if (!(xWidth % 2)) { - xWidth++; - } - tHeight = (xWidth + 1) / 2; - if (tHeight > space) { - tHeight = space; - } - space = (space - tHeight) / 2; - startx += pad; - starty = inset + height - pad - space; - offset = (sbPtr->selElement == SEL_BUTTONUP); - /* - * The points are slightly different for the up and down arrows - * because (for *.x), we need to account for a bug in the way - * XFillPolygon draws triangles, and we want to shift - * the arrows differently when allowing for depressed behavior. - */ - points[0].x = startx + offset; - points[0].y = starty + (offset ? 0 : -1); - points[1].x = startx + xWidth/2 + offset; - points[1].y = starty - tHeight + (offset ? 0 : -1); - points[2].x = startx + xWidth + offset; - points[2].y = points[0].y; - XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC, - points, 3, Convex, CoordModeOrigin); - - starty = inset + height + pad + space; - offset = (sbPtr->selElement == SEL_BUTTONDOWN); - points[0].x = startx + 1 + offset; - points[0].y = starty + (offset ? 1 : 0); - points[1].x = startx + xWidth/2 + offset; - points[1].y = starty + tHeight + (offset ? 0 : -1); - points[2].x = startx - 1 + xWidth + offset; - points[2].y = points[0].y; - XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC, - points, 3, Convex, CoordModeOrigin); - } - } + + xWidth -= 2*pad; + + /* + * Only draw the triangles if we have enough display space + */ + + if ((xWidth > 1)) { + XPoint points[3]; + int starty, space, offset; + + space = height - 2*pad; + + /* + * Ensure width of triangle is odd to guarantee a sharp tip + */ + + if (!(xWidth % 2)) { + xWidth++; + } + tHeight = (xWidth + 1) / 2; + if (tHeight > space) { + tHeight = space; + } + space = (space - tHeight) / 2; + startx += pad; + starty = inset + height - pad - space; + offset = (sbPtr->selElement == SEL_BUTTONUP); + + /* + * The points are slightly different for the up and down + * arrows because (for *.x), we need to account for a bug in + * the way XFillPolygon draws triangles, and we want to shift + * the arrows differently when allowing for depressed + * behavior. + */ + + points[0].x = startx + offset; + points[0].y = starty + (offset ? 0 : -1); + points[1].x = startx + xWidth/2 + offset; + points[1].y = starty - tHeight + (offset ? 0 : -1); + points[2].x = startx + xWidth + offset; + points[2].y = points[0].y; + XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC, + points, 3, Convex, CoordModeOrigin); + + starty = inset + height + pad + space; + offset = (sbPtr->selElement == SEL_BUTTONDOWN); + points[0].x = startx + 1 + offset; + points[0].y = starty + (offset ? 1 : 0); + points[1].x = startx + xWidth/2 + offset; + points[1].y = starty + tHeight + (offset ? 0 : -1); + points[2].x = startx - 1 + xWidth + offset; + points[2].y = points[0].y; + XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC, + points, 3, Convex, CoordModeOrigin); + } + } } /* - * Draw the border and focus highlight last, so they will overwrite - * any text that extends past the viewable part of the window. + * Draw the border and focus highlight last, so they will overwrite any + * text that extends past the viewable part of the window. */ - if (!TkpDrawEntryBorderAndFocus(entryPtr, pixmap, - (entryPtr->type == TK_SPINBOX))) { - xBound = entryPtr->highlightWidth; - if (entryPtr->relief != TK_RELIEF_FLAT) { + if (!TkpDrawEntryBorderAndFocus(entryPtr, pixmap, + (entryPtr->type == TK_SPINBOX))) { + xBound = entryPtr->highlightWidth; + if (entryPtr->relief != TK_RELIEF_FLAT) { Tk_Draw3DRectangle(tkwin, pixmap, border, xBound, xBound, - Tk_Width(tkwin) - 2 * xBound, + Tk_Width(tkwin) - 2 * xBound, Tk_Height(tkwin) - 2 * xBound, entryPtr->borderWidth, entryPtr->relief); - } - if (xBound > 0) { + } + if (xBound > 0) { GC fgGC, bgGC; bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, pixmap); if (entryPtr->flags & GOT_FOCUS) { - fgGC = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap); - TkpDrawHighlightBorder(tkwin, fgGC, bgGC, xBound, pixmap); + fgGC = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap); + TkpDrawHighlightBorder(tkwin, fgGC, bgGC, xBound, pixmap); } else { - TkpDrawHighlightBorder(tkwin, bgGC, bgGC, xBound, pixmap); + TkpDrawHighlightBorder(tkwin, bgGC, bgGC, xBound, pixmap); } - } + } } #ifndef TK_NO_DOUBLE_BUFFERING /* - * Everything's been redisplayed; now copy the pixmap onto the screen - * and free up the pixmap. + * Everything's been redisplayed; now copy the pixmap onto the screen and + * free up the pixmap. */ XCopyArea(entryPtr->display, pixmap, Tk_WindowId(tkwin), entryPtr->textGC, @@ -1898,24 +1851,24 @@ DisplayEntry(clientData) * * EntryComputeGeometry -- * - * This procedure is invoked to recompute information about where - * in its window an entry's string will be displayed. It also - * computes the requested size for the window. + * This function is invoked to recompute information about where in its + * window an entry's string will be displayed. It also computes the + * requested size for the window. * * Results: * None. * * Side effects: - * The leftX and tabOrigin fields are recomputed for entryPtr, - * and leftIndex may be adjusted. Tk_GeometryRequest is called - * to register the desired dimensions for the window. + * The leftX and tabOrigin fields are recomputed for entryPtr, and + * leftIndex may be adjusted. Tk_GeometryRequest is called to register + * the desired dimensions for the window. * *---------------------------------------------------------------------- */ static void -EntryComputeGeometry(entryPtr) - Entry *entryPtr; /* Widget record for entry. */ +EntryComputeGeometry( + Entry *entryPtr) /* Widget record for entry. */ { int totalLength, overflow, maxOffScreen, rightX; int height, width, i; @@ -1929,8 +1882,8 @@ EntryComputeGeometry(entryPtr) } /* - * If we're displaying a special character instead of the value of - * the entry, recompute the displayString. + * If we're displaying a special character instead of the value of the + * entry, recompute the displayString. */ if (entryPtr->showChar != NULL) { @@ -1939,10 +1892,10 @@ EntryComputeGeometry(entryPtr) int size; /* - * Normalize the special character so we can safely duplicate it - * in the display string. If we didn't do this, then two malformed - * characters might end up looking like one valid UTF character in - * the resulting string. + * Normalize the special character so we can safely duplicate it in + * the display string. If we didn't do this, then two malformed + * characters might end up looking like one valid UTF character in the + * resulting string. */ Tcl_UtfToUniChar(entryPtr->showChar, &ch); @@ -1966,21 +1919,21 @@ EntryComputeGeometry(entryPtr) entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2; /* - * Recompute where the leftmost character on the display will - * be drawn (entryPtr->leftX) and adjust leftIndex if necessary - * so that we don't let characters hang off the edge of the - * window unless the entire window is full. + * Recompute where the leftmost character on the display will be drawn + * (entryPtr->leftX) and adjust leftIndex if necessary so that we don't + * let characters hang off the edge of the window unless the entire window + * is full. */ overflow = totalLength - - (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth); + (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth); if (overflow <= 0) { entryPtr->leftIndex = 0; if (entryPtr->justify == TK_JUSTIFY_LEFT) { entryPtr->leftX = entryPtr->inset; } else if (entryPtr->justify == TK_JUSTIFY_RIGHT) { entryPtr->leftX = Tk_Width(entryPtr->tkwin) - entryPtr->inset - - entryPtr->xWidth - totalLength; + - entryPtr->xWidth - totalLength; } else { entryPtr->leftX = (Tk_Width(entryPtr->tkwin) - entryPtr->xWidth - totalLength)/2; @@ -1988,10 +1941,10 @@ EntryComputeGeometry(entryPtr) entryPtr->layoutX = entryPtr->leftX; } 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 leftIndex be any greater than that. + * 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 + * leftIndex be any greater than that. */ maxOffScreen = Tk_PointToChar(entryPtr->textLayout, overflow, 0); @@ -2040,23 +1993,25 @@ EntryComputeGeometry(entryPtr) * None. * * Side effects: - * New information gets added to entryPtr; it will be redisplayed - * soon, but not necessarily immediately. + * New information gets added to entryPtr; it will be redisplayed soon, + * but not necessarily immediately. * *---------------------------------------------------------------------- */ static void -InsertChars(entryPtr, index, value) - Entry *entryPtr; /* Entry that is to get the new elements. */ - int index; /* Add the new elements before this - * character index. */ - char *value; /* New characters to add (NULL-terminated +InsertChars( + Entry *entryPtr, /* Entry that is to get the new elements. */ + int index, /* Add the new elements before this character + * index. */ + char *value) /* New characters to add (NULL-terminated * string). */ { - int byteIndex, byteCount, oldChars, charsAdded, newByteCount; + ptrdiff_t byteIndex; + size_t byteCount, newByteCount; + int oldChars, charsAdded; CONST char *string; - char *new; + char *newStr; string = entryPtr->string; byteIndex = Tcl_UtfAtIndex(string, index) - string; @@ -2066,48 +2021,47 @@ InsertChars(entryPtr, index, value) } newByteCount = entryPtr->numBytes + byteCount + 1; - new = (char *) ckalloc((unsigned) newByteCount); - memcpy(new, string, (size_t) byteIndex); - strcpy(new + byteIndex, value); - strcpy(new + byteIndex + byteCount, string + byteIndex); + newStr = (char *) ckalloc((unsigned) newByteCount); + memcpy(newStr, string, byteIndex); + strcpy(newStr + byteIndex, value); + strcpy(newStr + byteIndex + byteCount, string + byteIndex); if ((entryPtr->validate == VALIDATE_KEY || - entryPtr->validate == VALIDATE_ALL) && - EntryValidateChange(entryPtr, value, new, index, - VALIDATE_INSERT) != TCL_OK) { - ckfree(new); + entryPtr->validate == VALIDATE_ALL) && + EntryValidateChange(entryPtr, value, newStr, index, + VALIDATE_INSERT) != TCL_OK) { + ckfree(newStr); return; } ckfree((char *)string); - entryPtr->string = new; + entryPtr->string = newStr; /* - * The following construction is used because inserting improperly - * formed UTF-8 sequences between other improperly formed UTF-8 - * sequences could result in actually forming valid UTF-8 sequences; - * the number of characters added may not be Tcl_NumUtfChars(string, -1), - * because of context. The actual number of characters added is how - * many characters are in the string now minus the number that - * used to be there. + * The following construction is used because inserting improperly formed + * UTF-8 sequences between other improperly formed UTF-8 sequences could + * result in actually forming valid UTF-8 sequences; the number of + * characters added may not be Tcl_NumUtfChars(string, -1), because of + * context. The actual number of characters added is how many characters + * are in the string now minus the number that used to be there. */ oldChars = entryPtr->numChars; - entryPtr->numChars = Tcl_NumUtfChars(new, -1); + entryPtr->numChars = Tcl_NumUtfChars(newStr, -1); charsAdded = entryPtr->numChars - oldChars; entryPtr->numBytes += byteCount; if (entryPtr->displayString == string) { - entryPtr->displayString = new; + entryPtr->displayString = newStr; entryPtr->numDisplayBytes = entryPtr->numBytes; } /* - * Inserting characters invalidates all indexes into the string. - * Touch up the indexes so that they still refer to the same - * characters (at new positions). When updating the selection - * end-points, don't include the new text in the selection unless - * it was completely surrounded by the selection. + * Inserting characters invalidates all indexes into the string. Touch up + * the indexes so that they still refer to the same characters (at new + * positions). When updating the selection end-points, don't include the + * new text in the selection unless it was completely surrounded by the + * selection. */ if (entryPtr->selectFirst >= index) { @@ -2116,8 +2070,7 @@ InsertChars(entryPtr, index, value) if (entryPtr->selectLast > index) { entryPtr->selectLast += charsAdded; } - if ((entryPtr->selectAnchor > index) - || (entryPtr->selectFirst >= index)) { + if ((entryPtr->selectAnchor > index) || (entryPtr->selectFirst >= index)) { entryPtr->selectAnchor += charsAdded; } if (entryPtr->leftIndex > index) { @@ -2147,14 +2100,14 @@ InsertChars(entryPtr, index, value) */ static void -DeleteChars(entryPtr, index, count) - Entry *entryPtr; /* Entry widget to modify. */ - int index; /* Index of first character to delete. */ - int count; /* How many characters to delete. */ +DeleteChars( + Entry *entryPtr, /* Entry widget to modify. */ + int index, /* Index of first character to delete. */ + int count) /* How many characters to delete. */ { int byteIndex, byteCount, newByteCount; CONST char *string; - char *new, *todelete; + char *newStr, *toDelete; if ((index + count) > entryPtr->numChars) { count = entryPtr->numChars - index; @@ -2165,41 +2118,41 @@ DeleteChars(entryPtr, index, count) string = entryPtr->string; byteIndex = Tcl_UtfAtIndex(string, index) - string; - byteCount = Tcl_UtfAtIndex(string + byteIndex, count) - (string + byteIndex); + byteCount = Tcl_UtfAtIndex(string + byteIndex, count) - (string+byteIndex); newByteCount = entryPtr->numBytes + 1 - byteCount; - new = (char *) ckalloc((unsigned) newByteCount); - memcpy(new, string, (size_t) byteIndex); - strcpy(new + byteIndex, string + byteIndex + byteCount); + newStr = (char *) ckalloc((unsigned) newByteCount); + memcpy(newStr, string, (size_t) byteIndex); + strcpy(newStr + byteIndex, string + byteIndex + byteCount); - todelete = (char *) ckalloc((unsigned) (byteCount + 1)); - memcpy(todelete, string + byteIndex, (size_t) byteCount); - todelete[byteCount] = '\0'; + toDelete = (char *) ckalloc((unsigned) (byteCount + 1)); + memcpy(toDelete, string + byteIndex, (size_t) byteCount); + toDelete[byteCount] = '\0'; if ((entryPtr->validate == VALIDATE_KEY || - entryPtr->validate == VALIDATE_ALL) && - EntryValidateChange(entryPtr, todelete, new, index, - VALIDATE_DELETE) != TCL_OK) { - ckfree(new); - ckfree(todelete); + entryPtr->validate == VALIDATE_ALL) && + EntryValidateChange(entryPtr, toDelete, newStr, index, + VALIDATE_DELETE) != TCL_OK) { + ckfree(newStr); + ckfree(toDelete); return; } - ckfree(todelete); + ckfree(toDelete); ckfree((char *)entryPtr->string); - entryPtr->string = new; + entryPtr->string = newStr; entryPtr->numChars -= count; entryPtr->numBytes -= byteCount; if (entryPtr->displayString == string) { - entryPtr->displayString = new; + entryPtr->displayString = newStr; entryPtr->numDisplayBytes = entryPtr->numBytes; } /* * Deleting characters results in the remaining characters being - * renumbered. Update the various indexes into the string to reflect - * this change. + * renumbered. Update the various indexes into the string to reflect this + * change. */ if (entryPtr->selectFirst >= index) { @@ -2249,10 +2202,9 @@ DeleteChars(entryPtr, index, count) * * EntryValueChanged -- * - * This procedure is invoked when characters are inserted into - * an entry or deleted from it. It updates the entry's associated - * variable, if there is one, and does other bookkeeping such - * as arranging for redisplay. + * This function is invoked when characters are inserted into an entry or + * deleted from it. It updates the entry's associated variable, if there + * is one, and does other bookkeeping such as arranging for redisplay. * * Results: * None. @@ -2264,10 +2216,10 @@ DeleteChars(entryPtr, index, count) */ static void -EntryValueChanged(entryPtr, newValue) - Entry *entryPtr; /* Entry whose value just changed. */ - CONST char *newValue; /* If this value is not NULL, we first - * force the value of the entry to this */ +EntryValueChanged( + Entry *entryPtr, /* Entry whose value just changed. */ + CONST char *newValue) /* If this value is not NULL, we first force + * the value of the entry to this. */ { if (newValue != NULL) { EntrySetValue(entryPtr, newValue); @@ -2283,10 +2235,10 @@ EntryValueChanged(entryPtr, newValue) if ((newValue != NULL) && (strcmp(newValue, entryPtr->string) != 0)) { /* * The value of the variable is different than what we asked for. - * This means that a trace on the variable modified it. In this - * case our trace procedure wasn't invoked since the modification - * came while a trace was already active on the variable. So, - * update our value to reflect the variable's latest value. + * This means that a trace on the variable modified it. In this case + * our trace function wasn't invoked since the modification came while + * a trace was already active on the variable. So, update our value to + * reflect the variable's latest value. */ EntrySetValue(entryPtr, newValue); @@ -2306,27 +2258,27 @@ EntryValueChanged(entryPtr, newValue) * * EntrySetValue -- * - * Replace the contents of a text entry with a given value. This - * procedure is invoked when updating the entry from the entry's - * associated variable. + * Replace the contents of a text entry with a given value. This function + * is invoked when updating the entry from the entry's associated + * variable. * * Results: * None. * * Side effects: - * The string displayed in the entry will change. The selection, - * insertion point, and view may have to be adjusted to keep them - * within the bounds of the new string. Note: this procedure does - * *not* update the entry's associated variable, since that could - * result in an infinite loop. + * The string displayed in the entry will change. The selection, + * insertion point, and view may have to be adjusted to keep them within + * the bounds of the new string. Note: this function does *not* update + * the entry's associated variable, since that could result in an + * infinite loop. * *---------------------------------------------------------------------- */ static void -EntrySetValue(entryPtr, value) - Entry *entryPtr; /* Entry whose value is to be changed. */ - CONST char *value; /* New text to display in entry. */ +EntrySetValue( + Entry *entryPtr, /* Entry whose value is to be changed. */ + CONST char *value) /* New text to display in entry. */ { CONST char *oldSource; int valueLen, malloced = 0; @@ -2340,23 +2292,27 @@ EntrySetValue(entryPtr, value) entryPtr->flags |= VALIDATE_ABORT; } else { /* - * If we validate, we create a copy of the value, as it may - * point to volatile memory, like the value of the -textvar - * which may get freed during validation + * If we validate, we create a copy of the value, as it may point to + * volatile memory, like the value of the -textvar which may get freed + * during validation */ + char *tmp = (char *) ckalloc((unsigned) (valueLen + 1)); + strcpy(tmp, value); value = tmp; malloced = 1; entryPtr->flags |= VALIDATE_VAR; - (void) EntryValidateChange(entryPtr, (char *) NULL, value, -1, + (void) EntryValidateChange(entryPtr, NULL, value, -1, VALIDATE_FORCED); entryPtr->flags &= ~VALIDATE_VAR; + /* * If VALIDATE_ABORT has been set, then this operation should be * aborted because the validatecommand did something else instead */ + if (entryPtr->flags & VALIDATE_ABORT) { entryPtr->flags &= ~VALIDATE_ABORT; ckfree((char *)value); @@ -2371,6 +2327,7 @@ EntrySetValue(entryPtr, value) entryPtr->string = value; } else { char *tmp = (char *) ckalloc((unsigned) (valueLen + 1)); + strcpy(tmp, value); entryPtr->string = tmp; } @@ -2411,23 +2368,23 @@ EntrySetValue(entryPtr, value) * * EntryEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on entries. + * This function is invoked by the Tk dispatcher for various events on + * entries. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -EntryEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +EntryEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { Entry *entryPtr = (Entry *) clientData; @@ -2458,34 +2415,33 @@ EntryEventProc(clientData, eventPtr) } switch (eventPtr->type) { - case Expose: - EventuallyRedraw(entryPtr); - entryPtr->flags |= BORDER_NEEDED; - break; - case DestroyNotify: - if (!(entryPtr->flags & ENTRY_DELETED)) { - entryPtr->flags |= (ENTRY_DELETED | VALIDATE_ABORT); - Tcl_DeleteCommandFromToken(entryPtr->interp, - entryPtr->widgetCmd); - if (entryPtr->flags & REDRAW_PENDING) { - Tcl_CancelIdleCall(DisplayEntry, clientData); - } - Tcl_EventuallyFree(clientData, DestroyEntry); - } - break; - case ConfigureNotify: - Tcl_Preserve((ClientData) entryPtr); - entryPtr->flags |= UPDATE_SCROLLBAR; - EntryComputeGeometry(entryPtr); - EventuallyRedraw(entryPtr); - Tcl_Release((ClientData) entryPtr); - break; - case FocusIn: - case FocusOut: - if (eventPtr->xfocus.detail != NotifyInferior) { - EntryFocusProc(entryPtr, (eventPtr->type == FocusIn)); + case Expose: + EventuallyRedraw(entryPtr); + entryPtr->flags |= BORDER_NEEDED; + break; + case DestroyNotify: + if (!(entryPtr->flags & ENTRY_DELETED)) { + entryPtr->flags |= (ENTRY_DELETED | VALIDATE_ABORT); + Tcl_DeleteCommandFromToken(entryPtr->interp, entryPtr->widgetCmd); + if (entryPtr->flags & REDRAW_PENDING) { + Tcl_CancelIdleCall(DisplayEntry, clientData); } - break; + Tcl_EventuallyFree(clientData, DestroyEntry); + } + break; + case ConfigureNotify: + Tcl_Preserve((ClientData) entryPtr); + entryPtr->flags |= UPDATE_SCROLLBAR; + EntryComputeGeometry(entryPtr); + EventuallyRedraw(entryPtr); + Tcl_Release((ClientData) entryPtr); + break; + case FocusIn: + case FocusOut: + if (eventPtr->xfocus.detail != NotifyInferior) { + EntryFocusProc(entryPtr, (eventPtr->type == FocusIn)); + } + break; } } @@ -2494,9 +2450,9 @@ EntryEventProc(clientData, eventPtr) * * EntryCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -2508,20 +2464,20 @@ EntryEventProc(clientData, eventPtr) */ static void -EntryCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +EntryCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { Entry *entryPtr = (Entry *) clientData; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (!(entryPtr->flags & ENTRY_DELETED)) { - Tk_DestroyWindow(entryPtr->tkwin); + Tk_DestroyWindow(entryPtr->tkwin); } } @@ -2530,15 +2486,14 @@ EntryCmdDeletedProc(clientData) * * GetEntryIndex -- * - * Parse an index into an entry and return either its value - * or an error. + * Parse an index into an entry and return either its value or an error. * * Results: - * A standard Tcl result. If all went well, then *indexPtr is - * filled in with the character index (into entryPtr) corresponding to - * string. The index value is guaranteed to lie between 0 and - * the number of characters in the string, inclusive. If an - * error occurs then an error message is left in the interp's result. + * A standard Tcl result. If all went well, then *indexPtr is filled in + * with the character index (into entryPtr) corresponding to string. The + * index value is guaranteed to lie between 0 and the number of + * characters in the string, inclusive. If an error occurs then an error + * message is left in the interp's result. * * Side effects: * None. @@ -2547,13 +2502,12 @@ EntryCmdDeletedProc(clientData) */ static int -GetEntryIndex(interp, entryPtr, string, indexPtr) - Tcl_Interp *interp; /* For error messages. */ - Entry *entryPtr; /* Entry for which the index is being +GetEntryIndex( + Tcl_Interp *interp, /* For error messages. */ + Entry *entryPtr, /* Entry for which the index is being * specified. */ - char *string; /* Specifies character in entryPtr. */ - int *indexPtr; /* Where to store converted character - * index. */ + char *string, /* Specifies character in entryPtr. */ + int *indexPtr) /* Where to store converted character index */ { size_t length; @@ -2563,17 +2517,17 @@ GetEntryIndex(interp, entryPtr, string, indexPtr) if (strncmp(string, "anchor", length) == 0) { *indexPtr = entryPtr->selectAnchor; } else { - badIndex: + badIndex: /* * Some of the paths here leave messages in the interp's result, * so we have to clear it out before storing our own message. */ - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + Tcl_SetResult(interp, NULL, TCL_STATIC); Tcl_AppendResult(interp, "bad ", (entryPtr->type == TK_ENTRY) ? "entry" : "spinbox", - " index \"", string, "\"", (char *) NULL); + " index \"", string, "\"", NULL); return TCL_ERROR; } } else if (string[0] == 'e') { @@ -2590,9 +2544,9 @@ GetEntryIndex(interp, entryPtr, string, indexPtr) } } else if (string[0] == 's') { if (entryPtr->selectFirst < 0) { - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + Tcl_SetResult(interp, NULL, TCL_STATIC); Tcl_AppendResult(interp, "selection isn't in widget ", - Tk_PathName(entryPtr->tkwin), (char *) NULL); + Tk_PathName(entryPtr->tkwin), NULL); return TCL_ERROR; } if (length < 5) { @@ -2625,10 +2579,10 @@ GetEntryIndex(interp, entryPtr, string, indexPtr) x - entryPtr->layoutX, 0); /* - * Special trick: if the x-position was off-screen to the right, - * round the index up to refer to the character just after the - * last visible one on the screen. This is needed to enable the - * last character to be selected, for example. + * Special trick: if the x-position was off-screen to the right, round + * the index up to refer to the character just after the last visible + * one on the screen. This is needed to enable the last character to + * be selected, for example. */ if (roundUp && (*indexPtr < entryPtr->numChars)) { @@ -2642,7 +2596,7 @@ GetEntryIndex(interp, entryPtr, string, indexPtr) *indexPtr = 0; } else if (*indexPtr > entryPtr->numChars) { *indexPtr = entryPtr->numChars; - } + } } return TCL_OK; } @@ -2652,8 +2606,8 @@ GetEntryIndex(interp, entryPtr, string, indexPtr) * * EntryScanTo -- * - * Given a y-coordinate (presumably of the curent mouse location) - * drag the view in the window to implement the scan operation. + * Given a y-coordinate (presumably of the curent mouse location) drag + * the view in the window to implement the scan operation. * * Results: * None. @@ -2665,21 +2619,21 @@ GetEntryIndex(interp, entryPtr, string, indexPtr) */ static void -EntryScanTo(entryPtr, x) - Entry *entryPtr; /* Information about widget. */ - int x; /* X-coordinate to use for scan operation. */ +EntryScanTo( + Entry *entryPtr, /* Information about widget. */ + int x) /* X-coordinate to use for scan operation. */ { int newLeftIndex; /* - * Compute new leftIndex for entry by amplifying the difference - * between the current position and the place where the scan - * started (the "mark" position). If we run off the left or right - * side of the entry, then reset the mark point so that the current - * position continues to correspond to the edge of the window. - * This means that the picture will start dragging as soon as the - * mouse reverses direction (without this reset, might have to slide - * mouse a long ways back before the picture starts moving again). + * Compute new leftIndex for entry by amplifying the difference between + * the current position and the place where the scan started (the "mark" + * position). If we run off the left or right side of the entry, then + * reset the mark point so that the current position continues to + * correspond to the edge of the window. This means that the picture will + * start dragging as soon as the mouse reverses direction (without this + * reset, might have to slide mouse a long ways back before the picture + * starts moving again). */ newLeftIndex = entryPtr->scanMarkIndex @@ -2691,7 +2645,7 @@ EntryScanTo(entryPtr, x) if (newLeftIndex < 0) { newLeftIndex = entryPtr->scanMarkIndex = 0; entryPtr->scanMarkX = x; - } + } if (newLeftIndex != entryPtr->leftIndex) { entryPtr->leftIndex = newLeftIndex; @@ -2710,8 +2664,8 @@ EntryScanTo(entryPtr, x) * * EntrySelectTo -- * - * Modify the selection by moving its un-anchored end. This could - * make the selection either larger or smaller. + * Modify the selection by moving its un-anchored end. This could make + * the selection either larger or smaller. * * Results: * None. @@ -2723,9 +2677,9 @@ EntryScanTo(entryPtr, x) */ static void -EntrySelectTo(entryPtr, index) - Entry *entryPtr; /* Information about widget. */ - int index; /* Character index of element that is to +EntrySelectTo( + Entry *entryPtr, /* Information about widget. */ + int index) /* Character index of element that is to * become the "other" end of the selection. */ { int newFirst, newLast; @@ -2771,15 +2725,15 @@ EntrySelectTo(entryPtr, index) * * EntryFetchSelection -- * - * This procedure is called back by Tk when the selection is - * requested by someone. It returns part or all of the selection - * in a buffer provided by the caller. + * This function is called back by Tk when the selection is requested by + * someone. It returns part or all of the selection in a buffer provided + * by the caller. * * Results: - * The return value is the number of non-NULL bytes stored - * at buffer. Buffer is filled (or partially filled) with a - * NULL-terminated string containing part or all of the selection, - * as given by offset and maxBytes. + * The return value is the number of non-NULL bytes stored at buffer. + * Buffer is filled (or partially filled) with a NULL-terminated string + * containing part or all of the selection, as given by offset and + * maxBytes. * * Side effects: * None. @@ -2788,14 +2742,13 @@ EntrySelectTo(entryPtr, index) */ static int -EntryFetchSelection(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Information about entry widget. */ - int offset; /* Byte offset within selection of first +EntryFetchSelection( + ClientData clientData, /* Information about entry widget. */ + int offset, /* Byte offset within selection of first * character to be returned. */ - char *buffer; /* Location in which to place selection. */ - int maxBytes; /* Maximum number of bytes to place at - * buffer, not including terminating NULL - * character. */ + char *buffer, /* Location in which to place selection. */ + int maxBytes) /* Maximum number of bytes to place at buffer, + * not including terminating NUL character. */ { Entry *entryPtr = (Entry *) clientData; int byteCount; @@ -2826,32 +2779,32 @@ EntryFetchSelection(clientData, offset, buffer, maxBytes) * * EntryLostSelection -- * - * This procedure is called back by Tk when the selection is - * grabbed away from an entry widget. + * This function is called back by Tk when the selection is grabbed away + * from an entry widget. * * Results: * None. * * Side effects: - * The existing selection is unhighlighted, and the window is - * marked as not containing a selection. + * The existing selection is unhighlighted, and the window is marked as + * not containing a selection. * *---------------------------------------------------------------------- */ static void -EntryLostSelection(clientData) - ClientData clientData; /* Information about entry widget. */ +EntryLostSelection( + ClientData clientData) /* Information about entry widget. */ { Entry *entryPtr = (Entry *) clientData; entryPtr->flags &= ~GOT_SELECTION; /* - * On Windows and Mac systems, we want to remember the selection - * for the next time the focus enters the window. On Unix, we need - * to clear the selection since it is always visible. This is - * controlled by ::tk::AlwaysShowSelection. + * On Windows and Mac systems, we want to remember the selection for the + * next time the focus enters the window. On Unix, we need to clear the + * selection since it is always visible. + * This is controlled by ::tk::AlwaysShowSelection. */ if (TkpAlwaysShowSelection(entryPtr->tkwin) @@ -2873,26 +2826,26 @@ EntryLostSelection(clientData) * None. * * Side effects: - * Information gets redisplayed. Right now we don't do selective - * redisplays: the whole window will be redrawn. This doesn't - * seem to hurt performance noticeably, but if it does then this - * could be changed. + * Information gets redisplayed. Right now we don't do selective + * redisplays: the whole window will be redrawn. This doesn't seem to + * hurt performance noticeably, but if it does then this could be + * changed. * *---------------------------------------------------------------------- */ static void -EventuallyRedraw(entryPtr) - Entry *entryPtr; /* Information about widget. */ +EventuallyRedraw( + Entry *entryPtr) /* Information about widget. */ { if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(entryPtr->tkwin)) { return; } /* - * Right now we don't do selective redisplays: the whole window - * will be redrawn. This doesn't seem to hurt performance noticeably, - * but if it does then this could be changed. + * Right now we don't do selective redisplays: the whole window will be + * redrawn. This doesn't seem to hurt performance noticeably, but if it + * does then this could be changed. */ if (!(entryPtr->flags & REDRAW_PENDING)) { @@ -2906,13 +2859,12 @@ EventuallyRedraw(entryPtr) * * EntryVisibleRange -- * - * Return information about the range of the entry that is - * currently visible. + * Return information about the range of the entry that is currently + * visible. * * Results: - * *firstPtr and *lastPtr are modified to hold fractions between - * 0 and 1 identifying the range of characters visible in the - * entry. + * *firstPtr and *lastPtr are modified to hold fractions between 0 and 1 + * identifying the range of characters visible in the entry. * * Side effects: * None. @@ -2921,11 +2873,11 @@ EventuallyRedraw(entryPtr) */ static void -EntryVisibleRange(entryPtr, firstPtr, lastPtr) - Entry *entryPtr; /* Information about widget. */ - double *firstPtr; /* Return position of first visible - * character in widget. */ - double *lastPtr; /* Return position of char just after last +EntryVisibleRange( + Entry *entryPtr, /* Information about widget. */ + double *firstPtr, /* Return position of first visible character + * in widget. */ + double *lastPtr) /* Return position of char just after last * visible one. */ { int charsInWindow; @@ -2956,10 +2908,10 @@ EntryVisibleRange(entryPtr, firstPtr, lastPtr) * * EntryUpdateScrollbar -- * - * This procedure is invoked whenever information has changed in - * an entry in a way that would invalidate a scrollbar display. - * If there is an associated scrollbar, then this procedure updates - * it by invoking a Tcl command. + * This function is invoked whenever information has changed in an entry + * in a way that would invalidate a scrollbar display. If there is an + * associated scrollbar, then this function updates it by invoking a Tcl + * command. * * Results: * None. @@ -2972,10 +2924,10 @@ EntryVisibleRange(entryPtr, firstPtr, lastPtr) */ static void -EntryUpdateScrollbar(entryPtr) - Entry *entryPtr; /* Information about widget. */ +EntryUpdateScrollbar( + Entry *entryPtr) /* Information about widget. */ { - char args[TCL_DOUBLE_SPACE * 2]; + char firstStr[TCL_DOUBLE_SPACE], lastStr[TCL_DOUBLE_SPACE]; int code; double first, last; Tcl_Interp *interp; @@ -2987,8 +2939,10 @@ EntryUpdateScrollbar(entryPtr) interp = entryPtr->interp; Tcl_Preserve((ClientData) interp); EntryVisibleRange(entryPtr, &first, &last); - sprintf(args, " %g %g", first, last); - code = Tcl_VarEval(interp, entryPtr->scrollCmd, args, (char *) NULL); + Tcl_PrintDouble(NULL, first, firstStr); + Tcl_PrintDouble(NULL, last, lastStr); + code = Tcl_VarEval(interp, entryPtr->scrollCmd, " ", firstStr, " ", + lastStr, NULL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (horizontal scrolling command executed by "); @@ -2996,7 +2950,7 @@ EntryUpdateScrollbar(entryPtr) Tcl_AddErrorInfo(interp, ")"); Tcl_BackgroundError(interp); } - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + Tcl_SetResult(interp, NULL, TCL_STATIC); Tcl_Release((ClientData) interp); } @@ -3005,22 +2959,22 @@ EntryUpdateScrollbar(entryPtr) * * EntryBlinkProc -- * - * This procedure is called as a timer handler to blink the - * insertion cursor off and on. + * This function is called as a timer handler to blink the insertion + * cursor off and on. * * Results: * None. * * Side effects: - * The cursor gets turned on or off, redisplay gets invoked, - * and this procedure reschedules itself. + * The cursor gets turned on or off, redisplay gets invoked, and this + * function reschedules itself. * *---------------------------------------------------------------------- */ static void -EntryBlinkProc(clientData) - ClientData clientData; /* Pointer to record describing entry. */ +EntryBlinkProc( + ClientData clientData) /* Pointer to record describing entry. */ { Entry *entryPtr = (Entry *) clientData; @@ -3046,9 +3000,9 @@ EntryBlinkProc(clientData) * * EntryFocusProc -- * - * This procedure is called whenever the entry gets or loses the - * input focus. It's also called whenever the window is reconfigured - * while it has the focus. + * This function is called whenever the entry gets or loses the input + * focus. It's also called whenever the window is reconfigured while it + * has the focus. * * Results: * None. @@ -3060,9 +3014,9 @@ EntryBlinkProc(clientData) */ static void -EntryFocusProc(entryPtr, gotFocus) - Entry *entryPtr; /* Entry that got or lost focus. */ - int gotFocus; /* 1 means window is getting focus, 0 means +EntryFocusProc( + Entry *entryPtr, /* Entry that got or lost focus. */ + int gotFocus) /* 1 means window is getting focus, 0 means * it's losing it. */ { Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler); @@ -3076,7 +3030,7 @@ EntryFocusProc(entryPtr, gotFocus) if (entryPtr->validate == VALIDATE_ALL || entryPtr->validate == VALIDATE_FOCUS || entryPtr->validate == VALIDATE_FOCUSIN) { - EntryValidateChange(entryPtr, (char *) NULL, + EntryValidateChange(entryPtr, NULL, entryPtr->string, -1, VALIDATE_FOCUSIN); } } else { @@ -3085,7 +3039,7 @@ EntryFocusProc(entryPtr, gotFocus) if (entryPtr->validate == VALIDATE_ALL || entryPtr->validate == VALIDATE_FOCUS || entryPtr->validate == VALIDATE_FOCUSOUT) { - EntryValidateChange(entryPtr, (char *) NULL, + EntryValidateChange(entryPtr, NULL, entryPtr->string, -1, VALIDATE_FOCUSOUT); } } @@ -3097,27 +3051,26 @@ EntryFocusProc(entryPtr, gotFocus) * * EntryTextVarProc -- * - * This procedure is invoked when someone changes the variable - * whose contents are to be displayed in an entry. + * This function is invoked when someone changes the variable whose + * contents are to be displayed in an entry. * * Results: * NULL is always returned. * * Side effects: - * The text displayed in the entry will change to match the - * variable. + * The text displayed in the entry will change to match the variable. * *-------------------------------------------------------------- */ /* ARGSUSED */ static char * -EntryTextVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about button. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Not used. */ - CONST char *name2; /* Not used. */ - int flags; /* Information about what happened. */ +EntryTextVarProc( + ClientData clientData, /* Information about button. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + CONST char *name1, /* Not used. */ + CONST char *name2, /* Not used. */ + int flags) /* Information about what happened. */ { Entry *entryPtr = (Entry *) clientData; CONST char *value; @@ -3126,12 +3079,12 @@ EntryTextVarProc(clientData, interp, name1, name2, flags) /* * Just abort early if we entered here while being deleted. */ - return (char *) NULL; + return NULL; } /* - * If the variable is unset, then immediately recreate it unless - * the whole interpreter is going away. + * If the variable is unset, then immediately recreate it unless the whole + * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { @@ -3143,14 +3096,13 @@ EntryTextVarProc(clientData, interp, name1, name2, flags) EntryTextVarProc, clientData); entryPtr->flags |= ENTRY_VAR_TRACED; } - return (char *) NULL; + return NULL; } /* - * Update the entry's text with the value of the variable, unless - * the entry already has that value (this happens when the variable - * changes value because we changed it because someone typed in - * the entry). + * Update the entry's text with the value of the variable, unless the + * entry already has that value (this happens when the variable changes + * value because we changed it because someone typed in the entry). */ value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY); @@ -3158,7 +3110,7 @@ EntryTextVarProc(clientData, interp, name1, name2, flags) value = ""; } EntrySetValue(entryPtr, value); - return (char *) NULL; + return NULL; } /* @@ -3166,25 +3118,25 @@ EntryTextVarProc(clientData, interp, name1, name2, flags) * * EntryValidate -- * - * This procedure is invoked when any character is added or - * removed from the entry widget, or a focus has trigerred validation. + * This function is invoked when any character is added or removed from + * the entry widget, or a focus has trigerred validation. * * Results: - * TCL_OK if the validatecommand passes the new string. - * TCL_BREAK if the vcmd executed OK, but rejects the string. - * TCL_ERROR if an error occurred while executing the vcmd - * or a valid Tcl_Bool is not returned. + + * TCL_OK if the validatecommand passes the new string. TCL_BREAK if the + * vcmd executed OK, but rejects the string. TCL_ERROR if an error + * occurred while executing the vcmd or a valid Tcl_Bool is not returned. * * Side effects: - * An error condition may arise + * An error condition may arise * *-------------------------------------------------------------- */ static int -EntryValidate(entryPtr, cmd) - register Entry *entryPtr; /* Entry that needs validation. */ - register char *cmd; /* Validation command (NULL-terminated +EntryValidate( + register Entry *entryPtr, /* Entry that needs validation. */ + register char *cmd) /* Validation command (NULL-terminated * string). */ { register Tcl_Interp *interp = entryPtr->interp; @@ -3193,9 +3145,10 @@ EntryValidate(entryPtr, cmd) code = Tcl_EvalEx(interp, cmd, -1, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); /* - * We accept TCL_OK and TCL_RETURN as valid return codes from the - * command callback. + * We accept TCL_OK and TCL_RETURN as valid return codes from the command + * callback. */ + if (code != TCL_OK && code != TCL_RETURN) { Tcl_AddErrorInfo(interp, "\n\t(in validation command executed by "); Tcl_AddErrorInfo(interp, Tk_PathName(entryPtr->tkwin)); @@ -3207,8 +3160,9 @@ EntryValidate(entryPtr, cmd) /* * The command callback should return an acceptable Tcl boolean. */ + if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp), - &bool) != TCL_OK) { + &bool) != TCL_OK) { Tcl_AddErrorInfo(interp, "\nvalid boolean not returned by validation command"); Tcl_BackgroundError(interp); @@ -3225,45 +3179,45 @@ EntryValidate(entryPtr, cmd) * * EntryValidateChange -- * - * This procedure is invoked when any character is added or - * removed from the entry widget, or a focus has trigerred validation. + * This function is invoked when any character is added or removed from + * the entry widget, or a focus has trigerred validation. * * Results: - * TCL_OK if the validatecommand accepts the new string, - * TCL_ERROR if any problems occured with validatecommand. + * TCL_OK if the validatecommand accepts the new string, TCL_ERROR if any + * problems occured with validatecommand. * * Side effects: - * The insertion/deletion may be aborted, and the - * validatecommand might turn itself off (if an error - * or loop condition arises). + * The insertion/deletion may be aborted, and the validatecommand might + * turn itself off (if an error or loop condition arises). * *-------------------------------------------------------------- */ static int -EntryValidateChange(entryPtr, change, new, index, type) - register Entry *entryPtr; /* Entry that needs validation. */ - char *change; /* Characters to be added/deleted - * (NULL-terminated string). */ - CONST char *new; /* Potential new value of entry string */ - int index; /* index of insert/delete, -1 otherwise */ - int type; /* forced, delete, insert, - * focusin or focusout */ +EntryValidateChange( + register Entry *entryPtr, /* Entry that needs validation. */ + char *change, /* Characters to be added/deleted + * (NUL-terminated string). */ + CONST char *newValue, /* Potential new value of entry string */ + int index, /* index of insert/delete, -1 otherwise */ + int type) /* forced, delete, insert, focusin or + * focusout */ { int code, varValidate = (entryPtr->flags & VALIDATE_VAR); char *p; Tcl_DString script; - + if (entryPtr->validateCmd == NULL || entryPtr->validate == VALIDATE_NONE) { return (varValidate ? TCL_ERROR : TCL_OK); } /* - * If we're already validating, then we're hitting a loop condition - * Return and set validate to 0 to disallow further validations - * and prevent current validation from finishing + * If we're already validating, then we're hitting a loop condition Return + * and set validate to 0 to disallow further validations and prevent + * current validation from finishing */ + if (entryPtr->flags & VALIDATING) { entryPtr->validate = VALIDATE_NONE; return (varValidate ? TCL_ERROR : TCL_OK); @@ -3277,7 +3231,7 @@ EntryValidateChange(entryPtr, change, new, index, type) Tcl_DStringInit(&script); ExpandPercents(entryPtr, entryPtr->validateCmd, - change, new, index, type, &script); + change, newValue, index, type, &script); Tcl_DStringAppend(&script, "", 1); p = Tcl_DStringValue(&script); @@ -3285,10 +3239,10 @@ EntryValidateChange(entryPtr, change, new, index, type) Tcl_DStringFree(&script); /* - * If e->validate has become VALIDATE_NONE during the validation, or - * we now have VALIDATE_VAR set (from EntrySetValue) and didn't before, - * it means that a loop condition almost occured. Do not allow - * this validation result to finish. + * 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 + * validation result to finish. */ if (entryPtr->validate == VALIDATE_NONE @@ -3297,8 +3251,8 @@ EntryValidateChange(entryPtr, change, new, index, type) } /* - * It's possible that the user deleted the entry during validation. - * In that case, abort future validation and return an error. + * It's possible that the user deleted the entry during validation. In + * that case, abort future validation and return an error. */ if (entryPtr->flags & ENTRY_DELETED) { @@ -3307,20 +3261,19 @@ EntryValidateChange(entryPtr, change, new, index, type) /* * If validate will return ERROR, then disallow further validations - * Otherwise, if it didn't accept the new string (returned TCL_BREAK) - * then eval the invalidCmd (if it's set) + * Otherwise, if it didn't accept the new string (returned TCL_BREAK) then + * eval the invalidCmd (if it's set) */ if (code == TCL_ERROR) { entryPtr->validate = VALIDATE_NONE; } else if (code == TCL_BREAK) { /* - * If we were doing forced validation (like via a variable - * trace) and the command returned 0, the we turn off validation - * because we assume that textvariables have precedence in - * managing the value. We also don't call the invcmd, as it - * may want to do entry manipulation which the setting of the - * var will later wipe anyway. + * If we were doing forced validation (like via a variable trace) and + * the command returned 0, the we turn off validation because we + * assume that textvariables have precedence in managing the value. + * We also don't call the invcmd, as it may want to do entry + * manipulation which the setting of the var will later wipe anyway. */ if (varValidate) { @@ -3328,13 +3281,13 @@ EntryValidateChange(entryPtr, change, new, index, type) } else if (entryPtr->invalidCmd != NULL) { Tcl_DStringInit(&script); ExpandPercents(entryPtr, entryPtr->invalidCmd, - change, new, index, type, &script); + change, newValue, index, type, &script); Tcl_DStringAppend(&script, "", 1); p = Tcl_DStringValue(&script); if (Tcl_EvalEx(entryPtr->interp, p, -1, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT) != TCL_OK) { Tcl_AddErrorInfo(entryPtr->interp, - "\n\t(in invalidcommand executed by entry)"); + "\n\t(in invalidcommand executed by entry)"); Tcl_BackgroundError(entryPtr->interp); code = TCL_ERROR; entryPtr->validate = VALIDATE_NONE; @@ -3342,8 +3295,9 @@ EntryValidateChange(entryPtr, change, new, index, type) Tcl_DStringFree(&script); /* - * It's possible that the user deleted the entry during validation. - * In that case, abort future validation and return an error. + * It's possible that the user deleted the entry during + * validation. In that case, abort future validation and return an + * error. */ if (entryPtr->flags & ENTRY_DELETED) { @@ -3362,13 +3316,12 @@ EntryValidateChange(entryPtr, change, new, index, type) * * ExpandPercents -- * - * Given a command and an event, produce a new command - * by replacing % constructs in the original command - * with information from the X event. + * Given a command and an event, produce a new command by replacing % + * constructs in the original command with information from the X event. * * Results: - * The new expanded command is appended to the dynamic string - * given by dsPtr. + * The new expanded command is appended to the dynamic string given by + * dsPtr. * * Side effects: * None. @@ -3377,18 +3330,18 @@ EntryValidateChange(entryPtr, change, new, index, type) */ static void -ExpandPercents(entryPtr, before, change, new, index, type, dsPtr) - register Entry *entryPtr; /* Entry that needs validation. */ - register CONST char *before; - /* Command containing percent - * expressions to be replaced. */ - char *change; /* Characters to added/deleted - * (NULL-terminated string). */ - CONST char *new; /* Potential new value of entry string */ - int index; /* index of insert/delete */ - int type; /* INSERT or DELETE */ - Tcl_DString *dsPtr; /* Dynamic string in which to append - * new command. */ +ExpandPercents( + register Entry *entryPtr, /* Entry that needs validation. */ + register CONST char *before, + /* Command containing percent expressions to + * be replaced. */ + CONST char *change, /* Characters to added/deleted (NUL-terminated + * string). */ + CONST char *newValue, /* Potential new value of entry string */ + int index, /* index of insert/delete */ + int type, /* INSERT or DELETE */ + Tcl_DString *dsPtr) /* Dynamic string in which to append new + * command. */ { int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl * list element. */ @@ -3402,14 +3355,18 @@ ExpandPercents(entryPtr, before, change, new, index, type, dsPtr) break; } /* - * Find everything up to the next % character and append it - * to the result string. + * Find everything up to the next % character and append it to the + * result string. */ string = before; - /* No need to convert '%', as it is in ascii range */ + + /* + * No need to convert '%', as it is in ascii range. + */ + string = Tcl_UtfFindFirst(before, '%'); - if (string == (char *) NULL) { + if (string == NULL) { Tcl_DStringAppend(dsPtr, before, -1); break; } else if (string != before) { @@ -3418,7 +3375,7 @@ ExpandPercents(entryPtr, before, change, new, index, type, dsPtr) } /* - * There's a percent sequence here. Process it. + * There's a percent sequence here. Process it. */ before++; /* skip over % */ @@ -3431,80 +3388,82 @@ ExpandPercents(entryPtr, before, change, new, index, type, dsPtr) /* * -command %-substitution */ + switch (ch) { - case 's': /* Current string value of spinbox */ - string = entryPtr->string; - break; - case 'd': /* direction, up or down */ - string = change; - break; - case 'W': /* widget name */ - string = Tk_PathName(entryPtr->tkwin); - break; - default: - length = Tcl_UniCharToUtf(ch, numStorage); - numStorage[length] = '\0'; - string = numStorage; - break; + case 's': /* Current string value of spinbox */ + string = entryPtr->string; + break; + case 'd': /* direction, up or down */ + string = change; + break; + case 'W': /* widget name */ + string = Tk_PathName(entryPtr->tkwin); + break; + default: + length = Tcl_UniCharToUtf(ch, numStorage); + numStorage[length] = '\0'; + string = numStorage; + break; } } else { /* * -validatecommand / -invalidcommand %-substitution */ + switch (ch) { - case 'd': /* Type of call that caused validation */ - switch (type) { - case VALIDATE_INSERT: - number = 1; - break; - case VALIDATE_DELETE: - number = 0; - break; - default: - number = -1; - break; - } - sprintf(numStorage, "%d", number); - string = numStorage; - break; - case 'i': /* index of insert/delete */ - sprintf(numStorage, "%d", index); - string = numStorage; + case 'd': /* Type of call that caused validation */ + switch (type) { + case VALIDATE_INSERT: + number = 1; break; - case 'P': /* 'Peeked' new value of the string */ - string = new; + case VALIDATE_DELETE: + number = 0; break; - case 's': /* Current string value of spinbox */ - string = entryPtr->string; - break; - case 'S': /* string to be inserted/deleted, if any */ - string = change; - break; - case 'v': /* type of validation currently set */ - string = validateStrings[entryPtr->validate]; + default: + number = -1; break; - case 'V': /* type of validation in effect */ - switch (type) { - case VALIDATE_INSERT: - case VALIDATE_DELETE: - string = validateStrings[VALIDATE_KEY]; - break; - case VALIDATE_FORCED: - string = "forced"; - break; - default: - string = validateStrings[type]; - break; - } + } + sprintf(numStorage, "%d", number); + string = numStorage; + break; + case 'i': /* index of insert/delete */ + sprintf(numStorage, "%d", index); + string = numStorage; + break; + case 'P': /* 'Peeked' new value of the string */ + string = newValue; + break; + case 's': /* Current string value of spinbox */ + string = entryPtr->string; + break; + case 'S': /* string to be inserted/deleted, if any */ + string = change; + break; + case 'v': /* type of validation currently set */ + string = validateStrings[entryPtr->validate]; + break; + case 'V': /* type of validation in effect */ + switch (type) { + case VALIDATE_INSERT: + case VALIDATE_DELETE: + string = validateStrings[VALIDATE_KEY]; break; - case 'W': /* widget name */ - string = Tk_PathName(entryPtr->tkwin); + case VALIDATE_FORCED: + string = "forced"; break; default: - length = Tcl_UniCharToUtf(ch, numStorage); - numStorage[length] = '\0'; - string = numStorage; + string = validateStrings[type]; break; + } + break; + case 'W': /* widget name */ + string = Tk_PathName(entryPtr->tkwin); + break; + default: + length = Tcl_UniCharToUtf(ch, numStorage); + numStorage[length] = '\0'; + string = numStorage; + break; } } @@ -3523,9 +3482,8 @@ ExpandPercents(entryPtr, before, change, new, index, type, dsPtr) * * Tk_SpinboxObjCmd -- * - * This procedure is invoked to process the "spinbox" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "spinbox" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -3537,11 +3495,11 @@ ExpandPercents(entryPtr, before, change, new, index, type, dsPtr) */ int -Tk_SpinboxObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_SpinboxObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register Entry *entryPtr; register Spinbox *sbPtr; @@ -3555,28 +3513,28 @@ Tk_SpinboxObjCmd(clientData, interp, objc, objv) } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, Tk will return the cached value. + * Create the option table for this widget class. If it has already been + * created, Tk will return the cached value. */ optionTable = Tk_CreateOptionTable(interp, sbOptSpec); /* - * Initialize the fields of the structure that won't be initialized - * by ConfigureEntry, or that ConfigureEntry requires to be - * initialized already (e.g. resource pointers). Only the non-NULL/0 - * data must be initialized as memset covers the rest. + * Initialize the fields of the structure that won't be initialized by + * ConfigureEntry, or that ConfigureEntry requires to be initialized + * already (e.g. resource pointers). Only the non-NULL/0 data must be + * initialized as memset covers the rest. */ sbPtr = (Spinbox *) ckalloc(sizeof(Spinbox)); entryPtr = (Entry *) sbPtr; - memset((VOID *) sbPtr, 0, sizeof(Spinbox)); + memset(sbPtr, 0, sizeof(Spinbox)); entryPtr->tkwin = tkwin; entryPtr->display = Tk_Display(tkwin); @@ -3618,7 +3576,7 @@ Tk_SpinboxObjCmd(clientData, interp, objc, objv) sbPtr->buRelief = TK_RELIEF_FLAT; /* - * Keep a hold of the associated tkwin until we destroy the listbox, + * Keep a hold of the associated tkwin until we destroy the spinbox, * otherwise Tk might free it while we still need it. */ @@ -3640,7 +3598,7 @@ Tk_SpinboxObjCmd(clientData, interp, objc, objv) if (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK) { goto error; } - + Tcl_SetResult(interp, Tk_PathName(entryPtr->tkwin), TCL_STATIC); return TCL_OK; @@ -3654,9 +3612,9 @@ Tk_SpinboxObjCmd(clientData, interp, objc, objv) * * SpinboxWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -3668,11 +3626,11 @@ Tk_SpinboxObjCmd(clientData, interp, objc, objv) */ static int -SpinboxWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about spinbox widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +SpinboxWidgetObjCmd( + ClientData clientData, /* Information about spinbox widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Entry *entryPtr = (Entry *) clientData; Spinbox *sbPtr = (Spinbox *) clientData; @@ -3685,8 +3643,8 @@ SpinboxWidgetObjCmd(clientData, interp, objc, objv) } /* - * Parse the widget command by looking up the second token in - * the list of valid command names. + * Parse the widget command by looking up the second token in the list of + * valid command names. */ result = Tcl_GetIndexFromObj(interp, objv[1], sbCmdNames, @@ -3697,471 +3655,454 @@ SpinboxWidgetObjCmd(clientData, interp, objc, objv) Tcl_Preserve((ClientData) entryPtr); switch ((enum sbCmd) cmdIndex) { - case SB_CMD_BBOX: { - int index, x, y, width, height; - char buf[TCL_INTEGER_SPACE * 4]; + case SB_CMD_BBOX: { + int index, x, y, width, height; + char buf[TCL_INTEGER_SPACE * 4]; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; - } - if ((index == entryPtr->numChars) && (index > 0)) { - index--; - } - Tk_CharBbox(entryPtr->textLayout, index, &x, &y, - &width, &height); - sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX, - y + entryPtr->layoutY, width, height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - break; - } - - case SB_CMD_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); - goto error; - } - - objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, - entryPtr->optionTable, objv[2], entryPtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } - break; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { + goto error; + } + if ((index == entryPtr->numChars) && (index > 0)) { + index--; } + Tk_CharBbox(entryPtr->textLayout, index, &x, &y, + &width, &height); + sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX, + y + entryPtr->layoutY, width, height); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + break; + } - case SB_CMD_CONFIGURE: { - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr, - entryPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - entryPtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } - } else { - result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0); - } - break; + case SB_CMD_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + goto error; } - case SB_CMD_DELETE: { - int first, last; + objPtr = Tk_GetOptionValue(interp, (char *) entryPtr, + entryPtr->optionTable, objv[2], entryPtr->tkwin); + if (objPtr == NULL) { + goto error; + } else { + Tcl_SetObjResult(interp, objPtr); + } + break; - if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); + case SB_CMD_CONFIGURE: + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr, + entryPtr->optionTable, + (objc == 3) ? objv[2] : NULL, + entryPtr->tkwin); + if (objPtr == NULL) { goto error; - } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &first) != TCL_OK) { - goto error; - } - if (objc == 3) { - last = first + 1; } else { - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]), - &last) != TCL_OK) { - goto error; - } - } - if ((last >= first) && (entryPtr->state == STATE_NORMAL)) { - DeleteChars(entryPtr, first, last - first); + Tcl_SetObjResult(interp, objPtr); } - break; + } else { + result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0); } + break; + + case SB_CMD_DELETE: { + int first, last; - case SB_CMD_GET: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &first) != TCL_OK) { + goto error; + } + if (objc == 3) { + last = first + 1; + } else { + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]), + &last) != TCL_OK) { goto error; } - Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1); - break; } + if ((last >= first) && (entryPtr->state == STATE_NORMAL)) { + DeleteChars(entryPtr, first, last - first); + } + break; + } - case SB_CMD_ICURSOR: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "pos"); + case SB_CMD_GET: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + goto error; + } + Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1); + break; + + case SB_CMD_ICURSOR: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "pos"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &entryPtr->insertPos) != TCL_OK) { + goto error; + } + EventuallyRedraw(entryPtr); + break; + + case SB_CMD_IDENTIFY: { + int x, y, elem; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "x y"); + goto error; + } + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || + (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { + goto error; + } + elem = GetSpinboxElement(sbPtr, x, y); + if (elem != SEL_NONE) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), + selElementNames[elem], -1); + } + break; + } + + case SB_CMD_INDEX: { + int index; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "string"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { + goto error; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + break; + } + + case SB_CMD_INSERT: { + int index; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "index text"); + goto error; + } + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { + goto error; + } + if (entryPtr->state == STATE_NORMAL) { + InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + } + break; + } + + case SB_CMD_INVOKE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "elemName"); + goto error; + } + result = Tcl_GetIndexFromObj(interp, objv[2], + selElementNames, "element", 0, &cmdIndex); + if (result != TCL_OK) { + goto error; + } + if (entryPtr->state != STATE_DISABLED) { + if (SpinboxInvoke(interp, sbPtr, cmdIndex) != TCL_OK) { goto error; } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &entryPtr->insertPos) != TCL_OK) { - goto error; - } - EventuallyRedraw(entryPtr); - break; } - - case SB_CMD_IDENTIFY: { - int x, y, elem; + break; + case SB_CMD_SCAN: { + int x; + char *minorCmd; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x"); + goto error; + } + if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { + goto error; + } + + minorCmd = Tcl_GetString(objv[2]); + if (minorCmd[0] == 'm' + && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) { + entryPtr->scanMarkX = x; + entryPtr->scanMarkIndex = entryPtr->leftIndex; + } else if ((minorCmd[0] == 'd') + && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) { + EntryScanTo(entryPtr, x); + } else { + Tcl_AppendResult(interp, "bad scan option \"", + Tcl_GetString(objv[2]), "\": must be mark or dragto", + NULL); + goto error; + } + break; + } + + case SB_CMD_SELECTION: { + int index, index2; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?index?"); + goto error; + } + + /* + * Parse the selection sub-command, using the command table + * "sbSelCmdNames" defined above. + */ + + result = Tcl_GetIndexFromObj(interp, objv[2], sbSelCmdNames, + "selection option", 0, &selIndex); + if (result != TCL_OK) { + goto error; + } + + /* + * Disabled entries don't allow the selection to be modified, but + * 'selection present' must return a boolean. + */ + + if ((entryPtr->state == STATE_DISABLED) + && (selIndex != SB_SEL_PRESENT)) { + goto done; + } + + switch (selIndex) { + case SB_SEL_ADJUST: if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "x y"); + Tcl_WrongNumArgs(interp, 3, objv, "index"); goto error; } - if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || - (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { goto error; } - elem = GetSpinboxElement(sbPtr, x, y); - if (elem != SEL_NONE) { - Tcl_SetStringObj(Tcl_GetObjResult(interp), - selElementNames[elem], -1); + if (entryPtr->selectFirst >= 0) { + int half1, half2; + + half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2; + half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2; + if (index < half1) { + entryPtr->selectAnchor = entryPtr->selectLast; + } else if (index > half2) { + entryPtr->selectAnchor = entryPtr->selectFirst; + } else { + /* + * We're at about the halfway point in the selection; just + * keep the existing anchor. + */ + } } + EntrySelectTo(entryPtr, index); break; - } - - case SB_CMD_INDEX: { - int index; + case SB_SEL_CLEAR: if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "string"); + Tcl_WrongNumArgs(interp, 3, objv, NULL); goto error; } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; + if (entryPtr->selectFirst >= 0) { + entryPtr->selectFirst = -1; + entryPtr->selectLast = -1; + EventuallyRedraw(entryPtr); } - Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); - break; - } - - case SB_CMD_INSERT: { - int index; + goto done; + case SB_SEL_FROM: if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "index text"); + Tcl_WrongNumArgs(interp, 3, objv, "index"); goto error; } - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; - } - if (entryPtr->state == STATE_NORMAL) { - InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { + goto error; } + entryPtr->selectAnchor = index; break; - } - case SB_CMD_INVOKE: { + case SB_SEL_PRESENT: if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "elemName"); + Tcl_WrongNumArgs(interp, 3, objv, NULL); goto error; } - result = Tcl_GetIndexFromObj(interp, objv[2], - selElementNames, "element", 0, &cmdIndex); - if (result != TCL_OK) { + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj((entryPtr->selectFirst >= 0))); + goto done; + + case SB_SEL_RANGE: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "start end"); goto error; } - if (entryPtr->state != STATE_DISABLED) { - if (SpinboxInvoke(interp, sbPtr, cmdIndex) != TCL_OK) { - goto error; - } - } - break; - } - - case SB_CMD_SCAN: { - int x; - char *minorCmd; - - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x"); + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { goto error; } - if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { - goto error; + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[4]),& index2) != TCL_OK) { + goto error; } - - minorCmd = Tcl_GetString(objv[2]); - if (minorCmd[0] == 'm' - && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) { - entryPtr->scanMarkX = x; - entryPtr->scanMarkIndex = entryPtr->leftIndex; - } else if ((minorCmd[0] == 'd') - && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) { - EntryScanTo(entryPtr, x); + if (index >= index2) { + entryPtr->selectFirst = -1; + entryPtr->selectLast = -1; } else { - Tcl_AppendResult(interp, "bad scan option \"", - Tcl_GetString(objv[2]), "\": must be mark or dragto", - (char *) NULL); - goto error; + entryPtr->selectFirst = index; + entryPtr->selectLast = index2; + } + if (!(entryPtr->flags & GOT_SELECTION) + && (entryPtr->exportSelection)) { + Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, + EntryLostSelection, (ClientData) entryPtr); + entryPtr->flags |= GOT_SELECTION; } + EventuallyRedraw(entryPtr); break; - } - - case SB_CMD_SELECTION: { - int index, index2; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option ?index?"); + case SB_SEL_TO: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); goto error; } - - /* - * Parse the selection sub-command, using the command - * table "sbSelCmdNames" defined above. - */ - - result = Tcl_GetIndexFromObj(interp, objv[2], sbSelCmdNames, - "selection option", 0, &selIndex); - if (result != TCL_OK) { - goto error; + if (GetEntryIndex(interp, entryPtr, + Tcl_GetString(objv[3]), &index) != TCL_OK) { + goto error; } + EntrySelectTo(entryPtr, index); + break; - /* - * Disabled entries don't allow the selection to be modified, - * but 'selection present' must return a boolean. - */ - - if ((entryPtr->state == STATE_DISABLED) - && (selIndex != SB_SEL_PRESENT)) { - goto done; + case SB_SEL_ELEMENT: + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 3, objv, "?elemName?"); + goto error; } + if (objc == 3) { + Tcl_SetStringObj(Tcl_GetObjResult(interp), + selElementNames[sbPtr->selElement], -1); + } else { + int lastElement = sbPtr->selElement; - switch (selIndex) { - case SB_SEL_ADJUST: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - if (entryPtr->selectFirst >= 0) { - int half1, half2; - - half1 = (entryPtr->selectFirst - + entryPtr->selectLast)/2; - half2 = (entryPtr->selectFirst - + entryPtr->selectLast + 1)/2; - if (index < half1) { - entryPtr->selectAnchor = entryPtr->selectLast; - } else if (index > half2) { - entryPtr->selectAnchor = entryPtr->selectFirst; - } else { - /* - * We're at about the halfway point in the - * selection; just keep the existing anchor. - */ - } - } - EntrySelectTo(entryPtr, index); - break; - } - - case SB_SEL_CLEAR: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); - goto error; - } - if (entryPtr->selectFirst >= 0) { - entryPtr->selectFirst = -1; - entryPtr->selectLast = -1; - EventuallyRedraw(entryPtr); - } - goto done; - } - - case SB_SEL_FROM: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - entryPtr->selectAnchor = index; - break; - } - - case SB_SEL_PRESENT: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL); - goto error; - } - Tcl_SetObjResult(interp, - Tcl_NewBooleanObj((entryPtr->selectFirst >= 0))); - goto done; + result = Tcl_GetIndexFromObj(interp, objv[3], selElementNames, + "selection element", 0, &(sbPtr->selElement)); + if (result != TCL_OK) { + goto error; } - - case SB_SEL_RANGE: { - if (objc != 5) { - Tcl_WrongNumArgs(interp, 3, objv, "start end"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[4]),& index2) != TCL_OK) { - goto error; - } - if (index >= index2) { - entryPtr->selectFirst = -1; - entryPtr->selectLast = -1; - } else { - entryPtr->selectFirst = index; - entryPtr->selectLast = index2; - } - if (!(entryPtr->flags & GOT_SELECTION) - && (entryPtr->exportSelection)) { - Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, - EntryLostSelection, (ClientData) entryPtr); - entryPtr->flags |= GOT_SELECTION; - } + if (lastElement != sbPtr->selElement) { EventuallyRedraw(entryPtr); - break; - } - - case SB_SEL_TO: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - goto error; - } - if (GetEntryIndex(interp, entryPtr, - Tcl_GetString(objv[3]), &index) != TCL_OK) { - goto error; - } - EntrySelectTo(entryPtr, index); - break; - } - - case SB_SEL_ELEMENT: { - if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 3, objv, "?elemName?"); - goto error; - } - if (objc == 3) { - Tcl_SetStringObj(Tcl_GetObjResult(interp), - selElementNames[sbPtr->selElement], -1); - } else { - int lastElement = sbPtr->selElement; - - result = Tcl_GetIndexFromObj(interp, objv[3], - selElementNames, "selection element", 0, - &(sbPtr->selElement)); - if (result != TCL_OK) { - goto error; - } - if (lastElement != sbPtr->selElement) { - EventuallyRedraw(entryPtr); - } - } - break; } } break; } + break; + } + + case SB_CMD_SET: + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?string?"); + goto error; + } + if (objc == 3) { + EntryValueChanged(entryPtr, Tcl_GetString(objv[2])); + } + Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1); + break; - case SB_CMD_SET: { - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?string?"); - goto error; - } - if (objc == 3) { - EntryValueChanged(entryPtr, Tcl_GetString(objv[2])); - } - Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1); - break; + case SB_CMD_VALIDATE: { + int code; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + goto error; } + selIndex = entryPtr->validate; + entryPtr->validate = VALIDATE_ALL; + code = EntryValidateChange(entryPtr, NULL, entryPtr->string, + -1, VALIDATE_FORCED); + if (entryPtr->validate != VALIDATE_NONE) { + entryPtr->validate = selIndex; + } + Tcl_SetObjResult(interp, Tcl_NewBooleanObj((code == TCL_OK))); + break; + } - case SB_CMD_VALIDATE: { - int code; + case SB_CMD_XVIEW: { + int index; - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + if (objc == 2) { + double first, last; + char buf[TCL_DOUBLE_SPACE]; + + EntryVisibleRange(entryPtr, &first, &last); + Tcl_PrintDouble(NULL, first, buf); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_PrintDouble(NULL, last, buf); + Tcl_AppendResult(interp, " ", buf, NULL); + goto done; + } else if (objc == 3) { + if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), + &index) != TCL_OK) { goto error; } - selIndex = entryPtr->validate; - entryPtr->validate = VALIDATE_ALL; - code = EntryValidateChange(entryPtr, (char *) NULL, - entryPtr->string, -1, VALIDATE_FORCED); - if (entryPtr->validate != VALIDATE_NONE) { - entryPtr->validate = selIndex; - } - Tcl_SetObjResult(interp, Tcl_NewBooleanObj((code == TCL_OK))); - break; - } + } else { + double fraction; + int count; - case SB_CMD_XVIEW: { - int index; - - if (objc == 2) { - double first, last; - char buf[TCL_DOUBLE_SPACE * 2]; - - EntryVisibleRange(entryPtr, &first, &last); - sprintf(buf, "%g %g", first, last); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - goto done; - } else if (objc == 3) { - if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]), - &index) != TCL_OK) { - goto error; - } - } else { - double fraction; - int count; - - index = entryPtr->leftIndex; - switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, - &count)) { - case TK_SCROLL_ERROR: { - goto error; - } - case TK_SCROLL_MOVETO: { - index = (int) ((fraction * entryPtr->numChars) + 0.5); - break; - } - case TK_SCROLL_PAGES: { - int charsPerPage; - - charsPerPage = ((Tk_Width(entryPtr->tkwin) - - 2 * entryPtr->inset - entryPtr->xWidth) - / entryPtr->avgWidth) - 2; - if (charsPerPage < 1) { - charsPerPage = 1; - } - index += count * charsPerPage; - break; - } - case TK_SCROLL_UNITS: { - index += count; - break; - } + index = entryPtr->leftIndex; + switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, + &count)) { + case TK_SCROLL_ERROR: + goto error; + case TK_SCROLL_MOVETO: + index = (int) ((fraction * entryPtr->numChars) + 0.5); + break; + case TK_SCROLL_PAGES: { + int charsPerPage; + + charsPerPage = ((Tk_Width(entryPtr->tkwin) + - 2 * entryPtr->inset - entryPtr->xWidth) + / entryPtr->avgWidth) - 2; + if (charsPerPage < 1) { + charsPerPage = 1; } + index += count * charsPerPage; + break; } - if (index >= entryPtr->numChars) { - index = entryPtr->numChars - 1; + case TK_SCROLL_UNITS: + index += count; + break; } - if (index < 0) { - index = 0; - } - entryPtr->leftIndex = index; - entryPtr->flags |= UPDATE_SCROLLBAR; - EntryComputeGeometry(entryPtr); - EventuallyRedraw(entryPtr); - break; } + if (index >= entryPtr->numChars) { + index = entryPtr->numChars - 1; + } + if (index < 0) { + index = 0; + } + entryPtr->leftIndex = index; + entryPtr->flags |= UPDATE_SCROLLBAR; + EntryComputeGeometry(entryPtr); + EventuallyRedraw(entryPtr); + break; + } } - done: + done: Tcl_Release((ClientData) entryPtr); return result; - error: + error: Tcl_Release((ClientData) entryPtr); return TCL_ERROR; } @@ -4183,11 +4124,10 @@ SpinboxWidgetObjCmd(clientData, interp, objc, objv) */ static int -GetSpinboxElement(sbPtr, x, y) - Spinbox *sbPtr; /* Spinbox for which the index is being +GetSpinboxElement( + Spinbox *sbPtr, /* Spinbox for which the index is being * specified. */ - int x; /* x coord */ - int y; /* y coord */ + int x, int y) /* Widget-relative coordinates. */ { Entry *entryPtr = (Entry *) sbPtr; @@ -4211,25 +4151,25 @@ GetSpinboxElement(sbPtr, x, y) * * SpinboxInvoke -- * - * This procedure is invoked when the invoke method for the - * widget is called. + * This function is invoked when the invoke method for the widget is + * called. * * Results: * TCL_OK. * * Side effects: - * An background error condition may arise when invoking the - * callback. The widget value may change. + * An background error condition may arise when invoking the callback. + * The widget value may change. * *-------------------------------------------------------------- */ static int -SpinboxInvoke(interp, sbPtr, element) - register Tcl_Interp *interp; /* Current interpreter. */ - register Spinbox *sbPtr; /* Spinbox to invoke. */ - int element; /* element to invoke, either the "up" - * or "down" button. */ +SpinboxInvoke( + register Tcl_Interp *interp,/* Current interpreter. */ + register Spinbox *sbPtr, /* Spinbox to invoke. */ + int element) /* Element to invoke, either the "up" or + * "down" button. */ { Entry *entryPtr = (Entry *) sbPtr; char *type; @@ -4237,16 +4177,16 @@ SpinboxInvoke(interp, sbPtr, element) Tcl_DString script; switch (element) { - case SEL_BUTTONUP: - type = "up"; - up = 1; - break; - case SEL_BUTTONDOWN: - type = "down"; - up = 0; - break; - default: - return TCL_OK; + case SEL_BUTTONUP: + type = "up"; + up = 1; + break; + case SEL_BUTTONDOWN: + type = "down"; + up = 0; + break; + default: + return TCL_OK; } if (fabs(sbPtr->increment) > MIN_DBL_VAL) { @@ -4256,11 +4196,11 @@ SpinboxInvoke(interp, sbPtr, element) Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr); if (strcmp(Tcl_GetString(objPtr), entryPtr->string)) { /* - * Somehow the string changed from what we expected, - * so let's do a search on the list to see if the current - * value is there. If not, move to the first element of - * the list. + * Somehow the string changed from what we expected, so let's + * do a search on the list to see if the current value is + * there. If not, move to the first element of the list. */ + int i, listc, elemLen, length = entryPtr->numChars; char *bytes; Tcl_Obj **listv; @@ -4298,45 +4238,46 @@ SpinboxInvoke(interp, sbPtr, element) } else if (!DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)) { double dvalue; - if (Tcl_GetDouble(NULL, entryPtr->string, &dvalue) != TCL_OK) { + if (sscanf(entryPtr->string, "%lf", &dvalue) == 0) { /* - * If the string is empty, or isn't a valid double value, - * just use the -from value + * If the string doesn't scan as a double value, just + * use the -from value */ + dvalue = sbPtr->fromValue; - } else { - if (up) { - dvalue += sbPtr->increment; - if (dvalue > sbPtr->toValue) { - if (sbPtr->wrap) { - dvalue = sbPtr->fromValue; - } else { - dvalue = sbPtr->toValue; - } - } else if (dvalue < sbPtr->fromValue) { - /* - * It's possible that when pressing up, we are - * still less than the fromValue, because the - * user may have manipulated the value by hand. - */ + } else if (up) { + dvalue += sbPtr->increment; + if (dvalue > sbPtr->toValue) { + if (sbPtr->wrap) { dvalue = sbPtr->fromValue; + } else { + dvalue = sbPtr->toValue; } - } else { - dvalue -= sbPtr->increment; - if (dvalue < sbPtr->fromValue) { - if (sbPtr->wrap) { - dvalue = sbPtr->toValue; - } else { - dvalue = sbPtr->fromValue; - } - } else if (dvalue > sbPtr->toValue) { - /* - * It's possible that when pressing down, we are - * still greater than the toValue, because the - * user may have manipulated the value by hand. - */ + } else if (dvalue < sbPtr->fromValue) { + /* + * It's possible that when pressing up, we are still less + * than the fromValue, because the user may have + * manipulated the value by hand. + */ + + dvalue = sbPtr->fromValue; + } + } else { + dvalue -= sbPtr->increment; + if (dvalue < sbPtr->fromValue) { + if (sbPtr->wrap) { dvalue = sbPtr->toValue; + } else { + dvalue = sbPtr->fromValue; } + } else if (dvalue > sbPtr->toValue) { + /* + * It's possible that when pressing down, we are still + * greater than the toValue, because the user may have + * manipulated the value by hand. + */ + + dvalue = sbPtr->toValue; } } sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue); @@ -4357,9 +4298,11 @@ SpinboxInvoke(interp, sbPtr, element) if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n\t(in command executed by spinbox)"); Tcl_BackgroundError(interp); + /* * Yes, it's an error, but a bg one, so we return OK */ + return TCL_OK; } @@ -4374,9 +4317,9 @@ SpinboxInvoke(interp, sbPtr, element) * * ComputeFormat -- * - * This procedure is invoked to recompute the "format" fields - * of a spinbox's widget record, which determines how the value - * of the dial is converted to a string. + * This function is invoked to recompute the "format" fields of a + * spinbox's widget record, which determines how the value of the dial is + * converted to a string. * * Results: * Tcl result code. @@ -4386,17 +4329,18 @@ SpinboxInvoke(interp, sbPtr, element) * *---------------------------------------------------------------------- */ + static int -ComputeFormat(sbPtr) - Spinbox *sbPtr; /* Information about dial widget. */ +ComputeFormat( + Spinbox *sbPtr) /* Information about dial widget. */ { double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; int eDigits, fDigits; /* - * Compute the displacement from the decimal of the most significant - * digit required for any number in the dial's range. + * Compute the displacement from the decimal of the most significant digit + * required for any number in the dial's range. */ if (sbPtr->reqFormat) { @@ -4418,6 +4362,7 @@ ComputeFormat(sbPtr) /* * A increment was specified, so use it. */ + leastSigDigit = (int) floor(log10(sbPtr->increment)); } else { leastSigDigit = 0; @@ -4428,13 +4373,13 @@ ComputeFormat(sbPtr) } /* - * Compute the number of characters required using "e" format and - * "f" format, and then choose whichever one takes fewer characters. + * Compute the number of characters required using "e" format and "f" + * format, and then choose whichever one takes fewer characters. */ eDigits = numDigits + 4; if (numDigits > 1) { - eDigits++; /* Decimal point. */ + eDigits++; /* Decimal point. */ } afterDecimal = numDigits - mostSigDigit - 1; if (afterDecimal < 0) { @@ -4442,10 +4387,10 @@ ComputeFormat(sbPtr) } fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal; if (afterDecimal > 0) { - fDigits++; /* Decimal point. */ + fDigits++; /* Decimal point. */ } if (mostSigDigit < 0) { - fDigits++; /* Zero to left of decimal point. */ + fDigits++; /* Zero to left of decimal point. */ } if (fDigits <= eDigits) { sprintf(sbPtr->digitFormat, "%%.%df", afterDecimal); @@ -4455,3 +4400,11 @@ ComputeFormat(sbPtr) sbPtr->valueFormat = sbPtr->digitFormat; return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkEntry.h b/generic/tkEntry.h index 3bb2f1d..7f8aa1f 100644 --- a/generic/tkEntry.h +++ b/generic/tkEntry.h @@ -1,13 +1,12 @@ /* * tkEntry.h -- - * - * This module defined the structures for the Entry & SpinBox widgets. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * This module defined the structures for the Entry & SpinBox widgets. * - * Copyright (c) 2002 Apple Computer, Inc. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * + * Copyright (c) 2002 Apple Computer, Inc. */ #ifndef _TKENTRY @@ -18,8 +17,8 @@ #endif #ifdef BUILD_tk -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLEXPORT +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT #endif enum EntryType { @@ -27,16 +26,16 @@ enum EntryType { }; /* - * A data structure of the following type is kept for each Entry - * widget managed by this file: + * A data structure of the following type is kept for each Entry widget + * managed by this file: */ typedef struct { - Tk_Window tkwin; /* Window that embodies the entry. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display containing widget. Used, among + Tk_Window tkwin; /* Window that embodies the entry. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up.*/ + Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with entry. */ @@ -48,9 +47,9 @@ typedef struct { /* * Fields that are set by widget commands other than "configure". */ - + CONST char *string; /* Pointer to storage for string; - * NULL-terminated; malloc-ed. */ + * NULL-terminated; malloc-ed. */ int insertPos; /* Character index before which next typed * character will be inserted. */ @@ -58,8 +57,8 @@ typedef struct { * Information about what's selected, if any. */ - int selectFirst; /* Character index of first selected - * character (-1 means nothing selected. */ + int selectFirst; /* Character index of first selected character + * (-1 means nothing selected. */ int selectLast; /* Character index just after last selected * character (-1 means nothing selected. */ int selectAnchor; /* Fixed end of selection (i.e. "select to" @@ -81,11 +80,11 @@ typedef struct { Tk_3DBorder normalBorder; /* Used for drawing border around whole * window, plus used for background. */ - Tk_3DBorder disabledBorder; /* Used for drawing border around whole - * window in disabled state, plus used for + Tk_3DBorder disabledBorder; /* Used for drawing border around whole window + * in disabled state, plus used for * background. */ - Tk_3DBorder readonlyBorder; /* Used for drawing border around whole - * window in readonly state, plus used for + Tk_3DBorder readonlyBorder; /* Used for drawing border around whole window + * in readonly state, plus used for * background. */ int borderWidth; /* Width of 3-D border around window. */ Tk_Cursor cursor; /* Current cursor for window, or None. */ @@ -94,12 +93,12 @@ typedef struct { Tk_Font tkfont; /* Information about text font, or NULL. */ XColor *fgColorPtr; /* Text color in normal mode. */ XColor *dfgColorPtr; /* Text color in disabled mode. */ - XColor *highlightBgColorPtr;/* Color for drawing traversal highlight - * area when highlight is off. */ + XColor *highlightBgColorPtr;/* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ Tk_3DBorder insertBorder; /* Used to draw vertical bar for insertion * cursor. */ int insertBorderWidth; /* Width of 3-D border around insert cursor. */ @@ -115,44 +114,46 @@ typedef struct { * characters. */ int selBorderWidth; /* Width of border around selection. */ XColor *selFgColorPtr; /* Foreground color for selected text. */ - int state; /* Normal or disabled. Entry is read-only - * when disabled. */ - char *textVarName; /* Name of variable (malloc'ed) or NULL. - * If non-NULL, entry's string tracks the - * contents of this variable and vice versa. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ + int state; /* Normal or disabled. Entry is read-only when + * disabled. */ + char *textVarName; /* Name of variable (malloc'ed) or NULL. If + * non-NULL, entry's string tracks the + * contents of this variable and vice + * versa. */ + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ int prefWidth; /* Desired width of window, measured in * average characters. */ char *scrollCmd; /* Command prefix for communicating with - * scrollbar(s). Malloc'ed. NULL means - * no command to issue. */ - char *showChar; /* Value of -show option. If non-NULL, first + * scrollbar(s). Malloc'ed. NULL means no + * command to issue. */ + char *showChar; /* Value of -show option. If non-NULL, first * character is used for displaying all - * characters in entry. Malloc'ed. - * This is only used by the Entry widget. */ + * characters in entry. Malloc'ed. This is + * only used by the Entry widget. */ /* * Fields whose values are derived from the current values of the * configuration settings above. */ - CONST char *displayString; /* String to use when displaying. This may - * be a pointer to string, or a pointer to + CONST char *displayString; /* String to use when displaying. This may be + * a pointer to string, or a pointer to * malloced memory with the same character - * length as string but whose characters - * are all equal to showChar. */ + * length as string but whose characters are + * all equal to showChar. */ int numBytes; /* Length of string in bytes. */ - int numChars; /* Length of string in characters. Both - * string and displayString have the same - * character length, but may have different - * byte lengths due to being made from - * different UTF-8 characters. */ + int numChars; /* Length of string in characters. Both string + * and displayString have the same character + * length, but may have different byte lengths + * due to being made from different UTF-8 + * characters. */ int numDisplayBytes; /* Length of displayString in bytes. */ int inset; /* Number of pixels on the left and right - * sides that are taken up by XPAD, borderWidth - * (if any), and highlightWidth (if any). */ + * sides that are taken up by XPAD, + * borderWidth (if any), and highlightWidth + * (if any). */ Tk_TextLayout textLayout; /* Cached text layout information. */ int layoutX, layoutY; /* Origin for layout. */ int leftX; /* X position at which character at leftIndex @@ -166,23 +167,22 @@ typedef struct { GC selTextGC; /* For drawing selected text. */ GC highlightGC; /* For drawing traversal highlight. */ int avgWidth; /* Width of average character. */ - int xWidth; /* Extra width to reserve for widget. - * Used by spinboxes for button space. */ - int flags; /* Miscellaneous flags; see below for + int xWidth; /* Extra width to reserve for widget. Used by + * spinboxes for button space. */ + int flags; /* Miscellaneous flags; see below for * definitions. */ - int validate; /* Non-zero means try to validate */ - char *validateCmd; /* Command prefix to use when invoking - * validate command. NULL means don't - * invoke commands. Malloc'ed. */ + int validate; /* Non-zero means try to validate */ + char *validateCmd; /* Command prefix to use when invoking + * validate command. NULL means don't invoke + * commands. Malloc'ed. */ char *invalidCmd; /* Command called when a validation returns 0 * (successfully fails), defaults to {}. */ - } Entry; /* - * A data structure of the following type is kept for each spinbox - * widget managed by this file: + * A data structure of the following type is kept for each spinbox widget + * managed by this file: */ typedef struct { @@ -200,8 +200,8 @@ typedef struct { Tk_Cursor bCursor; /* cursor for buttons, or None. */ int bdRelief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ int buRelief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ - char *command; /* Command to invoke for spin buttons. - * NULL means no command to issue. */ + char *command; /* Command to invoke for spin buttons. NULL + * means no command to issue. */ /* * Spinbox specific fields for use with configuration settings above. @@ -216,38 +216,37 @@ typedef struct { int repeatInterval; /* repeat interval */ double fromValue; /* Value corresponding to left/top of dial */ - double toValue; /* Value corresponding to right/bottom - * of dial */ - double increment; /* If > 0, all values are rounded to an - * even multiple of this value. */ + double toValue; /* Value corresponding to right/bottom of + * dial */ + double increment; /* If > 0, all values are rounded to an even + * multiple of this value. */ char *formatBuf; /* string into which to format value. * Malloc'ed. */ char *reqFormat; /* Sprintf conversion specifier used for the - * value that the users requests. Malloc'ed. */ - char *valueFormat; /* Sprintf conversion specifier used for - * the value. */ + * value that the users requests. Malloc'ed */ + char *valueFormat; /* Sprintf conversion specifier used for the + * value. */ char digitFormat[10]; /* Sprintf conversion specifier computed from - * digits and other information; used for - * the value. */ + * digits and other information; used for the + * value. */ char *valueStr; /* Values List. Malloc'ed. */ Tcl_Obj *listObj; /* Pointer to the list object being used */ int eIndex; /* Holds the current index into elements */ int nElements; /* Holds the current count of elements */ - } Spinbox; /* - * Assigned bits of "flags" fields of Entry structures, and what those - * bits mean: + * Assigned bits of "flags" fields of Entry structures, and what those bits + * mean: * * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has * already been queued to redisplay the entry. * BORDER_NEEDED: Non-zero means 3-D border must be redrawn - * around window during redisplay. Normally - * only text portion needs to be redrawn. + * around window during redisplay. Normally only + * text portion needs to be redrawn. * CURSOR_ON: Non-zero means insert cursor is displayed at - * present. 0 means it isn't displayed. + * present. 0 means it isn't displayed. * GOT_FOCUS: Non-zero means this window has the input * focus. * UPDATE_SCROLLBAR: Non-zero means scrollbar should be updated @@ -268,40 +267,40 @@ typedef struct { #define GOT_FOCUS 8 #define UPDATE_SCROLLBAR 0x10 #define GOT_SELECTION 0x20 -#define ENTRY_DELETED 0x40 -#define VALIDATING 0x80 -#define VALIDATE_VAR 0x100 -#define VALIDATE_ABORT 0x200 -#define ENTRY_VAR_TRACED 0x400 +#define ENTRY_DELETED 0x40 +#define VALIDATING 0x80 +#define VALIDATE_VAR 0x100 +#define VALIDATE_ABORT 0x200 +#define ENTRY_VAR_TRACED 0x400 /* - * The following enum is used to define a type for the -state option - * of the Entry widget. These values are used as indices into the - * string table below. + * The following enum is used to define a type for the -state option of the + * Entry widget. These values are used as indices into the string table below. */ enum state { STATE_DISABLED, STATE_NORMAL, STATE_READONLY }; -/* +/* * This is the element index corresponding to the strings in selElementNames. * If you modify them, you must modify the numbers here. */ - + enum selelement { SEL_NONE, SEL_BUTTONDOWN, SEL_BUTTONUP, SEL_NULL, SEL_ENTRY }; /* - * Declaration of procedures used in the implementation of the native side - * of the Entry widget. + * Declaration of functions used in the implementation of the native side of + * the Entry widget. */ -int TkpDrawEntryBorderAndFocus(Entry *entryPtr, Drawable d, int isSpinbox); -int TkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d); +MODULE_SCOPE int TkpDrawEntryBorderAndFocus(Entry *entryPtr, + Drawable d, int isSpinbox); +MODULE_SCOPE int TkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d); -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLIMPORT +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT -#endif /* _TKBUTTON */ +#endif /* _TKENTRY */ diff --git a/generic/tkError.c b/generic/tkError.c index dabf898..6617c37 100644 --- a/generic/tkError.c +++ b/generic/tkError.c @@ -1,109 +1,98 @@ -/* +/* * tkError.c -- * - * This file provides a high-performance mechanism for - * selectively dealing with errors that occur in talking - * to the X server. This is useful, for example, when - * communicating with a window that may not exist. + * This file provides a high-performance mechanism for selectively + * dealing with errors that occur in talking to the X server. This is + * useful, for example, when communicating with a window that may not + * exist. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* - * The default X error handler gets saved here, so that it can - * be invoked if an error occurs that we can't handle. + * The default X error handler gets saved here, so that it can be invoked if + * an error occurs that we can't handle. */ -static int (*defaultHandler) _ANSI_ARGS_((Display *display, - XErrorEvent *eventPtr)) = NULL; - +typedef int (*TkXErrorHandler)(Display *display, XErrorEvent *eventPtr); +static TkXErrorHandler defaultHandler = NULL; /* * Forward references to procedures declared later in this file: */ -static int ErrorProc _ANSI_ARGS_((Display *display, - XErrorEvent *errEventPtr)); +static int ErrorProc(Display *display, XErrorEvent *errEventPtr); /* *-------------------------------------------------------------- * * Tk_CreateErrorHandler -- * - * Arrange for all a given procedure to be invoked whenever - * certain errors occur. + * Arrange for all a given procedure to be invoked whenever certain + * errors occur. * * Results: - * The return value is a token identifying the handler; - * it must be passed to Tk_DeleteErrorHandler to delete the - * handler. + * The return value is a token identifying the handler; it must be passed + * to Tk_DeleteErrorHandler to delete the handler. * * Side effects: - * If an X error occurs that matches the error, request, - * and minor arguments, then errorProc will be invoked. - * ErrorProc should have the following structure: + * If an X error occurs that matches the error, request, and minor + * arguments, then errorProc will be invoked. ErrorProc should have the + * following structure: * * int - * errorProc(clientData, errorEventPtr) - * caddr_t clientData; - * XErrorEvent *errorEventPtr; - * { + * errorProc(caddr_t clientData, XErrorEvent *errorEventPtr) { * } * - * The clientData argument will be the same as the clientData - * argument to this procedure, and errorEvent will describe - * the error. If errorProc returns 0, it means that it - * completely "handled" the error: no further processing - * should be done. If errorProc returns 1, it means that it - * didn't know how to deal with the error, so we should look - * for other error handlers, or invoke the default error - * handler if no other handler returns zero. Handlers are - * invoked in order of age: youngest handler first. + * The clientData argument will be the same as the clientData argument to + * this procedure, and errorEvent will describe the error. If errorProc + * returns 0, it means that it completely "handled" the error: no further + * processing should be done. If errorProc returns 1, it means that it + * didn't know how to deal with the error, so we should look for other + * error handlers, or invoke the default error handler if no other + * handler returns zero. Handlers are invoked in order of age: youngest + * handler first. * - * Note: errorProc will only be called for errors associated - * with X requests made AFTER this call, but BEFORE the handler - * is deleted by calling Tk_DeleteErrorHandler. + * Note: errorProc will only be called for errors associated with X + * requests made AFTER this call, but BEFORE the handler is deleted by + * calling Tk_DeleteErrorHandler. * *-------------------------------------------------------------- */ Tk_ErrorHandler -Tk_CreateErrorHandler(display, error, request, minorCode, errorProc, clientData) - Display *display; /* Display for which to handle +Tk_CreateErrorHandler( + Display *display, /* Display for which to handle errors. */ + int error, /* Consider only errors with this error_code + * (-1 means consider all errors). */ + int request, /* Consider only errors with this major + * request code (-1 means consider all major + * codes). */ + int minorCode, /* Consider only errors with this minor + * request code (-1 means consider all minor + * codes). */ + Tk_ErrorProc *errorProc, /* Procedure to invoke when a matching error + * occurs. NULL means just ignore matching * errors. */ - int error; /* Consider only errors with this - * error_code (-1 means consider - * all errors). */ - int request; /* Consider only errors with this - * major request code (-1 means - * consider all major codes). */ - int minorCode; /* Consider only errors with this - * minor request code (-1 means - * consider all minor codes). */ - Tk_ErrorProc *errorProc; /* Procedure to invoke when a - * matching error occurs. NULL means - * just ignore matching errors. */ - ClientData clientData; /* Arbitrary value to pass to - * errorProc. */ + ClientData clientData) /* Arbitrary value to pass to errorProc. */ { register TkErrorHandler *errorPtr; register TkDisplay *dispPtr; /* - * Find the display. If Tk doesn't know about this display then - * it's an error: panic. + * Find the display. If Tk doesn't know about this display then it's an + * error: panic. */ dispPtr = TkGetDisplay(display); if (dispPtr == NULL) { - panic("Unknown display passed to Tk_CreateErrorHandler"); + Tcl_Panic("Unknown display passed to Tk_CreateErrorHandler"); } /* @@ -144,22 +133,19 @@ Tk_CreateErrorHandler(display, error, request, minorCode, errorProc, clientData) * None. * * Side effects: - * The handler denoted by the "handler" argument will not - * be invoked for any X errors associated with requests - * made after this call. However, if errors arrive later - * for requests made BEFORE this call, then the handler - * will still be invoked. Call XSync if you want to be - * sure that all outstanding errors have been received - * and processed. + * The handler denoted by the "handler" argument will not be invoked for + * any X errors associated with requests made after this call. However, + * if errors arrive later for requests made BEFORE this call, then the + * handler will still be invoked. Call XSync if you want to be sure that + * all outstanding errors have been received and processed. * *-------------------------------------------------------------- */ void -Tk_DeleteErrorHandler(handler) - Tk_ErrorHandler handler; /* Token for handler to delete; - * was previous return value from - * Tk_CreateErrorHandler. */ +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; @@ -167,17 +153,15 @@ Tk_DeleteErrorHandler(handler) errorPtr->lastRequest = NextRequest(dispPtr->display) - 1; /* - * Every once-in-a-while, cleanup handlers that are no longer - * active. We probably won't be able to free the handler that - * was just deleted (need to wait for any outstanding requests to - * be processed by server), but there may be previously-deleted - * handlers that are now ready for garbage collection. To reduce - * the cost of the cleanup, let a few dead handlers pile up, then - * clean them all at once. This adds a bit of overhead to errors - * that might occur while the dead handlers are hanging around, - * but reduces the overhead of scanning the list to clean up - * (particularly if there are many handlers that stay around - * forever). + * Every once-in-a-while, cleanup handlers that are no longer active. We + * probably won't be able to free the handler that was just deleted (need + * to wait for any outstanding requests to be processed by server), but + * there may be previously-deleted handlers that are now ready for garbage + * collection. To reduce the cost of the cleanup, let a few dead handlers + * pile up, then clean them all at once. This adds a bit of overhead to + * errors that might occur while the dead handlers are hanging around, but + * reduces the overhead of scanning the list to clean up (particularly if + * there are many handlers that stay around forever). */ dispPtr->deleteCount += 1; @@ -211,35 +195,33 @@ Tk_DeleteErrorHandler(handler) * * ErrorProc -- * - * This procedure is invoked by the X system when error - * events arrive. + * This procedure is invoked by the X system when error events arrive. * * Results: - * If it returns, the return value is zero. However, - * it is possible that one of the error handlers may - * just exit. + * If it returns, the return value is zero. However, it is possible that + * one of the error handlers may just exit. * * Side effects: - * This procedure does two things. First, it uses the - * serial # in the error event to eliminate handlers whose - * expiration serials are now in the past. Second, it - * invokes any handlers that want to deal with the error. + * This procedure does two things. First, it uses the serial # in the + * error event to eliminate handlers whose expiration serials are now in + * the past. Second, it invokes any handlers that want to deal with the + * error. * *-------------------------------------------------------------- */ static int -ErrorProc(display, errEventPtr) - Display *display; /* Display for which error - * occurred. */ - register XErrorEvent *errEventPtr; /* Information about error. */ +ErrorProc( + Display *display, /* Display for which error occurred. */ + register XErrorEvent *errEventPtr) + /* Information about error. */ { register TkDisplay *dispPtr; register TkErrorHandler *errorPtr; /* - * See if we know anything about the display. If not, then - * invoke the default error handler. + * See if we know anything about the display. If not, then invoke the + * default error handler. */ dispPtr = TkGetDisplay(display); @@ -264,42 +246,47 @@ ErrorProc(display, errEventPtr) && (errorPtr->lastRequest < errEventPtr->serial))) { continue; } - if (errorPtr->errorProc == NULL) { + if (errorPtr->errorProc == NULL || (*errorPtr->errorProc)( + errorPtr->clientData, errEventPtr) == 0) { return 0; - } else { - if ((*errorPtr->errorProc)(errorPtr->clientData, - errEventPtr) == 0) { - return 0; - } } } /* - * See if the error is a BadWindow error. If so, and it refers - * to a window that still exists in our window table, then ignore - * the error. Errors like this can occur if a window owned by us - * is deleted by someone externally, like a window manager. We'll - * ignore the errors at least long enough to clean up internally and - * remove the entry from the window table. + * See if the error is a BadWindow error. If so, and it refers to a window + * that still exists in our window table, then ignore the error. Errors + * like this can occur if a window owned by us is deleted by someone + * externally, like a window manager. We'll ignore the errors at least + * long enough to clean up internally and remove the entry from the window + * table. * - * NOTE: For embedding, we must also check whether the window was - * recently deleted. If so, it may be that Tk generated operations on - * windows that were deleted by the container. Now we are getting - * the errors (BadWindow) after Tk already deleted the window itself. + * NOTE: For embedding, we must also check whether the window was recently + * deleted. If so, it may be that Tk generated operations on windows that + * were deleted by the container. Now we are getting the errors + * (BadWindow) after Tk already deleted the window itself. */ - if ((errEventPtr->error_code == BadWindow) && - ((Tk_IdToWindow(display, (Window) errEventPtr->resourceid) != - NULL) || - (TkpWindowWasRecentlyDeleted((Window) errEventPtr->resourceid, - dispPtr)))) { - return 0; + if (errEventPtr->error_code == BadWindow) { + Window w = (Window) errEventPtr->resourceid; + + if (Tk_IdToWindow(display, w) != NULL + || TkpWindowWasRecentlyDeleted(w, dispPtr)) { + return 0; + } } /* - * We couldn't handle the error. Use the default handler. + * We couldn't handle the error. Use the default handler. */ - couldntHandle: + couldntHandle: return (*defaultHandler)(display, errEventPtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 2b4943f..7c41c22 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -1,69 +1,67 @@ -/* +/* * tkEvent.c -- * - * This file provides basic low-level facilities for managing - * X events in Tk. + * This file provides basic low-level facilities for managing X events in + * Tk. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * Copyright (c) 1998-2000 Ajuba Solutions. + * Copyright (c) 2004 George Peter Staplin * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" -#include <signal.h> /* - * There's a potential problem if a handler is deleted while it's - * current (i.e. its procedure is executing), since Tk_HandleEvent - * will need to read the handler's "nextPtr" field when the procedure - * returns. To handle this problem, structures of the type below - * indicate the next handler to be processed for any (recursively - * nested) dispatches in progress. The nextHandler fields get - * updated if the handlers pointed to are deleted. Tk_HandleEvent - * also needs to know if the entire window gets deleted; the winPtr - * field is set to zero if that particular window gets deleted. + * There's a potential problem if a handler is deleted while it's current + * (i.e. its function is executing), since Tk_HandleEvent will need to read + * the handler's "nextPtr" field when the function returns. To handle this + * problem, structures of the type below indicate the next handler to be + * processed for any (recursively nested) dispatches in progress. The + * nextHandler fields get updated if the handlers pointed to are deleted. + * Tk_HandleEvent also needs to know if the entire window gets deleted; the + * winPtr field is set to zero if that particular window gets deleted. */ typedef struct InProgress { - XEvent *eventPtr; /* Event currently being handled. */ - TkWindow *winPtr; /* Window for event. Gets set to None if - * window is deleted while event is being - * handled. */ - TkEventHandler *nextHandler; /* Next handler in search. */ - struct InProgress *nextPtr; /* Next higher nested search. */ + XEvent *eventPtr; /* Event currently being handled. */ + TkWindow *winPtr; /* Window for event. Gets set to None if + * window is deleted while event is being + * handled. */ + TkEventHandler *nextHandler;/* Next handler in search. */ + struct InProgress *nextPtr; /* Next higher nested search. */ } InProgress; /* - * For each call to Tk_CreateGenericHandler, an instance of the following - * structure will be created. All of the active handlers are linked into a - * list. + * For each call to Tk_CreateGenericHandler or Tk_CreateClientMessageHandler, + * an instance of the following structure will be created. All of the active + * handlers are linked into a list. */ typedef struct GenericHandler { - Tk_GenericProc *proc; /* Procedure to dispatch on all X events. */ - ClientData clientData; /* Client data to pass to procedure. */ - int deleteFlag; /* Flag to set when this handler is deleted. */ + Tk_GenericProc *proc; /* Function to dispatch on all X events. */ + ClientData clientData; /* Client data to pass to function. */ + int deleteFlag; /* Flag to set when this handler is + * deleted. */ struct GenericHandler *nextPtr; /* Next handler in list of all generic * handlers, or NULL for end of list. */ } GenericHandler; /* - * There's a potential problem if Tk_HandleEvent is entered recursively. - * A handler cannot be deleted physically until we have returned from - * calling it. Otherwise, we're looking at unallocated memory in advancing to - * its `next' entry. We deal with the problem by using the `delete flag' and + * There's a potential problem if Tk_HandleEvent is entered recursively. A + * handler cannot be deleted physically until we have returned from calling + * it. Otherwise, we're looking at unallocated memory in advancing to its + * `next' entry. We deal with the problem by using the `delete flag' and * deleting handlers only when it's known that there's no handler active. - * */ /* - * The following structure is used for queueing X-style events on the - * Tcl event queue. + * The following structure is used for queueing X-style events on the Tcl + * event queue. */ typedef struct TkWindowEvent { @@ -75,7 +73,7 @@ typedef struct TkWindowEvent { * Array of event masks corresponding to each X event: */ -static unsigned long eventMasks[TK_LASTEVENT] = { +static unsigned long realEventMasks[MappingNotify+1] = { 0, 0, KeyPressMask, /* KeyPress */ @@ -113,106 +111,694 @@ static unsigned long eventMasks[TK_LASTEVENT] = { 0, /* SelectionNotify */ ColormapChangeMask, /* ColormapNotify */ 0, /* ClientMessage */ - 0, /* Mapping Notify */ + 0 /* Mapping Notify */ +}; + +static unsigned long virtualEventMasks[TK_LASTEVENT-VirtualEvent] = { VirtualEventMask, /* VirtualEvents */ ActivateMask, /* ActivateNotify */ ActivateMask, /* DeactivateNotify */ MouseWheelMask /* MouseWheelEvent */ }; +/* + * For each exit handler created with a call to TkCreateExitHandler or + * TkCreateThreadExitHandler there is a structure of the following type: + */ + +typedef struct ExitHandler { + Tcl_ExitProc *proc; /* Function to call when process exits. */ + ClientData clientData; /* One word of information to pass to proc. */ + struct ExitHandler *nextPtr;/* Next in list of all exit handlers for this + * application, or NULL for end of list. */ +} ExitHandler; /* - * The structure below is used to store Data for the Event module that - * must be kept thread-local. The "dataKey" is used to fetch the - * thread-specific storage for the current thread. + * The structure below is used to store Data for the Event module that must be + * kept thread-local. The "dataKey" is used to fetch the thread-specific + * storage for the current thread. */ typedef struct ThreadSpecificData { - int handlersActive; /* The following variable has a non-zero - * value when a handler is active. */ - InProgress *pendingPtr; /* Topmost search in progress, or - * NULL if none. */ + int handlersActive; /* The following variable has a non-zero value + * when a handler is active. */ + InProgress *pendingPtr; /* Topmost search in progress, or NULL if + * none. */ + + /* + * List of generic handler records. + */ + + GenericHandler *genericList;/* First handler in the list, or NULL. */ + GenericHandler *lastGenericPtr; + /* Last handler in list. */ - GenericHandler *genericList; /* First handler in the list, or NULL. */ - GenericHandler *lastGenericPtr; /* Last handler in list. */ + /* + * List of client message handler records. + */ - GenericHandler *cmList; /* First handler in the list, or NULL. */ + GenericHandler *cmList; /* First handler in the list, or NULL. */ GenericHandler *lastCmPtr; /* Last handler in list. */ /* - * If someone has called Tk_RestrictEvents, the information below - * keeps track of it. + * If someone has called Tk_RestrictEvents, the information below keeps + * track of it. */ Tk_RestrictProc *restrictProc; - /* Procedure to call. NULL means no + /* Function to call. NULL means no * restrictProc is currently in effect. */ ClientData restrictArg; /* Argument to pass to restrictProc. */ + ExitHandler *firstExitPtr; /* First in list of all exit handlers for this + * thread. */ + int inExit; /* True when this thread is exiting. This is + * used as a hack to decide to close the + * standard channels. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Prototypes for procedures that are only referenced locally within - * this file. + * There are both per-process and per-thread exit handlers. The first list is + * controlled by a mutex. The other is in thread local storage. + */ + +static ExitHandler *firstExitPtr = NULL; + /* First in list of all exit handlers for + * application. */ +TCL_DECLARE_MUTEX(exitMutex) + +/* + * Prototypes for functions that are only referenced locally within this file. + */ + +static void CleanUpTkEvent(XEvent *eventPtr); +static void DelayedMotionProc(ClientData clientData); +static int GetButtonMask(unsigned int Button); +static unsigned long GetEventMaskFromXEvent(XEvent *eventPtr); +static TkWindow * GetTkWindowFromXEvent(XEvent *eventPtr); +static void InvokeClientMessageHandlers(ThreadSpecificData *tsdPtr, + Tk_Window tkwin, XEvent *eventPtr); +static int InvokeFocusHandlers(TkWindow **winPtrPtr, + unsigned long mask, XEvent *eventPtr); +static int InvokeGenericHandlers(ThreadSpecificData *tsdPtr, + XEvent *eventPtr); +static int InvokeMouseHandlers(TkWindow *winPtr, + unsigned long mask, XEvent *eventPtr); +static Window ParentXId(Display *display, Window w); +static int RefreshKeyboardMappingIfNeeded(XEvent *eventPtr); +static int TkXErrorHandler(ClientData clientData, + XErrorEvent *errEventPtr); +static void UpdateButtonEventState(XEvent *eventPtr); +static int WindowEventProc(Tcl_Event *evPtr, int flags); +#ifdef TK_USE_INPUT_METHODS +static void CreateXIC(TkWindow *winPtr); +#endif /* TK_USE_INPUT_METHODS */ + +/* + *---------------------------------------------------------------------- + * + * InvokeFocusHandlers -- + * + * Call focus-related code to look at FocusIn, FocusOut, Enter, and Leave + * events; depending on its return value, ignore the event. + * + * Results: + * 0 further processing can be done on the event. + * 1 we are done with the event passed. + * + * Side effects: + * The *winPtrPtr in the caller may be changed to the TkWindow for the + * window with focus. + * + *---------------------------------------------------------------------- + */ + +static int +InvokeFocusHandlers( + TkWindow **winPtrPtr, + unsigned long mask, + XEvent *eventPtr) +{ + if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask)) + && (TkFocusFilterEvent(*winPtrPtr, eventPtr) == 0)) { + return 1; + } + + /* + * MouseWheel events are not focus specific on Mac OS X. + */ + +#ifdef MAC_OSX_TK +#define FOCUS_DIRECTED_EVENT_MASK (KeyPressMask|KeyReleaseMask) +#else +#define FOCUS_DIRECTED_EVENT_MASK (KeyPressMask|KeyReleaseMask|MouseWheelMask) +#endif + + if (mask & FOCUS_DIRECTED_EVENT_MASK) { + (*winPtrPtr)->dispPtr->lastEventTime = eventPtr->xkey.time; + *winPtrPtr = TkFocusKeyEvent(*winPtrPtr, eventPtr); + if (*winPtrPtr == NULL) { + return 1; + } + } + + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * InvokeMouseHandlers -- + * + * Call a grab-related function to do special processing on pointer + * events. + * + * Results: + * 0 further processing can be done on the event. + * 1 we are done with the event passed. + * + * Side effects: + * New events may be queued from TkPointerEvent and grabs may be added + * and/or removed. The eventPtr may be changed by TkPointerEvent in some + * cases. + * + *---------------------------------------------------------------------- + */ + +static int +InvokeMouseHandlers( + TkWindow *winPtr, + unsigned long mask, + XEvent *eventPtr) +{ + if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask + |EnterWindowMask|LeaveWindowMask)) { + + if (mask & (ButtonPressMask|ButtonReleaseMask)) { + winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time; + } else if (mask & PointerMotionMask) { + winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time; + } else { + winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time; + } + + if (TkPointerEvent(eventPtr, winPtr) == 0) { + /* + * The event should be ignored to make grab work correctly (as the + * comment for TkPointerEvent states). + */ + + return 1; + } + } + + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * CreateXIC -- + * + * Create the X input context for our winPtr. + * XIM is only ever enabled on Unix. + * + *---------------------------------------------------------------------- + */ + +#if defined(TK_USE_INPUT_METHODS) +static void +CreateXIC( + TkWindow *winPtr) +{ + TkDisplay *dispPtr = winPtr->dispPtr; + long im_event_mask = 0L; + const char *preedit_attname = NULL; + XVaNestedList preedit_attlist = NULL; + + if (dispPtr->inputStyle & XIMPreeditPosition) { + XPoint spot = {0, 0}; + + preedit_attname = XNPreeditAttributes; + preedit_attlist = XVaCreateNestedList(0, + XNSpotLocation, &spot, + XNFontSet, dispPtr->inputXfs, + (void *) NULL); + } + + winPtr->inputContext = XCreateIC(dispPtr->inputMethod, + XNInputStyle, dispPtr->inputStyle, + XNClientWindow, winPtr->window, + XNFocusWindow, winPtr->window, + preedit_attname, preedit_attlist, + (void *) NULL); + + if (preedit_attlist) { + XFree(preedit_attlist); + } + + + if (winPtr->inputContext == NULL) { + /* XCreateIC failed. */ + return; + } + + /* + * Adjust the window's event mask if the IM requires it. + */ + XGetICValues(winPtr->inputContext, XNFilterEvents, &im_event_mask, (void *) NULL); + if ((winPtr->atts.event_mask & im_event_mask) != im_event_mask) { + winPtr->atts.event_mask |= im_event_mask; + XSelectInput(winPtr->display, winPtr->window, winPtr->atts.event_mask); + } +} +#endif + +/* + *---------------------------------------------------------------------- + * + * GetTkWindowFromXEvent -- + * + * Attempt to find which TkWindow is associated with an event. If it + * fails we attempt to get the TkWindow from the parent for a property + * notification. + * + * Results: + * The TkWindow associated with the event or NULL. + * + * Side effects: + * TkSelPropProc may influence selection on windows not known to Tk. + * + *---------------------------------------------------------------------- + */ + +static TkWindow * +GetTkWindowFromXEvent( + XEvent *eventPtr) +{ + TkWindow *winPtr; + Window parentXId, handlerWindow = eventPtr->xany.window; + + if ((eventPtr->xany.type == StructureNotifyMask) + && (eventPtr->xmap.event != eventPtr->xmap.window)) { + handlerWindow = eventPtr->xmap.event; + } + + winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow); + + if (winPtr == NULL) { + /* + * There isn't a TkWindow structure for this window. However, if the + * event is a PropertyNotify event then call the selection manager (it + * deals beneath-the-table with certain properties). Also, if the + * window's parent is a Tk window that has the TK_PROP_PROPCHANGE flag + * set, then we must propagate the PropertyNotify event up to the + * parent. + */ + + if (eventPtr->type != PropertyNotify) { + return NULL; + } + TkSelPropProc(eventPtr); + parentXId = ParentXId(eventPtr->xany.display, handlerWindow); + if (parentXId == None) { + return NULL; + } + winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId); + if (winPtr == NULL) { + return NULL; + } + if (!(winPtr->flags & TK_PROP_PROPCHANGE)) { + return NULL; + } + } + return winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * GetEventMaskFromXEvent -- + * + * The event type is looked up in our eventMasks tables, and may be + * changed to a different mask depending on the state of the event and + * window members. + * + * Results: + * The mask for the event. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static unsigned long +GetEventMaskFromXEvent( + XEvent *eventPtr) +{ + unsigned long mask; + + /* + * Get the event mask from the correct table. Note that there are two + * tables here because that means we no longer need this code to rely on + * the exact value of VirtualEvent, which has caused us problems in the + * past when X11 changed the value of LASTEvent. [Bug ???] + */ + + if (eventPtr->xany.type <= MappingNotify) { + mask = realEventMasks[eventPtr->xany.type]; + } else if (eventPtr->xany.type >= VirtualEvent + && eventPtr->xany.type<TK_LASTEVENT) { + mask = virtualEventMasks[eventPtr->xany.type - VirtualEvent]; + } else { + mask = 0; + } + + /* + * Events selected by StructureNotify require special handling. They look + * the same as those selected by SubstructureNotify. The only difference + * is whether the "event" and "window" fields are the same. Compare the + * two fields and convert StructureNotify to SubstructureNotify if + * necessary. + */ + + if (mask == StructureNotifyMask) { + if (eventPtr->xmap.event != eventPtr->xmap.window) { + mask = SubstructureNotifyMask; + } + } + return mask; +} + +/* + *---------------------------------------------------------------------- + * + * RefreshKeyboardMappingIfNeeded -- + * + * If the event is a MappingNotify event, find its display and refresh + * the keyboard mapping information for the display. + * + * Results: + * 0 if the event was not a MappingNotify event + * 1 if the event was a MappingNotify event + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +RefreshKeyboardMappingIfNeeded( + XEvent *eventPtr) +{ + TkDisplay *dispPtr; + + if (eventPtr->type == MappingNotify) { + dispPtr = TkGetDisplay(eventPtr->xmapping.display); + if (dispPtr != NULL) { + XRefreshKeyboardMapping(&eventPtr->xmapping); + dispPtr->bindInfoStale = 1; + } + return 1; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * GetButtonMask -- + * + * Return the proper Button${n}Mask for the button. + * + * Results: + * A button mask. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +GetButtonMask( + unsigned int button) +{ + switch (button) { + case 1: + return Button1Mask; + case 2: + return Button2Mask; + case 3: + return Button3Mask; + case 4: + return Button4Mask; + case 5: + return Button5Mask; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateButtonEventState -- + * + * Update the button event state in our TkDisplay using the XEvent + * passed. We also may modify the the XEvent passed to fit some aspects + * of our TkDisplay. + * + * Results: + * None. + * + * Side effects: + * The TkDisplay's private button state may be modified. The eventPtr's + * state may be updated to reflect masks stored in our TkDisplay that the + * event doesn't contain. The eventPtr may also be modified to not + * contain a button state for the window in which it was not pressed in. + * + *---------------------------------------------------------------------- */ -static void DelayedMotionProc _ANSI_ARGS_((ClientData clientData)); -static int WindowEventProc _ANSI_ARGS_((Tcl_Event *evPtr, - int flags)); -static int TkXErrorHandler _ANSI_ARGS_((ClientData clientData, - XErrorEvent *errEventPtr)); +static void +UpdateButtonEventState( + XEvent *eventPtr) +{ + TkDisplay *dispPtr; + int allButtonsMask = Button1Mask | Button2Mask | Button3Mask + | Button4Mask | Button5Mask; + switch (eventPtr->type) { + case ButtonPress: + dispPtr = TkGetDisplay(eventPtr->xbutton.display); + dispPtr->mouseButtonWindow = eventPtr->xbutton.window; + eventPtr->xbutton.state |= dispPtr->mouseButtonState; + + dispPtr->mouseButtonState |= GetButtonMask(eventPtr->xbutton.button); + break; + + case ButtonRelease: + dispPtr = TkGetDisplay(eventPtr->xbutton.display); + dispPtr->mouseButtonWindow = None; + dispPtr->mouseButtonState &= ~GetButtonMask(eventPtr->xbutton.button); + eventPtr->xbutton.state |= dispPtr->mouseButtonState; + break; + + case MotionNotify: + dispPtr = TkGetDisplay(eventPtr->xmotion.display); + if (dispPtr->mouseButtonState & allButtonsMask) { + if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) { + /* + * This motion event should not be interpreted as a button + * press + motion event since this is not the same window the + * button was pressed down in. + */ + + dispPtr->mouseButtonState &= ~allButtonsMask; + dispPtr->mouseButtonWindow = None; + } else { + eventPtr->xmotion.state |= dispPtr->mouseButtonState; + } + } + break; + } +} /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- + * + * InvokeClientMessageHandlers -- + * + * Iterate the list of handlers and invoke the function pointer for each. + * + * Results: + * None. + * + * Side effects: + * Handlers may be deleted and events may be sent to handlers. + * + *---------------------------------------------------------------------- + */ + +static void +InvokeClientMessageHandlers( + ThreadSpecificData *tsdPtr, + Tk_Window tkwin, + XEvent *eventPtr) +{ + GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->cmList; + + for (prevPtr = NULL; curPtr != NULL; ) { + if (curPtr->deleteFlag) { + if (!tsdPtr->handlersActive) { + /* + * This handler needs to be deleted and there are no calls + * pending through any handlers, so now is a safe time to + * delete it. + */ + + tmpPtr = curPtr->nextPtr; + if (prevPtr == NULL) { + tsdPtr->cmList = tmpPtr; + } else { + prevPtr->nextPtr = tmpPtr; + } + if (tmpPtr == NULL) { + tsdPtr->lastCmPtr = prevPtr; + } + (void) ckfree((char *) curPtr); + curPtr = tmpPtr; + continue; + } + } else { + int done; + + tsdPtr->handlersActive++; + done = (*(Tk_ClientMessageProc *)curPtr->proc)(tkwin, eventPtr); + tsdPtr->handlersActive--; + if (done) { + break; + } + } + prevPtr = curPtr; + curPtr = curPtr->nextPtr; + } +} + +/* + *---------------------------------------------------------------------- + * + * InvokeGenericHandlers -- + * + * Iterate the list of handlers and invoke the function pointer for each. + * If the handler invoked returns a non-zero value then we are done. + * + * Results: + * 0 when the event wasn't handled by a handler. Non-zero when it was + * processed and handled by a handler. + * + * Side effects: + * Handlers may be deleted and events may be sent to handlers. + * + *---------------------------------------------------------------------- + */ + +static int +InvokeGenericHandlers( + ThreadSpecificData *tsdPtr, + XEvent *eventPtr) +{ + GenericHandler *prevPtr, *tmpPtr, *curPtr = tsdPtr->genericList; + + for (prevPtr = NULL; curPtr != NULL; ) { + if (curPtr->deleteFlag) { + if (!tsdPtr->handlersActive) { + /* + * This handler needs to be deleted and there are no calls + * pending through the handler, so now is a safe time to + * delete it. + */ + + tmpPtr = curPtr->nextPtr; + if (prevPtr == NULL) { + tsdPtr->genericList = tmpPtr; + } else { + prevPtr->nextPtr = tmpPtr; + } + if (tmpPtr == NULL) { + tsdPtr->lastGenericPtr = prevPtr; + } + (void) ckfree((char *) curPtr); + curPtr = tmpPtr; + continue; + } + } else { + int done; + + tsdPtr->handlersActive++; + done = (*curPtr->proc)(curPtr->clientData, eventPtr); + tsdPtr->handlersActive--; + if (done) { + return done; + } + } + prevPtr = curPtr; + curPtr = curPtr->nextPtr; + } + return 0; +} + +/* + *---------------------------------------------------------------------- * * Tk_CreateEventHandler -- * - * Arrange for a given procedure to be invoked whenever - * events from a given class occur in a given window. + * Arrange for a given function to be invoked whenever events from a + * given class occur in a given window. * * Results: * None. * * Side effects: - * From now on, whenever an event of the type given by - * mask occurs for token and is processed by Tk_HandleEvent, - * proc will be called. See the manual entry for details - * of the calling sequence and return value for proc. + * From now on, whenever an event of the type given by mask occurs for + * token and is processed by Tk_HandleEvent, proc will be called. See the + * manual entry for details of the calling sequence and return value for + * proc. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_CreateEventHandler(token, mask, proc, clientData) - Tk_Window token; /* Token for window in which to - * create handler. */ - unsigned long mask; /* Events for which proc should - * be called. */ - Tk_EventProc *proc; /* Procedure to call for each - * selected event */ - ClientData clientData; /* Arbitrary data to pass to proc. */ +Tk_CreateEventHandler( + Tk_Window token, /* Token for window in which to create + * handler. */ + unsigned long mask, /* Events for which proc should be called. */ + Tk_EventProc *proc, /* Function to call for each selected event */ + ClientData clientData) /* Arbitrary data to pass to proc. */ { register TkEventHandler *handlerPtr; register TkWindow *winPtr = (TkWindow *) token; - int found; /* - * Skim through the list of existing handlers to (a) compute the - * overall event mask for the window (so we can pass this new - * value to the X system) and (b) see if there's already a handler - * declared with the same callback and clientData (if so, just - * change the mask). If no existing handler matches, then create - * a new handler. + * Skim through the list of existing handlers to (a) compute the overall + * event mask for the window (so we can pass this new value to the X + * system) and (b) see if there's already a handler declared with the same + * callback and clientData (if so, just change the mask). If no existing + * handler matches, then create a new handler. */ - found = 0; if (winPtr->handlerList == NULL) { - handlerPtr = (TkEventHandler *) ckalloc( - (unsigned) sizeof(TkEventHandler)); + /* + * No event handlers defined at all, so must create. + */ + + handlerPtr = (TkEventHandler *) ckalloc(sizeof(TkEventHandler)); winPtr->handlerList = handlerPtr; - goto initHandler; } else { + int found = 0; + for (handlerPtr = winPtr->handlerList; ; handlerPtr = handlerPtr->nextPtr) { if ((handlerPtr->proc == proc) @@ -224,31 +810,43 @@ Tk_CreateEventHandler(token, mask, proc, clientData) break; } } - } - /* - * Create a new handler if no matching old handler was found. - */ + /* + * If we found anything, we're done because we do not need to use + * XSelectInput; Tk always selects on all events anyway in order to + * support binding on classes, 'all' and other bind-tags. + */ + + if (found) { + return; + } + + /* + * No event handler matched, so create a new one. + */ - if (!found) { handlerPtr->nextPtr = (TkEventHandler *) ckalloc(sizeof(TkEventHandler)); handlerPtr = handlerPtr->nextPtr; - initHandler: - handlerPtr->mask = mask; - handlerPtr->proc = proc; - handlerPtr->clientData = clientData; - handlerPtr->nextPtr = NULL; } /* - * No need to call XSelectInput: Tk always selects on all events - * for all windows (needed to support bindings on classes and "all"). + * Initialize the new event handler. + */ + + handlerPtr->mask = mask; + handlerPtr->proc = proc; + handlerPtr->clientData = clientData; + handlerPtr->nextPtr = NULL; + + /* + * No need to call XSelectInput: Tk always selects on all events for all + * windows (needed to support bindings on classes and "all"). */ } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * Tk_DeleteEventHandler -- * @@ -258,30 +856,29 @@ Tk_CreateEventHandler(token, mask, proc, clientData) * None. * * Side effects: - * If there existed a handler as described by the - * parameters, the handler is deleted so that proc - * will not be invoked again. + * If there existed a handler as described by the parameters, the handler + * is deleted so that proc will not be invoked again. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_DeleteEventHandler(token, mask, proc, clientData) - Tk_Window token; /* Same as corresponding arguments passed */ - unsigned long mask; /* previously to Tk_CreateEventHandler. */ - Tk_EventProc *proc; - ClientData clientData; +Tk_DeleteEventHandler( + Tk_Window token, /* Same as corresponding arguments passed */ + unsigned long mask, /* previously to Tk_CreateEventHandler. */ + Tk_EventProc *proc, + ClientData clientData) { register TkEventHandler *handlerPtr; register InProgress *ipPtr; TkEventHandler *prevPtr; register TkWindow *winPtr = (TkWindow *) token; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * Find the event handler to be deleted, or return - * immediately if it doesn't exist. + * Find the event handler to be deleted, or return immediately if it + * doesn't exist. */ for (handlerPtr = winPtr->handlerList, prevPtr = NULL; ; @@ -296,8 +893,8 @@ Tk_DeleteEventHandler(token, mask, proc, clientData) } /* - * If Tk_HandleEvent is about to process this handler, tell it to - * process the next one instead. + * If Tk_HandleEvent is about to process this handler, tell it to process + * the next one instead. */ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { @@ -317,43 +914,42 @@ Tk_DeleteEventHandler(token, mask, proc, clientData) } ckfree((char *) handlerPtr); - /* - * No need to call XSelectInput: Tk always selects on all events - * for all windows (needed to support bindings on classes and "all"). + * No need to call XSelectInput: Tk always selects on all events for all + * windows (needed to support bindings on classes and "all"). */ } -/*-------------------------------------------------------------- +/*---------------------------------------------------------------------- * * Tk_CreateGenericHandler -- * - * Register a procedure to be called on each X event, regardless - * of display or window. Generic handlers are useful for capturing - * events that aren't associated with windows, or events for windows - * not managed by Tk. + * Register a function to be called on each X event, regardless of + * display or window. Generic handlers are useful for capturing events + * that aren't associated with windows, or events for windows not managed + * by Tk. * * Results: * None. * * Side Effects: - * From now on, whenever an X event is given to Tk_HandleEvent, - * invoke proc, giving it clientData and the event as arguments. + * From now on, whenever an X event is given to Tk_HandleEvent, invoke + * proc, giving it clientData and the event as arguments. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_CreateGenericHandler(proc, clientData) - Tk_GenericProc *proc; /* Procedure to call on every event. */ - ClientData clientData; /* One-word value to pass to proc. */ +Tk_CreateGenericHandler( + Tk_GenericProc *proc, /* Function to call on every event. */ + ClientData clientData) /* One-word value to pass to proc. */ { GenericHandler *handlerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler)); - + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + handlerPtr = (GenericHandler *) ckalloc(sizeof(GenericHandler)); + handlerPtr->proc = proc; handlerPtr->clientData = clientData; handlerPtr->deleteFlag = 0; @@ -367,7 +963,7 @@ Tk_CreateGenericHandler(proc, clientData) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * Tk_DeleteGenericHandler -- * @@ -377,77 +973,76 @@ Tk_CreateGenericHandler(proc, clientData) * None. * * Side Effects: - * If there existed a handler as described by the parameters, - * that handler is logically deleted so that proc will not be - * invoked again. The physical deletion happens in the event - * loop in Tk_HandleEvent. + * If there existed a handler as described by the parameters, that + * handler is logically deleted so that proc will not be invoked again. + * The physical deletion happens in the event loop in Tk_HandleEvent. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_DeleteGenericHandler(proc, clientData) - Tk_GenericProc *proc; - ClientData clientData; +Tk_DeleteGenericHandler( + Tk_GenericProc *proc, + ClientData clientData) { GenericHandler * handler; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - for (handler = tsdPtr->genericList; handler; handler = handler->nextPtr) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + for (handler=tsdPtr->genericList ; handler ; handler=handler->nextPtr) { if ((handler->proc == proc) && (handler->clientData == clientData)) { handler->deleteFlag = 1; } } } -/*-------------------------------------------------------------- +/*---------------------------------------------------------------------- * * Tk_CreateClientMessageHandler -- * - * Register a procedure to be called on each ClientMessage event. + * Register a function to be called on each ClientMessage event. * ClientMessage handlers are useful for Drag&Drop extensions. * * Results: * None. * * Side Effects: - * From now on, whenever a ClientMessage event is received that isn't - * a WM_PROTOCOL event or SelectionEvent, invoke proc, giving it - * tkwin and the event as arguments. + * From now on, whenever a ClientMessage event is received that isn't a + * WM_PROTOCOL event or SelectionEvent, invoke proc, giving it tkwin and + * the event as arguments. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_CreateClientMessageHandler(proc) - Tk_ClientMessageProc *proc; /* Procedure to call on event. */ +Tk_CreateClientMessageHandler( + Tk_ClientMessageProc *proc) /* Function to call on event. */ { GenericHandler *handlerPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * We use a GenericHandler struct, because it's basically the same, - * except with an extra clientData field we'll never use. + * We use a GenericHandler struct, because it's basically the same, except + * with an extra clientData field we'll never use. */ - handlerPtr = (GenericHandler *) - ckalloc (sizeof (GenericHandler)); - handlerPtr->proc = (Tk_GenericProc *) proc; - handlerPtr->clientData = NULL; /* never used */ - handlerPtr->deleteFlag = 0; - handlerPtr->nextPtr = NULL; + handlerPtr = (GenericHandler *) ckalloc(sizeof(GenericHandler)); + + handlerPtr->proc = (Tk_GenericProc *) proc; + handlerPtr->clientData = NULL; /* never used */ + handlerPtr->deleteFlag = 0; + handlerPtr->nextPtr = NULL; if (tsdPtr->cmList == NULL) { - tsdPtr->cmList = handlerPtr; + tsdPtr->cmList = handlerPtr; } else { tsdPtr->lastCmPtr->nextPtr = handlerPtr; } - tsdPtr->lastCmPtr = handlerPtr; + tsdPtr->lastCmPtr = handlerPtr; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * Tk_DeleteClientMessageHandler -- * @@ -457,24 +1052,23 @@ Tk_CreateClientMessageHandler(proc) * None. * * Side Effects: - * If there existed a handler as described by the parameters, - * that handler is logically deleted so that proc will not be - * invoked again. The physical deletion happens in the event - * loop in TkClientMessageEventProc. + * If there existed a handler as described by the parameters, that + * handler is logically deleted so that proc will not be invoked again. + * The physical deletion happens in the event loop in + * TkClientMessageEventProc. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_DeleteClientMessageHandler(proc) - Tk_ClientMessageProc *proc; +Tk_DeleteClientMessageHandler( + Tk_ClientMessageProc *proc) { GenericHandler * handler; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (handler = tsdPtr->cmList; handler != NULL; - handler = handler->nextPtr) { + for (handler=tsdPtr->cmList ; handler!=NULL ; handler=handler->nextPtr) { if (handler->proc == (Tk_GenericProc *) proc) { handler->deleteFlag = 1; } @@ -482,14 +1076,13 @@ Tk_DeleteClientMessageHandler(proc) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * TkEventInit -- * - * This procedures initializes all the event module - * structures used by the current thread. It must be - * called before any other procedure in this file is - * called. + * This functions initializes all the event module structures used by the + * current thread. It must be called before any other function in this + * file is called. * * Results: * None. @@ -497,14 +1090,14 @@ Tk_DeleteClientMessageHandler(proc) * Side Effects: * None. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -TkEventInit _ANSI_ARGS_((void)) +TkEventInit(void) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); tsdPtr->handlersActive = 0; tsdPtr->pendingPtr = NULL; @@ -517,28 +1110,26 @@ TkEventInit _ANSI_ARGS_((void)) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * TkXErrorHandler -- * - * TkXErrorHandler is an error handler, to be installed - * via Tk_CreateErrorHandler, that will set a flag if an - * X error occurred. + * TkXErrorHandler is an error handler, to be installed via + * Tk_CreateErrorHandler, that will set a flag if an X error occurred. * * Results: - * Always returns 0, indicating that the X error was - * handled. + * Always returns 0, indicating that the X error was handled. * * Side effects: * None. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -TkXErrorHandler (clientData, errEventPtr) - ClientData clientData; /* Pointer to flag we set */ - XErrorEvent *errEventPtr; /* X error info */ +TkXErrorHandler( + ClientData clientData, /* Pointer to flag we set. */ + XErrorEvent *errEventPtr) /* X error info. */ { int *error; @@ -548,12 +1139,12 @@ TkXErrorHandler (clientData, errEventPtr) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * ParentXId -- * - * Returns the parent of the given window, or "None" - * if the window doesn't exist. + * Returns the parent of the given window, or "None" if the window + * doesn't exist. * * Results: * Returns an X window ID. @@ -561,13 +1152,13 @@ TkXErrorHandler (clientData, errEventPtr) * Side effects: * None. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static Window -ParentXId(display, w) - Display *display; - Window w; +ParentXId( + Display *display, + Window w) { Tk_ErrorHandler handler; int gotXError; @@ -577,17 +1168,23 @@ ParentXId(display, w) Window *childList; unsigned int nChildren; - /* Handle errors ourselves. */ + /* + * Handle errors ourselves. + */ gotXError = 0; handler = Tk_CreateErrorHandler(display, -1, -1, -1, - TkXErrorHandler, (ClientData) (&gotXError)); + TkXErrorHandler, (ClientData) (&gotXError)); - /* Get the parent window. */ + /* + * Get the parent window. + */ status = XQueryTree(display, w, &root, &parent, &childList, &nChildren); - /* Do some cleanup; gotta return "None" if we got an error. */ + /* + * Do some cleanup; gotta return "None" if we got an error. + */ Tk_DeleteErrorHandler(handler); XSync(display, False); @@ -595,19 +1192,19 @@ ParentXId(display, w) XFree(childList); } if (status == 0) { - parent = None; + parent = None; } return parent; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * Tk_HandleEvent -- * - * Given an event, invoke all the handlers that have - * been registered for the event. + * Given an event, invoke all the handlers that have been registered for + * the event. * * Results: * None. @@ -615,348 +1212,106 @@ ParentXId(display, w) * Side effects: * Depends on the handlers. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_HandleEvent(eventPtr) - XEvent *eventPtr; /* Event to dispatch. */ +Tk_HandleEvent( + XEvent *eventPtr) /* Event to dispatch. */ { register TkEventHandler *handlerPtr; - register GenericHandler *genericPtr; - register GenericHandler *genPrevPtr; TkWindow *winPtr; unsigned long mask; InProgress ip; - Window handlerWindow; - Window parentXId; - TkDisplay *dispPtr; - Tcl_Interp *interp = (Tcl_Interp *) NULL; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - /* - * Hack for simulated X-events: Correct the state field - * of the event record to match with the ButtonPress - * and ButtonRelease events. - */ - - if (eventPtr->type==ButtonPress) { - dispPtr = TkGetDisplay(eventPtr->xbutton.display); - dispPtr->mouseButtonWindow = eventPtr->xbutton.window; - eventPtr->xbutton.state |= dispPtr->mouseButtonState; - switch (eventPtr->xbutton.button) { - case 1: dispPtr->mouseButtonState |= Button1Mask; break; - case 2: dispPtr->mouseButtonState |= Button2Mask; break; - case 3: dispPtr->mouseButtonState |= Button3Mask; break; - } - } else if (eventPtr->type==ButtonRelease) { - dispPtr = TkGetDisplay(eventPtr->xbutton.display); - dispPtr->mouseButtonWindow = 0; - switch (eventPtr->xbutton.button) { - case 1: dispPtr->mouseButtonState &= ~Button1Mask; break; - case 2: dispPtr->mouseButtonState &= ~Button2Mask; break; - case 3: dispPtr->mouseButtonState &= ~Button3Mask; break; - } - eventPtr->xbutton.state |= dispPtr->mouseButtonState; - } else if (eventPtr->type==MotionNotify) { - dispPtr = TkGetDisplay(eventPtr->xmotion.display); - if (dispPtr->mouseButtonState & (Button1Mask|Button2Mask|Button3Mask)) { - if (eventPtr->xbutton.window != dispPtr->mouseButtonWindow) { - /* - * This motion event should not be interpreted as a button - * press + motion event since this is not the same window - * the button was pressed down in. - */ - dispPtr->mouseButtonState &= - ~(Button1Mask|Button2Mask|Button3Mask); - dispPtr->mouseButtonWindow = 0; - } else { - eventPtr->xmotion.state |= dispPtr->mouseButtonState; - } - } - } - - /* - * Next, invoke all the generic event handlers (those that are - * invoked for all events). If a generic event handler reports that - * an event is fully processed, go no further. - */ + Tcl_Interp *interp = NULL; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (genPrevPtr = NULL, genericPtr = tsdPtr->genericList; - genericPtr != NULL; ) { - if (genericPtr->deleteFlag) { - if (!tsdPtr->handlersActive) { - GenericHandler *tmpPtr; - - /* - * This handler needs to be deleted and there are no - * calls pending through the handler, so now is a safe - * time to delete it. - */ - - tmpPtr = genericPtr->nextPtr; - if (genPrevPtr == NULL) { - tsdPtr->genericList = tmpPtr; - } else { - genPrevPtr->nextPtr = tmpPtr; - } - if (tmpPtr == NULL) { - tsdPtr->lastGenericPtr = genPrevPtr; - } - (void) ckfree((char *) genericPtr); - genericPtr = tmpPtr; - continue; - } - } else { - int done; - - tsdPtr->handlersActive++; - done = (*genericPtr->proc)(genericPtr->clientData, eventPtr); - tsdPtr->handlersActive--; - if (done) { - return; - } - } - genPrevPtr = genericPtr; - genericPtr = genPrevPtr->nextPtr; - } + UpdateButtonEventState(eventPtr); /* - * If the event is a MappingNotify event, find its display and - * refresh the keyboard mapping information for the display. - * After that there's nothing else to do with the event, so just - * quit. + * If the generic handler processed this event we are done and can return. */ - if (eventPtr->type == MappingNotify) { - dispPtr = TkGetDisplay(eventPtr->xmapping.display); - if (dispPtr != NULL) { - XRefreshKeyboardMapping(&eventPtr->xmapping); - dispPtr->bindInfoStale = 1; - } - return; + if (InvokeGenericHandlers(tsdPtr, eventPtr)) { + goto releaseEventResources; } - /* - * Events selected by StructureNotify require special handling. - * They look the same as those selected by SubstructureNotify. - * The only difference is whether the "event" and "window" fields - * are the same. Compare the two fields and convert StructureNotify - * to SubstructureNotify if necessary. - */ - - handlerWindow = eventPtr->xany.window; - mask = eventMasks[eventPtr->xany.type]; - if (mask == StructureNotifyMask) { - if (eventPtr->xmap.event != eventPtr->xmap.window) { - mask = SubstructureNotifyMask; - handlerWindow = eventPtr->xmap.event; - } - } - winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow); - if (winPtr == NULL) { + if (RefreshKeyboardMappingIfNeeded(eventPtr)) { /* - * There isn't a TkWindow structure for this window. - * However, if the event is a PropertyNotify event then call - * the selection manager (it deals beneath-the-table with - * certain properties). Also, if the window's parent is a - * Tk window that has the TK_PROP_PROPCHANGE flag set, then - * we must propagate the PropertyNotify event up to the parent. + * We are done with a MappingNotify event. */ - if (eventPtr->type != PropertyNotify) { - return; - } - - TkSelPropProc(eventPtr); - - /* Get handlerWindow's parent. */ - - parentXId = ParentXId(eventPtr->xany.display, handlerWindow); - if (parentXId == None) { - return; - } - - winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId); - if (winPtr == NULL) { - return; - } + goto releaseEventResources; + } - if (!(winPtr->flags & TK_PROP_PROPCHANGE)) { - return; - } + mask = GetEventMaskFromXEvent(eventPtr); + winPtr = GetTkWindowFromXEvent(eventPtr); - handlerWindow = parentXId; + if (winPtr == NULL) { + goto releaseEventResources; } /* * Once a window has started getting deleted, don't process any more - * events for it except for the DestroyNotify event. This check is - * needed because a DestroyNotify handler could re-invoke the event - * loop, causing other pending events to be handled for the window - * (the window doesn't get totally expunged from our tables until - * after the DestroyNotify event has been completely handled). + * events for it except for the DestroyNotify event. This check is needed + * because a DestroyNotify handler could re-invoke the event loop, causing + * other pending events to be handled for the window (the window doesn't + * get totally expunged from our tables until after the DestroyNotify + * event has been completely handled). */ if ((winPtr->flags & TK_ALREADY_DEAD) && (eventPtr->type != DestroyNotify)) { - return; + goto releaseEventResources; } if (winPtr->mainPtr != NULL) { + int result; + + interp = winPtr->mainPtr->interp; - /* - * Protect interpreter for this window from possible deletion - * while we are dealing with the event for this window. Thus, - * widget writers do not have to worry about protecting the - * interpreter in their own code. - */ - - interp = winPtr->mainPtr->interp; - Tcl_Preserve((ClientData) interp); - - /* - * Call focus-related code to look at FocusIn, FocusOut, Enter, - * and Leave events; depending on its return value, ignore the - * event. - */ - - if ((mask & (FocusChangeMask|EnterWindowMask|LeaveWindowMask)) - && !TkFocusFilterEvent(winPtr, eventPtr)) { - Tcl_Release((ClientData) interp); - return; - } - - /* - * Redirect KeyPress and KeyRelease events to the focus window, - * or ignore them entirely if there is no focus window. We also - * route the MouseWheel event to the focus window. The MouseWheel - * event is an extension to the X event set. Currently, it is only - * available on the Windows version of Tk. - */ - -#ifdef MAC_OSX_TK - /* MouseWheel events are not focus specific on Mac OS X */ - if (mask & (KeyPressMask|KeyReleaseMask)) { -#else - if (mask & (KeyPressMask|KeyReleaseMask|MouseWheelMask)) { -#endif - winPtr->dispPtr->lastEventTime = eventPtr->xkey.time; - winPtr = TkFocusKeyEvent(winPtr, eventPtr); - if (winPtr == NULL) { - Tcl_Release((ClientData) interp); - return; - } - } - /* - * Call a grab-related procedure to do special processing on - * pointer events. + * Protect interpreter for this window from possible deletion while we + * are dealing with the event for this window. Thus, widget writers do + * not have to worry about protecting the interpreter in their own + * code. */ - - if (mask & (ButtonPressMask|ButtonReleaseMask|PointerMotionMask - |EnterWindowMask|LeaveWindowMask)) { - if (mask & (ButtonPressMask|ButtonReleaseMask)) { - winPtr->dispPtr->lastEventTime = eventPtr->xbutton.time; - } else if (mask & PointerMotionMask) { - winPtr->dispPtr->lastEventTime = eventPtr->xmotion.time; - } else { - winPtr->dispPtr->lastEventTime = eventPtr->xcrossing.time; - } - if (TkPointerEvent(eventPtr, winPtr) == 0) { - goto done; - } + + Tcl_Preserve((ClientData) interp); + + result = ((InvokeFocusHandlers(&winPtr, mask, eventPtr)) + || (InvokeMouseHandlers(winPtr, mask, eventPtr))); + + if (result) { + goto releaseInterpreter; } } -#ifdef TK_USE_INPUT_METHODS /* - * Pass the event to the input method(s), if there are any, and - * discard the event if the input method(s) insist. Create the - * input context for the window if it hasn't already been done - * (XFilterEvent needs this context). XIM is only ever enabled on - * Unix, but this hasn't been factored out of the generic code yet. + * Create the input context for the window if it hasn't already been done + * (XFilterEvent needs this context). When the event is a FocusIn event, + * set the input context focus to the receiving window. This code is only + * ever active for X11. */ - dispPtr = winPtr->dispPtr; - if ((dispPtr->flags & TK_DISPLAY_USE_IM)) { - long im_event_mask = 0L; + +#ifdef TK_USE_INPUT_METHODS + if ((winPtr->dispPtr->flags & TK_DISPLAY_USE_IM)) { if (!(winPtr->flags & (TK_CHECKED_IC|TK_ALREADY_DEAD))) { winPtr->flags |= TK_CHECKED_IC; - if (dispPtr->inputMethod != NULL) { -#if TK_XIM_SPOT - if (dispPtr->flags & TK_DISPLAY_XIM_SPOT) { - XVaNestedList preedit_attr; - XPoint spot = {0, 0}; - - if (dispPtr->inputXfs == NULL) { - /* - * We only need to create one XFontSet - */ - char **missing_list; - int missing_count; - char *def_string; - - dispPtr->inputXfs = XCreateFontSet(dispPtr->display, - "-*-*-*-R-Normal--14-130-75-75-*-*", - &missing_list, &missing_count, &def_string); - if (missing_count > 0) { - XFreeStringList(missing_list); - } - } - - preedit_attr = XVaCreateNestedList(0, XNSpotLocation, - &spot, XNFontSet, dispPtr->inputXfs, NULL); - if (winPtr->inputContext != NULL) - panic("inputContext not NULL"); - winPtr->inputContext = XCreateIC(dispPtr->inputMethod, - XNInputStyle, XIMPreeditPosition|XIMStatusNothing, - XNClientWindow, winPtr->window, - XNFocusWindow, winPtr->window, - XNPreeditAttributes, preedit_attr, - NULL); - XFree(preedit_attr); - } else { - if (winPtr->inputContext != NULL) - panic("inputContext not NULL"); - winPtr->inputContext = XCreateIC(dispPtr->inputMethod, - XNInputStyle, XIMPreeditNothing|XIMStatusNothing, - XNClientWindow, winPtr->window, - XNFocusWindow, winPtr->window, - NULL); - } -#else - if (winPtr->inputContext != NULL) - panic("inputContext not NULL"); - winPtr->inputContext = XCreateIC(dispPtr->inputMethod, - XNInputStyle, XIMPreeditNothing|XIMStatusNothing, - XNClientWindow, winPtr->window, - XNFocusWindow, winPtr->window, - NULL); -#endif - } - } - if (winPtr->inputContext != NULL && - (eventPtr->xany.type == FocusIn)) { - XGetICValues(winPtr->inputContext, - XNFilterEvents, &im_event_mask, NULL); - if (im_event_mask != 0L) { - XSelectInput(winPtr->display, winPtr->window, - winPtr->atts.event_mask | im_event_mask); - XSetICFocus(winPtr->inputContext); + if (winPtr->dispPtr->inputMethod != NULL) { + CreateXIC(winPtr); } } - if (eventPtr->type == KeyPress || eventPtr->type == KeyRelease) { - if (XFilterEvent(eventPtr, None)) { - goto done; - } + if (eventPtr->type == FocusIn && winPtr->inputContext != NULL) { + XSetICFocus(winPtr->inputContext); } } -#endif /* TK_USE_INPUT_METHODS */ +#endif /* - * For events where it hasn't already been done, update the current - * time in the display. + * For events where it hasn't already been done, update the current time + * in the display. */ if (eventPtr->type == PropertyNotify) { @@ -964,8 +1319,8 @@ Tk_HandleEvent(eventPtr) } /* - * There's a potential interaction here with Tk_DeleteEventHandler. - * Read the documentation for pendingPtr. + * There's a potential interaction here with Tk_DeleteEventHandler. Read + * the documentation for pendingPtr. */ ip.eventPtr = eventPtr; @@ -983,49 +1338,8 @@ Tk_HandleEvent(eventPtr) Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS")) { TkWmProtocolEventProc(winPtr, eventPtr); } else { - /* - * Finally, invoke any ClientMessage event handlers. - */ - - for (genPrevPtr = NULL, genericPtr = tsdPtr->cmList; - genericPtr != NULL; ) { - if (genericPtr->deleteFlag) { - if (!tsdPtr->handlersActive) { - GenericHandler *tmpPtr; - - /* - * This handler needs to be deleted and there are - * no calls pending through any handlers, so now - * is a safe time to delete it. - */ - - tmpPtr = genericPtr->nextPtr; - if (genPrevPtr == NULL) { - tsdPtr->cmList = tmpPtr; - } else { - genPrevPtr->nextPtr = tmpPtr; - } - if (tmpPtr == NULL) { - tsdPtr->lastCmPtr = genPrevPtr; - } - (void) ckfree((char *) genericPtr); - genericPtr = tmpPtr; - continue; - } - } else { - int done; - - tsdPtr->handlersActive++; - done = (*(Tk_ClientMessageProc *)genericPtr->proc) - ((Tk_Window) winPtr, eventPtr); - tsdPtr->handlersActive--; - if (done) { - break; - } - } - genPrevPtr = genericPtr; - genericPtr = genPrevPtr->nextPtr; - } + InvokeClientMessageHandlers(tsdPtr, (Tk_Window)winPtr, + eventPtr); } } } else { @@ -1040,44 +1354,53 @@ Tk_HandleEvent(eventPtr) } /* - * Pass the event to the "bind" command mechanism. But, don't - * do this for SubstructureNotify events. The "bind" command - * doesn't support them anyway, and it's easier to filter out - * these events here than in the lower-level procedures. + * Pass the event to the "bind" command mechanism. But, don't do this + * for SubstructureNotify events. The "bind" command doesn't support + * them anyway, and it's easier to filter out these events here than + * in the lower-level functions. */ /* - * ...well, except when we use the tkwm patches, in which case - * we DO handle CreateNotify events, so we gotta pass 'em through. + * ...well, except when we use the tkwm patches, in which case we DO + * handle CreateNotify events, so we gotta pass 'em through. */ if ((ip.winPtr != None) && ((mask != SubstructureNotifyMask) - || (eventPtr->type == CreateNotify))) { + || (eventPtr->type == CreateNotify))) { TkBindEventProc(winPtr, eventPtr); } } tsdPtr->pendingPtr = ip.nextPtr; -done: /* * Release the interpreter for this window so that it can be potentially * deleted if requested. */ - - if (interp != (Tcl_Interp *) NULL) { - Tcl_Release((ClientData) interp); + + releaseInterpreter: + if (interp != NULL) { + Tcl_Release((ClientData) interp); } + + /* + * Release the user_data from the event (if it is a virtual event and the + * field was non-NULL in the first place.) Note that this is done using a + * Tcl_Obj interface, and we set the field back to NULL afterwards out of + * paranoia. Also clean up any cached %A substitutions from key events. + */ + + releaseEventResources: + CleanUpTkEvent(eventPtr); } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * TkEventDeadWindow -- * - * This procedure is invoked when it is determined that - * a window is dead. It cleans up event-related information - * about the window. + * This function is invoked when it is determined that a window is dead. + * It cleans up event-related information about the window. * * Results: * None. @@ -1085,31 +1408,30 @@ done: * Side effects: * Various things get cleaned up and recycled. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -TkEventDeadWindow(winPtr) - TkWindow *winPtr; /* Information about the window - * that is being deleted. */ +TkEventDeadWindow( + TkWindow *winPtr) /* Information about the window that is being + * deleted. */ { register TkEventHandler *handlerPtr; register InProgress *ipPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * While deleting all the handlers, be careful to check for - * Tk_HandleEvent being about to process one of the deleted - * handlers. If it is, tell it to quit (all of the handlers - * are being deleted). + * While deleting all the handlers, be careful to check for Tk_HandleEvent + * being about to process one of the deleted handlers. If it is, tell it + * to quit (all of the handlers are being deleted). */ while (winPtr->handlerList != NULL) { handlerPtr = winPtr->handlerList; winPtr->handlerList = handlerPtr->nextPtr; - for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; - ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; + ipPtr = ipPtr->nextPtr) { if (ipPtr->nextHandler == handlerPtr) { ipPtr->nextHandler = NULL; } @@ -1126,15 +1448,13 @@ TkEventDeadWindow(winPtr) * * TkCurrentTime -- * - * Try to deduce the current time. "Current time" means the time - * of the event that led to the current code being executed, which - * means the time in the most recently-nested invocation of - * Tk_HandleEvent. + * Try to deduce the current time. "Current time" means the time of the + * event that led to the current code being executed, which means the + * time in the most recently-nested invocation of Tk_HandleEvent. * * Results: - * The return value is the time from the current event, or - * CurrentTime if there is no current event or if the current - * event contains no time. + * The return value is the time from the current event, or CurrentTime if + * there is no current event or if the current event contains no time. * * Side effects: * None. @@ -1143,31 +1463,31 @@ TkEventDeadWindow(winPtr) */ Time -TkCurrentTime(dispPtr) - TkDisplay *dispPtr; /* Display for which the time is desired. */ +TkCurrentTime( + TkDisplay *dispPtr) /* Display for which the time is desired. */ { register XEvent *eventPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (tsdPtr->pendingPtr == NULL) { return dispPtr->lastEventTime; } eventPtr = tsdPtr->pendingPtr->eventPtr; switch (eventPtr->type) { - case ButtonPress: - case ButtonRelease: - return eventPtr->xbutton.time; - case KeyPress: - case KeyRelease: - return eventPtr->xkey.time; - case MotionNotify: - return eventPtr->xmotion.time; - case EnterNotify: - case LeaveNotify: - return eventPtr->xcrossing.time; - case PropertyNotify: - return eventPtr->xproperty.time; + case ButtonPress: + case ButtonRelease: + return eventPtr->xbutton.time; + case KeyPress: + case KeyRelease: + return eventPtr->xkey.time; + case MotionNotify: + return eventPtr->xmotion.time; + case EnterNotify: + case LeaveNotify: + return eventPtr->xcrossing.time; + case PropertyNotify: + return eventPtr->xproperty.time; } return dispPtr->lastEventTime; } @@ -1177,15 +1497,14 @@ TkCurrentTime(dispPtr) * * Tk_RestrictEvents -- * - * This procedure is used to globally restrict the set of events - * that will be dispatched. The restriction is done by filtering - * all incoming X events through a procedure that determines - * whether they are to be processed immediately, deferred, or - * discarded. + * This function is used to globally restrict the set of events that will + * be dispatched. The restriction is done by filtering all incoming X + * events through a function that determines whether they are to be + * processed immediately, deferred, or discarded. * * Results: - * The return value is the previous restriction procedure in effect, - * if there was one, or NULL if there wasn't. + * The return value is the previous restriction function in effect, if + * there was one, or NULL if there wasn't. * * Side effects: * From now on, proc will be called to determine whether to process, @@ -1195,16 +1514,15 @@ TkCurrentTime(dispPtr) */ Tk_RestrictProc * -Tk_RestrictEvents(proc, arg, prevArgPtr) - Tk_RestrictProc *proc; /* Procedure to call for each incoming - * event. */ - ClientData arg; /* Arbitrary argument to pass to proc. */ - ClientData *prevArgPtr; /* Place to store information about previous +Tk_RestrictEvents( + Tk_RestrictProc *proc, /* Function to call for each incoming event */ + ClientData arg, /* Arbitrary argument to pass to proc. */ + ClientData *prevArgPtr) /* Place to store information about previous * argument. */ { Tk_RestrictProc *prev; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); prev = tsdPtr->restrictProc; *prevArgPtr = tsdPtr->restrictArg; @@ -1218,7 +1536,7 @@ Tk_RestrictEvents(proc, arg, prevArgPtr) * * Tk_CollapseMotionEvents -- * - * This procedure controls whether we collapse motion events in a + * This function controls whether we collapse motion events in a * particular display or not. * * Results: @@ -1231,10 +1549,10 @@ Tk_RestrictEvents(proc, arg, prevArgPtr) */ int -Tk_CollapseMotionEvents(display, collapse) - Display *display; /* Display handling these events. */ - int collapse; /* boolean value that specifies whether - * motion events should be collapsed. */ +Tk_CollapseMotionEvents( + Display *display, /* Display handling these events. */ + int collapse) /* Boolean value that specifies whether motion + * events should be collapsed. */ { TkDisplay *dispPtr = (TkDisplay *) display; int prev = (dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS); @@ -1252,28 +1570,26 @@ Tk_CollapseMotionEvents(display, collapse) * * Tk_QueueWindowEvent -- * - * Given an X-style window event, this procedure adds it to the - * Tcl event queue at the given position. This procedure also - * performs mouse motion event collapsing if possible. + * Given an X-style window event, this function adds it to the Tcl event + * queue at the given position. This function also performs mouse motion + * event collapsing if possible. * * Results: * None. * * Side effects: - * Adds stuff to the event queue, which will eventually be - * processed. + * Adds stuff to the event queue, which will eventually be processed. * *---------------------------------------------------------------------- */ void -Tk_QueueWindowEvent(eventPtr, position) - XEvent *eventPtr; /* Event to add to queue. This - * procedures copies it before adding - * it to the queue. */ - Tcl_QueuePosition position; /* Where to put it on the queue: - * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, - * or TCL_QUEUE_MARK. */ +Tk_QueueWindowEvent( + XEvent *eventPtr, /* Event to add to queue. This function copies + * it before adding it to the queue. */ + Tcl_QueuePosition position) /* Where to put it on the queue: + * TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, or + * TCL_QUEUE_MARK. */ { TkWindowEvent *wevPtr; TkDisplay *dispPtr; @@ -1292,10 +1608,11 @@ Tk_QueueWindowEvent(eventPtr, position) } /* - * Don't filter motion events if the user - * defaulting to true (1), which could be set to false (0) when the - * user wishes to receive all the motion data) + * Don't filter motion events if the user defaulting to true (1), which + * could be set to false (0) when the user wishes to receive all the + * motion data) */ + if (!(dispPtr->flags & TK_DISPLAY_COLLAPSE_MOTION_EVENTS)) { wevPtr = (TkWindowEvent *) ckalloc(sizeof(TkWindowEvent)); wevPtr->header.proc = WindowEventProc; @@ -1308,9 +1625,8 @@ Tk_QueueWindowEvent(eventPtr, position) if ((eventPtr->type == MotionNotify) && (eventPtr->xmotion.window == dispPtr->delayedMotionPtr->event.xmotion.window)) { /* - * The new event is a motion event in the same window as the - * saved motion event. Just replace the saved event with the - * new one. + * The new event is a motion event in the same window as the saved + * motion event. Just replace the saved event with the new one. */ dispPtr->delayedMotionPtr->event = *eventPtr; @@ -1319,7 +1635,7 @@ Tk_QueueWindowEvent(eventPtr, position) && (eventPtr->type != NoExpose) && (eventPtr->type != Expose)) { /* - * The new event may conflict with the saved motion event. Queue + * The new event may conflict with the saved motion event. Queue * the saved motion event now so that it will be processed before * the new event. */ @@ -1335,13 +1651,13 @@ Tk_QueueWindowEvent(eventPtr, position) wevPtr->event = *eventPtr; if ((eventPtr->type == MotionNotify) && (position == TCL_QUEUE_TAIL)) { /* - * The new event is a motion event so don't queue it immediately; - * save it around in case another motion event arrives that it can - * be collapsed with. + * The new event is a motion event so don't queue it immediately; save + * it around in case another motion event arrives that it can be + * collapsed with. */ if (dispPtr->delayedMotionPtr != NULL) { - panic("Tk_QueueWindowEvent found unexpected delayed motion event"); + Tcl_Panic("Tk_QueueWindowEvent found unexpected delayed motion event"); } dispPtr->delayedMotionPtr = wevPtr; Tcl_DoWhenIdle(DelayedMotionProc, (ClientData) dispPtr); @@ -1351,12 +1667,12 @@ Tk_QueueWindowEvent(eventPtr, position) } /* - *--------------------------------------------------------------------------- + *---------------------------------------------------------------------- * * TkQueueEventForAllChildren -- * - * Given an XEvent, recursively queue the event for this window and - * all non-toplevel children of the given window. + * Given an XEvent, recursively queue the event for this window and all + * non-toplevel children of the given window. * * Results: * None. @@ -1364,23 +1680,23 @@ Tk_QueueWindowEvent(eventPtr, position) * Side effects: * Events queued. * - *--------------------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -TkQueueEventForAllChildren(winPtr, eventPtr) - TkWindow *winPtr; /* Window to which event is sent. */ - XEvent *eventPtr; /* The event to be sent. */ +TkQueueEventForAllChildren( + TkWindow *winPtr, /* Window to which event is sent. */ + XEvent *eventPtr) /* The event to be sent. */ { TkWindow *childPtr; if (!Tk_IsMapped(winPtr)) { - return; + return; } - + eventPtr->xany.window = winPtr->window; Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL); - + childPtr = winPtr->childList; while (childPtr != NULL) { if (!Tk_TopWinHierarchy(childPtr)) { @@ -1395,16 +1711,16 @@ TkQueueEventForAllChildren(winPtr, eventPtr) * * WindowEventProc -- * - * This procedure is called by Tcl_DoOneEvent when a window event - * reaches the front of the event queue. This procedure is responsible - * for actually handling the event. + * This function is called by Tcl_DoOneEvent when a window event reaches + * the front of the event queue. This function is responsible for + * actually handling the event. * * Results: - * Returns 1 if the event was handled, meaning it should be removed - * from the queue. Returns 0 if the event was not handled, meaning - * it should stay on the queue. The event isn't handled if the - * TCL_WINDOW_EVENTS bit isn't set in flags, if a restrict proc - * prevents the event from being handled. + * Returns 1 if the event was handled, meaning it should be removed from + * the queue. Returns 0 if the event was not handled, meaning it should + * stay on the queue. The event isn't handled if the TCL_WINDOW_EVENTS + * bit isn't set in flags, if a restrict proc prevents the event from + * being handled. * * Side effects: * Whatever the event handlers for the event do. @@ -1413,15 +1729,15 @@ TkQueueEventForAllChildren(winPtr, eventPtr) */ static int -WindowEventProc(evPtr, flags) - Tcl_Event *evPtr; /* Event to service. */ - int flags; /* Flags that indicate what events to - * handle, such as TCL_WINDOW_EVENTS. */ +WindowEventProc( + Tcl_Event *evPtr, /* Event to service. */ + int flags) /* Flags that indicate what events to handle, + * such as TCL_WINDOW_EVENTS. */ { TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr; Tk_RestrictAction result; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!(flags & TCL_WINDOW_EVENTS)) { return 0; @@ -1436,68 +1752,398 @@ WindowEventProc(evPtr, flags) * TK_DELETE_EVENT: return and say we processed the event, * even though we didn't do anything at all. */ + + CleanUpTkEvent(&wevPtr->event); return 1; } } } Tk_HandleEvent(&wevPtr->event); + CleanUpTkEvent(&wevPtr->event); return 1; } /* *---------------------------------------------------------------------- * + * CleanUpTkEvent -- + * + * This function is called to remove and deallocate any information in + * the event which is not directly in the event structure itself. It may + * be called multiple times per event, so it takes care to set the + * cleared pointer fields to NULL afterwards. + * + * Results: + * None. + * + * Side effects: + * Makes the event no longer have any external resources. + * + *---------------------------------------------------------------------- + */ + +static void +CleanUpTkEvent( + XEvent *eventPtr) +{ + switch (eventPtr->type) { + case KeyPress: + case KeyRelease: { + TkKeyEvent *kePtr = (TkKeyEvent *) eventPtr; + + if (kePtr->charValuePtr != NULL) { + ckfree(kePtr->charValuePtr); + kePtr->charValuePtr = NULL; + kePtr->charValueLen = 0; + } + break; + } + + case VirtualEvent: { + XVirtualEvent *vePtr = (XVirtualEvent *) eventPtr; + + if (vePtr->user_data != NULL) { + Tcl_DecrRefCount(vePtr->user_data); + vePtr->user_data = NULL; + } + break; + } + } +} + +/* + *---------------------------------------------------------------------- + * * DelayedMotionProc -- * - * This procedure is invoked as an idle handler when a mouse motion - * event has been delayed. It queues the delayed event so that it - * will finally be serviced. + * This function is invoked as an idle handler when a mouse motion event + * has been delayed. It queues the delayed event so that it will finally + * be serviced. * * Results: * None. * * Side effects: - * The delayed mouse motion event gets added to the Tcl event - * queue for servicing. + * The delayed mouse motion event gets added to the Tcl event queue for + * servicing. * *---------------------------------------------------------------------- */ static void -DelayedMotionProc(clientData) - ClientData clientData; /* Pointer to display containing a delayed +DelayedMotionProc( + ClientData clientData) /* Pointer to display containing a delayed * motion event to be serviced. */ { TkDisplay *dispPtr = (TkDisplay *) clientData; if (dispPtr->delayedMotionPtr == NULL) { - panic("DelayedMotionProc found no delayed mouse motion event"); + Tcl_Panic("DelayedMotionProc found no delayed mouse motion event"); } Tcl_QueueEvent(&dispPtr->delayedMotionPtr->header, TCL_QUEUE_TAIL); dispPtr->delayedMotionPtr = NULL; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- + * + * TkCreateExitHandler -- + * + * Same as Tcl_CreateExitHandler, but private to Tk. + * + * Results: + * None. + * + * Side effects. + * Sets a handler with Tcl_CreateExitHandler if this is the first call. + * + *---------------------------------------------------------------------- + */ + +void +TkCreateExitHandler( + Tcl_ExitProc *proc, /* Function to invoke. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr; + + exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler)); + exitPtr->proc = proc; + exitPtr->clientData = clientData; + Tcl_MutexLock(&exitMutex); + + /* + * The call to TclInExit() is disabled here. That's a private Tcl routine, + * and calling it is causing some trouble with portability of building Tk. + * We should avoid private Tcl routines generally. + * + * In this case, the TclInExit() call is being used only to prevent a + * Tcl_CreateExitHandler() call when Tcl finalization is in progress. + * That's a situation that shouldn't happen anyway. Recent changes within + * Tcl_Finalize now cause a Tcl_Panic() to happen if exit handlers get + * added after exit handling is complete. By disabling the guard here, + * that panic will serve to help us find the buggy conditions and correct + * them. + * + * We can restore this guard if we find we must (hopefully getting public + * access to TclInExit() if we discover extensions really do need this), + * but during alpha development, this is a good time to dig in and find + * the root causes of finalization bugs. + */ + + if (firstExitPtr == NULL/* && !TclInExit()*/) { + Tcl_CreateExitHandler(TkFinalize, NULL); + } + exitPtr->nextPtr = firstExitPtr; + firstExitPtr = exitPtr; + Tcl_MutexUnlock(&exitMutex); +} + +/* + *---------------------------------------------------------------------- + * + * TkDeleteExitHandler -- + * + * Same as Tcl_DeleteExitHandler, but private to Tk. + * + * Results: + * None. + * + * Side effects. + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkDeleteExitHandler( + Tcl_ExitProc *proc, /* Function that was previously registered. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr, *prevPtr; + + Tcl_MutexLock(&exitMutex); + for (prevPtr = NULL, exitPtr = firstExitPtr; exitPtr != NULL; + prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) { + if ((exitPtr->proc == proc) + && (exitPtr->clientData == clientData)) { + if (prevPtr == NULL) { + firstExitPtr = exitPtr->nextPtr; + } else { + prevPtr->nextPtr = exitPtr->nextPtr; + } + ckfree((char *) exitPtr); + break; + } + } + Tcl_MutexUnlock(&exitMutex); + return; +} + +/* + *---------------------------------------------------------------------- + * + * TkCreateThreadExitHandler -- + * + * Same as Tcl_CreateThreadExitHandler, but private to Tk. + * + * Results: + * None. + * + * Side effects: + * Proc will be invoked with clientData as argument when the application + * exits. + * + *---------------------------------------------------------------------- + */ + +void +TkCreateThreadExitHandler( + Tcl_ExitProc *proc, /* Function to invoke. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler)); + exitPtr->proc = proc; + exitPtr->clientData = clientData; + + /* + * See comments in TkCreateExitHandler(). + */ + + if (tsdPtr->firstExitPtr == NULL/* && !TclInExit()*/) { + Tcl_CreateThreadExitHandler(TkFinalizeThread, NULL); + } + exitPtr->nextPtr = tsdPtr->firstExitPtr; + tsdPtr->firstExitPtr = exitPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkDeleteThreadExitHandler -- + * + * Same as Tcl_DeleteThreadExitHandler, but private to Tk. + * + * Results: + * None. + * + * Side effects: + * If there is an exit handler corresponding to proc and clientData then + * it is cancelled; if no such handler exists then nothing happens. + * + *---------------------------------------------------------------------- + */ + +void +TkDeleteThreadExitHandler( + Tcl_ExitProc *proc, /* Function that was previously registered. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr, *prevPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + for (prevPtr = NULL, exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL; + prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) { + if ((exitPtr->proc == proc) + && (exitPtr->clientData == clientData)) { + if (prevPtr == NULL) { + tsdPtr->firstExitPtr = exitPtr->nextPtr; + } else { + prevPtr->nextPtr = exitPtr->nextPtr; + } + ckfree((char *) exitPtr); + return; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkFinalize -- + * + * Runs our private exit handlers and removes itself from Tcl. This is + * benificial should we want to protect from dangling pointers should the + * Tk shared library be unloaded prior to Tcl which can happen on windows + * should the process be forcefully exiting from an exception handler. + * + * Results: + * None. + * + * Side effects. + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkFinalize( + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr; + + Tcl_DeleteExitHandler(TkFinalize, NULL); + + Tcl_MutexLock(&exitMutex); + for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) { + /* + * Be careful to remove the handler from the list before invoking its + * callback. This protects us against double-freeing if the callback + * should call TkDeleteExitHandler on itself. + */ + + firstExitPtr = exitPtr->nextPtr; + Tcl_MutexUnlock(&exitMutex); + (*exitPtr->proc)(exitPtr->clientData); + ckfree((char *) exitPtr); + Tcl_MutexLock(&exitMutex); + } + firstExitPtr = NULL; + Tcl_MutexUnlock(&exitMutex); +} + +/* + *---------------------------------------------------------------------- + * + * TkFinalizeThread -- + * + * Runs our private thread exit handlers and removes itself from Tcl. + * This is benificial should we want to protect from dangling pointers + * should the Tk shared library be unloaded prior to Tcl which can happen + * on Windows should the process be forcefully exiting from an exception + * handler. + * + * Results: + * None. + * + * Side effects. + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkFinalizeThread( + ClientData clientData) /* Arbitrary value to pass to proc. */ +{ + ExitHandler *exitPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + Tcl_DeleteThreadExitHandler(TkFinalizeThread, NULL); + + if (tsdPtr != NULL) { + tsdPtr->inExit = 1; + + for (exitPtr = tsdPtr->firstExitPtr; exitPtr != NULL; + exitPtr = tsdPtr->firstExitPtr) { + /* + * Be careful to remove the handler from the list before invoking + * its callback. This protects us against double-freeing if the + * callback should call TkDeleteThreadExitHandler on itself. + */ + + tsdPtr->firstExitPtr = exitPtr->nextPtr; + (*exitPtr->proc)(exitPtr->clientData); + ckfree((char *) exitPtr); + } + } +} + +/* + *---------------------------------------------------------------------- * * Tk_MainLoop -- * - * Call Tcl_DoOneEvent over and over again in an infinite - * loop as long as there exist any main windows. + * Call Tcl_DoOneEvent over and over again in an infinite loop as long as + * there exist any main windows. * * Results: * None. * * Side effects: - * Arbitrary; depends on handlers for events. + * Arbitrary; depends on handlers for events. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ void -Tk_MainLoop() +Tk_MainLoop(void) { while (Tk_GetNumMainWindows() > 0) { Tcl_DoOneEvent(0); } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkFileFilter.c b/generic/tkFileFilter.c index 3fa8303..547dd9b 100644 --- a/generic/tkFileFilter.c +++ b/generic/tkFileFilter.c @@ -6,33 +6,29 @@ * * Copyright (c) 1996 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkFileFilter.h" -static int AddClause _ANSI_ARGS_(( - Tcl_Interp * interp, FileFilter * filterPtr, - CONST char * patternsStr, CONST char * ostypesStr, - int isWindows)); -static void FreeClauses _ANSI_ARGS_((FileFilter * filterPtr)); -static void FreeGlobPatterns _ANSI_ARGS_(( - FileFilterClause * clausePtr)); -static void FreeMacFileTypes _ANSI_ARGS_(( - FileFilterClause * clausePtr)); -static FileFilter * GetFilter _ANSI_ARGS_((FileFilterList * flistPtr, - CONST char * name)); +static int AddClause(Tcl_Interp *interp, + FileFilter *filterPtr, Tcl_Obj *patternsObj, + Tcl_Obj *ostypesObj, int isWindows); +static void FreeClauses(FileFilter *filterPtr); +static void FreeGlobPatterns(FileFilterClause *clausePtr); +static void FreeMacFileTypes(FileFilterClause *clausePtr); +static FileFilter * GetFilter(FileFilterList *flistPtr, CONST char *name); /* *---------------------------------------------------------------------- * * TkInitFileFilters -- * - * Initializes a FileFilterList data structure. A FileFilterList - * must be initialized EXACTLY ONCE before any calls to - * TkGetFileFilters() is made. The usual flow of control is: + * Initializes a FileFilterList data structure. A FileFilterList must be + * initialized EXACTLY ONCE before any calls to TkGetFileFilters() is + * made. The usual flow of control is: * TkInitFileFilters(&flist); * TkGetFileFilters(&flist, ...); * TkGetFileFilters(&flist, ...); @@ -44,12 +40,13 @@ static FileFilter * GetFilter _ANSI_ARGS_((FileFilterList * flistPtr, * * Side effects: * The fields in flistPtr are initialized. + * *---------------------------------------------------------------------- */ void -TkInitFileFilters(flistPtr) - FileFilterList * flistPtr; /* The structure to be initialized. */ +TkInitFileFilters( + FileFilterList *flistPtr) /* The structure to be initialized. */ { flistPtr->filters = NULL; flistPtr->filtersTail = NULL; @@ -61,11 +58,11 @@ TkInitFileFilters(flistPtr) * * TkGetFileFilters -- * - * This function is called by the Mac and Windows implementation - * of tk_getOpenFile and tk_getSaveFile to translate the string - * value of the -filetypes option of into an easy-to-parse C - * structure (flistPtr). The caller of this function will then use - * flistPtr to perform filetype matching in a platform specific way. + * This function is called by the Mac and Windows implementation of + * tk_getOpenFile and tk_getSaveFile to translate the string value of the + * -filetypes option into an easy-to-parse C structure (flistPtr). The + * caller of this function will then use flistPtr to perform filetype + * matching in a platform specific way. * * flistPtr must be initialized (See comments in TkInitFileFilters). * @@ -73,85 +70,74 @@ TkInitFileFilters(flistPtr) * A standard TCL return value. * * Side effects: - * The fields in flistPtr are changed according to string. + * The fields in flistPtr are changed according to 'types'. + * *---------------------------------------------------------------------- */ + int -TkGetFileFilters(interp, flistPtr, string, isWindows) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - FileFilterList * flistPtr; /* Stores the list of file filters. */ - char * string; /* Value of the -filetypes option. */ - int isWindows; /* True if we are running on Windows. */ +TkGetFileFilters( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + FileFilterList *flistPtr, /* Stores the list of file filters. */ + Tcl_Obj *types, /* Value of the -filetypes option. */ + int isWindows) /* True if we are running on Windows. */ { - int listArgc; - CONST char ** listArgv = NULL; - CONST char ** typeInfo = NULL; - int code = TCL_OK; + int listObjc; + Tcl_Obj ** listObjv = NULL; int i; - if (Tcl_SplitList(interp, string, &listArgc, &listArgv) != TCL_OK) { + if (types == NULL) { + return TCL_OK; + } + + if (Tcl_ListObjGetElements(interp, types, &listObjc, + &listObjv) != TCL_OK) { return TCL_ERROR; } - if (listArgc == 0) { - goto done; + if (listObjc == 0) { + return TCL_OK; } /* - * Free the filter information that have been allocated the previous - * time -- the -filefilters option may have been used more than once in - * the command line. + * Free the filter information that have been allocated the previous time; + * the -filefilters option may have been used more than once in the + * command line. */ TkFreeFileFilters(flistPtr); - for (i = 0; i<listArgc; i++) { + for (i = 0; i<listObjc; i++) { /* - * Each file type should have two or three elements: the first one - * is the name of the type and the second is the filter of the type. - * The third is the Mac OSType ID, but we don't care about them here. + * Each file type should have two or three elements: the first one is + * the name of the type and the second is the filter of the type. The + * third is the Mac OSType ID, but we don't care about them here. */ + int count; - FileFilter * filterPtr; + FileFilter *filterPtr; + Tcl_Obj **typeInfo; - if (Tcl_SplitList(interp, listArgv[i], &count, &typeInfo) != TCL_OK) { - code = TCL_ERROR; - goto done; + if (Tcl_ListObjGetElements(interp, listObjv[i], &count, + &typeInfo) != TCL_OK) { + return TCL_ERROR; } - + if (count != 2 && count != 3) { - Tcl_AppendResult(interp, "bad file type \"", listArgv[i], "\", ", - "should be \"typeName {extension ?extensions ...?} ", - "?{macType ?macTypes ...?}?\"", NULL); - code = TCL_ERROR; - goto done; + Tcl_AppendResult(interp, "bad file type \"", + Tcl_GetString(listObjv[i]), "\", ", + "should be \"typeName {extension ?extensions ...?} ", + "?{macType ?macTypes ...?}?\"", NULL); + return TCL_ERROR; } - filterPtr = GetFilter(flistPtr, typeInfo[0]); - - if (count == 2) { - code = AddClause(interp, filterPtr, typeInfo[1], NULL, - isWindows); - } else { - code = AddClause(interp, filterPtr, typeInfo[1], typeInfo[2], - isWindows); - } - if (code != TCL_OK) { - goto done; - } + filterPtr = GetFilter(flistPtr, Tcl_GetString(typeInfo[0])); - if (typeInfo) { - ckfree((char*)typeInfo); + if (AddClause(interp, filterPtr, typeInfo[1], + (count==2 ? NULL : typeInfo[2]), isWindows) != TCL_OK) { + return TCL_ERROR; } - typeInfo = NULL; } - done: - if (typeInfo) { - ckfree((char*)typeInfo); - } - if (listArgv) { - ckfree((char*)listArgv); - } - return code; + return TCL_OK; } /* @@ -166,19 +152,20 @@ TkGetFileFilters(interp, flistPtr, string, isWindows) * * Side effects: * The fields allocated by TkGetFileFilters() are freed. + * *---------------------------------------------------------------------- */ void -TkFreeFileFilters(flistPtr) - FileFilterList * flistPtr; /* List of file filters to free */ +TkFreeFileFilters( + FileFilterList *flistPtr) /* List of file filters to free */ { - FileFilter * filterPtr, *toFree; + FileFilter *filterPtr, *toFree; filterPtr=flistPtr->filters; - while (filterPtr) { + while (filterPtr != NULL) { toFree = filterPtr; - filterPtr=filterPtr->next; + filterPtr = filterPtr->next; FreeClauses(toFree); ckfree((char*)toFree->name); ckfree((char*)toFree); @@ -198,41 +185,82 @@ TkFreeFileFilters(flistPtr) * * Side effects: * The list of filter clauses are updated in filterPtr. + * *---------------------------------------------------------------------- */ -static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows) - Tcl_Interp * interp; /* Interpreter to use for error reporting. */ - FileFilter * filterPtr; /* Stores the new filter clause */ - CONST char * patternsStr; /* A TCL list of glob patterns. */ - CONST char * ostypesStr; /* A TCL list of Mac OSType strings. */ - int isWindows; /* True if we are running on Windows; False - * if we are running on the Mac; Glob - * patterns need to be processed differently - * on these two platforms */ +static int +AddClause( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + FileFilter *filterPtr, /* Stores the new filter clause */ + Tcl_Obj *patternsObj, /* A Tcl list of glob patterns. */ + Tcl_Obj *ostypesObj, /* A Tcl list of Mac OSType strings. */ + int isWindows) /* True if we are running on Windows; False if + * we are running on the Mac; Glob patterns + * need to be processed differently on these + * two platforms */ { - CONST char ** globList = NULL; - int globCount; - CONST char ** ostypeList = NULL; - int ostypeCount; - FileFilterClause * clausePtr; - int i; - int code = TCL_OK; + Tcl_Obj **globList = NULL, **ostypeList = NULL; + int globCount, ostypeCount, i, code = TCL_OK; + FileFilterClause *clausePtr; + Tcl_Encoding macRoman = NULL; - if (Tcl_SplitList(interp, patternsStr, &globCount, &globList)!= TCL_OK) { + if (Tcl_ListObjGetElements(interp, patternsObj, + &globCount, &globList) != TCL_OK) { code = TCL_ERROR; goto done; } - if (ostypesStr != NULL) { - if (Tcl_SplitList(interp, ostypesStr, &ostypeCount, &ostypeList) - != TCL_OK) { + if (ostypesObj != NULL) { + if (Tcl_ListObjGetElements(interp, ostypesObj, + &ostypeCount, &ostypeList) != TCL_OK) { code = TCL_ERROR; goto done; } + + /* + * We probably need this encoding now... + */ + + macRoman = Tcl_GetEncoding(NULL, "macRoman"); + + /* + * Might be cleaner to use 'Tcl_GetOSTypeFromObj' but that is actually + * static to the MacOS X/Darwin version of Tcl, and would therefore + * require further code refactoring. + */ + for (i=0; i<ostypeCount; i++) { - if (strlen(ostypeList[i]) != 4) { + int len; + CONST char *strType = Tcl_GetStringFromObj(ostypeList[i], &len); + + /* + * If len is < 4, it is definitely an error. If equal or longer, + * we need to use the macRoman encoding to determine the correct + * length (assuming there may be non-ascii characters, e.g., + * embedded nulls or accented characters in the string, the + * macRoman length will be different). + * + * If we couldn't load the encoding, then we can't actually check + * the correct length. But here we assume we're probably operating + * on unix/windows with a minimal set of encodings and so don't + * care about MacOS types. So we won't signal an error. + */ + + if (len >= 4 && macRoman != NULL) { + Tcl_DString osTypeDS; + + /* + * Convert utf to macRoman, since MacOS types are defined to + * be 4 macRoman characters long + */ + + Tcl_UtfToExternalDString(macRoman, strType, len, &osTypeDS); + len = Tcl_DStringLength(&osTypeDS); + Tcl_DStringFree(&osTypeDS); + } + if (len != 4) { Tcl_AppendResult(interp, "bad Macintosh file type \"", - ostypeList[i], "\"", NULL); + Tcl_GetString(ostypeList[i]), "\"", NULL); code = TCL_ERROR; goto done; } @@ -240,7 +268,7 @@ static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows) } /* - * Add the clause into the list of clauses + * Add the clause into the list of clauses */ clausePtr = (FileFilterClause*)ckalloc(sizeof(FileFilterClause)); @@ -259,40 +287,40 @@ static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows) if (globCount > 0 && globList != NULL) { for (i=0; i<globCount; i++) { - GlobPattern * globPtr = (GlobPattern*)ckalloc(sizeof(GlobPattern)); + GlobPattern *globPtr = (GlobPattern*)ckalloc(sizeof(GlobPattern)); int len; - - len = (strlen(globList[i]) + 1) * sizeof(char); - if (globList[i][0] && globList[i][0] != '*') { + CONST char *str = Tcl_GetStringFromObj(globList[i], &len); + len = (len + 1) * sizeof(char); + + if (str[0] && str[0] != '*') { /* * Prepend a "*" to patterns that do not have a leading "*" */ + globPtr->pattern = (char*)ckalloc((unsigned int) len+1); globPtr->pattern[0] = '*'; - strcpy(globPtr->pattern+1, globList[i]); - } - else if (isWindows) { - if (strcmp(globList[i], "*") == 0) { - globPtr->pattern = (char*)ckalloc(4*sizeof(char)); + strcpy(globPtr->pattern+1, str); + } else if (isWindows) { + if (strcmp(str, "*") == 0) { + globPtr->pattern = (char*)ckalloc(4 * sizeof(char)); strcpy(globPtr->pattern, "*.*"); - } - else if (strcmp(globList[i], "") == 0) { + } else if (strcmp(str, "") == 0) { /* * An empty string means "match all files with no * extensions" * BUG: "*." actually matches with all files on Win95 */ - globPtr->pattern = (char*)ckalloc(3*sizeof(char)); + + globPtr->pattern = (char *) ckalloc(3 * sizeof(char)); strcpy(globPtr->pattern, "*."); - } - else { - globPtr->pattern = (char*)ckalloc((unsigned int) len); - strcpy(globPtr->pattern, globList[i]); + } else { + globPtr->pattern = (char *) ckalloc((unsigned int) len); + strcpy(globPtr->pattern, str); } } else { - globPtr->pattern = (char*)ckalloc((unsigned int) len); - strcpy(globPtr->pattern, globList[i]); + globPtr->pattern = (char *) ckalloc((unsigned int) len); + strcpy(globPtr->pattern, str); } /* @@ -308,13 +336,27 @@ static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows) globPtr->next = NULL; } } - if (ostypeCount > 0 && ostypeList != NULL) { + if (ostypeList != NULL && ostypeCount > 0) { + if (macRoman == NULL) { + macRoman = Tcl_GetEncoding(NULL, "macRoman"); + } for (i=0; i<ostypeCount; i++) { - MacFileType * mfPtr = (MacFileType*)ckalloc(sizeof(MacFileType)); - CONST char *string = ostypeList[i]; + Tcl_DString osTypeDS; + int len; + MacFileType *mfPtr = (MacFileType *) ckalloc(sizeof(MacFileType)); + CONST char *strType = Tcl_GetStringFromObj(ostypeList[i], &len); + char *string; + /* + * Convert utf to macRoman, since MacOS types are defined to be 4 + * macRoman characters long + */ + + Tcl_UtfToExternalDString(macRoman, strType, len, &osTypeDS); + string = Tcl_DStringValue(&osTypeDS); mfPtr->type = (OSType) string[0] << 24 | (OSType) string[1] << 16 | (OSType) string[2] << 8 | (OSType) string[3]; + Tcl_DStringFree(&osTypeDS); /* * Add the Mac type pattern into the list of Mac types @@ -331,15 +373,11 @@ static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows) } done: - if (globList) { - ckfree((char*)globList); + if (macRoman != NULL) { + Tcl_FreeEncoding(macRoman); } - if (ostypeList) { - ckfree((char*)ostypeList); - } - return code; -} +} /* *---------------------------------------------------------------------- @@ -353,28 +391,30 @@ static int AddClause(interp, filterPtr, patternsStr, ostypesStr, isWindows) * * Side effects: * The list of filters are updated in flistPtr. + * *---------------------------------------------------------------------- */ -static FileFilter * GetFilter(flistPtr, name) - FileFilterList * flistPtr; /* The FileFilterList that contains the - * newly created filter */ - CONST char * name; /* Name of the filter. It is usually displayed +static FileFilter * +GetFilter( + FileFilterList *flistPtr, /* The FileFilterList that contains the newly + * created filter */ + CONST char *name) /* Name of the filter. It is usually displayed * in the "File Types" listbox in the file * dialogs. */ { - FileFilter * filterPtr; + FileFilter *filterPtr = flistPtr->filters; - for (filterPtr=flistPtr->filters; filterPtr; filterPtr=filterPtr->next) { - if (strcmp(filterPtr->name, name)==0) { + for (; filterPtr; filterPtr=filterPtr->next) { + if (strcmp(filterPtr->name, name) == 0) { return filterPtr; } } - filterPtr = (FileFilter*)ckalloc(sizeof(FileFilter)); + filterPtr = (FileFilter *) ckalloc(sizeof(FileFilter)); filterPtr->clauses = NULL; filterPtr->clausesTail = NULL; - filterPtr->name = (char*)ckalloc((strlen(name)+1) * sizeof(char)); + filterPtr->name = (char *) ckalloc((strlen(name)+1) * sizeof(char)); strcpy(filterPtr->name, name); if (flistPtr->filters == NULL) { @@ -401,22 +441,23 @@ static FileFilter * GetFilter(flistPtr, name) * * Side effects: * The list of clauses in filterPtr->clauses are freed. + * *---------------------------------------------------------------------- */ static void -FreeClauses(filterPtr) - FileFilter * filterPtr; /* FileFilter whose clauses are to be freed */ +FreeClauses( + FileFilter *filterPtr) /* FileFilter whose clauses are to be freed */ { - FileFilterClause * clausePtr, * toFree; + FileFilterClause *clausePtr = filterPtr->clauses; + + while (clausePtr != NULL) { + FileFilterClause *toFree = clausePtr; + clausePtr = clausePtr->next; - clausePtr = filterPtr->clauses; - while (clausePtr) { - toFree = clausePtr; - clausePtr=clausePtr->next; FreeGlobPatterns(toFree); FreeMacFileTypes(toFree); - ckfree((char*)toFree); + ckfree((char *) toFree); } filterPtr->clauses = NULL; filterPtr->clausesTail = NULL; @@ -434,22 +475,22 @@ FreeClauses(filterPtr) * * Side effects: * The list of glob patterns in clausePtr->patterns are freed. + * *---------------------------------------------------------------------- */ static void -FreeGlobPatterns(clausePtr) - FileFilterClause * clausePtr;/* The clause whose patterns are to be freed*/ +FreeGlobPatterns( + FileFilterClause *clausePtr)/* The clause whose patterns are to be freed*/ { - GlobPattern * globPtr, * toFree; + GlobPattern *globPtr = clausePtr->patterns; - globPtr = clausePtr->patterns; - while (globPtr) { - toFree = globPtr; - globPtr=globPtr->next; + while (globPtr != NULL) { + GlobPattern *toFree = globPtr; + globPtr = globPtr->next; - ckfree((char*)toFree->pattern); - ckfree((char*)toFree); + ckfree((char *) toFree->pattern); + ckfree((char *) toFree); } clausePtr->patterns = NULL; } @@ -466,21 +507,29 @@ FreeGlobPatterns(clausePtr) * * Side effects: * The list of Mac file types in clausePtr->macTypes are freed. + * *---------------------------------------------------------------------- */ static void -FreeMacFileTypes(clausePtr) - FileFilterClause * clausePtr; /* The clause whose mac types are to be - * freed */ +FreeMacFileTypes( + FileFilterClause *clausePtr)/* The clause whose mac types are to be + * freed */ { - MacFileType * mfPtr, * toFree; + MacFileType *mfPtr = clausePtr->macTypes; - mfPtr = clausePtr->macTypes; - while (mfPtr) { - toFree = mfPtr; - mfPtr=mfPtr->next; - ckfree((char*)toFree); + while (mfPtr != NULL) { + MacFileType *toFree = mfPtr; + mfPtr = mfPtr->next; + ckfree((char *) toFree); } clausePtr->macTypes = NULL; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkFileFilter.h b/generic/tkFileFilter.h index 8d7021e..24002df 100644 --- a/generic/tkFileFilter.h +++ b/generic/tkFileFilter.h @@ -1,23 +1,19 @@ /* * tkFileFilter.h -- * - * Declarations for the file filter processing routines needed by - * the file selection dialogs. + * Declarations for the file filter processing routines needed by the + * file selection dialogs. * * Copyright (c) 1996 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TK_FILE_FILTER #define _TK_FILE_FILTER -#ifdef MAC_TCL -#include <StandardFile.h> -#else #define OSType long -#endif #ifdef BUILD_tk # undef TCL_STORAGE_CLASS @@ -25,65 +21,65 @@ #endif typedef struct GlobPattern { - struct GlobPattern * next; /* Chains to the next glob pattern - * in a glob pattern list */ - char * pattern; /* String value of the pattern, such - * as "*.txt" or "*.*" - */ + struct GlobPattern *next; /* Chains to the next glob pattern in a glob + * pattern list */ + char *pattern; /* String value of the pattern, such as + * "*.txt" or "*.*" */ } GlobPattern; typedef struct MacFileType { - struct MacFileType * next; /* Chains to the next mac file type - * in a mac file type list */ - OSType type; /* Mac file type, such as 'TEXT' or - * 'GIFF' */ + struct MacFileType *next; /* Chains to the next mac file type in a mac + * file type list */ + OSType type; /* Mac file type, such as 'TEXT' or 'GIFF' */ } MacFileType; typedef struct FileFilterClause { - struct FileFilterClause * next; /* Chains to the next clause in - * a clause list */ - GlobPattern * patterns; /* Head of glob pattern type list */ - GlobPattern * patternsTail; /* Tail of glob pattern type list */ - MacFileType * macTypes; /* Head of mac file type list */ - MacFileType * macTypesTail; /* Tail of mac file type list */ + struct FileFilterClause *next; + /* Chains to the next clause in a clause + * list */ + GlobPattern *patterns; /* Head of glob pattern type list */ + GlobPattern *patternsTail; /* Tail of glob pattern type list */ + MacFileType *macTypes; /* Head of mac file type list */ + MacFileType *macTypesTail; /* Tail of mac file type list */ } FileFilterClause; typedef struct FileFilter { - struct FileFilter * next; /* Chains to the next filter - * in a filter list */ - char * name; /* Name of the file filter, - * such as "Text Documents" */ - FileFilterClause * clauses; /* Head of the clauses list */ - FileFilterClause * clausesTail; /* Tail of the clauses list */ + struct FileFilter *next; /* Chains to the next filter in a filter + * list */ + char *name; /* Name of the file filter, such as "Text + * Documents" */ + FileFilterClause *clauses; /* Head of the clauses list */ + FileFilterClause *clausesTail; + /* Tail of the clauses list */ } FileFilter; -/*---------------------------------------------------------------------- +/* + *---------------------------------------------------------------------- + * * FileFilterList -- * - * The routine TkGetFileFilters() translates the string value of the - * -filefilters option into a FileFilterList structure, which consists - * of a list of file filters. + * The routine TkGetFileFilters() translates the string value of the + * -filefilters option into a FileFilterList structure, which consists of + * a list of file filters. + * + * Each file filter consists of one or more clauses. Each clause has one + * or more glob patterns and/or one or more Mac file types * - * Each file filter consists of one or more clauses. Each clause has - * one or more glob patterns and/or one or more Mac file types *---------------------------------------------------------------------- */ typedef struct FileFilterList { - FileFilter * filters; /* Head of the filter list */ - FileFilter * filtersTail; /* Tail of the filter list */ - int numFilters; /* number of filters in the list */ + FileFilter *filters; /* Head of the filter list */ + FileFilter *filtersTail; /* Tail of the filter list */ + int numFilters; /* number of filters in the list */ } FileFilterList; -EXTERN void TkFreeFileFilters _ANSI_ARGS_(( - FileFilterList * flistPtr)); -EXTERN void TkInitFileFilters _ANSI_ARGS_(( - FileFilterList * flistPtr)); -EXTERN int TkGetFileFilters _ANSI_ARGS_ ((Tcl_Interp *interp, - FileFilterList * flistPtr, char * string, - int isWindows)); +MODULE_SCOPE void TkFreeFileFilters(FileFilterList *flistPtr); +MODULE_SCOPE void TkInitFileFilters(FileFilterList *flistPtr); +MODULE_SCOPE int TkGetFileFilters(Tcl_Interp *interp, + FileFilterList *flistPtr, Tcl_Obj *valuePtr, + int isWindows); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT - #endif diff --git a/generic/tkFocus.c b/generic/tkFocus.c index aad1305..42d8be3 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -1,23 +1,20 @@ -/* +/* * tkFocus.c -- * - * This file contains procedures that manage the input - * focus for Tk. + * This file contains functions that manage the input focus for Tk. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" - /* - * For each top-level window that has ever received the focus, there - * is a record of the following type: + * For each top-level window that has ever received the focus, there is a + * record of the following type: */ typedef struct TkToplevelFocusInfo { @@ -31,19 +28,17 @@ typedef struct TkToplevelFocusInfo { } ToplevelFocusInfo; /* - * One of the following structures exists for each display used by - * each application. These are linked together from the TkMainInfo - * structure. These structures are needed because it isn't - * sufficient to store a single piece of focus information in each - * display or in each application: we need the cross-product. - * There needs to be separate information for each display, because - * it's possible to have multiple focus windows active simultaneously - * on different displays. There also needs to be separate information - * for each application, because of embedding: if an embedded - * application has the focus, its container application also has - * the focus. Thus we keep a list of structures for each application: - * the same display can appear in structures for several applications - * at once. + * One of the following structures exists for each display used by each + * application. These are linked together from the TkMainInfo structure. + * These structures are needed because it isn't sufficient to store a single + * piece of focus information in each display or in each application: we need + * the cross-product. There needs to be separate information for each display, + * because it's possible to have multiple focus windows active simultaneously + * on different displays. There also needs to be separate information for each + * application, because of embedding: if an embedded application has the + * focus, its container application also has the focus. Thus we keep a list of + * structures for each application: the same display can appear in structures + * for several applications at once. */ typedef struct TkDisplayFocusInfo { @@ -58,49 +53,54 @@ typedef struct TkDisplayFocusInfo { * supposed to receive the X input focus as * soon as it is mapped (needed to handle the * fact that X won't allow the focus on an - * unmapped window). NULL means no delayed + * unmapped window). NULL means no delayed * focus op in progress for this display. */ - int forceFocus; /* Associated with focusOnMapPtr: non-zero + int forceFocus; /* Associated with focusOnMapPtr: non-zero * means claim the focus even if some other * application currently has it. */ unsigned long focusSerial; /* Serial number of last request this * application made to change the focus on - * this display. Used to identify stale - * focus notifications coming from the - * X server. */ + * this display. Used to identify stale focus + * notifications coming from the X server. */ struct TkDisplayFocusInfo *nextPtr; - /* Next in list of all display focus - * records for a given application. */ + /* Next in list of all display focus records + * for a given application. */ } DisplayFocusInfo; /* - * The following magic value is stored in the "send_event" field of - * FocusIn and FocusOut events that are generated in this file. This - * allows us to separate "real" events coming from the server from - * those that we generated. + * The following magic value is stored in the "send_event" field of FocusIn + * and FocusOut events that are generated in this file. This allows us to + * separate "real" events coming from the server from those that we generated. */ -#define GENERATED_EVENT_MAGIC ((Bool) 0x547321ac) +#define GENERATED_EVENT_MAGIC ((Bool) 0x547321ac) /* - * Forward declarations for procedures defined in this file: + * Debugging support... */ +#define DEBUG(dispPtr, arguments) \ + if ((dispPtr)->focusDebug) { \ + printf arguments; \ + } -static DisplayFocusInfo *FindDisplayFocusInfo _ANSI_ARGS_((TkMainInfo *mainPtr, - TkDisplay *dispPtr)); -static void FocusMapProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void GenerateFocusEvents _ANSI_ARGS_((TkWindow *sourcePtr, - TkWindow *destPtr)); +/* + * Forward declarations for functions defined in this file: + */ + +static DisplayFocusInfo*FindDisplayFocusInfo(TkMainInfo *mainPtr, + TkDisplay *dispPtr); +static void FocusMapProc(ClientData clientData, XEvent *eventPtr); +static void GenerateFocusEvents(TkWindow *sourcePtr, + TkWindow *destPtr); /* *-------------------------------------------------------------- * * Tk_FocusObjCmd -- * - * This procedure is invoked to process the "focus" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "focus" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -112,15 +112,14 @@ static void GenerateFocusEvents _ANSI_ARGS_((TkWindow *sourcePtr, */ int -Tk_FocusObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_FocusObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { static CONST char *focusOptions[] = { - "-displayof", "-force", "-lastfor", (char *) NULL + "-displayof", "-force", "-lastfor", NULL }; Tk_Window tkwin = (Tk_Window) clientData; TkWindow *winPtr = (TkWindow *) clientData; @@ -142,17 +141,17 @@ Tk_FocusObjCmd(clientData, interp, objc, objv) } /* - * If invoked with a single argument beginning with "." then focus - * on that window. + * If invoked with a single argument beginning with "." then focus on that + * window. */ if (objc == 2) { - windowName = Tcl_GetStringFromObj(objv[1], NULL); + windowName = Tcl_GetString(objv[1]); /* * The empty string case exists for backwards compatibility. */ - + if (windowName[0] == '\0') { return TCL_OK; } @@ -168,6 +167,10 @@ Tk_FocusObjCmd(clientData, interp, objc, objv) } } + /* + * We have a subcommand to parse and act upon. + */ + if (Tcl_GetIndexFromObj(interp, objv[1], focusOptions, "option", 0, &index) != TCL_OK) { return TCL_ERROR; @@ -177,63 +180,58 @@ Tk_FocusObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } switch (index) { - case 0: { /* -displayof */ - windowName = Tcl_GetStringFromObj(objv[2], NULL); - newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin); - if (newPtr == NULL) { - return TCL_ERROR; - } - newPtr = TkGetFocusWin(newPtr); - if (newPtr != NULL) { - Tcl_SetResult(interp, newPtr->pathName, TCL_STATIC); - } - break; + case 0: /* -displayof */ + windowName = Tcl_GetString(objv[2]); + newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin); + if (newPtr == NULL) { + return TCL_ERROR; + } + newPtr = TkGetFocusWin(newPtr); + if (newPtr != NULL) { + Tcl_SetResult(interp, newPtr->pathName, TCL_STATIC); } - case 1: { /* -force */ - windowName = Tcl_GetStringFromObj(objv[2], NULL); + break; + case 1: /* -force */ + windowName = Tcl_GetString(objv[2]); - /* - * The empty string case exists for backwards compatibility. - */ - - if (windowName[0] == '\0') { - return TCL_OK; - } - newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin); - if (newPtr == NULL) { - return TCL_ERROR; - } - TkSetFocusWin(newPtr, 1); - break; + /* + * The empty string case exists for backwards compatibility. + */ + + if (windowName[0] == '\0') { + return TCL_OK; } - case 2: { /* -lastfor */ - windowName = Tcl_GetStringFromObj(objv[2], NULL); - newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin); - if (newPtr == NULL) { - return TCL_ERROR; + newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin); + if (newPtr == NULL) { + return TCL_ERROR; + } + TkSetFocusWin(newPtr, 1); + break; + case 2: /* -lastfor */ + windowName = Tcl_GetString(objv[2]); + newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin); + if (newPtr == NULL) { + return TCL_ERROR; + } + for (topLevelPtr = newPtr; topLevelPtr != NULL; + topLevelPtr = topLevelPtr->parentPtr) { + if (!(topLevelPtr->flags & TK_TOP_HIERARCHY)) { + continue; } - for (topLevelPtr = newPtr; topLevelPtr != NULL; - topLevelPtr = topLevelPtr->parentPtr) { - if (topLevelPtr->flags & TK_TOP_HIERARCHY) { - for (tlFocusPtr = newPtr->mainPtr->tlFocusPtr; - tlFocusPtr != NULL; - tlFocusPtr = tlFocusPtr->nextPtr) { - if (tlFocusPtr->topLevelPtr == topLevelPtr) { - Tcl_SetResult(interp, - tlFocusPtr->focusWinPtr->pathName, - TCL_STATIC); - return TCL_OK; - } - } - Tcl_SetResult(interp, topLevelPtr->pathName, TCL_STATIC); + for (tlFocusPtr = newPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; + tlFocusPtr = tlFocusPtr->nextPtr) { + if (tlFocusPtr->topLevelPtr == topLevelPtr) { + Tcl_SetResult(interp, + tlFocusPtr->focusWinPtr->pathName, TCL_STATIC); return TCL_OK; } } - break; - } - default: { - panic("bad const entries to focusOptions in focus command"); + Tcl_SetResult(interp, topLevelPtr->pathName, TCL_STATIC); + return TCL_OK; } + break; + default: + Tcl_Panic("bad const entries to focusOptions in focus command"); } return TCL_OK; } @@ -243,13 +241,13 @@ Tk_FocusObjCmd(clientData, interp, objc, objv) * * TkFocusFilterEvent -- * - * This procedure is invoked by Tk_HandleEvent when it encounters - * a FocusIn, FocusOut, Enter, or Leave event. + * This function is invoked by Tk_HandleEvent when it encounters a + * FocusIn, FocusOut, Enter, or Leave event. * * Results: - * A return value of 1 means that Tk_HandleEvent should process - * the event normally (i.e. event handlers should be invoked). - * A return value of 0 means that this event should be ignored. + * A return value of 1 means that Tk_HandleEvent should process the event + * normally (i.e. event handlers should be invoked). A return value of 0 + * means that this event should be ignored. * * Side effects: * Additional events may be generated, and the focus may switch. @@ -258,27 +256,25 @@ Tk_FocusObjCmd(clientData, interp, objc, objv) */ int -TkFocusFilterEvent(winPtr, eventPtr) - TkWindow *winPtr; /* Window that focus event is directed to. */ - XEvent *eventPtr; /* FocusIn, FocusOut, Enter, or Leave +TkFocusFilterEvent( + TkWindow *winPtr, /* Window that focus event is directed to. */ + XEvent *eventPtr) /* FocusIn, FocusOut, Enter, or Leave * event. */ { /* - * Design notes: the window manager and X server work together to - * transfer the focus among top-level windows. This procedure takes - * care of transferring the focus from a top-level or wrapper window - * to the actual window within that top-level that has the focus. - * We do this by synthesizing X events to move the focus around. - * None of the FocusIn and FocusOut events generated by X are ever - * used outside of this procedure; only the synthesized events get - * through to the rest of the application. At one point (e.g. - * Tk4.0b1) Tk used to call X to move the focus from a top-level to - * one of its descendants, then just pass through the events - * generated by X. This approach didn't work very well, for a - * variety of reasons. For example, if X generates the events they - * go at the back of the event queue, which could cause problems if - * other things have already happened, such as moving the focus to - * yet another window. + * Design notes: the window manager and X server work together to transfer + * the focus among top-level windows. This function takes care of + * transferring the focus from a top-level or wrapper window to the actual + * window within that top-level that has the focus. We do this by + * synthesizing X events to move the focus around. None of the FocusIn and + * FocusOut events generated by X are ever used outside of this function; + * only the synthesized events get through to the rest of the application. + * At one point (e.g. Tk4.0b1) Tk used to call X to move the focus from a + * top-level to one of its descendants, then just pass through the events + * generated by X. This approach didn't work very well, for a variety of + * reasons. For example, if X generates the events they go at the back of + * the event queue, which could cause problems if other things have + * already happened, such as moving the focus to yet another window. */ ToplevelFocusInfo *tlFocusPtr; @@ -288,8 +284,8 @@ TkFocusFilterEvent(winPtr, eventPtr) int retValue, delta; /* - * If this was a generated event, just turn off the generated - * flag and pass the event through to Tk bindings. + * If this was a generated event, just turn off the generated flag and + * pass the event through to Tk bindings. */ if (eventPtr->xfocus.send_event == GENERATED_EVENT_MAGIC) { @@ -298,11 +294,11 @@ TkFocusFilterEvent(winPtr, eventPtr) } /* - * Check for special events generated by embedded applications to - * request the input focus. If this is one of those events, make - * the change in focus and return without any additional processing - * of the event (note: the "detail" field of the event indicates - * whether to claim the focus even if we don't already have it). + * Check for special events generated by embedded applications to request + * the input focus. If this is one of those events, make the change in + * focus and return without any additional processing of the event (note: + * the "detail" field of the event indicates whether to claim the focus + * even if we don't already have it). */ if ((eventPtr->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS) @@ -312,10 +308,9 @@ TkFocusFilterEvent(winPtr, eventPtr) } /* - * This was not a generated event. We'll return 1 (so that the - * event will be processed) if it's an Enter or Leave event, and - * 0 (so that the event won't be processed) if it's a FocusIn or - * FocusOut event. + * This was not a generated event. We'll return 1 (so that the event will + * be processed) if it's an Enter or Leave event, and 0 (so that the event + * won't be processed) if it's a FocusIn or FocusOut event. */ retValue = 0; @@ -323,26 +318,26 @@ TkFocusFilterEvent(winPtr, eventPtr) if (eventPtr->type == FocusIn) { /* * Skip FocusIn events that cause confusion - * NotifyVirtual and NotifyNonlinearVirtual - Virtual events occur - * on windows in between the origin and destination of the - * focus change. For FocusIn we may see this when focus - * goes into an embedded child. We don't care about this, - * although we may end up getting a NotifyPointer later. - * NotifyInferior - focus is coming to us from an embedded child. - * When focus is on an embeded focus, we still think we have - * the focus, too, so this message doesn't change our state. - * NotifyPointerRoot - should never happen because this is sent - * to the root window. + * NotifyVirtual and NotifyNonlinearVirtual - Virtual events occur on + * windows in between the origin and destination of the focus + * change. For FocusIn we may see this when focus goes into an + * embedded child. We don't care about this, although we may end + * up getting a NotifyPointer later. + * NotifyInferior - focus is coming to us from an embedded child. When + * focus is on an embeded focus, we still think we have the + * focus, too, so this message doesn't change our state. + * NotifyPointerRoot - should never happen because this is sent to the + * root window. * * Interesting FocusIn events are * NotifyAncestor - focus is coming from our parent, probably the root. * NotifyNonlinear - focus is coming from a different branch, probably * another toplevel. - * NotifyPointer - implicit focus because of the mouse position. - * This is only interesting on toplevels, when it means that the - * focus has been set to the root window but the mouse is over - * this toplevel. We take the focus implicitly (probably no - * window manager) + * NotifyPointer - implicit focus because of the mouse position. This + * is only interesting on toplevels, when it means that the focus + * has been set to the root window but the mouse is over this + * toplevel. We take the focus implicitly (probably no window + * manager) */ if ((eventPtr->xfocus.detail == NotifyVirtual) @@ -355,12 +350,12 @@ TkFocusFilterEvent(winPtr, eventPtr) /* * Skip FocusOut events that cause confusion. * NotifyPointer - the pointer is in us or a child, and we are losing - * focus because of an XSetInputFocus. Other focus events - * will set our state properly. - * NotifyPointerRoot - should never happen because this is sent - * to the root window. - * NotifyInferior - focus leaving us for an embedded child. We - * retain a notion of focus when an embedded child has focus. + * focus because of an XSetInputFocus. Other focus events will + * set our state properly. + * NotifyPointerRoot - should never happen because this is sent to the + * root window. + * NotifyInferior - focus leaving us for an embedded child. We retain + * a notion of focus when an embedded child has focus. * * Interesting events are: * NotifyAncestor - focus is going to root. @@ -392,8 +387,8 @@ TkFocusFilterEvent(winPtr, eventPtr) } /* - * If there is a grab in effect and this window is outside the - * grabbed tree, then ignore the event. + * If there is a grab in effect and this window is outside the grabbed + * tree, then ignore the event. */ if (TkGrabState(winPtr) == TK_GRAB_EXCLUDED) { @@ -401,16 +396,15 @@ TkFocusFilterEvent(winPtr, eventPtr) } /* - * It is possible that there were outstanding FocusIn and FocusOut - * events on their way to us at the time the focus was changed - * internally with the "focus" command. If so, these events could - * potentially cause us to lose the focus (switch it to the window - * of the last FocusIn event) even though the focus change occurred - * after those events. The following code detects this and ignores - * the stale events. + * It is possible that there were outstanding FocusIn and FocusOut events + * on their way to us at the time the focus was changed internally with + * the "focus" command. If so, these events could potentially cause us to + * lose the focus (switch it to the window of the last FocusIn event) even + * though the focus change occurred after those events. The following code + * detects this and ignores the stale events. * - * Note: the focusSerial is only generated by TkpChangeFocus, - * whereas in Tk 4.2 there was always a nop marker generated. + * Note: the focusSerial is only generated by TkpChangeFocus, whereas in + * Tk 4.2 there was always a nop marker generated. */ delta = eventPtr->xfocus.serial - displayFocusPtr->focusSerial; @@ -440,6 +434,7 @@ TkFocusFilterEvent(winPtr, eventPtr) /* * Ignore event if newFocus window is already dead! */ + if (newFocusPtr->flags & TK_ALREADY_DEAD) { return retValue; } @@ -451,7 +446,7 @@ TkFocusFilterEvent(winPtr, eventPtr) /* * NotifyPointer gets set when the focus has been set to the root - * window but we have the pointer. We'll treat this like an implicit + * window but we have the pointer. We'll treat this like an implicit * focus in event so that upon Leave events we release focus. */ @@ -463,12 +458,12 @@ TkFocusFilterEvent(winPtr, eventPtr) } } } else if (eventPtr->type == FocusOut) { - GenerateFocusEvents(displayFocusPtr->focusWinPtr, (TkWindow *) NULL); + GenerateFocusEvents(displayFocusPtr->focusWinPtr, NULL); /* - * Reset dispPtr->focusPtr, but only if it currently is the same - * as this application's focusWinPtr: this check is needed to - * handle embedded applications in the same process. + * Reset dispPtr->focusPtr, but only if it currently is the same as + * this application's focusWinPtr: this check is needed to handle + * embedded applications in the same process. */ if (dispPtr->focusPtr == displayFocusPtr->focusWinPtr) { @@ -478,25 +473,22 @@ TkFocusFilterEvent(winPtr, eventPtr) } else if (eventPtr->type == EnterNotify) { /* * If there is no window manager, or if the window manager isn't - * moving the focus around (e.g. the disgusting "NoTitleFocus" - * option has been selected in twm), then we won't get FocusIn - * or FocusOut events. Instead, the "focus" field will be set - * in an Enter event to indicate that we've already got the focus - * when the mouse enters the window (even though we didn't get - * a FocusIn event). Watch for this and grab the focus when it - * happens. Note: if this is an embedded application then don't - * accept the focus implicitly like this; the container - * application will give us the focus explicitly if it wants us - * to have it. + * moving the focus around (e.g. the disgusting "NoTitleFocus" option + * has been selected in twm), then we won't get FocusIn or FocusOut + * events. Instead, the "focus" field will be set in an Enter event to + * indicate that we've already got the focus when the mouse enters the + * window (even though we didn't get a FocusIn event). Watch for this + * and grab the focus when it happens. Note: if this is an embedded + * application then don't accept the focus implicitly like this; the + * container application will give us the focus explicitly if it wants + * us to have it. */ if (eventPtr->xcrossing.focus && - (displayFocusPtr->focusWinPtr == NULL) + (displayFocusPtr->focusWinPtr == NULL) && !(winPtr->flags & TK_EMBEDDED)) { - if (dispPtr->focusDebug) { - printf("Focussed implicitly on %s\n", - newFocusPtr->pathName); - } + DEBUG(dispPtr, + ("Focussed implicitly on %s\n", newFocusPtr->pathName)); GenerateFocusEvents(displayFocusPtr->focusWinPtr, newFocusPtr); displayFocusPtr->focusWinPtr = newFocusPtr; @@ -507,22 +499,19 @@ TkFocusFilterEvent(winPtr, eventPtr) /* * If the pointer just left a window for which we automatically * claimed the focus on enter, move the focus back to the root - * window, where it was before we claimed it above. Note: + * window, where it was before we claimed it above. Note: * dispPtr->implicitWinPtr may not be the same as - * displayFocusPtr->focusWinPtr (e.g. because the "focus" - * command was used to redirect the focus after it arrived at - * dispPtr->implicitWinPtr)!! In addition, we generate events + * displayFocusPtr->focusWinPtr (e.g. because the "focus" command + * was used to redirect the focus after it arrived at + * dispPtr->implicitWinPtr)!! In addition, we generate events * because the window manager won't give us a FocusOut event when - * we focus on the root. + * we focus on the root. */ if ((dispPtr->implicitWinPtr != NULL) && !(winPtr->flags & TK_EMBEDDED)) { - if (dispPtr->focusDebug) { - printf("Defocussed implicit Async\n"); - } - GenerateFocusEvents(displayFocusPtr->focusWinPtr, - (TkWindow *) NULL); + DEBUG(dispPtr, ("Defocussed implicit Async\n")); + GenerateFocusEvents(displayFocusPtr->focusWinPtr, NULL); XSetInputFocus(dispPtr->display, PointerRoot, RevertToPointerRoot, CurrentTime); displayFocusPtr->focusWinPtr = NULL; @@ -537,8 +526,8 @@ TkFocusFilterEvent(winPtr, eventPtr) * * TkSetFocusWin -- * - * This procedure is invoked to change the focus window for a - * given display in a given application. + * This function is invoked to change the focus window for a given + * display in a given application. * * Results: * None. @@ -551,12 +540,12 @@ TkFocusFilterEvent(winPtr, eventPtr) */ void -TkSetFocusWin(winPtr, force) - TkWindow *winPtr; /* Window that is to be the new focus for - * its display and application. */ - int force; /* If non-zero, set the X focus to this - * window even if the application doesn't - * currently have the X focus. */ +TkSetFocusWin( + TkWindow *winPtr, /* Window that is to be the new focus for its + * display and application. */ + int force) /* If non-zero, set the X focus to this window + * even if the application doesn't currently + * have the X focus. */ { ToplevelFocusInfo *tlFocusPtr; DisplayFocusInfo *displayFocusPtr; @@ -566,9 +555,9 @@ TkSetFocusWin(winPtr, force) displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); /* - * If force is set, we should make sure we grab the focus regardless - * of the current focus window since under Windows, we may need to - * take control away from another application. + * If force is set, we should make sure we grab the focus regardless of + * the current focus window since under Windows, we may need to take + * control away from another application. */ if (winPtr == displayFocusPtr->focusWinPtr && !force) { @@ -576,18 +565,19 @@ TkSetFocusWin(winPtr, force) } /* - * Find the top-level window for winPtr, then find (or create) - * a record for the top-level. Also see whether winPtr and all its - * ancestors are mapped. + * Find the top-level window for winPtr, then find (or create) a record + * for the top-level. Also see whether winPtr and all its ancestors are + * mapped. */ allMapped = 1; for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) { if (topLevelPtr == NULL) { /* - * The window is being deleted. No point in worrying about - * giving it the focus. + * The window is being deleted. No point in worrying about giving + * it the focus. */ + return; } if (!(topLevelPtr->flags & TK_MAPPED)) { @@ -599,11 +589,11 @@ TkSetFocusWin(winPtr, force) } /* - * If the new focus window isn't mapped, then we can't focus on it - * (X will generate an error, for example). Instead, create an - * event handler that will set the focus to this window once it gets - * mapped. At the same time, delete any old handler that might be - * around; it's no longer relevant. + * If the new focus window isn't mapped, then we can't focus on it (X will + * generate an error, for example). Instead, create an event handler that + * will set the focus to this window once it gets mapped. At the same + * time, delete any old handler that might be around; it's no longer + * relevant. */ if (displayFocusPtr->focusOnMapPtr != NULL) { @@ -637,16 +627,15 @@ TkSetFocusWin(winPtr, force) tlFocusPtr->focusWinPtr = winPtr; /* - * Reset the window system's focus window and generate focus events, - * with two special cases: + * Reset the window system's focus window and generate focus events, with + * two special cases: * - * 1. If the application is embedded and doesn't currently have the - * focus, don't set the focus directly. Instead, see if the - * embedding code can claim the focus from the enclosing - * container. - * 2. Otherwise, if the application doesn't currently have the - * focus, don't change the window system's focus unless it was - * already in this application or "force" was specified. + * 1. If the application is embedded and doesn't currently have the focus, + * don't set the focus directly. Instead, see if the embedding code can + * claim the focus from the enclosing container. + * 2. Otherwise, if the application doesn't currently have the focus, + * don't change the window system's focus unless it was already in this + * application or "force" was specified. */ if ((topLevelPtr->flags & TK_EMBEDDED) @@ -654,12 +643,11 @@ TkSetFocusWin(winPtr, force) TkpClaimFocus(topLevelPtr, force); } else if ((displayFocusPtr->focusWinPtr != NULL) || force) { /* - * Generate events to shift focus between Tk windows. - * We do this regardless of what TkpChangeFocus does with - * the real X focus so that Tk widgets track focus commands - * when there is no window manager. GenerateFocusEvents will - * set up a serial number marker so we discard focus events - * that are triggered by the ChangeFocus. + * Generate events to shift focus between Tk windows. We do this + * regardless of what TkpChangeFocus does with the real X focus so + * that Tk widgets track focus commands when there is no window + * manager. GenerateFocusEvents will set up a serial number marker so + * we discard focus events that are triggered by the ChangeFocus. */ serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force); @@ -677,13 +665,13 @@ TkSetFocusWin(winPtr, force) * * TkGetFocusWin -- * - * Given a window, this procedure returns the current focus - * window for its application and display. + * Given a window, this function returns the current focus window for its + * application and display. * * Results: - * The return value is a pointer to the window that currently - * has the input focus for the specified application and - * display, or NULL if none. + * The return value is a pointer to the window that currently has the + * input focus for the specified application and display, or NULL if + * none. * * Side effects: * None. @@ -692,14 +680,14 @@ TkSetFocusWin(winPtr, force) */ TkWindow * -TkGetFocusWin(winPtr) - TkWindow *winPtr; /* Window that selects an application - * and a display. */ +TkGetFocusWin( + TkWindow *winPtr) /* Window that selects an application and a + * display. */ { DisplayFocusInfo *displayFocusPtr; if (winPtr == NULL) { - return (TkWindow *) NULL; + return NULL; } displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); @@ -711,16 +699,16 @@ TkGetFocusWin(winPtr) * * TkFocusKeyEvent -- * - * Given a window and a key press or release event that arrived for - * the window, use information about the keyboard focus to compute - * which window should really get the event. In addition, update - * the event to refer to its new window. + * Given a window and a key press or release event that arrived for the + * window, use information about the keyboard focus to compute which + * window should really get the event. In addition, update the event to + * refer to its new window. * * Results: - * The return value is a pointer to the window that has the input - * focus in winPtr's application, or NULL if winPtr's application - * doesn't have the input focus. If a non-NULL value is returned, - * eventPtr will be updated to refer properly to the focus window. + * The return value is a pointer to the window that has the input focus + * in winPtr's application, or NULL if winPtr's application doesn't have + * the input focus. If a non-NULL value is returned, eventPtr will be + * updated to refer properly to the focus window. * * Side effects: * None. @@ -729,11 +717,11 @@ TkGetFocusWin(winPtr) */ TkWindow * -TkFocusKeyEvent(winPtr, eventPtr) - TkWindow *winPtr; /* Window that selects an application - * and a display. */ - XEvent *eventPtr; /* X event to redirect (should be KeyPress - * or KeyRelease). */ +TkFocusKeyEvent( + TkWindow *winPtr, /* Window that selects an application and a + * display. */ + XEvent *eventPtr) /* X event to redirect (should be KeyPress or + * KeyRelease). */ { DisplayFocusInfo *displayFocusPtr; TkWindow *focusWinPtr; @@ -760,9 +748,9 @@ TkFocusKeyEvent(winPtr, eventPtr) if ((focusWinPtr != NULL) && (focusWinPtr->mainPtr == winPtr->mainPtr)) { /* - * Map the x and y coordinates to make sense in the context of - * the focus window, if possible (make both -1 if the map-from - * and map-to windows don't share the same screen). + * Map the x and y coordinates to make sense in the context of the + * focus window, if possible (make both -1 if the map-from and map-to + * windows don't share the same screen). */ if ((focusWinPtr->display != winPtr->display) @@ -781,13 +769,13 @@ TkFocusKeyEvent(winPtr, eventPtr) } /* - * The event doesn't belong to us. Perhaps, due to embedding, it - * really belongs to someone else. Give the embedding code a chance - * to redirect the event. + * The event doesn't belong to us. Perhaps, due to embedding, it really + * belongs to someone else. Give the embedding code a chance to redirect + * the event. */ TkpRedirectKeyEvent(winPtr, eventPtr); - return (TkWindow *) NULL; + return NULL; } /* @@ -795,9 +783,8 @@ TkFocusKeyEvent(winPtr, eventPtr) * * TkFocusDeadWindow -- * - * This procedure is invoked when it is determined that - * a window is dead. It cleans up focus-related information - * about the window. + * This function is invoked when it is determined that a window is dead. + * It cleans up focus-related information about the window. * * Results: * None. @@ -809,25 +796,26 @@ TkFocusKeyEvent(winPtr, eventPtr) */ void -TkFocusDeadWindow(winPtr) - register TkWindow *winPtr; /* Information about the window - * that is being deleted. */ +TkFocusDeadWindow( + register TkWindow *winPtr) /* Information about the window that is being + * deleted. */ { ToplevelFocusInfo *tlFocusPtr, *prevPtr; DisplayFocusInfo *displayFocusPtr; TkDisplay *dispPtr = winPtr->dispPtr; /* - * Certain special windows like those used for send and clipboard - * have no mainPtr. + * Certain special windows like those used for send and clipboard have no + * mainPtr. */ - if (winPtr->mainPtr == NULL) - return; + if (winPtr->mainPtr == NULL) { + return; + } /* - * Search for focus records that refer to this window either as - * the top-level window or the current focus window. + * Search for focus records that refer to this window either as the + * top-level window or the current focus window. */ displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); @@ -836,16 +824,14 @@ TkFocusDeadWindow(winPtr) prevPtr = tlFocusPtr, tlFocusPtr = tlFocusPtr->nextPtr) { if (winPtr == tlFocusPtr->topLevelPtr) { /* - * The top-level window is the one being deleted: free - * the focus record and release the focus back to PointerRoot - * if we acquired it implicitly. + * The top-level window is the one being deleted: free the focus + * record and release the focus back to PointerRoot if we acquired + * it implicitly. */ if (dispPtr->implicitWinPtr == winPtr) { - if (dispPtr->focusDebug) { - printf("releasing focus to root after %s died\n", - tlFocusPtr->topLevelPtr->pathName); - } + DEBUG(dispPtr, ("releasing focus to root after %s died\n", + tlFocusPtr->topLevelPtr->pathName)); dispPtr->implicitWinPtr = NULL; displayFocusPtr->focusWinPtr = NULL; dispPtr->focusPtr = NULL; @@ -863,18 +849,15 @@ TkFocusDeadWindow(winPtr) break; } else if (winPtr == tlFocusPtr->focusWinPtr) { /* - * The deleted window had the focus for its top-level: - * move the focus to the top-level itself. + * The deleted window had the focus for its top-level: move the + * focus to the top-level itself. */ tlFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr; if ((displayFocusPtr->focusWinPtr == winPtr) && !(tlFocusPtr->topLevelPtr->flags & TK_ALREADY_DEAD)) { - if (dispPtr->focusDebug) { - printf("forwarding focus to %s after %s died\n", - tlFocusPtr->topLevelPtr->pathName, - winPtr->pathName); - } + DEBUG(dispPtr, ("forwarding focus to %s after %s died\n", + tlFocusPtr->topLevelPtr->pathName, winPtr->pathName)); GenerateFocusEvents(displayFocusPtr->focusWinPtr, tlFocusPtr->topLevelPtr); displayFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr; @@ -890,9 +873,7 @@ TkFocusDeadWindow(winPtr) */ if (displayFocusPtr->focusWinPtr == winPtr) { - if (dispPtr->focusDebug) { - printf("focus cleared after %s died\n", winPtr->pathName); - } + DEBUG(dispPtr, ("focus cleared after %s died\n", winPtr->pathName)); displayFocusPtr->focusWinPtr = NULL; } @@ -906,8 +887,8 @@ TkFocusDeadWindow(winPtr) * * GenerateFocusEvents -- * - * This procedure is called to create FocusIn and FocusOut events to - * move the input focus from one window to another. + * This function is called to create FocusIn and FocusOut events to move + * the input focus from one window to another. * * Results: * None. @@ -919,12 +900,11 @@ TkFocusDeadWindow(winPtr) */ static void -GenerateFocusEvents(sourcePtr, destPtr) - TkWindow *sourcePtr; /* Window that used to have the focus (may - * be NULL). */ - TkWindow *destPtr; /* New window to have the focus (may be +GenerateFocusEvents( + TkWindow *sourcePtr, /* Window that used to have the focus (may be + * NULL). */ + TkWindow *destPtr) /* New window to have the focus (may be * NULL). */ - { XEvent event; TkWindow *winPtr; @@ -950,26 +930,26 @@ GenerateFocusEvents(sourcePtr, destPtr) * * FocusMapProc -- * - * This procedure is called as an event handler for VisibilityNotify - * events, if a window receives the focus at a time when its - * toplevel isn't mapped. The procedure is needed because X - * won't allow the focus to be set to an unmapped window; we - * detect when the toplevel is mapped and set the focus to it then. + * This function is called as an event handler for VisibilityNotify + * events, if a window receives the focus at a time when its toplevel + * isn't mapped. The function is needed because X won't allow the focus + * to be set to an unmapped window; we detect when the toplevel is mapped + * and set the focus to it then. * * Results: * None. * * Side effects: - * If this is a map event, the focus gets set to the toplevel - * given by clientData. + * If this is a map event, the focus gets set to the toplevel given by + * clientData. * *---------------------------------------------------------------------- */ static void -FocusMapProc(clientData, eventPtr) - ClientData clientData; /* Toplevel window. */ - XEvent *eventPtr; /* Information about event. */ +FocusMapProc( + ClientData clientData, /* Toplevel window. */ + XEvent *eventPtr) /* Information about event. */ { TkWindow *winPtr = (TkWindow *) clientData; DisplayFocusInfo *displayFocusPtr; @@ -977,10 +957,8 @@ FocusMapProc(clientData, eventPtr) if (eventPtr->type == VisibilityNotify) { displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); - if (winPtr->dispPtr->focusDebug) { - printf("auto-focussing on %s, force %d\n", winPtr->pathName, - displayFocusPtr->forceFocus); - } + DEBUG(winPtr->dispPtr, ("auto-focussing on %s, force %d\n", + winPtr->pathName, displayFocusPtr->forceFocus)); Tk_DeleteEventHandler((Tk_Window) winPtr, VisibilityChangeMask, FocusMapProc, clientData); displayFocusPtr->focusOnMapPtr = NULL; @@ -993,9 +971,9 @@ FocusMapProc(clientData, eventPtr) * * FindDisplayFocusInfo -- * - * Given an application and a display, this procedure locate the - * focus record for that combination. If no such record exists, - * it creates a new record and initializes it. + * Given an application and a display, this function locate the focus + * record for that combination. If no such record exists, it creates a + * new record and initializes it. * * Results: * The return value is a pointer to the record. @@ -1007,10 +985,10 @@ FocusMapProc(clientData, eventPtr) */ static DisplayFocusInfo * -FindDisplayFocusInfo(mainPtr, dispPtr) - TkMainInfo *mainPtr; /* Record that identifies a particular +FindDisplayFocusInfo( + TkMainInfo *mainPtr, /* Record that identifies a particular * application. */ - TkDisplay *dispPtr; /* Display whose focus information is + TkDisplay *dispPtr) /* Display whose focus information is * needed. */ { DisplayFocusInfo *displayFocusPtr; @@ -1024,7 +1002,7 @@ FindDisplayFocusInfo(mainPtr, dispPtr) } /* - * The record doesn't exist yet. Make a new one. + * The record doesn't exist yet. Make a new one. */ displayFocusPtr = (DisplayFocusInfo *) ckalloc(sizeof(DisplayFocusInfo)); @@ -1055,21 +1033,154 @@ FindDisplayFocusInfo(mainPtr, dispPtr) */ void -TkFocusFree(mainPtr) - TkMainInfo *mainPtr; /* Record that identifies a particular +TkFocusFree( + TkMainInfo *mainPtr) /* Record that identifies a particular * application. */ { - DisplayFocusInfo *displayFocusPtr; - ToplevelFocusInfo *tlFocusPtr; - while (mainPtr->displayFocusPtr != NULL) { - displayFocusPtr = mainPtr->displayFocusPtr; + DisplayFocusInfo *displayFocusPtr = mainPtr->displayFocusPtr; + mainPtr->displayFocusPtr = mainPtr->displayFocusPtr->nextPtr; ckfree((char *) displayFocusPtr); } while (mainPtr->tlFocusPtr != NULL) { - tlFocusPtr = mainPtr->tlFocusPtr; + ToplevelFocusInfo *tlFocusPtr = mainPtr->tlFocusPtr; + mainPtr->tlFocusPtr = mainPtr->tlFocusPtr->nextPtr; ckfree((char *) tlFocusPtr); } } + +/* + *---------------------------------------------------------------------- + * + * TkFocusSplit -- + * + * Adjust focus window for a newly managed toplevel, thus splitting + * the toplevel into two toplevels. + * + * Results: + * None. + * + * Side effects: + * A new record is allocated for the new toplevel window. + * + *---------------------------------------------------------------------- + */ + +void +TkFocusSplit(winPtr) + TkWindow *winPtr; /* Window is the new toplevel + * Any focus point at or below window + * must be moved to this new toplevel */ +{ + ToplevelFocusInfo *tlFocusPtr; + TkWindow *topLevelPtr; + TkWindow *subWinPtr; + + FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); + + /* + * Find the top-level window for winPtr, then find (or create) + * a record for the top-level. Also see whether winPtr and all its + * ancestors are mapped. + */ + + for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) { + if (topLevelPtr == NULL) { + /* + * The window is being deleted. No point in worrying about + * giving it the focus. + */ + return; + } + if (topLevelPtr->flags & TK_TOP_HIERARCHY) { + break; + } + } + + /* Search all focus records to find child windows of winPtr */ + for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; + tlFocusPtr = tlFocusPtr->nextPtr) { + if (tlFocusPtr->topLevelPtr == topLevelPtr) { + break; + } + } + + if (tlFocusPtr == NULL) { + /* No focus record for this toplevel, nothing to do. */ + return; + } + + /* See if current focusWin is child of the new toplevel */ + for (subWinPtr = tlFocusPtr->focusWinPtr; + subWinPtr && subWinPtr != winPtr && subWinPtr != topLevelPtr; + subWinPtr = subWinPtr->parentPtr) {} + + if (subWinPtr == winPtr) { + /* Move focus to new toplevel */ + ToplevelFocusInfo *newTlFocusPtr; + + newTlFocusPtr = (ToplevelFocusInfo *) ckalloc(sizeof(ToplevelFocusInfo)); + newTlFocusPtr->topLevelPtr = winPtr; + newTlFocusPtr->focusWinPtr = tlFocusPtr->focusWinPtr; + newTlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr; + winPtr->mainPtr->tlFocusPtr = newTlFocusPtr; + /* Move old toplevel's focus to the toplevel itself */ + tlFocusPtr->focusWinPtr = topLevelPtr; + } + /* If it's not, then let focus progress naturally */ +} + +/* + *---------------------------------------------------------------------- + * + * TkFocusJoin -- + * + * Remove the focus record for this window that is nolonger managed + * + * Results: + * None. + * + * Side effects: + * A tlFocusPtr record is removed + * + *---------------------------------------------------------------------- + */ + +void +TkFocusJoin(winPtr) + TkWindow *winPtr; /* Window is no longer a toplevel */ +{ + ToplevelFocusInfo *tlFocusPtr; + ToplevelFocusInfo *tmpPtr; + + /* + * Remove old toplevel record + */ + if (winPtr && winPtr->mainPtr && winPtr->mainPtr->tlFocusPtr + && winPtr->mainPtr->tlFocusPtr->topLevelPtr == winPtr) { + tmpPtr = winPtr->mainPtr->tlFocusPtr; + winPtr->mainPtr->tlFocusPtr = tmpPtr->nextPtr; + ckfree((char *)tmpPtr); + } else { + for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; + tlFocusPtr = tlFocusPtr->nextPtr) { + if (tlFocusPtr->nextPtr && + tlFocusPtr->nextPtr->topLevelPtr == winPtr) { + tmpPtr = tlFocusPtr->nextPtr; + tlFocusPtr->nextPtr = tmpPtr->nextPtr; + ckfree((char *)tmpPtr); + break; + } + } + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkFont.c b/generic/tkFont.c index 95feec3..1a6474f 100644 --- a/generic/tkFont.c +++ b/generic/tkFont.c @@ -1,44 +1,42 @@ -/* +/* * tkFont.c -- * - * This file maintains a database of fonts for the Tk toolkit. - * It also provides several utility procedures for measuring and - * displaying text. + * This file maintains a database of fonts for the Tk toolkit. It also + * provides several utility functions for measuring and displaying text. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" #include "tkFont.h" /* - * The following structure is used to keep track of all the fonts that - * exist in the current application. It must be stored in the - * TkMainInfo for the application. + * The following structure is used to keep track of all the fonts that exist + * in the current application. It must be stored in the TkMainInfo for the + * application. */ - + typedef struct TkFontInfo { - Tcl_HashTable fontCache; /* Map a string to an existing Tk_Font. - * Keys are string font names, values are - * TkFont pointers. */ + Tcl_HashTable fontCache; /* Map a string to an existing Tk_Font. Keys + * are string font names, values are TkFont + * pointers. */ Tcl_HashTable namedTable; /* Map a name to a set of attributes for a * font, used when constructing a Tk_Font from - * a named font description. Keys are - * strings, values are NamedFont pointers. */ + * a named font description. Keys are strings, + * values are NamedFont pointers. */ TkMainInfo *mainPtr; /* Application that owns this structure. */ int updatePending; /* Non-zero when a World Changed event has - * already been queued to handle a change to - * a named font. */ + * already been queued to handle a change to a + * named font. */ } TkFontInfo; /* * The following data structure is used to keep track of the font attributes - * for each named font that has been defined. The named font is only deleted + * for each named font that has been defined. The named font is only deleted * when the last reference to it goes away. */ @@ -48,84 +46,83 @@ typedef struct NamedFont { * last reference goes away. */ TkFontAttributes fa; /* Desired attributes for named font. */ } NamedFont; - + /* - * The following two structures are used to keep track of string - * measurement information when using the text layout facilities. + * The following two structures are used to keep track of string measurement + * information when using the text layout facilities. * * A LayoutChunk represents a contiguous range of text that can be measured - * and displayed by low-level text calls. In general, chunks will be - * delimited by newlines and tabs. Low-level, platform-specific things - * like kerning and non-integer character widths may occur between the - * characters in a single chunk, but not between characters in different - * chunks. - * - * A TextLayout is a collection of LayoutChunks. It can be displayed with - * respect to any origin. It is the implementation of the Tk_TextLayout - * opaque token. + * and displayed by low-level text calls. In general, chunks will be delimited + * by newlines and tabs. Low-level, platform-specific things like kerning and + * non-integer character widths may occur between the characters in a single + * chunk, but not between characters in different chunks. + * + * A TextLayout is a collection of LayoutChunks. It can be displayed with + * respect to any origin. It is the implementation of the Tk_TextLayout opaque + * token. */ typedef struct LayoutChunk { - CONST char *start; /* Pointer to simple string to be displayed. + const char *start; /* Pointer to simple string to be displayed. * This is a pointer into the TkTextLayout's * string. */ int numBytes; /* The number of bytes in this chunk. */ int numChars; /* The number of characters in this chunk. */ int numDisplayChars; /* The number of characters to display when - * this chunk is displayed. Can be less than + * this chunk is displayed. Can be less than * numChars if extra space characters were - * absorbed by the end of the chunk. This - * will be < 0 if this is a chunk that is - * holding a tab or newline. */ + * absorbed by the end of the chunk. This will + * be < 0 if this is a chunk that is holding a + * tab or newline. */ int x, y; /* The origin of the first character in this * chunk with respect to the upper-left hand * corner of the TextLayout. */ - int totalWidth; /* Width in pixels of this chunk. Used - * when hit testing the invisible spaces at - * the end of a chunk. */ + int totalWidth; /* Width in pixels of this chunk. Used when + * hit testing the invisible spaces at the end + * of a chunk. */ int displayWidth; /* Width in pixels of the displayable - * characters in this chunk. Can be less than + * characters in this chunk. Can be less than * width if extra space characters were * absorbed by the end of the chunk. */ } LayoutChunk; typedef struct TextLayout { Tk_Font tkfont; /* The font used when laying out the text. */ - CONST char *string; /* The string that was layed out. */ - int width; /* The maximum width of all lines in the - * text layout. */ - int numChunks; /* Number of chunks actually used in - * following array. */ - LayoutChunk chunks[1]; /* Array of chunks. The actual size will - * be maxChunks. THIS FIELD MUST BE THE LAST - * IN THE STRUCTURE. */ + const char *string; /* The string that was layed out. */ + int width; /* The maximum width of all lines in the text + * layout. */ + int numChunks; /* Number of chunks actually used in following + * array. */ + LayoutChunk chunks[1]; /* Array of chunks. The actual size will be + * maxChunks. THIS FIELD MUST BE THE LAST IN + * THE STRUCTURE. */ } TextLayout; /* * The following structures are used as two-way maps between the values for - * the fields in the TkFontAttributes structure and the strings used in - * Tcl, when parsing both option-value format and style-list format font - * name strings. + * the fields in the TkFontAttributes structure and the strings used in Tcl, + * when parsing both option-value format and style-list format font name + * strings. */ -static TkStateMap weightMap[] = { +static const TkStateMap weightMap[] = { {TK_FW_NORMAL, "normal"}, {TK_FW_BOLD, "bold"}, {TK_FW_UNKNOWN, NULL} }; -static TkStateMap slantMap[] = { +static const TkStateMap slantMap[] = { {TK_FS_ROMAN, "roman"}, {TK_FS_ITALIC, "italic"}, {TK_FS_UNKNOWN, NULL} }; -static TkStateMap underlineMap[] = { +static const TkStateMap underlineMap[] = { {1, "underline"}, {0, NULL} }; -static TkStateMap overstrikeMap[] = { +static const TkStateMap overstrikeMap[] = { {1, "overstrike"}, {0, NULL} }; @@ -135,7 +132,7 @@ static TkStateMap overstrikeMap[] = { * TkFontAttributes. */ -static TkStateMap xlfdWeightMap[] = { +static const TkStateMap xlfdWeightMap[] = { {TK_FW_NORMAL, "normal"}, {TK_FW_NORMAL, "medium"}, {TK_FW_NORMAL, "book"}, @@ -144,16 +141,16 @@ static TkStateMap xlfdWeightMap[] = { {TK_FW_BOLD, "demi"}, {TK_FW_BOLD, "demibold"}, {TK_FW_NORMAL, NULL} /* Assume anything else is "normal". */ -}; +}; -static TkStateMap xlfdSlantMap[] = { +static const TkStateMap xlfdSlantMap[] = { {TK_FS_ROMAN, "r"}, {TK_FS_ITALIC, "i"}, {TK_FS_OBLIQUE, "o"}, {TK_FS_ROMAN, NULL} /* Assume anything else is "roman". */ }; -static TkStateMap xlfdSetwidthMap[] = { +static const TkStateMap xlfdSetwidthMap[] = { {TK_SW_NORMAL, "normal"}, {TK_SW_CONDENSE, "narrow"}, {TK_SW_CONDENSE, "semicondensed"}, @@ -162,11 +159,11 @@ static TkStateMap xlfdSetwidthMap[] = { }; /* - * The following structure and defines specify the valid builtin options - * when configuring a set of font attributes. + * The following structure and defines specify the valid builtin options when + * configuring a set of font attributes. */ -static CONST char *fontOpt[] = { +static const char *fontOpt[] = { "-family", "-size", "-weight", @@ -185,10 +182,10 @@ static CONST char *fontOpt[] = { #define FONT_NUMFIELDS 6 /* - * Hardcoded font aliases. These are used to describe (mostly) identical - * fonts whose names differ from platform to platform. If the - * user-supplied font name matches any of the names in one of the alias - * lists, the other names in the alias list are also automatically tried. + * Hardcoded font aliases. These are used to describe (mostly) identical fonts + * whose names differ from platform to platform. If the user-supplied font + * name matches any of the names in one of the alias lists, the other names in + * the alias list are also automatically tried. */ static char *timesAliases[] = { @@ -226,7 +223,7 @@ static char *gothicAliases[] = { /* Windows (MS goshikku). */ "\344\270\270\343\202\264\343\202\267\343\203\203\343\202\257\342\210\222\357\274\255", /* Mac (goshikku-M). */ - NULL + NULL }; static char *dingbatsAliases[] = { @@ -245,43 +242,46 @@ static char **fontAliases[] = { gothicAliases, dingbatsAliases, NULL -}; +}; /* - * Hardcoded font classes. If the character cannot be found in the base - * font, the classes are examined in order to see if some other similar - * font should be examined also. + * Hardcoded font classes. If the character cannot be found in the base font, + * the classes are examined in order to see if some other similar font should + * be examined also. */ static char *systemClass[] = { - "fixed", /* Unix. */ - /* Windows. */ - "chicago", "osaka", "sistemny", /* Mac. */ + "fixed", /* Unix. */ + /* Windows. */ + "chicago", "osaka", "sistemny", + /* Mac. */ NULL }; static char *serifClass[] = { - "times", "palatino", "mincho", /* All platforms. */ - "song ti", /* Unix. */ - "ms serif", "simplified arabic", /* Windows. */ - "latinski", /* Mac. */ + "times", "palatino", "mincho", + /* All platforms. */ + "song ti", /* Unix. */ + "ms serif", "simplified arabic", + /* Windows. */ + "latinski", /* Mac. */ NULL }; static char *sansClass[] = { - "helvetica", "gothic", /* All platforms. */ - /* Unix. */ + "helvetica", "gothic", /* All platforms. */ + /* Unix. */ "ms sans serif", "traditional arabic", - /* Windows. */ - "bastion", /* Mac. */ + /* Windows. */ + "bastion", /* Mac. */ NULL }; static char *monoClass[] = { - "courier", "gothic", /* All platforms. */ - "fangsong ti", /* Unix. */ - "simplified arabic fixed", /* Windows. */ - "monaco", "pryamoy", /* Mac. */ + "courier", "gothic", /* All platforms. */ + "fangsong ti", /* Unix. */ + "simplified arabic fixed", /* Windows. */ + "monaco", "pryamoy", /* Mac. */ NULL }; @@ -299,9 +299,9 @@ static char **fontFallbacks[] = { }; /* - * Global fallbacks. If the character could not be found in the preferred - * fallback list, this list is examined. If the character still cannot be - * found, all font families in the system are examined. + * Global fallbacks. If the character could not be found in the preferred + * fallback list, this list is examined. If the character still cannot be + * found, all font families in the system are examined. */ static char *globalFontClass[] = { @@ -314,43 +314,35 @@ static char *globalFontClass[] = { }; #define GetFontAttributes(tkfont) \ - ((CONST TkFontAttributes *) &((TkFont *) (tkfont))->fa) + ((const TkFontAttributes *) &((TkFont *) (tkfont))->fa) #define GetFontMetrics(tkfont) \ - ((CONST TkFontMetrics *) &((TkFont *) (tkfont))->fm) - - -static int ConfigAttributesObj _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, int objc, Tcl_Obj *CONST objv[], - TkFontAttributes *faPtr)); -static int CreateNamedFont _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *name, - TkFontAttributes *faPtr)); -static void DupFontObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, - Tcl_Obj *dupObjPtr)); -static int FieldSpecified _ANSI_ARGS_((CONST char *field)); -static void FreeFontObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); -static int GetAttributeInfoObj _ANSI_ARGS_((Tcl_Interp *interp, - CONST TkFontAttributes *faPtr, Tcl_Obj *objPtr)); -static LayoutChunk * NewChunk _ANSI_ARGS_((TextLayout **layoutPtrPtr, - int *maxPtr, CONST char *start, int numChars, - int curX, int newX, int y)); -static int ParseFontNameObj _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tcl_Obj *objPtr, - TkFontAttributes *faPtr)); -static void RecomputeWidgets _ANSI_ARGS_((TkWindow *winPtr)); -static int SetFontFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); -static void TheWorldHasChanged _ANSI_ARGS_(( - ClientData clientData)); -static void UpdateDependentFonts _ANSI_ARGS_((TkFontInfo *fiPtr, - Tk_Window tkwin, Tcl_HashEntry *namedHashPtr)); + ((const TkFontMetrics *) &((TkFont *) (tkfont))->fm) + + +static int ConfigAttributesObj(Tcl_Interp *interp, + Tk_Window tkwin, int objc, Tcl_Obj *const objv[], + TkFontAttributes *faPtr); +static void DupFontObjProc(Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr); +static int FieldSpecified(const char *field); +static void FreeFontObjProc(Tcl_Obj *objPtr); +static int GetAttributeInfoObj(Tcl_Interp *interp, + const TkFontAttributes *faPtr, Tcl_Obj *objPtr); +static LayoutChunk * NewChunk(TextLayout **layoutPtrPtr, int *maxPtr, + const char *start, int numChars, int curX, + int newX, int y); +static int ParseFontNameObj(Tcl_Interp *interp, Tk_Window tkwin, + Tcl_Obj *objPtr, TkFontAttributes *faPtr); +static void RecomputeWidgets(TkWindow *winPtr); +static int SetFontFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static void TheWorldHasChanged(ClientData clientData); +static void UpdateDependentFonts(TkFontInfo *fiPtr, + Tk_Window tkwin, Tcl_HashEntry *namedHashPtr); /* * The following structure defines the implementation of the "font" Tcl - * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of - * each font object points to the TkFont structure for the font, or - * NULL. + * object, used for drawing. The internalRep.twoPtrValue.ptr1 field of each + * font object points to the TkFont structure for the font, or NULL. */ Tcl_ObjType tkFontObjType = { @@ -360,29 +352,29 @@ Tcl_ObjType tkFontObjType = { NULL, /* updateStringProc */ SetFontFromAny /* setFromAnyProc */ }; - /* *--------------------------------------------------------------------------- * * TkFontPkgInit -- * - * This procedure is called when an application is created. It - * initializes all the structures that are used by the font - * package on a per application basis. + * This function is called when an application is created. It initializes + * all the structures that are used by the font package on a per + * application basis. * * Results: - * Stores a token in the mainPtr to hold information needed by this - * package on a per application basis. + * Stores a token in the mainPtr to hold information needed by this + * package on a per application basis. * * Side effects: * Memory allocated. * *--------------------------------------------------------------------------- */ + void -TkFontPkgInit(mainPtr) - TkMainInfo *mainPtr; /* The application being created. */ +TkFontPkgInit( + TkMainInfo *mainPtr) /* The application being created. */ { TkFontInfo *fiPtr; @@ -401,9 +393,9 @@ TkFontPkgInit(mainPtr) * * TkFontPkgFree -- * - * This procedure is called when an application is deleted. It - * deletes all the structures that were used by the font package - * for this application. + * This function is called when an application is deleted. It deletes all + * the structures that were used by the font package for this + * application. * * Results: * None. @@ -415,8 +407,8 @@ TkFontPkgInit(mainPtr) */ void -TkFontPkgFree(mainPtr) - TkMainInfo *mainPtr; /* The application being deleted. */ +TkFontPkgFree( + TkMainInfo *mainPtr) /* The application being deleted. */ { TkFontInfo *fiPtr; Tcl_HashEntry *hPtr, *searchPtr; @@ -431,15 +423,17 @@ TkFontPkgFree(mainPtr) searchPtr = Tcl_NextHashEntry(&search)) { fontsLeft++; #ifdef DEBUG_FONTS - fprintf(stderr, "Font %s still in cache.\n", + fprintf(stderr, "Font %s still in cache.\n", Tcl_GetHashKey(&fiPtr->fontCache, searchPtr)); #endif } + #ifdef PURIFY if (fontsLeft) { - panic("TkFontPkgFree: all fonts should have been freed already"); + Tcl_Panic("TkFontPkgFree: all fonts should have been freed already"); } #endif + Tcl_DeleteHashTable(&fiPtr->fontCache); hPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search); @@ -457,10 +451,10 @@ TkFontPkgFree(mainPtr) /* *--------------------------------------------------------------------------- * - * Tk_FontObjCmd -- + * Tk_FontObjCmd -- * - * This procedure is implemented to process the "font" Tcl command. - * See the user documentation for details on what it does. + * This function is implemented to process the "font" Tcl command. See + * the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -472,16 +466,16 @@ TkFontPkgFree(mainPtr) */ int -Tk_FontObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_FontObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { int index; Tk_Window tkwin; TkFontInfo *fiPtr; - static CONST char *optionStrings[] = { + static const char *optionStrings[] = { "actual", "configure", "create", "delete", "families", "measure", "metrics", "names", NULL @@ -504,259 +498,320 @@ Tk_FontObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case FONT_ACTUAL: { - int skip, result; - Tk_Font tkfont; - Tcl_Obj *objPtr; - CONST TkFontAttributes *faPtr; + case FONT_ACTUAL: { + int skip, result, n; + const char *s; + Tk_Font tkfont; + Tcl_Obj *optPtr, *charPtr, *resultPtr; + Tcl_UniChar uniChar = 0; + const TkFontAttributes *faPtr; + TkFontAttributes fa; - skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if ((objc < 3) || (objc - skip > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, - "font ?-displayof window? ?option?"); - return TCL_ERROR; - } - tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); - if (tkfont == NULL) { - return TCL_ERROR; - } - objc -= skip; - objv += skip; - faPtr = GetFontAttributes(tkfont); - objPtr = NULL; - if (objc > 3) { - objPtr = objv[3]; - } - result = GetAttributeInfoObj(interp, faPtr, objPtr); - Tk_FreeFont(tkfont); - return result; + /* + * Params 0 and 1 are 'font actual'. Param 2 is the font name. 3-4 may + * be '-displayof $window' + */ + + skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case FONT_CONFIGURE: { - int result; - char *string; - Tcl_Obj *objPtr; - NamedFont *nfPtr; - Tcl_HashEntry *namedHashPtr; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "fontname ?options?"); - return TCL_ERROR; - } - string = Tcl_GetString(objv[2]); - namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string); - nfPtr = NULL; /* lint. */ - if (namedHashPtr != NULL) { - nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); - } - if ((namedHashPtr == NULL) || (nfPtr->deletePending != 0)) { - Tcl_AppendResult(interp, "named font \"", string, - "\" doesn't exist", NULL); - return TCL_ERROR; - } - if (objc == 3) { - objPtr = NULL; - } else if (objc == 4) { - objPtr = objv[3]; + /* + * Next parameter may be an option. + */ + + n = skip + 3; + optPtr = NULL; + charPtr = NULL; + if (n < objc) { + s = Tcl_GetString(objv[n]); + if (s[0] == '-' && s[1] != '-') { + optPtr = objv[n]; + ++n; } else { - result = ConfigAttributesObj(interp, tkwin, objc - 3, - objv + 3, &nfPtr->fa); - UpdateDependentFonts(fiPtr, tkwin, namedHashPtr); - return result; + optPtr = NULL; } - return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr); } - case FONT_CREATE: { - int skip, i; - char *name; - char buf[16 + TCL_INTEGER_SPACE]; - TkFontAttributes fa; - Tcl_HashEntry *namedHashPtr; - skip = 3; - if (objc < 3) { - name = NULL; - } else { - name = Tcl_GetString(objv[2]); - if (name[0] == '-') { - name = NULL; - } - } - if (name == NULL) { - /* - * No font name specified. Generate one of the form "fontX". - */ + /* + * Next parameter may be '--' to mark end of options. + */ - for (i = 1; ; i++) { - sprintf(buf, "font%d", i); - namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, buf); - if (namedHashPtr == NULL) { - break; - } - } - name = buf; - skip = 2; + if (n < objc) { + if (!strcmp(Tcl_GetString(objv[n]), "--")) { + ++n; } - TkInitFontAttributes(&fa); - if (ConfigAttributesObj(interp, tkwin, objc - skip, objv + skip, - &fa) != TCL_OK) { - return TCL_ERROR; - } - if (CreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) { + } + + /* + * Next parameter is the character to get font information for. + */ + + if (n < objc) { + charPtr = objv[n]; + ++n; + } + + /* + * If there were fewer than 3 args, or args remain, that's an error. + */ + + if (objc < 3 || n < objc) { + Tcl_WrongNumArgs(interp, 2, objv, + "font ?-displayof window? ?option? ?--? ?char?"); + return TCL_ERROR; + } + + /* + * The 'charPtr' arg must be a single Unicode. + */ + + if (charPtr != NULL) { + if (Tcl_GetCharLength(charPtr) != 1) { + resultPtr = Tcl_NewStringObj( + "expected a single character but got \"", -1); + Tcl_AppendLimitedToObj(resultPtr, Tcl_GetString(charPtr), + -1, 40, "..."); + Tcl_AppendToObj(resultPtr, "\"", -1); + Tcl_SetObjResult(interp, resultPtr); return TCL_ERROR; } - Tcl_AppendResult(interp, name, NULL); - break; + uniChar = Tcl_GetUniChar(charPtr, 0); + } + + /* + * Find the font. + */ + + tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); + if (tkfont == NULL) { + return TCL_ERROR; } - case FONT_DELETE: { - int i; - char *string; - NamedFont *nfPtr; - Tcl_HashEntry *namedHashPtr; + /* + * Determine the font attributes. + */ + + if (charPtr == NULL) { + faPtr = GetFontAttributes(tkfont); + } else { + TkpGetFontAttrsForChar(tkwin, tkfont, uniChar, &fa); + faPtr = &fa; + } + result = GetAttributeInfoObj(interp, faPtr, optPtr); + + Tk_FreeFont(tkfont); + return result; + } + case FONT_CONFIGURE: { + int result; + char *string; + Tcl_Obj *objPtr; + NamedFont *nfPtr; + Tcl_HashEntry *namedHashPtr; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "fontname ?options?"); + return TCL_ERROR; + } + string = Tcl_GetString(objv[2]); + namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string); + nfPtr = NULL; /* lint. */ + if (namedHashPtr != NULL) { + nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); + } + if ((namedHashPtr == NULL) || (nfPtr->deletePending != 0)) { + Tcl_AppendResult(interp, "named font \"", string, + "\" doesn't exist", NULL); + return TCL_ERROR; + } + if (objc == 3) { + objPtr = NULL; + } else if (objc == 4) { + objPtr = objv[3]; + } else { + result = ConfigAttributesObj(interp, tkwin, objc - 3, objv + 3, + &nfPtr->fa); + UpdateDependentFonts(fiPtr, tkwin, namedHashPtr); + return result; + } + return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr); + } + case FONT_CREATE: { + int skip, i; + char *name; + char buf[16 + TCL_INTEGER_SPACE]; + TkFontAttributes fa; + Tcl_HashEntry *namedHashPtr; + + skip = 3; + if (objc < 3) { + name = NULL; + } else { + name = Tcl_GetString(objv[2]); + if (name[0] == '-') { + name = NULL; + } + } + if (name == NULL) { /* - * Delete the named font. If there are still widgets using this - * font, then it isn't deleted right away. + * No font name specified. Generate one of the form "fontX". */ - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "fontname ?fontname ...?"); - return TCL_ERROR; - } - for (i = 2; i < objc; i++) { - string = Tcl_GetString(objv[i]); - namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string); + for (i = 1; ; i++) { + sprintf(buf, "font%d", i); + namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, buf); if (namedHashPtr == NULL) { - Tcl_AppendResult(interp, "named font \"", string, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); - if (nfPtr->refCount != 0) { - nfPtr->deletePending = 1; - } else { - Tcl_DeleteHashEntry(namedHashPtr); - ckfree((char *) nfPtr); + break; } } - break; + name = buf; + skip = 2; + } + TkInitFontAttributes(&fa); + if (ConfigAttributesObj(interp, tkwin, objc - skip, objv + skip, + &fa) != TCL_OK) { + return TCL_ERROR; + } + if (TkCreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) { + return TCL_ERROR; } - case FONT_FAMILIES: { - int skip; + Tcl_AppendResult(interp, name, NULL); + break; + } + case FONT_DELETE: { + int i, result = TCL_OK; + char *string; - skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 2) { - Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?"); - return TCL_ERROR; - } - TkpGetFontFamilies(interp, tkwin); - break; + /* + * Delete the named font. If there are still widgets using this font, + * then it isn't deleted right away. + */ + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "fontname ?fontname ...?"); + return TCL_ERROR; } - case FONT_MEASURE: { - char *string; - Tk_Font tkfont; - int length, skip; - Tcl_Obj *resultPtr; - - skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); - if (skip < 0) { - return TCL_ERROR; - } - if (objc - skip != 4) { - Tcl_WrongNumArgs(interp, 2, objv, - "font ?-displayof window? text"); - return TCL_ERROR; - } - tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); - if (tkfont == NULL) { - return TCL_ERROR; - } - string = Tcl_GetStringFromObj(objv[3 + skip], &length); - resultPtr = Tcl_GetObjResult(interp); - Tcl_SetIntObj(resultPtr, Tk_TextWidth(tkfont, string, length)); - Tk_FreeFont(tkfont); - break; + for (i = 2; i < objc && result == TCL_OK; i++) { + string = Tcl_GetString(objv[i]); + result = TkDeleteNamedFont(interp, tkwin, string); + } + return result; + } + case FONT_FAMILIES: { + int skip; + + skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin); + if (skip < 0) { + return TCL_ERROR; } - case FONT_METRICS: { - Tk_Font tkfont; - int skip, index, i; - CONST TkFontMetrics *fmPtr; - static CONST char *switches[] = { - "-ascent", "-descent", "-linespace", "-fixed", NULL - }; + if (objc - skip != 2) { + Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?"); + return TCL_ERROR; + } + TkpGetFontFamilies(interp, tkwin); + break; + } + case FONT_MEASURE: { + char *string; + Tk_Font tkfont; + int length = 0, skip = 0; + Tcl_Obj *resultPtr; + if (objc > 4) { skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); if (skip < 0) { return TCL_ERROR; } - if ((objc < 3) || ((objc - skip) > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, - "font ?-displayof window? ?option?"); - return TCL_ERROR; - } - tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); - if (tkfont == NULL) { + } + if (objc - skip != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "font ?-displayof window? text"); + return TCL_ERROR; + } + tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); + if (tkfont == NULL) { + return TCL_ERROR; + } + string = Tcl_GetStringFromObj(objv[3 + skip], &length); + resultPtr = Tcl_GetObjResult(interp); + Tcl_SetIntObj(resultPtr, Tk_TextWidth(tkfont, string, length)); + Tk_FreeFont(tkfont); + break; + } + case FONT_METRICS: { + Tk_Font tkfont; + int skip, index, i; + const TkFontMetrics *fmPtr; + static const char *switches[] = { + "-ascent", "-descent", "-linespace", "-fixed", NULL + }; + + skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); + if (skip < 0) { + return TCL_ERROR; + } + if ((objc < 3) || ((objc - skip) > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, + "font ?-displayof window? ?option?"); + return TCL_ERROR; + } + tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); + if (tkfont == NULL) { + return TCL_ERROR; + } + objc -= skip; + objv += skip; + fmPtr = GetFontMetrics(tkfont); + if (objc == 3) { + char buf[64 + TCL_INTEGER_SPACE * 4]; + + sprintf(buf, "-ascent %d -descent %d -linespace %d -fixed %d", + fmPtr->ascent, fmPtr->descent, + fmPtr->ascent + fmPtr->descent, fmPtr->fixed); + Tcl_AppendResult(interp, buf, NULL); + } else { + if (Tcl_GetIndexFromObj(interp, objv[3], switches, "metric", 0, + &index) != TCL_OK) { + Tk_FreeFont(tkfont); return TCL_ERROR; } - objc -= skip; - objv += skip; - fmPtr = GetFontMetrics(tkfont); - if (objc == 3) { - char buf[64 + TCL_INTEGER_SPACE * 4]; - - sprintf(buf, "-ascent %d -descent %d -linespace %d -fixed %d", - fmPtr->ascent, fmPtr->descent, - fmPtr->ascent + fmPtr->descent, - fmPtr->fixed); - Tcl_AppendResult(interp, buf, NULL); - } else { - if (Tcl_GetIndexFromObj(interp, objv[3], switches, - "metric", 0, &index) != TCL_OK) { - Tk_FreeFont(tkfont); - return TCL_ERROR; - } - i = 0; /* Needed only to prevent compiler - * warning. */ - switch (index) { - case 0: i = fmPtr->ascent; break; - case 1: i = fmPtr->descent; break; - case 2: i = fmPtr->ascent + fmPtr->descent; break; - case 3: i = fmPtr->fixed; break; - } - Tcl_SetIntObj(Tcl_GetObjResult(interp), i); + i = 0; /* Needed only to prevent compiler warning. */ + switch (index) { + case 0: i = fmPtr->ascent; break; + case 1: i = fmPtr->descent; break; + case 2: i = fmPtr->ascent + fmPtr->descent; break; + case 3: i = fmPtr->fixed; break; } - Tk_FreeFont(tkfont); - break; + Tcl_SetIntObj(Tcl_GetObjResult(interp), i); } - case FONT_NAMES: { - char *string; - NamedFont *nfPtr; - Tcl_HashSearch search; - Tcl_HashEntry *namedHashPtr; - Tcl_Obj *strPtr, *resultPtr; - - if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "names"); - return TCL_ERROR; - } - resultPtr = Tcl_GetObjResult(interp); - namedHashPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search); - while (namedHashPtr != NULL) { - nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); - if (nfPtr->deletePending == 0) { - string = Tcl_GetHashKey(&fiPtr->namedTable, namedHashPtr); - strPtr = Tcl_NewStringObj(string, -1); - Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); - } - namedHashPtr = Tcl_NextHashEntry(&search); + Tk_FreeFont(tkfont); + break; + } + case FONT_NAMES: { + char *string; + NamedFont *nfPtr; + Tcl_HashSearch search; + Tcl_HashEntry *namedHashPtr; + Tcl_Obj *strPtr, *resultPtr; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "names"); + return TCL_ERROR; + } + resultPtr = Tcl_GetObjResult(interp); + namedHashPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search); + while (namedHashPtr != NULL) { + nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); + if (nfPtr->deletePending == 0) { + string = Tcl_GetHashKey(&fiPtr->namedTable, namedHashPtr); + strPtr = Tcl_NewStringObj(string, -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); } - break; + namedHashPtr = Tcl_NextHashEntry(&search); } + break; + } } return TCL_OK; } @@ -766,10 +821,10 @@ Tk_FontObjCmd(clientData, interp, objc, objv) * * UpdateDependentFonts, TheWorldHasChanged, RecomputeWidgets -- * - * Called when the attributes of a named font changes. Updates all - * the instantiated fonts that depend on that named font and then - * uses the brute force approach and prepares every widget to - * recompute its geometry. + * Called when the attributes of a named font changes. Updates all the + * instantiated fonts that depend on that named font and then uses the + * brute force approach and prepares every widget to recompute its + * geometry. * * Results: * None. @@ -781,10 +836,10 @@ Tk_FontObjCmd(clientData, interp, objc, objv) */ static void -UpdateDependentFonts(fiPtr, tkwin, namedHashPtr) - TkFontInfo *fiPtr; /* Info about application's fonts. */ - Tk_Window tkwin; /* A window in the application. */ - Tcl_HashEntry *namedHashPtr;/* The named font that is changing. */ +UpdateDependentFonts( + TkFontInfo *fiPtr, /* Info about application's fonts. */ + Tk_Window tkwin, /* A window in the application. */ + Tcl_HashEntry *namedHashPtr)/* The named font that is changing. */ { Tcl_HashEntry *cacheHashPtr; Tcl_HashSearch search; @@ -794,8 +849,8 @@ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr) nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); if (nfPtr->refCount == 0) { /* - * Well nobody's using this named font, so don't have to tell - * any widgets to recompute themselves. + * Well nobody's using this named font, so don't have to tell any + * widgets to recompute themselves. */ return; @@ -818,8 +873,8 @@ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr) } static void -TheWorldHasChanged(clientData) - ClientData clientData; /* Info about application's fonts. */ +TheWorldHasChanged( + ClientData clientData) /* Info about application's fonts. */ { TkFontInfo *fiPtr; @@ -830,8 +885,8 @@ TheWorldHasChanged(clientData) } static void -RecomputeWidgets(winPtr) - TkWindow *winPtr; /* Window to which command is sent. */ +RecomputeWidgets( + TkWindow *winPtr) /* Window to which command is sent. */ { Tk_ClassWorldChangedProc *proc; proc = Tk_GetClassProc(winPtr->classProcsPtr, worldChangedProc); @@ -842,22 +897,23 @@ RecomputeWidgets(winPtr) /* * Notify all the descendants of this window that the world has changed. * - * This could be done recursively or iteratively. The recursive version - * is easier to implement and understand, and typically, windows with a - * -font option will be leaf nodes in the widget heirarchy (buttons, - * labels, etc.), so the recursion depth will be shallow. + * This could be done recursively or iteratively. The recursive version is + * easier to implement and understand, and typically, windows with a -font + * option will be leaf nodes in the widget heirarchy (buttons, labels, + * etc.), so the recursion depth will be shallow. * - * However, the additional overhead of the recursive calls may become - * a performance problem if typical usage alters such that -font'ed widgets - * appear high in the heirarchy, causing deep recursion. This could happen + * However, the additional overhead of the recursive calls may become a + * performance problem if typical usage alters such that -font'ed widgets + * appear high in the heirarchy, causing deep recursion. This could happen * with text widgets, or more likely with the (not yet existant) labeled - * frame widget. With these widgets it is possible, even likely, that a + * frame widget. With these widgets it is possible, even likely, that a * -font'ed widget (text or labeled frame) will not be a leaf node, but - * will instead have many descendants. If this is ever found to cause - * a performance problem, it may be worth investigating an iterative - * version of the code below. + * will instead have many descendants. If this is ever found to cause a + * performance problem, it may be worth investigating an iterative version + * of the code below. */ - for (winPtr = winPtr->childList; winPtr != NULL; winPtr = winPtr->nextPtr) { + + for (winPtr=winPtr->childList ; winPtr!=NULL ; winPtr=winPtr->nextPtr) { RecomputeWidgets(winPtr); } } @@ -865,56 +921,57 @@ RecomputeWidgets(winPtr) /* *--------------------------------------------------------------------------- * - * CreateNamedFont -- + * TkCreateNamedFont -- * - * Create the specified named font with the given attributes in the - * named font table associated with the interp. + * Create the specified named font with the given attributes in the named + * font table associated with the interp. * * Results: - * Returns TCL_OK if the font was successfully created, or TCL_ERROR - * if the named font already existed. If TCL_ERROR is returned, an - * error message is left in the interp's result. + * Returns TCL_OK if the font was successfully created, or TCL_ERROR if + * the named font already existed. If TCL_ERROR is returned, an error + * message is left in the interp's result. * * Side effects: * Assume there used to exist a named font by the specified name, and * that the named font had been deleted, but there were still some - * widgets using the named font at the time it was deleted. If a - * new named font is created with the same name, all those widgets - * that were using the old named font will be redisplayed using - * the new named font's attributes. + * widgets using the named font at the time it was deleted. If a new + * named font is created with the same name, all those widgets that were + * using the old named font will be redisplayed using the new named + * font's attributes. * *--------------------------------------------------------------------------- */ -static int -CreateNamedFont(interp, tkwin, name, faPtr) - Tcl_Interp *interp; /* Interp for error return. */ - Tk_Window tkwin; /* A window associated with interp. */ - CONST char *name; /* Name for the new named font. */ - TkFontAttributes *faPtr; /* Attributes for the new named font. */ +int +TkCreateNamedFont( + Tcl_Interp *interp, /* Interp for error return (can be NULL). */ + Tk_Window tkwin, /* A window associated with interp. */ + const char *name, /* Name for the new named font. */ + TkFontAttributes *faPtr) /* Attributes for the new named font. */ { TkFontInfo *fiPtr; Tcl_HashEntry *namedHashPtr; - int new; - NamedFont *nfPtr; + int isNew; + NamedFont *nfPtr; fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr; - namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &new); - - if (new == 0) { + namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &isNew); + + if (!isNew) { nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); if (nfPtr->deletePending == 0) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "named font \"", name, - "\" already exists", (char *) NULL); + if (interp) { + Tcl_AppendResult(interp, "named font \"", name, + "\" already exists", NULL); + } return TCL_ERROR; } /* - * Recreating a named font with the same name as a previous - * named font. Some widgets were still using that named - * font, so they need to get redisplayed. + * Recreating a named font with the same name as a previous named + * font. Some widgets were still using that named font, so they need + * to get redisplayed. */ nfPtr->fa = *faPtr; @@ -927,7 +984,7 @@ CreateNamedFont(interp, tkwin, name, faPtr) nfPtr->deletePending = 0; Tcl_SetHashValue(namedHashPtr, nfPtr); nfPtr->fa = *faPtr; - nfPtr->refCount = 0; + nfPtr->refCount = 0; nfPtr->deletePending = 0; return TCL_OK; } @@ -935,76 +992,116 @@ CreateNamedFont(interp, tkwin, name, faPtr) /* *--------------------------------------------------------------------------- * - * Tk_GetFont -- + * TkDeleteNamedFont -- + * + * Delete the named font. If there are still widgets using this font, + * then it isn't deleted right away. + * + *--------------------------------------------------------------------------- + */ + +int +TkDeleteNamedFont( + Tcl_Interp *interp, /* Interp for error return (can be NULL). */ + Tk_Window tkwin, /* A window associated with interp. */ + CONST char *name) /* Name for the new named font. */ +{ + TkFontInfo *fiPtr; + NamedFont *nfPtr; + Tcl_HashEntry *namedHashPtr; + + fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr; + + namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, name); + if (namedHashPtr == NULL) { + if (interp) { + Tcl_AppendResult(interp, "named font \"", name, + "\" doesn't exist", NULL); + } + return TCL_ERROR; + } + nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); + if (nfPtr->refCount != 0) { + nfPtr->deletePending = 1; + } else { + Tcl_DeleteHashEntry(namedHashPtr); + ckfree((char *) nfPtr); + } + return TCL_OK; +} + +/* + *--------------------------------------------------------------------------- + * + * Tk_GetFont -- * * Given a string description of a font, map the description to a * corresponding Tk_Font that represents the font. * * Results: - * The return value is token for the font, or NULL if an error - * prevented the font from being created. If NULL is returned, an - * error message will be left in the interp's result. + * The return value is token for the font, or NULL if an error prevented + * the font from being created. If NULL is returned, an error message + * will be left in the interp's result. * * Side effects: - * The font is added to an internal database with a reference - * count. For each call to this procedure, there should eventually - * be a call to Tk_FreeFont() or Tk_FreeFontFromObj() so that the - * database is cleaned up when fonts aren't in use anymore. + * The font is added to an internal database with a reference count. For + * each call to this function, there should eventually be a call to + * Tk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned + * up when fonts aren't in use anymore. * *--------------------------------------------------------------------------- */ Tk_Font -Tk_GetFont(interp, tkwin, string) - Tcl_Interp *interp; /* Interp for database and error return, or - * NULL for no error messages. */ - Tk_Window tkwin; /* For display on which font will be used. */ - CONST char *string; /* String describing font, as: named font, +Tk_GetFont( + Tcl_Interp *interp, /* Interp for database and error return. */ + Tk_Window tkwin, /* For display on which font will be used. */ + const char *string) /* String describing font, as: named font, * native format, or parseable string. */ { - Tk_Font tkfont; + Tk_Font tkfont; Tcl_Obj *strPtr; strPtr = Tcl_NewStringObj((char *) string, -1); Tcl_IncrRefCount(strPtr); tkfont = Tk_AllocFontFromObj(interp, tkwin, strPtr); - Tcl_DecrRefCount(strPtr); + Tcl_DecrRefCount(strPtr); return tkfont; } /* *--------------------------------------------------------------------------- * - * Tk_AllocFontFromObj -- + * Tk_AllocFontFromObj -- * * Given a string description of a font, map the description to a * corresponding Tk_Font that represents the font. * * Results: - * The return value is token for the font, or NULL if an error - * prevented the font from being created. If NULL is returned, an - * error message will be left in interp's result object (if non-NULL). + * The return value is token for the font, or NULL if an error prevented + * the font from being created. If NULL is returned, an error message + * will be left in interp's result object. * * Side effects: - * The font is added to an internal database with a reference - * count. For each call to this procedure, there should eventually - * be a call to Tk_FreeFont() or Tk_FreeFontFromObj() so that the - * database is cleaned up when fonts aren't in use anymore. + * The font is added to an internal database with a reference count. For + * each call to this function, there should eventually be a call to + * Tk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned + * up when fonts aren't in use anymore. * *--------------------------------------------------------------------------- */ Tk_Font -Tk_AllocFontFromObj(interp, tkwin, objPtr) - Tcl_Interp *interp; /* Interp for database and error return. */ - Tk_Window tkwin; /* For screen on which font will be used. */ - Tcl_Obj *objPtr; /* Object describing font, as: named font, +Tk_AllocFontFromObj( + Tcl_Interp *interp, /* Interp for database and error return. */ + Tk_Window tkwin, /* For screen on which font will be used. */ + Tcl_Obj *objPtr) /* Object describing font, as: named font, * native format, or parseable string. */ { TkFontInfo *fiPtr; Tcl_HashEntry *cacheHashPtr, *namedHashPtr; TkFont *fontPtr, *firstFontPtr, *oldFontPtr; - int new, descent; + int isNew, descent; NamedFont *nfPtr; fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr; @@ -1017,8 +1114,8 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) if (oldFontPtr != NULL) { if (oldFontPtr->resourceRefCount == 0) { /* - * This is a stale reference: it refers to a TkFont that's - * no longer in use. Clear the reference. + * This is a stale reference: it refers to a TkFont that's no + * longer in use. Clear the reference. */ FreeFontObjProc(objPtr); @@ -1030,17 +1127,17 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) } /* - * Next, search the list of fonts that have the name we want, to see - * if one of them is for the right screen. + * Next, search the list of fonts that have the name we want, to see if + * one of them is for the right screen. */ - new = 0; + isNew = 0; if (oldFontPtr != NULL) { cacheHashPtr = oldFontPtr->cacheHashPtr; FreeFontObjProc(objPtr); } else { cacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache, - Tcl_GetString(objPtr), &new); + Tcl_GetString(objPtr), &isNew); } firstFontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr); for (fontPtr = firstFontPtr; (fontPtr != NULL); @@ -1048,13 +1145,13 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) if (Tk_Screen(tkwin) == fontPtr->screen) { fontPtr->resourceRefCount++; fontPtr->objRefCount++; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr; return (Tk_Font) fontPtr; } } /* - * The desired font isn't in the table. Make a new one. + * The desired font isn't in the table. Make a new one. */ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, @@ -1079,7 +1176,7 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) Tcl_Obj *dupObjPtr = Tcl_DuplicateObj(objPtr); if (ParseFontNameObj(interp, tkwin, dupObjPtr, &fa) != TCL_OK) { - if (new) { + if (isNew) { Tcl_DeleteHashEntry(cacheHashPtr); } Tcl_DecrRefCount(dupObjPtr); @@ -1095,6 +1192,19 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) } } + /* + * Detect the system font engine going wrong and fail more gracefully. + */ + + if (fontPtr == NULL) { + if (isNew) { + Tcl_DeleteHashEntry(cacheHashPtr); + } + Tcl_AppendResult(interp, "failed to allocate font due to ", + "internal system font engine problem", NULL); + return NULL; + } + fontPtr->resourceRefCount = 1; fontPtr->objRefCount = 1; fontPtr->cacheHashPtr = cacheHashPtr; @@ -1122,7 +1232,7 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) * Get information used for drawing underlines in generic code on a * non-underlined font. */ - + descent = fontPtr->fm.descent; fontPtr->underlinePos = descent / 2; fontPtr->underlineHeight = TkFontGetPixels(tkwin, fontPtr->fa.size) / 10; @@ -1131,9 +1241,9 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) } if (fontPtr->underlinePos + fontPtr->underlineHeight > descent) { /* - * If this set of values would cause the bottom of the underline - * bar to stick below the descent of the font, jack the underline - * up a bit higher. + * If this set of values would cause the bottom of the underline bar + * to stick below the descent of the font, jack the underline up a bit + * higher. */ fontPtr->underlineHeight = descent - fontPtr->underlinePos; @@ -1142,8 +1252,8 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) fontPtr->underlineHeight = 1; } } - - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr; + + objPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr; return (Tk_Font) fontPtr; } @@ -1152,31 +1262,31 @@ Tk_AllocFontFromObj(interp, tkwin, objPtr) * * Tk_GetFontFromObj -- * - * Find the font that corresponds to a given object. The font must - * have already been created by Tk_GetFont or Tk_AllocFontFromObj. + * Find the font that corresponds to a given object. The font must have + * already been created by Tk_GetFont or Tk_AllocFontFromObj. * * Results: - * The return value is a token for the font that matches objPtr - * and is suitable for use in tkwin. + * The return value is a token for the font that matches objPtr and is + * suitable for use in tkwin. * * Side effects: - * If the object is not already a font ref, the conversion will free - * any old internal representation. + * If the object is not already a font ref, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ Tk_Font -Tk_GetFontFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window that the font will be used in. */ - Tcl_Obj *objPtr; /* The object from which to get the font. */ +Tk_GetFontFromObj( + Tk_Window tkwin, /* The window that the font will be used in. */ + Tcl_Obj *objPtr) /* The object from which to get the font. */ { TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr; TkFont *fontPtr; Tcl_HashEntry *hashPtr; - + if (objPtr->typePtr != &tkFontObjType) { - SetFontFromAny((Tcl_Interp *) NULL, objPtr); + SetFontFromAny(NULL, objPtr); } fontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1; @@ -1184,8 +1294,8 @@ Tk_GetFontFromObj(tkwin, objPtr) if (fontPtr != NULL) { if (fontPtr->resourceRefCount == 0) { /* - * This is a stale reference: it refers to a TkFont that's - * no longer in use. Clear the reference. + * This is a stale reference: it refers to a TkFont that's no + * longer in use. Clear the reference. */ FreeFontObjProc(objPtr); @@ -1196,8 +1306,8 @@ Tk_GetFontFromObj(tkwin, objPtr) } /* - * Next, search the list of fonts that have the name we want, to see - * if one of them is for the right screen. + * Next, search the list of fonts that have the name we want, to see if + * one of them is for the right screen. */ if (fontPtr != NULL) { @@ -1211,13 +1321,13 @@ Tk_GetFontFromObj(tkwin, objPtr) fontPtr = fontPtr->nextPtr) { if (Tk_Screen(tkwin) == fontPtr->screen) { fontPtr->objRefCount++; - objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr; + objPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr; return (Tk_Font) fontPtr; } } } - panic("Tk_GetFontFromObj called with non-existent font!"); + Tcl_Panic("Tk_GetFontFromObj called with non-existent font!"); return NULL; } @@ -1226,28 +1336,28 @@ Tk_GetFontFromObj(tkwin, objPtr) * * SetFontFromAny -- * - * Convert the internal representation of a Tcl object to the - * font internal form. + * Convert the internal representation of a Tcl object to the font + * internal form. * * Results: * Always returns TCL_OK. * * Side effects: - * The object is left with its typePtr pointing to tkFontObjType. - * The TkFont pointer is NULL. + * The object is left with its typePtr pointing to tkFontObjType. The + * TkFont pointer is NULL. * *---------------------------------------------------------------------- */ static int -SetFontFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tcl_Obj *objPtr; /* The object to convert. */ +SetFontFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ Tcl_GetString(objPtr); @@ -1269,10 +1379,10 @@ SetFontFromAny(interp, objPtr) * Given a font, return a textual string identifying it. * * Results: - * The return value is the description that was passed to - * Tk_GetFont() to create the font. The storage for the returned - * string is only guaranteed to persist until the font is deleted. - * The caller should not modify this string. + * The return value is the description that was passed to Tk_GetFont() to + * create the font. The storage for the returned string is only + * guaranteed to persist until the font is deleted. The caller should not + * modify this string. * * Side effects: * None. @@ -1280,9 +1390,9 @@ SetFontFromAny(interp, objPtr) *--------------------------------------------------------------------------- */ -CONST char * -Tk_NameOfFont(tkfont) - Tk_Font tkfont; /* Font whose name is desired. */ +const char * +Tk_NameOfFont( + Tk_Font tkfont) /* Font whose name is desired. */ { TkFont *fontPtr; @@ -1293,7 +1403,7 @@ Tk_NameOfFont(tkfont) /* *--------------------------------------------------------------------------- * - * Tk_FreeFont -- + * Tk_FreeFont -- * * Called to release a font allocated by Tk_GetFont(). * @@ -1301,15 +1411,15 @@ Tk_NameOfFont(tkfont) * None. * * Side effects: - * The reference count associated with font is decremented, and - * only deallocated when no one is using it. + * The reference count associated with font is decremented, and only + * deallocated when no one is using it. * *--------------------------------------------------------------------------- */ void -Tk_FreeFont(tkfont) - Tk_Font tkfont; /* Font to be released. */ +Tk_FreeFont( + Tk_Font tkfont) /* Font to be released. */ { TkFont *fontPtr, *prevPtr; NamedFont *nfPtr; @@ -1324,9 +1434,8 @@ Tk_FreeFont(tkfont) } if (fontPtr->namedHashPtr != NULL) { /* - * This font derived from a named font. Reduce the reference - * count on the named font and free it if no-one else is - * using it. + * This font derived from a named font. Reduce the reference count on + * the named font and free it if no-one else is using it. */ nfPtr = (NamedFont *) Tcl_GetHashValue(fontPtr->namedHashPtr); @@ -1341,7 +1450,7 @@ Tk_FreeFont(tkfont) if (prevPtr == fontPtr) { if (fontPtr->nextPtr == NULL) { Tcl_DeleteHashEntry(fontPtr->cacheHashPtr); - } else { + } else { Tcl_SetHashValue(fontPtr->cacheHashPtr, fontPtr->nextPtr); } } else { @@ -1360,7 +1469,7 @@ Tk_FreeFont(tkfont) /* *--------------------------------------------------------------------------- * - * Tk_FreeFontFromObj -- + * Tk_FreeFontFromObj -- * * Called to release a font inside a Tcl_Obj *. Decrements the refCount * of the font and removes it from the hash tables if necessary. @@ -1369,17 +1478,17 @@ Tk_FreeFont(tkfont) * None. * * Side effects: - * The reference count associated with font is decremented, and - * only deallocated when no one is using it. + * The reference count associated with font is decremented, and only + * deallocated when no one is using it. * *--------------------------------------------------------------------------- */ void -Tk_FreeFontFromObj(tkwin, objPtr) - Tk_Window tkwin; /* The window this font lives in. Needed - * for the screen value. */ - Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */ +Tk_FreeFontFromObj( + Tk_Window tkwin, /* The window this font lives in. Needed for + * the screen value. */ + Tcl_Obj *objPtr) /* The Tcl_Obj * to be freed. */ { Tk_FreeFont(Tk_GetFontFromObj(tkwin, objPtr)); } @@ -1387,26 +1496,25 @@ Tk_FreeFontFromObj(tkwin, objPtr) /* *--------------------------------------------------------------------------- * - * FreeFontObjProc -- + * FreeFontObjProc -- * - * This proc is called to release an object reference to a font. - * Called when the object's internal rep is released or when - * the cached fontPtr needs to be changed. + * This proc is called to release an object reference to a font. Called + * when the object's internal rep is released or when the cached fontPtr + * needs to be changed. * * Results: * None. * * Side effects: - * The object reference count is decremented. When both it - * and the hash ref count go to zero, the font's resources - * are released. + * The object reference count is decremented. When both it and the hash + * ref count go to zero, the font's resources are released. * *--------------------------------------------------------------------------- */ static void -FreeFontObjProc(objPtr) - Tcl_Obj *objPtr; /* The object we are releasing. */ +FreeFontObjProc( + Tcl_Obj *objPtr) /* The object we are releasing. */ { TkFont *fontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1; @@ -1422,30 +1530,30 @@ FreeFontObjProc(objPtr) /* *--------------------------------------------------------------------------- * - * DupFontObjProc -- + * DupFontObjProc -- * - * When a cached font object is duplicated, this is called to - * update the internal reps. + * When a cached font object is duplicated, this is called to update the + * internal reps. * * Results: * None. * * Side effects: - * The font's objRefCount is incremented and the internal rep - * of the copy is set to point to it. + * The font's objRefCount is incremented and the internal rep of the copy + * is set to point to it. * *--------------------------------------------------------------------------- */ static void -DupFontObjProc(srcObjPtr, dupObjPtr) - Tcl_Obj *srcObjPtr; /* The object we are copying from. */ - Tcl_Obj *dupObjPtr; /* The object we are copying to. */ +DupFontObjProc( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { TkFont *fontPtr = (TkFont *) srcObjPtr->internalRep.twoPtrValue.ptr1; - + dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr; + dupObjPtr->internalRep.twoPtrValue.ptr1 = (void *) fontPtr; if (fontPtr != NULL) { fontPtr->objRefCount++; @@ -1457,10 +1565,10 @@ DupFontObjProc(srcObjPtr, dupObjPtr) * * Tk_FontId -- * - * Given a font, return an opaque handle that should be selected - * into the XGCValues structure in order to get the constructed - * gc to use this font. This procedure would go away if the - * XGCValues structure were replaced with a TkGCValues structure. + * Given a font, return an opaque handle that should be selected into the + * XGCValues structure in order to get the constructed gc to use this + * font. This function would go away if the XGCValues structure were + * replaced with a TkGCValues structure. * * Results: * As above. @@ -1472,8 +1580,9 @@ DupFontObjProc(srcObjPtr, dupObjPtr) */ Font -Tk_FontId(tkfont) - Tk_Font tkfont; /* Font that is going to be selected into GC. */ +Tk_FontId( + Tk_Font tkfont) /* Font that is going to be selected into + * GC. */ { TkFont *fontPtr; @@ -1486,26 +1595,27 @@ Tk_FontId(tkfont) * * Tk_GetFontMetrics -- * - * Returns overall ascent and descent metrics for the given font. - * These values can be used to space multiple lines of text and - * to align the baselines of text in different fonts. + * Returns overall ascent and descent metrics for the given font. These + * values can be used to space multiple lines of text and to align the + * baselines of text in different fonts. * * Results: - * If *heightPtr is non-NULL, it is filled with the overall height - * of the font, which is the sum of the ascent and descent. - * If *ascentPtr or *descentPtr is non-NULL, they are filled with - * the ascent and/or descent information for the font. + * If *heightPtr is non-NULL, it is filled with the overall height of the + * font, which is the sum of the ascent and descent. If *ascentPtr or + * *descentPtr is non-NULL, they are filled with the ascent and/or + * descent information for the font. * * Side effects: * None. * *--------------------------------------------------------------------------- */ + void -Tk_GetFontMetrics(tkfont, fmPtr) - Tk_Font tkfont; /* Font in which metrics are calculated. */ - Tk_FontMetrics *fmPtr; /* Pointer to structure in which font - * metrics for tkfont will be stored. */ +Tk_GetFontMetrics( + Tk_Font tkfont, /* Font in which metrics are calculated. */ + Tk_FontMetrics *fmPtr) /* Pointer to structure in which font metrics + * for tkfont will be stored. */ { TkFont *fontPtr; @@ -1520,33 +1630,32 @@ Tk_GetFontMetrics(tkfont, fmPtr) * * Tk_PostscriptFontName -- * - * Given a Tk_Font, return the name of the corresponding Postscript - * font. + * Given a Tk_Font, return the name of the corresponding Postscript font. * * Results: - * The return value is the pointsize of the given Tk_Font. - * The name of the Postscript font is appended to dsPtr. + * The return value is the pointsize of the given Tk_Font. The name of + * the Postscript font is appended to dsPtr. * * Side effects: - * If the font does not exist on the printer, the print job will - * fail at print time. Given a "reasonable" Postscript printer, - * the following Tk_Font font families should print correctly: + * If the font does not exist on the printer, the print job will fail at + * print time. Given a "reasonable" Postscript printer, the following + * Tk_Font font families should print correctly: * * Avant Garde, Arial, Bookman, Courier, Courier New, Geneva, * Helvetica, Monaco, New Century Schoolbook, New York, * Palatino, Symbol, Times, Times New Roman, Zapf Chancery, * and Zapf Dingbats. * - * Any other Tk_Font font families may not print correctly - * because the computed Postscript font name may be incorrect. + * Any other Tk_Font font families may not print correctly because the + * computed Postscript font name may be incorrect. * *--------------------------------------------------------------------------- */ int -Tk_PostscriptFontName(tkfont, dsPtr) - Tk_Font tkfont; /* Font in which text will be printed. */ - Tcl_DString *dsPtr; /* Pointer to an initialized Tcl_DString to +Tk_PostscriptFontName( + Tk_Font tkfont, /* Font in which text will be printed. */ + Tcl_DString *dsPtr) /* Pointer to an initialized Tcl_DString to * which the name of the Postscript font that * corresponds to tkfont will be appended. */ { @@ -1559,9 +1668,9 @@ Tk_PostscriptFontName(tkfont, dsPtr) fontPtr = (TkFont *) tkfont; /* - * Convert the case-insensitive Tk_Font family name to the - * case-sensitive Postscript family name. Take out any spaces and - * capitalize the first letter of each word. + * Convert the case-insensitive Tk_Font family name to the case-sensitive + * Postscript family name. Take out any spaces and capitalize the first + * letter of each word. */ family = fontPtr->fa.family; @@ -1589,8 +1698,8 @@ Tk_PostscriptFontName(tkfont, dsPtr) /* * Inline, capitalize the first letter of each word, lowercase the * rest of the letters in each word, and then take out the spaces - * between the words. This may make the DString shorter, which is - * safe to do. + * between the words. This may make the DString shorter, which is safe + * to do. */ Tcl_DStringAppend(dsPtr, family, -1); @@ -1607,7 +1716,7 @@ Tk_PostscriptFontName(tkfont, dsPtr) ch = Tcl_UniCharToUpper(ch); upper = 0; } else { - ch = Tcl_UniCharToLower(ch); + ch = Tcl_UniCharToLower(ch); } dest += Tcl_UniCharToUtf(ch, dest); } @@ -1655,14 +1764,12 @@ Tk_PostscriptFontName(tkfont, dsPtr) slantString = NULL; if (fontPtr->fa.slant == TK_FS_ROMAN) { ; + } else if ((strcmp(family, "Helvetica") == 0) + || (strcmp(family, "Courier") == 0) + || (strcmp(family, "AvantGarde") == 0)) { + slantString = "Oblique"; } else { - if ((strcmp(family, "Helvetica") == 0) - || (strcmp(family, "Courier") == 0) - || (strcmp(family, "AvantGarde") == 0)) { - slantString = "Oblique"; - } else { - slantString = "Italic"; - } + slantString = "Italic"; } /* @@ -1671,7 +1778,7 @@ Tk_PostscriptFontName(tkfont, dsPtr) */ if ((slantString == NULL) && (weightString == NULL)) { - if ((strcmp(family, "Times") == 0) + if ((strcmp(family, "Times") == 0) || (strcmp(family, "NewCenturySchlbk") == 0) || (strcmp(family, "Palatino") == 0)) { Tcl_DStringAppend(dsPtr, "-Roman", -1); @@ -1695,8 +1802,8 @@ Tk_PostscriptFontName(tkfont, dsPtr) * Tk_TextWidth -- * * A wrapper function for the more complicated interface of - * Tk_MeasureChars. Computes how much space the given - * simple string needs. + * Tk_MeasureChars. Computes how much space the given simple string + * needs. * * Results: * The return value is the width (in pixels) of the given string. @@ -1708,11 +1815,11 @@ Tk_PostscriptFontName(tkfont, dsPtr) */ int -Tk_TextWidth(tkfont, string, numBytes) - Tk_Font tkfont; /* Font in which text will be measured. */ - CONST char *string; /* String whose width will be computed. */ - int numBytes; /* Number of bytes to consider from - * string, or < 0 for strlen(). */ +Tk_TextWidth( + Tk_Font tkfont, /* Font in which text will be measured. */ + const char *string, /* String whose width will be computed. */ + int numBytes) /* Number of bytes to consider from string, or + * < 0 for strlen(). */ { int width; @@ -1726,15 +1833,15 @@ Tk_TextWidth(tkfont, string, numBytes) /* *--------------------------------------------------------------------------- * - * Tk_UnderlineChars -- + * Tk_UnderlineChars, TkUnderlineCharsInContext -- * - * This procedure draws an underline for a given range of characters - * in a given string. It doesn't draw the characters (which are - * assumed to have been displayed previously); it just draws the - * underline. This procedure would mainly be used to quickly - * underline a few characters without having to construct an - * underlined font. To produce properly underlined text, the - * appropriate underlined font should be constructed and used. + * These procedures draw an underline for a given range of characters in + * a given string. They don't draw the characters (which are assumed to + * have been displayed previously); they just draw the underline. These + * procedures would mainly be used to quickly underline a few characters + * without having to construct an underlined font. To produce properly + * underlined text, the appropriate underlined font should be constructed + * and used. * * Results: * None. @@ -1746,30 +1853,53 @@ Tk_TextWidth(tkfont, string, numBytes) */ void -Tk_UnderlineChars(display, drawable, gc, tkfont, string, x, y, firstByte, - lastByte) - Display *display; /* Display on which to draw. */ - Drawable drawable; /* Window or pixmap in which to draw. */ - GC gc; /* Graphics context for actually drawing +Tk_UnderlineChars( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for actually drawing * line. */ - Tk_Font tkfont; /* Font used in GC; must have been allocated - * by Tk_GetFont(). Used for character + Tk_Font tkfont, /* Font used in GC; must have been allocated + * by Tk_GetFont(). Used for character * dimensions, etc. */ - CONST char *string; /* String containing characters to be + const char *string, /* String containing characters to be * underlined or overstruck. */ - int x, y; /* Coordinates at which first character of + int x, int y, /* Coordinates at which first character of * string is drawn. */ - int firstByte; /* Index of first byte of first character. */ - int lastByte; /* Index of first byte after the last + int firstByte, /* Index of first byte of first character. */ + int lastByte) /* Index of first byte after the last + * character. */ +{ + TkUnderlineCharsInContext(display, drawable, gc, tkfont, string, + lastByte, x, y, firstByte, lastByte); +} + +void +TkUnderlineCharsInContext( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for actually drawing + * line. */ + Tk_Font tkfont, /* Font used in GC; must have been allocated + * by Tk_GetFont(). Used for character + * dimensions, etc. */ + const char *string, /* String containing characters to be + * underlined or overstruck. */ + int numBytes, /* Number of bytes in string. */ + int x, int y, /* Coordinates at which the first character of + * the whole string would be drawn. */ + int firstByte, /* Index of first byte of first character. */ + int lastByte) /* Index of first byte after the last * character. */ { TkFont *fontPtr; int startX, endX; fontPtr = (TkFont *) tkfont; - - Tk_MeasureChars(tkfont, string, firstByte, -1, 0, &startX); - Tk_MeasureChars(tkfont, string, lastByte, -1, 0, &endX); + + TkpMeasureCharsInContext(tkfont, string, numBytes, 0, firstByte, -1, 0, + &startX); + TkpMeasureCharsInContext(tkfont, string, numBytes, 0, lastByte, -1, 0, + &endX); XFillRectangle(display, drawable, gc, x + startX, y + fontPtr->underlinePos, (unsigned int) (endX - startX), @@ -1781,66 +1911,60 @@ Tk_UnderlineChars(display, drawable, gc, tkfont, string, x, y, firstByte, * * Tk_ComputeTextLayout -- * - * Computes the amount of screen space needed to display a - * multi-line, justified string of text. Records all the - * measurements that were done to determine to size and - * positioning of the individual lines of text; this information - * can be used by the Tk_DrawTextLayout() procedure to + * Computes the amount of screen space needed to display a multi-line, + * justified string of text. Records all the measurements that were done + * to determine to size and positioning of the individual lines of text; + * this information can be used by the Tk_DrawTextLayout() function to * display the text quickly (without remeasuring it). * - * This procedure is useful for simple widgets that want to - * display single-font, multi-line text and want Tk to handle the - * details. + * This function is useful for simple widgets that want to display + * single-font, multi-line text and want Tk to handle the details. * * Results: - * The return value is a Tk_TextLayout token that holds the - * measurement information for the given string. The token is - * only valid for the given string. If the string is freed, - * the token is no longer valid and must also be freed. To free - * the token, call Tk_FreeTextLayout(). + * The return value is a Tk_TextLayout token that holds the measurement + * information for the given string. The token is only valid for the + * given string. If the string is freed, the token is no longer valid and + * must also be freed. To free the token, call Tk_FreeTextLayout(). * - * The dimensions of the screen area needed to display the text - * are stored in *widthPtr and *heightPtr. + * The dimensions of the screen area needed to display the text are + * stored in *widthPtr and *heightPtr. * * Side effects: - * Memory is allocated to hold the measurement information. + * Memory is allocated to hold the measurement information. * *--------------------------------------------------------------------------- */ Tk_TextLayout -Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, - widthPtr, heightPtr) - Tk_Font tkfont; /* Font that will be used to display text. */ - CONST char *string; /* String whose dimensions are to be +Tk_ComputeTextLayout( + Tk_Font tkfont, /* Font that will be used to display text. */ + const char *string, /* String whose dimensions are to be * computed. */ - int numChars; /* Number of characters to consider from + int numChars, /* Number of characters to consider from * string, or < 0 for strlen(). */ - int wrapLength; /* Longest permissible line length, in - * pixels. <= 0 means no automatic wrapping: - * just let lines get as long as needed. */ - Tk_Justify justify; /* How to justify lines. */ - int flags; /* Flag bits OR-ed together. - * TK_IGNORE_TABS means that tab characters - * should not be expanded. TK_IGNORE_NEWLINES - * means that newline characters should not - * cause a line break. */ - int *widthPtr; /* Filled with width of string. */ - int *heightPtr; /* Filled with height of string. */ + int wrapLength, /* Longest permissible line length, in pixels. + * <= 0 means no automatic wrapping: just let + * lines get as long as needed. */ + Tk_Justify justify, /* How to justify lines. */ + int flags, /* Flag bits OR-ed together. TK_IGNORE_TABS + * means that tab characters should not be + * expanded. TK_IGNORE_NEWLINES means that + * newline characters should not cause a line + * break. */ + int *widthPtr, /* Filled with width of string. */ + int *heightPtr) /* Filled with height of string. */ { TkFont *fontPtr; - CONST char *start, *end, *special; - int n, y, bytesThisChunk, maxChunks; - int baseline, height, curX, newX, maxWidth; + const char *start, *end, *special; + int n, y, bytesThisChunk, maxChunks, curLine, layoutHeight; + int baseline, height, curX, newX, maxWidth, *lineLengths; TextLayout *layoutPtr; LayoutChunk *chunkPtr; - CONST TkFontMetrics *fmPtr; + const TkFontMetrics *fmPtr; Tcl_DString lineBuffer; - int *lineLengths; - int curLine, layoutHeight; Tcl_DStringInit(&lineBuffer); - + fontPtr = (TkFont *) tkfont; if ((fontPtr == NULL) || (string == NULL)) { if (widthPtr != NULL) { @@ -1865,11 +1989,11 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, maxChunks = 1; - layoutPtr = (TextLayout *) ckalloc(sizeof(TextLayout) - + (maxChunks - 1) * sizeof(LayoutChunk)); - layoutPtr->tkfont = tkfont; - layoutPtr->string = string; - layoutPtr->numChunks = 0; + layoutPtr = (TextLayout *) + ckalloc(sizeof(TextLayout) + (maxChunks-1) * sizeof(LayoutChunk)); + layoutPtr->tkfont = tkfont; + layoutPtr->string = string; + layoutPtr->numChunks = 0; baseline = fmPtr->ascent; maxWidth = 0; @@ -1884,7 +2008,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, special = string; flags &= TK_IGNORE_TABS | TK_IGNORE_NEWLINES; - flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE; + flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE; for (start = string; start < end; ) { if (start >= special) { /* @@ -1892,7 +2016,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, * * INTL: Note that it is safe to increment by byte, because we are * looking for 7-bit characters that will appear unchanged in - * UTF-8. At some point we may need to support the full Unicode + * UTF-8. At some point we may need to support the full Unicode * whitespace set. */ @@ -1912,7 +2036,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, /* * Special points at the next special character (or the end of the - * string). Process characters between start and special. + * string). Process characters between start and special. */ chunkPtr = NULL; @@ -1924,7 +2048,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, if (bytesThisChunk > 0) { chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, bytesThisChunk, curX, newX, baseline); - + start += bytesThisChunk; curX = newX; } @@ -1934,8 +2058,8 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, /* * Handle the special character. * - * INTL: Special will be pointing at a 7-bit character so we - * can safely treat it as a single byte. + * INTL: Special will be pointing at a 7-bit character so we can + * safely treat it as a single byte. */ chunkPtr = NULL; @@ -1955,7 +2079,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, flags &= ~TK_AT_LEAST_ONE; continue; } - } else { + } else { NewChunk(&layoutPtr, &maxChunks, start, 1, curX, curX, baseline)->numDisplayChars = -1; start++; @@ -1964,9 +2088,9 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, } /* - * No more characters are going to go on this line, either because - * no more characters can fit or there are no more characters left. - * Consume all extra spaces at end of line. + * No more characters are going to go on this line, either because no + * more characters can fit or there are no more characters left. + * Consume all extra spaces at end of line. */ while ((start < end) && isspace(UCHAR(*start))) { /* INTL: ISO space */ @@ -1983,12 +2107,12 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, start++; } if (chunkPtr != NULL) { - CONST char *end; + const char *end; /* - * Append all the extra spaces on this line to the end of the - * last text chunk. This is a little tricky because we are - * switching back and forth between characters and bytes. + * Append all the extra spaces on this line to the end of the last + * text chunk. This is a little tricky because we are switching + * back and forth between characters and bytes. */ end = chunkPtr->start + chunkPtr->numBytes; @@ -2002,7 +2126,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, } } - wrapLine: + wrapLine: flags |= TK_AT_LEAST_ONE; /* @@ -2015,8 +2139,8 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, } /* - * Remember width of this line, so that all chunks on this line - * can be centered or right justified, if necessary. + * Remember width of this line, so that all chunks on this line can be + * centered or right justified, if necessary. */ Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX)); @@ -2026,9 +2150,8 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, } /* - * If last line ends with a newline, then we need to make a 0 width - * chunk on the next line. Otherwise "Hello" and "Hello\n" are the - * same height. + * If last line ends with a newline, then we need to make a 0 width chunk + * on the next line. Otherwise "Hello" and "Hello\n" are the same height. */ if ((layoutPtr->numChunks > 0) && ((flags & TK_IGNORE_NEWLINES) == 0)) { @@ -2039,7 +2162,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX)); baseline += height; } - } + } layoutPtr->width = maxWidth; layoutHeight = baseline - fmPtr->ascent; @@ -2047,9 +2170,9 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, layoutHeight = height; /* - * This fake chunk is used by the other procedures so that they can - * pretend that there is a chunk with no chars in it, which makes - * the coding simpler. + * This fake chunk is used by the other functions so that they can + * pretend that there is a chunk with no chars in it, which makes the + * coding simpler. */ layoutPtr->numChunks = 1; @@ -2066,7 +2189,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, * Using maximum line length, shift all the chunks so that the lines * are all justified correctly. */ - + curLine = 0; chunkPtr = layoutPtr->chunks; y = chunkPtr->y; @@ -2104,8 +2227,8 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, * * Tk_FreeTextLayout -- * - * This procedure is called to release the storage associated with - * a Tk_TextLayout when it is no longer needed. + * This function is called to release the storage associated with a + * Tk_TextLayout when it is no longer needed. * * Results: * None. @@ -2117,8 +2240,8 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags, */ void -Tk_FreeTextLayout(textLayout) - Tk_TextLayout textLayout; /* The text layout to be released. */ +Tk_FreeTextLayout( + Tk_TextLayout textLayout) /* The text layout to be released. */ { TextLayout *layoutPtr; @@ -2136,9 +2259,8 @@ Tk_FreeTextLayout(textLayout) * Use the information in the Tk_TextLayout token to display a * multi-line, justified string of text. * - * This procedure is useful for simple widgets that need to - * display single-font, multi-line text and want Tk to handle - * the details. + * This function is useful for simple widgets that need to display + * single-font, multi-line text and want Tk to handle the details. * * Results: * None. @@ -2150,25 +2272,25 @@ Tk_FreeTextLayout(textLayout) */ void -Tk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar) - Display *display; /* Display on which to draw. */ - Drawable drawable; /* Window or pixmap in which to draw. */ - GC gc; /* Graphics context to use for drawing text. */ - Tk_TextLayout layout; /* Layout information, from a previous call - * to Tk_ComputeTextLayout(). */ - int x, y; /* Upper-left hand corner of rectangle in +Tk_DrawTextLayout( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context to use for drawing text. */ + Tk_TextLayout layout, /* Layout information, from a previous call to + * Tk_ComputeTextLayout(). */ + int x, int y, /* Upper-left hand corner of rectangle in * which to draw (pixels). */ - int firstChar; /* The index of the first character to draw - * from the given text item. 0 specfies the + int firstChar, /* The index of the first character to draw + * from the given text item. 0 specfies the * beginning. */ - int lastChar; /* The index just after the last character - * to draw from the given text item. A number - * < 0 means to draw all characters. */ + int lastChar) /* The index just after the last character to + * draw from the given text item. A number < 0 + * means to draw all characters. */ { TextLayout *layoutPtr; int i, numDisplayChars, drawX; - CONST char *firstByte; - CONST char *lastByte; + const char *firstByte; + const char *lastByte; LayoutChunk *chunkPtr; layoutPtr = (TextLayout *) layout; @@ -2214,15 +2336,14 @@ Tk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar) * * Tk_UnderlineTextLayout -- * - * Use the information in the Tk_TextLayout token to display an - * underline below an individual character. This procedure does - * not draw the text, just the underline. + * Use the information in the Tk_TextLayout token to display an underline + * below an individual character. This function does not draw the text, + * just the underline. * - * This procedure is useful for simple widgets that need to - * display single-font, multi-line text with an individual - * character underlined and want Tk to handle the details. - * To display larger amounts of underlined text, construct - * and use an underlined font. + * This function is useful for simple widgets that need to display + * single-font, multi-line text with an individual character underlined + * and want Tk to handle the details. To display larger amounts of + * underlined text, construct and use an underlined font. * * Results: * None. @@ -2234,16 +2355,16 @@ Tk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar) */ void -Tk_UnderlineTextLayout(display, drawable, gc, layout, x, y, underline) - Display *display; /* Display on which to draw. */ - Drawable drawable; /* Window or pixmap in which to draw. */ - GC gc; /* Graphics context to use for drawing text. */ - Tk_TextLayout layout; /* Layout information, from a previous call - * to Tk_ComputeTextLayout(). */ - int x, y; /* Upper-left hand corner of rectangle in +Tk_UnderlineTextLayout( + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context to use for drawing text. */ + Tk_TextLayout layout, /* Layout information, from a previous call to + * Tk_ComputeTextLayout(). */ + int x, int y, /* Upper-left hand corner of rectangle in * which to draw (pixels). */ - int underline; /* Index of the single character to - * underline, or -1 for no underline. */ + int underline) /* Index of the single character to underline, + * or -1 for no underline. */ { TextLayout *layoutPtr; TkFont *fontPtr; @@ -2254,7 +2375,7 @@ Tk_UnderlineTextLayout(display, drawable, gc, layout, x, y, underline) layoutPtr = (TextLayout *) layout; fontPtr = (TkFont *) layoutPtr->tkfont; - XFillRectangle(display, drawable, gc, x + xx, + XFillRectangle(display, drawable, gc, x + xx, y + yy + fontPtr->fm.ascent + fontPtr->underlinePos, (unsigned int) width, (unsigned int) fontPtr->underlineHeight); } @@ -2266,25 +2387,25 @@ Tk_UnderlineTextLayout(display, drawable, gc, layout, x, y, underline) * Tk_PointToChar -- * * Use the information in the Tk_TextLayout token to determine the - * character closest to the given point. The point must be - * specified with respect to the upper-left hand corner of the - * text layout, which is considered to be located at (0, 0). + * character closest to the given point. The point must be specified with + * respect to the upper-left hand corner of the text layout, which is + * considered to be located at (0, 0). * - * Any point whose y-value is less that 0 will be considered closest - * to the first character in the text layout; any point whose y-value - * is greater than the height of the text layout will be considered - * closest to the last character in the text layout. + * Any point whose y-value is less that 0 will be considered closest to + * the first character in the text layout; any point whose y-value is + * greater than the height of the text layout will be considered closest + * to the last character in the text layout. * - * Any point whose x-value is less than 0 will be considered closest - * to the first character on that line; any point whose x-value is - * greater than the width of the text layout will be considered - * closest to the last character on that line. + * Any point whose x-value is less than 0 will be considered closest to + * the first character on that line; any point whose x-value is greater + * than the width of the text layout will be considered closest to the + * last character on that line. * * Results: - * The return value is the index of the character that was - * closest to the point. Given a text layout with no characters, - * the value 0 will always be returned, referring to a hypothetical - * zero-width placeholder character. + * The return value is the index of the character that was closest to the + * point. Given a text layout with no characters, the value 0 will always + * be returned, referring to a hypothetical zero-width placeholder + * character. * * Side effects: * None. @@ -2293,12 +2414,12 @@ Tk_UnderlineTextLayout(display, drawable, gc, layout, x, y, underline) */ int -Tk_PointToChar(layout, x, y) - Tk_TextLayout layout; /* Layout information, from a previous call - * to Tk_ComputeTextLayout(). */ - int x, y; /* Coordinates of point to check, with - * respect to the upper-left corner of the - * text layout. */ +Tk_PointToChar( + Tk_TextLayout layout, /* Layout information, from a previous call to + * Tk_ComputeTextLayout(). */ + int x, int y) /* Coordinates of point to check, with respect + * to the upper-left corner of the text + * layout. */ { TextLayout *layoutPtr; LayoutChunk *chunkPtr, *lastPtr; @@ -2307,8 +2428,8 @@ Tk_PointToChar(layout, x, y) if (y < 0) { /* - * Point lies above any line in this layout. Return the index of - * the first char. + * Point lies above any line in this layout. Return the index of the + * first char. */ return 0; @@ -2327,30 +2448,30 @@ Tk_PointToChar(layout, x, y) if (y < baseline + fontPtr->fm.descent) { if (x < chunkPtr->x) { /* - * Point is to the left of all chunks on this line. Return - * the index of the first character on this line. + * Point is to the left of all chunks on this line. Return the + * index of the first character on this line. */ return numChars; } if (x >= layoutPtr->width) { /* - * If point lies off right side of the text layout, return - * the last char in the last chunk on this line. Without - * this, it might return the index of the first char that - * was located outside of the text layout. + * If point lies off right side of the text layout, return the + * last char in the last chunk on this line. Without this, it + * might return the index of the first char that was located + * outside of the text layout. */ x = INT_MAX; } /* - * Examine all chunks on this line to see which one contains - * the specified point. + * Examine all chunks on this line to see which one contains the + * specified point. */ lastPtr = chunkPtr; - while ((i < layoutPtr->numChunks) && (chunkPtr->y == baseline)) { + while ((i < layoutPtr->numChunks) && (chunkPtr->y == baseline)) { if (x < chunkPtr->x + chunkPtr->totalWidth) { /* * Point falls on one of the characters in this chunk. @@ -2377,7 +2498,7 @@ Tk_PointToChar(layout, x, y) /* * Point is to the right of all chars in all the chunks on this - * line. Return the index just past the last char in the last + * line. Return the index just past the last char in the last * chunk on this line. */ @@ -2393,8 +2514,8 @@ Tk_PointToChar(layout, x, y) } /* - * Point lies below any line in this text layout. Return the index - * just past the last char. + * Point lies below any line in this text layout. Return the index just + * past the last char. */ return (lastPtr->start + lastPtr->numChars) - layoutPtr->string; @@ -2405,29 +2526,28 @@ Tk_PointToChar(layout, x, y) * * Tk_CharBbox -- * - * Use the information in the Tk_TextLayout token to return the - * bounding box for the character specified by index. + * Use the information in the Tk_TextLayout token to return the bounding + * box for the character specified by index. * - * The width of the bounding box is the advance width of the - * character, and does not include and left- or right-bearing. - * Any character that extends partially outside of the - * text layout is considered to be truncated at the edge. Any - * character which is located completely outside of the text - * layout is considered to be zero-width and pegged against - * the edge. + * The width of the bounding box is the advance width of the character, + * and does not include and left- or right-bearing. Any character that + * extends partially outside of the text layout is considered to be + * truncated at the edge. Any character which is located completely + * outside of the text layout is considered to be zero-width and pegged + * against the edge. * * The height of the bounding box is the line height for this font, - * extending from the top of the ascent to the bottom of the - * descent. Information about the actual height of the individual - * letter is not available. + * extending from the top of the ascent to the bottom of the descent. + * Information about the actual height of the individual letter is not + * available. + * + * A text layout that contains no characters is considered to contain a + * single zero-width placeholder character. * - * A text layout that contains no characters is considered to - * contain a single zero-width placeholder character. - * * Results: - * The return value is 0 if the index did not specify a character - * in the text layout, or non-zero otherwise. In that case, - * *bbox is filled with the bounding box of the character. + * The return value is 0 if the index did not specify a character in the + * text layout, or non-zero otherwise. In that case, *bbox is filled with + * the bounding box of the character. * * Side effects: * None. @@ -2436,25 +2556,26 @@ Tk_PointToChar(layout, x, y) */ int -Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr) - Tk_TextLayout layout; /* Layout information, from a previous call to - * Tk_ComputeTextLayout(). */ - int index; /* The index of the character whose bbox is - * desired. */ - int *xPtr, *yPtr; /* Filled with the upper-left hand corner, in - * pixels, of the bounding box for the character - * specified by index, if non-NULL. */ - int *widthPtr, *heightPtr; - /* Filled with the width and height of the - * bounding box for the character specified by - * index, if non-NULL. */ +Tk_CharBbox( + Tk_TextLayout layout, /* Layout information, from a previous call to + * Tk_ComputeTextLayout(). */ + int index, /* The index of the character whose bbox is + * desired. */ + int *xPtr, int *yPtr, /* Filled with the upper-left hand corner, in + * pixels, of the bounding box for the + * character specified by index, if + * non-NULL. */ + int *widthPtr, int *heightPtr) + /* Filled with the width and height of the + * bounding box for the character specified by + * index, if non-NULL. */ { TextLayout *layoutPtr; LayoutChunk *chunkPtr; - int i, x, w; + int i, x = 0, w; Tk_Font tkfont; TkFont *fontPtr; - CONST char *end; + const char *end; if (index < 0) { return 0; @@ -2476,7 +2597,7 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr) end = Tcl_UtfAtIndex(chunkPtr->start, index); if (xPtr != NULL) { Tk_MeasureChars(tkfont, chunkPtr->start, - end - chunkPtr->start, -1, 0, &x); + end - chunkPtr->start, -1, 0, &x); x += chunkPtr->x; } if (widthPtr != NULL) { @@ -2488,25 +2609,26 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr) index -= chunkPtr->numChars; chunkPtr++; } - if (index == 0) { - /* - * Special case to get location just past last char in layout. - */ - - chunkPtr--; - x = chunkPtr->x + chunkPtr->totalWidth; - w = 0; - } else { + if (index != 0) { return 0; } /* - * Ensure that the bbox lies within the text layout. This forces all - * chars that extend off the right edge of the text layout to have - * truncated widths, and all chars that are completely off the right - * edge of the text layout to peg to the edge and have 0 width. + * Special case to get location just past last char in layout. + */ + + chunkPtr--; + x = chunkPtr->x + chunkPtr->totalWidth; + w = 0; + + /* + * Ensure that the bbox lies within the text layout. This forces all chars + * that extend off the right edge of the text layout to have truncated + * widths, and all chars that are completely off the right edge of the + * text layout to peg to the edge and have 0 width. */ - check: + + check: if (yPtr != NULL) { *yPtr = chunkPtr->y - fontPtr->fm.ascent; } @@ -2535,16 +2657,15 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr) * * Tk_DistanceToTextLayout -- * - * Computes the distance in pixels from the given point to the - * given text layout. Non-displaying space characters that occur - * at the end of individual lines in the text layout are ignored - * for hit detection purposes. + * Computes the distance in pixels from the given point to the given text + * layout. Non-displaying space characters that occur at the end of + * individual lines in the text layout are ignored for hit detection + * purposes. * * Results: - * The return value is 0 if the point (x, y) is inside the text - * layout. If the point isn't inside the text layout then the - * return value is the distance in pixels from the point to the - * text item. + * The return value is 0 if the point (x, y) is inside the text layout. + * If the point isn't inside the text layout then the return value is the + * distance in pixels from the point to the text item. * * Side effects: * None. @@ -2553,12 +2674,12 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr) */ int -Tk_DistanceToTextLayout(layout, x, y) - Tk_TextLayout layout; /* Layout information, from a previous call +Tk_DistanceToTextLayout( + Tk_TextLayout layout, /* Layout information, from a previous call * to Tk_ComputeTextLayout(). */ - int x, y; /* Coordinates of point to check, with - * respect to the upper-left corner of the - * text layout (in pixels). */ + int x, int y) /* Coordinates of point to check, with respect + * to the upper-left corner of the text layout + * (in pixels). */ { int i, x1, x2, y1, y2, xDiff, yDiff, dist, minDist, ascent, descent; LayoutChunk *chunkPtr; @@ -2569,14 +2690,14 @@ Tk_DistanceToTextLayout(layout, x, y) fontPtr = (TkFont *) layoutPtr->tkfont; ascent = fontPtr->fm.ascent; descent = fontPtr->fm.descent; - + minDist = 0; chunkPtr = layoutPtr->chunks; for (i = 0; i < layoutPtr->numChunks; i++) { if (chunkPtr->start[0] == '\n') { /* - * Newline characters are not counted when computing distance - * (but tab characters would still be considered). + * Newline characters are not counted when computing distance (but + * tab characters would still be considered). */ chunkPtr++; @@ -2620,15 +2741,15 @@ Tk_DistanceToTextLayout(layout, x, y) * * Tk_IntersectTextLayout -- * - * Determines whether a text layout lies entirely inside, - * entirely outside, or overlaps a given rectangle. Non-displaying - * space characters that occur at the end of individual lines in - * the text layout are ignored for intersection calculations. + * Determines whether a text layout lies entirely inside, entirely + * outside, or overlaps a given rectangle. Non-displaying space + * characters that occur at the end of individual lines in the text + * layout are ignored for intersection calculations. * * Results: - * The return value is -1 if the text layout is entirely outside of - * the rectangle, 0 if it overlaps, and 1 if it is entirely inside - * of the rectangle. + * The return value is -1 if the text layout is entirely outside of the + * rectangle, 0 if it overlaps, and 1 if it is entirely inside of the + * rectangle. * * Side effects: * None. @@ -2637,15 +2758,15 @@ Tk_DistanceToTextLayout(layout, x, y) */ int -Tk_IntersectTextLayout(layout, x, y, width, height) - Tk_TextLayout layout; /* Layout information, from a previous call - * to Tk_ComputeTextLayout(). */ - int x, y; /* Upper-left hand corner, in pixels, of +Tk_IntersectTextLayout( + Tk_TextLayout layout, /* Layout information, from a previous call to + * Tk_ComputeTextLayout(). */ + int x, int y, /* Upper-left hand corner, in pixels, of * rectangular area to compare with text - * layout. Coordinates are with respect to - * the upper-left hand corner of the text - * layout itself. */ - int width, height; /* The width and height of the above + * layout. Coordinates are with respect to the + * upper-left hand corner of the text layout + * itself. */ + int width, int height) /* The width and height of the above * rectangular area, in pixels. */ { int result, i, x1, y1, x2, y2; @@ -2656,19 +2777,19 @@ Tk_IntersectTextLayout(layout, x, y, width, height) /* * Scan the chunks one at a time, seeing whether each is entirely in, - * entirely out, or overlapping the rectangle. If an overlap is - * detected, return immediately; otherwise wait until all chunks have - * been processed and see if they were all inside or all outside. + * entirely out, or overlapping the rectangle. If an overlap is detected, + * return immediately; otherwise wait until all chunks have been processed + * and see if they were all inside or all outside. */ - + layoutPtr = (TextLayout *) layout; chunkPtr = layoutPtr->chunks; fontPtr = (TkFont *) layoutPtr->tkfont; - left = x; - top = y; - right = x + width; - bottom = y + height; + left = x; + top = y; + right = x + width; + bottom = y + height; result = 0; for (i = 0; i < layoutPtr->numChunks; i++) { @@ -2711,34 +2832,32 @@ Tk_IntersectTextLayout(layout, x, y, width, height) * * Tk_TextLayoutToPostscript -- * - * Outputs the contents of a text layout in Postscript format. - * The set of lines in the text layout will be rendered by the user - * supplied Postscript function. The function should be of the form: + * Outputs the contents of a text layout in Postscript format. The set of + * lines in the text layout will be rendered by the user supplied + * Postscript function. The function should be of the form: * - * justify x y string function -- + * justify x y string function -- * * Justify is -1, 0, or 1, depending on whether the following string - * should be left, center, or right justified, x and y is the - * location for the origin of the string, string is the sequence - * of characters to be printed, and function is the name of the - * caller-provided function; the function should leave nothing - * on the stack. - * - * The meaning of the origin of the string (x and y) depends on - * the justification. For left justification, x is where the - * left edge of the string should appear. For center justification, - * x is where the center of the string should appear. And for right - * justification, x is where the right edge of the string should - * appear. This behavior is necessary because, for example, right - * justified text on the screen is justified with screen metrics. - * The same string needs to be justified with printer metrics on - * the printer to appear in the correct place with respect to other - * similarly justified strings. In all circumstances, y is the - * location of the baseline for the string. + * should be left, center, or right justified, x and y is the location + * for the origin of the string, string is the sequence of characters to + * be printed, and function is the name of the caller-provided function; + * the function should leave nothing on the stack. + * + * The meaning of the origin of the string (x and y) depends on the + * justification. For left justification, x is where the left edge of the + * string should appear. For center justification, x is where the center + * of the string should appear. And for right justification, x is where + * the right edge of the string should appear. This behavior is necessary + * because, for example, right justified text on the screen is justified + * with screen metrics. The same string needs to be justified with + * printer metrics on the printer to appear in the correct place with + * respect to other similarly justified strings. In all circumstances, y + * is the location of the baseline for the string. * * Results: - * The interp's result is modified to hold the Postscript code that - * will render the text layout. + * The interp's result is modified to hold the Postscript code that will + * render the text layout. * * Side effects: * None. @@ -2747,20 +2866,17 @@ Tk_IntersectTextLayout(layout, x, y, width, height) */ void -Tk_TextLayoutToPostscript(interp, layout) - Tcl_Interp *interp; /* Filled with Postscript code. */ - Tk_TextLayout layout; /* The layout to be rendered. */ +Tk_TextLayoutToPostscript( + Tcl_Interp *interp, /* Filled with Postscript code. */ + Tk_TextLayout layout) /* The layout to be rendered. */ { #define MAXUSE 128 - char buf[MAXUSE+30]; + char buf[MAXUSE+30], uindex[5] = "\0\0\0\0", one_char[5]; LayoutChunk *chunkPtr; - int i, j, used, c, baseline; + int i, j, used, c, baseline, charsize; Tcl_UniChar ch; - CONST char *p, *last_p,*glyphname; + const char *p, *last_p, *glyphname; TextLayout *layoutPtr; - char uindex[5]="\0\0\0\0"; - char one_char[5]; - int charsize; int bytecount=0; layoutPtr = (TextLayout *) layout; @@ -2787,23 +2903,24 @@ Tk_TextLayoutToPostscript(interp, layout) p = chunkPtr->start; for (j = 0; j < chunkPtr->numDisplayChars; j++) { /* - * INTL: For now we just treat the characters as binary - * data and display the lower byte. Eventually this should - * be revised to handle international postscript fonts. + * INTL: For now we just treat the characters as binary data + * and display the lower byte. Eventually this should be + * revised to handle international postscript fonts. */ - last_p=p; - p +=(charsize= Tcl_UtfToUniChar(p,&ch)); - Tcl_UtfToExternal(interp,NULL,last_p,charsize,0,NULL,one_char,4, - NULL,&bytecount,NULL); - if (bytecount == 1) { + + last_p = p; + p += (charsize = Tcl_UtfToUniChar(p,&ch)); + Tcl_UtfToExternal(interp, NULL, last_p, charsize, 0, NULL, + one_char, 4, NULL, &bytecount, NULL); + if (bytecount == 1) { c = UCHAR(one_char[0]); /* c = UCHAR( ch & 0xFF) */; if ((c == '(') || (c == ')') || (c == '\\') || (c < 0x20) || (c >= UCHAR(0x7f))) { /* - * Tricky point: the "03" is necessary in the sprintf + * Tricky point: the "03" is necessary in the sprintf * below, so that a full three digits of octal are - * always generated. Without the "03", a number + * always generated. Without the "03", a number * following this sequence could be interpreted by * Postscript as part of this sequence. */ @@ -2814,36 +2931,42 @@ Tk_TextLayoutToPostscript(interp, layout) buf[used++] = c; } } else { - /* This character doesn't belong to system character set. - * So, we must use full glyph name */ - sprintf(uindex,"%04X",ch); /* endianness? */ - if ((glyphname = Tcl_GetVar2( interp , "::tk::psglyphs",uindex,0))) { - if (used > 0 && buf [used-1] == '(') + /* + * This character doesn't belong to system character set. + * So, we must use full glyph name. + */ + + sprintf(uindex, "%04X", ch); /* endianness? */ + glyphname = Tcl_GetVar2(interp,"::tk::psglyphs",uindex,0); + if (glyphname) { + if (used > 0 && buf [used-1] == '(') { --used; - else + } else { buf[used++] = ')'; + } buf[used++] = '/'; - while( (*glyphname) && (used < (MAXUSE+27))) + while ((*glyphname) && (used < (MAXUSE+27))) { buf[used++] = *glyphname++ ; + } buf[used++] = '('; } - + } if (used >= MAXUSE) { buf[used] = '\0'; - Tcl_AppendResult(interp, buf, (char *) NULL); + Tcl_AppendResult(interp, buf, NULL); used = 0; } } } if (used >= MAXUSE) { /* - * If there are a whole bunch of returns or tabs in a row, - * then buf[] could get filled up. + * If there are a whole bunch of returns or tabs in a row, then + * buf[] could get filled up. */ - + buf[used] = '\0'; - Tcl_AppendResult(interp, buf, (char *) NULL); + Tcl_AppendResult(interp, buf, NULL); used = 0; } chunkPtr++; @@ -2852,7 +2975,7 @@ Tk_TextLayoutToPostscript(interp, layout) buf[used++] = ']'; buf[used++] = '\n'; buf[used] = '\0'; - Tcl_AppendResult(interp, buf, (char *) NULL); + Tcl_AppendResult(interp, buf, NULL); } /* @@ -2864,33 +2987,32 @@ Tk_TextLayoutToPostscript(interp, layout) * initialized font attributes structure. * * Results: - * A standard Tcl return value. If TCL_ERROR is returned, an - * error message will be left in interp's result object (if non-NULL). + * A standard Tcl return value. If TCL_ERROR is returned, an error + * message will be left in interp's result object. * * Side effects: * The fields of the font attributes structure get filled in with - * information from argc/argv. If an error occurs while parsing, - * the font attributes structure will contain all modifications - * specified in the command line options up to the point of the - * error. + * information from argc/argv. If an error occurs while parsing, the font + * attributes structure will contain all modifications specified in the + * command line options up to the point of the error. * *--------------------------------------------------------------------------- */ static int -ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) - Tcl_Interp *interp; /* Interp for error return, or NULL. */ - Tk_Window tkwin; /* For display on which font will be used. */ - int objc; /* Number of elements in argv. */ - Tcl_Obj *CONST objv[]; /* Command line options. */ - TkFontAttributes *faPtr; /* Font attributes structure whose fields - * are to be modified. Structure must already - * be properly initialized. */ +ConfigAttributesObj( + Tcl_Interp *interp, /* Interp for error return. */ + Tk_Window tkwin, /* For display on which font will be used. */ + int objc, /* Number of elements in argv. */ + Tcl_Obj *const objv[], /* Command line options. */ + TkFontAttributes *faPtr) /* Font attributes structure whose fields are + * to be modified. Structure must already be + * properly initialized. */ { int i, n, index; Tcl_Obj *optionPtr, *valuePtr; char *value; - + for (i = 0; i < objc; i += 2) { optionPtr = objv[i]; valuePtr = objv[i + 1]; @@ -2901,63 +3023,55 @@ ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) } if ((i+2 >= objc) && (objc & 1)) { /* - * This test occurs after Tcl_GetIndexFromObj() so that - * "font create xyz -xyz" will return the error message - * that "-xyz" is a bad option, rather than that the value - * for "-xyz" is missing. + * This test occurs after Tcl_GetIndexFromObj() so that "font + * create xyz -xyz" will return the error message that "-xyz" is a + * bad option, rather than that the value for "-xyz" is missing. */ if (interp != NULL) { Tcl_AppendResult(interp, "value for \"", - Tcl_GetString(optionPtr), "\" option missing", - (char *) NULL); + Tcl_GetString(optionPtr), "\" option missing", NULL); } return TCL_ERROR; } switch (index) { - case FONT_FAMILY: { - value = Tcl_GetString(valuePtr); - faPtr->family = Tk_GetUid(value); - break; - } - case FONT_SIZE: { - if (Tcl_GetIntFromObj(interp, valuePtr, &n) != TCL_OK) { - return TCL_ERROR; - } - faPtr->size = n; - break; + case FONT_FAMILY: + value = Tcl_GetString(valuePtr); + faPtr->family = Tk_GetUid(value); + break; + case FONT_SIZE: + if (Tcl_GetIntFromObj(interp, valuePtr, &n) != TCL_OK) { + return TCL_ERROR; } - case FONT_WEIGHT: { - n = TkFindStateNumObj(interp, optionPtr, weightMap, valuePtr); - if (n == TK_FW_UNKNOWN) { - return TCL_ERROR; - } - faPtr->weight = n; - break; + faPtr->size = n; + break; + case FONT_WEIGHT: + n = TkFindStateNumObj(interp, optionPtr, weightMap, valuePtr); + if (n == TK_FW_UNKNOWN) { + return TCL_ERROR; } - case FONT_SLANT: { - n = TkFindStateNumObj(interp, optionPtr, slantMap, valuePtr); - if (n == TK_FS_UNKNOWN) { - return TCL_ERROR; - } - faPtr->slant = n; - break; + faPtr->weight = n; + break; + case FONT_SLANT: + n = TkFindStateNumObj(interp, optionPtr, slantMap, valuePtr); + if (n == TK_FS_UNKNOWN) { + return TCL_ERROR; } - case FONT_UNDERLINE: { - if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) { - return TCL_ERROR; - } - faPtr->underline = n; - break; + faPtr->slant = n; + break; + case FONT_UNDERLINE: + if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) { + return TCL_ERROR; } - case FONT_OVERSTRIKE: { - if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) { - return TCL_ERROR; - } - faPtr->overstrike = n; - break; + faPtr->underline = n; + break; + case FONT_OVERSTRIKE: + if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) { + return TCL_ERROR; } + faPtr->overstrike = n; + break; } } return TCL_OK; @@ -2971,14 +3085,13 @@ ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) * Return information about the font attributes as a Tcl list. * * Results: - * The return value is TCL_OK if the objPtr was non-NULL and - * specified a valid font attribute, TCL_ERROR otherwise. If TCL_OK - * is returned, the interp's result object is modified to hold a - * description of either the current value of a single option, or a - * list of all options and their current values for the given font - * attributes. If TCL_ERROR is returned, the interp's result is - * set to an error message describing that the objPtr did not refer - * to a valid option. + * The return value is TCL_OK if the objPtr was non-NULL and specified a + * valid font attribute, TCL_ERROR otherwise. If TCL_OK is returned, the + * interp's result object is modified to hold a description of either the + * current value of a single option, or a list of all options and their + * current values for the given font attributes. If TCL_ERROR is + * returned, the interp's result is set to an error message describing + * that the objPtr did not refer to a valid option. * * Side effects: * None. @@ -2987,16 +3100,16 @@ ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) */ static int -GetAttributeInfoObj(interp, faPtr, objPtr) - Tcl_Interp *interp; /* Interp to hold result. */ - CONST TkFontAttributes *faPtr; /* The font attributes to inspect. */ - Tcl_Obj *objPtr; /* If non-NULL, indicates the single - * option whose value is to be - * returned. Otherwise information is - * returned for all options. */ +GetAttributeInfoObj( + Tcl_Interp *interp, /* Interp to hold result. */ + const TkFontAttributes *faPtr, + /* The font attributes to inspect. */ + Tcl_Obj *objPtr) /* If non-NULL, indicates the single option + * whose value is to be returned. Otherwise + * information is returned for all options. */ { int i, index, start, end; - CONST char *str; + const char *str; Tcl_Obj *optionPtr, *valuePtr, *resultPtr; resultPtr = Tcl_GetObjResult(interp); @@ -3015,32 +3128,32 @@ GetAttributeInfoObj(interp, faPtr, objPtr) valuePtr = NULL; for (i = start; i < end; i++) { switch (i) { - case FONT_FAMILY: - str = faPtr->family; - valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1)); - break; + case FONT_FAMILY: + str = faPtr->family; + valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1)); + break; - case FONT_SIZE: - valuePtr = Tcl_NewIntObj(faPtr->size); - break; + case FONT_SIZE: + valuePtr = Tcl_NewIntObj(faPtr->size); + break; - case FONT_WEIGHT: - str = TkFindStateString(weightMap, faPtr->weight); - valuePtr = Tcl_NewStringObj(str, -1); - break; - - case FONT_SLANT: - str = TkFindStateString(slantMap, faPtr->slant); - valuePtr = Tcl_NewStringObj(str, -1); - break; + case FONT_WEIGHT: + str = TkFindStateString(weightMap, faPtr->weight); + valuePtr = Tcl_NewStringObj(str, -1); + break; - case FONT_UNDERLINE: - valuePtr = Tcl_NewBooleanObj(faPtr->underline); - break; + case FONT_SLANT: + str = TkFindStateString(slantMap, faPtr->slant); + valuePtr = Tcl_NewStringObj(str, -1); + break; - case FONT_OVERSTRIKE: - valuePtr = Tcl_NewBooleanObj(faPtr->overstrike); - break; + case FONT_UNDERLINE: + valuePtr = Tcl_NewBooleanObj(faPtr->underline); + break; + + case FONT_OVERSTRIKE: + valuePtr = Tcl_NewBooleanObj(faPtr->overstrike); + break; } if (objPtr != NULL) { Tcl_SetObjResult(interp, valuePtr); @@ -3058,8 +3171,8 @@ GetAttributeInfoObj(interp, faPtr, objPtr) * * ParseFontNameObj -- * - * Converts a object into a set of font attributes that can be used - * to construct a font. + * Converts a object into a set of font attributes that can be used to + * construct a font. * * The string rep of the object can be one of the following forms: * XLFD (see X documentation) @@ -3067,10 +3180,10 @@ GetAttributeInfoObj(interp, faPtr, objPtr) * "-option value [-option value ...]" * * Results: - * The return value is TCL_ERROR if the object was syntactically - * invalid. In that case an error message is left in interp's - * result object. Otherwise, fills the font attribute buffer with - * the values parsed from the string and returns TCL_OK; + * The return value is TCL_ERROR if the object was syntactically invalid. + * In that case an error message is left in interp's result object. + * Otherwise, fills the font attribute buffer with the values parsed from + * the string and returns TCL_OK; * * Side effects: * None. @@ -3079,13 +3192,12 @@ GetAttributeInfoObj(interp, faPtr, objPtr) */ static int -ParseFontNameObj(interp, tkwin, objPtr, faPtr) - Tcl_Interp *interp; /* Interp for error return, or NULL if no - * error messages are to be generated. */ - Tk_Window tkwin; /* For display on which font is used. */ - Tcl_Obj *objPtr; /* Parseable font description object. */ - TkFontAttributes *faPtr; /* Filled with attributes parsed from font - * name. Any attributes that were not +ParseFontNameObj( + Tcl_Interp *interp, /* Interp for error return. */ + Tk_Window tkwin, /* For display on which font is used. */ + Tcl_Obj *objPtr, /* Parseable font description object. */ + TkFontAttributes *faPtr) /* Filled with attributes parsed from font + * name. Any attributes that were not * specified in font name are filled with * default values. */ { @@ -3093,7 +3205,7 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) int objc, result, i, n; Tcl_Obj **objv; char *string; - + TkInitFontAttributes(faPtr); string = Tcl_GetString(objPtr); @@ -3102,7 +3214,7 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) * This may be an XLFD or an "-option value" string. * * If the string begins with "-*" or a "-foundry-family-*" pattern, - * then consider it an XLFD. + * then consider it an XLFD. */ if (string[1] == '*') { @@ -3120,13 +3232,13 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) return ConfigAttributesObj(interp, tkwin, objc, objv, faPtr); } - + if (*string == '*') { /* - * This is appears to be an XLFD. Under Unix, all valid XLFDs were - * already handled by TkpGetNativeFont. If we are here, either we - * have something that initially looks like an XLFD but isn't or we - * have encountered an XLFD on Windows or Mac. + * This is appears to be an XLFD. Under Unix, all valid XLFDs were + * already handled by TkpGetNativeFont. If we are here, either we have + * something that initially looks like an XLFD but isn't or we have + * encountered an XLFD on Windows or Mac. */ xlfd: @@ -3134,18 +3246,32 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) if (result == TCL_OK) { return TCL_OK; } + + /* + * If the string failed to parse but was considered to be a XLFD + * then it may be a "-option value" string with a hyphenated family + * name as per bug 2791352 + */ + + if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { + return TCL_ERROR; + } + + if (ConfigAttributesObj(interp, tkwin, objc, objv, faPtr) == TCL_OK) { + return TCL_OK; + } } /* - * Wasn't an XLFD or "-option value" string. Try it as a - * "font size style" list. + * Wasn't an XLFD or "-option value" string. Try it as a "font size style" + * list. */ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) || (objc < 1)) { if (interp != NULL) { Tcl_AppendResult(interp, "font \"", string, "\" doesn't exist", - (char *) NULL); + NULL); } return TCL_ERROR; } @@ -3193,7 +3319,7 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) if (interp != NULL) { Tcl_AppendResult(interp, "unknown font style \"", - Tcl_GetString(objv[i]), "\"", (char *) NULL); + Tcl_GetString(objv[i]), "\"", NULL); } return TCL_ERROR; } @@ -3205,9 +3331,8 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) * * NewChunk -- * - * Helper function for Tk_ComputeTextLayout(). Encapsulates a - * measured set of characters in a chunk that can be quickly - * drawn. + * Helper function for Tk_ComputeTextLayout(). Encapsulates a measured + * set of characters in a chunk that can be quickly drawn. * * Results: * A pointer to the new chunk in the text layout. @@ -3215,28 +3340,28 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr) * Side effects: * The text layout is reallocated to hold more chunks as necessary. * - * Currently, Tk_ComputeTextLayout() stores contiguous ranges of - * "normal" characters in a chunk, along with individual tab - * and newline chars in their own chunks. All characters in the - * text layout are accounted for. + * Currently, Tk_ComputeTextLayout() stores contiguous ranges of "normal" + * characters in a chunk, along with individual tab and newline chars in + * their own chunks. All characters in the text layout are accounted for. * *--------------------------------------------------------------------------- */ + static LayoutChunk * -NewChunk(layoutPtrPtr, maxPtr, start, numBytes, curX, newX, y) - TextLayout **layoutPtrPtr; - int *maxPtr; - CONST char *start; - int numBytes; - int curX; - int newX; - int y; +NewChunk( + TextLayout **layoutPtrPtr, + int *maxPtr, + const char *start, + int numBytes, + int curX, + int newX, + int y) { TextLayout *layoutPtr; LayoutChunk *chunkPtr; int maxChunks, numChars; size_t s; - + layoutPtr = *layoutPtrPtr; maxChunks = *maxPtr; if (layoutPtr->numChunks == maxChunks) { @@ -3271,8 +3396,8 @@ NewChunk(layoutPtrPtr, maxPtr, start, numBytes, curX, newX, y) * * Results: * Return value is TCL_ERROR if string was not a fully specified XLFD. - * Otherwise, fills font attribute buffer with the values parsed - * from the XLFD and returns TCL_OK. + * Otherwise, fills font attribute buffer with the values parsed from the + * XLFD and returns TCL_OK. * * Side effects: * None. @@ -3281,25 +3406,25 @@ NewChunk(layoutPtrPtr, maxPtr, start, numBytes, curX, newX, y) */ int -TkFontParseXLFD(string, faPtr, xaPtr) - CONST char *string; /* Parseable font description string. */ - TkFontAttributes *faPtr; /* Filled with attributes parsed from font - * name. Any attributes that were not +TkFontParseXLFD( + const char *string, /* Parseable font description string. */ + TkFontAttributes *faPtr, /* Filled with attributes parsed from font + * name. Any attributes that were not * specified in font name are filled with * default values. */ - TkXLFDAttributes *xaPtr; /* Filled with X-specific attributes parsed - * from font name. Any attributes that were + TkXLFDAttributes *xaPtr) /* Filled with X-specific attributes parsed + * from font name. Any attributes that were * not specified in font name are filled with - * default values. May be NULL if such + * default values. May be NULL if such * information is not desired. */ { char *src; - CONST char *str; + const char *str; int i, j; char *field[XLFD_NUMFIELDS + 2]; Tcl_DString ds; TkXLFDAttributes xa; - + if (xaPtr == NULL) { xaPtr = &xa; } @@ -3338,13 +3463,13 @@ TkFontParseXLFD(string, faPtr, xaPtr) /* * An XLFD of the form -adobe-times-medium-r-*-12-*-* is pretty common, - * but it is (strictly) malformed, because the first * is eliding both - * the Setwidth and the Addstyle fields. If the Addstyle field is a - * number, then assume the above incorrect form was used and shift all - * the rest of the fields right by one, so the number gets interpreted - * as a pixelsize. This fix is so that we don't get a million reports - * that "it works under X (as a native font name), but gives a syntax - * error under Windows (as a parsed set of attributes)". + * but it is (strictly) malformed, because the first * is eliding both the + * Setwidth and the Addstyle fields. If the Addstyle field is a number, + * then assume the above incorrect form was used and shift all the rest of + * the fields right by one, so the number gets interpreted as a pixelsize. + * This fix is so that we don't get a million reports that "it works under + * X (as a native font name), but gives a syntax error under Windows (as a + * parsed set of attributes)". */ if ((i > XLFD_ADD_STYLE) && (FieldSpecified(field[XLFD_ADD_STYLE]))) { @@ -3394,8 +3519,8 @@ TkFontParseXLFD(string, faPtr, xaPtr) /* XLFD_ADD_STYLE ignored. */ /* - * Pointsize in tenths of a point, but treat it as tenths of a pixel - * for historical compatibility. + * Pointsize in tenths of a point, but treat it as tenths of a pixel for + * historical compatibility. */ faPtr->size = 12; @@ -3422,7 +3547,7 @@ TkFontParseXLFD(string, faPtr, xaPtr) } /* - * Pixel height of font. If specified, overrides pointsize. + * Pixel height of font. If specified, overrides pointsize. */ if (FieldSpecified(field[XLFD_PIXEL_SIZE])) { @@ -3432,9 +3557,9 @@ TkFontParseXLFD(string, faPtr, xaPtr) * * [ N1 N2 N3 N4 ] * - * where N1 is the pixel size, and where N2, N3, and N4 - * are some additional numbers that I don't know - * the purpose of, so I ignore them. + * where N1 is the pixel size, and where N2, N3, and N4 are some + * additional numbers that I don't know the purpose of, so I + * ignore them. */ faPtr->size = atoi(field[XLFD_PIXEL_SIZE] + 1); @@ -3468,12 +3593,12 @@ TkFontParseXLFD(string, faPtr, xaPtr) * * FieldSpecified -- * - * Helper function for TkParseXLFD(). Determines if a field in the - * XLFD was set to a non-null, non-don't-care value. + * Helper function for TkParseXLFD(). Determines if a field in the XLFD + * was set to a non-null, non-don't-care value. * * Results: - * The return value is 0 if the field in the XLFD was not set and - * should be ignored, non-zero otherwise. + * The return value is 0 if the field in the XLFD was not set and should + * be ignored, non-zero otherwise. * * Side effects: * None. @@ -3482,11 +3607,12 @@ TkFontParseXLFD(string, faPtr, xaPtr) */ static int -FieldSpecified(field) - CONST char *field; /* The field of the XLFD to check. Strictly - * speaking, only when the string is "*" does it mean - * don't-care. However, an unspecified or question - * mark is also interpreted as don't-care. */ +FieldSpecified( + const char *field) /* The field of the XLFD to check. Strictly + * speaking, only when the string is "*" does + * it mean don't-care. However, an unspecified + * or question mark is also interpreted as + * don't-care. */ { char ch; @@ -3513,11 +3639,11 @@ FieldSpecified(field) * *--------------------------------------------------------------------------- */ - + int -TkFontGetPixels(tkwin, size) - Tk_Window tkwin; /* For point->pixel conversion factor. */ - int size; /* Font size. */ +TkFontGetPixels( + Tk_Window tkwin, /* For point->pixel conversion factor. */ + int size) /* Font size. */ { double d; @@ -3547,11 +3673,11 @@ TkFontGetPixels(tkwin, size) * *--------------------------------------------------------------------------- */ - + int -TkFontGetPoints(tkwin, size) - Tk_Window tkwin; /* For pixel->point conversion factor. */ - int size; /* Font size. */ +TkFontGetPoints( + Tk_Window tkwin, /* For pixel->point conversion factor. */ + int size) /* Font size. */ { double d; @@ -3570,24 +3696,24 @@ TkFontGetPoints(tkwin, size) * * TkFontGetAliasList -- * - * Given a font name, find the list of all aliases for that font - * name. One of the names in this list will probably be the name - * that this platform expects when asking for the font. + * Given a font name, find the list of all aliases for that font name. + * One of the names in this list will probably be the name that this + * platform expects when asking for the font. * * Results: - * As above. The return value is NULL if the font name has no - * aliases. + + * As above. The return value is NULL if the font name has no aliases. * * Side effects: * None. * *------------------------------------------------------------------------- */ - + char ** -TkFontGetAliasList(faceName) - CONST char *faceName; /* Font name to test for aliases. */ -{ +TkFontGetAliasList( + const char *faceName) /* Font name to test for aliases. */ +{ int i, j; for (i = 0; fontAliases[i] != NULL; i++) { @@ -3605,9 +3731,8 @@ TkFontGetAliasList(faceName) * * TkFontGetFallbacks -- * - * Get the list of font fallbacks that the platform-specific code - * can use to try to find the closest matching font the name - * requested. + * Get the list of font fallbacks that the platform-specific code can use + * to try to find the closest matching font the name requested. * * Results: * As above. @@ -3617,9 +3742,9 @@ TkFontGetAliasList(faceName) * *------------------------------------------------------------------------- */ - + char *** -TkFontGetFallbacks() +TkFontGetFallbacks(void) { return fontFallbacks; } @@ -3642,9 +3767,9 @@ TkFontGetFallbacks() * *------------------------------------------------------------------------- */ - + char ** -TkFontGetGlobalClass() +TkFontGetGlobalClass(void) { return globalFontClass; } @@ -3654,8 +3779,8 @@ TkFontGetGlobalClass() * * TkFontGetSymbolClass -- * - * Get the list of fonts that are symbolic; used if the operating - * system cannot apriori identify symbolic fonts on its own. + * Get the list of fonts that are symbolic; used if the operating system + * cannot apriori identify symbolic fonts on its own. * * Results: * As above. @@ -3665,9 +3790,9 @@ TkFontGetGlobalClass() * *------------------------------------------------------------------------- */ - + char ** -TkFontGetSymbolClass() +TkFontGetSymbolClass(void) { return symbolClass; } @@ -3677,13 +3802,12 @@ TkFontGetSymbolClass() * * TkDebugFont -- * - * This procedure returns debugging information about a font. + * This function returns debugging information about a font. * * Results: * The return value is a list with one sublist for each TkFont - * corresponding to "name". Each sublist has two elements that - * contain the resourceRefCount and objRefCount fields from the - * TkFont structure. + * corresponding to "name". Each sublist has two elements that contain + * the resourceRefCount and objRefCount fields from the TkFont structure. * * Side effects: * None. @@ -3692,10 +3816,10 @@ TkFontGetSymbolClass() */ Tcl_Obj * -TkDebugFont(tkwin, name) - Tk_Window tkwin; /* The window in which the font will be - * used (not currently used). */ - char *name; /* Name of the desired color. */ +TkDebugFont( + Tk_Window tkwin, /* The window in which the font will be used + * (not currently used). */ + char *name) /* Name of the desired color. */ { TkFont *fontPtr; Tcl_HashEntry *hashPtr; @@ -3707,14 +3831,14 @@ TkDebugFont(tkwin, name) if (hashPtr != NULL) { fontPtr = (TkFont *) Tcl_GetHashValue(hashPtr); if (fontPtr == NULL) { - panic("TkDebugFont found empty hash table entry"); + Tcl_Panic("TkDebugFont found empty hash table entry"); } for ( ; (fontPtr != NULL); fontPtr = fontPtr->nextPtr) { objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(fontPtr->resourceRefCount)); Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewIntObj(fontPtr->objRefCount)); + Tcl_NewIntObj(fontPtr->objRefCount)); Tcl_ListObjAppendElement(NULL, resultPtr, objPtr); } } @@ -3726,13 +3850,13 @@ TkDebugFont(tkwin, name) * * TkFontGetFirstTextLayout -- * - * This procedure returns the first chunk of a Tk_TextLayout, - * i.e. until the first font change on the first line (or the - * whole first line if there is no such font change). + * This function returns the first chunk of a Tk_TextLayout, i.e. until + * the first font change on the first line (or the whole first line if + * there is no such font change). * * Results: - * The return value is the byte length of the chunk, the chunk - * itself is copied into dst and its Tk_Font into font. + * The return value is the byte length of the chunk, the chunk itself is + * copied into dst and its Tk_Font into font. * * Side effects: * None. @@ -3742,21 +3866,20 @@ TkDebugFont(tkwin, name) int TkFontGetFirstTextLayout( - Tk_TextLayout layout, /* Layout information, from a previous call - * to Tk_ComputeTextLayout(). */ - Tk_Font * font, - char * dst) + Tk_TextLayout layout, /* Layout information, from a previous call to + * Tk_ComputeTextLayout(). */ + Tk_Font *font, + char *dst) { - TextLayout *layoutPtr; + TextLayout *layoutPtr; LayoutChunk *chunkPtr; int numBytesInChunk; layoutPtr = (TextLayout *)layout; - if ((layoutPtr==NULL) - || (layoutPtr->numChunks==0) - || (layoutPtr->chunks->numDisplayChars <= 0)) { - dst[0] = '\0'; - return 0; + if ((layoutPtr==NULL) || (layoutPtr->numChunks==0) + || (layoutPtr->chunks->numDisplayChars <= 0)) { + dst[0] = '\0'; + return 0; } chunkPtr = layoutPtr->chunks; numBytesInChunk = chunkPtr->numBytes; @@ -3764,3 +3887,11 @@ TkFontGetFirstTextLayout( *font = layoutPtr->tkfont; return numBytesInChunk; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkFont.h b/generic/tkFont.h index 71c598c..ef6336c 100644 --- a/generic/tkFont.h +++ b/generic/tkFont.h @@ -1,40 +1,40 @@ /* * tkFont.h -- * - * Declarations for interfaces between the generic and platform- - * specific parts of the font package. This information is not - * visible outside of the font package. + * Declarations for interfaces between the generic and platform-specific + * parts of the font package. This information is not visible outside of + * the font package. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKFONT #define _TKFONT #ifdef BUILD_tk -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLEXPORT +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT #endif /* - * The following structure keeps track of the attributes of a font. It can - * be used to keep track of either the desired attributes or the actual + * The following structure keeps track of the attributes of a font. It can be + * used to keep track of either the desired attributes or the actual * attributes gotten when the font was instantiated. */ -typedef struct TkFontAttributes { - Tk_Uid family; /* Font family, or NULL to represent - * plaform-specific default system font. */ +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 * negative number meaning pixel size. */ int weight; /* Weight flag; see below for def'n. */ int slant; /* Slant flag; see below for def'n. */ int underline; /* Non-zero for underline font. */ int overstrike; /* Non-zero for overstrike font. */ -} TkFontAttributes; +}; /* * Possible values for the "weight" field in a TkFontAttributes structure. @@ -45,7 +45,7 @@ typedef struct TkFontAttributes { #define TK_FW_NORMAL 0 #define TK_FW_BOLD 1 -#define TK_FW_UNKNOWN -1 /* Unknown weight. This value is used for +#define TK_FW_UNKNOWN -1 /* Unknown weight. This value is used for * error checking and is never actually stored * in the weight field. */ @@ -53,21 +53,21 @@ typedef struct TkFontAttributes { * Possible values for the "slant" field in a TkFontAttributes structure. */ -#define TK_FS_ROMAN 0 +#define TK_FS_ROMAN 0 #define TK_FS_ITALIC 1 -#define TK_FS_OBLIQUE 2 /* This value is only used when parsing X - * font names to determine the closest - * match. It is only stored in the - * XLFDAttributes structure, never in the - * slant field of the TkFontAttributes. */ +#define TK_FS_OBLIQUE 2 /* This value is only used when parsing X font + * names to determine the closest match. It is + * only stored in the XLFDAttributes + * structure, never in the slant field of the + * TkFontAttributes. */ -#define TK_FS_UNKNOWN -1 /* Unknown slant. This value is used for - * error checking and is never actually stored - * in the slant field. */ +#define TK_FS_UNKNOWN -1 /* Unknown slant. This value is used for error + * checking and is never actually stored in + * the slant field. */ /* * The following structure keeps track of the metrics for an instantiated - * font. The metrics are the physical properties of the font itself. + * font. The metrics are the physical properties of the font itself. */ typedef struct TkFontMetrics { @@ -80,9 +80,9 @@ typedef struct TkFontMetrics { /* * The following structure is used to keep track of the generic information - * about a font. Each platform-specific font is represented by a structure - * with the following structure at its beginning, plus any platform- - * specific stuff after that. + * about a font. Each platform-specific font is represented by a structure + * with the following structure at its beginning, plus any platform-specific + * stuff after that. */ typedef struct TkFont { @@ -92,14 +92,14 @@ typedef struct TkFont { int resourceRefCount; /* Number of active uses of this font (each * active use corresponds to a call to - * Tk_AllocFontFromTable or Tk_GetFont). - * If this count is 0, then this TkFont - * structure is no longer valid and it isn't - * present in a hash table: it is being - * kept around only because there are objects - * referring to it. The structure is freed - * when resourceRefCount and objRefCount - * are both 0. */ + * Tk_AllocFontFromTable or Tk_GetFont). If + * this count is 0, then this TkFont structure + * is no longer valid and it isn't present in + * a hash table: it is being kept around only + * because there are objects referring to it. + * The structure is freed when + * resourceRefCount and objRefCount are both + * 0. */ int objRefCount; /* The number of Tcl objects that reference * this structure. */ Tcl_HashEntry *cacheHashPtr;/* Entry in font cache for this structure, @@ -110,9 +110,9 @@ typedef struct TkFont { * was not based on a named font. */ Screen *screen; /* The screen where this font is valid. */ int tabWidth; /* Width of tabs in this font (pixels). */ - int underlinePos; /* Offset from baseline to origin of - * underline bar (used for drawing underlines - * on a non-underlined font). */ + int underlinePos; /* Offset from baseline to origin of underline + * bar (used for drawing underlines on a + * non-underlined font). */ int underlineHeight; /* Height of underline bar (used for drawing * underlines on a non-underlined font). */ @@ -122,33 +122,33 @@ typedef struct TkFont { */ Font fid; /* For backwards compatibility with XGCValues - * structures. Remove when TkGCValues is - * implemented. */ + * structures. Remove when TkGCValues is + * implemented. */ TkFontAttributes fa; /* Actual font attributes obtained when the * the font was created, as opposed to the * desired attributes passed in to - * TkpGetFontFromAttributes(). The desired + * TkpGetFontFromAttributes(). The desired * metrics can be determined from the string * that was used to create this font. */ TkFontMetrics fm; /* Font metrics determined when font was * created. */ struct TkFont *nextPtr; /* Points to the next TkFont structure with - * the same name. All fonts with the - * same name (but different displays) are - * chained together off a single entry in - * a hash table. */ + * the same name. All fonts with the same name + * (but different displays) are chained + * together off a single entry in a hash + * table. */ } TkFont; /* - * The following structure is used to return attributes when parsing an - * XLFD. The extra information is of interest to the Unix-specific code - * when attempting to find the closest matching font. + * The following structure is used to return attributes when parsing an XLFD. + * The extra information is of interest to the Unix-specific code when + * attempting to find the closest matching font. */ typedef struct TkXLFDAttributes { Tk_Uid foundry; /* The foundry of the font. */ - int slant; /* The tristate value for the slant, which - * is significant under X. */ + int slant; /* The tristate value for the slant, which is + * significant under X. */ int setwidth; /* The proportionate width, see below for * definition. */ Tk_Uid charset; /* The actual charset string. */ @@ -163,8 +163,8 @@ typedef struct TkXLFDAttributes { #define TK_SW_NORMAL 0 #define TK_SW_CONDENSE 1 #define TK_SW_EXPAND 2 -#define TK_SW_UNKNOWN 3 /* Unknown setwidth. This value may be - * stored in the setwidth field. */ +#define TK_SW_UNKNOWN 3 /* Unknown setwidth. This value may be stored + * in the setwidth field. */ /* * The following defines specify the meaning of the fields in a fully @@ -193,34 +193,34 @@ typedef struct TkXLFDAttributes { #define TkInitFontAttributes(fa) memset((fa), 0, sizeof(TkFontAttributes)); #define TkInitXLFDAttributes(xa) memset((xa), 0, sizeof(TkXLFDAttributes)); -EXTERN int TkFontParseXLFD _ANSI_ARGS_((CONST char *string, - TkFontAttributes *faPtr, TkXLFDAttributes *xaPtr)); -EXTERN char ** TkFontGetAliasList _ANSI_ARGS_((CONST char *faceName)); -EXTERN char *** TkFontGetFallbacks _ANSI_ARGS_((void)); -EXTERN int TkFontGetPixels _ANSI_ARGS_((Tk_Window tkwin, - int size)); -EXTERN int TkFontGetPoints _ANSI_ARGS_((Tk_Window tkwin, - int size)); -EXTERN char ** TkFontGetGlobalClass _ANSI_ARGS_((void)); -EXTERN char ** TkFontGetSymbolClass _ANSI_ARGS_((void)); -EXTERN int TkFontGetFirstTextLayout _ANSI_ARGS_(( - Tk_TextLayout layout, Tk_Font *font, char *dst)); +MODULE_SCOPE int TkFontParseXLFD(CONST char *string, + TkFontAttributes *faPtr, TkXLFDAttributes *xaPtr); +MODULE_SCOPE char ** TkFontGetAliasList(CONST char *faceName); +MODULE_SCOPE char *** TkFontGetFallbacks(void); +MODULE_SCOPE int TkFontGetPixels(Tk_Window tkwin, int size); +MODULE_SCOPE int TkFontGetPoints(Tk_Window tkwin, int size); +MODULE_SCOPE char ** TkFontGetGlobalClass(void); +MODULE_SCOPE char ** TkFontGetSymbolClass(void); +MODULE_SCOPE int TkCreateNamedFont(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *name, TkFontAttributes *faPtr); +MODULE_SCOPE int TkDeleteNamedFont(Tcl_Interp *interp, + Tk_Window tkwin, CONST char *name); +MODULE_SCOPE int TkFontGetFirstTextLayout(Tk_TextLayout layout, + Tk_Font *font, char *dst); /* - * Low-level API exported by platform-specific code to generic code. + * Low-level API exported by platform-specific code to generic code. */ -EXTERN void TkpDeleteFont _ANSI_ARGS_((TkFont *tkFontPtr)); -EXTERN void TkpFontPkgInit _ANSI_ARGS_((TkMainInfo *mainPtr)); -EXTERN TkFont * TkpGetFontFromAttributes _ANSI_ARGS_(( - TkFont *tkFontPtr, Tk_Window tkwin, - CONST TkFontAttributes *faPtr)); -EXTERN void TkpGetFontFamilies _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin)); -EXTERN TkFont * TkpGetNativeFont _ANSI_ARGS_((Tk_Window tkwin, - CONST char *name)); - -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLIMPORT +MODULE_SCOPE void TkpDeleteFont(TkFont *tkFontPtr); +MODULE_SCOPE void TkpFontPkgInit(TkMainInfo *mainPtr); +MODULE_SCOPE TkFont * TkpGetFontFromAttributes(TkFont *tkFontPtr, + Tk_Window tkwin, CONST TkFontAttributes *faPtr); +MODULE_SCOPE void TkpGetFontFamilies(Tcl_Interp *interp, + Tk_Window tkwin); +MODULE_SCOPE TkFont * TkpGetNativeFont(Tk_Window tkwin, CONST char *name); + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TKFONT */ diff --git a/generic/tkFrame.c b/generic/tkFrame.c index 453ad73..8662dd3 100644 --- a/generic/tkFrame.c +++ b/generic/tkFrame.c @@ -1,20 +1,18 @@ -/* +/* * tkFrame.c -- * * This module implements "frame", "labelframe" and "toplevel" widgets - * for the Tk toolkit. Frames are windows with a background color - * and possibly a 3-D effect, but not much else in the way of - * attributes. + * for the Tk toolkit. Frames are windows with a background color and + * possibly a 3-D effect, but not much else in the way of attributes. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "default.h" -#include "tkPort.h" #include "tkInt.h" /* @@ -31,29 +29,29 @@ enum FrameType { */ typedef struct { - Tk_Window tkwin; /* Window that embodies the frame. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up. */ - Display *display; /* Display containing widget. Used, among + Tk_Window tkwin; /* Window that embodies the frame. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up. */ + Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ - Tcl_Interp *interp; /* Interpreter associated with widget. Used - * to delete widget command. */ + Tcl_Interp *interp; /* Interpreter associated with widget. Used to + * delete widget command. */ Tcl_Command widgetCmd; /* Token for frame's widget command. */ Tk_OptionTable optionTable; /* Table that defines configuration options * available for this widget. */ char *className; /* Class name for widget (from configuration - * option). Malloc-ed. */ + * option). Malloc-ed. */ enum FrameType type; /* Type of widget, such as TYPE_FRAME. */ - char *screenName; /* Screen on which widget is created. Non-null - * only for top-levels. Malloc-ed, may be + char *screenName; /* Screen on which widget is created. Non-null + * only for top-levels. Malloc-ed, may be * NULL. */ char *visualName; /* Textual description of visual for window, - * from -visual option. Malloc-ed, may be + * from -visual option. Malloc-ed, may be * NULL. */ char *colormapName; /* Textual description of colormap for window, - * from -colormap option. Malloc-ed, may be + * from -colormap option. Malloc-ed, may be * NULL. */ char *menuName; /* Textual description of menu to use for * menubar. Malloc-ed, may be NULL. */ @@ -61,32 +59,32 @@ typedef struct { * allocated for this window, which must be * freed when the window is deleted. */ Tk_3DBorder border; /* Structure used to draw 3-D border and - * background. NULL means no background - * or border. */ + * background. NULL means no background or + * border. */ int borderWidth; /* Width of 3-D border (if any). */ int relief; /* 3-d effect: TK_RELIEF_RAISED etc. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * 0 means don't draw a highlight. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. 0 means don't + * draw a highlight. */ XColor *highlightBgColorPtr; - /* Color for drawing traversal highlight - * area when highlight is off. */ + /* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ - int width; /* Width to request for window. <= 0 means + int width; /* Width to request for window. <= 0 means * don't request any size. */ - int height; /* Height to request for window. <= 0 means + int height; /* Height to request for window. <= 0 means * don't request any size. */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ int isContainer; /* 1 means this window is a container, 0 means * that it isn't. */ char *useThis; /* If the window is embedded, this points to * the name of the window in which it is - * embedded (malloc'ed). For non-embedded + * embedded (malloc'ed). For non-embedded * windows this is NULL. */ - int flags; /* Various flags; see below for + int flags; /* Various flags; see below for * definitions. */ Tcl_Obj *padXPtr; /* Value of -padx option: specifies how many * pixels of extra space to leave on left and @@ -99,46 +97,41 @@ typedef struct { } Frame; /* - * A data structure of the following type is kept for each labelframe - * widget managed by this file: + * A data structure of the following type is kept for each labelframe widget + * managed by this file: */ typedef struct { Frame frame; /* A pointer to the generic frame structure. * This must be the first element of the * Labelframe. */ - /* * Labelframe specific configuration settings. */ - Tcl_Obj *textPtr; /* Value of -text option: specifies text to * display in button. */ - Tk_Font tkfont; /* Value of -font option: specifies font - * to use for display text. */ + Tk_Font tkfont; /* Value of -font option: specifies font to + * use for display text. */ XColor *textColorPtr; /* Value of -fg option: specifies foreground * color in normal mode. */ int labelAnchor; /* Value of -labelanchor option: specifies * where to place the label. */ - Tk_Window labelWin; /* Value of -labelwidget option: Window to - * use as label for the frame. */ - + Tk_Window labelWin; /* Value of -labelwidget option: Window to use + * as label for the frame. */ /* * Labelframe specific fields for use with configuration settings above. */ - GC textGC; /* GC for drawing text in normal mode. */ Tk_TextLayout textLayout; /* Stored text layout information. */ XRectangle labelBox; /* The label's actual size and position. */ int labelReqWidth; /* The label's requested width. */ int labelReqHeight; /* The label's requested height. */ int labelTextX, labelTextY; /* Position of the text to be drawn. */ - } Labelframe; /* - * The following macros define how many extra pixels to leave - * around a label's text. + * The following macros define how many extra pixels to leave around a label's + * text. */ #define LABELSPACING 1 @@ -147,20 +140,19 @@ typedef struct { /* * Flag bits for frames: * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler - * has already been queued to redraw - * this window. - * GOT_FOCUS: Non-zero means this widget currently - * has the input focus. + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has + * already been queued to redraw this window. + * GOT_FOCUS: Non-zero means this widget currently has the + * input focus. */ #define REDRAW_PENDING 1 #define GOT_FOCUS 4 /* - * The following enum is used to define a type for the -labelanchor option - * of the Labelframe widget. These values are used as indices into the - * string table below. + * The following enum is used to define a type for the -labelanchor option of + * the Labelframe widget. These values are used as indices into the string + * table below. */ enum labelanchor { @@ -172,32 +164,34 @@ enum labelanchor { static char *labelAnchorStrings[] = { "e", "en", "es", "n", "ne", "nw", "s", "se", "sw", "w", "wn", "ws", - (char *) NULL + NULL }; /* - * Information used for parsing configuration options. There are - * one common table used by all and one table for each widget class. + * Information used for parsing configuration options. There are one common + * table used by all and one table for each widget class. */ -static Tk_OptionSpec commonOptSpec[] = { +static const Tk_OptionSpec commonOptSpec[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_FRAME_BG_COLOR, -1, Tk_Offset(Frame, border), TK_OPTION_NULL_OK, (ClientData) DEF_FRAME_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_STRING, "-colormap", "colormap", "Colormap", DEF_FRAME_COLORMAP, -1, Tk_Offset(Frame, colormapName), TK_OPTION_NULL_OK, 0, 0}, + /* + * Having -container is useless in a labelframe since a container has + * no border. It should be deprecated. + */ {TK_OPTION_BOOLEAN, "-container", "container", "Container", - DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer), - 0, 0, 0}, + DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_FRAME_CURSOR, -1, Tk_Offset(Frame, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-height", "height", "Height", - DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height), - 0, 0, 0}, + DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, -1, Tk_Offset(Frame, highlightBgColorPtr), 0, 0, 0}, @@ -220,82 +214,71 @@ static Tk_OptionSpec commonOptSpec[] = { DEF_FRAME_VISUAL, -1, Tk_Offset(Frame, visualName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-width", "width", "Width", - DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width), - 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0, 0, 0, 0} + DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width), 0, 0, 0}, + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} }; -static Tk_OptionSpec frameOptSpec[] = { - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, +static const Tk_OptionSpec frameOptSpec[] = { + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), - 0, 0, 0}, + DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-class", "class", "Class", - DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className), - 0, 0, 0}, + DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), - 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0, 0, (ClientData) commonOptSpec, 0} + DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0}, + {TK_OPTION_END, NULL, NULL, NULL, + NULL, 0, 0, 0, (ClientData) commonOptSpec, 0} }; -static Tk_OptionSpec toplevelOptSpec[] = { - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, +static const Tk_OptionSpec toplevelOptSpec[] = { + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), - 0, 0, 0}, + DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0}, {TK_OPTION_STRING, "-class", "class", "Class", - DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className), - 0, 0, 0}, + DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, {TK_OPTION_STRING, "-menu", "menu", "Menu", DEF_TOPLEVEL_MENU, -1, Tk_Offset(Frame, menuName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), - 0, 0, 0}, + DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0}, {TK_OPTION_STRING, "-screen", "screen", "Screen", DEF_TOPLEVEL_SCREEN, -1, Tk_Offset(Frame, screenName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-use", "use", "Use", DEF_TOPLEVEL_USE, -1, Tk_Offset(Frame, useThis), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0, 0, (ClientData) commonOptSpec, 0} + {TK_OPTION_END, NULL, NULL, NULL, + NULL, 0, 0, 0, (ClientData) commonOptSpec, 0} }; -static Tk_OptionSpec labelframeOptSpec[] = { - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, +static const Tk_OptionSpec labelframeOptSpec[] = { + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_LABELFRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), - 0, 0, 0}, - {TK_OPTION_STRING, "-class", "class", "Class", - DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_STRING, "-class", "class", "Class", + DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_LABELFRAME_FONT, -1, Tk_Offset(Labelframe, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", DEF_LABELFRAME_FG, -1, Tk_Offset(Labelframe, textColorPtr), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-labelanchor", "labelAnchor", "LabelAnchor", DEF_LABELFRAME_LABELANCHOR, -1, Tk_Offset(Labelframe, labelAnchor), - 0, (ClientData) labelAnchorStrings, 0}, + 0, (ClientData) labelAnchorStrings, 0}, {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", - (char *) NULL, -1, Tk_Offset(Labelframe, labelWin), - TK_OPTION_NULL_OK, 0, 0}, + NULL, -1, Tk_Offset(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief), - 0, 0, 0}, + DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", DEF_LABELFRAME_TEXT, Tk_Offset(Labelframe, textPtr), -1, TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0, 0, (ClientData) commonOptSpec, 0} + {TK_OPTION_END, NULL, NULL, NULL, + NULL, 0, 0, 0, (ClientData) commonOptSpec, 0} }; /* @@ -305,48 +288,47 @@ static Tk_OptionSpec labelframeOptSpec[] = { static char *classNames[] = {"Frame", "Toplevel", "Labelframe"}; /* - * The following table maps from FrameType to the option template for - * that class of widgets. + * The following table maps from FrameType to the option template for that + * class of widgets. */ -static Tk_OptionSpec *optionSpecs[] = { +static const Tk_OptionSpec * const optionSpecs[] = { frameOptSpec, toplevelOptSpec, labelframeOptSpec, }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void ComputeFrameGeometry _ANSI_ARGS_((Frame *framePtr)); -static int ConfigureFrame _ANSI_ARGS_((Tcl_Interp *interp, - Frame *framePtr, int objc, Tcl_Obj *CONST objv[])); -static int CreateFrame _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST argv[], - enum FrameType type, char *appName)); -static void DestroyFrame _ANSI_ARGS_((char *memPtr)); -static void DestroyFramePartly _ANSI_ARGS_((Frame *framePtr)); -static void DisplayFrame _ANSI_ARGS_((ClientData clientData)); -static void FrameCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void FrameEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void FrameLostSlaveProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin)); -static void FrameRequestProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void FrameStructureProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -static int FrameWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static void FrameWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static void MapFrame _ANSI_ARGS_((ClientData clientData)); +static void ComputeFrameGeometry(Frame *framePtr); +static int ConfigureFrame(Tcl_Interp *interp, Frame *framePtr, + int objc, Tcl_Obj *CONST objv[]); +static int CreateFrame(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST argv[], + enum FrameType type, char *appName); +static void DestroyFrame(char *memPtr); +static void DestroyFramePartly(Frame *framePtr); +static void DisplayFrame(ClientData clientData); +static void FrameCmdDeletedProc(ClientData clientData); +static void FrameEventProc(ClientData clientData, + XEvent *eventPtr); +static void FrameLostSlaveProc(ClientData clientData, + Tk_Window tkwin); +static void FrameRequestProc(ClientData clientData, + Tk_Window tkwin); +static void FrameStructureProc(ClientData clientData, + XEvent *eventPtr); +static int FrameWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static void FrameWorldChanged(ClientData instanceData); +static void MapFrame(ClientData clientData); /* - * The structure below defines frame class behavior by means of procedures - * that can be invoked from generic window code. + * The structure below defines frame class behavior by means of functions that + * can be invoked from generic window code. */ static Tk_ClassProcs frameClass = { @@ -355,67 +337,63 @@ static Tk_ClassProcs frameClass = { }; /* - * The structure below defines the official type record for the - * labelframe's geometry manager: + * The structure below defines the official type record for the labelframe's + * geometry manager: */ -static Tk_GeomMgr frameGeomType = { - "labelframe", /* name */ - FrameRequestProc, /* requestProc */ - FrameLostSlaveProc /* lostSlaveProc */ +static const Tk_GeomMgr frameGeomType = { + "labelframe", /* name */ + FrameRequestProc, /* requestProc */ + FrameLostSlaveProc /* lostSlaveProc */ }; - /* *-------------------------------------------------------------- * * Tk_FrameObjCmd, Tk_ToplevelObjCmd, Tk_LabelframeObjCmd -- * - * These procedures are invoked to process the "frame", - * "toplevel" and "labelframe" Tcl commands. See the user - * documentation for details on what they do. + * These functions are invoked to process the "frame", "toplevel" and + * "labelframe" Tcl commands. See the user documentation for details on + * what they do. * * Results: * A standard Tcl result. * * Side effects: - * See the user documentation. These procedures are just wrappers; - * they call CreateFrame to do all of the real work. + * See the user documentation. These functions are just wrappers; they + * call CreateFrame to do all of the real work. * *-------------------------------------------------------------- */ int -Tk_FrameObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_FrameObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - return CreateFrame(clientData, interp, objc, objv, TYPE_FRAME, - (char *) NULL); + return CreateFrame(clientData, interp, objc, objv, TYPE_FRAME, NULL); } int -Tk_ToplevelObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_ToplevelObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - return CreateFrame(clientData, interp, objc, objv, TYPE_TOPLEVEL, - (char *) NULL); + return CreateFrame(clientData, interp, objc, objv, TYPE_TOPLEVEL, NULL); } int -Tk_LabelframeObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_LabelframeObjCmd( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - return CreateFrame(clientData, interp, objc, objv, TYPE_LABELFRAME, - (char *) NULL); + return CreateFrame(clientData, interp, objc, objv, TYPE_LABELFRAME, NULL); } /* @@ -423,10 +401,10 @@ Tk_LabelframeObjCmd(clientData, interp, objc, objv) * * TkCreateFrame -- * - * This procedure is the old command procedure for the "frame" - * and "toplevel" commands. Now it is used directly by Tk_Init to - * create a new main window. See the user documentation for the - * "frame" and "toplevel" commands for details on what it does. + * This function is the old command function for the "frame" and + * "toplevel" commands. Now it is used directly by Tk_Init to create a + * new main window. See the user documentation for the "frame" and + * "toplevel" commands for details on what it does. * * Results: * A standard Tcl result. @@ -438,20 +416,21 @@ Tk_LabelframeObjCmd(clientData, interp, objc, objv) */ int -TkCreateFrame(clientData, interp, argc, argv, toplevel, appName) - ClientData clientData; /* Either NULL or pointer to option table. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ - int toplevel; /* Non-zero means create a toplevel window, +TkCreateFrame( + ClientData clientData, /* Either NULL or pointer to option table. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + char **argv, /* Argument strings. */ + int toplevel, /* Non-zero means create a toplevel window, * zero means create a frame. */ - char *appName; /* Should only be non-NULL if there is no main + char *appName) /* 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. */ + * Gives the base name to use for the new + * application. */ { int result, i; Tcl_Obj **objv = (Tcl_Obj **) ckalloc((argc+1) * sizeof(Tcl_Obj **)); + for (i=0; i<argc; i++) { objv[i] = Tcl_NewStringObj(argv[i], -1); Tcl_IncrRefCount(objv[i]); @@ -467,23 +446,23 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName) } static int -CreateFrame(clientData, interp, objc, objv, type, appName) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ - enum FrameType type; /* What widget type to create. */ - char *appName; /* Should only be non-NULL if there are no - * Main window associated with the interpreter. - * Gives the base name to use for the - * new application. */ +CreateFrame( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument objects. */ + enum FrameType type, /* What widget type to create. */ + char *appName) /* Should only be non-NULL if there are no + * Main window associated with the + * interpreter. Gives the base name to use for + * the new application. */ { Tk_Window tkwin; Frame *framePtr; Tk_OptionTable optionTable; - Tk_Window new; + Tk_Window newWin; CONST char *className, *screenName, *visualName, *colormapName, *arg, *useOption; - int i, c, depth, length; + int i, c, length, depth; unsigned int mask; Colormap colormap; Visual *visual; @@ -494,17 +473,17 @@ CreateFrame(clientData, interp, objc, objv, type, appName) } /* - * Create the option table for this widget class. If it has already - * been created, the cached pointer will be returned. + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]); /* - * Pre-process the argument list. Scan through it to find any - * "-class", "-screen", "-visual", and "-colormap" options. These - * arguments need to be processed specially, before the window - * is configured using the usual Tk mechanisms. + * Pre-process the argument list. Scan through it to find any "-class", + * "-screen", "-visual", and "-colormap" options. These arguments need to + * be processed specially, before the window is configured using the usual + * Tk mechanisms. */ className = colormapName = screenName = visualName = useOption = NULL; @@ -515,8 +494,8 @@ CreateFrame(clientData, interp, objc, objv, type, appName) continue; } c = arg[1]; - if ((c == 'c') && (strncmp(arg, "-class", (unsigned) length) == 0) - && (length >= 3)) { + if ((c == 'c') && (length >= 3) + && (strncmp(arg, "-class", (unsigned) length) == 0)) { className = Tcl_GetString(objv[i+1]); } else if ((c == 'c') && (strncmp(arg, "-colormap", (unsigned) length) == 0)) { @@ -534,18 +513,17 @@ CreateFrame(clientData, interp, objc, objv, type, appName) } /* - * Create the window, and deal with the special options -use, - * -classname, -colormap, -screenname, and -visual. These options - * must be handle before calling ConfigureFrame below, and they must - * also be processed in a particular order, for the following - * reasons: - * 1. Must set the window's class before calling ConfigureFrame, - * so that unspecified options are looked up in the option - * database using the correct class. - * 2. Must set visual information before calling ConfigureFrame - * so that colors are allocated in a proper colormap. + * Create the window, and deal with the special options -use, -classname, + * -colormap, -screenname, and -visual. These options must be handle + * before calling ConfigureFrame below, and they must also be processed in + * a particular order, for the following reasons: + * 1. Must set the window's class before calling ConfigureFrame, so that + * unspecified options are looked up in the option database using the + * correct class. + * 2. Must set visual information before calling ConfigureFrame so that + * colors are allocated in a proper colormap. * 3. Must call TkpUseWindow before setting non-default visual - * information, since TkpUseWindow changes the defaults. + * information, since TkpUseWindow changes the defaults. */ if (screenName == NULL) { @@ -553,88 +531,93 @@ CreateFrame(clientData, interp, objc, objv, type, appName) } /* - * Main window associated with interpreter. - * If we're called by Tk_Init to create a - * new application, then this is NULL. + * Main window associated with interpreter. If we're called by Tk_Init to + * create a new application, then this is NULL. */ tkwin = Tk_MainWindow(interp); if (tkwin != NULL) { - new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), + newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), screenName); } else if (appName == NULL) { /* - * This occurs when someone tried to create a frame/toplevel - * while we are being destroyed. Let an error be thrown. + * This occurs when someone tried to create a frame/toplevel while we + * are being destroyed. Let an error be thrown. */ Tcl_AppendResult(interp, "unable to create widget \"", - Tcl_GetString(objv[1]), "\"", (char *) NULL); - new = NULL; + Tcl_GetString(objv[1]), "\"", NULL); + newWin = NULL; } else { /* - * We were called from Tk_Init; create a new application. + * We were called from Tk_Init; create a new application. */ - new = TkCreateMainWindow(interp, screenName, appName); + newWin = TkCreateMainWindow(interp, screenName, appName); } - if (new == NULL) { + if (newWin == NULL) { goto error; + } else { + /* + * Mark Tk frames as suitable candidates for [wm manage] + */ + TkWindow *winPtr = (TkWindow *)newWin; + winPtr->flags |= TK_WM_MANAGEABLE; } if (className == NULL) { - className = Tk_GetOption(new, "class", "Class"); + className = Tk_GetOption(newWin, "class", "Class"); if (className == NULL) { className = classNames[type]; } } - Tk_SetClass(new, className); + Tk_SetClass(newWin, className); if (useOption == NULL) { - useOption = Tk_GetOption(new, "use", "Use"); + useOption = Tk_GetOption(newWin, "use", "Use"); } if ((useOption != NULL) && (*useOption != 0)) { - if (TkpUseWindow(interp, new, useOption) != TCL_OK) { + if (TkpUseWindow(interp, newWin, useOption) != TCL_OK) { goto error; } } if (visualName == NULL) { - visualName = Tk_GetOption(new, "visual", "Visual"); + visualName = Tk_GetOption(newWin, "visual", "Visual"); } if (colormapName == NULL) { - colormapName = Tk_GetOption(new, "colormap", "Colormap"); + colormapName = Tk_GetOption(newWin, "colormap", "Colormap"); } if ((colormapName != NULL) && (*colormapName == 0)) { colormapName = NULL; } if (visualName != NULL) { - visual = Tk_GetVisual(interp, new, visualName, &depth, - (colormapName == NULL) ? &colormap : (Colormap *) NULL); + visual = Tk_GetVisual(interp, newWin, visualName, &depth, + (colormapName == NULL) ? &colormap : NULL); if (visual == NULL) { goto error; } - Tk_SetWindowVisual(new, visual, depth, colormap); + Tk_SetWindowVisual(newWin, visual, depth, colormap); } if (colormapName != NULL) { - colormap = Tk_GetColormap(interp, new, colormapName); + colormap = Tk_GetColormap(interp, newWin, colormapName); if (colormap == None) { goto error; } - Tk_SetWindowColormap(new, colormap); + Tk_SetWindowColormap(newWin, colormap); } /* - * For top-level windows, provide an initial geometry request of - * 200x200, just so the window looks nicer on the screen if it - * doesn't request a size for itself. + * For top-level windows, provide an initial geometry request of 200x200, + * just so the window looks nicer on the screen if it doesn't request a + * size for itself. */ if (type == TYPE_TOPLEVEL) { - Tk_GeometryRequest(new, 200, 200); + Tk_GeometryRequest(newWin, 200, 200); } /* - * Create the widget record, process configuration options, and - * create event handlers. Then fill in a few additional fields - * in the widget record from the special options. + * Create the widget record, process configuration options, and create + * event handlers. Then fill in a few additional fields in the widget + * record from the special options. */ if (type == TYPE_LABELFRAME) { @@ -644,11 +627,11 @@ CreateFrame(clientData, interp, objc, objv, type, appName) framePtr = (Frame *) ckalloc(sizeof(Frame)); memset((void *) framePtr, 0, (sizeof(Frame))); } - framePtr->tkwin = new; - framePtr->display = Tk_Display(new); + framePtr->tkwin = newWin; + framePtr->display = Tk_Display(newWin); framePtr->interp = interp; framePtr->widgetCmd = Tcl_CreateObjCommand(interp, - Tk_PathName(new), FrameWidgetObjCmd, + Tk_PathName(newWin), FrameWidgetObjCmd, (ClientData) framePtr, FrameCmdDeletedProc); framePtr->optionTable = optionTable; framePtr->type = type; @@ -665,14 +648,15 @@ CreateFrame(clientData, interp, objc, objv, type, appName) /* * Store backreference to frame widget in window structure. */ - Tk_SetClassProcs(new, &frameClass, (ClientData) framePtr); + + Tk_SetClassProcs(newWin, &frameClass, (ClientData) framePtr); mask = ExposureMask | StructureNotifyMask | FocusChangeMask; if (type == TYPE_TOPLEVEL) { - mask |= ActivateMask; + mask |= ActivateMask; } - Tk_CreateEventHandler(new, mask, FrameEventProc, (ClientData) framePtr); - if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, new) + Tk_CreateEventHandler(newWin, mask, FrameEventProc, (ClientData) framePtr); + if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, newWin) != TCL_OK) || (ConfigureFrame(interp, framePtr, objc-2, objv+2) != TCL_OK)) { goto error; @@ -682,19 +666,19 @@ CreateFrame(clientData, interp, objc, objv, type, appName) TkpMakeContainer(framePtr->tkwin); } else { Tcl_AppendResult(interp, "A window cannot have both the -use ", - "and the -container option set.", (char *) NULL); + "and the -container option set.", NULL); goto error; } } if (type == TYPE_TOPLEVEL) { Tcl_DoWhenIdle(MapFrame, (ClientData) framePtr); } - Tcl_SetResult(interp, Tk_PathName(new), TCL_STATIC); + Tcl_SetResult(interp, Tk_PathName(newWin), TCL_STATIC); return TCL_OK; - error: - if (new != NULL) { - Tk_DestroyWindow(new); + error: + if (newWin != NULL) { + Tk_DestroyWindow(newWin); } return TCL_ERROR; } @@ -704,9 +688,9 @@ CreateFrame(clientData, interp, objc, objv, type, appName) * * FrameWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a frame widget. See the user - * documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a frame widget. See the user documentation for details on what it + * does. * * Results: * A standard Tcl result. @@ -718,14 +702,14 @@ CreateFrame(clientData, interp, objc, objv, type, appName) */ static int -FrameWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about frame widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +FrameWidgetObjCmd( + ClientData clientData, /* Information about frame widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { static CONST char *frameOptions[] = { - "cget", "configure", (char *) NULL + "cget", "configure", NULL }; enum options { FRAME_CGET, FRAME_CONFIGURE @@ -745,27 +729,26 @@ FrameWidgetObjCmd(clientData, interp, objc, objv) } Tcl_Preserve((ClientData) framePtr); switch ((enum options) index) { - case FRAME_CGET: { + case FRAME_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; goto done; } - objPtr = Tk_GetOptionValue(interp, (char *) framePtr, + objPtr = Tk_GetOptionValue(interp, (char *) framePtr, framePtr->optionTable, objv[2], framePtr->tkwin); - if (objPtr == NULL) { + if (objPtr == NULL) { result = TCL_ERROR; goto done; - } else { + } else { Tcl_SetObjResult(interp, objPtr); - } + } break; - } - case FRAME_CONFIGURE: { + case FRAME_CONFIGURE: if (objc <= 3) { objPtr = Tk_GetOptionInfo(interp, (char *) framePtr, framePtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, + (objc == 3) ? objv[2] : NULL, framePtr->tkwin); if (objPtr == NULL) { result = TCL_ERROR; @@ -775,8 +758,8 @@ FrameWidgetObjCmd(clientData, interp, objc, objv) } } else { /* - * Don't allow the options -class, -colormap, -container, - * -newcmap, -screen, -use, or -visual to be changed. + * Don't allow the options -class, -colormap, -container, -screen, + * -use, or -visual to be changed. */ for (i = 2; i < objc; i++) { @@ -785,34 +768,47 @@ FrameWidgetObjCmd(clientData, interp, objc, objv) continue; } c = arg[1]; - if (((c == 'c') - && (strncmp(arg, "-class", (unsigned) length) == 0) - && (length >= 2)) - || ((c == 'c') - && (strncmp(arg, "-colormap", (unsigned) length) == 0) - && (length >= 3)) - || ((c == 'c') - && (strncmp(arg, "-container", (unsigned) length) == 0) - && (length >= 3)) - || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL) - && (strncmp(arg, "-screen", (unsigned) length) == 0)) - || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL) - && (strncmp(arg, "-use", (unsigned) length) == 0)) - || ((c == 'v') - && (strncmp(arg, "-visual", (unsigned) length) ==0))) { - Tcl_AppendResult(interp, "can't modify ", arg, - " option after widget is created", (char *) NULL); - result = TCL_ERROR; - goto done; + if (((c == 'c') && (length >= 2) + && (strncmp(arg, "-class", (unsigned)length) == 0)) + || ((c == 'c') && (length >= 3) + && (strncmp(arg, "-colormap", (unsigned)length) == 0)) + || ((c == 'c') && (length >= 3) + && (strncmp(arg, "-container", (unsigned)length) == 0)) + || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL) + && (strncmp(arg, "-screen", (unsigned)length) == 0)) + || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL) + && (strncmp(arg, "-use", (unsigned)length) == 0)) + || ((c == 'v') + && (strncmp(arg, "-visual", (unsigned)length) == 0))) { + + #ifdef SUPPORT_CONFIG_EMBEDDED + if (c == 'u') { + CONST char *string = Tcl_GetString(objv[i+1]); + if (TkpUseWindow(interp, framePtr->tkwin, + string) != TCL_OK) { + result = TCL_ERROR; + goto done; + } + } else { + Tcl_AppendResult(interp, "can't modify ", arg, + " option after widget is created", NULL); + result = TCL_ERROR; + goto done; + } + #else + Tcl_AppendResult(interp, "can't modify ", arg, + " option after widget is created", NULL); + result = TCL_ERROR; + goto done; + #endif } } result = ConfigureFrame(interp, framePtr, objc-2, objv+2); } break; - } } - done: + done: Tcl_Release((ClientData) framePtr); return result; } @@ -822,9 +818,9 @@ FrameWidgetObjCmd(clientData, interp, objc, objv) * * DestroyFrame -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a frame at a safe time - * (when no-one is using it anymore). + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of a frame at a safe time (when no-one is + * using it anymore). * * Results: * None. @@ -836,8 +832,8 @@ FrameWidgetObjCmd(clientData, interp, objc, objv) */ static void -DestroyFrame(memPtr) - char *memPtr; /* Info about frame widget. */ +DestroyFrame( + char *memPtr) /* Info about frame widget. */ { register Frame *framePtr = (Frame *) memPtr; register Labelframe *labelframePtr = (Labelframe *) memPtr; @@ -859,10 +855,9 @@ DestroyFrame(memPtr) * * DestroyFramePartly -- * - * This procedure is invoked to clean up everything that needs - * tkwin to be defined when deleted. During the destruction - * process tkwin is always set to NULL and this procedure must - * be called before that happens. + * This function is invoked to clean up everything that needs tkwin to be + * defined when deleted. During the destruction process tkwin is always + * set to NULL and this function must be called before that happens. * * Results: * None. @@ -874,16 +869,15 @@ DestroyFrame(memPtr) */ static void -DestroyFramePartly(framePtr) - Frame *framePtr; /* Info about frame widget. */ +DestroyFramePartly( + Frame *framePtr) /* Info about frame widget. */ { register Labelframe *labelframePtr = (Labelframe *) framePtr; if (framePtr->type == TYPE_LABELFRAME && labelframePtr->labelWin != NULL) { Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask, FrameStructureProc, (ClientData) framePtr); - Tk_ManageGeometry(labelframePtr->labelWin, (Tk_GeomMgr *) NULL, - (ClientData) NULL); + Tk_ManageGeometry(labelframePtr->labelWin, NULL, (ClientData) NULL); if (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) { Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin); } @@ -892,7 +886,7 @@ DestroyFramePartly(framePtr) } Tk_FreeConfigOptions((char *) framePtr, framePtr->optionTable, - framePtr->tkwin); + framePtr->tkwin); } /* @@ -900,29 +894,28 @@ DestroyFramePartly(framePtr) * * ConfigureFrame -- * - * This procedure is called to process an objv/objc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a frame widget. + * This function is called to process an objv/objc list, plus the Tk + * option database, in order to configure (or reconfigure) a frame + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as text string, colors, font, - * etc. get set for framePtr; old resources get freed, if there - * were any. + * Configuration information, such as text string, colors, font, etc. get + * set for framePtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureFrame(interp, framePtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - register Frame *framePtr; /* Information about widget; may or may - * not already have values for some fields. */ - int objc; /* Number of valid entries in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ +ConfigureFrame( + Tcl_Interp *interp, /* Used for error reporting. */ + register Frame *framePtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments. */ { Tk_SavedOptions savedOptions; char *oldMenuName; @@ -932,7 +925,7 @@ ConfigureFrame(interp, framePtr, objc, objv) /* * Need the old menubar name for the menu code to delete it. */ - + if (framePtr->menuName == NULL) { oldMenuName = NULL; } else { @@ -945,7 +938,7 @@ ConfigureFrame(interp, framePtr, objc, objv) } if (Tk_SetOptions(interp, (char *) framePtr, framePtr->optionTable, objc, objv, - framePtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { + framePtr->tkwin, &savedOptions, NULL) != TCL_OK) { if (oldMenuName != NULL) { ckfree(oldMenuName); } @@ -958,10 +951,11 @@ ConfigureFrame(interp, framePtr, objc, objv) * A few of the options require additional processing. */ - if (((oldMenuName == NULL) && (framePtr->menuName != NULL)) + if ((((oldMenuName == NULL) && (framePtr->menuName != NULL)) || ((oldMenuName != NULL) && (framePtr->menuName == NULL)) || ((oldMenuName != NULL) && (framePtr->menuName != NULL) - && strcmp(oldMenuName, framePtr->menuName) != 0)) { + && strcmp(oldMenuName, framePtr->menuName) != 0)) + && framePtr->type == TYPE_TOPLEVEL) { TkSetWindowMenuBar(interp, framePtr->tkwin, oldMenuName, framePtr->menuName); } @@ -987,8 +981,8 @@ ConfigureFrame(interp, framePtr, objc, objv) } /* - * If a -labelwidget is specified, check that it is valid and set - * up geometry management for it. + * If a -labelwidget is specified, check that it is valid and set up + * geometry management for it. */ if (framePtr->type == TYPE_LABELFRAME) { @@ -996,8 +990,7 @@ ConfigureFrame(interp, framePtr, objc, objv) if (oldWindow != NULL) { Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, FrameStructureProc, (ClientData) framePtr); - Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL, - (ClientData) NULL); + Tk_ManageGeometry(oldWindow, NULL, (ClientData) NULL); Tk_UnmaintainGeometry(oldWindow, framePtr->tkwin); Tk_UnmapWindow(oldWindow); } @@ -1005,10 +998,9 @@ ConfigureFrame(interp, framePtr, objc, objv) Tk_Window ancestor, parent, sibling = NULL; /* - * Make sure that the frame is either the parent of the - * window used as label or a descendant of that - * parent. Also, don't allow a top-level window to be - * managed inside the frame. + * Make sure that the frame is either the parent of the window + * used as label or a descendant of that parent. Also, don't + * allow a top-level window to be managed inside the frame. */ parent = Tk_Parent(labelframePtr->labelWin); @@ -1022,7 +1014,7 @@ ConfigureFrame(interp, framePtr, objc, objv) badWindow: Tcl_AppendResult(interp, "can't use ", Tk_PathName(labelframePtr->labelWin), - " as label in this frame", (char *) NULL); + " as label in this frame", NULL); labelframePtr->labelWin = NULL; return TCL_ERROR; } @@ -1040,9 +1032,8 @@ ConfigureFrame(interp, framePtr, objc, objv) (ClientData) framePtr); /* - * If the frame is not parent to the label, make - * sure the label is above its sibling in the stacking - * order. + * If the frame is not parent to the label, make sure the + * label is above its sibling in the stacking order. */ if (sibling != NULL) { @@ -1062,22 +1053,22 @@ ConfigureFrame(interp, framePtr, objc, objv) * * FrameWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: - * None. + * None. * * Side effects: - * Frame will be relayed out and redisplayed. + * Frame will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ - + static void -FrameWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +FrameWorldChanged( + ClientData instanceData) /* Information about widget. */ { Frame *framePtr = (Frame *) instanceData; Labelframe *labelframePtr = (Labelframe *) framePtr; @@ -1096,8 +1087,8 @@ FrameWorldChanged(instanceData) if (framePtr->type == TYPE_LABELFRAME) { /* - * The textGC is needed even in the labelWin case, so it's - * always created for a labelframe. + * The textGC is needed even in the labelWin case, so it's always + * created for a labelframe. */ gcValues.font = Tk_FontId(labelframePtr->tkfont); @@ -1113,7 +1104,7 @@ FrameWorldChanged(instanceData) /* * Calculate label size. */ - + labelframePtr->labelReqWidth = labelframePtr->labelReqHeight = 0; if (anyTextLabel) { @@ -1129,13 +1120,13 @@ FrameWorldChanged(instanceData) labelframePtr->labelReqHeight = Tk_ReqHeight(labelframePtr->labelWin); } - /* - * Make sure label size is at least as big as the border. - * This simplifies later calculations and gives a better - * appearance with thick borders. + /* + * Make sure label size is at least as big as the border. This + * simplifies later calculations and gives a better appearance with + * thick borders. */ - - if ((labelframePtr->labelAnchor >= LABELANCHOR_N) && + + if ((labelframePtr->labelAnchor >= LABELANCHOR_N) && (labelframePtr->labelAnchor <= LABELANCHOR_SW)) { if (labelframePtr->labelReqHeight < framePtr->borderWidth) { labelframePtr->labelReqHeight = framePtr->borderWidth; @@ -1151,34 +1142,34 @@ FrameWorldChanged(instanceData) * Calculate individual border widths. */ - bWidthBottom = bWidthTop = bWidthRight = bWidthLeft = - framePtr->borderWidth + framePtr->highlightWidth; + bWidthBottom = bWidthTop = bWidthRight = bWidthLeft = + framePtr->borderWidth + framePtr->highlightWidth; bWidthLeft += framePtr->padX; bWidthRight += framePtr->padX; bWidthTop += framePtr->padY; bWidthBottom += framePtr->padY; - + if (anyTextLabel || anyWindowLabel) { switch (labelframePtr->labelAnchor) { - case LABELANCHOR_E: - case LABELANCHOR_EN: - case LABELANCHOR_ES: + case LABELANCHOR_E: + case LABELANCHOR_EN: + case LABELANCHOR_ES: bWidthRight += labelframePtr->labelReqWidth - framePtr->borderWidth; break; - case LABELANCHOR_N: - case LABELANCHOR_NE: - case LABELANCHOR_NW: + case LABELANCHOR_N: + case LABELANCHOR_NE: + case LABELANCHOR_NW: bWidthTop += labelframePtr->labelReqHeight - framePtr->borderWidth; break; - case LABELANCHOR_S: - case LABELANCHOR_SE: - case LABELANCHOR_SW: + case LABELANCHOR_S: + case LABELANCHOR_SE: + case LABELANCHOR_SW: bWidthBottom += labelframePtr->labelReqHeight - framePtr->borderWidth; break; - default: + default: bWidthLeft += labelframePtr->labelReqWidth - framePtr->borderWidth; break; } @@ -1197,11 +1188,12 @@ FrameWorldChanged(instanceData) int minwidth = labelframePtr->labelReqWidth; int minheight = labelframePtr->labelReqHeight; int padding = framePtr->highlightWidth; + if (framePtr->borderWidth > 0) { padding += framePtr->borderWidth + LABELMARGIN; } padding *= 2; - if ((labelframePtr->labelAnchor >= LABELANCHOR_N) && + if ((labelframePtr->labelAnchor >= LABELANCHOR_N) && (labelframePtr->labelAnchor <= LABELANCHOR_SW)) { minwidth += padding; minheight += framePtr->borderWidth + framePtr->highlightWidth; @@ -1229,9 +1221,9 @@ FrameWorldChanged(instanceData) * * ComputeFrameGeometry -- * - * This procedure is called to compute various geometrical - * information for a frame, such as where various things get - * displayed. It's called when the window is reconfigured. + * This function is called to compute various geometrical information for + * a frame, such as where various things get displayed. It's called when + * the window is reconfigured. * * Results: * None. @@ -1243,8 +1235,8 @@ FrameWorldChanged(instanceData) */ static void -ComputeFrameGeometry(framePtr) - register Frame *framePtr; /* Information about widget. */ +ComputeFrameGeometry( + register Frame *framePtr) /* Information about widget. */ { int otherWidth, otherHeight, otherWidthT, otherHeightT, padding; int maxWidth, maxHeight; @@ -1256,12 +1248,13 @@ ComputeFrameGeometry(framePtr) */ if (framePtr->type != TYPE_LABELFRAME) return; - if ((labelframePtr->textPtr == NULL) && - (labelframePtr->labelWin == NULL)) return; + if (labelframePtr->textPtr == NULL && labelframePtr->labelWin == NULL) { + return; + } tkwin = framePtr->tkwin; - /* + /* * Calculate the available size for the label */ @@ -1270,15 +1263,15 @@ ComputeFrameGeometry(framePtr) padding = framePtr->highlightWidth; if (framePtr->borderWidth > 0) { - padding += framePtr->borderWidth + LABELMARGIN; + padding += framePtr->borderWidth + LABELMARGIN; } padding *= 2; maxHeight = Tk_Height(tkwin); maxWidth = Tk_Width(tkwin); - if ((labelframePtr->labelAnchor >= LABELANCHOR_N) && - (labelframePtr->labelAnchor <= LABELANCHOR_SW)) { + if ((labelframePtr->labelAnchor >= LABELANCHOR_N) && + (labelframePtr->labelAnchor <= LABELANCHOR_SW)) { maxWidth -= padding; if (maxWidth < 1) maxWidth = 1; } else { @@ -1293,9 +1286,9 @@ ComputeFrameGeometry(framePtr) } /* - * Calculate label and text position. - * The text's position is based on the requested size (= the text's - * real size) to get proper alignment if the text does not fit. + * Calculate label and text position. The text's position is based on the + * requested size (= the text's real size) to get proper alignment if the + * text does not fit. */ otherWidth = Tk_Width(tkwin) - labelframePtr->labelBox.width; @@ -1305,64 +1298,64 @@ ComputeFrameGeometry(framePtr) padding = framePtr->highlightWidth; switch (labelframePtr->labelAnchor) { - case LABELANCHOR_E: - case LABELANCHOR_EN: - case LABELANCHOR_ES: - labelframePtr->labelTextX = otherWidthT - padding; - labelframePtr->labelBox.x = otherWidth - padding; - break; - case LABELANCHOR_N: - case LABELANCHOR_NE: - case LABELANCHOR_NW: - labelframePtr->labelTextY = padding; - labelframePtr->labelBox.y = padding; - break; - case LABELANCHOR_S: - case LABELANCHOR_SE: - case LABELANCHOR_SW: - labelframePtr->labelTextY = otherHeightT - padding; - labelframePtr->labelBox.y = otherHeight - padding; - break; - default: - labelframePtr->labelTextX = padding; - labelframePtr->labelBox.x = padding; - break; + case LABELANCHOR_E: + case LABELANCHOR_EN: + case LABELANCHOR_ES: + labelframePtr->labelTextX = otherWidthT - padding; + labelframePtr->labelBox.x = otherWidth - padding; + break; + case LABELANCHOR_N: + case LABELANCHOR_NE: + case LABELANCHOR_NW: + labelframePtr->labelTextY = padding; + labelframePtr->labelBox.y = padding; + break; + case LABELANCHOR_S: + case LABELANCHOR_SE: + case LABELANCHOR_SW: + labelframePtr->labelTextY = otherHeightT - padding; + labelframePtr->labelBox.y = otherHeight - padding; + break; + default: + labelframePtr->labelTextX = padding; + labelframePtr->labelBox.x = padding; + break; } if (framePtr->borderWidth > 0) { - padding += framePtr->borderWidth + LABELMARGIN; + padding += framePtr->borderWidth + LABELMARGIN; } switch (labelframePtr->labelAnchor) { - case LABELANCHOR_NW: - case LABELANCHOR_SW: - labelframePtr->labelTextX = padding; - labelframePtr->labelBox.x = padding; - break; - case LABELANCHOR_N: - case LABELANCHOR_S: - labelframePtr->labelTextX = otherWidthT / 2; - labelframePtr->labelBox.x = otherWidth / 2; - break; - case LABELANCHOR_NE: - case LABELANCHOR_SE: - labelframePtr->labelTextX = otherWidthT - padding; - labelframePtr->labelBox.x = otherWidth - padding; - break; - case LABELANCHOR_EN: - case LABELANCHOR_WN: - labelframePtr->labelTextY = padding; - labelframePtr->labelBox.y = padding; - break; - case LABELANCHOR_E: - case LABELANCHOR_W: - labelframePtr->labelTextY = otherHeightT / 2; - labelframePtr->labelBox.y = otherHeight / 2; - break; - default: + case LABELANCHOR_NW: + case LABELANCHOR_SW: + labelframePtr->labelTextX = padding; + labelframePtr->labelBox.x = padding; + break; + case LABELANCHOR_N: + case LABELANCHOR_S: + labelframePtr->labelTextX = otherWidthT / 2; + labelframePtr->labelBox.x = otherWidth / 2; + break; + case LABELANCHOR_NE: + case LABELANCHOR_SE: + labelframePtr->labelTextX = otherWidthT - padding; + labelframePtr->labelBox.x = otherWidth - padding; + break; + case LABELANCHOR_EN: + case LABELANCHOR_WN: + labelframePtr->labelTextY = padding; + labelframePtr->labelBox.y = padding; + break; + case LABELANCHOR_E: + case LABELANCHOR_W: + labelframePtr->labelTextY = otherHeightT / 2; + labelframePtr->labelBox.y = otherHeight / 2; + break; + default: labelframePtr->labelTextY = otherHeightT - padding; labelframePtr->labelBox.y = otherHeight - padding; - break; + break; } } @@ -1371,21 +1364,20 @@ ComputeFrameGeometry(framePtr) * * DisplayFrame -- * - * This procedure is invoked to display a frame widget. + * This function is invoked to display a frame widget. * * Results: * None. * * Side effects: - * Commands are output to X to display the frame in its - * current mode. + * Commands are output to X to display the frame in its current mode. * *---------------------------------------------------------------------- */ static void -DisplayFrame(clientData) - ClientData clientData; /* Information about widget. */ +DisplayFrame( + ClientData clientData) /* Information about widget. */ { register Frame *framePtr = (Frame *) clientData; register Tk_Window tkwin = framePtr->tkwin; @@ -1394,8 +1386,7 @@ DisplayFrame(clientData) TkRegion clipRegion = NULL; framePtr->flags &= ~REDRAW_PENDING; - if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin) - || framePtr->isContainer) { + if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } @@ -1406,7 +1397,7 @@ DisplayFrame(clientData) hlWidth = framePtr->highlightWidth; if (hlWidth != 0) { - GC fgGC, bgGC; + GC fgGC, bgGC; bgGC = Tk_GCForColor(framePtr->highlightBgColorPtr, Tk_WindowId(tkwin)); @@ -1429,11 +1420,11 @@ DisplayFrame(clientData) if (framePtr->type != TYPE_LABELFRAME) { /* - * Pass to platform specific draw function. In general, it just - * draws a simple rectangle, but it may "theme" the background. + * Pass to platform specific draw function. In general, it just draws + * a simple rectangle, but it may "theme" the background. */ - noLabel: + noLabel: TkpDrawFrame(tkwin, framePtr->border, hlWidth, framePtr->borderWidth, framePtr->relief); } else { @@ -1446,10 +1437,10 @@ DisplayFrame(clientData) #ifndef TK_NO_DOUBLE_BUFFERING /* - * In order to avoid screen flashes, this procedure redraws the - * frame into off-screen memory, then copies it back on-screen - * in a single operation. This means there's no point in time - * where the on-screen image has been cleared. + * In order to avoid screen flashes, this function redraws the frame + * into off-screen memory, then copies it back on-screen in a single + * operation. This means there's no point in time where the on-screen + * image has been cleared. */ pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin), @@ -1458,7 +1449,7 @@ DisplayFrame(clientData) pixmap = Tk_WindowId(tkwin); #endif /* TK_NO_DOUBLE_BUFFERING */ - /* + /* * Clear the pixmap. */ @@ -1474,61 +1465,56 @@ DisplayFrame(clientData) bdY2 = Tk_Height(tkwin) - hlWidth; switch (labelframePtr->labelAnchor) { - case LABELANCHOR_E: - case LABELANCHOR_EN: - case LABELANCHOR_ES: - bdX2 -= (labelframePtr->labelBox.width - framePtr->borderWidth) - / 2; + case LABELANCHOR_E: + case LABELANCHOR_EN: + case LABELANCHOR_ES: + bdX2 -= (labelframePtr->labelBox.width-framePtr->borderWidth) / 2; break; - case LABELANCHOR_N: - case LABELANCHOR_NE: - case LABELANCHOR_NW: - /* - * Since the glyphs of the text tend to be in the lower part - * we favor a lower border position by rounding up. + case LABELANCHOR_N: + case LABELANCHOR_NE: + case LABELANCHOR_NW: + /* + * Since the glyphs of the text tend to be in the lower part we + * favor a lower border position by rounding up. */ - bdY1 += (labelframePtr->labelBox.height - framePtr->borderWidth +1) - / 2; + bdY1 += (labelframePtr->labelBox.height-framePtr->borderWidth+1)/2; break; - case LABELANCHOR_S: - case LABELANCHOR_SE: - case LABELANCHOR_SW: - bdY2 -= (labelframePtr->labelBox.height - framePtr->borderWidth) - / 2; + case LABELANCHOR_S: + case LABELANCHOR_SE: + case LABELANCHOR_SW: + bdY2 -= (labelframePtr->labelBox.height-framePtr->borderWidth) / 2; break; - default: - bdX1 += (labelframePtr->labelBox.width - framePtr->borderWidth) - / 2; + default: + bdX1 += (labelframePtr->labelBox.width-framePtr->borderWidth) / 2; break; } - /* - * Draw border - */ + /* + * Draw border + */ Tk_Draw3DRectangle(tkwin, pixmap, framePtr->border, bdX1, bdY1, bdX2 - bdX1, bdY2 - bdY1, framePtr->borderWidth, framePtr->relief); - if (labelframePtr->labelWin == NULL) { - /* - * Clear behind the label - */ - - Tk_Fill3DRectangle(tkwin, pixmap, - framePtr->border, labelframePtr->labelBox.x, - labelframePtr->labelBox.y, labelframePtr->labelBox.width, - labelframePtr->labelBox.height, 0, TK_RELIEF_FLAT); - - /* - * Draw label. - * If there is not room for the entire label, use clipping to - * get a nice appearance. - */ - + if (labelframePtr->labelWin == NULL) { + /* + * Clear behind the label + */ + + Tk_Fill3DRectangle(tkwin, pixmap, + framePtr->border, labelframePtr->labelBox.x, + labelframePtr->labelBox.y, labelframePtr->labelBox.width, + labelframePtr->labelBox.height, 0, TK_RELIEF_FLAT); + + /* + * Draw label. If there is not room for the entire label, use + * clipping to get a nice appearance. + */ + if ((labelframePtr->labelBox.width < labelframePtr->labelReqWidth) - || (labelframePtr->labelBox.height < + || (labelframePtr->labelBox.height < labelframePtr->labelReqHeight)) { clipRegion = TkCreateRegion(); TkUnionRectWithRegion(&labelframePtr->labelBox, clipRegion, @@ -1537,37 +1523,37 @@ DisplayFrame(clientData) clipRegion); } - Tk_DrawTextLayout(framePtr->display, pixmap, - labelframePtr->textGC, labelframePtr->textLayout, - labelframePtr->labelTextX + LABELSPACING, - labelframePtr->labelTextY + LABELSPACING, 0, -1); + Tk_DrawTextLayout(framePtr->display, pixmap, + labelframePtr->textGC, labelframePtr->textLayout, + labelframePtr->labelTextX + LABELSPACING, + labelframePtr->labelTextY + LABELSPACING, 0, -1); if (clipRegion != NULL) { XSetClipMask(framePtr->display, labelframePtr->textGC, None); TkDestroyRegion(clipRegion); } - } else { + } else { /* * Reposition and map the window (but in different ways depending * on whether the frame is the window's parent). */ - + if (framePtr->tkwin == Tk_Parent(labelframePtr->labelWin)) { if ((labelframePtr->labelBox.x != Tk_X(labelframePtr->labelWin)) || (labelframePtr->labelBox.y != Tk_Y(labelframePtr->labelWin)) - || (labelframePtr->labelBox.width != + || (labelframePtr->labelBox.width != Tk_Width(labelframePtr->labelWin)) - || (labelframePtr->labelBox.height != + || (labelframePtr->labelBox.height != Tk_Height(labelframePtr->labelWin))) { Tk_MoveResizeWindow(labelframePtr->labelWin, - labelframePtr->labelBox.x, labelframePtr->labelBox.y, + labelframePtr->labelBox.x, labelframePtr->labelBox.y, labelframePtr->labelBox.width, labelframePtr->labelBox.height); } Tk_MapWindow(labelframePtr->labelWin); } else { - Tk_MaintainGeometry(labelframePtr->labelWin, framePtr->tkwin, + Tk_MaintainGeometry(labelframePtr->labelWin, framePtr->tkwin, labelframePtr->labelBox.x, labelframePtr->labelBox.y, labelframePtr->labelBox.width, labelframePtr->labelBox.height); @@ -1577,7 +1563,7 @@ DisplayFrame(clientData) #ifndef TK_NO_DOUBLE_BUFFERING /* - * Everything's been redisplayed; now copy the pixmap onto the screen + * Everything's been redisplayed; now copy the pixmap onto the screen * and free up the pixmap. */ @@ -1597,24 +1583,24 @@ DisplayFrame(clientData) * * FrameEventProc -- * - * This procedure is invoked by the Tk dispatcher on - * structure changes to a frame. For frames with 3D - * borders, this procedure is also invoked for exposures. + * This function is invoked by the Tk dispatcher on structure changes to + * a frame. For frames with 3D borders, this function is also invoked for + * exposures. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -FrameEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - register XEvent *eventPtr; /* Information about event. */ +FrameEventProc( + ClientData clientData, /* Information about window. */ + register XEvent *eventPtr) /* Information about event. */ { register Frame *framePtr = (Frame *) clientData; @@ -1631,15 +1617,14 @@ FrameEventProc(clientData, eventPtr) framePtr->menuName = NULL; } if (framePtr->tkwin != NULL) { - /* - * If this window is a container, then this event could be - * coming from the embedded application, in which case - * Tk_DestroyWindow hasn't been called yet. When Tk_DestroyWindow - * is called later, then another destroy event will be generated. - * We need to be sure we ignore the second event, since the frame - * could be gone by then. To do so, delete the event handler - * explicitly (normally it's done implicitly by Tk_DestroyWindow). + * If this window is a container, then this event could be coming + * from the embedded application, in which case Tk_DestroyWindow + * hasn't been called yet. When Tk_DestroyWindow is called later, + * then another destroy event will be generated. We need to be + * sure we ignore the second event, since the frame could be gone + * by then. To do so, delete the event handler explicitly + * (normally it's done implicitly by Tk_DestroyWindow). */ /* @@ -1647,13 +1632,13 @@ FrameEventProc(clientData, eventPtr) * DestroyFrame, we must free all options now. */ - DestroyFramePartly(framePtr); + DestroyFramePartly(framePtr); Tk_DeleteEventHandler(framePtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, FrameEventProc, (ClientData) framePtr); framePtr->tkwin = NULL; - Tcl_DeleteCommandFromToken(framePtr->interp, framePtr->widgetCmd); + Tcl_DeleteCommandFromToken(framePtr->interp, framePtr->widgetCmd); } if (framePtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayFrame, (ClientData) framePtr); @@ -1680,7 +1665,7 @@ FrameEventProc(clientData, eventPtr) } return; - redraw: + redraw: if ((framePtr->tkwin != NULL) && !(framePtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayFrame, (ClientData) framePtr); framePtr->flags |= REDRAW_PENDING; @@ -1692,9 +1677,9 @@ FrameEventProc(clientData, eventPtr) * * FrameCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -1706,8 +1691,8 @@ FrameEventProc(clientData, eventPtr) */ static void -FrameCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +FrameCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { Frame *framePtr = (Frame *) clientData; Tk_Window tkwin = framePtr->tkwin; @@ -1720,19 +1705,19 @@ FrameCmdDeletedProc(clientData) } /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (tkwin != NULL) { - /* - * Some options need tkwin to be freed, so we free them here, - * before setting tkwin to NULL. + /* + * Some options need tkwin to be freed, so we free them here, before + * setting tkwin to NULL. */ - DestroyFramePartly(framePtr); + DestroyFramePartly(framePtr); framePtr->tkwin = NULL; Tk_DestroyWindow(tkwin); @@ -1744,8 +1729,8 @@ FrameCmdDeletedProc(clientData) * * MapFrame -- * - * This procedure is invoked as a when-idle handler to map a - * newly-created top-level frame. + * This function is invoked as a when-idle handler to map a newly-created + * top-level frame. * * Results: * None. @@ -1757,16 +1742,16 @@ FrameCmdDeletedProc(clientData) */ static void -MapFrame(clientData) - ClientData clientData; /* Pointer to frame structure. */ +MapFrame( + ClientData clientData) /* Pointer to frame structure. */ { Frame *framePtr = (Frame *) clientData; /* - * Wait for all other background events to be processed before - * mapping window. This ensures that the window's correct geometry - * will have been determined before it is first mapped, so that the - * window manager doesn't get a false idea of its desired geometry. + * Wait for all other background events to be processed before mapping + * window. This ensures that the window's correct geometry will have been + * determined before it is first mapped, so that the window manager + * doesn't get a false idea of its desired geometry. */ Tcl_Preserve((ClientData) framePtr); @@ -1776,8 +1761,8 @@ MapFrame(clientData) } /* - * After each event, make sure that the window still exists - * and quit if the window has been destroyed. + * After each event, make sure that the window still exists and quit + * if the window has been destroyed. */ if (framePtr->tkwin == NULL) { @@ -1794,24 +1779,23 @@ MapFrame(clientData) * * TkInstallFrameMenu -- * - * This function is needed when a Windows HWND is created - * and a menubar has been set to the window with a system - * menu. It notifies the menu package so that the system - * menu can be rebuilt. + * This function is needed when a Windows HWND is created and a menubar + * has been set to the window with a system menu. It notifies the menu + * package so that the system menu can be rebuilt. * * Results: * None. * * Side effects: - * The system menu (if any) is created for the menubar - * associated with this frame. + * The system menu (if any) is created for the menubar associated with + * this frame. * *-------------------------------------------------------------- */ void -TkInstallFrameMenu(tkwin) - Tk_Window tkwin; /* The window that was just created. */ +TkInstallFrameMenu( + Tk_Window tkwin) /* The window that was just created. */ { TkWindow *winPtr = (TkWindow *) tkwin; @@ -1819,9 +1803,9 @@ TkInstallFrameMenu(tkwin) Frame *framePtr; framePtr = (Frame*) winPtr->instanceData; if (framePtr == NULL) { - panic("TkInstallFrameMenu couldn't get frame pointer"); + Tcl_Panic("TkInstallFrameMenu couldn't get frame pointer"); } - TkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp, + TkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp, framePtr->menuName); } } @@ -1831,32 +1815,30 @@ TkInstallFrameMenu(tkwin) * * FrameStructureProc -- * - * This procedure is invoked whenever StructureNotify events - * occur for a window that's managed as label for the frame. - * This procudure's only purpose is to clean up when windows - * are deleted. + * This function is invoked whenever StructureNotify events occur for a + * window that's managed as label for the frame. This procudure's only + * purpose is to clean up when windows are deleted. * * Results: * None. * * Side effects: - * The window is disassociated from the frame when it is - * deleted. + * The window is disassociated from the frame when it is deleted. * *-------------------------------------------------------------- */ static void -FrameStructureProc(clientData, eventPtr) - ClientData clientData; /* Pointer to record describing frame. */ - XEvent *eventPtr; /* Describes what just happened. */ +FrameStructureProc( + ClientData clientData, /* Pointer to record describing frame. */ + XEvent *eventPtr) /* Describes what just happened. */ { Labelframe *labelframePtr = (Labelframe *) clientData; if (eventPtr->type == DestroyNotify) { /* - * This should only happen in a labelframe but it doesn't - * hurt to be careful. + * This should only happen in a labelframe but it doesn't hurt to be + * careful. */ if (labelframePtr->frame.type == TYPE_LABELFRAME) { @@ -1871,24 +1853,23 @@ FrameStructureProc(clientData, eventPtr) * * FrameRequestProc -- * - * This procedure is invoked whenever a window that's associated - * with a frame changes its requested dimensions. + * This function is invoked whenever a window that's associated with a + * frame changes its requested dimensions. * * Results: * None. * * Side effects: - * The size and location on the screen of the window may change. - * depending on the options specified for the frame. + * The size and location on the screen of the window may change depending + * on the options specified for the frame. * *-------------------------------------------------------------- */ static void -FrameRequestProc(clientData, tkwin) - ClientData clientData; /* Pointer to record for frame. */ - Tk_Window tkwin; /* Window that changed its desired - * size. */ +FrameRequestProc( + ClientData clientData, /* Pointer to record for frame. */ + Tk_Window tkwin) /* Window that changed its desired size. */ { Frame *framePtr = (Frame *) clientData; @@ -1900,8 +1881,8 @@ FrameRequestProc(clientData, tkwin) * * FrameLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This function is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. @@ -1913,19 +1894,19 @@ FrameRequestProc(clientData, tkwin) */ static void -FrameLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Frame structure for slave window that - * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ +FrameLostSlaveProc( + ClientData clientData, /* Frame structure for slave window that was + * stolen away. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { Frame *framePtr = (Frame *) clientData; Labelframe *labelframePtr = (Labelframe *) clientData; /* - * This should only happen in a labelframe but it doesn't - * hurt to be careful. + * This should only happen in a labelframe but it doesn't hurt to be + * careful. */ - + if (labelframePtr->frame.type == TYPE_LABELFRAME) { Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask, FrameStructureProc, (ClientData) labelframePtr); @@ -1938,20 +1919,46 @@ FrameLostSlaveProc(clientData, tkwin) FrameWorldChanged((ClientData) framePtr); } +void +TkMapTopFrame (tkwin) + Tk_Window tkwin; +{ + Frame *framePtr = ((TkWindow*)tkwin)->instanceData; + Tk_OptionTable optionTable; + if (Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_FRAME) { + framePtr->type = TYPE_TOPLEVEL; + Tcl_DoWhenIdle(MapFrame, (ClientData)framePtr); + if (framePtr->menuName != NULL) { + TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin, NULL, + framePtr->menuName); + } + } else if (!Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_TOPLEVEL) { + framePtr->type = TYPE_FRAME; + } else { + /* Not a frame or toplevel, skip it */ + return; + } + /* + * The option table has already been created so + * the cached pointer will be returned. + */ + optionTable = Tk_CreateOptionTable(framePtr->interp, optionSpecs[framePtr->type]); + framePtr->optionTable = optionTable; +} + /* *-------------------------------------------------------------- * * TkToplevelWindowFromCommandToken -- * - * If the given command name to the command for a toplevel window - * in the given interpreter, return the tkwin for that toplevel - * window. Note that this lookup can't be done using the - * standard tkwin internal table because the command might have - * been renamed. + * If the given command name to the command for a toplevel window in the + * given interpreter, return the tkwin for that toplevel window. Note + * that this lookup can't be done using the standard tkwin internal table + * because the command might have been renamed. * * Results: - * A Tk_Window token, or NULL if the name does not refer to a - * toplevel window. + * A Tk_Window token, or NULL if the name does not refer to a toplevel + * window. * * Side effects: * None. @@ -1960,9 +1967,9 @@ FrameLostSlaveProc(clientData, tkwin) */ Tk_Window -TkToplevelWindowForCommand(interp, cmdName) - Tcl_Interp *interp; - CONST char *cmdName; +TkToplevelWindowForCommand( + Tcl_Interp *interp, + CONST char *cmdName) { Tcl_CmdInfo cmdInfo; Frame *framePtr; @@ -1979,3 +1986,11 @@ TkToplevelWindowForCommand(interp, cmdName) } return framePtr->tkwin; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkGC.c b/generic/tkGC.c index 46a3a56..800e4d3 100644 --- a/generic/tkGC.c +++ b/generic/tkGC.c @@ -1,24 +1,23 @@ -/* +/* * tkGC.c -- * - * This file maintains a database of read-only graphics contexts - * for the Tk toolkit, in order to allow GC's to be shared. + * This file maintains a database of read-only graphics contexts for the + * Tk toolkit, in order to allow GC's to be shared. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* - * One of the following data structures exists for each GC that is - * currently active. The structure is indexed with two hash tables, - * one based on the values in the graphics context and the other - * based on the display and GC identifier. + * One of the following data structures exists for each GC that is currently + * active. The structure is indexed with two hash tables, one based on the + * values in the graphics context and the other based on the display and GC + * identifier. */ typedef struct { @@ -37,48 +36,48 @@ typedef struct { } ValueKey; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static void GCInit _ANSI_ARGS_((TkDisplay *dispPtr)); +static void GCInit(TkDisplay *dispPtr); /* *---------------------------------------------------------------------- * * Tk_GetGC -- * - * Given a desired set of values for a graphics context, find - * a read-only graphics context with the desired values. + * Given a desired set of values for a graphics context, find a read-only + * graphics context with the desired values. * * Results: - * The return value is the X identifer for the desired graphics - * context. The caller should never modify this GC, and should - * call Tk_FreeGC when the GC is no longer needed. + * The return value is the X identifer for the desired graphics context. + * The caller should never modify this GC, and should call Tk_FreeGC when + * the GC is no longer needed. * * Side effects: - * The GC is added to an internal database with a reference count. - * For each call to this procedure, there should eventually be a call - * to Tk_FreeGC, so that the database can be cleaned up when GC's - * aren't needed anymore. + * The GC is added to an internal database with a reference count. For + * each call to this function, there should eventually be a call to + * Tk_FreeGC, so that the database can be cleaned up when GC's aren't + * needed anymore. * *---------------------------------------------------------------------- */ GC -Tk_GetGC(tkwin, valueMask, valuePtr) - Tk_Window tkwin; /* Window in which GC will be used. */ - register unsigned long valueMask; - /* 1 bits correspond to values specified - * in *valuesPtr; other values are set - * from defaults. */ - register XGCValues *valuePtr; - /* Values are specified here for bits set - * in valueMask. */ +Tk_GetGC( + Tk_Window tkwin, /* Window in which GC will be used. */ + register unsigned long valueMask, + /* 1 bits correspond to values specified in + * *valuesPtr; other values are set from + * defaults. */ + register XGCValues *valuePtr) + /* Values are specified here for bits set in + * valueMask. */ { ValueKey valueKey; Tcl_HashEntry *valueHashPtr, *idHashPtr; register TkGC *gcPtr; - int new; + int isNew; Drawable d, freeDrawable; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -87,15 +86,15 @@ Tk_GetGC(tkwin, valueMask, valuePtr) } /* - * Must zero valueKey at start to clear out pad bytes that may be - * part of structure on some systems. + * Must zero valueKey at start to clear out pad bytes that may be part of + * structure on some systems. */ - memset((VOID *) &valueKey, 0, sizeof(valueKey)); + memset(&valueKey, 0, sizeof(valueKey)); /* - * First, check to see if there's already a GC that will work - * for this request (exact matches only, sorry). + * First, check to see if there's already a GC that will work for this + * request (exact matches only, sorry). */ if (valueMask & GCFunction) { @@ -216,24 +215,24 @@ Tk_GetGC(tkwin, valueMask, valuePtr) valueKey.display = Tk_Display(tkwin); valueKey.screenNum = Tk_ScreenNumber(tkwin); valueKey.depth = Tk_Depth(tkwin); - valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable, - (char *) &valueKey, &new); - if (!new) { + valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable, + (char *) &valueKey, &isNew); + if (!isNew) { gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr); gcPtr->refCount++; return gcPtr->gc; } /* - * No GC is currently available for this set of values. Allocate a - * new GC and add a new structure to the database. + * No GC is currently available for this set of values. Allocate a new GC + * and add a new structure to the database. */ gcPtr = (TkGC *) ckalloc(sizeof(TkGC)); /* - * Find or make a drawable to use to specify the screen and depth - * of the GC. We may have to make a small pixmap, to avoid doing + * Find or make a drawable to use to specify the screen and depth of the + * GC. We may have to make a small pixmap, to avoid doing * Tk_MakeWindowExist on the window. */ @@ -254,10 +253,10 @@ Tk_GetGC(tkwin, valueMask, valuePtr) gcPtr->display = valueKey.display; gcPtr->refCount = 1; gcPtr->valueHashPtr = valueHashPtr; - idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable, - (char *) gcPtr->gc, &new); - if (!new) { - panic("GC already registered in Tk_GetGC"); + idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable, + (char *) gcPtr->gc, &isNew); + if (!isNew) { + Tcl_Panic("GC already registered in Tk_GetGC"); } Tcl_SetHashValue(valueHashPtr, gcPtr); Tcl_SetHashValue(idHashPtr, gcPtr); @@ -273,43 +272,44 @@ Tk_GetGC(tkwin, valueMask, valuePtr) * * Tk_FreeGC -- * - * This procedure is called to release a graphics context allocated by + * This function is called to release a graphics context allocated by * Tk_GetGC. * * Results: * None. * * Side effects: - * The reference count associated with gc is decremented, and - * gc is officially deallocated if no-one is using it anymore. + * The reference count associated with gc is decremented, and gc is + * officially deallocated if no-one is using it anymore. * *---------------------------------------------------------------------- */ void -Tk_FreeGC(display, gc) - Display *display; /* Display for which gc was allocated. */ - GC gc; /* Graphics context to be released. */ +Tk_FreeGC( + Display *display, /* Display for which gc was allocated. */ + GC gc) /* Graphics context to be released. */ { Tcl_HashEntry *idHashPtr; register TkGC *gcPtr; TkDisplay *dispPtr = TkGetDisplay(display); if (!dispPtr->gcInit) { - panic("Tk_FreeGC called before Tk_GetGC"); + Tcl_Panic("Tk_FreeGC called before Tk_GetGC"); } if (dispPtr->gcInit < 0) { /* - * The GCCleanup has been called, and remaining GCs have been - * freed. This may still get called by other things shutting - * down, but the GCs should no longer be in use. + * The GCCleanup has been called, and remaining GCs have been freed. + * This may still get called by other things shutting down, but the + * GCs should no longer be in use. */ + return; } idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc); if (idHashPtr == NULL) { - panic("Tk_FreeGC received unknown gc argument"); + Tcl_Panic("Tk_FreeGC received unknown gc argument"); } gcPtr = (TkGC *) Tcl_GetHashValue(idHashPtr); gcPtr->refCount--; @@ -327,9 +327,8 @@ Tk_FreeGC(display, gc) * * TkGCCleanup -- * - * Frees the structures used for GC management. - * We need to have it called near the end, when other cleanup that - * calls Tk_FreeGC is all done. + * Frees the structures used for GC management. We need to have it called + * near the end, when other cleanup that calls Tk_FreeGC is all done. * * Results: * None. @@ -341,22 +340,23 @@ Tk_FreeGC(display, gc) */ void -TkGCCleanup(dispPtr) - TkDisplay *dispPtr; /* display to clean up resources in */ +TkGCCleanup( + TkDisplay *dispPtr) /* display to clean up resources in */ { Tcl_HashEntry *entryPtr; Tcl_HashSearch search; TkGC *gcPtr; for (entryPtr = Tcl_FirstHashEntry(&dispPtr->gcIdTable, &search); - entryPtr != NULL; - entryPtr = Tcl_NextHashEntry(&search)) { + entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) { gcPtr = (TkGC *) 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. + * 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); @@ -384,13 +384,21 @@ TkGCCleanup(dispPtr) */ static void -GCInit(dispPtr) - TkDisplay *dispPtr; +GCInit( + TkDisplay *dispPtr) { if (dispPtr->gcInit < 0) { - panic("called GCInit after GCCleanup"); + Tcl_Panic("called GCInit after GCCleanup"); } dispPtr->gcInit = 1; Tcl_InitHashTable(&dispPtr->gcValueTable, sizeof(ValueKey)/sizeof(int)); Tcl_InitHashTable(&dispPtr->gcIdTable, TCL_ONE_WORD_KEYS); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index d53b6dd..4c8e4f8 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -1,23 +1,22 @@ -/* +/* * tkGeometry.c -- * - * This file contains generic Tk code for geometry management - * (stuff that's used by all geometry managers). + * This file contains generic Tk code for geometry management (stuff + * that's used by all geometry managers). * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* - * Data structures of the following type are used by Tk_MaintainGeometry. - * For each slave managed by Tk_MaintainGeometry, there is one of these - * structures associated with its master. + * Data structures of the following type are used by Tk_MaintainGeometry. For + * each slave managed by Tk_MaintainGeometry, there is one of these structures + * associated with its master. */ typedef struct MaintainSlave { @@ -29,68 +28,67 @@ typedef struct MaintainSlave { * master. */ int width, height; /* Desired dimensions of slave. */ struct MaintainSlave *nextPtr; - /* Next in list of Maintains associated - * with master. */ + /* Next in list of Maintains associated with + * master. */ } MaintainSlave; /* - * For each window that has been specified as a master to - * Tk_MaintainGeometry, there is a structure of the following type: + * For each window that has been specified as a master to Tk_MaintainGeometry, + * there is a structure of the following type: */ typedef struct MaintainMaster { - Tk_Window ancestor; /* The lowest ancestor of this window - * for which we have *not* created a - * StructureNotify handler. May be the - * same as the window itself. */ - int checkScheduled; /* Non-zero means that there is already a - * call to MaintainCheckProc scheduled as - * an idle handler. */ - MaintainSlave *slavePtr; /* First in list of all slaves associated - * with this master. */ + Tk_Window ancestor; /* The lowest ancestor of this window for + * which we have *not* created a + * StructureNotify handler. May be the same as + * the window itself. */ + int checkScheduled; /* Non-zero means that there is already a call + * to MaintainCheckProc scheduled as an idle + * handler. */ + MaintainSlave *slavePtr; /* First in list of all slaves associated with + * this master. */ } MaintainMaster; /* * Prototypes for static procedures in this file: */ -static void MaintainCheckProc _ANSI_ARGS_((ClientData clientData)); -static void MaintainMasterProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void MaintainSlaveProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); +static void MaintainCheckProc(ClientData clientData); +static void MaintainMasterProc(ClientData clientData, + XEvent *eventPtr); +static void MaintainSlaveProc(ClientData clientData, + XEvent *eventPtr); /* *-------------------------------------------------------------- * * Tk_ManageGeometry -- * - * Arrange for a particular procedure to manage the geometry - * of a given slave window. + * Arrange for a particular procedure to manage the geometry of a given + * slave window. * * Results: * None. * * Side effects: - * Proc becomes the new geometry manager for tkwin, replacing - * any previous geometry manager. The geometry manager will - * be notified (by calling procedures in *mgrPtr) when interesting - * things happen in the future. If there was an existing geometry - * manager for tkwin different from the new one, it is notified - * by calling its lostSlaveProc. + * Proc becomes the new geometry manager for tkwin, replacing any + * previous geometry manager. The geometry manager will be notified (by + * calling procedures in *mgrPtr) when interesting things happen in the + * future. If there was an existing geometry manager for tkwin different + * from the new one, it is notified by calling its lostSlaveProc. * *-------------------------------------------------------------- */ void -Tk_ManageGeometry(tkwin, mgrPtr, clientData) - Tk_Window tkwin; /* Window whose geometry is to - * be managed by proc. */ - Tk_GeomMgr *mgrPtr; /* Static structure describing the - * geometry manager. This structure - * must never go away. */ - ClientData clientData; /* Arbitrary one-word argument to - * pass to geometry manager procedures. */ +Tk_ManageGeometry( + Tk_Window tkwin, /* Window whose geometry is to be managed by + * proc. */ + CONST Tk_GeomMgr *mgrPtr, /* Static structure describing the geometry + * manager. This structure must never go + * away. */ + ClientData clientData) /* Arbitrary one-word argument to pass to + * geometry manager procedures. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -110,37 +108,35 @@ Tk_ManageGeometry(tkwin, mgrPtr, clientData) * * Tk_GeometryRequest -- * - * This procedure is invoked by widget code to indicate - * its preferences about the size of a window it manages. - * In general, widget code should call this procedure - * rather than Tk_ResizeWindow. + * This procedure is invoked by widget code to indicate its preferences + * about the size of a window it manages. In general, widget code should + * call this procedure rather than Tk_ResizeWindow. * * Results: * None. * * Side effects: - * The geometry manager for tkwin (if any) is invoked to - * handle the request. If possible, it will reconfigure - * tkwin and/or other windows to satisfy the request. The - * caller gets no indication of success or failure, but it - * will get X events if the window size was actually + * The geometry manager for tkwin (if any) is invoked to handle the + * request. If possible, it will reconfigure tkwin and/or other windows + * to satisfy the request. The caller gets no indication of success or + * failure, but it will get X events if the window size was actually * changed. * *-------------------------------------------------------------- */ void -Tk_GeometryRequest(tkwin, reqWidth, reqHeight) - Tk_Window tkwin; /* Window that geometry information - * pertains to. */ - int reqWidth, reqHeight; /* Minimum desired dimensions for - * window, in pixels. */ +Tk_GeometryRequest( + Tk_Window tkwin, /* Window that geometry information pertains + * to. */ + int reqWidth, int reqHeight)/* Minimum desired dimensions for window, in + * pixels. */ { register TkWindow *winPtr = (TkWindow *) tkwin; /* - * X gets very upset if a window requests a width or height of - * zero, so rounds requested sizes up to at least 1. + * X gets very upset if a window requests a width or height of zero, so + * rounds requested sizes up to at least 1. */ if (reqWidth <= 0) { @@ -165,9 +161,9 @@ Tk_GeometryRequest(tkwin, reqWidth, reqHeight) * * Tk_SetInternalBorderEx -- * - * Notify relevant geometry managers that a window has an internal - * border of a given width and that child windows should not be - * placed on that border. + * Notify relevant geometry managers that a window has an internal border + * of a given width and that child windows should not be placed on that + * border. * * Results: * None. @@ -181,10 +177,10 @@ Tk_GeometryRequest(tkwin, reqWidth, reqHeight) */ void -Tk_SetInternalBorderEx(tkwin, left, right, top, bottom) - Tk_Window tkwin; /* Window that will have internal border. */ - int left, right; /* Width of internal border, in pixels. */ - int top, bottom; +Tk_SetInternalBorderEx( + Tk_Window tkwin, /* Window that will have internal border. */ + int left, int right, /* Width of internal border, in pixels. */ + int top, int bottom) { register TkWindow *winPtr = (TkWindow *) tkwin; register int changed = 0; @@ -223,40 +219,40 @@ Tk_SetInternalBorderEx(tkwin, left, right, top, bottom) /* * All the slaves for which this is the master window must now be - * repositioned to take account of the new internal border width. - * To signal all the geometry managers to do this, just resize the - * window to its current size. The ConfigureNotify event will - * cause geometry managers to recompute everything. + * repositioned to take account of the new internal border width. To + * signal all the geometry managers to do this, just resize the window to + * its current size. The ConfigureNotify event will cause geometry + * managers to recompute everything. */ if (changed) { Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin)); } } + /* *---------------------------------------------------------------------- * * Tk_SetInternalBorder -- * - * Notify relevant geometry managers that a window has an internal - * border of a given width and that child windows should not be - * placed on that border. + * Notify relevant geometry managers that a window has an internal border + * of a given width and that child windows should not be placed on that + * border. * * Results: * None. * * Side effects: - * The border width is recorded for the window, and all geometry - * managers of all children are notified so that can re-layout, if - * necessary. + * The border width is recorded for the window, and all geometry managers + * of all children are notified so that can re-layout, if necessary. * *---------------------------------------------------------------------- */ void -Tk_SetInternalBorder(tkwin, width) - Tk_Window tkwin; /* Window that will have internal border. */ - int width; /* Width of internal border, in pixels. */ +Tk_SetInternalBorder( + Tk_Window tkwin, /* Window that will have internal border. */ + int width) /* Width of internal border, in pixels. */ { Tk_SetInternalBorderEx(tkwin, width, width, width, width); } @@ -266,23 +262,23 @@ Tk_SetInternalBorder(tkwin, width) * * Tk_SetMinimumRequestSize -- * - * Notify relevant geometry managers that a window has a minimum - * request size. + * Notify relevant geometry managers that a window has a minimum request + * size. * * Results: * None. * * Side effects: - * The minimum request size is recorded for the window, and - * a new size is requested for the window, if necessary. + * The minimum request size is recorded for the window, and a new size is + * requested for the window, if necessary. * *---------------------------------------------------------------------- */ void -Tk_SetMinimumRequestSize(tkwin, minWidth, minHeight) - Tk_Window tkwin; /* Window that will have internal border. */ - int minWidth, minHeight; /* Minimum requested size, in pixels. */ +Tk_SetMinimumRequestSize( + Tk_Window tkwin, /* Window that will have internal border. */ + int minWidth, int minHeight)/* Minimum requested size, in pixels. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -295,11 +291,11 @@ Tk_SetMinimumRequestSize(tkwin, minWidth, minHeight) winPtr->minReqHeight = minHeight; /* - * The changed min size may cause geometry managers to get a - * different result, so make them recompute. - * To signal all the geometry managers to do this, just resize the - * window to its current size. The ConfigureNotify event will - * cause geometry managers to recompute everything. + * The changed min size may cause geometry managers to get a different + * result, so make them recompute. To signal all the geometry managers to + * do this, just resize the window to its current size. The + * ConfigureNotify event will cause geometry managers to recompute + * everything. */ Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin)); @@ -310,40 +306,40 @@ Tk_SetMinimumRequestSize(tkwin, minWidth, minHeight) * * Tk_MaintainGeometry -- * - * This procedure is invoked by geometry managers to handle slaves - * whose master's are not their parents. It translates the desired - * geometry for the slave into the coordinate system of the parent - * and respositions the slave if it isn't already at the right place. - * Furthermore, it sets up event handlers so that if the master (or - * any of its ancestors up to the slave's parent) is mapped, unmapped, - * or moved, then the slave will be adjusted to match. + * This procedure is invoked by geometry managers to handle slaves whose + * master's are not their parents. It translates the desired geometry for + * the slave into the coordinate system of the parent and respositions + * the slave if it isn't already at the right place. Furthermore, it sets + * up event handlers so that if the master (or any of its ancestors up to + * the slave's parent) is mapped, unmapped, or moved, then the slave will + * be adjusted to match. * * Results: * None. * * Side effects: - * Event handlers are created and state is allocated to keep track - * of slave. Note: if slave was already managed for master by - * Tk_MaintainGeometry, then the previous information is replaced - * with the new information. The caller must eventually call - * Tk_UnmaintainGeometry to eliminate the correspondence (or, the - * state is automatically freed when either window is destroyed). + * Event handlers are created and state is allocated to keep track of + * slave. Note: if slave was already managed for master by + * Tk_MaintainGeometry, then the previous information is replaced with + * the new information. The caller must eventually call + * Tk_UnmaintainGeometry to eliminate the correspondence (or, the state + * is automatically freed when either window is destroyed). * *---------------------------------------------------------------------- */ void -Tk_MaintainGeometry(slave, master, x, y, width, height) - Tk_Window slave; /* Slave for geometry management. */ - Tk_Window master; /* Master for slave; must be a descendant - * of slave's parent. */ - int x, y; /* Desired position of slave within master. */ - int width, height; /* Desired dimensions for slave. */ +Tk_MaintainGeometry( + Tk_Window slave, /* Slave for geometry management. */ + Tk_Window master, /* Master for slave; must be a descendant of + * slave's parent. */ + int x, int y, /* Desired position of slave within master. */ + int width, int height) /* Desired dimensions for slave. */ { Tcl_HashEntry *hPtr; MaintainMaster *masterPtr; register MaintainSlave *slavePtr; - int new, map; + int isNew, map; Tk_Window ancestor, parent; TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; @@ -354,6 +350,7 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) * call to Tk_MoveResizeWindow; the parent/child relationship will * take care of the rest. */ + Tk_MoveResizeWindow(slave, x, y, width, height); /* @@ -361,6 +358,7 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) * until the master is mapped later (in which case mapping the slave * is taken care of elsewhere). */ + if (Tk_IsMapped(master)) { Tk_MapWindow(slave); } @@ -373,14 +371,14 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) } /* - * See if there is already a MaintainMaster structure for the master; - * if not, then create one. + * See if there is already a MaintainMaster structure for the master; if + * not, then create one. */ parent = Tk_Parent(slave); - hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable, - (char *) master, &new); - if (!new) { + hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable, + (char *) master, &isNew); + if (!isNew) { masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr); } else { masterPtr = (MaintainMaster *) ckalloc(sizeof(MaintainMaster)); @@ -391,8 +389,8 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) } /* - * Create a MaintainSlave structure for the slave if there isn't - * already one. + * Create a MaintainSlave structure for the slave if there isn't already + * one. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; @@ -410,10 +408,10 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) (ClientData) slavePtr); /* - * Make sure that there are event handlers registered for all - * the windows between master and slave's parent (including master - * but not slave's parent). There may already be handlers for master - * and some of its ancestors (masterPtr->ancestor tells how many). + * Make sure that there are event handlers registered for all the windows + * between master and slave's parent (including master but not slave's + * parent). There may already be handlers for master and some of its + * ancestors (masterPtr->ancestor tells how many). */ for (ancestor = master; ancestor != parent; @@ -426,11 +424,11 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) } /* - * Fill in up-to-date information in the structure, then update the - * window if it's not currently in the right place or state. + * Fill in up-to-date information in the structure, then update the window + * if it's not currently in the right place or state. */ - gotSlave: + gotSlave: slavePtr->x = x; slavePtr->y = y; slavePtr->width = width; @@ -464,26 +462,25 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) * * Tk_UnmaintainGeometry -- * - * This procedure cancels a previous Tk_MaintainGeometry call, - * so that the relationship between slave and master is no longer - * maintained. + * This procedure cancels a previous Tk_MaintainGeometry call, so that + * the relationship between slave and master is no longer maintained. * * Results: * None. * * Side effects: - * The slave is unmapped and state is released, so that slave won't - * track master any more. If we weren't previously managing slave - * relative to master, then this procedure has no effect. + * The slave is unmapped and state is released, so that slave won't track + * master any more. If we weren't previously managing slave relative to + * master, then this procedure has no effect. * *---------------------------------------------------------------------- */ void -Tk_UnmaintainGeometry(slave, master) - Tk_Window slave; /* Slave for geometry management. */ - Tk_Window master; /* Master for slave; must be a descendant - * of slave's parent. */ +Tk_UnmaintainGeometry( + Tk_Window slave, /* Slave for geometry management. */ + Tk_Window master) /* Master for slave; must be a descendant of + * slave's parent. */ { Tcl_HashEntry *hPtr; MaintainMaster *masterPtr; @@ -495,11 +492,11 @@ Tk_UnmaintainGeometry(slave, master) /* * If the slave is a direct descendant of the master, * Tk_MaintainGeometry will not have set up any of the extra - * infrastructure. Don't even bother to look for it, just return. + * infrastructure. Don't even bother to look for it, just return. */ return; } - + if (!dispPtr->geomInit) { dispPtr->geomInit = 1; Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS); @@ -554,27 +551,27 @@ Tk_UnmaintainGeometry(slave, master) * * MaintainMasterProc -- * - * This procedure is invoked by the Tk event dispatcher in - * response to StructureNotify events on the master or one - * of its ancestors, on behalf of Tk_MaintainGeometry. + * This procedure is invoked by the Tk event dispatcher in response to + * StructureNotify events on the master or one of its ancestors, on + * behalf of Tk_MaintainGeometry. * * Results: * None. * * Side effects: - * It schedules a call to MaintainCheckProc, which will eventually - * caused the postions and mapped states to be recalculated for all - * the maintained slaves of the master. Or, if the master window is - * being deleted then state is cleaned up. + * It schedules a call to MaintainCheckProc, which will eventually caused + * the postions and mapped states to be recalculated for all the + * maintained slaves of the master. Or, if the master window is being + * deleted then state is cleaned up. * *---------------------------------------------------------------------- */ static void -MaintainMasterProc(clientData, eventPtr) - ClientData clientData; /* Pointer to MaintainMaster structure - * for the master window. */ - XEvent *eventPtr; /* Describes what just happened. */ +MaintainMasterProc( + ClientData clientData, /* Pointer to MaintainMaster structure for the + * master window. */ + XEvent *eventPtr) /* Describes what just happened. */ { MaintainMaster *masterPtr = (MaintainMaster *) clientData; MaintainSlave *slavePtr; @@ -589,9 +586,9 @@ MaintainMasterProc(clientData, eventPtr) } } else if (eventPtr->type == DestroyNotify) { /* - * Delete all of the state associated with this master, but - * be careful not to use masterPtr after the last slave is - * deleted, since its memory will have been freed. + * Delete all of the state associated with this master, but be careful + * not to use masterPtr after the last slave is deleted, since its + * memory will have been freed. */ done = 0; @@ -610,25 +607,25 @@ MaintainMasterProc(clientData, eventPtr) * * MaintainSlaveProc -- * - * This procedure is invoked by the Tk event dispatcher in - * response to StructureNotify events on a slave being managed - * by Tk_MaintainGeometry. + * This procedure is invoked by the Tk event dispatcher in response to + * StructureNotify events on a slave being managed by + * Tk_MaintainGeometry. * * Results: * None. * * Side effects: - * If the event is a DestroyNotify event then the Maintain state - * and event handlers for this slave are deleted. + * If the event is a DestroyNotify event then the Maintain state and + * event handlers for this slave are deleted. * *---------------------------------------------------------------------- */ static void -MaintainSlaveProc(clientData, eventPtr) - ClientData clientData; /* Pointer to MaintainSlave structure - * for master-slave pair. */ - XEvent *eventPtr; /* Describes what just happened. */ +MaintainSlaveProc( + ClientData clientData, /* Pointer to MaintainSlave structure for + * master-slave pair. */ + XEvent *eventPtr) /* Describes what just happened. */ { MaintainSlave *slavePtr = (MaintainSlave *) clientData; @@ -642,12 +639,11 @@ MaintainSlaveProc(clientData, eventPtr) * * MaintainCheckProc -- * - * This procedure is invoked by the Tk event dispatcher as an - * idle handler, when a master or one of its ancestors has been - * reconfigured, mapped, or unmapped. Its job is to scan all of - * the slaves for the master and reposition them, map them, or - * unmap them as needed to maintain their geometry relative to - * the master. + * This procedure is invoked by the Tk event dispatcher as an idle + * handler, when a master or one of its ancestors has been reconfigured, + * mapped, or unmapped. Its job is to scan all of the slaves for the + * master and reposition them, map them, or unmap them as needed to + * maintain their geometry relative to the master. * * Results: * None. @@ -659,9 +655,9 @@ MaintainSlaveProc(clientData, eventPtr) */ static void -MaintainCheckProc(clientData) - ClientData clientData; /* Pointer to MaintainMaster structure - * for the master window. */ +MaintainCheckProc( + ClientData clientData) /* Pointer to MaintainMaster structure for the + * master window. */ { MaintainMaster *masterPtr = (MaintainMaster *) clientData; MaintainSlave *slavePtr; @@ -696,3 +692,11 @@ MaintainCheckProc(clientData) } } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkGet.c b/generic/tkGet.c index 10643ea..9fc0d50 100644 --- a/generic/tkGet.c +++ b/generic/tkGet.c @@ -1,27 +1,25 @@ -/* +/* * tkGet.c -- * - * This file contains a number of "Tk_GetXXX" procedures, which - * parse text strings into useful forms for Tk. This file has - * the simpler procedures, like Tk_GetDirection and Tk_GetUid. - * The more complex procedures like Tk_GetColor are in separate - * files. + * This file contains a number of "Tk_GetXXX" procedures, which parse + * text strings into useful forms for Tk. This file has the simpler + * functions, like Tk_GetDirection and Tk_GetUid. The more complex + * functions like Tk_GetColor are in separate files. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" /* - * One of these structures is created per thread to store - * thread-specific data. In this case, it is used to house the - * Tk_Uid structs used by each thread. The "dataKey" below is - * used to locate the ThreadSpecificData for the current thread. + * One of these structures is created per thread to store thread-specific + * data. In this case, it is used to house the Tk_Uid structs used by each + * thread. The "dataKey" below is used to locate the ThreadSpecificData for + * the current thread. */ typedef struct ThreadSpecificData { @@ -30,7 +28,7 @@ typedef struct ThreadSpecificData { } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -static void FreeUidThreadExitProc _ANSI_ARGS_((ClientData clientData)); +static void FreeUidThreadExitProc(ClientData clientData); /* * The following tables defines the string values for reliefs, which are @@ -38,12 +36,11 @@ static void FreeUidThreadExitProc _ANSI_ARGS_((ClientData clientData)); */ static CONST char *anchorStrings[] = { - "n", "ne", "e", "se", "s", "sw", "w", "nw", "center", (char *) NULL + "n", "ne", "e", "se", "s", "sw", "w", "nw", "center", NULL }; static CONST char *justifyStrings[] = { - "left", "right", "center", (char *) NULL + "left", "right", "center", NULL }; - /* *---------------------------------------------------------------------- @@ -64,17 +61,17 @@ static CONST char *justifyStrings[] = { */ int -Tk_GetAnchorFromObj(interp, objPtr, anchorPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Tcl_Obj *objPtr; /* The object we are trying to get the - * value from. */ - Tk_Anchor *anchorPtr; /* Where to place the Tk_Anchor that +Tk_GetAnchorFromObj( + Tcl_Interp *interp, /* Used for error reporting. */ + Tcl_Obj *objPtr, /* The object we are trying to get the value + * from. */ + Tk_Anchor *anchorPtr) /* Where to place the Tk_Anchor that * corresponds to the string value of * objPtr. */ { int index, code; - code = Tcl_GetIndexFromObj(interp, objPtr, anchorStrings, "anchor", 0, + code = Tcl_GetIndexFromObj(interp, objPtr, anchorStrings, "anchor", 0, &index); if (code == TCL_OK) { *anchorPtr = (Tk_Anchor) index; @@ -90,11 +87,10 @@ Tk_GetAnchorFromObj(interp, objPtr, anchorPtr) * Given a string, return the corresponding Tk_Anchor. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * position is stored at *anchorPtr; otherwise TCL_ERROR - * is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the position is stored at + * *anchorPtr; otherwise TCL_ERROR is returned and an error message is + * left in the interp's result. * * Side effects: * None. @@ -103,62 +99,61 @@ Tk_GetAnchorFromObj(interp, objPtr, anchorPtr) */ int -Tk_GetAnchor(interp, string, anchorPtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - CONST char *string; /* String describing a direction. */ - Tk_Anchor *anchorPtr; /* Where to store Tk_Anchor corresponding - * to string. */ +Tk_GetAnchor( + Tcl_Interp *interp, /* Use this for error reporting. */ + CONST char *string, /* String describing a direction. */ + Tk_Anchor *anchorPtr) /* Where to store Tk_Anchor corresponding to + * string. */ { switch (string[0]) { - case 'n': - if (string[1] == 0) { - *anchorPtr = TK_ANCHOR_N; - return TCL_OK; - } else if ((string[1] == 'e') && (string[2] == 0)) { - *anchorPtr = TK_ANCHOR_NE; - return TCL_OK; - } else if ((string[1] == 'w') && (string[2] == 0)) { - *anchorPtr = TK_ANCHOR_NW; - return TCL_OK; - } - goto error; - case 's': - if (string[1] == 0) { - *anchorPtr = TK_ANCHOR_S; - return TCL_OK; - } else if ((string[1] == 'e') && (string[2] == 0)) { - *anchorPtr = TK_ANCHOR_SE; - return TCL_OK; - } else if ((string[1] == 'w') && (string[2] == 0)) { - *anchorPtr = TK_ANCHOR_SW; - return TCL_OK; - } else { - goto error; - } - case 'e': - if (string[1] == 0) { - *anchorPtr = TK_ANCHOR_E; - return TCL_OK; - } - goto error; - case 'w': - if (string[1] == 0) { - *anchorPtr = TK_ANCHOR_W; - return TCL_OK; - } - goto error; - case 'c': - if (strncmp(string, "center", strlen(string)) == 0) { - *anchorPtr = TK_ANCHOR_CENTER; - return TCL_OK; - } + case 'n': + if (string[1] == 0) { + *anchorPtr = TK_ANCHOR_N; + return TCL_OK; + } else if ((string[1] == 'e') && (string[2] == 0)) { + *anchorPtr = TK_ANCHOR_NE; + return TCL_OK; + } else if ((string[1] == 'w') && (string[2] == 0)) { + *anchorPtr = TK_ANCHOR_NW; + return TCL_OK; + } + goto error; + case 's': + if (string[1] == 0) { + *anchorPtr = TK_ANCHOR_S; + return TCL_OK; + } else if ((string[1] == 'e') && (string[2] == 0)) { + *anchorPtr = TK_ANCHOR_SE; + return TCL_OK; + } else if ((string[1] == 'w') && (string[2] == 0)) { + *anchorPtr = TK_ANCHOR_SW; + return TCL_OK; + } else { goto error; + } + case 'e': + if (string[1] == 0) { + *anchorPtr = TK_ANCHOR_E; + return TCL_OK; + } + goto error; + case 'w': + if (string[1] == 0) { + *anchorPtr = TK_ANCHOR_W; + return TCL_OK; + } + goto error; + case 'c': + if (strncmp(string, "center", strlen(string)) == 0) { + *anchorPtr = TK_ANCHOR_CENTER; + return TCL_OK; + } + goto error; } - error: + error: Tcl_AppendResult(interp, "bad anchor position \"", string, - "\": must be n, ne, e, se, s, sw, w, nw, or center", - (char *) NULL); + "\": must be n, ne, e, se, s, sw, w, nw, or center", NULL); return TCL_ERROR; } @@ -167,8 +162,7 @@ Tk_GetAnchor(interp, string, anchorPtr) * * Tk_NameOfAnchor -- * - * Given a Tk_Anchor, return the string that corresponds - * to it. + * Given a Tk_Anchor, return the string that corresponds to it. * * Results: * None. @@ -180,20 +174,20 @@ Tk_GetAnchor(interp, string, anchorPtr) */ CONST char * -Tk_NameOfAnchor(anchor) - Tk_Anchor anchor; /* Anchor for which identifying string - * is desired. */ +Tk_NameOfAnchor( + Tk_Anchor anchor) /* Anchor for which identifying string is + * desired. */ { switch (anchor) { - case TK_ANCHOR_N: return "n"; - case TK_ANCHOR_NE: return "ne"; - case TK_ANCHOR_E: return "e"; - case TK_ANCHOR_SE: return "se"; - case TK_ANCHOR_S: return "s"; - case TK_ANCHOR_SW: return "sw"; - case TK_ANCHOR_W: return "w"; - case TK_ANCHOR_NW: return "nw"; - case TK_ANCHOR_CENTER: return "center"; + case TK_ANCHOR_N: return "n"; + case TK_ANCHOR_NE: return "ne"; + case TK_ANCHOR_E: return "e"; + case TK_ANCHOR_SE: return "se"; + case TK_ANCHOR_S: return "s"; + case TK_ANCHOR_SW: return "sw"; + case TK_ANCHOR_W: return "w"; + case TK_ANCHOR_NW: return "nw"; + case TK_ANCHOR_CENTER: return "center"; } return "unknown anchor position"; } @@ -206,11 +200,10 @@ Tk_NameOfAnchor(anchor) * Given a string, return the corresponding Tk JoinStyle. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * justification is stored at *joinPtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the justification is stored at + * *joinPtr; otherwise TCL_ERROR is returned and an error message is left + * in the interp's result. * * Side effects: * None. @@ -219,11 +212,11 @@ Tk_NameOfAnchor(anchor) */ int -Tk_GetJoinStyle(interp, string, joinPtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - CONST char *string; /* String describing a justification style. */ - int *joinPtr; /* Where to store join style corresponding - * to string. */ +Tk_GetJoinStyle( + Tcl_Interp *interp, /* Use this for error reporting. */ + CONST char *string, /* String describing a justification style. */ + int *joinPtr) /* Where to store join style corresponding to + * string. */ { int c; size_t length; @@ -245,8 +238,7 @@ Tk_GetJoinStyle(interp, string, joinPtr) } Tcl_AppendResult(interp, "bad join style \"", string, - "\": must be bevel, miter, or round", - (char *) NULL); + "\": must be bevel, miter, or round", NULL); return TCL_ERROR; } @@ -255,8 +247,7 @@ Tk_GetJoinStyle(interp, string, joinPtr) * * Tk_NameOfJoinStyle -- * - * Given a Tk JoinStyle, return the string that corresponds - * to it. + * Given a Tk JoinStyle, return the string that corresponds to it. * * Results: * None. @@ -268,14 +259,14 @@ Tk_GetJoinStyle(interp, string, joinPtr) */ CONST char * -Tk_NameOfJoinStyle(join) - int join; /* Join style for which identifying string - * is desired. */ +Tk_NameOfJoinStyle( + int join) /* Join style for which identifying string is + * desired. */ { switch (join) { - case JoinBevel: return "bevel"; - case JoinMiter: return "miter"; - case JoinRound: return "round"; + case JoinBevel: return "bevel"; + case JoinMiter: return "miter"; + case JoinRound: return "round"; } return "unknown join style"; } @@ -288,11 +279,10 @@ Tk_NameOfJoinStyle(join) * Given a string, return the corresponding Tk CapStyle. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * justification is stored at *capPtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the justification is stored at + * *capPtr; otherwise TCL_ERROR is returned and an error message is left + * in the interp's result. * * Side effects: * None. @@ -301,11 +291,11 @@ Tk_NameOfJoinStyle(join) */ int -Tk_GetCapStyle(interp, string, capPtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - CONST char *string; /* String describing a justification style. */ - int *capPtr; /* Where to store cap style corresponding - * to string. */ +Tk_GetCapStyle( + Tcl_Interp *interp, /* Use this for error reporting. */ + CONST char *string, /* String describing a justification style. */ + int *capPtr) /* Where to store cap style corresponding to + * string. */ { int c; size_t length; @@ -327,8 +317,7 @@ Tk_GetCapStyle(interp, string, capPtr) } Tcl_AppendResult(interp, "bad cap style \"", string, - "\": must be butt, projecting, or round", - (char *) NULL); + "\": must be butt, projecting, or round", NULL); return TCL_ERROR; } @@ -337,8 +326,7 @@ Tk_GetCapStyle(interp, string, capPtr) * * Tk_NameOfCapStyle -- * - * Given a Tk CapStyle, return the string that corresponds - * to it. + * Given a Tk CapStyle, return the string that corresponds to it. * * Results: * None. @@ -350,14 +338,14 @@ Tk_GetCapStyle(interp, string, capPtr) */ CONST char * -Tk_NameOfCapStyle(cap) - int cap; /* Cap style for which identifying string - * is desired. */ +Tk_NameOfCapStyle( + int cap) /* Cap style for which identifying string is + * desired. */ { switch (cap) { - case CapButt: return "butt"; - case CapProjecting: return "projecting"; - case CapRound: return "round"; + case CapButt: return "butt"; + case CapProjecting: return "projecting"; + case CapRound: return "round"; } return "unknown cap style"; } @@ -381,11 +369,11 @@ Tk_NameOfCapStyle(cap) */ int -Tk_GetJustifyFromObj(interp, objPtr, justifyPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Tcl_Obj *objPtr; /* The object we are trying to get the - * value from. */ - Tk_Justify *justifyPtr; /* Where to place the Tk_Justify that +Tk_GetJustifyFromObj( + Tcl_Interp *interp, /* Used for error reporting. */ + Tcl_Obj *objPtr, /* The object we are trying to get the value + * from. */ + Tk_Justify *justifyPtr) /* Where to place the Tk_Justify that * corresponds to the string value of * objPtr. */ { @@ -407,11 +395,10 @@ Tk_GetJustifyFromObj(interp, objPtr, justifyPtr) * Given a string, return the corresponding Tk_Justify. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * justification is stored at *justifyPtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the justification is stored at + * *justifyPtr; otherwise TCL_ERROR is returned and an error message is + * left in the interp's result. * * Side effects: * None. @@ -420,11 +407,11 @@ Tk_GetJustifyFromObj(interp, objPtr, justifyPtr) */ int -Tk_GetJustify(interp, string, justifyPtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - CONST char *string; /* String describing a justification style. */ - Tk_Justify *justifyPtr; /* Where to store Tk_Justify corresponding - * to string. */ +Tk_GetJustify( + Tcl_Interp *interp, /* Use this for error reporting. */ + CONST char *string, /* String describing a justification style. */ + Tk_Justify *justifyPtr) /* Where to store Tk_Justify corresponding to + * string. */ { int c; size_t length; @@ -446,8 +433,7 @@ Tk_GetJustify(interp, string, justifyPtr) } Tcl_AppendResult(interp, "bad justification \"", string, - "\": must be left, right, or center", - (char *) NULL); + "\": must be left, right, or center", NULL); return TCL_ERROR; } @@ -469,14 +455,14 @@ Tk_GetJustify(interp, string, justifyPtr) */ CONST char * -Tk_NameOfJustify(justify) - Tk_Justify justify; /* Justification style for which - * identifying string is desired. */ +Tk_NameOfJustify( + Tk_Justify justify) /* Justification style for which identifying + * string is desired. */ { switch (justify) { - case TK_JUSTIFY_LEFT: return "left"; - case TK_JUSTIFY_RIGHT: return "right"; - case TK_JUSTIFY_CENTER: return "center"; + case TK_JUSTIFY_LEFT: return "left"; + case TK_JUSTIFY_RIGHT: return "right"; + case TK_JUSTIFY_CENTER: return "center"; } return "unknown justification style"; } @@ -498,10 +484,10 @@ Tk_NameOfJustify(justify) */ static void -FreeUidThreadExitProc(clientData) - ClientData clientData; /* Not used. */ +FreeUidThreadExitProc( + ClientData clientData) /* Not used. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_DeleteHashTable(&tsdPtr->uidTable); tsdPtr->initialized = 0; @@ -512,17 +498,16 @@ FreeUidThreadExitProc(clientData) * * Tk_GetUid -- * - * Given a string, this procedure returns a unique identifier - * for the string. + * Given a string, this function returns a unique identifier for the + * string. * * Results: - * This procedure returns a Tk_Uid corresponding to the "string" - * argument. The Tk_Uid has a string value identical to string - * (strcmp will return 0), but it's guaranteed that any other - * calls to this procedure with a string equal to "string" will - * return exactly the same result (i.e. can compare Tk_Uid - * *values* directly, without having to call strcmp on what they - * point to). + * This function returns a Tk_Uid corresponding to the "string" argument. + * The Tk_Uid has a string value identical to string (strcmp will return + * 0), but it's guaranteed that any other calls to this function with a + * string equal to "string" will return exactly the same result (i.e. can + * compare Tk_Uid *values* directly, without having to call strcmp on + * what they point to). * * Side effects: * New information may be entered into the identifier table. @@ -531,11 +516,11 @@ FreeUidThreadExitProc(clientData) */ Tk_Uid -Tk_GetUid(string) - CONST char *string; /* String to convert. */ +Tk_GetUid( + CONST char *string) /* String to convert. */ { int dummy; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashTable *tablePtr = &tsdPtr->uidTable; @@ -553,15 +538,14 @@ Tk_GetUid(string) * * Tk_GetScreenMM -- * - * Given a string, returns the number of screen millimeters - * corresponding to that string. + * Given a string, returns the number of screen millimeters corresponding + * to that string. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * screen distance is stored at *doublePtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the screen distance is stored + * at *doublePtr; otherwise TCL_ERROR is returned and an error message is + * left in the interp's result. * * Side effects: * None. @@ -570,13 +554,13 @@ Tk_GetUid(string) */ int -Tk_GetScreenMM(interp, tkwin, string, doublePtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - Tk_Window tkwin; /* Window whose screen determines conversion +Tk_GetScreenMM( + Tcl_Interp *interp, /* Use this for error reporting. */ + Tk_Window tkwin, /* Window whose screen determines conversion * from centimeters and other absolute * units. */ - CONST char *string; /* String describing a screen distance. */ - double *doublePtr; /* Place to store converted result. */ + CONST char *string, /* String describing a screen distance. */ + double *doublePtr) /* Place to store converted result. */ { char *end; double d; @@ -584,35 +568,34 @@ Tk_GetScreenMM(interp, tkwin, string, doublePtr) d = strtod(string, &end); if (end == string) { error: - Tcl_AppendResult(interp, "bad screen distance \"", string, - "\"", (char *) NULL); + Tcl_AppendResult(interp, "bad screen distance \"", string, "\"", NULL); return TCL_ERROR; } while ((*end != '\0') && isspace(UCHAR(*end))) { end++; } switch (*end) { - case 0: - d /= WidthOfScreen(Tk_Screen(tkwin)); - d *= WidthMMOfScreen(Tk_Screen(tkwin)); - break; - case 'c': - d *= 10; - end++; - break; - case 'i': - d *= 25.4; - end++; - break; - case 'm': - end++; - break; - case 'p': - d *= 25.4/72.0; - end++; - break; - default: - goto error; + case 0: + d /= WidthOfScreen(Tk_Screen(tkwin)); + d *= WidthMMOfScreen(Tk_Screen(tkwin)); + break; + case 'c': + d *= 10; + end++; + break; + case 'i': + d *= 25.4; + end++; + break; + case 'm': + end++; + break; + case 'p': + d *= 25.4/72.0; + end++; + break; + default: + goto error; } while ((*end != '\0') && isspace(UCHAR(*end))) { end++; @@ -629,15 +612,14 @@ Tk_GetScreenMM(interp, tkwin, string, doublePtr) * * Tk_GetPixels -- * - * Given a string, returns the number of pixels corresponding - * to that string. + * Given a string, returns the number of pixels corresponding to that + * string. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * rounded pixel distance is stored at *intPtr; otherwise - * TCL_ERROR is returned and an error message is left in - * the interp's result. + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the rounded pixel distance is + * stored at *intPtr; otherwise TCL_ERROR is returned and an error + * message is left in the interp's result. * * Side effects: * None. @@ -646,13 +628,13 @@ Tk_GetScreenMM(interp, tkwin, string, doublePtr) */ int -Tk_GetPixels(interp, tkwin, string, intPtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - Tk_Window tkwin; /* Window whose screen determines conversion +Tk_GetPixels( + Tcl_Interp *interp, /* Use this for error reporting. */ + Tk_Window tkwin, /* Window whose screen determines conversion * from centimeters and other absolute * units. */ - CONST char *string; /* String describing a number of pixels. */ - int *intPtr; /* Place to store converted result. */ + CONST char *string, /* String describing a number of pixels. */ + int *intPtr) /* Place to store converted result. */ { double d; @@ -672,15 +654,15 @@ Tk_GetPixels(interp, tkwin, string, intPtr) * * TkGetDoublePixels -- * - * Given a string, returns the number of pixels corresponding - * to that string. + * Given a string, returns the number of pixels corresponding to that + * string. * * Results: - * The return value is a standard Tcl return result. If - * TCL_OK is returned, then everything went well and the - * pixel distance is stored at *doublePtr; otherwise - * TCL_ERROR is returned and an error message is left in - * interp->result. + + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the pixel distance is stored + * at *doublePtr; otherwise TCL_ERROR is returned and an error message is + * left in interp->result. * * Side effects: * None. @@ -689,52 +671,51 @@ Tk_GetPixels(interp, tkwin, string, intPtr) */ int -TkGetDoublePixels(interp, tkwin, string, doublePtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - Tk_Window tkwin; /* Window whose screen determines conversion +TkGetDoublePixels( + Tcl_Interp *interp, /* Use this for error reporting. */ + Tk_Window tkwin, /* Window whose screen determines conversion * from centimeters and other absolute * units. */ - CONST char *string; /* String describing a number of pixels. */ - double *doublePtr; /* Place to store converted result. */ + CONST char *string, /* String describing a number of pixels. */ + double *doublePtr) /* Place to store converted result. */ { char *end; double d; d = strtod((char *) string, &end); if (end == string) { - error: - Tcl_AppendResult(interp, "bad screen distance \"", string, - "\"", (char *) NULL); + error: + Tcl_AppendResult(interp, "bad screen distance \"", string, "\"", NULL); return TCL_ERROR; } while ((*end != '\0') && isspace(UCHAR(*end))) { end++; } switch (*end) { - case 0: - break; - case 'c': - d *= 10*WidthOfScreen(Tk_Screen(tkwin)); - d /= WidthMMOfScreen(Tk_Screen(tkwin)); - end++; - break; - case 'i': - d *= 25.4*WidthOfScreen(Tk_Screen(tkwin)); - d /= WidthMMOfScreen(Tk_Screen(tkwin)); - end++; - break; - case 'm': - d *= WidthOfScreen(Tk_Screen(tkwin)); - d /= WidthMMOfScreen(Tk_Screen(tkwin)); - end++; - break; - case 'p': - d *= (25.4/72.0)*WidthOfScreen(Tk_Screen(tkwin)); - d /= WidthMMOfScreen(Tk_Screen(tkwin)); - end++; - break; - default: - goto error; + case 0: + break; + case 'c': + d *= 10*WidthOfScreen(Tk_Screen(tkwin)); + d /= WidthMMOfScreen(Tk_Screen(tkwin)); + end++; + break; + case 'i': + d *= 25.4*WidthOfScreen(Tk_Screen(tkwin)); + d /= WidthMMOfScreen(Tk_Screen(tkwin)); + end++; + break; + case 'm': + d *= WidthOfScreen(Tk_Screen(tkwin)); + d /= WidthMMOfScreen(Tk_Screen(tkwin)); + end++; + break; + case 'p': + d *= (25.4/72.0)*WidthOfScreen(Tk_Screen(tkwin)); + d /= WidthMMOfScreen(Tk_Screen(tkwin)); + end++; + break; + default: + goto error; } while ((*end != '\0') && isspace(UCHAR(*end))) { end++; @@ -745,5 +726,11 @@ TkGetDoublePixels(interp, tkwin, string, doublePtr) *doublePtr = d; return TCL_OK; } - - + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkGrab.c b/generic/tkGrab.c index 3f4748c..57f8614 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -1,45 +1,42 @@ -/* +/* * tkGrab.c -- * - * This file provides procedures that implement grabs for Tk. + * This file provides functions that implement grabs for Tk. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) #include "tkUnixInt.h" #endif /* - * The grab state machine has four states: ungrabbed, button pressed, - * grabbed, and button pressed while grabbed. In addition, there are - * three pieces of grab state information: the current grab window, - * the current restrict window, and whether the mouse is captured. - * - * The current grab window specifies the point in the Tk window - * heirarchy above which pointer events will not be reported. Any - * window within the subtree below the grab window will continue to - * receive events as normal. Events outside of the grab tree will be - * reported to the grab window. - * - * If the current restrict window is set, then all pointer events will - * be reported only to the restrict window. The restrict window is - * normally set during an automatic button grab. - * - * The mouse capture state specifies whether the window system will - * report mouse events outside of any Tk toplevels. This is set - * during a global grab or an automatic button grab. - * - * The transitions between different states is given in the following - * table: - * + * The grab state machine has four states: ungrabbed, button pressed, grabbed, + * and button pressed while grabbed. In addition, there are three pieces of + * grab state information: the current grab window, the current restrict + * window, and whether the mouse is captured. + * + * The current grab window specifies the point in the Tk window heirarchy + * above which pointer events will not be reported. Any window within the + * subtree below the grab window will continue to receive events as normal. + * Events outside of the grab tree will be reported to the grab window. + * + * If the current restrict window is set, then all pointer events will be + * reported only to the restrict window. The restrict window is normally set + * during an automatic button grab. + * + * The mouse capture state specifies whether the window system will report + * mouse events outside of any Tk toplevels. This is set during a global grab + * or an automatic button grab. + * + * The transitions between different states is given in the following table: + * * Event\State U B G GB * ----------- -- -- -- -- * FirstPress B B GB GB @@ -60,15 +57,14 @@ * Grabbed 1 0 b/g * Grab and Button 1 1 1 * - * Note: 0 means variable is set to NULL, 1 means variable is set to - * some window, b/g means the variable is set to a window if a button - * is currently down or a global grab is in effect. + * Note: 0 means variable is set to NULL, 1 means variable is set to some + * window, b/g means the variable is set to a window if a button is currently + * down or a global grab is in effect. * - * The final complication to all of this is enter and leave events. - * In order to correctly handle all of the various cases, Tk cannot - * rely on X enter/leave events in all situations. The following - * describes the correct sequence of enter and leave events that - * should be observed by Tk scripts: + * The final complication to all of this is enter and leave events. In order + * to correctly handle all of the various cases, Tk cannot rely on X + * enter/leave events in all situations. The following describes the correct + * sequence of enter and leave events that should be observed by Tk scripts: * * Event(state) Enter/Leave From -> To * ------------ ---------------------- @@ -80,13 +76,13 @@ * Ungrab(G): anc(grab window, event window) -> event window * Ungrab(GB): restrict window -> event window * - * Note: anc(x,y) returns the least ancestor of y that is in the tree - * of x, terminating at toplevels. + * Note: anc(x,y) returns the least ancestor of y that is in the tree of x, + * terminating at toplevels. */ /* - * The following structure is used to pass information to - * GrabRestrictProc from EatGrabEvents. + * The following structure is used to pass information to GrabRestrictProc + * from EatGrabEvents. */ typedef struct { @@ -99,47 +95,46 @@ typedef struct { * * GRAB_GLOBAL 1 means this is a global grab (we grabbed via * the server so all applications are locked out). - * 0 means this is a local grab that affects - * only this application. + * 0 means this is a local grab that affects only + * this application. * GRAB_TEMP_GLOBAL 1 means we've temporarily grabbed via the - * server because a button is down and we want - * to make sure that we get the button-up - * event. The grab will be released when the - * last mouse button goes up. + * server because a button is down and we want to + * make sure that we get the button-up event. The + * grab will be released when the last mouse + * button goes up. */ #define GRAB_GLOBAL 1 #define GRAB_TEMP_GLOBAL 4 /* - * The following structure is a Tcl_Event that triggers a change in - * the grabWinPtr field of a display. This event guarantees that - * the change occurs in the proper order relative to enter and leave - * events. + * The following structure is a Tcl_Event that triggers a change in the + * grabWinPtr field of a display. This event guarantees that the change occurs + * in the proper order relative to enter and leave events. */ typedef struct NewGrabWinEvent { Tcl_Event header; /* Standard information for all Tcl events. */ TkDisplay *dispPtr; /* Display whose grab window is to change. */ - Window grabWindow; /* New grab window for display. This is + Window grabWindow; /* New grab window for display. This is * recorded instead of a (TkWindow *) because - * it will allow us to detect cases where - * the window is destroyed before this event - * is processed. */ + * it will allow us to detect cases where the + * window is destroyed before this event is + * processed. */ } NewGrabWinEvent; /* * The following magic value is stored in the "send_event" field of - * EnterNotify and LeaveNotify events that are generated in this - * file. This allows us to separate "real" events coming from the - * server from those that we generated. + * EnterNotify and LeaveNotify events that are generated in this file. This + * allows us to separate "real" events coming from the server from those that + * we generated. */ #define GENERATED_EVENT_MAGIC ((Bool) 0x147321ac) /* - * Mask that selects any of the state bits corresponding to buttons, - * plus masks that select individual buttons' bits: + * Mask that selects any of the state bits corresponding to buttons, plus + * masks that select individual buttons' bits: */ #define ALL_BUTTONS \ @@ -149,32 +144,27 @@ static unsigned int buttonStates[] = { }; /* - * Forward declarations for procedures declared later in this file: + * Forward declarations for functions declared later in this file: */ -static void EatGrabEvents _ANSI_ARGS_((TkDisplay *dispPtr, - unsigned int serial)); -static TkWindow * FindCommonAncestor _ANSI_ARGS_((TkWindow *winPtr1, - TkWindow *winPtr2, int *countPtr1, - int *countPtr2)); -static Tk_RestrictAction GrabRestrictProc _ANSI_ARGS_((ClientData arg, - XEvent *eventPtr)); -static int GrabWinEventProc _ANSI_ARGS_((Tcl_Event *evPtr, - int flags)); -static void MovePointer2 _ANSI_ARGS_((TkWindow *sourcePtr, - TkWindow *destPtr, int mode, int leaveEvents, - int EnterEvents)); -static void QueueGrabWindowChange _ANSI_ARGS_((TkDisplay *dispPtr, - TkWindow *grabWinPtr)); -static void ReleaseButtonGrab _ANSI_ARGS_((TkDisplay *dispPtr)); +static void EatGrabEvents(TkDisplay *dispPtr, unsigned int serial); +static TkWindow * FindCommonAncestor(TkWindow *winPtr1, + TkWindow *winPtr2, int *countPtr1, int *countPtr2); +static Tk_RestrictAction GrabRestrictProc(ClientData arg, XEvent *eventPtr); +static int GrabWinEventProc(Tcl_Event *evPtr, int flags); +static void MovePointer2(TkWindow *sourcePtr, TkWindow *destPtr, + int mode, int leaveEvents, int EnterEvents); +static void QueueGrabWindowChange(TkDisplay *dispPtr, + TkWindow *grabWinPtr); +static void ReleaseButtonGrab(TkDisplay *dispPtr); /* *---------------------------------------------------------------------- * * Tk_GrabObjCmd -- * - * This procedure is invoked to process the "grab" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "grab" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -187,12 +177,11 @@ static void ReleaseButtonGrab _ANSI_ARGS_((TkDisplay *dispPtr)); /* ARGSUSED */ int -Tk_GrabObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_GrabObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { int globalGrab; Tk_Window tkwin; @@ -200,14 +189,16 @@ Tk_GrabObjCmd(clientData, interp, objc, objv) char *arg; int index; int len; - static CONST char *optionStrings[] = { "current", "release", - "set", "status", (char *) NULL }; - - static CONST char *flagStrings[] = { "-global", (char *) NULL }; - - enum options { GRABCMD_CURRENT, GRABCMD_RELEASE, - GRABCMD_SET, GRABCMD_STATUS }; - + static CONST char *optionStrings[] = { + "current", "release", "set", "status", NULL + }; + static CONST char *flagStrings[] = { + "-global", NULL + }; + enum options { + GRABCMD_CURRENT, GRABCMD_RELEASE, GRABCMD_SET, GRABCMD_STATUS + }; + if (objc < 2) { /* * Can't use Tcl_WrongNumArgs here because we want the message to @@ -221,8 +212,7 @@ Tk_GrabObjCmd(clientData, interp, objc, objv) Tcl_ResetResult(interp); Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetString(objv[0]), " ?-global? window\" or \"", - Tcl_GetString(objv[0]), " option ?arg arg ...?\"", - (char *) NULL); + Tcl_GetString(objv[0]), " option ?arg arg ...?\"", NULL); return TCL_ERROR; } @@ -262,115 +252,114 @@ Tk_GrabObjCmd(clientData, interp, objc, objv) } /* - * First argument is not a window name and not "-global", find out - * which option it is. + * First argument is not a window name and not "-global", find out which + * option it is. */ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - + switch ((enum options) index) { - case GRABCMD_CURRENT: { - /* [grab current ?window?] */ - if (objc > 3) { - Tcl_WrongNumArgs(interp, 1, objv, "current ?window?"); + case GRABCMD_CURRENT: + /* [grab current ?window?] */ + if (objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "current ?window?"); + return TCL_ERROR; + } + if (objc == 3) { + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), + (Tk_Window) clientData); + if (tkwin == NULL) { return TCL_ERROR; } - if (objc == 3) { - tkwin = Tk_NameToWindow(interp, - Tcl_GetString(objv[2]), (Tk_Window) clientData); - if (tkwin == NULL) { - return TCL_ERROR; - } - dispPtr = ((TkWindow *) tkwin)->dispPtr; + dispPtr = ((TkWindow *) tkwin)->dispPtr; + if (dispPtr->eventualGrabWinPtr != NULL) { + Tcl_SetResult(interp, dispPtr->eventualGrabWinPtr->pathName, + TCL_STATIC); + } + } else { + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; + dispPtr = dispPtr->nextPtr) { if (dispPtr->eventualGrabWinPtr != NULL) { - Tcl_SetResult(interp, - dispPtr->eventualGrabWinPtr->pathName, TCL_STATIC); - } - } else { - for (dispPtr = TkGetDisplayList(); dispPtr != NULL; - dispPtr = dispPtr->nextPtr) { - if (dispPtr->eventualGrabWinPtr != NULL) { - Tcl_AppendElement(interp, - dispPtr->eventualGrabWinPtr->pathName); - } + Tcl_AppendElement(interp, + dispPtr->eventualGrabWinPtr->pathName); } } - return TCL_OK; } + return TCL_OK; - case GRABCMD_RELEASE: { - /* [grab release window] */ - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "release window"); - return TCL_ERROR; - } - tkwin = Tk_NameToWindow(interp, - Tcl_GetString(objv[2]), (Tk_Window) clientData); - if (tkwin == NULL) { - Tcl_ResetResult(interp); - } else { - Tk_Ungrab(tkwin); - } - break; + case GRABCMD_RELEASE: + /* [grab release window] */ + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "release window"); + return TCL_ERROR; } - - case GRABCMD_SET: { - /* [grab set ?-global? window] */ - if ((objc != 3) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 1, objv, "set ?-global? window"); - return TCL_ERROR; - } - if (objc == 3) { - globalGrab = 0; - tkwin = Tk_NameToWindow(interp, - Tcl_GetString(objv[2]), (Tk_Window) clientData); - } else { - globalGrab = 1; - /* - * We could just test the argument by hand instead of using - * Tcl_GetIndexFromObj; the benefit of using the function is - * that it sets up the error message for us, so we are - * certain to be consistant with the rest of Tcl. - */ - if (Tcl_GetIndexFromObj(interp, objv[2], flagStrings, "option", - 0, &index) != TCL_OK) { - return TCL_ERROR; - } - tkwin = Tk_NameToWindow(interp, - Tcl_GetString(objv[3]), (Tk_Window) clientData); - } - if (tkwin == NULL) { - return TCL_ERROR; - } - return Tk_Grab(interp, tkwin, globalGrab); + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), + (Tk_Window) clientData); + if (tkwin == NULL) { + Tcl_ResetResult(interp); + } else { + Tk_Ungrab(tkwin); } + break; - case GRABCMD_STATUS: { - /* [grab status window] */ - TkWindow *winPtr; + case GRABCMD_SET: + /* [grab set ?-global? window] */ + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 1, objv, "set ?-global? window"); + return TCL_ERROR; + } + if (objc == 3) { + globalGrab = 0; + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), + (Tk_Window) clientData); + } else { + globalGrab = 1; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "status window"); - return TCL_ERROR; - } - winPtr = (TkWindow *) Tk_NameToWindow(interp, - Tcl_GetString(objv[2]), (Tk_Window) clientData); - if (winPtr == NULL) { + /* + * We could just test the argument by hand instead of using + * Tcl_GetIndexFromObj; the benefit of using the function is that + * it sets up the error message for us, so we are certain to be + * consistant with the rest of Tcl. + */ + + if (Tcl_GetIndexFromObj(interp, objv[2], flagStrings, "option", + 0, &index) != TCL_OK) { return TCL_ERROR; } - dispPtr = winPtr->dispPtr; - if (dispPtr->eventualGrabWinPtr != winPtr) { - Tcl_SetResult(interp, "none", TCL_STATIC); - } else if (dispPtr->grabFlags & GRAB_GLOBAL) { - Tcl_SetResult(interp, "global", TCL_STATIC); - } else { - Tcl_SetResult(interp, "local", TCL_STATIC); - } - break; + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[3]), + (Tk_Window) clientData); + } + if (tkwin == NULL) { + return TCL_ERROR; + } + return Tk_Grab(interp, tkwin, globalGrab); + + case GRABCMD_STATUS: { + /* [grab status window] */ + TkWindow *winPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "status window"); + return TCL_ERROR; + } + winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[2]), + (Tk_Window) clientData); + if (winPtr == NULL) { + return TCL_ERROR; + } + dispPtr = winPtr->dispPtr; + if (dispPtr->eventualGrabWinPtr != winPtr) { + Tcl_SetResult(interp, "none", TCL_STATIC); + } else if (dispPtr->grabFlags & GRAB_GLOBAL) { + Tcl_SetResult(interp, "global", TCL_STATIC); + } else { + Tcl_SetResult(interp, "local", TCL_STATIC); } + break; + } } return TCL_OK; @@ -381,34 +370,32 @@ Tk_GrabObjCmd(clientData, interp, objc, objv) * * Tk_Grab -- * - * Grabs the pointer and keyboard, so that mouse-related events are - * only reported relative to a given window and its descendants. + * Grabs the pointer and keyboard, so that mouse-related events are only + * reported relative to a given window and its descendants. * * Results: - * A standard Tcl result is returned. TCL_OK is the normal return - * value; if the grab could not be set then TCL_ERROR is returned - * and the interp's result will hold an error message. + * A standard Tcl result is returned. TCL_OK is the normal return value; + * if the grab could not be set then TCL_ERROR is returned and the + * interp's result will hold an error message. * * Side effects: - * Once this call completes successfully, no window outside the - * tree rooted at tkwin will receive pointer- or keyboard-related - * events until the next call to Tk_Ungrab. If a previous grab was - * in effect within this application, then it is replaced with a new - * one. + * Once this call completes successfully, no window outside the tree + * rooted at tkwin will receive pointer- or keyboard-related events until + * the next call to Tk_Ungrab. If a previous grab was in effect within + * this application, then it is replaced with a new one. * *---------------------------------------------------------------------- */ int -Tk_Grab(interp, tkwin, grabGlobal) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Window tkwin; /* Window on whose behalf the pointer - * is to be grabbed. */ - int grabGlobal; /* Non-zero means issue a grab to the - * server so that no other application - * gets mouse or keyboard events. - * Zero means the grab only applies - * within this application. */ +Tk_Grab( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Window tkwin, /* Window on whose behalf the pointer is to be + * grabbed. */ + int grabGlobal) /* Non-zero means issue a grab to the server + * so that no other application gets mouse or + * keyboard events. Zero means the grab only + * applies within this application. */ { int grabResult, numTries; TkWindow *winPtr = (TkWindow *) tkwin; @@ -423,7 +410,7 @@ Tk_Grab(interp, tkwin, grabGlobal) return TCL_OK; } if (dispPtr->eventualGrabWinPtr->mainPtr != winPtr->mainPtr) { - alreadyGrabbed: + alreadyGrabbed: Tcl_SetResult(interp, "grab failed: another application has grab", TCL_STATIC); return TCL_ERROR; @@ -438,11 +425,11 @@ Tk_Grab(interp, tkwin, grabGlobal) unsigned int state; /* - * Local grab. However, if any mouse buttons are down, turn - * it into a global grab temporarily, until the last button - * goes up. This does two things: (a) it makes sure that we - * see the button-up event; and (b) it allows us to track mouse - * motion among all of the windows of this application. + * Local grab. However, if any mouse buttons are down, turn it into a + * global grab temporarily, until the last button goes up. This does + * two things: (a) it makes sure that we see the button-up event; and + * (b) it allows us to track mouse motion among all of the windows of + * this application. */ dispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL); @@ -454,30 +441,28 @@ Tk_Grab(interp, tkwin, grabGlobal) } } else { dispPtr->grabFlags |= GRAB_GLOBAL; - setGlobalGrab: + setGlobalGrab: /* - * Tricky point: must ungrab before grabbing. This is needed - * in case there is a button auto-grab already in effect. If - * there is, and the mouse has moved to a different window, X - * won't generate enter and leave events to move the mouse if - * we grab without ungrabbing. + * Tricky point: must ungrab before grabbing. This is needed in case + * there is a button auto-grab already in effect. If there is, and the + * mouse has moved to a different window, X won't generate enter and + * leave events to move the mouse if we grab without ungrabbing. */ XUngrabPointer(dispPtr->display, CurrentTime); serial = NextRequest(dispPtr->display); /* - * Another tricky point: there are races with some window - * managers that can cause grabs to fail because the window - * manager hasn't released its grab quickly enough. To work - * around this problem, retry a few times after AlreadyGrabbed - * errors to give the grab release enough time to register with - * the server. + * Another tricky point: there are races with some window managers + * that can cause grabs to fail because the window manager hasn't + * released its grab quickly enough. To work around this problem, + * retry a few times after AlreadyGrabbed errors to give the grab + * release enough time to register with the server. */ - grabResult = 0; /* Needed only to prevent gcc - * compiler warnings. */ + grabResult = 0; /* Needed only to prevent gcc compiler + * warnings. */ for (numTries = 0; numTries < 10; numTries++) { grabResult = XGrabPointer(dispPtr->display, winPtr->window, True, ButtonPressMask|ButtonReleaseMask|ButtonMotionMask @@ -489,7 +474,7 @@ Tk_Grab(interp, tkwin, grabGlobal) Tcl_Sleep(100); } if (grabResult != 0) { - grabError: + grabError: if (grabResult == GrabNotViewable) { Tcl_SetResult(interp, "grab failed: window not viewable", TCL_STATIC); @@ -503,10 +488,10 @@ Tk_Grab(interp, tkwin, grabGlobal) TCL_STATIC); } else { char msg[64 + TCL_INTEGER_SPACE]; - + sprintf(msg, "grab failed for unknown reason (code %d)", grabResult); - Tcl_AppendResult(interp, msg, (char *) NULL); + Tcl_AppendResult(interp, msg, NULL); } return TCL_ERROR; } @@ -519,13 +504,13 @@ Tk_Grab(interp, tkwin, grabGlobal) /* * Eat up any grab-related events generated by the server for the - * grab. There are several reasons for doing this: + * grab. There are several reasons for doing this: * * 1. We have to synthesize the events for local grabs anyway, since * the server doesn't participate in them. * 2. The server doesn't always generate the right events for global - * grabs (e.g. it generates events even if the current window is - * in the grab tree, which we don't want). + * grabs (e.g. it generates events even if the current window is in + * the grab tree, which we don't want). * 3. We want all the grab-related events to be processed immediately * (before other events that are already queued); events coming * from the server will be in the wrong place, but events we @@ -536,8 +521,8 @@ Tk_Grab(interp, tkwin, grabGlobal) } /* - * Synthesize leave events to move the pointer from its current window - * up to the lowest ancestor that it has in common with the grab window. + * Synthesize leave events to move the pointer from its current window up + * to the lowest ancestor that it has in common with the grab window. * However, only do this if the pointer is outside the grab window's * subtree but inside the grab window's application. */ @@ -563,8 +548,8 @@ Tk_Grab(interp, tkwin, grabGlobal) * * Tk_Ungrab -- * - * Releases a grab on the mouse pointer and keyboard, if there - * is one set on the specified window. + * Releases a grab on the mouse pointer and keyboard, if there is one set + * on the specified window. * * Results: * None. @@ -577,9 +562,8 @@ Tk_Grab(interp, tkwin, grabGlobal) */ void -Tk_Ungrab(tkwin) - Tk_Window tkwin; /* Window whose grab should be - * released. */ +Tk_Ungrab( + Tk_Window tkwin) /* Window whose grab should be released. */ { TkDisplay *dispPtr; TkWindow *grabWinPtr, *winPtr; @@ -591,7 +575,7 @@ Tk_Ungrab(tkwin) return; } ReleaseButtonGrab(dispPtr); - QueueGrabWindowChange(dispPtr, (TkWindow *) NULL); + QueueGrabWindowChange(dispPtr, NULL); if (dispPtr->grabFlags & (GRAB_GLOBAL|GRAB_TEMP_GLOBAL)) { dispPtr->grabFlags &= ~(GRAB_GLOBAL|GRAB_TEMP_GLOBAL); serial = NextRequest(dispPtr->display); @@ -601,17 +585,17 @@ Tk_Ungrab(tkwin) } /* - * Generate events to move the pointer back to the window where it - * really is. Some notes: - * 1. As with grabs, only do this if the "real" window is not a - * descendant of the grab window, since in this case the pointer - * is already where it's supposed to be. + * Generate events to move the pointer back to the window where it really + * is. Some notes: + * 1. As with grabs, only do this if the "real" window is not a descendant + * of the grab window, since in this case the pointer is already where + * it's supposed to be. * 2. If the "real" window is in some other application then don't - * generate any events at all, since everything's already been - * reported correctly. - * 3. Only generate enter events. Don't generate leave events, - * because we never told the lower-level windows that they - * had the pointer in the first place. + * generate any events at all, since everything's already been reported + * correctly. + * 3. Only generate enter events. Don't generate leave events, because we + * never told the lower-level windows that they had the pointer in the + * first place. */ for (winPtr = dispPtr->serverWinPtr; ; winPtr = winPtr->parentPtr) { @@ -634,26 +618,26 @@ Tk_Ungrab(tkwin) * * ReleaseButtonGrab -- * - * This procedure is called to release a simulated button grab, if - * there is one in effect. A button grab is present whenever - * dispPtr->buttonWinPtr is non-NULL or when the GRAB_TEMP_GLOBAL - * flag is set. + * This function is called to release a simulated button grab, if there + * is one in effect. A button grab is present whenever + * dispPtr->buttonWinPtr is non-NULL or when the GRAB_TEMP_GLOBAL flag is + * set. * * Results: * None. * * Side effects: - * DispPtr->buttonWinPtr is reset to NULL, and enter and leave - * events are generated if necessary to move the pointer from - * the button grab window to its current window. + * DispPtr->buttonWinPtr is reset to NULL, and enter and leave events are + * generated if necessary to move the pointer from the button grab window + * to its current window. * *---------------------------------------------------------------------- */ static void -ReleaseButtonGrab(dispPtr) - register TkDisplay *dispPtr; /* Display whose button grab is to be - * released. */ +ReleaseButtonGrab( + register TkDisplay *dispPtr)/* Display whose button grab is to be + * released. */ { unsigned int serial; @@ -678,64 +662,64 @@ ReleaseButtonGrab(dispPtr) * * TkPointerEvent -- * - * This procedure is called for each pointer-related event, before - * the event has been processed. It does various things to make - * grabs work correctly. + * This function is called for each pointer-related event, before the + * event has been processed. It does various things to make grabs work + * correctly. * * Results: - * If the return value is 1 it means the event should be processed - * (event handlers should be invoked). If the return value is 0 - * it means the event should be ignored in order to make grabs - * work correctly. In some cases this procedure modifies the event. + * If the return value is 1 it means the event should be processed (event + * handlers should be invoked). If the return value is 0 it means the + * event should be ignored in order to make grabs work correctly. In some + * cases this function modifies the event. * * Side effects: - * Grab state information may be updated. New events may also be - * pushed back onto the event queue to replace or augment the - * one passed in here. + * Grab state information may be updated. New events may also be pushed + * back onto the event queue to replace or augment the one passed in + * here. * *---------------------------------------------------------------------- */ int -TkPointerEvent(eventPtr, winPtr) - register XEvent *eventPtr; /* Pointer to the event. */ - TkWindow *winPtr; /* Tk's information for window - * where event was reported. */ +TkPointerEvent( + register XEvent *eventPtr, /* Pointer to the event. */ + TkWindow *winPtr) /* Tk's information for window where event was + * reported. */ { register TkWindow *winPtr2; TkDisplay *dispPtr = winPtr->dispPtr; unsigned int serial; int outsideGrabTree = 0; int ancestorOfGrab = 0; - int appGrabbed = 0; /* Non-zero means event is being - * reported to an application that is - * affected by the grab. */ + int appGrabbed = 0; /* Non-zero means event is being reported to + * an application that is affected by the + * grab. */ /* * Collect information about the grab (if any). */ switch (TkGrabState(winPtr)) { - case TK_GRAB_IN_TREE: - appGrabbed = 1; - break; - case TK_GRAB_ANCESTOR: - appGrabbed = 1; - outsideGrabTree = 1; - ancestorOfGrab = 1; - break; - case TK_GRAB_EXCLUDED: - appGrabbed = 1; - outsideGrabTree = 1; - break; + case TK_GRAB_IN_TREE: + appGrabbed = 1; + break; + case TK_GRAB_ANCESTOR: + appGrabbed = 1; + outsideGrabTree = 1; + ancestorOfGrab = 1; + break; + case TK_GRAB_EXCLUDED: + appGrabbed = 1; + outsideGrabTree = 1; + break; } if ((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) { /* - * Keep track of what window the mouse is *really* over. - * Any events that we generate have a special send_event value, - * which is detected below and used to ignore the event for - * purposes of setting serverWinPtr. + * Keep track of what window the mouse is *really* over. Any events + * that we generate have a special send_event value, which is detected + * below and used to ignore the event for purposes of setting + * serverWinPtr. */ if (eventPtr->xcrossing.send_event != GENERATED_EVENT_MAGIC) { @@ -748,13 +732,13 @@ TkPointerEvent(eventPtr, winPtr) } /* - * When a grab is active, X continues to report enter and leave - * events for windows outside the tree of the grab window: - * 1. Detect these events and ignore them except for - * windows above the grab window. - * 2. Allow Enter and Leave events to pass through the - * windows above the grab window, but never let them - * end up with the pointer *in* one of those windows. + * When a grab is active, X continues to report enter and leave events + * for windows outside the tree of the grab window: + * 1. Detect these events and ignore them except for windows above the + * grab window. + * 2. Allow Enter and Leave events to pass through the windows above + * the grab window, but never let them end up with the pointer *in* + * one of those windows. */ if (dispPtr->grabWinPtr != NULL) { @@ -763,22 +747,21 @@ TkPointerEvent(eventPtr, winPtr) return 0; } switch (eventPtr->xcrossing.detail) { - case NotifyInferior: - return 0; - case NotifyAncestor: - eventPtr->xcrossing.detail = NotifyVirtual; - break; - case NotifyNonlinear: - eventPtr->xcrossing.detail = NotifyNonlinearVirtual; - break; + case NotifyInferior: + return 0; + case NotifyAncestor: + eventPtr->xcrossing.detail = NotifyVirtual; + break; + case NotifyNonlinear: + eventPtr->xcrossing.detail = NotifyNonlinearVirtual; + break; } } /* - * Make buttons have the same grab-like behavior inside a grab - * as they do outside a grab: do this by ignoring enter and - * leave events except for the window in which the button was - * pressed. + * Make buttons have the same grab-like behavior inside a grab as + * they do outside a grab: do this by ignoring enter and leave + * events except for the window in which the button was pressed. */ if ((dispPtr->buttonWinPtr != NULL) @@ -796,12 +779,12 @@ TkPointerEvent(eventPtr, winPtr) if (eventPtr->type == MotionNotify) { /* * When grabs are active, X reports motion events relative to the - * window under the pointer. Instead, it should report the events + * window under the pointer. Instead, it should report the events * relative to the window the button went down in, if there is a - * button down. Otherwise, if the pointer window is outside the - * subtree of the grab window, the events should be reported - * relative to the grab window. Otherwise, the event should be - * reported to the pointer window. + * button down. Otherwise, if the pointer window is outside the + * subtree of the grab window, the events should be reported relative + * to the grab window. Otherwise, the event should be reported to the + * pointer window. */ winPtr2 = winPtr; @@ -820,32 +803,32 @@ TkPointerEvent(eventPtr, winPtr) /* * Process ButtonPress and ButtonRelease events: - * 1. Keep track of whether a button is down and what window it - * went down in. - * 2. If the first button goes down outside the grab tree, pretend - * it went down in the grab window. Note: it's important to - * redirect events to the grab window like this in order to make - * things like menus work, where button presses outside the - * grabbed menu need to be seen. An application can always - * ignore the events if they occur outside its window. - * 3. If a button press or release occurs outside the window where - * the first button was pressed, retarget the event so it's reported - * to the window where the first button was pressed. - * 4. If the last button is released in a window different than where - * the first button was pressed, generate Enter/Leave events to - * move the mouse from the button window to its current window. - * 5. If the grab is set at a time when a button is already down, or - * if the window where the button was pressed was deleted, then - * dispPtr->buttonWinPtr will stay NULL. Just forget about the - * auto-grab for the button press; events will go to whatever - * window contains the pointer. If this window isn't in the grab - * tree then redirect events to the grab window. - * 6. When a button is pressed during a local grab, the X server sets - * a grab of its own, since it doesn't even know about our local - * grab. This causes enter and leave events no longer to be - * generated in the same way as for global grabs. To eliminate this - * problem, set a temporary global grab when the first button goes - * down and release it when the last button comes up. + * 1. Keep track of whether a button is down and what window it went down + * in. + * 2. If the first button goes down outside the grab tree, pretend it went + * down in the grab window. Note: it's important to redirect events to + * the grab window like this in order to make things like menus work, + * where button presses outside the grabbed menu need to be seen. An + * application can always ignore the events if they occur outside its + * window. + * 3. If a button press or release occurs outside the window where the + * first button was pressed, retarget the event so it's reported to the + * window where the first button was pressed. + * 4. If the last button is released in a window different than where the + * first button was pressed, generate Enter/Leave events to move the + * mouse from the button window to its current window. + * 5. If the grab is set at a time when a button is already down, or if + * the window where the button was pressed was deleted, then + * dispPtr->buttonWinPtr will stay NULL. Just forget about the + * auto-grab for the button press; events will go to whatever window + * contains the pointer. If this window isn't in the grab tree then + * redirect events to the grab window. + * 6. When a button is pressed during a local grab, the X server sets a + * grab of its own, since it doesn't even know about our local grab. + * This causes enter and leave events no longer to be generated in the + * same way as for global grabs. To eliminate this problem, set a + * temporary global grab when the first button goes down and release it + * when the last button comes up. */ if ((eventPtr->type == ButtonPress) || (eventPtr->type == ButtonRelease)) { @@ -906,12 +889,12 @@ TkPointerEvent(eventPtr, winPtr) * TkChangeEventWindow -- * * Given an event and a new window to which the event should be - * retargeted, modify fields of the event so that the event is - * properly retargeted to the new window. + * retargeted, modify fields of the event so that the event is properly + * retargeted to the new window. * * Results: - * The following fields of eventPtr are modified: window, - * subwindow, x, y, same_screen. + * The following fields of eventPtr are modified: window, subwindow, x, + * y, same_screen. * * Side effects: * None. @@ -920,12 +903,12 @@ TkPointerEvent(eventPtr, winPtr) */ void -TkChangeEventWindow(eventPtr, winPtr) - register XEvent *eventPtr; /* Event to retarget. Must have - * type ButtonPress, ButtonRelease, KeyPress, - * KeyRelease, MotionNotify, EnterNotify, - * or LeaveNotify. */ - TkWindow *winPtr; /* New target window for event. */ +TkChangeEventWindow( + register XEvent *eventPtr, /* Event to retarget. Must have type + * ButtonPress, ButtonRelease, KeyPress, + * KeyRelease, MotionNotify, EnterNotify, or + * LeaveNotify. */ + TkWindow *winPtr) /* New target window for event. */ { int x, y, sameScreen, bd; register TkWindow *childPtr; @@ -970,44 +953,44 @@ TkChangeEventWindow(eventPtr, winPtr) * * TkInOutEvents -- * - * This procedure synthesizes EnterNotify and LeaveNotify events - * to correctly transfer the pointer from one window to another. - * It can also be used to generate FocusIn and FocusOut events - * to move the input focus. + * This function synthesizes EnterNotify and LeaveNotify events to + * correctly transfer the pointer from one window to another. It can also + * be used to generate FocusIn and FocusOut events to move the input + * focus. * * Results: * None. * * Side effects: - * Synthesized events may be pushed back onto the event queue. - * The event pointed to by eventPtr is modified. + * Synthesized events may be pushed back onto the event queue. The event + * pointed to by eventPtr is modified. * *---------------------------------------------------------------------- */ void -TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) - XEvent *eventPtr; /* A template X event. Must have all fields +TkInOutEvents( + XEvent *eventPtr, /* A template X event. Must have all fields * properly set except for type, window, - * subwindow, x, y, detail, and same_screen + * subwindow, x, y, detail, and same_screen. * (Not all of these fields are valid for - * FocusIn/FocusOut events; x_root and y_root + * FocusIn/FocusOut events; x_root and y_root * must be valid for Enter/Leave events, even * though x and y needn't be valid). */ - TkWindow *sourcePtr; /* Window that used to have the pointer or + TkWindow *sourcePtr, /* Window that used to have the pointer or * focus (NULL means it was not in a window * managed by this process). */ - TkWindow *destPtr; /* Window that is to end up with the pointer + TkWindow *destPtr, /* Window that is to end up with the pointer * or focus (NULL means it's not one managed * by this process). */ - int leaveType; /* Type of events to generate for windows - * being left (LeaveNotify or FocusOut). 0 + int leaveType, /* Type of events to generate for windows + * being left (LeaveNotify or FocusOut). 0 * means don't generate leave events. */ - int enterType; /* Type of events to generate for windows - * being entered (EnterNotify or FocusIn). 0 + int enterType, /* Type of events to generate for windows + * being entered (EnterNotify or FocusIn). 0 * means don't generate enter events. */ - Tcl_QueuePosition position; /* Position at which events are added to - * the system event queue. */ + Tcl_QueuePosition position) /* Position at which events are added to the + * system event queue. */ { register TkWindow *winPtr; int upLevels, downLevels, i, j, focus; @@ -1015,17 +998,15 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) /* * There are four possible cases to deal with: * - * 1. SourcePtr and destPtr are the same. There's nothing to do in - * this case. - * 2. SourcePtr is an ancestor of destPtr in the same top-level - * window. Must generate events down the window tree from source - * to dest. - * 3. DestPtr is an ancestor of sourcePtr in the same top-level - * window. Must generate events up the window tree from sourcePtr - * to destPtr. - * 4. All other cases. Must first generate events up the window tree - * from sourcePtr to its top-level, then down from destPtr's - * top-level to destPtr. This form is called "non-linear." + * 1. SourcePtr and destPtr are the same. There's nothing to do in this + * case. + * 2. SourcePtr is an ancestor of destPtr in the same top-level window. + * Must generate events down the window tree from source to dest. + * 3. DestPtr is an ancestor of sourcePtr in the same top-level window. + * Must generate events up the window tree from sourcePtr to destPtr. + * 4. All other cases. Must first generate events up the window tree from + * sourcePtr to its top-level, then down from destPtr's top-level to + * destPtr. This form is called "non-linear." * * The call to FindCommonAncestor separates these four cases and decides * how many levels up and down events have to be generated for. @@ -1045,7 +1026,6 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) * Generate enter/leave events and add them to the grab event queue. */ - #define QUEUE(w, t, d) \ if (w->window != None) { \ eventPtr->type = t; \ @@ -1060,7 +1040,6 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) } if (downLevels == 0) { - /* * SourcePtr is an inferior of destPtr. */ @@ -1076,7 +1055,6 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) QUEUE(destPtr, enterType, NotifyInferior); } } else if (upLevels == 0) { - /* * DestPtr is an inferior of sourcePtr. */ @@ -1088,6 +1066,7 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) for (i = downLevels-1; i > 0; i--) { for (winPtr = destPtr->parentPtr, j = 1; j < i; winPtr = winPtr->parentPtr, j++) { + /* empty */ } QUEUE(winPtr, enterType, NotifyVirtual); } @@ -1096,9 +1075,8 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) } } } else { - /* - * Non-linear: neither window is an inferior of the other. + * Non-linear: neither window is an inferior of the other. */ if (leaveType != 0) { @@ -1127,11 +1105,11 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) * * MovePointer2 -- * - * This procedure synthesizes EnterNotify and LeaveNotify events - * to correctly transfer the pointer from one window to another. - * It is different from TkInOutEvents in that no template X event - * needs to be supplied; this procedure generates the template - * event and calls TkInOutEvents. + * This function synthesizes EnterNotify and LeaveNotify events to + * correctly transfer the pointer from one window to another. It is + * different from TkInOutEvents in that no template X event needs to be + * supplied; this function generates the template event and calls + * TkInOutEvents. * * Results: * None. @@ -1143,20 +1121,20 @@ TkInOutEvents(eventPtr, sourcePtr, destPtr, leaveType, enterType, position) */ static void -MovePointer2(sourcePtr, destPtr, mode, leaveEvents, enterEvents) - TkWindow *sourcePtr; /* Window currently containing pointer (NULL +MovePointer2( + TkWindow *sourcePtr, /* Window currently containing pointer (NULL * means it's not one managed by this * process). */ - TkWindow *destPtr; /* Window that is to end up containing the - * pointer (NULL means it's not one managed - * by this process). */ - int mode; /* Mode for enter/leave events, such as + TkWindow *destPtr, /* Window that is to end up containing the + * pointer (NULL means it's not one managed by + * this process). */ + int mode, /* Mode for enter/leave events, such as * NotifyNormal or NotifyUngrab. */ - int leaveEvents; /* Non-zero means generate leave events for the - * windows being left. Zero means don't + int leaveEvents, /* Non-zero means generate leave events for + * the windows being left. Zero means don't * generate leave events. */ - int enterEvents; /* Non-zero means generate enter events for the - * windows being entered. Zero means don't + int enterEvents) /* Non-zero means generate enter events for + * the windows being entered. Zero means don't * generate enter events. */ { XEvent event; @@ -1172,12 +1150,10 @@ MovePointer2(sourcePtr, destPtr, mode, leaveEvents, enterEvents) } } - event.xcrossing.serial = LastKnownRequestProcessed( - winPtr->display); + event.xcrossing.serial = LastKnownRequestProcessed(winPtr->display); event.xcrossing.send_event = GENERATED_EVENT_MAGIC; event.xcrossing.display = winPtr->display; - event.xcrossing.root = RootWindow(winPtr->display, - winPtr->screenNum); + event.xcrossing.root = RootWindow(winPtr->display, winPtr->screenNum); event.xcrossing.time = TkCurrentTime(winPtr->dispPtr); XQueryPointer(winPtr->display, winPtr->window, &dummy1, &dummy2, &event.xcrossing.x_root, &event.xcrossing.y_root, @@ -1193,30 +1169,30 @@ MovePointer2(sourcePtr, destPtr, mode, leaveEvents, enterEvents) * * TkGrabDeadWindow -- * - * This procedure is invoked whenever a window is deleted, so that + * This function is invoked whenever a window is deleted, so that * grab-related cleanup can be performed. * * Results: * None. * * Side effects: - * Various cleanups happen, such as generating events to move the - * pointer back to its "natural" window as if an ungrab had been - * done. See the code. + * Various cleanups happen, such as generating events to move the pointer + * back to its "natural" window as if an ungrab had been done. See the + * code. * *---------------------------------------------------------------------- */ void -TkGrabDeadWindow(winPtr) - register TkWindow *winPtr; /* Window that is in the process - * of being deleted. */ +TkGrabDeadWindow( + register TkWindow *winPtr) /* Window that is in the process of being + * deleted. */ { TkDisplay *dispPtr = winPtr->dispPtr; if (dispPtr->eventualGrabWinPtr == winPtr) { /* - * Grab window was deleted. Release the grab. + * Grab window was deleted. Release the grab. */ Tk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr); @@ -1240,26 +1216,25 @@ TkGrabDeadWindow(winPtr) * * EatGrabEvents -- * - * This procedure is called to eliminate any Enter, Leave, - * FocusIn, or FocusOut events in the event queue for a - * display that have mode NotifyGrab or NotifyUngrab and - * have a serial number no less than a given value and are not - * generated by the grab module. + * This function is called to eliminate any Enter, Leave, FocusIn, or + * FocusOut events in the event queue for a display that have mode + * NotifyGrab or NotifyUngrab and have a serial number no less than a + * given value and are not generated by the grab module. * * Results: * None. * * Side effects: - * DispPtr's display gets sync-ed, and some of the events get - * removed from the Tk event queue. + * DispPtr's display gets sync-ed, and some of the events get removed + * from the Tk event queue. * *---------------------------------------------------------------------- */ static void -EatGrabEvents(dispPtr, serial) - TkDisplay *dispPtr; /* Display from which to consume events. */ - unsigned int serial; /* Only discard events that have a serial +EatGrabEvents( + TkDisplay *dispPtr, /* Display from which to consume events. */ + unsigned int serial) /* Only discard events that have a serial * number at least this great. */ { Tk_RestrictProc *oldProc; @@ -1280,10 +1255,10 @@ EatGrabEvents(dispPtr, serial) * * GrabRestrictProc -- * - * A Tk_RestrictProc used by EatGrabEvents to eliminate any - * Enter, Leave, FocusIn, or FocusOut events in the event queue - * for a display that has mode NotifyGrab or NotifyUngrab and - * have a serial number no less than a given value. + * A Tk_RestrictProc used by EatGrabEvents to eliminate any Enter, Leave, + * FocusIn, or FocusOut events in the event queue for a display that has + * mode NotifyGrab or NotifyUngrab and have a serial number no less than + * a given value. * * Results: * Returns either TK_DISCARD_EVENT or TK_DEFER_EVENT. @@ -1295,17 +1270,17 @@ EatGrabEvents(dispPtr, serial) */ static Tk_RestrictAction -GrabRestrictProc(arg, eventPtr) - ClientData arg; - XEvent *eventPtr; +GrabRestrictProc( + ClientData arg, + XEvent *eventPtr) { GrabInfo *info = (GrabInfo *) arg; int mode, diff; /* - * The diff caculation is trickier than it may seem. Don't forget - * that serial numbers can wrap around, so can't compare the two - * serial numbers directly. + * The diff caculation is trickier than it may seem. Don't forget that + * serial numbers can wrap around, so can't compare the two serial numbers + * directly. */ diff = eventPtr->xany.serial - info->serial; @@ -1331,29 +1306,28 @@ GrabRestrictProc(arg, eventPtr) * * QueueGrabWindowChange -- * - * This procedure queues a special event in the Tcl event queue, - * which will cause the "grabWinPtr" field for the display to get - * modified when the event is processed. This is needed to make - * sure that the grab window changes at the proper time relative - * to grab-related enter and leave events that are also in the - * queue. In particular, this approach works even when multiple - * grabs and ungrabs happen back-to-back. + * This function queues a special event in the Tcl event queue, which + * will cause the "grabWinPtr" field for the display to get modified when + * the event is processed. This is needed to make sure that the grab + * window changes at the proper time relative to grab-related enter and + * leave events that are also in the queue. In particular, this approach + * works even when multiple grabs and ungrabs happen back-to-back. * * Results: * None. * * Side effects: - * DispPtr->grabWinPtr will be modified later (by GrabWinEventProc) - * when the event is removed from the grab event queue. + * DispPtr->grabWinPtr will be modified later (by GrabWinEventProc) when + * the event is removed from the grab event queue. * *---------------------------------------------------------------------- */ static void -QueueGrabWindowChange(dispPtr, grabWinPtr) - TkDisplay *dispPtr; /* Display on which to change the grab +QueueGrabWindowChange( + TkDisplay *dispPtr, /* Display on which to change the grab * window. */ - TkWindow *grabWinPtr; /* Window that is to become the new grab + TkWindow *grabWinPtr) /* Window that is to become the new grab * window (may be NULL). */ { NewGrabWinEvent *grabEvPtr; @@ -1375,25 +1349,25 @@ QueueGrabWindowChange(dispPtr, grabWinPtr) * * GrabWinEventProc -- * - * This procedure is invoked as a handler for Tcl_Events of type - * NewGrabWinEvent. It updates the current grab window field in - * a display. + * This function is invoked as a handler for Tcl_Events of type + * NewGrabWinEvent. It updates the current grab window field in a + * display. * * Results: - * Returns 1 if the event was processed, 0 if it should be deferred - * for processing later. + * Returns 1 if the event was processed, 0 if it should be deferred for + * processing later. * * Side effects: - * The grabWinPtr field is modified in the display associated with - * the event. + * The grabWinPtr field is modified in the display associated with the + * event. * *---------------------------------------------------------------------- */ static int -GrabWinEventProc(evPtr, flags) - Tcl_Event *evPtr; /* Event of type NewGrabWinEvent. */ - int flags; /* Flags argument to Tk_DoOneEvent: indicates +GrabWinEventProc( + Tcl_Event *evPtr, /* Event of type NewGrabWinEvent. */ + int flags) /* Flags argument to Tk_DoOneEvent: indicates * what kinds of events are being processed * right now. */ { @@ -1409,19 +1383,19 @@ GrabWinEventProc(evPtr, flags) * * FindCommonAncestor -- * - * Given two windows, this procedure finds their least common - * ancestor and also computes how many levels up this ancestor - * is from each of the original windows. + * Given two windows, this function finds their least common ancestor and + * also computes how many levels up this ancestor is from each of the + * original windows. * * Results: - * If the windows are in different applications or top-level - * windows, then NULL is returned and *countPtr1 and *countPtr2 - * are set to the depths of the two windows in their respective - * top-level windows (1 means the window is a top-level, 2 means - * its parent is a top-level, and so on). Otherwise, the return - * value is a pointer to the common ancestor and the counts are - * set to the distance of winPtr1 and winPtr2 from this ancestor - * (1 means they're children, 2 means grand-children, etc.). + * If the windows are in different applications or top-level windows, + * then NULL is returned and *countPtr1 and *countPtr2 are set to the + * depths of the two windows in their respective top-level windows (1 + * means the window is a top-level, 2 means its parent is a top-level, + * and so on). Otherwise, the return value is a pointer to the common + * ancestor and the counts are set to the distance of winPtr1 and winPtr2 + * from this ancestor (1 means they're children, 2 means grand-children, + * etc.). * * Side effects: * None. @@ -1430,12 +1404,12 @@ GrabWinEventProc(evPtr, flags) */ static TkWindow * -FindCommonAncestor(winPtr1, winPtr2, countPtr1, countPtr2) - TkWindow *winPtr1; /* First window. May be NULL. */ - TkWindow *winPtr2; /* Second window. May be NULL. */ - int *countPtr1; /* Store nesting level of winPtr1 within +FindCommonAncestor( + TkWindow *winPtr1, /* First window. May be NULL. */ + TkWindow *winPtr2, /* Second window. May be NULL. */ + int *countPtr1, /* Store nesting level of winPtr1 within * common ancestor here. */ - int *countPtr2; /* Store nesting level of winPtr2 within + int *countPtr2) /* Store nesting level of winPtr2 within * common ancestor here. */ { register TkWindow *winPtr; @@ -1456,8 +1430,8 @@ FindCommonAncestor(winPtr1, winPtr2, countPtr1, countPtr2) } /* - * Search upwards from winPtr2 until an ancestor of winPtr1 is - * found or a top-level window is reached. + * Search upwards from winPtr2 until an ancestor of winPtr1 is found or a + * top-level window is reached. */ winPtr = winPtr2; @@ -1510,15 +1484,13 @@ FindCommonAncestor(winPtr1, winPtr2, countPtr1, countPtr2) * * TkPositionInTree -- * - * Compute where the given window is relative to a particular - * subtree of the window hierarchy. + * Compute where the given window is relative to a particular subtree of + * the window hierarchy. * * Results: - * - * Returns TK_GRAB_IN_TREE if the window is contained in the - * subtree. Returns TK_GRAB_ANCESTOR if the window is an - * ancestor of the subtree, in the same toplevel. Otherwise - * it returns TK_GRAB_EXCLUDED. + * Returns TK_GRAB_IN_TREE if the window is contained in the subtree. + * Returns TK_GRAB_ANCESTOR if the window is an ancestor of the subtree, + * in the same toplevel. Otherwise it returns TK_GRAB_EXCLUDED. * * Side effects: * None. @@ -1527,9 +1499,9 @@ FindCommonAncestor(winPtr1, winPtr2, countPtr1, countPtr2) */ int -TkPositionInTree(winPtr, treePtr) - TkWindow *winPtr; /* Window to be checked. */ - TkWindow *treePtr; /* Root of tree to compare against. */ +TkPositionInTree( + TkWindow *winPtr, /* Window to be checked. */ + TkWindow *treePtr) /* Root of tree to compare against. */ { TkWindow *winPtr2; @@ -1556,21 +1528,20 @@ TkPositionInTree(winPtr, treePtr) * * TkGrabState -- * - * Given a window, this procedure returns a value that indicates - * the grab state of the application relative to the window. + * Given a window, this function returns a value that indicates the grab + * state of the application relative to the window. * * Results: * The return value is one of three things: * TK_GRAB_NONE - no grab is in effect. - * TK_GRAB_IN_TREE - there is a grab in effect, and winPtr - * is in the grabbed subtree. - * TK_GRAB_ANCESTOR - there is a grab in effect; winPtr is - * an ancestor of the grabbed window, in - * the same toplevel. - * TK_GRAB_EXCLUDED - there is a grab in effect; winPtr is - * outside the tree of the grab and is not - * an ancestor of the grabbed window in the - * same toplevel. + * TK_GRAB_IN_TREE - there is a grab in effect, and winPtr is in + * the grabbed subtree. + * TK_GRAB_ANCESTOR - there is a grab in effect; winPtr is an + * ancestor of the grabbed window, in the same + * toplevel. + * TK_GRAB_EXCLUDED - there is a grab in effect; winPtr is outside + * the tree of the grab and is not an ancestor of + * the grabbed window in the same toplevel. * * Side effects: * None. @@ -1579,8 +1550,8 @@ TkPositionInTree(winPtr, treePtr) */ int -TkGrabState(winPtr) - TkWindow *winPtr; /* Window for which grab information is +TkGrabState( + TkWindow *winPtr) /* Window for which grab information is * needed. */ { TkWindow *grabWinPtr = winPtr->dispPtr->grabWinPtr; @@ -1595,3 +1566,11 @@ TkGrabState(winPtr) return TkPositionInTree(winPtr, grabWinPtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 008e321..c6a00d5 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -5,8 +5,8 @@ * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" @@ -19,26 +19,22 @@ # undef MAX #endif #define MAX(x,y) ((x) > (y) ? (x) : (y)) -#ifdef MIN -# undef MIN -#endif -#define MIN(x,y) ((x) > (y) ? (y) : (x)) -#define COLUMN (1) /* working on column offsets */ -#define ROW (2) /* working on row offsets */ +#define COLUMN (1) /* Working on column offsets. */ +#define ROW (2) /* Working on row offsets. */ -#define CHECK_ONLY (1) /* check max slot constraint */ -#define CHECK_SPACE (2) /* alloc more space, don't change max */ +#define CHECK_ONLY (1) /* Check max slot constraint. */ +#define CHECK_SPACE (2) /* Alloc more space, don't change max. */ /* - * Pre-allocate enough row and column slots for "typical" sized tables - * this value should be chosen so by the time the extra malloc's are - * required, the layout calculations overwehlm them. [A "slot" contains - * information for either a row or column, depending upon the context.] + * Pre-allocate enough row and column slots for "typical" sized tables this + * value should be chosen so by the time the extra malloc's are required, the + * layout calculations overwehlm them. [A "slot" contains information for + * either a row or column, depending upon the context.] */ -#define TYPICAL_SIZE 25 /* (arbitrary guess) */ -#define PREALLOC 10 /* extra slots to allocate */ +#define TYPICAL_SIZE 25 /* (Arbitrary guess) */ +#define PREALLOC 10 /* Extra slots to allocate. */ /* * Pre-allocate room for uniform groups during layout. @@ -46,10 +42,10 @@ #define UNIFORM_PREALLOC 10 -/* - * Data structures are allocated dynamically to support arbitrary sized tables. - * However, the space is proportional to the highest numbered slot with - * some non-default property. This limit is used to head off mistakes and +/* + * Data structures are allocated dynamically to support arbitrary sized + * tables. However, the space is proportional to the highest numbered slot + * with some non-default property. This limit is used to head off mistakes and * denial of service attacks by limiting the amount of storage required. */ @@ -64,63 +60,67 @@ #define REL_VERT '^' /* Extend widget from row above. */ /* - * Structure to hold information for grid masters. A slot is either - * a row or column. + * Default value for 'grid anchor'. + */ + +#define GRID_DEFAULT_ANCHOR TK_ANCHOR_NW + +/* + * Structure to hold information for grid masters. A slot is either a row or + * column. */ typedef struct SlotInfo { - int minSize; /* The minimum size of this slot (in pixels). + int minSize; /* The minimum size of this slot (in pixels). * It is set via the rowconfigure or * columnconfigure commands. */ - int weight; /* The resize weight of this slot. (0) means + int weight; /* The resize weight of this slot. (0) means * this slot doesn't resize. Extra space in * the layout is given distributed among slots * inproportion to their weights. */ - int pad; /* Extra padding, in pixels, required for - * this slot. This amount is "added" to the - * largest slave in the slot. */ - Tk_Uid uniform; /* Value of -uniform option. It is used to + int pad; /* Extra padding, in pixels, required for this + * slot. This amount is "added" to the largest + * slave in the slot. */ + Tk_Uid uniform; /* Value of -uniform option. It is used to * group slots that should have the same * size. */ - int offset; /* This is a cached value used for - * introspection. It is the pixel - * offset of the right or bottom edge - * of this slot from the beginning of the - * layout. */ - int temp; /* This is a temporary value used for - * calculating adjusted weights when - * shrinking the layout below its - * nominal size. */ + int offset; /* This is a cached value used for + * introspection. It is the pixel offset of + * the right or bottom edge of this slot from + * the beginning of the layout. */ + int temp; /* This is a temporary value used for + * calculating adjusted weights when shrinking + * the layout below its nominal size. */ } SlotInfo; /* - * Structure to hold information during layout calculations. There - * is one of these for each slot, an array for each of the rows or columns. + * Structure to hold information during layout calculations. There is one of + * these for each slot, an array for each of the rows or columns. */ typedef struct GridLayout { - struct Gridder *binNextPtr; /* The next slave window in this bin. - * Each bin contains a list of all - * slaves whose spans are >1 and whose - * right edges fall in this slot. */ - int minSize; /* Minimum size needed for this slot, - * in pixels. This is the space required - * to hold any slaves contained entirely - * in this slot, adjusted for any slot - * constrants, such as size or padding. */ + struct Gridder *binNextPtr; /* The next slave window in this bin. Each bin + * contains a list of all slaves whose spans + * are >1 and whose right edges fall in this + * slot. */ + int minSize; /* Minimum size needed for this slot, in + * pixels. This is the space required to hold + * any slaves contained entirely in this slot, + * adjusted for any slot constrants, such as + * size or padding. */ int pad; /* Padding needed for this slot */ int weight; /* Slot weight, controls resizing. */ - Tk_Uid uniform; /* Value of -uniform option. It is used to + Tk_Uid uniform; /* Value of -uniform option. It is used to * group slots that should have the same * size. */ - int minOffset; /* The minimum offset, in pixels, from - * the beginning of the layout to the - * right/bottom edge of the slot calculated - * from top/left to bottom/right. */ - int maxOffset; /* The maximum offset, in pixels, from - * the beginning of the layout to the - * right-or-bottom edge of the slot calculated - * from bottom-or-right to top-or-left. */ + int minOffset; /* The minimum offset, in pixels, from the + * beginning of the layout to the bottom/right + * edge of the slot calculated from top/left + * to bottom/right. */ + int maxOffset; /* The maximum offset, in pixels, from the + * beginning of the layout to the bottom/right + * edge of the slot calculated from + * bottom/right to top/left. */ } GridLayout; /* @@ -136,81 +136,84 @@ typedef struct { * column constraints. */ int rowEnd; /* The last row occupied by any slave. */ int rowMax; /* The number of rows with constraints. */ - int rowSpace; /* The number of slots currently allocated - * for row constraints. */ + int rowSpace; /* The number of slots currently allocated for + * row constraints. */ int startX; /* Pixel offset of this layout within its - * parent. */ + * master. */ int startY; /* Pixel offset of this layout within its - * parent. */ + * master. */ + Tk_Anchor anchor; /* Value of anchor option: specifies where a + * grid without weight should be placed. */ } GridMaster; /* - * For each window that the grid cares about (either because - * the window is managed by the grid or because the window - * has slaves that are managed by the grid), there is a - * structure of the following type: + * For each window that the grid cares about (either because the window is + * managed by the grid or because the window has slaves that are managed by + * the grid), there is a structure of the following type: */ typedef struct Gridder { - Tk_Window tkwin; /* Tk token for window. NULL means that - * the window has been deleted, but the - * gridder hasn't had a chance to clean up - * yet because the structure is still in - * use. */ - struct Gridder *masterPtr; /* Master window within which this window - * is managed (NULL means this window - * isn't managed by the gridder). */ - struct Gridder *nextPtr; /* Next window managed within same - * parent. List order doesn't matter. */ - struct Gridder *slavePtr; /* First in list of slaves managed - * inside this window (NULL means - * no grid slaves). */ + Tk_Window tkwin; /* Tk token for window. NULL means that the + * window has been deleted, but the gridder + * hasn't had a chance to clean up yet because + * the structure is still in use. */ + struct Gridder *masterPtr; /* Master window within which this window is + * managed (NULL means this window isn't + * managed by the gridder). */ + struct Gridder *nextPtr; /* Next window managed within same master. + * List order doesn't matter. */ + struct Gridder *slavePtr; /* First in list of slaves managed inside this + * window (NULL means no grid slaves). */ GridMaster *masterDataPtr; /* Additional data for geometry master. */ - int column, row; /* Location in the grid (starting - * from zero). */ + Tcl_Obj *in; /* Store master name when removed. */ + int column, row; /* Location in the grid (starting from + * zero). */ int numCols, numRows; /* Number of columns or rows this slave spans. * Should be at least 1. */ int padX, padY; /* Total additional pixels to leave around the - * window. Some is of this space is on each - * side. This is space *outside* the window: + * window. Some is of this space is on each + * side. This is space *outside* the window: * we'll allocate extra space in frame but * won't enlarge window). */ - int padLeft, padTop; /* The part of padX or padY to use on the - * left or top of the widget, respectively. - * By default, this is half of padX or padY. */ + int padLeft, padTop; /* The part of padX or padY to use on the left + * or top of the widget, respectively. By + * default, this is half of padX or padY. */ int iPadX, iPadY; /* Total extra pixels to allocate inside the * window (half this amount will appear on * each side). */ int sticky; /* which sides of its cavity this window * sticks to. See below for definitions */ - int doubleBw; /* Twice the window's last known border - * width. If this changes, the window - * must be re-arranged within its parent. */ - int *abortPtr; /* If non-NULL, it means that there is a nested - * call to ArrangeGrid already working on - * this window. *abortPtr may be set to 1 to - * abort that nested call. This happens, for - * example, if tkwin or any of its slaves + int doubleBw; /* Twice the window's last known border width. + * If this changes, the window must be + * re-arranged within its master. */ + int *abortPtr; /* If non-NULL, it means that there is a + * nested call to ArrangeGrid already working + * on this window. *abortPtr may be set to 1 + * to abort that nested call. This happens, + * for example, if tkwin or any of its slaves * is deleted. */ - int flags; /* Miscellaneous flags; see below - * for definitions. */ + int flags; /* Miscellaneous flags; see below for + * definitions. */ /* * These fields are used temporarily for layout calculations only. */ struct Gridder *binNextPtr; /* Link to next span>1 slave in this bin. */ - int size; /* Nominal size (width or height) in pixels - * of the slave. This includes the padding. */ + int size; /* Nominal size (width or height) in pixels of + * the slave. This includes the padding. */ } Gridder; -/* Flag values for "sticky"ness The 16 combinations subsume the packer's +/* + * Flag values for "sticky"ness. The 16 combinations subsume the packer's * notion of anchor and fill. * - * STICK_NORTH This window sticks to the top of its cavity. - * STICK_EAST This window sticks to the right edge of its cavity. - * STICK_SOUTH This window sticks to the bottom of its cavity. - * STICK_WEST This window sticks to the left edge of its cavity. + * STICK_NORTH This window sticks to the top of its cavity. + * STICK_EAST This window sticks to the right edge of its + * cavity. + * STICK_SOUTH This window sticks to the bottom of its cavity. + * STICK_WEST This window sticks to the left edge of its + * cavity. */ #define STICK_NORTH 1 @@ -231,14 +234,13 @@ typedef struct UniformGroup { /* * Flag values for Grid structures: * - * REQUESTED_RELAYOUT: 1 means a Tcl_DoWhenIdle request - * has already been made to re-arrange - * all the slaves of this window. - * - * DONT_PROPAGATE: 1 means don't set this window's requested - * size. 0 means if this window is a master - * then Tk will set its requested size to fit - * the needs of its slaves. + * REQUESTED_RELAYOUT 1 means a Tcl_DoWhenIdle request has already + * been made to re-arrange all the slaves of this + * window. + * DONT_PROPAGATE 1 means don't set this window's requested + * size. 0 means if this window is a master then + * Tk will set its requested size to fit the + * needs of its slaves. */ #define REQUESTED_RELAYOUT 1 @@ -248,66 +250,71 @@ typedef struct UniformGroup { * Prototypes for procedures used only in this file: */ -static void AdjustForSticky _ANSI_ARGS_((Gridder *slavePtr, int *xPtr, - int *yPtr, int *widthPtr, int *heightPtr)); -static int AdjustOffsets _ANSI_ARGS_((int width, - int elements, SlotInfo *slotPtr)); -static void ArrangeGrid _ANSI_ARGS_((ClientData clientData)); -static int CheckSlotData _ANSI_ARGS_((Gridder *masterPtr, int slot, - int slotType, int checkOnly)); -static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, int objc, Tcl_Obj *CONST objv[])); -static void DestroyGrid _ANSI_ARGS_((char *memPtr)); -static Gridder *GetGrid _ANSI_ARGS_((Tk_Window tkwin)); -static int GridBboxCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridForgetRemoveCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridInfoCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridLocationCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridPropagateCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridRowColumnConfigureCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridSizeCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridSlavesCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static void GridStructureProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -static void GridLostSlaveProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void GridReqProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void InitMasterData _ANSI_ARGS_((Gridder *masterPtr)); -static Tcl_Obj *NewPairObj _ANSI_ARGS_((Tcl_Interp*, int, int)); -static Tcl_Obj *NewQuadObj _ANSI_ARGS_((Tcl_Interp*, int, int, int, int)); -static int ResolveConstraints _ANSI_ARGS_((Gridder *gridPtr, - int rowOrColumn, int maxOffset)); -static void SetGridSize _ANSI_ARGS_((Gridder *gridPtr)); -static int SetSlaveColumn _ANSI_ARGS_((Tcl_Interp *interp, - Gridder *slavePtr, int column, int numCols)); -static int SetSlaveRow _ANSI_ARGS_((Tcl_Interp *interp, - Gridder *slavePtr, int row, int numRows)); -static void StickyToString _ANSI_ARGS_((int flags, char *result)); -static int StringToSticky _ANSI_ARGS_((char *string)); -static void Unlink _ANSI_ARGS_((Gridder *gridPtr)); - -static Tk_GeomMgr gridMgrType = { +static void AdjustForSticky(Gridder *slavePtr, int *xPtr, + int *yPtr, int *widthPtr, int *heightPtr); +static int AdjustOffsets(int width, int elements, + SlotInfo *slotPtr); +static void ArrangeGrid(ClientData clientData); +static int CheckSlotData(Gridder *masterPtr, int slot, + int slotType, int checkOnly); +static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, + int objc, Tcl_Obj *CONST objv[]); +static void DestroyGrid(char *memPtr); +static Gridder * GetGrid(Tk_Window tkwin); +static int GridAnchorCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridBboxCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridForgetRemoveCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridInfoCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridLocationCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridPropagateCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridRowColumnConfigureCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridSizeCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridSlavesCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static void GridStructureProc(ClientData clientData, + XEvent *eventPtr); +static void GridLostSlaveProc(ClientData clientData, + Tk_Window tkwin); +static void GridReqProc(ClientData clientData, Tk_Window tkwin); +static void InitMasterData(Gridder *masterPtr); +static Tcl_Obj * NewPairObj(int, int); +static Tcl_Obj * NewQuadObj(int, int, int, int); +static int ResolveConstraints(Gridder *gridPtr, int rowOrColumn, + int maxOffset); +static void SetGridSize(Gridder *gridPtr); +static int SetSlaveColumn(Tcl_Interp *interp, Gridder *slavePtr, + int column, int numCols); +static int SetSlaveRow(Tcl_Interp *interp, Gridder *slavePtr, + int row, int numRows); +static void StickyToString(int flags, char *result); +static int StringToSticky(char *string); +static void Unlink(Gridder *gridPtr); + +static const Tk_GeomMgr gridMgrType = { "grid", /* name */ GridReqProc, /* requestProc */ GridLostSlaveProc, /* lostSlaveProc */ }; /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * Tk_GridCmd -- * - * This procedure is invoked to process the "grid" Tcl command. - * See the user documentation for details on what it does. + * This procedure is invoked to process the "grid" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -315,31 +322,32 @@ static Tk_GeomMgr gridMgrType = { * Side effects: * See the user documentation. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ int -Tk_GridObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_GridObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; static CONST char *optionStrings[] = { - "bbox", "columnconfigure", "configure", "forget", - "info", "location", "propagate", "remove", - "rowconfigure", "size", "slaves", (char *) NULL }; + "anchor", "bbox", "columnconfigure", "configure", + "forget", "info", "location", "propagate", "remove", + "rowconfigure", "size", "slaves", NULL + }; enum options { - GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE, GRID_FORGET, - GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE, - GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES }; + GRID_ANCHOR, GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE, + GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE, + GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES + }; int index; - - + if (objc >= 2) { char *argv1 = Tcl_GetString(objv[1]); + if ((argv1[0] == '.') || (argv1[0] == REL_SKIP) || (argv1[0] == REL_VERT)) { return ConfigureSlaves(interp, tkwin, objc-1, objv+1); @@ -356,22 +364,24 @@ Tk_GridObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case GRID_BBOX: + case GRID_ANCHOR: + return GridAnchorCommand(tkwin, interp, objc, objv); + case GRID_BBOX: return GridBboxCommand(tkwin, interp, objc, objv); - case GRID_CONFIGURE: + case GRID_CONFIGURE: return ConfigureSlaves(interp, tkwin, objc-2, objv+2); - case GRID_FORGET: - case GRID_REMOVE: + case GRID_FORGET: + case GRID_REMOVE: return GridForgetRemoveCommand(tkwin, interp, objc, objv); - case GRID_INFO: + case GRID_INFO: return GridInfoCommand(tkwin, interp, objc, objv); - case GRID_LOCATION: + case GRID_LOCATION: return GridLocationCommand(tkwin, interp, objc, objv); - case GRID_PROPAGATE: + case GRID_PROPAGATE: return GridPropagateCommand(tkwin, interp, objc, objv); - case GRID_SIZE: + case GRID_SIZE: return GridSizeCommand(tkwin, interp, objc, objv); - case GRID_SLAVES: + case GRID_SLAVES: return GridSlavesCommand(tkwin, interp, objc, objv); /* @@ -383,8 +393,8 @@ Tk_GridObjCmd(clientData, interp, objc, objv) * grid rowconfigure <master> <index> -option value -option value. */ - case GRID_COLUMNCONFIGURE: - case GRID_ROWCONFIGURE: + case GRID_COLUMNCONFIGURE: + case GRID_ROWCONFIGURE: return GridRowColumnConfigureCommand(tkwin, interp, objc, objv); } @@ -396,6 +406,75 @@ Tk_GridObjCmd(clientData, interp, objc, objv) /* *---------------------------------------------------------------------- * + * GridAnchorCommand -- + * + * Implementation of the [grid anchor] subcommand. See the user + * documentation for details on what it does. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * May recompute grid geometry. + * + *---------------------------------------------------------------------- + */ + +static int +GridAnchorCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + Tk_Window master; + Gridder *masterPtr; + GridMaster *gridPtr; + Tk_Anchor old; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?anchor?"); + return TCL_ERROR; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(master); + + if (objc == 3) { + gridPtr = masterPtr->masterDataPtr; + Tcl_SetResult(interp, (char *) Tk_NameOfAnchor(gridPtr == NULL ? + GRID_DEFAULT_ANCHOR : gridPtr->anchor), TCL_VOLATILE); + return TCL_OK; + } + + InitMasterData(masterPtr); + gridPtr = masterPtr->masterDataPtr; + old = gridPtr->anchor; + if (Tk_GetAnchorFromObj(interp, objv[3], &gridPtr->anchor) != TCL_OK) { + return TCL_ERROR; + } + + /* + * Only request a relayout if the anchor changes. + */ + + if (old != gridPtr->anchor) { + if (masterPtr->abortPtr != NULL) { + *masterPtr->abortPtr = 1; + } + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * GridBboxCommand -- * * Implementation of the [grid bbox] subcommand. @@ -410,11 +489,11 @@ Tk_GridObjCmd(clientData, interp, objc, objv) */ static int -GridBboxCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridBboxCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; /* master grid record */ @@ -424,17 +503,17 @@ GridBboxCommand(tkwin, interp, objc, objv) int endX, endY; /* last column/row in the layout */ int x=0, y=0; /* starting pixels for this bounding box */ int width, height; /* size of the bounding box */ - + if (objc!=3 && objc != 5 && objc != 7) { Tcl_WrongNumArgs(interp, 2, objv, "master ?column row ?column row??"); return TCL_ERROR; } - + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { return TCL_ERROR; } masterPtr = GetGrid(master); - + if (objc >= 5) { if (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) { return TCL_ERROR; @@ -445,7 +524,7 @@ GridBboxCommand(tkwin, interp, objc, objv) column2 = column; row2 = row; } - + if (objc == 7) { if (Tcl_GetIntFromObj(interp, objv[5], &column2) != TCL_OK) { return TCL_ERROR; @@ -454,65 +533,70 @@ GridBboxCommand(tkwin, interp, objc, objv) return TCL_ERROR; } } - + gridPtr = masterPtr->masterDataPtr; if (gridPtr == NULL) { - Tcl_SetObjResult(interp, NewQuadObj(interp, 0, 0, 0, 0)); + Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0)); return TCL_OK; } - + SetGridSize(masterPtr); endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); - + if ((endX == 0) || (endY == 0)) { - Tcl_SetObjResult(interp, NewQuadObj(interp, 0, 0, 0, 0)); + Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0)); return TCL_OK; } if (objc == 3) { - row = column = 0; + row = 0; + column = 0; row2 = endY; column2 = endX; } - + if (column > column2) { int temp = column; - column = column2, column2 = temp; + + column = column2; + column2 = temp; } if (row > row2) { int temp = row; - row = row2, row2 = temp; + + row = row2; + row2 = temp; } - + if (column > 0 && column < endX) { x = gridPtr->columnPtr[column-1].offset; - } else if (column > 0) { + } else if (column > 0) { x = gridPtr->columnPtr[endX-1].offset; } - + if (row > 0 && row < endY) { y = gridPtr->rowPtr[row-1].offset; } else if (row > 0) { y = gridPtr->rowPtr[endY-1].offset; } - + if (column2 < 0) { width = 0; } else if (column2 >= endX) { width = gridPtr->columnPtr[endX-1].offset - x; } else { width = gridPtr->columnPtr[column2].offset - x; - } - + } + if (row2 < 0) { height = 0; } else if (row2 >= endY) { height = gridPtr->rowPtr[endY-1].offset - y; } else { height = gridPtr->rowPtr[row2].offset - y; - } - - Tcl_SetObjResult(interp, NewQuadObj(interp, + } + + Tcl_SetObjResult(interp, NewQuadObj( x + gridPtr->startX, y + gridPtr->startY, width, height)); return TCL_OK; } @@ -522,8 +606,8 @@ GridBboxCommand(tkwin, interp, objc, objv) * * GridForgetRemoveCommand -- * - * Implementation of the [grid forget]/[grid remove] subcommands. - * See the user documentation for details on what these do. + * Implementation of the [grid forget]/[grid remove] subcommands. See the + * user documentation for details on what these do. * * Results: * Standard Tcl result. @@ -535,18 +619,18 @@ GridBboxCommand(tkwin, interp, objc, objv) */ static int -GridForgetRemoveCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridForgetRemoveCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window slave; Gridder *slavePtr; int i; char *string = Tcl_GetString(objv[1]); char c = string[0]; - + for (i = 2; i < objc; i++) { if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) { return TCL_ERROR; @@ -554,27 +638,48 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv) slavePtr = GetGrid(slave); if (slavePtr->masterPtr != NULL) { - /* * For "forget", reset all the settings to their defaults */ - + if (c == 'f') { - slavePtr->column = slavePtr->row = -1; + slavePtr->column = -1; + slavePtr->row = -1; slavePtr->numCols = 1; slavePtr->numRows = 1; - slavePtr->padX = slavePtr->padY = 0; - slavePtr->padLeft = slavePtr->padTop = 0; - slavePtr->iPadX = slavePtr->iPadY = 0; + slavePtr->padX = 0; + slavePtr->padY = 0; + slavePtr->padLeft = 0; + slavePtr->padTop = 0; + slavePtr->iPadX = 0; + slavePtr->iPadY = 0; + if (slavePtr->in != NULL) { + Tcl_DecrRefCount(slavePtr->in); + slavePtr->in = NULL; + } slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; if (slavePtr->flags & REQUESTED_RELAYOUT) { Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr); } slavePtr->flags = 0; slavePtr->sticky = 0; + } else { + /* + * When removing, store name of master to be able to + * restore it later, even if the master is recreated. + */ + + if (slavePtr->in != NULL) { + Tcl_DecrRefCount(slavePtr->in); + slavePtr->in = NULL; + } + if (slavePtr->masterPtr != NULL) { + slavePtr->in = Tcl_NewStringObj( + Tk_PathName(slavePtr->masterPtr->tkwin), -1); + Tcl_IncrRefCount(slavePtr->in); + } } - Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, - (ClientData) NULL); + Tk_ManageGeometry(slave, NULL, (ClientData) NULL); if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); @@ -591,7 +696,7 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv) * * GridInfoCommand -- * - * Implementation of the [grid info] subcommand. See the user + * Implementation of the [grid info] subcommand. See the user * documentation for details on what it does. * * Results: @@ -604,16 +709,16 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv) */ static int -GridInfoCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridInfoCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register Gridder *slavePtr; Tk_Window slave; char buffer[64 + TCL_INTEGER_SPACE * 4]; - + if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; @@ -626,19 +731,19 @@ GridInfoCommand(tkwin, interp, objc, objv) Tcl_ResetResult(interp); return TCL_OK; } - + Tcl_AppendElement(interp, "-in"); Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin)); sprintf(buffer, " -column %d -row %d -columnspan %d -rowspan %d", slavePtr->column, slavePtr->row, slavePtr->numCols, slavePtr->numRows); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); TkPrintPadAmount(interp, "ipadx", slavePtr->iPadX/2, slavePtr->iPadX); TkPrintPadAmount(interp, "ipady", slavePtr->iPadY/2, slavePtr->iPadY); TkPrintPadAmount(interp, "padx", slavePtr->padLeft, slavePtr->padX); TkPrintPadAmount(interp, "pady", slavePtr->padTop, slavePtr->padY); StickyToString(slavePtr->sticky, buffer); - Tcl_AppendResult(interp, " -sticky ", buffer, (char *) NULL); + Tcl_AppendResult(interp, " -sticky ", buffer, NULL); return TCL_OK; } @@ -647,7 +752,7 @@ GridInfoCommand(tkwin, interp, objc, objv) * * GridLocationCommand -- * - * Implementation of the [grid location] subcommand. See the user + * Implementation of the [grid location] subcommand. See the user * documentation for details on what it does. * * Results: @@ -660,58 +765,58 @@ GridInfoCommand(tkwin, interp, objc, objv) */ static int -GridLocationCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridLocationCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; - Gridder *masterPtr; /* master grid record */ - GridMaster *gridPtr; /* pointer to grid data */ + Gridder *masterPtr; /* Master grid record. */ + GridMaster *gridPtr; /* Pointer to grid data. */ register SlotInfo *slotPtr; - int x, y; /* Offset in pixels, from edge of parent. */ - int i, j; /* Corresponding column and row indeces. */ - int endX, endY; /* end of grid */ - + int x, y; /* Offset in pixels, from edge of master. */ + int i, j; /* Corresponding column and row indeces. */ + int endX, endY; /* End of grid. */ + if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "master x y"); return TCL_ERROR; } - + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { return TCL_ERROR; } - + if (Tk_GetPixelsFromObj(interp, master, objv[3], &x) != TCL_OK) { return TCL_ERROR; } if (Tk_GetPixelsFromObj(interp, master, objv[4], &y) != TCL_OK) { return TCL_ERROR; } - + masterPtr = GetGrid(master); if (masterPtr->masterDataPtr == NULL) { - Tcl_SetObjResult(interp, NewPairObj(interp, -1, -1)); + Tcl_SetObjResult(interp, NewPairObj(-1, -1)); return TCL_OK; } gridPtr = masterPtr->masterDataPtr; - - /* - * Update any pending requests. This is not always the - * steady state value, as more configure events could be in - * the pipeline, but its as close as its easy to get. + + /* + * Update any pending requests. This is not always the steady state value, + * as more configure events could be in the pipeline, but its as close as + * its easy to get. */ - + while (masterPtr->flags & REQUESTED_RELAYOUT) { Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr); - ArrangeGrid ((ClientData) masterPtr); + ArrangeGrid((ClientData) masterPtr); } SetGridSize(masterPtr); endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); - - slotPtr = masterPtr->masterDataPtr->columnPtr; + + slotPtr = masterPtr->masterDataPtr->columnPtr; if (x < masterPtr->masterDataPtr->startX) { i = -1; } else { @@ -720,8 +825,8 @@ GridLocationCommand(tkwin, interp, objc, objv) /* null body */ } } - - slotPtr = masterPtr->masterDataPtr->rowPtr; + + slotPtr = masterPtr->masterDataPtr->rowPtr; if (y < masterPtr->masterDataPtr->startY) { j = -1; } else { @@ -730,8 +835,8 @@ GridLocationCommand(tkwin, interp, objc, objv) /* null body */ } } - - Tcl_SetObjResult(interp, NewPairObj(interp, i, j)); + + Tcl_SetObjResult(interp, NewPairObj(i, j)); return TCL_OK; } @@ -740,7 +845,7 @@ GridLocationCommand(tkwin, interp, objc, objv) * * GridPropagateCommand -- * - * Implementation of the [grid propagate] subcommand. See the user + * Implementation of the [grid propagate] subcommand. See the user * documentation for details on what it does. * * Results: @@ -753,16 +858,16 @@ GridLocationCommand(tkwin, interp, objc, objv) */ static int -GridPropagateCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridPropagateCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; int propagate, old; - + if (objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); return TCL_ERROR; @@ -780,9 +885,11 @@ GridPropagateCommand(tkwin, interp, objc, objv) if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) { return TCL_ERROR; } - - /* Only request a relayout if the propagation bit changes */ - + + /* + * Only request a relayout if the propagation bit changes. + */ + old = !(masterPtr->flags & DONT_PROPAGATE); if (propagate != old) { if (propagate) { @@ -790,12 +897,12 @@ GridPropagateCommand(tkwin, interp, objc, objv) } else { masterPtr->flags |= DONT_PROPAGATE; } - + /* * Re-arrange the master to allow new geometry information to * propagate upwards to the master's master. */ - + if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } @@ -813,8 +920,7 @@ GridPropagateCommand(tkwin, interp, objc, objv) * GridRowColumnConfigureCommand -- * * Implementation of the [grid rowconfigure] and [grid columnconfigure] - * subcommands. See the user documentation for details on what these - * do. + * subcommands. See the user documentation for details on what these do. * * Results: * Standard Tcl result. @@ -826,27 +932,29 @@ GridPropagateCommand(tkwin, interp, objc, objv) */ static int -GridRowColumnConfigureCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridRowColumnConfigureCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - Tk_Window master; - Gridder *masterPtr; + Tk_Window master, slave; + Gridder *masterPtr, *slavePtr; SlotInfo *slotPtr = NULL; int slot; /* the column or row number */ int slotType; /* COLUMN or ROW */ int size; /* the configuration value */ - int checkOnly; /* check the size only */ int lObjc; /* Number of items in index list */ Tcl_Obj **lObjv; /* array of indices */ int ok; /* temporary TCL result code */ - int i, j; + int i, j, first, last; char *string; static CONST char *optionStrings[] = { - "-minsize", "-pad", "-uniform", "-weight", (char *) NULL }; - enum options { ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT }; + "-minsize", "-pad", "-uniform", "-weight", NULL + }; + enum options { + ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT + }; int index; Tcl_Obj *listCopy; @@ -871,41 +979,40 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) if (lObjc == 0) { Tcl_AppendResult(interp, "no ", (slotType == COLUMN) ? "column" : "row", - " indices specified", (char *) NULL); + " indices specified", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; } - checkOnly = ((objc == 4) || (objc == 5)); masterPtr = GetGrid(master); - if (checkOnly && (lObjc > 1)) { - Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", - Tcl_GetString(objv[1]), - ": must specify a single element on retrieval", (char *) NULL); - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } - for (j = 0; j < lObjc; j++) { - if (Tcl_GetIntFromObj(interp, lObjv[j], &slot) != TCL_OK) { + first = 0; /* lint */ + last = 0; /* lint */ + + if ((objc == 4) || (objc == 5)) { + if (lObjc != 1) { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), + ": must specify a single element on retrieval", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; } - ok = CheckSlotData(masterPtr, slot, slotType, checkOnly); - if ((ok != TCL_OK) && ((objc < 4) || (objc > 5))) { - Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", - Tcl_GetString(objv[1]), ": \"", Tcl_GetString(lObjv[j]), - "\" is out of range", (char *) NULL); + if (Tcl_GetIntFromObj(interp, lObjv[0], &slot) != TCL_OK) { + Tcl_AppendResult(interp, + " (when retreiving options only integer indices are " + "allowed)", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; - } else if (ok == TCL_OK) { + } + ok = CheckSlotData(masterPtr, slot, slotType, /* checkOnly */ 1); + if (ok == TCL_OK) { slotPtr = (slotType == COLUMN) ? masterPtr->masterDataPtr->columnPtr : masterPtr->masterDataPtr->rowPtr; } /* - * Return all of the options for this row or column. If the - * request is out of range, return all 0's. + * Return all of the options for this row or column. If the request is + * out of range, return all 0's. */ if (objc == 4) { @@ -939,116 +1046,200 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) } /* - * Loop through each option value pair, setting the values as - * required. If only one option is given, with no value, the - * current value is returned. + * If only one option is given, with no value, the current value is + * returned. */ - for (i = 4; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", - 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[4], optionStrings, "option", 0, + &index) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } + if (index == ROWCOL_MINSIZE) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].minSize : 0)); + } else if (index == ROWCOL_WEIGHT) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].weight : 0)); + } else if (index == ROWCOL_UNIFORM) { + Tk_Uid value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; + + Tcl_SetObjResult(interp, + Tcl_NewStringObj(value == NULL ? "" : value, -1)); + } else if (index == ROWCOL_PAD) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].pad : 0)); + } + Tcl_DecrRefCount(listCopy); + return TCL_OK; + } + + for (j = 0; j < lObjc; j++) { + int allSlaves = 0; + + if (Tcl_GetIntFromObj(NULL, lObjv[j], &slot) == TCL_OK) { + first = slot; + last = slot; + slavePtr = NULL; + } else if (strcmp(Tcl_GetString(lObjv[j]), "all") == 0) { + /* + * Make sure master is initialised. + */ + + InitMasterData(masterPtr); + + slavePtr = masterPtr->slavePtr; + if (slavePtr == NULL) { + continue; + } + allSlaves = 1; + } else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &slave) + == TCL_OK) { + /* + * Is it gridded in this master? + */ + + slavePtr = GetGrid(slave); + if (slavePtr->masterPtr != masterPtr) { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": the window \"", + Tcl_GetString(lObjv[j]), "\" is not managed by \"", + Tcl_GetString(objv[2]), "\"", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; } - if (index == ROWCOL_MINSIZE) { - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].minSize : 0)); - } else if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) - != TCL_OK) { - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else { - slotPtr[slot].minSize = size; - } - } else if (index == ROWCOL_WEIGHT) { - int wt; - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].weight : 0)); - } else if (Tcl_GetIntFromObj(interp, objv[i+1], &wt) - != TCL_OK) { - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else if (wt < 0) { - Tcl_AppendResult(interp, "invalid arg \"", - Tcl_GetString(objv[i]), - "\": should be non-negative", (char *) NULL); - Tcl_DecrRefCount(listCopy); + } else { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": illegal index \"", + Tcl_GetString(lObjv[j]), "\"", NULL); + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } + + /* + * The outer loop is only to handle "all". + */ + + do { + if (slavePtr != NULL) { + first = (slotType == COLUMN) ? + slavePtr->column : slavePtr->row; + last = first - 1 + ((slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows); + } + + for (slot = first; slot <= last; slot++) { + ok = CheckSlotData(masterPtr, slot, slotType, /*checkOnly*/ 0); + if (ok != TCL_OK) { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": \"", + Tcl_GetString(lObjv[j]), + "\" is out of range", NULL); + Tcl_DecrRefCount(listCopy); return TCL_ERROR; - } else { - slotPtr[slot].weight = wt; } - } else if (index == ROWCOL_UNIFORM) { - if (objc == 5) { - Tk_Uid value; - value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; - if (value == NULL) { - value = ""; + slotPtr = (slotType == COLUMN) ? + masterPtr->masterDataPtr->columnPtr : + masterPtr->masterDataPtr->rowPtr; + + /* + * Loop through each option value pair, setting the values as + * required. + */ + + for (i = 4; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, + "option", 0, &index) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewStringObj(value, -1)); - } else { - slotPtr[slot].uniform = Tk_GetUid(Tcl_GetString(objv[i+1])); - if (slotPtr[slot].uniform != NULL && - slotPtr[slot].uniform[0] == 0) { - slotPtr[slot].uniform = NULL; + if (index == ROWCOL_MINSIZE) { + if (Tk_GetPixelsFromObj(interp, master, objv[i+1], + &size) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else { + slotPtr[slot].minSize = size; + } + } else if (index == ROWCOL_WEIGHT) { + int wt; + + if (Tcl_GetIntFromObj(interp,objv[i+1],&wt)!=TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else if (wt < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", NULL); + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else { + slotPtr[slot].weight = wt; + } + } else if (index == ROWCOL_UNIFORM) { + slotPtr[slot].uniform = + Tk_GetUid(Tcl_GetString(objv[i+1])); + if (slotPtr[slot].uniform != NULL && + slotPtr[slot].uniform[0] == 0) { + slotPtr[slot].uniform = NULL; + } + } else if (index == ROWCOL_PAD) { + if (Tk_GetPixelsFromObj(interp, master, objv[i+1], + &size) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else if (size < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", NULL); + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else { + slotPtr[slot].pad = size; + } } } - } else if (index == ROWCOL_PAD) { - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].pad : 0)); - } else if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) - != TCL_OK) { - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else if (size < 0) { - Tcl_AppendResult(interp, "invalid arg \"", - Tcl_GetString(objv[i]), - "\": should be non-negative", (char *) NULL); - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else { - slotPtr[slot].pad = size; - } } - } + if (slavePtr != NULL) { + slavePtr = slavePtr->nextPtr; + } + } while ((allSlaves == 1) && (slavePtr != NULL)); } Tcl_DecrRefCount(listCopy); /* - * If we changed a property, re-arrange the table, - * and check for constraint shrinkage. + * We changed a property, re-arrange the table, and check for constraint + * shrinkage. A null slotPtr will occur for 'all' checks. */ - if (objc != 5) { + if (slotPtr != NULL) { if (slotType == ROW) { int last = masterPtr->masterDataPtr->rowMax - 1; + while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0) + && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0) && (slotPtr[last].uniform == NULL)) { last--; } masterPtr->masterDataPtr->rowMax = last+1; } else { int last = masterPtr->masterDataPtr->columnMax - 1; + while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0) + && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0) && (slotPtr[last].uniform == NULL)) { last--; } masterPtr->masterDataPtr->columnMax = last + 1; } + } - if (masterPtr->abortPtr != NULL) { - *masterPtr->abortPtr = 1; - } - if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { - masterPtr->flags |= REQUESTED_RELAYOUT; - Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); - } + if (masterPtr->abortPtr != NULL) { + *masterPtr->abortPtr = 1; + } + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); } return TCL_OK; } @@ -1058,7 +1249,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) * * GridSizeCommand -- * - * Implementation of the [grid size] subcommand. See the user + * Implementation of the [grid size] subcommand. See the user * documentation for details on what it does. * * Results: @@ -1071,16 +1262,16 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) */ static int -GridSizeCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridSizeCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; GridMaster *gridPtr; /* pointer to grid data */ - + if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; @@ -1090,15 +1281,15 @@ GridSizeCommand(tkwin, interp, objc, objv) return TCL_ERROR; } masterPtr = GetGrid(master); - + if (masterPtr->masterDataPtr != NULL) { SetGridSize(masterPtr); gridPtr = masterPtr->masterDataPtr; - Tcl_SetObjResult(interp, NewPairObj(interp, + Tcl_SetObjResult(interp, NewPairObj( MAX(gridPtr->columnEnd, gridPtr->columnMax), MAX(gridPtr->rowEnd, gridPtr->rowMax))); } else { - Tcl_SetObjResult(interp, NewPairObj(interp, 0, 0)); + Tcl_SetObjResult(interp, NewPairObj(0, 0)); } return TCL_OK; } @@ -1108,42 +1299,42 @@ GridSizeCommand(tkwin, interp, objc, objv) * * GridSlavesCommand -- * - * Implementation of the [grid slaves] subcommand. See the user + * Implementation of the [grid slaves] subcommand. See the user * documentation for details on what it does. * * Results: * Standard Tcl result. * * Side effects: - * Places a list of slaves of the specified window in the - * interpreter's result field. + * Places a list of slaves of the specified window in the interpreter's + * result field. * *---------------------------------------------------------------------- */ static int -GridSlavesCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridSlavesCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; /* master grid record */ Gridder *slavePtr; - int i, value; + int i, value, index; int row = -1, column = -1; static CONST char *optionStrings[] = { - "-column", "-row", (char *) NULL }; + "-column", "-row", NULL + }; enum options { SLAVES_COLUMN, SLAVES_ROW }; - int index; Tcl_Obj *res; - + if ((objc < 3) || ((objc % 2) == 0)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value...?"); return TCL_ERROR; } - + for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, &index) != TCL_OK) { @@ -1154,8 +1345,7 @@ GridSlavesCommand(tkwin, interp, objc, objv) } if (value < 0) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), - " is an invalid value: should NOT be < 0", - (char *) NULL); + " is an invalid value: should NOT be < 0", NULL); return TCL_ERROR; } if (index == SLAVES_COLUMN) { @@ -1172,7 +1362,7 @@ GridSlavesCommand(tkwin, interp, objc, objv) res = Tcl_NewListObj(0, NULL); for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { + slavePtr = slavePtr->nextPtr) { if (column>=0 && (slavePtr->column > column || slavePtr->column+slavePtr->numCols-1 < column)) { continue; @@ -1189,30 +1379,29 @@ GridSlavesCommand(tkwin, interp, objc, objv) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * GridReqProc -- * - * This procedure is invoked by Tk_GeometryRequest for - * windows managed by the grid. + * This procedure is invoked by Tk_GeometryRequest for windows managed by + * the grid. * * Results: * None. * * Side effects: - * Arranges for tkwin, and all its managed siblings, to - * be re-arranged at the next idle point. + * Arranges for tkwin, and all its managed siblings, to be re-arranged at + * the next idle point. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -GridReqProc(clientData, tkwin) - ClientData clientData; /* Grid's information about - * window that got new preferred - * geometry. */ - Tk_Window tkwin; /* Other Tk-related information - * about the window. */ +GridReqProc( + ClientData clientData, /* Grid's information about window that got + * new preferred geometry. */ + Tk_Window tkwin) /* Other Tk-related information about the + * window. */ { register Gridder *gridPtr = (Gridder *) clientData; @@ -1224,12 +1413,12 @@ GridReqProc(clientData, tkwin) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * GridLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This procedure is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. @@ -1237,14 +1426,14 @@ GridReqProc(clientData, tkwin) * Side effects: * Forgets all grid-related information about the slave. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -GridLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Grid structure for slave window that - * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ +GridLostSlaveProc( + ClientData clientData, /* Grid structure for slave window that was + * stolen away. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { register Gridder *slavePtr = (Gridder *) clientData; @@ -1256,39 +1445,38 @@ GridLostSlaveProc(clientData, tkwin) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * AdjustOffsets -- * - * This procedure adjusts the size of the layout to fit in the - * space provided. If it needs more space, the extra is added - * according to the weights. If it needs less, the space is removed - * according to the weights, but at no time does the size drop below - * the minsize specified for that slot. + * This procedure adjusts the size of the layout to fit in the space + * provided. If it needs more space, the extra is added according to the + * weights. If it needs less, the space is removed according to the + * weights, but at no time does the size drop below the minsize specified + * for that slot. * * Results: - * The initial offset of the layout, - * if all the weights are zero, else 0. + * The size used by the layout. * * Side effects: * The slot offsets are modified to shrink the layout. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -AdjustOffsets(size, slots, slotPtr) - int size; /* The total layout size (in pixels). */ - int slots; /* Number of slots. */ - register SlotInfo *slotPtr; /* Pointer to slot array. */ +AdjustOffsets( + int size, /* The total layout size (in pixels). */ + int slots, /* Number of slots. */ + register SlotInfo *slotPtr) /* Pointer to slot array. */ { register int slot; /* Current slot. */ int diff; /* Extra pixels needed to add to the layout. */ - int totalWeight = 0; /* Sum of the weights for all the slots. */ - int weight = 0; /* Sum of the weights so far. */ + int totalWeight; /* Sum of the weights for all the slots. */ + int weight; /* Sum of the weights so far. */ int minSize; /* Minimum possible layout size. */ - int newDiff; /* The most pixels that can be added on - * the current pass. */ + int newDiff; /* The most pixels that can be added on the + * current pass. */ diff = size - slotPtr[slots-1].offset; @@ -1297,24 +1485,24 @@ AdjustOffsets(size, slots, slotPtr) */ if (diff == 0) { - return(0); + return size; } /* - * If all the weights are zero, center the layout in its parent if - * there is extra space, else clip on the bottom/right. + * If all the weights are zero, there is nothing more to do. */ + totalWeight = 0; for (slot = 0; slot < slots; slot++) { totalWeight += slotPtr[slot].weight; } - if (totalWeight == 0 ) { - return(diff > 0 ? diff/2 : 0); + if (totalWeight == 0) { + return slotPtr[slots-1].offset; } /* - * Add extra space according to the slot weights. This is done + * Add extra space according to the slot weights. This is done * cumulatively to prevent round-off error accumulation. */ @@ -1324,13 +1512,13 @@ AdjustOffsets(size, slots, slotPtr) weight += slotPtr[slot].weight; slotPtr[slot].offset += diff * weight / totalWeight; } - return(0); + return size; } /* - * The layout must shrink below its requested size. Compute the - * minimum possible size by looking at the slot minSizes. - * Store each slot's minimum size in temp. + * The layout must shrink below its requested size. Compute the minimum + * possible size by looking at the slot minSizes. Store each slot's + * minimum size in temp. */ minSize = 0; @@ -1346,34 +1534,35 @@ AdjustOffsets(size, slots, slotPtr) } /* - * If the requested size is less than the minimum required size, - * set the slot sizes to their minimum values, then clip on the - * bottom/right. + * If the requested size is less than the minimum required size, set the + * slot sizes to their minimum values. */ if (size <= minSize) { int offset = 0; + for (slot = 0; slot < slots; slot++) { offset += slotPtr[slot].temp; slotPtr[slot].offset = offset; } - return(0); + return minSize; } /* - * Remove space from slots according to their weights. The weights - * get renormalized anytime a slot shrinks to its minimum size. + * Remove space from slots according to their weights. The weights get + * renormalized anytime a slot shrinks to its minimum size. */ while (diff < 0) { - /* * Find the total weight for the shrinkable slots. */ - for (totalWeight=slot=0; slot < slots; slot++) { + totalWeight = 0; + for (slot = 0; slot < slots; slot++) { int current = (slot == 0) ? slotPtr[slot].offset : slotPtr[slot].offset - slotPtr[slot-1].offset; + if (current > slotPtr[slot].minSize) { totalWeight += slotPtr[slot].weight; slotPtr[slot].temp = slotPtr[slot].weight; @@ -1391,9 +1580,10 @@ AdjustOffsets(size, slots, slotPtr) newDiff = diff; for (slot = 0; slot < slots; slot++) { - int current; /* current size of this slot */ - int maxDiff; /* max diff that would cause - * this slot to equal its minsize */ + int current; /* Current size of this slot. */ + int maxDiff; /* Maximum diff that would cause this slot to + * equal its minsize. */ + if (slotPtr[slot].temp == 0) { continue; } @@ -1410,43 +1600,44 @@ AdjustOffsets(size, slots, slotPtr) * Now distribute the space. */ - for (weight=slot=0; slot < slots; slot++) { + weight = 0; + for (slot = 0; slot < slots; slot++) { weight += slotPtr[slot].temp; slotPtr[slot].offset += newDiff * weight / totalWeight; } diff -= newDiff; } - return(0); + return size; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * AdjustForSticky -- * - * This procedure adjusts the size of a slave in its cavity based - * on its "sticky" flags. + * This procedure adjusts the size of a slave in its cavity based on its + * "sticky" flags. * * Results: - * The input x, y, width, and height are changed to represent the - * desired coordinates of the slave. + * The input x, y, width, and height are changed to represent the desired + * coordinates of the slave. * * Side effects: * None. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) - Gridder *slavePtr; /* Slave window to arrange in its cavity. */ - int *xPtr; /* Pixel location of the left edge of the cavity. */ - int *yPtr; /* Pixel location of the top edge of the cavity. */ - int *widthPtr; /* Width of the cavity (in pixels). */ - int *heightPtr; /* Height of the cavity (in pixels). */ +AdjustForSticky( + Gridder *slavePtr, /* Slave window to arrange in its cavity. */ + int *xPtr, /* Pixel location of the left edge of the cavity. */ + int *yPtr, /* Pixel location of the top edge of the cavity. */ + int *widthPtr, /* Width of the cavity (in pixels). */ + int *heightPtr) /* Height of the cavity (in pixels). */ { - int diffx=0; /* Cavity width - slave width. */ - int diffy=0; /* Cavity hight - slave height. */ + int diffx = 0; /* Cavity width - slave width. */ + int diffy = 0; /* Cavity hight - slave height. */ int sticky = slavePtr->sticky; *xPtr += slavePtr->padLeft; @@ -1479,14 +1670,13 @@ AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * ArrangeGrid -- * - * This procedure is invoked (using the Tcl_DoWhenIdle - * mechanism) to re-layout a set of windows managed by - * the grid. It is invoked at idle time so that a - * series of grid requests can be merged into a single + * This procedure is invoked (using the Tcl_DoWhenIdle mechanism) to + * re-layout a set of windows managed by the grid. It is invoked at idle + * time so that a series of grid requests can be merged into a single * layout operation. * * Results: @@ -1495,28 +1685,29 @@ AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) * Side effects: * The slaves of masterPtr may get resized or moved. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -ArrangeGrid(clientData) - ClientData clientData; /* Structure describing parent whose slaves +ArrangeGrid( + ClientData clientData) /* Structure describing master whose slaves * are to be re-layed out. */ { register Gridder *masterPtr = (Gridder *) clientData; - register Gridder *slavePtr; + register Gridder *slavePtr; GridMaster *slotPtr = masterPtr->masterDataPtr; int abort; - int width, height; /* requested size of layout, in pixels */ - int realWidth, realHeight; /* actual size layout should take-up */ + int width, height; /* Requested size of layout, in pixels. */ + int realWidth, realHeight; /* Actual size layout should take-up. */ + int usedX, usedY; masterPtr->flags &= ~REQUESTED_RELAYOUT; /* - * If the parent has no slaves anymore, then don't do anything - * at all: just leave the parent's size as-is. Otherwise there is - * no way to "relinquish" control over the parent so another geometry - * manager can take over. + * If the master has no slaves anymore, then don't do anything at all: + * just leave the master's size as-is. Otherwise there is no way to + * "relinquish" control over the master so another geometry manager can + * take over. */ if (masterPtr->slavePtr == NULL) { @@ -1528,9 +1719,9 @@ ArrangeGrid(clientData) } /* - * Abort any nested call to ArrangeGrid for this window, since - * we'll do everything necessary here, and set up so this call - * can be aborted if necessary. + * Abort any nested call to ArrangeGrid for this window, since we'll do + * everything necessary here, and set up so this call can be aborted if + * necessary. */ if (masterPtr->abortPtr != NULL) { @@ -1545,13 +1736,13 @@ ArrangeGrid(clientData) */ SetGridSize(masterPtr); - width = ResolveConstraints(masterPtr, COLUMN, 0); + width = ResolveConstraints(masterPtr, COLUMN, 0); height = ResolveConstraints(masterPtr, ROW, 0); width += Tk_InternalBorderLeft(masterPtr->tkwin) + Tk_InternalBorderRight(masterPtr->tkwin); height += Tk_InternalBorderTop(masterPtr->tkwin) + Tk_InternalBorderBottom(masterPtr->tkwin); - + if (width < Tk_MinReqWidth(masterPtr->tkwin)) { width = Tk_MinReqWidth(masterPtr->tkwin); } @@ -1569,15 +1760,14 @@ ArrangeGrid(clientData) } masterPtr->abortPtr = NULL; Tcl_Release((ClientData) masterPtr); - return; + return; } /* - * If the currently requested layout size doesn't match the parent's - * window size, then adjust the slot offsets according to the - * weights. If all of the weights are zero, center the layout in - * its parent. I haven't decided what to do if the parent is smaller - * than the requested size. + * If the currently requested layout size doesn't match the master's + * window size, then adjust the slot offsets according to the weights. If + * all of the weights are zero, place the layout according to the anchor + * value. */ realWidth = Tk_Width(masterPtr->tkwin) - @@ -1586,23 +1776,22 @@ ArrangeGrid(clientData) realHeight = Tk_Height(masterPtr->tkwin) - Tk_InternalBorderTop(masterPtr->tkwin) - Tk_InternalBorderBottom(masterPtr->tkwin); - slotPtr->startX = AdjustOffsets(realWidth, - MAX(slotPtr->columnEnd,slotPtr->columnMax), slotPtr->columnPtr); - slotPtr->startY = AdjustOffsets(realHeight, - MAX(slotPtr->rowEnd,slotPtr->rowMax), slotPtr->rowPtr); - slotPtr->startX += Tk_InternalBorderLeft(masterPtr->tkwin); - slotPtr->startY += Tk_InternalBorderTop(masterPtr->tkwin); + usedX = AdjustOffsets(realWidth, + MAX(slotPtr->columnEnd, slotPtr->columnMax), slotPtr->columnPtr); + usedY = AdjustOffsets(realHeight, MAX(slotPtr->rowEnd, slotPtr->rowMax), + slotPtr->rowPtr); + TkComputeAnchor(masterPtr->masterDataPtr->anchor, masterPtr->tkwin, + 0, 0, usedX, usedY, &slotPtr->startX, &slotPtr->startY); /* - * Now adjust the actual size of the slave to its cavity by - * computing the cavity size, and adjusting the widget according - * to its stickyness. + * Now adjust the actual size of the slave to its cavity by computing the + * cavity size, and adjusting the widget according to its stickyness. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; slavePtr = slavePtr->nextPtr) { - int x, y; /* top left coordinate */ - int width, height; /* slot or slave size */ + int x, y; /* Top left coordinate */ + int width, height; /* Slot or slave size */ int col = slavePtr->column; int row = slavePtr->row; @@ -1612,49 +1801,47 @@ ArrangeGrid(clientData) width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x; height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y; - x += slotPtr->startX; - y += slotPtr->startY; + x += slotPtr->startX; + y += slotPtr->startY; AdjustForSticky(slavePtr, &x, &y, &width, &height); /* - * Now put the window in the proper spot. (This was taken directly - * from tkPack.c.) If the slave is a child of the master, then - * do this here. Otherwise let Tk_MaintainGeometry do the work. - */ - - if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { - if ((width <= 0) || (height <= 0)) { - Tk_UnmapWindow(slavePtr->tkwin); - } else { - if ((x != Tk_X(slavePtr->tkwin)) - || (y != Tk_Y(slavePtr->tkwin)) - || (width != Tk_Width(slavePtr->tkwin)) - || (height != Tk_Height(slavePtr->tkwin))) { - Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); - } - if (abort) { - break; - } - - /* - * Don't map the slave if the master isn't mapped: wait - * until the master gets mapped later. - */ - - if (Tk_IsMapped(masterPtr->tkwin)) { - Tk_MapWindow(slavePtr->tkwin); - } - } - } else { - if ((width <= 0) || (height <= 0)) { - Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); - Tk_UnmapWindow(slavePtr->tkwin); - } else { - Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, - x, y, width, height); - } - } + * Now put the window in the proper spot. (This was taken directly + * from tkPack.c.) If the slave is a child of the master, then do this + * here. Otherwise let Tk_MaintainGeometry do the work. + */ + + if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { + if ((width <= 0) || (height <= 0)) { + Tk_UnmapWindow(slavePtr->tkwin); + } else { + if ((x != Tk_X(slavePtr->tkwin)) + || (y != Tk_Y(slavePtr->tkwin)) + || (width != Tk_Width(slavePtr->tkwin)) + || (height != Tk_Height(slavePtr->tkwin))) { + Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); + } + if (abort) { + break; + } + + /* + * Don't map the slave if the master isn't mapped: wait until + * the master gets mapped later. + */ + + if (Tk_IsMapped(masterPtr->tkwin)) { + Tk_MapWindow(slavePtr->tkwin); + } + } + } else if ((width <= 0) || (height <= 0)) { + Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); + Tk_UnmapWindow(slavePtr->tkwin); + } else { + Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y, + width, height); + } } masterPtr->abortPtr = NULL; @@ -1662,13 +1849,13 @@ ArrangeGrid(clientData) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * ResolveConstraints -- * - * Resolve all of the column and row boundaries. Most of - * the calculations are identical for rows and columns, so this procedure - * is called twice, once for rows, and again for columns. + * Resolve all of the column and row boundaries. Most of the calculations + * are identical for rows and columns, so this procedure is called twice, + * once for rows, and again for columns. * * Results: * The offset (in pixels) from the left/top edge of this layout is @@ -1678,34 +1865,34 @@ ArrangeGrid(clientData) * The slot offsets are copied into the SlotInfo structure for the * geometry master. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -ResolveConstraints(masterPtr, slotType, maxOffset) - Gridder *masterPtr; /* The geometry master for this grid. */ - int slotType; /* Either ROW or COLUMN. */ - int maxOffset; /* The actual maximum size of this layout - * in pixels, or 0 (not currently used). */ +ResolveConstraints( + Gridder *masterPtr, /* The geometry master for this grid. */ + int slotType, /* Either ROW or COLUMN. */ + int maxOffset) /* The actual maximum size of this layout in + * pixels, or 0 (not currently used). */ { register SlotInfo *slotPtr; /* Pointer to row/col constraints. */ register Gridder *slavePtr; /* List of slave windows in this grid. */ int constraintCount; /* Count of rows or columns that have - * constraints. */ + * constraints. */ int slotCount; /* Last occupied row or column. */ - int gridCount; /* The larger of slotCount and constraintCount. - */ + int gridCount; /* The larger of slotCount and + * constraintCount. */ GridLayout *layoutPtr; /* Temporary layout structure. */ int requiredSize; /* The natural size of the grid (pixels). * This is the minimum size needed to * accomodate all of the slaves at their * requested sizes. */ int offset; /* The pixel offset of the right edge of the - * current slot from the beginning of the - * layout. */ + * current slot from the beginning of the + * layout. */ int slot; /* The current slot. */ int start; /* The first slot of a contiguous set whose - * constraints are not yet fully resolved. */ + * constraints are not yet fully resolved. */ int end; /* The Last slot of a contiguous set whose * constraints are not yet fully resolved. */ UniformGroup uniformPre[UNIFORM_PREALLOC]; @@ -1713,13 +1900,14 @@ ResolveConstraints(masterPtr, slotType, maxOffset) UniformGroup *uniformGroupPtr; /* Uniform groups data. */ int uniformGroups; /* Number of currently used uniform groups. */ - int uniformGroupsAlloced; /* Size of allocated space for uniform groups. - */ + int uniformGroupsAlloced; /* Size of allocated space for uniform + * groups. */ int weight, minSize; + int prevGrow, accWeight, grow; /* - * For typical sized tables, we'll use stack space for the layout data - * to avoid the overhead of a malloc and free for every layout. + * For typical sized tables, we'll use stack space for the layout data to + * avoid the overhead of a malloc and free for every layout. */ GridLayout layoutData[TYPICAL_SIZE + 1]; @@ -1727,30 +1915,32 @@ ResolveConstraints(masterPtr, slotType, maxOffset) if (slotType == COLUMN) { constraintCount = masterPtr->masterDataPtr->columnMax; slotCount = masterPtr->masterDataPtr->columnEnd; - slotPtr = masterPtr->masterDataPtr->columnPtr; + slotPtr = masterPtr->masterDataPtr->columnPtr; } else { constraintCount = masterPtr->masterDataPtr->rowMax; slotCount = masterPtr->masterDataPtr->rowEnd; - slotPtr = masterPtr->masterDataPtr->rowPtr; + slotPtr = masterPtr->masterDataPtr->rowPtr; } /* * Make sure there is enough memory for the layout. */ - gridCount = MAX(constraintCount,slotCount); + gridCount = MAX(constraintCount, slotCount); if (gridCount >= TYPICAL_SIZE) { - layoutPtr = (GridLayout *) ckalloc(sizeof(GridLayout) * (1+gridCount)); + layoutPtr = (GridLayout *) + ckalloc(sizeof(GridLayout) * (1+gridCount)); } else { layoutPtr = layoutData; } /* - * Allocate an extra layout slot to represent the left/top edge of - * the 0th slot to make it easier to calculate slot widths from - * offsets without special case code. - * Initialize the "dummy" slot to the left/top of the table. - * This slot avoids special casing the first slot. + * Allocate an extra layout slot to represent the left/top edge of the 0th + * slot to make it easier to calculate slot widths from offsets without + * special case code. + * + * Initialize the "dummy" slot to the left/top of the table. This slot + * avoids special casing the first slot. */ layoutPtr->minOffset = 0; @@ -1759,74 +1949,77 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * Step 1. - * Copy the slot constraints into the layout structure, - * and initialize the rest of the fields. + * Copy the slot constraints into the layout structure, and initialize the + * rest of the fields. */ for (slot=0; slot < constraintCount; slot++) { - layoutPtr[slot].minSize = slotPtr[slot].minSize; - layoutPtr[slot].weight = slotPtr[slot].weight; - layoutPtr[slot].uniform = slotPtr[slot].uniform; - layoutPtr[slot].pad = slotPtr[slot].pad; - layoutPtr[slot].binNextPtr = NULL; + layoutPtr[slot].minSize = slotPtr[slot].minSize; + layoutPtr[slot].weight = slotPtr[slot].weight; + layoutPtr[slot].uniform = slotPtr[slot].uniform; + layoutPtr[slot].pad = slotPtr[slot].pad; + layoutPtr[slot].binNextPtr = NULL; } - for(;slot<gridCount;slot++) { - layoutPtr[slot].minSize = 0; - layoutPtr[slot].weight = 0; - layoutPtr[slot].uniform = NULL; - layoutPtr[slot].pad = 0; - layoutPtr[slot].binNextPtr = NULL; + for (; slot<gridCount; slot++) { + layoutPtr[slot].minSize = 0; + layoutPtr[slot].weight = 0; + layoutPtr[slot].uniform = NULL; + layoutPtr[slot].pad = 0; + layoutPtr[slot].binNextPtr = NULL; } /* * Step 2. - * Slaves with a span of 1 are used to determine the minimum size of - * each slot. Slaves whose span is two or more slots don't - * contribute to the minimum size of each slot directly, but can cause - * slots to grow if their size exceeds the the sizes of the slots they - * span. - * - * Bin all slaves whose spans are > 1 by their right edges. This - * allows the computation on minimum and maximum possible layout - * sizes at each slot boundary, without the need to re-sort the slaves. + * Slaves with a span of 1 are used to determine the minimum size of each + * slot. Slaves whose span is two or more slots don't contribute to the + * minimum size of each slot directly, but can cause slots to grow if + * their size exceeds the the sizes of the slots they span. + * + * Bin all slaves whose spans are > 1 by their right edges. This allows + * the computation on minimum and maximum possible layout sizes at each + * slot boundary, without the need to re-sort the slaves. */ - + switch (slotType) { - case COLUMN: - for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - int rightEdge = slavePtr->column + slavePtr->numCols - 1; - slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + - slavePtr->padX + slavePtr->iPadX + slavePtr->doubleBw; - if (slavePtr->numCols > 1) { - slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; - layoutPtr[rightEdge].binNextPtr = slavePtr; - } else { - int size = slavePtr->size + layoutPtr[rightEdge].pad; - if (size > layoutPtr[rightEdge].minSize) { - layoutPtr[rightEdge].minSize = size; - } + case COLUMN: + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + int rightEdge = slavePtr->column + slavePtr->numCols - 1; + + slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->padX + + slavePtr->iPadX + slavePtr->doubleBw; + if (slavePtr->numCols > 1) { + slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; + layoutPtr[rightEdge].binNextPtr = slavePtr; + } else { + int size = slavePtr->size + layoutPtr[rightEdge].pad; + + if (size > layoutPtr[rightEdge].minSize) { + layoutPtr[rightEdge].minSize = size; } } - break; - case ROW: - for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - int rightEdge = slavePtr->row + slavePtr->numRows - 1; - slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + - slavePtr->padY + slavePtr->iPadY + slavePtr->doubleBw; - if (slavePtr->numRows > 1) { - slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; - layoutPtr[rightEdge].binNextPtr = slavePtr; - } else { - int size = slavePtr->size + layoutPtr[rightEdge].pad; - if (size > layoutPtr[rightEdge].minSize) { - layoutPtr[rightEdge].minSize = size; - } + } + break; + case ROW: + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + int rightEdge = slavePtr->row + slavePtr->numRows - 1; + + slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->padY + + slavePtr->iPadY + slavePtr->doubleBw; + if (slavePtr->numRows > 1) { + slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; + layoutPtr[rightEdge].binNextPtr = slavePtr; + } else { + int size = slavePtr->size + layoutPtr[rightEdge].pad; + + if (size > layoutPtr[rightEdge].minSize) { + layoutPtr[rightEdge].minSize = size; } } - break; } + break; + } /* * Step 2b. @@ -1858,13 +2051,14 @@ ResolveConstraints(masterPtr, slotType, maxOffset) * sizeof(UniformGroup); size_t newSize = (uniformGroupsAlloced + UNIFORM_PREALLOC) * sizeof(UniformGroup); - UniformGroup *new = (UniformGroup *) ckalloc(newSize); - UniformGroup *old = uniformGroupPtr; - memcpy((VOID *) new, (VOID *) old, oldSize); - if (old != uniformPre) { - ckfree((char *) old); + UniformGroup *newUG = (UniformGroup *) ckalloc(newSize); + UniformGroup *oldUG = uniformGroupPtr; + + memcpy(newUG, oldUG, oldSize); + if (oldUG != uniformPre) { + ckfree((char *) oldUG); } - uniformGroupPtr = new; + uniformGroupPtr = newUG; uniformGroupsAlloced += UNIFORM_PREALLOC; } uniformGroups++; @@ -1907,54 +2101,58 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * Step 3. - * Determine the minimum slot offsets going from left to right - * that would fit all of the slaves. This determines the minimum + * Determine the minimum slot offsets going from left to right that would + * fit all of the slaves. This determines the minimum */ - for (offset=slot=0; slot < gridCount; slot++) { - layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; - for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; - slavePtr = slavePtr->binNextPtr) { - int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; - int required = slavePtr->size + layoutPtr[slot - span].minOffset; - if (required > layoutPtr[slot].minOffset) { - layoutPtr[slot].minOffset = required; - } - } - offset = layoutPtr[slot].minOffset; + for (offset=0,slot=0; slot < gridCount; slot++) { + layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; + for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; + slavePtr = slavePtr->binNextPtr) { + int span = (slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows; + int required = slavePtr->size + layoutPtr[slot - span].minOffset; + + if (required > layoutPtr[slot].minOffset) { + layoutPtr[slot].minOffset = required; + } + } + offset = layoutPtr[slot].minOffset; } /* * At this point, we know the minimum required size of the entire layout. - * It might be prudent to stop here if our "master" will resize itself - * to this size. + * It might be prudent to stop here if our "master" will resize itself to + * this size. */ requiredSize = offset; if (maxOffset > offset) { - offset=maxOffset; + offset=maxOffset; } /* * Step 4. - * Determine the minimum slot offsets going from right to left, - * bounding the pixel range of each slot boundary. - * Pre-fill all of the right offsets with the actual size of the table; - * they will be reduced as required. + * Determine the minimum slot offsets going from right to left, bounding + * the pixel range of each slot boundary. Pre-fill all of the right + * offsets with the actual size of the table; they will be reduced as + * required. */ for (slot=0; slot < gridCount; slot++) { - layoutPtr[slot].maxOffset = offset; + layoutPtr[slot].maxOffset = offset; } for (slot=gridCount-1; slot > 0;) { - for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; - slavePtr = slavePtr->binNextPtr) { - int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; - int require = offset - slavePtr->size; - int startSlot = slot - span; - if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { - layoutPtr[startSlot].maxOffset = require; - } + for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; + slavePtr = slavePtr->binNextPtr) { + int span = (slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows; + int require = offset - slavePtr->size; + int startSlot = slot - span; + + if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { + layoutPtr[startSlot].maxOffset = require; + } } offset -= layoutPtr[slot].minSize; slot--; @@ -1967,58 +2165,56 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * Step 5. - * At this point, each slot boundary has a range of values that - * will satisfy the overall layout size. - * Make repeated passes over the layout structure looking for - * spans of slot boundaries where the minOffsets are less than - * the maxOffsets, and adjust the offsets according to the slot - * weights. At each pass, at least one slot boundary will have - * its range of possible values fixed at a single value. + * At this point, each slot boundary has a range of values that will + * satisfy the overall layout size. Make repeated passes over the layout + * structure looking for spans of slot boundaries where the minOffsets are + * less than the maxOffsets, and adjust the offsets according to the slot + * weights. At each pass, at least one slot boundary will have its range + * of possible values fixed at a single value. */ - for (start=0; start < gridCount;) { - int totalWeight = 0; /* Sum of the weights for all of the - * slots in this span. */ - int need = 0; /* The minimum space needed to layout - * this span. */ - int have; /* The actual amount of space that will - * be taken up by this span. */ - int weight; /* Cumulative weights of the columns in - * this span. */ - int noWeights = 0; /* True if the span has no weights. */ - - /* - * Find a span by identifying ranges of slots whose edges are - * already constrained at fixed offsets, but whose internal - * slot boundaries have a range of possible positions. - */ - - if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { + for (start = 0; start < gridCount;) { + int totalWeight = 0; /* Sum of the weights for all of the slots in + * this span. */ + int need = 0; /* The minimum space needed to layout this + * span. */ + int have; /* The actual amount of space that will be + * taken up by this span. */ + int weight; /* Cumulative weights of the columns in this + * span. */ + int noWeights = 0; /* True if the span has no weights. */ + + /* + * Find a span by identifying ranges of slots whose edges are already + * constrained at fixed offsets, but whose internal slot boundaries + * have a range of possible positions. + */ + + if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { start++; continue; } - for (end=start+1; end<gridCount; end++) { + for (end = start + 1; end < gridCount; end++) { if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) { break; } } /* - * We found a span. Compute the total weight, minumum space required, - * for this span, and the actual amount of space the span should - * use. + * We found a span. Compute the total weight, minumum space required, + * for this span, and the actual amount of space the span should use. */ - for (slot=start; slot<=end; slot++) { + for (slot = start; slot <= end; slot++) { totalWeight += layoutPtr[slot].weight; need += layoutPtr[slot].minSize; } have = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset; /* - * If all the weights in the span are zero, then distribute the - * extra space evenly. + * If all the weights in the span are zero, then distribute the extra + * space evenly. */ if (totalWeight == 0) { @@ -2028,100 +2224,180 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * It might not be possible to give the span all of the space - * available on this pass without violating the size constraints - * of one or more of the internal slot boundaries. - * Determine the maximum amount of space that when added to the - * entire span, would cause a slot boundary to have its possible - * range reduced to one value, and reduce the amount of extra - * space allocated on this pass accordingly. - * - * The calculation is done cumulatively to avoid accumulating - * roundoff errors. + * available on this pass without violating the size constraints of + * one or more of the internal slot boundaries. Try to determine the + * maximum amount of space that when added to the entire span, would + * cause a slot boundary to have its possible range reduced to one + * value, and reduce the amount of extra space allocated on this pass + * accordingly. + * + * The calculation is done cumulatively to avoid accumulating roundoff + * errors. */ - for (weight=0,slot=start; slot<end; slot++) { - int diff = layoutPtr[slot].maxOffset - layoutPtr[slot].minOffset; - weight += noWeights ? 1 : layoutPtr[slot].weight; - if ((noWeights || layoutPtr[slot].weight>0) && - (diff*totalWeight/weight) < (have-need)) { - have = diff * totalWeight / weight + need; + do { + int prevMinOffset = layoutPtr[start - 1].minOffset; + + prevGrow = 0; + accWeight = 0; + for (slot = start; slot <= end; slot++) { + weight = noWeights ? 1 : layoutPtr[slot].weight; + accWeight += weight; + grow = (have - need) * accWeight / totalWeight - prevGrow; + prevGrow += grow; + + if ((weight > 0) && + ((prevMinOffset + layoutPtr[slot].minSize + grow) + > layoutPtr[slot].maxOffset)) { + int newHave; + + /* + * There is not enough room to grow that much. Calculate + * how much this slot can grow and how much "have" that + * corresponds to. + */ + + grow = layoutPtr[slot].maxOffset - + layoutPtr[slot].minSize - prevMinOffset; + newHave = grow * totalWeight / weight; + if (newHave > totalWeight) { + /* + * By distributing multiples of totalWeight we + * minimize rounding errors since they will only + * happen in the last loop(s). + */ + + newHave = newHave / totalWeight * totalWeight; + } + if (newHave <= 0) { + /* + * We can end up with a "have" of 0 here if the + * previous slots have taken all the space. In that + * case we cannot guess an appropriate "have" so we + * just try some lower "have" that is >= 1, to make + * sure this terminates. + */ + + newHave = (have - need) - 1; + if (newHave > (3 * totalWeight)) { + /* + * Go down 25% for large values. + */ + newHave = newHave * 3 / 4; + } + + if (newHave > totalWeight) { + /* + * Round down to a multiple of totalWeight. + */ + newHave = newHave / totalWeight * totalWeight; + } + + if (newHave <= 0) { + newHave = 1; + } + } + have = newHave + need; + + /* + * Restart loop to check if the new "have" will fit. + */ + + break; + } + prevMinOffset += layoutPtr[slot].minSize + grow; + if (prevMinOffset < layoutPtr[slot].minOffset) { + prevMinOffset = layoutPtr[slot].minOffset; + } } - } + + /* + * Quit the outer loop if the inner loop ran all the way. + */ + } while (slot <= end); /* - * Now distribute the extra space among the slots by - * adjusting the minSizes and minOffsets. + * Now distribute the extra space among the slots by adjusting the + * minSizes and minOffsets. */ - for (weight=0,slot=start; slot<end; slot++) { - weight += noWeights ? 1 : layoutPtr[slot].weight; - layoutPtr[slot].minOffset += - (int)((double) (have-need) * weight/totalWeight + 0.5); - layoutPtr[slot].minSize = layoutPtr[slot].minOffset - - layoutPtr[slot-1].minOffset; + prevGrow = 0; + accWeight = 0; + for (slot = start; slot <= end; slot++) { + accWeight += noWeights ? 1 : layoutPtr[slot].weight; + grow = (have - need) * accWeight / totalWeight - prevGrow; + prevGrow += grow; + layoutPtr[slot].minSize += grow; + if ((layoutPtr[slot-1].minOffset + layoutPtr[slot].minSize) + > layoutPtr[slot].minOffset) { + layoutPtr[slot].minOffset = layoutPtr[slot-1].minOffset + + layoutPtr[slot].minSize; + } } - layoutPtr[slot].minSize = layoutPtr[slot].minOffset - - layoutPtr[slot-1].minOffset; /* - * Having pushed the top/left boundaries of the slots to - * take up extra space, the bottom/right space is recalculated - * to propagate the new space allocation. + * Having pushed the top/left boundaries of the slots to take up extra + * space, the bottom/right space is recalculated to propagate the new + * space allocation. */ - for (slot=end; slot > start; slot--) { - layoutPtr[slot-1].maxOffset = - layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; + for (slot = end; slot > start; slot--) { + /* + * maxOffset may not go up. + */ + + if ((layoutPtr[slot].maxOffset-layoutPtr[slot].minSize) + < layoutPtr[slot-1].maxOffset) { + layoutPtr[slot-1].maxOffset = + layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; + } } } - /* * Step 6. - * All of the space has been apportioned; copy the - * layout information back into the master. + * All of the space has been apportioned; copy the layout information back + * into the master. */ for (slot=0; slot < gridCount; slot++) { - slotPtr[slot].offset = layoutPtr[slot].minOffset; + slotPtr[slot].offset = layoutPtr[slot].minOffset; } --layoutPtr; if (layoutPtr != layoutData) { - ckfree((char *)layoutPtr); + ckfree((char *) layoutPtr); } return requiredSize; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * GetGrid -- * - * This internal procedure is used to locate a Grid - * structure for a given window, creating one if one - * doesn't exist already. + * This internal procedure is used to locate a Grid structure for a given + * window, creating one if one doesn't exist already. * * Results: - * The return value is a pointer to the Grid structure - * corresponding to tkwin. + * The return value is a pointer to the Grid structure corresponding to + * tkwin. * * Side effects: - * A new grid structure may be created. If so, then - * a callback is set up to clean things up when the - * window is deleted. + * A new grid structure may be created. If so, then a callback is set up + * to clean things up when the window is deleted. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static Gridder * -GetGrid(tkwin) - Tk_Window tkwin; /* Token for window for which - * grid structure is desired. */ +GetGrid( + Tk_Window tkwin) /* Token for window for which grid structure + * is desired. */ { register Gridder *gridPtr; Tcl_HashEntry *hPtr; - int new; + int isNew; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->gridInit) { @@ -2130,12 +2406,12 @@ GetGrid(tkwin) } /* - * See if there's already grid for this window. If not, - * then create a new one. + * See if there's already grid for this window. If not, then create a new + * one. */ - hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char *) tkwin, &new); - if (!new) { + hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char*) tkwin, &isNew); + if (!isNew) { return (Gridder *) Tcl_GetHashValue(hPtr); } gridPtr = (Gridder *) ckalloc(sizeof(Gridder)); @@ -2146,18 +2422,23 @@ GetGrid(tkwin) gridPtr->slavePtr = NULL; gridPtr->binNextPtr = NULL; - gridPtr->column = gridPtr->row = -1; + gridPtr->column = -1; + gridPtr->row = -1; gridPtr->numCols = 1; gridPtr->numRows = 1; - gridPtr->padX = gridPtr->padY = 0; - gridPtr->padLeft = gridPtr->padTop = 0; - gridPtr->iPadX = gridPtr->iPadY = 0; + gridPtr->padX = 0; + gridPtr->padY = 0; + gridPtr->padLeft = 0; + gridPtr->padTop = 0; + gridPtr->iPadX = 0; + gridPtr->iPadY = 0; gridPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; gridPtr->abortPtr = NULL; gridPtr->flags = 0; gridPtr->sticky = 0; gridPtr->size = 0; + gridPtr->in = NULL; gridPtr->masterDataPtr = NULL; Tcl_SetHashValue(hPtr, gridPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, @@ -2166,35 +2447,34 @@ GetGrid(tkwin) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * SetGridSize -- * - * This internal procedure sets the size of the grid occupied - * by slaves. + * This internal procedure sets the size of the grid occupied by slaves. * * Results: - * none + * None * * Side effects: - * The width and height arguments are filled in the master data structure. - * Additional space is allocated for the constraints to accomodate - * the offsets. + * The width and height arguments are filled in the master data + * structure. Additional space is allocated for the constraints to + * accomodate the offsets. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -SetGridSize(masterPtr) - Gridder *masterPtr; /* The geometry master for this grid. */ +SetGridSize( + Gridder *masterPtr) /* The geometry master for this grid. */ { - register Gridder *slavePtr; /* Current slave window. */ + register Gridder *slavePtr; /* Current slave window. */ int maxX = 0, maxY = 0; for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - maxX = MAX(maxX,slavePtr->numCols + slavePtr->column); - maxY = MAX(maxY,slavePtr->numRows + slavePtr->row); + slavePtr = slavePtr->nextPtr) { + maxX = MAX(maxX, slavePtr->numCols + slavePtr->column); + maxY = MAX(maxY, slavePtr->numRows + slavePtr->row); } masterPtr->masterDataPtr->columnEnd = maxX; masterPtr->masterDataPtr->rowEnd = maxY; @@ -2207,37 +2487,37 @@ SetGridSize(masterPtr) * * SetSlaveColumn -- * - * Update column data for a slave, checking that MAX_ELEMENT bound + * Update column data for a slave, checking that MAX_ELEMENT bound * is not passed. * * Results: - * TCL_ERROR if out of bounds, TCL_OK otherwise + * TCL_ERROR if out of bounds, TCL_OK otherwise * * Side effects: - * Slave fields are updated. + * Slave fields are updated. * *---------------------------------------------------------------------- */ static int SetSlaveColumn( - Tcl_Interp *interp, /* Interp for error message */ - Gridder *slavePtr, /* Slave to be updated */ - int column, /* New column or -1 to be unchanged */ - int numCols) /* New columnspan or -1 to be unchanged */ + Tcl_Interp *interp, /* Interp for error message. */ + Gridder *slavePtr, /* Slave to be updated. */ + int column, /* New column or -1 to be unchanged. */ + int numCols) /* New columnspan or -1 to be unchanged. */ { int newColumn, newNumCols, lastCol; - newColumn = (column >= 0) ? column : slavePtr->column; + newColumn = (column >= 0) ? column : slavePtr->column; newNumCols = (numCols >= 1) ? numCols : slavePtr->numCols; - lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols; + lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols; if (lastCol >= MAX_ELEMENT) { - Tcl_SetResult(interp, "Column out of bounds", TCL_STATIC); - return TCL_ERROR; + Tcl_SetResult(interp, "Column out of bounds", TCL_STATIC); + return TCL_ERROR; } - slavePtr->column = newColumn; + slavePtr->column = newColumn; slavePtr->numCols = newNumCols; return TCL_OK; } @@ -2247,70 +2527,70 @@ SetSlaveColumn( * * SetSlaveRow -- * - * Update row data for a slave, checking that MAX_ELEMENT bound + * Update row data for a slave, checking that MAX_ELEMENT bound * is not passed. * * Results: - * TCL_ERROR if out of bounds, TCL_OK otherwise + * TCL_ERROR if out of bounds, TCL_OK otherwise * * Side effects: - * Slave fields are updated. + * Slave fields are updated. * *---------------------------------------------------------------------- */ static int SetSlaveRow( - Tcl_Interp *interp, /* Interp for error message */ - Gridder *slavePtr, /* Slave to be updated */ - int row, /* New row or -1 to be unchanged */ - int numRows) /* New rowspan or -1 to be unchanged */ + Tcl_Interp *interp, /* Interp for error message. */ + Gridder *slavePtr, /* Slave to be updated. */ + int row, /* New row or -1 to be unchanged. */ + int numRows) /* New rowspan or -1 to be unchanged. */ { int newRow, newNumRows, lastRow; - newRow = (row >= 0) ? row : slavePtr->row; + newRow = (row >= 0) ? row : slavePtr->row; newNumRows = (numRows >= 1) ? numRows : slavePtr->numRows; - lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows; + lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows; if (lastRow >= MAX_ELEMENT) { - Tcl_SetResult(interp, "Row out of bounds", TCL_STATIC); - return TCL_ERROR; + Tcl_SetResult(interp, "Row out of bounds", TCL_STATIC); + return TCL_ERROR; } - slavePtr->row = newRow; + slavePtr->row = newRow; slavePtr->numRows = newNumRows; return TCL_OK; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * CheckSlotData -- * - * This internal procedure is used to manage the storage for - * row and column (slot) constraints. + * This internal procedure is used to manage the storage for row and + * column (slot) constraints. * * Results: * TRUE if the index is OK, False otherwise. * * Side effects: - * A new master grid structure may be created. If so, then - * it is initialized. In addition, additional storage for - * a row or column constraints may be allocated, and the constraint - * maximums are adjusted. + * A new master grid structure may be created. If so, then it is + * initialized. In addition, additional storage for a row or column + * constraints may be allocated, and the constraint maximums are + * adjusted. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -CheckSlotData(masterPtr, slot, slotType, checkOnly) - Gridder *masterPtr; /* the geometry master for this grid */ - int slot; /* which slot to look at */ - int slotType; /* ROW or COLUMN */ - int checkOnly; /* don't allocate new space if true */ +CheckSlotData( + Gridder *masterPtr, /* The geometry master for this grid. */ + int slot, /* Which slot to look at. */ + int slotType, /* ROW or COLUMN. */ + int checkOnly) /* Don't allocate new space if true. */ { - int numSlot; /* number of slots already allocated (Space) */ - int end; /* last used constraint */ + int numSlot; /* Number of slots already allocated (Space) */ + int end; /* Last used constraint. */ /* * If slot is out of bounds, return immediately. @@ -2326,35 +2606,36 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly) /* * If we need to allocate more space, allocate a little extra to avoid - * repeated re-alloc's for large tables. We need enough space to - * hold all of the offsets as well. + * repeated re-alloc's for large tables. We need enough space to hold all + * of the offsets as well. */ InitMasterData(masterPtr); end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax : masterPtr->masterDataPtr->columnMax; if (checkOnly == CHECK_ONLY) { - return (end < slot) ? TCL_ERROR : TCL_OK; + return ((end < slot) ? TCL_ERROR : TCL_OK); } else { - numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace - : masterPtr->masterDataPtr->columnSpace; + numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace + : masterPtr->masterDataPtr->columnSpace; if (slot >= numSlot) { - int newNumSlot = slot + PREALLOC ; - size_t oldSize = numSlot * sizeof(SlotInfo) ; - size_t newSize = newNumSlot * sizeof(SlotInfo) ; - SlotInfo *new = (SlotInfo *) ckalloc(newSize); - SlotInfo *old = (slotType == ROW) ? - masterPtr->masterDataPtr->rowPtr : - masterPtr->masterDataPtr->columnPtr; - memcpy((VOID *) new, (VOID *) old, oldSize ); - memset((VOID *) (new+numSlot), 0, newSize - oldSize ); - ckfree((char *) old); + int newNumSlot = slot + PREALLOC; + size_t oldSize = numSlot * sizeof(SlotInfo); + size_t newSize = newNumSlot * sizeof(SlotInfo); + SlotInfo *newSI = (SlotInfo *) ckalloc(newSize); + SlotInfo *oldSI = (slotType == ROW) + ? masterPtr->masterDataPtr->rowPtr + : masterPtr->masterDataPtr->columnPtr; + + memcpy(newSI, oldSI, oldSize); + memset(newSI+numSlot, 0, newSize - oldSize); + ckfree((char *) oldSI); if (slotType == ROW) { - masterPtr->masterDataPtr->rowPtr = new ; - masterPtr->masterDataPtr->rowSpace = newNumSlot ; + masterPtr->masterDataPtr->rowPtr = newSI; + masterPtr->masterDataPtr->rowSpace = newNumSlot; } else { - masterPtr->masterDataPtr->columnPtr = new; - masterPtr->masterDataPtr->columnSpace = newNumSlot ; + masterPtr->masterDataPtr->columnPtr = newSI; + masterPtr->masterDataPtr->columnSpace = newNumSlot; } } if (slot >= end && checkOnly != CHECK_SPACE) { @@ -2369,33 +2650,31 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * InitMasterData -- * - * This internal procedure is used to allocate and initialize - * the data for a geometry master, if the data - * doesn't exist already. + * This internal procedure is used to allocate and initialize the data + * for a geometry master, if the data doesn't exist already. * * Results: * none * * Side effects: - * A new master grid structure may be created. If so, then - * it is initialized. + * A new master grid structure may be created. If so, then it is + * initialized. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -InitMasterData(masterPtr) - Gridder *masterPtr; +InitMasterData( + Gridder *masterPtr) { - size_t size; if (masterPtr->masterDataPtr == NULL) { - GridMaster *gridPtr = masterPtr->masterDataPtr = - (GridMaster *) ckalloc(sizeof(GridMaster)); - size = sizeof(SlotInfo) * TYPICAL_SIZE; + GridMaster *gridPtr = masterPtr->masterDataPtr = (GridMaster *) + ckalloc(sizeof(GridMaster)); + size_t size = sizeof(SlotInfo) * TYPICAL_SIZE; gridPtr->columnEnd = 0; gridPtr->columnMax = 0; @@ -2407,9 +2686,10 @@ InitMasterData(masterPtr) gridPtr->rowSpace = TYPICAL_SIZE; gridPtr->startX = 0; gridPtr->startY = 0; + gridPtr->anchor = GRID_DEFAULT_ANCHOR; - memset((VOID *) gridPtr->columnPtr, 0, size); - memset((VOID *) gridPtr->rowPtr, 0, size); + memset(gridPtr->columnPtr, 0, size); + memset(gridPtr->rowPtr, 0, size); } } @@ -2418,21 +2698,21 @@ InitMasterData(masterPtr) * * Unlink -- * - * Remove a grid from its parent's list of slaves. + * Remove a grid from its master's list of slaves. * * Results: * None. * * Side effects: - * The parent will be scheduled for re-arranging, and the size of the + * The master will be scheduled for re-arranging, and the size of the * grid will be adjusted accordingly * *---------------------------------------------------------------------- */ static void -Unlink(slavePtr) - register Gridder *slavePtr; /* Window to unlink. */ +Unlink( + register Gridder *slavePtr) /* Window to unlink. */ { register Gridder *masterPtr, *slavePtr2; @@ -2444,9 +2724,9 @@ Unlink(slavePtr) if (masterPtr->slavePtr == slavePtr) { masterPtr->slavePtr = slavePtr->nextPtr; } else { - for (slavePtr2 = masterPtr->slavePtr; ; slavePtr2 = slavePtr2->nextPtr) { + for (slavePtr2=masterPtr->slavePtr ; ; slavePtr2=slavePtr2->nextPtr) { if (slavePtr2 == NULL) { - panic("Unlink couldn't find previous window"); + Tcl_Panic("Unlink couldn't find previous window"); } if (slavePtr2->nextPtr == slavePtr) { slavePtr2->nextPtr = slavePtr->nextPtr; @@ -2471,11 +2751,11 @@ Unlink(slavePtr) * * DestroyGrid -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a grid at a safe time - * (when no-one is using it anymore). Cleaning up the grid involves - * freeing the main structure for all windows. and the master structure - * for geometry managers. + * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to + * clean up the internal structure of a grid at a safe time (when no-one + * is using it anymore). Cleaning up the grid involves freeing the main + * structure for all windows and the master structure for geometry + * managers. * * Results: * None. @@ -2487,8 +2767,8 @@ Unlink(slavePtr) */ static void -DestroyGrid(memPtr) - char *memPtr; /* Info about window that is now dead. */ +DestroyGrid( + char *memPtr) /* Info about window that is now dead. */ { register Gridder *gridPtr = (Gridder *) memPtr; @@ -2501,6 +2781,9 @@ DestroyGrid(memPtr) } ckfree((char *) gridPtr->masterDataPtr); } + if (gridPtr->in != NULL) { + Tcl_DecrRefCount(gridPtr->in); + } ckfree((char *) gridPtr); } @@ -2509,37 +2792,37 @@ DestroyGrid(memPtr) * * GridStructureProc -- * - * This procedure is invoked by the Tk event dispatcher in response - * to StructureNotify events. + * This procedure is invoked by the Tk event dispatcher in response to + * StructureNotify events. * * Results: * None. * * Side effects: * If a window was just deleted, clean up all its grid-related - * information. If it was just resized, re-configure its slaves, if - * any. + * information. If it was just resized, re-configure its slaves, if any. * *---------------------------------------------------------------------- */ static void -GridStructureProc(clientData, eventPtr) - ClientData clientData; /* Our information about window - * referred to by eventPtr. */ - XEvent *eventPtr; /* Describes what just happened. */ +GridStructureProc( + ClientData clientData, /* Our information about window referred to by + * eventPtr. */ + XEvent *eventPtr) /* Describes what just happened. */ { register Gridder *gridPtr = (Gridder *) clientData; TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr; if (eventPtr->type == ConfigureNotify) { - if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { + if ((gridPtr->slavePtr != NULL) + && !(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } - if (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width) { - if ((gridPtr->masterPtr != NULL) && - !(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { + if ((gridPtr->masterPtr != NULL) && + (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width)) { + if (!(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width; gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr->masterPtr); @@ -2552,7 +2835,7 @@ GridStructureProc(clientData, eventPtr) Unlink(gridPtr); } for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; - gridPtr2 = nextPtr) { + gridPtr2 = nextPtr) { Tk_UnmapWindow(gridPtr2->tkwin); gridPtr2->masterPtr = NULL; nextPtr = gridPtr2->nextPtr; @@ -2566,7 +2849,8 @@ GridStructureProc(clientData, eventPtr) gridPtr->tkwin = NULL; Tcl_EventuallyFree((ClientData) gridPtr, DestroyGrid); } else if (eventPtr->type == MapNotify) { - if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { + if ((gridPtr->slavePtr != NULL) + && !(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } @@ -2574,7 +2858,7 @@ GridStructureProc(clientData, eventPtr) register Gridder *gridPtr2; for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; - gridPtr2 = gridPtr2->nextPtr) { + gridPtr2 = gridPtr2->nextPtr) { Tk_UnmapWindow(gridPtr2->tkwin); } } @@ -2585,15 +2869,14 @@ GridStructureProc(clientData, eventPtr) * * ConfigureSlaves -- * - * This implements the guts of the "grid configure" command. Given - * a list of slaves and configuration options, it arranges for the - * grid to manage the slaves and sets the specified options. - * arguments consist of windows or window shortcuts followed by - * "-option value" pairs. + * This implements the guts of the "grid configure" command. Given a list + * of slaves and configuration options, it arranges for the grid to + * manage the slaves and sets the specified options. Arguments consist + * of windows or window shortcuts followed by "-option value" pairs. * * Results: - * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is - * returned and the interp's result is set to contain an error message. + * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned + * and the interp's result is set to contain an error message. * * Side effects: * Slave windows get taken over by the grid. @@ -2602,57 +2885,90 @@ GridStructureProc(clientData, eventPtr) */ static int -ConfigureSlaves(interp, tkwin, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Any window in application containing - * slaves. Used to look up slave names. */ - int objc; /* Number of elements in argv. */ - Tcl_Obj *CONST objv[]; /* Argument objects: contains one or more - * window names followed by any number - * of "option value" pairs. Caller must - * make sure that there is at least one - * window name. */ +ConfigureSlaves( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Any window in application containing + * slaves. Used to look up slave names. */ + int objc, /* Number of elements in argv. */ + Tcl_Obj *CONST objv[]) /* Argument objects: contains one or more + * window names followed by any number of + * "option value" pairs. Caller must make sure + * that there is at least one window name. */ { - Gridder *masterPtr; + Gridder *masterPtr = NULL; Gridder *slavePtr; Tk_Window other, slave, parent, ancestor; int i, j, tmp; - int length; int numWindows; int width; - int defaultColumn = 0; /* default column number */ - int defaultColumnSpan = 1; /* default number of columns */ - char *lastWindow; /* use this window to base current - * Row/col on */ - int numSkip; /* number of 'x' found */ + int defaultRow = -1; + int defaultColumn = 0; /* Default column number */ + int defaultColumnSpan = 1; /* Default number of columns */ + char *lastWindow; /* Use this window to base current row/col + * on */ + int numSkip; /* Number of 'x' found */ static CONST char *optionStrings[] = { "-column", "-columnspan", "-in", "-ipadx", "-ipady", - "-padx", "-pady", "-row", "-rowspan", "-sticky", - (char *) NULL }; + "-padx", "-pady", "-row", "-rowspan", "-sticky", NULL + }; enum options { CONF_COLUMN, CONF_COLUMNSPAN, CONF_IN, CONF_IPADX, CONF_IPADY, CONF_PADX, CONF_PADY, CONF_ROW, CONF_ROWSPAN, CONF_STICKY }; int index; char *string; - char firstChar, prevChar; + char firstChar; + int positionGiven; /* * Count the number of windows, or window short-cuts. */ firstChar = 0; - for (numWindows = i = 0; i < objc; i++) { - prevChar = firstChar; + for (numWindows=0, i=0; i < objc; i++) { + int length; + char prevChar = firstChar; + string = Tcl_GetStringFromObj(objv[i], &length); firstChar = string[0]; - + if (firstChar == '.') { + /* + * Check that windows are valid, and locate the first slave's + * parent window (default for -in). + */ + + if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) { + return TCL_ERROR; + } + if (masterPtr == NULL) { + /* + * Is there any saved -in from a removed slave? + * If there is, it becomes default for -in. + * If the stored master does not exist, just ignore it. + */ + + struct Gridder *slavePtr = GetGrid(slave); + if (slavePtr->in != NULL) { + if (TkGetWindowFromObj(interp, slave, slavePtr->in, &parent) + == TCL_OK) { + masterPtr = GetGrid(parent); + InitMasterData(masterPtr); + } + } + } + if (masterPtr == NULL) { + parent = Tk_Parent(slave); + if (parent != NULL) { + masterPtr = GetGrid(parent); + InitMasterData(masterPtr); + } + } numWindows++; continue; } if (length > 1 && i == 0) { Tcl_AppendResult(interp, "bad argument \"", string, - "\": must be name of window", (char *) NULL); + "\": must be name of window", NULL); return TCL_ERROR; } if (length > 1 && firstChar == '-') { @@ -2661,15 +2977,14 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (length > 1) { Tcl_AppendResult(interp, "unexpected parameter, \"", string, "\", in configure list. ", - "Should be window name or option", (char *) NULL); + "Should be window name or option", NULL); return TCL_ERROR; } if ((firstChar == REL_HORIZ) && ((numWindows == 0) || (prevChar == REL_SKIP) || (prevChar == REL_VERT))) { Tcl_AppendResult(interp, - "Must specify window before shortcut '-'.", - (char *) NULL); + "Must specify window before shortcut '-'.", NULL); return TCL_ERROR; } @@ -2679,36 +2994,79 @@ ConfigureSlaves(interp, tkwin, objc, objv) } Tcl_AppendResult(interp, "invalid window shortcut, \"", - string, "\" should be '-', 'x', or '^'", (char *) NULL); + string, "\" should be '-', 'x', or '^'", NULL); return TCL_ERROR; } numWindows = i; if ((objc - numWindows) & 1) { - Tcl_AppendResult(interp, "extra option or", - " option with no value", (char *) NULL); + Tcl_AppendResult(interp, "extra option or option with no value", NULL); return TCL_ERROR; } /* - * Iterate over all of the slave windows and short-cuts, parsing - * options for each slave. It's a bit wasteful to re-parse the - * options for each slave, but things get too messy if we try to - * parse the arguments just once at the beginning. For example, - * if a slave already is managed we want to just change a few - * existing values without resetting everything. If there are - * multiple windows, the -in option only gets processed for the - * first window. + * Go through all options looking for -in and -row, which are needed to be + * found first to handle the special case where ^ is used on a row without + * windows names, but with an -in option. Since all options are checked + * here, we do not need to handle the error case again later. + */ + + for (i = numWindows; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == CONF_IN) { + if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != + TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(other); + InitMasterData(masterPtr); + } else if (index == CONF_ROW) { + if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK + || tmp < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "bad row value \"", + Tcl_GetString(objv[i+1]), "\": must be ", + "a non-negative integer", NULL); + return TCL_ERROR; + } + defaultRow = tmp; + } + } + + /* + * If no -row is given, use the first unoccupied row of the master. + */ + + if (defaultRow < 0) { + if (masterPtr != NULL && masterPtr->masterDataPtr != NULL) { + SetGridSize(masterPtr); + defaultRow = masterPtr->masterDataPtr->rowEnd; + } else { + defaultRow = 0; + } + } + + /* + * Iterate over all of the slave windows and short-cuts, parsing options + * for each slave. It's a bit wasteful to re-parse the options for each + * slave, but things get too messy if we try to parse the arguments just + * once at the beginning. For example, if a slave already is managed we + * want to just change a few existing values without resetting everything. + * If there are multiple windows, the -in option only gets processed for + * the first window. */ - masterPtr = NULL; + positionGiven = 0; for (j = 0; j < numWindows; j++) { string = Tcl_GetString(objv[j]); firstChar = string[0]; /* - * '^' and 'x' cause us to skip a column. '-' is processed - * as part of its preceeding slave. + * '^' and 'x' cause us to skip a column. '-' is processed as part of + * its preceeding slave. */ if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) { @@ -2722,6 +3080,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) for (defaultColumnSpan = 1; j + defaultColumnSpan < numWindows; defaultColumnSpan++) { char *string = Tcl_GetString(objv[j + defaultColumnSpan]); + if (*string != REL_HORIZ) { break; } @@ -2733,7 +3092,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (Tk_TopWinHierarchy(slave)) { Tcl_AppendResult(interp, "can't manage \"", Tcl_GetString(objv[j]), - "\": it's a top-level window", (char *) NULL); + "\": it's a top-level window", NULL); return TCL_ERROR; } slavePtr = GetGrid(slave); @@ -2742,49 +3101,48 @@ ConfigureSlaves(interp, tkwin, objc, objv) * The following statement is taken from tkPack.c: * * "If the slave isn't currently managed, reset all of its - * configuration information to default values (there could - * be old values left from a previous packer)." + * configuration information to default values (there could be old + * values left from a previous packer)." * - * I [D.S.] disagree with this statement. If a slave is disabled (using - * "forget") and then re-enabled, I submit that 90% of the time the - * programmer will want it to retain its old configuration information. - * If the programmer doesn't want this behavior, then the + * I [D.S.] disagree with this statement. If a slave is disabled + * (using "forget") and then re-enabled, I submit that 90% of the time + * the programmer will want it to retain its old configuration + * information. If the programmer doesn't want this behavior, then the * defaults can be reestablished by hand, without having to worry - * about keeping track of the old state. + * about keeping track of the old state. */ for (i = numWindows; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, - &index) != TCL_OK) { - return TCL_ERROR; - } - if (index == CONF_COLUMN) { - if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK || - tmp < 0) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad column value \"", - Tcl_GetString(objv[i+1]), - "\": must be a non-negative integer", (char *)NULL); + Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, + &index); + switch ((enum options) index) { + case CONF_COLUMN: + if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK + || tmp < 0) { + Tcl_AppendResult(interp, "bad column value \"", + Tcl_GetString(objv[i+1]), "\": must be ", + "a non-negative integer", NULL); return TCL_ERROR; } if (SetSlaveColumn(interp, slavePtr, tmp, -1) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_COLUMNSPAN) { - if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK || - tmp <= 0) { - Tcl_ResetResult(interp); + break; + case CONF_COLUMNSPAN: + if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK + || tmp <= 0) { Tcl_AppendResult(interp, "bad columnspan value \"", - Tcl_GetString(objv[i+1]), - "\": must be a positive integer", (char *)NULL); + Tcl_GetString(objv[i+1]), "\": must be ", + "a positive integer", NULL); return TCL_ERROR; } if (SetSlaveColumn(interp, slavePtr, -1, tmp) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_IN) { - if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != - TCL_OK) { + break; + case CONF_IN: + if (TkGetWindowFromObj(interp, tkwin, objv[i+1], + &other) != TCL_OK) { return TCL_ERROR; } if (other == slave) { @@ -2792,89 +3150,106 @@ ConfigureSlaves(interp, tkwin, objc, objv) TCL_STATIC); return TCL_ERROR; } + positionGiven = 1; masterPtr = GetGrid(other); InitMasterData(masterPtr); - } else if (index == CONF_IPADX) { - if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) - != TCL_OK) - || (tmp < 0)) { - Tcl_ResetResult(interp); + break; + case CONF_STICKY: { + int sticky = StringToSticky(Tcl_GetString(objv[i+1])); + + if (sticky == -1) { + Tcl_AppendResult(interp, "bad stickyness value \"", + Tcl_GetString(objv[i+1]), "\": must be ", + "a string containing n, e, s, and/or w", NULL); + return TCL_ERROR; + } + slavePtr->sticky = sticky; + break; + } + case CONF_IPADX: + if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1], + &tmp) != TCL_OK) || (tmp < 0)) { Tcl_AppendResult(interp, "bad ipadx value \"", - Tcl_GetString(objv[i+1]), - "\": must be positive screen distance", - (char *) NULL); + Tcl_GetString(objv[i+1]), "\": must be ", + "positive screen distance", NULL); return TCL_ERROR; } slavePtr->iPadX = tmp*2; - } else if (index == CONF_IPADY) { - if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) - != TCL_OK) - || (tmp < 0)) { - Tcl_ResetResult(interp); + break; + case CONF_IPADY: + if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1], + &tmp) != TCL_OK) || (tmp < 0)) { Tcl_AppendResult(interp, "bad ipady value \"", - Tcl_GetString(objv[i+1]), - "\": must be positive screen distance", - (char *) NULL); + Tcl_GetString(objv[i+1]), "\": must be ", + "positive screen distance", NULL); return TCL_ERROR; } slavePtr->iPadY = tmp*2; - } else if (index == CONF_PADX) { + break; + case CONF_PADX: if (TkParsePadAmount(interp, tkwin, objv[i+1], &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_PADY) { + break; + case CONF_PADY: if (TkParsePadAmount(interp, tkwin, objv[i+1], &slavePtr->padTop, &slavePtr->padY) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_ROW) { - if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK + break; + case CONF_ROW: + if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK || tmp < 0) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad grid value \"", + Tcl_AppendResult(interp, "bad row value \"", Tcl_GetString(objv[i+1]), - "\": must be a non-negative integer", (char *)NULL); + "\": must be a non-negative integer", NULL); return TCL_ERROR; } if (SetSlaveRow(interp, slavePtr, tmp, -1) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_ROWSPAN) { - if ((Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) + break; + case CONF_ROWSPAN: + if ((Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK) || tmp <= 0) { - Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad rowspan value \"", Tcl_GetString(objv[i+1]), - "\": must be a positive integer", (char *)NULL); + "\": must be a positive integer", NULL); return TCL_ERROR; } if (SetSlaveRow(interp, slavePtr, -1, tmp) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_STICKY) { - int sticky = StringToSticky(Tcl_GetString(objv[i+1])); - if (sticky == -1) { - Tcl_AppendResult(interp, "bad stickyness value \"", - Tcl_GetString(objv[i+1]), - "\": must be a string containing n, e, s, and/or w", - (char *)NULL); - return TCL_ERROR; - } - slavePtr->sticky = sticky; + break; } } /* - * Make sure we have a geometry master. We look at: - * 1) the -in flag - * 2) the geometry master of the first slave (if specified) - * 3) the parent of the first slave. + * If no position was specified via -in and the slave is already + * packed, then leave it in its current location. */ - - if (masterPtr == NULL) { + + if (!positionGiven && (slavePtr->masterPtr != NULL)) { masterPtr = slavePtr->masterPtr; + goto scheduleLayout; } + + /* + * If the same -in window is passed in again, then just leave it in + * its current location. + */ + + if (positionGiven && (masterPtr == slavePtr->masterPtr)) { + goto scheduleLayout; + } + + /* + * Make sure we have a geometry master. We look at: + * 1) the -in flag + * 2) the parent of the first slave. + */ + parent = Tk_Parent(slave); if (masterPtr == NULL) { masterPtr = GetGrid(parent); @@ -2888,15 +3263,16 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (slavePtr->masterPtr == NULL) { Gridder *tempPtr = masterPtr->slavePtr; + slavePtr->masterPtr = masterPtr; masterPtr->slavePtr = slavePtr; slavePtr->nextPtr = tempPtr; } /* - * Make sure that the slave's parent is either the master or - * an ancestor of the master, and that the master and slave - * aren't the same. + * Make sure that the slave's parent is either the master or an + * ancestor of the master, and that the master and slave aren't the + * same. */ for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { @@ -2905,8 +3281,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (Tk_TopWinHierarchy(ancestor)) { Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]), - " inside ", Tk_PathName(masterPtr->tkwin), - (char *) NULL); + " inside ", Tk_PathName(masterPtr->tkwin), NULL); Unlink(slavePtr); return TCL_ERROR; } @@ -2919,8 +3294,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (masterPtr->masterPtr == slavePtr) { Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]), " inside ", Tk_PathName(masterPtr->tkwin), - ", would cause management loop.", - (char *) NULL); + ", would cause management loop.", NULL); Unlink(slavePtr); return TCL_ERROR; } @@ -2932,7 +3306,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) */ if (slavePtr->column == -1) { - if (SetSlaveColumn(interp, slavePtr, defaultColumn, -1) != TCL_OK) { + if (SetSlaveColumn(interp, slavePtr, defaultColumn,-1) != TCL_OK){ return TCL_ERROR; } } @@ -2941,23 +3315,18 @@ ConfigureSlaves(interp, tkwin, objc, objv) return TCL_ERROR; } if (slavePtr->row == -1) { - if (masterPtr->masterDataPtr == NULL) { - slavePtr->row = 0; - } else { - if (SetSlaveRow(interp, slavePtr, - masterPtr->masterDataPtr->rowEnd, -1) != TCL_OK) { - return TCL_ERROR; - } + if (SetSlaveRow(interp, slavePtr, defaultRow, -1) != TCL_OK) { + return TCL_ERROR; } } defaultColumn += slavePtr->numCols; defaultColumnSpan = 1; /* - * Arrange for the parent to be re-arranged at the first - * idle moment. + * Arrange for the master to be re-arranged at the first idle moment. */ + scheduleLayout: if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } @@ -2967,14 +3336,16 @@ ConfigureSlaves(interp, tkwin, objc, objv) } } - /* Now look for all the "^"'s. */ + /* + * Now look for all the "^"'s. + */ lastWindow = NULL; numSkip = 0; for (j = 0; j < numWindows; j++) { struct Gridder *otherPtr; - int match; /* found a match for the ^ */ - int lastRow, lastColumn; /* implied end of table */ + int match; /* Found a match for the ^ */ + int lastRow, lastColumn; /* Implied end of table. */ string = Tcl_GetString(objv[j]); firstChar = string[0]; @@ -2991,28 +3362,28 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (masterPtr == NULL) { - Tcl_AppendResult(interp, "can't use '^', cant find master", - (char *) NULL); + Tcl_AppendResult(interp, "can't use '^', cant find master", NULL); return TCL_ERROR; } - /* Count the number of consecutive ^'s starting from this position */ + /* + * Count the number of consecutive ^'s starting from this position. + */ + for (width = 1; width + j < numWindows; width++) { char *string = Tcl_GetString(objv[j+width]); - if (*string != REL_VERT) break; + + if (*string != REL_VERT) { + break; + } } /* * Find the implied grid location of the ^ */ - if (lastWindow == NULL) { - if (masterPtr->masterDataPtr != NULL) { - SetGridSize(masterPtr); - lastRow = masterPtr->masterDataPtr->rowEnd - 2; - } else { - lastRow = 0; - } + if (lastWindow == NULL) { + lastRow = defaultRow - 1; lastColumn = 0; } else { other = Tk_NameToWindow(interp, lastWindow, tkwin); @@ -3023,13 +3394,13 @@ ConfigureSlaves(interp, tkwin, objc, objv) lastColumn += numSkip; - for (match=0, slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { + match = 0; + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { if (slavePtr->column == lastColumn && slavePtr->row + slavePtr->numRows - 1 == lastRow) { if (slavePtr->numCols <= width) { - if (SetSlaveRow(interp, slavePtr, -1, slavePtr->numRows + 1) != TCL_OK) { return TCL_ERROR; @@ -3044,14 +3415,13 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (!match) { Tcl_AppendResult(interp, "can't find slave to extend with \"^\".", - (char *) NULL); + NULL); return TCL_ERROR; } } if (masterPtr == NULL) { - Tcl_AppendResult(interp, "can't determine master window", - (char *) NULL); + Tcl_AppendResult(interp, "can't determine master window", NULL); return TCL_ERROR; } SetGridSize(masterPtr); @@ -3063,8 +3433,8 @@ ConfigureSlaves(interp, tkwin, objc, objv) * * StickyToString * - * Converts the internal boolean combination of "sticky" bits onto - * a TCL list element containing zero or mor of n, s, e, or w. + * Converts the internal boolean combination of "sticky" bits onto a Tcl + * list element containing zero or more of n, s, e, or w. * * Results: * A string is placed into the "result" pointer. @@ -3076,9 +3446,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) */ static void -StickyToString(flags, result) - int flags; /* the sticky flags */ - char *result; /* where to put the result */ +StickyToString( + int flags, /* The sticky flags. */ + char *result) /* Where to put the result. */ { int count = 0; if (flags&STICK_NORTH) { @@ -3096,7 +3466,7 @@ StickyToString(flags, result) if (count) { result[count] = '\0'; } else { - sprintf(result,"{}"); + sprintf(result, "{}"); } } @@ -3105,12 +3475,12 @@ StickyToString(flags, result) * * StringToSticky -- * - * Converts an ascii string representing a widgets stickyness - * into the boolean result. + * Converts an ascii string representing a widgets stickyness into the + * boolean result. * * Results: - * The boolean combination of the "sticky" bits is retuned. If an - * error occurs, such as an invalid character, -1 is returned instead. + * The boolean combination of the "sticky" bits is retuned. If an error + * occurs, such as an invalid character, -1 is returned instead. * * Side effects: * none @@ -3119,20 +3489,30 @@ StickyToString(flags, result) */ static int -StringToSticky(string) - char *string; +StringToSticky( + char *string) { int sticky = 0; char c; while ((c = *string++) != '\0') { switch (c) { - case 'n': case 'N': sticky |= STICK_NORTH; break; - case 'e': case 'E': sticky |= STICK_EAST; break; - case 's': case 'S': sticky |= STICK_SOUTH; break; - case 'w': case 'W': sticky |= STICK_WEST; break; - case ' ': case ',': case '\t': case '\r': case '\n': break; - default: return -1; + case 'n': case 'N': + sticky |= STICK_NORTH; + break; + case 'e': case 'E': + sticky |= STICK_EAST; + break; + case 's': case 'S': + sticky |= STICK_SOUTH; + break; + case 'w': case 'W': + sticky |= STICK_WEST; + break; + case ' ': case ',': case '\t': case '\r': case '\n': + break; + default: + return -1; } } return sticky; @@ -3155,14 +3535,14 @@ StringToSticky(string) */ static Tcl_Obj * -NewPairObj(interp, val1, val2) - Tcl_Interp *interp; /* Current interpreter. */ - int val1, val2; +NewPairObj( + int val1, int val2) { - Tcl_Obj *res = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val2)); - return res; + Tcl_Obj *ary[2]; + + ary[0] = Tcl_NewIntObj(val1); + ary[1] = Tcl_NewIntObj(val2); + return Tcl_NewListObj(2, ary); } /* @@ -3182,14 +3562,22 @@ NewPairObj(interp, val1, val2) */ static Tcl_Obj * -NewQuadObj(interp, val1, val2, val3, val4) - Tcl_Interp *interp; /* Current interpreter. */ - int val1, val2, val3, val4; +NewQuadObj( + int val1, int val2, int val3, int val4) { - Tcl_Obj *res = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val2)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val3)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val4)); - return res; + Tcl_Obj *ary[4]; + + ary[0] = Tcl_NewIntObj(val1); + ary[1] = Tcl_NewIntObj(val2); + ary[2] = Tcl_NewIntObj(val3); + ary[3] = Tcl_NewIntObj(val4); + return Tcl_NewListObj(4, ary); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkImage.c b/generic/tkImage.c index 35f013f..6c7c9cd 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -1,19 +1,17 @@ -/* +/* * tkImage.c -- * - * This module implements the image protocol, which allows lots - * of different kinds of images to be used in lots of different - * widgets. + * This module implements the image protocol, which allows lots of + * different kinds of images to be used in lots of different widgets. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" /* * Each call to Tk_GetImage returns a pointer to one of the following @@ -25,114 +23,162 @@ typedef struct Image { Tk_Window tkwin; /* Window passed to Tk_GetImage (needed to * "re-get" the image later if the manager * changes). */ - Display *display; /* Display for tkwin. Needed because when - * the image is eventually freed tkwin may - * not exist anymore. */ + Display *display; /* Display for tkwin. Needed because when the + * image is eventually freed tkwin may not + * exist anymore. */ struct ImageMaster *masterPtr; /* Master for this image (identifiers image * manager, for example). */ - ClientData instanceData; - /* One word argument to pass to image manager + ClientData instanceData; /* One word argument to pass to image manager * when dealing with this image instance. */ Tk_ImageChangedProc *changeProc; /* Code in widget to call when image changes * in a way that affects redisplay. */ - ClientData widgetClientData; - /* Argument to pass to changeProc. */ + ClientData widgetClientData;/* Argument to pass to changeProc. */ struct Image *nextPtr; /* Next in list of all image instances * associated with the same name. */ - } Image; /* - * For each image master there is one of the following structures, - * which represents a name in the image table and all of the images - * instantiated from it. Entries in mainPtr->imageTable point to - * these structures. + * For each image master there is one of the following structures, which + * represents a name in the image table and all of the images instantiated + * from it. Entries in mainPtr->imageTable point to these structures. */ typedef struct ImageMaster { - Tk_ImageType *typePtr; /* Information about image type. NULL means - * that no image manager owns this image: the + Tk_ImageType *typePtr; /* Information about image type. NULL means + * that no image manager owns this image: the * image was deleted. */ - ClientData masterData; /* One-word argument to pass to image mgr - * when dealing with the master, as opposed - * to instances. */ + ClientData masterData; /* One-word argument to pass to image mgr when + * dealing with the master, as opposed to + * instances. */ int width, height; /* Last known dimensions for image. */ - Tcl_HashTable *tablePtr; /* Pointer to hash table containing image - * (the imageTable field in some TkMainInfo + Tcl_HashTable *tablePtr; /* Pointer to hash table containing image (the + * imageTable field in some TkMainInfo * structure). */ - Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for - * this structure (used to delete the hash + Tcl_HashEntry *hPtr; /* Hash entry in mainPtr->imageTable for this + * structure (used to delete the hash * entry). */ Image *instancePtr; /* Pointer to first in list of instances * derived from this name. */ int deleted; /* Flag set when image is being deleted. */ - TkWindow *winPtr; /* Main window of interpreter (used to - * detect when the world is falling apart.) */ + TkWindow *winPtr; /* Main window of interpreter (used to detect + * when the world is falling apart.) */ } ImageMaster; typedef struct ThreadSpecificData { - Tk_ImageType *imageTypeList;/* First in a list of all known image - * types. */ - Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image - * types. */ -} ThreadSpecificData; + Tk_ImageType *imageTypeList;/* First in a list of all known image + * types. */ + Tk_ImageType *oldImageTypeList; + /* First in a list of all known old-style + * image types. */ + int initialized; /* Set to 1 if we've initialized the + * structure. */ +} ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Prototypes for local procedures: + * Prototypes for local functions: */ -static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr)); -static void EventuallyDeleteImage _ANSI_ARGS_((ImageMaster *masterPtr, - int forgetHashEntryNow)); +static void ImageTypeThreadExitProc(ClientData clientData); +static void DeleteImage(ImageMaster *masterPtr); +static void EventuallyDeleteImage(ImageMaster *masterPtr, + int forgetImageHashNow); + +/* + *---------------------------------------------------------------------- + * + * ImageTypeThreadExitProc -- + * + * Clean up the registered list of image types. + * + * Results: + * None. + * + * Side effects: + * The thread's linked lists of photo image formats is deleted. + * + *---------------------------------------------------------------------- + */ + +static void +ImageTypeThreadExitProc( + ClientData clientData) /* not used */ +{ + Tk_ImageType *freePtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + while (tsdPtr->oldImageTypeList != NULL) { + freePtr = tsdPtr->oldImageTypeList; + tsdPtr->oldImageTypeList = tsdPtr->oldImageTypeList->nextPtr; + ckfree((char *) freePtr); + } + while (tsdPtr->imageTypeList != NULL) { + freePtr = tsdPtr->imageTypeList; + tsdPtr->imageTypeList = tsdPtr->imageTypeList->nextPtr; + ckfree((char *) freePtr); + } +} /* *---------------------------------------------------------------------- * * Tk_CreateOldImageType, Tk_CreateImageType -- * - * This procedure is invoked by an image manager to tell Tk about - * a new kind of image and the procedures that manage the new type. - * The procedure is typically invoked during Tcl_AppInit. + * This function is invoked by an image manager to tell Tk about a new + * kind of image and the functions that manage the new type. The function + * is typically invoked during Tcl_AppInit. * * Results: * None. * * Side effects: - * The new image type is entered into a table used in the "image - * create" command. + * The new image type is entered into a table used in the "image create" + * command. * *---------------------------------------------------------------------- */ void -Tk_CreateOldImageType(typePtr) - Tk_ImageType *typePtr; /* Structure describing the type. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreateImageType previously. */ +Tk_CreateOldImageType( + Tk_ImageType *typePtr) /* Structure describing the type. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tk_ImageType *copyPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - typePtr->nextPtr = tsdPtr->oldImageTypeList; - tsdPtr->oldImageTypeList = typePtr; + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL); + } + copyPtr = (Tk_ImageType *) ckalloc(sizeof(Tk_ImageType)); + *copyPtr = *typePtr; + copyPtr->nextPtr = tsdPtr->oldImageTypeList; + tsdPtr->oldImageTypeList = copyPtr; } void -Tk_CreateImageType(typePtr) - Tk_ImageType *typePtr; /* Structure describing the type. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreateImageType previously. */ +Tk_CreateImageType( + Tk_ImageType *typePtr) /* Structure describing the type. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tk_ImageType *copyPtr; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - typePtr->nextPtr = tsdPtr->imageTypeList; - tsdPtr->imageTypeList = typePtr; + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + Tcl_CreateThreadExitHandler(ImageTypeThreadExitProc, NULL); + } + copyPtr = (Tk_ImageType *) ckalloc(sizeof(Tk_ImageType)); + *copyPtr = *typePtr; + copyPtr->nextPtr = tsdPtr->imageTypeList; + tsdPtr->imageTypeList = copyPtr; } /* @@ -140,8 +186,8 @@ Tk_CreateImageType(typePtr) * * Tk_ImageObjCmd -- * - * This procedure is invoked to process the "image" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "image" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -153,30 +199,31 @@ Tk_CreateImageType(typePtr) */ int -Tk_ImageObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +Tk_ImageObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { static CONST char *imageOptions[] = { "create", "delete", "height", "inuse", "names", "type", "types", - "width", (char *) NULL + "width", NULL }; enum options { IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_INUSE, IMAGE_NAMES, IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH }; TkWindow *winPtr = (TkWindow *) clientData; - int i, new, firstOption, index; + int i, isNew, firstOption, index; Tk_ImageType *typePtr; ImageMaster *masterPtr; Image *imagePtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; - char idString[16 + TCL_INTEGER_SPACE], *name; + char idString[16 + TCL_INTEGER_SPACE]; TkDisplay *dispPtr = winPtr->dispPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + char *arg, *name; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { @@ -189,276 +236,256 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } switch ((enum options) index) { - case IMAGE_CREATE: { - char *arg; - Tcl_Obj **args; - int oldimage = 0; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?"); - return TCL_ERROR; - } + case IMAGE_CREATE: { + Tcl_Obj **args; + int oldimage = 0; + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?"); + return TCL_ERROR; + } - /* - * Look up the image type. - */ + /* + * Look up the image type. + */ - arg = Tcl_GetString(objv[2]); - for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { + arg = Tcl_GetString(objv[2]); + for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + if ((*arg == typePtr->name[0]) + && (strcmp(arg, typePtr->name) == 0)) { + break; + } + } + if (typePtr == NULL) { + oldimage = 1; + for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { if ((*arg == typePtr->name[0]) && (strcmp(arg, typePtr->name) == 0)) { break; } } - if (typePtr == NULL) { - oldimage = 1; - for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { - if ((*arg == typePtr->name[0]) - && (strcmp(arg, typePtr->name) == 0)) { - break; - } - } - } - if (typePtr == NULL) { - Tcl_AppendResult(interp, "image type \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } + } + if (typePtr == NULL) { + Tcl_AppendResult(interp, "image type \"", arg, "\" doesn't exist", + NULL); + return TCL_ERROR; + } - /* - * Figure out a name to use for the new image. - */ + /* + * Figure out a name to use for the new image. + */ - if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) { - Tcl_CmdInfo dummy; - do { - dispPtr->imageId++; - sprintf(idString, "image%d", dispPtr->imageId); - name = idString; - } while (Tcl_GetCommandInfo(interp, name, &dummy) != 0); - firstOption = 3; - } else { - TkWindow *topWin; - - name = arg; - firstOption = 4; - /* - * Need to check if the _command_ that we are about to - * create is the name of the current master widget - * command (normally "." but could have been renamed) - * and fail in that case before a really nasty and - * hard to stop crash happens. - */ - topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name); - if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) { - Tcl_AppendResult(interp, "images may not be named the ", - "same as the main window", (char *) NULL); - return TCL_ERROR; - } - } + if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) { + Tcl_CmdInfo dummy; + do { + dispPtr->imageId++; + sprintf(idString, "image%d", dispPtr->imageId); + name = idString; + } while (Tcl_GetCommandInfo(interp, name, &dummy) != 0); + firstOption = 3; + } else { + TkWindow *topWin; + + name = arg; + firstOption = 4; /* - * Create the data structure for the new image. + * Need to check if the _command_ that we are about to create is + * the name of the current master widget command (normally "." but + * could have been renamed) and fail in that case before a really + * nasty and hard to stop crash happens. */ - hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, - name, &new); - if (new) { - masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster)); - masterPtr->typePtr = NULL; - masterPtr->masterData = NULL; - masterPtr->width = masterPtr->height = 1; - masterPtr->tablePtr = &winPtr->mainPtr->imageTable; - masterPtr->hPtr = hPtr; - masterPtr->instancePtr = NULL; - masterPtr->deleted = 0; - masterPtr->winPtr = winPtr->mainPtr->winPtr; - Tcl_Preserve((ClientData) masterPtr->winPtr); - Tcl_SetHashValue(hPtr, masterPtr); - } else { - /* - * An image already exists by this name. Disconnect the - * instances from the master. - */ - - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - if (masterPtr->typePtr != NULL) { - for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; - imagePtr = imagePtr->nextPtr) { - (*masterPtr->typePtr->freeProc)( - imagePtr->instanceData, imagePtr->display); - (*imagePtr->changeProc)(imagePtr->widgetClientData, - 0, 0, masterPtr->width, masterPtr->height, - masterPtr->width, masterPtr->height); - } - (*masterPtr->typePtr->deleteProc)(masterPtr->masterData); - masterPtr->typePtr = NULL; - } + topWin = (TkWindow *) TkToplevelWindowForCommand(interp, name); + if (topWin != NULL && winPtr->mainPtr->winPtr == topWin) { + Tcl_AppendResult(interp, "images may not be named the ", + "same as the main window", NULL); + return TCL_ERROR; } + } + /* + * Create the data structure for the new image. + */ + + hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &isNew); + if (isNew) { + masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster)); + masterPtr->typePtr = NULL; + masterPtr->masterData = NULL; + masterPtr->width = masterPtr->height = 1; + masterPtr->tablePtr = &winPtr->mainPtr->imageTable; + masterPtr->hPtr = hPtr; + masterPtr->instancePtr = NULL; + masterPtr->deleted = 0; + masterPtr->winPtr = winPtr->mainPtr->winPtr; + Tcl_Preserve((ClientData) masterPtr->winPtr); + Tcl_SetHashValue(hPtr, masterPtr); + } else { /* - * Call the image type manager so that it can perform its own - * initialization, then re-"get" for any existing instances of - * the image. + * An image already exists by this name. Disconnect the instances + * from the master. */ - objv += firstOption; - objc -= firstOption; - args = (Tcl_Obj **) objv; - if (oldimage) { - int i; - args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *)); - for (i = 0; i < objc; i++) { - args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]); + masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->typePtr != NULL) { + for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; + imagePtr = imagePtr->nextPtr) { + (*masterPtr->typePtr->freeProc)(imagePtr->instanceData, + imagePtr->display); + (*imagePtr->changeProc)(imagePtr->widgetClientData, + 0, 0, masterPtr->width, masterPtr->height, + masterPtr->width, masterPtr->height); } - args[objc] = NULL; + (*masterPtr->typePtr->deleteProc)(masterPtr->masterData); + masterPtr->typePtr = NULL; } - Tcl_Preserve((ClientData) masterPtr); - if ((*typePtr->createProc)(interp, name, objc, - args, typePtr, (Tk_ImageMaster) masterPtr, - &masterPtr->masterData) != TCL_OK) { - EventuallyDeleteImage(masterPtr, 0); - Tcl_Release((ClientData) masterPtr); - if (oldimage) { - ckfree((char *) args); - } - return TCL_ERROR; + masterPtr->deleted = 0; + } + + /* + * Call the image type manager so that it can perform its own + * initialization, then re-"get" for any existing instances of the + * image. + */ + + objv += firstOption; + objc -= firstOption; + args = (Tcl_Obj **) objv; + if (oldimage) { + int i; + + args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *)); + for (i = 0; i < objc; i++) { + args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]); } + args[objc] = NULL; + } + Tcl_Preserve((ClientData) masterPtr); + if ((*typePtr->createProc)(interp, name, objc, args, typePtr, + (Tk_ImageMaster)masterPtr, &masterPtr->masterData) != TCL_OK) { + EventuallyDeleteImage(masterPtr, 0); Tcl_Release((ClientData) masterPtr); if (oldimage) { ckfree((char *) args); } - masterPtr->typePtr = typePtr; - for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; - imagePtr = imagePtr->nextPtr) { - imagePtr->instanceData = (*typePtr->getProc)( - imagePtr->tkwin, masterPtr->masterData); - } - Tcl_SetResult(interp, - Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), - TCL_STATIC); - break; + return TCL_ERROR; } - case IMAGE_DELETE: { - for (i = 2; i < objc; i++) { - char *arg = Tcl_GetString(objv[i]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - DeleteImage((ImageMaster *) Tcl_GetHashValue(hPtr)); - } - break; + Tcl_Release((ClientData) masterPtr); + if (oldimage) { + ckfree((char *) args); } - case IMAGE_HEIGHT: { - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height); - break; + masterPtr->typePtr = typePtr; + for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; + imagePtr = imagePtr->nextPtr) { + imagePtr->instanceData = (*typePtr->getProc)(imagePtr->tkwin, + masterPtr->masterData); } - - case IMAGE_INUSE: { - int count = 0; - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); + Tcl_SetResult(interp, + Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), + TCL_STATIC); + break; + } + case IMAGE_DELETE: + for (i = 2; i < objc; i++) { + arg = Tcl_GetString(objv[i]); hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; + goto alreadyDeleted; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); - if (masterPtr->typePtr != NULL && masterPtr->instancePtr != NULL) { - count = 1; + if (masterPtr->deleted) { + goto alreadyDeleted; } - Tcl_SetBooleanObj(Tcl_GetObjResult(interp), count); - break; + DeleteImage(masterPtr); } - - case IMAGE_NAMES: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; + break; + case IMAGE_NAMES: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search); + for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->deleted) { + continue; } - hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search); - for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - Tcl_AppendElement(interp, Tcl_GetHashKey( + Tcl_AppendElement(interp, Tcl_GetHashKey( &winPtr->mainPtr->imageTable, hPtr)); - } - break; } - - case IMAGE_TYPE: { - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + break; + case IMAGE_TYPES: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + Tcl_AppendElement(interp, typePtr->name); + } + for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; + typePtr = typePtr->nextPtr) { + Tcl_AppendElement(interp, typePtr->name); + } + break; + + case IMAGE_HEIGHT: + case IMAGE_INUSE: + case IMAGE_TYPE: + case IMAGE_WIDTH: + /* + * These operations all parse virtually identically. First check to + * see if three args are given. Then get a non-deleted master from the + * third arg. + */ + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "name"); + return TCL_ERROR; + } + + arg = Tcl_GetString(objv[2]); + hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); + if (hPtr == NULL) { + goto alreadyDeleted; + } + masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->deleted) { + goto alreadyDeleted; + } + + /* + * Now we read off the specific piece of data we were asked for. + */ + + switch ((enum options) index) { + case IMAGE_HEIGHT: + Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height); + break; + case IMAGE_INUSE: + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), + masterPtr->typePtr!=NULL && masterPtr->instancePtr!=NULL); + break; + case IMAGE_TYPE: if (masterPtr->typePtr != NULL) { Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC); } break; - } - case IMAGE_TYPES: { - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - return TCL_ERROR; - } - for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { - Tcl_AppendElement(interp, typePtr->name); - } - for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL; - typePtr = typePtr->nextPtr) { - Tcl_AppendElement(interp, typePtr->name); - } - break; - } - case IMAGE_WIDTH: { - char *arg; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "name"); - return TCL_ERROR; - } - arg = Tcl_GetString(objv[2]); - hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "image \"", arg, - "\" doesn't exist", (char *) NULL); - return TCL_ERROR; - } - masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + case IMAGE_WIDTH: Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width); break; + default: + Tcl_Panic("can't happen"); } + break; } return TCL_OK; + + alreadyDeleted: + Tcl_AppendResult(interp, "image \"", arg, "\" doesn't exist", NULL); + return TCL_ERROR; } /* @@ -466,33 +493,32 @@ Tk_ImageObjCmd(clientData, interp, objc, objv) * * Tk_ImageChanged -- * - * This procedure is called by an image manager whenever something - * has happened that requires the image to be redrawn (some of its - * pixels have changed, or its size has changed). + * This function is called by an image manager whenever something has + * happened that requires the image to be redrawn (some of its pixels + * have changed, or its size has changed). * * Results: * None. * * Side effects: - * Any widgets that display the image are notified so that they - * can redisplay themselves as appropriate. + * Any widgets that display the image are notified so that they can + * redisplay themselves as appropriate. * *---------------------------------------------------------------------- */ void -Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, - imageHeight) - Tk_ImageMaster imageMaster; /* Image that needs redisplay. */ - int x, y; /* Coordinates of upper-left pixel of - * region of image that needs to be - * redrawn. */ - int width, height; /* Dimensions (in pixels) of region of - * image to redraw. If either dimension - * is zero then the image doesn't need to - * be redrawn (perhaps all that happened is - * that its size changed). */ - int imageWidth, imageHeight;/* New dimensions of image. */ +Tk_ImageChanged( + Tk_ImageMaster imageMaster, /* Image that needs redisplay. */ + int x, int y, /* Coordinates of upper-left pixel of region + * of image that needs to be redrawn. */ + int width, int height, /* Dimensions (in pixels) of region of image + * to redraw. If either dimension is zero then + * the image doesn't need to be redrawn + * (perhaps all that happened is that its size + * changed). */ + int imageWidth, int imageHeight) + /* New dimensions of image. */ { ImageMaster *masterPtr = (ImageMaster *) imageMaster; Image *imagePtr; @@ -500,7 +526,7 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, masterPtr->width = imageWidth; masterPtr->height = imageHeight; for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; - imagePtr = imagePtr->nextPtr) { + imagePtr = imagePtr->nextPtr) { (*imagePtr->changeProc)(imagePtr->widgetClientData, x, y, width, height, imageWidth, imageHeight); } @@ -511,8 +537,8 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, * * Tk_NameOfImage -- * - * Given a token for an image master, this procedure returns - * the name of the image. + * Given a token for an image master, this function returns the name of + * the image. * * Results: * The return value is the string name for imageMaster. @@ -524,8 +550,8 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth, */ CONST char * -Tk_NameOfImage(imageMaster) - Tk_ImageMaster imageMaster; /* Token for image. */ +Tk_NameOfImage( + Tk_ImageMaster imageMaster) /* Token for image. */ { ImageMaster *masterPtr = (ImageMaster *) imageMaster; @@ -540,36 +566,34 @@ Tk_NameOfImage(imageMaster) * * Tk_GetImage -- * - * This procedure is invoked by a widget when it wants to use - * a particular image in a particular window. + * This function is invoked by a widget when it wants to use a particular + * image in a particular window. * * Results: - * The return value is a token for the image. If there is no image - * by the given name, then NULL is returned and an error message is - * left in the interp's result. + * The return value is a token for the image. If there is no image by the + * given name, then NULL is returned and an error message is left in the + * interp's result. * * Side effects: - * Tk records the fact that the widget is using the image, and - * it will invoke changeProc later if the widget needs redisplay - * (i.e. its size changes or some of its pixels change). The - * caller must eventually invoke Tk_FreeImage when it no longer - * needs the image. + * Tk records the fact that the widget is using the image, and it will + * invoke changeProc later if the widget needs redisplay (i.e. its size + * changes or some of its pixels change). The caller must eventually + * invoke Tk_FreeImage when it no longer needs the image. * *---------------------------------------------------------------------- */ Tk_Image -Tk_GetImage(interp, tkwin, name, changeProc, clientData) - Tcl_Interp *interp; /* Place to leave error message if image - * can't be found. */ - Tk_Window tkwin; /* Token for window in which image will - * be used. */ - CONST char *name; /* Name of desired image. */ - Tk_ImageChangedProc *changeProc; - /* Procedure to invoke when redisplay is - * needed because image's pixels or size - * changed. */ - ClientData clientData; /* One-word argument to pass to damageProc. */ +Tk_GetImage( + Tcl_Interp *interp, /* Place to leave error message if image can't + * be found. */ + Tk_Window tkwin, /* Token for window in which image will be + * used. */ + CONST char *name, /* Name of desired image. */ + Tk_ImageChangedProc *changeProc, + /* Function to invoke when redisplay is needed + * because image's pixels or size changed. */ + ClientData clientData) /* One-word argument to pass to damageProc. */ { Tcl_HashEntry *hPtr; ImageMaster *masterPtr; @@ -583,6 +607,9 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) if (masterPtr->typePtr == NULL) { goto noSuchImage; } + if (masterPtr->deleted) { + goto noSuchImage; + } imagePtr = (Image *) ckalloc(sizeof(Image)); imagePtr->tkwin = tkwin; imagePtr->display = Tk_Display(tkwin); @@ -595,9 +622,10 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) masterPtr->instancePtr = imagePtr; return (Tk_Image) imagePtr; - noSuchImage: - Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist", - (char *) NULL); + noSuchImage: + if (interp) { + Tcl_AppendResult(interp, "image \"", name, "\" doesn't exist", NULL); + } return NULL; } @@ -606,9 +634,9 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) * * Tk_FreeImage -- * - * This procedure is invoked by a widget when it no longer needs - * an image acquired by a previous call to Tk_GetImage. For each - * call to Tk_GetImage there must be exactly one call to Tk_FreeImage. + * This function is invoked by a widget when it no longer needs an image + * acquired by a previous call to Tk_GetImage. For each call to + * Tk_GetImage there must be exactly one call to Tk_FreeImage. * * Results: * None. @@ -620,9 +648,9 @@ Tk_GetImage(interp, tkwin, name, changeProc, clientData) */ void -Tk_FreeImage(image) - Tk_Image image; /* Token for image that is no longer - * needed by a widget. */ +Tk_FreeImage( + Tk_Image image) /* Token for image that is no longer needed by + * a widget. */ { Image *imagePtr = (Image *) image; ImageMaster *masterPtr = imagePtr->masterPtr; @@ -647,16 +675,16 @@ Tk_FreeImage(image) } ckfree((char *) imagePtr); - /* - * If there are no more instances left for the master, and if the - * master image has been deleted, then delete the master too. + /* + * If there are no more instances left for the master, and if the master + * image has been deleted, then delete the master too. */ if ((masterPtr->typePtr == NULL) && (masterPtr->instancePtr == NULL)) { if (masterPtr->hPtr != NULL) { Tcl_DeleteHashEntry(masterPtr->hPtr); } - Tcl_Release(masterPtr->winPtr); + Tcl_Release((ClientData) masterPtr->winPtr); ckfree((char *) masterPtr); } } @@ -666,29 +694,29 @@ Tk_FreeImage(image) * * Tk_PostscriptImage -- * - * This procedure is called by widgets that contain images in order - * to redisplay an image on the screen or an off-screen pixmap. + * This function is called by widgets that contain images in order to + * redisplay an image on the screen or an off-screen pixmap. * * Results: * None. * * Side effects: - * The image's manager is notified, and it redraws the desired - * portion of the image before returning. + * The image's manager is notified, and it redraws the desired portion of + * the image before returning. * *---------------------------------------------------------------------- */ int -Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) - Tk_Image image; /* Token for image to redisplay. */ - Tcl_Interp *interp; - Tk_Window tkwin; - Tk_PostscriptInfo psinfo; /* postscript info */ - int x, y; /* Upper-left pixel of region in image that +Tk_PostscriptImage( + Tk_Image image, /* Token for image to redisplay. */ + Tcl_Interp *interp, + Tk_Window tkwin, + Tk_PostscriptInfo psinfo, /* postscript info */ + int x, int y, /* Upper-left pixel of region in image that * needs to be redisplayed. */ - int width, height; /* Dimensions of region to redraw. */ - int prepass; + int width, int height, /* Dimensions of region to redraw. */ + int prepass) { Image *imagePtr = (Image *) image; int result; @@ -701,12 +729,13 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) /* * No master for image, so nothing to display on postscript. */ + return TCL_OK; } /* - * Check if an image specific postscript-generation function - * exists; otherwise go on with generic code. + * Check if an image specific postscript-generation function exists; + * otherwise go on with generic code. */ if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) { @@ -721,12 +750,12 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) /* * Create a Pixmap, tell the image to redraw itself there, and then - * generate an XImage from the Pixmap. We can then read pixel - * values out of the XImage. + * generate an XImage from the Pixmap. We can then read pixel values out + * of the XImage. */ - pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), - width, height, Tk_Depth(tkwin)); + pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), width, height, + Tk_Depth(tkwin)); gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin)); newGC = Tk_GetGC(tkwin, GCForeground, &gcValues); @@ -742,11 +771,13 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); Tk_FreePixmap(Tk_Display(tkwin), pmap); - + if (ximage == NULL) { - /* The XGetImage() function is apparently not - * implemented on this system. Just ignore it. + /* + * The XGetImage() function is apparently not implemented on this + * system. Just ignore it. */ + return TCL_OK; } result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y, @@ -755,39 +786,38 @@ Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass) XDestroyImage(ximage); return result; } - + /* *---------------------------------------------------------------------- * * Tk_RedrawImage -- * - * This procedure is called by widgets that contain images in order - * to redisplay an image on the screen or an off-screen pixmap. + * This function is called by widgets that contain images in order to + * redisplay an image on the screen or an off-screen pixmap. * * Results: * None. * * Side effects: - * The image's manager is notified, and it redraws the desired - * portion of the image before returning. + * The image's manager is notified, and it redraws the desired portion of + * the image before returning. * *---------------------------------------------------------------------- */ void -Tk_RedrawImage(image, imageX, imageY, width, height, drawable, - drawableX, drawableY) - Tk_Image image; /* Token for image to redisplay. */ - int imageX, imageY; /* Upper-left pixel of region in image that +Tk_RedrawImage( + Tk_Image image, /* Token for image to redisplay. */ + int imageX, int imageY, /* Upper-left pixel of region in image that * needs to be redisplayed. */ - int width, height; /* Dimensions of region to redraw. */ - Drawable drawable; /* Drawable in which to display image - * (window or pixmap). If this is a pixmap, - * it must have the same depth as the window - * used in the Tk_GetImage call for the - * image. */ - int drawableX, drawableY; /* Coordinates in drawable that correspond - * to imageX and imageY. */ + int width, int height, /* Dimensions of region to redraw. */ + Drawable drawable, /* Drawable in which to display image (window + * or pixmap). If this is a pixmap, it must + * have the same depth as the window used in + * the Tk_GetImage call for the image. */ + int drawableX, int drawableY) + /* Coordinates in drawable that correspond to + * imageX and imageY. */ { Image *imagePtr = (Image *) image; @@ -829,11 +859,11 @@ Tk_RedrawImage(image, imageX, imageY, width, height, drawable, * * Tk_SizeOfImage -- * - * This procedure returns the current dimensions of an image. + * This function returns the current dimensions of an image. * * Results: - * The width and height of the image are returned in *widthPtr - * and *heightPtr. + * The width and height of the image are returned in *widthPtr and + * *heightPtr. * * Side effects: * None. @@ -842,10 +872,10 @@ Tk_RedrawImage(image, imageX, imageY, width, height, drawable, */ void -Tk_SizeOfImage(image, widthPtr, heightPtr) - Tk_Image image; /* Token for image whose size is wanted. */ - int *widthPtr; /* Return width of image here. */ - int *heightPtr; /* Return height of image here. */ +Tk_SizeOfImage( + Tk_Image image, /* Token for image whose size is wanted. */ + int *widthPtr, /* Return width of image here. */ + int *heightPtr) /* Return height of image here. */ { Image *imagePtr = (Image *) image; @@ -858,25 +888,23 @@ Tk_SizeOfImage(image, widthPtr, heightPtr) * * Tk_DeleteImage -- * - * Given the name of an image, this procedure destroys the - * image. + * Given the name of an image, this function destroys the image. * * Results: * None. * * Side effects: - * The image is destroyed; existing instances will display as - * blank areas. If no such image exists then the procedure does - * nothing. + * The image is destroyed; existing instances will display as blank + * areas. If no such image exists then the function does nothing. * *---------------------------------------------------------------------- */ void -Tk_DeleteImage(interp, name) - Tcl_Interp *interp; /* Interpreter in which the image was +Tk_DeleteImage( + Tcl_Interp *interp, /* Interpreter in which the image was * created. */ - CONST char *name; /* Name of image. */ + CONST char *name) /* Name of image. */ { Tcl_HashEntry *hPtr; TkWindow *winPtr; @@ -897,22 +925,22 @@ Tk_DeleteImage(interp, name) * * DeleteImage -- * - * This procedure is responsible for deleting an image. + * This function is responsible for deleting an image. * * Results: * None. * * Side effects: - * The connection is dropped between instances of this image and - * an image master. Image instances will redisplay themselves - * as empty areas, but existing instances will not be deleted. + * The connection is dropped between instances of this image and an image + * master. Image instances will redisplay themselves as empty areas, but + * existing instances will not be deleted. * *---------------------------------------------------------------------- */ static void -DeleteImage(masterPtr) - ImageMaster *masterPtr; /* Pointer to main data structure for image. */ +DeleteImage( + ImageMaster *masterPtr) /* Pointer to main data structure for image. */ { Image *imagePtr; Tk_ImageType *typePtr; @@ -922,9 +950,9 @@ DeleteImage(masterPtr) if (typePtr != NULL) { for (imagePtr = masterPtr->instancePtr; imagePtr != NULL; imagePtr = imagePtr->nextPtr) { - (*typePtr->freeProc)(imagePtr->instanceData, - imagePtr->display); - (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0, + (*typePtr->freeProc)(imagePtr->instanceData, + imagePtr->display); + (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0, masterPtr->width, masterPtr->height, masterPtr->width, masterPtr->height); } @@ -936,6 +964,8 @@ DeleteImage(masterPtr) } Tcl_Release((ClientData) masterPtr->winPtr); ckfree((char *) masterPtr); + } else { + masterPtr->deleted = 1; } } @@ -950,19 +980,20 @@ DeleteImage(masterPtr) * None. * * Side effects: - * Image will get freed, though not until it is no longer - * Tcl_Preserve()d by anything. May be called multiple times on - * the same image without ill effects. + * Image will get freed, though not until it is no longer Tcl_Preserve()d + * by anything. May be called multiple times on the same image without + * ill effects. * *---------------------------------------------------------------------- */ static void -EventuallyDeleteImage(masterPtr, forgetHashEntryNow) - ImageMaster *masterPtr; /* Pointer to main data structure for image. */ - int forgetHashEntryNow; +EventuallyDeleteImage( + ImageMaster *masterPtr, /* Pointer to main data structure for image. */ + int forgetImageHashNow) /* Flag to say whether the hash table is about + * to vanish. */ { - if (forgetHashEntryNow) { + if (forgetImageHashNow) { masterPtr->hPtr = NULL; } if (!masterPtr->deleted) { @@ -977,10 +1008,9 @@ EventuallyDeleteImage(masterPtr, forgetHashEntryNow) * * TkDeleteAllImages -- * - * This procedure is called when an application is deleted. It - * calls back all of the managers for all images so that they - * can cleanup, then it deletes all of Tk's internal information - * about images. + * This function is called when an application is deleted. It calls back + * all of the managers for all images so that they can cleanup, then it + * deletes all of Tk's internal information about images. * * Results: * None. @@ -992,8 +1022,8 @@ EventuallyDeleteImage(masterPtr, forgetHashEntryNow) */ void -TkDeleteAllImages(mainPtr) - TkMainInfo *mainPtr; /* Structure describing application that is +TkDeleteAllImages( + TkMainInfo *mainPtr) /* Structure describing application that is * going away. */ { Tcl_HashSearch search; @@ -1011,15 +1041,14 @@ TkDeleteAllImages(mainPtr) * * Tk_GetImageMasterData -- * - * Given the name of an image, this procedure returns the type - * of the image and the clientData associated with its master. + * Given the name of an image, this function returns the type of the + * image and the clientData associated with its master. * * Results: - * If there is no image by the given name, then NULL is returned - * and a NULL value is stored at *typePtrPtr. Otherwise the return - * value is the clientData returned by the createProc when the - * image was created and a pointer to the type structure for the - * image is stored at *typePtrPtr. + * If there is no image by the given name, then NULL is returned and a + * NULL value is stored at *typePtrPtr. Otherwise the return value is the + * clientData returned by the createProc when the image was created and a + * pointer to the type structure for the image is stored at *typePtrPtr. * * Side effects: * None. @@ -1028,12 +1057,12 @@ TkDeleteAllImages(mainPtr) */ ClientData -Tk_GetImageMasterData(interp, name, typePtrPtr) - Tcl_Interp *interp; /* Interpreter in which the image was +Tk_GetImageMasterData( + Tcl_Interp *interp, /* Interpreter in which the image was * created. */ - CONST char *name; /* Name of image. */ - Tk_ImageType **typePtrPtr; /* Points to location to fill in with - * pointer to type information for image. */ + CONST char *name, /* Name of image. */ + Tk_ImageType **typePtrPtr) /* Points to location to fill in with pointer + * to type information for image. */ { Tcl_HashEntry *hPtr; TkWindow *winPtr; @@ -1046,36 +1075,41 @@ Tk_GetImageMasterData(interp, name, typePtrPtr) return NULL; } masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr); + if (masterPtr->deleted) { + *typePtrPtr = NULL; + return NULL; + } *typePtrPtr = masterPtr->typePtr; return masterPtr->masterData; } - + /* *---------------------------------------------------------------------- * * Tk_SetTSOrigin -- * - * Set the pattern origin of the tile to a common point (i.e. the - * origin (0,0) of the top level window) so that tiles from two - * different widgets will match up. This done by setting the - * GCTileStipOrigin field is set to the translated origin of the - * toplevel window in the hierarchy. + * Set the pattern origin of the tile to a common point (i.e. the origin + * (0,0) of the top level window) so that tiles from two different + * widgets will match up. This done by setting the GCTileStipOrigin field + * is set to the translated origin of the toplevel window in the + * hierarchy. * * Results: * None. * * Side Effects: - * The GCTileStipOrigin is reset in the GC. This will cause the - * tile origin to change when the GC is used for drawing. + * The GCTileStipOrigin is reset in the GC. This will cause the tile + * origin to change when the GC is used for drawing. * *---------------------------------------------------------------------- */ + /*ARGSUSED*/ void -Tk_SetTSOrigin(tkwin, gc, x, y) - Tk_Window tkwin; - GC gc; - int x, y; +Tk_SetTSOrigin( + Tk_Window tkwin, + GC gc, + int x, int y) { while (!Tk_TopWinHierarchy(tkwin)) { x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width; @@ -1084,4 +1118,11 @@ Tk_SetTSOrigin(tkwin, gc, x, y) } XSetTSOrigin(Tk_Display(tkwin), gc, x, y); } - + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index e1ccecb..8598e88 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -1,4 +1,4 @@ -/* +/* * tkImgBmap.c -- * * This procedure implements images of type "bitmap" for Tk. @@ -12,7 +12,6 @@ */ #include "tkInt.h" -#include "tkPort.h" /* * The following data structure represents the master for a bitmap @@ -20,21 +19,19 @@ */ typedef struct BitmapMaster { - Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means - * the image is being deleted. */ - Tcl_Interp *interp; /* Interpreter for application that is - * using image. */ - Tcl_Command imageCmd; /* Token for image command (used to delete - * it when the image goes away). NULL means - * the image command has already been - * deleted. */ + Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means the + * image is being deleted. */ + Tcl_Interp *interp; /* Interpreter for application that is using + * image. */ + Tcl_Command imageCmd; /* Token for image command (used to delete it + * when the image goes away). NULL means the + * image command has already been deleted. */ int width, height; /* Dimensions of image. */ - char *data; /* Data comprising bitmap (suitable for - * input to XCreateBitmapFromData). May - * be NULL if no data. Malloc'ed. */ - char *maskData; /* Data for bitmap's mask (suitable for - * input to XCreateBitmapFromData). - * Malloc'ed. */ + char *data; /* Data comprising bitmap (suitable for input + * to XCreateBitmapFromData). May be NULL if + * no data. Malloc'ed. */ + char *maskData; /* Data for bitmap's mask (suitable for input + * to XCreateBitmapFromData). Malloc'ed. */ Tk_Uid fgUid; /* Value of -foreground option (malloc'ed). */ Tk_Uid bgUid; /* Value of -background option (malloc'ed). */ char *fileString; /* Value of -file option (malloc'ed). */ @@ -47,13 +44,13 @@ typedef struct BitmapMaster { } BitmapMaster; /* - * The following data structure represents all of the instances of an - * image that lie within a particular window: + * The following data structure represents all of the instances of an image + * that lie within a particular window: */ typedef struct BitmapInstance { - int refCount; /* Number of instances that share this - * data structure. */ + int refCount; /* Number of instances that share this data + * structure. */ BitmapMaster *masterPtr; /* Pointer to master for image. */ Tk_Window tkwin; /* Window in which the instances will be * displayed. */ @@ -63,37 +60,35 @@ typedef struct BitmapInstance { Pixmap mask; /* Mask: only display bitmap pixels where * there are 1's here. */ GC gc; /* Graphics context for displaying bitmap. - * None means there was an error while - * setting up the instance, so it cannot - * be displayed. */ + * None means there was an error while setting + * up the instance, so it cannot be + * displayed. */ struct BitmapInstance *nextPtr; /* Next in list of all instance structures - * associated with masterPtr (NULL means - * end of list). */ + * associated with masterPtr (NULL means end + * of list). */ } BitmapInstance; /* * The type record for bitmap images: */ -static int GetByte _ANSI_ARGS_((Tcl_Channel chan)); -static int ImgBmapCreate _ANSI_ARGS_((Tcl_Interp *interp, +static int GetByte(Tcl_Channel chan); +static int ImgBmapCreate(Tcl_Interp *interp, char *name, int argc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, - ClientData *clientDataPtr)); -static ClientData ImgBmapGet _ANSI_ARGS_((Tk_Window tkwin, - ClientData clientData)); -static void ImgBmapDisplay _ANSI_ARGS_((ClientData clientData, - Display *display, Drawable drawable, + ClientData *clientDataPtr); +static ClientData ImgBmapGet(Tk_Window tkwin, ClientData clientData); +static void ImgBmapDisplay(ClientData clientData, + Display *display, Drawable drawable, int imageX, int imageY, int width, int height, - int drawableX, int drawableY)); -static void ImgBmapFree _ANSI_ARGS_((ClientData clientData, - Display *display)); -static void ImgBmapDelete _ANSI_ARGS_((ClientData clientData)); -static int ImgBmapPostscript _ANSI_ARGS_((ClientData clientData, + int drawableX, int drawableY); +static void ImgBmapFree(ClientData clientData, Display *display); +static void ImgBmapDelete(ClientData clientData); +static int ImgBmapPostscript(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, - int width, int height, int prepass)); + int width, int height, int prepass); Tk_ImageType tkBitmapImageType = { "bitmap", /* name */ @@ -103,7 +98,7 @@ Tk_ImageType tkBitmapImageType = { ImgBmapFree, /* freeProc */ ImgBmapDelete, /* deleteProc */ ImgBmapPostscript, /* postscriptProc */ - (Tk_ImageType *) NULL /* nextPtr */ + NULL /* nextPtr */ }; /* @@ -111,28 +106,25 @@ Tk_ImageType tkBitmapImageType = { */ static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_UID, "-background", (char *) NULL, (char *) NULL, + {TK_CONFIG_UID, "-background", NULL, NULL, "", Tk_Offset(BitmapMaster, bgUid), 0}, - {TK_CONFIG_STRING, "-data", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_UID, "-foreground", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-data", NULL, NULL, + NULL, Tk_Offset(BitmapMaster, dataString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_STRING, "-file", NULL, NULL, + NULL, Tk_Offset(BitmapMaster, fileString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_UID, "-foreground", NULL, NULL, "#000000", Tk_Offset(BitmapMaster, fgUid), 0}, - {TK_CONFIG_STRING, "-maskdata", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapMaster, maskDataString), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-maskfile", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(BitmapMaster, maskFileString), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_STRING, "-maskdata", NULL, NULL, + NULL, Tk_Offset(BitmapMaster, maskDataString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_STRING, "-maskfile", NULL, NULL, + NULL, Tk_Offset(BitmapMaster, maskFileString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * The following data structure is used to describe the state of - * parsing a bitmap file or string. It is used for communication - * between TkGetBitmapData and NextBitmapWord. + * The following data structure is used to describe the state of parsing a + * bitmap file or string. It is used for communication between TkGetBitmapData + * and NextBitmapWord. */ #define MAX_WORD_LENGTH 100 @@ -140,8 +132,8 @@ typedef struct ParseInfo { char *string; /* Next character of string data for bitmap, * or NULL if bitmap is being read from * file. */ - Tcl_Channel chan; /* File containing bitmap data, or NULL - * if no file. */ + Tcl_Channel chan; /* File containing bitmap data, or NULL if no + * file. */ char word[MAX_WORD_LENGTH+1]; /* Current word of bitmap data, NULL * terminated. */ @@ -152,24 +144,20 @@ typedef struct ParseInfo { * Prototypes for procedures used only locally in this file: */ -static int ImgBmapCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[])); -static void ImgBmapCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void ImgBmapConfigureInstance _ANSI_ARGS_(( - BitmapInstance *instancePtr)); -static int ImgBmapConfigureMaster _ANSI_ARGS_(( - BitmapMaster *masterPtr, int argc, Tcl_Obj *CONST objv[], - int flags)); -static int NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr)); +static int ImgBmapCmd(ClientData clientData, Tcl_Interp *interp, + int argc, Tcl_Obj *CONST objv[]); +static void ImgBmapCmdDeletedProc(ClientData clientData); +static void ImgBmapConfigureInstance(BitmapInstance *instancePtr); +static int ImgBmapConfigureMaster(BitmapMaster *masterPtr, + int argc, Tcl_Obj *CONST objv[], int flags); +static int NextBitmapWord(ParseInfo *parseInfoPtr); /* *---------------------------------------------------------------------- * * ImgBmapCreate -- * - * This procedure is called by the Tk image code to create "test" - * images. + * This procedure is called by the Tk image code to create "test" images. * * Results: * A standard Tcl result. @@ -182,18 +170,18 @@ static int NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr)); /* ARGSUSED */ static int -ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) - Tcl_Interp *interp; /* Interpreter for application containing +ImgBmapCreate( + Tcl_Interp *interp, /* Interpreter for application containing * image. */ - char *name; /* Name to use for image. */ - int argc; /* Number of arguments. */ - Tcl_Obj *CONST argv[]; /* Argument objects for options (doesn't + char *name, /* Name to use for image. */ + int argc, /* Number of arguments. */ + Tcl_Obj *CONST argv[], /* Argument objects for options (doesn't * include image name or type). */ - Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ - Tk_ImageMaster master; /* Token for image, to be used by us in - * later callbacks. */ - ClientData *clientDataPtr; /* Store manager's token for image here; - * it will be returned in later callbacks. */ + Tk_ImageType *typePtr, /* Pointer to our type record (not used). */ + Tk_ImageMaster master, /* Token for image, to be used by us in later + * callbacks. */ + ClientData *clientDataPtr) /* Store manager's token for image here; it + * will be returned in later callbacks. */ { BitmapMaster *masterPtr; @@ -226,28 +214,28 @@ ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) * ImgBmapConfigureMaster -- * * This procedure is called when a bitmap image is created or - * reconfigured. It process configuration options and resets - * any instances of the image. + * reconfigured. It process configuration options and resets any + * instances of the image. * * Results: - * A standard Tcl return value. If TCL_ERROR is returned then - * an error message is left in the masterPtr->interp's result. + * A standard Tcl return value. If TCL_ERROR is returned then an error + * message is left in the masterPtr->interp's result. * * Side effects: - * Existing instances of the image will be redisplayed to match - * the new configuration options. + * Existing instances of the image will be redisplayed to match the new + * configuration options. * *---------------------------------------------------------------------- */ static int -ImgBmapConfigureMaster(masterPtr, objc, objv, flags) - BitmapMaster *masterPtr; /* Pointer to data structure describing +ImgBmapConfigureMaster( + BitmapMaster *masterPtr, /* Pointer to data structure describing * overall bitmap image to (reconfigure). */ - int objc; /* Number of entries in objv. */ - Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */ - int flags; /* Flags to pass to Tk_ConfigureWidget, - * such as TK_CONFIG_ARGV_ONLY. */ + int objc, /* Number of entries in objv. */ + Tcl_Obj *CONST objv[], /* Pairs of configuration options for image. */ + int flags) /* Flags to pass to Tk_ConfigureWidget, such + * as TK_CONFIG_ARGV_ONLY. */ { BitmapInstance *instancePtr; int maskWidth, maskHeight, dummy1, dummy2; @@ -267,8 +255,8 @@ ImgBmapConfigureMaster(masterPtr, objc, objv, flags) ckfree((char *) argv); /* - * Parse the bitmap and/or mask to create binary data. Make sure that - * the bitmap and mask have the same dimensions. + * Parse the bitmap and/or mask to create binary data. Make sure that the + * bitmap and mask have the same dimensions. */ if (masterPtr->data != NULL) { @@ -311,9 +299,9 @@ ImgBmapConfigureMaster(masterPtr, objc, objv, flags) } /* - * Cycle through all of the instances of this image, regenerating - * the information for each instance. Then force the image to be - * redisplayed everywhere that it is used. + * Cycle through all of the instances of this image, regenerating the + * information for each instance. Then force the image to be redisplayed + * everywhere that it is used. */ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; @@ -330,24 +318,24 @@ ImgBmapConfigureMaster(masterPtr, objc, objv, flags) * * ImgBmapConfigureInstance -- * - * This procedure is called to create displaying information for - * a bitmap image instance based on the configuration information - * in the master. It is invoked both when new instances are - * created and when the master is reconfigured. + * This procedure is called to create displaying information for a bitmap + * image instance based on the configuration information in the master. + * It is invoked both when new instances are created and when the master + * is reconfigured. * * Results: * None. * * Side effects: - * Generates errors via Tcl_BackgroundError if there are problems - * in setting up the instance. + * Generates errors via Tcl_BackgroundError if there are problems in + * setting up the instance. * *---------------------------------------------------------------------- */ static void -ImgBmapConfigureInstance(instancePtr) - BitmapInstance *instancePtr; /* Instance to reconfigure. */ +ImgBmapConfigureInstance( + BitmapInstance *instancePtr)/* Instance to reconfigure. */ { BitmapMaster *masterPtr = instancePtr->masterPtr; XColor *colorPtr; @@ -357,8 +345,8 @@ ImgBmapConfigureInstance(instancePtr) Pixmap oldBitmap, oldMask; /* - * For each of the options in masterPtr, translate the string - * form into an internal form appropriate for instancePtr. + * For each of the options in masterPtr, translate the string form into an + * internal form appropriate for instancePtr. */ if (*masterPtr->bgUid != 0) { @@ -385,9 +373,6 @@ ImgBmapConfigureInstance(instancePtr) } instancePtr->fg = colorPtr; - oldMask = instancePtr->mask; - instancePtr->mask = None; - /* * Careful: We have to allocate new Pixmaps before deleting the old ones. * Otherwise, The XID allocator will always return the same XID for the @@ -447,11 +432,10 @@ ImgBmapConfigureInstance(instancePtr) instancePtr->gc = gc; return; - error: + error: /* - * An error occurred: clear the graphics context in the instance to - * make it clear that this instance cannot be displayed. Then report - * the error. + * An error occurred: clear the graphics context in the instance to make + * it clear that this instance cannot be displayed. Then report the error. */ if (instancePtr->gc != None) { @@ -469,17 +453,16 @@ ImgBmapConfigureInstance(instancePtr) * * TkGetBitmapData -- * - * Given a file name or ASCII string, this procedure parses the - * file or string contents to produce binary data for a bitmap. + * Given a file name or ASCII string, this procedure parses the file or + * string contents to produce binary data for a bitmap. * * Results: - * If the bitmap description was parsed successfully then the - * return value is a malloc-ed array containing the bitmap data. - * The dimensions of the data are stored in *widthPtr and - * *heightPtr. *hotXPtr and *hotYPtr are set to the bitmap - * hotspot if one is defined, otherwise they are set to -1, -1. - * If an error occurred, NULL is returned and an error message is - * left in the interp's result. + * If the bitmap description was parsed successfully then the return + * value is a malloc-ed array containing the bitmap data. The dimensions + * of the data are stored in *widthPtr and *heightPtr. *hotXPtr and + * *hotYPtr are set to the bitmap hotspot if one is defined, otherwise + * they are set to -1, -1. If an error occurred, NULL is returned and an + * error message is left in the interp's result. * * Side effects: * A bitmap is created. @@ -488,18 +471,15 @@ ImgBmapConfigureInstance(instancePtr) */ char * -TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, - hotXPtr, hotYPtr) - Tcl_Interp *interp; /* For reporting errors, or NULL. */ - char *string; /* String describing bitmap. May - * be NULL. */ - char *fileName; /* Name of file containing bitmap - * description. Used only if string - * is NULL. Must not be NULL if - * string is NULL. */ - int *widthPtr, *heightPtr; /* Dimensions of bitmap get returned - * here. */ - int *hotXPtr, *hotYPtr; /* Position of hot spot or -1,-1. */ +TkGetBitmapData( + Tcl_Interp *interp, /* For reporting errors, or NULL. */ + char *string, /* String describing bitmap. May be NULL. */ + char *fileName, /* Name of file containing bitmap description. + * Used only if string is NULL. Must not be + * NULL if string is NULL. */ + int *widthPtr, int *heightPtr, + /* Dimensions of bitmap get returned here. */ + int *hotXPtr, int *hotYPtr) /* Position of hot spot or -1,-1. */ { int width, height, numBytes, hotX, hotY; CONST char *expandedFileName; @@ -510,11 +490,11 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, pi.string = string; if (string == NULL) { - if ((interp != NULL) && Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't get bitmap data from a file in a", - " safe interpreter", (char *) NULL); - return NULL; - } + if ((interp != NULL) && Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't get bitmap data from a file in a", + " safe interpreter", NULL); + return NULL; + } expandedFileName = Tcl_TranslateFileName(interp, fileName, &buffer); if (expandedFileName == NULL) { return NULL; @@ -525,29 +505,28 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, if (interp != NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't read bitmap file \"", - fileName, "\": ", Tcl_PosixError(interp), - (char *) NULL); + fileName, "\": ", Tcl_PosixError(interp), NULL); } return NULL; } - - if (Tcl_SetChannelOption(interp, pi.chan, "-translation", "binary") + + if (Tcl_SetChannelOption(interp, pi.chan, "-translation", "binary") != TCL_OK) { - return NULL; - } - if (Tcl_SetChannelOption(interp, pi.chan, "-encoding", "binary") + return NULL; + } + if (Tcl_SetChannelOption(interp, pi.chan, "-encoding", "binary") != TCL_OK) { - return NULL; - } + return NULL; + } } else { pi.chan = NULL; } /* - * Parse the lines that define the dimensions of the bitmap, - * plus the first line that defines the bitmap data (it declares - * the name of a data variable but doesn't include any actual - * data). These lines look something like the following: + * Parse the lines that define the dimensions of the bitmap, plus the + * first line that defines the bitmap data (it declares the name of a data + * variable but doesn't include any actual data). These lines look + * something like the following: * * #define foo_width 16 * #define foo_height 16 @@ -555,9 +534,9 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, * #define foo_y_hot 3 * static char foo_bits[] = { * - * The x_hot and y_hot lines may or may not be present. It's - * important to check for "char" in the last line, in order to - * reject old X10-style bitmaps that used shorts. + * The x_hot and y_hot lines may or may not be present. It's important to + * check for "char" in the last line, in order to reject old X10-style + * bitmaps that used shorts. */ width = 0; @@ -616,19 +595,18 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, } else if ((pi.word[0] == '{') && (pi.word[1] == 0)) { if (interp != NULL) { Tcl_AppendResult(interp, "format error in bitmap data; ", - "looks like it's an obsolete X10 bitmap file", - (char *) NULL); + "looks like it's an obsolete X10 bitmap file", NULL); } goto errorCleanup; } } /* - * Now we've read everything but the data. Allocate an array - * and read in the data. + * Now we've read everything but the data. Allocate an array and read in + * the data. */ - getData: + getData: if ((width <= 0) || (height <= 0)) { goto error; } @@ -645,7 +623,7 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, } /* - * All done. Clean up and return. + * All done. Clean up and return. */ if (pi.chan != NULL) { @@ -657,12 +635,12 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, *hotYPtr = hotY; return data; - error: + error: if (interp != NULL) { Tcl_SetResult(interp, "format error in bitmap data", TCL_STATIC); } - - errorCleanup: + + errorCleanup: if (data != NULL) { ckfree(data); } @@ -677,13 +655,13 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, * * NextBitmapWord -- * - * This procedure retrieves the next word of information (stuff - * between commas or white space) from a bitmap description. + * This procedure retrieves the next word of information (stuff between + * commas or white space) from a bitmap description. * * Results: - * Returns TCL_OK if all went well. In this case the next word, - * and its length, will be availble in *parseInfoPtr. If the end - * of the bitmap description was reached then TCL_ERROR is returned. + * Returns TCL_OK if all went well. In this case the next word, and its + * length, will be availble in *parseInfoPtr. If the end of the bitmap + * description was reached then TCL_ERROR is returned. * * Side effects: * None. @@ -692,9 +670,9 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr, */ static int -NextBitmapWord(parseInfoPtr) - ParseInfo *parseInfoPtr; /* Describes what we're reading - * and where we are in it. */ +NextBitmapWord( + ParseInfo *parseInfoPtr) /* Describes what we're reading and where we + * are in it. */ { char *src, *dst; int c; @@ -746,9 +724,9 @@ NextBitmapWord(parseInfoPtr) * * ImgBmapCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to an image managed by this module. - * See the user documentation for details on what it does. + * This procedure is invoked to process the Tcl command that corresponds + * to an image managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -760,15 +738,15 @@ NextBitmapWord(parseInfoPtr) */ static int -ImgBmapCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about the image master. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +ImgBmapCmd( + ClientData clientData, /* Information about the image master. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - static CONST char *bmapOptions[] = {"cget", "configure", (char *) NULL}; + static CONST char *bmapOptions[] = {"cget", "configure", NULL}; BitmapMaster *masterPtr = (BitmapMaster *) clientData; - int code, index; + int index; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); @@ -779,33 +757,29 @@ ImgBmapCmd(clientData, interp, objc, objv) return TCL_ERROR; } switch (index) { - case 0: { + case 0: /* cget */ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); return TCL_ERROR; } return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, Tcl_GetString(objv[2]), 0); - } - case 1: { + case 1: /* configure */ if (objc == 2) { - code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), - configSpecs, (char *) masterPtr, (char *) NULL, 0); + return Tk_ConfigureInfo(interp, Tk_MainWindow(interp), + configSpecs, (char *) masterPtr, NULL, 0); } else if (objc == 3) { - code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), + return Tk_ConfigureInfo(interp, Tk_MainWindow(interp), configSpecs, (char *) masterPtr, Tcl_GetString(objv[2]), 0); } else { - code = ImgBmapConfigureMaster(masterPtr, objc-2, objv+2, + return ImgBmapConfigureMaster(masterPtr, objc-2, objv+2, TK_CONFIG_ARGV_ONLY); } - return code; - } - default: { - panic("bad const entries to bmapOptions in ImgBmapCmd"); - } + default: + Tcl_Panic("bad const entries to bmapOptions in ImgBmapCmd"); + return TCL_OK; } - return TCL_OK; } /* @@ -813,33 +787,32 @@ ImgBmapCmd(clientData, interp, objc, objv) * * ImgBmapGet -- * - * This procedure is called for each use of a bitmap image in a - * widget. + * This procedure is called for each use of a bitmap image in a widget. * * Results: - * The return value is a token for the instance, which is passed - * back to us in calls to ImgBmapDisplay and ImgBmapFree. + * The return value is a token for the instance, which is passed back to + * us in calls to ImgBmapDisplay and ImgBmapFree. * * Side effects: - * A data structure is set up for the instance (or, an existing - * instance is re-used for the new one). + * A data structure is set up for the instance (or, an existing instance + * is re-used for the new one). * *---------------------------------------------------------------------- */ static ClientData -ImgBmapGet(tkwin, masterData) - Tk_Window tkwin; /* Window in which the instance will be +ImgBmapGet( + Tk_Window tkwin, /* Window in which the instance will be * used. */ - ClientData masterData; /* Pointer to our master structure for the + ClientData masterData) /* Pointer to our master structure for the * image. */ { BitmapMaster *masterPtr = (BitmapMaster *) masterData; BitmapInstance *instancePtr; /* - * See if there is already an instance for this window. If so - * then just re-use it. + * See if there is already an instance for this window. If so then just + * re-use it. */ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; @@ -851,8 +824,8 @@ ImgBmapGet(tkwin, masterData) } /* - * The image isn't already in use in this window. Make a new - * instance of the image. + * The image isn't already in use in this window. Make a new instance of + * the image. */ instancePtr = (BitmapInstance *) ckalloc(sizeof(BitmapInstance)); @@ -897,24 +870,24 @@ ImgBmapGet(tkwin, masterData) */ static void -ImgBmapDisplay(clientData, display, drawable, imageX, imageY, width, - height, drawableX, drawableY) - ClientData clientData; /* Pointer to BitmapInstance structure for - * for instance to be displayed. */ - Display *display; /* Display on which to draw image. */ - Drawable drawable; /* Pixmap or window in which to draw image. */ - int imageX, imageY; /* Upper-left corner of region within image - * to draw. */ - int width, height; /* Dimensions of region within image to draw. */ - int drawableX, drawableY; /* Coordinates within drawable that - * correspond to imageX and imageY. */ +ImgBmapDisplay( + ClientData clientData, /* Pointer to BitmapInstance structure for + * instance to be displayed. */ + Display *display, /* Display on which to draw image. */ + Drawable drawable, /* Pixmap or window in which to draw image. */ + int imageX, int imageY, /* Upper-left corner of region within image to + * draw. */ + int width, int height, /* Dimensions of region within image to draw. */ + int drawableX, int drawableY) + /* Coordinates within drawable that correspond + * to imageX and imageY. */ { BitmapInstance *instancePtr = (BitmapInstance *) clientData; int masking; /* - * If there's no graphics context, it means that an error occurred - * while creating the image instance so it can't be displayed. + * If there's no graphics context, it means that an error occurred while + * creating the image instance so it can't be displayed. */ if (instancePtr->gc == None) { @@ -922,10 +895,9 @@ ImgBmapDisplay(clientData, display, drawable, imageX, imageY, width, } /* - * If masking is in effect, must modify the mask origin within - * the graphics context to line up with the image's origin. - * Then draw the image and reset the clip origin, if there's - * a mask. + * If masking is in effect, must modify the mask origin within the + * graphics context to line up with the image's origin. Then draw the + * image and reset the clip origin, if there's a mask. */ masking = (instancePtr->mask != None) || (instancePtr->bg == NULL); @@ -946,8 +918,8 @@ ImgBmapDisplay(clientData, display, drawable, imageX, imageY, width, * * ImgBmapFree -- * - * This procedure is called when a widget ceases to use a - * particular instance of an image. + * This procedure is called when a widget ceases to use a particular + * instance of an image. * * Results: * None. @@ -959,10 +931,10 @@ ImgBmapDisplay(clientData, display, drawable, imageX, imageY, width, */ static void -ImgBmapFree(clientData, display) - ClientData clientData; /* Pointer to BitmapInstance structure for - * for instance to be displayed. */ - Display *display; /* Display containing window that used image. */ +ImgBmapFree( + ClientData clientData, /* Pointer to BitmapInstance structure for + * instance to be displayed. */ + Display *display) /* Display containing window that used image. */ { BitmapInstance *instancePtr = (BitmapInstance *) clientData; BitmapInstance *prevPtr; @@ -973,8 +945,8 @@ ImgBmapFree(clientData, display) } /* - * There are no more uses of the image within this widget. Free - * the instance structure. + * There are no more uses of the image within this widget. Free the + * instance structure. */ if (instancePtr->fg != NULL) { @@ -1009,8 +981,8 @@ ImgBmapFree(clientData, display) * * ImgBmapDelete -- * - * This procedure is called by the image code to delete the - * master structure for an image. + * This procedure is called by the image code to delete the master + * structure for an image. * * Results: * None. @@ -1022,14 +994,14 @@ ImgBmapFree(clientData, display) */ static void -ImgBmapDelete(masterData) - ClientData masterData; /* Pointer to BitmapMaster structure for - * image. Must not have any more instances. */ +ImgBmapDelete( + ClientData masterData) /* Pointer to BitmapMaster structure for + * image. Must not have any more instances. */ { BitmapMaster *masterPtr = (BitmapMaster *) masterData; if (masterPtr->instancePtr != NULL) { - panic("tried to delete bitmap image when instances still exist"); + Tcl_Panic("tried to delete bitmap image when instances still exist"); } masterPtr->tkMaster = NULL; if (masterPtr->imageCmd != NULL) { @@ -1041,7 +1013,7 @@ ImgBmapDelete(masterData) if (masterPtr->maskData != NULL) { ckfree(masterPtr->maskData); } - Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0); + Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0); ckfree((char *) masterPtr); } @@ -1050,8 +1022,8 @@ ImgBmapDelete(masterData) * * ImgBmapCmdDeletedProc -- * - * This procedure is invoked when the image command for an image - * is deleted. It deletes the image. + * This procedure is invoked when the image command for an image is + * deleted. It deletes the image. * * Results: * None. @@ -1063,8 +1035,8 @@ ImgBmapDelete(masterData) */ static void -ImgBmapCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to BitmapMaster structure for +ImgBmapCmdDeletedProc( + ClientData clientData) /* Pointer to BitmapMaster structure for * image. */ { BitmapMaster *masterPtr = (BitmapMaster *) clientData; @@ -1092,8 +1064,8 @@ ImgBmapCmdDeletedProc(clientData) */ static int -GetByte(chan) - Tcl_Channel chan; /* The channel we read from. */ +GetByte( + Tcl_Channel chan) /* The channel we read from. */ { char buffer; int size; @@ -1112,29 +1084,28 @@ GetByte(chan) * * ImgBmapPsImagemask -- * - * This procedure generates postscript suitable for rendering a - * single bitmap of an image. A single bitmap image might contain both - * a foreground and a background bitmap. This routine is called once - * for each such bitmap in a bitmap image. + * This procedure generates postscript suitable for rendering a single + * bitmap of an image. A single bitmap image might contain both a + * foreground and a background bitmap. This routine is called once for + * each such bitmap in a bitmap image. * - * Prior to invoking this routine, the following setup has occurred: + * Prior to invoking this routine, the following setup has occurred: * - * 1. The postscript foreground color has been set to the color - * used to render the bitmap. + * 1. The postscript foreground color has been set to the color used + * to render the bitmap. * - * 2. The origin of the postscript coordinate system is set to - * the lower left corner of the bitmap. + * 2. The origin of the postscript coordinate system is set to the + * lower left corner of the bitmap. * - * 3. The postscript coordinate system has been scaled so that - * the entire bitmap is one unit squared. + * 3. The postscript coordinate system has been scaled so that the + * entire bitmap is one unit squared. * - * Some postscript implementations cannot handle bitmap strings - * longer than about 60k characters. If the bitmap data is that big - * or bigger, then we render it by splitting it into several smaller - * bitmaps. + * Some postscript implementations cannot handle bitmap strings longer + * than about 60k characters. If the bitmap data is that big or bigger, + * then we render it by splitting it into several smaller bitmaps. * * Results: - * Returns TCL_OK on success. Returns TCL_ERROR and leaves and error + * Returns TCL_OK on success. Returns TCL_ERROR and leaves and error * message in interp->result if there is a problem. * * Side effects: @@ -1144,21 +1115,22 @@ GetByte(chan) */ static int -ImgBmapPsImagemask(interp, width, height, data) - Tcl_Interp *interp; /* Append postscript to this interpreter */ - int width, height; /* Width and height of the bitmap in pixels */ - char *data; /* Data for the bitmap */ +ImgBmapPsImagemask( + Tcl_Interp *interp, /* Append postscript to this interpreter */ + int width, int height, /* Width and height of the bitmap in pixels */ + char *data) /* Data for the bitmap */ { int i, j, nBytePerRow; char buffer[200]; - /* + /* * The bit order of bitmaps in Tk is the opposite of the bit order that - * postscript uses. (In Tk, the least significant bit is on the right - * side of the bitmap and in postscript the least significant bit is shown - * on the left.) The following array is used to reverse the order of bits + * postscript uses. (In Tk, the least significant bit is on the right side + * of the bitmap and in postscript the least significant bit is shown on + * the left.) The following array is used to reverse the order of bits * within a byte so that the bits will be in the order postscript expects. */ + static unsigned char bit_reverse[] = { 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, @@ -1184,17 +1156,21 @@ ImgBmapPsImagemask(interp, width, height, data) "larger than 60000 pixels", NULL); return TCL_ERROR; } + sprintf(buffer, "0 0 moveto %d %d true [%d 0 0 %d 0 %d] {<\n", - width, height, width, -height, height); + width, height, width, -height, height); Tcl_AppendResult(interp, buffer, NULL); + nBytePerRow = (width+7)/8; for(i=0; i<height; i++){ - for(j=0; j<nBytePerRow; j++){ - sprintf(buffer, " %02x", bit_reverse[0xff & data[i*nBytePerRow + j]]); - Tcl_AppendResult(interp, buffer, NULL); - } - Tcl_AppendResult(interp, "\n", NULL); + for(j=0; j<nBytePerRow; j++){ + sprintf(buffer, " %02x", + bit_reverse[0xff & data[i*nBytePerRow + j]]); + Tcl_AppendResult(interp, buffer, NULL); + } + Tcl_AppendResult(interp, "\n", NULL); } + Tcl_AppendResult(interp, ">} imagemask \n", NULL); return TCL_OK; } @@ -1207,9 +1183,10 @@ ImgBmapPsImagemask(interp, width, height, data) * This procedure generates postscript for rendering a bitmap image. * * Results: + * On success, this routine writes postscript code into interp->result - * and returns TCL_OK TCL_ERROR is returned and an error - * message is left in interp->result if anything goes wrong. + * and returns TCL_OK TCL_ERROR is returned and an error message is left + * in interp->result if anything goes wrong. * * Side effects: * None. @@ -1218,13 +1195,13 @@ ImgBmapPsImagemask(interp, width, height, data) */ static int -ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, - prepass) - ClientData clientData; - Tcl_Interp *interp; - Tk_Window tkwin; - Tk_PostscriptInfo psinfo; - int x, y, width, height, prepass; +ImgBmapPostscript( + ClientData clientData, + Tcl_Interp *interp, + Tk_Window tkwin, + Tk_PostscriptInfo psinfo, + int x, int y, int width, int height, + int prepass) { BitmapMaster *masterPtr = (BitmapMaster *) clientData; char buffer[200]; @@ -1234,38 +1211,42 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, } /* - * There is nothing to do for bitmaps with zero width or height + * There is nothing to do for bitmaps with zero width or height. */ - if( width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<=0 ){ + + if (width<=0 || height<=0 || masterPtr->width<=0 || masterPtr->height<= 0){ return TCL_OK; } /* * Translate the origin of the coordinate system to be the lower-left - * corner of the bitmap and adjust the scale of the coordinate system - * so that entire bitmap covers one square unit of the page. - * The calling function put a "gsave" into the postscript and - * will add a "grestore" at after this routine returns, so it is safe - * to make whatever changes are necessary here. + * corner of the bitmap and adjust the scale of the coordinate system so + * that entire bitmap covers one square unit of the page. The calling + * function put a "gsave" into the postscript and will add a "grestore" at + * after this routine returns, so it is safe to make whatever changes are + * necessary here. */ - if( x!=0 || y!=0 ){ + + if (x!=0 || y!=0) { sprintf(buffer, "%d %d moveto\n", x, y); Tcl_AppendResult(interp, buffer, NULL); } - if( width!=1 || height!=1 ){ + if (width!=1 || height!=1) { sprintf(buffer, "%d %d scale\n", width, height); Tcl_AppendResult(interp, buffer, NULL); } /* - * Color the background, if there is one. This step is skipped if the - * background is transparent. If the background is not transparent and + * Color the background, if there is one. This step is skipped if the + * background is transparent. If the background is not transparent and * there is no background mask, then color the complete rectangle that - * encloses the bitmap. If there is a background mask, then only apply + * encloses the bitmap. If there is a background mask, then only apply * color to the bits specified by the mask. */ + if ((masterPtr->bgUid != NULL) && (masterPtr->bgUid[0] != '\000')) { XColor color; + TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { @@ -1273,10 +1254,10 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, } if (masterPtr->maskData == NULL) { Tcl_AppendResult(interp, - "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto " - "closepath fill\n", NULL); + "0 0 moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto ", + "closepath fill\n", NULL); } else if (ImgBmapPsImagemask(interp, masterPtr->width, - masterPtr->height, masterPtr->maskData) != TCL_OK) { + masterPtr->height, masterPtr->maskData) != TCL_OK) { return TCL_ERROR; } } @@ -1284,8 +1265,10 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, /* * Draw the bitmap foreground, assuming there is one. */ - if ( (masterPtr->fgUid != NULL) && (masterPtr->data != NULL) ) { + + if ((masterPtr->fgUid != NULL) && (masterPtr->data != NULL)) { XColor color; + TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { @@ -1298,3 +1281,11 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, } return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index bbb3178..e576559 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -1,20 +1,20 @@ /* * tkImgGIF.c -- * - * A photo image file handler for GIF files. Reads 87a and 89a GIF - * files. At present, there only is a file write function. GIF images - * may be read using the -data option of the photo image. The data may be - * given as a binary string in a Tcl_Obj or by representing - * the data as BASE64 encoded ascii. Derived from the giftoppm code - * found in the pbmplus package and tkImgFmtPPM.c in the tk4.0b2 - * distribution. + * A photo image file handler for GIF files. Reads 87a and 89a GIF files. + * At present, there only is a file write function. GIF images may be + * read using the -data option of the photo image. The data may be given + * as a binary string in a Tcl_Obj or by representing the data as BASE64 + * encoded ascii. Derived from the giftoppm code found in the pbmplus + * package and tkImgFmtPPM.c in the tk4.0b2 distribution. * * Copyright (c) Reed Wade (wade@cs.utk.edu), University of Tennessee * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1997 Australian National University + * Copyright (c) 2005 Donal K. Fellows * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This file also contains code from the giftoppm program, which is * copyrighted as follows: @@ -25,18 +25,22 @@ * | and its documentation for any purpose and without fee is hereby | * | granted, provided that the above copyright notice appear in all | * | copies and that both that copyright notice and this permission | - * | notice appear in supporting documentation. This software is | + * | notice appear in supporting documentation. This software is | * | provided "as is" without express or implied warranty. | - * +-------------------------------------------------------------------+ + * +--------------------------------------------------------------------+ + * + * This file also contains code from miGIF. See lower down in file for the + * applicable copyright notice for that portion. */ +#include "tkInt.h" + /* - * GIF's are represented as data in base64 format. - * base64 strings consist of 4 6-bit characters -> 3 8 bit bytes. - * A-Z, a-z, 0-9, + and / represent the 64 values (in order). - * '=' is a trailing padding char when the un-encoded data is not a - * multiple of 3 bytes. We'll ignore white space when encountered. - * Any other invalid character is treated as an EOF + * GIF's are represented as data in either binary or base64 format. base64 + * strings consist of 4 6-bit characters -> 3 8 bit bytes. A-Z, a-z, 0-9, + + * and / represent the 64 values (in order). '=' is a trailing padding char + * when the un-encoded data is not a multiple of 3 bytes. We'll ignore white + * space when encountered. Any other invalid character is treated as an EOF */ #define GIF_SPECIAL (256) @@ -46,77 +50,86 @@ #define GIF_DONE (GIF_SPECIAL+4) /* - * structure to "mimic" FILE for Mread, so we can look like fread. - * The decoder state keeps track of which byte we are about to read, - * or EOF. + * structure to "mimic" FILE for Mread, so we can look like fread. The decoder + * state keeps track of which byte we are about to read, or EOF. */ typedef struct mFile { unsigned char *data; /* mmencoded source string */ - int length; /* Length of string in bytes */ 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 */ } MFile; -#include "tkInt.h" -#include "tkPort.h" - /* * Non-ASCII encoding support: - * Most data in a GIF image is binary and is treated as such. However, - * a few key bits are stashed in ASCII. If we try to compare those pieces - * to the char they represent, it will fail on any non-ASCII (eg, EBCDIC) - * system. To accomodate these systems, we test against the numeric value - * of the ASCII characters instead of the characters themselves. This is - * encoding independant. + * Most data in a GIF image is binary and is treated as such. However, a few + * key bits are stashed in ASCII. If we try to compare those pieces to the + * char they represent, it will fail on any non-ASCII (eg, EBCDIC) system. To + * accomodate these systems, we test against the numeric value of the ASCII + * characters instead of the characters themselves. This is encoding + * independant. */ -static CONST char GIF87a[] = { /* ASCII GIF87a */ +static const char GIF87a[] = { /* ASCII GIF87a */ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00 }; -static CONST char GIF89a[] = { /* ASCII GIF89a */ +static const char GIF89a[] = { /* ASCII GIF89a */ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00 }; -# define GIF_TERMINATOR 0x3b /* ASCII ; */ -# define GIF_EXTENSION 0x21 /* ASCII ! */ -# define GIF_START 0x2c /* ASCII , */ +#define GIF_TERMINATOR 0x3b /* ASCII ; */ +#define GIF_EXTENSION 0x21 /* ASCII ! */ +#define GIF_START 0x2c /* ASCII , */ /* - * HACK ALERT!! HACK ALERT!! HACK ALERT!! - * This code is hard-wired for reading from files. In order to read - * from a data stream, we'll trick fread so we can reuse the same code. - * 0==from file; 1==from base64 encoded data; 2==from binary data + * Flags used to notify that we've got inline data instead of a file to read + * from. Note that we need to figure out which type of inline data we've got + * before handing off to the GIF reading code; this is done in StringReadGIF. */ -typedef struct ThreadSpecificData { - int fromData; -} ThreadSpecificData; -static Tcl_ThreadDataKey dataKey; +#define INLINE_DATA_BINARY ((const char *) 0x01) +#define INLINE_DATA_BASE64 ((const char *) 0x02) + +/* + * HACK ALERT!! HACK ALERT!! HACK ALERT!! + * This code is hard-wired for reading from files. In order to read from a + * data stream, we'll trick fread so we can reuse the same code. 0==from file; + * 1==from base64 encoded data; 2==from binary data + */ + +typedef struct { + const char *fromData; + unsigned char workingBuffer[280]; + struct { + int bytes; + int done; + unsigned int window; + int bitsInWindow; + unsigned char *c; + } reader; +} GIFImageConfig; /* * The format record for the GIF file format: */ -static int FileMatchGIF _ANSI_ARGS_((Tcl_Channel chan, CONST char *fileName, - Tcl_Obj *format, int *widthPtr, int *heightPtr, - Tcl_Interp *interp)); -static int FileReadGIF _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, CONST char *fileName, Tcl_Obj *format, - Tk_PhotoHandle imageHandle, int destX, int destY, - int width, int height, int srcX, int srcY)); -static int StringMatchGIF _ANSI_ARGS_(( Tcl_Obj *dataObj, - Tcl_Obj *format, int *widthPtr, int *heightPtr, - Tcl_Interp *interp)); -static int StringReadGIF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj, - Tcl_Obj *format, Tk_PhotoHandle imageHandle, - int destX, int destY, int width, int height, - int srcX, int srcY)); -static int FileWriteGIF _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *filename, Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr)); -static int CommonWriteGIF _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel handle, Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr)); +static int FileMatchGIF(Tcl_Channel chan, const char *fileName, + Tcl_Obj *format, int *widthPtr, int *heightPtr, + Tcl_Interp *interp); +static int FileReadGIF(Tcl_Interp *interp, Tcl_Channel chan, + const char *fileName, Tcl_Obj *format, + Tk_PhotoHandle imageHandle, int destX, int destY, + int width, int height, int srcX, int srcY); +static int StringMatchGIF(Tcl_Obj *dataObj, Tcl_Obj *format, + int *widthPtr, int *heightPtr, Tcl_Interp *interp); +static int StringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj, + Tcl_Obj *format, Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, + int srcX, int srcY); +static int FileWriteGIF(Tcl_Interp *interp, const char *filename, + Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); +static int CommonWriteGIF(Tcl_Interp *interp, Tcl_Channel handle, + Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); Tk_PhotoImageFormat tkImgFmtGIF = { "gif", /* name */ @@ -138,54 +151,53 @@ Tk_PhotoImageFormat tkImgFmtGIF = { #define CM_ALPHA 3 #define MAX_LWZ_BITS 12 #define LM_to_uint(a,b) (((b)<<8)|(a)) -#define ReadOK(file,buffer,len) (Fread(buffer, len, 1, file) != 0) /* - * Prototypes for local procedures defined in this file: + * Prototypes for local functions defined in this file: */ -static int DoExtension _ANSI_ARGS_((Tcl_Channel chan, int label, - int *transparent)); -static int GetCode _ANSI_ARGS_((Tcl_Channel chan, int code_size, - int flag)); -static int GetDataBlock _ANSI_ARGS_((Tcl_Channel chan, - unsigned char *buf)); -static int ReadColorMap _ANSI_ARGS_((Tcl_Channel chan, int number, - unsigned char buffer[MAXCOLORMAPSIZE][4])); -static int ReadGIFHeader _ANSI_ARGS_((Tcl_Channel chan, - int *widthPtr, int *heightPtr)); -static int ReadImage _ANSI_ARGS_((Tcl_Interp *interp, - char *imagePtr, Tcl_Channel chan, - int len, int rows, - unsigned char cmap[MAXCOLORMAPSIZE][4], - int width, int height, int srcX, int srcY, - int interlace, int transparent)); +static int DoExtension(GIFImageConfig *gifConfPtr, + Tcl_Channel chan, int label, unsigned char *buffer, + int *transparent); +static int GetCode(Tcl_Channel chan, int code_size, int flag, + GIFImageConfig *gifConfPtr); +static int GetDataBlock(GIFImageConfig *gifConfPtr, + Tcl_Channel chan, unsigned char *buf); +static int ReadColorMap(GIFImageConfig *gifConfPtr, + Tcl_Channel chan, int number, + unsigned char buffer[MAXCOLORMAPSIZE][4]); +static int ReadGIFHeader(GIFImageConfig *gifConfPtr, + Tcl_Channel chan, int *widthPtr, int *heightPtr); +static int ReadImage(GIFImageConfig *gifConfPtr, + Tcl_Interp *interp, unsigned char *imagePtr, + Tcl_Channel chan, int len, int rows, + unsigned char cmap[MAXCOLORMAPSIZE][4], int srcX, + int srcY, int interlace, int transparent); /* * these are for the BASE64 image reader code only */ -static int Fread _ANSI_ARGS_((unsigned char *dst, size_t size, - size_t count, Tcl_Channel chan)); -static int Mread _ANSI_ARGS_((unsigned char *dst, size_t size, - size_t count, MFile *handle)); -static int Mgetc _ANSI_ARGS_((MFile *handle)); -static int char64 _ANSI_ARGS_((int c)); -static void mInit _ANSI_ARGS_((unsigned char *string, - int length, MFile *handle)); - +static int 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, + MFile *handle); +static int Mgetc(MFile *handle); +static int char64(int c); +static void mInit(unsigned char *string, MFile *handle, + int length); /* *---------------------------------------------------------------------- * * FileMatchGIF -- * - * This procedure is invoked by the photo image type to see if - * a file contains image data in GIF format. + * This function is invoked by the photo image type to see if a file + * contains image data in GIF format. * * Results: - * The return value is 1 if the first characters in file f look - * like GIF data, and 0 otherwise. + * The return value is 1 if the first characters in file f look like GIF + * data, and 0 otherwise. * * Side effects: * The access position in f may change. @@ -194,16 +206,19 @@ static void mInit _ANSI_ARGS_((unsigned char *string, */ static int -FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp) - Tcl_Channel chan; /* The image file, open for reading. */ - CONST char *fileName; /* The name of the image file. */ - Tcl_Obj *format; /* User-specified format object, or NULL. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here if the file is a valid - * raw GIF file. */ - Tcl_Interp *interp; /* not used */ +FileMatchGIF( + Tcl_Channel chan, /* The image file, open for reading. */ + const char *fileName, /* The name of the image file. */ + Tcl_Obj *format, /* User-specified format object, or NULL. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here if the file is a valid raw GIF file. */ + Tcl_Interp *interp) /* not used */ { - return ReadGIFHeader(chan, widthPtr, heightPtr); + GIFImageConfig gifConf; + + memset(&gifConf, 0, sizeof(GIFImageConfig)); + return ReadGIFHeader(&gifConf, chan, widthPtr, heightPtr); } /* @@ -211,88 +226,108 @@ FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp) * * FileReadGIF -- * - * This procedure is called by the photo image type to read - * GIF format data from a file and write it into a given - * photo image. + * This function is called by the photo image type to read GIF format + * data from a file and write it into a given photo image. * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. * * Side effects: - * The access position in file f is changed, and new data is - * added to the image given by imageHandle. + * The access position in file f is changed, and new data is added to the + * image given by imageHandle. * *---------------------------------------------------------------------- */ static int -FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Channel chan; /* The image file, open for reading. */ - CONST char *fileName; /* The name of the image file. */ - Tcl_Obj *format; /* User-specified format object, or NULL. */ - Tk_PhotoHandle imageHandle; /* The photo image to write into. */ - int destX, destY; /* Coordinates of top-left pixel in - * photo image to be written to. */ - int width, height; /* Dimensions of block of photo image to - * be written to. */ - int srcX, srcY; /* Coordinates of top-left pixel to be used - * in image being read. */ +FileReadGIF( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Channel chan, /* The image file, open for reading. */ + const char *fileName, /* The name of the image file. */ + Tcl_Obj *format, /* User-specified format object, or NULL. */ + Tk_PhotoHandle imageHandle, /* The photo image to write into. */ + int destX, int destY, /* Coordinates of top-left pixel in photo + * image to be written to. */ + int width, int height, /* Dimensions of block of photo image to be + * written to. */ + int srcX, int srcY) /* Coordinates of top-left pixel to be used in + * image being read. */ { int fileWidth, fileHeight, imageWidth, imageHeight; - int nBytes, index = 0, argc = 0, i; + int nBytes, index = 0, argc = 0, i, result = TCL_ERROR; Tcl_Obj **objv; - Tk_PhotoImageBlock block; unsigned char buf[100]; unsigned char *trashBuffer = NULL; int bitPixel; unsigned char colorMap[MAXCOLORMAPSIZE][4]; int transparent = -1; - static CONST char *optionStrings[] = { - "-index", NULL + static const char *optionStrings[] = { + "-index", NULL }; + GIFImageConfig gifConf, *gifConfPtr = &gifConf; + + /* + * Decode the magic used to convey when we're sourcing data from a string + * source and not a file. + */ + + memset(gifConfPtr, 0, sizeof(GIFImageConfig)); + if (fileName == INLINE_DATA_BINARY || fileName == INLINE_DATA_BASE64) { + gifConfPtr->fromData = fileName; + fileName = "inline data"; + } + + /* + * Parse the format string to get options. + */ if (format && Tcl_ListObjGetElements(interp, format, &argc, &objv) != TCL_OK) { return TCL_ERROR; } for (i = 1; i < argc; i++) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name", 0, - &nBytes) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name", + 0, &nBytes) != TCL_OK) { return TCL_ERROR; } if (i == (argc-1)) { Tcl_AppendResult(interp, "no value given for \"", - Tcl_GetStringFromObj(objv[i], NULL), - "\" option", (char *) NULL); + Tcl_GetString(objv[i]), "\" option", NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[++i], &index) != TCL_OK) { return TCL_ERROR; } } - if (!ReadGIFHeader(chan, &fileWidth, &fileHeight)) { - Tcl_AppendResult(interp, "couldn't read GIF header from file \"", + + /* + * Read the GIF file header and check for some sanity. + */ + + if (!ReadGIFHeader(gifConfPtr, chan, &fileWidth, &fileHeight)) { + Tcl_AppendResult(interp, "couldn't read GIF header from file \"", fileName, "\"", NULL); return TCL_ERROR; } if ((fileWidth <= 0) || (fileHeight <= 0)) { Tcl_AppendResult(interp, "GIF image file \"", fileName, - "\" has dimension(s) <= 0", (char *) NULL); + "\" has dimension(s) <= 0", NULL); return TCL_ERROR; } - if (Fread(buf, 1, 3, chan) != 3) { + /* + * Get the general colormap information. + */ + + if (Fread(gifConfPtr, buf, 1, 3, chan) != 3) { return TCL_OK; } - bitPixel = 2<<(buf[0]&0x07); + bitPixel = 2 << (buf[0] & 0x07); if (BitSet(buf[0], LOCALCOLORMAP)) { /* Global Colormap */ - if (!ReadColorMap(chan, bitPixel, colorMap)) { - Tcl_AppendResult(interp, "error reading color map", - (char *) NULL); + if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) { + Tcl_AppendResult(interp, "error reading color map", NULL); return TCL_ERROR; } } @@ -308,85 +343,87 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY, return TCL_OK; } - Tk_PhotoExpand(imageHandle, destX + width, destY + height); + /* + * Make sure we have enough space in the photo image to hold the data from + * the GIF. + */ + + if (Tk_PhotoExpand(interp, imageHandle, + destX + width, destY + height) != TCL_OK) { + return TCL_ERROR; + } - block.width = width; - block.height = height; - block.pixelSize = 4; - block.pitch = block.pixelSize * block.width; - block.offset[0] = 0; - block.offset[1] = 1; - block.offset[2] = 2; - block.offset[3] = 3; - block.pixelPtr = NULL; + /* + * Search for the frame from the GIF to display. + */ while (1) { - if (Fread(buf, 1, 1, chan) != 1) { + if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) { /* * Premature end of image. */ - Tcl_AppendResult(interp,"premature end of image data for this index", - (char *) NULL); + Tcl_AppendResult(interp, + "premature end of image data for this index", NULL); goto error; } - if (buf[0] == GIF_TERMINATOR) { - /* - * GIF terminator. - */ - - Tcl_AppendResult(interp,"no image data for this index", - (char *) NULL); + switch (buf[0]) { + case GIF_TERMINATOR: + Tcl_AppendResult(interp, "no image data for this index", NULL); goto error; - } - if (buf[0] == GIF_EXTENSION) { + case GIF_EXTENSION: /* * This is a GIF extension. */ - if (Fread(buf, 1, 1, chan) != 1) { + if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) { Tcl_SetResult(interp, "error reading extension function code in GIF image", TCL_STATIC); goto error; } - if (DoExtension(chan, buf[0], &transparent) < 0) { + if (DoExtension(gifConfPtr, chan, buf[0], + gifConfPtr->workingBuffer, &transparent) < 0) { Tcl_SetResult(interp, "error reading extension in GIF image", TCL_STATIC); goto error; } continue; - } - - if (buf[0] != GIF_START) { + case GIF_START: + if (Fread(gifConfPtr, buf, 1, 9, chan) != 9) { + Tcl_SetResult(interp, + "couldn't read left/top/width/height in GIF image", + TCL_STATIC); + goto error; + } + break; + default: /* * Not a valid start character; ignore it. */ - continue; - } - if (Fread(buf, 1, 9, chan) != 9) { - Tcl_SetResult(interp, - "couldn't read left/top/width/height in GIF image", - TCL_STATIC); - goto error; + continue; } - imageWidth = LM_to_uint(buf[4],buf[5]); - imageHeight = LM_to_uint(buf[6],buf[7]); + /* + * We've read the header for a GIF frame. Work out what we are going + * to do about it. + */ - bitPixel = 1<<((buf[8]&0x07)+1); + imageWidth = LM_to_uint(buf[4], buf[5]); + imageHeight = LM_to_uint(buf[6], buf[7]); + bitPixel = 1 << ((buf[8] & 0x07) + 1); if (index--) { /* - * This is not the image we want to read: skip it. + * This is not the GIF frame we want to read: skip it. */ + if (BitSet(buf[8], LOCALCOLORMAP)) { - if (!ReadColorMap(chan, bitPixel, colorMap)) { - Tcl_AppendResult(interp, - "error reading color map", (char *) NULL); + if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) { + Tcl_AppendResult(interp, "error reading color map", NULL); goto error; } } @@ -394,113 +431,126 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY, /* * If we've not yet allocated a trash buffer, do so now. */ + if (trashBuffer == NULL) { nBytes = fileWidth * fileHeight * 3; - trashBuffer = - (unsigned char *) ckalloc((unsigned int) nBytes); + trashBuffer = (unsigned char *) ckalloc((unsigned) nBytes); } /* - * Slurp! Process the data for this image and stuff it in - * a trash buffer. + * Slurp! Process the data for this image and stuff it in a trash + * buffer. * - * Yes, it might be more efficient here to *not* store the - * data (we're just going to throw it away later). - * However, I elected to implement it this way for good - * reasons. First, I wanted to avoid duplicating the - * (fairly complex) LWZ decoder in ReadImage. Fine, you - * say, why didn't you just modify it to allow the use of - * a NULL specifier for the output buffer? I tried that, - * but it negatively impacted the performance of what I - * think will be the common case: reading the first image - * in the file. Rather than marginally improve the speed - * of the less frequent case, I chose to maintain high - * performance for the common case. + * Yes, it might be more efficient here to *not* store the data + * (we're just going to throw it away later). However, I elected + * to implement it this way for good reasons. First, I wanted to + * avoid duplicating the (fairly complex) LWZ decoder in + * ReadImage. Fine, you say, why didn't you just modify it to + * allow the use of a NULL specifier for the output buffer? I + * tried that, but it negatively impacted the performance of what + * I think will be the common case: reading the first image in the + * file. Rather than marginally improve the speed of the less + * frequent case, I chose to maintain high performance for the + * common case. */ - if (ReadImage(interp, (char *) trashBuffer, chan, imageWidth, - imageHeight, colorMap, 0, 0, 0, 0, 0, -1) != TCL_OK) { + + if (ReadImage(gifConfPtr, interp, trashBuffer, chan, imageWidth, + imageHeight, colorMap, 0, 0, 0, -1) != TCL_OK) { goto error; } continue; } + break; + } - if (BitSet(buf[8], LOCALCOLORMAP)) { - if (!ReadColorMap(chan, bitPixel, colorMap)) { - Tcl_AppendResult(interp, "error reading color map", - (char *) NULL); - goto error; - } - } + /* + * Found the frame we want to read. Next, check for a local color map for + * this frame. + */ - index = LM_to_uint(buf[0],buf[1]); - srcX -= index; - if (srcX<0) { - destX -= srcX; width += srcX; - srcX = 0; + if (BitSet(buf[8], LOCALCOLORMAP)) { + if (!ReadColorMap(gifConfPtr, chan, bitPixel, colorMap)) { + Tcl_AppendResult(interp, "error reading color map", NULL); + goto error; } + } - if (width > imageWidth) { - width = imageWidth; - } + /* + * Extract the location within the overall visible image to put the data + * in this frame, together with the size of this frame. + */ - index = LM_to_uint(buf[2],buf[3]); - srcY -= index; - if (index > srcY) { - destY -= srcY; height += srcY; - srcY = 0; - } - if (height > imageHeight) { - height = imageHeight; - } + index = LM_to_uint(buf[0], buf[1]); + srcX -= index; + if (srcX<0) { + destX -= srcX; width += srcX; + srcX = 0; + } - if ((width <= 0) || (height <= 0)) { - block.pixelPtr = 0; - goto noerror; - } + if (width > imageWidth) { + width = imageWidth; + } + + index = LM_to_uint(buf[2], buf[3]); + srcY -= index; + if (index > srcY) { + destY -= srcY; height += srcY; + srcY = 0; + } + if (height > imageHeight) { + height = imageHeight; + } + + if ((width > 0) && (height > 0)) { + Tk_PhotoImageBlock block; + + /* + * Read the data and put it into the photo buffer for display by the + * general image machinery. + */ block.width = width; block.height = height; block.pixelSize = (transparent>=0) ? 4 : 3; + block.offset[0] = 0; + block.offset[1] = 1; + block.offset[2] = 2; block.offset[3] = (transparent>=0) ? 3 : 0; block.pitch = block.pixelSize * imageWidth; nBytes = block.pitch * imageHeight; block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes); - if (ReadImage(interp, (char *) block.pixelPtr, chan, imageWidth, - imageHeight, colorMap, fileWidth, fileHeight, srcX, srcY, - BitSet(buf[8], INTERLACE), transparent) != TCL_OK) { + if (ReadImage(gifConfPtr, interp, block.pixelPtr, chan, imageWidth, + imageHeight, colorMap, srcX, srcY, BitSet(buf[8],INTERLACE), + transparent) != TCL_OK) { + ckfree((char *) block.pixelPtr); goto error; } - break; + if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY, + width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) { + ckfree((char *) block.pixelPtr); + goto error; + } + ckfree((char *) block.pixelPtr); } - Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height, - TK_PHOTO_COMPOSITE_SET); - - noerror: /* - * If a trash buffer has been allocated, free it now. + * We've successfully read the GIF frame (or there was nothing to read, + * which suits as well). We're done. */ - if (trashBuffer != NULL) { - ckfree((char *)trashBuffer); - } - if (block.pixelPtr) { - ckfree((char *) block.pixelPtr); - } - Tcl_AppendResult(interp, tkImgFmtGIF.name, (char *) NULL); - return TCL_OK; - error: + Tcl_AppendResult(interp, tkImgFmtGIF.name, NULL); + result = TCL_OK; + + error: /* * If a trash buffer has been allocated, free it now. */ + if (trashBuffer != NULL) { - ckfree((char *)trashBuffer); - } - if (block.pixelPtr) { - ckfree((char *) block.pixelPtr); + ckfree((char *) trashBuffer); } - return TCL_ERROR; + return result; } /* @@ -508,26 +558,26 @@ FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY, * * StringMatchGIF -- * - * This procedure is invoked by the photo image type to see if - * an object contains image data in GIF format. + * This function is invoked by the photo image type to see if an object + * contains image data in GIF format. * * Results: - * The return value is 1 if the first characters in the data are - * like GIF data, and 0 otherwise. + * The return value is 1 if the first characters in the data are like GIF + * data, and 0 otherwise. * * Side effects: - * the size of the image is placed in widthPre and heightPtr. + * The size of the image is placed in widthPtr and heightPtr. * *---------------------------------------------------------------------- */ static int -StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp) - Tcl_Obj *dataObj; /* the object containing the image data */ - Tcl_Obj *format; /* the image format object, or NULL */ - int *widthPtr; /* where to put the string width */ - int *heightPtr; /* where to put the string height */ - Tcl_Interp *interp; /* not used */ +StringMatchGIF( + Tcl_Obj *dataObj, /* the object containing the image data */ + Tcl_Obj *format, /* the image format object, or NULL */ + int *widthPtr, /* where to put the string width */ + int *heightPtr, /* where to put the string height */ + Tcl_Interp *interp) /* not used */ { unsigned char *data, header[10]; int got, length; @@ -538,6 +588,7 @@ StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp) /* * Header is a minimum of 10 bytes. */ + if (length < 10) { return 0; } @@ -546,97 +597,99 @@ StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp) * Check whether the data is Base64 encoded. */ - if ((strncmp(GIF87a, (char *) data, 6) != 0) && + if ((strncmp(GIF87a, (char *) data, 6) != 0) && (strncmp(GIF89a, (char *) data, 6) != 0)) { /* * Try interpreting the data as Base64 encoded */ - mInit((unsigned char *) data, length, &handle); + + mInit((unsigned char *) data, &handle, length); got = Mread(header, 10, 1, &handle); - if (got != 10 - || ((strncmp(GIF87a, (char *) header, 6) != 0) + if (got != 10 || + ((strncmp(GIF87a, (char *) header, 6) != 0) && (strncmp(GIF89a, (char *) header, 6) != 0))) { return 0; } } else { - memcpy((VOID *) header, (VOID *) data, 10); + memcpy(header, data, 10); } - *widthPtr = LM_to_uint(header[6],header[7]); - *heightPtr = LM_to_uint(header[8],header[9]); + *widthPtr = LM_to_uint(header[6], header[7]); + *heightPtr = LM_to_uint(header[8], header[9]); return 1; } /* *---------------------------------------------------------------------- * - * StringReadGif -- -- + * StringReadGIF -- * - * This procedure is called by the photo image type to read - * GIF format data from an object, optionally base64 encoded, - * and give it to the photo image. + * This function is called by the photo image type to read GIF format + * data from an object, optionally base64 encoded, and give it to the + * photo image. * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. * * Side effects: - * new data is added to the image given by imageHandle. This - * procedure calls FileReadGif by redefining the operation of - * fprintf temporarily. + * New data is added to the image given by imageHandle. This function + * calls FileReadGIF by redefining the operation of fprintf temporarily. * *---------------------------------------------------------------------- */ static int -StringReadGIF(interp, dataObj, format, imageHandle, - destX, destY, width, height, srcX, srcY) - Tcl_Interp *interp; /* interpreter for reporting errors in */ - Tcl_Obj *dataObj; /* object containing the image */ - Tcl_Obj *format; /* format object, or NULL */ - Tk_PhotoHandle imageHandle; /* the image to write this data into */ - int destX, destY; /* The rectangular region of the */ - int width, height; /* image to copy */ - int srcX, srcY; +StringReadGIF( + Tcl_Interp *interp, /* interpreter for reporting errors in */ + Tcl_Obj *dataObj, /* object containing the image */ + Tcl_Obj *format, /* format object, or NULL */ + Tk_PhotoHandle imageHandle, /* the image to write this data into */ + int destX, int destY, /* The rectangular region of the */ + int width, int height, /* image to copy */ + int srcX, int srcY) { - int result, length; - MFile handle; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - Tcl_Channel dataSrc; - char *data; + MFile handle, *hdlPtr = &handle; + int length; + const char *xferFormat; + unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length); + + mInit(data, hdlPtr, length); /* - * Check whether the data is Base64 encoded + * Check whether the data is Base64 encoded by doing a character-by- + * charcter comparison with the binary-format headers; BASE64-encoded + * never matches (matching the other way is harder because of potential + * padding of the BASE64 data). */ - data = (char *) Tcl_GetByteArrayFromObj(dataObj, &length); - if ((strncmp(GIF87a, data, 6) != 0) && (strncmp(GIF89a, data, 6) != 0)) { - mInit((unsigned char *)data, length, &handle); - tsdPtr->fromData = 1; - dataSrc = (Tcl_Channel) &handle; + + if (strncmp(GIF87a, (char *) data, 6) + && strncmp(GIF89a, (char *) data, 6)) { + xferFormat = INLINE_DATA_BASE64; } else { - tsdPtr->fromData = 2; - mInit((unsigned char *)data, length, &handle); - dataSrc = (Tcl_Channel) &handle; + xferFormat = INLINE_DATA_BINARY; } - result = FileReadGIF(interp, dataSrc, "inline data", - format, imageHandle, destX, destY, width, height, srcX, srcY); - tsdPtr->fromData = 0; - return result; -} + /* + * Fall through to the file reader now that we have a correctly-configured + * pseudo-channel to pull the data from. + */ + + return FileReadGIF(interp, (Tcl_Channel) hdlPtr, xferFormat, format, + imageHandle, destX, destY, width, height, srcX, srcY); +} + /* *---------------------------------------------------------------------- * * ReadGIFHeader -- * - * This procedure reads the GIF header from the beginning of a - * GIF file and returns the dimensions of the image. + * This function reads the GIF header from the beginning of a GIF file + * and returns the dimensions of the image. * * Results: - * The return value is 1 if file "f" appears to start with - * a valid GIF header, 0 otherwise. If the header is valid, - * then *widthPtr and *heightPtr are modified to hold the - * dimensions of the image. + * The return value is 1 if file "f" appears to start with a valid GIF + * header, 0 otherwise. If the header is valid, then *widthPtr and + * *heightPtr are modified to hold the dimensions of the image. * * Side effects: * The access position in f advances. @@ -645,68 +698,70 @@ StringReadGIF(interp, dataObj, format, imageHandle, */ static int -ReadGIFHeader(chan, widthPtr, heightPtr) - Tcl_Channel chan; /* Image file to read the header from */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ +ReadGIFHeader( + GIFImageConfig *gifConfPtr, + Tcl_Channel chan, /* Image file to read the header from */ + int *widthPtr, int *heightPtr) + /* The dimensions of the image are returned + * here. */ { unsigned char buf[7]; - if ((Fread(buf, 1, 6, chan) != 6) + if ((Fread(gifConfPtr, buf, 1, 6, chan) != 6) || ((strncmp(GIF87a, (char *) buf, 6) != 0) && (strncmp(GIF89a, (char *) buf, 6) != 0))) { return 0; } - if (Fread(buf, 1, 4, chan) != 4) { + if (Fread(gifConfPtr, buf, 1, 4, chan) != 4) { return 0; } - *widthPtr = LM_to_uint(buf[0],buf[1]); - *heightPtr = LM_to_uint(buf[2],buf[3]); + *widthPtr = LM_to_uint(buf[0], buf[1]); + *heightPtr = LM_to_uint(buf[2], buf[3]); return 1; } - + /* *----------------------------------------------------------------- - * The code below is copied from the giftoppm program and modified - * just slightly. + * The code below is copied from the giftoppm program and modified just + * slightly. *----------------------------------------------------------------- */ static int -ReadColorMap(chan, number, buffer) - Tcl_Channel chan; - int number; - unsigned char buffer[MAXCOLORMAPSIZE][4]; +ReadColorMap( + GIFImageConfig *gifConfPtr, + Tcl_Channel chan, + int number, + unsigned char buffer[MAXCOLORMAPSIZE][4]) { int i; unsigned char rgb[3]; for (i = 0; i < number; ++i) { - if (! ReadOK(chan, rgb, sizeof(rgb))) { + if (Fread(gifConfPtr, rgb, sizeof(rgb), 1, chan) <= 0) { return 0; } if (buffer) { - buffer[i][CM_RED] = rgb[0] ; - buffer[i][CM_GREEN] = rgb[1] ; - buffer[i][CM_BLUE] = rgb[2] ; - buffer[i][CM_ALPHA] = 255 ; + buffer[i][CM_RED] = rgb[0]; + buffer[i][CM_GREEN] = rgb[1]; + buffer[i][CM_BLUE] = rgb[2]; + buffer[i][CM_ALPHA] = 255; } } return 1; } - - - + static int -DoExtension(chan, label, transparent) - Tcl_Channel chan; - int label; - int *transparent; +DoExtension( + GIFImageConfig *gifConfPtr, + Tcl_Channel chan, + int label, + unsigned char *buf, + int *transparent) { - static unsigned char buf[256]; int count; switch (label) { @@ -718,12 +773,12 @@ DoExtension(chan, label, transparent) case 0xfe: /* Comment Extension */ do { - count = GetDataBlock(chan, (unsigned char*) buf); + count = GetDataBlock(gifConfPtr, chan, buf); } while (count > 0); return count; case 0xf9: /* Graphic Control Extension */ - count = GetDataBlock(chan, (unsigned char*) buf); + count = GetDataBlock(gifConfPtr, chan, buf); if (count < 0) { return 1; } @@ -732,53 +787,52 @@ DoExtension(chan, label, transparent) } do { - count = GetDataBlock(chan, (unsigned char*) buf); + count = GetDataBlock(gifConfPtr, chan, buf); } while (count > 0); return count; } do { - count = GetDataBlock(chan, (unsigned char*) buf); + count = GetDataBlock(gifConfPtr, chan, buf); } while (count > 0); return count; } - + static int -GetDataBlock(chan, buf) - Tcl_Channel chan; - unsigned char *buf; +GetDataBlock( + GIFImageConfig *gifConfPtr, + Tcl_Channel chan, + unsigned char *buf) { unsigned char count; - if (! ReadOK(chan, &count,1)) { + if (Fread(gifConfPtr, &count, 1, 1, chan) <= 0) { return -1; } - if ((count != 0) && (! ReadOK(chan, buf, count))) { + if ((count != 0) && (Fread(gifConfPtr, buf, count, 1, chan) <= 0)) { return -1; } return count; } - - /* *---------------------------------------------------------------------- * * ReadImage -- * - * Process a GIF image from a given source, with a given height, - * width, transparency, etc. + * Process a GIF image from a given source, with a given height, width, + * transparency, etc. * * This code is based on the code found in the ImageMagick GIF decoder, * which is (c) 2000 ImageMagick Studio. * * Some thoughts on our implementation: - * It sure would be nice if ReadImage didn't take 11 parameters! I think + * It sure would be nice if ReadImage didn't take 11 parameters! I think * that if we were smarter, we could avoid doing that. * - * Possible further optimizations: we could pull the GetCode function + * Possible further optimizations: we could pull the GetCode function * directly into ReadImage, which would improve our speed. * * Results: @@ -791,37 +845,36 @@ GetDataBlock(chan, buf) */ static int -ReadImage(interp, imagePtr, chan, len, rows, cmap, - width, height, srcX, srcY, interlace, transparent) - Tcl_Interp *interp; - char *imagePtr; - Tcl_Channel chan; - int len, rows; - unsigned char cmap[MAXCOLORMAPSIZE][4]; - int width, height; - int srcX, srcY; - int interlace; - int transparent; +ReadImage( + GIFImageConfig *gifConfPtr, + Tcl_Interp *interp, + unsigned char *imagePtr, + Tcl_Channel chan, + int len, int rows, + unsigned char cmap[MAXCOLORMAPSIZE][4], + int srcX, int srcY, + int interlace, + int transparent) { unsigned char initialCodeSize; - int v; int xpos = 0, ypos = 0, pass = 0, i; - register char *pixelPtr; - static CONST int interlaceStep[] = { 8, 8, 4, 2 }; - static CONST int interlaceStart[] = { 0, 4, 2, 1 }; + register unsigned char *pixelPtr; + static const int interlaceStep[] = { 8, 8, 4, 2 }; + static const int interlaceStart[] = { 0, 4, 2, 1 }; unsigned short prefix[(1 << MAX_LWZ_BITS)]; - unsigned char append[(1 << MAX_LWZ_BITS)]; - unsigned char stack[(1 << MAX_LWZ_BITS)*2]; + unsigned char append[(1 << MAX_LWZ_BITS)]; + unsigned char stack[(1 << MAX_LWZ_BITS)*2]; register unsigned char *top; int codeSize, clearCode, inCode, endCode, oldCode, maxCode; - int code, firstCode; + int code, firstCode, v; /* - * Initialize the decoder + * Initialize the decoder */ - if (! ReadOK(chan, &initialCodeSize, 1)) { + + if (Fread(gifConfPtr, &initialCodeSize, 1, 1, chan) <= 0) { Tcl_AppendResult(interp, "error reading GIF image: ", - Tcl_PosixError(interp), (char *) NULL); + Tcl_PosixError(interp), NULL); return TCL_ERROR; } @@ -848,46 +901,49 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, * code size size of the next code to retrieve * max code next available table position */ + clearCode = 1 << (int) initialCodeSize; endCode = clearCode + 1; codeSize = (int) initialCodeSize + 1; maxCode = clearCode + 2; oldCode = -1; firstCode = -1; - - memset((void *)prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short)); - memset((void *)append, 0, (1 << MAX_LWZ_BITS) * sizeof(char)); + + memset(prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short)); + memset(append, 0, (1 << MAX_LWZ_BITS) * sizeof(char)); for (i = 0; i < clearCode; i++) { append[i] = i; } top = stack; - GetCode(chan, 0, 1); + GetCode(chan, 0, 1, gifConfPtr); /* * Read until we finish the image */ + for (i = 0, ypos = 0; i < rows; i++) { for (xpos = 0; xpos < len; ) { - if (top == stack) { /* - * Bummer -- our stack is empty. Now we have to work! + * Bummer - our stack is empty. Now we have to work! */ - code = GetCode(chan, codeSize, 0); + + code = GetCode(chan, codeSize, 0, gifConfPtr); if (code < 0) { return TCL_OK; } if (code > maxCode || code == endCode) { /* - * If we're doing things right, we should never - * receive a code that is greater than our current - * maximum code. If we do, bail, because our decoder - * does not yet have that code set up. + * If we're doing things right, we should never receive a + * code that is greater than our current maximum code. If + * we do, bail, because our decoder does not yet have that + * code set up. * * If the code is the magic endCode value, quit. */ + return TCL_OK; } @@ -895,44 +951,48 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, /* * Reset the decoder. */ + codeSize = initialCodeSize + 1; maxCode = clearCode + 2; oldCode = -1; continue; } - + if (oldCode == -1) { /* - * 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. + * 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. */ + *top++ = append[code]; oldCode = code; firstCode = code; continue; } - + inCode = code; if (code == maxCode) { /* * 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. ??? + * code. If the code we see is equal to maxCode, then we + * are about to add a new string to the table. ??? */ + *top++ = firstCode; code = oldCode; } while (code > clearCode) { /* - * Populate the stack by tracing the string in the - * string table from its tail to its head + * Populate the stack by tracing the string in the string + * table from its tail to its head */ + *top++ = append[code]; code = prefix[code]; } @@ -942,6 +1002,7 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, * If there's no more room in our string table, quit. * Otherwise, add a new string to the table */ + if (maxCode >= (1 << MAX_LWZ_BITS)) { return TCL_OK; } @@ -949,21 +1010,24 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, /* * Push the head of the string onto the stack. */ + *top++ = firstCode; /* * Add a new string to the string table */ + prefix[maxCode] = oldCode; append[maxCode] = firstCode; maxCode++; /* - * maxCode tells us the maximum code value we can accept. - * If we see that we need more bits to represent it than - * we are requesting from the unpacker, we need to increase - * the number we ask for. + * maxCode tells us the maximum code value we can accept. If + * we see that we need more bits to represent it than we are + * requesting from the unpacker, we need to increase the + * number we ask for. */ + if ((maxCode >= (1 << codeSize)) && (maxCode < (1<<MAX_LWZ_BITS))) { codeSize++; @@ -974,16 +1038,18 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, /* * Pop the next color index off the stack. */ + v = *(--top); if (v < 0) { return TCL_OK; } - /* + /* * If pixelPtr is null, we're skipping this image (presumably - * there are more in the file and we will be called to read - * one of them later) + * there are more in the file and we will be called to read one of + * them later) */ + *pixelPtr++ = cmap[v][CM_RED]; *pixelPtr++ = cmap[v][CM_GREEN]; *pixelPtr++ = cmap[v][CM_BLUE]; @@ -995,8 +1061,9 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, } /* - * If interlacing, the next ypos is not just +1 + * If interlacing, the next ypos is not just +1. */ + if (interlace) { ypos += interlaceStep[pass]; while (ypos >= rows) { @@ -1013,27 +1080,25 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, } return TCL_OK; } - /* *---------------------------------------------------------------------- * * GetCode -- * - * Extract the next compression code from the file. In GIF's, the - * compression codes are between 3 and 12 bits long and are then - * packed into 8 bit bytes, left to right, for example: + * Extract the next compression code from the file. In GIF's, the + * compression codes are between 3 and 12 bits long and are then packed + * into 8 bit bytes, left to right, for example: * bbbaaaaa * dcccccbb * eeeedddd * ... - * We use a byte buffer read from the file and a sliding window - * to unpack the bytes. Thanks to ImageMagick for the sliding window - * idea. + * We use a byte buffer read from the file and a sliding window to unpack + * the bytes. Thanks to ImageMagick for the sliding window idea. * args: chan the channel to read from * code_size size of the code to extract - * flag boolean indicating whether the extractor - * should be reset or not + * flag boolean indicating whether the extractor should be + * reset or not * * Results: * code the next compression code @@ -1045,69 +1110,72 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap, */ static int -GetCode(chan, code_size, flag) - Tcl_Channel chan; - int code_size; - int flag; +GetCode( + Tcl_Channel chan, + int code_size, + int flag, + GIFImageConfig *gifConfPtr) { - static unsigned char buf[280]; - static int bytes = 0, done; - static unsigned char *c; - - static unsigned int window; - static int bitsInWindow = 0; int ret; - + if (flag) { /* * Initialize the decoder. */ - bitsInWindow = 0; - bytes = 0; - window = 0; - done = 0; - c = NULL; + + gifConfPtr->reader.bitsInWindow = 0; + gifConfPtr->reader.bytes = 0; + gifConfPtr->reader.window = 0; + gifConfPtr->reader.done = 0; + gifConfPtr->reader.c = NULL; return 0; } - while (bitsInWindow < code_size) { + while (gifConfPtr->reader.bitsInWindow < code_size) { /* * Not enough bits in our window to cover the request. */ - if (done) { + + if (gifConfPtr->reader.done) { return -1; } - if (bytes == 0) { + if (gifConfPtr->reader.bytes == 0) { /* * Not enough bytes in our buffer to add to the window. */ - bytes = GetDataBlock(chan, buf); - c = buf; - if (bytes <= 0) { - done = 1; + + gifConfPtr->reader.bytes = + GetDataBlock(gifConfPtr, chan, gifConfPtr->workingBuffer); + gifConfPtr->reader.c = gifConfPtr->workingBuffer; + if (gifConfPtr->reader.bytes <= 0) { + gifConfPtr->reader.done = 1; break; } } + /* * Tack another byte onto the window, see if that's enough. */ - window += (*c) << bitsInWindow; - c++; - bitsInWindow += 8; - bytes--; - } + gifConfPtr->reader.window += + (*gifConfPtr->reader.c) << gifConfPtr->reader.bitsInWindow; + gifConfPtr->reader.c++; + gifConfPtr->reader.bitsInWindow += 8; + gifConfPtr->reader.bytes--; + } /* * The next code will always be the last code_size bits of the window. */ - ret = window & ((1 << code_size) - 1); - + + ret = gifConfPtr->reader.window & ((1 << code_size) - 1); + /* * Shift data in the window to put the next code at the end. */ - window >>= code_size; - bitsInWindow -= code_size; + + gifConfPtr->reader.window >>= code_size; + gifConfPtr->reader.bitsInWindow -= code_size; return ret; } @@ -1116,27 +1184,27 @@ GetCode(chan, code_size, flag) * * Minit -- -- * - * This procedure initializes a base64 decoder handle + * This function initializes a base64 decoder handle * * Results: - * none + * None * * Side effects: - * the base64 handle is initialized + * The base64 handle is initialized * *---------------------------------------------------------------------- */ static void -mInit(string, length, handle) - unsigned char *string; /* string containing initial mmencoded data */ - int length; /* Length of string */ - MFile *handle; /* mmdecode "file" handle */ +mInit( + unsigned char *string, /* string containing initial mmencoded data */ + MFile *handle, /* mmdecode "file" handle */ + int length) /* Number of bytes in string */ { handle->data = string; - handle->length = length; handle->state = 0; handle->c = 0; + handle->length = length; } /* @@ -1144,9 +1212,9 @@ mInit(string, length, handle) * * Mread -- * - * This procedure is invoked by the GIF file reader as a - * temporary replacement for "fread", to get GIF data out - * of a string (using Mgetc). + * This function is invoked by the GIF file reader as a temporary + * replacement for "fread", to get GIF data out of a string (using + * Mgetc). * * Results: * The return value is the number of characters "read" @@ -1158,50 +1226,45 @@ mInit(string, length, handle) */ static int -Mread(dst, chunkSize, numChunks, handle) - 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 */ +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; - for(i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) { + for (i=0; i<count && (c=Mgetc(handle)) != GIF_DONE; i++) { *dst++ = c; } return i; } - -/* - * get the next decoded character from an mmencode handle - * This causes at least 1 character to be "read" from the encoded string - */ /* *---------------------------------------------------------------------- * * Mgetc -- * - * This procedure decodes and returns the next byte from a base64 - * encoded string. + * This function gets the next decoded character from an mmencode handle. + * This causes at least 1 character to be "read" from the encoded string. * * Results: - * The next byte (or GIF_DONE) is returned. + * The next byte (or GIF_DONE) is returned. * * Side effects: - * The base64 handle will change state. + * The base64 handle will change state. * *---------------------------------------------------------------------- */ static int -Mgetc(handle) - MFile *handle; /* Handle containing decoder data and state */ +Mgetc( + MFile *handle) /* Handle containing decoder data and state */ { int c; - int result = 0; /* Initialization needed only to prevent - * gcc compiler warning. */ + int result = 0; /* Initialization needed only to prevent gcc + * compiler warning. */ if (handle->state == GIF_DONE) { return GIF_DONE; @@ -1209,7 +1272,6 @@ Mgetc(handle) do { if (handle->length-- <= 0) { - handle->state = GIF_DONE; return GIF_DONE; } c = char64(*handle->data); @@ -1247,21 +1309,22 @@ Mgetc(handle) * * char64 -- * - * This procedure converts a base64 ascii character into its binary - * equivalent. This code is a slightly modified version of the - * char64 proc in N. Borenstein's metamail decoder. + * This function converts a base64 ascii character into its binary + * equivalent. This code is a slightly modified version of the char64 + * function in N. Borenstein's metamail decoder. * * Results: * The binary value, or an error code. * * Side effects: * None. + * *---------------------------------------------------------------------- */ static int -char64(c) -int c; +char64( + int c) { switch(c) { case 'A': return 0; case 'B': return 1; case 'C': return 2; @@ -1303,52 +1366,53 @@ int c; * * Fread -- * - * This procedure calls either fread or Mread to read data - * from a file or a base64 encoded string. + * This function calls either fread or Mread to read data from a file or + * a base64 encoded string. * - * Results: - same as fread + * Results: - same as POSIX fread() or Tcl Tcl_Read() * *---------------------------------------------------------------------- */ static int -Fread(dst, hunk, count, chan) - unsigned char *dst; /* where to put the result */ - size_t hunk,count; /* how many */ - Tcl_Channel chan; +Fread( + GIFImageConfig *gifConfPtr, + unsigned char *dst, /* where to put the result */ + size_t hunk, size_t count, /* how many */ + Tcl_Channel chan) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - MFile *handle; - - switch (tsdPtr->fromData) { - case 1: + if (gifConfPtr->fromData == INLINE_DATA_BASE64) { return Mread(dst, hunk, count, (MFile *) chan); - case 2: - handle = (MFile *) chan; - if (handle->length <= 0 || (size_t)handle->length < (size_t) (hunk * count)) { + } + + if (gifConfPtr->fromData == INLINE_DATA_BINARY) { + MFile *handle = (MFile *) chan; + + if (handle->length <= 0 || (size_t) handle->length < hunk*count) { return -1; } - memcpy((VOID *)dst, (VOID *) handle->data, (size_t) (hunk * count)); + memcpy(dst, handle->data, (size_t) (hunk * count)); handle->data += hunk * count; - handle->length -= hunk * count; return (int)(hunk * count); - default: - return Tcl_Read(chan, (char *) dst, (int) (hunk * count)); } -} + /* + * Otherwise we've got a real file to read. + */ + + return Tcl_Read(chan, (char *) dst, (int) (hunk * count)); +} /* * ChanWriteGIF - writes a image in GIF format. *------------------------------------------------------------------------- - * Author: Lolo - * Engeneering Projects Area - * Department of Mining - * University of Oviedo - * e-mail zz11425958@zeus.etsimo.uniovi.es - * lolo@pcsig22.etsimo.uniovi.es - * Date: Fri September 20 1996 + * Author: Lolo + * Engeneering Projects Area + * Department of Mining + * University of Oviedo + * e-mail zz11425958@zeus.etsimo.uniovi.es + * lolo@pcsig22.etsimo.uniovi.es + * Date: Fri September 20 1996 * * Modified for transparency handling (gif89a) and miGIF compression * by Jan Nijtmans <j.nijtmans@chello.nl> @@ -1356,60 +1420,65 @@ Fread(dst, hunk, count, chan) *---------------------------------------------------------------------- * FileWriteGIF- * - * This procedure is called by the photo image type to write - * GIF format data from a photo image into a given file + * This function is called by the photo image type to write GIF format + * data from a photo image into a given file * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in interp->result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in interp->result. * *---------------------------------------------------------------------- */ - /* - * Types, defines and variables needed to write and compress a GIF. - */ - -typedef int (* ifunptr) _ANSI_ARGS_((void)); - -#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF)) -#define MSB(a) ((unsigned char) (((short)(a)) >> 8)) - -#define GIFBITS 12 -#define HSIZE 5003 /* 80% occupancy */ +/* + * Types, defines and variables needed to write and compress a GIF. + */ -static int ssize; -static int csize; -static int rsize; -static unsigned char *pixelo; -static int pixelSize; -static int pixelPitch; -static int greenOffset; -static int blueOffset; -static int alphaOffset; -static int num; -static unsigned char mapa[MAXCOLORMAPSIZE][3]; +typedef int (* ifunptr) (ClientData clientData); + +#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF)) +#define MSB(a) ((unsigned char) (((short)(a)) >> 8)) + +#define GIFBITS 12 +#define HSIZE 5003 /* 80% occupancy */ + +typedef struct { + int ssize; + int csize; + int rsize; + unsigned char *pixelo; + int pixelSize; + int pixelPitch; + int greenOffset; + int blueOffset; + int alphaOffset; + int num; + unsigned char mapa[MAXCOLORMAPSIZE][3]; +} GifWriterState; /* - * Definition of new functions to write GIFs + * Definition of new functions to write GIFs */ -static int color _ANSI_ARGS_((int red,int green, int blue, - unsigned char mapa[MAXCOLORMAPSIZE][3])); -static void compress _ANSI_ARGS_((int init_bits, Tcl_Channel handle, - ifunptr readValue)); -static int nuevo _ANSI_ARGS_((int red, int green ,int blue, - unsigned char mapa[MAXCOLORMAPSIZE][3])); -static void savemap _ANSI_ARGS_((Tk_PhotoImageBlock *blockPtr, - unsigned char mapa[MAXCOLORMAPSIZE][3])); -static int ReadValue _ANSI_ARGS_((void)); - +static int color(GifWriterState *statePtr, + int red, int green, int blue, + unsigned char mapa[MAXCOLORMAPSIZE][3]); +static void compress(int initBits, Tcl_Channel handle, + ifunptr readValue, ClientData clientData); +static int nuevo(GifWriterState *statePtr, + int red, int green, int blue, + unsigned char mapa[MAXCOLORMAPSIZE][3]); +static void savemap(GifWriterState *statePtr, + Tk_PhotoImageBlock *blockPtr, + unsigned char mapa[MAXCOLORMAPSIZE][3]); +static int ReadValue(ClientData clientData); + static int -FileWriteGIF(interp, filename, format, blockPtr) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - CONST char *filename; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; +FileWriteGIF( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + const char *filename, + Tcl_Obj *format, + Tk_PhotoImageBlock *blockPtr) { Tcl_Channel chan = NULL; int result; @@ -1418,167 +1487,168 @@ FileWriteGIF(interp, filename, format, blockPtr) if (!chan) { return TCL_ERROR; } - if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) { + if (Tcl_SetChannelOption(interp, chan, "-translation", + "binary") != TCL_OK) { Tcl_Close(NULL, chan); return TCL_ERROR; } result = CommonWriteGIF(interp, chan, format, blockPtr); + if (Tcl_Close(interp, chan) == TCL_ERROR) { return TCL_ERROR; } return result; } - -#define Mputc(c,handle) Tcl_Write(handle,(char *) &c,1) - + static int -CommonWriteGIF(interp, handle, format, blockPtr) - Tcl_Interp *interp; - Tcl_Channel handle; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; +CommonWriteGIF( + Tcl_Interp *interp, + Tcl_Channel handle, + Tcl_Obj *format, + Tk_PhotoImageBlock *blockPtr) { - int resolution; - - long width,height,x; + GifWriterState state, *statePtr = &state; + int resolution; + long width, height, x; unsigned char c; - unsigned int top,left; + unsigned int top, left; top = 0; left = 0; - pixelSize = blockPtr->pixelSize; - greenOffset = blockPtr->offset[1]-blockPtr->offset[0]; - blueOffset = blockPtr->offset[2]-blockPtr->offset[0]; - alphaOffset = blockPtr->offset[0]; - if (alphaOffset < blockPtr->offset[2]) { - alphaOffset = blockPtr->offset[2]; + memset(statePtr, 0, sizeof(state)); + + statePtr->pixelSize = blockPtr->pixelSize; + statePtr->greenOffset = blockPtr->offset[1]-blockPtr->offset[0]; + statePtr->blueOffset = blockPtr->offset[2]-blockPtr->offset[0]; + statePtr->alphaOffset = blockPtr->offset[0]; + if (statePtr->alphaOffset < blockPtr->offset[2]) { + statePtr->alphaOffset = blockPtr->offset[2]; } - if (++alphaOffset < pixelSize) { - alphaOffset -= blockPtr->offset[0]; + if (++statePtr->alphaOffset < statePtr->pixelSize) { + statePtr->alphaOffset -= blockPtr->offset[0]; } else { - alphaOffset = 0; + statePtr->alphaOffset = 0; } - Tcl_Write(handle, (char *) (alphaOffset ? GIF89a : GIF87a), 6); + Tcl_Write(handle, (char *) (statePtr->alphaOffset ? GIF89a : GIF87a), 6); for (x=0 ; x<MAXCOLORMAPSIZE ; x++) { - mapa[x][CM_RED] = 255; - mapa[x][CM_GREEN] = 255; - mapa[x][CM_BLUE] = 255; + statePtr->mapa[x][CM_RED] = 255; + statePtr->mapa[x][CM_GREEN] = 255; + statePtr->mapa[x][CM_BLUE] = 255; } - width = blockPtr->width; height = blockPtr->height; - pixelo = blockPtr->pixelPtr + blockPtr->offset[0]; - pixelPitch = blockPtr->pitch; - savemap(blockPtr,mapa); - if (num >= MAXCOLORMAPSIZE) { - Tcl_AppendResult(interp, "too many colors", (char *) NULL); + statePtr->pixelo = blockPtr->pixelPtr + blockPtr->offset[0]; + statePtr->pixelPitch = blockPtr->pitch; + savemap(statePtr, blockPtr, statePtr->mapa); + if (statePtr->num >= MAXCOLORMAPSIZE) { + Tcl_AppendResult(interp, "too many colors", NULL); return TCL_ERROR; } - if (num<2) { - num = 2; + if (statePtr->num<2) { + statePtr->num = 2; } c = LSB(width); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = MSB(width); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = LSB(height); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = MSB(height); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); resolution = 0; - while (num >> resolution) { + while (statePtr->num >> resolution) { resolution++; } c = 111 + resolution * 17; - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); - num = 1 << resolution; + statePtr->num = 1 << resolution; /* - * background color + * Background color */ c = 0; - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); /* - * zero for future expansion. + * Zero for future expansion. */ - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); - for (x=0 ; x<num ; x++) { - c = mapa[x][CM_RED]; - Mputc(c,handle); - c = mapa[x][CM_GREEN]; - Mputc(c,handle); - c = mapa[x][CM_BLUE]; - Mputc(c,handle); + for (x=0 ; x<statePtr->num ; x++) { + c = statePtr->mapa[x][CM_RED]; + Tcl_Write(handle, (char *) &c, 1); + c = statePtr->mapa[x][CM_GREEN]; + Tcl_Write(handle, (char *) &c, 1); + c = statePtr->mapa[x][CM_BLUE]; + Tcl_Write(handle, (char *) &c, 1); } /* * Write out extension for transparent colour index, if necessary. */ - if (alphaOffset) { + if (statePtr->alphaOffset) { c = GIF_EXTENSION; - Mputc(c, handle); + Tcl_Write(handle, (char *) &c, 1); Tcl_Write(handle, "\371\4\1\0\0\0", 7); } c = GIF_START; - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = LSB(top); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = MSB(top); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = LSB(left); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = MSB(left); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = LSB(width); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = MSB(width); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = LSB(height); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = MSB(height); - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = 0; - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); c = resolution; - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); - ssize = rsize = blockPtr->width; - csize = blockPtr->height; - compress(resolution+1, handle, ReadValue); + statePtr->ssize = statePtr->rsize = blockPtr->width; + statePtr->csize = blockPtr->height; + compress(resolution+1, handle, ReadValue, (ClientData) statePtr); - c = 0; - Mputc(c,handle); + c = 0; + Tcl_Write(handle, (char *) &c, 1); c = GIF_TERMINATOR; - Mputc(c,handle); + Tcl_Write(handle, (char *) &c, 1); - return TCL_OK; + return TCL_OK; } - + static int -color(red, green, blue, mapa) - int red; - int green; - int blue; - unsigned char mapa[MAXCOLORMAPSIZE][3]; +color( + GifWriterState *statePtr, + int red, int green, int blue, + unsigned char mapa[MAXCOLORMAPSIZE][3]) { - int x; - for (x=(alphaOffset != 0) ; x<=MAXCOLORMAPSIZE ; x++) { + int x = (statePtr->alphaOffset != 0); + + for (; x<=MAXCOLORMAPSIZE ; x++) { if ((mapa[x][CM_RED] == red) && (mapa[x][CM_GREEN] == green) && (mapa[x][CM_BLUE] == blue)) { return x; @@ -1586,15 +1656,16 @@ color(red, green, blue, mapa) } return -1; } - static int -nuevo(red, green, blue, mapa) - int red,green,blue; - unsigned char mapa[MAXCOLORMAPSIZE][3]; +nuevo( + GifWriterState *statePtr, + int red, int green, int blue, + unsigned char mapa[MAXCOLORMAPSIZE][3]) { - int x = (alphaOffset != 0); - for (; x<=num ; x++) { + int x = (statePtr->alphaOffset != 0); + + for (; x<=statePtr->num ; x++) { if ((mapa[x][CM_RED] == red) && (mapa[x][CM_GREEN] == green) && (mapa[x][CM_BLUE] == blue)) { return 0; @@ -1602,74 +1673,76 @@ nuevo(red, green, blue, mapa) } return 1; } - + static void -savemap(blockPtr,mapa) - Tk_PhotoImageBlock *blockPtr; - unsigned char mapa[MAXCOLORMAPSIZE][3]; +savemap( + GifWriterState *statePtr, + Tk_PhotoImageBlock *blockPtr, + unsigned char mapa[MAXCOLORMAPSIZE][3]) { unsigned char *colores; - int x,y; - unsigned char red,green,blue; + int x, y; + unsigned char red, green, blue; - if (alphaOffset) { - num = 0; + if (statePtr->alphaOffset) { + statePtr->num = 0; mapa[0][CM_RED] = 0xd9; mapa[0][CM_GREEN] = 0xd9; mapa[0][CM_BLUE] = 0xd9; } else { - num = -1; + statePtr->num = -1; } - for(y=0 ; y<blockPtr->height ; y++) { - colores = blockPtr->pixelPtr + blockPtr->offset[0] - + y * blockPtr->pitch; - for(x=0 ; x<blockPtr->width ; x++) { - if (!alphaOffset || (colores[alphaOffset] != 0)) { + for (y=0 ; y<blockPtr->height ; y++) { + colores = blockPtr->pixelPtr + blockPtr->offset[0] + y*blockPtr->pitch; + for (x=0 ; x<blockPtr->width ; x++) { + if (!statePtr->alphaOffset || colores[statePtr->alphaOffset]!=0) { red = colores[0]; - green = colores[greenOffset]; - blue = colores[blueOffset]; - if (nuevo(red,green,blue,mapa)) { - num++; - if (num >= MAXCOLORMAPSIZE) { + green = colores[statePtr->greenOffset]; + blue = colores[statePtr->blueOffset]; + if (nuevo(statePtr, red, green, blue, mapa)) { + statePtr->num++; + if (statePtr->num >= MAXCOLORMAPSIZE) { return; } - mapa[num][CM_RED] = red; - mapa[num][CM_GREEN] = green; - mapa[num][CM_BLUE] = blue; + mapa[statePtr->num][CM_RED] = red; + mapa[statePtr->num][CM_GREEN] = green; + mapa[statePtr->num][CM_BLUE] = blue; } } - colores += pixelSize; + colores += statePtr->pixelSize; } } - return; } - + static int -ReadValue() +ReadValue( + ClientData clientData) { + GifWriterState *statePtr = (GifWriterState *) clientData; unsigned int col; - if (csize == 0) { + if (statePtr->csize == 0) { return EOF; } - if (alphaOffset && (pixelo[alphaOffset] == 0)) { + if (statePtr->alphaOffset && statePtr->pixelo[statePtr->alphaOffset]==0) { col = 0; } else { - col = color(pixelo[0], pixelo[greenOffset], pixelo[blueOffset], mapa); + col = color(statePtr, statePtr->pixelo[0], + statePtr->pixelo[statePtr->greenOffset], + statePtr->pixelo[statePtr->blueOffset], statePtr->mapa); } - pixelo += pixelSize; - if (--ssize <= 0) { - ssize = rsize; - csize--; - pixelo += pixelPitch - (rsize * pixelSize); + statePtr->pixelo += statePtr->pixelSize; + if (--statePtr->ssize <= 0) { + statePtr->ssize = statePtr->rsize; + statePtr->csize--; + statePtr->pixelo += statePtr->pixelPitch + - (statePtr->rsize * statePtr->pixelSize); } return col; } - - /* *----------------------------------------------------------------------- * @@ -1681,30 +1754,27 @@ ReadValue() * http://www.hasc.com * info@hasc.com * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that the above copyright notice appear in all - * copies and that both that copyright notice and this permission - * notice appear in supporting documentation. This software is - * provided "AS IS." The Hutchison Avenue Software Corporation - * disclaims all warranties, either express or implied, including but - * not limited to implied warranties of merchantability and fitness - * for a particular purpose, with respect to this code and + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "AS IS." The Hutchison Avenue + * Software Corporation disclaims all warranties, either express or implied, + * including but not limited to implied warranties of merchantability and + * fitness for a particular purpose, with respect to this code and * accompanying documentation. - * - * The miGIF compression routines do not, strictly speaking, generate - * files conforming to the GIF spec, since the image data is not - * LZW-compressed (this is the point: in order to avoid transgression - * of the Unisys patent on the LZW algorithm.) However, miGIF - * generates data streams that any reasonably sane LZW decompresser - * will decompress to what we want. - * - * miGIF compression uses run length encoding. It compresses - * horizontal runs of pixels of the same color. This type of - * compression gives good results on images with many runs, for - * example images with lines, text and solid shapes on a solid-colored - * background. It gives little or no compression on images with few - * runs, for example digital or scanned photos. + * + * The miGIF compression routines do not, strictly speaking, generate files + * conforming to the GIF spec, since the image data is not LZW-compressed + * (this is the point: in order to avoid transgression of the Unisys patent on + * the LZW algorithm.) However, miGIF generates data streams that any + * reasonably sane LZW decompresser will decompress to what we want. + * + * miGIF compression uses run length encoding. It compresses horizontal runs + * of pixels of the same color. This type of compression gives good results on + * images with many runs, for example images with lines, text and solid shapes + * on a solid-colored background. It gives little or no compression on images + * with few runs, for example digital or scanned photos. * * der Mouse * mouse@rodents.montreal.qc.ca @@ -1712,35 +1782,36 @@ ReadValue() * * ivo@hasc.com * - * The Graphics Interchange Format(c) is the Copyright property of - * CompuServe Incorporated. GIF(sm) is a Service Mark property of - * CompuServe Incorporated. + * The Graphics Interchange Format(c) is the Copyright property of CompuServe + * Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated. * *----------------------------------------------------------------------- */ -static int rl_pixel; -static int rl_basecode; -static int rl_count; -static int rl_table_pixel; -static int rl_table_max; -static int just_cleared; -static int out_bits; -static int out_bits_init; -static int out_count; -static int out_bump; -static int out_bump_init; -static int out_clear; -static int out_clear_init; -static int max_ocodes; -static int code_clear; -static int code_eof; -static unsigned int obuf; -static int obits; -static Tcl_Channel ofile; -static unsigned char oblock[256]; -static int oblen; - +typedef struct { + int runlengthPixel; + int runlengthBaseCode; + int runlengthCount; + int runlengthTablePixel; + int runlengthTableMax; + int justCleared; + int outputBits; + int outputBitsInit; + int outputCount; + int outputBump; + int outputBumpInit; + int outputClear; + int outputClearInit; + int maxOcodes; + int codeClear; + int codeEOF; + unsigned int obuf; + int obits; + Tcl_Channel ofile; + unsigned char oblock[256]; + int oblen; +} miGIFState_t; + /* * Used only when debugging GIF compression code */ @@ -1748,23 +1819,28 @@ static int oblen; #ifdef MIGIF_DEBUGGING_ENVARS -static int verbose_set = 0; +/* + * This debugging code is _absolutely_ not thread-safe. It's also not normally + * enabled either. + */ + +static int verboseSet = 0; static int verbose; -#define MIGIF_VERBOSE (verbose_set?verbose:set_verbose()) -#define DEBUGMSG(printf_args) if (MIGIF_VERBOSE) { printf printf_args; } +#define MIGIF_VERBOSE (verboseSet?verbose:setVerbose()) +#define DEBUGMSG(printfArgs) if (MIGIF_VERBOSE) { printf printfArgs; } static int -set_verbose(void) +setVerbose(void) { verbose = !!getenv("MIGIF_VERBOSE"); - verbose_set = 1; + verboseSet = 1; return verbose; } -static CONST char * -binformat(v, nbits) - unsigned int v; - int nbits; +static const char * +binformat( + unsigned int v, + int nbits) { static char bufs[8][64]; static int bhand = 0; @@ -1786,112 +1862,119 @@ binformat(v, nbits) *bp = '\0'; return &bufs[bhand][0]; } - -#else - -#define MIGIF_VERBOSE 0 -#define DEBUGMSG(printf_args) /* do nothing */ - +#else /* !MIGIF_DEBUGGING_ENVARS */ +#define DEBUGMSG(printfArgs) /* do nothing */ #endif - + static void -write_block() +writeBlock( + miGIFState_t *statePtr) { - int i; unsigned char c; +#ifdef MIGIF_DEBUGGING_ENVARS if (MIGIF_VERBOSE) { - printf("write_block %d:", oblen); - for (i=0 ; i<oblen ; i++) { - printf(" %02x", oblock[i]); + int i; + printf("writeBlock %d:", statePtr->oblen); + for (i=0 ; i<statePtr->oblen ; i++) { + printf(" %02x", statePtr->oblock[i]); } printf("\n"); } - c = oblen; - Tcl_Write(ofile, (char *) &c, 1); - Tcl_Write(ofile, (char *) &oblock[0], oblen); - oblen = 0; +#endif + c = statePtr->oblen; + Tcl_Write(statePtr->ofile, (char *) &c, 1); + Tcl_Write(statePtr->ofile, (char *) &statePtr->oblock[0], statePtr->oblen); + statePtr->oblen = 0; } - + static void -block_out(c) - unsigned char c; +blockOut( + miGIFState_t *statePtr, + unsigned c) { - DEBUGMSG(("block_out %s\n", binformat(c, 8))); - oblock[oblen++] = c; - if (oblen >= 255) { - write_block(); + DEBUGMSG(("blockOut %s\n", binformat(c, 8))); + statePtr->oblock[statePtr->oblen++] = (unsigned char) c; + if (statePtr->oblen >= 255) { + writeBlock(statePtr); } } - + static void -block_flush() +blockFlush( + miGIFState_t *statePtr) { - DEBUGMSG(("block_flush\n")); - if (oblen > 0) { - write_block(); + DEBUGMSG(("blockFlush\n")); + if (statePtr->oblen > 0) { + writeBlock(statePtr); } } - + static void -output(val) - int val; +output( + miGIFState_t *statePtr, + int val) { - DEBUGMSG(("output %s [%s %d %d]\n", binformat(val, out_bits), - binformat(obuf, obits), obits, out_bits)); - obuf |= val << obits; - obits += out_bits; - while (obits >= 8) { - block_out(UCHAR(obuf&0xff)); - obuf >>= 8; - obits -= 8; - } - DEBUGMSG(("output leaving [%s %d]\n", binformat(obuf, obits), obits)); + DEBUGMSG(("output %s [%s %d %d]\n", binformat(val, statePtr->outputBits), + binformat(statePtr->obuf, statePtr->obits), statePtr->obits, + statePtr->outputBits)); + statePtr->obuf |= val << statePtr->obits; + statePtr->obits += statePtr->outputBits; + while (statePtr->obits >= 8) { + blockOut(statePtr, statePtr->obuf & 0xff); + statePtr->obuf >>= 8; + statePtr->obits -= 8; + } + DEBUGMSG(("output leaving [%s %d]\n", + binformat(statePtr->obuf, statePtr->obits), statePtr->obits)); } - + static void -output_flush() +outputFlush( + miGIFState_t *statePtr) { - DEBUGMSG(("output_flush\n")); - if (obits > 0) { - block_out(UCHAR(obuf)); + DEBUGMSG(("outputFlush\n")); + if (statePtr->obits > 0) { + blockOut(statePtr, statePtr->obuf); } - block_flush(); + blockFlush(statePtr); } - + static void -did_clear() +didClear( + miGIFState_t *statePtr) { - DEBUGMSG(("did_clear\n")); - out_bits = out_bits_init; - out_bump = out_bump_init; - out_clear = out_clear_init; - out_count = 0; - rl_table_max = 0; - just_cleared = 1; + DEBUGMSG(("didClear\n")); + statePtr->outputBits = statePtr->outputBitsInit; + statePtr->outputBump = statePtr->outputBumpInit; + statePtr->outputClear = statePtr->outputClearInit; + statePtr->outputCount = 0; + statePtr->runlengthTableMax = 0; + statePtr->justCleared = 1; } - + static void -output_plain(c) - int c; +outputPlain( + miGIFState_t *statePtr, + int c) { - DEBUGMSG(("output_plain %s\n", binformat(c, out_bits))); - just_cleared = 0; - output(c); - out_count++; - if (out_count >= out_bump) { - out_bits++; - out_bump += 1 << (out_bits - 1); - } - if (out_count >= out_clear) { - output(code_clear); - did_clear(); + DEBUGMSG(("outputPlain %s\n", binformat(c, statePtr->outputBits))); + statePtr->justCleared = 0; + output(statePtr, c); + statePtr->outputCount++; + if (statePtr->outputCount >= statePtr->outputBump) { + statePtr->outputBits++; + statePtr->outputBump += 1 << (statePtr->outputBits - 1); + } + if (statePtr->outputCount >= statePtr->outputClear) { + output(statePtr, statePtr->codeClear); + didClear(statePtr); } } - + static unsigned int -isqrt(x) - unsigned int x; +isqrt( + unsigned int x) { unsigned int r; unsigned int v; @@ -1908,11 +1991,11 @@ isqrt(x) r = v; } } - -static unsigned int -compute_triangle_count(count, nrepcodes) - unsigned int count; - unsigned int nrepcodes; + +static int +computeTriangleCount( + unsigned int count, + unsigned int nrepcodes) { unsigned int perrep; unsigned int cost; @@ -1924,8 +2007,8 @@ compute_triangle_count(count, nrepcodes) count -= perrep; } if (count > 0) { - unsigned int n; - n = isqrt(count); + unsigned int n = isqrt(count); + while (n*(n+1) >= 2*count) { n--; } @@ -1934,204 +2017,233 @@ compute_triangle_count(count, nrepcodes) } cost += n; } - return cost; + return (int) cost + 1; } - + static void -max_out_clear() +maxOutputClear( + miGIFState_t *statePtr) { - out_clear = max_ocodes; + statePtr->outputClear = statePtr->maxOcodes; } - + static void -reset_out_clear() +resetOutputClear( + miGIFState_t *statePtr) { - out_clear = out_clear_init; - if (out_count >= out_clear) { - output(code_clear); - did_clear(); + statePtr->outputClear = statePtr->outputClearInit; + if (statePtr->outputCount >= statePtr->outputClear) { + output(statePtr, statePtr->codeClear); + didClear(statePtr); } } - + static void -rl_flush_fromclear(count) - int count; +runlengthFlushFromClear( + miGIFState_t *statePtr, + int count) { int n; - DEBUGMSG(("rl_flush_fromclear %d\n", count)); - max_out_clear(); - rl_table_pixel = rl_pixel; + DEBUGMSG(("runlengthFlushFromClear %d\n", count)); + maxOutputClear(statePtr); + statePtr->runlengthTablePixel = statePtr->runlengthPixel; n = 1; while (count > 0) { if (n == 1) { - rl_table_max = 1; - output_plain(rl_pixel); + statePtr->runlengthTableMax = 1; + outputPlain(statePtr, statePtr->runlengthPixel); count--; } else if (count >= n) { - rl_table_max = n; - output_plain(rl_basecode+n-2); + statePtr->runlengthTableMax = n; + outputPlain(statePtr, statePtr->runlengthBaseCode+n-2); count -= n; } else if (count == 1) { - rl_table_max++; - output_plain(rl_pixel); + statePtr->runlengthTableMax++; + outputPlain(statePtr, statePtr->runlengthPixel); count = 0; } else { - rl_table_max++; - output_plain(rl_basecode+count-2); + statePtr->runlengthTableMax++; + outputPlain(statePtr, statePtr->runlengthBaseCode+count-2); count = 0; } - if (out_count == 0) { + if (statePtr->outputCount == 0) { n = 1; } else { n++; } } - reset_out_clear(); - DEBUGMSG(("rl_flush_fromclear leaving table_max=%d\n", rl_table_max)); + resetOutputClear(statePtr); + DEBUGMSG(("runlengthFlushFromClear leaving tableMax=%d\n", + statePtr->runlengthTableMax)); } - + static void -rl_flush_clearorrep(count) - int count; +runlengthFlushClearOrRep( + miGIFState_t *statePtr, + int count) { int withclr; - DEBUGMSG(("rl_flush_clearorrep %d\n", count)); - withclr = 1 + compute_triangle_count(count, max_ocodes); + DEBUGMSG(("runlengthFlushClearOrRep %d\n", count)); + withclr = computeTriangleCount((unsigned) count, + (unsigned) statePtr->maxOcodes); if (withclr < count) { - output(code_clear); - did_clear(); - rl_flush_fromclear(count); + output(statePtr, statePtr->codeClear); + didClear(statePtr); + runlengthFlushFromClear(statePtr, count); } else { for (; count>0 ; count--) { - output_plain(rl_pixel); + outputPlain(statePtr, statePtr->runlengthPixel); } } } - + static void -rl_flush_withtable(count) - int count; +runlengthFlushWithTable( + miGIFState_t *statePtr, + int count) { int repmax; int repleft; int leftover; - DEBUGMSG(("rl_flush_withtable %d\n", count)); - repmax = count / rl_table_max; - leftover = count % rl_table_max; + DEBUGMSG(("runlengthFlushWithTable %d\n", count)); + repmax = count / statePtr->runlengthTableMax; + leftover = count % statePtr->runlengthTableMax; repleft = (leftover ? 1 : 0); - if (out_count+repmax+repleft > max_ocodes) { - repmax = max_ocodes - out_count; - leftover = count - (repmax * rl_table_max); - repleft = 1 + compute_triangle_count(leftover, max_ocodes); + if (statePtr->outputCount+repmax+repleft > statePtr->maxOcodes) { + repmax = statePtr->maxOcodes - statePtr->outputCount; + leftover = count - (repmax * statePtr->runlengthTableMax); + repleft = computeTriangleCount((unsigned) leftover, + (unsigned) statePtr->maxOcodes); } - DEBUGMSG(("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n", + DEBUGMSG(("runlengthFlushWithTable repmax=%d leftover=%d repleft=%d\n", repmax, leftover, repleft)); - if (1+(int)compute_triangle_count(count, max_ocodes) < repmax+repleft) { - output(code_clear); - did_clear(); - rl_flush_fromclear(count); + if (computeTriangleCount((unsigned) count, (unsigned) statePtr->maxOcodes) + < repmax+repleft) { + output(statePtr, statePtr->codeClear); + didClear(statePtr); + runlengthFlushFromClear(statePtr, count); return; } - max_out_clear(); + maxOutputClear(statePtr); for (; repmax>0 ; repmax--) { - output_plain(rl_basecode + rl_table_max - 2); + outputPlain(statePtr, + statePtr->runlengthBaseCode + statePtr->runlengthTableMax - 2); } if (leftover) { - if (just_cleared) { - rl_flush_fromclear(leftover); + if (statePtr->justCleared) { + runlengthFlushFromClear(statePtr, leftover); } else if (leftover == 1) { - output_plain(rl_pixel); + outputPlain(statePtr, statePtr->runlengthPixel); } else { - output_plain(rl_basecode + leftover - 2); + outputPlain(statePtr, statePtr->runlengthBaseCode + leftover - 2); } } - reset_out_clear(); + resetOutputClear(statePtr); } - + static void -rl_flush() +runlengthFlush( + miGIFState_t *statePtr) { - DEBUGMSG(("rl_flush [ %d %d\n", rl_count, rl_pixel)); - if (rl_count == 1) { - output_plain(rl_pixel); - rl_count = 0; - DEBUGMSG(("rl_flush ]\n")); + DEBUGMSG(("runlengthFlush [ %d %d\n", statePtr->runlengthCount, + statePtr->runlengthPixel)); + if (statePtr->runlengthCount == 1) { + outputPlain(statePtr, statePtr->runlengthPixel); + statePtr->runlengthCount = 0; + DEBUGMSG(("runlengthFlush ]\n")); return; } - if (just_cleared) { - rl_flush_fromclear(rl_count); - } else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel)) { - rl_flush_clearorrep(rl_count); + if (statePtr->justCleared) { + runlengthFlushFromClear(statePtr, statePtr->runlengthCount); + } else if ((statePtr->runlengthTableMax < 2) + || (statePtr->runlengthTablePixel != statePtr->runlengthPixel)) { + runlengthFlushClearOrRep(statePtr, statePtr->runlengthCount); } else { - rl_flush_withtable(rl_count); + runlengthFlushWithTable(statePtr, statePtr->runlengthCount); } - DEBUGMSG(("rl_flush ]\n")); - rl_count = 0; + DEBUGMSG(("runlengthFlush ]\n")); + statePtr->runlengthCount = 0; } - - + static void -compress(init_bits, handle, readValue) - int init_bits; - Tcl_Channel handle; - ifunptr readValue; +compress( + int initBits, + Tcl_Channel handle, + ifunptr readValue, + ClientData clientData) { int c; + miGIFState_t state, *statePtr = &state; + + memset(statePtr, 0, sizeof(state)); + + statePtr->ofile = handle; + statePtr->obuf = 0; + statePtr->obits = 0; + statePtr->oblen = 0; + statePtr->codeClear = 1 << (initBits - 1); + statePtr->codeEOF = statePtr->codeClear + 1; + statePtr->runlengthBaseCode = statePtr->codeEOF + 1; + statePtr->outputBumpInit = (1 << (initBits - 1)) - 1; - ofile = handle; - obuf = 0; - obits = 0; - oblen = 0; - code_clear = 1 << (init_bits - 1); - code_eof = code_clear + 1; - rl_basecode = code_eof + 1; - out_bump_init = (1 << (init_bits - 1)) - 1; /* - * For images with a lot of runs, making out_clear_init larger - * will give better compression. + * For images with a lot of runs, making outputClearInit larger will give + * better compression. */ - out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1); + + statePtr->outputClearInit = + (initBits <= 3) ? 9 : (statePtr->outputBumpInit-1); #ifdef MIGIF_DEBUGGING_ENVARS { - const char *ocienv; - ocienv = getenv("MIGIF_OUT_CLEAR_INIT"); + const char *ocienv = getenv("MIGIF_OUT_CLEAR_INIT"); + if (ocienv) { - out_clear_init = atoi(ocienv); - DEBUGMSG(("[overriding out_clear_init to %d]\n", out_clear_init)); + statePtr->outputClearInit = atoi(ocienv); + DEBUGMSG(("[overriding outputClearInit to %d]\n", + statePtr->outputClearInit)); } } #endif - out_bits_init = init_bits; - max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3); - did_clear(); - output(code_clear); - rl_count = 0; + statePtr->outputBitsInit = initBits; + statePtr->maxOcodes = + (1 << GIFBITS) - ((1 << (statePtr->outputBitsInit - 1)) + 3); + didClear(statePtr); + output(statePtr, statePtr->codeClear); + statePtr->runlengthCount = 0; while (1) { - c = readValue(); - if ((rl_count > 0) && (c != rl_pixel)) { - rl_flush(); + c = readValue(clientData); + if (statePtr->runlengthCount>0 && statePtr->runlengthPixel!=c) { + runlengthFlush(statePtr); } if (c == EOF) { break; } - if (rl_pixel == c) { - rl_count++; + if (statePtr->runlengthPixel == c) { + statePtr->runlengthCount++; } else { - rl_pixel = c; - rl_count = 1; + statePtr->runlengthPixel = c; + statePtr->runlengthCount = 1; } } - output(code_eof); - output_flush(); + output(statePtr, statePtr->codeEOF); + outputFlush(statePtr); } /* *----------------------------------------------------------------------- * - * End of miGIF section - See copyright notice at start of section. + * End of miGIF section - See copyright notice at start of section. * *----------------------------------------------------------------------- */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c index ffa369d..8a46fde 100644 --- a/generic/tkImgPPM.c +++ b/generic/tkImgPPM.c @@ -6,20 +6,19 @@ * Copyright (c) 1994 The Australian National University. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), - * Department of Computer Science, - * Australian National University. + * Department of Computer Science, + * Australian National University. */ #include "tkInt.h" -#include "tkPort.h" /* - * The maximum amount of memory to allocate for data read from the - * file. If we need more than this, we do it in pieces. + * The maximum amount of memory to allocate for data read from the file. If we + * need more than this, we do it in pieces. */ #define MAX_MEMORY 10000 /* don't allocate > 10KB */ @@ -35,28 +34,23 @@ * The format record for the PPM file format: */ -static int FileMatchPPM _ANSI_ARGS_((Tcl_Channel chan, +static int FileMatchPPM(Tcl_Channel chan, CONST char *fileName, + Tcl_Obj *format, int *widthPtr, int *heightPtr, + Tcl_Interp *interp); +static int FileReadPPM(Tcl_Interp *interp, Tcl_Channel chan, CONST char *fileName, Tcl_Obj *format, - int *widthPtr, int *heightPtr, - Tcl_Interp *interp)); -static int FileReadPPM _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, CONST char *fileName, + Tk_PhotoHandle imageHandle, int destX, int destY, + int width, int height, int srcX, int srcY); +static int FileWritePPM(Tcl_Interp *interp, CONST char *fileName, + Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); +static int StringWritePPM(Tcl_Interp *interp, Tcl_Obj *format, + Tk_PhotoImageBlock *blockPtr); +static int StringMatchPPM(Tcl_Obj *dataObj, Tcl_Obj *format, + int *widthPtr, int *heightPtr, Tcl_Interp *interp); +static int StringReadPPM(Tcl_Interp *interp, Tcl_Obj *dataObj, Tcl_Obj *format, Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, - int srcX, int srcY)); -static int FileWritePPM _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *fileName, Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr)); -static int StringWritePPM _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr)); -static int StringMatchPPM _ANSI_ARGS_((Tcl_Obj *dataObj, - Tcl_Obj *format, int *widthPtr, int *heightPtr, - Tcl_Interp *interp)); -static int StringReadPPM _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *dataObj, Tcl_Obj *format, - Tk_PhotoHandle imageHandle, int destX, int destY, - int width, int height, int srcX, int srcY)); - + int srcX, int srcY); Tk_PhotoImageFormat tkImgFmtPPM = { "ppm", /* name */ @@ -69,28 +63,26 @@ Tk_PhotoImageFormat tkImgFmtPPM = { }; /* - * Prototypes for local procedures defined in this file: + * Prototypes for local functions defined in this file: */ -static int ReadPPMFileHeader _ANSI_ARGS_((Tcl_Channel chan, - int *widthPtr, int *heightPtr, - int *maxIntensityPtr)); -static int ReadPPMStringHeader _ANSI_ARGS_((Tcl_Obj *dataObj, - int *widthPtr, int *heightPtr, - int *maxIntensityPtr, - unsigned char **dataBufferPtr, int *dataSizePtr)); +static int ReadPPMFileHeader(Tcl_Channel chan, int *widthPtr, + int *heightPtr, int *maxIntensityPtr); +static int ReadPPMStringHeader(Tcl_Obj *dataObj, int *widthPtr, + int *heightPtr, int *maxIntensityPtr, + unsigned char **dataBufferPtr, int *dataSizePtr); /* *---------------------------------------------------------------------- * * FileMatchPPM -- * - * This procedure is invoked by the photo image type to see if - * a file contains image data in PPM format. + * This function is invoked by the photo image type to see if a file + * contains image data in PPM format. * * Results: - * The return value is >0 if the first characters in file "f" look - * like PPM data, and 0 otherwise. + * The return value is >0 if the first characters in file "f" look like + * PPM data, and 0 otherwise. * * Side effects: * The access position in f may change. @@ -99,14 +91,15 @@ static int ReadPPMStringHeader _ANSI_ARGS_((Tcl_Obj *dataObj, */ static int -FileMatchPPM(chan, fileName, format, widthPtr, heightPtr, interp) - Tcl_Channel chan; /* The image file, open for reading. */ - CONST char *fileName; /* The name of the image file. */ - Tcl_Obj *format; /* User-specified format string, or NULL. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here if the file is a valid - * raw PPM file. */ - Tcl_Interp *interp; +FileMatchPPM( + Tcl_Channel chan, /* The image file, open for reading. */ + CONST char *fileName, /* The name of the image file. */ + Tcl_Obj *format, /* User-specified format string, or NULL. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here if the file is a valid raw PPM + * file. */ + Tcl_Interp *interp) /* unused */ { int dummy; @@ -118,35 +111,33 @@ FileMatchPPM(chan, fileName, format, widthPtr, heightPtr, interp) * * FileReadPPM -- * - * This procedure is called by the photo image type to read - * PPM format data from a file and write it into a given - * photo image. + * This function is called by the photo image type to read PPM format + * data from a file and write it into a given photo image. * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. * * Side effects: - * The access position in file f is changed, and new data is - * added to the image given by imageHandle. + * The access position in file f is changed, and new data is added to the + * image given by imageHandle. * *---------------------------------------------------------------------- */ static int -FileReadPPM(interp, chan, fileName, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Channel chan; /* The image file, open for reading. */ - CONST char *fileName; /* The name of the image file. */ - Tcl_Obj *format; /* User-specified format string, or NULL. */ - Tk_PhotoHandle imageHandle; /* The photo image to write into. */ - int destX, destY; /* Coordinates of top-left pixel in - * photo image to be written to. */ - int width, height; /* Dimensions of block of photo image to - * be written to. */ - int srcX, srcY; /* Coordinates of top-left pixel to be used - * in image being read. */ +FileReadPPM( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Channel chan, /* The image file, open for reading. */ + CONST char *fileName, /* The name of the image file. */ + Tcl_Obj *format, /* User-specified format string, or NULL. */ + Tk_PhotoHandle imageHandle, /* The photo image to write into. */ + int destX, int destY, /* Coordinates of top-left pixel in photo + * image to be written to. */ + int width, int height, /* Dimensions of block of photo image to be + * written to. */ + int srcX, int srcY) /* Coordinates of top-left pixel to be used in + * image being read. */ { int fileWidth, fileHeight, maxIntensity; int nLines, nBytes, h, type, count; @@ -185,14 +176,13 @@ FileReadPPM(interp, chan, fileName, format, imageHandle, destX, destY, } if (type == PGM) { - block.pixelSize = 1; - block.offset[0] = 0; + block.pixelSize = 1; + block.offset[0] = 0; block.offset[1] = 0; block.offset[2] = 0; - } - else { - block.pixelSize = 3; - block.offset[0] = 0; + } else { + block.pixelSize = 3; + block.offset[0] = 0; block.offset[1] = 1; block.offset[2] = 2; } @@ -200,7 +190,10 @@ FileReadPPM(interp, chan, fileName, format, imageHandle, destX, destY, block.width = width; block.pitch = block.pixelSize * fileWidth; - Tk_PhotoExpand(imageHandle, destX + width, destY + height); + if (Tk_PhotoExpand(interp, imageHandle, + destX + width, destY + height) != TCL_OK) { + return TCL_ERROR; + } if (srcY > 0) { Tcl_Seek(chan, (Tcl_WideInt)(srcY * block.pitch), SEEK_CUR); @@ -239,8 +232,11 @@ FileReadPPM(interp, chan, fileName, format, imageHandle, destX, destY, } } block.height = nLines; - Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, nLines, - TK_PHOTO_COMPOSITE_SET); + if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY, + width, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) { + ckfree((char *) pixelPtr); + return TCL_ERROR; + } destY += nLines; } @@ -253,12 +249,12 @@ FileReadPPM(interp, chan, fileName, format, imageHandle, destX, destY, * * FileWritePPM -- * - * This procedure is invoked to write image data to a file in PPM - * format. + * This function is invoked to write image data to a file in PPM format + * (although we can read PGM files, we never write them). * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. * * Side effects: * Data is written to the file given by "fileName". @@ -267,15 +263,14 @@ FileReadPPM(interp, chan, fileName, format, imageHandle, destX, destY, */ static int -FileWritePPM(interp, fileName, format, blockPtr) - Tcl_Interp *interp; - CONST char *fileName; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; +FileWritePPM( + Tcl_Interp *interp, + CONST char *fileName, + Tcl_Obj *format, + Tk_PhotoImageBlock *blockPtr) { Tcl_Channel chan; - int w, h; - int greenOffset, blueOffset, nBytes; + int w, h, greenOffset, blueOffset, nBytes; unsigned char *pixelPtr, *pixLinePtr; char header[16 + TCL_INTEGER_SPACE * 2]; @@ -312,9 +307,9 @@ FileWritePPM(interp, fileName, format, blockPtr) 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) == -1 || + Tcl_Write(chan,(char *)&pixelPtr[greenOffset],1)==-1 || + Tcl_Write(chan,(char *)&pixelPtr[blueOffset],1) ==-1) { goto writeerror; } pixelPtr += blockPtr->pixelSize; @@ -328,7 +323,7 @@ FileWritePPM(interp, fileName, format, blockPtr) } chan = NULL; - writeerror: + writeerror: Tcl_AppendResult(interp, "error writing \"", fileName, "\": ", Tcl_PosixError(interp), NULL); if (chan != NULL) { @@ -342,12 +337,12 @@ FileWritePPM(interp, fileName, format, blockPtr) * * StringWritePPM -- * - * This procedure is invoked to write image data to a string in PPM + * This function is invoked to write image data to a string in PPM * format. * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. * * Side effects: * None. @@ -356,10 +351,10 @@ FileWritePPM(interp, fileName, format, blockPtr) */ static int -StringWritePPM(interp, format, blockPtr) - Tcl_Interp *interp; - Tcl_Obj *format; - Tk_PhotoImageBlock *blockPtr; +StringWritePPM( + Tcl_Interp *interp, + Tcl_Obj *format, + Tk_PhotoImageBlock *blockPtr) { int w, h, size, greenOffset, blueOffset; unsigned char *pixLinePtr, *byteArray; @@ -367,10 +362,12 @@ StringWritePPM(interp, format, blockPtr) Tcl_Obj *byteArrayObj; sprintf(header, "P6\n%d %d\n255\n", blockPtr->width, blockPtr->height); + /* * Construct a byte array of the right size with the header and * get a pointer to the data part of it. */ + size = strlen(header); byteArrayObj = Tcl_NewByteArrayObj((unsigned char *)header, size); byteArray = Tcl_SetByteArrayLength(byteArrayObj, @@ -384,6 +381,7 @@ StringWritePPM(interp, format, blockPtr) /* * Check if we can do the data move in single action. */ + if ((greenOffset == 1) && (blueOffset == 2) && (blockPtr->pixelSize == 3) && (blockPtr->pitch == (blockPtr->width * 3))) { memcpy(byteArray, pixLinePtr, @@ -405,6 +403,7 @@ StringWritePPM(interp, format, blockPtr) /* * Return the object in the interpreter result. */ + Tcl_SetObjResult(interp, byteArrayObj); return TCL_OK; } @@ -414,12 +413,12 @@ StringWritePPM(interp, format, blockPtr) * * StringMatchPPM -- * - * This procedure is invoked by the photo image type to see if - * a string contains image data in PPM format. + * This function is invoked by the photo image type to see if a string + * contains image data in PPM format. * * Results: - * The return value is >0 if the first characters in file "f" look - * like PPM data, and 0 otherwise. + * The return value is >0 if the first characters in file "f" look like + * PPM data, and 0 otherwise. * * Side effects: * The access position in f may change. @@ -428,13 +427,14 @@ StringWritePPM(interp, format, blockPtr) */ static int -StringMatchPPM(dataObj, format, widthPtr, heightPtr, interp) - Tcl_Obj *dataObj; /* The image data. */ - Tcl_Obj *format; /* User-specified format string, or NULL. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here if the file is a valid - * raw PPM file. */ - Tcl_Interp *interp; /* unused */ +StringMatchPPM( + Tcl_Obj *dataObj, /* The image data. */ + Tcl_Obj *format, /* User-specified format string, or NULL. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here if the file is a valid raw PPM + * file. */ + Tcl_Interp *interp) /* unused */ { int dummy; @@ -447,13 +447,12 @@ StringMatchPPM(dataObj, format, widthPtr, heightPtr, interp) * * StringReadPPM -- * - * This procedure is called by the photo image type to read - * PPM format data from a string and write it into a given - * photo image. + * This function is called by the photo image type to read PPM format + * data from a string and write it into a given photo image. * * Results: - * A standard TCL completion code. If TCL_ERROR is returned - * then an error message is left in the interp's result. + * A standard TCL completion code. If TCL_ERROR is returned then an error + * message is left in the interp's result. * * Side effects: * New data is added to the image given by imageHandle. @@ -462,18 +461,17 @@ StringMatchPPM(dataObj, format, widthPtr, heightPtr, interp) */ static int -StringReadPPM(interp, dataObj, format, imageHandle, destX, destY, - width, height, srcX, srcY) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Obj *dataObj; /* The image data. */ - Tcl_Obj *format; /* User-specified format string, or NULL. */ - Tk_PhotoHandle imageHandle; /* The photo image to write into. */ - int destX, destY; /* Coordinates of top-left pixel in - * photo image to be written to. */ - int width, height; /* Dimensions of block of photo image to - * be written to. */ - int srcX, srcY; /* Coordinates of top-left pixel to be used - * in image being read. */ +StringReadPPM( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Obj *dataObj, /* The image data. */ + Tcl_Obj *format, /* User-specified format string, or NULL. */ + Tk_PhotoHandle imageHandle, /* The photo image to write into. */ + int destX, int destY, /* Coordinates of top-left pixel in photo + * image to be written to. */ + int width, int height, /* Dimensions of block of photo image to be + * written to. */ + int srcX, int srcY) /* Coordinates of top-left pixel to be used in + * image being read. */ { int fileWidth, fileHeight, maxIntensity; int nLines, nBytes, h, type, count, dataSize; @@ -514,13 +512,13 @@ StringReadPPM(interp, dataObj, format, imageHandle, destX, destY, } if (type == PGM) { - block.pixelSize = 1; - block.offset[0] = 0; + block.pixelSize = 1; + block.offset[0] = 0; block.offset[1] = 0; block.offset[2] = 0; } else { - block.pixelSize = 3; - block.offset[0] = 0; + block.pixelSize = 3; + block.offset[0] = 0; block.offset[1] = 1; block.offset[2] = 2; } @@ -535,21 +533,23 @@ StringReadPPM(interp, dataObj, format, imageHandle, destX, destY, if (maxIntensity == 255) { /* - * We have all the data in memory, so write everything in one - * go. + * We have all the data in memory, so write everything in one go. */ + if (block.pitch*height > dataSize) { Tcl_AppendResult(interp, "truncated PPM data", NULL); return TCL_ERROR; } block.pixelPtr = dataBuffer + srcX * block.pixelSize; block.height = height; - Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height, - TK_PHOTO_COMPOSITE_SET); - return TCL_OK; + return Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY, + width, height, TK_PHOTO_COMPOSITE_SET); } - Tk_PhotoExpand(imageHandle, destX + width, destY + height); + if (Tk_PhotoExpand(interp, imageHandle, + destX + width, destY + height) != TCL_OK) { + return TCL_ERROR; + } nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch; if (nLines > height) { @@ -579,8 +579,11 @@ StringReadPPM(interp, dataObj, format, imageHandle, destX, destY, } dataSize -= nBytes; block.height = nLines; - Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, nLines, - TK_PHOTO_COMPOSITE_SET); + if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY, + width, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) { + ckfree((char *) pixelPtr); + return TCL_ERROR; + } destY += nLines; } @@ -593,16 +596,15 @@ StringReadPPM(interp, dataObj, format, imageHandle, destX, destY, * * ReadPPMFileHeader -- * - * This procedure reads the PPM header from the beginning of a - * PPM file and returns information from the header. + * This function reads the PPM header from the beginning of a PPM file + * and returns information from the header. * * Results: - * The return value is PGM if file "f" appears to start with - * a valid PGM header, PPM if "f" appears to start with a valid - * PPM header, and 0 otherwise. If the header is valid, - * then *widthPtr and *heightPtr are modified to hold the - * dimensions of the image and *maxIntensityPtr is modified to - * hold the value of a "fully on" intensity value. + * The return value is PGM if file "f" appears to start with a valid PGM + * header, PPM if "f" appears to start with a valid PPM header, and 0 + * otherwise. If the header is valid, then *widthPtr and *heightPtr are + * modified to hold the dimensions of the image and *maxIntensityPtr is + * modified to hold the value of a "fully on" intensity value. * * Side effects: * The access position in f advances. @@ -611,22 +613,21 @@ StringReadPPM(interp, dataObj, format, imageHandle, destX, destY, */ static int -ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr) - Tcl_Channel chan; /* Image file to read the header from */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ - int *maxIntensityPtr; /* The maximum intensity value for - * the image is stored here. */ +ReadPPMFileHeader( + Tcl_Channel chan, /* Image file to read the header from. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here. */ + int *maxIntensityPtr) /* The maximum intensity value for the image + * is stored here. */ { #define BUFFER_SIZE 1000 - char buffer[BUFFER_SIZE]; - int i, numFields; - int type = 0; - char c; + char buffer[BUFFER_SIZE], c; + int i, numFields, type = 0; /* - * Read 4 space-separated fields from the file, ignoring - * comments (any line that starts with "#"). + * Read 4 space-separated fields from the file, ignoring comments (any + * line that starts with "#"). */ if (Tcl_Read(chan, &c, 1) != 1) { @@ -672,7 +673,8 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr) i++; } } - done: + + done: buffer[i] = 0; /* @@ -698,16 +700,16 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr) * * ReadPPMStringHeader -- * - * This procedure reads the PPM header from the beginning of a - * PPM-format string and returns information from the header. + * This function reads the PPM header from the beginning of a PPM-format + * string and returns information from the header. * * Results: - * The return value is PGM if the string appears to start with - * a valid PGM header, PPM if the string appears to start with - * a valid PPM header, and 0 otherwise. If the header is valid, - * then *widthPtr and *heightPtr are modified to hold the - * dimensions of the image and *maxIntensityPtr is modified to - * hold the value of a "fully on" intensity value. + * The return value is PGM if the string appears to start with a valid + * PGM header, PPM if the string appears to start with a valid PPM + * header, and 0 otherwise. If the header is valid, then *widthPtr and + * *heightPtr are modified to hold the dimensions of the image and + * *maxIntensityPtr is modified to hold the value of a "fully on" + * intensity value. * * Side effects: * None @@ -716,28 +718,26 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr) */ static int -ReadPPMStringHeader(dataPtr, widthPtr, heightPtr, maxIntensityPtr, - dataBufferPtr, dataSizePtr) - Tcl_Obj *dataPtr; /* Object to read the header from. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ - int *maxIntensityPtr; /* The maximum intensity value for - * the image is stored here. */ - unsigned char **dataBufferPtr; - int *dataSizePtr; +ReadPPMStringHeader( + Tcl_Obj *dataPtr, /* Object to read the header from. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here. */ + int *maxIntensityPtr, /* The maximum intensity value for the image + * is stored here. */ + unsigned char **dataBufferPtr, + int *dataSizePtr) { #define BUFFER_SIZE 1000 - char buffer[BUFFER_SIZE]; - int i, numFields, dataSize; - int type = 0; - char c; + char buffer[BUFFER_SIZE], c; + int i, numFields, dataSize, type = 0; unsigned char *dataBuffer; dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize); /* - * Read 4 space-separated fields from the string, ignoring - * comments (any line that starts with "#"). + * Read 4 space-separated fields from the string, ignoring comments (any + * line that starts with "#"). */ if (dataSize-- < 1) { @@ -787,7 +787,8 @@ ReadPPMStringHeader(dataPtr, widthPtr, heightPtr, maxIntensityPtr, i++; } } - done: + + done: buffer[i] = 0; /* @@ -811,3 +812,11 @@ ReadPPMStringHeader(dataPtr, widthPtr, heightPtr, maxIntensityPtr, } return type; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index ffbb47c..ffff4fc 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -1,17 +1,17 @@ /* * tkImgPhoto.c -- * - * Implements images of type "photo" for Tk. Photo images are - * stored in full color (32 bits per pixel including alpha channel) - * and displayed using dithering if necessary. + * Implements images of type "photo" for Tk. Photo images are stored in + * full color (32 bits per pixel including alpha channel) and displayed + * using dithering if necessary. * * Copyright (c) 1994 The Australian National University. * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2002 Donal K. Fellows + * 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. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), * Department of Computer Science, @@ -19,8 +19,6 @@ */ #include "tkInt.h" -#include "tkPort.h" -#include "tclMath.h" #include <ctype.h> #ifdef __WIN32__ @@ -31,12 +29,12 @@ * Declaration for internal Xlib function used here: */ -extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); +extern int _XInitImageFuncPtrs(XImage *image); /* - * A signed 8-bit integral type. If chars are unsigned and the compiler - * isn't an ANSI one, then we have to use short instead (which wastes - * space) to get signed behavior. + * A signed 8-bit integral type. If chars are unsigned and the compiler isn't + * an ANSI one, then we have to use short instead (which wastes space) to get + * signed behavior. */ #if defined(__STDC__) || defined(_AIX) @@ -50,16 +48,15 @@ extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); #endif /* - * An unsigned 32-bit integral type, used for pixel values. - * We use int rather than long here to accommodate those systems - * where longs are 64 bits. + * An unsigned 32-bit integral type, used for pixel values. We use int rather + * than long here to accommodate those systems where longs are 64 bits. */ typedef unsigned int pixel; /* - * The maximum number of pixels to transmit to the server in a - * single XPutImage call. + * The maximum number of pixels to transmit to the server in a single + * XPutImage call. */ #define MAX_PIXELS 65536 @@ -67,20 +64,19 @@ typedef unsigned int pixel; /* * The set of colors required to display a photo image in a window depends on: * - the visual used by the window - * - the palette, which specifies how many levels of each primary - * color to use, and + * - the palette, which specifies how many levels of each primary color to + * use, and * - the gamma value for the image. * - * Pixel values allocated for specific colors are valid only for the - * colormap in which they were allocated. Sets of pixel values - * allocated for displaying photos are re-used in other windows if - * possible, that is, if the display, colormap, palette and gamma - * values match. A hash table is used to locate these sets of pixel - * values, using the following data structure as key: + * Pixel values allocated for specific colors are valid only for the colormap + * in which they were allocated. Sets of pixel values allocated for displaying + * photos are re-used in other windows if possible, that is, if the display, + * colormap, palette and gamma values match. A hash table is used to locate + * these sets of pixel values, using the following data structure as key: */ typedef struct { - Display *display; /* Qualifies the colormap resource ID */ + Display *display; /* Qualifies the colormap resource ID. */ Colormap colormap; /* Colormap that the windows are using. */ double gamma; /* Gamma exponent value for images. */ Tk_Uid palette; /* Specifies how many shades of each primary @@ -88,33 +84,33 @@ typedef struct { } ColorTableId; /* - * For a particular (display, colormap, palette, gamma) combination, - * a data structure of the following type is used to store the allocated - * pixel values and other information: + * For a particular (display, colormap, palette, gamma) combination, a data + * structure of the following type is used to store the allocated pixel values + * and other information: */ typedef struct ColorTable { - ColorTableId id; /* Information used in selecting this - * color table. */ + ColorTableId id; /* Information used in selecting this color + * table. */ int flags; /* See below. */ int refCount; /* Number of instances using this map. */ - int liveRefCount; /* Number of instances which are actually - * in use, using this map. */ + int liveRefCount; /* Number of instances which are actually in + * use, using this map. */ int numColors; /* Number of colors allocated for this map. */ XVisualInfo visualInfo; /* Information about the visual for windows * using this color table. */ - pixel redValues[256]; /* Maps 8-bit values of red intensity - * to a pixel value or index in pixelMap. */ - pixel greenValues[256]; /* Ditto for green intensity */ - pixel blueValues[256]; /* Ditto for blue intensity */ + pixel redValues[256]; /* Maps 8-bit values of red intensity to a + * pixel value or index in pixelMap. */ + pixel greenValues[256]; /* Ditto for green intensity. */ + pixel blueValues[256]; /* Ditto for blue intensity. */ unsigned long *pixelMap; /* Actual pixel values allocated. */ unsigned char colorQuant[3][256]; /* Maps 8-bit intensities to quantized - * intensities. The first index is 0 for - * red, 1 for green, 2 for blue. */ + * intensities. The first index is 0 for red, + * 1 for green, 2 for blue. */ } ColorTable; /* @@ -123,12 +119,13 @@ typedef struct ColorTable { * available. * COLOR_WINDOW: 1 means a full 3-D color cube has been * allocated. - * DISPOSE_PENDING: 1 means a call to DisposeColorTable has - * been scheduled as an idle handler, but it - * hasn't been invoked yet. - * MAP_COLORS: 1 means pixel values should be mapped - * through pixelMap. + * DISPOSE_PENDING: 1 means a call to DisposeColorTable has been + * scheduled as an idle handler, but it hasn't + * been invoked yet. + * MAP_COLORS: 1 means pixel values should be mapped through + * pixelMap. */ + #ifdef COLOR_WINDOW #undef COLOR_WINDOW #endif @@ -143,14 +140,13 @@ typedef struct ColorTable { */ typedef struct PhotoMaster { - Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means - * the image is being deleted. */ - Tcl_Interp *interp; /* Interpreter associated with the - * application using this image. */ - Tcl_Command imageCmd; /* Token for image command (used to delete - * it when the image goes away). NULL means - * the image command has already been - * deleted. */ + Tk_ImageMaster tkMaster; /* Tk's token for image master. NULL means the + * image is being deleted. */ + Tcl_Interp *interp; /* Interpreter associated with the application + * using this image. */ + Tcl_Command imageCmd; /* Token for image command (used to delete it + * when the image goes away). NULL means the + * image command has already been deleted. */ int flags; /* Sundry flags, defined below. */ int width, height; /* Dimensions of image. */ int userWidth, userHeight; /* User-declared image dimensions. */ @@ -159,26 +155,27 @@ typedef struct PhotoMaster { double gamma; /* Display gamma value to correct for. */ char *fileString; /* Name of file to read into image. */ Tcl_Obj *dataString; /* Object to use as contents of image. */ - Tcl_Obj *format; /* User-specified format of data in image - * file or string value. */ + Tcl_Obj *format; /* User-specified format of data in image file + * or string value. */ unsigned char *pix32; /* Local storage for 32-bit image. */ - int ditherX, ditherY; /* Location of first incorrectly - * dithered pixel in image. */ - TkRegion validRegion; /* Tk region indicating which parts of - * the image have valid image data. */ + int ditherX, ditherY; /* Location of first incorrectly dithered + * pixel in image. */ + TkRegion validRegion; /* Tk region indicating which parts of the + * image have valid image data. */ struct PhotoInstance *instancePtr; - /* First in the list of instances - * associated with this master. */ + /* First in the list of instances associated + * with this master. */ } PhotoMaster; /* * Bit definitions for the flags field of a PhotoMaster. * COLOR_IMAGE: 1 means that the image has different color * components. - * IMAGE_CHANGED: 1 means that the instances of this image - * need to be redithered. - * COMPLEX_ALPHA: 1 means that the instances of this image - * have alpha values that aren't 0 or 255. + * IMAGE_CHANGED: 1 means that the instances of this image need + * to be redithered. + * COMPLEX_ALPHA: 1 means that the instances of this image have + * alpha values that aren't 0 or 255, and so need + * the copy-merge-replace renderer . */ #define COLOR_IMAGE 1 @@ -193,9 +190,8 @@ typedef struct PhotoMaster { #define SOURCE_IS_SIMPLE_ALPHA_PHOTO 0x10000000 /* - * The following data structure represents all of the instances of - * a photo image in windows on a given screen that are using the - * same colormap. + * The following data structure represents all of the instances of a photo + * image in windows on a given screen that are using the same colormap. */ typedef struct PhotoInstance { @@ -204,34 +200,34 @@ typedef struct PhotoInstance { Colormap colormap; /* The image may only be used in windows with * this particular colormap. */ struct PhotoInstance *nextPtr; - /* Pointer to the next instance in the list - * of instances associated with this master. */ + /* Pointer to the next instance in the list of + * instances associated with this master. */ int refCount; /* Number of instances using this structure. */ Tk_Uid palette; /* Palette for these particular instances. */ double gamma; /* Gamma value for these instances. */ - Tk_Uid defaultPalette; /* Default palette to use if a palette - * is not specified for the master. */ + Tk_Uid defaultPalette; /* Default palette to use if a palette is not + * specified for the master. */ ColorTable *colorTablePtr; /* Pointer to information about colors - * allocated for image display in windows - * like this one. */ + * allocated for image display in windows like + * this one. */ Pixmap pixels; /* X pixmap containing dithered image. */ int width, height; /* Dimensions of the pixmap. */ schar *error; /* Error image, used in dithering. */ XImage *imagePtr; /* Image structure for converted pixels. */ XVisualInfo visualInfo; /* Information about the visual that these * windows are using. */ - GC gc; /* Graphics context for writing images - * to the pixmap. */ + GC gc; /* Graphics context for writing images to the + * pixmap. */ } PhotoInstance; /* - * The following data structure is used to return information - * from ParseSubcommandOptions: + * The following data structure is used to return information from + * ParseSubcommandOptions: */ struct SubcommandOptions { - int options; /* Individual bits indicate which - * options were specified - see below. */ + int options; /* Individual bits indicate which options were + * specified - see below. */ Tcl_Obj *name; /* Name specified without an option. */ int fromX, fromY; /* Values specified for -from option. */ int fromX2, fromY2; /* Second coordinate pair for -from option. */ @@ -241,15 +237,16 @@ struct SubcommandOptions { int subsampleX, subsampleY; /* Values specified for -subsample option. */ Tcl_Obj *format; /* Value specified for -format option. */ XColor *background; /* Value specified for -background option. */ - int compositingRule; /* Value specified for -compositingrule opt */ + int compositingRule; /* Value specified for -compositingrule + * option. */ }; /* - * Bit definitions for use with ParseSubcommandOptions: - * Each bit is set in the allowedOptions parameter on a call to - * ParseSubcommandOptions if that option is allowed for the current - * photo image subcommand. On return, the bit is set in the options - * field of the SubcommandOptions structure if that option was specified. + * Bit definitions for use with ParseSubcommandOptions: each bit is set in the + * allowedOptions parameter on a call to ParseSubcommandOptions if that option + * is allowed for the current photo image subcommand. On return, the bit is + * set in the options field of the SubcommandOptions structure if that option + * was specified. * * OPT_BACKGROUND: Set if -format option allowed/specified. * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd. @@ -273,8 +270,8 @@ struct SubcommandOptions { #define OPT_ZOOM 0x100 /* - * List of option names. The order here must match the order of - * declarations of the OPT_* constants above. + * List of option names. The order here must match the order of declarations + * of the OPT_* constants above. */ static char *optionNames[] = { @@ -287,13 +284,14 @@ static char *optionNames[] = { "-subsample", "-to", "-zoom", - (char *) NULL + NULL }; /* - * Message to generate when an attempt to resize an image fails due - * to memory problems. + * Message to generate when an attempt to resize an image fails due to memory + * problems. */ + #define TK_PHOTO_ALLOC_FAILURE_MESSAGE \ "not enough free memory for image buffer" @@ -301,23 +299,21 @@ static char *optionNames[] = { * Functions used in the type record for photo images. */ -static int ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int objc, Tcl_Obj *CONST objv[], +static int ImgPhotoCreate(Tcl_Interp *interp, char *name, + int objc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, - ClientData *clientDataPtr)); -static ClientData ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin, - ClientData clientData)); -static void ImgPhotoDisplay _ANSI_ARGS_((ClientData clientData, + ClientData *clientDataPtr); +static ClientData ImgPhotoGet(Tk_Window tkwin, ClientData clientData); +static void ImgPhotoDisplay(ClientData clientData, Display *display, Drawable drawable, int imageX, int imageY, int width, int height, - int drawableX, int drawableY)); -static void ImgPhotoFree _ANSI_ARGS_((ClientData clientData, - Display *display)); -static void ImgPhotoDelete _ANSI_ARGS_((ClientData clientData)); -static int ImgPhotoPostscript _ANSI_ARGS_((ClientData clientData, + int drawableX, int drawableY); +static void ImgPhotoFree(ClientData clientData, Display *display); +static void ImgPhotoDelete(ClientData clientData); +static int ImgPhotoPostscript(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, int x, int y, int width, - int height, int prepass)); + int height, int prepass); /* * The type record itself for photo images: @@ -331,15 +327,18 @@ Tk_ImageType tkPhotoImageType = { ImgPhotoFree, /* freeProc */ ImgPhotoDelete, /* deleteProc */ ImgPhotoPostscript, /* postscriptProc */ - (Tk_ImageType *) NULL /* nextPtr */ + NULL /* nextPtr */ }; typedef struct ThreadSpecificData { - Tk_PhotoImageFormat *formatList; /* Pointer to the first in the - * list of known photo image formats.*/ - Tk_PhotoImageFormat *oldFormatList; /* Pointer to the first in the - * list of known photo image formats.*/ - int initialized; /* set to 1 if we've initialized the strucuture */ + Tk_PhotoImageFormat *formatList; + /* Pointer to the first in the list of known + * photo image formats.*/ + Tk_PhotoImageFormat *oldFormatList; + /* Pointer to the first in the list of known + * photo image formats.*/ + int initialized; /* Set to 1 if we've initialized the + * strucuture. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -355,24 +354,24 @@ static Tcl_ThreadDataKey dataKey; /* * Information used for parsing configuration specifications: */ + static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL, + {TK_CONFIG_STRING, "-file", NULL, NULL, + NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK}, + {TK_CONFIG_DOUBLE, "-gamma", NULL, NULL, DEF_PHOTO_GAMMA, Tk_Offset(PhotoMaster, gamma), 0}, - {TK_CONFIG_INT, "-height", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-height", NULL, NULL, DEF_PHOTO_HEIGHT, Tk_Offset(PhotoMaster, userHeight), 0}, - {TK_CONFIG_UID, "-palette", (char *) NULL, (char *) NULL, + {TK_CONFIG_UID, "-palette", NULL, NULL, DEF_PHOTO_PALETTE, Tk_Offset(PhotoMaster, palette), 0}, - {TK_CONFIG_INT, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_INT, "-width", NULL, NULL, DEF_PHOTO_WIDTH, Tk_Offset(PhotoMaster, userWidth), 0}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Hash table used to hash from (display, colormap, palette, gamma) - * to ColorTable address. + * Hash table used to hash from (display, colormap, palette, gamma) to + * ColorTable address. */ static Tcl_HashTable imgPhotoColorHash; @@ -392,61 +391,53 @@ static int imgPhotoColorHashInitialized; * Forward declarations */ -static void PhotoFormatThreadExitProc _ANSI_ARGS_(( - ClientData clientData)); -static int ImgPhotoCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int ParseSubcommandOptions _ANSI_ARGS_(( +static void PhotoFormatThreadExitProc(ClientData clientData); +static int ImgPhotoCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int ParseSubcommandOptions( struct SubcommandOptions *optPtr, Tcl_Interp *interp, int allowedOptions, - int *indexPtr, int objc, Tcl_Obj *CONST objv[])); -static void ImgPhotoCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static int ImgPhotoConfigureMaster _ANSI_ARGS_(( - Tcl_Interp *interp, PhotoMaster *masterPtr, - int objc, Tcl_Obj *CONST objv[], int flags)); -static void ImgPhotoConfigureInstance _ANSI_ARGS_(( - PhotoInstance *instancePtr)); -static int ToggleComplexAlphaIfNeeded _ANSI_ARGS_(( - PhotoMaster *mPtr)); -static void ImgPhotoBlendComplexAlpha _ANSI_ARGS_(( - XImage *bgImg, PhotoInstance *iPtr, - int xOffset, int yOffset, int width, int height)); -static int ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr, - int width, int height)); -static void ImgPhotoInstanceSetSize _ANSI_ARGS_(( - PhotoInstance *instancePtr)); -static int ImgStringWrite _ANSI_ARGS_((Tcl_Interp *interp, + int *indexPtr, int objc, Tcl_Obj *const objv[]); +static void ImgPhotoCmdDeletedProc(ClientData clientData); +static int ImgPhotoConfigureMaster(Tcl_Interp *interp, + PhotoMaster *masterPtr, int objc, + Tcl_Obj *const objv[], int flags); +static void ImgPhotoConfigureInstance(PhotoInstance *instancePtr); +static int ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr); +static void ImgPhotoBlendComplexAlpha(XImage *bgImg, + PhotoInstance *iPtr, int xOffset, int yOffset, + int width, int height); +static int ImgPhotoSetSize(PhotoMaster *masterPtr, int width, + int height); +static void ImgPhotoInstanceSetSize(PhotoInstance *instancePtr); +static int ImgStringWrite(Tcl_Interp *interp, Tcl_Obj *formatString, - Tk_PhotoImageBlock *blockPtr)); -static char * ImgGetPhoto _ANSI_ARGS_((PhotoMaster *masterPtr, + Tk_PhotoImageBlock *blockPtr); +static char * ImgGetPhoto(PhotoMaster *masterPtr, Tk_PhotoImageBlock *blockPtr, - struct SubcommandOptions *optPtr)); -static int IsValidPalette _ANSI_ARGS_((PhotoInstance *instancePtr, - CONST char *palette)); -static int CountBits _ANSI_ARGS_((pixel mask)); -static void GetColorTable _ANSI_ARGS_((PhotoInstance *instancePtr)); -static void FreeColorTable _ANSI_ARGS_((ColorTable *colorPtr, - int force)); -static void AllocateColors _ANSI_ARGS_((ColorTable *colorPtr)); -static void DisposeColorTable _ANSI_ARGS_((ClientData clientData)); -static void DisposeInstance _ANSI_ARGS_((ClientData clientData)); -static int ReclaimColors _ANSI_ARGS_((ColorTableId *id, - int numColors)); -static int MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Channel chan, char *fileName, Tcl_Obj *formatString, + struct SubcommandOptions *optPtr); +static int IsValidPalette(PhotoInstance *instancePtr, + const char *palette); +static int CountBits(pixel mask); +static void GetColorTable(PhotoInstance *instancePtr); +static void FreeColorTable(ColorTable *colorPtr, int force); +static void AllocateColors(ColorTable *colorPtr); +static void DisposeColorTable(ClientData clientData); +static void DisposeInstance(ClientData clientData); +static int ReclaimColors(ColorTableId *id, int numColors); +static int MatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan, + char *fileName, Tcl_Obj *formatString, Tk_PhotoImageFormat **imageFormatPtr, - int *widthPtr, int *heightPtr, int *oldformat)); -static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *data, Tcl_Obj *formatString, + int *widthPtr, int *heightPtr, int *oldformat); +static int MatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data, + Tcl_Obj *formatString, Tk_PhotoImageFormat **imageFormatPtr, - int *widthPtr, int *heightPtr, int *oldformat)); -static Tcl_ObjCmdProc * PhotoOptionFind _ANSI_ARGS_((Tcl_Interp * interp, - Tcl_Obj *obj)); -static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr, - int x, int y, int width, int height)); -static void PhotoOptionCleanupProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); + int *widthPtr, int *heightPtr, int *oldformat); +static Tcl_ObjCmdProc * PhotoOptionFind(Tcl_Interp *interp, Tcl_Obj *obj); +static void DitherInstance(PhotoInstance *instancePtr, int x, + int y, int width, int height); +static void PhotoOptionCleanupProc(ClientData clientData, + Tcl_Interp *interp); #undef MIN #define MIN(a, b) ((a) < (b)? (a): (b)) @@ -456,35 +447,30 @@ static void PhotoOptionCleanupProc _ANSI_ARGS_(( /* *---------------------------------------------------------------------- * - * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat -- + * PhotoFormatThreadExitProc -- * - * This procedure is invoked by an image file handler to register - * a new photo image format and the procedures that handle the - * new format. The procedure is typically invoked during - * Tcl_AppInit. + * Clean up the registered list of photo formats. * * Results: * None. * * Side effects: - * The new image file format is entered into a table used in the - * photo image "read" and "write" subcommands. + * The thread's linked lists of photo image formats is deleted. * *---------------------------------------------------------------------- */ static void -PhotoFormatThreadExitProc(clientData) - ClientData clientData; /* not used */ +PhotoFormatThreadExitProc( + ClientData clientData) /* not used */ { Tk_PhotoImageFormat *freePtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); while (tsdPtr->oldFormatList != NULL) { freePtr = tsdPtr->oldFormatList; tsdPtr->oldFormatList = tsdPtr->oldFormatList->nextPtr; - ckfree((char *) freePtr->name); ckfree((char *) freePtr); } while (tsdPtr->formatList != NULL) { @@ -500,31 +486,30 @@ PhotoFormatThreadExitProc(clientData) * * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat -- * - * This procedure is invoked by an image file handler to register - * a new photo image format and the procedures that handle the - * new format. The procedure is typically invoked during - * Tcl_AppInit. + * This function is invoked by an image file handler to register a new + * photo image format and the functions that handle the new format. The + * function is typically invoked during Tcl_AppInit. * * Results: * None. * * Side effects: - * The new image file format is entered into a table used in the - * photo image "read" and "write" subcommands. + * The new image file format is entered into a table used in the photo + * image "read" and "write" subcommands. * *---------------------------------------------------------------------- */ + void -Tk_CreateOldPhotoImageFormat(formatPtr) - Tk_PhotoImageFormat *formatPtr; - /* Structure describing the format. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreatePhotoImageFormat previously. */ +Tk_CreateOldPhotoImageFormat( + Tk_PhotoImageFormat *formatPtr) + /* Structure describing the format. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { Tk_PhotoImageFormat *copyPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; @@ -532,23 +517,20 @@ Tk_CreateOldPhotoImageFormat(formatPtr) } copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); *copyPtr = *formatPtr; - copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); - strcpy(copyPtr->name, formatPtr->name); copyPtr->nextPtr = tsdPtr->oldFormatList; tsdPtr->oldFormatList = copyPtr; } void -Tk_CreatePhotoImageFormat(formatPtr) - Tk_PhotoImageFormat *formatPtr; - /* Structure describing the format. All of - * the fields except "nextPtr" must be filled - * in by caller. Must not have been passed - * to Tk_CreatePhotoImageFormat previously. */ +Tk_CreatePhotoImageFormat( + Tk_PhotoImageFormat *formatPtr) + /* Structure describing the format. All of the + * fields except "nextPtr" must be filled in + * by caller. */ { Tk_PhotoImageFormat *copyPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; @@ -556,12 +538,14 @@ Tk_CreatePhotoImageFormat(formatPtr) } copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); *copyPtr = *formatPtr; - copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); - strcpy(copyPtr->name, formatPtr->name); if (isupper((unsigned char) *formatPtr->name)) { copyPtr->nextPtr = tsdPtr->oldFormatList; tsdPtr->oldFormatList = copyPtr; } else { + /* for compatibility with aMSN: make a copy of formatPtr->name */ + char *name = ckalloc(strlen(formatPtr->name) + 1); + strcpy(name, formatPtr->name); + copyPtr->name = name; copyPtr->nextPtr = tsdPtr->formatList; tsdPtr->formatList = copyPtr; } @@ -572,32 +556,31 @@ Tk_CreatePhotoImageFormat(formatPtr) * * ImgPhotoCreate -- * - * This procedure is called by the Tk image code to create - * a new photo image. + * This function is called by the Tk image code to create a new photo + * image. * * Results: * A standard Tcl result. * * Side effects: - * The data structure for a new photo image is allocated and - * initialized. + * The data structure for a new photo image is allocated and initialized. * *---------------------------------------------------------------------- */ static int -ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) - Tcl_Interp *interp; /* Interpreter for application containing +ImgPhotoCreate( + Tcl_Interp *interp, /* Interpreter for application containing * image. */ - char *name; /* Name to use for image. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects for options (doesn't + char *name, /* Name to use for image. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument objects for options (doesn't * include image name or type). */ - Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ - Tk_ImageMaster master; /* Token for image, to be used by us in - * later callbacks. */ - ClientData *clientDataPtr; /* Store manager's token for image here; - * it will be returned in later callbacks. */ + Tk_ImageType *typePtr, /* Pointer to our type record (not used). */ + Tk_ImageMaster master, /* Token for image, to be used by us in later + * callbacks. */ + ClientData *clientDataPtr) /* Store manager's token for image here; it + * will be returned in later callbacks. */ { PhotoMaster *masterPtr; @@ -606,7 +589,7 @@ ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) */ masterPtr = (PhotoMaster *) ckalloc(sizeof(PhotoMaster)); - memset((void *) masterPtr, 0, sizeof(PhotoMaster)); + memset(masterPtr, 0, sizeof(PhotoMaster)); masterPtr->tkMaster = master; masterPtr->interp = interp; masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgPhotoCmd, @@ -634,9 +617,9 @@ ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) * * ImgPhotoCmd -- * - * This procedure is invoked to process the Tcl command that - * corresponds to a photo image. See the user documentation - * for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a photo image. See the user documentation for details on what it + * does. * * Results: * A standard Tcl result. @@ -648,42 +631,35 @@ ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) */ static int -ImgPhotoCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about photo master. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +ImgPhotoCmd( + ClientData clientData, /* Information about photo master. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - int oldformat = 0; - static CONST char *photoOptions[] = { + static const char *photoOptions[] = { "blank", "cget", "configure", "copy", "data", "get", "put", - "read", "redither", "transparency", "write", (char *) NULL + "read", "redither", "transparency", "write", NULL }; - enum options { + enum PhotoOptions { PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA, PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_TRANS, PHOTO_WRITE }; PhotoMaster *masterPtr = (PhotoMaster *) clientData; - int result, index; - int x, y, width, height; - int dataWidth, dataHeight; + int result, index, x, y, width, height, dataWidth, dataHeight, listObjc; struct SubcommandOptions options; - int listArgc; - CONST char **listArgv; - CONST char **srcArgv; + Tcl_Obj **listObjv, **srcObjv; unsigned char *pixelPtr; Tk_PhotoImageBlock block; Tk_Window tkwin; - XColor color; Tk_PhotoImageFormat *imageFormat; - int imageWidth, imageHeight; - int length, matched; + int imageWidth, imageHeight, matched, length, oldformat = 0; Tcl_Channel chan; Tk_PhotoHandle srcHandle; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); @@ -694,13 +670,13 @@ ImgPhotoCmd(clientData, interp, objc, objv) &index) != TCL_OK) { Tcl_ObjCmdProc *proc; proc = PhotoOptionFind(interp, objv[1]); - if (proc == (Tcl_ObjCmdProc *) NULL) { + if (proc == NULL) { return TCL_ERROR; } return proc(clientData, interp, objc, objv); } - switch ((enum options) index) { + switch ((enum PhotoOptions) index) { case PHOTO_BLANK: /* * photo blank command - just call Tk_PhotoBlank. @@ -710,7 +686,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) Tk_PhotoBlank(masterPtr); return TCL_OK; } else { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } @@ -744,53 +720,51 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (objc == 2) { Tcl_Obj *obj, *subobj; + result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp), - configSpecs, (char *) masterPtr, (char *) NULL, 0); + configSpecs, (char *) masterPtr, NULL, 0); if (result != TCL_OK) { return result; } obj = Tcl_NewObj(); subobj = Tcl_NewStringObj("-data {} {} {}", 14); if (masterPtr->dataString) { - Tcl_ListObjAppendElement(interp, subobj, masterPtr->dataString); + Tcl_ListObjAppendElement(NULL, subobj, masterPtr->dataString); } else { - Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL); + Tcl_AppendStringsToObj(subobj, " {}", NULL); } Tcl_ListObjAppendElement(interp, obj, subobj); subobj = Tcl_NewStringObj("-format {} {} {}", 16); if (masterPtr->format) { - Tcl_ListObjAppendElement(interp, subobj, masterPtr->format); + Tcl_ListObjAppendElement(NULL, subobj, masterPtr->format); } else { - Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL); + Tcl_AppendStringsToObj(subobj, " {}", NULL); } Tcl_ListObjAppendElement(interp, obj, subobj); Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp)); Tcl_SetObjResult(interp, obj); return TCL_OK; - } - if (objc == 3) { + + } else if (objc == 3) { char *arg = Tcl_GetStringFromObj(objv[2], &length); - if (!strncmp(arg, "-data", (unsigned) length)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "-data {} {} {}", (char *) NULL); + if (length > 1 && !strncmp(arg, "-data", (unsigned) length)) { + Tcl_AppendResult(interp, "-data {} {} {}", NULL); if (masterPtr->dataString) { Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), masterPtr->dataString); } else { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - " {}", (char *) NULL); + Tcl_AppendResult(interp, " {}", NULL); } return TCL_OK; - } else if (!strncmp(arg, "-format", (unsigned) length)) { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "-format {} {} {}", (char *) NULL); + } else if (length > 1 && + !strncmp(arg, "-format", (unsigned) length)) { + Tcl_AppendResult(interp, "-format {} {} {}", NULL); if (masterPtr->format) { Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), masterPtr->format); } else { - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - " {}", (char *) NULL); + Tcl_AppendResult(interp, " {}", NULL); } return TCL_OK; } else { @@ -807,7 +781,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.zoomX = options.zoomY = 1; options.subsampleX = options.subsampleY = 1; options.name = NULL; @@ -832,7 +806,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (srcHandle == NULL) { Tcl_AppendResult(interp, "image \"", Tcl_GetString(options.name), "\" doesn't", - " exist or is not a photo image", (char *) NULL); + " exist or is not a photo image", NULL); return TCL_ERROR; } Tk_PhotoGetImage(srcHandle, &block); @@ -840,7 +814,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > block.width) || (options.fromY2 > block.height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside source image", (char *) NULL); + "outside source image", NULL); return TCL_ERROR; } @@ -893,8 +867,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (ImgPhotoSetSize(masterPtr, options.toX2, options.toY2) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); return TCL_ERROR; } } @@ -907,12 +880,11 @@ ImgPhotoCmd(clientData, interp, objc, objv) + options.fromY * block.pitch; block.width = options.fromX2 - options.fromX; block.height = options.fromY2 - options.fromY; - Tk_PhotoPutZoomedBlock((Tk_PhotoHandle) masterPtr, &block, - options.toX, options.toY, options.toX2 - options.toX, + 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); - return TCL_OK; case PHOTO_DATA: { char *data; @@ -920,10 +892,11 @@ ImgPhotoCmd(clientData, interp, objc, objv) /* * photo data command - first parse and check any options given. */ + Tk_ImageStringWriteProc *stringWriteProc = NULL; index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; options.fromX = 0; @@ -942,7 +915,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > masterPtr->width) || (options.fromY2 > masterPtr->height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside image", (char *) NULL); + "outside image", NULL); return TCL_ERROR; } @@ -990,8 +963,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (stringWriteProc == NULL) { Tcl_AppendResult(interp, "image string format \"", Tcl_GetString(options.format), "\" is ", - (matched ? "not supported" : "unknown"), - (char *) NULL); + (matched ? "not supported" : "unknown"), NULL); return TCL_ERROR; } } else { @@ -999,8 +971,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) } /* - * Call the handler's string write procedure to write out - * the image. + * Call the handler's string write function to write out the image. */ data = ImgGetPhoto(masterPtr, &block, &options); @@ -1009,9 +980,9 @@ ImgPhotoCmd(clientData, interp, objc, objv) Tcl_DString buffer; Tcl_DStringInit(&buffer); - result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_DString *buffer, char *formatString, - Tk_PhotoImageBlock *blockPtr))) stringWriteProc) + result = ((int (*) (Tcl_Interp *interp, + Tcl_DString *dataPtr, char *formatString, + Tk_PhotoImageBlock *blockPtr)) stringWriteProc) (interp, &buffer, Tcl_GetString(options.format), &block); if (result == TCL_OK) { Tcl_DStringResult(interp, &buffer); @@ -1019,10 +990,11 @@ ImgPhotoCmd(clientData, interp, objc, objv) Tcl_DStringFree(&buffer); } } else { - result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp, + + result = ((int (*) (Tcl_Interp *interp, Tcl_Obj *formatString, Tk_PhotoImageBlock *blockPtr, - VOID *dummy))) stringWriteProc) - (interp, options.format, &block, (VOID *) NULL); + void *dummy)) stringWriteProc) + (interp, options.format, &block, NULL); } if (options.background) { Tk_FreeColor(options.background); @@ -1051,7 +1023,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " get: ", - "coordinates out of range", (char *) NULL); + "coordinates out of range", NULL); return TCL_ERROR; } @@ -1062,7 +1034,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) pixelPtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1], pixelPtr[2]); - Tcl_AppendResult(interp, string, (char *) NULL); + Tcl_AppendResult(interp, string, NULL); return TCL_OK; } @@ -1072,7 +1044,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT, &index, objc, objv) != TCL_OK) { @@ -1083,7 +1055,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_ERROR; } - if (MatchStringFormat(interp, options.name ? objv[2]:NULL, + if (MatchStringFormat(interp, options.name ? objv[2]:NULL, options.format, &imageFormat, &imageWidth, &imageHeight, &oldformat) == TCL_OK) { Tcl_Obj *format, *data; @@ -1119,8 +1091,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_ERROR; } Tcl_ResetResult(interp); - if (Tcl_SplitList(interp, Tcl_GetString(options.name), - &dataHeight, &srcArgv) != TCL_OK) { + if (Tcl_ListObjGetElements(interp, options.name, + &dataHeight, &srcObjv) != TCL_OK) { return TCL_ERROR; } tkwin = Tk_MainWindow(interp); @@ -1128,44 +1100,80 @@ ImgPhotoCmd(clientData, interp, objc, objv) dataWidth = 0; pixelPtr = NULL; for (y = 0; y < dataHeight; ++y) { - if (Tcl_SplitList(interp, srcArgv[y], &listArgc, &listArgv) - != TCL_OK) { + if (Tcl_ListObjGetElements(interp, srcObjv[y], + &listObjc, &listObjv) != TCL_OK) { break; } + if (y == 0) { - if (listArgc == 0) { + if (listObjc == 0) { /* * Lines must be non-empty... */ + break; } - dataWidth = listArgc; + dataWidth = listObjc; pixelPtr = (unsigned char *) ckalloc((unsigned) dataWidth * dataHeight * 3); block.pixelPtr = pixelPtr; - } else if (listArgc != dataWidth) { + } else if (listObjc != dataWidth) { Tcl_AppendResult(interp, "all elements of color list must", - " have the same number of elements", (char *) NULL); - ckfree((char *) listArgv); + " have the same number of elements", NULL); break; } + for (x = 0; x < dataWidth; ++x) { + 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), - listArgv[x], &color)) { + colorString, &color)) { Tcl_AppendResult(interp, "can't parse color \"", - listArgv[x], "\"", (char *) NULL); + colorString, "\"", NULL); break; } *pixelPtr++ = color.red >> 8; *pixelPtr++ = color.green >> 8; *pixelPtr++ = color.blue >> 8; } - ckfree((char *) listArgv); if (x < dataWidth) { break; } } - ckfree((char *) srcArgv); if (y < dataHeight || dataHeight == 0 || dataWidth == 0) { if (block.pixelPtr != NULL) { ckfree((char *) block.pixelPtr); @@ -1177,8 +1185,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) } /* - * Fill in default values for the -to option, then - * copy the block in using Tk_PhotoPutBlock. + * Fill in default values for the -to option, then copy the block in + * using Tk_PhotoPutBlock. */ if (!(options.options & OPT_TO) || (options.toX2 < 0)) { @@ -1193,11 +1201,12 @@ ImgPhotoCmd(clientData, interp, objc, objv) block.offset[1] = 1; block.offset[2] = 2; block.offset[3] = 0; - Tk_PhotoPutBlock((ClientData)masterPtr, &block, + result = Tk_PhotoPutBlock(interp, (ClientData)masterPtr, &block, options.toX, options.toY, options.toX2 - options.toX, - options.toY2 - options.toY, TK_PHOTO_COMPOSITE_SET); + options.toY2 - options.toY, + TK_PHOTO_COMPOSITE_SET); ckfree((char *) block.pixelPtr); - return TCL_OK; + return result; case PHOTO_READ: { Tcl_Obj *format; @@ -1207,7 +1216,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, @@ -1220,16 +1229,16 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_ERROR; } - /* - * Prevent file system access in safe interpreters. - */ + /* + * Prevent file system access in safe interpreters. + */ + + if (Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't get image from a file in a", + " safe interpreter", NULL); + return TCL_ERROR; + } - if (Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't get image from a file in a", - " safe interpreter", (char *) NULL); - return TCL_ERROR; - } - /* * Open the image file and look for a handler for it. */ @@ -1239,17 +1248,17 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (chan == NULL) { return TCL_ERROR; } - if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") + if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) { Tcl_Close(NULL, chan); - return TCL_ERROR; - } - if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary") + return TCL_ERROR; + } + if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary") != TCL_OK) { Tcl_Close(NULL, chan); - return TCL_ERROR; - } - + return TCL_ERROR; + } + if (MatchFileFormat(interp, chan, Tcl_GetString(options.name), options.format, &imageFormat, &imageWidth, &imageHeight, &oldformat) != TCL_OK) { @@ -1265,7 +1274,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > imageWidth) || (options.fromY2 > imageHeight)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside source image", (char *) NULL); + "outside source image", NULL); Tcl_Close(NULL, chan); return TCL_ERROR; } @@ -1285,15 +1294,14 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (ImgPhotoSetSize(masterPtr, options.toX + width, options.toY + height) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); return TCL_ERROR; } } /* - * Call the handler's file read procedure to read the data - * into the image. + * Call the handler's file read function to read the data into the + * image. */ format = options.format; @@ -1312,13 +1320,13 @@ ImgPhotoCmd(clientData, interp, objc, objv) case PHOTO_REDITHER: if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } /* - * Call Dither if any part of the image is not correctly - * dithered at present. + * Call Dither if any part of the image is not correctly dithered at + * present. */ x = masterPtr->ditherX; @@ -1346,8 +1354,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) return TCL_OK; case PHOTO_TRANS: { - static CONST char *photoTransOptions[] = { - "get", "set", (char *) NULL + static const char *photoTransOptions[] = { + "get", "set", NULL }; enum transOptions { PHOTO_TRANS_GET, PHOTO_TRANS_SET @@ -1378,8 +1386,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), - " transparency get: coordinates out of range", - (char *) NULL); + " transparency get: coordinates out of range", NULL); return TCL_ERROR; } @@ -1416,8 +1423,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) if ((x < 0) || (x >= masterPtr->width) || (y < 0) || (y >= masterPtr->height)) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), - " transparency set: coordinates out of range", - (char *) NULL); + " transparency set: coordinates out of range", NULL); return TCL_ERROR; } @@ -1431,20 +1437,24 @@ ImgPhotoCmd(clientData, interp, objc, objv) /* * Make pixel transparent. */ + TkRegion clearRegion = TkCreateRegion(); TkUnionRectWithRegion(&setBox, clearRegion, clearRegion); TkSubtractRegion(masterPtr->validRegion, clearRegion, masterPtr->validRegion); TkDestroyRegion(clearRegion); + /* * Set the alpha value correctly. */ + pixelPtr[3] = 0; } else { /* * Make pixel opaque. */ + TkUnionRectWithRegion(&setBox, masterPtr->validRegion, masterPtr->validRegion); pixelPtr[3] = 255; @@ -1460,31 +1470,31 @@ ImgPhotoCmd(clientData, interp, objc, objv) masterPtr->flags &= ~IMAGE_CHANGED; return TCL_OK; } - } - panic("unexpected fallthrough"); + } + Tcl_Panic("unexpected fallthrough"); } case PHOTO_WRITE: { char *data; Tcl_Obj *format; - /* - * Prevent file system access in safe interpreters. - */ + /* + * Prevent file system access in safe interpreters. + */ + + if (Tcl_IsSafe(interp)) { + Tcl_AppendResult(interp, "can't write image to a file in a", + " safe interpreter", NULL); + return TCL_ERROR; + } - if (Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't write image to a file in a", - " safe interpreter", (char *) NULL); - return TCL_ERROR; - } - /* * photo write command - first parse and check any options given. */ index = 2; - memset((VOID *) &options, 0, sizeof(options)); + memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; if (ParseSubcommandOptions(&options, interp, @@ -1501,7 +1511,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) || (options.fromX2 > masterPtr->width) || (options.fromY2 > masterPtr->height)) { Tcl_AppendResult(interp, "coordinates for -from option extend ", - "outside image", (char *) NULL); + "outside image", NULL); return TCL_ERROR; } @@ -1515,8 +1525,8 @@ ImgPhotoCmd(clientData, interp, objc, objv) } /* - * Search for an appropriate image file format handler, - * and give an error if none is found. + * Search for an appropriate image file format handler, and give an + * error if none is found. */ matched = 0; @@ -1548,23 +1558,21 @@ ImgPhotoCmd(clientData, interp, objc, objv) if (imageFormat == NULL) { if (options.format == NULL) { Tcl_AppendResult(interp, "no available image file format ", - "has file writing capability", (char *) NULL); + "has file writing capability", NULL); } else if (!matched) { Tcl_AppendResult(interp, "image file format \"", Tcl_GetString(options.format), - "\" is unknown", (char *) NULL); + "\" is unknown", NULL); } else { Tcl_AppendResult(interp, "image file format \"", Tcl_GetString(options.format), - "\" has no file writing capability", - (char *) NULL); + "\" has no file writing capability", NULL); } return TCL_ERROR; } /* - * Call the handler's file write procedure to write out - * the image. + * Call the handler's file write function to write out the image. */ data = ImgGetPhoto(masterPtr, &block, &options); @@ -1584,7 +1592,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) } } - panic("unexpected fallthrough"); + Tcl_Panic("unexpected fallthrough"); return TCL_ERROR; /* NOT REACHED */ } @@ -1593,10 +1601,9 @@ ImgPhotoCmd(clientData, interp, objc, objv) * * ParseSubcommandOptions -- * - * This procedure 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. + * 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. * * Results: * A standard Tcl result. @@ -1608,29 +1615,27 @@ ImgPhotoCmd(clientData, interp, objc, objv) */ static int -ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) - struct SubcommandOptions *optPtr; - /* Information about the options specified - * and the values given is returned here. */ - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - int allowedOptions; /* Indicates which options are valid for - * the current command. */ - int *optIndexPtr; /* Points to a variable containing the - * current index in objv; this variable is - * updated by this procedure. */ - int objc; /* Number of arguments in objv[]. */ - Tcl_Obj *CONST objv[]; /* Arguments to be parsed. */ +ParseSubcommandOptions( + struct SubcommandOptions *optPtr, + /* Information about the options specified and + * the values given is returned here. */ + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + int allowedOptions, /* Indicates which options are valid for the + * current command. */ + int *optIndexPtr, /* Points to a variable containing the current + * index in objv; this variable is updated by + * this function. */ + int objc, /* Number of arguments in objv[]. */ + Tcl_Obj *const objv[]) /* Arguments to be parsed. */ { - int index, c, bit, currentBit; - int length; + int index, c, bit, currentBit, length; + int values[4], numValues, maxValues, argIndex; char *option, **listPtr; - int values[4]; - int numValues, maxValues, argIndex; for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) { /* - * We can have one value specified without an option; - * it goes into optPtr->name. + * We can have one value specified without an option; it goes into + * optPtr->name. */ option = Tcl_GetStringFromObj(objv[index], &length); @@ -1662,24 +1667,24 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } /* - * If this option is not recognized and allowed, put - * an error message in the interpreter and return. + * If this option is not recognized and allowed, put an error message + * in the interpreter and return. */ if ((allowedOptions & bit) == 0) { Tcl_AppendResult(interp, "unrecognized option \"", Tcl_GetString(objv[index]), - "\": must be ", (char *)NULL); + "\": must be ", NULL); bit = 1; for (listPtr = optionNames; *listPtr != NULL; ++listPtr) { if ((allowedOptions & bit) != 0) { if ((allowedOptions & (bit - 1)) != 0) { - Tcl_AppendResult(interp, ", ", (char *) NULL); + Tcl_AppendResult(interp, ", ", NULL); if ((allowedOptions & ~((bit << 1) - 1)) == 0) { - Tcl_AppendResult(interp, "or ", (char *) NULL); + Tcl_AppendResult(interp, "or ", NULL); } } - Tcl_AppendResult(interp, *listPtr, (char *) NULL); + Tcl_AppendResult(interp, *listPtr, NULL); } bit <<= 1; } @@ -1687,9 +1692,8 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } /* - * For the -from, -to, -zoom and -subsample options, - * parse the values given. Report an error if too few - * or too many values are given. + * For the -from, -to, -zoom and -subsample options, parse the values + * given. Report an error if too few or too many values are given. */ if (bit == OPT_BACKGROUND) { @@ -1706,14 +1710,13 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } } else { Tcl_AppendResult(interp, "the \"-background\" option ", - "requires a value", (char *) NULL); + "requires a value", NULL); return TCL_ERROR; } } else if (bit == OPT_FORMAT) { /* - * The -format option takes a single string value. Note - * that parsing this is outside the scope of this - * function. + * The -format option takes a single string value. Note that + * parsing this is outside the scope of this function. */ if (index + 1 < objc) { @@ -1721,13 +1724,13 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) optPtr->format = objv[index]; } else { Tcl_AppendResult(interp, "the \"-format\" option ", - "requires a value", (char *) NULL); + "requires a value", NULL); return TCL_ERROR; } } else if (bit == OPT_COMPOSITE) { /* - * The -compositingrule option takes a single value from - * a well-known set. + * The -compositingrule option takes a single value from a + * well-known set. */ if (index + 1 < objc) { @@ -1735,9 +1738,9 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) * Note that these must match the TK_PHOTO_COMPOSITE_* * constants. */ - static CONST char *compositingRules[] = { - "overlay", "set", - NULL + + static const char *compositingRules[] = { + "overlay", "set", NULL }; index++; @@ -1749,7 +1752,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) *optIndexPtr = index; } else { Tcl_AppendResult(interp, "the \"-compositingrule\" option ", - "requires a value", (char *) NULL); + "requires a value", NULL); return TCL_ERROR; } } else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) { @@ -1760,7 +1763,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) if (argIndex >= objc) { break; } - val = Tcl_GetString(objv[argIndex]); + val = Tcl_GetString(objv[argIndex]); if ((argIndex < objc) && (isdigit(UCHAR(val[0])) || ((val[0] == '-') && isdigit(UCHAR(val[1]))))) { if (Tcl_GetInt(interp, val, &values[numValues]) @@ -1776,7 +1779,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) if (numValues == 0) { Tcl_AppendResult(interp, "the \"", option, "\" option ", "requires one ", maxValues == 2? "or two": "to four", - " integer values", (char *) NULL); + " integer values", NULL); return TCL_ERROR; } *optIndexPtr = (index += numValues); @@ -1793,62 +1796,62 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) } /* - * Check the values given and put them in the appropriate - * field of the SubcommandOptions structure. + * Check the values given and put them in the appropriate field of + * the SubcommandOptions structure. */ switch (bit) { - case OPT_FROM: - if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) - && ((values[2] < 0) || (values[3] < 0)))) { - Tcl_AppendResult(interp, "value(s) for the -from", - " option must be non-negative", (char *) NULL); - return TCL_ERROR; - } - if (numValues <= 2) { - optPtr->fromX = values[0]; - optPtr->fromY = values[1]; - optPtr->fromX2 = -1; - optPtr->fromY2 = -1; - } else { - optPtr->fromX = MIN(values[0], values[2]); - optPtr->fromY = MIN(values[1], values[3]); - optPtr->fromX2 = MAX(values[0], values[2]); - optPtr->fromY2 = MAX(values[1], values[3]); - } - break; - case OPT_SUBSAMPLE: - optPtr->subsampleX = values[0]; - optPtr->subsampleY = values[1]; - break; - case OPT_TO: - if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) - && ((values[2] < 0) || (values[3] < 0)))) { - Tcl_AppendResult(interp, "value(s) for the -to", - " option must be non-negative", (char *) NULL); - return TCL_ERROR; - } - if (numValues <= 2) { - optPtr->toX = values[0]; - optPtr->toY = values[1]; - optPtr->toX2 = -1; - optPtr->toY2 = -1; - } else { - optPtr->toX = MIN(values[0], values[2]); - optPtr->toY = MIN(values[1], values[3]); - optPtr->toX2 = MAX(values[0], values[2]); - optPtr->toY2 = MAX(values[1], values[3]); - } - break; - case OPT_ZOOM: - if ((values[0] <= 0) || (values[1] <= 0)) { - Tcl_AppendResult(interp, "value(s) for the -zoom", - " option must be positive", (char *) NULL); - return TCL_ERROR; - } - optPtr->zoomX = values[0]; - optPtr->zoomY = values[1]; - break; + case OPT_FROM: + if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) + && ((values[2] < 0) || (values[3] < 0)))) { + Tcl_AppendResult(interp, "value(s) for the -from", + " option must be non-negative", NULL); + return TCL_ERROR; + } + if (numValues <= 2) { + optPtr->fromX = values[0]; + optPtr->fromY = values[1]; + optPtr->fromX2 = -1; + optPtr->fromY2 = -1; + } else { + optPtr->fromX = MIN(values[0], values[2]); + optPtr->fromY = MIN(values[1], values[3]); + optPtr->fromX2 = MAX(values[0], values[2]); + optPtr->fromY2 = MAX(values[1], values[3]); + } + break; + case OPT_SUBSAMPLE: + optPtr->subsampleX = values[0]; + optPtr->subsampleY = values[1]; + break; + case OPT_TO: + if ((values[0] < 0) || (values[1] < 0) || ((numValues > 2) + && ((values[2] < 0) || (values[3] < 0)))) { + Tcl_AppendResult(interp, "value(s) for the -to", + " option must be non-negative", NULL); + return TCL_ERROR; + } + if (numValues <= 2) { + optPtr->toX = values[0]; + optPtr->toY = values[1]; + optPtr->toX2 = -1; + optPtr->toY2 = -1; + } else { + optPtr->toX = MIN(values[0], values[2]); + optPtr->toY = MIN(values[1], values[3]); + optPtr->toX2 = MAX(values[0], values[2]); + optPtr->toY2 = MAX(values[1], values[3]); + } + break; + case OPT_ZOOM: + if ((values[0] <= 0) || (values[1] <= 0)) { + Tcl_AppendResult(interp, "value(s) for the -zoom", + " option must be positive", NULL); + return TCL_ERROR; + } + optPtr->zoomX = values[0]; + optPtr->zoomY = values[1]; + break; } } @@ -1867,45 +1870,42 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv) * * ImgPhotoConfigureMaster -- * - * This procedure is called when a photo image is created or - * reconfigured. It processes configuration options and resets - * any instances of the image. + * This function is called when a photo image is created or reconfigured. + * It processes configuration options and resets any instances of the + * image. * * Results: - * A standard Tcl return value. If TCL_ERROR is returned then - * an error message is left in the masterPtr->interp's result. + * A standard Tcl return value. If TCL_ERROR is returned then an error + * message is left in the masterPtr->interp's result. * * Side effects: - * Existing instances of the image will be redisplayed to match - * the new configuration options. + * Existing instances of the image will be redisplayed to match the new + * configuration options. * *---------------------------------------------------------------------- */ static int -ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - PhotoMaster *masterPtr; /* Pointer to data structure describing +ImgPhotoConfigureMaster( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + PhotoMaster *masterPtr, /* Pointer to data structure describing * overall photo image to (re)configure. */ - int objc; /* Number of entries in objv. */ - Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */ - int flags; /* Flags to pass to Tk_ConfigureWidget, - * such as TK_CONFIG_ARGV_ONLY. */ + int objc, /* Number of entries in objv. */ + Tcl_Obj *const objv[], /* Pairs of configuration options for image. */ + int flags) /* Flags to pass to Tk_ConfigureWidget, such + * as TK_CONFIG_ARGV_ONLY. */ { PhotoInstance *instancePtr; - CONST char *oldFileString, *oldPaletteString; + const char *oldFileString, *oldPaletteString; Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL; - int length, i, j; + Tcl_Obj *tempdata, *tempformat; + int length, i, j, result, imageWidth, imageHeight, oldformat; double oldGamma; - int result; Tcl_Channel chan; Tk_PhotoImageFormat *imageFormat; - int imageWidth, imageHeight; - CONST char **args; - int oldformat; - Tcl_Obj *tempdata, *tempformat; + const char **args; - args = (CONST char **) ckalloc((objc + 1) * sizeof(char *)); + args = (const char **) ckalloc((objc + 1) * sizeof(char *)); for (i = 0, j = 0; i < objc; i++,j++) { args[j] = Tcl_GetStringFromObj(objv[i], &length); if ((length > 1) && (args[j][0] == '-')) { @@ -1916,7 +1916,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) j--; } else { Tcl_AppendResult(interp, - "value for \"-data\" missing", (char *) NULL); + "value for \"-data\" missing", NULL); return TCL_ERROR; } } else if ((args[j][1] == 'f') && @@ -1926,7 +1926,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) j--; } else { Tcl_AppendResult(interp, - "value for \"-format\" missing", (char *) NULL); + "value for \"-format\" missing", NULL); return TCL_ERROR; } } @@ -1934,12 +1934,10 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } /* - * Save the current values for fileString and dataString, so we - * can tell if the user specifies them anew. - * IMPORTANT: if the format changes we have to interpret - * "-file" and "-data" again as well!!!!!!! It might be - * that the format string influences how "-data" or "-file" - * is interpreted. + * Save the current values for fileString and dataString, so we can tell + * if the user specifies them anew. IMPORTANT: if the format changes we + * have to interpret "-file" and "-data" again as well! It might be that + * the format string influences how "-data" or "-file" is interpreted. */ oldFileString = masterPtr->fileString; @@ -1970,8 +1968,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) ckfree((char *) args); /* - * Regard the empty string for -file, -data or -format as the null - * value. + * Regard the empty string for -file, -data or -format as the null value. */ if ((masterPtr->fileString != NULL) && (masterPtr->fileString[0] == 0)) { @@ -1980,9 +1977,10 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } if (data) { /* - * Force into ByteArray format, which most (all) image handlers - * will use anyway. Empty length means ignore the -data option. + * Force into ByteArray format, which most (all) image handlers will + * use anyway. Empty length means ignore the -data option. */ + (void) Tcl_GetByteArrayFromObj(data, &length); if (length) { Tcl_IncrRefCount(data); @@ -1996,9 +1994,10 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } if (format) { /* - * Stringify to ignore -format "". It may come in as a list or - * other object. + * Stringify to ignore -format "". It may come in as a list or other + * object. */ + (void) Tcl_GetStringFromObj(format, &length); if (length) { Tcl_IncrRefCount(format); @@ -2011,47 +2010,47 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) masterPtr->format = format; } /* - * Set the image to the user-requested size, if any, - * and make sure storage is correctly allocated for this image. + * Set the image to the user-requested size, if any, and make sure storage + * is correctly allocated for this image. */ if (ImgPhotoSetSize(masterPtr, masterPtr->width, masterPtr->height) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); goto errorExit; } /* - * Read in the image from the file or string if the user has - * specified the -file or -data option. + * Read in the image from the file or string if the user has specified the + * -file or -data option. */ if ((masterPtr->fileString != NULL) && ((masterPtr->fileString != oldFileString) || (masterPtr->format != oldFormat))) { - /* - * Prevent file system access in a safe interpreter. - */ + /* + * Prevent file system access in a safe interpreter. + */ - if (Tcl_IsSafe(interp)) { + if (Tcl_IsSafe(interp)) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - "can't get image from a file in a safe interpreter", - (char *) NULL); + Tcl_AppendResult(interp, + "can't get image from a file in a safe interpreter", NULL); goto errorExit; - } - + } + chan = Tcl_OpenFileChannel(interp, masterPtr->fileString, "r", 0); if (chan == NULL) { goto errorExit; } + /* * -translation binary also sets -encoding binary */ - if ((Tcl_SetChannelOption(interp, chan, + + if ((Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) || (MatchFileFormat(interp, chan, masterPtr->fileString, masterPtr->format, &imageFormat, &imageWidth, @@ -2063,8 +2062,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) if (result != TCL_OK) { Tcl_Close(NULL, chan); Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); goto errorExit; } tempformat = masterPtr->format; @@ -2072,9 +2070,8 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) tempformat = (Tcl_Obj *) Tcl_GetString(tempformat); } result = (*imageFormat->fileReadProc)(interp, chan, - masterPtr->fileString, tempformat, - (Tk_PhotoHandle) masterPtr, 0, 0, - imageWidth, imageHeight, 0, 0); + masterPtr->fileString, tempformat, (Tk_PhotoHandle) masterPtr, + 0, 0, imageWidth, imageHeight, 0, 0); Tcl_Close(NULL, chan); if (result != TCL_OK) { goto errorExit; @@ -2095,8 +2092,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } if (ImgPhotoSetSize(masterPtr, imageWidth, imageHeight) != TCL_OK) { Tcl_ResetResult(interp); - Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), - TK_PHOTO_ALLOC_FAILURE_MESSAGE, (char *) NULL); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); goto errorExit; } tempformat = masterPtr->format; @@ -2131,9 +2127,9 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } /* - * Cycle through all of the instances of this image, regenerating - * the information for each instance. Then force the image to be - * redisplayed everywhere that it is used. + * Cycle through all of the instances of this image, regenerating the + * information for each instance. Then force the image to be redisplayed + * everywhere that it is used. */ for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; @@ -2142,8 +2138,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) } /* - * Inform the generic image code that the image - * has (potentially) changed. + * Inform the generic image code that the image has (potentially) changed. */ Tk_ImageChanged(masterPtr->tkMaster, 0, 0, masterPtr->width, @@ -2176,24 +2171,24 @@ ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags) * * ImgPhotoConfigureInstance -- * - * This procedure is called to create displaying information for - * a photo image instance based on the configuration information - * in the master. It is invoked both when new instances are - * created and when the master is reconfigured. + * This function is called to create displaying information for a photo + * image instance based on the configuration information in the master. + * It is invoked both when new instances are created and when the master + * is reconfigured. * * Results: * None. * * Side effects: - * Generates errors via Tcl_BackgroundError if there are problems - * in setting up the instance. + * Generates errors via Tcl_BackgroundError if there are problems in + * setting up the instance. * *---------------------------------------------------------------------- */ static void -ImgPhotoConfigureInstance(instancePtr) - PhotoInstance *instancePtr; /* Instance to reconfigure. */ +ImgPhotoConfigureInstance( + PhotoInstance *instancePtr) /* Instance to reconfigure. */ { PhotoMaster *masterPtr = instancePtr->masterPtr; XImage *imagePtr; @@ -2202,10 +2197,9 @@ ImgPhotoConfigureInstance(instancePtr) XRectangle validBox; /* - * If the -palette configuration option has been set for the master, - * use the value specified for our palette, but only if it is - * a valid palette for our windows. Use the gamma value specified - * the master. + * If the -palette configuration option has been set for the master, use + * the value specified for our palette, but only if it is a valid palette + * for our windows. Use the gamma value specified the master. */ if ((masterPtr->palette && masterPtr->palette[0]) @@ -2217,9 +2211,9 @@ ImgPhotoConfigureInstance(instancePtr) instancePtr->gamma = masterPtr->gamma; /* - * If we don't currently have a color table, or if the one we - * have no longer applies (e.g. because our palette or gamma - * has changed), get a new one. + * If we don't currently have a color table, or if the one we have no + * longer applies (e.g. because our palette or gamma has changed), get a + * new one. */ colorTablePtr = instancePtr->colorTablePtr; @@ -2238,8 +2232,8 @@ ImgPhotoConfigureInstance(instancePtr) GetColorTable(instancePtr); /* - * Create a new XImage structure for sending data to - * the X server, if necessary. + * Create a new XImage structure for sending data to the X server, if + * necessary. */ if (instancePtr->colorTablePtr->flags & BLACK_AND_WHITE) { @@ -2255,7 +2249,7 @@ ImgPhotoConfigureInstance(instancePtr) } imagePtr = XCreateImage(instancePtr->display, instancePtr->visualInfo.visual, (unsigned) bitsPerPixel, - (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, (char *) NULL, + (bitsPerPixel > 1? ZPixmap: XYBitmap), 0, NULL, 1, 1, 32, 0); instancePtr->imagePtr = imagePtr; @@ -2278,11 +2272,10 @@ ImgPhotoConfigureInstance(instancePtr) } /* - * If the user has specified a width and/or height for the master - * which is different from our current width/height, set the size - * to the values specified by the user. If we have no pixmap, we - * do this also, since it has the side effect of allocating a - * pixmap for us. + * If the user has specified a width and/or height for the master which is + * different from our current width/height, set the size to the values + * specified by the user. If we have no pixmap, we do this also, since it + * has the side effect of allocating a pixmap for us. */ if ((instancePtr->pixels == None) || (instancePtr->error == NULL) @@ -2310,62 +2303,60 @@ ImgPhotoConfigureInstance(instancePtr) * * ImgPhotoGet -- * - * This procedure is called for each use of a photo image in a - * widget. + * This function is called for each use of a photo image in a widget. * * Results: - * The return value is a token for the instance, which is passed - * back to us in calls to ImgPhotoDisplay and ImgPhotoFree. + * The return value is a token for the instance, which is passed back to + * us in calls to ImgPhotoDisplay and ImgPhotoFree. * * Side effects: - * A data structure is set up for the instance (or, an existing - * instance is re-used for the new one). + * A data structure is set up for the instance (or, an existing instance + * is re-used for the new one). * *---------------------------------------------------------------------- */ static ClientData -ImgPhotoGet(tkwin, masterData) - Tk_Window tkwin; /* Window in which the instance will be +ImgPhotoGet( + Tk_Window tkwin, /* Window in which the instance will be * used. */ - ClientData masterData; /* Pointer to our master structure for the + ClientData masterData) /* Pointer to our master structure for the * image. */ { PhotoMaster *masterPtr = (PhotoMaster *) masterData; PhotoInstance *instancePtr; Colormap colormap; - int mono, nRed, nGreen, nBlue; + int mono, nRed, nGreen, nBlue, numVisuals; XVisualInfo visualInfo, *visInfoPtr; char buf[TCL_INTEGER_SPACE * 3]; - int numVisuals; XColor *white, *black; XGCValues gcValues; /* - * Table of "best" choices for palette for PseudoColor displays - * with between 3 and 15 bits/pixel. + * Table of "best" choices for palette for PseudoColor displays with + * between 3 and 15 bits/pixel. */ - static int paletteChoice[13][3] = { + static const int paletteChoice[13][3] = { /* #red, #green, #blue */ - {2, 2, 2, /* 3 bits, 8 colors */}, - {2, 3, 2, /* 4 bits, 12 colors */}, - {3, 4, 2, /* 5 bits, 24 colors */}, - {4, 5, 3, /* 6 bits, 60 colors */}, - {5, 6, 4, /* 7 bits, 120 colors */}, - {7, 7, 4, /* 8 bits, 198 colors */}, - {8, 10, 6, /* 9 bits, 480 colors */}, - {10, 12, 8, /* 10 bits, 960 colors */}, - {14, 15, 9, /* 11 bits, 1890 colors */}, - {16, 20, 12, /* 12 bits, 3840 colors */}, - {20, 24, 16, /* 13 bits, 7680 colors */}, - {26, 30, 20, /* 14 bits, 15600 colors */}, - {32, 32, 30, /* 15 bits, 30720 colors */} + {2, 2, 2, /* 3 bits, 8 colors */}, + {2, 3, 2, /* 4 bits, 12 colors */}, + {3, 4, 2, /* 5 bits, 24 colors */}, + {4, 5, 3, /* 6 bits, 60 colors */}, + {5, 6, 4, /* 7 bits, 120 colors */}, + {7, 7, 4, /* 8 bits, 198 colors */}, + {8, 10, 6, /* 9 bits, 480 colors */}, + {10, 12, 8, /* 10 bits, 960 colors */}, + {14, 15, 9, /* 11 bits, 1890 colors */}, + {16, 20, 12, /* 12 bits, 3840 colors */}, + {20, 24, 16, /* 13 bits, 7680 colors */}, + {26, 30, 20, /* 14 bits, 15600 colors */}, + {32, 32, 30, /* 15 bits, 30720 colors */} }; /* - * See if there is already an instance for windows using - * the same colormap. If so then just re-use it. + * See if there is already an instance for windows using the same + * colormap. If so then just re-use it. */ colormap = Tk_Colormap(tkwin); @@ -2373,7 +2364,6 @@ ImgPhotoGet(tkwin, masterData) instancePtr = instancePtr->nextPtr) { if ((colormap == instancePtr->colormap) && (Tk_Display(tkwin) == instancePtr->display)) { - /* * Re-use this instance. */ @@ -2395,8 +2385,8 @@ ImgPhotoGet(tkwin, masterData) } /* - * The image isn't already in use in a window with the same colormap. - * Make a new instance of the image. + * The image isn't already in use in a window with the same colormap. Make + * a new instance of the image. */ instancePtr = (PhotoInstance *) ckalloc(sizeof(PhotoInstance)); @@ -2415,53 +2405,51 @@ ImgPhotoGet(tkwin, masterData) masterPtr->instancePtr = instancePtr; /* - * Obtain information about the visual and decide on the - * default palette. + * Obtain information about the visual and decide on the default palette. */ visualInfo.screen = Tk_ScreenNumber(tkwin); visualInfo.visualid = XVisualIDFromVisual(Tk_Visual(tkwin)); visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask | VisualIDMask, &visualInfo, &numVisuals); + if (visInfoPtr == NULL) { + Tcl_Panic("ImgPhotoGet couldn't find visual for window"); + } + nRed = 2; nGreen = nBlue = 0; mono = 1; - if (visInfoPtr != NULL) { - instancePtr->visualInfo = *visInfoPtr; - switch (visInfoPtr->class) { - case DirectColor: - case TrueColor: - nRed = 1 << CountBits(visInfoPtr->red_mask); - nGreen = 1 << CountBits(visInfoPtr->green_mask); - nBlue = 1 << CountBits(visInfoPtr->blue_mask); - mono = 0; - break; - case PseudoColor: - case StaticColor: - if (visInfoPtr->depth > 15) { - nRed = 32; - nGreen = 32; - nBlue = 32; - mono = 0; - } else if (visInfoPtr->depth >= 3) { - int *ip = paletteChoice[visInfoPtr->depth - 3]; - - nRed = ip[0]; - nGreen = ip[1]; - nBlue = ip[2]; - mono = 0; - } - break; - case GrayScale: - case StaticGray: - nRed = 1 << visInfoPtr->depth; - break; - } - XFree((char *) visInfoPtr); - - } else { - panic("ImgPhotoGet couldn't find visual for window"); - } + instancePtr->visualInfo = *visInfoPtr; + switch (visInfoPtr->class) { + case DirectColor: + case TrueColor: + nRed = 1 << CountBits(visInfoPtr->red_mask); + nGreen = 1 << CountBits(visInfoPtr->green_mask); + nBlue = 1 << CountBits(visInfoPtr->blue_mask); + mono = 0; + break; + case PseudoColor: + case StaticColor: + if (visInfoPtr->depth > 15) { + nRed = 32; + nGreen = 32; + nBlue = 32; + mono = 0; + } else if (visInfoPtr->depth >= 3) { + const int *ip = paletteChoice[visInfoPtr->depth - 3]; + + nRed = ip[0]; + nGreen = ip[1]; + nBlue = ip[2]; + mono = 0; + } + break; + case GrayScale: + case StaticGray: + nRed = 1 << visInfoPtr->depth; + break; + } + XFree((char *) visInfoPtr); sprintf(buf, ((mono) ? "%d": "%d/%d/%d"), nRed, nGreen, nBlue); instancePtr->defaultPalette = Tk_GetUid(buf); @@ -2483,8 +2471,8 @@ ImgPhotoGet(tkwin, masterData) GCForeground|GCBackground|GCGraphicsExposures, &gcValues); /* - * Set configuration options and finish the initialization of the instance. - * This will also dither the image if necessary. + * Set configuration options and finish the initialization of the + * instance. This will also dither the image if necessary. */ ImgPhotoConfigureInstance(instancePtr); @@ -2506,9 +2494,9 @@ ImgPhotoGet(tkwin, masterData) * * ToggleComplexAlphaIfNeeded -- * - * This procedure is called when an image is modified to - * check if any partially transparent pixels exist, which - * requires blending instead of straight copy. + * This function is called when an image is modified to check if any + * partially transparent pixels exist, which requires blending instead of + * straight copy. * * Results: * None. @@ -2520,19 +2508,21 @@ ImgPhotoGet(tkwin, masterData) */ static int -ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr) +ToggleComplexAlphaIfNeeded( + PhotoMaster *mPtr) { size_t len = MAX(mPtr->userWidth, mPtr->width) * - MAX(mPtr->userHeight, mPtr->height) * 4; - unsigned char *c = mPtr->pix32; + MAX(mPtr->userHeight, mPtr->height) * 4; + unsigned char *c = mPtr->pix32; unsigned char *end = c + len; /* * Set the COMPLEX_ALPHA flag if we have an image with partially * transparent bits. */ + mPtr->flags &= ~COMPLEX_ALPHA; - c += 3; /* start at first alpha byte */ + c += 3; /* Start at first alpha byte. */ for (; c < end; c += 4) { if (*c && *c != 255) { mPtr->flags |= COMPLEX_ALPHA; @@ -2547,8 +2537,13 @@ ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr) * * ImgPhotoBlendComplexAlpha -- * - * This procedure is called when an image with partially - * transparent pixels must be drawn over another image. + * This function is called when an image with partially transparent + * pixels must be drawn over another image. It blends the photo data onto + * a local copy of the surface that we are drawing on, *including* the + * pixels drawn by everything that should be drawn underneath the image. + * + * Much of this code has hard-coded values in for speed because this + * routine is performance critical for complex image drawing. * * Results: * None. @@ -2556,53 +2551,61 @@ ToggleComplexAlphaIfNeeded(PhotoMaster *mPtr) * Side effects: * Background image passed in gets drawn over with image data. * - *---------------------------------------------------------------------- - */ - -/* - * This should work on all platforms that set mask and shift data properly - * from the visualInfo. - * RGB is really only a 24+ bpp version whereas RGB15 is the correct version - * and works for 15bpp+, but it slower, so it's only used for 15bpp+. + * Notes: + * This should work on all platforms that set mask and shift data + * properly from the visualInfo. RGB is really only a 24+ bpp version + * whereas RGB15 is the correct version and works for 15bpp+, but it + * slower, so it's only used for 15bpp+. + * + * Note that Win32 pre-defines those operations that we really need. * - * Note that Win32 pre-defines those operations that we really need. + *---------------------------------------------------------------------- */ #ifndef __WIN32__ -#define GetRValue(rgb) (UCHAR((rgb & red_mask) >> red_shift)) -#define GetGValue(rgb) (UCHAR((rgb & green_mask) >> green_shift)) -#define GetBValue(rgb) (UCHAR((rgb & blue_mask) >> blue_shift)) -#define RGB(r,g,b) ((unsigned)((UCHAR(r)<<red_shift)|(UCHAR(g)<<green_shift)|(UCHAR(b)<<blue_shift))) -#define RGB15(r,g,b) ((unsigned)(((r*red_mask/255)&red_mask)|((g*green_mask/255)&green_mask)|((b*blue_mask/255)&blue_mask))) +#define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift)) +#define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift)) +#define GetBValue(rgb) (UCHAR(((rgb) & blue_mask) >> blue_shift)) +#define RGB(r, g, b) ((unsigned)( \ + (UCHAR(r) << red_shift) | \ + (UCHAR(g) << green_shift) | \ + (UCHAR(b) << blue_shift) )) +#define RGB15(r, g, b) ((unsigned)( \ + (((r) * red_mask / 255) & red_mask) | \ + (((g) * green_mask / 255) & green_mask) | \ + (((b) * blue_mask / 255) & blue_mask) )) #endif /* !__WIN32__ */ static void -ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) - XImage *bgImg; /* background image to draw on */ - PhotoInstance *iPtr; /* image instance to draw */ - int xOffset, yOffset; /* X & Y offset into image instance to draw */ - int width, height; /* width & height of image to draw */ +ImgPhotoBlendComplexAlpha( + XImage *bgImg, /* Background image to draw on. */ + PhotoInstance *iPtr, /* Image instance to draw. */ + int xOffset, int yOffset, /* X & Y offset into image instance to + * draw. */ + int width, int height) /* Width & height of image to draw. */ { int x, y, line; unsigned long pixel; - unsigned char r, g, b, alpha, unalpha; + unsigned char r, g, b, alpha, unalpha, *masterPtr; unsigned char *alphaAr = iPtr->masterPtr->pix32; - unsigned char *masterPtr; /* - * This blending is an integer version of the Source-Over - * compositing rule (see Porter&Duff, "Compositing Digital - * Images", proceedings of SIGGRAPH 1984) that has been hard-coded - * (for speed) to work with targetting a solid surface. + * This blending is an integer version of the Source-Over compositing rule + * (see Porter&Duff, "Compositing Digital Images", proceedings of SIGGRAPH + * 1984) that has been hard-coded (for speed) to work with targetting a + * solid surface. + * + * The 'unalpha' field must be 255-alpha; it is separated out to encourage + * more efficient compilation. */ #define ALPHA_BLEND(bgPix, imgPix, alpha, unalpha) \ ((bgPix * unalpha + imgPix * alpha) / 255) /* - * We have to get the mask and shift info from the visual on - * non-Win32 so that the macros Get*Value(), RGB() and RGB15() - * work correctly. This might be cached for better performance. + * We have to get the mask and shift info from the visual on non-Win32 so + * that the macros Get*Value(), RGB() and RGB15() work correctly. This + * might be cached for better performance. */ #ifndef __WIN32__ @@ -2628,9 +2631,9 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) #endif /* !__WIN32__ */ /* - * Only unix requires the special case for <24bpp. It varies with - * 3 extra shifts and uses RGB15. The 24+bpp version could also - * then be further optimized. + * Only UNIX requires the special case for <24bpp. It varies with 3 extra + * shifts and uses RGB15. The 24+bpp version could also then be further + * optimized. */ #if !(defined(__WIN32__) || defined(MAC_OSX_TK)) @@ -2645,14 +2648,17 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) for (x = 0; x < width; x++) { masterPtr = alphaAr + ((line + x + xOffset) * 4); alpha = masterPtr[3]; + /* * Ignore pixels that are fully transparent */ + if (alpha) { /* * We could perhaps be more efficient than XGetPixel for * 24 and 32 bit displays, but this seems "fast enough". */ + r = masterPtr[0]; g = masterPtr[1]; b = masterPtr[2]; @@ -2660,13 +2666,14 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) /* * Only blend pixels that have some transparency */ + unsigned char ra, ga, ba; pixel = XGetPixel(bgImg, x, y); ra = GetRValue(pixel) << red_mlen; ga = GetGValue(pixel) << green_mlen; ba = GetBValue(pixel) << blue_mlen; - unalpha = 255 - alpha; + unalpha = 255 - alpha; /* Calculate once. */ r = ALPHA_BLEND(ra, r, alpha, unalpha); g = ALPHA_BLEND(ga, g, alpha, unalpha); b = ALPHA_BLEND(ba, b, alpha, unalpha); @@ -2684,14 +2691,17 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) for (x = 0; x < width; x++) { masterPtr = alphaAr + ((line + x + xOffset) * 4); alpha = masterPtr[3]; + /* * Ignore pixels that are fully transparent */ + if (alpha) { /* - * We could perhaps be more efficient than XGetPixel for - * 24 and 32 bit displays, but this seems "fast enough". + * We could perhaps be more efficient than XGetPixel for 24 + * and 32 bit displays, but this seems "fast enough". */ + r = masterPtr[0]; g = masterPtr[1]; b = masterPtr[2]; @@ -2699,13 +2709,14 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) /* * Only blend pixels that have some transparency */ + unsigned char ra, ga, ba; pixel = XGetPixel(bgImg, x, y); ra = GetRValue(pixel); ga = GetGValue(pixel); ba = GetBValue(pixel); - unalpha = 255 - alpha; + unalpha = 255 - alpha; /* Calculate once. */ r = ALPHA_BLEND(ra, r, alpha, unalpha); g = ALPHA_BLEND(ga, g, alpha, unalpha); b = ALPHA_BLEND(ba, b, alpha, unalpha); @@ -2714,7 +2725,6 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) } } } - #undef ALPHA_BLEND } @@ -2723,7 +2733,7 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) * * ImgPhotoDisplay -- * - * This procedure is invoked to draw a photo image. + * This function is invoked to draw a photo image. * * Results: * None. @@ -2735,48 +2745,31 @@ ImgPhotoBlendComplexAlpha(bgImg, iPtr, xOffset, yOffset, width, height) */ static void -ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, - height, drawableX, drawableY) - ClientData clientData; /* Pointer to PhotoInstance structure for - * for instance to be displayed. */ - Display *display; /* Display on which to draw image. */ - Drawable drawable; /* Pixmap or window in which to draw image. */ - int imageX, imageY; /* Upper-left corner of region within image - * to draw. */ - int width, height; /* Dimensions of region within image to draw. */ - int drawableX, drawableY; /* Coordinates within drawable that - * correspond to imageX and imageY. */ +ImgPhotoDisplay( + ClientData clientData, /* Pointer to PhotoInstance structure for + * instance to be displayed. */ + Display *display, /* Display on which to draw image. */ + Drawable drawable, /* Pixmap or window in which to draw image. */ + int imageX, int imageY, /* Upper-left corner of region within image to + * draw. */ + int width, int height, /* Dimensions of region within image to + * draw. */ + int drawableX,int drawableY)/* Coordinates within drawable that correspond + * to imageX and imageY. */ { PhotoInstance *instancePtr = (PhotoInstance *) clientData; XVisualInfo visInfo = instancePtr->visualInfo; /* - * If there's no pixmap, it means that an error occurred - * while creating the image instance so it can't be displayed. + * If there's no pixmap, it means that an error occurred while creating + * the image instance so it can't be displayed. */ if (instancePtr->pixels == None) { return; } - /* - * Check for bogus widths/heights. This prevents us from calling - * XGetImage with a zero size, which it does not like. [Bug 979239] - */ - - if (width < 1 || height < 1) { - return; - } - - if ( -#if defined(MAC_TCL) - /* - * The retrieval of bgImg is currently not functional on OS9 - * so skip attempts to alpha blend. - */ - 0 && -#endif - (instancePtr->masterPtr->flags & COMPLEX_ALPHA) + if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA) && visInfo.depth >= 15 && (visInfo.class == DirectColor || visInfo.class == TrueColor)) { Tk_ErrorHandler handler; @@ -2786,25 +2779,30 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, * Create an error handler to suppress the case where the input was * not properly constrained, which can cause an X error. [Bug 979239] */ - handler = Tk_CreateErrorHandler(display, -1, -1, -1, - (Tk_ErrorProc *) NULL, (ClientData) NULL); + + handler = Tk_CreateErrorHandler(display, -1, -1, -1, NULL, + (ClientData) NULL); + /* * Pull the current background from the display to blend with */ + bgImg = XGetImage(display, drawable, drawableX, drawableY, (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); if (bgImg == NULL) { Tk_DeleteErrorHandler(handler); - return; + /* We failed to get the image so draw without blending alpha. It's the best we can do */ + goto fallBack; } - ImgPhotoBlendComplexAlpha(bgImg, instancePtr, - imageX, imageY, width, height); + ImgPhotoBlendComplexAlpha(bgImg, instancePtr, imageX, imageY, width, + height); /* - * Color info is unimportant as we only do this operation for - * depth >= 15. + * Color info is unimportant as we only do this operation for depth >= + * 15. */ + TkPutImage(NULL, 0, display, drawable, instancePtr->gc, bgImg, 0, 0, drawableX, drawableY, (unsigned int) width, (unsigned int) height); @@ -2812,21 +2810,23 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, Tk_DeleteErrorHandler(handler); } else { /* - * masterPtr->region describes which parts of the image contain - * valid data. We set this region as the clip mask for the gc, - * setting its origin appropriately, and use it when drawing the - * image. + * masterPtr->region describes which parts of the image contain valid + * data. We set this region as the clip mask for the gc, setting its + * origin appropriately, and use it when drawing the image. */ - TkSetRegion(display, instancePtr->gc, instancePtr->masterPtr->validRegion); + + fallBack: + TkSetRegion(display, instancePtr->gc, + instancePtr->masterPtr->validRegion); XSetClipOrigin(display, instancePtr->gc, drawableX - imageX, - drawableY - imageY); + drawableY - imageY); XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc, - imageX, imageY, (unsigned) width, (unsigned) height, - drawableX, drawableY); + imageX, imageY, (unsigned) width, (unsigned) height, + drawableX, drawableY); XSetClipMask(display, instancePtr->gc, None); XSetClipOrigin(display, instancePtr->gc, 0, 0); } - XFlush (display); + XFlush(display); } /* @@ -2834,10 +2834,9 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, * * ImgPhotoFree -- * - * This procedure is called when a widget ceases to use a - * particular instance of an image. We don't actually get - * rid of the instance until later because we may be about - * to get this instance again. + * This function is called when a widget ceases to use a particular + * instance of an image. We don't actually get rid of the instance until + * later because we may be about to get this instance again. * * Results: * None. @@ -2849,10 +2848,11 @@ ImgPhotoDisplay(clientData, display, drawable, imageX, imageY, width, */ static void -ImgPhotoFree(clientData, display) - ClientData clientData; /* Pointer to PhotoInstance structure for - * for instance to be displayed. */ - Display *display; /* Display containing window that used image. */ +ImgPhotoFree( + ClientData clientData, /* Pointer to PhotoInstance structure for + * instance to be displayed. */ + Display *display) /* Display containing window that used + * image. */ { PhotoInstance *instancePtr = (PhotoInstance *) clientData; ColorTable *colorPtr; @@ -2863,17 +2863,17 @@ ImgPhotoFree(clientData, display) } /* - * There are no more uses of the image within this widget. - * Decrement the count of live uses of its color table, so - * that its colors can be reclaimed if necessary, and - * set up an idle call to free the instance structure. + * There are no more uses of the image within this widget. Decrement the + * count of live uses of its color table, so that its colors can be + * reclaimed if necessary, and set up an idle call to free the instance + * structure. */ colorPtr = instancePtr->colorTablePtr; if (colorPtr != NULL) { colorPtr->liveRefCount -= 1; } - + Tcl_DoWhenIdle(DisposeInstance, (ClientData) instancePtr); } @@ -2882,8 +2882,8 @@ ImgPhotoFree(clientData, display) * * ImgPhotoDelete -- * - * This procedure is called by the image code to delete the - * master structure for an image. + * This function is called by the image code to delete the master + * structure for an image. * * Results: * None. @@ -2895,16 +2895,16 @@ ImgPhotoFree(clientData, display) */ static void -ImgPhotoDelete(masterData) - ClientData masterData; /* Pointer to PhotoMaster structure for - * image. Must not have any more instances. */ +ImgPhotoDelete( + ClientData masterData) /* Pointer to PhotoMaster structure for image. + * Must not have any more instances. */ { PhotoMaster *masterPtr = (PhotoMaster *) masterData; PhotoInstance *instancePtr; while ((instancePtr = masterPtr->instancePtr) != NULL) { if (instancePtr->refCount > 0) { - panic("tried to delete photo image when instances still exist"); + Tcl_Panic("tried to delete photo image when instances still exist"); } Tcl_CancelIdleCall(DisposeInstance, (ClientData) instancePtr); DisposeInstance((ClientData) instancePtr); @@ -2925,7 +2925,7 @@ ImgPhotoDelete(masterData) if (masterPtr->format != NULL) { Tcl_DecrRefCount(masterPtr->format); } - Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0); + Tk_FreeOptions(configSpecs, (char *) masterPtr, NULL, 0); ckfree((char *) masterPtr); } @@ -2934,8 +2934,8 @@ ImgPhotoDelete(masterData) * * ImgPhotoCmdDeletedProc -- * - * This procedure is invoked when the image command for an image - * is deleted. It deletes the image. + * This function is invoked when the image command for an image is + * deleted. It deletes the image. * * Results: * None. @@ -2947,8 +2947,8 @@ ImgPhotoDelete(masterData) */ static void -ImgPhotoCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to PhotoMaster structure for +ImgPhotoCmdDeletedProc( + ClientData clientData) /* Pointer to PhotoMaster structure for * image. */ { PhotoMaster *masterPtr = (PhotoMaster *) clientData; @@ -2964,13 +2964,13 @@ ImgPhotoCmdDeletedProc(clientData) * * ImgPhotoSetSize -- * - * This procedure reallocates the image storage and instance - * pixmaps for a photo image, as necessary, to change the - * image's size to `width' x `height' pixels. + * This function reallocates the image storage and instance pixmaps for a + * photo image, as necessary, to change the image's size to `width' x + * `height' pixels. * * Results: - * TCL_OK if successful, TCL_ERROR if failure occurred (currently - * just with memory allocation.) + * TCL_OK if successful, TCL_ERROR if failure occurred (currently just + * with memory allocation.) * * Side effects: * Storage gets reallocated, for the master and all its instances. @@ -2979,9 +2979,9 @@ ImgPhotoCmdDeletedProc(clientData) */ static int -ImgPhotoSetSize(masterPtr, width, height) - PhotoMaster *masterPtr; - int width, height; +ImgPhotoSetSize( + PhotoMaster *masterPtr, + int width, int height) { unsigned char *newPix32 = NULL; int h, offset, pitch; @@ -3000,19 +3000,22 @@ ImgPhotoSetSize(masterPtr, width, height) pitch = width * 4; /* - * Test if we're going to (re)allocate the main buffer now, so - * that any failures will leave the photo unchanged. + * Test if we're going to (re)allocate the main buffer now, so that any + * failures will leave the photo unchanged. */ + if ((width != masterPtr->width) || (height != masterPtr->height) || (masterPtr->pix32 == NULL)) { /* * Not a u-long, but should be one. */ + unsigned /*long*/ newPixSize = (unsigned /*long*/) (height * pitch); /* * Some mallocs() really hate allocating zero bytes. [Bug 619544] */ + if (newPixSize == 0) { newPix32 = NULL; } else { @@ -3024,8 +3027,8 @@ ImgPhotoSetSize(masterPtr, width, height) } /* - * We have to trim the valid region if it is currently - * larger than the new image size. + * We have to trim the valid region if it is currently larger than the new + * image size. */ TkClipBox(masterPtr->validRegion, &validBox); @@ -3044,36 +3047,35 @@ ImgPhotoSetSize(masterPtr, width, height) } /* - * Use the reallocated storage (allocation above) for the 32-bit - * image and copy over valid regions. Note that this test is true - * precisely when the allocation has already been done. + * Use the reallocated storage (allocation above) for the 32-bit image and + * copy over valid regions. Note that this test is true precisely when the + * allocation has already been done. */ + if (newPix32 != NULL) { /* - * Zero the new array. The dithering code shouldn't read the - * areas outside validBox, but they might be copied to another - * photo image or written to a file. + * Zero the new array. The dithering code shouldn't read the areas + * outside validBox, but they might be copied to another photo image + * or written to a file. */ if ((masterPtr->pix32 != NULL) && ((width == masterPtr->width) || (width == validBox.width))) { if (validBox.y > 0) { - memset((VOID *) newPix32, 0, (size_t) (validBox.y * pitch)); + memset(newPix32, 0, (size_t) (validBox.y * pitch)); } h = validBox.y + validBox.height; if (h < height) { - memset((VOID *) (newPix32 + h * pitch), 0, - (size_t) ((height - h) * pitch)); + memset(newPix32 + h*pitch, 0, (size_t) ((height - h) * pitch)); } } else { - memset((VOID *) newPix32, 0, (size_t) (height * pitch)); + memset(newPix32, 0, (size_t) (height * pitch)); } if (masterPtr->pix32 != NULL) { - /* - * Copy the common area over to the new array array and - * free the old array. + * Copy the common area over to the new array array and free the + * old array. */ if (width == masterPtr->width) { @@ -3083,12 +3085,10 @@ ImgPhotoSetSize(masterPtr, width, height) */ offset = validBox.y * pitch; - memcpy((VOID *) (newPix32 + offset), - (VOID *) (masterPtr->pix32 + offset), + memcpy(newPix32 + offset, masterPtr->pix32 + offset, (size_t) (validBox.height * pitch)); } else if ((validBox.width > 0) && (validBox.height > 0)) { - /* * Area to be copied is not contiguous - copy line by line. */ @@ -3097,8 +3097,7 @@ ImgPhotoSetSize(masterPtr, width, height) srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width + validBox.x) * 4; for (h = validBox.height; h > 0; h--) { - memcpy((VOID *) destPtr, (VOID *) srcPtr, - (size_t) (validBox.width * 4)); + memcpy(destPtr, srcPtr, (size_t) (validBox.width * 4)); destPtr += width * 4; srcPtr += masterPtr->width * 4; } @@ -3112,8 +3111,8 @@ ImgPhotoSetSize(masterPtr, width, height) masterPtr->height = height; /* - * Dithering will be correct up to the end of the last - * pre-existing complete scanline. + * Dithering will be correct up to the end of the last pre-existing + * complete scanline. */ if ((validBox.x > 0) || (validBox.y > 0)) { @@ -3150,9 +3149,9 @@ ImgPhotoSetSize(masterPtr, width, height) * * ImgPhotoInstanceSetSize -- * - * This procedure reallocates the instance pixmap and dithering - * error array for a photo instance, as necessary, to change the - * image's size to `width' x `height' pixels. + * This function reallocates the instance pixmap and dithering error + * array for a photo instance, as necessary, to change the image's size + * to `width' x `height' pixels. * * Results: * None. @@ -3164,13 +3163,11 @@ ImgPhotoSetSize(masterPtr, width, height) */ static void -ImgPhotoInstanceSetSize(instancePtr) - PhotoInstance *instancePtr; /* Instance whose size is to be - * changed. */ +ImgPhotoInstanceSetSize( + PhotoInstance *instancePtr) /* Instance whose size is to be changed. */ { PhotoMaster *masterPtr; - schar *newError; - schar *errSrcPtr, *errDestPtr; + schar *newError, *errSrcPtr, *errDestPtr; int h, offset; XRectangle validBox; Pixmap newPixmap; @@ -3183,22 +3180,21 @@ ImgPhotoInstanceSetSize(instancePtr) || (instancePtr->pixels == None)) { newPixmap = Tk_GetPixmap(instancePtr->display, RootWindow(instancePtr->display, - instancePtr->visualInfo.screen), + instancePtr->visualInfo.screen), (masterPtr->width > 0) ? masterPtr->width: 1, (masterPtr->height > 0) ? masterPtr->height: 1, instancePtr->visualInfo.depth); - if (!newPixmap) { - panic("Fail to create pixmap with Tk_GetPixmap in ImgPhotoInstanceSetSize.\n"); - return; - } + if (!newPixmap) { + Tcl_Panic("Fail to create pixmap with Tk_GetPixmap in ImgPhotoInstanceSetSize.\n"); + } /* * The following is a gross hack needed to properly support colormaps - * under Windows. Before the pixels can be copied to the pixmap, - * the relevent colormap must be associated with the drawable. - * Normally we can infer this association from the window that - * was used to create the pixmap. However, in this case we're - * using the root window, so we have to be more explicit. + * under Windows. Before the pixels can be copied to the pixmap, the + * relevent colormap must be associated with the drawable. Normally we + * can infer this association from the window that was used to create + * the pixmap. However, in this case we're using the root window, so + * we have to be more explicit. */ TkSetPixmapColormap(newPixmap, instancePtr->colormap); @@ -3207,6 +3203,7 @@ ImgPhotoInstanceSetSize(instancePtr) /* * Copy any common pixels from the old pixmap and free it. */ + XCopyArea(instancePtr->display, instancePtr->pixels, newPixmap, instancePtr->gc, validBox.x, validBox.y, validBox.width, validBox.height, validBox.x, validBox.y); @@ -3224,54 +3221,51 @@ ImgPhotoInstanceSetSize(instancePtr) masterPtr->height * masterPtr->width * 3 * sizeof(schar)); /* - * Zero the new array so that we don't get bogus error - * values propagating into areas we dither later. + * Zero the new array so that we don't get bogus error values + * propagating into areas we dither later. */ if ((instancePtr->error != NULL) && ((instancePtr->width == masterPtr->width) || (validBox.width == masterPtr->width))) { if (validBox.y > 0) { - memset((VOID *) newError, 0, (size_t) + memset(newError, 0, (size_t) validBox.y * masterPtr->width * 3 * sizeof(schar)); } h = validBox.y + validBox.height; if (h < masterPtr->height) { - memset((VOID *) (newError + h * masterPtr->width * 3), 0, + memset(newError + h*masterPtr->width*3, 0, (size_t) (masterPtr->height - h) * masterPtr->width * 3 * sizeof(schar)); } } else { - memset((VOID *) newError, 0, (size_t) - masterPtr->height * masterPtr->width * 3 * sizeof(schar)); + memset(newError, 0, (size_t) + masterPtr->height * masterPtr->width *3*sizeof(schar)); } } else { newError = NULL; } if (instancePtr->error != NULL) { - /* - * Copy the common area over to the new array - * and free the old array. + * Copy the common area over to the new array and free the old + * array. */ if (masterPtr->width == instancePtr->width) { - offset = validBox.y * masterPtr->width * 3; - memcpy((VOID *) (newError + offset), - (VOID *) (instancePtr->error + offset), + memcpy(newError + offset, instancePtr->error + offset, (size_t) (validBox.height * masterPtr->width * 3 * sizeof(schar))); } else if (validBox.width > 0 && validBox.height > 0) { + errDestPtr = newError + + (validBox.y * masterPtr->width + validBox.x) * 3; + errSrcPtr = instancePtr->error + + (validBox.y * instancePtr->width + validBox.x) * 3; - errDestPtr = newError - + (validBox.y * masterPtr->width + validBox.x) * 3; - errSrcPtr = instancePtr->error - + (validBox.y * instancePtr->width + validBox.x) * 3; for (h = validBox.height; h > 0; --h) { - memcpy((VOID *) errDestPtr, (VOID *) errSrcPtr, + memcpy(errDestPtr, errSrcPtr, validBox.width * 3 * sizeof(schar)); errDestPtr += masterPtr->width * 3; errSrcPtr += instancePtr->width * 3; @@ -3292,9 +3286,8 @@ ImgPhotoInstanceSetSize(instancePtr) * * IsValidPalette -- * - * This procedure is called to check whether a value given for - * the -palette option is valid for a particular instance - * of a photo image. + * This function is called to check whether a value given for the + * -palette option is valid for a particular instance of a photo image. * * Results: * A boolean value: 1 if the palette is acceptable, 0 otherwise. @@ -3306,17 +3299,16 @@ ImgPhotoInstanceSetSize(instancePtr) */ static int -IsValidPalette(instancePtr, palette) - PhotoInstance *instancePtr; /* Instance to which the palette - * specification is to be applied. */ - CONST char *palette; /* Palette specification string. */ +IsValidPalette( + PhotoInstance *instancePtr, /* Instance to which the palette specification + * is to be applied. */ + const char *palette) /* Palette specification string. */ { int nRed, nGreen, nBlue, mono, numColors; char *endp; /* - * First parse the specification: it must be of the form - * %d or %d/%d/%d. + * First parse the specification: it must be of the form %d or %d/%d/%d. */ nRed = strtol(palette, &endp, 10); @@ -3345,32 +3337,30 @@ IsValidPalette(instancePtr, palette) } switch (instancePtr->visualInfo.class) { - case DirectColor: - case TrueColor: - if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask))) - || (nGreen > (1 - << CountBits(instancePtr->visualInfo.green_mask))) - || (nBlue > (1 - << CountBits(instancePtr->visualInfo.blue_mask)))) { - return 0; - } - break; - case PseudoColor: - case StaticColor: - numColors = nRed; - if (!mono) { - numColors *= nGreen*nBlue; - } - if (numColors > (1 << instancePtr->visualInfo.depth)) { - return 0; - } - break; - case GrayScale: - case StaticGray: - if (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) { - return 0; - } - break; + case DirectColor: + case TrueColor: + if ((nRed > (1 << CountBits(instancePtr->visualInfo.red_mask))) + || (nGreen>(1<<CountBits(instancePtr->visualInfo.green_mask))) + || (nBlue>(1<<CountBits(instancePtr->visualInfo.blue_mask)))) { + return 0; + } + break; + case PseudoColor: + case StaticColor: + numColors = nRed; + if (!mono) { + numColors *= nGreen*nBlue; + } + if (numColors > (1 << instancePtr->visualInfo.depth)) { + return 0; + } + break; + case GrayScale: + case StaticGray: + if (!mono || (nRed > (1 << instancePtr->visualInfo.depth))) { + return 0; + } + break; } return 1; @@ -3381,7 +3371,7 @@ IsValidPalette(instancePtr, palette) * * CountBits -- * - * This procedure counts how many bits are set to 1 in `mask'. + * This function counts how many bits are set to 1 in `mask'. * * Results: * The integer number of bits. @@ -3393,13 +3383,14 @@ IsValidPalette(instancePtr, palette) */ static int -CountBits(mask) - pixel mask; /* Value to count the 1 bits in. */ +CountBits( + pixel mask) /* Value to count the 1 bits in. */ { int n; - for( n = 0; mask != 0; mask &= mask - 1 ) + for (n=0 ; mask!=0 ; mask&=mask-1) { n++; + } return n; } @@ -3408,28 +3399,27 @@ CountBits(mask) * * GetColorTable -- * - * This procedure is called to allocate a table of colormap - * information for an instance of a photo image. Only one such - * table is allocated for all photo instances using the same - * display, colormap, palette and gamma values, so that the - * application need only request a set of colors from the X - * server once for all such photo widgets. This procedure - * maintains a hash table to find previously-allocated + * This function is called to allocate a table of colormap information + * for an instance of a photo image. Only one such table is allocated for + * all photo instances using the same display, colormap, palette and + * gamma values, so that the application need only request a set of + * colors from the X server once for all such photo widgets. This + * function maintains a hash table to find previously-allocated * ColorTables. * * Results: * None. * * Side effects: - * A new ColorTable may be allocated and placed in the hash - * table, and have colors allocated for it. + * A new ColorTable may be allocated and placed in the hash table, and + * have colors allocated for it. * *---------------------------------------------------------------------- */ static void -GetColorTable(instancePtr) - PhotoInstance *instancePtr; /* Instance needing a color table. */ +GetColorTable( + PhotoInstance *instancePtr) /* Instance needing a color table. */ { ColorTable *colorPtr; Tcl_HashEntry *entry; @@ -3440,7 +3430,7 @@ GetColorTable(instancePtr) * Look for an existing ColorTable in the hash table. */ - memset((VOID *) &id, 0, sizeof(id)); + memset(&id, 0, sizeof(id)); id.display = instancePtr->display; id.colormap = instancePtr->colormap; id.palette = instancePtr->palette; @@ -3457,7 +3447,6 @@ GetColorTable(instancePtr) */ colorPtr = (ColorTable *) Tcl_GetHashValue(entry); - } else { /* * No color table currently available; need to make one. @@ -3466,16 +3455,15 @@ GetColorTable(instancePtr) colorPtr = (ColorTable *) ckalloc(sizeof(ColorTable)); /* - * The following line of code should not normally be needed due - * to the assignment in the following line. However, it compensates - * for bugs in some compilers (HP, for example) where - * sizeof(ColorTable) is 24 but the assignment only copies 20 bytes, - * leaving 4 bytes uninitialized; these cause problems when using - * the id for lookups in imgPhotoColorHash, and can result in - * core dumps. + * The following line of code should not normally be needed due to the + * assignment in the following line. However, it compensates for bugs + * in some compilers (HP, for example) where sizeof(ColorTable) is 24 + * but the assignment only copies 20 bytes, leaving 4 bytes + * uninitialized; these cause problems when using the id for lookups + * in imgPhotoColorHash, and can result in core dumps. */ - memset((VOID *) &colorPtr->id, 0, sizeof(ColorTableId)); + memset(&colorPtr->id, 0, sizeof(ColorTableId)); colorPtr->id = id; Tk_PreserveColormap(colorPtr->id.display, colorPtr->id.colormap); colorPtr->flags = 0; @@ -3510,30 +3498,30 @@ GetColorTable(instancePtr) * * FreeColorTable -- * - * This procedure is called when an instance ceases using a - * color table. + * This function is called when an instance ceases using a color table. * * Results: * None. * * Side effects: - * If no other instances are using this color table, a when-idle - * handler is registered to free up the color table and the colors - * allocated for it. + * If no other instances are using this color table, a when-idle handler + * is registered to free up the color table and the colors allocated for + * it. * *---------------------------------------------------------------------- */ static void -FreeColorTable(colorPtr, force) - ColorTable *colorPtr; /* Pointer to the color table which is - * no longer required by an instance. */ - int force; /* Force free to happen immediately. */ +FreeColorTable( + ColorTable *colorPtr, /* Pointer to the color table which is no + * longer required by an instance. */ + int force) /* Force free to happen immediately. */ { colorPtr->refCount--; if (colorPtr->refCount > 0) { return; } + if (force) { if ((colorPtr->flags & DISPOSE_PENDING) != 0) { Tcl_CancelIdleCall(DisposeColorTable, (ClientData) colorPtr); @@ -3551,24 +3539,24 @@ FreeColorTable(colorPtr, force) * * AllocateColors -- * - * This procedure allocates the colors required by a color table, - * and sets up the fields in the color table data structure which - * are used in dithering. + * This function allocates the colors required by a color table, and sets + * up the fields in the color table data structure which are used in + * dithering. * * Results: * None. * * Side effects: - * Colors are allocated from the X server. Fields in the - * color table data structure are updated. + * Colors are allocated from the X server. Fields in the color table data + * structure are updated. * *---------------------------------------------------------------------- */ static void -AllocateColors(colorPtr) - ColorTable *colorPtr; /* Pointer to the color table requiring - * colors to be allocated. */ +AllocateColors( + ColorTable *colorPtr) /* Pointer to the color table requiring colors + * to be allocated. */ { int i, r, g, b, rMult, mono; int numColors, nRed, nGreen, nBlue; @@ -3576,11 +3564,13 @@ AllocateColors(colorPtr) XColor *colors; unsigned long *pixels; - /* 16-bit intensity value for i/n of full intensity. */ -# define CFRAC(i, n) ((i) * 65535 / (n)) + /* + * 16-bit intensity value for i/n of full intensity. + */ +#define CFRAC(i, n) ((i) * 65535 / (n)) /* As for CFRAC, but apply exponent of g. */ -# define CGFRAC(i, n, g) ((int)(65535 * pow((double)(i) / (n), (g)))) +#define CGFRAC(i, n, g) ((int)(65535 * pow((double)(i) / (n), (g)))) /* * First parse the palette specification to get the required number of @@ -3592,16 +3582,14 @@ AllocateColors(colorPtr) igam = 1.0 / colorPtr->id.gamma; /* - * Each time around this loop, we reduce the number of colors we're - * trying to allocate until we succeed in allocating all of the colors - * we need. + * Each time around this loop, we reduce the number of colors we're trying + * to allocate until we succeed in allocating all of the colors we need. */ for (;;) { /* - * If we are using 1 bit/pixel, we don't need to allocate - * any colors (we just use the foreground and background - * colors in the GC). + * If we are using 1 bit/pixel, we don't need to allocate any colors + * (we just use the foreground and background colors in the GC). */ if (mono && (nRed <= 2)) { @@ -3610,12 +3598,12 @@ AllocateColors(colorPtr) } /* - * Calculate the RGB coordinates of the colors we want to - * allocate and store them in *colors. + * Calculate the RGB coordinates of the colors we want to allocate and + * store them in *colors. */ if ((colorPtr->visualInfo.class == DirectColor) - || (colorPtr->visualInfo.class == TrueColor)) { + || (colorPtr->visualInfo.class == TrueColor)) { /* * Direct/True Color: allocate shades of red, green, blue @@ -3642,8 +3630,8 @@ AllocateColors(colorPtr) } } else { /* - * PseudoColor, StaticColor, GrayScale or StaticGray visual: - * we have to allocate each color in the color cube separately. + * PseudoColor, StaticColor, GrayScale or StaticGray visual: we + * have to allocate each color in the color cube separately. */ numColors = (mono) ? nRed: (nRed * nGreen * nBlue); @@ -3695,7 +3683,6 @@ AllocateColors(colorPtr) for (i = 0; i < numColors; ++i) { if (!XAllocColor(colorPtr->id.display, colorPtr->id.colormap, &colors[i])) { - /* * Can't get all the colors we want in the default colormap; * first try freeing colors from other unused color tables. @@ -3707,6 +3694,7 @@ AllocateColors(colorPtr) /* * Still can't allocate the color. */ + break; } } @@ -3714,9 +3702,8 @@ AllocateColors(colorPtr) } /* - * If we didn't get all of the colors, reduce the - * resolution of the color cube, free the ones we got, - * and try again. + * If we didn't get all of the colors, reduce the resolution of the + * color cube, free the ones we got, and try again. */ if (i >= numColors) { @@ -3735,10 +3722,10 @@ AllocateColors(colorPtr) mono = 1; } else { /* - * Reduce the number of shades of each primary to about - * 3/4 of the previous value. This should reduce the - * total number of colors required to about half the - * previous value for PseudoColor displays. + * Reduce the number of shades of each primary to about 3/4 of + * the previous value. This should reduce the total number of + * colors required to about half the previous value for + * PseudoColor displays. */ nRed = (nRed * 3 + 2) / 4; @@ -3753,23 +3740,22 @@ AllocateColors(colorPtr) nRed = nRed / 2; } } - + /* - * We have allocated all of the necessary colors: - * fill in various fields of the ColorTable record. + * We have allocated all of the necessary colors: fill in various fields + * of the ColorTable record. */ if (!mono) { colorPtr->flags |= COLOR_WINDOW; /* - * The following is a hairy hack. We only want to index into - * the pixelMap on colormap displays. However, if the display - * is on Windows, then we actually want to store the index not - * the value since we will be passing the color table into the - * TkPutImage call. + * The following is a hairy hack. We only want to index into the + * pixelMap on colormap displays. However, if the display is on + * Windows, then we actually want to store the index not the value + * since we will be passing the color table into the TkPutImage call. */ - + #ifndef __WIN32__ if ((colorPtr->visualInfo.class != DirectColor) && (colorPtr->visualInfo.class != TrueColor)) { @@ -3784,6 +3770,7 @@ AllocateColors(colorPtr) /* * Set up quantization tables for dithering. */ + rMult = nGreen * nBlue; for (i = 0; i < 256; ++i) { r = (i * (nRed - 1) + 127) / 255; @@ -3799,12 +3786,12 @@ AllocateColors(colorPtr) b = (i * (nBlue - 1) + 127) / 255; if ((colorPtr->visualInfo.class == DirectColor) || (colorPtr->visualInfo.class == TrueColor)) { - colorPtr->redValues[i] = colors[r].pixel - & colorPtr->visualInfo.red_mask; - colorPtr->greenValues[i] = colors[g].pixel - & colorPtr->visualInfo.green_mask; - colorPtr->blueValues[i] = colors[b].pixel - & colorPtr->visualInfo.blue_mask; + colorPtr->redValues[i] = + colors[r].pixel & colorPtr->visualInfo.red_mask; + colorPtr->greenValues[i] = + colors[g].pixel & colorPtr->visualInfo.green_mask; + colorPtr->blueValues[i] = + colors[b].pixel & colorPtr->visualInfo.blue_mask; } else { r *= rMult; g *= nBlue; @@ -3834,27 +3821,27 @@ AllocateColors(colorPtr) * * DisposeColorTable -- * + * Release a color table and its associated resources. * * Results: * None. * * Side effects: - * The colors in the argument color table are freed, as is the - * color table structure itself. The color table is removed - * from the hash table which is used to locate color tables. + * The colors in the argument color table are freed, as is the color + * table structure itself. The color table is removed from the hash table + * which is used to locate color tables. * *---------------------------------------------------------------------- */ static void -DisposeColorTable(clientData) - ClientData clientData; /* Pointer to the ColorTable whose +DisposeColorTable( + ClientData clientData) /* Pointer to the ColorTable whose * colors are to be released. */ { - ColorTable *colorPtr; + ColorTable *colorPtr = (ColorTable *) clientData; Tcl_HashEntry *entry; - colorPtr = (ColorTable *) clientData; if (colorPtr->pixelMap != NULL) { if (colorPtr->numColors > 0) { XFreeColors(colorPtr->id.display, colorPtr->id.colormap, @@ -3866,7 +3853,7 @@ DisposeColorTable(clientData) entry = Tcl_FindHashEntry(&imgPhotoColorHash, (char *) &colorPtr->id); if (entry == NULL) { - panic("DisposeColorTable couldn't find hash entry"); + Tcl_Panic("DisposeColorTable couldn't find hash entry"); } Tcl_DeleteHashEntry(entry); @@ -3878,48 +3865,46 @@ DisposeColorTable(clientData) * * ReclaimColors -- * - * This procedure is called to try to free up colors in the - * colormap used by a color table. It looks for other color - * tables with the same colormap and with a zero live reference - * count, and frees their colors. It only does so if there is - * the possibility of freeing up at least `numColors' colors. + * This function is called to try to free up colors in the colormap used + * by a color table. It looks for other color tables with the same + * colormap and with a zero live reference count, and frees their colors. + * It only does so if there is the possibility of freeing up at least + * `numColors' colors. * * Results: - * The return value is TRUE if any colors were freed, FALSE - * otherwise. + * The return value is TRUE if any colors were freed, FALSE otherwise. * * Side effects: - * ColorTables which are not currently in use may lose their - * color allocations. + * ColorTables which are not currently in use may lose their color + * allocations. * - *---------------------------------------------------------------------- */ + *---------------------------------------------------------------------- + */ static int -ReclaimColors(id, numColors) - ColorTableId *id; /* Pointer to information identifying +ReclaimColors( + ColorTableId *id, /* Pointer to information identifying * the color table which needs more colors. */ - int numColors; /* Number of colors required. */ + int numColors) /* Number of colors required. */ { Tcl_HashSearch srch; Tcl_HashEntry *entry; ColorTable *colorPtr; - int nAvail; + int nAvail = 0; /* - * First scan through the color hash table to get an - * upper bound on how many colors we might be able to free. + * First scan through the color hash table to get an upper bound on how + * many colors we might be able to free. */ - nAvail = 0; entry = Tcl_FirstHashEntry(&imgPhotoColorHash, &srch); while (entry != NULL) { colorPtr = (ColorTable *) Tcl_GetHashValue(entry); if ((colorPtr->id.display == id->display) - && (colorPtr->id.colormap == id->colormap) - && (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0) - && ((colorPtr->id.palette != id->palette) - || (colorPtr->id.gamma != id->gamma))) { - + && (colorPtr->id.colormap == id->colormap) + && (colorPtr->liveRefCount == 0 )&& (colorPtr->numColors != 0) + && ((colorPtr->id.palette != id->palette) + || (colorPtr->id.gamma != id->gamma))) { /* * We could take this guy's colors off him. */ @@ -3948,8 +3933,7 @@ ReclaimColors(id, numColors) && (colorPtr->id.colormap == id->colormap) && (colorPtr->liveRefCount == 0) && (colorPtr->numColors != 0) && ((colorPtr->id.palette != id->palette) - || (colorPtr->id.gamma != id->gamma))) { - + || (colorPtr->id.gamma != id->gamma))) { /* * Free the colors that this ColorTable has. */ @@ -3964,7 +3948,7 @@ ReclaimColors(id, numColors) entry = Tcl_NextHashEntry(&srch); } - return 1; /* we freed some colors */ + return 1; /* We freed some colors. */ } /* @@ -3972,23 +3956,22 @@ ReclaimColors(id, numColors) * * DisposeInstance -- * - * This procedure is called to finally free up an instance - * of a photo image which is no longer required. + * This function is called to finally free up an instance of a photo + * image which is no longer required. * * Results: * None. * * Side effects: - * The instance data structure and the resources it references - * are freed. + * The instance data structure and the resources it references are freed. * *---------------------------------------------------------------------- */ static void -DisposeInstance(clientData) - ClientData clientData; /* Pointer to the instance whose resources - * are to be released. */ +DisposeInstance( + ClientData clientData) /* Pointer to the instance whose resources are + * to be released. */ { PhotoInstance *instancePtr = (PhotoInstance *) clientData; PhotoInstance *prevPtr; @@ -4014,7 +3997,7 @@ DisposeInstance(clientData) } else { for (prevPtr = instancePtr->masterPtr->instancePtr; prevPtr->nextPtr != instancePtr; prevPtr = prevPtr->nextPtr) { - /* Empty loop body */ + /* Empty loop body. */ } prevPtr->nextPtr = instancePtr->nextPtr; } @@ -4027,16 +4010,16 @@ DisposeInstance(clientData) * * MatchFileFormat -- * - * This procedure is called to find a photo image file format - * handler which can parse the image data in the given file. - * If a user-specified format string is provided, only handlers - * whose names match a prefix of the format string are tried. + * This function is called to find a photo image file format handler + * which can parse the image data in the given file. If a user-specified + * format string is provided, only handlers whose names match a prefix of + * the format string are tried. * * Results: - * A standard TCL return value. If the return value is TCL_OK, a - * pointer to the image format record is returned in - * *imageFormatPtr, and the width and height of the image are - * returned in *widthPtr and *heightPtr. + * A standard TCL return value. If the return value is TCL_OK, a pointer + * to the image format record is returned in *imageFormatPtr, and the + * width and height of the image are returned in *widthPtr and + * *heightPtr. * * Side effects: * None. @@ -4045,24 +4028,23 @@ DisposeInstance(clientData) */ static int -MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, - widthPtr, heightPtr, oldformat) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Channel chan; /* The image file, open for reading. */ - char *fileName; /* The name of the image file. */ - Tcl_Obj *formatObj; /* User-specified format string, or NULL. */ - Tk_PhotoImageFormat **imageFormatPtr; - /* A pointer to the photo image format - * record is returned here. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ - int *oldformat; +MatchFileFormat( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Channel chan, /* The image file, open for reading. */ + char *fileName, /* The name of the image file. */ + Tcl_Obj *formatObj, /* User-specified format string, or NULL. */ + Tk_PhotoImageFormat **imageFormatPtr, + /* A pointer to the photo image format record + * is returned here. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here. */ + int *oldformat) /* Returns 1 if the old image API is used. */ { - int matched; - int useoldformat = 0; + int matched = 0, useoldformat = 0; Tk_PhotoImageFormat *formatPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char *formatString = NULL; if (formatObj) { @@ -4070,13 +4052,12 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, } /* - * Scan through the table of file format handlers to find - * one which can handle the image. + * Scan through the table of file format handlers to find one which can + * handle the image. */ - matched = 0; for (formatPtr = tsdPtr->formatList; formatPtr != NULL; - formatPtr = formatPtr->nextPtr) { + formatPtr = formatPtr->nextPtr) { if (formatObj != NULL) { if (strncasecmp(formatString, formatPtr->name, strlen(formatPtr->name)) != 0) { @@ -4085,13 +4066,13 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, matched = 1; if (formatPtr->fileMatchProc == NULL) { Tcl_AppendResult(interp, "-file option isn't supported for ", - formatString, " images", (char *) NULL); + formatString, " images", NULL); return TCL_ERROR; } } if (formatPtr->fileMatchProc != NULL) { (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET); - + if ((*formatPtr->fileMatchProc)(chan, fileName, formatObj, widthPtr, heightPtr, interp)) { if (*widthPtr < 1) { @@ -4116,7 +4097,7 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, matched = 1; if (formatPtr->fileMatchProc == NULL) { Tcl_AppendResult(interp, "-file option isn't supported", - " for ", formatString, " images", (char *) NULL); + " for ", formatString, " images", NULL); return TCL_ERROR; } } @@ -4138,13 +4119,12 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, if (formatPtr == NULL) { if ((formatObj != NULL) && !matched) { - Tcl_AppendResult(interp, "image file format \"", - formatString, - "\" is not supported", (char *) NULL); + Tcl_AppendResult(interp, "image file format \"", formatString, + "\" is not supported", NULL); } else { Tcl_AppendResult(interp, - "couldn't recognize data in image file \"", - fileName, "\"", (char *) NULL); + "couldn't recognize data in image file \"", fileName, "\"", + NULL); } return TCL_ERROR; } @@ -4160,16 +4140,16 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, * * MatchStringFormat -- * - * This procedure is called to find a photo image file format - * handler which can parse the image data in the given string. - * If a user-specified format string is provided, only handlers - * whose names match a prefix of the format string are tried. + * This function is called to find a photo image file format handler + * which can parse the image data in the given string. If a + * user-specified format string is provided, only handlers whose names + * match a prefix of the format string are tried. * * Results: - * A standard TCL return value. If the return value is TCL_OK, a - * pointer to the image format record is returned in - * *imageFormatPtr, and the width and height of the image are - * returned in *widthPtr and *heightPtr. + * A standard TCL return value. If the return value is TCL_OK, a pointer + * to the image format record is returned in *imageFormatPtr, and the + * width and height of the image are returned in *widthPtr and + * *heightPtr. * * Side effects: * None. @@ -4178,35 +4158,33 @@ MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr, */ static int -MatchStringFormat(interp, data, formatObj, imageFormatPtr, - widthPtr, heightPtr, oldformat) - Tcl_Interp *interp; /* Interpreter to use for reporting errors. */ - Tcl_Obj *data; /* Object containing the image data. */ - Tcl_Obj *formatObj; /* User-specified format string, or NULL. */ - Tk_PhotoImageFormat **imageFormatPtr; - /* A pointer to the photo image format - * record is returned here. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are - * returned here. */ - int *oldformat; /* returns 1 if the old image API is used */ +MatchStringFormat( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Obj *data, /* Object containing the image data. */ + Tcl_Obj *formatObj, /* User-specified format string, or NULL. */ + Tk_PhotoImageFormat **imageFormatPtr, + /* A pointer to the photo image format record + * is returned here. */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here. */ + int *oldformat) /* Returns 1 if the old image API is used. */ { - int matched; - int useoldformat = 0; + int matched = 0, useoldformat = 0; Tk_PhotoImageFormat *formatPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char *formatString = NULL; - + if (formatObj) { formatString = Tcl_GetString(formatObj); } /* - * Scan through the table of file format handlers to find - * one which can handle the image. + * Scan through the table of file format handlers to find one which can + * handle the image. */ - matched = 0; for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { if (formatObj != NULL) { @@ -4217,7 +4195,7 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, matched = 1; if (formatPtr->stringMatchProc == NULL) { Tcl_AppendResult(interp, "-data option isn't supported for ", - formatString, " images", (char *) NULL); + formatString, " images", NULL); return TCL_ERROR; } } @@ -4241,7 +4219,7 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, matched = 1; if (formatPtr->stringMatchProc == NULL) { Tcl_AppendResult(interp, "-data option isn't supported", - " for ", formatString, " images", (char *) NULL); + " for ", formatString, " images", NULL); return TCL_ERROR; } } @@ -4258,10 +4236,9 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, if (formatPtr == NULL) { if ((formatObj != NULL) && !matched) { Tcl_AppendResult(interp, "image format \"", formatString, - "\" is not supported", (char *) NULL); + "\" is not supported", NULL); } else { - Tcl_AppendResult(interp, "couldn't recognize image data", - (char *) NULL); + Tcl_AppendResult(interp, "couldn't recognize image data", NULL); } return TCL_ERROR; } @@ -4276,14 +4253,14 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, * * Tk_FindPhoto -- * - * This procedure is called to get an opaque handle (actually a - * PhotoMaster *) for a given image, which can be used in - * subsequent calls to Tk_PhotoPutBlock, etc. The `name' - * parameter is the name of the image. + * This function is called to get an opaque handle (actually a + * PhotoMaster *) for a given image, which can be used in subsequent + * calls to Tk_PhotoPutBlock, etc. The `name' parameter is the name of + * the image. * * Results: - * The handle for the photo image, or NULL if there is no - * photo image with the name given. + * The handle for the photo image, or NULL if there is no photo image + * with the name given. * * Side effects: * None. @@ -4292,16 +4269,16 @@ MatchStringFormat(interp, data, formatObj, imageFormatPtr, */ Tk_PhotoHandle -Tk_FindPhoto(interp, imageName) - Tcl_Interp *interp; /* Interpreter (application) in which image +Tk_FindPhoto( + Tcl_Interp *interp, /* Interpreter (application) in which image * exists. */ - CONST char *imageName; /* Name of the desired photo image. */ + CONST char *imageName) /* Name of the desired photo image. */ { ClientData clientData; Tk_ImageType *typePtr; clientData = Tk_GetImageMasterData(interp, imageName, &typePtr); - if (typePtr != &tkPhotoImageType) { + if ((typePtr == NULL) || (typePtr->name != tkPhotoImageType.name)) { return NULL; } return (Tk_PhotoHandle) clientData; @@ -4312,39 +4289,40 @@ Tk_FindPhoto(interp, imageName) * * Tk_PhotoPutBlock -- * - * This procedure is called to put image data into a photo image. + * This function is called to put image data into a photo image. * * Results: - * None. + * A standard Tcl result code. * * Side effects: - * The image data is stored. The image may be expanded. - * The Tk image code is informed that the image has changed. + * The image data is stored. The image may be expanded. The Tk image code + * is informed that the image has changed. If the result code is + * TCL_ERROR, an error message will be placed in the interpreter (if + * non-NULL). * - *---------------------------------------------------------------------- */ + *---------------------------------------------------------------------- + */ -void -Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) - Tk_PhotoHandle handle; /* Opaque handle for the photo image - * to be updated. */ - register Tk_PhotoImageBlock *blockPtr; - /* Pointer to a structure describing the - * pixel data to be copied into the image. */ - int x, y; /* Coordinates of the top-left pixel to - * be updated in the image. */ - int width, height; /* Dimensions of the area of the image - * to be updated. */ - int compRule; /* Compositing rule to use when processing +int +Tk_PhotoPutBlock( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Opaque handle for the photo image to be + * updated. */ + register 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 + * updated in the image. */ + int width, int height, /* Dimensions of the area of the image to be + * updated. */ + int compRule) /* Compositing rule to use when processing * transparent pixels. */ { register PhotoMaster *masterPtr; - int xEnd, yEnd; - int greenOffset, blueOffset, alphaOffset; - int wLeft, hLeft; - int wCopy, hCopy; - unsigned char *srcPtr, *srcLinePtr; - unsigned char *destPtr, *destLinePtr; - int pitch; + int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; + int wLeft, hLeft, wCopy, hCopy, pitch; + unsigned char *srcPtr, *srcLinePtr, *destPtr, *destLinePtr; int sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO; XRectangle rect; @@ -4359,16 +4337,21 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) height = masterPtr->userHeight - y; } if ((width <= 0) || (height <= 0)) { - return; + return TCL_OK; } 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) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } if (sameSrc) { blockPtr->pixelPtr = masterPtr->pix32; @@ -4376,12 +4359,12 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) } } - if ((y < masterPtr->ditherY) || ((y == masterPtr->ditherY) && (x < masterPtr->ditherX))) { /* * The dithering isn't correct past the start of this block. */ + masterPtr->ditherX = x; masterPtr->ditherY = y; } @@ -4405,111 +4388,162 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) } /* - * Copy the data into our local 32-bit/pixel array. - * If we can do it with a single memmove, we do. + * Copy the data into our local 32-bit/pixel array. If we can do it with a + * single memmove, we do. */ destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4; pitch = masterPtr->width * 4; /* - * This test is probably too restrictive. We should also be able to - * do a memmove if pixelSize == 3 and alphaOffset == 0. Maybe other cases - * too. + * Test to see if we can do the whole write in a single copy. This test is + * probably too restrictive. We should also be able to do a memmove if + * pixelSize == 3 and alphaOffset == 0. Maybe other cases too. */ + if ((blockPtr->pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) && (width <= blockPtr->width) && (height <= blockPtr->height) && ((height == 1) || ((x == 0) && (width == masterPtr->width) && (blockPtr->pitch == pitch))) && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memmove((VOID *) destLinePtr, - (VOID *) (blockPtr->pixelPtr + blockPtr->offset[0]), + memmove(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0], (size_t) (height * width * 4)); - } else { - int alpha; - for (hLeft = height; hLeft > 0;) { - srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; - hCopy = MIN(hLeft, blockPtr->height); - hLeft -= hCopy; - for (; hCopy > 0; --hCopy) { - if ((blockPtr->pixelSize == 4) && (greenOffset == 1) + + /* + * We know there's an alpha offset and we're setting the data, so skip + * directly to the point when we recompute the photo validity region. + */ + + goto recalculateValidRegion; + } + + /* + * Copy and merge pixels according to the compositing rule. + */ + + for (hLeft = height; hLeft > 0;) { + int pixelSize = blockPtr->pixelSize; + int compRuleSet = (compRule == TK_PHOTO_COMPOSITE_SET); + + srcLinePtr = blockPtr->pixelPtr + blockPtr->offset[0]; + hCopy = MIN(hLeft, blockPtr->height); + hLeft -= hCopy; + for (; hCopy > 0; --hCopy) { + /* + * If the layout of the source line matches our memory layout and + * we're setting, we can just copy the bytes directly, which is + * much faster. + */ + + if ((pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3) && (width <= blockPtr->width) - && (compRule == TK_PHOTO_COMPOSITE_SET)) { - memcpy((VOID *) destLinePtr, (VOID *) srcLinePtr, - (size_t) (width * 4)); - } else { - destPtr = destLinePtr; - for (wLeft = width; wLeft > 0;) { - wCopy = MIN(wLeft, blockPtr->width); - wLeft -= wCopy; - srcPtr = srcLinePtr; - for (; wCopy > 0; --wCopy) { - alpha = srcPtr[alphaOffset]; - - /* - * In the easy case, we can just copy. - */ - if (!alphaOffset || (alpha == 255)) { - /* new solid part of the image */ - *destPtr++ = srcPtr[0]; - *destPtr++ = srcPtr[greenOffset]; - *destPtr++ = srcPtr[blueOffset]; - *destPtr++ = 255; - srcPtr += blockPtr->pixelSize; - continue; - } + && compRuleSet) { + memcpy(destLinePtr, srcLinePtr, (size_t) (width * 4)); + srcLinePtr += blockPtr->pitch; + destLinePtr += pitch; + continue; + } - /* - * Combine according to the compositing rule. - */ - switch (compRule) { - case TK_PHOTO_COMPOSITE_OVERLAY: - if (!destPtr[3]) { - /* - * The destination is entirely - * blank, so set it to the source, - * just as if we used the SET - * compositing rule. - */ - case TK_PHOTO_COMPOSITE_SET: - *destPtr++ = srcPtr[0]; - *destPtr++ = srcPtr[greenOffset]; - *destPtr++ = srcPtr[blueOffset]; - *destPtr++ = alpha; - break; - } + /* + * Have to copy the slow way. + */ - if (alpha) { - int Alpha = destPtr[3]; + destPtr = destLinePtr; + for (wLeft = width; wLeft > 0;) { + wCopy = MIN(wLeft, blockPtr->width); + wLeft -= wCopy; + srcPtr = srcLinePtr; - /* - * This implements the Porter-Duff - * Source-Over compositing rule. - */ + /* + * But we might be lucky and be able to use fairly fast loops. + * It's worth checking... + */ - destPtr[0] = PD_SRC_OVER(srcPtr[0],alpha,destPtr[0],Alpha); - destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,destPtr[1],Alpha); - destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset],alpha,destPtr[2],Alpha); - destPtr[3] = PD_SRC_OVER_ALPHA(alpha,Alpha); - } - /* - * else should be empty space - */ - destPtr += 4; - break; - - default: - panic("unknown compositing rule: %d", compRule); - } - srcPtr += blockPtr->pixelSize; - } + if (alphaOffset == 0) { + /* + * This is the non-alpha case, so can still be fairly + * fast. Note that in the non-alpha-source case, the + * compositing rule doesn't apply. + */ + + for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) { + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = 255; + } + continue; + } else if (compRuleSet) { + /* + * This is the SET compositing rule, which just replaces + * what was there before with the new data. This is + * another fairly fast case. No point in doing a memcpy(); + * the order of channels is probably wrong. + */ + + for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) { + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = srcPtr[alphaOffset]; } + continue; + } + + /* + * Bother; need to consider the alpha value of each pixel to + * know what to do. + */ + + for (; wCopy>0 ; --wCopy, srcPtr+=pixelSize) { + int alpha = srcPtr[alphaOffset]; + + if (alpha == 255 || !destPtr[3]) { + /* + * Either the source is 100% opaque, or the + * destination is entirely blank. In all cases, we + * just set the destination to the source. + */ + + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = alpha; + continue; + } + + /* + * Can still skip doing work if the source is 100% + * transparent at this point. + */ + + if (alpha) { + int Alpha = destPtr[3]; + + /* + * OK, there's real work to be done. Luckily, there's + * a substantial literature on what to do in this + * case. In particular, Porter and Duff have done a + * taxonomy of compositing rules, and the right one is + * the "Source Over" rule. This code implements that. + */ + + destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha, destPtr[0], + Alpha); + destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset], alpha, + destPtr[1], Alpha); + destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha, + destPtr[2], Alpha); + destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha); + } + + destPtr += 4; } - srcLinePtr += blockPtr->pitch; - destLinePtr += pitch; } + srcLinePtr += blockPtr->pitch; + destLinePtr += pitch; } } @@ -4518,34 +4552,35 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) */ if (alphaOffset) { - int x1, y1, end; - /* - * This block is grossly inefficient. For each row in the image, it + * This block is grossly inefficient. For each row in the image, it * finds each continguous string of nontransparent pixels, then marks - * those areas as valid in the validRegion mask. This makes drawing + * those areas as valid in the validRegion mask. This makes drawing * very efficient, because of the way we use X: we just say, here's - * your mask, and here's your data. We need not worry about the - * current background color, etc. But this costs us a lot on the - * image setup. Still, image setup only happens once, whereas the - * drawing happens many times, so this might be the best way to go. + * your mask, and here's your data. We need not worry about the + * current background color, etc. But this costs us a lot on the image + * setup. Still, image setup only happens once, whereas the drawing + * happens many times, so this might be the best way to go. * * An alternative might be to not set up this mask, and instead, at * drawing time, for each transparent pixel, set its color to the - * color of the background behind that pixel. This is what I suspect - * most of programs do. However, they don't have to deal with the + * color of the background behind that pixel. This is what I suspect + * most of programs do. However, they don't have to deal with the * canvas, which could have many different background colors. * Determining the correct bg color for a given pixel might be * expensive. */ if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) { + TkRegion workRgn; + /* - * Don't need this when using the OVERLAY compositing rule, - * which always strictly increases the valid region. + * Don't need this when using the OVERLAY compositing rule, which + * always strictly increases the valid region. */ - TkRegion workRgn = TkCreateRegion(); + recalculateValidRegion: + workRgn = TkCreateRegion(); rect.x = x; rect.y = y; rect.width = width; @@ -4556,34 +4591,15 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) TkDestroyRegion(workRgn); } - destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3; - for (y1 = 0; y1 < height; y1++) { - x1 = 0; - destPtr = destLinePtr; - while (x1 < width) { - /* search for first non-transparent pixel */ - while ((x1 < width) && !*destPtr) { - x1++; - destPtr += 4; - } - end = x1; - /* search for first transparent pixel */ - while ((end < width) && *destPtr) { - end++; - destPtr += 4; - } - if (end > x1) { - rect.x = x + x1; - rect.y = y + y1; - rect.width = end - x1; - rect.height = 1; - TkUnionRectWithRegion(&rect, masterPtr->validRegion, - masterPtr->validRegion); - } - x1 = end; - } - destLinePtr += masterPtr->width * 4; - } + /* + * Factorize out the main part of the building of the region data to + * allow for more efficient per-platform implementations. [Bug 919066] + */ + + TkpBuildRegionFromAlphaData(masterPtr->validRegion, (unsigned) x, + (unsigned) y, (unsigned) width, (unsigned) height, + masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3, + 4, (unsigned) masterPtr->width * 4); } else { rect.x = x; rect.y = y; @@ -4603,6 +4619,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * builds up large simple-alpha images by single pixels. We don't * negate COMPLEX_ALPHA in this case. [Bug 1409140] */ + if (!(masterPtr->flags & COMPLEX_ALPHA)) { unsigned char newAlpha; @@ -4620,6 +4637,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * Toggle to only checking the changed pixels requires knowing where * the alpha pixels are. */ + ToggleComplexAlphaIfNeeded(masterPtr); } @@ -4633,8 +4651,9 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * Tell the core image code that this image has changed. */ - Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, - masterPtr->height); + Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, + masterPtr->width, masterPtr->height); + return TCL_OK; } /* @@ -4642,60 +4661,56 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule) * * Tk_PhotoPutZoomedBlock -- * - * This procedure is called to put image data into a photo image, - * with possible subsampling and/or zooming of the pixels. + * This function is called to put image data into a photo image, with + * possible subsampling and/or zooming of the pixels. * * Results: * None. * * Side effects: - * The image data is stored. The image may be expanded. - * The Tk image code is informed that the image has changed. + * The image data is stored. The image may be expanded. The Tk image code + * is informed that the image has changed. * *---------------------------------------------------------------------- */ -void -Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, - subsampleX, subsampleY, compRule) - Tk_PhotoHandle handle; /* Opaque handle for the photo image - * to be updated. */ - register Tk_PhotoImageBlock *blockPtr; - /* Pointer to a structure describing the - * pixel data to be copied into the image. */ - int x, y; /* Coordinates of the top-left pixel to - * be updated in the image. */ - int width, height; /* Dimensions of the area of the image - * to be updated. */ - int zoomX, zoomY; /* Zoom factors for the X and Y axes. */ - int subsampleX, subsampleY; /* Subsampling factors for the X and Y axes. */ - int compRule; /* Compositing rule to use when processing +int +Tk_PhotoPutZoomedBlock( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Opaque handle for the photo image to be + * updated. */ + register 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 + * updated in the image. */ + int width, int height, /* Dimensions of the area of the image to be + * updated. */ + int zoomX, int zoomY, /* Zoom factors for the X and Y axes. */ + int subsampleX, int subsampleY, + /* Subsampling factors for the X and Y + * axes. */ + int compRule) /* Compositing rule to use when processing * transparent pixels. */ { - register PhotoMaster *masterPtr; - int xEnd, yEnd; - int greenOffset, blueOffset, alphaOffset; - int wLeft, hLeft; - int wCopy, hCopy; - int blockWid, blockHt; - unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr; - unsigned char *destPtr, *destLinePtr; - int pitch; - int xRepeat, yRepeat; - int blockXSkip, blockYSkip, sourceIsSimplePhoto; + register PhotoMaster *masterPtr = (PhotoMaster *) handle; + int xEnd, yEnd, greenOffset, blueOffset, alphaOffset; + int wLeft, hLeft, wCopy, hCopy, blockWid, blockHt; + unsigned char *srcPtr, *srcLinePtr, *srcOrigPtr, *destPtr, *destLinePtr; + int pitch, xRepeat, yRepeat, blockXSkip, blockYSkip, sourceIsSimplePhoto; XRectangle rect; if (zoomX==1 && zoomY==1 && subsampleX==1 && subsampleY==1) { - Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, compRule); - return; + return Tk_PhotoPutBlock(interp, handle, blockPtr, x, y, width, height, + compRule); } sourceIsSimplePhoto = compRule & SOURCE_IS_SIMPLE_ALPHA_PHOTO; compRule &= ~SOURCE_IS_SIMPLE_ALPHA_PHOTO; - masterPtr = (PhotoMaster *) handle; if (zoomX <= 0 || zoomY <= 0) { - return; + return TCL_OK; } if ((masterPtr->userWidth != 0) && ((x + width) > masterPtr->userWidth)) { width = masterPtr->userWidth - x; @@ -4705,7 +4720,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, height = masterPtr->userHeight - y; } if (width <= 0 || height <= 0) { - return; + return TCL_OK; } xEnd = x + width; @@ -4714,7 +4729,11 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, int sameSrc = (blockPtr->pixelPtr == masterPtr->pix32); if (ImgPhotoSetSize(masterPtr, MAX(xEnd, masterPtr->width), MAX(yEnd, masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } if (sameSrc) { blockPtr->pixelPtr = masterPtr->pix32; @@ -4799,10 +4818,12 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, srcPtr = srcLinePtr; for (; wCopy > 0; wCopy -= zoomX) { for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) { - int alpha = srcPtr[alphaOffset]; + int alpha = srcPtr[alphaOffset];/* Source alpha. */ + /* * Common case (solid pixels) first */ + if (!alphaOffset || (alpha == 255)) { *destPtr++ = srcPtr[0]; *destPtr++ = srcPtr[greenOffset]; @@ -4811,32 +4832,33 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, continue; } - switch (compRule) { - case TK_PHOTO_COMPOSITE_OVERLAY: - if (!destPtr[3]) { - /* - * The destination is entirely blank, - * so set it to the source, just as if - * we used the SET compositing rule. - */ - case TK_PHOTO_COMPOSITE_SET: - *destPtr++ = srcPtr[0]; - *destPtr++ = srcPtr[greenOffset]; - *destPtr++ = srcPtr[blueOffset]; - *destPtr++ = alpha; - break; - } - if (alpha) { - int Alpha = destPtr[3]; - destPtr[0] = PD_SRC_OVER(srcPtr[0],alpha,destPtr[0],Alpha); - destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha,destPtr[1],Alpha); - destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset],alpha,destPtr[2],Alpha); - destPtr[3] = PD_SRC_OVER_ALPHA(alpha,Alpha); - } + if (compRule==TK_PHOTO_COMPOSITE_SET || !destPtr[3]) { + /* + * Either this is the SET rule (we overwrite + * whatever is there) or the destination is + * entirely blank. In both cases, we just set the + * destination to the source. + */ + + *destPtr++ = srcPtr[0]; + *destPtr++ = srcPtr[greenOffset]; + *destPtr++ = srcPtr[blueOffset]; + *destPtr++ = alpha; + } else if (alpha) { + int Alpha = destPtr[3]; /* Destination + * alpha. */ + + destPtr[0] = PD_SRC_OVER(srcPtr[0], alpha, + destPtr[0], Alpha); + destPtr[1] = PD_SRC_OVER(srcPtr[greenOffset],alpha, + destPtr[1], Alpha); + destPtr[2] = PD_SRC_OVER(srcPtr[blueOffset], alpha, + destPtr[2], Alpha); + destPtr[3] = PD_SRC_OVER_ALPHA(alpha, Alpha); + + destPtr += 4; + } else { destPtr += 4; - break; - default: - panic("unknown compositing rule: %d", compRule); } } srcPtr += blockXSkip; @@ -4856,13 +4878,12 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, */ if (alphaOffset) { - int x1, y1, end; - if (compRule != TK_PHOTO_COMPOSITE_OVERLAY) { /* * Don't need this when using the OVERLAY compositing rule, which * always strictly increases the valid region. */ + TkRegion workRgn = TkCreateRegion(); rect.x = x; @@ -4875,34 +4896,10 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, TkDestroyRegion(workRgn); } - destLinePtr = masterPtr->pix32 + (y * masterPtr->width + x) * 4 + 3; - for (y1 = 0; y1 < height; y1++) { - x1 = 0; - destPtr = destLinePtr; - while (x1 < width) { - /* search for first non-transparent pixel */ - while ((x1 < width) && !*destPtr) { - x1++; - destPtr += 4; - } - end = x1; - /* search for first transparent pixel */ - while ((end < width) && *destPtr) { - end++; - destPtr += 4; - } - if (end > x1) { - rect.x = x + x1; - rect.y = y + y1; - rect.width = end - x1; - rect.height = 1; - TkUnionRectWithRegion(&rect, masterPtr->validRegion, - masterPtr->validRegion); - } - x1 = end; - } - destLinePtr += masterPtr->width * 4; - } + TkpBuildRegionFromAlphaData(masterPtr->validRegion, + (unsigned)x, (unsigned)y, (unsigned)width, (unsigned)height, + &masterPtr->pix32[(y * masterPtr->width + x) * 4 + 3], 4, + (unsigned) masterPtr->width * 4); } else { rect.x = x; rect.y = y; @@ -4946,7 +4943,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, * Update each instance. */ - Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height); + Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y, width, height); /* * Tell the core image code that this image has changed. @@ -4954,6 +4951,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, Tk_ImageChanged(masterPtr->tkMaster, x, y, width, height, masterPtr->width, masterPtr->height); + return TCL_OK; } /* @@ -4961,27 +4959,27 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY, * * Tk_DitherPhoto -- * - * This procedure is called to update an area of each instance's - * pixmap by dithering the corresponding area of the image master. + * This function is called to update an area of each instance's pixmap by + * dithering the corresponding area of the image master. * * Results: * None. * * Side effects: - * The pixmap of each instance of this image gets updated. - * The fields in *masterPtr indicating which area of the image - * is correctly dithered get updated. + * The pixmap of each instance of this image gets updated. The fields in + * *masterPtr indicating which area of the image is correctly dithered + * get updated. * *---------------------------------------------------------------------- */ void -Tk_DitherPhoto(photo, x, y, width, height) - Tk_PhotoHandle photo; /* Image master whose instances are - * to be updated. */ - int x, y; /* Coordinates of the top-left pixel - * in the area to be dithered. */ - int width, height; /* Dimensions of the area to be dithered. */ +Tk_DitherPhoto( + Tk_PhotoHandle photo, /* Image master whose instances are to be + * updated. */ + int x, int y, /* Coordinates of the top-left pixel in the + * area to be dithered. */ + int width, int height) /* Dimensions of the area to be dithered. */ { PhotoMaster *masterPtr = (PhotoMaster *) photo; PhotoInstance *instancePtr; @@ -4996,14 +4994,13 @@ Tk_DitherPhoto(photo, x, y, width, height) } /* - * Work out whether this block will be correctly dithered - * and whether it will extend the correctly dithered region. + * Work out whether this block will be correctly dithered and whether it + * will extend the correctly dithered region. */ if (((y < masterPtr->ditherY) || ((y == masterPtr->ditherY) && (x <= masterPtr->ditherX))) && ((y + height) > (masterPtr->ditherY))) { - /* * This block starts inside (or immediately after) the correctly * dithered region, so the first scan line at least will be right. @@ -5012,8 +5009,8 @@ Tk_DitherPhoto(photo, x, y, width, height) if ((x == 0) && (width == masterPtr->width)) { /* - * We are doing the full width, therefore the dithering - * will be correct to the end. + * We are doing the full width, therefore the dithering will be + * correct to the end. */ masterPtr->ditherX = 0; @@ -5021,8 +5018,8 @@ Tk_DitherPhoto(photo, x, y, width, height) } else { /* * We are doing partial scanlines, therefore the - * correctly-dithered region will be extended by - * at most one scan line. + * correctly-dithered region will be extended by at most one scan + * line. */ if (x <= masterPtr->ditherX) { @@ -5034,16 +5031,15 @@ Tk_DitherPhoto(photo, x, y, width, height) } } } - -} +} /* *---------------------------------------------------------------------- * * DitherInstance -- * - * This procedure is called to update an area of an instance's - * pixmap by dithering the corresponding area of the master. + * This function is called to update an area of an instance's pixmap by + * dithering the corresponding area of the master. * * Results: * None. @@ -5055,33 +5051,24 @@ Tk_DitherPhoto(photo, x, y, width, height) */ static void -DitherInstance(instancePtr, xStart, yStart, width, height) - PhotoInstance *instancePtr; /* The instance to be updated. */ - int xStart, yStart; /* Coordinates of the top-left pixel in the +DitherInstance( + PhotoInstance *instancePtr, /* The instance to be updated. */ + int xStart, int yStart, /* Coordinates of the top-left pixel in the * block to be dithered. */ - int width, height; /* Dimensions of the block to be dithered. */ + int width, int height) /* Dimensions of the block to be dithered. */ { - PhotoMaster *masterPtr; - ColorTable *colorPtr; + PhotoMaster *masterPtr = instancePtr->masterPtr; + ColorTable *colorPtr = instancePtr->colorTablePtr; XImage *imagePtr; - int nLines, bigEndian; - int i, c, x, y; - int xEnd, yEnd; + int nLines, bigEndian, i, c, x, y, xEnd, doDithering = 1; int bitsPerPixel, bytesPerLine, lineLength; - unsigned char *srcLinePtr, *srcPtr; - schar *errLinePtr, *errPtr; - unsigned char *destBytePtr, *dstLinePtr; - pixel *destLongPtr; + unsigned char *srcLinePtr; + schar *errLinePtr; pixel firstBit, word, mask; - int col[3]; - int doDithering = 1; - - colorPtr = instancePtr->colorTablePtr; - masterPtr = instancePtr->masterPtr; /* - * Turn dithering off in certain cases where it is not - * needed (TrueColor, DirectColor with many colors). + * Turn dithering off in certain cases where it is not needed (TrueColor, + * DirectColor with many colors). */ if ((colorPtr->visualInfo.class == DirectColor) @@ -5097,9 +5084,8 @@ DitherInstance(instancePtr, xStart, yStart, width, height) } /* - * First work out how many lines to do at a time, - * then how many bytes we'll need for pixel storage, - * and allocate it. + * First work out how many lines to do at a time, then how many bytes + * we'll need for pixel storage, and allocate it. */ nLines = (MAX_PIXELS + width - 1) / width; @@ -5112,14 +5098,15 @@ DitherInstance(instancePtr, xStart, yStart, width, height) imagePtr = instancePtr->imagePtr; if (imagePtr == NULL) { - return; /* we must be really tight on memory */ + return; /* We must be really tight on memory. */ } bitsPerPixel = imagePtr->bits_per_pixel; bytesPerLine = ((bitsPerPixel * width + 31) >> 3) & ~3; imagePtr->width = width; imagePtr->height = nLines; imagePtr->bytes_per_line = bytesPerLine; - imagePtr->data = (char *) ckalloc((unsigned) (imagePtr->bytes_per_line * nLines)); + imagePtr->data = (char *) + ckalloc((unsigned) (imagePtr->bytes_per_line * nLines)); bigEndian = imagePtr->bitmap_bit_order == MSBFirst; firstBit = bigEndian? (1 << (imagePtr->bitmap_unit - 1)): 1; @@ -5129,46 +5116,50 @@ DitherInstance(instancePtr, xStart, yStart, width, height) xEnd = xStart + width; /* - * Loop over the image, doing at most nLines lines before - * updating the screen image. + * Loop over the image, doing at most nLines lines before updating the + * screen image. */ for (; height > 0; height -= nLines) { + unsigned char *dstLinePtr = (unsigned char *) imagePtr->data; + int yEnd; + if (nLines > height) { nLines = height; } - dstLinePtr = (unsigned char *) imagePtr->data; yEnd = yStart + nLines; for (y = yStart; y < yEnd; ++y) { - srcPtr = srcLinePtr; - errPtr = errLinePtr; - destBytePtr = dstLinePtr; - destLongPtr = (pixel *) dstLinePtr; + unsigned char *srcPtr = srcLinePtr; + schar *errPtr = errLinePtr; + unsigned char *destBytePtr = dstLinePtr; + pixel *destLongPtr = (pixel *) dstLinePtr; + if (colorPtr->flags & COLOR_WINDOW) { /* - * Color window. We dither the three components - * independently, using Floyd-Steinberg dithering, - * which propagates errors from the quantization of - * pixels to the pixels below and to the right. + * Color window. We dither the three components independently, + * using Floyd-Steinberg dithering, which propagates errors + * from the quantization of pixels to the pixels below and to + * the right. */ for (x = xStart; x < xEnd; ++x) { + int col[3]; + if (doDithering) { for (i = 0; i < 3; ++i) { /* * Compute the error propagated into this pixel - * for this component. - * If e[x,y] is the array of quantization error - * values, we compute + * for this component. If e[x,y] is the array of + * quantization error values, we compute * 7/16 * e[x-1,y] + 1/16 * e[x-1,y-1] * + 5/16 * e[x,y-1] + 3/16 * e[x+1,y-1] * and round it to an integer. * - * The expression ((c + 2056) >> 4) - 128 - * computes round(c / 16), and works correctly on - * machines without a sign-extending right shift. + * The expression ((c + 2056) >> 4) - 128 computes + * round(c / 16), and works correctly on machines + * without a sign-extending right shift. */ - + c = (x > 0) ? errPtr[-3] * 7: 0; if (y > 0) { if (x > 0) { @@ -5179,13 +5170,13 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += errPtr[-lineLength+3] * 3; } } - + /* * Add the propagated error to the value of this * component, quantize it, and store the * quantization error. */ - + c = ((c + 2056) >> 4) - 128 + *srcPtr++; if (c < 0) { c = 0; @@ -5196,9 +5187,9 @@ DitherInstance(instancePtr, xStart, yStart, width, height) *errPtr++ = c - col[i]; } } else { - /* - * Output is virtually continuous in this case, - * so don't bother dithering. + /* + * Output is virtually continuous in this case, so + * don't bother dithering. */ col[0] = *srcPtr++; @@ -5208,8 +5199,8 @@ DitherInstance(instancePtr, xStart, yStart, width, height) srcPtr++; /* - * Translate the quantized component values into - * an X pixel value, and store it in the image. + * Translate the quantized component values into an X + * pixel value, and store it in the image. */ i = colorPtr->redValues[col[0]] @@ -5219,32 +5210,34 @@ DitherInstance(instancePtr, xStart, yStart, width, height) i = colorPtr->pixelMap[i]; } switch (bitsPerPixel) { - case NBBY: - *destBytePtr++ = i; - break; + case NBBY: + *destBytePtr++ = i; + break; #ifndef __WIN32__ -/* - * This case is not valid for Windows because the image format is different - * from the pixel format in Win32. Eventually we need to fix the image - * code in Tk to use the Windows native image ordering. This would speed - * up the image code for all of the common sizes. - */ + /* + * This case is not valid for Windows because the + * image format is different from the pixel format in + * Win32. Eventually we need to fix the image code in + * Tk to use the Windows native image ordering. This + * would speed up the image code for all of the common + * sizes. + */ - case NBBY * sizeof(pixel): - *destLongPtr++ = i; - break; + case NBBY * sizeof(pixel): + *destLongPtr++ = i; + break; #endif - default: - XPutPixel(imagePtr, x - xStart, y - yStart, - (unsigned) i); + default: + XPutPixel(imagePtr, x - xStart, y - yStart, + (unsigned) i); } } } else if (bitsPerPixel > 1) { /* - * Multibit monochrome window. The operation here is similar + * Multibit monochrome window. The operation here is similar * to the color window case above, except that there is only - * one component. If the master image is in color, use the + * one component. If the master image is in color, use the * luminance computed as * 0.344 * red + 0.5 * green + 0.156 * blue. */ @@ -5266,7 +5259,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += srcPtr[0]; } else { c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16 - + srcPtr[2] * 5 + 16) >> 5; + + srcPtr[2] * 5 + 16) >> 5; } srcPtr += 4; @@ -5279,40 +5272,42 @@ DitherInstance(instancePtr, xStart, yStart, width, height) *errPtr++ = c - i; i = colorPtr->redValues[i]; switch (bitsPerPixel) { - case NBBY: - *destBytePtr++ = i; - break; + case NBBY: + *destBytePtr++ = i; + break; #ifndef __WIN32__ -/* - * This case is not valid for Windows because the image format is different - * from the pixel format in Win32. Eventually we need to fix the image - * code in Tk to use the Windows native image ordering. This would speed - * up the image code for all of the common sizes. - */ + /* + * This case is not valid for Windows because the + * image format is different from the pixel format in + * Win32. Eventually we need to fix the image code in + * Tk to use the Windows native image ordering. This + * would speed up the image code for all of the common + * sizes. + */ - case NBBY * sizeof(pixel): - *destLongPtr++ = i; - break; + case NBBY * sizeof(pixel): + *destLongPtr++ = i; + break; #endif - default: - XPutPixel(imagePtr, x - xStart, y - yStart, - (unsigned) i); + default: + XPutPixel(imagePtr, x - xStart, y - yStart, + (unsigned) i); } } } else { /* - * 1-bit monochrome window. This is similar to the - * multibit monochrome case above, except that the - * quantization is simpler (we only have black = 0 - * and white = 255), and we produce an XY-Bitmap. + * 1-bit monochrome window. This is similar to the multibit + * monochrome case above, except that the quantization is + * simpler (we only have black = 0 and white = 255), and we + * produce an XY-Bitmap. */ word = 0; mask = firstBit; for (x = xStart; x < xEnd; ++x) { /* - * If we have accumulated a whole word, store it - * in the image and start a new word. + * If we have accumulated a whole word, store it in the + * image and start a new word. */ if (mask == 0) { @@ -5337,7 +5332,7 @@ DitherInstance(instancePtr, xStart, yStart, width, height) c += srcPtr[0]; } else { c += (unsigned)(srcPtr[0] * 11 + srcPtr[1] * 16 - + srcPtr[2] * 5 + 16) >> 5; + + srcPtr[2] * 5 + 16) >> 5; } srcPtr += 4; @@ -5362,8 +5357,8 @@ DitherInstance(instancePtr, xStart, yStart, width, height) } /* - * Update the pixmap for this instance with the block of - * pixels that we have just computed. + * Update the pixmap for this instance with the block of pixels that + * we have just computed. */ TkPutImage(colorPtr->pixelMap, colorPtr->numColors, @@ -5371,7 +5366,6 @@ DitherInstance(instancePtr, xStart, yStart, width, height) instancePtr->gc, imagePtr, 0, 0, xStart, yStart, (unsigned) width, (unsigned) nLines); yStart = yEnd; - } ckfree(imagePtr->data); @@ -5383,26 +5377,25 @@ DitherInstance(instancePtr, xStart, yStart, width, height) * * Tk_PhotoBlank -- * - * This procedure is called to clear an entire photo image. + * This function is called to clear an entire photo image. * * Results: * None. * * Side effects: - * The valid region for the image is set to the null region. - * The generic image code is notified that the image has changed. + * The valid region for the image is set to the null region. The generic + * image code is notified that the image has changed. * *---------------------------------------------------------------------- */ void -Tk_PhotoBlank(handle) - Tk_PhotoHandle handle; /* Handle for the image to be blanked. */ +Tk_PhotoBlank( + Tk_PhotoHandle handle) /* Handle for the image to be blanked. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; PhotoInstance *instancePtr; - masterPtr = (PhotoMaster *) handle; masterPtr->ditherX = masterPtr->ditherY = 0; masterPtr->flags = 0; @@ -5416,16 +5409,16 @@ Tk_PhotoBlank(handle) masterPtr->validRegion = TkCreateRegion(); /* - * Clear out the 32-bit pixel storage array. - * Clear out the dithering error arrays for each instance. + * Clear out the 32-bit pixel storage array. Clear out the dithering error + * arrays for each instance. */ - memset((VOID *) masterPtr->pix32, 0, + memset(masterPtr->pix32, 0, (size_t) (masterPtr->width * masterPtr->height * 4)); for (instancePtr = masterPtr->instancePtr; instancePtr != NULL; instancePtr = instancePtr->nextPtr) { if (instancePtr->error) { - memset((VOID *) instancePtr->error, 0, + memset(instancePtr->error, 0, (size_t) (masterPtr->width * masterPtr->height * 3 * sizeof(schar))); } @@ -5444,30 +5437,29 @@ Tk_PhotoBlank(handle) * * Tk_PhotoExpand -- * - * This procedure is called to request that a photo image be - * expanded if necessary to be at least `width' pixels wide and - * `height' pixels high. If the user has declared a definite - * image size (using the -width and -height configuration - * options) then this call has no effect. + * This function is called to request that a photo image be expanded if + * necessary to be at least `width' pixels wide and `height' pixels high. + * If the user has declared a definite image size (using the -width and + * -height configuration options) then this call has no effect. * * Results: * None. * * Side effects: - * The size of the photo image may change; if so the generic - * image code is informed. + * The size of the photo image may change; if so the generic image code + * is informed. * *---------------------------------------------------------------------- */ -void -Tk_PhotoExpand(handle, width, height) - Tk_PhotoHandle handle; /* Handle for the image to be expanded. */ - int width, height; /* Desired minimum dimensions of the image. */ +int +Tk_PhotoExpand( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Handle for the image to be expanded. */ + int width, int height) /* Desired minimum dimensions of the image. */ { - PhotoMaster *masterPtr; - - masterPtr = (PhotoMaster *) handle; + PhotoMaster *masterPtr = (PhotoMaster *) handle; if (width <= masterPtr->width) { width = masterPtr->width; @@ -5478,11 +5470,16 @@ Tk_PhotoExpand(handle, width, height) if ((width != masterPtr->width) || (height != masterPtr->height)) { if (ImgPhotoSetSize(masterPtr, MAX(width, masterPtr->width), MAX(height, masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width, masterPtr->height); } + return TCL_OK; } /* @@ -5490,12 +5487,10 @@ Tk_PhotoExpand(handle, width, height) * * Tk_PhotoGetSize -- * - * This procedure is called to obtain the current size of a photo - * image. + * This function is called to obtain the current size of a photo image. * * Results: - * The image's width and height are returned in *widthp - * and *heightp. + * The image's width and height are returned in *widthp and *heightp. * * Side effects: * None. @@ -5504,15 +5499,15 @@ Tk_PhotoExpand(handle, width, height) */ void -Tk_PhotoGetSize(handle, widthPtr, heightPtr) - Tk_PhotoHandle handle; /* Handle for the image whose dimensions - * are requested. */ - int *widthPtr, *heightPtr; /* The dimensions of the image are returned +Tk_PhotoGetSize( + Tk_PhotoHandle handle, /* Handle for the image whose dimensions are + * requested. */ + int *widthPtr, int *heightPtr) + /* The dimensions of the image are returned * here. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; - masterPtr = (PhotoMaster *) handle; *widthPtr = masterPtr->width; *heightPtr = masterPtr->height; } @@ -5522,38 +5517,42 @@ Tk_PhotoGetSize(handle, widthPtr, heightPtr) * * Tk_PhotoSetSize -- * - * This procedure is called to set size of a photo image. - * This call is equivalent to using the -width and -height - * configuration options. + * This function is called to set size of a photo image. This call is + * equivalent to using the -width and -height configuration options. * * Results: * None. * * Side effects: - * The size of the image may change; if so the generic - * image code is informed. + * The size of the image may change; if so the generic image code is + * informed. * *---------------------------------------------------------------------- */ -void -Tk_PhotoSetSize(handle, width, height) - Tk_PhotoHandle handle; /* Handle for the image whose size is to - * be set. */ - int width, height; /* New dimensions for the image. */ +int +Tk_PhotoSetSize( + Tcl_Interp *interp, /* Interpreter for passing back error + * messages, or NULL. */ + Tk_PhotoHandle handle, /* Handle for the image whose size is to be + * set. */ + int width, int height) /* New dimensions for the image. */ { - PhotoMaster *masterPtr; - - masterPtr = (PhotoMaster *) handle; + PhotoMaster *masterPtr = (PhotoMaster *) handle; masterPtr->userWidth = width; masterPtr->userHeight = height; if (ImgPhotoSetSize(masterPtr, ((width > 0) ? width: masterPtr->width), ((height > 0) ? height: masterPtr->height)) == TCL_ERROR) { - panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + if (interp != NULL) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, TK_PHOTO_ALLOC_FAILURE_MESSAGE, NULL); + } + return TCL_ERROR; } Tk_ImageChanged(masterPtr->tkMaster, 0, 0, 0, 0, masterPtr->width, masterPtr->height); + return TCL_OK; } /* @@ -5561,14 +5560,14 @@ Tk_PhotoSetSize(handle, width, height) * * TkGetPhotoValidRegion -- * - * This procedure is called to get the part of the photo where - * there is valid data. Or, conversely, the part of the photo - * which is transparent. + * This function is called to get the part of the photo where there is + * valid data. Or, conversely, the part of the photo which is + * transparent. * * Results: - * A TkRegion value that indicates the current area of the photo - * that is valid. This value should not be used after any - * modification to the photo image. + * A TkRegion value that indicates the current area of the photo that is + * valid. This value should not be used after any modification to the + * photo image. * * Side Effects: * None. @@ -5577,13 +5576,12 @@ Tk_PhotoSetSize(handle, width, height) */ TkRegion -TkPhotoGetValidRegion(handle) - Tk_PhotoHandle handle; /* Handle for the image whose valid region - * is to obtained. */ +TkPhotoGetValidRegion( + Tk_PhotoHandle handle) /* Handle for the image whose valid region is + * to obtained. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; - masterPtr = (PhotoMaster *) handle; return masterPtr->validRegion; } @@ -5592,15 +5590,15 @@ TkPhotoGetValidRegion(handle) * * ImgGetPhoto -- * - * This procedure is called to obtain image data from a photo - * image. This procedure fills in the Tk_PhotoImageBlock structure - * pointed to by `blockPtr' with details of the address and - * layout of the image data in memory. + * This function is called to obtain image data from a photo image. This + * function fills in the Tk_PhotoImageBlock structure pointed to by + * `blockPtr' with details of the address and layout of the image data in + * memory. * * Results: - * A pointer to the allocated data which should be freed later. - * NULL if there is no need to free data because - * blockPtr->pixelPtr points directly to the image data. + * A pointer to the allocated data which should be freed later. NULL if + * there is no need to free data because blockPtr->pixelPtr points + * directly to the image data. * * Side effects: * None. @@ -5609,13 +5607,13 @@ TkPhotoGetValidRegion(handle) */ static char * -ImgGetPhoto(masterPtr, blockPtr, optPtr) - PhotoMaster *masterPtr; /* Handle for the photo image from which - * image data is desired. */ - Tk_PhotoImageBlock *blockPtr; - /* Information about the address and layout - * of the image data is returned here. */ - struct SubcommandOptions *optPtr; +ImgGetPhoto( + PhotoMaster *masterPtr, /* Handle for the photo image from which image + * data is desired. */ + Tk_PhotoImageBlock *blockPtr, + /* Information about the address and layout of + * the image data is returned here. */ + struct SubcommandOptions *optPtr) { unsigned char *pixelPtr; int x, y, greenOffset, blueOffset, alphaOffset; @@ -5630,8 +5628,7 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) (!(optPtr->options & OPT_BACKGROUND) || ((optPtr->background->red == optPtr->background->green) && (optPtr->background->red == optPtr->background->blue)))) { - blockPtr->offset[0] = blockPtr->offset[1] = - blockPtr->offset[2]; + blockPtr->offset[0] = blockPtr->offset[1] = blockPtr->offset[2]; } alphaOffset = 0; for (y = 0; y < blockPtr->height; y++) { @@ -5657,13 +5654,14 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) greenOffset = blockPtr->offset[1] - blockPtr->offset[0]; blueOffset = blockPtr->offset[2] - blockPtr->offset[0]; if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) || - ((optPtr->options & OPT_GRAYSCALE) && (greenOffset || blueOffset))) { + ((optPtr->options & OPT_GRAYSCALE) && (greenOffset||blueOffset))) { int newPixelSize,x,y; unsigned char *srcPtr, *destPtr; char *data; - newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset) ? 2 : 1; - if ((greenOffset || blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) { + newPixelSize = (!(optPtr->options & OPT_BACKGROUND) && alphaOffset) + ? 2 : 1; + if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) { newPixelSize += 2; } data = ckalloc((unsigned int) (newPixelSize * @@ -5677,17 +5675,19 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } else if (optPtr->options & OPT_GRAYSCALE) { for (y = blockPtr->height; y > 0; y--) { for (x = blockPtr->width; x > 0; x--) { - *destPtr = (unsigned char) ((srcPtr[0] * 11 + srcPtr[1] * 16 - + srcPtr[2] * 5 + 16) >> 5); + *destPtr = (unsigned char) ((srcPtr[0]*11 + srcPtr[1]*16 + + srcPtr[2]*5 + 16) >> 5); srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } else { for (y = blockPtr->height; y > 0; y--) { @@ -5698,18 +5698,22 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } srcPtr = blockPtr->pixelPtr + alphaOffset; destPtr = (unsigned char *) data; if (!alphaOffset) { - /* nothing to be done */ + /* + * Nothing to be done. + */ } else if (optPtr->options & OPT_BACKGROUND) { if (newPixelSize > 2) { - int red = optPtr->background->red>>8; - int green = optPtr->background->green>>8; - int blue = optPtr->background->blue>>8; + int red = optPtr->background->red>>8; + int green = optPtr->background->green>>8; + int blue = optPtr->background->blue>>8; + for (y = blockPtr->height; y > 0; y--) { for (x = blockPtr->width; x > 0; x--) { destPtr[0] += (unsigned char) (((255 - *srcPtr) * @@ -5721,12 +5725,14 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } else { int gray = (unsigned char) (((optPtr->background->red>>8) * 11 - + (optPtr->background->green>>8) * 16 - + (optPtr->background->blue>>8) * 5 + 16) >> 5); + + (optPtr->background->green>>8) * 16 + + (optPtr->background->blue>>8) * 5 + 16) >> 5); + for (y = blockPtr->height; y > 0; y--) { for (x = blockPtr->width; x > 0; x--) { destPtr[0] += ((255 - *srcPtr) * @@ -5734,7 +5740,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } } else { @@ -5745,7 +5752,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) srcPtr += blockPtr->pixelSize; destPtr += newPixelSize; } - srcPtr += blockPtr->pitch - (blockPtr->width * blockPtr->pixelSize); + srcPtr += blockPtr->pitch - + blockPtr->width * blockPtr->pixelSize; } } blockPtr->pixelPtr = (unsigned char *) data; @@ -5769,8 +5777,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) * * ImgStringWrite -- * - * Default string write function. The data is formatted in - * the default format as accepted by the "<img> put" command. + * Default string write function. The data is formatted in the default + * format as accepted by the "<img> put" command. * * Results: * A standard Tcl result. @@ -5782,12 +5790,12 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr) */ static int -ImgStringWrite(interp, formatString, blockPtr) - Tcl_Interp *interp; - Tcl_Obj *formatString; - Tk_PhotoImageBlock *blockPtr; +ImgStringWrite( + Tcl_Interp *interp, + Tcl_Obj *formatString, + Tk_PhotoImageBlock *blockPtr) { - int row,col; + int row, col; char *line, *linePtr; unsigned char *pixelPtr; int greenOffset, blueOffset; @@ -5822,14 +5830,14 @@ ImgStringWrite(interp, formatString, blockPtr) * * Tk_PhotoGetImage -- * - * This procedure is called to obtain image data from a photo - * image. This procedure fills in the Tk_PhotoImageBlock structure - * pointed to by `blockPtr' with details of the address and - * layout of the image data in memory. + * This function is called to obtain image data from a photo image. This + * function fills in the Tk_PhotoImageBlock structure pointed to by + * `blockPtr' with details of the address and layout of the image data in + * memory. * * Results: - * TRUE (1) indicating that image data is available, - * for backwards compatibility with the old photo widget. + * TRUE (1) indicating that image data is available, for backwards + * compatibility with the old photo widget. * * Side effects: * None. @@ -5838,16 +5846,15 @@ ImgStringWrite(interp, formatString, blockPtr) */ int -Tk_PhotoGetImage(handle, blockPtr) - Tk_PhotoHandle handle; /* Handle for the photo image from which - * image data is desired. */ - Tk_PhotoImageBlock *blockPtr; - /* Information about the address and layout - * of the image data is returned here. */ +Tk_PhotoGetImage( + Tk_PhotoHandle handle, /* Handle for the photo image from which image + * data is desired. */ + Tk_PhotoImageBlock *blockPtr) + /* Information about the address and layout of + * the image data is returned here. */ { - PhotoMaster *masterPtr; + PhotoMaster *masterPtr = (PhotoMaster *) handle; - masterPtr = (PhotoMaster *) handle; blockPtr->pixelPtr = masterPtr->pix32; blockPtr->width = masterPtr->width; blockPtr->height = masterPtr->height; @@ -5859,7 +5866,7 @@ Tk_PhotoGetImage(handle, blockPtr) blockPtr->offset[3] = 3; return 1; } - + /* *---------------------------------------------------------------------- * @@ -5877,57 +5884,56 @@ Tk_PhotoGetImage(handle, blockPtr) */ typedef struct OptionAssocData { - struct OptionAssocData *nextPtr; /* pointer to next OptionAssocData */ - Tcl_ObjCmdProc *command; /* command associated with this - * option */ - char name[1]; /* name of option (remaining chars) */ + struct OptionAssocData *nextPtr; + /* Pointer to next OptionAssocData. */ + Tcl_ObjCmdProc *command; /* Command associated with this option. */ + char name[1]; /* Name of option (remaining chars) */ } OptionAssocData; static Tcl_ObjCmdProc * -PhotoOptionFind(interp, obj) - Tcl_Interp *interp; /* Interpreter that is being deleted. */ - Tcl_Obj *obj; /* Name of option to be found. */ +PhotoOptionFind( + Tcl_Interp *interp, /* Interpreter that is being deleted. */ + Tcl_Obj *obj) /* Name of option to be found. */ { int length; char *name = Tcl_GetStringFromObj(obj, &length); - OptionAssocData *list; char *prevname = NULL; - Tcl_ObjCmdProc *proc = (Tcl_ObjCmdProc *) NULL; + Tcl_ObjCmdProc *proc = NULL; + OptionAssocData *list = (OptionAssocData *) Tcl_GetAssocData(interp, + "photoOption", NULL); - list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption", - (Tcl_InterpDeleteProc **) NULL); - while (list != (OptionAssocData *) NULL) { + while (list != NULL) { if (strncmp(name, list->name, (unsigned) length) == 0) { - if (proc != (Tcl_ObjCmdProc *) NULL) { + if (proc != NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "ambiguous option \"", name, - "\": must be ", prevname, (char *) NULL); - while (list->nextPtr != (OptionAssocData *) NULL) { - Tcl_AppendResult(interp, prevname, ", ",(char *) NULL); + "\": must be ", prevname, NULL); + while (list->nextPtr != NULL) { + Tcl_AppendResult(interp, prevname, ", ",NULL); list = list->nextPtr; prevname = list->name; } - Tcl_AppendResult(interp, ", or", prevname, (char *) NULL); - return (Tcl_ObjCmdProc *) NULL; + Tcl_AppendResult(interp, ", or", prevname, NULL); + return NULL; } proc = list->command; prevname = list->name; } list = list->nextPtr; } - if (proc != (Tcl_ObjCmdProc *) NULL) { + if (proc != NULL) { Tcl_ResetResult(interp); } return proc; } - + /* *---------------------------------------------------------------------- * * PhotoOptionCleanupProc -- * - * This procedure is invoked whenever an interpreter is deleted - * to cleanup the AssocData for "photoVisitor". + * This function is invoked whenever an interpreter is deleted to cleanup + * the AssocData for "photoVisitor". * * Results: * None. @@ -5939,49 +5945,47 @@ PhotoOptionFind(interp, obj) */ static void -PhotoOptionCleanupProc(clientData, interp) - ClientData clientData; /* Points to "photoVisitor" AssocData - * for the interpreter. */ - Tcl_Interp *interp; /* Interpreter that is being deleted. */ +PhotoOptionCleanupProc( + ClientData clientData, /* Points to "photoVisitor" AssocData for the + * interpreter. */ + Tcl_Interp *interp) /* Interpreter that is being deleted. */ { OptionAssocData *list = (OptionAssocData *) clientData; - OptionAssocData *ptr; while (list != NULL) { + register OptionAssocData *ptr; + list = (ptr = list)->nextPtr; ckfree((char *) ptr); } } - + /* *-------------------------------------------------------------- * * Tk_CreatePhotoOption -- * - * This procedure may be invoked to add a new kind of photo - * option to the core photo command supported by Tk. + * This function may be invoked to add a new kind of photo option to the + * core photo command supported by Tk. * * Results: * None. * * Side effects: - * From now on, the new option will be useable by the - * photo command. + * From now on, the new option will be useable by the photo command. * *-------------------------------------------------------------- */ -void -Tk_CreatePhotoOption(interp, name, proc) - Tcl_Interp *interp; /* interpreter */ - CONST char *name; /* option name */ - Tcl_ObjCmdProc *proc; /* proc to execute command */ +MODULE_SCOPE void +Tk_CreatePhotoOption( + Tcl_Interp *interp, /* Interpreter. */ + CONST char *name, /* Option name. */ + Tcl_ObjCmdProc *proc) /* Function to execute command. */ { OptionAssocData *typePtr2, *prevPtr, *ptr; - OptionAssocData *list; - - list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption", - (Tcl_InterpDeleteProc **) NULL); + OptionAssocData *list = (OptionAssocData *) + Tcl_GetAssocData(interp, "photoOption", NULL); /* * If there's already a photo option with the given name, remove it. @@ -6004,7 +6008,7 @@ Tk_CreatePhotoOption(interp, name, proc) ptr->command = proc; ptr->nextPtr = list; Tcl_SetAssocData(interp, "photoOption", PhotoOptionCleanupProc, - (ClientData) ptr); + (ClientData) ptr); } /* @@ -6012,9 +6016,8 @@ Tk_CreatePhotoOption(interp, name, proc) * * TkPostscriptPhoto -- * - * This procedure is called to output the contents of a - * photo image in Postscript by calling the Tk_PostscriptPhoto - * function. + * This function is called to output the contents of a photo image in + * Postscript by calling the Tk_PostscriptPhoto function. * * Results: * Returns a standard Tcl return value. @@ -6024,16 +6027,16 @@ Tk_CreatePhotoOption(interp, name, proc) * *-------------------------------------------------------------- */ + static int -ImgPhotoPostscript(clientData, interp, tkwin, psInfo, - x, y, width, height, prepass) - ClientData clientData; /* Handle for the photo image */ - Tcl_Interp *interp; /* Interpreter */ - Tk_Window tkwin; /* (unused) */ - Tk_PostscriptInfo psInfo; /* postscript info */ - int x, y; /* First pixel to output */ - int width, height; /* Width and height of area */ - int prepass; /* (unused) */ +ImgPhotoPostscript( + ClientData clientData, /* Handle for the photo image. */ + Tcl_Interp *interp, /* Interpreter. */ + Tk_Window tkwin, /* (unused) */ + Tk_PostscriptInfo psInfo, /* Postscript info. */ + int x, int y, /* First pixel to output. */ + int width, int height, /* Width and height of area. */ + int prepass) /* (unused) */ { Tk_PhotoImageBlock block; @@ -6048,29 +6051,105 @@ ImgPhotoPostscript(clientData, interp, tkwin, psInfo, * * Tk_PhotoPutBlock_NoComposite, Tk_PhotoPutZoomedBlock_NoComposite -- * - * These backward-compatability functions just exist to fill slots in - * stubs table. For the behaviour of *_NoComposite, refer to the - * corresponding function without the extra suffix. + * These backward-compatability functions just exist to fill slots in stubs + * table. For the behaviour of *_NoComposite, refer to the corresponding + * function without the extra suffix, except that the compositing rule is + * always "overlay" and the function always panics on memory-allocation + * failure. + * + *---------------------------------------------------------------------- + */ + +void +Tk_PhotoPutBlock_NoComposite( + Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, + int x, int y, int width, int height) +{ + if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height, + TK_PHOTO_COMPOSITE_OVERLAY) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +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) +{ + if (Tk_PhotoPutZoomedBlock(NULL, handle, blockPtr, x, y, width, height, + zoomX, zoomY, subsampleX, subsampleY, + TK_PHOTO_COMPOSITE_OVERLAY) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_PhotoExpand_Panic, Tk_PhotoPutBlock_Panic, + * Tk_PhotoPutZoomedBlock_Panic, Tk_PhotoSetSize_Panic + * + * Backward compatability functions for preserving the old behaviour (i.e. + * panic on memory allocation failure) so that extensions do not need to be + * significantly updated to take account of TIP #116. These call the new + * interface (i.e. the interface without the extra suffix), but panic if an + * error condition is returned. * *---------------------------------------------------------------------- */ + +void +Tk_PhotoExpand_Panic( + Tk_PhotoHandle handle, + int width, int height) +{ + if (Tk_PhotoExpand(NULL, handle, width, height) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + +void +Tk_PhotoPutBlock_Panic( + Tk_PhotoHandle handle, + Tk_PhotoImageBlock *blockPtr, + int x, int y, int width, int height, int compRule) +{ + if (Tk_PhotoPutBlock(NULL, handle, blockPtr, x, y, width, height, + compRule) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } +} + void -Tk_PhotoPutBlock_NoComposite(handle, blockPtr, x, y, width, height) - Tk_PhotoHandle handle; - Tk_PhotoImageBlock *blockPtr; - int x, y, width, height; +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) { - Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height, - TK_PHOTO_COMPOSITE_OVERLAY); + if (Tk_PhotoPutZoomedBlock(NULL, handle, blockPtr, x, y, width, height, + zoomX, zoomY, subsampleX, subsampleY, compRule) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } } void -Tk_PhotoPutZoomedBlock_NoComposite(handle, blockPtr, x, y, width, height, - zoomX, zoomY, subsampleX, subsampleY) - Tk_PhotoHandle handle; - Tk_PhotoImageBlock *blockPtr; - int x, y, width, height, zoomX, zoomY, subsampleX, subsampleY; +Tk_PhotoSetSize_Panic( + Tk_PhotoHandle handle, + int width, int height) { - Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, - zoomX, zoomY, subsampleX, subsampleY, TK_PHOTO_COMPOSITE_OVERLAY); + if (Tk_PhotoSetSize(NULL, handle, width, height) != TCL_OK) { + Tcl_Panic(TK_PHOTO_ALLOC_FAILURE_MESSAGE); + } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkImgUtil.c b/generic/tkImgUtil.c index 0bb599a..8ba6c0e 100644 --- a/generic/tkImgUtil.c +++ b/generic/tkImgUtil.c @@ -1,16 +1,15 @@ -/* +/* * tkImgUtil.c -- * * This file contains image related utility functions. * * Copyright (c) 1995 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" #include "xbytes.h" @@ -19,12 +18,11 @@ * * TkAlignImageData -- * - * This function takes an image and copies the data into an - * aligned buffer, performing any necessary bit swapping. + * This function takes an image and copies the data into an aligned + * buffer, performing any necessary bit swapping. * * Results: - * Returns a newly allocated buffer that should be freed by the - * caller. + * Returns a newly allocated buffer that should be freed by the caller. * * Side effects: * None. @@ -33,18 +31,19 @@ */ char * -TkAlignImageData(image, alignment, bitOrder) - XImage *image; /* Image to be aligned. */ - int alignment; /* Number of bytes to which the data should - * be aligned (e.g. 2 or 4) */ - int bitOrder; /* Desired bit order: LSBFirst or MSBFirst. */ +TkAlignImageData( + XImage *image, /* Image to be aligned. */ + int alignment, /* Number of bytes to which the data should be + * aligned (e.g. 2 or 4) */ + int bitOrder) /* Desired bit order: LSBFirst or MSBFirst. */ { long dataWidth; char *data, *srcPtr, *destPtr; int i, j; if (image->bits_per_pixel != 1) { - panic("TkAlignImageData: Can't handle image depths greater than 1."); + Tcl_Panic( + "TkAlignImageData: Can't handle image depths greater than 1."); } /* @@ -56,7 +55,7 @@ TkAlignImageData(image, alignment, bitOrder) dataWidth += (alignment - (dataWidth % alignment)); } - data = ckalloc(dataWidth * image->height); + data = ckalloc((unsigned) dataWidth * image->height); destPtr = data; for (i = 0; i < image->height; i++) { @@ -74,3 +73,11 @@ TkAlignImageData(image, alignment, bitOrder) } return data; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkInitScript.h b/generic/tkInitScript.h deleted file mode 100644 index 4997fe7..0000000 --- a/generic/tkInitScript.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * tkInitScript.h -- - * - * This file contains Unix & Windows common init script - * It is not used on the Mac. (the mac init script is in tkMacInit.c) - * - * Copyright (c) 1997 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ - - - -/* - * In order to find tk.tcl during initialization, the following script - * is invoked by Tk_Init(). It looks in several different directories: - * - * $tk_library - can specify a primary location, if set - * no other locations will be checked - * - * $env(TK_LIBRARY) - highest priority so user can always override - * the search path unless the application has - * specified an exact directory above - * - * $tcl_library/../tk$tk_version - * - look relative to init.tcl in an installed - * lib directory (e.g. /usr/local) - * - * <executable directory>/../lib/tk$tk_version - * - look for a lib/tk<ver> in a sibling of - * the bin directory (e.g. /usr/local) - * - * <executable directory>/../library - * - look in Tk build directory - * - * <executable directory>/../../tk$tk_patchLevel/library - * - look for Tk build directory relative - * to a parallel build directory - * - * The first directory on this path that contains a valid tk.tcl script - * will be set ast the value of tk_library. - * - * Note that this entire search mechanism can be bypassed by defining an - * alternate tkInit procedure before calling Tk_Init(). - */ - -static char initScript[] = "if {[info proc tkInit]==\"\"} {\n\ - proc tkInit {} {\n\ - global tk_library tk_version tk_patchLevel\n\ - rename tkInit {}\n\ - tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\ - }\n\ -}\n\ -tkInit"; - diff --git a/generic/tkInt.decls b/generic/tkInt.decls index e1f4ffc..39b121c 100644 --- a/generic/tkInt.decls +++ b/generic/tkInt.decls @@ -5,6 +5,8 @@ # tkIntDecls.h, tkIntPlatDecls.h, tkIntStub.c, and tkPlatStub.c files. # # 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. @@ -223,7 +225,7 @@ declare 57 { void TkpClaimFocus(TkWindow *topLevelPtr, int force) } declare 58 { - void TkpDisplayWarning( const char *msg, const char *title) + void TkpDisplayWarning(const char *msg, const char *title) } declare 59 { void TkpGetAppName(Tcl_Interp *interp, Tcl_DString *name) @@ -254,7 +256,7 @@ declare 67 { void TkpMenuNotifyToplevelCreate(Tcl_Interp *interp, char *menuName) } declare 68 { - TkDisplay *TkpOpenDisplay( const char *display_name) + TkDisplay *TkpOpenDisplay(const char *display_name) } declare 69 { int TkPointerEvent(XEvent *eventPtr, TkWindow *winPtr) @@ -403,38 +405,38 @@ declare 111 { declare 112 { void TkpMenuThreadInit(void) } -declare 113 {mac aqua win} { +declare 113 {aqua win} { void TkClipBox(TkRegion rgn, XRectangle *rect_return) } -declare 114 {mac aqua win} { +declare 114 {aqua win} { TkRegion TkCreateRegion(void) } -declare 115 {mac aqua win} { +declare 115 {aqua win} { void TkDestroyRegion(TkRegion rgn) } -declare 116 {mac aqua win} { +declare 116 {aqua win} { void TkIntersectRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return) } -declare 117 {mac aqua win} { +declare 117 {aqua win} { int TkRectInRegion(TkRegion rgn, int x, int y, unsigned int width, unsigned int height) } -declare 118 {mac aqua win} { +declare 118 {aqua win} { void TkSetRegion(Display *display, GC gc, TkRegion rgn) } -declare 119 {mac aqua win} { +declare 119 {aqua win} { void TkUnionRectWithRegion(XRectangle *rect, TkRegion src, TkRegion dr_return) } -declare 121 {mac aqua} { - Pixmap TkpCreateNativeBitmap(Display *display, const char *source) +declare 121 aqua { + Pixmap TkpCreateNativeBitmap(Display *display, const char *source) } -declare 122 {mac aqua} { +declare 122 aqua { void TkpDefineNativeBitmaps(void) } -declare 124 {mac aqua} { +declare 124 aqua { Pixmap TkpGetNativeAppBitmap(Display *display, - const char *name, int *width, int *height) + const char *name, int *width, int *height) } declare 135 { void TkpDrawHighlightBorder(Tk_Window tkwin, GC fgGC, GC bgGC, @@ -468,7 +470,7 @@ declare 143 { declare 144 { void TkGCCleanup(TkDisplay *dispPtr) } -declare 145 {mac win aqua} { +declare 145 {win aqua} { void TkSubtractRegion(TkRegion sra, TkRegion srcb, TkRegion dr_return) } declare 146 { @@ -485,11 +487,88 @@ declare 149 { const Tk_OptionSpec *TkGetOptionSpec(const char *name, Tk_OptionTable optionTable) } + +# TIP#168 +declare 150 { + int TkMakeRawCurve(Tk_Canvas canvas, double *pointPtr, int numPoints, + int numSteps, XPoint xPoints[], double dblPoints[]) +} +declare 151 { + void TkMakeRawCurvePostscript(Tcl_Interp *interp, + Tk_Canvas canvas, double *pointPtr, int numPoints) +} declare 152 { void TkpDrawFrame(Tk_Window tkwin, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief) } +declare 153 { + void TkCreateThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData) +} +declare 154 { + void TkDeleteThreadExitHandler(Tcl_ExitProc *proc, ClientData clientData) +} +# entries needed only by tktest: +declare 156 { + int TkpTestembedCmd(ClientData clientData, Tcl_Interp *interp, int argc, + const char **argv) +} +declare 157 { + int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp, int argc, + const char **argv) +} + +# Next group of functions exposed due to [Bug 2768945]. Numbers are chosen so +# as to match 8.6 branch/HEAD. +declare 169 { + int TkStateParseProc(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, const char *value, char *widgRec, int offset) +} +declare 170 { + char *TkStatePrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) +} +declare 171 { + int TkCanvasDashParseProc(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, const char *value, char *widgRec, int offset) +} +declare 172 { + char *TkCanvasDashPrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) +} +declare 173 { + int TkOffsetParseProc(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, const char *value, char *widgRec, int offset) +} +declare 174 { + char *TkOffsetPrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) +} +declare 175 { + int TkPixelParseProc(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, const char *value, char *widgRec, int offset) +} +declare 176 { + char *TkPixelPrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) +} +declare 177 { + int TkOrientParseProc(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, const char *value, char *widgRec, int offset) +} +declare 178 { + char *TkOrientPrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) +} +declare 179 { + int TkSmoothParseProc(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, const char *value, char *widgRec, int offset) +} +declare 180 { + char *TkSmoothPrintProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset, Tcl_FreeProc **freeProcPtr) +} + ############################################################################## # Define the platform specific internal Tcl interface. These functions are @@ -539,6 +618,11 @@ declare 11 x11 { declare 12 x11 { int TkpWmSetState(TkWindow *winPtr, int state) } +# only needed by tktest: +declare 13 x11 { + int TkpTestsendCmd(ClientData clientData, Tcl_Interp *interp, int argc, + const char **argv) +} ################################ # Windows specific functions @@ -655,190 +739,17 @@ declare 33 win { declare 34 win { void TkWinSetHINSTANCE(HINSTANCE hInstance) } +declare 35 win { + int TkWinGetPlatformTheme(void) +} -################################ -# Mac specific functions +# Exported through stub table since Tk 8.5.9 -declare 0 mac { - void TkGenerateActivateEvents(TkWindow *winPtr, int active) +declare 36 win { + LRESULT CALLBACK TkWinChildProc(HWND hwnd, + UINT message, WPARAM wParam, LPARAM lParam) } -declare 3 mac { - unsigned long TkpGetMS(void) -} -declare 5 mac { - void TkPointerDeadWindow(TkWindow *winPtr) -} -declare 6 mac { - void TkpSetCapture(TkWindow *winPtr) -} -declare 7 mac { - void TkpSetCursor(TkpCursor cursor) -} -declare 8 mac { - void TkpWmSetState(TkWindow *winPtr, int state) -} -declare 10 mac { - void TkAboutDlg(void) -} -declare 13 mac { - Window TkGetTransientMaster(TkWindow *winPtr) -} -declare 14 mac { - int TkGenerateButtonEvent(int x, int y, - Window window, unsigned int state) -} -declare 16 mac { - void TkGenWMDestroyEvent(Tk_Window tkwin) -} -# removed duplicate from tkPlat table(tk.decls) -#declare 17 mac { -# void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y, -# int width, int height, int flags) -#} -declare 18 mac { - unsigned int TkMacButtonKeyState(void) -} -declare 19 mac { - void TkMacClearMenubarActive(void) -} -# removed duplicate from tkPlat table(tk.decls) -#declare 20 mac { -# int TkMacConvertEvent(EventRecord *eventPtr) -#} -declare 21 mac { - int TkMacDispatchMenuEvent(int menuID, int index) -} -declare 22 mac { - void TkMacInstallCursor(int resizeOverride) -} -# removed duplicate from tkPlat table(tk.decls) -#declare 23 mac { -# int TkMacConvertTkEvent(EventRecord *eventPtr, Window window) -#} -declare 24 mac { - void TkMacHandleTearoffMenu(void) -} -# removed duplicate from tkPlat table(tk.decls) -#declare 26 mac { -# void TkMacInvalClipRgns(TkWindow *winPtr) -#} -declare 27 mac { - void TkMacDoHLEvent(EventRecord *theEvent) -} -declare 29 mac { - Time TkMacGenerateTime(void) -} -# removed duplicate from tkPlat table(tk.decls) -#declare 30 mac { -# GWorldPtr TkMacGetDrawablePort(Drawable drawable) -#} -declare 31 mac { - TkWindow *TkMacGetScrollbarGrowWindow(TkWindow *winPtr) -} -declare 32 mac { - Window TkMacGetXWindow(WindowRef macWinPtr) -} -declare 33 mac { - int TkMacGrowToplevel(WindowRef whichWindow, Point start) -} -declare 34 mac { - void TkMacHandleMenuSelect(long mResult, int optionKeyPressed) -} -# removed duplicates from tkPlat table(tk.decls) -#declare 35 mac { -# int TkMacHaveAppearance(void) -#} -# -#declare 36 mac { -# void TkMacInitAppleEvents(Tcl_Interp *interp) -#} -# -#declare 37 mac { -# void TkMacInitMenus(Tcl_Interp *interp) -#} -declare 38 mac { - void TkMacInvalidateWindow(MacDrawable *macWin, int flag) -} -declare 39 mac { - int TkMacIsCharacterMissing(Tk_Font tkfont, unsigned int searchChar) -} -declare 40 mac { - void TkMacMakeRealWindowExist(TkWindow *winPtr) -} -declare 41 mac { - BitMapPtr TkMacMakeStippleMap(Drawable d1, Drawable d2) -} -declare 42 mac { - void TkMacMenuClick(void) -} -declare 43 mac { - void TkMacRegisterOffScreenWindow(Window window, GWorldPtr portPtr) -} -declare 44 mac { - int TkMacResizable(TkWindow *winPtr) -} -declare 46 mac { - void TkMacSetHelpMenuItemCount(void) -} -declare 47 mac { - void TkMacSetScrollbarGrow(TkWindow *winPtr, int flag) -} -declare 48 mac { - void TkMacSetUpClippingRgn(Drawable drawable) -} -declare 49 mac { - void TkMacSetUpGraphicsPort(GC gc) -} -declare 50 mac { - void TkMacUpdateClipRgn(TkWindow *winPtr) -} -declare 51 mac { - void TkMacUnregisterMacWindow(GWorldPtr portPtr) -} -declare 52 mac { - int TkMacUseMenuID(short macID) -} -declare 53 mac { - RgnHandle TkMacVisableClipRgn(TkWindow *winPtr) -} -declare 54 mac { - void TkMacWinBounds(TkWindow *winPtr, Rect *geometry) -} -declare 55 mac { - void TkMacWindowOffset(WindowRef wRef, int *xOffset, int *yOffset) -} -declare 57 mac { - int TkSetMacColor(unsigned long pixel, RGBColor *macColor) -} -declare 58 mac { - void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid) -} -declare 59 mac { - void TkSuspendClipboard(void) -} -declare 61 mac { - int TkMacZoomToplevel(WindowPtr whichWindow, Point where, short zoomPart) -} -declare 62 mac { - Tk_Window Tk_TopCoordsToWindow(Tk_Window tkwin, - int rootX, int rootY, int *newX, int *newY) -} -declare 63 mac { - MacDrawable *TkMacContainerId(TkWindow *winPtr) -} -declare 64 mac { - MacDrawable *TkMacGetHostToplevel(TkWindow *winPtr) -} -declare 65 mac { - void TkMacPreprocessMenu(void) -} -declare 66 mac { - int TkpIsWindowFloating(WindowRef window) -} -declare 35 win { - int TkWinGetPlatformTheme(void) -} ################################ # Aqua specific functions @@ -1403,322 +1314,322 @@ declare 105 win { } ################################ -# X functions for Mac and Aqua +# X functions for Aqua -declare 0 {mac aqua} { +declare 0 aqua { void XSetDashes(Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n) } -declare 1 {mac aqua} { +declare 1 aqua { XModifierKeymap *XGetModifierMapping(Display *d) } -declare 2 {mac aqua} { +declare 2 aqua { XImage *XCreateImage(Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4) } -declare 3 {mac aqua} { +declare 3 aqua { XImage *XGetImage(Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3) } -declare 4 {mac aqua} { +declare 4 aqua { char *XGetAtomName(Display *d, Atom a) } -declare 5 {mac aqua} { +declare 5 aqua { char *XKeysymToString(KeySym k) } -declare 6 {mac aqua} { +declare 6 aqua { Colormap XCreateColormap(Display *d, Window w, Visual *v, int i) } -declare 7 {mac aqua} { +declare 7 aqua { GContext XGContextFromGC(GC g) } -declare 8 {mac aqua} { +declare 8 aqua { KeySym XKeycodeToKeysym(Display *d, KeyCode k, int i) } -declare 9 {mac aqua} { +declare 9 aqua { KeySym XStringToKeysym(_Xconst char *c) } -declare 10 {mac aqua} { +declare 10 aqua { Window XRootWindow(Display *d, int i) } -declare 11 {mac aqua} { +declare 11 aqua { XErrorHandler XSetErrorHandler(XErrorHandler x) } -declare 12 {mac aqua} { +declare 12 aqua { Status XAllocColor(Display *d, Colormap c, XColor *xp) } -declare 13 {mac aqua} { +declare 13 aqua { void XBell(Display *d, int i) } -declare 14 {mac aqua} { +declare 14 aqua { void XChangeProperty(Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3) } -declare 15 {mac aqua} { +declare 15 aqua { void XChangeWindowAttributes(Display *d, Window w, unsigned long ul, XSetWindowAttributes *x) } -declare 16 {mac aqua} { +declare 16 aqua { void XConfigureWindow(Display *d, Window w, unsigned int i, XWindowChanges *x) } -declare 17 {mac aqua} { +declare 17 aqua { void XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4) } -declare 18 {mac aqua} { +declare 18 aqua { void XCopyPlane(Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul) } -declare 19 {mac aqua} { +declare 19 aqua { Pixmap XCreateBitmapFromData(Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height) } -declare 20 {mac aqua} { +declare 20 aqua { void XDefineCursor(Display *d, Window w, Cursor c) } -declare 21 {mac aqua} { +declare 21 aqua { void XDestroyWindow(Display *d, Window w) } -declare 22 {mac aqua} { +declare 22 aqua { void XDrawArc(Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4) } -declare 23 {mac aqua} { +declare 23 aqua { void XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2) } -declare 24 {mac aqua} { +declare 24 aqua { void XDrawRectangle(Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2) } -declare 25 {mac aqua} { +declare 25 aqua { void XFillArc(Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4) } -declare 26 {mac aqua} { +declare 26 aqua { void XFillPolygon(Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3) } -declare 27 {mac aqua} { +declare 27 aqua { void XFillRectangles(Display *d, Drawable dr, GC g, XRectangle *x, int i) } -declare 28 {mac aqua} { +declare 28 aqua { void XFreeColormap(Display *d, Colormap c) } -declare 29 {mac aqua} { +declare 29 aqua { void XFreeColors(Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul) } -declare 30 {mac aqua} { +declare 30 aqua { void XFreeModifiermap(XModifierKeymap *x) } -declare 31 {mac aqua} { +declare 31 aqua { Status XGetGeometry(Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4) } -declare 32 {mac aqua} { +declare 32 aqua { int XGetWindowProperty(Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp) } -declare 33 {mac aqua} { +declare 33 aqua { int XGrabKeyboard(Display *d, Window w, Bool b, int i1, int i2, Time t) } -declare 34 {mac aqua} { +declare 34 aqua { int XGrabPointer(Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t) } -declare 35 {mac aqua} { +declare 35 aqua { KeyCode XKeysymToKeycode(Display *d, KeySym k) } -declare 36 {mac aqua} { +declare 36 aqua { void XMapWindow(Display *d, Window w) } -declare 37 {mac aqua} { +declare 37 aqua { void XMoveResizeWindow(Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2) } -declare 38 {mac aqua} { +declare 38 aqua { void XMoveWindow(Display *d, Window w, int i1, int i2) } -declare 39 {mac aqua} { +declare 39 aqua { Bool XQueryPointer(Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui) } -declare 40 {mac aqua} { +declare 40 aqua { void XRaiseWindow(Display *d, Window w) } -declare 41 {mac aqua} { +declare 41 aqua { void XRefreshKeyboardMapping(XMappingEvent *x) } -declare 42 {mac aqua} { +declare 42 aqua { void XResizeWindow(Display *d, Window w, unsigned int ui1, unsigned int ui2) } -declare 43 {mac aqua} { +declare 43 aqua { void XSelectInput(Display *d, Window w, long l) } -declare 44 {mac aqua} { +declare 44 aqua { Status XSendEvent(Display *d, Window w, Bool b, long l, XEvent *x) } -declare 45 {mac aqua} { +declare 45 aqua { void XSetIconName(Display *d, Window w, _Xconst char *c) } -declare 46 {mac aqua} { +declare 46 aqua { void XSetInputFocus(Display *d, Window w, int i, Time t) } -declare 47 {mac aqua} { +declare 47 aqua { void XSetSelectionOwner(Display *d, Atom a, Window w, Time t) } -declare 48 {mac aqua} { +declare 48 aqua { void XSetWindowBackground(Display *d, Window w, unsigned long ul) } -declare 49 {mac aqua} { +declare 49 aqua { void XSetWindowBackgroundPixmap(Display *d, Window w, Pixmap p) } -declare 50 {mac aqua} { +declare 50 aqua { void XSetWindowBorder(Display *d, Window w, unsigned long ul) } -declare 51 {mac aqua} { +declare 51 aqua { void XSetWindowBorderPixmap(Display *d, Window w, Pixmap p) } -declare 52 {mac aqua} { +declare 52 aqua { void XSetWindowBorderWidth(Display *d, Window w, unsigned int ui) } -declare 53 {mac aqua} { +declare 53 aqua { void XSetWindowColormap(Display *d, Window w, Colormap c) } -declare 54 {mac aqua} { +declare 54 aqua { void XUngrabKeyboard(Display *d, Time t) } -declare 55 {mac aqua} { +declare 55 aqua { void XUngrabPointer(Display *d, Time t) } -declare 56 {mac aqua} { +declare 56 aqua { void XUnmapWindow(Display *d, Window w) } -declare 57 {mac aqua} { +declare 57 aqua { void TkPutImage(unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height) } -declare 58 {mac aqua} { +declare 58 aqua { Status XParseColor(Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr) } -declare 59 {mac aqua} { +declare 59 aqua { GC XCreateGC(Display *display, Drawable d, unsigned long valuemask, XGCValues *values) } -declare 60 {mac aqua} { +declare 60 aqua { void XFreeGC(Display *display, GC gc) } -declare 61 {mac aqua} { +declare 61 aqua { Atom XInternAtom(Display *display, _Xconst char *atom_name, Bool only_if_exists) } -declare 62 {mac aqua} { +declare 62 aqua { void XSetBackground(Display *display, GC gc, unsigned long foreground) } -declare 63 {mac aqua} { +declare 63 aqua { void XSetForeground(Display *display, GC gc, unsigned long foreground) } -declare 64 {mac aqua} { +declare 64 aqua { void XSetClipMask(Display *display, GC gc, Pixmap pixmap) } -declare 65 {mac aqua} { +declare 65 aqua { void XSetClipOrigin(Display *display, GC gc, int clip_x_origin, int clip_y_origin) } -declare 66 {mac aqua} { +declare 66 aqua { void XSetTSOrigin(Display *display, GC gc, int ts_x_origin, int ts_y_origin) } -declare 67 {mac aqua} { +declare 67 aqua { void XChangeGC(Display *d, GC gc, unsigned long mask, XGCValues *values) } -declare 68 {mac aqua} { +declare 68 aqua { void XSetFont(Display *display, GC gc, Font font) } -declare 69 {mac aqua} { +declare 69 aqua { void XSetArcMode(Display *display, GC gc, int arc_mode) } -declare 70 {mac aqua} { +declare 70 aqua { void XSetStipple(Display *display, GC gc, Pixmap stipple) } -declare 71 {mac aqua} { +declare 71 aqua { void XSetFillRule(Display *display, GC gc, int fill_rule) } -declare 72 {mac aqua} { +declare 72 aqua { void XSetFillStyle(Display *display, GC gc, int fill_style) } -declare 73 {mac aqua} { +declare 73 aqua { void XSetFunction(Display *display, GC gc, int function) } -declare 74 {mac aqua} { +declare 74 aqua { void XSetLineAttributes(Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style) } -declare 75 {mac aqua} { +declare 75 aqua { int _XInitImageFuncPtrs(XImage *image) } -declare 76 {mac aqua} { +declare 76 aqua { XIC XCreateIC(void) } -declare 77 {mac aqua} { +declare 77 aqua { XVisualInfo *XGetVisualInfo(Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return) } -declare 78 {mac aqua} { +declare 78 aqua { void XSetWMClientMachine(Display *display, Window w, XTextProperty *text_prop) } -declare 79 {mac aqua} { +declare 79 aqua { Status XStringListToTextProperty(char **list, int count, XTextProperty *text_prop_return) } -declare 80 {mac aqua} { +declare 80 aqua { void XDrawSegments(Display *display, Drawable d, GC gc, XSegment *segments, int nsegments) } -declare 81 {mac aqua} { +declare 81 aqua { void XForceScreenSaver(Display *display, int mode) } -declare 82 {mac aqua} { +declare 82 aqua { void XDrawLine(Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2) } -declare 83 {mac aqua} { +declare 83 aqua { void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height) } -declare 84 {mac aqua} { +declare 84 aqua { void XClearWindow(Display *d, Window w) } -declare 85 {mac aqua} { +declare 85 aqua { void XDrawPoint(Display *display, Drawable d, GC gc, int x, int y) } -declare 86 {mac aqua} { +declare 86 aqua { void XDrawPoints(Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode) } -declare 87 {mac aqua} { +declare 87 aqua { void 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) } -declare 88 {mac aqua} { +declare 88 aqua { void XQueryColor(Display *display, Colormap colormap, XColor *def_in_out) } -declare 89 {mac aqua} { +declare 89 aqua { void XQueryColors(Display *display, Colormap colormap, XColor *defs_in_out, int ncolors) } -declare 90 {mac aqua} { +declare 90 aqua { Status XQueryTree(Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui) } diff --git a/generic/tkInt.h b/generic/tkInt.h index a6e09ee..b152a7a 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1,15 +1,15 @@ /* * tkInt.h -- * - * Declarations for things used internally by the Tk - * procedures but not exported outside the module. + * Declarations for things used internally by the Tk functions but not + * exported outside the module. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKINT @@ -41,7 +41,7 @@ # ifdef BIG_ENDIAN # if BYTE_ORDER == BIG_ENDIAN # undef WORDS_BIGENDIAN -# define WORDS_BIGENDIAN +# define WORDS_BIGENDIAN 1 # endif # endif # ifdef LITTLE_ENDIAN @@ -65,10 +65,36 @@ #endif /* + * Macros used to cast between pointers and integers (e.g. when storing an int + * in ClientData), on 64-bit architectures they avoid gcc warning about "cast + * to/from pointer from/to integer of different size". + */ + +#if !defined(INT2PTR) && !defined(PTR2INT) +# if defined(HAVE_INTPTR_T) || defined(intptr_t) +# define INT2PTR(p) ((void*)(intptr_t)(p)) +# define PTR2INT(p) ((int)(intptr_t)(p)) +# else +# define INT2PTR(p) ((void*)(p)) +# define PTR2INT(p) ((int)(p)) +# endif +#endif +#if !defined(UINT2PTR) && !defined(PTR2UINT) +# if defined(HAVE_UINTPTR_T) || defined(uintptr_t) +# define UINT2PTR(p) ((void*)(uintptr_t)(p)) +# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) +# else +# define UINT2PTR(p) ((void*)(p)) +# define PTR2UINT(p) ((unsigned int)(p)) +# endif +#endif + +/* * Opaque type declarations: */ typedef struct TkColormap TkColormap; +typedef struct TkFontAttributes TkFontAttributes; typedef struct TkGrabEvent TkGrabEvent; typedef struct TkpCursor_ *TkpCursor; typedef struct TkRegion_ *TkRegion; @@ -76,18 +102,17 @@ typedef struct TkStressedCmap TkStressedCmap; typedef struct TkBindInfo_ *TkBindInfo; /* - * Procedure types. + * Function types. */ -typedef int (TkBindEvalProc) _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, XEvent *eventPtr, Tk_Window tkwin, - KeySym keySym)); -typedef void (TkBindFreeProc) _ANSI_ARGS_((ClientData clientData)); +typedef int (TkBindEvalProc)(ClientData clientData, Tcl_Interp *interp, + XEvent *eventPtr, Tk_Window tkwin, KeySym keySym); +typedef void (TkBindFreeProc)(ClientData clientData); /* - * One of the following structures is maintained for each cursor in - * use in the system. This structure is used by tkCursor.c and the - * various system specific cursor files. + * One of the following structures is maintained for each cursor in use in the + * system. This structure is used by tkCursor.c and the various system + * specific cursor files. */ typedef struct TkCursor { @@ -96,65 +121,53 @@ typedef struct TkCursor { * disposal and retrieval of cursors. */ int resourceRefCount; /* Number of active uses of this cursor (each * active use corresponds to a call to - * Tk_AllocPreserveFromObj or Tk_Preserve). - * If this count is 0, then this structure - * is no longer valid and it isn't present - * in a hash table: it is being kept around - * only because there are objects referring - * to it. The structure is freed when - * resourceRefCount and objRefCount are - * both 0. */ - int objRefCount; /* Number of Tcl objects that reference - * this structure.. */ - Tcl_HashTable *otherTable; /* Second table (other than idTable) used - * to index this entry. */ + * Tk_AllocPreserveFromObj or Tk_Preserve). If + * this count is 0, then this structure is no + * longer valid and it isn't present in a hash + * table: it is being kept around only because + * there are objects referring to it. The + * structure is freed when resourceRefCount + * and objRefCount are both 0. */ + int objRefCount; /* Number of Tcl objects that reference this + * structure.. */ + Tcl_HashTable *otherTable; /* Second table (other than idTable) used to + * index this entry. */ Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure * (needed when deleting). */ - Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure - * (needed when deleting). */ + Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure (needed + * when deleting). */ struct TkCursor *nextPtr; /* Points to the next TkCursor structure with - * the same name. Cursors with the same - * name but different displays are chained - * together off a single hash table entry. */ + * the same name. Cursors with the same name + * but different displays are chained together + * off a single hash table entry. */ } TkCursor; /* - * This defines whether we should try to use XIM over-the-spot style - * input. Allow users to override it. It is a much more elegant use - * of XIM, but uses a bit more memory. - */ - -#ifndef TK_XIM_SPOT -# define TK_XIM_SPOT 1 -#endif - -/* * The following structure is kept one-per-TkDisplay to maintain information - * about the caret (cursor location) on this display. This is used to - * dictate global focus location (Windows Accessibility guidelines) and to - * position the IME or XIM over-the-spot window. + * about the caret (cursor location) on this display. This is used to dictate + * global focus location (Windows Accessibility guidelines) and to position + * the IME or XIM over-the-spot window. */ typedef struct TkCaret { - struct TkWindow *winPtr; /* the window on which we requested caret - * placement */ - int x; /* relative x coord of the caret */ - int y; /* relative y coord of the caret */ - int height; /* specified height of the window */ + struct TkWindow *winPtr; /* The window on which we requested caret + * placement. */ + int x; /* Relative x coord of the caret. */ + int y; /* Relative y coord of the caret. */ + int height; /* Specified height of the window. */ } TkCaret; /* - * One of the following structures is maintained for each display - * containing a window managed by Tk. In part, the structure is - * used to store thread-specific data, since each thread will have - * its own TkDisplay structure. + * One of the following structures is maintained for each display containing a + * window managed by Tk. In part, the structure is used to store thread- + * specific data, since each thread will have its own TkDisplay structure. */ typedef struct TkDisplay { Display *display; /* Xlib's info about display. */ struct TkDisplay *nextPtr; /* Next in list of all displays. */ - char *name; /* Name of display (with any screen - * identifier removed). Malloc-ed. */ + char *name; /* Name of display (with any screen identifier + * removed). Malloc-ed. */ Time lastEventTime; /* Time of last event received for this * display. */ @@ -162,16 +175,16 @@ typedef struct TkDisplay { * Information used primarily by tk3d.c: */ - int borderInit; /* 0 means borderTable needs initializing. */ - Tcl_HashTable borderTable; /* Maps from color name to TkBorder + int borderInit; /* 0 means borderTable needs initializing. */ + Tcl_HashTable borderTable; /* Maps from color name to TkBorder * structure. */ /* * Information used by tkAtom.c only: */ - int atomInit; /* 0 means stuff below hasn't been - * initialized yet. */ + int atomInit; /* 0 means stuff below hasn't been initialized + * yet. */ Tcl_HashTable nameTable; /* Maps from names to Atom's. */ Tcl_HashTable atomTable; /* Maps from Atom's back to names. */ @@ -179,139 +192,137 @@ typedef struct TkDisplay { * Information used primarily by tkBind.c: */ - int bindInfoStale; /* Non-zero means the variables in this - * part of the structure are potentially - * incorrect and should be recomputed. */ + int bindInfoStale; /* Non-zero means the variables in this part + * of the structure are potentially incorrect + * and should be recomputed. */ unsigned int modeModMask; /* Has one bit set to indicate the modifier - * corresponding to "mode shift". If no - * such modifier, than this is zero. */ + * corresponding to "mode shift". If no such + * modifier, than this is zero. */ unsigned int metaModMask; /* Has one bit set to indicate the modifier - * corresponding to the "Meta" key. If no - * such modifier, then this is zero. */ + * corresponding to the "Meta" key. If no such + * modifier, then this is zero. */ unsigned int altModMask; /* Has one bit set to indicate the modifier - * corresponding to the "Meta" key. If no - * such modifier, then this is zero. */ + * corresponding to the "Meta" key. If no such + * modifier, then this is zero. */ enum {LU_IGNORE, LU_CAPS, LU_SHIFT} lockUsage; - /* Indicates how to interpret lock modifier. */ + /* Indicates how to interpret lock + * modifier. */ int numModKeyCodes; /* Number of entries in modKeyCodes array * below. */ - KeyCode *modKeyCodes; /* Pointer to an array giving keycodes for - * all of the keys that have modifiers - * associated with them. Malloc'ed, but - * may be NULL. */ + KeyCode *modKeyCodes; /* Pointer to an array giving keycodes for all + * of the keys that have modifiers associated + * with them. Malloc'ed, but may be NULL. */ /* * Information used by tkBitmap.c only: */ - - int bitmapInit; /* 0 means tables above need initializing. */ - int bitmapAutoNumber; /* Used to number bitmaps. */ - Tcl_HashTable bitmapNameTable; - /* Maps from name of bitmap to the first + + int bitmapInit; /* 0 means tables above need initializing. */ + int bitmapAutoNumber; /* Used to number bitmaps. */ + Tcl_HashTable bitmapNameTable; + /* Maps from name of bitmap to the first * TkBitmap record for that name. */ Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap * structure for the bitmap. */ - Tcl_HashTable bitmapDataTable; - /* Used by Tk_GetBitmapFromData to map from - * a collection of in-core data about a - * bitmap to a reference giving an auto- - * matically-generated name for the bitmap. */ + Tcl_HashTable bitmapDataTable; + /* Used by Tk_GetBitmapFromData to map from a + * collection of in-core data about a bitmap + * to a reference giving an automatically- + * generated name for the bitmap. */ /* * Information used by tkCanvas.c only: */ - int numIdSearches; + int numIdSearches; int numSlowSearches; /* * Used by tkColor.c only: */ - int colorInit; /* 0 means color module needs initializing. */ - TkStressedCmap *stressPtr; /* First in list of colormaps that have - * filled up, so we have to pick an - * approximate color. */ + int colorInit; /* 0 means color module needs initializing. */ + TkStressedCmap *stressPtr; /* First in list of colormaps that have filled + * up, so we have to pick an approximate + * color. */ Tcl_HashTable colorNameTable; - /* Maps from color name to TkColor structure + /* Maps from color name to TkColor structure * for that color. */ Tcl_HashTable colorValueTable; - /* Maps from integer RGB values to TkColor + /* Maps from integer RGB values to TkColor * structures. */ /* * Used by tkCursor.c only: */ - int cursorInit; /* 0 means cursor module need initializing. */ + int cursorInit; /* 0 means cursor module need initializing. */ Tcl_HashTable cursorNameTable; - /* Maps from a string name to a cursor to the + /* Maps from a string name to a cursor to the * TkCursor record for the cursor. */ Tcl_HashTable cursorDataTable; - /* Maps from a collection of in-core data + /* Maps from a collection of in-core data * about a cursor to a TkCursor structure. */ Tcl_HashTable cursorIdTable; - /* Maps from a cursor id to the TkCursor + /* Maps from a cursor id to the TkCursor * structure for the cursor. */ - char cursorString[20]; /* Used to store a cursor id string. */ - Font cursorFont; /* Font to use for standard cursors. - * None means font not loaded yet. */ + char cursorString[20]; /* Used to store a cursor id string. */ + Font cursorFont; /* Font to use for standard cursors. None + * means font not loaded yet. */ /* * Information used by tkError.c only: */ struct TkErrorHandler *errorPtr; - /* First in list of error handlers - * for this display. NULL means - * no handlers exist at present. */ - int deleteCount; /* Counts # of handlers deleted since - * last time inactive handlers were - * garbage-collected. When this number - * gets big, handlers get cleaned up. */ + /* First in list of error handlers for this + * display. NULL means no handlers exist at + * present. */ + int deleteCount; /* Counts # of handlers deleted since last + * time inactive handlers were garbage- + * collected. When this number gets big, + * handlers get cleaned up. */ /* * Used by tkEvent.c only: */ struct TkWindowEvent *delayedMotionPtr; - /* Points to a malloc-ed motion event - * whose processing has been delayed in - * the hopes that another motion event - * will come along right away and we can - * merge the two of them together. NULL - * means that there is no delayed motion - * event. */ + /* Points to a malloc-ed motion event whose + * processing has been delayed in the hopes + * that another motion event will come along + * right away and we can merge the two of them + * together. NULL means that there is no + * delayed motion event. */ /* * Information used by tkFocus.c only: */ - int focusDebug; /* 1 means collect focus debugging + int focusDebug; /* 1 means collect focus debugging * statistics. */ struct TkWindow *implicitWinPtr; /* If the focus arrived at a toplevel window - * implicitly via an Enter event (rather - * than via a FocusIn event), this points - * to the toplevel window. Otherwise it is - * NULL. */ + * implicitly via an Enter event (rather than + * via a FocusIn event), this points to the + * toplevel window. Otherwise it is NULL. */ struct TkWindow *focusPtr; /* Points to the window on this display that - * should be receiving keyboard events. When + * should be receiving keyboard events. When * multiple applications on the display have - * the focus, this will refer to the - * innermost window in the innermost - * application. This information isn't used - * under Unix or Windows, but it's needed on - * the Macintosh. */ + * the focus, this will refer to the innermost + * window in the innermost application. This + * information isn't used on Windows, but it's + * needed on the Mac, and also on X11 when XIM + * processing is being done. */ /* * Information used by tkGC.c only: */ - + Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure * describing a GC with those values. */ - Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */ - int gcInit; /* 0 means the tables below need + Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */ + int gcInit; /* 0 means the tables below need * initializing. */ /* @@ -319,24 +330,23 @@ typedef struct TkDisplay { */ Tcl_HashTable maintainHashTable; - /* Hash table that maps from a master's - * Tk_Window token to a list of slaves - * managed by that master. */ - int geomInit; + /* Hash table that maps from a master's + * Tk_Window token to a list of slaves managed + * by that master. */ + int geomInit; /* * Information used by tkGet.c only: */ - - Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */ - int uidInit; /* 0 means uidTable needs initializing. */ + + Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */ + int uidInit; /* 0 means uidTable needs initializing. */ /* * Information used by tkGrab.c only: */ - struct TkWindow *grabWinPtr; - /* Window in which the pointer is currently + struct TkWindow *grabWinPtr;/* Window in which the pointer is currently * grabbed, or NULL if none. */ struct TkWindow *eventualGrabWinPtr; /* Value that grabWinPtr will have once the @@ -348,68 +358,65 @@ typedef struct TkDisplay { * if no such press in effect. */ struct TkWindow *serverWinPtr; /* If no application contains the pointer then - * this is NULL. Otherwise it contains the - * last window for which we've gotten an - * Enter or Leave event from the server (i.e. - * the last window known to have contained - * the pointer). Doesn't reflect events - * that were synthesized in tkGrab.c. */ + * this is NULL. Otherwise it contains the + * last window for which we've gotten an Enter + * or Leave event from the server (i.e. the + * last window known to have contained the + * pointer). Doesn't reflect events that were + * synthesized in tkGrab.c. */ TkGrabEvent *firstGrabEventPtr; /* First in list of enter/leave events - * synthesized by grab code. These events - * must be processed in order before any other - * events are processed. NULL means no such + * synthesized by grab code. These events must + * be processed in order before any other + * events are processed. NULL means no such * events. */ TkGrabEvent *lastGrabEventPtr; /* Last in list of synthesized events, or NULL * if list is empty. */ - int grabFlags; /* Miscellaneous flag values. See definitions + int grabFlags; /* Miscellaneous flag values. See definitions * in tkGrab.c. */ /* * Information used by tkGrid.c only: */ - int gridInit; /* 0 means table below needs initializing. */ - Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to - * corresponding Grid structures. */ + int gridInit; /* 0 means table below needs initializing. */ + Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to corresponding + * Grid structures. */ /* * Information used by tkImage.c only: */ - int imageId; /* Value used to number image ids. */ + int imageId; /* Value used to number image ids. */ /* * Information used by tkMacWinMenu.c only: */ - int postCommandGeneration; + int postCommandGeneration; /* * Information used by tkOption.c only. */ - - /* * Information used by tkPack.c only. */ - int packInit; /* 0 means table below needs initializing. */ + int packInit; /* 0 means table below needs initializing. */ Tcl_HashTable packerHashTable; - /* Maps from Tk_Window tokens to - * corresponding Packer structures. */ - + /* Maps from Tk_Window tokens to corresponding + * Packer structures. */ /* * Information used by tkPlace.c only. */ - int placeInit; /* 0 means tables below need initializing. */ - Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master + int placeInit; /* 0 means tables below need initializing. */ + Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master * structure for the window, if it exists. */ - Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave + Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave * structure for the window, if it exists. */ /* @@ -418,11 +425,11 @@ typedef struct TkDisplay { struct TkSelectionInfo *selectionInfoPtr; /* First in list of selection information - * records. Each entry contains information + * records. Each entry contains information * about the current owner of a particular * selection on this display. */ - Atom multipleAtom; /* Atom for MULTIPLE. None means - * selection stuff isn't initialized. */ + Atom multipleAtom; /* Atom for MULTIPLE. None means selection + * stuff isn't initialized. */ Atom incrAtom; /* Atom for INCR. */ Atom targetsAtom; /* Atom for TARGETS. */ Atom timestampAtom; /* Atom for TIMESTAMP. */ @@ -443,7 +450,7 @@ typedef struct TkDisplay { /* Last application that owned clipboard. */ struct TkClipboardTarget *clipTargetPtr; /* First in list of clipboard type information - * records. Each entry contains information + * records. Each entry contains information * about the buffers for a given selection * target. */ @@ -451,13 +458,13 @@ typedef struct TkDisplay { * Information used by tkSend.c only: */ - Tk_Window commTkwin; /* Window used for communication - * between interpreters during "send" - * commands. NULL means send info hasn't - * been initialized yet. */ + Tk_Window commTkwin; /* Window used for communication between + * interpreters during "send" commands. NULL + * means send info hasn't been initialized + * yet. */ Atom commProperty; /* X's name for comm property. */ - Atom registryProperty; /* X's name for property containing - * registry of interpreter names. */ + Atom registryProperty; /* X's name for property containing registry + * of interpreter names. */ Atom appNameProperty; /* X's name for property used to hold the * application name on each comm window. */ @@ -469,12 +476,11 @@ typedef struct TkDisplay { /* First in list of chunks of free resource * identifiers, or NULL if there are no free * resources. */ - XID (*defaultAllocProc) _ANSI_ARGS_((Display *display)); + XID (*defaultAllocProc) (Display *display); /* Default resource allocator for display. */ struct TkIdStack *windowStackPtr; - /* First in list of chunks of window - * identifers that can't be reused right - * now. */ + /* First in list of chunks of window ids that + * can't be reused right now. */ Tcl_TimerToken idCleanupScheduled; /* If set, it means a call to WindowIdCleanup * has already been scheduled, 0 means it @@ -484,17 +490,16 @@ typedef struct TkDisplay { * Information used by tkUnixWm.c and tkWinWm.c only: */ - struct TkWmInfo *firstWmPtr; /* Points to first top-level window. */ - struct TkWmInfo *foregroundWmPtr; - /* Points to the foreground window. */ + struct TkWmInfo *firstWmPtr;/* Points to first top-level window. */ + struct TkWmInfo *foregroundWmPtr; + /* Points to the foreground window. */ /* * Information maintained by tkWindow.c for use later on by tkXId.c: */ - - int destroyCount; /* Number of Tk_DestroyWindow operations - * in progress. */ + int destroyCount; /* Number of Tk_DestroyWindow operations in + * progress. */ unsigned long lastDestroyRequest; /* Id of most recent XDestroyWindow request; * can re-use ids in windowStackPtr when @@ -513,25 +518,25 @@ typedef struct TkDisplay { */ #ifdef TK_USE_INPUT_METHODS - XIM inputMethod; /* Input method for this display */ -#if TK_XIM_SPOT + XIM inputMethod; /* Input method for this display. */ + XIMStyle inputStyle; /* Input style selected for this display. */ XFontSet inputXfs; /* XFontSet cached for over-the-spot XIM. */ -#endif #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 - * are using this display. Used to clean up - * the display when we no longer have any - * Tk applications using it. - */ + * are using this display. Used to clean up + * the display when we no longer have any Tk + * applications using it. */ + /* * The following field were all added for Tk8.3 */ - int mouseButtonState; /* current mouse button state for this - * display */ - Window mouseButtonWindow; /* Window the button state was set in, - * added in Tk 8.4. */ + + int mouseButtonState; /* Current mouse button state for this + * display. */ + Window mouseButtonWindow; /* Window the button state was set in, added + * in Tk 8.4. */ Window warpWindow; int warpX; int warpY; @@ -539,13 +544,14 @@ typedef struct TkDisplay { /* * The following field(s) were all added for Tk8.4 */ - unsigned int flags; /* Various flag values: these are all - * defined in below. */ - TkCaret caret; /* information about the caret for this - * display. This is not a pointer. */ - int iconDataSize; /* size of default iconphoto image data */ - unsigned char *iconDataPtr; /* default iconphoto image data, if set */ + unsigned int flags; /* Various flag values: these are all defined + * in below. */ + TkCaret caret; /* Information about the caret for this + * display. This is not a pointer. */ + + int iconDataSize; /* Size of default iconphoto image data. */ + unsigned char *iconDataPtr; /* Default iconphoto image data, if set. */ } TkDisplay; /* @@ -554,8 +560,6 @@ typedef struct TkDisplay { * Indicates that we should collapse motion events on this display * TK_DISPLAY_USE_IM: (default on, set via tk.tcl) * Whether to use input methods for this display - * TK_DISPLAY_XIM_SPOT: (default off) - * Indicates that we should use over-the-spot XIM on this display * TK_DISPLAY_WM_TRACING: (default off) * Whether we should do wm tracing on this display. * TK_DISPLAY_IN_WARP: (default off) @@ -564,88 +568,75 @@ typedef struct TkDisplay { #define TK_DISPLAY_COLLAPSE_MOTION_EVENTS (1 << 0) #define TK_DISPLAY_USE_IM (1 << 1) -#define TK_DISPLAY_XIM_SPOT (1 << 2) #define TK_DISPLAY_WM_TRACING (1 << 3) #define TK_DISPLAY_IN_WARP (1 << 4) /* - * One of the following structures exists for each error handler - * created by a call to Tk_CreateErrorHandler. The structure - * is managed by tkError.c. + * One of the following structures exists for each error handler created by a + * call to Tk_CreateErrorHandler. The structure is managed by tkError.c. */ typedef struct TkErrorHandler { TkDisplay *dispPtr; /* Display to which handler applies. */ - unsigned long firstRequest; /* Only errors with serial numbers - * >= to this are considered. */ - unsigned long lastRequest; /* Only errors with serial numbers - * <= to this are considered. This - * field is filled in when XUnhandle - * is called. -1 means XUnhandle - * hasn't been called yet. */ - int error; /* Consider only errors with this - * error_code (-1 means consider - * all errors). */ - int request; /* Consider only errors with this - * major request code (-1 means - * consider all major codes). */ - int minorCode; /* Consider only errors with this - * minor request code (-1 means - * consider all minor codes). */ - Tk_ErrorProc *errorProc; /* Procedure to invoke when a matching - * error occurs. NULL means just ignore - * errors. */ - ClientData clientData; /* Arbitrary value to pass to - * errorProc. */ + unsigned long firstRequest; /* Only errors with serial numbers >= to this + * are considered. */ + unsigned long lastRequest; /* Only errors with serial numbers <= to this + * are considered. This field is filled in + * when XUnhandle is called. -1 means + * XUnhandle hasn't been called yet. */ + int error; /* Consider only errors with this error_code + * (-1 means consider all errors). */ + int request; /* Consider only errors with this major + * request code (-1 means consider all major + * codes). */ + int minorCode; /* Consider only errors with this minor + * request code (-1 means consider all minor + * codes). */ + Tk_ErrorProc *errorProc; /* Function to invoke when a matching error + * occurs. NULL means just ignore errors. */ + ClientData clientData; /* Arbitrary value to pass to errorProc. */ struct TkErrorHandler *nextPtr; - /* Pointer to next older handler for - * this display, or NULL for end of - * list. */ + /* Pointer to next older handler for this + * display, or NULL for end of list. */ } TkErrorHandler; - /* - * One of the following structures exists for each event handler - * created by calling Tk_CreateEventHandler. This information - * is used by tkEvent.c only. + * One of the following structures exists for each event handler created by + * calling Tk_CreateEventHandler. This information is used by tkEvent.c only. */ typedef struct TkEventHandler { - unsigned long mask; /* Events for which to invoke - * proc. */ - Tk_EventProc *proc; /* Procedure to invoke when an event - * in mask occurs. */ + unsigned long mask; /* Events for which to invoke proc. */ + Tk_EventProc *proc; /* Function to invoke when an event in mask + * occurs. */ ClientData clientData; /* Argument to pass to proc. */ struct TkEventHandler *nextPtr; - /* Next in list of handlers - * associated with window (NULL means - * end of list). */ + /* Next in list of handlers associated with + * window (NULL means end of list). */ } TkEventHandler; /* - * Tk keeps one of the following data structures for each main - * window (created by a call to TkCreateMainWindow). It stores - * information that is shared by all of the windows associated - * with a particular main window. + * Tk keeps one of the following data structures for each main window (created + * by a call to TkCreateMainWindow). It stores information that is shared by + * all of the windows associated with a particular main window. */ typedef struct TkMainInfo { int refCount; /* Number of windows whose "mainPtr" fields - * point here. When this becomes zero, can - * free up the structure (the reference - * count is zero because windows can get - * deleted in almost any order; the main - * window isn't necessarily the last one - * deleted). */ + * point here. When this becomes zero, can + * free up the structure (the reference count + * is zero because windows can get deleted in + * almost any order; the main window isn't + * necessarily the last one deleted). */ struct TkWindow *winPtr; /* Pointer to main window. */ Tcl_Interp *interp; /* Interpreter associated with application. */ Tcl_HashTable nameTable; /* Hash table mapping path names to TkWindow * structs for all windows related to this - * main window. Managed by tkWindow.c. */ - long deletionEpoch; /* Incremented by window deletions */ + * main window. Managed by tkWindow.c. */ + long deletionEpoch; /* Incremented by window deletions. */ Tk_BindingTable bindingTable; - /* Used in conjunction with "bind" command - * to bind events to Tcl commands. */ + /* Used in conjunction with "bind" command to + * bind events to Tcl commands. */ TkBindInfo bindInfo; /* Information used by tkBind.c on a per * application basis. */ struct TkFontInfo *fontInfoPtr; @@ -659,21 +650,21 @@ typedef struct TkMainInfo { struct TkToplevelFocusInfo *tlFocusPtr; /* First in list of records containing focus * information for each top-level in the - * application. Used only by tkFocus.c. */ + * application. Used only by tkFocus.c. */ struct TkDisplayFocusInfo *displayFocusPtr; /* First in list of records containing focus * information for each display that this - * application has ever used. Used only - * by tkFocus.c. */ + * application has ever used. Used only by + * tkFocus.c. */ struct ElArray *optionRootPtr; - /* Top level of option hierarchy for this - * main window. NULL means uninitialized. - * Managed by tkOption.c. */ + /* Top level of option hierarchy for this main + * window. NULL means uninitialized. Managed + * by tkOption.c. */ Tcl_HashTable imageTable; /* Maps from image names to Tk_ImageMaster - * structures. Managed by tkImage.c. */ - int strictMotif; /* This is linked to the tk_strictMotif - * global variable. */ + * structures. Managed by tkImage.c. */ + int strictMotif; /* This is linked to the tk_strictMotif global + * variable. */ int alwaysShowSelection; /* This is linked to the * ::tk::AlwaysShowSelection variable. */ struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by @@ -681,172 +672,157 @@ typedef struct TkMainInfo { } TkMainInfo; /* - * Tk keeps the following data structure for each of it's builtin - * bitmaps. This structure is only used by tkBitmap.c and other - * platform specific bitmap files. + * Tk keeps the following data structure for each of it's builtin bitmaps. + * This structure is only used by tkBitmap.c and other platform specific + * bitmap files. */ typedef struct { - CONST char *source; /* Bits for bitmap. */ + const char *source; /* Bits for bitmap. */ int width, height; /* Dimensions of bitmap. */ - int native; /* 0 means generic (X style) bitmap, - * 1 means native style bitmap. */ + int native; /* 0 means generic (X style) bitmap, 1 means + * native style bitmap. */ } TkPredefBitmap; /* - * Tk keeps one of the following structures for each window. - * Some of the information (like size and location) is a shadow - * of information managed by the X server, and some is special - * information used here, such as event and geometry management - * information. This information is (mostly) managed by tkWindow.c. - * WARNING: the declaration below must be kept consistent with the - * Tk_FakeWin structure in tk.h. If you change one, be sure to - * change the other!! + * Tk keeps one of the following structures for each window. Some of the + * information (like size and location) is a shadow of information managed by + * the X server, and some is special information used here, such as event and + * geometry management information. This information is (mostly) managed by + * tkWindow.c. WARNING: the declaration below must be kept consistent with the + * Tk_FakeWin structure in tk.h. If you change one, be sure to change the + * other! */ typedef struct TkWindow { - /* * Structural information: */ Display *display; /* Display containing window. */ - TkDisplay *dispPtr; /* Tk's information about display - * for window. */ - int screenNum; /* Index of screen for window, among all - * those for dispPtr. */ - Visual *visual; /* Visual to use for window. If not default, + TkDisplay *dispPtr; /* Tk's information about display for + * window. */ + int screenNum; /* Index of screen for window, among all those + * for dispPtr. */ + Visual *visual; /* Visual to use for window. If not default, * MUST be set before X window is created. */ int depth; /* Number of bits/pixel. */ - Window window; /* X's id for window. NULL means window - * hasn't actually been created yet, or it's - * been deleted. */ - struct TkWindow *childList; /* First in list of child windows, - * or NULL if no children. List is in - * stacking order, lowest window first.*/ - struct TkWindow *lastChildPtr; - /* Last in list of child windows (highest - * in stacking order), or NULL if no - * children. */ - struct TkWindow *parentPtr; /* Pointer to parent window (logical - * parent, not necessarily X parent). NULL - * means either this is the main window, or - * the window's parent has already been + Window window; /* X's id for window. NULL means window hasn't + * actually been created yet, or it's been * deleted. */ - struct TkWindow *nextPtr; /* Next higher sibling (in stacking order) - * in list of children with same parent. NULL + struct TkWindow *childList; /* First in list of child windows, or NULL if + * no children. List is in stacking order, + * lowest window first.*/ + struct TkWindow *lastChildPtr; + /* Last in list of child windows (highest in + * stacking order), or NULL if no children. */ + struct TkWindow *parentPtr; /* Pointer to parent window (logical parent, + * not necessarily X parent). NULL means + * either this is the main window, or the + * window's parent has already been deleted. */ + struct TkWindow *nextPtr; /* Next higher sibling (in stacking order) in + * list of children with same parent. NULL * means end of list. */ TkMainInfo *mainPtr; /* Information shared by all windows - * associated with a particular main - * window. NULL means this window is - * a rogue that isn't associated with - * any application (at present, this - * only happens for the dummy windows - * used for "send" communication). */ + * associated with a particular main window. + * NULL means this window is a rogue that is + * not associated with any application (at + * present, this only happens for the dummy + * windows used for "send" communication). */ /* * Name and type information for the window: */ - char *pathName; /* Path name of window (concatenation - * of all names between this window and - * its top-level ancestor). This is a - * pointer into an entry in - * mainPtr->nameTable. NULL means that - * the window hasn't been completely - * created yet. */ + char *pathName; /* Path name of window (concatenation of all + * names between this window and its top-level + * ancestor). This is a pointer into an entry + * in mainPtr->nameTable. NULL means that the + * window hasn't been completely created + * yet. */ Tk_Uid nameUid; /* Name of the window within its parent * (unique within the parent). */ - Tk_Uid classUid; /* Class of the window. NULL means window + Tk_Uid classUid; /* Class of the window. NULL means window * hasn't been given a class yet. */ /* - * Geometry and other attributes of window. This information - * may not be updated on the server immediately; stuff that - * hasn't been reflected in the server yet is called "dirty". - * At present, information can be dirty only if the window - * hasn't yet been created. + * Geometry and other attributes of window. This information may not be + * updated on the server immediately; stuff that hasn't been reflected in + * the server yet is called "dirty". At present, information can be dirty + * only if the window hasn't yet been created. */ - XWindowChanges changes; /* Geometry and other info about - * window. */ - unsigned int dirtyChanges; /* Bits indicate fields of "changes" - * that are dirty. */ + XWindowChanges changes; /* Geometry and other info about window. */ + unsigned int dirtyChanges; /* Bits indicate fields of "changes" that are + * dirty. */ XSetWindowAttributes atts; /* Current attributes of window. */ - unsigned long dirtyAtts; /* Bits indicate fields of "atts" - * that are dirty. */ + unsigned long dirtyAtts; /* Bits indicate fields of "atts" that are + * dirty. */ - unsigned int flags; /* Various flag values: these are all - * defined in tk.h (confusing, but they're - * needed there for some query macros). */ + unsigned int flags; /* Various flag values: these are all defined + * in tk.h (confusing, but they're needed + * there for some query macros). */ /* * Information kept by the event manager (tkEvent.c): */ - TkEventHandler *handlerList;/* First in list of event handlers - * declared for this window, or - * NULL if none. */ + TkEventHandler *handlerList;/* First in list of event handlers declared + * for this window, or NULL if none. */ #ifdef TK_USE_INPUT_METHODS XIC inputContext; /* XIM input context. */ #endif /* TK_USE_INPUT_METHODS */ /* - * Information used for event bindings (see "bind" and "bindtags" - * commands in tkCmds.c): + * Information used for event bindings (see "bind" and "bindtags" commands + * in tkCmds.c): */ ClientData *tagPtr; /* Points to array of tags used for bindings - * on this window. Each tag is a Tk_Uid. - * Malloc'ed. NULL means no tags. */ + * on this window. Each tag is a Tk_Uid. + * Malloc'ed. NULL means no tags. */ int numTags; /* Number of tags at *tagPtr. */ /* - * Information used by tkOption.c to manage options for the - * window. + * Information used by tkOption.c to manage options for the window. */ - int optionLevel; /* -1 means no option information is - * currently cached for this window. - * Otherwise this gives the level in - * the option stack at which info is - * cached. */ + int optionLevel; /* -1 means no option information is currently + * cached for this window. Otherwise this + * gives the level in the option stack at + * which info is cached. */ /* * Information used by tkSelect.c to manage the selection. */ struct TkSelHandler *selHandlerList; - /* First in list of handlers for - * returning the selection in various - * forms. */ + /* First in list of handlers for returning the + * selection in various forms. */ /* * Information used by tkGeometry.c for geometry management. */ - Tk_GeomMgr *geomMgrPtr; /* Information about geometry manager for - * this window. */ - ClientData geomData; /* Argument for geometry manager procedures. */ + const Tk_GeomMgr *geomMgrPtr; /* Information about geometry manager for this + * window. */ + ClientData geomData; /* Argument for geometry manager functions. */ int reqWidth, reqHeight; /* Arguments from last call to * Tk_GeometryRequest, or 0's if - * Tk_GeometryRequest hasn't been - * called. */ - int internalBorderLeft; /* Width of internal border of window - * (0 means no internal border). Geometry - * managers should not normally place children - * on top of the border. - * Fields for the other three sides are found - * below. */ + * Tk_GeometryRequest hasn't been called. */ + int internalBorderLeft; /* Width of internal border of window (0 means + * no internal border). Geometry managers + * should not normally place children on top + * of the border. Fields for the other three + * sides are found below. */ /* * Information maintained by tkWm.c for window manager communication. */ - struct TkWmInfo *wmInfoPtr; /* For top-level windows (and also - * for special Unix menubar and wrapper - * windows), points to structure with - * wm-related info (see tkWm.c). For - * other windows, this is NULL. */ + struct TkWmInfo *wmInfoPtr; /* For top-level windows (and also for special + * Unix menubar and wrapper windows), points + * to structure with wm-related info (see + * tkWm.c). For other windows, this is NULL. */ /* * Information used by widget classes. @@ -866,32 +842,50 @@ typedef struct TkWindow { */ /* The remaining fields of internal border. */ - int internalBorderRight; + int internalBorderRight; int internalBorderTop; int internalBorderBottom; - + int minReqWidth; /* Minimum requested width. */ int minReqHeight; /* Minimum requested height. */ } TkWindow; /* - * The following structure is used as a two way map between integers - * and strings, usually to map between an internal C representation - * and the strings used in Tcl. + * Real definition of some events. Note that these events come from outside + * but have internally generated pieces added to them. + */ + +typedef struct { + XKeyEvent keyEvent; /* The real event from X11. */ + char *charValuePtr; /* A pointer to a string that holds the key's + * %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 + * is non-NULL. */ + KeySym keysym; /* Key symbol computed after input methods + * have been invoked */ +} TkKeyEvent; + +/* + * The following structure is used as a two way map between integers and + * strings, usually to map between an internal C representation and the + * strings used in Tcl. */ typedef struct TkStateMap { int numKey; /* Integer representation of a value. */ - char *strKey; /* String representation of a value. */ + const char *strKey; /* String representation of a value. */ } TkStateMap; /* - * This structure is used by the Mac and Window porting layers as - * the internal representation of a clip_mask in a GC. + * This structure is used by the Mac and Window porting layers as the internal + * representation of a clip_mask in a GC. */ typedef struct TkpClipMask { - int type; /* One of TKP_CLIP_PIXMAP or TKP_CLIP_REGION */ + int type; /* TKP_CLIP_PIXMAP or TKP_CLIP_REGION. */ union { Pixmap pixmap; TkRegion region; @@ -917,318 +911,299 @@ extern TkDisplay *tkDisplayList; #define TK_GRAB_EXCLUDED 3 /* - * The macro below is used to modify a "char" value (e.g. by casting - * it to an unsigned character) so that it can be used safely with - * macros such as isspace. + * Additional flag for TkpMeasureCharsInContext. Coordinate with other flags + * for this routine, but don't make public until TkpMeasureCharsInContext is + * made public, too. + */ + +#define TK_ISOLATE_END 32 + +/* + * The macro below is used to modify a "char" value (e.g. by casting it to an + * unsigned character) so that it can be used safely with macros such as + * isspace(). */ #define UCHAR(c) ((unsigned char) (c)) /* - * The following symbol is used in the mode field of FocusIn events - * generated by an embedded application to request the input focus from - * its container. + * The following symbol is used in the mode field of FocusIn events generated + * by an embedded application to request the input focus from its container. */ #define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20) /* - * The following special modifier mask bits are defined, to indicate - * logical modifiers such as Meta and Alt that may float among the - * actual modifier bits. + * The following special modifier mask bits are defined, to indicate logical + * modifiers such as Meta and Alt that may float among the actual modifier + * bits. */ #define META_MASK (AnyModifier<<1) #define ALT_MASK (AnyModifier<<2) +#define EXTENDED_MASK (AnyModifier<<3) /* - * Object types not declared in tkObj.c need to be mentioned here so - * they can be properly registered with Tcl: + * Object types not declared in tkObj.c need to be mentioned here so they can + * be properly registered with Tcl: */ -extern Tcl_ObjType tkBorderObjType; -extern Tcl_ObjType tkBitmapObjType; -extern Tcl_ObjType tkColorObjType; -extern Tcl_ObjType tkCursorObjType; -extern Tcl_ObjType tkFontObjType; -extern Tcl_ObjType tkOptionObjType; -extern Tcl_ObjType tkStateKeyObjType; +MODULE_SCOPE Tcl_ObjType tkBorderObjType; +MODULE_SCOPE Tcl_ObjType tkBitmapObjType; +MODULE_SCOPE Tcl_ObjType tkColorObjType; +MODULE_SCOPE Tcl_ObjType tkCursorObjType; +MODULE_SCOPE Tcl_ObjType tkFontObjType; +MODULE_SCOPE Tcl_ObjType tkOptionObjType; +MODULE_SCOPE Tcl_ObjType tkStateKeyObjType; +MODULE_SCOPE Tcl_ObjType tkTextIndexType; /* - * Miscellaneous variables shared among Tk modules but not exported - * to the outside world: + * Miscellaneous variables shared among Tk modules but not exported to the + * outside world: */ -extern Tk_SmoothMethod tkBezierSmoothMethod; -extern Tk_ImageType tkBitmapImageType; -extern Tk_PhotoImageFormat tkImgFmtGIF; -extern void (*tkHandleEventProc) _ANSI_ARGS_(( - XEvent* eventPtr)); -extern Tk_PhotoImageFormat tkImgFmtPPM; -extern TkMainInfo *tkMainWindowList; -extern Tk_ImageType tkPhotoImageType; -extern Tcl_HashTable tkPredefBitmapTable; -extern int tkSendSerial; +MODULE_SCOPE Tk_SmoothMethod tkBezierSmoothMethod; +MODULE_SCOPE Tk_ImageType tkBitmapImageType; +MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtGIF; +MODULE_SCOPE void (*tkHandleEventProc) (XEvent* eventPtr); +MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPPM; +MODULE_SCOPE TkMainInfo *tkMainWindowList; +MODULE_SCOPE Tk_ImageType tkPhotoImageType; +MODULE_SCOPE Tcl_HashTable tkPredefBitmapTable; #include "tkIntDecls.h" #ifdef BUILD_tk -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLEXPORT +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT #endif /* - * Internal procedures shared among Tk modules but not exported - * to the outside world: + * Themed widget set init function: */ -EXTERN int Tk_BellObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_BindObjCmd _ANSI_ARGS_((ClientData clientData, +MODULE_SCOPE int Ttk_Init(Tcl_Interp *interp); + +/* + * Internal functions shared among Tk modules but not exported to the outside + * world: + */ + +MODULE_SCOPE int Tk_BellObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_BindObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_BindtagsObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_BindtagsObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ButtonObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ButtonObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_CanvasObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_CanvasObjCmd(ClientData clientData, Tcl_Interp *interp, int argc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_CheckbuttonObjCmd _ANSI_ARGS_(( - ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_CheckbuttonObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ClipboardObjCmd _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tk_ChooseColorObjCmd _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tk_ChooseDirectoryObjCmd _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[])); -EXTERN int Tk_ChooseFontObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_DestroyObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_EntryObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_EventObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ClipboardObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_FileeventCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, char **argv)); -EXTERN int Tk_FrameObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ChooseColorObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_FocusObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_FontObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_GetOpenFileObjCmd _ANSI_ARGS_(( - ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_GetSaveFileObjCmd _ANSI_ARGS_(( - ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_GrabObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ChooseDirectoryObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_GridObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ChooseFontObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ImageObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_DestroyObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_LabelframeObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_EntryObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ListboxObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_EventObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_LowerObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_FrameObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_MenubuttonObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_MessageObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_FocusObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_PanedWindowObjCmd _ANSI_ARGS_(( - ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_FontObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_OptionObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_GetOpenFileObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_PackObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_GetSaveFileObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_PlaceObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_GrabObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_RadiobuttonObjCmd _ANSI_ARGS_(( - ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_GridObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_RaiseObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ImageObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ScaleObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ScrollbarCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int Tk_SelectionObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_LabelObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_SendCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int Tk_SendObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_SpinboxObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_TextCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_LabelframeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_TkwaitObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ListboxObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_ToplevelObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_LowerObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_UpdateObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_WinfoObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_MenubuttonObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -EXTERN int Tk_WmObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_MessageBoxObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); - -EXTERN void TkEventInit _ANSI_ARGS_((void)); - -EXTERN void TkRegisterObjTypes _ANSI_ARGS_((void)); - -EXTERN int TkCreateMenuCmd _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, CONST char **argv)); + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_MessageObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_PanedWindowObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_OptionObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_PackObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_PlaceObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_RadiobuttonObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_RaiseObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ScaleObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ScrollbarCmd(ClientData clientData, + Tcl_Interp *interp, int argc, const char **argv); +MODULE_SCOPE int Tk_SelectionObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_SendCmd(ClientData clientData, + Tcl_Interp *interp, int argc, const char **argv); +MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_SpinboxObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_TextObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_TkObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_TkwaitObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_ToplevelObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_UpdateObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_WinfoObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +MODULE_SCOPE int Tk_WmObjCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); -EXTERN int TkpTestembedCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkCanvasGetCoordObj _ANSI_ARGS_((Tcl_Interp *interp, +MODULE_SCOPE int Tk_GetDoublePixelsFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr, + double *doublePtr); + +MODULE_SCOPE void TkEventInit(void); +MODULE_SCOPE void TkRegisterObjTypes(void); +MODULE_SCOPE int TkCreateMenuCmd(Tcl_Interp *interp); +MODULE_SCOPE int TkDeadAppCmd(ClientData clientData, + Tcl_Interp *interp, int argc, const char **argv); +MODULE_SCOPE int TkCanvasGetCoordObj(Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj, - double *doublePtr)); -EXTERN int TkCanvasDashParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, char *widgRec, - int offset)); -EXTERN char * TkCanvasDashPrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN int TkGetDoublePixels _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *string, - double *doublePtr)); -EXTERN int TkOffsetParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, char *widgRec, - int offset)); -EXTERN char * TkOffsetPrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN int TkOrientParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, - char *widgRec, int offset)); -EXTERN char * TkOrientPrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN int TkPixelParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, char *widgRec, - int offset)); -EXTERN char * TkPixelPrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN int TkPostscriptImage _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_PostscriptInfo psInfo, - XImage *ximage, int x, int y, int width, - int height)); -EXTERN int TkSmoothParseProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, Tk_Window tkwin, - CONST char *value, char *recordPtr, int offset)); -EXTERN char * TkSmoothPrintProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *recordPtr, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN int TkStateParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, - char *widgRec, int offset)); -EXTERN char * TkStatePrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN int TkTileParseProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - Tk_Window tkwin, CONST char *value, char *widgRec, - int offset)); -EXTERN char * TkTilePrintProc _ANSI_ARGS_(( - ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -EXTERN void TkCreateExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc, - ClientData clientData)); -EXTERN void TkDeleteExitHandler _ANSI_ARGS_((Tcl_ExitProc *proc, - ClientData clientData)); -EXTERN Tcl_ExitProc TkFinalize; -EXTERN void TkPrintPadAmount _ANSI_ARGS_((Tcl_Interp *interp, - char *buffer, int pad1, int pad2)); -EXTERN int TkParsePadAmount _ANSI_ARGS_((Tcl_Interp *interp, + double *doublePtr); +MODULE_SCOPE int TkGetDoublePixels(Tcl_Interp *interp, Tk_Window tkwin, + const char *string, double *doublePtr); +MODULE_SCOPE int TkPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin, + Tk_PostscriptInfo psInfo, XImage *ximage, + int x, int y, int width, int height); +MODULE_SCOPE void TkMapTopFrame(Tk_Window tkwin); +MODULE_SCOPE XEvent * TkpGetBindingXEvent(Tcl_Interp *interp); +MODULE_SCOPE void TkCreateExitHandler(Tcl_ExitProc *proc, + ClientData clientData); +MODULE_SCOPE void TkDeleteExitHandler(Tcl_ExitProc *proc, + ClientData clientData); +MODULE_SCOPE Tcl_ExitProc TkFinalize; +MODULE_SCOPE Tcl_ExitProc TkFinalizeThread; +MODULE_SCOPE void TkpBuildRegionFromAlphaData(TkRegion region, + unsigned x, unsigned y, unsigned width, + unsigned height, unsigned char *dataPtr, + unsigned pixelStride, unsigned lineStride); +MODULE_SCOPE void TkPrintPadAmount(Tcl_Interp *interp, + char *buffer, int pad1, int pad2); +MODULE_SCOPE int TkParsePadAmount(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, - int *pad1Ptr, int *pad2Ptr)); -EXTERN int TkpAlwaysShowSelection _ANSI_ARGS_((Tk_Window tkwin)); + int *pad1Ptr, int *pad2Ptr); +MODULE_SCOPE void TkFocusSplit(TkWindow *winPtr); +MODULE_SCOPE void TkFocusJoin(TkWindow *winPtr); +MODULE_SCOPE int TkpAlwaysShowSelection(Tk_Window tkwin); +MODULE_SCOPE void TkpDrawCharsInContext(Display * display, + Drawable drawable, GC gc, Tk_Font tkfont, + const char *source, int numBytes, int rangeStart, + int rangeLength, int x, int y); +MODULE_SCOPE int TkpMeasureCharsInContext(Tk_Font tkfont, + const char *source, int numBytes, int rangeStart, + int rangeLength, int maxLength, int flags, + int *lengthPtr); +MODULE_SCOPE void TkUnderlineCharsInContext(Display *display, + Drawable drawable, GC gc, Tk_Font tkfont, + const char *string, int numBytes, int x, int y, + int firstByte, int lastByte); +MODULE_SCOPE void TkpGetFontAttrsForChar(Tk_Window tkwin, Tk_Font tkfont, + Tcl_UniChar c, struct TkFontAttributes *faPtr); #ifdef __WIN32__ #define TkParseColor XParseColor #else -EXTERN Status TkParseColor _ANSI_ARGS_((Display * display, +MODULE_SCOPE Status TkParseColor (Display * display, Colormap map, CONST char* spec, - XColor * colorPtr)); + XColor * colorPtr); #endif /* * Unsupported commands. */ -EXTERN int TkUnsupported1ObjCmd _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[])); -# undef TCL_STORAGE_CLASS -# define TCL_STORAGE_CLASS DLLIMPORT +MODULE_SCOPE int TkUnsupported1ObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); -#endif /* _TKINT */ +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLIMPORT + +#endif /* _TKINT */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkIntDecls.h b/generic/tkIntDecls.h index 280e6c8..298c322 100644 --- a/generic/tkIntDecls.h +++ b/generic/tkIntDecls.h @@ -32,468 +32,769 @@ * Exported function declarations: */ +#ifndef TkAllocWindow_TCL_DECLARED +#define TkAllocWindow_TCL_DECLARED /* 0 */ -EXTERN TkWindow * TkAllocWindow _ANSI_ARGS_((TkDisplay *dispPtr, - int screenNum, TkWindow *parentPtr)); +EXTERN TkWindow * TkAllocWindow(TkDisplay *dispPtr, int screenNum, + TkWindow *parentPtr); +#endif +#ifndef TkBezierPoints_TCL_DECLARED +#define TkBezierPoints_TCL_DECLARED /* 1 */ -EXTERN void TkBezierPoints _ANSI_ARGS_((double control[], - int numSteps, double *coordPtr)); +EXTERN void TkBezierPoints(double control[], int numSteps, + double *coordPtr); +#endif +#ifndef TkBezierScreenPoints_TCL_DECLARED +#define TkBezierScreenPoints_TCL_DECLARED /* 2 */ -EXTERN void TkBezierScreenPoints _ANSI_ARGS_((Tk_Canvas canvas, +EXTERN void TkBezierScreenPoints(Tk_Canvas canvas, double control[], int numSteps, - XPoint *xPointPtr)); + XPoint *xPointPtr); +#endif +#ifndef TkBindDeadWindow_TCL_DECLARED +#define TkBindDeadWindow_TCL_DECLARED /* 3 */ -EXTERN void TkBindDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkBindDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkBindEventProc_TCL_DECLARED +#define TkBindEventProc_TCL_DECLARED /* 4 */ -EXTERN void TkBindEventProc _ANSI_ARGS_((TkWindow *winPtr, - XEvent *eventPtr)); +EXTERN void TkBindEventProc(TkWindow *winPtr, XEvent *eventPtr); +#endif +#ifndef TkBindFree_TCL_DECLARED +#define TkBindFree_TCL_DECLARED /* 5 */ -EXTERN void TkBindFree _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkBindFree(TkMainInfo *mainPtr); +#endif +#ifndef TkBindInit_TCL_DECLARED +#define TkBindInit_TCL_DECLARED /* 6 */ -EXTERN void TkBindInit _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkBindInit(TkMainInfo *mainPtr); +#endif +#ifndef TkChangeEventWindow_TCL_DECLARED +#define TkChangeEventWindow_TCL_DECLARED /* 7 */ -EXTERN void TkChangeEventWindow _ANSI_ARGS_((XEvent *eventPtr, - TkWindow *winPtr)); +EXTERN void TkChangeEventWindow(XEvent *eventPtr, + TkWindow *winPtr); +#endif +#ifndef TkClipInit_TCL_DECLARED +#define TkClipInit_TCL_DECLARED /* 8 */ -EXTERN int TkClipInit _ANSI_ARGS_((Tcl_Interp *interp, - TkDisplay *dispPtr)); +EXTERN int TkClipInit(Tcl_Interp *interp, TkDisplay *dispPtr); +#endif +#ifndef TkComputeAnchor_TCL_DECLARED +#define TkComputeAnchor_TCL_DECLARED /* 9 */ -EXTERN void TkComputeAnchor _ANSI_ARGS_((Tk_Anchor anchor, - Tk_Window tkwin, int padX, int padY, - int innerWidth, int innerHeight, int *xPtr, - int *yPtr)); +EXTERN void TkComputeAnchor(Tk_Anchor anchor, Tk_Window tkwin, + int padX, int padY, int innerWidth, + int innerHeight, int *xPtr, int *yPtr); +#endif +#ifndef TkCopyAndGlobalEval_TCL_DECLARED +#define TkCopyAndGlobalEval_TCL_DECLARED /* 10 */ -EXTERN int TkCopyAndGlobalEval _ANSI_ARGS_((Tcl_Interp *interp, - char *script)); +EXTERN int TkCopyAndGlobalEval(Tcl_Interp *interp, char *script); +#endif +#ifndef TkCreateBindingProcedure_TCL_DECLARED +#define TkCreateBindingProcedure_TCL_DECLARED /* 11 */ -EXTERN unsigned long TkCreateBindingProcedure _ANSI_ARGS_(( - Tcl_Interp *interp, +EXTERN unsigned long TkCreateBindingProcedure(Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventString, TkBindEvalProc *evalProc, TkBindFreeProc *freeProc, - ClientData clientData)); + ClientData clientData); +#endif +#ifndef TkCreateCursorFromData_TCL_DECLARED +#define TkCreateCursorFromData_TCL_DECLARED /* 12 */ -EXTERN TkCursor * TkCreateCursorFromData _ANSI_ARGS_((Tk_Window tkwin, +EXTERN TkCursor * TkCreateCursorFromData(Tk_Window tkwin, CONST char *source, CONST char *mask, int width, int height, int xHot, int yHot, - XColor fg, XColor bg)); + XColor fg, XColor bg); +#endif +#ifndef TkCreateFrame_TCL_DECLARED +#define TkCreateFrame_TCL_DECLARED /* 13 */ -EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData, +EXTERN int TkCreateFrame(ClientData clientData, Tcl_Interp *interp, int argc, char **argv, - int toplevel, char *appName)); + int toplevel, char *appName); +#endif +#ifndef TkCreateMainWindow_TCL_DECLARED +#define TkCreateMainWindow_TCL_DECLARED /* 14 */ -EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *screenName, char *baseName)); +EXTERN Tk_Window TkCreateMainWindow(Tcl_Interp *interp, + CONST char *screenName, char *baseName); +#endif +#ifndef TkCurrentTime_TCL_DECLARED +#define TkCurrentTime_TCL_DECLARED /* 15 */ -EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN Time TkCurrentTime(TkDisplay *dispPtr); +#endif +#ifndef TkDeleteAllImages_TCL_DECLARED +#define TkDeleteAllImages_TCL_DECLARED /* 16 */ -EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkDeleteAllImages(TkMainInfo *mainPtr); +#endif +#ifndef TkDoConfigureNotify_TCL_DECLARED +#define TkDoConfigureNotify_TCL_DECLARED /* 17 */ -EXTERN void TkDoConfigureNotify _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkDoConfigureNotify(TkWindow *winPtr); +#endif +#ifndef TkDrawInsetFocusHighlight_TCL_DECLARED +#define TkDrawInsetFocusHighlight_TCL_DECLARED /* 18 */ -EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_(( - Tk_Window tkwin, GC gc, int width, - Drawable drawable, int padding)); +EXTERN void TkDrawInsetFocusHighlight(Tk_Window tkwin, GC gc, + int width, Drawable drawable, int padding); +#endif +#ifndef TkEventDeadWindow_TCL_DECLARED +#define TkEventDeadWindow_TCL_DECLARED /* 19 */ -EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkEventDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkFillPolygon_TCL_DECLARED +#define TkFillPolygon_TCL_DECLARED /* 20 */ -EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas, - double *coordPtr, int numPoints, - Display *display, Drawable drawable, GC gc, - GC outlineGC)); +EXTERN void TkFillPolygon(Tk_Canvas canvas, double *coordPtr, + int numPoints, Display *display, + Drawable drawable, GC gc, GC outlineGC); +#endif +#ifndef TkFindStateNum_TCL_DECLARED +#define TkFindStateNum_TCL_DECLARED /* 21 */ -EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int TkFindStateNum(Tcl_Interp *interp, CONST char *option, CONST TkStateMap *mapPtr, - CONST char *strKey)); + CONST char *strKey); +#endif +#ifndef TkFindStateString_TCL_DECLARED +#define TkFindStateString_TCL_DECLARED /* 22 */ -EXTERN char * TkFindStateString _ANSI_ARGS_(( - CONST TkStateMap *mapPtr, int numKey)); +EXTERN char * TkFindStateString(CONST TkStateMap *mapPtr, + int numKey); +#endif +#ifndef TkFocusDeadWindow_TCL_DECLARED +#define TkFocusDeadWindow_TCL_DECLARED /* 23 */ -EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkFocusDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkFocusFilterEvent_TCL_DECLARED +#define TkFocusFilterEvent_TCL_DECLARED /* 24 */ -EXTERN int TkFocusFilterEvent _ANSI_ARGS_((TkWindow *winPtr, - XEvent *eventPtr)); +EXTERN int TkFocusFilterEvent(TkWindow *winPtr, + XEvent *eventPtr); +#endif +#ifndef TkFocusKeyEvent_TCL_DECLARED +#define TkFocusKeyEvent_TCL_DECLARED /* 25 */ -EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow *winPtr, - XEvent *eventPtr)); +EXTERN TkWindow * TkFocusKeyEvent(TkWindow *winPtr, XEvent *eventPtr); +#endif +#ifndef TkFontPkgInit_TCL_DECLARED +#define TkFontPkgInit_TCL_DECLARED /* 26 */ -EXTERN void TkFontPkgInit _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkFontPkgInit(TkMainInfo *mainPtr); +#endif +#ifndef TkFontPkgFree_TCL_DECLARED +#define TkFontPkgFree_TCL_DECLARED /* 27 */ -EXTERN void TkFontPkgFree _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkFontPkgFree(TkMainInfo *mainPtr); +#endif +#ifndef TkFreeBindingTags_TCL_DECLARED +#define TkFreeBindingTags_TCL_DECLARED /* 28 */ -EXTERN void TkFreeBindingTags _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkFreeBindingTags(TkWindow *winPtr); +#endif +#ifndef TkpFreeCursor_TCL_DECLARED +#define TkpFreeCursor_TCL_DECLARED /* 29 */ -EXTERN void TkpFreeCursor _ANSI_ARGS_((TkCursor *cursorPtr)); +EXTERN void TkpFreeCursor(TkCursor *cursorPtr); +#endif +#ifndef TkGetBitmapData_TCL_DECLARED +#define TkGetBitmapData_TCL_DECLARED /* 30 */ -EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp *interp, - char *string, char *fileName, int *widthPtr, - int *heightPtr, int *hotXPtr, int *hotYPtr)); +EXTERN char * TkGetBitmapData(Tcl_Interp *interp, char *string, + char *fileName, int *widthPtr, + int *heightPtr, int *hotXPtr, int *hotYPtr); +#endif +#ifndef TkGetButtPoints_TCL_DECLARED +#define TkGetButtPoints_TCL_DECLARED /* 31 */ -EXTERN void TkGetButtPoints _ANSI_ARGS_((double p1[], - double p2[], double width, int project, - double m1[], double m2[])); +EXTERN void TkGetButtPoints(double p1[], double p2[], + double width, int project, double m1[], + double m2[]); +#endif +#ifndef TkGetCursorByName_TCL_DECLARED +#define TkGetCursorByName_TCL_DECLARED /* 32 */ -EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_Uid string)); +EXTERN TkCursor * TkGetCursorByName(Tcl_Interp *interp, + Tk_Window tkwin, Tk_Uid string); +#endif +#ifndef TkGetDefaultScreenName_TCL_DECLARED +#define TkGetDefaultScreenName_TCL_DECLARED /* 33 */ -EXTERN CONST84_RETURN char * TkGetDefaultScreenName _ANSI_ARGS_(( - Tcl_Interp *interp, CONST char *screenName)); +EXTERN CONST84_RETURN char * TkGetDefaultScreenName(Tcl_Interp *interp, + CONST char *screenName); +#endif +#ifndef TkGetDisplay_TCL_DECLARED +#define TkGetDisplay_TCL_DECLARED /* 34 */ -EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display *display)); +EXTERN TkDisplay * TkGetDisplay(Display *display); +#endif +#ifndef TkGetDisplayOf_TCL_DECLARED +#define TkGetDisplayOf_TCL_DECLARED /* 35 */ -EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp *interp, - int objc, Tcl_Obj * CONST objv[], - Tk_Window *tkwinPtr)); +EXTERN int TkGetDisplayOf(Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[], Tk_Window *tkwinPtr); +#endif +#ifndef TkGetFocusWin_TCL_DECLARED +#define TkGetFocusWin_TCL_DECLARED /* 36 */ -EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN TkWindow * TkGetFocusWin(TkWindow *winPtr); +#endif +#ifndef TkGetInterpNames_TCL_DECLARED +#define TkGetInterpNames_TCL_DECLARED /* 37 */ -EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin)); +EXTERN int TkGetInterpNames(Tcl_Interp *interp, Tk_Window tkwin); +#endif +#ifndef TkGetMiterPoints_TCL_DECLARED +#define TkGetMiterPoints_TCL_DECLARED /* 38 */ -EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], - double p2[], double p3[], double width, - double m1[], double m2[])); +EXTERN int TkGetMiterPoints(double p1[], double p2[], + double p3[], double width, double m1[], + double m2[]); +#endif +#ifndef TkGetPointerCoords_TCL_DECLARED +#define TkGetPointerCoords_TCL_DECLARED /* 39 */ -EXTERN void TkGetPointerCoords _ANSI_ARGS_((Tk_Window tkwin, - int *xPtr, int *yPtr)); +EXTERN void TkGetPointerCoords(Tk_Window tkwin, int *xPtr, + int *yPtr); +#endif +#ifndef TkGetServerInfo_TCL_DECLARED +#define TkGetServerInfo_TCL_DECLARED /* 40 */ -EXTERN void TkGetServerInfo _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin)); +EXTERN void TkGetServerInfo(Tcl_Interp *interp, Tk_Window tkwin); +#endif +#ifndef TkGrabDeadWindow_TCL_DECLARED +#define TkGrabDeadWindow_TCL_DECLARED /* 41 */ -EXTERN void TkGrabDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkGrabDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkGrabState_TCL_DECLARED +#define TkGrabState_TCL_DECLARED /* 42 */ -EXTERN int TkGrabState _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN int TkGrabState(TkWindow *winPtr); +#endif +#ifndef TkIncludePoint_TCL_DECLARED +#define TkIncludePoint_TCL_DECLARED /* 43 */ -EXTERN void TkIncludePoint _ANSI_ARGS_((Tk_Item *itemPtr, - double *pointPtr)); +EXTERN void TkIncludePoint(Tk_Item *itemPtr, double *pointPtr); +#endif +#ifndef TkInOutEvents_TCL_DECLARED +#define TkInOutEvents_TCL_DECLARED /* 44 */ -EXTERN void TkInOutEvents _ANSI_ARGS_((XEvent *eventPtr, - TkWindow *sourcePtr, TkWindow *destPtr, - int leaveType, int enterType, - Tcl_QueuePosition position)); +EXTERN void TkInOutEvents(XEvent *eventPtr, TkWindow *sourcePtr, + TkWindow *destPtr, int leaveType, + int enterType, Tcl_QueuePosition position); +#endif +#ifndef TkInstallFrameMenu_TCL_DECLARED +#define TkInstallFrameMenu_TCL_DECLARED /* 45 */ -EXTERN void TkInstallFrameMenu _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void TkInstallFrameMenu(Tk_Window tkwin); +#endif +#ifndef TkKeysymToString_TCL_DECLARED +#define TkKeysymToString_TCL_DECLARED /* 46 */ -EXTERN char * TkKeysymToString _ANSI_ARGS_((KeySym keysym)); +EXTERN char * TkKeysymToString(KeySym keysym); +#endif +#ifndef TkLineToArea_TCL_DECLARED +#define TkLineToArea_TCL_DECLARED /* 47 */ -EXTERN int TkLineToArea _ANSI_ARGS_((double end1Ptr[], - double end2Ptr[], double rectPtr[])); +EXTERN int TkLineToArea(double end1Ptr[], double end2Ptr[], + double rectPtr[]); +#endif +#ifndef TkLineToPoint_TCL_DECLARED +#define TkLineToPoint_TCL_DECLARED /* 48 */ -EXTERN double TkLineToPoint _ANSI_ARGS_((double end1Ptr[], - double end2Ptr[], double pointPtr[])); +EXTERN double TkLineToPoint(double end1Ptr[], double end2Ptr[], + double pointPtr[]); +#endif +#ifndef TkMakeBezierCurve_TCL_DECLARED +#define TkMakeBezierCurve_TCL_DECLARED /* 49 */ -EXTERN int TkMakeBezierCurve _ANSI_ARGS_((Tk_Canvas canvas, - double *pointPtr, int numPoints, - int numSteps, XPoint xPoints[], - double dblPoints[])); +EXTERN int TkMakeBezierCurve(Tk_Canvas canvas, double *pointPtr, + int numPoints, int numSteps, + XPoint xPoints[], double dblPoints[]); +#endif +#ifndef TkMakeBezierPostscript_TCL_DECLARED +#define TkMakeBezierPostscript_TCL_DECLARED /* 50 */ -EXTERN void TkMakeBezierPostscript _ANSI_ARGS_(( - Tcl_Interp *interp, Tk_Canvas canvas, - double *pointPtr, int numPoints)); +EXTERN void TkMakeBezierPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, double *pointPtr, + int numPoints); +#endif +#ifndef TkOptionClassChanged_TCL_DECLARED +#define TkOptionClassChanged_TCL_DECLARED /* 51 */ -EXTERN void TkOptionClassChanged _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkOptionClassChanged(TkWindow *winPtr); +#endif +#ifndef TkOptionDeadWindow_TCL_DECLARED +#define TkOptionDeadWindow_TCL_DECLARED /* 52 */ -EXTERN void TkOptionDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkOptionDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkOvalToArea_TCL_DECLARED +#define TkOvalToArea_TCL_DECLARED /* 53 */ -EXTERN int TkOvalToArea _ANSI_ARGS_((double *ovalPtr, - double *rectPtr)); +EXTERN int TkOvalToArea(double *ovalPtr, double *rectPtr); +#endif +#ifndef TkOvalToPoint_TCL_DECLARED +#define TkOvalToPoint_TCL_DECLARED /* 54 */ -EXTERN double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[], - double width, int filled, double pointPtr[])); +EXTERN double TkOvalToPoint(double ovalPtr[], double width, + int filled, double pointPtr[]); +#endif +#ifndef TkpChangeFocus_TCL_DECLARED +#define TkpChangeFocus_TCL_DECLARED /* 55 */ -EXTERN int TkpChangeFocus _ANSI_ARGS_((TkWindow *winPtr, - int force)); +EXTERN int TkpChangeFocus(TkWindow *winPtr, int force); +#endif +#ifndef TkpCloseDisplay_TCL_DECLARED +#define TkpCloseDisplay_TCL_DECLARED /* 56 */ -EXTERN void TkpCloseDisplay _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkpCloseDisplay(TkDisplay *dispPtr); +#endif +#ifndef TkpClaimFocus_TCL_DECLARED +#define TkpClaimFocus_TCL_DECLARED /* 57 */ -EXTERN void TkpClaimFocus _ANSI_ARGS_((TkWindow *topLevelPtr, - int force)); +EXTERN void TkpClaimFocus(TkWindow *topLevelPtr, int force); +#endif +#ifndef TkpDisplayWarning_TCL_DECLARED +#define TkpDisplayWarning_TCL_DECLARED /* 58 */ -EXTERN void TkpDisplayWarning _ANSI_ARGS_((CONST char *msg, - CONST char *title)); +EXTERN void TkpDisplayWarning(CONST char *msg, CONST char *title); +#endif +#ifndef TkpGetAppName_TCL_DECLARED +#define TkpGetAppName_TCL_DECLARED /* 59 */ -EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_DString *name)); +EXTERN void TkpGetAppName(Tcl_Interp *interp, Tcl_DString *name); +#endif +#ifndef TkpGetOtherWindow_TCL_DECLARED +#define TkpGetOtherWindow_TCL_DECLARED /* 60 */ -EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN TkWindow * TkpGetOtherWindow(TkWindow *winPtr); +#endif +#ifndef TkpGetWrapperWindow_TCL_DECLARED +#define TkpGetWrapperWindow_TCL_DECLARED /* 61 */ -EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN TkWindow * TkpGetWrapperWindow(TkWindow *winPtr); +#endif +#ifndef TkpInit_TCL_DECLARED +#define TkpInit_TCL_DECLARED /* 62 */ -EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN int TkpInit(Tcl_Interp *interp); +#endif +#ifndef TkpInitializeMenuBindings_TCL_DECLARED +#define TkpInitializeMenuBindings_TCL_DECLARED /* 63 */ -EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_(( - Tcl_Interp *interp, - Tk_BindingTable bindingTable)); +EXTERN void TkpInitializeMenuBindings(Tcl_Interp *interp, + Tk_BindingTable bindingTable); +#endif +#ifndef TkpMakeContainer_TCL_DECLARED +#define TkpMakeContainer_TCL_DECLARED /* 64 */ -EXTERN void TkpMakeContainer _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void TkpMakeContainer(Tk_Window tkwin); +#endif +#ifndef TkpMakeMenuWindow_TCL_DECLARED +#define TkpMakeMenuWindow_TCL_DECLARED /* 65 */ -EXTERN void TkpMakeMenuWindow _ANSI_ARGS_((Tk_Window tkwin, - int transient)); +EXTERN void TkpMakeMenuWindow(Tk_Window tkwin, int transient); +#endif +#ifndef TkpMakeWindow_TCL_DECLARED +#define TkpMakeWindow_TCL_DECLARED /* 66 */ -EXTERN Window TkpMakeWindow _ANSI_ARGS_((TkWindow *winPtr, - Window parent)); +EXTERN Window TkpMakeWindow(TkWindow *winPtr, Window parent); +#endif +#ifndef TkpMenuNotifyToplevelCreate_TCL_DECLARED +#define TkpMenuNotifyToplevelCreate_TCL_DECLARED /* 67 */ -EXTERN void TkpMenuNotifyToplevelCreate _ANSI_ARGS_(( - Tcl_Interp *interp1, char *menuName)); +EXTERN void TkpMenuNotifyToplevelCreate(Tcl_Interp *interp, + char *menuName); +#endif +#ifndef TkpOpenDisplay_TCL_DECLARED +#define TkpOpenDisplay_TCL_DECLARED /* 68 */ -EXTERN TkDisplay * TkpOpenDisplay _ANSI_ARGS_((CONST char *display_name)); +EXTERN TkDisplay * TkpOpenDisplay(CONST char *display_name); +#endif +#ifndef TkPointerEvent_TCL_DECLARED +#define TkPointerEvent_TCL_DECLARED /* 69 */ -EXTERN int TkPointerEvent _ANSI_ARGS_((XEvent *eventPtr, - TkWindow *winPtr)); +EXTERN int TkPointerEvent(XEvent *eventPtr, TkWindow *winPtr); +#endif +#ifndef TkPolygonToArea_TCL_DECLARED +#define TkPolygonToArea_TCL_DECLARED /* 70 */ -EXTERN int TkPolygonToArea _ANSI_ARGS_((double *polyPtr, - int numPoints, double *rectPtr)); +EXTERN int TkPolygonToArea(double *polyPtr, int numPoints, + double *rectPtr); +#endif +#ifndef TkPolygonToPoint_TCL_DECLARED +#define TkPolygonToPoint_TCL_DECLARED /* 71 */ -EXTERN double TkPolygonToPoint _ANSI_ARGS_((double *polyPtr, - int numPoints, double *pointPtr)); +EXTERN double TkPolygonToPoint(double *polyPtr, int numPoints, + double *pointPtr); +#endif +#ifndef TkPositionInTree_TCL_DECLARED +#define TkPositionInTree_TCL_DECLARED /* 72 */ -EXTERN int TkPositionInTree _ANSI_ARGS_((TkWindow *winPtr, - TkWindow *treePtr)); +EXTERN int TkPositionInTree(TkWindow *winPtr, TkWindow *treePtr); +#endif +#ifndef TkpRedirectKeyEvent_TCL_DECLARED +#define TkpRedirectKeyEvent_TCL_DECLARED /* 73 */ -EXTERN void TkpRedirectKeyEvent _ANSI_ARGS_((TkWindow *winPtr, - XEvent *eventPtr)); +EXTERN void TkpRedirectKeyEvent(TkWindow *winPtr, + XEvent *eventPtr); +#endif +#ifndef TkpSetMainMenubar_TCL_DECLARED +#define TkpSetMainMenubar_TCL_DECLARED /* 74 */ -EXTERN void TkpSetMainMenubar _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, char *menuName)); +EXTERN void TkpSetMainMenubar(Tcl_Interp *interp, + Tk_Window tkwin, char *menuName); +#endif +#ifndef TkpUseWindow_TCL_DECLARED +#define TkpUseWindow_TCL_DECLARED /* 75 */ -EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, CONST char *string)); +EXTERN int TkpUseWindow(Tcl_Interp *interp, Tk_Window tkwin, + CONST char *string); +#endif +#ifndef TkpWindowWasRecentlyDeleted_TCL_DECLARED +#define TkpWindowWasRecentlyDeleted_TCL_DECLARED /* 76 */ -EXTERN int TkpWindowWasRecentlyDeleted _ANSI_ARGS_((Window win, - TkDisplay *dispPtr)); +EXTERN int TkpWindowWasRecentlyDeleted(Window win, + TkDisplay *dispPtr); +#endif +#ifndef TkQueueEventForAllChildren_TCL_DECLARED +#define TkQueueEventForAllChildren_TCL_DECLARED /* 77 */ -EXTERN void TkQueueEventForAllChildren _ANSI_ARGS_(( - TkWindow *winPtr, XEvent *eventPtr)); +EXTERN void TkQueueEventForAllChildren(TkWindow *winPtr, + XEvent *eventPtr); +#endif +#ifndef TkReadBitmapFile_TCL_DECLARED +#define TkReadBitmapFile_TCL_DECLARED /* 78 */ -EXTERN int TkReadBitmapFile _ANSI_ARGS_((Display *display, - Drawable d, CONST char *filename, +EXTERN int TkReadBitmapFile(Display *display, Drawable d, + CONST char *filename, unsigned int *width_return, unsigned int *height_return, Pixmap *bitmap_return, int *x_hot_return, - int *y_hot_return)); + int *y_hot_return); +#endif +#ifndef TkScrollWindow_TCL_DECLARED +#define TkScrollWindow_TCL_DECLARED /* 79 */ -EXTERN int TkScrollWindow _ANSI_ARGS_((Tk_Window tkwin, GC gc, - int x, int y, int width, int height, int dx, - int dy, TkRegion damageRgn)); +EXTERN int TkScrollWindow(Tk_Window tkwin, GC gc, int x, int y, + int width, int height, int dx, int dy, + TkRegion damageRgn); +#endif +#ifndef TkSelDeadWindow_TCL_DECLARED +#define TkSelDeadWindow_TCL_DECLARED /* 80 */ -EXTERN void TkSelDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkSelDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkSelEventProc_TCL_DECLARED +#define TkSelEventProc_TCL_DECLARED /* 81 */ -EXTERN void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin, - XEvent *eventPtr)); +EXTERN void TkSelEventProc(Tk_Window tkwin, XEvent *eventPtr); +#endif +#ifndef TkSelInit_TCL_DECLARED +#define TkSelInit_TCL_DECLARED /* 82 */ -EXTERN void TkSelInit _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void TkSelInit(Tk_Window tkwin); +#endif +#ifndef TkSelPropProc_TCL_DECLARED +#define TkSelPropProc_TCL_DECLARED /* 83 */ -EXTERN void TkSelPropProc _ANSI_ARGS_((XEvent *eventPtr)); +EXTERN void TkSelPropProc(XEvent *eventPtr); +#endif /* Slot 84 is reserved */ +#ifndef TkSetWindowMenuBar_TCL_DECLARED +#define TkSetWindowMenuBar_TCL_DECLARED /* 85 */ -EXTERN void TkSetWindowMenuBar _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN void TkSetWindowMenuBar(Tcl_Interp *interp, Tk_Window tkwin, char *oldMenuName, - char *menuName)); + char *menuName); +#endif +#ifndef TkStringToKeysym_TCL_DECLARED +#define TkStringToKeysym_TCL_DECLARED /* 86 */ -EXTERN KeySym TkStringToKeysym _ANSI_ARGS_((char *name)); +EXTERN KeySym TkStringToKeysym(char *name); +#endif +#ifndef TkThickPolyLineToArea_TCL_DECLARED +#define TkThickPolyLineToArea_TCL_DECLARED /* 87 */ -EXTERN int TkThickPolyLineToArea _ANSI_ARGS_((double *coordPtr, +EXTERN int TkThickPolyLineToArea(double *coordPtr, int numPoints, double width, int capStyle, - int joinStyle, double *rectPtr)); + int joinStyle, double *rectPtr); +#endif +#ifndef TkWmAddToColormapWindows_TCL_DECLARED +#define TkWmAddToColormapWindows_TCL_DECLARED /* 88 */ -EXTERN void TkWmAddToColormapWindows _ANSI_ARGS_(( - TkWindow *winPtr)); +EXTERN void TkWmAddToColormapWindows(TkWindow *winPtr); +#endif +#ifndef TkWmDeadWindow_TCL_DECLARED +#define TkWmDeadWindow_TCL_DECLARED /* 89 */ -EXTERN void TkWmDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkWmDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkWmFocusToplevel_TCL_DECLARED +#define TkWmFocusToplevel_TCL_DECLARED /* 90 */ -EXTERN TkWindow * TkWmFocusToplevel _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN TkWindow * TkWmFocusToplevel(TkWindow *winPtr); +#endif +#ifndef TkWmMapWindow_TCL_DECLARED +#define TkWmMapWindow_TCL_DECLARED /* 91 */ -EXTERN void TkWmMapWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkWmMapWindow(TkWindow *winPtr); +#endif +#ifndef TkWmNewWindow_TCL_DECLARED +#define TkWmNewWindow_TCL_DECLARED /* 92 */ -EXTERN void TkWmNewWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkWmNewWindow(TkWindow *winPtr); +#endif +#ifndef TkWmProtocolEventProc_TCL_DECLARED +#define TkWmProtocolEventProc_TCL_DECLARED /* 93 */ -EXTERN void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow *winPtr, - XEvent *evenvPtr)); +EXTERN void TkWmProtocolEventProc(TkWindow *winPtr, + XEvent *evenvPtr); +#endif +#ifndef TkWmRemoveFromColormapWindows_TCL_DECLARED +#define TkWmRemoveFromColormapWindows_TCL_DECLARED /* 94 */ -EXTERN void TkWmRemoveFromColormapWindows _ANSI_ARGS_(( - TkWindow *winPtr)); +EXTERN void TkWmRemoveFromColormapWindows(TkWindow *winPtr); +#endif +#ifndef TkWmRestackToplevel_TCL_DECLARED +#define TkWmRestackToplevel_TCL_DECLARED /* 95 */ -EXTERN void TkWmRestackToplevel _ANSI_ARGS_((TkWindow *winPtr, - int aboveBelow, TkWindow *otherPtr)); +EXTERN void TkWmRestackToplevel(TkWindow *winPtr, int aboveBelow, + TkWindow *otherPtr); +#endif +#ifndef TkWmSetClass_TCL_DECLARED +#define TkWmSetClass_TCL_DECLARED /* 96 */ -EXTERN void TkWmSetClass _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkWmSetClass(TkWindow *winPtr); +#endif +#ifndef TkWmUnmapWindow_TCL_DECLARED +#define TkWmUnmapWindow_TCL_DECLARED /* 97 */ -EXTERN void TkWmUnmapWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkWmUnmapWindow(TkWindow *winPtr); +#endif +#ifndef TkDebugBitmap_TCL_DECLARED +#define TkDebugBitmap_TCL_DECLARED /* 98 */ -EXTERN Tcl_Obj * TkDebugBitmap _ANSI_ARGS_((Tk_Window tkwin, - char *name)); +EXTERN Tcl_Obj * TkDebugBitmap(Tk_Window tkwin, char *name); +#endif +#ifndef TkDebugBorder_TCL_DECLARED +#define TkDebugBorder_TCL_DECLARED /* 99 */ -EXTERN Tcl_Obj * TkDebugBorder _ANSI_ARGS_((Tk_Window tkwin, - char *name)); +EXTERN Tcl_Obj * TkDebugBorder(Tk_Window tkwin, char *name); +#endif +#ifndef TkDebugCursor_TCL_DECLARED +#define TkDebugCursor_TCL_DECLARED /* 100 */ -EXTERN Tcl_Obj * TkDebugCursor _ANSI_ARGS_((Tk_Window tkwin, - char *name)); +EXTERN Tcl_Obj * TkDebugCursor(Tk_Window tkwin, char *name); +#endif +#ifndef TkDebugColor_TCL_DECLARED +#define TkDebugColor_TCL_DECLARED /* 101 */ -EXTERN Tcl_Obj * TkDebugColor _ANSI_ARGS_((Tk_Window tkwin, - char *name)); +EXTERN Tcl_Obj * TkDebugColor(Tk_Window tkwin, char *name); +#endif +#ifndef TkDebugConfig_TCL_DECLARED +#define TkDebugConfig_TCL_DECLARED /* 102 */ -EXTERN Tcl_Obj * TkDebugConfig _ANSI_ARGS_((Tcl_Interp *interp, - Tk_OptionTable table)); +EXTERN Tcl_Obj * TkDebugConfig(Tcl_Interp *interp, + Tk_OptionTable table); +#endif +#ifndef TkDebugFont_TCL_DECLARED +#define TkDebugFont_TCL_DECLARED /* 103 */ -EXTERN Tcl_Obj * TkDebugFont _ANSI_ARGS_((Tk_Window tkwin, char *name)); +EXTERN Tcl_Obj * TkDebugFont(Tk_Window tkwin, char *name); +#endif +#ifndef TkFindStateNumObj_TCL_DECLARED +#define TkFindStateNumObj_TCL_DECLARED /* 104 */ -EXTERN int TkFindStateNumObj _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int TkFindStateNumObj(Tcl_Interp *interp, Tcl_Obj *optionPtr, CONST TkStateMap *mapPtr, - Tcl_Obj *keyPtr)); + Tcl_Obj *keyPtr); +#endif +#ifndef TkGetBitmapPredefTable_TCL_DECLARED +#define TkGetBitmapPredefTable_TCL_DECLARED /* 105 */ -EXTERN Tcl_HashTable * TkGetBitmapPredefTable _ANSI_ARGS_((void)); +EXTERN Tcl_HashTable * TkGetBitmapPredefTable(void); +#endif +#ifndef TkGetDisplayList_TCL_DECLARED +#define TkGetDisplayList_TCL_DECLARED /* 106 */ -EXTERN TkDisplay * TkGetDisplayList _ANSI_ARGS_((void)); +EXTERN TkDisplay * TkGetDisplayList(void); +#endif +#ifndef TkGetMainInfoList_TCL_DECLARED +#define TkGetMainInfoList_TCL_DECLARED /* 107 */ -EXTERN TkMainInfo * TkGetMainInfoList _ANSI_ARGS_((void)); +EXTERN TkMainInfo * TkGetMainInfoList(void); +#endif +#ifndef TkGetWindowFromObj_TCL_DECLARED +#define TkGetWindowFromObj_TCL_DECLARED /* 108 */ -EXTERN int TkGetWindowFromObj _ANSI_ARGS_((Tcl_Interp *interp, +EXTERN int TkGetWindowFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, - Tk_Window *windowPtr)); + Tk_Window *windowPtr); +#endif +#ifndef TkpGetString_TCL_DECLARED +#define TkpGetString_TCL_DECLARED /* 109 */ -EXTERN char * TkpGetString _ANSI_ARGS_((TkWindow *winPtr, - XEvent *eventPtr, Tcl_DString *dsPtr)); +EXTERN char * TkpGetString(TkWindow *winPtr, XEvent *eventPtr, + Tcl_DString *dsPtr); +#endif +#ifndef TkpGetSubFonts_TCL_DECLARED +#define TkpGetSubFonts_TCL_DECLARED /* 110 */ -EXTERN void TkpGetSubFonts _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Font tkfont)); +EXTERN void TkpGetSubFonts(Tcl_Interp *interp, Tk_Font tkfont); +#endif +#ifndef TkpGetSystemDefault_TCL_DECLARED +#define TkpGetSystemDefault_TCL_DECLARED /* 111 */ -EXTERN Tcl_Obj * TkpGetSystemDefault _ANSI_ARGS_((Tk_Window tkwin, - CONST char *dbName, CONST char *className)); +EXTERN Tcl_Obj * TkpGetSystemDefault(Tk_Window tkwin, + CONST char *dbName, CONST char *className); +#endif +#ifndef TkpMenuThreadInit_TCL_DECLARED +#define TkpMenuThreadInit_TCL_DECLARED /* 112 */ -EXTERN void TkpMenuThreadInit _ANSI_ARGS_((void)); -#ifdef __WIN32__ -/* 113 */ -EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, - XRectangle *rect_return)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void TkpMenuThreadInit(void); +#endif +#ifdef __WIN32__ /* WIN */ +#ifndef TkClipBox_TCL_DECLARED +#define TkClipBox_TCL_DECLARED /* 113 */ -EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, - XRectangle *rect_return)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN void TkClipBox(TkRegion rgn, XRectangle *rect_return); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkClipBox_TCL_DECLARED +#define TkClipBox_TCL_DECLARED /* 113 */ -EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn, - XRectangle *rect_return)); -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -/* 114 */ -EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void TkClipBox(TkRegion rgn, XRectangle *rect_return); +#endif +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ +#ifndef TkCreateRegion_TCL_DECLARED +#define TkCreateRegion_TCL_DECLARED /* 114 */ -EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN TkRegion TkCreateRegion(void); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkCreateRegion_TCL_DECLARED +#define TkCreateRegion_TCL_DECLARED /* 114 */ -EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void)); -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -/* 115 */ -EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN TkRegion TkCreateRegion(void); +#endif +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ +#ifndef TkDestroyRegion_TCL_DECLARED +#define TkDestroyRegion_TCL_DECLARED /* 115 */ -EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN void TkDestroyRegion(TkRegion rgn); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkDestroyRegion_TCL_DECLARED +#define TkDestroyRegion_TCL_DECLARED /* 115 */ -EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn)); -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -/* 116 */ -EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, - TkRegion srcb, TkRegion dr_return)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void TkDestroyRegion(TkRegion rgn); +#endif +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ +#ifndef TkIntersectRegion_TCL_DECLARED +#define TkIntersectRegion_TCL_DECLARED /* 116 */ -EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, - TkRegion srcb, TkRegion dr_return)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN void TkIntersectRegion(TkRegion sra, TkRegion srcb, + TkRegion dr_return); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkIntersectRegion_TCL_DECLARED +#define TkIntersectRegion_TCL_DECLARED /* 116 */ -EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra, - TkRegion srcb, TkRegion dr_return)); -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -/* 117 */ -EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, - int y, unsigned int width, - unsigned int height)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void TkIntersectRegion(TkRegion sra, TkRegion srcb, + TkRegion dr_return); +#endif +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ +#ifndef TkRectInRegion_TCL_DECLARED +#define TkRectInRegion_TCL_DECLARED /* 117 */ -EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, - int y, unsigned int width, - unsigned int height)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN int TkRectInRegion(TkRegion rgn, int x, int y, + unsigned int width, unsigned int height); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkRectInRegion_TCL_DECLARED +#define TkRectInRegion_TCL_DECLARED /* 117 */ -EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x, - int y, unsigned int width, - unsigned int height)); -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -/* 118 */ -EXTERN void TkSetRegion _ANSI_ARGS_((Display *display, GC gc, - TkRegion rgn)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN int TkRectInRegion(TkRegion rgn, int x, int y, + unsigned int width, unsigned int height); +#endif +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ +#ifndef TkSetRegion_TCL_DECLARED +#define TkSetRegion_TCL_DECLARED /* 118 */ -EXTERN void TkSetRegion _ANSI_ARGS_((Display *display, GC gc, - TkRegion rgn)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN void TkSetRegion(Display *display, GC gc, TkRegion rgn); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkSetRegion_TCL_DECLARED +#define TkSetRegion_TCL_DECLARED /* 118 */ -EXTERN void TkSetRegion _ANSI_ARGS_((Display *display, GC gc, - TkRegion rgn)); -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -/* 119 */ -EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle *rect, - TkRegion src, TkRegion dr_return)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void TkSetRegion(Display *display, GC gc, TkRegion rgn); +#endif +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ +#ifndef TkUnionRectWithRegion_TCL_DECLARED +#define TkUnionRectWithRegion_TCL_DECLARED /* 119 */ -EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle *rect, - TkRegion src, TkRegion dr_return)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN void TkUnionRectWithRegion(XRectangle *rect, TkRegion src, + TkRegion dr_return); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkUnionRectWithRegion_TCL_DECLARED +#define TkUnionRectWithRegion_TCL_DECLARED /* 119 */ -EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle *rect, - TkRegion src, TkRegion dr_return)); -#endif /* MAC_OSX_TK */ +EXTERN void TkUnionRectWithRegion(XRectangle *rect, TkRegion src, + TkRegion dr_return); +#endif +#endif /* AQUA */ /* Slot 120 is reserved */ -#ifdef MAC_TCL -/* 121 */ -EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display *display, - CONST char *source)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkpCreateNativeBitmap_TCL_DECLARED +#define TkpCreateNativeBitmap_TCL_DECLARED /* 121 */ -EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display *display, - CONST char *source)); -#endif /* MAC_OSX_TK */ -#ifdef MAC_TCL -/* 122 */ -EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN Pixmap TkpCreateNativeBitmap(Display *display, + CONST char *source); +#endif +#endif /* AQUA */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkpDefineNativeBitmaps_TCL_DECLARED +#define TkpDefineNativeBitmaps_TCL_DECLARED /* 122 */ -EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void)); -#endif /* MAC_OSX_TK */ +EXTERN void TkpDefineNativeBitmaps(void); +#endif +#endif /* AQUA */ /* Slot 123 is reserved */ -#ifdef MAC_TCL -/* 124 */ -EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display *display, - CONST char *name, int *width, int *height)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkpGetNativeAppBitmap_TCL_DECLARED +#define TkpGetNativeAppBitmap_TCL_DECLARED /* 124 */ -EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display *display, - CONST char *name, int *width, int *height)); -#endif /* MAC_OSX_TK */ +EXTERN Pixmap TkpGetNativeAppBitmap(Display *display, + CONST char *name, int *width, int *height); +#endif +#endif /* AQUA */ /* Slot 125 is reserved */ /* Slot 126 is reserved */ /* Slot 127 is reserved */ @@ -504,304 +805,459 @@ EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display *display, /* Slot 132 is reserved */ /* Slot 133 is reserved */ /* Slot 134 is reserved */ +#ifndef TkpDrawHighlightBorder_TCL_DECLARED +#define TkpDrawHighlightBorder_TCL_DECLARED /* 135 */ -EXTERN void TkpDrawHighlightBorder _ANSI_ARGS_((Tk_Window tkwin, - GC fgGC, GC bgGC, int highlightWidth, - Drawable drawable)); +EXTERN void TkpDrawHighlightBorder(Tk_Window tkwin, GC fgGC, + GC bgGC, int highlightWidth, + Drawable drawable); +#endif +#ifndef TkSetFocusWin_TCL_DECLARED +#define TkSetFocusWin_TCL_DECLARED /* 136 */ -EXTERN void TkSetFocusWin _ANSI_ARGS_((TkWindow *winPtr, - int force)); +EXTERN void TkSetFocusWin(TkWindow *winPtr, int force); +#endif +#ifndef TkpSetKeycodeAndState_TCL_DECLARED +#define TkpSetKeycodeAndState_TCL_DECLARED /* 137 */ -EXTERN void TkpSetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin, - KeySym keySym, XEvent *eventPtr)); +EXTERN void TkpSetKeycodeAndState(Tk_Window tkwin, KeySym keySym, + XEvent *eventPtr); +#endif +#ifndef TkpGetKeySym_TCL_DECLARED +#define TkpGetKeySym_TCL_DECLARED /* 138 */ -EXTERN KeySym TkpGetKeySym _ANSI_ARGS_((TkDisplay *dispPtr, - XEvent *eventPtr)); +EXTERN KeySym TkpGetKeySym(TkDisplay *dispPtr, XEvent *eventPtr); +#endif +#ifndef TkpInitKeymapInfo_TCL_DECLARED +#define TkpInitKeymapInfo_TCL_DECLARED /* 139 */ -EXTERN void TkpInitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkpInitKeymapInfo(TkDisplay *dispPtr); +#endif +#ifndef TkPhotoGetValidRegion_TCL_DECLARED +#define TkPhotoGetValidRegion_TCL_DECLARED /* 140 */ -EXTERN TkRegion TkPhotoGetValidRegion _ANSI_ARGS_(( - Tk_PhotoHandle handle)); +EXTERN TkRegion TkPhotoGetValidRegion(Tk_PhotoHandle handle); +#endif +#ifndef TkWmStackorderToplevel_TCL_DECLARED +#define TkWmStackorderToplevel_TCL_DECLARED /* 141 */ -EXTERN TkWindow ** TkWmStackorderToplevel _ANSI_ARGS_(( - TkWindow *parentPtr)); +EXTERN TkWindow ** TkWmStackorderToplevel(TkWindow *parentPtr); +#endif +#ifndef TkFocusFree_TCL_DECLARED +#define TkFocusFree_TCL_DECLARED /* 142 */ -EXTERN void TkFocusFree _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkFocusFree(TkMainInfo *mainPtr); +#endif +#ifndef TkClipCleanup_TCL_DECLARED +#define TkClipCleanup_TCL_DECLARED /* 143 */ -EXTERN void TkClipCleanup _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkClipCleanup(TkDisplay *dispPtr); +#endif +#ifndef TkGCCleanup_TCL_DECLARED +#define TkGCCleanup_TCL_DECLARED /* 144 */ -EXTERN void TkGCCleanup _ANSI_ARGS_((TkDisplay *dispPtr)); -#ifdef __WIN32__ -/* 145 */ -EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra, - TkRegion srcb, TkRegion dr_return)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void TkGCCleanup(TkDisplay *dispPtr); +#endif +#ifdef __WIN32__ /* WIN */ +#ifndef TkSubtractRegion_TCL_DECLARED +#define TkSubtractRegion_TCL_DECLARED /* 145 */ -EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra, - TkRegion srcb, TkRegion dr_return)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN void TkSubtractRegion(TkRegion sra, TkRegion srcb, + TkRegion dr_return); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkSubtractRegion_TCL_DECLARED +#define TkSubtractRegion_TCL_DECLARED /* 145 */ -EXTERN void TkSubtractRegion _ANSI_ARGS_((TkRegion sra, - TkRegion srcb, TkRegion dr_return)); -#endif /* MAC_OSX_TK */ +EXTERN void TkSubtractRegion(TkRegion sra, TkRegion srcb, + TkRegion dr_return); +#endif +#endif /* AQUA */ +#ifndef TkStylePkgInit_TCL_DECLARED +#define TkStylePkgInit_TCL_DECLARED /* 146 */ -EXTERN void TkStylePkgInit _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkStylePkgInit(TkMainInfo *mainPtr); +#endif +#ifndef TkStylePkgFree_TCL_DECLARED +#define TkStylePkgFree_TCL_DECLARED /* 147 */ -EXTERN void TkStylePkgFree _ANSI_ARGS_((TkMainInfo *mainPtr)); +EXTERN void TkStylePkgFree(TkMainInfo *mainPtr); +#endif +#ifndef TkToplevelWindowForCommand_TCL_DECLARED +#define TkToplevelWindowForCommand_TCL_DECLARED /* 148 */ -EXTERN Tk_Window TkToplevelWindowForCommand _ANSI_ARGS_(( - Tcl_Interp *interp, CONST char *cmdName)); +EXTERN Tk_Window TkToplevelWindowForCommand(Tcl_Interp *interp, + CONST char *cmdName); +#endif +#ifndef TkGetOptionSpec_TCL_DECLARED +#define TkGetOptionSpec_TCL_DECLARED /* 149 */ -EXTERN CONST Tk_OptionSpec * TkGetOptionSpec _ANSI_ARGS_((CONST char *name, - Tk_OptionTable optionTable)); -/* Slot 150 is reserved */ -/* Slot 151 is reserved */ +EXTERN CONST Tk_OptionSpec * TkGetOptionSpec(CONST char *name, + Tk_OptionTable optionTable); +#endif +#ifndef TkMakeRawCurve_TCL_DECLARED +#define TkMakeRawCurve_TCL_DECLARED +/* 150 */ +EXTERN int TkMakeRawCurve(Tk_Canvas canvas, double *pointPtr, + int numPoints, int numSteps, + XPoint xPoints[], double dblPoints[]); +#endif +#ifndef TkMakeRawCurvePostscript_TCL_DECLARED +#define TkMakeRawCurvePostscript_TCL_DECLARED +/* 151 */ +EXTERN void TkMakeRawCurvePostscript(Tcl_Interp *interp, + Tk_Canvas canvas, double *pointPtr, + int numPoints); +#endif +#ifndef TkpDrawFrame_TCL_DECLARED +#define TkpDrawFrame_TCL_DECLARED /* 152 */ -EXTERN void TkpDrawFrame _ANSI_ARGS_((Tk_Window tkwin, - Tk_3DBorder border, int highlightWidth, - int borderWidth, int relief)); +EXTERN void TkpDrawFrame(Tk_Window tkwin, Tk_3DBorder border, + int highlightWidth, int borderWidth, + int relief); +#endif +#ifndef TkCreateThreadExitHandler_TCL_DECLARED +#define TkCreateThreadExitHandler_TCL_DECLARED +/* 153 */ +EXTERN void TkCreateThreadExitHandler(Tcl_ExitProc *proc, + ClientData clientData); +#endif +#ifndef TkDeleteThreadExitHandler_TCL_DECLARED +#define TkDeleteThreadExitHandler_TCL_DECLARED +/* 154 */ +EXTERN void TkDeleteThreadExitHandler(Tcl_ExitProc *proc, + ClientData clientData); +#endif +/* Slot 155 is reserved */ +#ifndef TkpTestembedCmd_TCL_DECLARED +#define TkpTestembedCmd_TCL_DECLARED +/* 156 */ +EXTERN int TkpTestembedCmd(ClientData clientData, + Tcl_Interp *interp, int argc, + CONST char **argv); +#endif +#ifndef TkpTesttextCmd_TCL_DECLARED +#define TkpTesttextCmd_TCL_DECLARED +/* 157 */ +EXTERN int TkpTesttextCmd(ClientData dummy, Tcl_Interp *interp, + int argc, CONST char **argv); +#endif +/* Slot 158 is reserved */ +/* Slot 159 is reserved */ +/* Slot 160 is reserved */ +/* Slot 161 is reserved */ +/* Slot 162 is reserved */ +/* Slot 163 is reserved */ +/* Slot 164 is reserved */ +/* Slot 165 is reserved */ +/* Slot 166 is reserved */ +/* Slot 167 is reserved */ +/* Slot 168 is reserved */ +#ifndef TkStateParseProc_TCL_DECLARED +#define TkStateParseProc_TCL_DECLARED +/* 169 */ +EXTERN int TkStateParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef TkStatePrintProc_TCL_DECLARED +#define TkStatePrintProc_TCL_DECLARED +/* 170 */ +EXTERN char * TkStatePrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif +#ifndef TkCanvasDashParseProc_TCL_DECLARED +#define TkCanvasDashParseProc_TCL_DECLARED +/* 171 */ +EXTERN int TkCanvasDashParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef TkCanvasDashPrintProc_TCL_DECLARED +#define TkCanvasDashPrintProc_TCL_DECLARED +/* 172 */ +EXTERN char * TkCanvasDashPrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif +#ifndef TkOffsetParseProc_TCL_DECLARED +#define TkOffsetParseProc_TCL_DECLARED +/* 173 */ +EXTERN int TkOffsetParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef TkOffsetPrintProc_TCL_DECLARED +#define TkOffsetPrintProc_TCL_DECLARED +/* 174 */ +EXTERN char * TkOffsetPrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif +#ifndef TkPixelParseProc_TCL_DECLARED +#define TkPixelParseProc_TCL_DECLARED +/* 175 */ +EXTERN int TkPixelParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef TkPixelPrintProc_TCL_DECLARED +#define TkPixelPrintProc_TCL_DECLARED +/* 176 */ +EXTERN char * TkPixelPrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif +#ifndef TkOrientParseProc_TCL_DECLARED +#define TkOrientParseProc_TCL_DECLARED +/* 177 */ +EXTERN int TkOrientParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef TkOrientPrintProc_TCL_DECLARED +#define TkOrientPrintProc_TCL_DECLARED +/* 178 */ +EXTERN char * TkOrientPrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif +#ifndef TkSmoothParseProc_TCL_DECLARED +#define TkSmoothParseProc_TCL_DECLARED +/* 179 */ +EXTERN int TkSmoothParseProc(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + CONST char *value, char *widgRec, int offset); +#endif +#ifndef TkSmoothPrintProc_TCL_DECLARED +#define TkSmoothPrintProc_TCL_DECLARED +/* 180 */ +EXTERN char * TkSmoothPrintProc(ClientData clientData, + Tk_Window tkwin, char *widgRec, int offset, + Tcl_FreeProc **freeProcPtr); +#endif typedef struct TkIntStubs { int magic; struct TkIntStubHooks *hooks; - TkWindow * (*tkAllocWindow) _ANSI_ARGS_((TkDisplay *dispPtr, int screenNum, TkWindow *parentPtr)); /* 0 */ - void (*tkBezierPoints) _ANSI_ARGS_((double control[], int numSteps, double *coordPtr)); /* 1 */ - void (*tkBezierScreenPoints) _ANSI_ARGS_((Tk_Canvas canvas, double control[], int numSteps, XPoint *xPointPtr)); /* 2 */ - void (*tkBindDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 3 */ - void (*tkBindEventProc) _ANSI_ARGS_((TkWindow *winPtr, XEvent *eventPtr)); /* 4 */ - void (*tkBindFree) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 5 */ - void (*tkBindInit) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 6 */ - void (*tkChangeEventWindow) _ANSI_ARGS_((XEvent *eventPtr, TkWindow *winPtr)); /* 7 */ - int (*tkClipInit) _ANSI_ARGS_((Tcl_Interp *interp, TkDisplay *dispPtr)); /* 8 */ - void (*tkComputeAnchor) _ANSI_ARGS_((Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int *xPtr, int *yPtr)); /* 9 */ - int (*tkCopyAndGlobalEval) _ANSI_ARGS_((Tcl_Interp *interp, char *script)); /* 10 */ - unsigned long (*tkCreateBindingProcedure) _ANSI_ARGS_((Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventString, TkBindEvalProc *evalProc, TkBindFreeProc *freeProc, ClientData clientData)); /* 11 */ - TkCursor * (*tkCreateCursorFromData) _ANSI_ARGS_((Tk_Window tkwin, CONST char *source, CONST char *mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg)); /* 12 */ - int (*tkCreateFrame) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv, int toplevel, char *appName)); /* 13 */ - Tk_Window (*tkCreateMainWindow) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *screenName, char *baseName)); /* 14 */ - Time (*tkCurrentTime) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 15 */ - void (*tkDeleteAllImages) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 16 */ - void (*tkDoConfigureNotify) _ANSI_ARGS_((TkWindow *winPtr)); /* 17 */ - void (*tkDrawInsetFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding)); /* 18 */ - void (*tkEventDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 19 */ - void (*tkFillPolygon) _ANSI_ARGS_((Tk_Canvas canvas, double *coordPtr, int numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC)); /* 20 */ - int (*tkFindStateNum) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *option, CONST TkStateMap *mapPtr, CONST char *strKey)); /* 21 */ - char * (*tkFindStateString) _ANSI_ARGS_((CONST TkStateMap *mapPtr, int numKey)); /* 22 */ - void (*tkFocusDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 23 */ - int (*tkFocusFilterEvent) _ANSI_ARGS_((TkWindow *winPtr, XEvent *eventPtr)); /* 24 */ - TkWindow * (*tkFocusKeyEvent) _ANSI_ARGS_((TkWindow *winPtr, XEvent *eventPtr)); /* 25 */ - void (*tkFontPkgInit) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 26 */ - void (*tkFontPkgFree) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 27 */ - void (*tkFreeBindingTags) _ANSI_ARGS_((TkWindow *winPtr)); /* 28 */ - void (*tkpFreeCursor) _ANSI_ARGS_((TkCursor *cursorPtr)); /* 29 */ - char * (*tkGetBitmapData) _ANSI_ARGS_((Tcl_Interp *interp, char *string, char *fileName, int *widthPtr, int *heightPtr, int *hotXPtr, int *hotYPtr)); /* 30 */ - void (*tkGetButtPoints) _ANSI_ARGS_((double p1[], double p2[], double width, int project, double m1[], double m2[])); /* 31 */ - TkCursor * (*tkGetCursorByName) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid string)); /* 32 */ - CONST84_RETURN char * (*tkGetDefaultScreenName) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *screenName)); /* 33 */ - TkDisplay * (*tkGetDisplay) _ANSI_ARGS_((Display *display)); /* 34 */ - int (*tkGetDisplayOf) _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[], Tk_Window *tkwinPtr)); /* 35 */ - TkWindow * (*tkGetFocusWin) _ANSI_ARGS_((TkWindow *winPtr)); /* 36 */ - int (*tkGetInterpNames) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin)); /* 37 */ - int (*tkGetMiterPoints) _ANSI_ARGS_((double p1[], double p2[], double p3[], double width, double m1[], double m2[])); /* 38 */ - void (*tkGetPointerCoords) _ANSI_ARGS_((Tk_Window tkwin, int *xPtr, int *yPtr)); /* 39 */ - void (*tkGetServerInfo) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin)); /* 40 */ - void (*tkGrabDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 41 */ - int (*tkGrabState) _ANSI_ARGS_((TkWindow *winPtr)); /* 42 */ - void (*tkIncludePoint) _ANSI_ARGS_((Tk_Item *itemPtr, double *pointPtr)); /* 43 */ - void (*tkInOutEvents) _ANSI_ARGS_((XEvent *eventPtr, TkWindow *sourcePtr, TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position)); /* 44 */ - void (*tkInstallFrameMenu) _ANSI_ARGS_((Tk_Window tkwin)); /* 45 */ - char * (*tkKeysymToString) _ANSI_ARGS_((KeySym keysym)); /* 46 */ - int (*tkLineToArea) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double rectPtr[])); /* 47 */ - double (*tkLineToPoint) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double pointPtr[])); /* 48 */ - int (*tkMakeBezierCurve) _ANSI_ARGS_((Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[])); /* 49 */ - void (*tkMakeBezierPostscript) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints)); /* 50 */ - void (*tkOptionClassChanged) _ANSI_ARGS_((TkWindow *winPtr)); /* 51 */ - void (*tkOptionDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 52 */ - int (*tkOvalToArea) _ANSI_ARGS_((double *ovalPtr, double *rectPtr)); /* 53 */ - double (*tkOvalToPoint) _ANSI_ARGS_((double ovalPtr[], double width, int filled, double pointPtr[])); /* 54 */ - int (*tkpChangeFocus) _ANSI_ARGS_((TkWindow *winPtr, int force)); /* 55 */ - void (*tkpCloseDisplay) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 56 */ - void (*tkpClaimFocus) _ANSI_ARGS_((TkWindow *topLevelPtr, int force)); /* 57 */ - void (*tkpDisplayWarning) _ANSI_ARGS_((CONST char *msg, CONST char *title)); /* 58 */ - void (*tkpGetAppName) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_DString *name)); /* 59 */ - TkWindow * (*tkpGetOtherWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 60 */ - TkWindow * (*tkpGetWrapperWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 61 */ - int (*tkpInit) _ANSI_ARGS_((Tcl_Interp *interp)); /* 62 */ - void (*tkpInitializeMenuBindings) _ANSI_ARGS_((Tcl_Interp *interp, Tk_BindingTable bindingTable)); /* 63 */ - void (*tkpMakeContainer) _ANSI_ARGS_((Tk_Window tkwin)); /* 64 */ - void (*tkpMakeMenuWindow) _ANSI_ARGS_((Tk_Window tkwin, int transient)); /* 65 */ - Window (*tkpMakeWindow) _ANSI_ARGS_((TkWindow *winPtr, Window parent)); /* 66 */ - void (*tkpMenuNotifyToplevelCreate) _ANSI_ARGS_((Tcl_Interp *interp1, char *menuName)); /* 67 */ - TkDisplay * (*tkpOpenDisplay) _ANSI_ARGS_((CONST char *display_name)); /* 68 */ - int (*tkPointerEvent) _ANSI_ARGS_((XEvent *eventPtr, TkWindow *winPtr)); /* 69 */ - int (*tkPolygonToArea) _ANSI_ARGS_((double *polyPtr, int numPoints, double *rectPtr)); /* 70 */ - double (*tkPolygonToPoint) _ANSI_ARGS_((double *polyPtr, int numPoints, double *pointPtr)); /* 71 */ - int (*tkPositionInTree) _ANSI_ARGS_((TkWindow *winPtr, TkWindow *treePtr)); /* 72 */ - void (*tkpRedirectKeyEvent) _ANSI_ARGS_((TkWindow *winPtr, XEvent *eventPtr)); /* 73 */ - void (*tkpSetMainMenubar) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, char *menuName)); /* 74 */ - int (*tkpUseWindow) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, CONST char *string)); /* 75 */ - int (*tkpWindowWasRecentlyDeleted) _ANSI_ARGS_((Window win, TkDisplay *dispPtr)); /* 76 */ - void (*tkQueueEventForAllChildren) _ANSI_ARGS_((TkWindow *winPtr, XEvent *eventPtr)); /* 77 */ - int (*tkReadBitmapFile) _ANSI_ARGS_((Display *display, Drawable d, CONST char *filename, unsigned int *width_return, unsigned int *height_return, Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return)); /* 78 */ - int (*tkScrollWindow) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn)); /* 79 */ - void (*tkSelDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 80 */ - void (*tkSelEventProc) _ANSI_ARGS_((Tk_Window tkwin, XEvent *eventPtr)); /* 81 */ - void (*tkSelInit) _ANSI_ARGS_((Tk_Window tkwin)); /* 82 */ - void (*tkSelPropProc) _ANSI_ARGS_((XEvent *eventPtr)); /* 83 */ + TkWindow * (*tkAllocWindow) (TkDisplay *dispPtr, int screenNum, TkWindow *parentPtr); /* 0 */ + void (*tkBezierPoints) (double control[], int numSteps, double *coordPtr); /* 1 */ + void (*tkBezierScreenPoints) (Tk_Canvas canvas, double control[], int numSteps, XPoint *xPointPtr); /* 2 */ + void (*tkBindDeadWindow) (TkWindow *winPtr); /* 3 */ + void (*tkBindEventProc) (TkWindow *winPtr, XEvent *eventPtr); /* 4 */ + void (*tkBindFree) (TkMainInfo *mainPtr); /* 5 */ + void (*tkBindInit) (TkMainInfo *mainPtr); /* 6 */ + void (*tkChangeEventWindow) (XEvent *eventPtr, TkWindow *winPtr); /* 7 */ + int (*tkClipInit) (Tcl_Interp *interp, TkDisplay *dispPtr); /* 8 */ + void (*tkComputeAnchor) (Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int *xPtr, int *yPtr); /* 9 */ + int (*tkCopyAndGlobalEval) (Tcl_Interp *interp, char *script); /* 10 */ + unsigned long (*tkCreateBindingProcedure) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, CONST char *eventString, TkBindEvalProc *evalProc, TkBindFreeProc *freeProc, ClientData clientData); /* 11 */ + TkCursor * (*tkCreateCursorFromData) (Tk_Window tkwin, CONST char *source, CONST char *mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg); /* 12 */ + int (*tkCreateFrame) (ClientData clientData, Tcl_Interp *interp, int argc, char **argv, int toplevel, char *appName); /* 13 */ + Tk_Window (*tkCreateMainWindow) (Tcl_Interp *interp, CONST char *screenName, char *baseName); /* 14 */ + Time (*tkCurrentTime) (TkDisplay *dispPtr); /* 15 */ + void (*tkDeleteAllImages) (TkMainInfo *mainPtr); /* 16 */ + void (*tkDoConfigureNotify) (TkWindow *winPtr); /* 17 */ + void (*tkDrawInsetFocusHighlight) (Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding); /* 18 */ + void (*tkEventDeadWindow) (TkWindow *winPtr); /* 19 */ + void (*tkFillPolygon) (Tk_Canvas canvas, double *coordPtr, int numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC); /* 20 */ + int (*tkFindStateNum) (Tcl_Interp *interp, CONST char *option, CONST TkStateMap *mapPtr, CONST char *strKey); /* 21 */ + char * (*tkFindStateString) (CONST TkStateMap *mapPtr, int numKey); /* 22 */ + void (*tkFocusDeadWindow) (TkWindow *winPtr); /* 23 */ + int (*tkFocusFilterEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 24 */ + TkWindow * (*tkFocusKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 25 */ + void (*tkFontPkgInit) (TkMainInfo *mainPtr); /* 26 */ + void (*tkFontPkgFree) (TkMainInfo *mainPtr); /* 27 */ + void (*tkFreeBindingTags) (TkWindow *winPtr); /* 28 */ + void (*tkpFreeCursor) (TkCursor *cursorPtr); /* 29 */ + char * (*tkGetBitmapData) (Tcl_Interp *interp, char *string, char *fileName, int *widthPtr, int *heightPtr, int *hotXPtr, int *hotYPtr); /* 30 */ + void (*tkGetButtPoints) (double p1[], double p2[], double width, int project, double m1[], double m2[]); /* 31 */ + TkCursor * (*tkGetCursorByName) (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid string); /* 32 */ + CONST84_RETURN char * (*tkGetDefaultScreenName) (Tcl_Interp *interp, CONST char *screenName); /* 33 */ + TkDisplay * (*tkGetDisplay) (Display *display); /* 34 */ + int (*tkGetDisplayOf) (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], Tk_Window *tkwinPtr); /* 35 */ + TkWindow * (*tkGetFocusWin) (TkWindow *winPtr); /* 36 */ + int (*tkGetInterpNames) (Tcl_Interp *interp, Tk_Window tkwin); /* 37 */ + int (*tkGetMiterPoints) (double p1[], double p2[], double p3[], double width, double m1[], double m2[]); /* 38 */ + void (*tkGetPointerCoords) (Tk_Window tkwin, int *xPtr, int *yPtr); /* 39 */ + void (*tkGetServerInfo) (Tcl_Interp *interp, Tk_Window tkwin); /* 40 */ + void (*tkGrabDeadWindow) (TkWindow *winPtr); /* 41 */ + int (*tkGrabState) (TkWindow *winPtr); /* 42 */ + void (*tkIncludePoint) (Tk_Item *itemPtr, double *pointPtr); /* 43 */ + void (*tkInOutEvents) (XEvent *eventPtr, TkWindow *sourcePtr, TkWindow *destPtr, int leaveType, int enterType, Tcl_QueuePosition position); /* 44 */ + void (*tkInstallFrameMenu) (Tk_Window tkwin); /* 45 */ + char * (*tkKeysymToString) (KeySym keysym); /* 46 */ + int (*tkLineToArea) (double end1Ptr[], double end2Ptr[], double rectPtr[]); /* 47 */ + double (*tkLineToPoint) (double end1Ptr[], double end2Ptr[], double pointPtr[]); /* 48 */ + int (*tkMakeBezierCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 49 */ + void (*tkMakeBezierPostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 50 */ + void (*tkOptionClassChanged) (TkWindow *winPtr); /* 51 */ + void (*tkOptionDeadWindow) (TkWindow *winPtr); /* 52 */ + int (*tkOvalToArea) (double *ovalPtr, double *rectPtr); /* 53 */ + double (*tkOvalToPoint) (double ovalPtr[], double width, int filled, double pointPtr[]); /* 54 */ + int (*tkpChangeFocus) (TkWindow *winPtr, int force); /* 55 */ + void (*tkpCloseDisplay) (TkDisplay *dispPtr); /* 56 */ + void (*tkpClaimFocus) (TkWindow *topLevelPtr, int force); /* 57 */ + void (*tkpDisplayWarning) (CONST char *msg, CONST char *title); /* 58 */ + void (*tkpGetAppName) (Tcl_Interp *interp, Tcl_DString *name); /* 59 */ + TkWindow * (*tkpGetOtherWindow) (TkWindow *winPtr); /* 60 */ + TkWindow * (*tkpGetWrapperWindow) (TkWindow *winPtr); /* 61 */ + int (*tkpInit) (Tcl_Interp *interp); /* 62 */ + void (*tkpInitializeMenuBindings) (Tcl_Interp *interp, Tk_BindingTable bindingTable); /* 63 */ + void (*tkpMakeContainer) (Tk_Window tkwin); /* 64 */ + void (*tkpMakeMenuWindow) (Tk_Window tkwin, int transient); /* 65 */ + Window (*tkpMakeWindow) (TkWindow *winPtr, Window parent); /* 66 */ + void (*tkpMenuNotifyToplevelCreate) (Tcl_Interp *interp, char *menuName); /* 67 */ + TkDisplay * (*tkpOpenDisplay) (CONST char *display_name); /* 68 */ + int (*tkPointerEvent) (XEvent *eventPtr, TkWindow *winPtr); /* 69 */ + int (*tkPolygonToArea) (double *polyPtr, int numPoints, double *rectPtr); /* 70 */ + double (*tkPolygonToPoint) (double *polyPtr, int numPoints, double *pointPtr); /* 71 */ + int (*tkPositionInTree) (TkWindow *winPtr, TkWindow *treePtr); /* 72 */ + void (*tkpRedirectKeyEvent) (TkWindow *winPtr, XEvent *eventPtr); /* 73 */ + void (*tkpSetMainMenubar) (Tcl_Interp *interp, Tk_Window tkwin, char *menuName); /* 74 */ + int (*tkpUseWindow) (Tcl_Interp *interp, Tk_Window tkwin, CONST char *string); /* 75 */ + int (*tkpWindowWasRecentlyDeleted) (Window win, TkDisplay *dispPtr); /* 76 */ + void (*tkQueueEventForAllChildren) (TkWindow *winPtr, XEvent *eventPtr); /* 77 */ + int (*tkReadBitmapFile) (Display *display, Drawable d, CONST char *filename, unsigned int *width_return, unsigned int *height_return, Pixmap *bitmap_return, int *x_hot_return, int *y_hot_return); /* 78 */ + int (*tkScrollWindow) (Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn); /* 79 */ + void (*tkSelDeadWindow) (TkWindow *winPtr); /* 80 */ + void (*tkSelEventProc) (Tk_Window tkwin, XEvent *eventPtr); /* 81 */ + void (*tkSelInit) (Tk_Window tkwin); /* 82 */ + void (*tkSelPropProc) (XEvent *eventPtr); /* 83 */ VOID *reserved84; - void (*tkSetWindowMenuBar) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, char *oldMenuName, char *menuName)); /* 85 */ - KeySym (*tkStringToKeysym) _ANSI_ARGS_((char *name)); /* 86 */ - int (*tkThickPolyLineToArea) _ANSI_ARGS_((double *coordPtr, int numPoints, double width, int capStyle, int joinStyle, double *rectPtr)); /* 87 */ - void (*tkWmAddToColormapWindows) _ANSI_ARGS_((TkWindow *winPtr)); /* 88 */ - void (*tkWmDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 89 */ - TkWindow * (*tkWmFocusToplevel) _ANSI_ARGS_((TkWindow *winPtr)); /* 90 */ - void (*tkWmMapWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 91 */ - void (*tkWmNewWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 92 */ - void (*tkWmProtocolEventProc) _ANSI_ARGS_((TkWindow *winPtr, XEvent *evenvPtr)); /* 93 */ - void (*tkWmRemoveFromColormapWindows) _ANSI_ARGS_((TkWindow *winPtr)); /* 94 */ - void (*tkWmRestackToplevel) _ANSI_ARGS_((TkWindow *winPtr, int aboveBelow, TkWindow *otherPtr)); /* 95 */ - void (*tkWmSetClass) _ANSI_ARGS_((TkWindow *winPtr)); /* 96 */ - void (*tkWmUnmapWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 97 */ - Tcl_Obj * (*tkDebugBitmap) _ANSI_ARGS_((Tk_Window tkwin, char *name)); /* 98 */ - Tcl_Obj * (*tkDebugBorder) _ANSI_ARGS_((Tk_Window tkwin, char *name)); /* 99 */ - Tcl_Obj * (*tkDebugCursor) _ANSI_ARGS_((Tk_Window tkwin, char *name)); /* 100 */ - Tcl_Obj * (*tkDebugColor) _ANSI_ARGS_((Tk_Window tkwin, char *name)); /* 101 */ - Tcl_Obj * (*tkDebugConfig) _ANSI_ARGS_((Tcl_Interp *interp, Tk_OptionTable table)); /* 102 */ - Tcl_Obj * (*tkDebugFont) _ANSI_ARGS_((Tk_Window tkwin, char *name)); /* 103 */ - int (*tkFindStateNumObj) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *optionPtr, CONST TkStateMap *mapPtr, Tcl_Obj *keyPtr)); /* 104 */ - Tcl_HashTable * (*tkGetBitmapPredefTable) _ANSI_ARGS_((void)); /* 105 */ - TkDisplay * (*tkGetDisplayList) _ANSI_ARGS_((void)); /* 106 */ - TkMainInfo * (*tkGetMainInfoList) _ANSI_ARGS_((void)); /* 107 */ - int (*tkGetWindowFromObj) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr)); /* 108 */ - char * (*tkpGetString) _ANSI_ARGS_((TkWindow *winPtr, XEvent *eventPtr, Tcl_DString *dsPtr)); /* 109 */ - void (*tkpGetSubFonts) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Font tkfont)); /* 110 */ - Tcl_Obj * (*tkpGetSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, CONST char *dbName, CONST char *className)); /* 111 */ - void (*tkpMenuThreadInit) _ANSI_ARGS_((void)); /* 112 */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tkSetWindowMenuBar) (Tcl_Interp *interp, Tk_Window tkwin, char *oldMenuName, char *menuName); /* 85 */ + KeySym (*tkStringToKeysym) (char *name); /* 86 */ + int (*tkThickPolyLineToArea) (double *coordPtr, int numPoints, double width, int capStyle, int joinStyle, double *rectPtr); /* 87 */ + void (*tkWmAddToColormapWindows) (TkWindow *winPtr); /* 88 */ + void (*tkWmDeadWindow) (TkWindow *winPtr); /* 89 */ + TkWindow * (*tkWmFocusToplevel) (TkWindow *winPtr); /* 90 */ + void (*tkWmMapWindow) (TkWindow *winPtr); /* 91 */ + void (*tkWmNewWindow) (TkWindow *winPtr); /* 92 */ + void (*tkWmProtocolEventProc) (TkWindow *winPtr, XEvent *evenvPtr); /* 93 */ + void (*tkWmRemoveFromColormapWindows) (TkWindow *winPtr); /* 94 */ + void (*tkWmRestackToplevel) (TkWindow *winPtr, int aboveBelow, TkWindow *otherPtr); /* 95 */ + void (*tkWmSetClass) (TkWindow *winPtr); /* 96 */ + void (*tkWmUnmapWindow) (TkWindow *winPtr); /* 97 */ + Tcl_Obj * (*tkDebugBitmap) (Tk_Window tkwin, char *name); /* 98 */ + Tcl_Obj * (*tkDebugBorder) (Tk_Window tkwin, char *name); /* 99 */ + Tcl_Obj * (*tkDebugCursor) (Tk_Window tkwin, char *name); /* 100 */ + Tcl_Obj * (*tkDebugColor) (Tk_Window tkwin, char *name); /* 101 */ + Tcl_Obj * (*tkDebugConfig) (Tcl_Interp *interp, Tk_OptionTable table); /* 102 */ + Tcl_Obj * (*tkDebugFont) (Tk_Window tkwin, char *name); /* 103 */ + int (*tkFindStateNumObj) (Tcl_Interp *interp, Tcl_Obj *optionPtr, CONST TkStateMap *mapPtr, Tcl_Obj *keyPtr); /* 104 */ + Tcl_HashTable * (*tkGetBitmapPredefTable) (void); /* 105 */ + TkDisplay * (*tkGetDisplayList) (void); /* 106 */ + TkMainInfo * (*tkGetMainInfoList) (void); /* 107 */ + int (*tkGetWindowFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Tk_Window *windowPtr); /* 108 */ + 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 */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved113; -#endif /* UNIX */ -#ifdef __WIN32__ - void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle *rect_return)); /* 113 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle *rect_return)); /* 113 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle *rect_return)); /* 113 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + void (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved113; /* Dummy entry for stubs table backwards compatibility */ + void (*tkClipBox) (TkRegion rgn, XRectangle *rect_return); /* 113 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved114; -#endif /* UNIX */ -#ifdef __WIN32__ - TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + TkRegion (*tkCreateRegion) (void); /* 114 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved114; /* Dummy entry for stubs table backwards compatibility */ + TkRegion (*tkCreateRegion) (void); /* 114 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved115; -#endif /* UNIX */ -#ifdef __WIN32__ - void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + void (*tkDestroyRegion) (TkRegion rgn); /* 115 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved115; /* Dummy entry for stubs table backwards compatibility */ + void (*tkDestroyRegion) (TkRegion rgn); /* 115 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved116; -#endif /* UNIX */ -#ifdef __WIN32__ - void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + void (*tkIntersectRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 116 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved116; /* Dummy entry for stubs table backwards compatibility */ + void (*tkIntersectRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 116 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved117; -#endif /* UNIX */ -#ifdef __WIN32__ - int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + int (*tkRectInRegion) (TkRegion rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved117; /* Dummy entry for stubs table backwards compatibility */ + int (*tkRectInRegion) (TkRegion rgn, int x, int y, unsigned int width, unsigned int height); /* 117 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved118; -#endif /* UNIX */ -#ifdef __WIN32__ - void (*tkSetRegion) _ANSI_ARGS_((Display *display, GC gc, TkRegion rgn)); /* 118 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkSetRegion) _ANSI_ARGS_((Display *display, GC gc, TkRegion rgn)); /* 118 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkSetRegion) _ANSI_ARGS_((Display *display, GC gc, TkRegion rgn)); /* 118 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + void (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved118; /* Dummy entry for stubs table backwards compatibility */ + void (*tkSetRegion) (Display *display, GC gc, TkRegion rgn); /* 118 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved119; -#endif /* UNIX */ -#ifdef __WIN32__ - void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle *rect, TkRegion src, TkRegion dr_return)); /* 119 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle *rect, TkRegion src, TkRegion dr_return)); /* 119 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle *rect, TkRegion src, TkRegion dr_return)); /* 119 */ -#endif /* MAC_OSX_TK */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + void (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved119; /* Dummy entry for stubs table backwards compatibility */ + void (*tkUnionRectWithRegion) (XRectangle *rect, TkRegion src, TkRegion dr_return); /* 119 */ +#endif /* AQUA */ VOID *reserved120; -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved121; -#endif /* UNIX */ -#ifdef __WIN32__ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ VOID *reserved121; -#endif /* __WIN32__ */ -#ifdef MAC_TCL - Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display *display, CONST char *source)); /* 121 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display *display, CONST char *source)); /* 121 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved121; /* Dummy entry for stubs table backwards compatibility */ + Pixmap (*tkpCreateNativeBitmap) (Display *display, CONST char *source); /* 121 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved122; -#endif /* UNIX */ -#ifdef __WIN32__ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ VOID *reserved122; -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */ -#endif /* MAC_OSX_TK */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved122; /* Dummy entry for stubs table backwards compatibility */ + void (*tkpDefineNativeBitmaps) (void); /* 122 */ +#endif /* AQUA */ VOID *reserved123; -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved124; -#endif /* UNIX */ -#ifdef __WIN32__ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ VOID *reserved124; -#endif /* __WIN32__ */ -#ifdef MAC_TCL - Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display *display, CONST char *name, int *width, int *height)); /* 124 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display *display, CONST char *name, int *width, int *height)); /* 124 */ -#endif /* MAC_OSX_TK */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved124; /* Dummy entry for stubs table backwards compatibility */ + Pixmap (*tkpGetNativeAppBitmap) (Display *display, CONST char *name, int *width, int *height); /* 124 */ +#endif /* AQUA */ VOID *reserved125; VOID *reserved126; VOID *reserved127; @@ -812,35 +1268,61 @@ typedef struct TkIntStubs { VOID *reserved132; VOID *reserved133; VOID *reserved134; - void (*tkpDrawHighlightBorder) _ANSI_ARGS_((Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable)); /* 135 */ - void (*tkSetFocusWin) _ANSI_ARGS_((TkWindow *winPtr, int force)); /* 136 */ - void (*tkpSetKeycodeAndState) _ANSI_ARGS_((Tk_Window tkwin, KeySym keySym, XEvent *eventPtr)); /* 137 */ - KeySym (*tkpGetKeySym) _ANSI_ARGS_((TkDisplay *dispPtr, XEvent *eventPtr)); /* 138 */ - void (*tkpInitKeymapInfo) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 139 */ - TkRegion (*tkPhotoGetValidRegion) _ANSI_ARGS_((Tk_PhotoHandle handle)); /* 140 */ - TkWindow ** (*tkWmStackorderToplevel) _ANSI_ARGS_((TkWindow *parentPtr)); /* 141 */ - void (*tkFocusFree) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 142 */ - void (*tkClipCleanup) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 143 */ - void (*tkGCCleanup) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 144 */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ + void (*tkpDrawHighlightBorder) (Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable); /* 135 */ + void (*tkSetFocusWin) (TkWindow *winPtr, int force); /* 136 */ + void (*tkpSetKeycodeAndState) (Tk_Window tkwin, KeySym keySym, XEvent *eventPtr); /* 137 */ + KeySym (*tkpGetKeySym) (TkDisplay *dispPtr, XEvent *eventPtr); /* 138 */ + void (*tkpInitKeymapInfo) (TkDisplay *dispPtr); /* 139 */ + TkRegion (*tkPhotoGetValidRegion) (Tk_PhotoHandle handle); /* 140 */ + TkWindow ** (*tkWmStackorderToplevel) (TkWindow *parentPtr); /* 141 */ + void (*tkFocusFree) (TkMainInfo *mainPtr); /* 142 */ + void (*tkClipCleanup) (TkDisplay *dispPtr); /* 143 */ + void (*tkGCCleanup) (TkDisplay *dispPtr); /* 144 */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ VOID *reserved145; -#endif /* UNIX */ -#ifdef __WIN32__ - void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkSubtractRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 145 */ -#endif /* MAC_OSX_TK */ - void (*tkStylePkgInit) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 146 */ - void (*tkStylePkgFree) _ANSI_ARGS_((TkMainInfo *mainPtr)); /* 147 */ - Tk_Window (*tkToplevelWindowForCommand) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *cmdName)); /* 148 */ - CONST Tk_OptionSpec * (*tkGetOptionSpec) _ANSI_ARGS_((CONST char *name, Tk_OptionTable optionTable)); /* 149 */ - VOID *reserved150; - VOID *reserved151; - void (*tkpDrawFrame) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief)); /* 152 */ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ + void (*tkSubtractRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 145 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + VOID *reserved145; /* Dummy entry for stubs table backwards compatibility */ + void (*tkSubtractRegion) (TkRegion sra, TkRegion srcb, TkRegion dr_return); /* 145 */ +#endif /* AQUA */ + void (*tkStylePkgInit) (TkMainInfo *mainPtr); /* 146 */ + void (*tkStylePkgFree) (TkMainInfo *mainPtr); /* 147 */ + Tk_Window (*tkToplevelWindowForCommand) (Tcl_Interp *interp, CONST char *cmdName); /* 148 */ + CONST Tk_OptionSpec * (*tkGetOptionSpec) (CONST char *name, Tk_OptionTable optionTable); /* 149 */ + int (*tkMakeRawCurve) (Tk_Canvas canvas, double *pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[]); /* 150 */ + void (*tkMakeRawCurvePostscript) (Tcl_Interp *interp, Tk_Canvas canvas, double *pointPtr, int numPoints); /* 151 */ + void (*tkpDrawFrame) (Tk_Window tkwin, Tk_3DBorder border, int highlightWidth, int borderWidth, int relief); /* 152 */ + void (*tkCreateThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 153 */ + void (*tkDeleteThreadExitHandler) (Tcl_ExitProc *proc, ClientData clientData); /* 154 */ + VOID *reserved155; + int (*tkpTestembedCmd) (ClientData clientData, Tcl_Interp *interp, int argc, CONST char **argv); /* 156 */ + int (*tkpTesttextCmd) (ClientData dummy, Tcl_Interp *interp, int argc, CONST char **argv); /* 157 */ + VOID *reserved158; + VOID *reserved159; + VOID *reserved160; + VOID *reserved161; + VOID *reserved162; + VOID *reserved163; + VOID *reserved164; + VOID *reserved165; + VOID *reserved166; + VOID *reserved167; + VOID *reserved168; + int (*tkStateParseProc) (ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, CONST char *value, char *widgRec, int offset); /* 169 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + char * (*tkSmoothPrintProc) (ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr); /* 180 */ } TkIntStubs; #ifdef __cplusplus @@ -1306,170 +1788,110 @@ extern TkIntStubs *tkIntStubsPtr; #define TkpMenuThreadInit \ (tkIntStubsPtr->tkpMenuThreadInit) /* 112 */ #endif -#ifdef __WIN32__ -#ifndef TkClipBox -#define TkClipBox \ - (tkIntStubsPtr->tkClipBox) /* 113 */ -#endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#ifdef __WIN32__ /* WIN */ #ifndef TkClipBox #define TkClipBox \ (tkIntStubsPtr->tkClipBox) /* 113 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkClipBox #define TkClipBox \ (tkIntStubsPtr->tkClipBox) /* 113 */ #endif -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ #ifndef TkCreateRegion #define TkCreateRegion \ (tkIntStubsPtr->tkCreateRegion) /* 114 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkCreateRegion #define TkCreateRegion \ (tkIntStubsPtr->tkCreateRegion) /* 114 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -#ifndef TkCreateRegion -#define TkCreateRegion \ - (tkIntStubsPtr->tkCreateRegion) /* 114 */ -#endif -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ #ifndef TkDestroyRegion #define TkDestroyRegion \ (tkIntStubsPtr->tkDestroyRegion) /* 115 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkDestroyRegion #define TkDestroyRegion \ (tkIntStubsPtr->tkDestroyRegion) /* 115 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -#ifndef TkDestroyRegion -#define TkDestroyRegion \ - (tkIntStubsPtr->tkDestroyRegion) /* 115 */ -#endif -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -#ifndef TkIntersectRegion -#define TkIntersectRegion \ - (tkIntStubsPtr->tkIntersectRegion) /* 116 */ -#endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ #ifndef TkIntersectRegion #define TkIntersectRegion \ (tkIntStubsPtr->tkIntersectRegion) /* 116 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkIntersectRegion #define TkIntersectRegion \ (tkIntStubsPtr->tkIntersectRegion) /* 116 */ #endif -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ #ifndef TkRectInRegion #define TkRectInRegion \ (tkIntStubsPtr->tkRectInRegion) /* 117 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkRectInRegion #define TkRectInRegion \ (tkIntStubsPtr->tkRectInRegion) /* 117 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -#ifndef TkRectInRegion -#define TkRectInRegion \ - (tkIntStubsPtr->tkRectInRegion) /* 117 */ -#endif -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ -#ifndef TkSetRegion -#define TkSetRegion \ - (tkIntStubsPtr->tkSetRegion) /* 118 */ -#endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ #ifndef TkSetRegion #define TkSetRegion \ (tkIntStubsPtr->tkSetRegion) /* 118 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkSetRegion #define TkSetRegion \ (tkIntStubsPtr->tkSetRegion) /* 118 */ #endif -#endif /* MAC_OSX_TK */ -#ifdef __WIN32__ +#endif /* AQUA */ +#ifdef __WIN32__ /* WIN */ #ifndef TkUnionRectWithRegion #define TkUnionRectWithRegion \ (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkUnionRectWithRegion #define TkUnionRectWithRegion \ (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -#ifndef TkUnionRectWithRegion -#define TkUnionRectWithRegion \ - (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */ -#endif -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ /* Slot 120 is reserved */ -#ifdef MAC_TCL +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkpCreateNativeBitmap #define TkpCreateNativeBitmap \ (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -#ifndef TkpCreateNativeBitmap -#define TkpCreateNativeBitmap \ - (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */ -#endif -#endif /* MAC_OSX_TK */ -#ifdef MAC_TCL +#endif /* AQUA */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkpDefineNativeBitmaps #define TkpDefineNativeBitmaps \ (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -#ifndef TkpDefineNativeBitmaps -#define TkpDefineNativeBitmaps \ - (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */ -#endif -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ /* Slot 123 is reserved */ -#ifdef MAC_TCL -#ifndef TkpGetNativeAppBitmap -#define TkpGetNativeAppBitmap \ - (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */ -#endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkpGetNativeAppBitmap #define TkpGetNativeAppBitmap \ (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */ #endif -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ /* Slot 125 is reserved */ /* Slot 126 is reserved */ /* Slot 127 is reserved */ @@ -1520,24 +1942,18 @@ extern TkIntStubs *tkIntStubsPtr; #define TkGCCleanup \ (tkIntStubsPtr->tkGCCleanup) /* 144 */ #endif -#ifdef __WIN32__ -#ifndef TkSubtractRegion -#define TkSubtractRegion \ - (tkIntStubsPtr->tkSubtractRegion) /* 145 */ -#endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#ifdef __WIN32__ /* WIN */ #ifndef TkSubtractRegion #define TkSubtractRegion \ (tkIntStubsPtr->tkSubtractRegion) /* 145 */ #endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkSubtractRegion #define TkSubtractRegion \ (tkIntStubsPtr->tkSubtractRegion) /* 145 */ #endif -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ #ifndef TkStylePkgInit #define TkStylePkgInit \ (tkIntStubsPtr->tkStylePkgInit) /* 146 */ @@ -1554,12 +1970,94 @@ extern TkIntStubs *tkIntStubsPtr; #define TkGetOptionSpec \ (tkIntStubsPtr->tkGetOptionSpec) /* 149 */ #endif -/* Slot 150 is reserved */ -/* Slot 151 is reserved */ +#ifndef TkMakeRawCurve +#define TkMakeRawCurve \ + (tkIntStubsPtr->tkMakeRawCurve) /* 150 */ +#endif +#ifndef TkMakeRawCurvePostscript +#define TkMakeRawCurvePostscript \ + (tkIntStubsPtr->tkMakeRawCurvePostscript) /* 151 */ +#endif #ifndef TkpDrawFrame #define TkpDrawFrame \ (tkIntStubsPtr->tkpDrawFrame) /* 152 */ #endif +#ifndef TkCreateThreadExitHandler +#define TkCreateThreadExitHandler \ + (tkIntStubsPtr->tkCreateThreadExitHandler) /* 153 */ +#endif +#ifndef TkDeleteThreadExitHandler +#define TkDeleteThreadExitHandler \ + (tkIntStubsPtr->tkDeleteThreadExitHandler) /* 154 */ +#endif +/* Slot 155 is reserved */ +#ifndef TkpTestembedCmd +#define TkpTestembedCmd \ + (tkIntStubsPtr->tkpTestembedCmd) /* 156 */ +#endif +#ifndef TkpTesttextCmd +#define TkpTesttextCmd \ + (tkIntStubsPtr->tkpTesttextCmd) /* 157 */ +#endif +/* Slot 158 is reserved */ +/* Slot 159 is reserved */ +/* Slot 160 is reserved */ +/* Slot 161 is reserved */ +/* Slot 162 is reserved */ +/* Slot 163 is reserved */ +/* Slot 164 is reserved */ +/* Slot 165 is reserved */ +/* Slot 166 is reserved */ +/* Slot 167 is reserved */ +/* Slot 168 is reserved */ +#ifndef TkStateParseProc +#define TkStateParseProc \ + (tkIntStubsPtr->tkStateParseProc) /* 169 */ +#endif +#ifndef TkStatePrintProc +#define TkStatePrintProc \ + (tkIntStubsPtr->tkStatePrintProc) /* 170 */ +#endif +#ifndef TkCanvasDashParseProc +#define TkCanvasDashParseProc \ + (tkIntStubsPtr->tkCanvasDashParseProc) /* 171 */ +#endif +#ifndef TkCanvasDashPrintProc +#define TkCanvasDashPrintProc \ + (tkIntStubsPtr->tkCanvasDashPrintProc) /* 172 */ +#endif +#ifndef TkOffsetParseProc +#define TkOffsetParseProc \ + (tkIntStubsPtr->tkOffsetParseProc) /* 173 */ +#endif +#ifndef TkOffsetPrintProc +#define TkOffsetPrintProc \ + (tkIntStubsPtr->tkOffsetPrintProc) /* 174 */ +#endif +#ifndef TkPixelParseProc +#define TkPixelParseProc \ + (tkIntStubsPtr->tkPixelParseProc) /* 175 */ +#endif +#ifndef TkPixelPrintProc +#define TkPixelPrintProc \ + (tkIntStubsPtr->tkPixelPrintProc) /* 176 */ +#endif +#ifndef TkOrientParseProc +#define TkOrientParseProc \ + (tkIntStubsPtr->tkOrientParseProc) /* 177 */ +#endif +#ifndef TkOrientPrintProc +#define TkOrientPrintProc \ + (tkIntStubsPtr->tkOrientPrintProc) /* 178 */ +#endif +#ifndef TkSmoothParseProc +#define TkSmoothParseProc \ + (tkIntStubsPtr->tkSmoothParseProc) /* 179 */ +#endif +#ifndef TkSmoothPrintProc +#define TkSmoothPrintProc \ + (tkIntStubsPtr->tkSmoothPrintProc) /* 180 */ +#endif #endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ diff --git a/generic/tkIntPlatDecls.h b/generic/tkIntPlatDecls.h index b59ab19..8de3a71 100644 --- a/generic/tkIntPlatDecls.h +++ b/generic/tkIntPlatDecls.h @@ -30,576 +30,644 @@ * Exported function declarations: */ -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ +#ifndef TkAlignImageData_TCL_DECLARED +#define TkAlignImageData_TCL_DECLARED /* 0 */ -EXTERN char * TkAlignImageData _ANSI_ARGS_((XImage *image, - int alignment, int bitOrder)); +EXTERN char * TkAlignImageData(XImage *image, int alignment, + int bitOrder); +#endif /* Slot 1 is reserved */ +#ifndef TkGenerateActivateEvents_TCL_DECLARED +#define TkGenerateActivateEvents_TCL_DECLARED /* 2 */ -EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( - TkWindow *winPtr, int active)); +EXTERN void TkGenerateActivateEvents(TkWindow *winPtr, + int active); +#endif +#ifndef TkpGetMS_TCL_DECLARED +#define TkpGetMS_TCL_DECLARED /* 3 */ -EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); +EXTERN unsigned long TkpGetMS(void); +#endif +#ifndef TkPointerDeadWindow_TCL_DECLARED +#define TkPointerDeadWindow_TCL_DECLARED /* 4 */ -EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkPointerDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkpPrintWindowId_TCL_DECLARED +#define TkpPrintWindowId_TCL_DECLARED /* 5 */ -EXTERN void TkpPrintWindowId _ANSI_ARGS_((char *buf, - Window window)); +EXTERN void TkpPrintWindowId(char *buf, Window window); +#endif +#ifndef TkpScanWindowId_TCL_DECLARED +#define TkpScanWindowId_TCL_DECLARED /* 6 */ -EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *string, Window *idPtr)); +EXTERN int TkpScanWindowId(Tcl_Interp *interp, + CONST char *string, Window *idPtr); +#endif +#ifndef TkpSetCapture_TCL_DECLARED +#define TkpSetCapture_TCL_DECLARED /* 7 */ -EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkpSetCapture(TkWindow *winPtr); +#endif +#ifndef TkpSetCursor_TCL_DECLARED +#define TkpSetCursor_TCL_DECLARED /* 8 */ -EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +EXTERN void TkpSetCursor(TkpCursor cursor); +#endif +#ifndef TkpWmSetState_TCL_DECLARED +#define TkpWmSetState_TCL_DECLARED /* 9 */ -EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow *winPtr, - int state)); +EXTERN void TkpWmSetState(TkWindow *winPtr, int state); +#endif +#ifndef TkSetPixmapColormap_TCL_DECLARED +#define TkSetPixmapColormap_TCL_DECLARED /* 10 */ -EXTERN void TkSetPixmapColormap _ANSI_ARGS_((Pixmap pixmap, - Colormap colormap)); +EXTERN void TkSetPixmapColormap(Pixmap pixmap, Colormap colormap); +#endif +#ifndef TkWinCancelMouseTimer_TCL_DECLARED +#define TkWinCancelMouseTimer_TCL_DECLARED /* 11 */ -EXTERN void TkWinCancelMouseTimer _ANSI_ARGS_((void)); +EXTERN void TkWinCancelMouseTimer(void); +#endif +#ifndef TkWinClipboardRender_TCL_DECLARED +#define TkWinClipboardRender_TCL_DECLARED /* 12 */ -EXTERN void TkWinClipboardRender _ANSI_ARGS_((TkDisplay *dispPtr, - UINT format)); +EXTERN void TkWinClipboardRender(TkDisplay *dispPtr, UINT format); +#endif +#ifndef TkWinEmbeddedEventProc_TCL_DECLARED +#define TkWinEmbeddedEventProc_TCL_DECLARED /* 13 */ -EXTERN LRESULT TkWinEmbeddedEventProc _ANSI_ARGS_((HWND hwnd, - UINT message, WPARAM wParam, LPARAM lParam)); +EXTERN LRESULT TkWinEmbeddedEventProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); +#endif +#ifndef TkWinFillRect_TCL_DECLARED +#define TkWinFillRect_TCL_DECLARED /* 14 */ -EXTERN void TkWinFillRect _ANSI_ARGS_((HDC dc, int x, int y, - int width, int height, int pixel)); +EXTERN void TkWinFillRect(HDC dc, int x, int y, int width, + int height, int pixel); +#endif +#ifndef TkWinGetBorderPixels_TCL_DECLARED +#define TkWinGetBorderPixels_TCL_DECLARED /* 15 */ -EXTERN COLORREF TkWinGetBorderPixels _ANSI_ARGS_((Tk_Window tkwin, - Tk_3DBorder border, int which)); +EXTERN COLORREF TkWinGetBorderPixels(Tk_Window tkwin, + Tk_3DBorder border, int which); +#endif +#ifndef TkWinGetDrawableDC_TCL_DECLARED +#define TkWinGetDrawableDC_TCL_DECLARED /* 16 */ -EXTERN HDC TkWinGetDrawableDC _ANSI_ARGS_((Display *display, - Drawable d, TkWinDCState *state)); +EXTERN HDC TkWinGetDrawableDC(Display *display, Drawable d, + TkWinDCState *state); +#endif +#ifndef TkWinGetModifierState_TCL_DECLARED +#define TkWinGetModifierState_TCL_DECLARED /* 17 */ -EXTERN int TkWinGetModifierState _ANSI_ARGS_((void)); +EXTERN int TkWinGetModifierState(void); +#endif +#ifndef TkWinGetSystemPalette_TCL_DECLARED +#define TkWinGetSystemPalette_TCL_DECLARED /* 18 */ -EXTERN HPALETTE TkWinGetSystemPalette _ANSI_ARGS_((void)); +EXTERN HPALETTE TkWinGetSystemPalette(void); +#endif +#ifndef TkWinGetWrapperWindow_TCL_DECLARED +#define TkWinGetWrapperWindow_TCL_DECLARED /* 19 */ -EXTERN HWND TkWinGetWrapperWindow _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN HWND TkWinGetWrapperWindow(Tk_Window tkwin); +#endif +#ifndef TkWinHandleMenuEvent_TCL_DECLARED +#define TkWinHandleMenuEvent_TCL_DECLARED /* 20 */ -EXTERN int TkWinHandleMenuEvent _ANSI_ARGS_((HWND *phwnd, - UINT *pMessage, WPARAM *pwParam, - LPARAM *plParam, LRESULT *plResult)); +EXTERN int TkWinHandleMenuEvent(HWND *phwnd, UINT *pMessage, + WPARAM *pwParam, LPARAM *plParam, + LRESULT *plResult); +#endif +#ifndef TkWinIndexOfColor_TCL_DECLARED +#define TkWinIndexOfColor_TCL_DECLARED /* 21 */ -EXTERN int TkWinIndexOfColor _ANSI_ARGS_((XColor *colorPtr)); +EXTERN int TkWinIndexOfColor(XColor *colorPtr); +#endif +#ifndef TkWinReleaseDrawableDC_TCL_DECLARED +#define TkWinReleaseDrawableDC_TCL_DECLARED /* 22 */ -EXTERN void TkWinReleaseDrawableDC _ANSI_ARGS_((Drawable d, - HDC hdc, TkWinDCState *state)); +EXTERN void TkWinReleaseDrawableDC(Drawable d, HDC hdc, + TkWinDCState *state); +#endif +#ifndef TkWinResendEvent_TCL_DECLARED +#define TkWinResendEvent_TCL_DECLARED /* 23 */ -EXTERN LRESULT TkWinResendEvent _ANSI_ARGS_((WNDPROC wndproc, - HWND hwnd, XEvent *eventPtr)); +EXTERN LRESULT TkWinResendEvent(WNDPROC wndproc, HWND hwnd, + XEvent *eventPtr); +#endif +#ifndef TkWinSelectPalette_TCL_DECLARED +#define TkWinSelectPalette_TCL_DECLARED /* 24 */ -EXTERN HPALETTE TkWinSelectPalette _ANSI_ARGS_((HDC dc, - Colormap colormap)); +EXTERN HPALETTE TkWinSelectPalette(HDC dc, Colormap colormap); +#endif +#ifndef TkWinSetMenu_TCL_DECLARED +#define TkWinSetMenu_TCL_DECLARED /* 25 */ -EXTERN void TkWinSetMenu _ANSI_ARGS_((Tk_Window tkwin, - HMENU hMenu)); +EXTERN void TkWinSetMenu(Tk_Window tkwin, HMENU hMenu); +#endif +#ifndef TkWinSetWindowPos_TCL_DECLARED +#define TkWinSetWindowPos_TCL_DECLARED /* 26 */ -EXTERN void TkWinSetWindowPos _ANSI_ARGS_((HWND hwnd, - HWND siblingHwnd, int pos)); +EXTERN void TkWinSetWindowPos(HWND hwnd, HWND siblingHwnd, + int pos); +#endif +#ifndef TkWinWmCleanup_TCL_DECLARED +#define TkWinWmCleanup_TCL_DECLARED /* 27 */ -EXTERN void TkWinWmCleanup _ANSI_ARGS_((HINSTANCE hInstance)); +EXTERN void TkWinWmCleanup(HINSTANCE hInstance); +#endif +#ifndef TkWinXCleanup_TCL_DECLARED +#define TkWinXCleanup_TCL_DECLARED /* 28 */ -EXTERN void TkWinXCleanup _ANSI_ARGS_((ClientData clientData)); +EXTERN void TkWinXCleanup(ClientData clientData); +#endif +#ifndef TkWinXInit_TCL_DECLARED +#define TkWinXInit_TCL_DECLARED /* 29 */ -EXTERN void TkWinXInit _ANSI_ARGS_((HINSTANCE hInstance)); +EXTERN void TkWinXInit(HINSTANCE hInstance); +#endif +#ifndef TkWinSetForegroundWindow_TCL_DECLARED +#define TkWinSetForegroundWindow_TCL_DECLARED /* 30 */ -EXTERN void TkWinSetForegroundWindow _ANSI_ARGS_(( - TkWindow *winPtr)); +EXTERN void TkWinSetForegroundWindow(TkWindow *winPtr); +#endif +#ifndef TkWinDialogDebug_TCL_DECLARED +#define TkWinDialogDebug_TCL_DECLARED /* 31 */ -EXTERN void TkWinDialogDebug _ANSI_ARGS_((int debug)); +EXTERN void TkWinDialogDebug(int debug); +#endif +#ifndef TkWinGetMenuSystemDefault_TCL_DECLARED +#define TkWinGetMenuSystemDefault_TCL_DECLARED /* 32 */ -EXTERN Tcl_Obj * TkWinGetMenuSystemDefault _ANSI_ARGS_(( - Tk_Window tkwin, CONST char *dbName, - CONST char *className)); +EXTERN Tcl_Obj * TkWinGetMenuSystemDefault(Tk_Window tkwin, + CONST char *dbName, CONST char *className); +#endif +#ifndef TkWinGetPlatformId_TCL_DECLARED +#define TkWinGetPlatformId_TCL_DECLARED /* 33 */ -EXTERN int TkWinGetPlatformId _ANSI_ARGS_((void)); +EXTERN int TkWinGetPlatformId(void); +#endif +#ifndef TkWinSetHINSTANCE_TCL_DECLARED +#define TkWinSetHINSTANCE_TCL_DECLARED /* 34 */ -EXTERN void TkWinSetHINSTANCE _ANSI_ARGS_((HINSTANCE hInstance)); +EXTERN void TkWinSetHINSTANCE(HINSTANCE hInstance); +#endif +#ifndef TkWinGetPlatformTheme_TCL_DECLARED +#define TkWinGetPlatformTheme_TCL_DECLARED /* 35 */ -EXTERN int TkWinGetPlatformTheme _ANSI_ARGS_((void)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL -/* 0 */ -EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( - TkWindow *winPtr, int active)); -/* Slot 1 is reserved */ -/* Slot 2 is reserved */ -/* 3 */ -EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); -/* Slot 4 is reserved */ -/* 5 */ -EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); -/* 6 */ -EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow *winPtr)); -/* 7 */ -EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); -/* 8 */ -EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow *winPtr, - int state)); -/* Slot 9 is reserved */ -/* 10 */ -EXTERN void TkAboutDlg _ANSI_ARGS_((void)); -/* Slot 11 is reserved */ -/* Slot 12 is reserved */ -/* 13 */ -EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow *winPtr)); -/* 14 */ -EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, - Window window, unsigned int state)); -/* Slot 15 is reserved */ -/* 16 */ -EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); -/* Slot 17 is reserved */ -/* 18 */ -EXTERN unsigned int TkMacButtonKeyState _ANSI_ARGS_((void)); -/* 19 */ -EXTERN void TkMacClearMenubarActive _ANSI_ARGS_((void)); -/* Slot 20 is reserved */ -/* 21 */ -EXTERN int TkMacDispatchMenuEvent _ANSI_ARGS_((int menuID, - int index)); -/* 22 */ -EXTERN void TkMacInstallCursor _ANSI_ARGS_((int resizeOverride)); -/* Slot 23 is reserved */ -/* 24 */ -EXTERN void TkMacHandleTearoffMenu _ANSI_ARGS_((void)); -/* Slot 25 is reserved */ -/* Slot 26 is reserved */ -/* 27 */ -EXTERN void TkMacDoHLEvent _ANSI_ARGS_((EventRecord *theEvent)); -/* Slot 28 is reserved */ -/* 29 */ -EXTERN Time TkMacGenerateTime _ANSI_ARGS_((void)); -/* Slot 30 is reserved */ -/* 31 */ -EXTERN TkWindow * TkMacGetScrollbarGrowWindow _ANSI_ARGS_(( - TkWindow *winPtr)); -/* 32 */ -EXTERN Window TkMacGetXWindow _ANSI_ARGS_((WindowRef macWinPtr)); -/* 33 */ -EXTERN int TkMacGrowToplevel _ANSI_ARGS_((WindowRef whichWindow, - Point start)); -/* 34 */ -EXTERN void TkMacHandleMenuSelect _ANSI_ARGS_((long mResult, - int optionKeyPressed)); -/* Slot 35 is reserved */ -/* Slot 36 is reserved */ -/* Slot 37 is reserved */ -/* 38 */ -EXTERN void TkMacInvalidateWindow _ANSI_ARGS_(( - MacDrawable *macWin, int flag)); -/* 39 */ -EXTERN int TkMacIsCharacterMissing _ANSI_ARGS_((Tk_Font tkfont, - unsigned int searchChar)); -/* 40 */ -EXTERN void TkMacMakeRealWindowExist _ANSI_ARGS_(( - TkWindow *winPtr)); -/* 41 */ -EXTERN BitMapPtr TkMacMakeStippleMap _ANSI_ARGS_((Drawable d1, - Drawable d2)); -/* 42 */ -EXTERN void TkMacMenuClick _ANSI_ARGS_((void)); -/* 43 */ -EXTERN void TkMacRegisterOffScreenWindow _ANSI_ARGS_(( - Window window, GWorldPtr portPtr)); -/* 44 */ -EXTERN int TkMacResizable _ANSI_ARGS_((TkWindow *winPtr)); -/* Slot 45 is reserved */ -/* 46 */ -EXTERN void TkMacSetHelpMenuItemCount _ANSI_ARGS_((void)); -/* 47 */ -EXTERN void TkMacSetScrollbarGrow _ANSI_ARGS_((TkWindow *winPtr, - int flag)); -/* 48 */ -EXTERN void TkMacSetUpClippingRgn _ANSI_ARGS_((Drawable drawable)); -/* 49 */ -EXTERN void TkMacSetUpGraphicsPort _ANSI_ARGS_((GC gc)); -/* 50 */ -EXTERN void TkMacUpdateClipRgn _ANSI_ARGS_((TkWindow *winPtr)); -/* 51 */ -EXTERN void TkMacUnregisterMacWindow _ANSI_ARGS_(( - GWorldPtr portPtr)); -/* 52 */ -EXTERN int TkMacUseMenuID _ANSI_ARGS_((short macID)); -/* 53 */ -EXTERN RgnHandle TkMacVisableClipRgn _ANSI_ARGS_((TkWindow *winPtr)); -/* 54 */ -EXTERN void TkMacWinBounds _ANSI_ARGS_((TkWindow *winPtr, - Rect *geometry)); -/* 55 */ -EXTERN void TkMacWindowOffset _ANSI_ARGS_((WindowRef wRef, - int *xOffset, int *yOffset)); -/* Slot 56 is reserved */ -/* 57 */ -EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel, - RGBColor *macColor)); -/* 58 */ -EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow *winPtr, - Tk_Uid titleUid)); -/* 59 */ -EXTERN void TkSuspendClipboard _ANSI_ARGS_((void)); -/* Slot 60 is reserved */ -/* 61 */ -EXTERN int TkMacZoomToplevel _ANSI_ARGS_((WindowPtr whichWindow, - Point where, short zoomPart)); -/* 62 */ -EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, - int rootX, int rootY, int *newX, int *newY)); -/* 63 */ -EXTERN MacDrawable * TkMacContainerId _ANSI_ARGS_((TkWindow *winPtr)); -/* 64 */ -EXTERN MacDrawable * TkMacGetHostToplevel _ANSI_ARGS_((TkWindow *winPtr)); -/* 65 */ -EXTERN void TkMacPreprocessMenu _ANSI_ARGS_((void)); -/* 66 */ -EXTERN int TkpIsWindowFloating _ANSI_ARGS_((WindowRef window)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN int TkWinGetPlatformTheme(void); +#endif +#ifndef TkWinChildProc_TCL_DECLARED +#define TkWinChildProc_TCL_DECLARED +/* 36 */ +EXTERN LRESULT CALLBACK TkWinChildProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef TkGenerateActivateEvents_TCL_DECLARED +#define TkGenerateActivateEvents_TCL_DECLARED /* 0 */ -EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( - TkWindow *winPtr, int active)); +EXTERN void TkGenerateActivateEvents(TkWindow *winPtr, + int active); +#endif /* Slot 1 is reserved */ /* Slot 2 is reserved */ +#ifndef TkPointerDeadWindow_TCL_DECLARED +#define TkPointerDeadWindow_TCL_DECLARED /* 3 */ -EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkPointerDeadWindow(TkWindow *winPtr); +#endif +#ifndef TkpSetCapture_TCL_DECLARED +#define TkpSetCapture_TCL_DECLARED /* 4 */ -EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkpSetCapture(TkWindow *winPtr); +#endif +#ifndef TkpSetCursor_TCL_DECLARED +#define TkpSetCursor_TCL_DECLARED /* 5 */ -EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor)); +EXTERN void TkpSetCursor(TkpCursor cursor); +#endif +#ifndef TkpWmSetState_TCL_DECLARED +#define TkpWmSetState_TCL_DECLARED /* 6 */ -EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow *winPtr, - int state)); +EXTERN void TkpWmSetState(TkWindow *winPtr, int state); +#endif +#ifndef TkAboutDlg_TCL_DECLARED +#define TkAboutDlg_TCL_DECLARED /* 7 */ -EXTERN void TkAboutDlg _ANSI_ARGS_((void)); +EXTERN void TkAboutDlg(void); +#endif +#ifndef TkMacOSXButtonKeyState_TCL_DECLARED +#define TkMacOSXButtonKeyState_TCL_DECLARED /* 8 */ -EXTERN unsigned int TkMacOSXButtonKeyState _ANSI_ARGS_((void)); +EXTERN unsigned int TkMacOSXButtonKeyState(void); +#endif +#ifndef TkMacOSXClearMenubarActive_TCL_DECLARED +#define TkMacOSXClearMenubarActive_TCL_DECLARED /* 9 */ -EXTERN void TkMacOSXClearMenubarActive _ANSI_ARGS_((void)); +EXTERN void TkMacOSXClearMenubarActive(void); +#endif +#ifndef TkMacOSXDispatchMenuEvent_TCL_DECLARED +#define TkMacOSXDispatchMenuEvent_TCL_DECLARED /* 10 */ -EXTERN int TkMacOSXDispatchMenuEvent _ANSI_ARGS_((int menuID, - int index)); +EXTERN int TkMacOSXDispatchMenuEvent(int menuID, int index); +#endif +#ifndef TkMacOSXInstallCursor_TCL_DECLARED +#define TkMacOSXInstallCursor_TCL_DECLARED /* 11 */ -EXTERN void TkMacOSXInstallCursor _ANSI_ARGS_(( - int resizeOverride)); +EXTERN void TkMacOSXInstallCursor(int resizeOverride); +#endif +#ifndef TkMacOSXHandleTearoffMenu_TCL_DECLARED +#define TkMacOSXHandleTearoffMenu_TCL_DECLARED /* 12 */ -EXTERN void TkMacOSXHandleTearoffMenu _ANSI_ARGS_((void)); +EXTERN void TkMacOSXHandleTearoffMenu(void); +#endif /* Slot 13 is reserved */ +#ifndef TkMacOSXDoHLEvent_TCL_DECLARED +#define TkMacOSXDoHLEvent_TCL_DECLARED /* 14 */ -EXTERN int TkMacOSXDoHLEvent _ANSI_ARGS_((EventRecord *theEvent)); +EXTERN int TkMacOSXDoHLEvent(EventRecord *theEvent); +#endif /* Slot 15 is reserved */ +#ifndef TkMacOSXGetXWindow_TCL_DECLARED +#define TkMacOSXGetXWindow_TCL_DECLARED /* 16 */ -EXTERN Window TkMacOSXGetXWindow _ANSI_ARGS_((WindowRef macWinPtr)); +EXTERN Window TkMacOSXGetXWindow(WindowRef macWinPtr); +#endif +#ifndef TkMacOSXGrowToplevel_TCL_DECLARED +#define TkMacOSXGrowToplevel_TCL_DECLARED /* 17 */ -EXTERN int TkMacOSXGrowToplevel _ANSI_ARGS_(( - WindowRef whichWindow, Point start)); +EXTERN int TkMacOSXGrowToplevel(WindowRef whichWindow, + Point start); +#endif +#ifndef TkMacOSXHandleMenuSelect_TCL_DECLARED +#define TkMacOSXHandleMenuSelect_TCL_DECLARED /* 18 */ -EXTERN void TkMacOSXHandleMenuSelect _ANSI_ARGS_((MenuID theMenu, - MenuItemIndex theItem, int optionKeyPressed)); +EXTERN void TkMacOSXHandleMenuSelect(MenuID theMenu, + MenuItemIndex theItem, int optionKeyPressed); +#endif /* Slot 19 is reserved */ /* Slot 20 is reserved */ +#ifndef TkMacOSXInvalidateWindow_TCL_DECLARED +#define TkMacOSXInvalidateWindow_TCL_DECLARED /* 21 */ -EXTERN void TkMacOSXInvalidateWindow _ANSI_ARGS_(( - MacDrawable *macWin, int flag)); +EXTERN void TkMacOSXInvalidateWindow(MacDrawable *macWin, + int flag); +#endif +#ifndef TkMacOSXIsCharacterMissing_TCL_DECLARED +#define TkMacOSXIsCharacterMissing_TCL_DECLARED /* 22 */ -EXTERN int TkMacOSXIsCharacterMissing _ANSI_ARGS_(( - Tk_Font tkfont, unsigned int searchChar)); +EXTERN int TkMacOSXIsCharacterMissing(Tk_Font tkfont, + unsigned int searchChar); +#endif +#ifndef TkMacOSXMakeRealWindowExist_TCL_DECLARED +#define TkMacOSXMakeRealWindowExist_TCL_DECLARED /* 23 */ -EXTERN void TkMacOSXMakeRealWindowExist _ANSI_ARGS_(( - TkWindow *winPtr)); +EXTERN void TkMacOSXMakeRealWindowExist(TkWindow *winPtr); +#endif +#ifndef TkMacOSXMakeStippleMap_TCL_DECLARED +#define TkMacOSXMakeStippleMap_TCL_DECLARED /* 24 */ -EXTERN BitMapPtr TkMacOSXMakeStippleMap _ANSI_ARGS_((Drawable d1, - Drawable d2)); +EXTERN BitMapPtr TkMacOSXMakeStippleMap(Drawable d1, Drawable d2); +#endif +#ifndef TkMacOSXMenuClick_TCL_DECLARED +#define TkMacOSXMenuClick_TCL_DECLARED /* 25 */ -EXTERN void TkMacOSXMenuClick _ANSI_ARGS_((void)); +EXTERN void TkMacOSXMenuClick(void); +#endif +#ifndef TkMacOSXRegisterOffScreenWindow_TCL_DECLARED +#define TkMacOSXRegisterOffScreenWindow_TCL_DECLARED /* 26 */ -EXTERN void TkMacOSXRegisterOffScreenWindow _ANSI_ARGS_(( - Window window, GWorldPtr portPtr)); +EXTERN void TkMacOSXRegisterOffScreenWindow(Window window, + GWorldPtr portPtr); +#endif +#ifndef TkMacOSXResizable_TCL_DECLARED +#define TkMacOSXResizable_TCL_DECLARED /* 27 */ -EXTERN int TkMacOSXResizable _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN int TkMacOSXResizable(TkWindow *winPtr); +#endif +#ifndef TkMacOSXSetHelpMenuItemCount_TCL_DECLARED +#define TkMacOSXSetHelpMenuItemCount_TCL_DECLARED /* 28 */ -EXTERN void TkMacOSXSetHelpMenuItemCount _ANSI_ARGS_((void)); +EXTERN void TkMacOSXSetHelpMenuItemCount(void); +#endif +#ifndef TkMacOSXSetScrollbarGrow_TCL_DECLARED +#define TkMacOSXSetScrollbarGrow_TCL_DECLARED /* 29 */ -EXTERN void TkMacOSXSetScrollbarGrow _ANSI_ARGS_(( - TkWindow *winPtr, int flag)); +EXTERN void TkMacOSXSetScrollbarGrow(TkWindow *winPtr, int flag); +#endif +#ifndef TkMacOSXSetUpClippingRgn_TCL_DECLARED +#define TkMacOSXSetUpClippingRgn_TCL_DECLARED /* 30 */ -EXTERN void TkMacOSXSetUpClippingRgn _ANSI_ARGS_(( - Drawable drawable)); +EXTERN void TkMacOSXSetUpClippingRgn(Drawable drawable); +#endif +#ifndef TkMacOSXSetUpGraphicsPort_TCL_DECLARED +#define TkMacOSXSetUpGraphicsPort_TCL_DECLARED /* 31 */ -EXTERN void TkMacOSXSetUpGraphicsPort _ANSI_ARGS_((GC gc, - GWorldPtr destPort)); +EXTERN void TkMacOSXSetUpGraphicsPort(GC gc, GWorldPtr destPort); +#endif +#ifndef TkMacOSXUpdateClipRgn_TCL_DECLARED +#define TkMacOSXUpdateClipRgn_TCL_DECLARED /* 32 */ -EXTERN void TkMacOSXUpdateClipRgn _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkMacOSXUpdateClipRgn(TkWindow *winPtr); +#endif +#ifndef TkMacOSXUnregisterMacWindow_TCL_DECLARED +#define TkMacOSXUnregisterMacWindow_TCL_DECLARED /* 33 */ -EXTERN void TkMacOSXUnregisterMacWindow _ANSI_ARGS_(( - WindowRef portPtr)); +EXTERN void TkMacOSXUnregisterMacWindow(WindowRef portPtr); +#endif +#ifndef TkMacOSXUseMenuID_TCL_DECLARED +#define TkMacOSXUseMenuID_TCL_DECLARED /* 34 */ -EXTERN int TkMacOSXUseMenuID _ANSI_ARGS_((short macID)); +EXTERN int TkMacOSXUseMenuID(short macID); +#endif +#ifndef TkMacOSXVisableClipRgn_TCL_DECLARED +#define TkMacOSXVisableClipRgn_TCL_DECLARED /* 35 */ -EXTERN RgnHandle TkMacOSXVisableClipRgn _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN RgnHandle TkMacOSXVisableClipRgn(TkWindow *winPtr); +#endif +#ifndef TkMacOSXWinBounds_TCL_DECLARED +#define TkMacOSXWinBounds_TCL_DECLARED /* 36 */ -EXTERN void TkMacOSXWinBounds _ANSI_ARGS_((TkWindow *winPtr, - Rect *geometry)); +EXTERN void TkMacOSXWinBounds(TkWindow *winPtr, Rect *geometry); +#endif +#ifndef TkMacOSXWindowOffset_TCL_DECLARED +#define TkMacOSXWindowOffset_TCL_DECLARED /* 37 */ -EXTERN void TkMacOSXWindowOffset _ANSI_ARGS_((WindowRef wRef, - int *xOffset, int *yOffset)); +EXTERN void TkMacOSXWindowOffset(WindowRef wRef, int *xOffset, + int *yOffset); +#endif +#ifndef TkSetMacColor_TCL_DECLARED +#define TkSetMacColor_TCL_DECLARED /* 38 */ -EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel, - RGBColor *macColor)); +EXTERN int TkSetMacColor(unsigned long pixel, + RGBColor *macColor); +#endif +#ifndef TkSetWMName_TCL_DECLARED +#define TkSetWMName_TCL_DECLARED /* 39 */ -EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow *winPtr, - Tk_Uid titleUid)); +EXTERN void TkSetWMName(TkWindow *winPtr, Tk_Uid titleUid); +#endif +#ifndef TkSuspendClipboard_TCL_DECLARED +#define TkSuspendClipboard_TCL_DECLARED /* 40 */ -EXTERN void TkSuspendClipboard _ANSI_ARGS_((void)); +EXTERN void TkSuspendClipboard(void); +#endif +#ifndef TkMacOSXZoomToplevel_TCL_DECLARED +#define TkMacOSXZoomToplevel_TCL_DECLARED /* 41 */ -EXTERN int TkMacOSXZoomToplevel _ANSI_ARGS_(( - WindowPtr whichWindow, short zoomPart)); +EXTERN int TkMacOSXZoomToplevel(WindowPtr whichWindow, + short zoomPart); +#endif +#ifndef Tk_TopCoordsToWindow_TCL_DECLARED +#define Tk_TopCoordsToWindow_TCL_DECLARED /* 42 */ -EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin, - int rootX, int rootY, int *newX, int *newY)); +EXTERN Tk_Window Tk_TopCoordsToWindow(Tk_Window tkwin, int rootX, + int rootY, int *newX, int *newY); +#endif +#ifndef TkMacOSXContainerId_TCL_DECLARED +#define TkMacOSXContainerId_TCL_DECLARED /* 43 */ -EXTERN MacDrawable * TkMacOSXContainerId _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN MacDrawable * TkMacOSXContainerId(TkWindow *winPtr); +#endif +#ifndef TkMacOSXGetHostToplevel_TCL_DECLARED +#define TkMacOSXGetHostToplevel_TCL_DECLARED /* 44 */ -EXTERN MacDrawable * TkMacOSXGetHostToplevel _ANSI_ARGS_(( - TkWindow *winPtr)); +EXTERN MacDrawable * TkMacOSXGetHostToplevel(TkWindow *winPtr); +#endif +#ifndef TkMacOSXPreprocessMenu_TCL_DECLARED +#define TkMacOSXPreprocessMenu_TCL_DECLARED /* 45 */ -EXTERN void TkMacOSXPreprocessMenu _ANSI_ARGS_((void)); +EXTERN void TkMacOSXPreprocessMenu(void); +#endif +#ifndef TkpIsWindowFloating_TCL_DECLARED +#define TkpIsWindowFloating_TCL_DECLARED /* 46 */ -EXTERN int TkpIsWindowFloating _ANSI_ARGS_((WindowRef window)); +EXTERN int TkpIsWindowFloating(WindowRef window); +#endif +#ifndef TkMacOSXGetCapture_TCL_DECLARED +#define TkMacOSXGetCapture_TCL_DECLARED /* 47 */ -EXTERN Tk_Window TkMacOSXGetCapture _ANSI_ARGS_((void)); +EXTERN Tk_Window TkMacOSXGetCapture(void); +#endif /* Slot 48 is reserved */ +#ifndef TkGetTransientMaster_TCL_DECLARED +#define TkGetTransientMaster_TCL_DECLARED /* 49 */ -EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN Window TkGetTransientMaster(TkWindow *winPtr); +#endif +#ifndef TkGenerateButtonEvent_TCL_DECLARED +#define TkGenerateButtonEvent_TCL_DECLARED /* 50 */ -EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y, - Window window, unsigned int state)); +EXTERN int TkGenerateButtonEvent(int x, int y, Window window, + unsigned int state); +#endif +#ifndef TkGenWMDestroyEvent_TCL_DECLARED +#define TkGenWMDestroyEvent_TCL_DECLARED /* 51 */ -EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void TkGenWMDestroyEvent(Tk_Window tkwin); +#endif /* Slot 52 is reserved */ +#ifndef TkpGetMS_TCL_DECLARED +#define TkpGetMS_TCL_DECLARED /* 53 */ -EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void)); -#endif /* MAC_OSX_TK */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ +EXTERN unsigned long TkpGetMS(void); +#endif +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ +#ifndef TkCreateXEventSource_TCL_DECLARED +#define TkCreateXEventSource_TCL_DECLARED /* 0 */ -EXTERN void TkCreateXEventSource _ANSI_ARGS_((void)); +EXTERN void TkCreateXEventSource(void); +#endif +#ifndef TkFreeWindowId_TCL_DECLARED +#define TkFreeWindowId_TCL_DECLARED /* 1 */ -EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay *dispPtr, - Window w)); +EXTERN void TkFreeWindowId(TkDisplay *dispPtr, Window w); +#endif +#ifndef TkInitXId_TCL_DECLARED +#define TkInitXId_TCL_DECLARED /* 2 */ -EXTERN void TkInitXId _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkInitXId(TkDisplay *dispPtr); +#endif +#ifndef TkpCmapStressed_TCL_DECLARED +#define TkpCmapStressed_TCL_DECLARED /* 3 */ -EXTERN int TkpCmapStressed _ANSI_ARGS_((Tk_Window tkwin, - Colormap colormap)); +EXTERN int TkpCmapStressed(Tk_Window tkwin, Colormap colormap); +#endif +#ifndef TkpSync_TCL_DECLARED +#define TkpSync_TCL_DECLARED /* 4 */ -EXTERN void TkpSync _ANSI_ARGS_((Display *display)); +EXTERN void TkpSync(Display *display); +#endif +#ifndef TkUnixContainerId_TCL_DECLARED +#define TkUnixContainerId_TCL_DECLARED /* 5 */ -EXTERN Window TkUnixContainerId _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN Window TkUnixContainerId(TkWindow *winPtr); +#endif +#ifndef TkUnixDoOneXEvent_TCL_DECLARED +#define TkUnixDoOneXEvent_TCL_DECLARED /* 6 */ -EXTERN int TkUnixDoOneXEvent _ANSI_ARGS_((Tcl_Time *timePtr)); +EXTERN int TkUnixDoOneXEvent(Tcl_Time *timePtr); +#endif +#ifndef TkUnixSetMenubar_TCL_DECLARED +#define TkUnixSetMenubar_TCL_DECLARED /* 7 */ -EXTERN void TkUnixSetMenubar _ANSI_ARGS_((Tk_Window tkwin, - Tk_Window menubar)); +EXTERN void TkUnixSetMenubar(Tk_Window tkwin, Tk_Window menubar); +#endif +#ifndef TkpScanWindowId_TCL_DECLARED +#define TkpScanWindowId_TCL_DECLARED /* 8 */ -EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *string, Window *idPtr)); +EXTERN int TkpScanWindowId(Tcl_Interp *interp, + CONST char *string, Window *idPtr); +#endif +#ifndef TkWmCleanup_TCL_DECLARED +#define TkWmCleanup_TCL_DECLARED /* 9 */ -EXTERN void TkWmCleanup _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkWmCleanup(TkDisplay *dispPtr); +#endif +#ifndef TkSendCleanup_TCL_DECLARED +#define TkSendCleanup_TCL_DECLARED /* 10 */ -EXTERN void TkSendCleanup _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkSendCleanup(TkDisplay *dispPtr); +#endif +#ifndef TkFreeXId_TCL_DECLARED +#define TkFreeXId_TCL_DECLARED /* 11 */ -EXTERN void TkFreeXId _ANSI_ARGS_((TkDisplay *dispPtr)); +EXTERN void TkFreeXId(TkDisplay *dispPtr); +#endif +#ifndef TkpWmSetState_TCL_DECLARED +#define TkpWmSetState_TCL_DECLARED /* 12 */ -EXTERN int TkpWmSetState _ANSI_ARGS_((TkWindow *winPtr, - int state)); +EXTERN int TkpWmSetState(TkWindow *winPtr, int state); +#endif +#ifndef TkpTestsendCmd_TCL_DECLARED +#define TkpTestsendCmd_TCL_DECLARED +/* 13 */ +EXTERN int TkpTestsendCmd(ClientData clientData, + Tcl_Interp *interp, int argc, + CONST char **argv); +#endif #endif /* X11 */ typedef struct TkIntPlatStubs { int magic; struct TkIntPlatStubHooks *hooks; -#ifdef __WIN32__ - char * (*tkAlignImageData) _ANSI_ARGS_((XImage *image, int alignment, int bitOrder)); /* 0 */ +#ifdef __WIN32__ /* WIN */ + char * (*tkAlignImageData) (XImage *image, int alignment, int bitOrder); /* 0 */ VOID *reserved1; - void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow *winPtr, int active)); /* 2 */ - unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ - void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 4 */ - void (*tkpPrintWindowId) _ANSI_ARGS_((char *buf, Window window)); /* 5 */ - int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *string, Window *idPtr)); /* 6 */ - void (*tkpSetCapture) _ANSI_ARGS_((TkWindow *winPtr)); /* 7 */ - void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 8 */ - void (*tkpWmSetState) _ANSI_ARGS_((TkWindow *winPtr, int state)); /* 9 */ - void (*tkSetPixmapColormap) _ANSI_ARGS_((Pixmap pixmap, Colormap colormap)); /* 10 */ - void (*tkWinCancelMouseTimer) _ANSI_ARGS_((void)); /* 11 */ - void (*tkWinClipboardRender) _ANSI_ARGS_((TkDisplay *dispPtr, UINT format)); /* 12 */ - LRESULT (*tkWinEmbeddedEventProc) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); /* 13 */ - void (*tkWinFillRect) _ANSI_ARGS_((HDC dc, int x, int y, int width, int height, int pixel)); /* 14 */ - COLORREF (*tkWinGetBorderPixels) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 15 */ - HDC (*tkWinGetDrawableDC) _ANSI_ARGS_((Display *display, Drawable d, TkWinDCState *state)); /* 16 */ - int (*tkWinGetModifierState) _ANSI_ARGS_((void)); /* 17 */ - HPALETTE (*tkWinGetSystemPalette) _ANSI_ARGS_((void)); /* 18 */ - HWND (*tkWinGetWrapperWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 19 */ - int (*tkWinHandleMenuEvent) _ANSI_ARGS_((HWND *phwnd, UINT *pMessage, WPARAM *pwParam, LPARAM *plParam, LRESULT *plResult)); /* 20 */ - int (*tkWinIndexOfColor) _ANSI_ARGS_((XColor *colorPtr)); /* 21 */ - void (*tkWinReleaseDrawableDC) _ANSI_ARGS_((Drawable d, HDC hdc, TkWinDCState *state)); /* 22 */ - LRESULT (*tkWinResendEvent) _ANSI_ARGS_((WNDPROC wndproc, HWND hwnd, XEvent *eventPtr)); /* 23 */ - HPALETTE (*tkWinSelectPalette) _ANSI_ARGS_((HDC dc, Colormap colormap)); /* 24 */ - void (*tkWinSetMenu) _ANSI_ARGS_((Tk_Window tkwin, HMENU hMenu)); /* 25 */ - void (*tkWinSetWindowPos) _ANSI_ARGS_((HWND hwnd, HWND siblingHwnd, int pos)); /* 26 */ - void (*tkWinWmCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 27 */ - void (*tkWinXCleanup) _ANSI_ARGS_((ClientData clientData)); /* 28 */ - void (*tkWinXInit) _ANSI_ARGS_((HINSTANCE hInstance)); /* 29 */ - void (*tkWinSetForegroundWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 30 */ - void (*tkWinDialogDebug) _ANSI_ARGS_((int debug)); /* 31 */ - Tcl_Obj * (*tkWinGetMenuSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, CONST char *dbName, CONST char *className)); /* 32 */ - int (*tkWinGetPlatformId) _ANSI_ARGS_((void)); /* 33 */ - void (*tkWinSetHINSTANCE) _ANSI_ARGS_((HINSTANCE hInstance)); /* 34 */ - int (*tkWinGetPlatformTheme) _ANSI_ARGS_((void)); /* 35 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow *winPtr, int active)); /* 0 */ + void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 2 */ + unsigned long (*tkpGetMS) (void); /* 3 */ + void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 4 */ + void (*tkpPrintWindowId) (char *buf, Window window); /* 5 */ + int (*tkpScanWindowId) (Tcl_Interp *interp, CONST char *string, Window *idPtr); /* 6 */ + void (*tkpSetCapture) (TkWindow *winPtr); /* 7 */ + void (*tkpSetCursor) (TkpCursor cursor); /* 8 */ + void (*tkpWmSetState) (TkWindow *winPtr, int state); /* 9 */ + void (*tkSetPixmapColormap) (Pixmap pixmap, Colormap colormap); /* 10 */ + void (*tkWinCancelMouseTimer) (void); /* 11 */ + void (*tkWinClipboardRender) (TkDisplay *dispPtr, UINT format); /* 12 */ + LRESULT (*tkWinEmbeddedEventProc) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* 13 */ + void (*tkWinFillRect) (HDC dc, int x, int y, int width, int height, int pixel); /* 14 */ + COLORREF (*tkWinGetBorderPixels) (Tk_Window tkwin, Tk_3DBorder border, int which); /* 15 */ + HDC (*tkWinGetDrawableDC) (Display *display, Drawable d, TkWinDCState *state); /* 16 */ + int (*tkWinGetModifierState) (void); /* 17 */ + HPALETTE (*tkWinGetSystemPalette) (void); /* 18 */ + HWND (*tkWinGetWrapperWindow) (Tk_Window tkwin); /* 19 */ + int (*tkWinHandleMenuEvent) (HWND *phwnd, UINT *pMessage, WPARAM *pwParam, LPARAM *plParam, LRESULT *plResult); /* 20 */ + int (*tkWinIndexOfColor) (XColor *colorPtr); /* 21 */ + void (*tkWinReleaseDrawableDC) (Drawable d, HDC hdc, TkWinDCState *state); /* 22 */ + LRESULT (*tkWinResendEvent) (WNDPROC wndproc, HWND hwnd, XEvent *eventPtr); /* 23 */ + HPALETTE (*tkWinSelectPalette) (HDC dc, Colormap colormap); /* 24 */ + void (*tkWinSetMenu) (Tk_Window tkwin, HMENU hMenu); /* 25 */ + void (*tkWinSetWindowPos) (HWND hwnd, HWND siblingHwnd, int pos); /* 26 */ + void (*tkWinWmCleanup) (HINSTANCE hInstance); /* 27 */ + void (*tkWinXCleanup) (ClientData clientData); /* 28 */ + void (*tkWinXInit) (HINSTANCE hInstance); /* 29 */ + void (*tkWinSetForegroundWindow) (TkWindow *winPtr); /* 30 */ + void (*tkWinDialogDebug) (int debug); /* 31 */ + Tcl_Obj * (*tkWinGetMenuSystemDefault) (Tk_Window tkwin, CONST char *dbName, CONST char *className); /* 32 */ + int (*tkWinGetPlatformId) (void); /* 33 */ + void (*tkWinSetHINSTANCE) (HINSTANCE hInstance); /* 34 */ + int (*tkWinGetPlatformTheme) (void); /* 35 */ + LRESULT (CALLBACK *tkWinChildProc) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); /* 36 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + void (*tkGenerateActivateEvents) (TkWindow *winPtr, int active); /* 0 */ VOID *reserved1; VOID *reserved2; - unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */ - VOID *reserved4; - void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 5 */ - void (*tkpSetCapture) _ANSI_ARGS_((TkWindow *winPtr)); /* 6 */ - void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 7 */ - void (*tkpWmSetState) _ANSI_ARGS_((TkWindow *winPtr, int state)); /* 8 */ - VOID *reserved9; - void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 10 */ - VOID *reserved11; - VOID *reserved12; - Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow *winPtr)); /* 13 */ - int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 14 */ - VOID *reserved15; - void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 16 */ - VOID *reserved17; - unsigned int (*tkMacButtonKeyState) _ANSI_ARGS_((void)); /* 18 */ - void (*tkMacClearMenubarActive) _ANSI_ARGS_((void)); /* 19 */ - VOID *reserved20; - int (*tkMacDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 21 */ - void (*tkMacInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 22 */ - VOID *reserved23; - void (*tkMacHandleTearoffMenu) _ANSI_ARGS_((void)); /* 24 */ - VOID *reserved25; - VOID *reserved26; - void (*tkMacDoHLEvent) _ANSI_ARGS_((EventRecord *theEvent)); /* 27 */ - VOID *reserved28; - Time (*tkMacGenerateTime) _ANSI_ARGS_((void)); /* 29 */ - VOID *reserved30; - TkWindow * (*tkMacGetScrollbarGrowWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 31 */ - Window (*tkMacGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 32 */ - int (*tkMacGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 33 */ - void (*tkMacHandleMenuSelect) _ANSI_ARGS_((long mResult, int optionKeyPressed)); /* 34 */ - VOID *reserved35; - VOID *reserved36; - VOID *reserved37; - void (*tkMacInvalidateWindow) _ANSI_ARGS_((MacDrawable *macWin, int flag)); /* 38 */ - int (*tkMacIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 39 */ - void (*tkMacMakeRealWindowExist) _ANSI_ARGS_((TkWindow *winPtr)); /* 40 */ - BitMapPtr (*tkMacMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 41 */ - void (*tkMacMenuClick) _ANSI_ARGS_((void)); /* 42 */ - void (*tkMacRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 43 */ - int (*tkMacResizable) _ANSI_ARGS_((TkWindow *winPtr)); /* 44 */ - VOID *reserved45; - void (*tkMacSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 46 */ - void (*tkMacSetScrollbarGrow) _ANSI_ARGS_((TkWindow *winPtr, int flag)); /* 47 */ - void (*tkMacSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 48 */ - void (*tkMacSetUpGraphicsPort) _ANSI_ARGS_((GC gc)); /* 49 */ - void (*tkMacUpdateClipRgn) _ANSI_ARGS_((TkWindow *winPtr)); /* 50 */ - void (*tkMacUnregisterMacWindow) _ANSI_ARGS_((GWorldPtr portPtr)); /* 51 */ - int (*tkMacUseMenuID) _ANSI_ARGS_((short macID)); /* 52 */ - RgnHandle (*tkMacVisableClipRgn) _ANSI_ARGS_((TkWindow *winPtr)); /* 53 */ - void (*tkMacWinBounds) _ANSI_ARGS_((TkWindow *winPtr, Rect *geometry)); /* 54 */ - void (*tkMacWindowOffset) _ANSI_ARGS_((WindowRef wRef, int *xOffset, int *yOffset)); /* 55 */ - VOID *reserved56; - int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor *macColor)); /* 57 */ - void (*tkSetWMName) _ANSI_ARGS_((TkWindow *winPtr, Tk_Uid titleUid)); /* 58 */ - void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 59 */ - VOID *reserved60; - int (*tkMacZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, Point where, short zoomPart)); /* 61 */ - Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY)); /* 62 */ - MacDrawable * (*tkMacContainerId) _ANSI_ARGS_((TkWindow *winPtr)); /* 63 */ - MacDrawable * (*tkMacGetHostToplevel) _ANSI_ARGS_((TkWindow *winPtr)); /* 64 */ - void (*tkMacPreprocessMenu) _ANSI_ARGS_((void)); /* 65 */ - int (*tkpIsWindowFloating) _ANSI_ARGS_((WindowRef window)); /* 66 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow *winPtr, int active)); /* 0 */ - VOID *reserved1; - VOID *reserved2; - void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow *winPtr)); /* 3 */ - void (*tkpSetCapture) _ANSI_ARGS_((TkWindow *winPtr)); /* 4 */ - void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 5 */ - void (*tkpWmSetState) _ANSI_ARGS_((TkWindow *winPtr, int state)); /* 6 */ - void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 7 */ - unsigned int (*tkMacOSXButtonKeyState) _ANSI_ARGS_((void)); /* 8 */ - void (*tkMacOSXClearMenubarActive) _ANSI_ARGS_((void)); /* 9 */ - int (*tkMacOSXDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 10 */ - void (*tkMacOSXInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 11 */ - void (*tkMacOSXHandleTearoffMenu) _ANSI_ARGS_((void)); /* 12 */ + void (*tkPointerDeadWindow) (TkWindow *winPtr); /* 3 */ + void (*tkpSetCapture) (TkWindow *winPtr); /* 4 */ + void (*tkpSetCursor) (TkpCursor cursor); /* 5 */ + void (*tkpWmSetState) (TkWindow *winPtr, int state); /* 6 */ + void (*tkAboutDlg) (void); /* 7 */ + unsigned int (*tkMacOSXButtonKeyState) (void); /* 8 */ + void (*tkMacOSXClearMenubarActive) (void); /* 9 */ + int (*tkMacOSXDispatchMenuEvent) (int menuID, int index); /* 10 */ + void (*tkMacOSXInstallCursor) (int resizeOverride); /* 11 */ + void (*tkMacOSXHandleTearoffMenu) (void); /* 12 */ VOID *reserved13; - int (*tkMacOSXDoHLEvent) _ANSI_ARGS_((EventRecord *theEvent)); /* 14 */ + int (*tkMacOSXDoHLEvent) (EventRecord *theEvent); /* 14 */ VOID *reserved15; - Window (*tkMacOSXGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 16 */ - int (*tkMacOSXGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 17 */ - void (*tkMacOSXHandleMenuSelect) _ANSI_ARGS_((MenuID theMenu, MenuItemIndex theItem, int optionKeyPressed)); /* 18 */ + Window (*tkMacOSXGetXWindow) (WindowRef macWinPtr); /* 16 */ + int (*tkMacOSXGrowToplevel) (WindowRef whichWindow, Point start); /* 17 */ + void (*tkMacOSXHandleMenuSelect) (MenuID theMenu, MenuItemIndex theItem, int optionKeyPressed); /* 18 */ VOID *reserved19; VOID *reserved20; - void (*tkMacOSXInvalidateWindow) _ANSI_ARGS_((MacDrawable *macWin, int flag)); /* 21 */ - int (*tkMacOSXIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 22 */ - void (*tkMacOSXMakeRealWindowExist) _ANSI_ARGS_((TkWindow *winPtr)); /* 23 */ - BitMapPtr (*tkMacOSXMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 24 */ - void (*tkMacOSXMenuClick) _ANSI_ARGS_((void)); /* 25 */ - void (*tkMacOSXRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 26 */ - int (*tkMacOSXResizable) _ANSI_ARGS_((TkWindow *winPtr)); /* 27 */ - void (*tkMacOSXSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 28 */ - void (*tkMacOSXSetScrollbarGrow) _ANSI_ARGS_((TkWindow *winPtr, int flag)); /* 29 */ - void (*tkMacOSXSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 30 */ - void (*tkMacOSXSetUpGraphicsPort) _ANSI_ARGS_((GC gc, GWorldPtr destPort)); /* 31 */ - void (*tkMacOSXUpdateClipRgn) _ANSI_ARGS_((TkWindow *winPtr)); /* 32 */ - void (*tkMacOSXUnregisterMacWindow) _ANSI_ARGS_((WindowRef portPtr)); /* 33 */ - int (*tkMacOSXUseMenuID) _ANSI_ARGS_((short macID)); /* 34 */ - RgnHandle (*tkMacOSXVisableClipRgn) _ANSI_ARGS_((TkWindow *winPtr)); /* 35 */ - void (*tkMacOSXWinBounds) _ANSI_ARGS_((TkWindow *winPtr, Rect *geometry)); /* 36 */ - void (*tkMacOSXWindowOffset) _ANSI_ARGS_((WindowRef wRef, int *xOffset, int *yOffset)); /* 37 */ - int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor *macColor)); /* 38 */ - void (*tkSetWMName) _ANSI_ARGS_((TkWindow *winPtr, Tk_Uid titleUid)); /* 39 */ - void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 40 */ - int (*tkMacOSXZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, short zoomPart)); /* 41 */ - Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int *newX, int *newY)); /* 42 */ - MacDrawable * (*tkMacOSXContainerId) _ANSI_ARGS_((TkWindow *winPtr)); /* 43 */ - MacDrawable * (*tkMacOSXGetHostToplevel) _ANSI_ARGS_((TkWindow *winPtr)); /* 44 */ - void (*tkMacOSXPreprocessMenu) _ANSI_ARGS_((void)); /* 45 */ - int (*tkpIsWindowFloating) _ANSI_ARGS_((WindowRef window)); /* 46 */ - Tk_Window (*tkMacOSXGetCapture) _ANSI_ARGS_((void)); /* 47 */ + void (*tkMacOSXInvalidateWindow) (MacDrawable *macWin, int flag); /* 21 */ + int (*tkMacOSXIsCharacterMissing) (Tk_Font tkfont, unsigned int searchChar); /* 22 */ + void (*tkMacOSXMakeRealWindowExist) (TkWindow *winPtr); /* 23 */ + BitMapPtr (*tkMacOSXMakeStippleMap) (Drawable d1, Drawable d2); /* 24 */ + void (*tkMacOSXMenuClick) (void); /* 25 */ + void (*tkMacOSXRegisterOffScreenWindow) (Window window, GWorldPtr portPtr); /* 26 */ + int (*tkMacOSXResizable) (TkWindow *winPtr); /* 27 */ + void (*tkMacOSXSetHelpMenuItemCount) (void); /* 28 */ + void (*tkMacOSXSetScrollbarGrow) (TkWindow *winPtr, int flag); /* 29 */ + void (*tkMacOSXSetUpClippingRgn) (Drawable drawable); /* 30 */ + void (*tkMacOSXSetUpGraphicsPort) (GC gc, GWorldPtr destPort); /* 31 */ + void (*tkMacOSXUpdateClipRgn) (TkWindow *winPtr); /* 32 */ + void (*tkMacOSXUnregisterMacWindow) (WindowRef portPtr); /* 33 */ + int (*tkMacOSXUseMenuID) (short macID); /* 34 */ + RgnHandle (*tkMacOSXVisableClipRgn) (TkWindow *winPtr); /* 35 */ + void (*tkMacOSXWinBounds) (TkWindow *winPtr, Rect *geometry); /* 36 */ + void (*tkMacOSXWindowOffset) (WindowRef wRef, int *xOffset, int *yOffset); /* 37 */ + int (*tkSetMacColor) (unsigned long pixel, RGBColor *macColor); /* 38 */ + void (*tkSetWMName) (TkWindow *winPtr, Tk_Uid titleUid); /* 39 */ + void (*tkSuspendClipboard) (void); /* 40 */ + int (*tkMacOSXZoomToplevel) (WindowPtr 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 */ + MacDrawable * (*tkMacOSXGetHostToplevel) (TkWindow *winPtr); /* 44 */ + void (*tkMacOSXPreprocessMenu) (void); /* 45 */ + int (*tkpIsWindowFloating) (WindowRef window); /* 46 */ + Tk_Window (*tkMacOSXGetCapture) (void); /* 47 */ VOID *reserved48; - Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow *winPtr)); /* 49 */ - int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 50 */ - void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 51 */ + Window (*tkGetTransientMaster) (TkWindow *winPtr); /* 49 */ + int (*tkGenerateButtonEvent) (int x, int y, Window window, unsigned int state); /* 50 */ + void (*tkGenWMDestroyEvent) (Tk_Window tkwin); /* 51 */ VOID *reserved52; - unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 53 */ -#endif /* MAC_OSX_TK */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ - void (*tkCreateXEventSource) _ANSI_ARGS_((void)); /* 0 */ - void (*tkFreeWindowId) _ANSI_ARGS_((TkDisplay *dispPtr, Window w)); /* 1 */ - void (*tkInitXId) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 2 */ - int (*tkpCmapStressed) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 3 */ - void (*tkpSync) _ANSI_ARGS_((Display *display)); /* 4 */ - Window (*tkUnixContainerId) _ANSI_ARGS_((TkWindow *winPtr)); /* 5 */ - int (*tkUnixDoOneXEvent) _ANSI_ARGS_((Tcl_Time *timePtr)); /* 6 */ - void (*tkUnixSetMenubar) _ANSI_ARGS_((Tk_Window tkwin, Tk_Window menubar)); /* 7 */ - int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp *interp, CONST char *string, Window *idPtr)); /* 8 */ - void (*tkWmCleanup) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 9 */ - void (*tkSendCleanup) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 10 */ - void (*tkFreeXId) _ANSI_ARGS_((TkDisplay *dispPtr)); /* 11 */ - int (*tkpWmSetState) _ANSI_ARGS_((TkWindow *winPtr, int state)); /* 12 */ + unsigned long (*tkpGetMS) (void); /* 53 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ + void (*tkCreateXEventSource) (void); /* 0 */ + void (*tkFreeWindowId) (TkDisplay *dispPtr, Window w); /* 1 */ + void (*tkInitXId) (TkDisplay *dispPtr); /* 2 */ + int (*tkpCmapStressed) (Tk_Window tkwin, Colormap colormap); /* 3 */ + void (*tkpSync) (Display *display); /* 4 */ + Window (*tkUnixContainerId) (TkWindow *winPtr); /* 5 */ + int (*tkUnixDoOneXEvent) (Tcl_Time *timePtr); /* 6 */ + void (*tkUnixSetMenubar) (Tk_Window tkwin, Tk_Window menubar); /* 7 */ + int (*tkpScanWindowId) (Tcl_Interp *interp, CONST char *string, Window *idPtr); /* 8 */ + void (*tkWmCleanup) (TkDisplay *dispPtr); /* 9 */ + void (*tkSendCleanup) (TkDisplay *dispPtr); /* 10 */ + void (*tkFreeXId) (TkDisplay *dispPtr); /* 11 */ + int (*tkpWmSetState) (TkWindow *winPtr, int state); /* 12 */ + int (*tkpTestsendCmd) (ClientData clientData, Tcl_Interp *interp, int argc, CONST char **argv); /* 13 */ #endif /* X11 */ } TkIntPlatStubs; @@ -617,7 +685,7 @@ extern TkIntPlatStubs *tkIntPlatStubsPtr; * Inline function declarations: */ -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ #ifndef TkAlignImageData #define TkAlignImageData \ (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */ @@ -759,218 +827,12 @@ extern TkIntPlatStubs *tkIntPlatStubsPtr; #define TkWinGetPlatformTheme \ (tkIntPlatStubsPtr->tkWinGetPlatformTheme) /* 35 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL -#ifndef TkGenerateActivateEvents -#define TkGenerateActivateEvents \ - (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */ -#endif -/* Slot 1 is reserved */ -/* Slot 2 is reserved */ -#ifndef TkpGetMS -#define TkpGetMS \ - (tkIntPlatStubsPtr->tkpGetMS) /* 3 */ -#endif -/* Slot 4 is reserved */ -#ifndef TkPointerDeadWindow -#define TkPointerDeadWindow \ - (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 5 */ -#endif -#ifndef TkpSetCapture -#define TkpSetCapture \ - (tkIntPlatStubsPtr->tkpSetCapture) /* 6 */ -#endif -#ifndef TkpSetCursor -#define TkpSetCursor \ - (tkIntPlatStubsPtr->tkpSetCursor) /* 7 */ -#endif -#ifndef TkpWmSetState -#define TkpWmSetState \ - (tkIntPlatStubsPtr->tkpWmSetState) /* 8 */ +#ifndef TkWinChildProc +#define TkWinChildProc \ + (tkIntPlatStubsPtr->tkWinChildProc) /* 36 */ #endif -/* Slot 9 is reserved */ -#ifndef TkAboutDlg -#define TkAboutDlg \ - (tkIntPlatStubsPtr->tkAboutDlg) /* 10 */ -#endif -/* Slot 11 is reserved */ -/* Slot 12 is reserved */ -#ifndef TkGetTransientMaster -#define TkGetTransientMaster \ - (tkIntPlatStubsPtr->tkGetTransientMaster) /* 13 */ -#endif -#ifndef TkGenerateButtonEvent -#define TkGenerateButtonEvent \ - (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 14 */ -#endif -/* Slot 15 is reserved */ -#ifndef TkGenWMDestroyEvent -#define TkGenWMDestroyEvent \ - (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 16 */ -#endif -/* Slot 17 is reserved */ -#ifndef TkMacButtonKeyState -#define TkMacButtonKeyState \ - (tkIntPlatStubsPtr->tkMacButtonKeyState) /* 18 */ -#endif -#ifndef TkMacClearMenubarActive -#define TkMacClearMenubarActive \ - (tkIntPlatStubsPtr->tkMacClearMenubarActive) /* 19 */ -#endif -/* Slot 20 is reserved */ -#ifndef TkMacDispatchMenuEvent -#define TkMacDispatchMenuEvent \ - (tkIntPlatStubsPtr->tkMacDispatchMenuEvent) /* 21 */ -#endif -#ifndef TkMacInstallCursor -#define TkMacInstallCursor \ - (tkIntPlatStubsPtr->tkMacInstallCursor) /* 22 */ -#endif -/* Slot 23 is reserved */ -#ifndef TkMacHandleTearoffMenu -#define TkMacHandleTearoffMenu \ - (tkIntPlatStubsPtr->tkMacHandleTearoffMenu) /* 24 */ -#endif -/* Slot 25 is reserved */ -/* Slot 26 is reserved */ -#ifndef TkMacDoHLEvent -#define TkMacDoHLEvent \ - (tkIntPlatStubsPtr->tkMacDoHLEvent) /* 27 */ -#endif -/* Slot 28 is reserved */ -#ifndef TkMacGenerateTime -#define TkMacGenerateTime \ - (tkIntPlatStubsPtr->tkMacGenerateTime) /* 29 */ -#endif -/* Slot 30 is reserved */ -#ifndef TkMacGetScrollbarGrowWindow -#define TkMacGetScrollbarGrowWindow \ - (tkIntPlatStubsPtr->tkMacGetScrollbarGrowWindow) /* 31 */ -#endif -#ifndef TkMacGetXWindow -#define TkMacGetXWindow \ - (tkIntPlatStubsPtr->tkMacGetXWindow) /* 32 */ -#endif -#ifndef TkMacGrowToplevel -#define TkMacGrowToplevel \ - (tkIntPlatStubsPtr->tkMacGrowToplevel) /* 33 */ -#endif -#ifndef TkMacHandleMenuSelect -#define TkMacHandleMenuSelect \ - (tkIntPlatStubsPtr->tkMacHandleMenuSelect) /* 34 */ -#endif -/* Slot 35 is reserved */ -/* Slot 36 is reserved */ -/* Slot 37 is reserved */ -#ifndef TkMacInvalidateWindow -#define TkMacInvalidateWindow \ - (tkIntPlatStubsPtr->tkMacInvalidateWindow) /* 38 */ -#endif -#ifndef TkMacIsCharacterMissing -#define TkMacIsCharacterMissing \ - (tkIntPlatStubsPtr->tkMacIsCharacterMissing) /* 39 */ -#endif -#ifndef TkMacMakeRealWindowExist -#define TkMacMakeRealWindowExist \ - (tkIntPlatStubsPtr->tkMacMakeRealWindowExist) /* 40 */ -#endif -#ifndef TkMacMakeStippleMap -#define TkMacMakeStippleMap \ - (tkIntPlatStubsPtr->tkMacMakeStippleMap) /* 41 */ -#endif -#ifndef TkMacMenuClick -#define TkMacMenuClick \ - (tkIntPlatStubsPtr->tkMacMenuClick) /* 42 */ -#endif -#ifndef TkMacRegisterOffScreenWindow -#define TkMacRegisterOffScreenWindow \ - (tkIntPlatStubsPtr->tkMacRegisterOffScreenWindow) /* 43 */ -#endif -#ifndef TkMacResizable -#define TkMacResizable \ - (tkIntPlatStubsPtr->tkMacResizable) /* 44 */ -#endif -/* Slot 45 is reserved */ -#ifndef TkMacSetHelpMenuItemCount -#define TkMacSetHelpMenuItemCount \ - (tkIntPlatStubsPtr->tkMacSetHelpMenuItemCount) /* 46 */ -#endif -#ifndef TkMacSetScrollbarGrow -#define TkMacSetScrollbarGrow \ - (tkIntPlatStubsPtr->tkMacSetScrollbarGrow) /* 47 */ -#endif -#ifndef TkMacSetUpClippingRgn -#define TkMacSetUpClippingRgn \ - (tkIntPlatStubsPtr->tkMacSetUpClippingRgn) /* 48 */ -#endif -#ifndef TkMacSetUpGraphicsPort -#define TkMacSetUpGraphicsPort \ - (tkIntPlatStubsPtr->tkMacSetUpGraphicsPort) /* 49 */ -#endif -#ifndef TkMacUpdateClipRgn -#define TkMacUpdateClipRgn \ - (tkIntPlatStubsPtr->tkMacUpdateClipRgn) /* 50 */ -#endif -#ifndef TkMacUnregisterMacWindow -#define TkMacUnregisterMacWindow \ - (tkIntPlatStubsPtr->tkMacUnregisterMacWindow) /* 51 */ -#endif -#ifndef TkMacUseMenuID -#define TkMacUseMenuID \ - (tkIntPlatStubsPtr->tkMacUseMenuID) /* 52 */ -#endif -#ifndef TkMacVisableClipRgn -#define TkMacVisableClipRgn \ - (tkIntPlatStubsPtr->tkMacVisableClipRgn) /* 53 */ -#endif -#ifndef TkMacWinBounds -#define TkMacWinBounds \ - (tkIntPlatStubsPtr->tkMacWinBounds) /* 54 */ -#endif -#ifndef TkMacWindowOffset -#define TkMacWindowOffset \ - (tkIntPlatStubsPtr->tkMacWindowOffset) /* 55 */ -#endif -/* Slot 56 is reserved */ -#ifndef TkSetMacColor -#define TkSetMacColor \ - (tkIntPlatStubsPtr->tkSetMacColor) /* 57 */ -#endif -#ifndef TkSetWMName -#define TkSetWMName \ - (tkIntPlatStubsPtr->tkSetWMName) /* 58 */ -#endif -#ifndef TkSuspendClipboard -#define TkSuspendClipboard \ - (tkIntPlatStubsPtr->tkSuspendClipboard) /* 59 */ -#endif -/* Slot 60 is reserved */ -#ifndef TkMacZoomToplevel -#define TkMacZoomToplevel \ - (tkIntPlatStubsPtr->tkMacZoomToplevel) /* 61 */ -#endif -#ifndef Tk_TopCoordsToWindow -#define Tk_TopCoordsToWindow \ - (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 62 */ -#endif -#ifndef TkMacContainerId -#define TkMacContainerId \ - (tkIntPlatStubsPtr->tkMacContainerId) /* 63 */ -#endif -#ifndef TkMacGetHostToplevel -#define TkMacGetHostToplevel \ - (tkIntPlatStubsPtr->tkMacGetHostToplevel) /* 64 */ -#endif -#ifndef TkMacPreprocessMenu -#define TkMacPreprocessMenu \ - (tkIntPlatStubsPtr->tkMacPreprocessMenu) /* 65 */ -#endif -#ifndef TkpIsWindowFloating -#define TkpIsWindowFloating \ - (tkIntPlatStubsPtr->tkpIsWindowFloating) /* 66 */ -#endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef TkGenerateActivateEvents #define TkGenerateActivateEvents \ (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */ @@ -1163,8 +1025,8 @@ extern TkIntPlatStubs *tkIntPlatStubsPtr; #define TkpGetMS \ (tkIntPlatStubsPtr->tkpGetMS) /* 53 */ #endif -#endif /* MAC_OSX_TK */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ #ifndef TkCreateXEventSource #define TkCreateXEventSource \ (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */ @@ -1217,6 +1079,10 @@ extern TkIntPlatStubs *tkIntPlatStubsPtr; #define TkpWmSetState \ (tkIntPlatStubsPtr->tkpWmSetState) /* 12 */ #endif +#ifndef TkpTestsendCmd +#define TkpTestsendCmd \ + (tkIntPlatStubsPtr->tkpTestsendCmd) /* 13 */ +#endif #endif /* X11 */ #endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ diff --git a/generic/tkIntXlibDecls.h b/generic/tkIntXlibDecls.h index 77f6b4d..bf80342 100644 --- a/generic/tkIntXlibDecls.h +++ b/generic/tkIntXlibDecls.h @@ -13,11 +13,7 @@ #ifndef _TKINTXLIBDECLS #define _TKINTXLIBDECLS -#ifdef MAC_TCL -#include "Xutil.h" -#else #include "X11/Xutil.h" -#endif #ifdef BUILD_tk #undef TCL_STORAGE_CLASS @@ -36,1217 +32,1370 @@ * Exported function declarations: */ -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ +#ifndef XSetDashes_TCL_DECLARED +#define XSetDashes_TCL_DECLARED /* 0 */ -EXTERN void XSetDashes _ANSI_ARGS_((Display *display, GC gc, - int dash_offset, _Xconst char *dash_list, - int n)); +EXTERN void XSetDashes(Display *display, GC gc, int dash_offset, + _Xconst char *dash_list, int n); +#endif +#ifndef XGetModifierMapping_TCL_DECLARED +#define XGetModifierMapping_TCL_DECLARED /* 1 */ -EXTERN XModifierKeymap * XGetModifierMapping _ANSI_ARGS_((Display *d)); +EXTERN XModifierKeymap * XGetModifierMapping(Display *d); +#endif +#ifndef XCreateImage_TCL_DECLARED +#define XCreateImage_TCL_DECLARED /* 2 */ -EXTERN XImage * XCreateImage _ANSI_ARGS_((Display *d, Visual *v, - unsigned int ui1, int i1, int i2, char *cp, - unsigned int ui2, unsigned int ui3, int i3, - int i4)); +EXTERN XImage * XCreateImage(Display *d, Visual *v, unsigned int ui1, + int i1, int i2, char *cp, unsigned int ui2, + unsigned int ui3, int i3, int i4); +#endif +#ifndef XGetImage_TCL_DECLARED +#define XGetImage_TCL_DECLARED /* 3 */ -EXTERN XImage * XGetImage _ANSI_ARGS_((Display *d, Drawable dr, - int i1, int i2, unsigned int ui1, - unsigned int ui2, unsigned long ul, int i3)); +EXTERN XImage * XGetImage(Display *d, Drawable dr, int i1, int i2, + unsigned int ui1, unsigned int ui2, + unsigned long ul, int i3); +#endif +#ifndef XGetAtomName_TCL_DECLARED +#define XGetAtomName_TCL_DECLARED /* 4 */ -EXTERN char * XGetAtomName _ANSI_ARGS_((Display *d, Atom a)); +EXTERN char * XGetAtomName(Display *d, Atom a); +#endif +#ifndef XKeysymToString_TCL_DECLARED +#define XKeysymToString_TCL_DECLARED /* 5 */ -EXTERN char * XKeysymToString _ANSI_ARGS_((KeySym k)); +EXTERN char * XKeysymToString(KeySym k); +#endif +#ifndef XCreateColormap_TCL_DECLARED +#define XCreateColormap_TCL_DECLARED /* 6 */ -EXTERN Colormap XCreateColormap _ANSI_ARGS_((Display *d, Window w, - Visual *v, int i)); +EXTERN Colormap XCreateColormap(Display *d, Window w, Visual *v, + int i); +#endif +#ifndef XCreatePixmapCursor_TCL_DECLARED +#define XCreatePixmapCursor_TCL_DECLARED /* 7 */ -EXTERN Cursor XCreatePixmapCursor _ANSI_ARGS_((Display *d, - Pixmap p1, Pixmap p2, XColor *x1, XColor *x2, - unsigned int ui1, unsigned int ui2)); +EXTERN Cursor XCreatePixmapCursor(Display *d, Pixmap p1, Pixmap p2, + XColor *x1, XColor *x2, unsigned int ui1, + unsigned int ui2); +#endif +#ifndef XCreateGlyphCursor_TCL_DECLARED +#define XCreateGlyphCursor_TCL_DECLARED /* 8 */ -EXTERN Cursor XCreateGlyphCursor _ANSI_ARGS_((Display *d, Font f1, - Font f2, unsigned int ui1, unsigned int ui2, - XColor *x1, XColor *x2)); +EXTERN Cursor XCreateGlyphCursor(Display *d, Font f1, Font f2, + unsigned int ui1, unsigned int ui2, + XColor *x1, XColor *x2); +#endif +#ifndef XGContextFromGC_TCL_DECLARED +#define XGContextFromGC_TCL_DECLARED /* 9 */ -EXTERN GContext XGContextFromGC _ANSI_ARGS_((GC g)); +EXTERN GContext XGContextFromGC(GC g); +#endif +#ifndef XListHosts_TCL_DECLARED +#define XListHosts_TCL_DECLARED /* 10 */ -EXTERN XHostAddress * XListHosts _ANSI_ARGS_((Display *d, int *i, Bool *b)); +EXTERN XHostAddress * XListHosts(Display *d, int *i, Bool *b); +#endif +#ifndef XKeycodeToKeysym_TCL_DECLARED +#define XKeycodeToKeysym_TCL_DECLARED /* 11 */ -EXTERN KeySym XKeycodeToKeysym _ANSI_ARGS_((Display *d, - unsigned int k, int i)); +EXTERN KeySym XKeycodeToKeysym(Display *d, unsigned int k, int i); +#endif +#ifndef XStringToKeysym_TCL_DECLARED +#define XStringToKeysym_TCL_DECLARED /* 12 */ -EXTERN KeySym XStringToKeysym _ANSI_ARGS_((_Xconst char *c)); +EXTERN KeySym XStringToKeysym(_Xconst char *c); +#endif +#ifndef XRootWindow_TCL_DECLARED +#define XRootWindow_TCL_DECLARED /* 13 */ -EXTERN Window XRootWindow _ANSI_ARGS_((Display *d, int i)); +EXTERN Window XRootWindow(Display *d, int i); +#endif +#ifndef XSetErrorHandler_TCL_DECLARED +#define XSetErrorHandler_TCL_DECLARED /* 14 */ -EXTERN XErrorHandler XSetErrorHandler _ANSI_ARGS_((XErrorHandler x)); +EXTERN XErrorHandler XSetErrorHandler(XErrorHandler x); +#endif +#ifndef XIconifyWindow_TCL_DECLARED +#define XIconifyWindow_TCL_DECLARED /* 15 */ -EXTERN Status XIconifyWindow _ANSI_ARGS_((Display *d, Window w, - int i)); +EXTERN Status XIconifyWindow(Display *d, Window w, int i); +#endif +#ifndef XWithdrawWindow_TCL_DECLARED +#define XWithdrawWindow_TCL_DECLARED /* 16 */ -EXTERN Status XWithdrawWindow _ANSI_ARGS_((Display *d, Window w, - int i)); +EXTERN Status XWithdrawWindow(Display *d, Window w, int i); +#endif +#ifndef XGetWMColormapWindows_TCL_DECLARED +#define XGetWMColormapWindows_TCL_DECLARED /* 17 */ -EXTERN Status XGetWMColormapWindows _ANSI_ARGS_((Display *d, - Window w, Window **wpp, int *ip)); +EXTERN Status XGetWMColormapWindows(Display *d, Window w, + Window **wpp, int *ip); +#endif +#ifndef XAllocColor_TCL_DECLARED +#define XAllocColor_TCL_DECLARED /* 18 */ -EXTERN Status XAllocColor _ANSI_ARGS_((Display *d, Colormap c, - XColor *xp)); +EXTERN Status XAllocColor(Display *d, Colormap c, XColor *xp); +#endif +#ifndef XBell_TCL_DECLARED +#define XBell_TCL_DECLARED /* 19 */ -EXTERN void XBell _ANSI_ARGS_((Display *d, int i)); +EXTERN void XBell(Display *d, int i); +#endif +#ifndef XChangeProperty_TCL_DECLARED +#define XChangeProperty_TCL_DECLARED /* 20 */ -EXTERN void XChangeProperty _ANSI_ARGS_((Display *d, Window w, - Atom a1, Atom a2, int i1, int i2, - _Xconst unsigned char *c, int i3)); +EXTERN void XChangeProperty(Display *d, Window w, Atom a1, + Atom a2, int i1, int i2, + _Xconst unsigned char *c, int i3); +#endif +#ifndef XChangeWindowAttributes_TCL_DECLARED +#define XChangeWindowAttributes_TCL_DECLARED /* 21 */ -EXTERN void XChangeWindowAttributes _ANSI_ARGS_((Display *d, - Window w, unsigned long ul, - XSetWindowAttributes *x)); +EXTERN void XChangeWindowAttributes(Display *d, Window w, + unsigned long ul, XSetWindowAttributes *x); +#endif +#ifndef XClearWindow_TCL_DECLARED +#define XClearWindow_TCL_DECLARED /* 22 */ -EXTERN void XClearWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XClearWindow(Display *d, Window w); +#endif +#ifndef XConfigureWindow_TCL_DECLARED +#define XConfigureWindow_TCL_DECLARED /* 23 */ -EXTERN void XConfigureWindow _ANSI_ARGS_((Display *d, Window w, - unsigned int i, XWindowChanges *x)); +EXTERN void XConfigureWindow(Display *d, Window w, + unsigned int i, XWindowChanges *x); +#endif +#ifndef XCopyArea_TCL_DECLARED +#define XCopyArea_TCL_DECLARED /* 24 */ -EXTERN void XCopyArea _ANSI_ARGS_((Display *d, Drawable dr1, - Drawable dr2, GC g, int i1, int i2, - unsigned int ui1, unsigned int ui2, int i3, - int i4)); +EXTERN void XCopyArea(Display *d, Drawable dr1, Drawable dr2, + GC g, int i1, int i2, unsigned int ui1, + unsigned int ui2, int i3, int i4); +#endif +#ifndef XCopyPlane_TCL_DECLARED +#define XCopyPlane_TCL_DECLARED /* 25 */ -EXTERN void XCopyPlane _ANSI_ARGS_((Display *d, Drawable dr1, - Drawable dr2, GC g, int i1, int i2, - unsigned int ui1, unsigned int ui2, int i3, - int i4, unsigned long ul)); +EXTERN void XCopyPlane(Display *d, Drawable dr1, Drawable dr2, + GC g, int i1, int i2, unsigned int ui1, + unsigned int ui2, int i3, int i4, + unsigned long ul); +#endif +#ifndef XCreateBitmapFromData_TCL_DECLARED +#define XCreateBitmapFromData_TCL_DECLARED /* 26 */ -EXTERN Pixmap XCreateBitmapFromData _ANSI_ARGS_((Display *display, - Drawable d, _Xconst char *data, - unsigned int width, unsigned int height)); +EXTERN Pixmap XCreateBitmapFromData(Display *display, Drawable d, + _Xconst char *data, unsigned int width, + unsigned int height); +#endif +#ifndef XDefineCursor_TCL_DECLARED +#define XDefineCursor_TCL_DECLARED /* 27 */ -EXTERN void XDefineCursor _ANSI_ARGS_((Display *d, Window w, - Cursor c)); +EXTERN void XDefineCursor(Display *d, Window w, Cursor c); +#endif +#ifndef XDeleteProperty_TCL_DECLARED +#define XDeleteProperty_TCL_DECLARED /* 28 */ -EXTERN void XDeleteProperty _ANSI_ARGS_((Display *d, Window w, - Atom a)); +EXTERN void XDeleteProperty(Display *d, Window w, Atom a); +#endif +#ifndef XDestroyWindow_TCL_DECLARED +#define XDestroyWindow_TCL_DECLARED /* 29 */ -EXTERN void XDestroyWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XDestroyWindow(Display *d, Window w); +#endif +#ifndef XDrawArc_TCL_DECLARED +#define XDrawArc_TCL_DECLARED /* 30 */ -EXTERN void XDrawArc _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int i1, int i2, unsigned int ui1, - unsigned int ui2, int i3, int i4)); +EXTERN void XDrawArc(Display *d, Drawable dr, GC g, int i1, + int i2, unsigned int ui1, unsigned int ui2, + int i3, int i4); +#endif +#ifndef XDrawLines_TCL_DECLARED +#define XDrawLines_TCL_DECLARED /* 31 */ -EXTERN void XDrawLines _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XPoint *x, int i1, int i2)); +EXTERN void XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, + int i1, int i2); +#endif +#ifndef XDrawRectangle_TCL_DECLARED +#define XDrawRectangle_TCL_DECLARED /* 32 */ -EXTERN void XDrawRectangle _ANSI_ARGS_((Display *d, Drawable dr, - GC g, int i1, int i2, unsigned int ui1, - unsigned int ui2)); +EXTERN void XDrawRectangle(Display *d, Drawable dr, GC g, int i1, + int i2, unsigned int ui1, unsigned int ui2); +#endif +#ifndef XFillArc_TCL_DECLARED +#define XFillArc_TCL_DECLARED /* 33 */ -EXTERN void XFillArc _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int i1, int i2, unsigned int ui1, - unsigned int ui2, int i3, int i4)); +EXTERN void XFillArc(Display *d, Drawable dr, GC g, int i1, + int i2, unsigned int ui1, unsigned int ui2, + int i3, int i4); +#endif +#ifndef XFillPolygon_TCL_DECLARED +#define XFillPolygon_TCL_DECLARED /* 34 */ -EXTERN void XFillPolygon _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XPoint *x, int i1, int i2, int i3)); +EXTERN void XFillPolygon(Display *d, Drawable dr, GC g, + XPoint *x, int i1, int i2, int i3); +#endif +#ifndef XFillRectangles_TCL_DECLARED +#define XFillRectangles_TCL_DECLARED /* 35 */ -EXTERN void XFillRectangles _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XRectangle *x, int i)); +EXTERN void XFillRectangles(Display *d, Drawable dr, GC g, + XRectangle *x, int i); +#endif +#ifndef XForceScreenSaver_TCL_DECLARED +#define XForceScreenSaver_TCL_DECLARED /* 36 */ -EXTERN void XForceScreenSaver _ANSI_ARGS_((Display *d, int i)); +EXTERN void XForceScreenSaver(Display *d, int i); +#endif +#ifndef XFreeColormap_TCL_DECLARED +#define XFreeColormap_TCL_DECLARED /* 37 */ -EXTERN void XFreeColormap _ANSI_ARGS_((Display *d, Colormap c)); +EXTERN void XFreeColormap(Display *d, Colormap c); +#endif +#ifndef XFreeColors_TCL_DECLARED +#define XFreeColors_TCL_DECLARED /* 38 */ -EXTERN void XFreeColors _ANSI_ARGS_((Display *d, Colormap c, - unsigned long *ulp, int i, unsigned long ul)); +EXTERN void XFreeColors(Display *d, Colormap c, + unsigned long *ulp, int i, unsigned long ul); +#endif +#ifndef XFreeCursor_TCL_DECLARED +#define XFreeCursor_TCL_DECLARED /* 39 */ -EXTERN void XFreeCursor _ANSI_ARGS_((Display *d, Cursor c)); +EXTERN void XFreeCursor(Display *d, Cursor c); +#endif +#ifndef XFreeModifiermap_TCL_DECLARED +#define XFreeModifiermap_TCL_DECLARED /* 40 */ -EXTERN void XFreeModifiermap _ANSI_ARGS_((XModifierKeymap *x)); +EXTERN void XFreeModifiermap(XModifierKeymap *x); +#endif +#ifndef XGetGeometry_TCL_DECLARED +#define XGetGeometry_TCL_DECLARED /* 41 */ -EXTERN Status XGetGeometry _ANSI_ARGS_((Display *d, Drawable dr, - Window *w, int *i1, int *i2, - unsigned int *ui1, unsigned int *ui2, - unsigned int *ui3, unsigned int *ui4)); +EXTERN Status XGetGeometry(Display *d, Drawable dr, Window *w, + int *i1, int *i2, unsigned int *ui1, + unsigned int *ui2, unsigned int *ui3, + unsigned int *ui4); +#endif +#ifndef XGetInputFocus_TCL_DECLARED +#define XGetInputFocus_TCL_DECLARED /* 42 */ -EXTERN void XGetInputFocus _ANSI_ARGS_((Display *d, Window *w, - int *i)); +EXTERN void XGetInputFocus(Display *d, Window *w, int *i); +#endif +#ifndef XGetWindowProperty_TCL_DECLARED +#define XGetWindowProperty_TCL_DECLARED /* 43 */ -EXTERN int XGetWindowProperty _ANSI_ARGS_((Display *d, Window w, - Atom a1, long l1, long l2, Bool b, Atom a2, - Atom *ap, int *ip, unsigned long *ulp1, - unsigned long *ulp2, unsigned char **cpp)); +EXTERN int XGetWindowProperty(Display *d, Window w, Atom a1, + long l1, long l2, Bool b, Atom a2, Atom *ap, + int *ip, unsigned long *ulp1, + unsigned long *ulp2, unsigned char **cpp); +#endif +#ifndef XGetWindowAttributes_TCL_DECLARED +#define XGetWindowAttributes_TCL_DECLARED /* 44 */ -EXTERN Status XGetWindowAttributes _ANSI_ARGS_((Display *d, - Window w, XWindowAttributes *x)); +EXTERN Status XGetWindowAttributes(Display *d, Window w, + XWindowAttributes *x); +#endif +#ifndef XGrabKeyboard_TCL_DECLARED +#define XGrabKeyboard_TCL_DECLARED /* 45 */ -EXTERN int XGrabKeyboard _ANSI_ARGS_((Display *d, Window w, - Bool b, int i1, int i2, Time t)); +EXTERN int XGrabKeyboard(Display *d, Window w, Bool b, int i1, + int i2, Time t); +#endif +#ifndef XGrabPointer_TCL_DECLARED +#define XGrabPointer_TCL_DECLARED /* 46 */ -EXTERN int XGrabPointer _ANSI_ARGS_((Display *d, Window w1, - Bool b, unsigned int ui, int i1, int i2, - Window w2, Cursor c, Time t)); +EXTERN int XGrabPointer(Display *d, Window w1, Bool b, + unsigned int ui, int i1, int i2, Window w2, + Cursor c, Time t); +#endif +#ifndef XKeysymToKeycode_TCL_DECLARED +#define XKeysymToKeycode_TCL_DECLARED /* 47 */ -EXTERN KeyCode XKeysymToKeycode _ANSI_ARGS_((Display *d, KeySym k)); +EXTERN KeyCode XKeysymToKeycode(Display *d, KeySym k); +#endif +#ifndef XLookupColor_TCL_DECLARED +#define XLookupColor_TCL_DECLARED /* 48 */ -EXTERN Status XLookupColor _ANSI_ARGS_((Display *d, Colormap c1, - _Xconst char *c2, XColor *x1, XColor *x2)); +EXTERN Status XLookupColor(Display *d, Colormap c1, + _Xconst char *c2, XColor *x1, XColor *x2); +#endif +#ifndef XMapWindow_TCL_DECLARED +#define XMapWindow_TCL_DECLARED /* 49 */ -EXTERN void XMapWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XMapWindow(Display *d, Window w); +#endif +#ifndef XMoveResizeWindow_TCL_DECLARED +#define XMoveResizeWindow_TCL_DECLARED /* 50 */ -EXTERN void XMoveResizeWindow _ANSI_ARGS_((Display *d, Window w, - int i1, int i2, unsigned int ui1, - unsigned int ui2)); +EXTERN void XMoveResizeWindow(Display *d, Window w, int i1, + int i2, unsigned int ui1, unsigned int ui2); +#endif +#ifndef XMoveWindow_TCL_DECLARED +#define XMoveWindow_TCL_DECLARED /* 51 */ -EXTERN void XMoveWindow _ANSI_ARGS_((Display *d, Window w, - int i1, int i2)); +EXTERN void XMoveWindow(Display *d, Window w, int i1, int i2); +#endif +#ifndef XNextEvent_TCL_DECLARED +#define XNextEvent_TCL_DECLARED /* 52 */ -EXTERN void XNextEvent _ANSI_ARGS_((Display *d, XEvent *x)); +EXTERN void XNextEvent(Display *d, XEvent *x); +#endif +#ifndef XPutBackEvent_TCL_DECLARED +#define XPutBackEvent_TCL_DECLARED /* 53 */ -EXTERN void XPutBackEvent _ANSI_ARGS_((Display *d, XEvent *x)); +EXTERN void XPutBackEvent(Display *d, XEvent *x); +#endif +#ifndef XQueryColors_TCL_DECLARED +#define XQueryColors_TCL_DECLARED /* 54 */ -EXTERN void XQueryColors _ANSI_ARGS_((Display *d, Colormap c, - XColor *x, int i)); +EXTERN void XQueryColors(Display *d, Colormap c, XColor *x, + int i); +#endif +#ifndef XQueryPointer_TCL_DECLARED +#define XQueryPointer_TCL_DECLARED /* 55 */ -EXTERN Bool XQueryPointer _ANSI_ARGS_((Display *d, Window w1, - Window *w2, Window *w3, int *i1, int *i2, - int *i3, int *i4, unsigned int *ui)); +EXTERN Bool XQueryPointer(Display *d, Window w1, Window *w2, + Window *w3, int *i1, int *i2, int *i3, + int *i4, unsigned int *ui); +#endif +#ifndef XQueryTree_TCL_DECLARED +#define XQueryTree_TCL_DECLARED /* 56 */ -EXTERN Status XQueryTree _ANSI_ARGS_((Display *d, Window w1, - Window *w2, Window *w3, Window **w4, - unsigned int *ui)); +EXTERN Status XQueryTree(Display *d, Window w1, Window *w2, + Window *w3, Window **w4, unsigned int *ui); +#endif +#ifndef XRaiseWindow_TCL_DECLARED +#define XRaiseWindow_TCL_DECLARED /* 57 */ -EXTERN void XRaiseWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XRaiseWindow(Display *d, Window w); +#endif +#ifndef XRefreshKeyboardMapping_TCL_DECLARED +#define XRefreshKeyboardMapping_TCL_DECLARED /* 58 */ -EXTERN void XRefreshKeyboardMapping _ANSI_ARGS_(( - XMappingEvent *x)); +EXTERN void XRefreshKeyboardMapping(XMappingEvent *x); +#endif +#ifndef XResizeWindow_TCL_DECLARED +#define XResizeWindow_TCL_DECLARED /* 59 */ -EXTERN void XResizeWindow _ANSI_ARGS_((Display *d, Window w, - unsigned int ui1, unsigned int ui2)); +EXTERN void XResizeWindow(Display *d, Window w, unsigned int ui1, + unsigned int ui2); +#endif +#ifndef XSelectInput_TCL_DECLARED +#define XSelectInput_TCL_DECLARED /* 60 */ -EXTERN void XSelectInput _ANSI_ARGS_((Display *d, Window w, - long l)); +EXTERN void XSelectInput(Display *d, Window w, long l); +#endif +#ifndef XSendEvent_TCL_DECLARED +#define XSendEvent_TCL_DECLARED /* 61 */ -EXTERN Status XSendEvent _ANSI_ARGS_((Display *d, Window w, Bool b, - long l, XEvent *x)); +EXTERN Status XSendEvent(Display *d, Window w, Bool b, long l, + XEvent *x); +#endif +#ifndef XSetCommand_TCL_DECLARED +#define XSetCommand_TCL_DECLARED /* 62 */ -EXTERN void XSetCommand _ANSI_ARGS_((Display *d, Window w, - CONST char **c, int i)); +EXTERN void XSetCommand(Display *d, Window w, CONST char **c, + int i); +#endif +#ifndef XSetIconName_TCL_DECLARED +#define XSetIconName_TCL_DECLARED /* 63 */ -EXTERN void XSetIconName _ANSI_ARGS_((Display *d, Window w, - _Xconst char *c)); +EXTERN void XSetIconName(Display *d, Window w, _Xconst char *c); +#endif +#ifndef XSetInputFocus_TCL_DECLARED +#define XSetInputFocus_TCL_DECLARED /* 64 */ -EXTERN void XSetInputFocus _ANSI_ARGS_((Display *d, Window w, - int i, Time t)); +EXTERN void XSetInputFocus(Display *d, Window w, int i, Time t); +#endif +#ifndef XSetSelectionOwner_TCL_DECLARED +#define XSetSelectionOwner_TCL_DECLARED /* 65 */ -EXTERN void XSetSelectionOwner _ANSI_ARGS_((Display *d, Atom a, - Window w, Time t)); +EXTERN void XSetSelectionOwner(Display *d, Atom a, Window w, + Time t); +#endif +#ifndef XSetWindowBackground_TCL_DECLARED +#define XSetWindowBackground_TCL_DECLARED /* 66 */ -EXTERN void XSetWindowBackground _ANSI_ARGS_((Display *d, - Window w, unsigned long ul)); +EXTERN void XSetWindowBackground(Display *d, Window w, + unsigned long ul); +#endif +#ifndef XSetWindowBackgroundPixmap_TCL_DECLARED +#define XSetWindowBackgroundPixmap_TCL_DECLARED /* 67 */ -EXTERN void XSetWindowBackgroundPixmap _ANSI_ARGS_((Display *d, - Window w, Pixmap p)); +EXTERN void XSetWindowBackgroundPixmap(Display *d, Window w, + Pixmap p); +#endif +#ifndef XSetWindowBorder_TCL_DECLARED +#define XSetWindowBorder_TCL_DECLARED /* 68 */ -EXTERN void XSetWindowBorder _ANSI_ARGS_((Display *d, Window w, - unsigned long ul)); +EXTERN void XSetWindowBorder(Display *d, Window w, + unsigned long ul); +#endif +#ifndef XSetWindowBorderPixmap_TCL_DECLARED +#define XSetWindowBorderPixmap_TCL_DECLARED /* 69 */ -EXTERN void XSetWindowBorderPixmap _ANSI_ARGS_((Display *d, - Window w, Pixmap p)); +EXTERN void XSetWindowBorderPixmap(Display *d, Window w, + Pixmap p); +#endif +#ifndef XSetWindowBorderWidth_TCL_DECLARED +#define XSetWindowBorderWidth_TCL_DECLARED /* 70 */ -EXTERN void XSetWindowBorderWidth _ANSI_ARGS_((Display *d, - Window w, unsigned int ui)); +EXTERN void XSetWindowBorderWidth(Display *d, Window w, + unsigned int ui); +#endif +#ifndef XSetWindowColormap_TCL_DECLARED +#define XSetWindowColormap_TCL_DECLARED /* 71 */ -EXTERN void XSetWindowColormap _ANSI_ARGS_((Display *d, Window w, - Colormap c)); +EXTERN void XSetWindowColormap(Display *d, Window w, Colormap c); +#endif +#ifndef XTranslateCoordinates_TCL_DECLARED +#define XTranslateCoordinates_TCL_DECLARED /* 72 */ -EXTERN Bool XTranslateCoordinates _ANSI_ARGS_((Display *d, - Window w1, Window w2, int i1, int i2, - int *i3, int *i4, Window *w3)); +EXTERN Bool XTranslateCoordinates(Display *d, Window w1, + Window w2, int i1, int i2, int *i3, int *i4, + Window *w3); +#endif +#ifndef XUngrabKeyboard_TCL_DECLARED +#define XUngrabKeyboard_TCL_DECLARED /* 73 */ -EXTERN void XUngrabKeyboard _ANSI_ARGS_((Display *d, Time t)); +EXTERN void XUngrabKeyboard(Display *d, Time t); +#endif +#ifndef XUngrabPointer_TCL_DECLARED +#define XUngrabPointer_TCL_DECLARED /* 74 */ -EXTERN void XUngrabPointer _ANSI_ARGS_((Display *d, Time t)); +EXTERN void XUngrabPointer(Display *d, Time t); +#endif +#ifndef XUnmapWindow_TCL_DECLARED +#define XUnmapWindow_TCL_DECLARED /* 75 */ -EXTERN void XUnmapWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XUnmapWindow(Display *d, Window w); +#endif +#ifndef XWindowEvent_TCL_DECLARED +#define XWindowEvent_TCL_DECLARED /* 76 */ -EXTERN void XWindowEvent _ANSI_ARGS_((Display *d, Window w, - long l, XEvent *x)); +EXTERN void XWindowEvent(Display *d, Window w, long l, XEvent *x); +#endif +#ifndef XDestroyIC_TCL_DECLARED +#define XDestroyIC_TCL_DECLARED /* 77 */ -EXTERN void XDestroyIC _ANSI_ARGS_((XIC x)); +EXTERN void XDestroyIC(XIC x); +#endif +#ifndef XFilterEvent_TCL_DECLARED +#define XFilterEvent_TCL_DECLARED /* 78 */ -EXTERN Bool XFilterEvent _ANSI_ARGS_((XEvent *x, Window w)); +EXTERN Bool XFilterEvent(XEvent *x, Window w); +#endif +#ifndef XmbLookupString_TCL_DECLARED +#define XmbLookupString_TCL_DECLARED /* 79 */ -EXTERN int XmbLookupString _ANSI_ARGS_((XIC xi, - XKeyPressedEvent *xk, char *c, int i, - KeySym *k, Status *s)); +EXTERN int XmbLookupString(XIC xi, XKeyPressedEvent *xk, + char *c, int i, KeySym *k, Status *s); +#endif +#ifndef TkPutImage_TCL_DECLARED +#define TkPutImage_TCL_DECLARED /* 80 */ -EXTERN void TkPutImage _ANSI_ARGS_((unsigned long *colors, - int ncolors, Display *display, Drawable d, - GC gc, XImage *image, int src_x, int src_y, +EXTERN void TkPutImage(unsigned long *colors, int ncolors, + Display *display, Drawable d, GC gc, + XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, - unsigned int height)); + unsigned int height); +#endif /* Slot 81 is reserved */ +#ifndef XParseColor_TCL_DECLARED +#define XParseColor_TCL_DECLARED /* 82 */ -EXTERN Status XParseColor _ANSI_ARGS_((Display *display, - Colormap map, _Xconst char *spec, - XColor *colorPtr)); +EXTERN Status XParseColor(Display *display, Colormap map, + _Xconst char *spec, XColor *colorPtr); +#endif +#ifndef XCreateGC_TCL_DECLARED +#define XCreateGC_TCL_DECLARED /* 83 */ -EXTERN GC XCreateGC _ANSI_ARGS_((Display *display, Drawable d, - unsigned long valuemask, XGCValues *values)); +EXTERN GC XCreateGC(Display *display, Drawable d, + unsigned long valuemask, XGCValues *values); +#endif +#ifndef XFreeGC_TCL_DECLARED +#define XFreeGC_TCL_DECLARED /* 84 */ -EXTERN void XFreeGC _ANSI_ARGS_((Display *display, GC gc)); +EXTERN void XFreeGC(Display *display, GC gc); +#endif +#ifndef XInternAtom_TCL_DECLARED +#define XInternAtom_TCL_DECLARED /* 85 */ -EXTERN Atom XInternAtom _ANSI_ARGS_((Display *display, - _Xconst char *atom_name, Bool only_if_exists)); +EXTERN Atom XInternAtom(Display *display, + _Xconst char *atom_name, Bool only_if_exists); +#endif +#ifndef XSetBackground_TCL_DECLARED +#define XSetBackground_TCL_DECLARED /* 86 */ -EXTERN void XSetBackground _ANSI_ARGS_((Display *display, GC gc, - unsigned long foreground)); +EXTERN void XSetBackground(Display *display, GC gc, + unsigned long foreground); +#endif +#ifndef XSetForeground_TCL_DECLARED +#define XSetForeground_TCL_DECLARED /* 87 */ -EXTERN void XSetForeground _ANSI_ARGS_((Display *display, GC gc, - unsigned long foreground)); +EXTERN void XSetForeground(Display *display, GC gc, + unsigned long foreground); +#endif +#ifndef XSetClipMask_TCL_DECLARED +#define XSetClipMask_TCL_DECLARED /* 88 */ -EXTERN void XSetClipMask _ANSI_ARGS_((Display *display, GC gc, - Pixmap pixmap)); +EXTERN void XSetClipMask(Display *display, GC gc, Pixmap pixmap); +#endif +#ifndef XSetClipOrigin_TCL_DECLARED +#define XSetClipOrigin_TCL_DECLARED /* 89 */ -EXTERN void XSetClipOrigin _ANSI_ARGS_((Display *display, GC gc, - int clip_x_origin, int clip_y_origin)); +EXTERN void XSetClipOrigin(Display *display, GC gc, + int clip_x_origin, int clip_y_origin); +#endif +#ifndef XSetTSOrigin_TCL_DECLARED +#define XSetTSOrigin_TCL_DECLARED /* 90 */ -EXTERN void XSetTSOrigin _ANSI_ARGS_((Display *display, GC gc, - int ts_x_origin, int ts_y_origin)); +EXTERN void XSetTSOrigin(Display *display, GC gc, + int ts_x_origin, int ts_y_origin); +#endif +#ifndef XChangeGC_TCL_DECLARED +#define XChangeGC_TCL_DECLARED /* 91 */ -EXTERN void XChangeGC _ANSI_ARGS_((Display *d, GC gc, - unsigned long mask, XGCValues *values)); +EXTERN void XChangeGC(Display *d, GC gc, unsigned long mask, + XGCValues *values); +#endif +#ifndef XSetFont_TCL_DECLARED +#define XSetFont_TCL_DECLARED /* 92 */ -EXTERN void XSetFont _ANSI_ARGS_((Display *display, GC gc, - Font font)); +EXTERN void XSetFont(Display *display, GC gc, Font font); +#endif +#ifndef XSetArcMode_TCL_DECLARED +#define XSetArcMode_TCL_DECLARED /* 93 */ -EXTERN void XSetArcMode _ANSI_ARGS_((Display *display, GC gc, - int arc_mode)); +EXTERN void XSetArcMode(Display *display, GC gc, int arc_mode); +#endif +#ifndef XSetStipple_TCL_DECLARED +#define XSetStipple_TCL_DECLARED /* 94 */ -EXTERN void XSetStipple _ANSI_ARGS_((Display *display, GC gc, - Pixmap stipple)); +EXTERN void XSetStipple(Display *display, GC gc, Pixmap stipple); +#endif +#ifndef XSetFillRule_TCL_DECLARED +#define XSetFillRule_TCL_DECLARED /* 95 */ -EXTERN void XSetFillRule _ANSI_ARGS_((Display *display, GC gc, - int fill_rule)); +EXTERN void XSetFillRule(Display *display, GC gc, int fill_rule); +#endif +#ifndef XSetFillStyle_TCL_DECLARED +#define XSetFillStyle_TCL_DECLARED /* 96 */ -EXTERN void XSetFillStyle _ANSI_ARGS_((Display *display, GC gc, - int fill_style)); +EXTERN void XSetFillStyle(Display *display, GC gc, + int fill_style); +#endif +#ifndef XSetFunction_TCL_DECLARED +#define XSetFunction_TCL_DECLARED /* 97 */ -EXTERN void XSetFunction _ANSI_ARGS_((Display *display, GC gc, - int function)); +EXTERN void XSetFunction(Display *display, GC gc, int function); +#endif +#ifndef XSetLineAttributes_TCL_DECLARED +#define XSetLineAttributes_TCL_DECLARED /* 98 */ -EXTERN void XSetLineAttributes _ANSI_ARGS_((Display *display, - GC gc, unsigned int line_width, - int line_style, int cap_style, - int join_style)); +EXTERN void XSetLineAttributes(Display *display, GC gc, + unsigned int line_width, int line_style, + int cap_style, int join_style); +#endif +#ifndef _XInitImageFuncPtrs_TCL_DECLARED +#define _XInitImageFuncPtrs_TCL_DECLARED /* 99 */ -EXTERN int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); +EXTERN int _XInitImageFuncPtrs(XImage *image); +#endif +#ifndef XCreateIC_TCL_DECLARED +#define XCreateIC_TCL_DECLARED /* 100 */ -EXTERN XIC XCreateIC _ANSI_ARGS_((void)); +EXTERN XIC XCreateIC(void); +#endif +#ifndef XGetVisualInfo_TCL_DECLARED +#define XGetVisualInfo_TCL_DECLARED /* 101 */ -EXTERN XVisualInfo * XGetVisualInfo _ANSI_ARGS_((Display *display, - long vinfo_mask, XVisualInfo *vinfo_template, - int *nitems_return)); +EXTERN XVisualInfo * XGetVisualInfo(Display *display, long vinfo_mask, + XVisualInfo *vinfo_template, + int *nitems_return); +#endif +#ifndef XSetWMClientMachine_TCL_DECLARED +#define XSetWMClientMachine_TCL_DECLARED /* 102 */ -EXTERN void XSetWMClientMachine _ANSI_ARGS_((Display *display, - Window w, XTextProperty *text_prop)); +EXTERN void XSetWMClientMachine(Display *display, Window w, + XTextProperty *text_prop); +#endif +#ifndef XStringListToTextProperty_TCL_DECLARED +#define XStringListToTextProperty_TCL_DECLARED /* 103 */ -EXTERN Status XStringListToTextProperty _ANSI_ARGS_((char **list, - int count, XTextProperty *text_prop_return)); +EXTERN Status XStringListToTextProperty(char **list, int count, + XTextProperty *text_prop_return); +#endif +#ifndef XDrawLine_TCL_DECLARED +#define XDrawLine_TCL_DECLARED /* 104 */ -EXTERN void XDrawLine _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int x1, int y1, int x2, int y2)); +EXTERN void XDrawLine(Display *d, Drawable dr, GC g, int x1, + int y1, int x2, int y2); +#endif +#ifndef XWarpPointer_TCL_DECLARED +#define XWarpPointer_TCL_DECLARED /* 105 */ -EXTERN void XWarpPointer _ANSI_ARGS_((Display *d, Window s, - Window dw, int sx, int sy, unsigned int sw, - unsigned int sh, int dx, int dy)); +EXTERN void XWarpPointer(Display *d, Window s, Window dw, int sx, + int sy, unsigned int sw, unsigned int sh, + int dx, int dy); +#endif +#ifndef XFillRectangle_TCL_DECLARED +#define XFillRectangle_TCL_DECLARED /* 106 */ -EXTERN void XFillRectangle _ANSI_ARGS_((Display *display, - Drawable d, GC gc, int x, int y, - unsigned int width, unsigned int height)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL +EXTERN void XFillRectangle(Display *display, Drawable d, GC gc, + int x, int y, unsigned int width, + unsigned int height); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef XSetDashes_TCL_DECLARED +#define XSetDashes_TCL_DECLARED /* 0 */ -EXTERN void XSetDashes _ANSI_ARGS_((Display *display, GC gc, - int dash_offset, _Xconst char *dash_list, - int n)); +EXTERN void XSetDashes(Display *display, GC gc, int dash_offset, + _Xconst char *dash_list, int n); +#endif +#ifndef XGetModifierMapping_TCL_DECLARED +#define XGetModifierMapping_TCL_DECLARED /* 1 */ -EXTERN XModifierKeymap * XGetModifierMapping _ANSI_ARGS_((Display *d)); +EXTERN XModifierKeymap * XGetModifierMapping(Display *d); +#endif +#ifndef XCreateImage_TCL_DECLARED +#define XCreateImage_TCL_DECLARED /* 2 */ -EXTERN XImage * XCreateImage _ANSI_ARGS_((Display *d, Visual *v, - unsigned int ui1, int i1, int i2, char *cp, - unsigned int ui2, unsigned int ui3, int i3, - int i4)); +EXTERN XImage * XCreateImage(Display *d, Visual *v, unsigned int ui1, + int i1, int i2, char *cp, unsigned int ui2, + unsigned int ui3, int i3, int i4); +#endif +#ifndef XGetImage_TCL_DECLARED +#define XGetImage_TCL_DECLARED /* 3 */ -EXTERN XImage * XGetImage _ANSI_ARGS_((Display *d, Drawable dr, - int i1, int i2, unsigned int ui1, - unsigned int ui2, unsigned long ul, int i3)); +EXTERN XImage * XGetImage(Display *d, Drawable dr, int i1, int i2, + unsigned int ui1, unsigned int ui2, + unsigned long ul, int i3); +#endif +#ifndef XGetAtomName_TCL_DECLARED +#define XGetAtomName_TCL_DECLARED /* 4 */ -EXTERN char * XGetAtomName _ANSI_ARGS_((Display *d, Atom a)); +EXTERN char * XGetAtomName(Display *d, Atom a); +#endif +#ifndef XKeysymToString_TCL_DECLARED +#define XKeysymToString_TCL_DECLARED /* 5 */ -EXTERN char * XKeysymToString _ANSI_ARGS_((KeySym k)); +EXTERN char * XKeysymToString(KeySym k); +#endif +#ifndef XCreateColormap_TCL_DECLARED +#define XCreateColormap_TCL_DECLARED /* 6 */ -EXTERN Colormap XCreateColormap _ANSI_ARGS_((Display *d, Window w, - Visual *v, int i)); +EXTERN Colormap XCreateColormap(Display *d, Window w, Visual *v, + int i); +#endif +#ifndef XGContextFromGC_TCL_DECLARED +#define XGContextFromGC_TCL_DECLARED /* 7 */ -EXTERN GContext XGContextFromGC _ANSI_ARGS_((GC g)); +EXTERN GContext XGContextFromGC(GC g); +#endif +#ifndef XKeycodeToKeysym_TCL_DECLARED +#define XKeycodeToKeysym_TCL_DECLARED /* 8 */ -EXTERN KeySym XKeycodeToKeysym _ANSI_ARGS_((Display *d, KeyCode k, - int i)); +EXTERN KeySym XKeycodeToKeysym(Display *d, KeyCode k, int i); +#endif +#ifndef XStringToKeysym_TCL_DECLARED +#define XStringToKeysym_TCL_DECLARED /* 9 */ -EXTERN KeySym XStringToKeysym _ANSI_ARGS_((_Xconst char *c)); +EXTERN KeySym XStringToKeysym(_Xconst char *c); +#endif +#ifndef XRootWindow_TCL_DECLARED +#define XRootWindow_TCL_DECLARED /* 10 */ -EXTERN Window XRootWindow _ANSI_ARGS_((Display *d, int i)); +EXTERN Window XRootWindow(Display *d, int i); +#endif +#ifndef XSetErrorHandler_TCL_DECLARED +#define XSetErrorHandler_TCL_DECLARED /* 11 */ -EXTERN XErrorHandler XSetErrorHandler _ANSI_ARGS_((XErrorHandler x)); +EXTERN XErrorHandler XSetErrorHandler(XErrorHandler x); +#endif +#ifndef XAllocColor_TCL_DECLARED +#define XAllocColor_TCL_DECLARED /* 12 */ -EXTERN Status XAllocColor _ANSI_ARGS_((Display *d, Colormap c, - XColor *xp)); +EXTERN Status XAllocColor(Display *d, Colormap c, XColor *xp); +#endif +#ifndef XBell_TCL_DECLARED +#define XBell_TCL_DECLARED /* 13 */ -EXTERN void XBell _ANSI_ARGS_((Display *d, int i)); +EXTERN void XBell(Display *d, int i); +#endif +#ifndef XChangeProperty_TCL_DECLARED +#define XChangeProperty_TCL_DECLARED /* 14 */ -EXTERN void XChangeProperty _ANSI_ARGS_((Display *d, Window w, - Atom a1, Atom a2, int i1, int i2, - _Xconst unsigned char *c, int i3)); +EXTERN void XChangeProperty(Display *d, Window w, Atom a1, + Atom a2, int i1, int i2, + _Xconst unsigned char *c, int i3); +#endif +#ifndef XChangeWindowAttributes_TCL_DECLARED +#define XChangeWindowAttributes_TCL_DECLARED /* 15 */ -EXTERN void XChangeWindowAttributes _ANSI_ARGS_((Display *d, - Window w, unsigned long ul, - XSetWindowAttributes *x)); +EXTERN void XChangeWindowAttributes(Display *d, Window w, + unsigned long ul, XSetWindowAttributes *x); +#endif +#ifndef XConfigureWindow_TCL_DECLARED +#define XConfigureWindow_TCL_DECLARED /* 16 */ -EXTERN void XConfigureWindow _ANSI_ARGS_((Display *d, Window w, - unsigned int i, XWindowChanges *x)); +EXTERN void XConfigureWindow(Display *d, Window w, + unsigned int i, XWindowChanges *x); +#endif +#ifndef XCopyArea_TCL_DECLARED +#define XCopyArea_TCL_DECLARED /* 17 */ -EXTERN void XCopyArea _ANSI_ARGS_((Display *d, Drawable dr1, - Drawable dr2, GC g, int i1, int i2, - unsigned int ui1, unsigned int ui2, int i3, - int i4)); -/* 18 */ -EXTERN void XCopyPlane _ANSI_ARGS_((Display *d, Drawable dr1, - Drawable dr2, GC g, int i1, int i2, - unsigned int ui1, unsigned int ui2, int i3, - int i4, unsigned long ul)); -/* 19 */ -EXTERN Pixmap XCreateBitmapFromData _ANSI_ARGS_((Display *display, - Drawable d, _Xconst char *data, - unsigned int width, unsigned int height)); -/* 20 */ -EXTERN void XDefineCursor _ANSI_ARGS_((Display *d, Window w, - Cursor c)); -/* 21 */ -EXTERN void XDestroyWindow _ANSI_ARGS_((Display *d, Window w)); -/* 22 */ -EXTERN void XDrawArc _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int i1, int i2, unsigned int ui1, - unsigned int ui2, int i3, int i4)); -/* 23 */ -EXTERN void XDrawLines _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XPoint *x, int i1, int i2)); -/* 24 */ -EXTERN void XDrawRectangle _ANSI_ARGS_((Display *d, Drawable dr, +EXTERN void XCopyArea(Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, - unsigned int ui2)); -/* 25 */ -EXTERN void XFillArc _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int i1, int i2, unsigned int ui1, - unsigned int ui2, int i3, int i4)); -/* 26 */ -EXTERN void XFillPolygon _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XPoint *x, int i1, int i2, int i3)); -/* 27 */ -EXTERN void XFillRectangles _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XRectangle *x, int i)); -/* 28 */ -EXTERN void XFreeColormap _ANSI_ARGS_((Display *d, Colormap c)); -/* 29 */ -EXTERN void XFreeColors _ANSI_ARGS_((Display *d, Colormap c, - unsigned long *ulp, int i, unsigned long ul)); -/* 30 */ -EXTERN void XFreeModifiermap _ANSI_ARGS_((XModifierKeymap *x)); -/* 31 */ -EXTERN Status XGetGeometry _ANSI_ARGS_((Display *d, Drawable dr, - Window *w, int *i1, int *i2, - unsigned int *ui1, unsigned int *ui2, - unsigned int *ui3, unsigned int *ui4)); -/* 32 */ -EXTERN int XGetWindowProperty _ANSI_ARGS_((Display *d, Window w, - Atom a1, long l1, long l2, Bool b, Atom a2, - Atom *ap, int *ip, unsigned long *ulp1, - unsigned long *ulp2, unsigned char **cpp)); -/* 33 */ -EXTERN int XGrabKeyboard _ANSI_ARGS_((Display *d, Window w, - Bool b, int i1, int i2, Time t)); -/* 34 */ -EXTERN int XGrabPointer _ANSI_ARGS_((Display *d, Window w1, - Bool b, unsigned int ui, int i1, int i2, - Window w2, Cursor c, Time t)); -/* 35 */ -EXTERN KeyCode XKeysymToKeycode _ANSI_ARGS_((Display *d, KeySym k)); -/* 36 */ -EXTERN void XMapWindow _ANSI_ARGS_((Display *d, Window w)); -/* 37 */ -EXTERN void XMoveResizeWindow _ANSI_ARGS_((Display *d, Window w, - int i1, int i2, unsigned int ui1, - unsigned int ui2)); -/* 38 */ -EXTERN void XMoveWindow _ANSI_ARGS_((Display *d, Window w, - int i1, int i2)); -/* 39 */ -EXTERN Bool XQueryPointer _ANSI_ARGS_((Display *d, Window w1, - Window *w2, Window *w3, int *i1, int *i2, - int *i3, int *i4, unsigned int *ui)); -/* 40 */ -EXTERN void XRaiseWindow _ANSI_ARGS_((Display *d, Window w)); -/* 41 */ -EXTERN void XRefreshKeyboardMapping _ANSI_ARGS_(( - XMappingEvent *x)); -/* 42 */ -EXTERN void XResizeWindow _ANSI_ARGS_((Display *d, Window w, - unsigned int ui1, unsigned int ui2)); -/* 43 */ -EXTERN void XSelectInput _ANSI_ARGS_((Display *d, Window w, - long l)); -/* 44 */ -EXTERN Status XSendEvent _ANSI_ARGS_((Display *d, Window w, Bool b, - long l, XEvent *x)); -/* 45 */ -EXTERN void XSetIconName _ANSI_ARGS_((Display *d, Window w, - _Xconst char *c)); -/* 46 */ -EXTERN void XSetInputFocus _ANSI_ARGS_((Display *d, Window w, - int i, Time t)); -/* 47 */ -EXTERN void XSetSelectionOwner _ANSI_ARGS_((Display *d, Atom a, - Window w, Time t)); -/* 48 */ -EXTERN void XSetWindowBackground _ANSI_ARGS_((Display *d, - Window w, unsigned long ul)); -/* 49 */ -EXTERN void XSetWindowBackgroundPixmap _ANSI_ARGS_((Display *d, - Window w, Pixmap p)); -/* 50 */ -EXTERN void XSetWindowBorder _ANSI_ARGS_((Display *d, Window w, - unsigned long ul)); -/* 51 */ -EXTERN void XSetWindowBorderPixmap _ANSI_ARGS_((Display *d, - Window w, Pixmap p)); -/* 52 */ -EXTERN void XSetWindowBorderWidth _ANSI_ARGS_((Display *d, - Window w, unsigned int ui)); -/* 53 */ -EXTERN void XSetWindowColormap _ANSI_ARGS_((Display *d, Window w, - Colormap c)); -/* 54 */ -EXTERN void XUngrabKeyboard _ANSI_ARGS_((Display *d, Time t)); -/* 55 */ -EXTERN void XUngrabPointer _ANSI_ARGS_((Display *d, Time t)); -/* 56 */ -EXTERN void XUnmapWindow _ANSI_ARGS_((Display *d, Window w)); -/* 57 */ -EXTERN void TkPutImage _ANSI_ARGS_((unsigned long *colors, - int ncolors, Display *display, Drawable d, - GC gc, XImage *image, int src_x, int src_y, - int dest_x, int dest_y, unsigned int width, - unsigned int height)); -/* 58 */ -EXTERN Status XParseColor _ANSI_ARGS_((Display *display, - Colormap map, _Xconst char *spec, - XColor *colorPtr)); -/* 59 */ -EXTERN GC XCreateGC _ANSI_ARGS_((Display *display, Drawable d, - unsigned long valuemask, XGCValues *values)); -/* 60 */ -EXTERN void XFreeGC _ANSI_ARGS_((Display *display, GC gc)); -/* 61 */ -EXTERN Atom XInternAtom _ANSI_ARGS_((Display *display, - _Xconst char *atom_name, Bool only_if_exists)); -/* 62 */ -EXTERN void XSetBackground _ANSI_ARGS_((Display *display, GC gc, - unsigned long foreground)); -/* 63 */ -EXTERN void XSetForeground _ANSI_ARGS_((Display *display, GC gc, - unsigned long foreground)); -/* 64 */ -EXTERN void XSetClipMask _ANSI_ARGS_((Display *display, GC gc, - Pixmap pixmap)); -/* 65 */ -EXTERN void XSetClipOrigin _ANSI_ARGS_((Display *display, GC gc, - int clip_x_origin, int clip_y_origin)); -/* 66 */ -EXTERN void XSetTSOrigin _ANSI_ARGS_((Display *display, GC gc, - int ts_x_origin, int ts_y_origin)); -/* 67 */ -EXTERN void XChangeGC _ANSI_ARGS_((Display *d, GC gc, - unsigned long mask, XGCValues *values)); -/* 68 */ -EXTERN void XSetFont _ANSI_ARGS_((Display *display, GC gc, - Font font)); -/* 69 */ -EXTERN void XSetArcMode _ANSI_ARGS_((Display *display, GC gc, - int arc_mode)); -/* 70 */ -EXTERN void XSetStipple _ANSI_ARGS_((Display *display, GC gc, - Pixmap stipple)); -/* 71 */ -EXTERN void XSetFillRule _ANSI_ARGS_((Display *display, GC gc, - int fill_rule)); -/* 72 */ -EXTERN void XSetFillStyle _ANSI_ARGS_((Display *display, GC gc, - int fill_style)); -/* 73 */ -EXTERN void XSetFunction _ANSI_ARGS_((Display *display, GC gc, - int function)); -/* 74 */ -EXTERN void XSetLineAttributes _ANSI_ARGS_((Display *display, - GC gc, unsigned int line_width, - int line_style, int cap_style, - int join_style)); -/* 75 */ -EXTERN int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); -/* 76 */ -EXTERN XIC XCreateIC _ANSI_ARGS_((void)); -/* 77 */ -EXTERN XVisualInfo * XGetVisualInfo _ANSI_ARGS_((Display *display, - long vinfo_mask, XVisualInfo *vinfo_template, - int *nitems_return)); -/* 78 */ -EXTERN void XSetWMClientMachine _ANSI_ARGS_((Display *display, - Window w, XTextProperty *text_prop)); -/* 79 */ -EXTERN Status XStringListToTextProperty _ANSI_ARGS_((char **list, - int count, XTextProperty *text_prop_return)); -/* 80 */ -EXTERN void XDrawSegments _ANSI_ARGS_((Display *display, - Drawable d, GC gc, XSegment *segments, - int nsegments)); -/* 81 */ -EXTERN void XForceScreenSaver _ANSI_ARGS_((Display *display, - int mode)); -/* 82 */ -EXTERN void XDrawLine _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int x1, int y1, int x2, int y2)); -/* 83 */ -EXTERN void XFillRectangle _ANSI_ARGS_((Display *display, - Drawable d, GC gc, int x, int y, - unsigned int width, unsigned int height)); -/* 84 */ -EXTERN void XClearWindow _ANSI_ARGS_((Display *d, Window w)); -/* 85 */ -EXTERN void XDrawPoint _ANSI_ARGS_((Display *display, Drawable d, - GC gc, int x, int y)); -/* 86 */ -EXTERN void XDrawPoints _ANSI_ARGS_((Display *display, - Drawable d, GC gc, XPoint *points, - int npoints, int mode)); -/* 87 */ -EXTERN void XWarpPointer _ANSI_ARGS_((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)); -/* 88 */ -EXTERN void XQueryColor _ANSI_ARGS_((Display *display, - Colormap colormap, XColor *def_in_out)); -/* 89 */ -EXTERN void XQueryColors _ANSI_ARGS_((Display *display, - Colormap colormap, XColor *defs_in_out, - int ncolors)); -/* 90 */ -EXTERN Status XQueryTree _ANSI_ARGS_((Display *d, Window w1, - Window *w2, Window *w3, Window **w4, - unsigned int *ui)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK -/* 0 */ -EXTERN void XSetDashes _ANSI_ARGS_((Display *display, GC gc, - int dash_offset, _Xconst char *dash_list, - int n)); -/* 1 */ -EXTERN XModifierKeymap * XGetModifierMapping _ANSI_ARGS_((Display *d)); -/* 2 */ -EXTERN XImage * XCreateImage _ANSI_ARGS_((Display *d, Visual *v, - unsigned int ui1, int i1, int i2, char *cp, - unsigned int ui2, unsigned int ui3, int i3, - int i4)); -/* 3 */ -EXTERN XImage * XGetImage _ANSI_ARGS_((Display *d, Drawable dr, - int i1, int i2, unsigned int ui1, - unsigned int ui2, unsigned long ul, int i3)); -/* 4 */ -EXTERN char * XGetAtomName _ANSI_ARGS_((Display *d, Atom a)); -/* 5 */ -EXTERN char * XKeysymToString _ANSI_ARGS_((KeySym k)); -/* 6 */ -EXTERN Colormap XCreateColormap _ANSI_ARGS_((Display *d, Window w, - Visual *v, int i)); -/* 7 */ -EXTERN GContext XGContextFromGC _ANSI_ARGS_((GC g)); -/* 8 */ -EXTERN KeySym XKeycodeToKeysym _ANSI_ARGS_((Display *d, KeyCode k, - int i)); -/* 9 */ -EXTERN KeySym XStringToKeysym _ANSI_ARGS_((_Xconst char *c)); -/* 10 */ -EXTERN Window XRootWindow _ANSI_ARGS_((Display *d, int i)); -/* 11 */ -EXTERN XErrorHandler XSetErrorHandler _ANSI_ARGS_((XErrorHandler x)); -/* 12 */ -EXTERN Status XAllocColor _ANSI_ARGS_((Display *d, Colormap c, - XColor *xp)); -/* 13 */ -EXTERN void XBell _ANSI_ARGS_((Display *d, int i)); -/* 14 */ -EXTERN void XChangeProperty _ANSI_ARGS_((Display *d, Window w, - Atom a1, Atom a2, int i1, int i2, - _Xconst unsigned char *c, int i3)); -/* 15 */ -EXTERN void XChangeWindowAttributes _ANSI_ARGS_((Display *d, - Window w, unsigned long ul, - XSetWindowAttributes *x)); -/* 16 */ -EXTERN void XConfigureWindow _ANSI_ARGS_((Display *d, Window w, - unsigned int i, XWindowChanges *x)); -/* 17 */ -EXTERN void XCopyArea _ANSI_ARGS_((Display *d, Drawable dr1, - Drawable dr2, GC g, int i1, int i2, - unsigned int ui1, unsigned int ui2, int i3, - int i4)); + unsigned int ui2, int i3, int i4); +#endif +#ifndef XCopyPlane_TCL_DECLARED +#define XCopyPlane_TCL_DECLARED /* 18 */ -EXTERN void XCopyPlane _ANSI_ARGS_((Display *d, Drawable dr1, - Drawable dr2, GC g, int i1, int i2, - unsigned int ui1, unsigned int ui2, int i3, - int i4, unsigned long ul)); +EXTERN void XCopyPlane(Display *d, Drawable dr1, Drawable dr2, + GC g, int i1, int i2, unsigned int ui1, + unsigned int ui2, int i3, int i4, + unsigned long ul); +#endif +#ifndef XCreateBitmapFromData_TCL_DECLARED +#define XCreateBitmapFromData_TCL_DECLARED /* 19 */ -EXTERN Pixmap XCreateBitmapFromData _ANSI_ARGS_((Display *display, - Drawable d, _Xconst char *data, - unsigned int width, unsigned int height)); +EXTERN Pixmap XCreateBitmapFromData(Display *display, Drawable d, + _Xconst char *data, unsigned int width, + unsigned int height); +#endif +#ifndef XDefineCursor_TCL_DECLARED +#define XDefineCursor_TCL_DECLARED /* 20 */ -EXTERN void XDefineCursor _ANSI_ARGS_((Display *d, Window w, - Cursor c)); +EXTERN void XDefineCursor(Display *d, Window w, Cursor c); +#endif +#ifndef XDestroyWindow_TCL_DECLARED +#define XDestroyWindow_TCL_DECLARED /* 21 */ -EXTERN void XDestroyWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XDestroyWindow(Display *d, Window w); +#endif +#ifndef XDrawArc_TCL_DECLARED +#define XDrawArc_TCL_DECLARED /* 22 */ -EXTERN void XDrawArc _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int i1, int i2, unsigned int ui1, - unsigned int ui2, int i3, int i4)); +EXTERN void XDrawArc(Display *d, Drawable dr, GC g, int i1, + int i2, unsigned int ui1, unsigned int ui2, + int i3, int i4); +#endif +#ifndef XDrawLines_TCL_DECLARED +#define XDrawLines_TCL_DECLARED /* 23 */ -EXTERN void XDrawLines _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XPoint *x, int i1, int i2)); +EXTERN void XDrawLines(Display *d, Drawable dr, GC g, XPoint *x, + int i1, int i2); +#endif +#ifndef XDrawRectangle_TCL_DECLARED +#define XDrawRectangle_TCL_DECLARED /* 24 */ -EXTERN void XDrawRectangle _ANSI_ARGS_((Display *d, Drawable dr, - GC g, int i1, int i2, unsigned int ui1, - unsigned int ui2)); +EXTERN void XDrawRectangle(Display *d, Drawable dr, GC g, int i1, + int i2, unsigned int ui1, unsigned int ui2); +#endif +#ifndef XFillArc_TCL_DECLARED +#define XFillArc_TCL_DECLARED /* 25 */ -EXTERN void XFillArc _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int i1, int i2, unsigned int ui1, - unsigned int ui2, int i3, int i4)); +EXTERN void XFillArc(Display *d, Drawable dr, GC g, int i1, + int i2, unsigned int ui1, unsigned int ui2, + int i3, int i4); +#endif +#ifndef XFillPolygon_TCL_DECLARED +#define XFillPolygon_TCL_DECLARED /* 26 */ -EXTERN void XFillPolygon _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XPoint *x, int i1, int i2, int i3)); +EXTERN void XFillPolygon(Display *d, Drawable dr, GC g, + XPoint *x, int i1, int i2, int i3); +#endif +#ifndef XFillRectangles_TCL_DECLARED +#define XFillRectangles_TCL_DECLARED /* 27 */ -EXTERN void XFillRectangles _ANSI_ARGS_((Display *d, Drawable dr, - GC g, XRectangle *x, int i)); +EXTERN void XFillRectangles(Display *d, Drawable dr, GC g, + XRectangle *x, int i); +#endif +#ifndef XFreeColormap_TCL_DECLARED +#define XFreeColormap_TCL_DECLARED /* 28 */ -EXTERN void XFreeColormap _ANSI_ARGS_((Display *d, Colormap c)); +EXTERN void XFreeColormap(Display *d, Colormap c); +#endif +#ifndef XFreeColors_TCL_DECLARED +#define XFreeColors_TCL_DECLARED /* 29 */ -EXTERN void XFreeColors _ANSI_ARGS_((Display *d, Colormap c, - unsigned long *ulp, int i, unsigned long ul)); +EXTERN void XFreeColors(Display *d, Colormap c, + unsigned long *ulp, int i, unsigned long ul); +#endif +#ifndef XFreeModifiermap_TCL_DECLARED +#define XFreeModifiermap_TCL_DECLARED /* 30 */ -EXTERN void XFreeModifiermap _ANSI_ARGS_((XModifierKeymap *x)); +EXTERN void XFreeModifiermap(XModifierKeymap *x); +#endif +#ifndef XGetGeometry_TCL_DECLARED +#define XGetGeometry_TCL_DECLARED /* 31 */ -EXTERN Status XGetGeometry _ANSI_ARGS_((Display *d, Drawable dr, - Window *w, int *i1, int *i2, - unsigned int *ui1, unsigned int *ui2, - unsigned int *ui3, unsigned int *ui4)); +EXTERN Status XGetGeometry(Display *d, Drawable dr, Window *w, + int *i1, int *i2, unsigned int *ui1, + unsigned int *ui2, unsigned int *ui3, + unsigned int *ui4); +#endif +#ifndef XGetWindowProperty_TCL_DECLARED +#define XGetWindowProperty_TCL_DECLARED /* 32 */ -EXTERN int XGetWindowProperty _ANSI_ARGS_((Display *d, Window w, - Atom a1, long l1, long l2, Bool b, Atom a2, - Atom *ap, int *ip, unsigned long *ulp1, - unsigned long *ulp2, unsigned char **cpp)); +EXTERN int XGetWindowProperty(Display *d, Window w, Atom a1, + long l1, long l2, Bool b, Atom a2, Atom *ap, + int *ip, unsigned long *ulp1, + unsigned long *ulp2, unsigned char **cpp); +#endif +#ifndef XGrabKeyboard_TCL_DECLARED +#define XGrabKeyboard_TCL_DECLARED /* 33 */ -EXTERN int XGrabKeyboard _ANSI_ARGS_((Display *d, Window w, - Bool b, int i1, int i2, Time t)); +EXTERN int XGrabKeyboard(Display *d, Window w, Bool b, int i1, + int i2, Time t); +#endif +#ifndef XGrabPointer_TCL_DECLARED +#define XGrabPointer_TCL_DECLARED /* 34 */ -EXTERN int XGrabPointer _ANSI_ARGS_((Display *d, Window w1, - Bool b, unsigned int ui, int i1, int i2, - Window w2, Cursor c, Time t)); +EXTERN int XGrabPointer(Display *d, Window w1, Bool b, + unsigned int ui, int i1, int i2, Window w2, + Cursor c, Time t); +#endif +#ifndef XKeysymToKeycode_TCL_DECLARED +#define XKeysymToKeycode_TCL_DECLARED /* 35 */ -EXTERN KeyCode XKeysymToKeycode _ANSI_ARGS_((Display *d, KeySym k)); +EXTERN KeyCode XKeysymToKeycode(Display *d, KeySym k); +#endif +#ifndef XMapWindow_TCL_DECLARED +#define XMapWindow_TCL_DECLARED /* 36 */ -EXTERN void XMapWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XMapWindow(Display *d, Window w); +#endif +#ifndef XMoveResizeWindow_TCL_DECLARED +#define XMoveResizeWindow_TCL_DECLARED /* 37 */ -EXTERN void XMoveResizeWindow _ANSI_ARGS_((Display *d, Window w, - int i1, int i2, unsigned int ui1, - unsigned int ui2)); +EXTERN void XMoveResizeWindow(Display *d, Window w, int i1, + int i2, unsigned int ui1, unsigned int ui2); +#endif +#ifndef XMoveWindow_TCL_DECLARED +#define XMoveWindow_TCL_DECLARED /* 38 */ -EXTERN void XMoveWindow _ANSI_ARGS_((Display *d, Window w, - int i1, int i2)); +EXTERN void XMoveWindow(Display *d, Window w, int i1, int i2); +#endif +#ifndef XQueryPointer_TCL_DECLARED +#define XQueryPointer_TCL_DECLARED /* 39 */ -EXTERN Bool XQueryPointer _ANSI_ARGS_((Display *d, Window w1, - Window *w2, Window *w3, int *i1, int *i2, - int *i3, int *i4, unsigned int *ui)); +EXTERN Bool XQueryPointer(Display *d, Window w1, Window *w2, + Window *w3, int *i1, int *i2, int *i3, + int *i4, unsigned int *ui); +#endif +#ifndef XRaiseWindow_TCL_DECLARED +#define XRaiseWindow_TCL_DECLARED /* 40 */ -EXTERN void XRaiseWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XRaiseWindow(Display *d, Window w); +#endif +#ifndef XRefreshKeyboardMapping_TCL_DECLARED +#define XRefreshKeyboardMapping_TCL_DECLARED /* 41 */ -EXTERN void XRefreshKeyboardMapping _ANSI_ARGS_(( - XMappingEvent *x)); +EXTERN void XRefreshKeyboardMapping(XMappingEvent *x); +#endif +#ifndef XResizeWindow_TCL_DECLARED +#define XResizeWindow_TCL_DECLARED /* 42 */ -EXTERN void XResizeWindow _ANSI_ARGS_((Display *d, Window w, - unsigned int ui1, unsigned int ui2)); +EXTERN void XResizeWindow(Display *d, Window w, unsigned int ui1, + unsigned int ui2); +#endif +#ifndef XSelectInput_TCL_DECLARED +#define XSelectInput_TCL_DECLARED /* 43 */ -EXTERN void XSelectInput _ANSI_ARGS_((Display *d, Window w, - long l)); +EXTERN void XSelectInput(Display *d, Window w, long l); +#endif +#ifndef XSendEvent_TCL_DECLARED +#define XSendEvent_TCL_DECLARED /* 44 */ -EXTERN Status XSendEvent _ANSI_ARGS_((Display *d, Window w, Bool b, - long l, XEvent *x)); +EXTERN Status XSendEvent(Display *d, Window w, Bool b, long l, + XEvent *x); +#endif +#ifndef XSetIconName_TCL_DECLARED +#define XSetIconName_TCL_DECLARED /* 45 */ -EXTERN void XSetIconName _ANSI_ARGS_((Display *d, Window w, - _Xconst char *c)); +EXTERN void XSetIconName(Display *d, Window w, _Xconst char *c); +#endif +#ifndef XSetInputFocus_TCL_DECLARED +#define XSetInputFocus_TCL_DECLARED /* 46 */ -EXTERN void XSetInputFocus _ANSI_ARGS_((Display *d, Window w, - int i, Time t)); +EXTERN void XSetInputFocus(Display *d, Window w, int i, Time t); +#endif +#ifndef XSetSelectionOwner_TCL_DECLARED +#define XSetSelectionOwner_TCL_DECLARED /* 47 */ -EXTERN void XSetSelectionOwner _ANSI_ARGS_((Display *d, Atom a, - Window w, Time t)); +EXTERN void XSetSelectionOwner(Display *d, Atom a, Window w, + Time t); +#endif +#ifndef XSetWindowBackground_TCL_DECLARED +#define XSetWindowBackground_TCL_DECLARED /* 48 */ -EXTERN void XSetWindowBackground _ANSI_ARGS_((Display *d, - Window w, unsigned long ul)); +EXTERN void XSetWindowBackground(Display *d, Window w, + unsigned long ul); +#endif +#ifndef XSetWindowBackgroundPixmap_TCL_DECLARED +#define XSetWindowBackgroundPixmap_TCL_DECLARED /* 49 */ -EXTERN void XSetWindowBackgroundPixmap _ANSI_ARGS_((Display *d, - Window w, Pixmap p)); +EXTERN void XSetWindowBackgroundPixmap(Display *d, Window w, + Pixmap p); +#endif +#ifndef XSetWindowBorder_TCL_DECLARED +#define XSetWindowBorder_TCL_DECLARED /* 50 */ -EXTERN void XSetWindowBorder _ANSI_ARGS_((Display *d, Window w, - unsigned long ul)); +EXTERN void XSetWindowBorder(Display *d, Window w, + unsigned long ul); +#endif +#ifndef XSetWindowBorderPixmap_TCL_DECLARED +#define XSetWindowBorderPixmap_TCL_DECLARED /* 51 */ -EXTERN void XSetWindowBorderPixmap _ANSI_ARGS_((Display *d, - Window w, Pixmap p)); +EXTERN void XSetWindowBorderPixmap(Display *d, Window w, + Pixmap p); +#endif +#ifndef XSetWindowBorderWidth_TCL_DECLARED +#define XSetWindowBorderWidth_TCL_DECLARED /* 52 */ -EXTERN void XSetWindowBorderWidth _ANSI_ARGS_((Display *d, - Window w, unsigned int ui)); +EXTERN void XSetWindowBorderWidth(Display *d, Window w, + unsigned int ui); +#endif +#ifndef XSetWindowColormap_TCL_DECLARED +#define XSetWindowColormap_TCL_DECLARED /* 53 */ -EXTERN void XSetWindowColormap _ANSI_ARGS_((Display *d, Window w, - Colormap c)); +EXTERN void XSetWindowColormap(Display *d, Window w, Colormap c); +#endif +#ifndef XUngrabKeyboard_TCL_DECLARED +#define XUngrabKeyboard_TCL_DECLARED /* 54 */ -EXTERN void XUngrabKeyboard _ANSI_ARGS_((Display *d, Time t)); +EXTERN void XUngrabKeyboard(Display *d, Time t); +#endif +#ifndef XUngrabPointer_TCL_DECLARED +#define XUngrabPointer_TCL_DECLARED /* 55 */ -EXTERN void XUngrabPointer _ANSI_ARGS_((Display *d, Time t)); +EXTERN void XUngrabPointer(Display *d, Time t); +#endif +#ifndef XUnmapWindow_TCL_DECLARED +#define XUnmapWindow_TCL_DECLARED /* 56 */ -EXTERN void XUnmapWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XUnmapWindow(Display *d, Window w); +#endif +#ifndef TkPutImage_TCL_DECLARED +#define TkPutImage_TCL_DECLARED /* 57 */ -EXTERN void TkPutImage _ANSI_ARGS_((unsigned long *colors, - int ncolors, Display *display, Drawable d, - GC gc, XImage *image, int src_x, int src_y, +EXTERN void TkPutImage(unsigned long *colors, int ncolors, + Display *display, Drawable d, GC gc, + XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, - unsigned int height)); + unsigned int height); +#endif +#ifndef XParseColor_TCL_DECLARED +#define XParseColor_TCL_DECLARED /* 58 */ -EXTERN Status XParseColor _ANSI_ARGS_((Display *display, - Colormap map, _Xconst char *spec, - XColor *colorPtr)); +EXTERN Status XParseColor(Display *display, Colormap map, + _Xconst char *spec, XColor *colorPtr); +#endif +#ifndef XCreateGC_TCL_DECLARED +#define XCreateGC_TCL_DECLARED /* 59 */ -EXTERN GC XCreateGC _ANSI_ARGS_((Display *display, Drawable d, - unsigned long valuemask, XGCValues *values)); +EXTERN GC XCreateGC(Display *display, Drawable d, + unsigned long valuemask, XGCValues *values); +#endif +#ifndef XFreeGC_TCL_DECLARED +#define XFreeGC_TCL_DECLARED /* 60 */ -EXTERN void XFreeGC _ANSI_ARGS_((Display *display, GC gc)); +EXTERN void XFreeGC(Display *display, GC gc); +#endif +#ifndef XInternAtom_TCL_DECLARED +#define XInternAtom_TCL_DECLARED /* 61 */ -EXTERN Atom XInternAtom _ANSI_ARGS_((Display *display, - _Xconst char *atom_name, Bool only_if_exists)); +EXTERN Atom XInternAtom(Display *display, + _Xconst char *atom_name, Bool only_if_exists); +#endif +#ifndef XSetBackground_TCL_DECLARED +#define XSetBackground_TCL_DECLARED /* 62 */ -EXTERN void XSetBackground _ANSI_ARGS_((Display *display, GC gc, - unsigned long foreground)); +EXTERN void XSetBackground(Display *display, GC gc, + unsigned long foreground); +#endif +#ifndef XSetForeground_TCL_DECLARED +#define XSetForeground_TCL_DECLARED /* 63 */ -EXTERN void XSetForeground _ANSI_ARGS_((Display *display, GC gc, - unsigned long foreground)); +EXTERN void XSetForeground(Display *display, GC gc, + unsigned long foreground); +#endif +#ifndef XSetClipMask_TCL_DECLARED +#define XSetClipMask_TCL_DECLARED /* 64 */ -EXTERN void XSetClipMask _ANSI_ARGS_((Display *display, GC gc, - Pixmap pixmap)); +EXTERN void XSetClipMask(Display *display, GC gc, Pixmap pixmap); +#endif +#ifndef XSetClipOrigin_TCL_DECLARED +#define XSetClipOrigin_TCL_DECLARED /* 65 */ -EXTERN void XSetClipOrigin _ANSI_ARGS_((Display *display, GC gc, - int clip_x_origin, int clip_y_origin)); +EXTERN void XSetClipOrigin(Display *display, GC gc, + int clip_x_origin, int clip_y_origin); +#endif +#ifndef XSetTSOrigin_TCL_DECLARED +#define XSetTSOrigin_TCL_DECLARED /* 66 */ -EXTERN void XSetTSOrigin _ANSI_ARGS_((Display *display, GC gc, - int ts_x_origin, int ts_y_origin)); +EXTERN void XSetTSOrigin(Display *display, GC gc, + int ts_x_origin, int ts_y_origin); +#endif +#ifndef XChangeGC_TCL_DECLARED +#define XChangeGC_TCL_DECLARED /* 67 */ -EXTERN void XChangeGC _ANSI_ARGS_((Display *d, GC gc, - unsigned long mask, XGCValues *values)); +EXTERN void XChangeGC(Display *d, GC gc, unsigned long mask, + XGCValues *values); +#endif +#ifndef XSetFont_TCL_DECLARED +#define XSetFont_TCL_DECLARED /* 68 */ -EXTERN void XSetFont _ANSI_ARGS_((Display *display, GC gc, - Font font)); +EXTERN void XSetFont(Display *display, GC gc, Font font); +#endif +#ifndef XSetArcMode_TCL_DECLARED +#define XSetArcMode_TCL_DECLARED /* 69 */ -EXTERN void XSetArcMode _ANSI_ARGS_((Display *display, GC gc, - int arc_mode)); +EXTERN void XSetArcMode(Display *display, GC gc, int arc_mode); +#endif +#ifndef XSetStipple_TCL_DECLARED +#define XSetStipple_TCL_DECLARED /* 70 */ -EXTERN void XSetStipple _ANSI_ARGS_((Display *display, GC gc, - Pixmap stipple)); +EXTERN void XSetStipple(Display *display, GC gc, Pixmap stipple); +#endif +#ifndef XSetFillRule_TCL_DECLARED +#define XSetFillRule_TCL_DECLARED /* 71 */ -EXTERN void XSetFillRule _ANSI_ARGS_((Display *display, GC gc, - int fill_rule)); +EXTERN void XSetFillRule(Display *display, GC gc, int fill_rule); +#endif +#ifndef XSetFillStyle_TCL_DECLARED +#define XSetFillStyle_TCL_DECLARED /* 72 */ -EXTERN void XSetFillStyle _ANSI_ARGS_((Display *display, GC gc, - int fill_style)); +EXTERN void XSetFillStyle(Display *display, GC gc, + int fill_style); +#endif +#ifndef XSetFunction_TCL_DECLARED +#define XSetFunction_TCL_DECLARED /* 73 */ -EXTERN void XSetFunction _ANSI_ARGS_((Display *display, GC gc, - int function)); +EXTERN void XSetFunction(Display *display, GC gc, int function); +#endif +#ifndef XSetLineAttributes_TCL_DECLARED +#define XSetLineAttributes_TCL_DECLARED /* 74 */ -EXTERN void XSetLineAttributes _ANSI_ARGS_((Display *display, - GC gc, unsigned int line_width, - int line_style, int cap_style, - int join_style)); +EXTERN void XSetLineAttributes(Display *display, GC gc, + unsigned int line_width, int line_style, + int cap_style, int join_style); +#endif +#ifndef _XInitImageFuncPtrs_TCL_DECLARED +#define _XInitImageFuncPtrs_TCL_DECLARED /* 75 */ -EXTERN int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); +EXTERN int _XInitImageFuncPtrs(XImage *image); +#endif +#ifndef XCreateIC_TCL_DECLARED +#define XCreateIC_TCL_DECLARED /* 76 */ -EXTERN XIC XCreateIC _ANSI_ARGS_((void)); +EXTERN XIC XCreateIC(void); +#endif +#ifndef XGetVisualInfo_TCL_DECLARED +#define XGetVisualInfo_TCL_DECLARED /* 77 */ -EXTERN XVisualInfo * XGetVisualInfo _ANSI_ARGS_((Display *display, - long vinfo_mask, XVisualInfo *vinfo_template, - int *nitems_return)); +EXTERN XVisualInfo * XGetVisualInfo(Display *display, long vinfo_mask, + XVisualInfo *vinfo_template, + int *nitems_return); +#endif +#ifndef XSetWMClientMachine_TCL_DECLARED +#define XSetWMClientMachine_TCL_DECLARED /* 78 */ -EXTERN void XSetWMClientMachine _ANSI_ARGS_((Display *display, - Window w, XTextProperty *text_prop)); +EXTERN void XSetWMClientMachine(Display *display, Window w, + XTextProperty *text_prop); +#endif +#ifndef XStringListToTextProperty_TCL_DECLARED +#define XStringListToTextProperty_TCL_DECLARED /* 79 */ -EXTERN Status XStringListToTextProperty _ANSI_ARGS_((char **list, - int count, XTextProperty *text_prop_return)); +EXTERN Status XStringListToTextProperty(char **list, int count, + XTextProperty *text_prop_return); +#endif +#ifndef XDrawSegments_TCL_DECLARED +#define XDrawSegments_TCL_DECLARED /* 80 */ -EXTERN void XDrawSegments _ANSI_ARGS_((Display *display, - Drawable d, GC gc, XSegment *segments, - int nsegments)); +EXTERN void XDrawSegments(Display *display, Drawable d, GC gc, + XSegment *segments, int nsegments); +#endif +#ifndef XForceScreenSaver_TCL_DECLARED +#define XForceScreenSaver_TCL_DECLARED /* 81 */ -EXTERN void XForceScreenSaver _ANSI_ARGS_((Display *display, - int mode)); +EXTERN void XForceScreenSaver(Display *display, int mode); +#endif +#ifndef XDrawLine_TCL_DECLARED +#define XDrawLine_TCL_DECLARED /* 82 */ -EXTERN void XDrawLine _ANSI_ARGS_((Display *d, Drawable dr, GC g, - int x1, int y1, int x2, int y2)); +EXTERN void XDrawLine(Display *d, Drawable dr, GC g, int x1, + int y1, int x2, int y2); +#endif +#ifndef XFillRectangle_TCL_DECLARED +#define XFillRectangle_TCL_DECLARED /* 83 */ -EXTERN void XFillRectangle _ANSI_ARGS_((Display *display, - Drawable d, GC gc, int x, int y, - unsigned int width, unsigned int height)); +EXTERN void XFillRectangle(Display *display, Drawable d, GC gc, + int x, int y, unsigned int width, + unsigned int height); +#endif +#ifndef XClearWindow_TCL_DECLARED +#define XClearWindow_TCL_DECLARED /* 84 */ -EXTERN void XClearWindow _ANSI_ARGS_((Display *d, Window w)); +EXTERN void XClearWindow(Display *d, Window w); +#endif +#ifndef XDrawPoint_TCL_DECLARED +#define XDrawPoint_TCL_DECLARED /* 85 */ -EXTERN void XDrawPoint _ANSI_ARGS_((Display *display, Drawable d, - GC gc, int x, int y)); +EXTERN void XDrawPoint(Display *display, Drawable d, GC gc, + int x, int y); +#endif +#ifndef XDrawPoints_TCL_DECLARED +#define XDrawPoints_TCL_DECLARED /* 86 */ -EXTERN void XDrawPoints _ANSI_ARGS_((Display *display, - Drawable d, GC gc, XPoint *points, - int npoints, int mode)); +EXTERN void XDrawPoints(Display *display, Drawable d, GC gc, + XPoint *points, int npoints, int mode); +#endif +#ifndef XWarpPointer_TCL_DECLARED +#define XWarpPointer_TCL_DECLARED /* 87 */ -EXTERN void XWarpPointer _ANSI_ARGS_((Display *display, - Window src_w, Window dest_w, int src_x, - int src_y, unsigned int src_width, +EXTERN void 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)); + int dest_y); +#endif +#ifndef XQueryColor_TCL_DECLARED +#define XQueryColor_TCL_DECLARED /* 88 */ -EXTERN void XQueryColor _ANSI_ARGS_((Display *display, - Colormap colormap, XColor *def_in_out)); +EXTERN void XQueryColor(Display *display, Colormap colormap, + XColor *def_in_out); +#endif +#ifndef XQueryColors_TCL_DECLARED +#define XQueryColors_TCL_DECLARED /* 89 */ -EXTERN void XQueryColors _ANSI_ARGS_((Display *display, - Colormap colormap, XColor *defs_in_out, - int ncolors)); +EXTERN void XQueryColors(Display *display, Colormap colormap, + XColor *defs_in_out, int ncolors); +#endif +#ifndef XQueryTree_TCL_DECLARED +#define XQueryTree_TCL_DECLARED /* 90 */ -EXTERN Status XQueryTree _ANSI_ARGS_((Display *d, Window w1, - Window *w2, Window *w3, Window **w4, - unsigned int *ui)); +EXTERN Status XQueryTree(Display *d, Window w1, Window *w2, + Window *w3, Window **w4, unsigned int *ui); +#endif +#ifndef XSync_TCL_DECLARED +#define XSync_TCL_DECLARED /* 91 */ -EXTERN int XSync _ANSI_ARGS_((Display *display, Bool flag)); -#endif /* MAC_OSX_TK */ +EXTERN int XSync(Display *display, Bool flag); +#endif +#endif /* AQUA */ typedef struct TkIntXlibStubs { int magic; struct TkIntXlibStubHooks *hooks; -#ifdef __WIN32__ - void (*xSetDashes) _ANSI_ARGS_((Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n)); /* 0 */ - XModifierKeymap * (*xGetModifierMapping) _ANSI_ARGS_((Display *d)); /* 1 */ - XImage * (*xCreateImage) _ANSI_ARGS_((Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4)); /* 2 */ - XImage * (*xGetImage) _ANSI_ARGS_((Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)); /* 3 */ - char * (*xGetAtomName) _ANSI_ARGS_((Display *d, Atom a)); /* 4 */ - char * (*xKeysymToString) _ANSI_ARGS_((KeySym k)); /* 5 */ - Colormap (*xCreateColormap) _ANSI_ARGS_((Display *d, Window w, Visual *v, int i)); /* 6 */ - Cursor (*xCreatePixmapCursor) _ANSI_ARGS_((Display *d, Pixmap p1, Pixmap p2, XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2)); /* 7 */ - Cursor (*xCreateGlyphCursor) _ANSI_ARGS_((Display *d, Font f1, Font f2, unsigned int ui1, unsigned int ui2, XColor *x1, XColor *x2)); /* 8 */ - GContext (*xGContextFromGC) _ANSI_ARGS_((GC g)); /* 9 */ - XHostAddress * (*xListHosts) _ANSI_ARGS_((Display *d, int *i, Bool *b)); /* 10 */ - KeySym (*xKeycodeToKeysym) _ANSI_ARGS_((Display *d, unsigned int k, int i)); /* 11 */ - KeySym (*xStringToKeysym) _ANSI_ARGS_((_Xconst char *c)); /* 12 */ - Window (*xRootWindow) _ANSI_ARGS_((Display *d, int i)); /* 13 */ - XErrorHandler (*xSetErrorHandler) _ANSI_ARGS_((XErrorHandler x)); /* 14 */ - Status (*xIconifyWindow) _ANSI_ARGS_((Display *d, Window w, int i)); /* 15 */ - Status (*xWithdrawWindow) _ANSI_ARGS_((Display *d, Window w, int i)); /* 16 */ - Status (*xGetWMColormapWindows) _ANSI_ARGS_((Display *d, Window w, Window **wpp, int *ip)); /* 17 */ - Status (*xAllocColor) _ANSI_ARGS_((Display *d, Colormap c, XColor *xp)); /* 18 */ - void (*xBell) _ANSI_ARGS_((Display *d, int i)); /* 19 */ - void (*xChangeProperty) _ANSI_ARGS_((Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3)); /* 20 */ - void (*xChangeWindowAttributes) _ANSI_ARGS_((Display *d, Window w, unsigned long ul, XSetWindowAttributes *x)); /* 21 */ - void (*xClearWindow) _ANSI_ARGS_((Display *d, Window w)); /* 22 */ - void (*xConfigureWindow) _ANSI_ARGS_((Display *d, Window w, unsigned int i, XWindowChanges *x)); /* 23 */ - void (*xCopyArea) _ANSI_ARGS_((Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 24 */ - void (*xCopyPlane) _ANSI_ARGS_((Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul)); /* 25 */ - Pixmap (*xCreateBitmapFromData) _ANSI_ARGS_((Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height)); /* 26 */ - void (*xDefineCursor) _ANSI_ARGS_((Display *d, Window w, Cursor c)); /* 27 */ - void (*xDeleteProperty) _ANSI_ARGS_((Display *d, Window w, Atom a)); /* 28 */ - void (*xDestroyWindow) _ANSI_ARGS_((Display *d, Window w)); /* 29 */ - void (*xDrawArc) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 30 */ - void (*xDrawLines) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)); /* 31 */ - void (*xDrawRectangle) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 32 */ - void (*xFillArc) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 33 */ - void (*xFillPolygon) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3)); /* 34 */ - void (*xFillRectangles) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XRectangle *x, int i)); /* 35 */ - void (*xForceScreenSaver) _ANSI_ARGS_((Display *d, int i)); /* 36 */ - void (*xFreeColormap) _ANSI_ARGS_((Display *d, Colormap c)); /* 37 */ - void (*xFreeColors) _ANSI_ARGS_((Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul)); /* 38 */ - void (*xFreeCursor) _ANSI_ARGS_((Display *d, Cursor c)); /* 39 */ - void (*xFreeModifiermap) _ANSI_ARGS_((XModifierKeymap *x)); /* 40 */ - Status (*xGetGeometry) _ANSI_ARGS_((Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4)); /* 41 */ - void (*xGetInputFocus) _ANSI_ARGS_((Display *d, Window *w, int *i)); /* 42 */ - int (*xGetWindowProperty) _ANSI_ARGS_((Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp)); /* 43 */ - Status (*xGetWindowAttributes) _ANSI_ARGS_((Display *d, Window w, XWindowAttributes *x)); /* 44 */ - int (*xGrabKeyboard) _ANSI_ARGS_((Display *d, Window w, Bool b, int i1, int i2, Time t)); /* 45 */ - int (*xGrabPointer) _ANSI_ARGS_((Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t)); /* 46 */ - KeyCode (*xKeysymToKeycode) _ANSI_ARGS_((Display *d, KeySym k)); /* 47 */ - Status (*xLookupColor) _ANSI_ARGS_((Display *d, Colormap c1, _Xconst char *c2, XColor *x1, XColor *x2)); /* 48 */ - void (*xMapWindow) _ANSI_ARGS_((Display *d, Window w)); /* 49 */ - void (*xMoveResizeWindow) _ANSI_ARGS_((Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 50 */ - void (*xMoveWindow) _ANSI_ARGS_((Display *d, Window w, int i1, int i2)); /* 51 */ - void (*xNextEvent) _ANSI_ARGS_((Display *d, XEvent *x)); /* 52 */ - void (*xPutBackEvent) _ANSI_ARGS_((Display *d, XEvent *x)); /* 53 */ - void (*xQueryColors) _ANSI_ARGS_((Display *d, Colormap c, XColor *x, int i)); /* 54 */ - Bool (*xQueryPointer) _ANSI_ARGS_((Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui)); /* 55 */ - Status (*xQueryTree) _ANSI_ARGS_((Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui)); /* 56 */ - void (*xRaiseWindow) _ANSI_ARGS_((Display *d, Window w)); /* 57 */ - void (*xRefreshKeyboardMapping) _ANSI_ARGS_((XMappingEvent *x)); /* 58 */ - void (*xResizeWindow) _ANSI_ARGS_((Display *d, Window w, unsigned int ui1, unsigned int ui2)); /* 59 */ - void (*xSelectInput) _ANSI_ARGS_((Display *d, Window w, long l)); /* 60 */ - Status (*xSendEvent) _ANSI_ARGS_((Display *d, Window w, Bool b, long l, XEvent *x)); /* 61 */ - void (*xSetCommand) _ANSI_ARGS_((Display *d, Window w, CONST char **c, int i)); /* 62 */ - void (*xSetIconName) _ANSI_ARGS_((Display *d, Window w, _Xconst char *c)); /* 63 */ - void (*xSetInputFocus) _ANSI_ARGS_((Display *d, Window w, int i, Time t)); /* 64 */ - void (*xSetSelectionOwner) _ANSI_ARGS_((Display *d, Atom a, Window w, Time t)); /* 65 */ - void (*xSetWindowBackground) _ANSI_ARGS_((Display *d, Window w, unsigned long ul)); /* 66 */ - void (*xSetWindowBackgroundPixmap) _ANSI_ARGS_((Display *d, Window w, Pixmap p)); /* 67 */ - void (*xSetWindowBorder) _ANSI_ARGS_((Display *d, Window w, unsigned long ul)); /* 68 */ - void (*xSetWindowBorderPixmap) _ANSI_ARGS_((Display *d, Window w, Pixmap p)); /* 69 */ - void (*xSetWindowBorderWidth) _ANSI_ARGS_((Display *d, Window w, unsigned int ui)); /* 70 */ - void (*xSetWindowColormap) _ANSI_ARGS_((Display *d, Window w, Colormap c)); /* 71 */ - Bool (*xTranslateCoordinates) _ANSI_ARGS_((Display *d, Window w1, Window w2, int i1, int i2, int *i3, int *i4, Window *w3)); /* 72 */ - void (*xUngrabKeyboard) _ANSI_ARGS_((Display *d, Time t)); /* 73 */ - void (*xUngrabPointer) _ANSI_ARGS_((Display *d, Time t)); /* 74 */ - void (*xUnmapWindow) _ANSI_ARGS_((Display *d, Window w)); /* 75 */ - void (*xWindowEvent) _ANSI_ARGS_((Display *d, Window w, long l, XEvent *x)); /* 76 */ - void (*xDestroyIC) _ANSI_ARGS_((XIC x)); /* 77 */ - Bool (*xFilterEvent) _ANSI_ARGS_((XEvent *x, Window w)); /* 78 */ - int (*xmbLookupString) _ANSI_ARGS_((XIC xi, XKeyPressedEvent *xk, char *c, int i, KeySym *k, Status *s)); /* 79 */ - void (*tkPutImage) _ANSI_ARGS_((unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)); /* 80 */ +#ifdef __WIN32__ /* WIN */ + void (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */ + XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */ + XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */ + XImage * (*xGetImage) (Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3); /* 3 */ + char * (*xGetAtomName) (Display *d, Atom a); /* 4 */ + char * (*xKeysymToString) (KeySym k); /* 5 */ + Colormap (*xCreateColormap) (Display *d, Window w, Visual *v, int i); /* 6 */ + Cursor (*xCreatePixmapCursor) (Display *d, Pixmap p1, Pixmap p2, XColor *x1, XColor *x2, unsigned int ui1, unsigned int ui2); /* 7 */ + Cursor (*xCreateGlyphCursor) (Display *d, Font f1, Font f2, unsigned int ui1, unsigned int ui2, XColor *x1, XColor *x2); /* 8 */ + GContext (*xGContextFromGC) (GC g); /* 9 */ + XHostAddress * (*xListHosts) (Display *d, int *i, Bool *b); /* 10 */ + KeySym (*xKeycodeToKeysym) (Display *d, unsigned int k, int i); /* 11 */ + KeySym (*xStringToKeysym) (_Xconst char *c); /* 12 */ + Window (*xRootWindow) (Display *d, int i); /* 13 */ + XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 14 */ + Status (*xIconifyWindow) (Display *d, Window w, int i); /* 15 */ + Status (*xWithdrawWindow) (Display *d, Window w, int i); /* 16 */ + Status (*xGetWMColormapWindows) (Display *d, Window w, Window **wpp, int *ip); /* 17 */ + Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 18 */ + void (*xBell) (Display *d, int i); /* 19 */ + void (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 20 */ + void (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 21 */ + void (*xClearWindow) (Display *d, Window w); /* 22 */ + void (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 23 */ + void (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 24 */ + void (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 25 */ + Pixmap (*xCreateBitmapFromData) (Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height); /* 26 */ + void (*xDefineCursor) (Display *d, Window w, Cursor c); /* 27 */ + void (*xDeleteProperty) (Display *d, Window w, Atom a); /* 28 */ + void (*xDestroyWindow) (Display *d, Window w); /* 29 */ + void (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 30 */ + void (*xDrawLines) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2); /* 31 */ + void (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 32 */ + void (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 33 */ + void (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 34 */ + void (*xFillRectangles) (Display *d, Drawable dr, GC g, XRectangle *x, int i); /* 35 */ + void (*xForceScreenSaver) (Display *d, int i); /* 36 */ + void (*xFreeColormap) (Display *d, Colormap c); /* 37 */ + void (*xFreeColors) (Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul); /* 38 */ + void (*xFreeCursor) (Display *d, Cursor c); /* 39 */ + void (*xFreeModifiermap) (XModifierKeymap *x); /* 40 */ + Status (*xGetGeometry) (Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4); /* 41 */ + void (*xGetInputFocus) (Display *d, Window *w, int *i); /* 42 */ + int (*xGetWindowProperty) (Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp); /* 43 */ + Status (*xGetWindowAttributes) (Display *d, Window w, XWindowAttributes *x); /* 44 */ + int (*xGrabKeyboard) (Display *d, Window w, Bool b, int i1, int i2, Time t); /* 45 */ + int (*xGrabPointer) (Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t); /* 46 */ + KeyCode (*xKeysymToKeycode) (Display *d, KeySym k); /* 47 */ + Status (*xLookupColor) (Display *d, Colormap c1, _Xconst char *c2, XColor *x1, XColor *x2); /* 48 */ + void (*xMapWindow) (Display *d, Window w); /* 49 */ + void (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 50 */ + void (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 51 */ + void (*xNextEvent) (Display *d, XEvent *x); /* 52 */ + void (*xPutBackEvent) (Display *d, XEvent *x); /* 53 */ + void (*xQueryColors) (Display *d, Colormap c, XColor *x, int i); /* 54 */ + Bool (*xQueryPointer) (Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui); /* 55 */ + Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 56 */ + void (*xRaiseWindow) (Display *d, Window w); /* 57 */ + void (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 58 */ + void (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 59 */ + void (*xSelectInput) (Display *d, Window w, long l); /* 60 */ + Status (*xSendEvent) (Display *d, Window w, Bool b, long l, XEvent *x); /* 61 */ + void (*xSetCommand) (Display *d, Window w, CONST char **c, int i); /* 62 */ + void (*xSetIconName) (Display *d, Window w, _Xconst char *c); /* 63 */ + void (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 64 */ + void (*xSetSelectionOwner) (Display *d, Atom a, Window w, Time t); /* 65 */ + void (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 66 */ + void (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 67 */ + void (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 68 */ + void (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 69 */ + void (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 70 */ + void (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 71 */ + Bool (*xTranslateCoordinates) (Display *d, Window w1, Window w2, int i1, int i2, int *i3, int *i4, Window *w3); /* 72 */ + void (*xUngrabKeyboard) (Display *d, Time t); /* 73 */ + void (*xUngrabPointer) (Display *d, Time t); /* 74 */ + void (*xUnmapWindow) (Display *d, Window w); /* 75 */ + void (*xWindowEvent) (Display *d, Window w, long l, XEvent *x); /* 76 */ + void (*xDestroyIC) (XIC x); /* 77 */ + Bool (*xFilterEvent) (XEvent *x, Window w); /* 78 */ + int (*xmbLookupString) (XIC xi, XKeyPressedEvent *xk, char *c, int i, KeySym *k, Status *s); /* 79 */ + void (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 80 */ VOID *reserved81; - Status (*xParseColor) _ANSI_ARGS_((Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr)); /* 82 */ - GC (*xCreateGC) _ANSI_ARGS_((Display *display, Drawable d, unsigned long valuemask, XGCValues *values)); /* 83 */ - void (*xFreeGC) _ANSI_ARGS_((Display *display, GC gc)); /* 84 */ - Atom (*xInternAtom) _ANSI_ARGS_((Display *display, _Xconst char *atom_name, Bool only_if_exists)); /* 85 */ - void (*xSetBackground) _ANSI_ARGS_((Display *display, GC gc, unsigned long foreground)); /* 86 */ - void (*xSetForeground) _ANSI_ARGS_((Display *display, GC gc, unsigned long foreground)); /* 87 */ - void (*xSetClipMask) _ANSI_ARGS_((Display *display, GC gc, Pixmap pixmap)); /* 88 */ - void (*xSetClipOrigin) _ANSI_ARGS_((Display *display, GC gc, int clip_x_origin, int clip_y_origin)); /* 89 */ - void (*xSetTSOrigin) _ANSI_ARGS_((Display *display, GC gc, int ts_x_origin, int ts_y_origin)); /* 90 */ - void (*xChangeGC) _ANSI_ARGS_((Display *d, GC gc, unsigned long mask, XGCValues *values)); /* 91 */ - void (*xSetFont) _ANSI_ARGS_((Display *display, GC gc, Font font)); /* 92 */ - void (*xSetArcMode) _ANSI_ARGS_((Display *display, GC gc, int arc_mode)); /* 93 */ - void (*xSetStipple) _ANSI_ARGS_((Display *display, GC gc, Pixmap stipple)); /* 94 */ - void (*xSetFillRule) _ANSI_ARGS_((Display *display, GC gc, int fill_rule)); /* 95 */ - void (*xSetFillStyle) _ANSI_ARGS_((Display *display, GC gc, int fill_style)); /* 96 */ - void (*xSetFunction) _ANSI_ARGS_((Display *display, GC gc, int function)); /* 97 */ - void (*xSetLineAttributes) _ANSI_ARGS_((Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style)); /* 98 */ - int (*_XInitImageFuncPtrs) _ANSI_ARGS_((XImage *image)); /* 99 */ - XIC (*xCreateIC) _ANSI_ARGS_((void)); /* 100 */ - XVisualInfo * (*xGetVisualInfo) _ANSI_ARGS_((Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return)); /* 101 */ - void (*xSetWMClientMachine) _ANSI_ARGS_((Display *display, Window w, XTextProperty *text_prop)); /* 102 */ - Status (*xStringListToTextProperty) _ANSI_ARGS_((char **list, int count, XTextProperty *text_prop_return)); /* 103 */ - void (*xDrawLine) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2)); /* 104 */ - void (*xWarpPointer) _ANSI_ARGS_((Display *d, Window s, Window dw, int sx, int sy, unsigned int sw, unsigned int sh, int dx, int dy)); /* 105 */ - void (*xFillRectangle) _ANSI_ARGS_((Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height)); /* 106 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*xSetDashes) _ANSI_ARGS_((Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n)); /* 0 */ - XModifierKeymap * (*xGetModifierMapping) _ANSI_ARGS_((Display *d)); /* 1 */ - XImage * (*xCreateImage) _ANSI_ARGS_((Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4)); /* 2 */ - XImage * (*xGetImage) _ANSI_ARGS_((Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)); /* 3 */ - char * (*xGetAtomName) _ANSI_ARGS_((Display *d, Atom a)); /* 4 */ - char * (*xKeysymToString) _ANSI_ARGS_((KeySym k)); /* 5 */ - Colormap (*xCreateColormap) _ANSI_ARGS_((Display *d, Window w, Visual *v, int i)); /* 6 */ - GContext (*xGContextFromGC) _ANSI_ARGS_((GC g)); /* 7 */ - KeySym (*xKeycodeToKeysym) _ANSI_ARGS_((Display *d, KeyCode k, int i)); /* 8 */ - KeySym (*xStringToKeysym) _ANSI_ARGS_((_Xconst char *c)); /* 9 */ - Window (*xRootWindow) _ANSI_ARGS_((Display *d, int i)); /* 10 */ - XErrorHandler (*xSetErrorHandler) _ANSI_ARGS_((XErrorHandler x)); /* 11 */ - Status (*xAllocColor) _ANSI_ARGS_((Display *d, Colormap c, XColor *xp)); /* 12 */ - void (*xBell) _ANSI_ARGS_((Display *d, int i)); /* 13 */ - void (*xChangeProperty) _ANSI_ARGS_((Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3)); /* 14 */ - void (*xChangeWindowAttributes) _ANSI_ARGS_((Display *d, Window w, unsigned long ul, XSetWindowAttributes *x)); /* 15 */ - void (*xConfigureWindow) _ANSI_ARGS_((Display *d, Window w, unsigned int i, XWindowChanges *x)); /* 16 */ - void (*xCopyArea) _ANSI_ARGS_((Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 17 */ - void (*xCopyPlane) _ANSI_ARGS_((Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul)); /* 18 */ - Pixmap (*xCreateBitmapFromData) _ANSI_ARGS_((Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height)); /* 19 */ - void (*xDefineCursor) _ANSI_ARGS_((Display *d, Window w, Cursor c)); /* 20 */ - void (*xDestroyWindow) _ANSI_ARGS_((Display *d, Window w)); /* 21 */ - void (*xDrawArc) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 22 */ - void (*xDrawLines) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)); /* 23 */ - void (*xDrawRectangle) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 24 */ - void (*xFillArc) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 25 */ - void (*xFillPolygon) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3)); /* 26 */ - void (*xFillRectangles) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XRectangle *x, int i)); /* 27 */ - void (*xFreeColormap) _ANSI_ARGS_((Display *d, Colormap c)); /* 28 */ - void (*xFreeColors) _ANSI_ARGS_((Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul)); /* 29 */ - void (*xFreeModifiermap) _ANSI_ARGS_((XModifierKeymap *x)); /* 30 */ - Status (*xGetGeometry) _ANSI_ARGS_((Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4)); /* 31 */ - int (*xGetWindowProperty) _ANSI_ARGS_((Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp)); /* 32 */ - int (*xGrabKeyboard) _ANSI_ARGS_((Display *d, Window w, Bool b, int i1, int i2, Time t)); /* 33 */ - int (*xGrabPointer) _ANSI_ARGS_((Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t)); /* 34 */ - KeyCode (*xKeysymToKeycode) _ANSI_ARGS_((Display *d, KeySym k)); /* 35 */ - void (*xMapWindow) _ANSI_ARGS_((Display *d, Window w)); /* 36 */ - void (*xMoveResizeWindow) _ANSI_ARGS_((Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 37 */ - void (*xMoveWindow) _ANSI_ARGS_((Display *d, Window w, int i1, int i2)); /* 38 */ - Bool (*xQueryPointer) _ANSI_ARGS_((Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui)); /* 39 */ - void (*xRaiseWindow) _ANSI_ARGS_((Display *d, Window w)); /* 40 */ - void (*xRefreshKeyboardMapping) _ANSI_ARGS_((XMappingEvent *x)); /* 41 */ - void (*xResizeWindow) _ANSI_ARGS_((Display *d, Window w, unsigned int ui1, unsigned int ui2)); /* 42 */ - void (*xSelectInput) _ANSI_ARGS_((Display *d, Window w, long l)); /* 43 */ - Status (*xSendEvent) _ANSI_ARGS_((Display *d, Window w, Bool b, long l, XEvent *x)); /* 44 */ - void (*xSetIconName) _ANSI_ARGS_((Display *d, Window w, _Xconst char *c)); /* 45 */ - void (*xSetInputFocus) _ANSI_ARGS_((Display *d, Window w, int i, Time t)); /* 46 */ - void (*xSetSelectionOwner) _ANSI_ARGS_((Display *d, Atom a, Window w, Time t)); /* 47 */ - void (*xSetWindowBackground) _ANSI_ARGS_((Display *d, Window w, unsigned long ul)); /* 48 */ - void (*xSetWindowBackgroundPixmap) _ANSI_ARGS_((Display *d, Window w, Pixmap p)); /* 49 */ - void (*xSetWindowBorder) _ANSI_ARGS_((Display *d, Window w, unsigned long ul)); /* 50 */ - void (*xSetWindowBorderPixmap) _ANSI_ARGS_((Display *d, Window w, Pixmap p)); /* 51 */ - void (*xSetWindowBorderWidth) _ANSI_ARGS_((Display *d, Window w, unsigned int ui)); /* 52 */ - void (*xSetWindowColormap) _ANSI_ARGS_((Display *d, Window w, Colormap c)); /* 53 */ - void (*xUngrabKeyboard) _ANSI_ARGS_((Display *d, Time t)); /* 54 */ - void (*xUngrabPointer) _ANSI_ARGS_((Display *d, Time t)); /* 55 */ - void (*xUnmapWindow) _ANSI_ARGS_((Display *d, Window w)); /* 56 */ - void (*tkPutImage) _ANSI_ARGS_((unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)); /* 57 */ - Status (*xParseColor) _ANSI_ARGS_((Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr)); /* 58 */ - GC (*xCreateGC) _ANSI_ARGS_((Display *display, Drawable d, unsigned long valuemask, XGCValues *values)); /* 59 */ - void (*xFreeGC) _ANSI_ARGS_((Display *display, GC gc)); /* 60 */ - Atom (*xInternAtom) _ANSI_ARGS_((Display *display, _Xconst char *atom_name, Bool only_if_exists)); /* 61 */ - void (*xSetBackground) _ANSI_ARGS_((Display *display, GC gc, unsigned long foreground)); /* 62 */ - void (*xSetForeground) _ANSI_ARGS_((Display *display, GC gc, unsigned long foreground)); /* 63 */ - void (*xSetClipMask) _ANSI_ARGS_((Display *display, GC gc, Pixmap pixmap)); /* 64 */ - void (*xSetClipOrigin) _ANSI_ARGS_((Display *display, GC gc, int clip_x_origin, int clip_y_origin)); /* 65 */ - void (*xSetTSOrigin) _ANSI_ARGS_((Display *display, GC gc, int ts_x_origin, int ts_y_origin)); /* 66 */ - void (*xChangeGC) _ANSI_ARGS_((Display *d, GC gc, unsigned long mask, XGCValues *values)); /* 67 */ - void (*xSetFont) _ANSI_ARGS_((Display *display, GC gc, Font font)); /* 68 */ - void (*xSetArcMode) _ANSI_ARGS_((Display *display, GC gc, int arc_mode)); /* 69 */ - void (*xSetStipple) _ANSI_ARGS_((Display *display, GC gc, Pixmap stipple)); /* 70 */ - void (*xSetFillRule) _ANSI_ARGS_((Display *display, GC gc, int fill_rule)); /* 71 */ - void (*xSetFillStyle) _ANSI_ARGS_((Display *display, GC gc, int fill_style)); /* 72 */ - void (*xSetFunction) _ANSI_ARGS_((Display *display, GC gc, int function)); /* 73 */ - void (*xSetLineAttributes) _ANSI_ARGS_((Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style)); /* 74 */ - int (*_XInitImageFuncPtrs) _ANSI_ARGS_((XImage *image)); /* 75 */ - XIC (*xCreateIC) _ANSI_ARGS_((void)); /* 76 */ - XVisualInfo * (*xGetVisualInfo) _ANSI_ARGS_((Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return)); /* 77 */ - void (*xSetWMClientMachine) _ANSI_ARGS_((Display *display, Window w, XTextProperty *text_prop)); /* 78 */ - Status (*xStringListToTextProperty) _ANSI_ARGS_((char **list, int count, XTextProperty *text_prop_return)); /* 79 */ - void (*xDrawSegments) _ANSI_ARGS_((Display *display, Drawable d, GC gc, XSegment *segments, int nsegments)); /* 80 */ - void (*xForceScreenSaver) _ANSI_ARGS_((Display *display, int mode)); /* 81 */ - void (*xDrawLine) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2)); /* 82 */ - void (*xFillRectangle) _ANSI_ARGS_((Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height)); /* 83 */ - void (*xClearWindow) _ANSI_ARGS_((Display *d, Window w)); /* 84 */ - void (*xDrawPoint) _ANSI_ARGS_((Display *display, Drawable d, GC gc, int x, int y)); /* 85 */ - void (*xDrawPoints) _ANSI_ARGS_((Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode)); /* 86 */ - void (*xWarpPointer) _ANSI_ARGS_((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) _ANSI_ARGS_((Display *display, Colormap colormap, XColor *def_in_out)); /* 88 */ - void (*xQueryColors) _ANSI_ARGS_((Display *display, Colormap colormap, XColor *defs_in_out, int ncolors)); /* 89 */ - Status (*xQueryTree) _ANSI_ARGS_((Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui)); /* 90 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*xSetDashes) _ANSI_ARGS_((Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n)); /* 0 */ - XModifierKeymap * (*xGetModifierMapping) _ANSI_ARGS_((Display *d)); /* 1 */ - XImage * (*xCreateImage) _ANSI_ARGS_((Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4)); /* 2 */ - XImage * (*xGetImage) _ANSI_ARGS_((Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)); /* 3 */ - char * (*xGetAtomName) _ANSI_ARGS_((Display *d, Atom a)); /* 4 */ - char * (*xKeysymToString) _ANSI_ARGS_((KeySym k)); /* 5 */ - Colormap (*xCreateColormap) _ANSI_ARGS_((Display *d, Window w, Visual *v, int i)); /* 6 */ - GContext (*xGContextFromGC) _ANSI_ARGS_((GC g)); /* 7 */ - KeySym (*xKeycodeToKeysym) _ANSI_ARGS_((Display *d, KeyCode k, int i)); /* 8 */ - KeySym (*xStringToKeysym) _ANSI_ARGS_((_Xconst char *c)); /* 9 */ - Window (*xRootWindow) _ANSI_ARGS_((Display *d, int i)); /* 10 */ - XErrorHandler (*xSetErrorHandler) _ANSI_ARGS_((XErrorHandler x)); /* 11 */ - Status (*xAllocColor) _ANSI_ARGS_((Display *d, Colormap c, XColor *xp)); /* 12 */ - void (*xBell) _ANSI_ARGS_((Display *d, int i)); /* 13 */ - void (*xChangeProperty) _ANSI_ARGS_((Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3)); /* 14 */ - void (*xChangeWindowAttributes) _ANSI_ARGS_((Display *d, Window w, unsigned long ul, XSetWindowAttributes *x)); /* 15 */ - void (*xConfigureWindow) _ANSI_ARGS_((Display *d, Window w, unsigned int i, XWindowChanges *x)); /* 16 */ - void (*xCopyArea) _ANSI_ARGS_((Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 17 */ - void (*xCopyPlane) _ANSI_ARGS_((Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul)); /* 18 */ - Pixmap (*xCreateBitmapFromData) _ANSI_ARGS_((Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height)); /* 19 */ - void (*xDefineCursor) _ANSI_ARGS_((Display *d, Window w, Cursor c)); /* 20 */ - void (*xDestroyWindow) _ANSI_ARGS_((Display *d, Window w)); /* 21 */ - void (*xDrawArc) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 22 */ - void (*xDrawLines) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2)); /* 23 */ - void (*xDrawRectangle) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 24 */ - void (*xFillArc) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 25 */ - void (*xFillPolygon) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3)); /* 26 */ - void (*xFillRectangles) _ANSI_ARGS_((Display *d, Drawable dr, GC g, XRectangle *x, int i)); /* 27 */ - void (*xFreeColormap) _ANSI_ARGS_((Display *d, Colormap c)); /* 28 */ - void (*xFreeColors) _ANSI_ARGS_((Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul)); /* 29 */ - void (*xFreeModifiermap) _ANSI_ARGS_((XModifierKeymap *x)); /* 30 */ - Status (*xGetGeometry) _ANSI_ARGS_((Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4)); /* 31 */ - int (*xGetWindowProperty) _ANSI_ARGS_((Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp)); /* 32 */ - int (*xGrabKeyboard) _ANSI_ARGS_((Display *d, Window w, Bool b, int i1, int i2, Time t)); /* 33 */ - int (*xGrabPointer) _ANSI_ARGS_((Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t)); /* 34 */ - KeyCode (*xKeysymToKeycode) _ANSI_ARGS_((Display *d, KeySym k)); /* 35 */ - void (*xMapWindow) _ANSI_ARGS_((Display *d, Window w)); /* 36 */ - void (*xMoveResizeWindow) _ANSI_ARGS_((Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 37 */ - void (*xMoveWindow) _ANSI_ARGS_((Display *d, Window w, int i1, int i2)); /* 38 */ - Bool (*xQueryPointer) _ANSI_ARGS_((Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui)); /* 39 */ - void (*xRaiseWindow) _ANSI_ARGS_((Display *d, Window w)); /* 40 */ - void (*xRefreshKeyboardMapping) _ANSI_ARGS_((XMappingEvent *x)); /* 41 */ - void (*xResizeWindow) _ANSI_ARGS_((Display *d, Window w, unsigned int ui1, unsigned int ui2)); /* 42 */ - void (*xSelectInput) _ANSI_ARGS_((Display *d, Window w, long l)); /* 43 */ - Status (*xSendEvent) _ANSI_ARGS_((Display *d, Window w, Bool b, long l, XEvent *x)); /* 44 */ - void (*xSetIconName) _ANSI_ARGS_((Display *d, Window w, _Xconst char *c)); /* 45 */ - void (*xSetInputFocus) _ANSI_ARGS_((Display *d, Window w, int i, Time t)); /* 46 */ - void (*xSetSelectionOwner) _ANSI_ARGS_((Display *d, Atom a, Window w, Time t)); /* 47 */ - void (*xSetWindowBackground) _ANSI_ARGS_((Display *d, Window w, unsigned long ul)); /* 48 */ - void (*xSetWindowBackgroundPixmap) _ANSI_ARGS_((Display *d, Window w, Pixmap p)); /* 49 */ - void (*xSetWindowBorder) _ANSI_ARGS_((Display *d, Window w, unsigned long ul)); /* 50 */ - void (*xSetWindowBorderPixmap) _ANSI_ARGS_((Display *d, Window w, Pixmap p)); /* 51 */ - void (*xSetWindowBorderWidth) _ANSI_ARGS_((Display *d, Window w, unsigned int ui)); /* 52 */ - void (*xSetWindowColormap) _ANSI_ARGS_((Display *d, Window w, Colormap c)); /* 53 */ - void (*xUngrabKeyboard) _ANSI_ARGS_((Display *d, Time t)); /* 54 */ - void (*xUngrabPointer) _ANSI_ARGS_((Display *d, Time t)); /* 55 */ - void (*xUnmapWindow) _ANSI_ARGS_((Display *d, Window w)); /* 56 */ - void (*tkPutImage) _ANSI_ARGS_((unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)); /* 57 */ - Status (*xParseColor) _ANSI_ARGS_((Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr)); /* 58 */ - GC (*xCreateGC) _ANSI_ARGS_((Display *display, Drawable d, unsigned long valuemask, XGCValues *values)); /* 59 */ - void (*xFreeGC) _ANSI_ARGS_((Display *display, GC gc)); /* 60 */ - Atom (*xInternAtom) _ANSI_ARGS_((Display *display, _Xconst char *atom_name, Bool only_if_exists)); /* 61 */ - void (*xSetBackground) _ANSI_ARGS_((Display *display, GC gc, unsigned long foreground)); /* 62 */ - void (*xSetForeground) _ANSI_ARGS_((Display *display, GC gc, unsigned long foreground)); /* 63 */ - void (*xSetClipMask) _ANSI_ARGS_((Display *display, GC gc, Pixmap pixmap)); /* 64 */ - void (*xSetClipOrigin) _ANSI_ARGS_((Display *display, GC gc, int clip_x_origin, int clip_y_origin)); /* 65 */ - void (*xSetTSOrigin) _ANSI_ARGS_((Display *display, GC gc, int ts_x_origin, int ts_y_origin)); /* 66 */ - void (*xChangeGC) _ANSI_ARGS_((Display *d, GC gc, unsigned long mask, XGCValues *values)); /* 67 */ - void (*xSetFont) _ANSI_ARGS_((Display *display, GC gc, Font font)); /* 68 */ - void (*xSetArcMode) _ANSI_ARGS_((Display *display, GC gc, int arc_mode)); /* 69 */ - void (*xSetStipple) _ANSI_ARGS_((Display *display, GC gc, Pixmap stipple)); /* 70 */ - void (*xSetFillRule) _ANSI_ARGS_((Display *display, GC gc, int fill_rule)); /* 71 */ - void (*xSetFillStyle) _ANSI_ARGS_((Display *display, GC gc, int fill_style)); /* 72 */ - void (*xSetFunction) _ANSI_ARGS_((Display *display, GC gc, int function)); /* 73 */ - void (*xSetLineAttributes) _ANSI_ARGS_((Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style)); /* 74 */ - int (*_XInitImageFuncPtrs) _ANSI_ARGS_((XImage *image)); /* 75 */ - XIC (*xCreateIC) _ANSI_ARGS_((void)); /* 76 */ - XVisualInfo * (*xGetVisualInfo) _ANSI_ARGS_((Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return)); /* 77 */ - void (*xSetWMClientMachine) _ANSI_ARGS_((Display *display, Window w, XTextProperty *text_prop)); /* 78 */ - Status (*xStringListToTextProperty) _ANSI_ARGS_((char **list, int count, XTextProperty *text_prop_return)); /* 79 */ - void (*xDrawSegments) _ANSI_ARGS_((Display *display, Drawable d, GC gc, XSegment *segments, int nsegments)); /* 80 */ - void (*xForceScreenSaver) _ANSI_ARGS_((Display *display, int mode)); /* 81 */ - void (*xDrawLine) _ANSI_ARGS_((Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2)); /* 82 */ - void (*xFillRectangle) _ANSI_ARGS_((Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height)); /* 83 */ - void (*xClearWindow) _ANSI_ARGS_((Display *d, Window w)); /* 84 */ - void (*xDrawPoint) _ANSI_ARGS_((Display *display, Drawable d, GC gc, int x, int y)); /* 85 */ - void (*xDrawPoints) _ANSI_ARGS_((Display *display, Drawable d, GC gc, XPoint *points, int npoints, int mode)); /* 86 */ - void (*xWarpPointer) _ANSI_ARGS_((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) _ANSI_ARGS_((Display *display, Colormap colormap, XColor *def_in_out)); /* 88 */ - void (*xQueryColors) _ANSI_ARGS_((Display *display, Colormap colormap, XColor *defs_in_out, int ncolors)); /* 89 */ - Status (*xQueryTree) _ANSI_ARGS_((Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui)); /* 90 */ - int (*xSync) _ANSI_ARGS_((Display *display, Bool flag)); /* 91 */ -#endif /* MAC_OSX_TK */ + Status (*xParseColor) (Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); /* 82 */ + GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 83 */ + void (*xFreeGC) (Display *display, GC gc); /* 84 */ + Atom (*xInternAtom) (Display *display, _Xconst char *atom_name, Bool only_if_exists); /* 85 */ + void (*xSetBackground) (Display *display, GC gc, unsigned long foreground); /* 86 */ + void (*xSetForeground) (Display *display, GC gc, unsigned long foreground); /* 87 */ + void (*xSetClipMask) (Display *display, GC gc, Pixmap pixmap); /* 88 */ + void (*xSetClipOrigin) (Display *display, GC gc, int clip_x_origin, int clip_y_origin); /* 89 */ + void (*xSetTSOrigin) (Display *display, GC gc, int ts_x_origin, int ts_y_origin); /* 90 */ + void (*xChangeGC) (Display *d, GC gc, unsigned long mask, XGCValues *values); /* 91 */ + void (*xSetFont) (Display *display, GC gc, Font font); /* 92 */ + void (*xSetArcMode) (Display *display, GC gc, int arc_mode); /* 93 */ + void (*xSetStipple) (Display *display, GC gc, Pixmap stipple); /* 94 */ + void (*xSetFillRule) (Display *display, GC gc, int fill_rule); /* 95 */ + void (*xSetFillStyle) (Display *display, GC gc, int fill_style); /* 96 */ + void (*xSetFunction) (Display *display, GC gc, int function); /* 97 */ + void (*xSetLineAttributes) (Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style); /* 98 */ + int (*_XInitImageFuncPtrs) (XImage *image); /* 99 */ + XIC (*xCreateIC) (void); /* 100 */ + XVisualInfo * (*xGetVisualInfo) (Display *display, long vinfo_mask, XVisualInfo *vinfo_template, int *nitems_return); /* 101 */ + void (*xSetWMClientMachine) (Display *display, Window w, XTextProperty *text_prop); /* 102 */ + Status (*xStringListToTextProperty) (char **list, int count, XTextProperty *text_prop_return); /* 103 */ + void (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 104 */ + void (*xWarpPointer) (Display *d, Window s, Window dw, int sx, int sy, unsigned int sw, unsigned int sh, int dx, int dy); /* 105 */ + void (*xFillRectangle) (Display *display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height); /* 106 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + void (*xSetDashes) (Display *display, GC gc, int dash_offset, _Xconst char *dash_list, int n); /* 0 */ + XModifierKeymap * (*xGetModifierMapping) (Display *d); /* 1 */ + XImage * (*xCreateImage) (Display *d, Visual *v, unsigned int ui1, int i1, int i2, char *cp, unsigned int ui2, unsigned int ui3, int i3, int i4); /* 2 */ + XImage * (*xGetImage) (Display *d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3); /* 3 */ + char * (*xGetAtomName) (Display *d, Atom a); /* 4 */ + char * (*xKeysymToString) (KeySym k); /* 5 */ + Colormap (*xCreateColormap) (Display *d, Window w, Visual *v, int i); /* 6 */ + GContext (*xGContextFromGC) (GC g); /* 7 */ + KeySym (*xKeycodeToKeysym) (Display *d, KeyCode k, int i); /* 8 */ + KeySym (*xStringToKeysym) (_Xconst char *c); /* 9 */ + Window (*xRootWindow) (Display *d, int i); /* 10 */ + XErrorHandler (*xSetErrorHandler) (XErrorHandler x); /* 11 */ + Status (*xAllocColor) (Display *d, Colormap c, XColor *xp); /* 12 */ + void (*xBell) (Display *d, int i); /* 13 */ + void (*xChangeProperty) (Display *d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char *c, int i3); /* 14 */ + void (*xChangeWindowAttributes) (Display *d, Window w, unsigned long ul, XSetWindowAttributes *x); /* 15 */ + void (*xConfigureWindow) (Display *d, Window w, unsigned int i, XWindowChanges *x); /* 16 */ + void (*xCopyArea) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 17 */ + void (*xCopyPlane) (Display *d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul); /* 18 */ + Pixmap (*xCreateBitmapFromData) (Display *display, Drawable d, _Xconst char *data, unsigned int width, unsigned int height); /* 19 */ + void (*xDefineCursor) (Display *d, Window w, Cursor c); /* 20 */ + void (*xDestroyWindow) (Display *d, Window w); /* 21 */ + void (*xDrawArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 22 */ + void (*xDrawLines) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2); /* 23 */ + void (*xDrawRectangle) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 24 */ + void (*xFillArc) (Display *d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4); /* 25 */ + void (*xFillPolygon) (Display *d, Drawable dr, GC g, XPoint *x, int i1, int i2, int i3); /* 26 */ + void (*xFillRectangles) (Display *d, Drawable dr, GC g, XRectangle *x, int i); /* 27 */ + void (*xFreeColormap) (Display *d, Colormap c); /* 28 */ + void (*xFreeColors) (Display *d, Colormap c, unsigned long *ulp, int i, unsigned long ul); /* 29 */ + void (*xFreeModifiermap) (XModifierKeymap *x); /* 30 */ + Status (*xGetGeometry) (Display *d, Drawable dr, Window *w, int *i1, int *i2, unsigned int *ui1, unsigned int *ui2, unsigned int *ui3, unsigned int *ui4); /* 31 */ + int (*xGetWindowProperty) (Display *d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom *ap, int *ip, unsigned long *ulp1, unsigned long *ulp2, unsigned char **cpp); /* 32 */ + int (*xGrabKeyboard) (Display *d, Window w, Bool b, int i1, int i2, Time t); /* 33 */ + int (*xGrabPointer) (Display *d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t); /* 34 */ + KeyCode (*xKeysymToKeycode) (Display *d, KeySym k); /* 35 */ + void (*xMapWindow) (Display *d, Window w); /* 36 */ + void (*xMoveResizeWindow) (Display *d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2); /* 37 */ + void (*xMoveWindow) (Display *d, Window w, int i1, int i2); /* 38 */ + Bool (*xQueryPointer) (Display *d, Window w1, Window *w2, Window *w3, int *i1, int *i2, int *i3, int *i4, unsigned int *ui); /* 39 */ + void (*xRaiseWindow) (Display *d, Window w); /* 40 */ + void (*xRefreshKeyboardMapping) (XMappingEvent *x); /* 41 */ + void (*xResizeWindow) (Display *d, Window w, unsigned int ui1, unsigned int ui2); /* 42 */ + void (*xSelectInput) (Display *d, Window w, long l); /* 43 */ + Status (*xSendEvent) (Display *d, Window w, Bool b, long l, XEvent *x); /* 44 */ + void (*xSetIconName) (Display *d, Window w, _Xconst char *c); /* 45 */ + void (*xSetInputFocus) (Display *d, Window w, int i, Time t); /* 46 */ + void (*xSetSelectionOwner) (Display *d, Atom a, Window w, Time t); /* 47 */ + void (*xSetWindowBackground) (Display *d, Window w, unsigned long ul); /* 48 */ + void (*xSetWindowBackgroundPixmap) (Display *d, Window w, Pixmap p); /* 49 */ + void (*xSetWindowBorder) (Display *d, Window w, unsigned long ul); /* 50 */ + void (*xSetWindowBorderPixmap) (Display *d, Window w, Pixmap p); /* 51 */ + void (*xSetWindowBorderWidth) (Display *d, Window w, unsigned int ui); /* 52 */ + void (*xSetWindowColormap) (Display *d, Window w, Colormap c); /* 53 */ + void (*xUngrabKeyboard) (Display *d, Time t); /* 54 */ + void (*xUngrabPointer) (Display *d, Time t); /* 55 */ + void (*xUnmapWindow) (Display *d, Window w); /* 56 */ + void (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 57 */ + Status (*xParseColor) (Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); /* 58 */ + GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 59 */ + void (*xFreeGC) (Display *display, GC gc); /* 60 */ + Atom (*xInternAtom) (Display *display, _Xconst char *atom_name, Bool only_if_exists); /* 61 */ + void (*xSetBackground) (Display *display, GC gc, unsigned long foreground); /* 62 */ + void (*xSetForeground) (Display *display, GC gc, unsigned long foreground); /* 63 */ + void (*xSetClipMask) (Display *display, GC gc, Pixmap pixmap); /* 64 */ + void (*xSetClipOrigin) (Display *display, GC gc, int clip_x_origin, int clip_y_origin); /* 65 */ + void (*xSetTSOrigin) (Display *display, GC gc, int ts_x_origin, int ts_y_origin); /* 66 */ + void (*xChangeGC) (Display *d, GC gc, unsigned long mask, XGCValues *values); /* 67 */ + void (*xSetFont) (Display *display, GC gc, Font font); /* 68 */ + void (*xSetArcMode) (Display *display, GC gc, int arc_mode); /* 69 */ + void (*xSetStipple) (Display *display, GC gc, Pixmap stipple); /* 70 */ + void (*xSetFillRule) (Display *display, GC gc, int fill_rule); /* 71 */ + void (*xSetFillStyle) (Display *display, GC gc, int fill_style); /* 72 */ + void (*xSetFunction) (Display *display, GC gc, int function); /* 73 */ + void (*xSetLineAttributes) (Display *display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style); /* 74 */ + int (*_XInitImageFuncPtrs) (XImage *image); /* 75 */ + XIC (*xCreateIC) (void); /* 76 */ + 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 */ + void (*xForceScreenSaver) (Display *display, int mode); /* 81 */ + void (*xDrawLine) (Display *d, Drawable dr, GC g, int x1, int y1, int x2, int y2); /* 82 */ + void (*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 */ + void (*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 */ + Status (*xQueryTree) (Display *d, Window w1, Window *w2, Window *w3, Window **w4, unsigned int *ui); /* 90 */ + int (*xSync) (Display *display, Bool flag); /* 91 */ +#endif /* AQUA */ } TkIntXlibStubs; #ifdef __cplusplus @@ -1263,7 +1412,7 @@ extern TkIntXlibStubs *tkIntXlibStubsPtr; * Inline function declarations: */ -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ #ifndef XSetDashes #define XSetDashes \ (tkIntXlibStubsPtr->xSetDashes) /* 0 */ @@ -1689,374 +1838,8 @@ extern TkIntXlibStubs *tkIntXlibStubsPtr; #define XFillRectangle \ (tkIntXlibStubsPtr->xFillRectangle) /* 106 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL -#ifndef XSetDashes -#define XSetDashes \ - (tkIntXlibStubsPtr->xSetDashes) /* 0 */ -#endif -#ifndef XGetModifierMapping -#define XGetModifierMapping \ - (tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */ -#endif -#ifndef XCreateImage -#define XCreateImage \ - (tkIntXlibStubsPtr->xCreateImage) /* 2 */ -#endif -#ifndef XGetImage -#define XGetImage \ - (tkIntXlibStubsPtr->xGetImage) /* 3 */ -#endif -#ifndef XGetAtomName -#define XGetAtomName \ - (tkIntXlibStubsPtr->xGetAtomName) /* 4 */ -#endif -#ifndef XKeysymToString -#define XKeysymToString \ - (tkIntXlibStubsPtr->xKeysymToString) /* 5 */ -#endif -#ifndef XCreateColormap -#define XCreateColormap \ - (tkIntXlibStubsPtr->xCreateColormap) /* 6 */ -#endif -#ifndef XGContextFromGC -#define XGContextFromGC \ - (tkIntXlibStubsPtr->xGContextFromGC) /* 7 */ -#endif -#ifndef XKeycodeToKeysym -#define XKeycodeToKeysym \ - (tkIntXlibStubsPtr->xKeycodeToKeysym) /* 8 */ -#endif -#ifndef XStringToKeysym -#define XStringToKeysym \ - (tkIntXlibStubsPtr->xStringToKeysym) /* 9 */ -#endif -#ifndef XRootWindow -#define XRootWindow \ - (tkIntXlibStubsPtr->xRootWindow) /* 10 */ -#endif -#ifndef XSetErrorHandler -#define XSetErrorHandler \ - (tkIntXlibStubsPtr->xSetErrorHandler) /* 11 */ -#endif -#ifndef XAllocColor -#define XAllocColor \ - (tkIntXlibStubsPtr->xAllocColor) /* 12 */ -#endif -#ifndef XBell -#define XBell \ - (tkIntXlibStubsPtr->xBell) /* 13 */ -#endif -#ifndef XChangeProperty -#define XChangeProperty \ - (tkIntXlibStubsPtr->xChangeProperty) /* 14 */ -#endif -#ifndef XChangeWindowAttributes -#define XChangeWindowAttributes \ - (tkIntXlibStubsPtr->xChangeWindowAttributes) /* 15 */ -#endif -#ifndef XConfigureWindow -#define XConfigureWindow \ - (tkIntXlibStubsPtr->xConfigureWindow) /* 16 */ -#endif -#ifndef XCopyArea -#define XCopyArea \ - (tkIntXlibStubsPtr->xCopyArea) /* 17 */ -#endif -#ifndef XCopyPlane -#define XCopyPlane \ - (tkIntXlibStubsPtr->xCopyPlane) /* 18 */ -#endif -#ifndef XCreateBitmapFromData -#define XCreateBitmapFromData \ - (tkIntXlibStubsPtr->xCreateBitmapFromData) /* 19 */ -#endif -#ifndef XDefineCursor -#define XDefineCursor \ - (tkIntXlibStubsPtr->xDefineCursor) /* 20 */ -#endif -#ifndef XDestroyWindow -#define XDestroyWindow \ - (tkIntXlibStubsPtr->xDestroyWindow) /* 21 */ -#endif -#ifndef XDrawArc -#define XDrawArc \ - (tkIntXlibStubsPtr->xDrawArc) /* 22 */ -#endif -#ifndef XDrawLines -#define XDrawLines \ - (tkIntXlibStubsPtr->xDrawLines) /* 23 */ -#endif -#ifndef XDrawRectangle -#define XDrawRectangle \ - (tkIntXlibStubsPtr->xDrawRectangle) /* 24 */ -#endif -#ifndef XFillArc -#define XFillArc \ - (tkIntXlibStubsPtr->xFillArc) /* 25 */ -#endif -#ifndef XFillPolygon -#define XFillPolygon \ - (tkIntXlibStubsPtr->xFillPolygon) /* 26 */ -#endif -#ifndef XFillRectangles -#define XFillRectangles \ - (tkIntXlibStubsPtr->xFillRectangles) /* 27 */ -#endif -#ifndef XFreeColormap -#define XFreeColormap \ - (tkIntXlibStubsPtr->xFreeColormap) /* 28 */ -#endif -#ifndef XFreeColors -#define XFreeColors \ - (tkIntXlibStubsPtr->xFreeColors) /* 29 */ -#endif -#ifndef XFreeModifiermap -#define XFreeModifiermap \ - (tkIntXlibStubsPtr->xFreeModifiermap) /* 30 */ -#endif -#ifndef XGetGeometry -#define XGetGeometry \ - (tkIntXlibStubsPtr->xGetGeometry) /* 31 */ -#endif -#ifndef XGetWindowProperty -#define XGetWindowProperty \ - (tkIntXlibStubsPtr->xGetWindowProperty) /* 32 */ -#endif -#ifndef XGrabKeyboard -#define XGrabKeyboard \ - (tkIntXlibStubsPtr->xGrabKeyboard) /* 33 */ -#endif -#ifndef XGrabPointer -#define XGrabPointer \ - (tkIntXlibStubsPtr->xGrabPointer) /* 34 */ -#endif -#ifndef XKeysymToKeycode -#define XKeysymToKeycode \ - (tkIntXlibStubsPtr->xKeysymToKeycode) /* 35 */ -#endif -#ifndef XMapWindow -#define XMapWindow \ - (tkIntXlibStubsPtr->xMapWindow) /* 36 */ -#endif -#ifndef XMoveResizeWindow -#define XMoveResizeWindow \ - (tkIntXlibStubsPtr->xMoveResizeWindow) /* 37 */ -#endif -#ifndef XMoveWindow -#define XMoveWindow \ - (tkIntXlibStubsPtr->xMoveWindow) /* 38 */ -#endif -#ifndef XQueryPointer -#define XQueryPointer \ - (tkIntXlibStubsPtr->xQueryPointer) /* 39 */ -#endif -#ifndef XRaiseWindow -#define XRaiseWindow \ - (tkIntXlibStubsPtr->xRaiseWindow) /* 40 */ -#endif -#ifndef XRefreshKeyboardMapping -#define XRefreshKeyboardMapping \ - (tkIntXlibStubsPtr->xRefreshKeyboardMapping) /* 41 */ -#endif -#ifndef XResizeWindow -#define XResizeWindow \ - (tkIntXlibStubsPtr->xResizeWindow) /* 42 */ -#endif -#ifndef XSelectInput -#define XSelectInput \ - (tkIntXlibStubsPtr->xSelectInput) /* 43 */ -#endif -#ifndef XSendEvent -#define XSendEvent \ - (tkIntXlibStubsPtr->xSendEvent) /* 44 */ -#endif -#ifndef XSetIconName -#define XSetIconName \ - (tkIntXlibStubsPtr->xSetIconName) /* 45 */ -#endif -#ifndef XSetInputFocus -#define XSetInputFocus \ - (tkIntXlibStubsPtr->xSetInputFocus) /* 46 */ -#endif -#ifndef XSetSelectionOwner -#define XSetSelectionOwner \ - (tkIntXlibStubsPtr->xSetSelectionOwner) /* 47 */ -#endif -#ifndef XSetWindowBackground -#define XSetWindowBackground \ - (tkIntXlibStubsPtr->xSetWindowBackground) /* 48 */ -#endif -#ifndef XSetWindowBackgroundPixmap -#define XSetWindowBackgroundPixmap \ - (tkIntXlibStubsPtr->xSetWindowBackgroundPixmap) /* 49 */ -#endif -#ifndef XSetWindowBorder -#define XSetWindowBorder \ - (tkIntXlibStubsPtr->xSetWindowBorder) /* 50 */ -#endif -#ifndef XSetWindowBorderPixmap -#define XSetWindowBorderPixmap \ - (tkIntXlibStubsPtr->xSetWindowBorderPixmap) /* 51 */ -#endif -#ifndef XSetWindowBorderWidth -#define XSetWindowBorderWidth \ - (tkIntXlibStubsPtr->xSetWindowBorderWidth) /* 52 */ -#endif -#ifndef XSetWindowColormap -#define XSetWindowColormap \ - (tkIntXlibStubsPtr->xSetWindowColormap) /* 53 */ -#endif -#ifndef XUngrabKeyboard -#define XUngrabKeyboard \ - (tkIntXlibStubsPtr->xUngrabKeyboard) /* 54 */ -#endif -#ifndef XUngrabPointer -#define XUngrabPointer \ - (tkIntXlibStubsPtr->xUngrabPointer) /* 55 */ -#endif -#ifndef XUnmapWindow -#define XUnmapWindow \ - (tkIntXlibStubsPtr->xUnmapWindow) /* 56 */ -#endif -#ifndef TkPutImage -#define TkPutImage \ - (tkIntXlibStubsPtr->tkPutImage) /* 57 */ -#endif -#ifndef XParseColor -#define XParseColor \ - (tkIntXlibStubsPtr->xParseColor) /* 58 */ -#endif -#ifndef XCreateGC -#define XCreateGC \ - (tkIntXlibStubsPtr->xCreateGC) /* 59 */ -#endif -#ifndef XFreeGC -#define XFreeGC \ - (tkIntXlibStubsPtr->xFreeGC) /* 60 */ -#endif -#ifndef XInternAtom -#define XInternAtom \ - (tkIntXlibStubsPtr->xInternAtom) /* 61 */ -#endif -#ifndef XSetBackground -#define XSetBackground \ - (tkIntXlibStubsPtr->xSetBackground) /* 62 */ -#endif -#ifndef XSetForeground -#define XSetForeground \ - (tkIntXlibStubsPtr->xSetForeground) /* 63 */ -#endif -#ifndef XSetClipMask -#define XSetClipMask \ - (tkIntXlibStubsPtr->xSetClipMask) /* 64 */ -#endif -#ifndef XSetClipOrigin -#define XSetClipOrigin \ - (tkIntXlibStubsPtr->xSetClipOrigin) /* 65 */ -#endif -#ifndef XSetTSOrigin -#define XSetTSOrigin \ - (tkIntXlibStubsPtr->xSetTSOrigin) /* 66 */ -#endif -#ifndef XChangeGC -#define XChangeGC \ - (tkIntXlibStubsPtr->xChangeGC) /* 67 */ -#endif -#ifndef XSetFont -#define XSetFont \ - (tkIntXlibStubsPtr->xSetFont) /* 68 */ -#endif -#ifndef XSetArcMode -#define XSetArcMode \ - (tkIntXlibStubsPtr->xSetArcMode) /* 69 */ -#endif -#ifndef XSetStipple -#define XSetStipple \ - (tkIntXlibStubsPtr->xSetStipple) /* 70 */ -#endif -#ifndef XSetFillRule -#define XSetFillRule \ - (tkIntXlibStubsPtr->xSetFillRule) /* 71 */ -#endif -#ifndef XSetFillStyle -#define XSetFillStyle \ - (tkIntXlibStubsPtr->xSetFillStyle) /* 72 */ -#endif -#ifndef XSetFunction -#define XSetFunction \ - (tkIntXlibStubsPtr->xSetFunction) /* 73 */ -#endif -#ifndef XSetLineAttributes -#define XSetLineAttributes \ - (tkIntXlibStubsPtr->xSetLineAttributes) /* 74 */ -#endif -#ifndef _XInitImageFuncPtrs -#define _XInitImageFuncPtrs \ - (tkIntXlibStubsPtr->_XInitImageFuncPtrs) /* 75 */ -#endif -#ifndef XCreateIC -#define XCreateIC \ - (tkIntXlibStubsPtr->xCreateIC) /* 76 */ -#endif -#ifndef XGetVisualInfo -#define XGetVisualInfo \ - (tkIntXlibStubsPtr->xGetVisualInfo) /* 77 */ -#endif -#ifndef XSetWMClientMachine -#define XSetWMClientMachine \ - (tkIntXlibStubsPtr->xSetWMClientMachine) /* 78 */ -#endif -#ifndef XStringListToTextProperty -#define XStringListToTextProperty \ - (tkIntXlibStubsPtr->xStringListToTextProperty) /* 79 */ -#endif -#ifndef XDrawSegments -#define XDrawSegments \ - (tkIntXlibStubsPtr->xDrawSegments) /* 80 */ -#endif -#ifndef XForceScreenSaver -#define XForceScreenSaver \ - (tkIntXlibStubsPtr->xForceScreenSaver) /* 81 */ -#endif -#ifndef XDrawLine -#define XDrawLine \ - (tkIntXlibStubsPtr->xDrawLine) /* 82 */ -#endif -#ifndef XFillRectangle -#define XFillRectangle \ - (tkIntXlibStubsPtr->xFillRectangle) /* 83 */ -#endif -#ifndef XClearWindow -#define XClearWindow \ - (tkIntXlibStubsPtr->xClearWindow) /* 84 */ -#endif -#ifndef XDrawPoint -#define XDrawPoint \ - (tkIntXlibStubsPtr->xDrawPoint) /* 85 */ -#endif -#ifndef XDrawPoints -#define XDrawPoints \ - (tkIntXlibStubsPtr->xDrawPoints) /* 86 */ -#endif -#ifndef XWarpPointer -#define XWarpPointer \ - (tkIntXlibStubsPtr->xWarpPointer) /* 87 */ -#endif -#ifndef XQueryColor -#define XQueryColor \ - (tkIntXlibStubsPtr->xQueryColor) /* 88 */ -#endif -#ifndef XQueryColors -#define XQueryColors \ - (tkIntXlibStubsPtr->xQueryColors) /* 89 */ -#endif -#ifndef XQueryTree -#define XQueryTree \ - (tkIntXlibStubsPtr->xQueryTree) /* 90 */ -#endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef XSetDashes #define XSetDashes \ (tkIntXlibStubsPtr->xSetDashes) /* 0 */ @@ -2425,7 +2208,7 @@ extern TkIntXlibStubs *tkIntXlibStubsPtr; #define XSync \ (tkIntXlibStubsPtr->xSync) /* 91 */ #endif -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ #endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ diff --git a/generic/tkListbox.c b/generic/tkListbox.c index cc73937..44421d2 100644 --- a/generic/tkListbox.c +++ b/generic/tkListbox.c @@ -1,18 +1,17 @@ -/* +/* * tkListbox.c -- * - * This module implements listbox widgets for the Tk - * toolkit. A listbox displays a collection of strings, - * one per line, and provides scrolling and selection. + * This module implements listbox widgets for the Tk toolkit. A listbox + * displays a collection of strings, one per line, and provides scrolling + * and selection. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "default.h" #include "tkInt.h" @@ -21,38 +20,40 @@ #endif typedef struct { - Tk_OptionTable listboxOptionTable; /* Table defining configuration options - * available for the listbox */ - Tk_OptionTable itemAttrOptionTable; /* Table definining configuration - * options available for listbox - * items */ + Tk_OptionTable listboxOptionTable; + /* Table defining configuration options + * available for the listbox. */ + Tk_OptionTable itemAttrOptionTable; + /* Table definining configuration options + * available for listbox items. */ } ListboxOptionTables; /* - * A data structure of the following type is kept for each listbox - * widget managed by this file: + * A data structure of the following type is kept for each listbox widget + * managed by this file: */ typedef struct { - Tk_Window tkwin; /* Window that embodies the listbox. NULL + Tk_Window tkwin; /* Window that embodies the listbox. NULL * means that the window has been destroyed * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display containing widget. Used, among + * cleaned up. */ + Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with listbox. */ Tcl_Command widgetCmd; /* Token for listbox's widget command. */ Tk_OptionTable optionTable; /* Table that defines configuration options * available for this widget. */ - Tk_OptionTable itemAttrOptionTable; /* Table that defines configuration - * options available for listbox - * items */ - char *listVarName; /* List variable name */ - Tcl_Obj *listObj; /* Pointer to the list object being used */ - int nElements; /* Holds the current count of elements */ - Tcl_HashTable *selection; /* Tracks selection */ - Tcl_HashTable *itemAttrTable; /* Tracks item attributes */ + Tk_OptionTable itemAttrOptionTable; + /* Table that defines configuration options + * available for listbox items. */ + char *listVarName; /* List variable name */ + Tcl_Obj *listObj; /* Pointer to the list object being used */ + int nElements; /* Holds the current count of elements */ + Tcl_HashTable *selection; /* Tracks selection */ + Tcl_HashTable *itemAttrTable; + /* Tracks item attributes */ /* * Information used when displaying widget: @@ -62,18 +63,18 @@ typedef struct { * window, plus used for background. */ int borderWidth; /* Width of 3-D border around window. */ int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ XColor *highlightBgColorPtr; - /* Color for drawing traversal highlight - * area when highlight is off. */ + /* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. - * Indicates how much interior stuff must - * be offset from outside edges to leave - * room for borders. */ + * Indicates how much interior stuff must be + * offset from outside edges to leave room for + * borders. */ Tk_Font tkfont; /* Information about text font, or NULL. */ XColor *fgColorPtr; /* Text color in normal mode. */ XColor *dfgColorPtr; /* Text color in disabled mode. */ @@ -85,20 +86,20 @@ typedef struct { GC selTextGC; /* For drawing selected text. */ int width; /* Desired width of window, in characters. */ int height; /* Desired height of window, in lines. */ - int lineHeight; /* Number of pixels allocated for each line - * in display. */ + int lineHeight; /* Number of pixels allocated for each line in + * display. */ int topIndex; /* Index of top-most element visible in * window. */ int fullLines; /* Number of lines that fit are completely - * visible in window. There may be one + * visible in window. There may be one * additional line at the bottom that is * partially visible. */ int partialLine; /* 0 means that the window holds exactly - * fullLines lines. 1 means that there is - * one additional line that is partially + * fullLines lines. 1 means that there is one + * additional line that is partially * visble. */ - int setGrid; /* Non-zero means pass gridding information - * to window manager. */ + int setGrid; /* Non-zero means pass gridding information to + * window manager. */ /* * Information to support horizontal scrolling: @@ -110,26 +111,26 @@ typedef struct { * horizontal scrolling (window scrolls * horizontally in increments of this size). * This is an average character size. */ - int xOffset; /* The left edge of each string in the - * listbox is offset to the left by this - * many pixels (0 means no offset, positive - * means there is an offset). */ + int xOffset; /* The left edge of each string in the listbox + * is offset to the left by this many pixels + * (0 means no offset, positive means there is + * an offset). */ /* * Information about what's selected or active, if any. */ Tk_Uid selectMode; /* Selection style: single, browse, multiple, - * or extended. This value isn't used in C + * or extended. This value isn't used in C * code, but the Tcl bindings use it. */ int numSelected; /* Number of elements currently selected. */ - int selectAnchor; /* Fixed end of selection (i.e. element - * at which selection was started.) */ - int exportSelection; /* Non-zero means tie internal listbox - * to X selection. */ - int active; /* Index of "active" element (the one that - * has been selected by keyboard traversal). - * -1 means none. */ + int selectAnchor; /* Fixed end of selection (i.e. element at + * which selection was started.) */ + int exportSelection; /* Non-zero means tie internal listbox to X + * selection. */ + int active; /* Index of "active" element (the one that has + * been selected by keyboard traversal). -1 + * means none. */ int activeStyle; /* style in which to draw the active element. * One of: underline, none, dotbox */ @@ -151,18 +152,18 @@ typedef struct { */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ char *yScrollCmd; /* Command prefix for communicating with - * vertical scrollbar. NULL means no command - * to issue. Malloc'ed. */ + * vertical scrollbar. NULL means no command + * to issue. Malloc'ed. */ char *xScrollCmd; /* Command prefix for communicating with - * horizontal scrollbar. NULL means no command - * to issue. Malloc'ed. */ + * horizontal scrollbar. NULL means no command + * to issue. Malloc'ed. */ int state; /* Listbox state. */ Pixmap gray; /* Pixmap for displaying disabled text. */ - int flags; /* Various flag bits: see below for + int flags; /* Various flag bits: see below for * definitions. */ } Listbox; @@ -170,26 +171,26 @@ typedef struct { * ItemAttr structures are used to store item configuration information for * the items in a listbox */ + typedef struct { Tk_3DBorder border; /* Used for drawing background around text */ Tk_3DBorder selBorder; /* Used for selected text */ XColor *fgColor; /* Text color in normal mode. */ XColor *selFgColor; /* Text color in selected mode. */ -} ItemAttr; +} ItemAttr; /* * Flag bits for listboxes: * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler - * has already been queued to redraw - * this window. - * UPDATE_V_SCROLLBAR: Non-zero means vertical scrollbar needs - * to be updated. - * UPDATE_H_SCROLLBAR: Non-zero means horizontal scrollbar needs - * to be updated. - * GOT_FOCUS: Non-zero means this widget currently - * has the input focus. - * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has + * already been queued to redraw this window. + * UPDATE_V_SCROLLBAR: Non-zero means vertical scrollbar needs to be + * updated. + * UPDATE_H_SCROLLBAR: Non-zero means horizontal scrollbar needs to + * be updated. + * GOT_FOCUS: Non-zero means this widget currently has the + * input focus. + * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date * LISTBOX_DELETED: This listbox has been effectively destroyed. */ @@ -201,9 +202,9 @@ typedef struct { #define LISTBOX_DELETED 32 /* - * The following enum is used to define a type for the -state option - * of the Entry widget. These values are used as indices into the - * string table below. + * The following enum is used to define a type for the -state option of the + * Listbox widget. These values are used as indices into the string table + * below. */ enum state { @@ -211,7 +212,7 @@ enum state { }; static char *stateStrings[] = { - "disabled", "normal", (char *) NULL + "disabled", "normal", NULL }; enum activeStyle { @@ -219,24 +220,25 @@ enum activeStyle { }; static char *activeStyleStrings[] = { - "dotbox", "none", "underline", (char *) NULL + "dotbox", "none", "underline", NULL }; /* * The optionSpecs table defines the valid configuration options for the - * listbox widget + * listbox widget. */ -static Tk_OptionSpec optionSpecs[] = { + +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING_TABLE, "-activestyle", "activeStyle", "ActiveStyle", DEF_LISTBOX_ACTIVE_STYLE, -1, Tk_Offset(Listbox, activeStyle), - 0, (ClientData) activeStyleStrings, 0}, + 0, (ClientData) activeStyleStrings, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", DEF_LISTBOX_BG_COLOR, -1, Tk_Offset(Listbox, normalBorder), 0, (ClientData) DEF_LISTBOX_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_LISTBOX_BORDER_WIDTH, -1, Tk_Offset(Listbox, borderWidth), 0, 0, 0}, @@ -249,8 +251,8 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, -1, Tk_Offset(Listbox, exportSelection), 0, 0, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_LISTBOX_FONT, -1, Tk_Offset(Listbox, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", @@ -258,7 +260,7 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_INT, "-height", "height", "Height", DEF_LISTBOX_HEIGHT, -1, Tk_Offset(Listbox, height), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", - "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1, + "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1, Tk_Offset(Listbox, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(Listbox, highlightColorPtr), @@ -283,8 +285,8 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid", DEF_LISTBOX_SET_GRID, -1, Tk_Offset(Listbox, setGrid), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_LISTBOX_STATE, -1, Tk_Offset(Listbox, state), - 0, (ClientData) stateStrings, 0}, + DEF_LISTBOX_STATE, -1, Tk_Offset(Listbox, state), + 0, (ClientData) stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(Listbox, takeFocus), TK_OPTION_NULL_OK, 0, 0}, @@ -299,50 +301,48 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_STRING, "-listvariable", "listVariable", "Variable", DEF_LISTBOX_LIST_VARIABLE, -1, Tk_Offset(Listbox, listVarName), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* * The itemAttrOptionSpecs table defines the valid configuration options for * listbox items */ -static Tk_OptionSpec itemAttrOptionSpecs[] = { + +static const Tk_OptionSpec itemAttrOptionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", - (char *)NULL, -1, Tk_Offset(ItemAttr, border), + NULL, -1, Tk_Offset(ItemAttr, border), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, (ClientData) DEF_LISTBOX_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - (char *) NULL, -1, Tk_Offset(ItemAttr, fgColor), + NULL, -1, Tk_Offset(ItemAttr, fgColor), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0}, {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", - (char *) NULL, -1, Tk_Offset(ItemAttr, selBorder), + NULL, -1, Tk_Offset(ItemAttr, selBorder), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, (ClientData) DEF_LISTBOX_SELECT_MONO, 0}, {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", - (char *) NULL, -1, Tk_Offset(ItemAttr, selFgColor), + NULL, -1, Tk_Offset(ItemAttr, selFgColor), TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, (ClientData) DEF_LISTBOX_SELECT_FG_MONO, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* - * The following tables define the listbox widget commands (and sub- - * commands) and map the indexes into the string tables into - * enumerated types used to dispatch the listbox widget command. + * The following tables define the listbox widget commands (and sub- commands) + * and map the indexes into the string tables into enumerated types used to + * dispatch the listbox widget command. */ -static CONST char *commandNames[] = { + +static const char *commandNames[] = { "activate", "bbox", "cget", "configure", "curselection", "delete", "get", "index", "insert", "itemcget", "itemconfigure", "nearest", "scan", - "see", "selection", "size", "xview", "yview", - (char *) NULL + "see", "selection", "size", "xview", "yview", NULL }; - enum command { COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CURSELECTION, COMMAND_DELETE, COMMAND_GET, COMMAND_INDEX, @@ -351,99 +351,84 @@ enum command { COMMAND_SIZE, COMMAND_XVIEW, COMMAND_YVIEW }; -static CONST char *selCommandNames[] = { - "anchor", "clear", "includes", "set", (char *) NULL +static const char *selCommandNames[] = { + "anchor", "clear", "includes", "set", NULL }; - enum selcommand { SELECTION_ANCHOR, SELECTION_CLEAR, SELECTION_INCLUDES, SELECTION_SET }; -static CONST char *scanCommandNames[] = { - "mark", "dragto", (char *) NULL +static const char *scanCommandNames[] = { + "mark", "dragto", NULL }; - enum scancommand { SCAN_MARK, SCAN_DRAGTO }; -static CONST char *indexNames[] = { - "active", "anchor", "end", (char *)NULL +static const char *indexNames[] = { + "active", "anchor", "end", NULL }; - enum indices { INDEX_ACTIVE, INDEX_ANCHOR, INDEX_END }; +/* + * Declarations for procedures defined later in this file. + */ -/* Declarations for procedures defined later in this file */ -static void ChangeListboxOffset _ANSI_ARGS_((Listbox *listPtr, - int offset)); -static void ChangeListboxView _ANSI_ARGS_((Listbox *listPtr, - int index)); -static int ConfigureListbox _ANSI_ARGS_((Tcl_Interp *interp, - Listbox *listPtr, int objc, Tcl_Obj *CONST objv[], - int flags)); -static int ConfigureListboxItem _ANSI_ARGS_ ((Tcl_Interp *interp, +static void ChangeListboxOffset(Listbox *listPtr, int offset); +static void ChangeListboxView(Listbox *listPtr, int index); +static int ConfigureListbox(Tcl_Interp *interp, Listbox *listPtr, + int objc, Tcl_Obj *const objv[], int flags); +static int ConfigureListboxItem(Tcl_Interp *interp, Listbox *listPtr, ItemAttr *attrs, int objc, - Tcl_Obj *CONST objv[], int index)); -static int ListboxDeleteSubCmd _ANSI_ARGS_((Listbox *listPtr, - int first, int last)); -static void DestroyListbox _ANSI_ARGS_((char *memPtr)); -static void DestroyListboxOptionTables _ANSI_ARGS_ ( - (ClientData clientData, Tcl_Interp *interp)); -static void DisplayListbox _ANSI_ARGS_((ClientData clientData)); -static int GetListboxIndex _ANSI_ARGS_((Tcl_Interp *interp, - Listbox *listPtr, Tcl_Obj *index, int endIsSize, - int *indexPtr)); -static int ListboxInsertSubCmd _ANSI_ARGS_((Listbox *listPtr, - int index, int objc, Tcl_Obj *CONST objv[])); -static void ListboxCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void ListboxComputeGeometry _ANSI_ARGS_((Listbox *listPtr, - int fontChanged, int maxIsStale, int updateGrid)); -static void ListboxEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int ListboxFetchSelection _ANSI_ARGS_(( - ClientData clientData, int offset, char *buffer, - int maxBytes)); -static void ListboxLostSelection _ANSI_ARGS_(( - ClientData clientData)); -static void EventuallyRedrawRange _ANSI_ARGS_((Listbox *listPtr, - int first, int last)); -static void ListboxScanTo _ANSI_ARGS_((Listbox *listPtr, - int x, int y)); -static int ListboxSelect _ANSI_ARGS_((Listbox *listPtr, - int first, int last, int select)); -static void ListboxUpdateHScrollbar _ANSI_ARGS_( - (Listbox *listPtr)); -static void ListboxUpdateVScrollbar _ANSI_ARGS_( - (Listbox *listPtr)); -static int ListboxWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static int ListboxBboxSubCmd _ANSI_ARGS_ ((Tcl_Interp *interp, - Listbox *listPtr, int index)); -static int ListboxSelectionSubCmd _ANSI_ARGS_ ( - (Tcl_Interp *interp, Listbox *listPtr, int objc, - Tcl_Obj *CONST objv[])); -static int ListboxXviewSubCmd _ANSI_ARGS_ ((Tcl_Interp *interp, - Listbox *listPtr, int objc, - Tcl_Obj *CONST objv[])); -static int ListboxYviewSubCmd _ANSI_ARGS_ ((Tcl_Interp *interp, - Listbox *listPtr, int objc, - Tcl_Obj *CONST objv[])); -static ItemAttr * ListboxGetItemAttributes _ANSI_ARGS_ ( - (Tcl_Interp *interp, Listbox *listPtr, int index)); -static void ListboxWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static int NearestListboxElement _ANSI_ARGS_((Listbox *listPtr, - int y)); -static char * ListboxListVarProc _ANSI_ARGS_ ((ClientData clientData, - Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static void MigrateHashEntries _ANSI_ARGS_ ((Tcl_HashTable *table, - int first, int last, int offset)); + Tcl_Obj *const objv[], int index); +static int ListboxDeleteSubCmd(Listbox *listPtr, + int first, int last); +static void DestroyListbox(char *memPtr); +static void DestroyListboxOptionTables(ClientData clientData, + Tcl_Interp *interp); +static void DisplayListbox(ClientData clientData); +static int GetListboxIndex(Tcl_Interp *interp, Listbox *listPtr, + Tcl_Obj *index, int endIsSize, int *indexPtr); +static int ListboxInsertSubCmd(Listbox *listPtr, + int index, int objc, Tcl_Obj *const objv[]); +static void ListboxCmdDeletedProc(ClientData clientData); +static void ListboxComputeGeometry(Listbox *listPtr, + int fontChanged, int maxIsStale, int updateGrid); +static void ListboxEventProc(ClientData clientData, + XEvent *eventPtr); +static int ListboxFetchSelection(ClientData clientData, + int offset, char *buffer, int maxBytes); +static void ListboxLostSelection(ClientData clientData); +static void EventuallyRedrawRange(Listbox *listPtr, + int first, int last); +static void ListboxScanTo(Listbox *listPtr, int x, int y); +static int ListboxSelect(Listbox *listPtr, + int first, int last, int select); +static void ListboxUpdateHScrollbar(Listbox *listPtr); +static void ListboxUpdateVScrollbar(Listbox *listPtr); +static int ListboxWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int ListboxBboxSubCmd(Tcl_Interp *interp, + Listbox *listPtr, int index); +static int ListboxSelectionSubCmd(Tcl_Interp *interp, + Listbox *listPtr, int objc, Tcl_Obj *const objv[]); +static int ListboxXviewSubCmd(Tcl_Interp *interp, + Listbox *listPtr, int objc, Tcl_Obj *const objv[]); +static int ListboxYviewSubCmd(Tcl_Interp *interp, + Listbox *listPtr, int objc, Tcl_Obj *const objv[]); +static ItemAttr * ListboxGetItemAttributes(Tcl_Interp *interp, + Listbox *listPtr, int index); +static void ListboxWorldChanged(ClientData instanceData); +static int NearestListboxElement(Listbox *listPtr, int y); +static char * ListboxListVarProc(ClientData clientData, + Tcl_Interp *interp, const char *name1, + const char *name2, int flags); +static void MigrateHashEntries(Tcl_HashTable *table, + int first, int last, int offset); + /* * The structure below defines button class behavior by means of procedures * that can be invoked from generic window code. @@ -452,17 +437,17 @@ static void MigrateHashEntries _ANSI_ARGS_ ((Tcl_HashTable *table, static Tk_ClassProcs listboxClass = { sizeof(Tk_ClassProcs), /* size */ ListboxWorldChanged, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ }; - /* *-------------------------------------------------------------- * * Tk_ListboxObjCmd -- * - * This procedure is invoked to process the "listbox" Tcl - * command. See the user documentation for details on what - * it does. + * This procedure is invoked to process the "listbox" Tcl command. See + * the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -474,11 +459,11 @@ static Tk_ClassProcs listboxClass = { */ int -Tk_ListboxObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_ListboxObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { register Listbox *listPtr; Tk_Window tkwin; @@ -490,7 +475,7 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } @@ -499,56 +484,64 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) Tcl_GetAssocData(interp, "ListboxOptionTables", NULL); if (optionTables == NULL) { /* - * We haven't created the option tables for this widget class yet. - * Do it now and save the a pointer to them as the ClientData for - * the command, so future invocations will have access to it. + * We haven't created the option tables for this widget class yet. Do + * it now and save the a pointer to them as the ClientData for the + * command, so future invocations will have access to it. */ optionTables = (ListboxOptionTables *) - ckalloc(sizeof(ListboxOptionTables)); - /* Set up an exit handler to free the optionTables struct */ + ckalloc(sizeof(ListboxOptionTables)); + + /* + * Set up an exit handler to free the optionTables struct. + */ + Tcl_SetAssocData(interp, "ListboxOptionTables", DestroyListboxOptionTables, (ClientData) optionTables); - /* Create the listbox option table and the listbox item option table */ + /* + * Create the listbox option table and the listbox item option table. + */ + optionTables->listboxOptionTable = - Tk_CreateOptionTable(interp, optionSpecs); + Tk_CreateOptionTable(interp, optionSpecs); optionTables->itemAttrOptionTable = - Tk_CreateOptionTable(interp, itemAttrOptionSpecs); + Tk_CreateOptionTable(interp, itemAttrOptionSpecs); } /* - * Initialize the fields of the structure that won't be initialized - * by ConfigureListbox, or that ConfigureListbox requires to be - * initialized already (e.g. resource pointers). + * Initialize the fields of the structure that won't be initialized by + * ConfigureListbox, or that ConfigureListbox requires to be initialized + * already (e.g. resource pointers). */ - listPtr = (Listbox *) ckalloc(sizeof(Listbox)); - memset((void *) listPtr, 0, (sizeof(Listbox))); - listPtr->tkwin = tkwin; - listPtr->display = Tk_Display(tkwin); - listPtr->interp = interp; - listPtr->widgetCmd = Tcl_CreateObjCommand(interp, + listPtr = (Listbox *) ckalloc(sizeof(Listbox)); + memset(listPtr, 0, (sizeof(Listbox))); + + listPtr->tkwin = tkwin; + listPtr->display = Tk_Display(tkwin); + listPtr->interp = interp; + listPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(listPtr->tkwin), ListboxWidgetObjCmd, (ClientData) listPtr, ListboxCmdDeletedProc); - listPtr->optionTable = optionTables->listboxOptionTable; - listPtr->itemAttrOptionTable = optionTables->itemAttrOptionTable; - listPtr->selection = - (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + listPtr->optionTable = optionTables->listboxOptionTable; + listPtr->itemAttrOptionTable = optionTables->itemAttrOptionTable; + listPtr->selection = (Tcl_HashTable *) + ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(listPtr->selection, TCL_ONE_WORD_KEYS); - listPtr->itemAttrTable = - (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); + listPtr->itemAttrTable = (Tcl_HashTable *) + ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS); - listPtr->relief = TK_RELIEF_RAISED; - listPtr->textGC = None; - listPtr->selFgColorPtr = None; - listPtr->selTextGC = None; - listPtr->fullLines = 1; - listPtr->xScrollUnit = 1; - listPtr->exportSelection = 1; - listPtr->cursor = None; - listPtr->state = STATE_NORMAL; - listPtr->gray = None; + listPtr->relief = TK_RELIEF_RAISED; + listPtr->textGC = None; + listPtr->selFgColorPtr = None; + listPtr->selTextGC = None; + listPtr->fullLines = 1; + listPtr->xScrollUnit = 1; + listPtr->exportSelection = 1; + listPtr->cursor = None; + listPtr->state = STATE_NORMAL; + listPtr->gray = None; /* * Keep a hold of the associated tkwin until we destroy the listbox, @@ -585,8 +578,8 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) * ListboxWidgetObjCmd -- * * This Tcl_Obj based procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. See the user - * documentation for details on what it does. + * that corresponds to a widget managed by this module. See the user + * documentation for details on what it does. * * Results: * A standard Tcl result. @@ -598,25 +591,26 @@ Tk_ListboxObjCmd(clientData, interp, objc, objv) */ static int -ListboxWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about listbox widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Arguments as Tcl_Obj's. */ +ListboxWidgetObjCmd( + ClientData clientData, /* Information about listbox widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Arguments as Tcl_Obj's. */ { register Listbox *listPtr = (Listbox *) clientData; int cmdIndex, index; int result = TCL_OK; - + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } /* - * Parse the command by looking up the second argument in the list - * of valid subcommand names + * Parse the command by looking up the second argument in the list of + * valid subcommand names */ + result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, "option", 0, &cmdIndex); if (result != TCL_OK) { @@ -624,448 +618,436 @@ ListboxWidgetObjCmd(clientData, interp, objc, objv) } Tcl_Preserve((ClientData)listPtr); - /* The subcommand was valid, so continue processing */ - switch (cmdIndex) { - case COMMAND_ACTIVATE: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "index"); - result = TCL_ERROR; - break; - } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); - if (result != TCL_OK) { - break; - } - if (!(listPtr->state & STATE_NORMAL)) { - break; - } + /* + * The subcommand was valid, so continue processing. + */ - if (index >= listPtr->nElements) { - index = listPtr->nElements-1; - } - if (index < 0) { - index = 0; - } - listPtr->active = index; - EventuallyRedrawRange(listPtr, listPtr->active, listPtr->active); - result = TCL_OK; + switch (cmdIndex) { + case COMMAND_ACTIVATE: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + result = TCL_ERROR; + break; + } + result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); + if (result != TCL_OK) { break; } - case COMMAND_BBOX: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "index"); - result = TCL_ERROR; - break; - } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); - if (result != TCL_OK) { - break; - } - - result = ListboxBboxSubCmd(interp, listPtr, index); + if (!(listPtr->state & STATE_NORMAL)) { break; } - case COMMAND_CGET: { - Tcl_Obj *objPtr; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); - result = TCL_ERROR; - break; - } + if (index >= listPtr->nElements) { + index = listPtr->nElements-1; + } + if (index < 0) { + index = 0; + } + listPtr->active = index; + EventuallyRedrawRange(listPtr, listPtr->active, listPtr->active); + result = TCL_OK; + break; - objPtr = Tk_GetOptionValue(interp, (char *)listPtr, - listPtr->optionTable, objv[2], listPtr->tkwin); - if (objPtr == NULL) { - result = TCL_ERROR; - break; - } - Tcl_SetObjResult(interp, objPtr); - result = TCL_OK; + case COMMAND_BBOX: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + result = TCL_ERROR; break; } - - case COMMAND_CONFIGURE: { - Tcl_Obj *objPtr; - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) listPtr, - listPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - listPtr->tkwin); - if (objPtr == NULL) { - result = TCL_ERROR; - break; - } else { - Tcl_SetObjResult(interp, objPtr); - result = TCL_OK; - } - } else { - result = ConfigureListbox(interp, listPtr, objc-2, objv+2, 0); - } + result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); + if (result != TCL_OK) { break; } - case COMMAND_CURSELECTION: { - char indexStringRep[TCL_INTEGER_SPACE]; - int i; - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - result = TCL_ERROR; - break; - } - /* - * Of course, it would be more efficient to use the Tcl_HashTable - * search functions (Tcl_FirstHashEntry, Tcl_NextHashEntry), but - * then the result wouldn't be in sorted order. So instead we - * loop through the indices in order, adding them to the result - * if they are selected - */ - for (i = 0; i < listPtr->nElements; i++) { - if (Tcl_FindHashEntry(listPtr->selection, (char *)i) != NULL) { - sprintf(indexStringRep, "%d", i); - Tcl_AppendElement(interp, indexStringRep); - } - } - result = TCL_OK; + result = ListboxBboxSubCmd(interp, listPtr, index); + break; + + case COMMAND_CGET: { + Tcl_Obj *objPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + result = TCL_ERROR; break; } - - case COMMAND_DELETE: { - int first, last; - if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, - "firstIndex ?lastIndex?"); - result = TCL_ERROR; - break; - } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &first); - if (result != TCL_OK) { - break; - } + objPtr = Tk_GetOptionValue(interp, (char *) listPtr, + listPtr->optionTable, objv[2], listPtr->tkwin); + if (objPtr == NULL) { + result = TCL_ERROR; + break; + } + Tcl_SetObjResult(interp, objPtr); + result = TCL_OK; + break; + } - if (!(listPtr->state & STATE_NORMAL)) { - break; - } + case COMMAND_CONFIGURE: { + Tcl_Obj *objPtr; - if (first < listPtr->nElements) { - /* - * if a "last index" was given, get it now; otherwise, use the - * first index as the last index - */ - if (objc == 4) { - result = GetListboxIndex(interp, listPtr, - objv[3], 0, &last); - if (result != TCL_OK) { - break; - } - } else { - last = first; - } - if (last >= listPtr->nElements) { - last = listPtr->nElements - 1; - } - result = ListboxDeleteSubCmd(listPtr, first, last); + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) listPtr, + listPtr->optionTable, + (objc == 3) ? objv[2] : NULL, listPtr->tkwin); + if (objPtr == NULL) { + result = TCL_ERROR; + break; } else { + Tcl_SetObjResult(interp, objPtr); result = TCL_OK; } + } else { + result = ConfigureListbox(interp, listPtr, objc-2, objv+2, 0); + } + break; + } + + case COMMAND_CURSELECTION: { + char indexStringRep[TCL_INTEGER_SPACE]; + int i; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + result = TCL_ERROR; break; } - case COMMAND_GET: { - int first, last; - Tcl_Obj **elemPtrs; - int listLen; - if (objc != 3 && objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); - result = TCL_ERROR; - break; - } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &first); - if (result != TCL_OK) { - break; + /* + * Of course, it would be more efficient to use the Tcl_HashTable + * search functions (Tcl_FirstHashEntry, Tcl_NextHashEntry), but then + * the result wouldn't be in sorted order. So instead we loop through + * the indices in order, adding them to the result if they are + * selected. + */ + + for (i = 0; i < listPtr->nElements; i++) { + if (Tcl_FindHashEntry(listPtr->selection, (char *) INT2PTR(i))) { + sprintf(indexStringRep, "%d", i); + Tcl_AppendElement(interp, indexStringRep); } - last = first; + } + result = TCL_OK; + break; + } + + case COMMAND_DELETE: { + int first, last; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); + result = TCL_ERROR; + break; + } + + result = GetListboxIndex(interp, listPtr, objv[2], 0, &first); + if (result != TCL_OK) { + break; + } + + if (!(listPtr->state & STATE_NORMAL)) { + break; + } + + if (first < listPtr->nElements) { + /* + * if a "last index" was given, get it now; otherwise, use the + * first index as the last index. + */ + if (objc == 4) { result = GetListboxIndex(interp, listPtr, objv[3], 0, &last); if (result != TCL_OK) { break; } - } - if (first >= listPtr->nElements) { - result = TCL_OK; - break; + } else { + last = first; } if (last >= listPtr->nElements) { last = listPtr->nElements - 1; } - if (first < 0) { - first = 0; - } - if (first > last) { - result = TCL_OK; - break; - } - result = Tcl_ListObjGetElements(interp, listPtr->listObj, &listLen, - &elemPtrs); - if (result != TCL_OK) { - break; - } - if (objc == 3) { - /* - * One element request - we return a string - */ - Tcl_SetObjResult(interp, elemPtrs[first]); - } else { - Tcl_SetListObj(Tcl_GetObjResult(interp), (last - first + 1), - &(elemPtrs[first])); - } + result = ListboxDeleteSubCmd(listPtr, first, last); + } else { result = TCL_OK; - break; } + break; + } - case COMMAND_INDEX:{ - char buf[TCL_INTEGER_SPACE]; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "index"); - result = TCL_ERROR; - break; - } - result = GetListboxIndex(interp, listPtr, objv[2], 1, &index); + case COMMAND_GET: { + int first, last, listLen; + Tcl_Obj **elemPtrs; + + if (objc != 3 && objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); + result = TCL_ERROR; + break; + } + result = GetListboxIndex(interp, listPtr, objv[2], 0, &first); + if (result != TCL_OK) { + break; + } + last = first; + if (objc == 4) { + result = GetListboxIndex(interp, listPtr, objv[3], 0, &last); if (result != TCL_OK) { break; } - sprintf(buf, "%d", index); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + if (first >= listPtr->nElements) { + result = TCL_OK; + break; + } + if (last >= listPtr->nElements) { + last = listPtr->nElements - 1; + } + if (first < 0) { + first = 0; + } + if (first > last) { result = TCL_OK; break; } + result = Tcl_ListObjGetElements(interp, listPtr->listObj, &listLen, + &elemPtrs); + if (result != TCL_OK) { + break; + } + if (objc == 3) { + /* + * One element request - we return a string + */ - case COMMAND_INSERT: { - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, - "index ?element element ...?"); - result = TCL_ERROR; - break; - } + Tcl_SetObjResult(interp, elemPtrs[first]); + } else { + Tcl_SetListObj(Tcl_GetObjResult(interp), (last - first + 1), + &(elemPtrs[first])); + } + result = TCL_OK; + break; + } - result = GetListboxIndex(interp, listPtr, objv[2], 1, &index); - if (result != TCL_OK) { - break; - } + case COMMAND_INDEX: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + result = TCL_ERROR; + break; + } + result = GetListboxIndex(interp, listPtr, objv[2], 1, &index); + if (result != TCL_OK) { + break; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + result = TCL_OK; + break; - if (!(listPtr->state & STATE_NORMAL)) { - break; - } + case COMMAND_INSERT: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index ?element element ...?"); + result = TCL_ERROR; + break; + } - result = ListboxInsertSubCmd(listPtr, index, objc-3, objv+3); + result = GetListboxIndex(interp, listPtr, objv[2], 1, &index); + if (result != TCL_OK) { break; } - case COMMAND_ITEMCGET: { - Tcl_Obj *objPtr; - ItemAttr *attrPtr; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "index option"); - result = TCL_ERROR; - break; - } + if (!(listPtr->state & STATE_NORMAL)) { + break; + } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); - if (result != TCL_OK) { - break; - } + result = ListboxInsertSubCmd(listPtr, index, objc-3, objv+3); + break; - if (index < 0 || index >= listPtr->nElements) { - Tcl_AppendResult(interp, "item number \"", - Tcl_GetString(objv[2]), "\" out of range", - (char *)NULL); - result = TCL_ERROR; - break; - } - - attrPtr = ListboxGetItemAttributes(interp, listPtr, index); + case COMMAND_ITEMCGET: { + Tcl_Obj *objPtr; + ItemAttr *attrPtr; - objPtr = Tk_GetOptionValue(interp, (char *)attrPtr, - listPtr->itemAttrOptionTable, objv[3], listPtr->tkwin); - if (objPtr == NULL) { - result = TCL_ERROR; - break; - } - Tcl_SetObjResult(interp, objPtr); - result = TCL_OK; + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "index option"); + result = TCL_ERROR; break; } - case COMMAND_ITEMCONFIGURE: { - Tcl_Obj *objPtr; - ItemAttr *attrPtr; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, - "index ?option? ?value? ?option value ...?"); - result = TCL_ERROR; - break; - } + result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); + if (result != TCL_OK) { + break; + } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); - if (result != TCL_OK) { - break; - } - - if (index < 0 || index >= listPtr->nElements) { - Tcl_AppendResult(interp, "item number \"", - Tcl_GetString(objv[2]), "\" out of range", - (char *)NULL); - result = TCL_ERROR; - break; - } - - attrPtr = ListboxGetItemAttributes(interp, listPtr, index); - if (objc <= 4) { - objPtr = Tk_GetOptionInfo(interp, (char *)attrPtr, - listPtr->itemAttrOptionTable, - (objc == 4) ? objv[3] : (Tcl_Obj *) NULL, - listPtr->tkwin); - if (objPtr == NULL) { - result = TCL_ERROR; - break; - } else { - Tcl_SetObjResult(interp, objPtr); - result = TCL_OK; - } - } else { - result = ConfigureListboxItem(interp, listPtr, attrPtr, - objc-3, objv+3, index); - } + if (index < 0 || index >= listPtr->nElements) { + Tcl_AppendResult(interp, "item number \"", + Tcl_GetString(objv[2]), "\" out of range", NULL); + result = TCL_ERROR; break; } - - case COMMAND_NEAREST: { - char buf[TCL_INTEGER_SPACE]; - int y; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "y"); - result = TCL_ERROR; - break; - } - - result = Tcl_GetIntFromObj(interp, objv[2], &y); - if (result != TCL_OK) { - break; - } - index = NearestListboxElement(listPtr, y); - sprintf(buf, "%d", index); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - result = TCL_OK; + + attrPtr = ListboxGetItemAttributes(interp, listPtr, index); + + objPtr = Tk_GetOptionValue(interp, (char *) attrPtr, + listPtr->itemAttrOptionTable, objv[3], listPtr->tkwin); + if (objPtr == NULL) { + result = TCL_ERROR; break; } - - case COMMAND_SCAN: { - int x, y, scanCmdIndex; + Tcl_SetObjResult(interp, objPtr); + result = TCL_OK; + break; + } - if (objc != 5) { - Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y"); - result = TCL_ERROR; - break; - } + case COMMAND_ITEMCONFIGURE: { + Tcl_Obj *objPtr; + ItemAttr *attrPtr; - if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK - || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) { - result = TCL_ERROR; - break; - } + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "index ?option? ?value? ?option value ...?"); + result = TCL_ERROR; + break; + } - result = Tcl_GetIndexFromObj(interp, objv[2], scanCommandNames, - "option", 0, &scanCmdIndex); - if (result != TCL_OK) { - break; - } - switch (scanCmdIndex) { - case SCAN_MARK: { - listPtr->scanMarkX = x; - listPtr->scanMarkY = y; - listPtr->scanMarkXOffset = listPtr->xOffset; - listPtr->scanMarkYIndex = listPtr->topIndex; - break; - } - case SCAN_DRAGTO: { - ListboxScanTo(listPtr, x, y); - break; - } - } - result = TCL_OK; + result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); + if (result != TCL_OK) { + break; + } + + if (index < 0 || index >= listPtr->nElements) { + Tcl_AppendResult(interp, "item number \"", Tcl_GetString(objv[2]), + "\" out of range", NULL); + result = TCL_ERROR; break; } - case COMMAND_SEE: { - int diff; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "index"); + attrPtr = ListboxGetItemAttributes(interp, listPtr, index); + if (objc <= 4) { + objPtr = Tk_GetOptionInfo(interp, (char *) attrPtr, + listPtr->itemAttrOptionTable, + (objc == 4) ? objv[3] : NULL, listPtr->tkwin); + if (objPtr == NULL) { result = TCL_ERROR; break; - } - result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); - if (result != TCL_OK) { - break; - } - if (index >= listPtr->nElements) { - index = listPtr->nElements - 1; - } - if (index < 0) { - index = 0; - } - diff = listPtr->topIndex - index; - if (diff > 0) { - if (diff <= (listPtr->fullLines/3)) { - ChangeListboxView(listPtr, index); - } else { - ChangeListboxView(listPtr, - index - (listPtr->fullLines-1)/2); - } } else { - diff = index - (listPtr->topIndex + listPtr->fullLines - 1); - if (diff > 0) { - if (diff <= (listPtr->fullLines/3)) { - ChangeListboxView(listPtr, listPtr->topIndex + diff); - } else { - ChangeListboxView(listPtr, - index - (listPtr->fullLines-1)/2); - } - } + Tcl_SetObjResult(interp, objPtr); + result = TCL_OK; } - result = TCL_OK; + } else { + result = ConfigureListboxItem(interp, listPtr, attrPtr, + objc-3, objv+3, index); + } + break; + } + + case COMMAND_NEAREST: { + int y; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "y"); + result = TCL_ERROR; break; } - case COMMAND_SELECTION: { - result = ListboxSelectionSubCmd(interp, listPtr, objc, objv); + result = Tcl_GetIntFromObj(interp, objv[2], &y); + if (result != TCL_OK) { break; } + index = NearestListboxElement(listPtr, y); + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + result = TCL_OK; + break; + } - case COMMAND_SIZE: { - char buf[TCL_INTEGER_SPACE]; - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, NULL); - result = TCL_ERROR; - break; - } - sprintf(buf, "%d", listPtr->nElements); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - result = TCL_OK; + case COMMAND_SCAN: { + int x, y, scanCmdIndex; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y"); + result = TCL_ERROR; + break; + } + + if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) { + result = TCL_ERROR; + break; + } + + result = Tcl_GetIndexFromObj(interp, objv[2], scanCommandNames, + "option", 0, &scanCmdIndex); + if (result != TCL_OK) { break; } + switch (scanCmdIndex) { + case SCAN_MARK: + listPtr->scanMarkX = x; + listPtr->scanMarkY = y; + listPtr->scanMarkXOffset = listPtr->xOffset; + listPtr->scanMarkYIndex = listPtr->topIndex; + break; + case SCAN_DRAGTO: + ListboxScanTo(listPtr, x, y); + break; + } + result = TCL_OK; + break; + } - case COMMAND_XVIEW: { - result = ListboxXviewSubCmd(interp, listPtr, objc, objv); + case COMMAND_SEE: { + int diff; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + result = TCL_ERROR; + break; + } + result = GetListboxIndex(interp, listPtr, objv[2], 0, &index); + if (result != TCL_OK) { break; } - - case COMMAND_YVIEW: { - result = ListboxYviewSubCmd(interp, listPtr, objc, objv); + if (index >= listPtr->nElements) { + index = listPtr->nElements - 1; + } + if (index < 0) { + index = 0; + } + diff = listPtr->topIndex - index; + if (diff > 0) { + if (diff <= (listPtr->fullLines/3)) { + ChangeListboxView(listPtr, index); + } else { + ChangeListboxView(listPtr, index - (listPtr->fullLines-1)/2); + } + } else { + diff = index - (listPtr->topIndex + listPtr->fullLines - 1); + if (diff > 0) { + if (diff <= (listPtr->fullLines/3)) { + ChangeListboxView(listPtr, listPtr->topIndex + diff); + } else { + ChangeListboxView(listPtr, index-(listPtr->fullLines-1)/2); + } + } + } + result = TCL_OK; + break; + } + + case COMMAND_SELECTION: + result = ListboxSelectionSubCmd(interp, listPtr, objc, objv); + break; + case COMMAND_SIZE: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + result = TCL_ERROR; break; } + Tcl_SetObjResult(interp, Tcl_NewIntObj(listPtr->nElements)); + result = TCL_OK; + break; + case COMMAND_XVIEW: + result = ListboxXviewSubCmd(interp, listPtr, objc, objv); + break; + case COMMAND_YVIEW: + result = ListboxYviewSubCmd(interp, listPtr, objc, objv); + break; } Tcl_Release((ClientData)listPtr); return result; @@ -1076,34 +1058,41 @@ ListboxWidgetObjCmd(clientData, interp, objc, objv) * * ListboxBboxSubCmd -- * - * This procedure is invoked to process a listbox bbox request. - * See the user documentation for more information. + * This procedure is invoked to process a listbox bbox request. See the + * user documentation for more information. * * Results: * A standard Tcl result. * * Side effects: - * For valid indices, places the bbox of the requested element in - * the interpreter's result. + * For valid indices, places the bbox of the requested element in the + * interpreter's result. * *---------------------------------------------------------------------- */ static int -ListboxBboxSubCmd(interp, listPtr, index) - Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */ - Listbox *listPtr; /* Information about the listbox */ - int index; /* Index of the element to get bbox info on */ +ListboxBboxSubCmd( + Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */ + Listbox *listPtr, /* Information about the listbox */ + int index) /* Index of the element to get bbox info on */ { int lastVisibleIndex; - /* Determine the index of the last visible item in the listbox */ + + /* + * Determine the index of the last visible item in the listbox. + */ + lastVisibleIndex = listPtr->topIndex + listPtr->fullLines - + listPtr->partialLine; + + listPtr->partialLine; if (listPtr->nElements < lastVisibleIndex) { lastVisibleIndex = listPtr->nElements; } - /* Only allow bbox requests for indices that are visible */ + /* + * Only allow bbox requests for indices that are visible. + */ + if ((listPtr->topIndex <= index) && (index < lastVisibleIndex)) { char buf[TCL_INTEGER_SPACE * 4]; Tcl_Obj *el; @@ -1111,7 +1100,10 @@ ListboxBboxSubCmd(interp, listPtr, index) int pixelWidth, stringLen, x, y, result; Tk_FontMetrics fm; - /* Compute the pixel width of the requested element */ + /* + * Compute the pixel width of the requested element. + */ + result = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el); if (result != TCL_OK) { return result; @@ -1123,7 +1115,7 @@ ListboxBboxSubCmd(interp, listPtr, index) x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset; y = ((index - listPtr->topIndex)*listPtr->lineHeight) - + listPtr->inset + listPtr->selBorderWidth; + + listPtr->inset + listPtr->selBorderWidth; sprintf(buf, "%d %d %d %d", x, y, pixelWidth, fm.linespace); Tcl_SetResult(interp, buf, TCL_VOLATILE); } @@ -1135,8 +1127,8 @@ ListboxBboxSubCmd(interp, listPtr, index) * * ListboxSelectionSubCmd -- * - * This procedure is invoked to process the selection sub command - * for listbox widgets. + * This procedure is invoked to process the selection sub command for + * listbox widgets. * * Results: * Standard Tcl result. @@ -1148,14 +1140,15 @@ ListboxBboxSubCmd(interp, listPtr, index) */ static int -ListboxSelectionSubCmd(interp, listPtr, objc, objv) - Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */ - Listbox *listPtr; /* Information about the listbox */ - int objc; /* Number of arguments in the objv array */ - Tcl_Obj *CONST objv[]; /* Array of arguments to the procedure */ +ListboxSelectionSubCmd( + Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */ + Listbox *listPtr, /* Information about the listbox */ + int objc, /* Number of arguments in the objv array */ + Tcl_Obj *const objv[]) /* Array of arguments to the procedure */ { int selCmdIndex, first, last; int result = TCL_OK; + if (objc != 4 && objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "option index ?index?"); return TCL_ERROR; @@ -1187,40 +1180,36 @@ ListboxSelectionSubCmd(interp, listPtr, objc, objv) } switch (selCmdIndex) { - case SELECTION_ANCHOR: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - return TCL_ERROR; - } - if (first >= listPtr->nElements) { - first = listPtr->nElements - 1; - } - if (first < 0) { - first = 0; - } - listPtr->selectAnchor = first; - result = TCL_OK; - break; + case SELECTION_ANCHOR: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); + return TCL_ERROR; } - case SELECTION_CLEAR: { - result = ListboxSelect(listPtr, first, last, 0); - break; + if (first >= listPtr->nElements) { + first = listPtr->nElements - 1; } - case SELECTION_INCLUDES: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - return TCL_ERROR; - } - Tcl_SetObjResult(interp, - Tcl_NewBooleanObj((Tcl_FindHashEntry(listPtr->selection, - (char *)first) != NULL))); - result = TCL_OK; - break; + if (first < 0) { + first = 0; } - case SELECTION_SET: { - result = ListboxSelect(listPtr, first, last, 1); - break; + listPtr->selectAnchor = first; + result = TCL_OK; + break; + case SELECTION_CLEAR: + result = ListboxSelect(listPtr, first, last, 0); + break; + case SELECTION_INCLUDES: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); + return TCL_ERROR; } + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj((Tcl_FindHashEntry(listPtr->selection, + (char *) INT2PTR(first)) != NULL))); + result = TCL_OK; + break; + case SELECTION_SET: + result = ListboxSelect(listPtr, first, last, 1); + break; } return result; } @@ -1242,33 +1231,35 @@ ListboxSelectionSubCmd(interp, listPtr, objc, objv) */ static int -ListboxXviewSubCmd(interp, listPtr, objc, objv) - Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */ - Listbox *listPtr; /* Information about the listbox */ - int objc; /* Number of arguments in the objv array */ - Tcl_Obj *CONST objv[]; /* Array of arguments to the procedure */ +ListboxXviewSubCmd( + Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */ + Listbox *listPtr, /* Information about the listbox */ + int objc, /* Number of arguments in the objv array */ + Tcl_Obj *const objv[]) /* Array of arguments to the procedure */ { int index, count, type, windowWidth, windowUnits; int offset = 0; /* Initialized to stop gcc warnings. */ double fraction, fraction2; - + windowWidth = Tk_Width(listPtr->tkwin) - - 2*(listPtr->inset + listPtr->selBorderWidth); + - 2*(listPtr->inset + listPtr->selBorderWidth); if (objc == 2) { if (listPtr->maxWidth == 0) { - Tcl_SetResult(interp, "0 1", TCL_STATIC); + Tcl_SetResult(interp, "0.0 1.0", TCL_STATIC); } else { - char buf[TCL_DOUBLE_SPACE * 2]; - + char buf[TCL_DOUBLE_SPACE]; + fraction = listPtr->xOffset/((double) listPtr->maxWidth); fraction2 = (listPtr->xOffset + windowWidth) - /((double) listPtr->maxWidth); + / ((double) listPtr->maxWidth); if (fraction2 > 1.0) { fraction2 = 1.0; } - sprintf(buf, "%g %g", fraction, fraction2); + Tcl_PrintDouble(NULL, fraction, buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_PrintDouble(NULL, fraction2, buf); + Tcl_AppendResult(interp, " ", buf, NULL); } } else if (objc == 3) { if (Tcl_GetIntFromObj(interp, objv[2], &index) != TCL_OK) { @@ -1278,23 +1269,23 @@ ListboxXviewSubCmd(interp, listPtr, objc, objv) } else { type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { - case TK_SCROLL_ERROR: - return TCL_ERROR; - case TK_SCROLL_MOVETO: - offset = (int) (fraction*listPtr->maxWidth + 0.5); - break; - case TK_SCROLL_PAGES: - windowUnits = windowWidth/listPtr->xScrollUnit; - if (windowUnits > 2) { - offset = listPtr->xOffset + case TK_SCROLL_ERROR: + return TCL_ERROR; + case TK_SCROLL_MOVETO: + offset = (int) (fraction*listPtr->maxWidth + 0.5); + break; + case TK_SCROLL_PAGES: + windowUnits = windowWidth/listPtr->xScrollUnit; + if (windowUnits > 2) { + offset = listPtr->xOffset + count*listPtr->xScrollUnit*(windowUnits-2); - } else { - offset = listPtr->xOffset + count*listPtr->xScrollUnit; - } - break; - case TK_SCROLL_UNITS: + } else { offset = listPtr->xOffset + count*listPtr->xScrollUnit; - break; + } + break; + case TK_SCROLL_UNITS: + offset = listPtr->xOffset + count*listPtr->xScrollUnit; + break; } ChangeListboxOffset(listPtr, offset); } @@ -1318,29 +1309,31 @@ ListboxXviewSubCmd(interp, listPtr, objc, objv) */ static int -ListboxYviewSubCmd(interp, listPtr, objc, objv) - Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */ - Listbox *listPtr; /* Information about the listbox */ - int objc; /* Number of arguments in the objv array */ - Tcl_Obj *CONST objv[]; /* Array of arguments to the procedure */ +ListboxYviewSubCmd( + Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */ + Listbox *listPtr, /* Information about the listbox */ + int objc, /* Number of arguments in the objv array */ + Tcl_Obj *const objv[]) /* Array of arguments to the procedure */ { int index, count, type; double fraction, fraction2; - + if (objc == 2) { if (listPtr->nElements == 0) { - Tcl_SetResult(interp, "0 1", TCL_STATIC); + Tcl_SetResult(interp, "0.0 1.0", TCL_STATIC); } else { - char buf[TCL_DOUBLE_SPACE * 2]; - + char buf[TCL_DOUBLE_SPACE]; + fraction = listPtr->topIndex/((double) listPtr->nElements); fraction2 = (listPtr->topIndex+listPtr->fullLines) - /((double) listPtr->nElements); + /((double) listPtr->nElements); if (fraction2 > 1.0) { fraction2 = 1.0; } - sprintf(buf, "%g %g", fraction, fraction2); + Tcl_PrintDouble(NULL, fraction, buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_PrintDouble(NULL, fraction2, buf); + Tcl_AppendResult(interp, " ", buf, NULL); } } else if (objc == 3) { if (GetListboxIndex(interp, listPtr, objv[2], 0, &index) != TCL_OK) { @@ -1350,22 +1343,22 @@ ListboxYviewSubCmd(interp, listPtr, objc, objv) } else { type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count); switch (type) { - case TK_SCROLL_ERROR: - return TCL_ERROR; - case TK_SCROLL_MOVETO: - index = (int) (listPtr->nElements*fraction + 0.5); - break; - case TK_SCROLL_PAGES: - if (listPtr->fullLines > 2) { - index = listPtr->topIndex - + count*(listPtr->fullLines-2); - } else { - index = listPtr->topIndex + count; - } - break; - case TK_SCROLL_UNITS: + case TK_SCROLL_MOVETO: + index = (int) (listPtr->nElements*fraction + 0.5); + break; + case TK_SCROLL_PAGES: + if (listPtr->fullLines > 2) { + index = listPtr->topIndex + count*(listPtr->fullLines-2); + } else { index = listPtr->topIndex + count; - break; + } + break; + case TK_SCROLL_UNITS: + index = listPtr->topIndex + count; + break; + case TK_SCROLL_ERROR: + default: + return TCL_ERROR; } ChangeListboxView(listPtr, index); } @@ -1377,8 +1370,8 @@ ListboxYviewSubCmd(interp, listPtr, objc, objv) * * ListboxGetItemAttributes -- * - * Returns a pointer to the ItemAttr record for a given index, - * creating one if it does not already exist. + * Returns a pointer to the ItemAttr record for a given index, creating + * one if it does not already exist. * * Results: * Pointer to an ItemAttr record. @@ -1390,18 +1383,19 @@ ListboxYviewSubCmd(interp, listPtr, objc, objv) */ static ItemAttr * -ListboxGetItemAttributes(interp, listPtr, index) - Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */ - Listbox *listPtr; /* Information about the listbox */ - int index; /* Index of the item to retrieve attributes - * for */ +ListboxGetItemAttributes( + Tcl_Interp *interp, /* Pointer to the calling Tcl interpreter */ + Listbox *listPtr, /* Information about the listbox */ + int index) /* Index of the item to retrieve attributes + * for. */ { - int new; + int isNew; Tcl_HashEntry *entry; ItemAttr *attrs; - entry = Tcl_CreateHashEntry(listPtr->itemAttrTable, (char *)index, &new); - if (new) { + entry = Tcl_CreateHashEntry(listPtr->itemAttrTable, + (char *) INT2PTR(index), &isNew); + if (isNew) { attrs = (ItemAttr *) ckalloc(sizeof(ItemAttr)); attrs->border = NULL; attrs->selBorder = NULL; @@ -1420,9 +1414,9 @@ ListboxGetItemAttributes(interp, listPtr, index) * * DestroyListbox -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a listbox at a safe time - * (when no-one is using it anymore). + * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to + * clean up the internal structure of a listbox at a safe time (when + * no-one is using it anymore). * * Results: * None. @@ -1434,14 +1428,17 @@ ListboxGetItemAttributes(interp, listPtr, index) */ static void -DestroyListbox(memPtr) - char *memPtr; /* Info about listbox widget. */ +DestroyListbox( + char *memPtr) /* Info about listbox widget. */ { register Listbox *listPtr = (Listbox *) memPtr; Tcl_HashEntry *entry; Tcl_HashSearch search; - /* If we have an internal list object, free it */ + /* + * If we have an internal list object, free it. + */ + if (listPtr->listObj != NULL) { Tcl_DecrRefCount(listPtr->listObj); listPtr->listObj = NULL; @@ -1452,23 +1449,28 @@ DestroyListbox(memPtr) TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, (ClientData) listPtr); } - - /* Free the selection hash table */ + + /* + * Free the selection hash table. + */ + Tcl_DeleteHashTable(listPtr->selection); ckfree((char *)listPtr->selection); - /* Free the item attribute hash table */ + /* + * Free the item attribute hash table. + */ + for (entry = Tcl_FirstHashEntry(listPtr->itemAttrTable, &search); - entry != NULL; entry = Tcl_NextHashEntry(&search)) { + entry != NULL; entry = Tcl_NextHashEntry(&search)) { ckfree((char *)Tcl_GetHashValue(entry)); } Tcl_DeleteHashTable(listPtr->itemAttrTable); ckfree((char *)listPtr->itemAttrTable); /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ if (listPtr->textGC != None) { @@ -1494,7 +1496,7 @@ DestroyListbox(memPtr) * DestroyListboxOptionTables -- * * This procedure is registered as an exit callback when the listbox - * command is first called. It cleans up the OptionTables structure + * command is first called. It cleans up the OptionTables structure * allocated by that command. * * Results: @@ -1507,11 +1509,11 @@ DestroyListbox(memPtr) */ static void -DestroyListboxOptionTables(clientData, interp) - ClientData clientData; /* Pointer to the OptionTables struct */ - Tcl_Interp *interp; /* Pointer to the calling interp */ +DestroyListboxOptionTables( + ClientData clientData, /* Pointer to the OptionTables struct */ + Tcl_Interp *interp) /* Pointer to the calling interp */ { - ckfree((char *)clientData); + ckfree((char *) clientData); return; } @@ -1520,30 +1522,29 @@ DestroyListboxOptionTables(clientData, interp) * * ConfigureListbox -- * - * This procedure is called to process an objv/objc list, plus - * the Tk option database, in order to configure (or reconfigure) - * a listbox widget. + * This procedure is called to process an objv/objc list, plus the Tk + * option database, in order to configure (or reconfigure) a listbox + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for listPtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for listPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureListbox(interp, listPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - register Listbox *listPtr; /* Information about widget; may or may - * not already have values for some fields. */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureListbox( + Tcl_Interp *interp, /* Used for error reporting. */ + register Listbox *listPtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *const objv[], /* Arguments. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { Tk_SavedOptions savedOptions; Tcl_Obj *oldListObj = NULL; @@ -1565,7 +1566,7 @@ ConfigureListbox(interp, listPtr, objc, objv, flags) if (Tk_SetOptions(interp, (char *) listPtr, listPtr->optionTable, objc, objv, - listPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { + listPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -1601,29 +1602,32 @@ ConfigureListbox(interp, listPtr, objc, objv, flags) (ClientData) listPtr); } - /* Verify the current status of the list var. + /* + * Verify the current status of the list var. * PREVIOUS STATE | NEW STATE | ACTION * ---------------+------------+---------------------------------- - * no listvar | listvar | If listvar does not exist, create - * it and copy the internal list obj's - * content to the new var. If it does - * exist, toss the internal list obj. + * no listvar | listvar | If listvar does not exist, create it + * and copy the internal list obj's + * content to the new var. If it does + * exist, toss the internal list obj. * - * listvar | no listvar | Copy old listvar content to the - * internal list obj + * listvar | no listvar | Copy old listvar content to the + * internal list obj * - * listvar | listvar | no special action + * listvar | listvar | no special action * * no listvar | no listvar | no special action */ + oldListObj = listPtr->listObj; if (listPtr->listVarName != NULL) { Tcl_Obj *listVarObj = Tcl_GetVar2Ex(interp, listPtr->listVarName, - (char *) NULL, TCL_GLOBAL_ONLY); + NULL, TCL_GLOBAL_ONLY); int dummy; + if (listVarObj == NULL) { listVarObj = (oldListObj ? oldListObj : Tcl_NewObj()); - if (Tcl_SetVar2Ex(interp, listPtr->listVarName, (char *) NULL, + if (Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, listVarObj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) { if (oldListObj == NULL) { @@ -1632,11 +1636,15 @@ ConfigureListbox(interp, listPtr, objc, objv, flags) continue; } } - /* Make sure the object is a good list object */ + + /* + * Make sure the object is a good list object. + */ + if (Tcl_ListObjLength(listPtr->interp, listVarObj, &dummy) != TCL_OK) { Tcl_AppendResult(listPtr->interp, - ": invalid -listvariable value", (char *) NULL); + ": invalid -listvariable value", NULL); continue; } @@ -1657,11 +1665,14 @@ ConfigureListbox(interp, listPtr, objc, objv, flags) Tk_FreeSavedOptions(&savedOptions); } - /* Make sure that the list length is correct */ + /* + * Make sure that the list length is correct. + */ + Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements); - + if (error) { - Tcl_SetObjResult(interp, errorResult); + Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; } else { @@ -1675,45 +1686,46 @@ ConfigureListbox(interp, listPtr, objc, objv, flags) * * ConfigureListboxItem -- * - * This procedure is called to process an objv/objc list, plus - * the Tk option database, in order to configure (or reconfigure) - * a listbox item. + * This procedure is called to process an objv/objc list, plus the Tk + * option database, in order to configure (or reconfigure) a listbox + * item. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for a listbox item; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for a listbox item; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureListboxItem(interp, listPtr, attrs, objc, objv, index) - Tcl_Interp *interp; /* Used for error reporting. */ - register Listbox *listPtr; /* Information about widget; may or may - * not already have values for some fields. */ - ItemAttr *attrs; /* Information about the item to configure */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ - int index; /* Index of the listbox item being configure */ +ConfigureListboxItem( + Tcl_Interp *interp, /* Used for error reporting. */ + register Listbox *listPtr, /* Information about widget; may or may not + * already have values for some fields. */ + ItemAttr *attrs, /* Information about the item to configure */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *const objv[], /* Arguments. */ + int index) /* Index of the listbox item being configure */ { Tk_SavedOptions savedOptions; if (Tk_SetOptions(interp, (char *)attrs, listPtr->itemAttrOptionTable, objc, objv, listPtr->tkwin, - &savedOptions, (int *)NULL) != TCL_OK) { + &savedOptions, NULL) != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } Tk_FreeSavedOptions(&savedOptions); + /* - * Redraw this index - ListboxWorldChanged would need to be called - * if item attributes were checked in the "world". + * Redraw this index - ListboxWorldChanged would need to be called if item + * attributes were checked in the "world". */ + EventuallyRedrawRange(listPtr, index, index); return TCL_OK; } @@ -1723,50 +1735,46 @@ ConfigureListboxItem(interp, listPtr, attrs, objc, objv, index) * * ListboxWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This procedure is called when the world has changed in some way and + * the widget needs to recompute all its graphics contexts and determine + * its new geometry. * * Results: - * None. + * None. * * Side effects: - * Listbox will be relayed out and redisplayed. + * Listbox will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ - + static void -ListboxWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +ListboxWorldChanged( + ClientData instanceData) /* Information about widget. */ { XGCValues gcValues; GC gc; unsigned long mask; - Listbox *listPtr; - - listPtr = (Listbox *) instanceData; + Listbox *listPtr = (Listbox *) instanceData; if (listPtr->state & STATE_NORMAL) { gcValues.foreground = listPtr->fgColorPtr->pixel; gcValues.graphics_exposures = False; mask = GCForeground | GCFont | GCGraphicsExposures; + } else if (listPtr->dfgColorPtr != NULL) { + gcValues.foreground = listPtr->dfgColorPtr->pixel; + gcValues.graphics_exposures = False; + mask = GCForeground | GCFont | GCGraphicsExposures; } else { - if (listPtr->dfgColorPtr != NULL) { - gcValues.foreground = listPtr->dfgColorPtr->pixel; - gcValues.graphics_exposures = False; - mask = GCForeground | GCFont | GCGraphicsExposures; - } else { - gcValues.foreground = listPtr->fgColorPtr->pixel; - mask = GCForeground | GCFont; - if (listPtr->gray == None) { - listPtr->gray = Tk_GetBitmap(NULL, listPtr->tkwin, "gray50"); - } - if (listPtr->gray != None) { - gcValues.fill_style = FillStippled; - gcValues.stipple = listPtr->gray; - mask |= GCFillStyle | GCStipple; - } + gcValues.foreground = listPtr->fgColorPtr->pixel; + mask = GCForeground | GCFont; + if (listPtr->gray == None) { + listPtr->gray = Tk_GetBitmap(NULL, listPtr->tkwin, "gray50"); + } + if (listPtr->gray != None) { + gcValues.fill_style = FillStippled; + gcValues.stipple = listPtr->gray; + mask |= GCFillStyle | GCStipple; } } @@ -1789,8 +1797,8 @@ ListboxWorldChanged(instanceData) listPtr->selTextGC = gc; /* - * Register the desired geometry for the window and arrange for - * the window to be redisplayed. + * Register the desired geometry for the window and arrange for the window + * to be redisplayed. */ ListboxComputeGeometry(listPtr, 1, 1, 1); @@ -1815,25 +1823,24 @@ ListboxWorldChanged(instanceData) */ static void -DisplayListbox(clientData) - ClientData clientData; /* Information about window. */ +DisplayListbox( + ClientData clientData) /* Information about window. */ { register Listbox *listPtr = (Listbox *) clientData; register Tk_Window tkwin = listPtr->tkwin; GC gc; - int i, limit, x, y, width = 0, prevSelected, freeGC; + int i, limit, x, y, prevSelected, freeGC, stringLen; Tk_FontMetrics fm; Tcl_Obj *curElement; Tcl_HashEntry *entry; char *stringRep; - int stringLen; ItemAttr *attrs; Tk_3DBorder selectedBg; XGCValues gcValues; unsigned long mask; - int left, right; /* Non-zero values here indicate - * that the left or right edge of - * the listbox is off-screen. */ + int left, right; /* Non-zero values here indicate that the left + * or right edge of the listbox is + * off-screen. */ Pixmap pixmap; listPtr->flags &= ~REDRAW_PENDING; @@ -1867,11 +1874,11 @@ DisplayListbox(clientData) #ifndef TK_NO_DOUBLE_BUFFERING /* - * Redrawing is done in a temporary pixmap that is allocated - * here and freed at the end of the procedure. All drawing is - * done to the pixmap, and the pixmap is copied to the screen - * at the end of the procedure. This provides the smoothest - * possible visual effects (no flashing on the screen). + * Redrawing is done in a temporary pixmap that is allocated here and + * freed at the end of the procedure. All drawing is done to the pixmap, + * and the pixmap is copied to the screen at the end of the procedure. + * This provides the smoothest possible visual effects (no flashing on the + * screen). */ pixmap = Tk_GetPixmap(listPtr->display, Tk_WindowId(tkwin), @@ -1882,7 +1889,10 @@ DisplayListbox(clientData) Tk_Fill3DRectangle(tkwin, pixmap, listPtr->normalBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); - /* Display each item in the listbox */ + /* + * Display each item in the listbox. + */ + limit = listPtr->topIndex + listPtr->fullLines + listPtr->partialLine - 1; if (limit >= listPtr->nElements) { limit = listPtr->nElements-1; @@ -1892,40 +1902,54 @@ DisplayListbox(clientData) left = listPtr->selBorderWidth+1; } if ((listPtr->maxWidth - listPtr->xOffset) > (Tk_Width(listPtr->tkwin) - - 2*(listPtr->inset + listPtr->selBorderWidth))) { + - 2*(listPtr->inset + listPtr->selBorderWidth))) { right = listPtr->selBorderWidth+1; } prevSelected = 0; - + for (i = listPtr->topIndex; i <= limit; i++) { + int width = Tk_Width(tkwin); /* zeroth approx to silence warning */ + x = listPtr->inset; - y = ((i - listPtr->topIndex) * listPtr->lineHeight) - + listPtr->inset; + y = ((i - listPtr->topIndex) * listPtr->lineHeight) + listPtr->inset; gc = listPtr->textGC; freeGC = 0; + /* * Lookup this item in the item attributes table, to see if it has - * special foreground/background colors + * special foreground/background colors. */ - entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *)i); + + entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *) INT2PTR(i)); /* - * If the listbox is enabled, items may be drawn differently; - * they may be drawn selected, or they may have special foreground - * or background colors. + * If the listbox is enabled, items may be drawn differently; they may + * be drawn selected, or they may have special foreground or + * background colors. */ + if (listPtr->state & STATE_NORMAL) { - if (Tcl_FindHashEntry(listPtr->selection, (char *)i) != NULL) { - /* Selected items are drawn differently. */ + if (Tcl_FindHashEntry(listPtr->selection, (char *) INT2PTR(i))) { + /* + * Selected items are drawn differently. + */ + gc = listPtr->selTextGC; width = Tk_Width(tkwin) - 2*listPtr->inset; selectedBg = listPtr->selBorder; - - /* If there is attribute information for this item, - * adjust the drawing accordingly */ + + /* + * If there is attribute information for this item, adjust the + * drawing accordingly. + */ + if (entry != NULL) { attrs = (ItemAttr *)Tcl_GetHashValue(entry); - /* Default GC has the values from the widget at large */ + + /* + * Default GC has the values from the widget at large. + */ + if (listPtr->selFgColorPtr) { gcValues.foreground = listPtr->selFgColorPtr->pixel; } else { @@ -1934,11 +1958,11 @@ DisplayListbox(clientData) gcValues.font = Tk_FontId(listPtr->tkfont); gcValues.graphics_exposures = False; mask = GCForeground | GCFont | GCGraphicsExposures; - + if (attrs->selBorder != NULL) { selectedBg = attrs->selBorder; } - + if (attrs->selFgColor != NULL) { gcValues.foreground = attrs->selFgColor->pixel; gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues); @@ -1988,7 +2012,7 @@ DisplayListbox(clientData) /* Draw bottom bevel */ if (i + 1 == listPtr->nElements || Tcl_FindHashEntry(listPtr->selection, - (char *)(i + 1)) == NULL ) { + (char *) INT2PTR(i + 1)) == NULL ) { Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg, x-left, y + listPtr->lineHeight - listPtr->selBorderWidth, width+left+right, listPtr->selBorderWidth, 0, 0, 0, @@ -2000,28 +2024,29 @@ DisplayListbox(clientData) * If there is an item attributes record for this item, draw * the background box and set the foreground color accordingly */ + if (entry != NULL) { attrs = (ItemAttr *)Tcl_GetHashValue(entry); gcValues.foreground = listPtr->fgColorPtr->pixel; gcValues.font = Tk_FontId(listPtr->tkfont); gcValues.graphics_exposures = False; mask = GCForeground | GCFont | GCGraphicsExposures; - + /* * If the item has its own background color, draw it now. */ - + if (attrs->border != NULL) { width = Tk_Width(tkwin) - 2*listPtr->inset; Tk_Fill3DRectangle(tkwin, pixmap, attrs->border, x, y, width, listPtr->lineHeight, 0, TK_RELIEF_FLAT); } - + /* * If the item has its own foreground, use it to override * the value in the gcValues structure. */ - + if ((listPtr->state & STATE_NORMAL) && attrs->fgColor != NULL) { gcValues.foreground = attrs->fgColor->pixel; @@ -2033,7 +2058,10 @@ DisplayListbox(clientData) } } - /* Draw the actual text of this item */ + /* + * Draw the actual text of this item. + */ + Tk_GetFontMetrics(listPtr->tkfont, &fm); y += fm.ascent + listPtr->selBorderWidth; x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset; @@ -2042,10 +2070,16 @@ DisplayListbox(clientData) Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont, stringRep, stringLen, x, y); - /* If this is the active element, apply the activestyle to it. */ + /* + * If this is the active element, apply the activestyle to it. + */ + if ((i == listPtr->active) && (listPtr->flags & GOT_FOCUS)) { if (listPtr->activeStyle == ACTIVE_STYLE_UNDERLINE) { - /* Underline the text. */ + /* + * Underline the text. + */ + Tk_UnderlineChars(listPtr->display, pixmap, gc, listPtr->tkfont, stringRep, x, y, 0, stringLen); } else if (listPtr->activeStyle == ACTIVE_STYLE_DOTBOX) { @@ -2053,52 +2087,59 @@ DisplayListbox(clientData) /* * This provides for exact default look and feel on Windows. */ + TkWinDCState state; HDC dc; RECT rect; dc = TkWinGetDrawableDC(listPtr->display, pixmap, &state); - rect.left = listPtr->inset; - rect.top = ((i - listPtr->topIndex) * listPtr->lineHeight) - + listPtr->inset; - rect.right = rect.left + width; + rect.left = listPtr->inset; + rect.top = ((i - listPtr->topIndex) * listPtr->lineHeight) + + listPtr->inset; + rect.right = rect.left + width; rect.bottom = rect.top + listPtr->lineHeight; DrawFocusRect(dc, &rect); TkWinReleaseDrawableDC(pixmap, dc, &state); -#else +#else /* !WIN32 */ /* * Draw a dotted box around the text. */ + x = listPtr->inset; y = ((i - listPtr->topIndex) * listPtr->lineHeight) - + listPtr->inset; + + listPtr->inset; width = Tk_Width(tkwin) - 2*listPtr->inset - 1; - gcValues.line_style = LineOnOffDash; - gcValues.line_width = listPtr->selBorderWidth; + gcValues.line_style = LineOnOffDash; + gcValues.line_width = listPtr->selBorderWidth; if (gcValues.line_width <= 0) { gcValues.line_width = 1; } gcValues.dash_offset = 0; - gcValues.dashes = 1; + gcValues.dashes = 1; + /* * You would think the XSetDashes was necessary, but it - * appears that the default dotting for just saying we - * want dashes appears to work correctly. + * appears that the default dotting for just saying we want + * dashes appears to work correctly. static char dashList[] = { 1 }; - static int dashLen = sizeof(dashList); + static int dashLen = sizeof(dashList); XSetDashes(listPtr->display, gc, 0, dashList, dashLen); */ + mask = GCLineWidth | GCLineStyle | GCDashList | GCDashOffset; XChangeGC(listPtr->display, gc, mask, &gcValues); XDrawRectangle(listPtr->display, pixmap, gc, x, y, (unsigned) width, (unsigned) listPtr->lineHeight - 1); if (!freeGC) { - /* Don't bother changing if it is about to be freed. */ + /* + * Don't bother changing if it is about to be freed. + */ + gcValues.line_style = LineSolid; XChangeGC(listPtr->display, gc, GCLineStyle, &gcValues); } -#endif +#endif /* WIN32 */ } } @@ -2108,8 +2149,8 @@ DisplayListbox(clientData) } /* - * Redraw the border for the listbox to make sure that it's on top - * of any of the text of the listbox entries. + * Redraw the border for the listbox to make sure that it's on top of any + * of the text of the listbox entries. */ Tk_Draw3DRectangle(tkwin, pixmap, listPtr->normalBorder, @@ -2123,11 +2164,11 @@ DisplayListbox(clientData) bgGC = Tk_GCForColor(listPtr->highlightBgColorPtr, pixmap); if (listPtr->flags & GOT_FOCUS) { fgGC = Tk_GCForColor(listPtr->highlightColorPtr, pixmap); - TkpDrawHighlightBorder(tkwin, fgGC, bgGC, - listPtr->highlightWidth, pixmap); + TkpDrawHighlightBorder(tkwin, fgGC, bgGC, + listPtr->highlightWidth, pixmap); } else { - TkpDrawHighlightBorder(tkwin, bgGC, bgGC, - listPtr->highlightWidth, pixmap); + TkpDrawHighlightBorder(tkwin, bgGC, bgGC, + listPtr->highlightWidth, pixmap); } } #ifndef TK_NO_DOUBLE_BUFFERING @@ -2143,51 +2184,51 @@ DisplayListbox(clientData) * * ListboxComputeGeometry -- * - * This procedure is invoked to recompute geometry information - * such as the sizes of the elements and the overall dimensions - * desired for the listbox. + * This procedure is invoked to recompute geometry information such as + * the sizes of the elements and the overall dimensions desired for the + * listbox. * * Results: * None. * * Side effects: - * Geometry information is updated and a new requested size is - * registered for the widget. Internal border and gridding - * information is also set. + * Geometry information is updated and a new requested size is registered + * for the widget. Internal border and gridding information is also set. * *---------------------------------------------------------------------- */ static void -ListboxComputeGeometry(listPtr, fontChanged, maxIsStale, updateGrid) - Listbox *listPtr; /* Listbox whose geometry is to be +ListboxComputeGeometry( + Listbox *listPtr, /* Listbox whose geometry is to be * recomputed. */ - int fontChanged; /* Non-zero means the font may have changed - * so per-element width information also - * has to be computed. */ - int maxIsStale; /* Non-zero means the "maxWidth" field may - * no longer be up-to-date and must - * be recomputed. If fontChanged is 1 then - * this must be 1. */ - int updateGrid; /* Non-zero means call Tk_SetGrid or - * Tk_UnsetGrid to update gridding for - * the window. */ + int fontChanged, /* Non-zero means the font may have changed so + * per-element width information also has to + * be computed. */ + int maxIsStale, /* Non-zero means the "maxWidth" field may no + * longer be up-to-date and must be + * recomputed. If fontChanged is 1 then this + * must be 1. */ + int updateGrid) /* Non-zero means call Tk_SetGrid or + * Tk_UnsetGrid to update gridding for the + * window. */ { - int width, height, pixelWidth, pixelHeight; + int width, height, pixelWidth, pixelHeight, textLength, i, result; Tk_FontMetrics fm; Tcl_Obj *element; - int textLength; char *text; - int i, result; - - if (fontChanged || maxIsStale) { + + if (fontChanged || maxIsStale) { listPtr->xScrollUnit = Tk_TextWidth(listPtr->tkfont, "0", 1); if (listPtr->xScrollUnit == 0) { listPtr->xScrollUnit = 1; } listPtr->maxWidth = 0; for (i = 0; i < listPtr->nElements; i++) { - /* Compute the pixel width of the current element */ + /* + * Compute the pixel width of the current element. + */ + result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element); if (result != TCL_OK) { @@ -2239,87 +2280,92 @@ ListboxComputeGeometry(listPtr, fontChanged, maxIsStale, updateGrid) * * ListboxInsertSubCmd -- * - * This procedure is invoked to handle the listbox "insert" - * subcommand. + * This procedure is invoked to handle the listbox "insert" subcommand. * * Results: * Standard Tcl result. * * Side effects: - * New elements are added to the listbox pointed to by listPtr; - * a refresh callback is registered for the listbox. + * New elements are added to the listbox pointed to by listPtr; a refresh + * callback is registered for the listbox. * *---------------------------------------------------------------------- */ static int -ListboxInsertSubCmd(listPtr, index, objc, objv) - register Listbox *listPtr; /* Listbox that is to get the new - * elements. */ - int index; /* Add the new elements before this +ListboxInsertSubCmd( + register Listbox *listPtr, /* Listbox that is to get the new elements. */ + int index, /* Add the new elements before this * element. */ - int objc; /* Number of new elements to add. */ - Tcl_Obj *CONST objv[]; /* New elements (one per entry). */ + int objc, /* Number of new elements to add. */ + Tcl_Obj *const objv[]) /* New elements (one per entry). */ { - int i, oldMaxWidth; + int i, oldMaxWidth, pixelWidth, result, length; Tcl_Obj *newListObj; - int pixelWidth; - int result; char *stringRep; - int length; - + oldMaxWidth = listPtr->maxWidth; for (i = 0; i < objc; i++) { /* * Check if any of the new elements are wider than the current widest; * if so, update our notion of "widest." */ + stringRep = Tcl_GetStringFromObj(objv[i], &length); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length); if (pixelWidth > listPtr->maxWidth) { listPtr->maxWidth = pixelWidth; } } - - /* Adjust selection and attribute information for every index after - * the first index */ + + /* + * Adjust selection and attribute information for every index after the + * first index. + */ + MigrateHashEntries(listPtr->selection, index, listPtr->nElements-1, objc); MigrateHashEntries(listPtr->itemAttrTable, index, listPtr->nElements-1, objc); - - /* If the object is shared, duplicate it before writing to it */ + + /* + * If the object is shared, duplicate it before writing to it. + */ + if (Tcl_IsShared(listPtr->listObj)) { newListObj = Tcl_DuplicateObj(listPtr->listObj); } else { newListObj = listPtr->listObj; } - result = - Tcl_ListObjReplace(listPtr->interp, newListObj, index, 0, objc, objv); + result = Tcl_ListObjReplace(listPtr->interp, newListObj, index, 0, + objc, objv); if (result != TCL_OK) { return result; } /* - * Replace the current object and set attached listvar, if any. - * This may error if listvar points to a var in a deleted namespace, but - * we ignore those errors. If the namespace is recreated, it will - * auto-sync with the current value. [Bug 1424513] + * Replace the current object and set attached listvar, if any. This may + * error if listvar points to a var in a deleted namespace, but we ignore + * those errors. If the namespace is recreated, it will auto-sync with the + * current value. [Bug 1424513] */ Tcl_IncrRefCount(newListObj); Tcl_DecrRefCount(listPtr->listObj); listPtr->listObj = newListObj; if (listPtr->listVarName != NULL) { - Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName, - (char *) NULL, listPtr->listObj, TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName, NULL, + listPtr->listObj, TCL_GLOBAL_ONLY); } - /* Get the new list length */ + /* + * Get the new list length. + */ + Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements); /* - * Update the "special" indices (anchor, topIndex, active) to account - * for the renumbering that just occurred. Then arrange for the new + * Update the "special" indices (anchor, topIndex, active) to account for + * the renumbering that just occurred. Then arrange for the new * information to be displayed. */ @@ -2350,8 +2396,8 @@ ListboxInsertSubCmd(listPtr, index, objc, objv) * * ListboxDeleteSubCmd -- * - * Process a listbox "delete" subcommand by removing one or more - * elements from a listbox widget. + * Process a listbox "delete" subcommand by removing one or more elements + * from a listbox widget. * * Results: * Standard Tcl result. @@ -2363,23 +2409,19 @@ ListboxInsertSubCmd(listPtr, index, objc, objv) */ static int -ListboxDeleteSubCmd(listPtr, first, last) - register Listbox *listPtr; /* Listbox widget to modify. */ - int first; /* Index of first element to delete. */ - int last; /* Index of last element to delete. */ +ListboxDeleteSubCmd( + register Listbox *listPtr, /* Listbox widget to modify. */ + int first, /* Index of first element to delete. */ + int last) /* Index of last element to delete. */ { - int count, i, widthChanged; - Tcl_Obj *newListObj; - Tcl_Obj *element; - int length; + int count, i, widthChanged, length, result, pixelWidth; + Tcl_Obj *newListObj, *element; char *stringRep; - int result; - int pixelWidth; Tcl_HashEntry *entry; - + /* - * Adjust the range to fit within the existing elements of the - * listbox, and make sure there's something to delete. + * Adjust the range to fit within the existing elements of the listbox, + * and make sure there's something to delete. */ if (first < 0) { @@ -2395,30 +2437,36 @@ ListboxDeleteSubCmd(listPtr, first, last) /* * Foreach deleted index we must: - * a) remove selection information + * a) remove selection information, * b) check the width of the element; if it is equal to the max, set * widthChanged to 1, because it may be the only element with that - * width + * width. */ + widthChanged = 0; for (i = first; i <= last; i++) { - /* Remove selection information */ - entry = Tcl_FindHashEntry(listPtr->selection, (char *)i); + /* + * Remove selection information. + */ + + entry = Tcl_FindHashEntry(listPtr->selection, (char *) INT2PTR(i)); if (entry != NULL) { listPtr->numSelected--; Tcl_DeleteHashEntry(entry); } - entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *)i); + entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *) INT2PTR(i)); if (entry != NULL) { ckfree((char *)Tcl_GetHashValue(entry)); Tcl_DeleteHashEntry(entry); } - - /* Check width of the element. We only have to check if widthChanged + + /* + * Check width of the element. We only have to check if widthChanged * has not already been set to 1, because we only need one maxWidth * element to disappear for us to have to recompute the width */ + if (widthChanged == 0) { Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element); stringRep = Tcl_GetStringFromObj(element, &length); @@ -2429,13 +2477,19 @@ ListboxDeleteSubCmd(listPtr, first, last) } } - /* Adjust selection and attribute info for indices after lastIndex */ + /* + * Adjust selection and attribute info for indices after lastIndex. + */ + MigrateHashEntries(listPtr->selection, last+1, listPtr->nElements-1, count*-1); MigrateHashEntries(listPtr->itemAttrTable, last+1, listPtr->nElements-1, count*-1); - /* Delete the requested elements */ + /* + * Delete the requested elements. + */ + if (Tcl_IsShared(listPtr->listObj)) { newListObj = Tcl_DuplicateObj(listPtr->listObj); } else { @@ -2448,27 +2502,30 @@ ListboxDeleteSubCmd(listPtr, first, last) } /* - * Replace the current object and set attached listvar, if any. - * This may error if listvar points to a var in a deleted namespace, but - * we ignore those errors. If the namespace is recreated, it will - * auto-sync with the current value. [Bug 1424513] + * Replace the current object and set attached listvar, if any. This may + * error if listvar points to a var in a deleted namespace, but we ignore + * those errors. If the namespace is recreated, it will auto-sync with the + * current value. [Bug 1424513] */ Tcl_IncrRefCount(newListObj); Tcl_DecrRefCount(listPtr->listObj); listPtr->listObj = newListObj; if (listPtr->listVarName != NULL) { - Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName, - (char *) NULL, listPtr->listObj, TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName, NULL, + listPtr->listObj, TCL_GLOBAL_ONLY); } - /* Get the new list length */ + /* + * Get the new list length. + */ + Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements); /* - * Update the selection and viewing information to reflect the change - * in the element numbering, and redisplay to slide information up over - * the elements that were deleted. + * Update the selection and viewing information to reflect the change in + * the element numbering, and redisplay to slide information up over the + * elements that were deleted. */ if (first <= listPtr->selectAnchor) { @@ -2512,26 +2569,26 @@ ListboxDeleteSubCmd(listPtr, first, last) * * ListboxEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on listboxes. + * This procedure is invoked by the Tk dispatcher for various events on + * listboxes. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -ListboxEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +ListboxEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { Listbox *listPtr = (Listbox *) clientData; - + if (eventPtr->type == Expose) { EventuallyRedrawRange(listPtr, NearestListboxElement(listPtr, eventPtr->xexpose.y), @@ -2564,10 +2621,9 @@ ListboxEventProc(clientData, eventPtr) ChangeListboxOffset(listPtr, listPtr->xOffset); /* - * Redraw the whole listbox. It's hard to tell what needs - * to be redrawn (e.g. if the listbox has shrunk then we - * may only need to redraw the borders), so just redraw - * everything for safety. + * Redraw the whole listbox. It's hard to tell what needs to be + * redrawn (e.g. if the listbox has shrunk then we may only need to + * redraw the borders), so just redraw everything for safety. */ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1); @@ -2589,9 +2645,9 @@ ListboxEventProc(clientData, eventPtr) * * ListboxCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This procedure is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -2603,16 +2659,16 @@ ListboxEventProc(clientData, eventPtr) */ static void -ListboxCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +ListboxCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { Listbox *listPtr = (Listbox *) clientData; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This procedure could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this procedure destroys the + * widget. */ if (!(listPtr->flags & LISTBOX_DELETED)) { @@ -2625,13 +2681,12 @@ ListboxCmdDeletedProc(clientData) * * GetListboxIndex -- * - * Parse an index into a listbox and return either its value - * or an error. + * Parse an index into a listbox and return either its value or an error. * * Results: - * A standard Tcl result. If all went well, then *indexPtr is - * filled in with the index (into listPtr) corresponding to - * string. Otherwise an error message is left in the interp's result. + * A standard Tcl result. If all went well, then *indexPtr is filled in + * with the index (into listPtr) corresponding to string. Otherwise an + * error message is left in the interp's result. * * Side effects: * None. @@ -2640,62 +2695,62 @@ ListboxCmdDeletedProc(clientData) */ static int -GetListboxIndex(interp, listPtr, indexObj, endIsSize, indexPtr) - Tcl_Interp *interp; /* For error messages. */ - Listbox *listPtr; /* Listbox for which the index is being +GetListboxIndex( + Tcl_Interp *interp, /* For error messages. */ + Listbox *listPtr, /* Listbox for which the index is being * specified. */ - Tcl_Obj *indexObj; /* Specifies an element in the listbox. */ - int endIsSize; /* If 1, "end" refers to the number of - * entries in the listbox. If 0, "end" - * refers to 1 less than the number of - * entries. */ - int *indexPtr; /* Where to store converted index. */ + Tcl_Obj *indexObj, /* Specifies an element in the listbox. */ + int endIsSize, /* If 1, "end" refers to the number of entries + * in the listbox. If 0, "end" refers to 1 + * less than the number of entries. */ + int *indexPtr) /* Where to store converted index. */ { - int result; - int index; + int result, index; char *stringRep; - - /* First see if the index is one of the named indices */ + + /* + * First see if the index is one of the named indices. + */ + result = Tcl_GetIndexFromObj(NULL, indexObj, indexNames, "", 0, &index); if (result == TCL_OK) { switch (index) { - case INDEX_ACTIVE: { - /* "active" index */ - *indexPtr = listPtr->active; - break; - } - - case INDEX_ANCHOR: { - /* "anchor" index */ - *indexPtr = listPtr->selectAnchor; - break; - } - - case INDEX_END: { - /* "end" index */ - if (endIsSize) { - *indexPtr = listPtr->nElements; - } else { - *indexPtr = listPtr->nElements - 1; - } - break; + case INDEX_ACTIVE: + /* "active" index */ + *indexPtr = listPtr->active; + break; + case INDEX_ANCHOR: + /* "anchor" index */ + *indexPtr = listPtr->selectAnchor; + break; + case INDEX_END: + /* "end" index */ + if (endIsSize) { + *indexPtr = listPtr->nElements; + } else { + *indexPtr = listPtr->nElements - 1; } + break; } return TCL_OK; } - /* The index didn't match any of the named indices; maybe it's an @x,y */ + /* + * The index didn't match any of the named indices; maybe it's an @x,y + */ + stringRep = Tcl_GetString(indexObj); if (stringRep[0] == '@') { /* @x,y index */ int y; char *start, *end; + start = stringRep + 1; - strtol(start, &end, 0); + y = strtol(start, &end, 0); if ((start == end) || (*end != ',')) { Tcl_AppendResult(interp, "bad listbox index \"", stringRep, "\": must be active, anchor, end, @x,y, or a number", - (char *)NULL); + NULL); return TCL_ERROR; } start = end+1; @@ -2703,23 +2758,29 @@ GetListboxIndex(interp, listPtr, indexObj, endIsSize, indexPtr) if ((start == end) || (*end != '\0')) { Tcl_AppendResult(interp, "bad listbox index \"", stringRep, "\": must be active, anchor, end, @x,y, or a number", - (char *)NULL); + NULL); return TCL_ERROR; } *indexPtr = NearestListboxElement(listPtr, y); return TCL_OK; } - - /* Maybe the index is just an integer */ + + /* + * Maybe the index is just an integer. + */ + if (Tcl_GetIntFromObj(interp, indexObj, indexPtr) == TCL_OK) { return TCL_OK; } - /* Everything failed, nothing matched. Throw up an error message */ + /* + * Everything failed, nothing matched. Throw up an error message. + */ + Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad listbox index \"", Tcl_GetString(indexObj), "\": must be active, anchor, ", - "end, @x,y, or a number", (char *) NULL); + "end, @x,y, or a number", NULL); return TCL_ERROR; } @@ -2728,26 +2789,25 @@ GetListboxIndex(interp, listPtr, indexObj, endIsSize, indexPtr) * * ChangeListboxView -- * - * Change the view on a listbox widget so that a given element - * is displayed at the top. + * Change the view on a listbox widget so that a given element is + * displayed at the top. * * Results: * None. * * Side effects: - * What's displayed on the screen is changed. If there is a - * scrollbar associated with this widget, then the scrollbar - * is instructed to change its display too. + * What's displayed on the screen is changed. If there is a scrollbar + * associated with this widget, then the scrollbar is instructed to + * change its display too. * *---------------------------------------------------------------------- */ static void -ChangeListboxView(listPtr, index) - register Listbox *listPtr; /* Information about widget. */ - int index; /* Index of element in listPtr - * that should now appear at the - * top of the listbox. */ +ChangeListboxView( + register Listbox *listPtr, /* Information about widget. */ + int index) /* Index of element in listPtr that should now + * appear at the top of the listbox. */ { if (index >= (listPtr->nElements - listPtr->fullLines)) { index = listPtr->nElements - listPtr->fullLines; @@ -2773,26 +2833,24 @@ ChangeListboxView(listPtr, index) * None. * * Side effects: - * The listbox may be redrawn to reflect its new horizontal - * offset. + * The listbox may be redrawn to reflect its new horizontal offset. * *---------------------------------------------------------------------- */ static void -ChangeListboxOffset(listPtr, offset) - register Listbox *listPtr; /* Information about widget. */ - int offset; /* Desired new "xOffset" for - * listbox. */ +ChangeListboxOffset( + register Listbox *listPtr, /* Information about widget. */ + int offset) /* Desired new "xOffset" for listbox. */ { int maxOffset; - + /* - * Make sure that the new offset is within the allowable range, and - * round it off to an even multiple of xScrollUnit. + * Make sure that the new offset is within the allowable range, and round + * it off to an even multiple of xScrollUnit. * - * Add half a scroll unit to do entry/text-like synchronization. - * [Bug #225025] + * Add half a scroll unit to do entry/text-like synchronization. [Bug + * #225025] */ offset += listPtr->xScrollUnit / 2; @@ -2818,8 +2876,8 @@ ChangeListboxOffset(listPtr, offset) * * ListboxScanTo -- * - * Given a point (presumably of the curent mouse location) - * drag the view in the window to implement the scan operation. + * Given a point (presumably of the curent mouse location) drag the view + * in the window to implement the scan operation. * * Results: * None. @@ -2831,29 +2889,26 @@ ChangeListboxOffset(listPtr, offset) */ static void -ListboxScanTo(listPtr, x, y) - register Listbox *listPtr; /* Information about widget. */ - int x; /* X-coordinate to use for scan - * operation. */ - int y; /* Y-coordinate to use for scan - * operation. */ +ListboxScanTo( + register Listbox *listPtr, /* Information about widget. */ + int x, /* X-coordinate to use for scan operation. */ + int y) /* Y-coordinate to use for scan operation. */ { int newTopIndex, newOffset, maxIndex, maxOffset; - + maxIndex = listPtr->nElements - listPtr->fullLines; maxOffset = listPtr->maxWidth + (listPtr->xScrollUnit - 1) - (Tk_Width(listPtr->tkwin) - 2*listPtr->inset - 2*listPtr->selBorderWidth - listPtr->xScrollUnit); /* - * Compute new top line for screen by amplifying the difference - * between the current position and the place where the scan - * started (the "mark" position). If we run off the top or bottom - * of the list, then reset the mark point so that the current - * position continues to correspond to the edge of the window. - * This means that the picture will start dragging as soon as the - * mouse reverses direction (without this reset, might have to slide - * mouse a long ways back before the picture starts moving again). + * Compute new top line for screen by amplifying the difference between + * the current position and the place where the scan started (the "mark" + * position). If we run off the top or bottom of the list, then reset the + * mark point so that the current position continues to correspond to the + * edge of the window. This means that the picture will start dragging as + * soon as the mouse reverses direction (without this reset, might have to + * slide mouse a long ways back before the picture starts moving again). */ newTopIndex = listPtr->scanMarkYIndex @@ -2873,7 +2928,7 @@ ListboxScanTo(listPtr, x, y) * scan started. */ - newOffset = listPtr->scanMarkXOffset - (10*(x - listPtr->scanMarkX)); + newOffset = listPtr->scanMarkXOffset - 10*(x - listPtr->scanMarkX); if (newOffset > maxOffset) { newOffset = listPtr->scanMarkXOffset = maxOffset; listPtr->scanMarkX = x; @@ -2889,13 +2944,12 @@ ListboxScanTo(listPtr, x, y) * * NearestListboxElement -- * - * Given a y-coordinate inside a listbox, compute the index of - * the element under that y-coordinate (or closest to that - * y-coordinate). + * Given a y-coordinate inside a listbox, compute the index of the + * element under that y-coordinate (or closest to that y-coordinate). * * Results: - * The return value is an index of an element of listPtr. If - * listPtr has no elements, then 0 is always returned. + * The return value is an index of an element of listPtr. If listPtr has + * no elements, then 0 is always returned. * * Side effects: * None. @@ -2904,9 +2958,9 @@ ListboxScanTo(listPtr, x, y) */ static int -NearestListboxElement(listPtr, y) - register Listbox *listPtr; /* Information about widget. */ - int y; /* Y-coordinate in listPtr's window. */ +NearestListboxElement( + register Listbox *listPtr, /* Information about widget. */ + int y) /* Y-coordinate in listPtr's window. */ { int index; @@ -2935,29 +2989,28 @@ NearestListboxElement(listPtr, y) * Standard Tcl result. * * Side effects: - * All of the elements in the range between first and last are - * marked as either selected or deselected, depending on the - * "select" argument. Any items whose state changes are redisplayed. - * The selection is claimed from X when the number of selected - * elements changes from zero to non-zero. + * All of the elements in the range between first and last are marked as + * either selected or deselected, depending on the "select" argument. Any + * items whose state changes are redisplayed. The selection is claimed + * from X when the number of selected elements changes from zero to + * non-zero. * *---------------------------------------------------------------------- */ static int -ListboxSelect(listPtr, first, last, select) - register Listbox *listPtr; /* Information about widget. */ - int first; /* Index of first element to - * select or deselect. */ - int last; /* Index of last element to - * select or deselect. */ - int select; /* 1 means select items, 0 means - * deselect them. */ +ListboxSelect( + register Listbox *listPtr, /* Information about widget. */ + int first, /* Index of first element to select or + * deselect. */ + int last, /* Index of last element to select or + * deselect. */ + int select) /* 1 means select items, 0 means deselect + * them. */ { - int i, firstRedisplay, oldCount; + int i, firstRedisplay, oldCount, isNew; Tcl_HashEntry *entry; - int new; - + if (last < first) { i = first; first = last; @@ -2976,12 +3029,13 @@ ListboxSelect(listPtr, first, last, select) firstRedisplay = -1; /* - * For each index in the range, find it in our selection hash table. - * If it's not there but should be, add it. If it's there but shouldn't - * be, remove it. + * For each index in the range, find it in our selection hash table. If + * it's not there but should be, add it. If it's there but shouldn't be, + * remove it. */ + for (i = first; i <= last; i++) { - entry = Tcl_FindHashEntry(listPtr->selection, (char *)i); + entry = Tcl_FindHashEntry(listPtr->selection, (char *) INT2PTR(i)); if (entry != NULL) { if (!select) { Tcl_DeleteHashEntry(entry); @@ -2993,7 +3047,7 @@ ListboxSelect(listPtr, first, last, select) } else { if (select) { entry = Tcl_CreateHashEntry(listPtr->selection, - (char *)i, &new); + (char *) INT2PTR(i), &isNew); Tcl_SetHashValue(entry, (ClientData) NULL); listPtr->numSelected++; if (firstRedisplay < 0) { @@ -3019,17 +3073,16 @@ ListboxSelect(listPtr, first, last, select) * * ListboxFetchSelection -- * - * This procedure is called back by Tk when the selection is - * requested by someone. It returns part or all of the selection - * in a buffer provided by the caller. + * This procedure is called back by Tk when the selection is requested by + * someone. It returns part or all of the selection in a buffer provided + * by the caller. * * Results: - * The return value is the number of non-NULL bytes stored - * at buffer. Buffer is filled (or partially filled) with a - * NULL-terminated string containing part or all of the selection, - * as given by offset and maxBytes. The selection is returned - * as a Tcl list with one list element for each element in the - * listbox. + * The return value is the number of non-NULL bytes stored at buffer. + * Buffer is filled (or partially filled) with a NULL-terminated string + * containing part or all of the selection, as given by offset and + * maxBytes. The selection is returned as a Tcl list with one list + * element for each element in the listbox. * * Side effects: * None. @@ -3038,25 +3091,22 @@ ListboxSelect(listPtr, first, last, select) */ static int -ListboxFetchSelection(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Information about listbox widget. */ - int offset; /* Offset within selection of first - * byte to be returned. */ - char *buffer; /* Location in which to place - * selection. */ - int maxBytes; /* Maximum number of bytes to place - * at buffer, not including terminating - * NULL character. */ +ListboxFetchSelection( + ClientData clientData, /* Information about listbox widget. */ + int offset, /* Offset within selection of first byte to be + * returned. */ + char *buffer, /* Location in which to place selection. */ + int maxBytes) /* Maximum number of bytes to place at buffer, + * not including terminating NULL + * character. */ { register Listbox *listPtr = (Listbox *) clientData; Tcl_DString selection; - int length, count, needNewline; + int length, count, needNewline, stringLen, i; Tcl_Obj *curElement; char *stringRep; - int stringLen; Tcl_HashEntry *entry; - int i; - + if (!listPtr->exportSelection) { return -1; } @@ -3068,7 +3118,7 @@ ListboxFetchSelection(clientData, offset, buffer, maxBytes) needNewline = 0; Tcl_DStringInit(&selection); for (i = 0; i < listPtr->nElements; i++) { - entry = Tcl_FindHashEntry(listPtr->selection, (char *)i); + entry = Tcl_FindHashEntry(listPtr->selection, (char *) INT2PTR(i)); if (entry != NULL) { if (needNewline) { Tcl_DStringAppend(&selection, "\n", 1); @@ -3097,9 +3147,7 @@ ListboxFetchSelection(clientData, offset, buffer, maxBytes) if (count > maxBytes) { count = maxBytes; } - memcpy((VOID *) buffer, - (VOID *) (Tcl_DStringValue(&selection) + offset), - (size_t) count); + memcpy(buffer, Tcl_DStringValue(&selection) + offset, (size_t) count); } buffer[count] = '\0'; Tcl_DStringFree(&selection); @@ -3111,25 +3159,25 @@ ListboxFetchSelection(clientData, offset, buffer, maxBytes) * * ListboxLostSelection -- * - * This procedure is called back by Tk when the selection is - * grabbed away from a listbox widget. + * This procedure is called back by Tk when the selection is grabbed away + * from a listbox widget. * * Results: * None. * * Side effects: - * The existing selection is unhighlighted, and the window is - * marked as not containing a selection. + * The existing selection is unhighlighted, and the window is marked as + * not containing a selection. * *---------------------------------------------------------------------- */ static void -ListboxLostSelection(clientData) - ClientData clientData; /* Information about listbox widget. */ +ListboxLostSelection( + ClientData clientData) /* Information about listbox widget. */ { register Listbox *listPtr = (Listbox *) clientData; - + if ((listPtr->exportSelection) && (listPtr->nElements > 0)) { ListboxSelect(listPtr, 0, listPtr->nElements-1, 0); } @@ -3140,8 +3188,8 @@ ListboxLostSelection(clientData) * * EventuallyRedrawRange -- * - * Ensure that a given range of elements is eventually redrawn on - * the display (if those elements in fact appear on the display). + * Ensure that a given range of elements is eventually redrawn on the + * display (if those elements in fact appear on the display). * * Results: * None. @@ -3153,17 +3201,19 @@ ListboxLostSelection(clientData) */ static void -EventuallyRedrawRange(listPtr, first, last) - register Listbox *listPtr; /* Information about widget. */ - int first; /* Index of first element in list - * that needs to be redrawn. */ - int last; /* Index of last element in list - * that needs to be redrawn. May - * be less than first; - * these just bracket a range. */ +EventuallyRedrawRange( + register Listbox *listPtr, /* Information about widget. */ + int first, /* Index of first element in list that needs + * to be redrawn. */ + int last) /* Index of last element in list that needs to + * be redrawn. May be less than first; these + * just bracket a range. */ { - /* We don't have to register a redraw callback if one is already pending, - * or if the window doesn't exist, or if the window isn't mapped */ + /* + * We don't have to register a redraw callback if one is already pending, + * or if the window doesn't exist, or if the window isn't mapped. + */ + if ((listPtr->flags & REDRAW_PENDING) || (listPtr->flags & LISTBOX_DELETED) || !Tk_IsMapped(listPtr->tkwin)) { @@ -3178,30 +3228,30 @@ EventuallyRedrawRange(listPtr, first, last) * * ListboxUpdateVScrollbar -- * - * This procedure is invoked whenever information has changed in - * a listbox in a way that would invalidate a vertical scrollbar - * display. If there is an associated scrollbar, then this command - * updates it by invoking a Tcl command. + * This procedure is invoked whenever information has changed in a + * listbox in a way that would invalidate a vertical scrollbar display. + * If there is an associated scrollbar, then this command updates it by + * invoking a Tcl command. * * Results: * None. * * Side effects: - * A Tcl command is invoked, and an additional command may be - * invoked to process errors in the command. + * A Tcl command is invoked, and an additional command may be invoked to + * process errors in the command. * *---------------------------------------------------------------------- */ static void -ListboxUpdateVScrollbar(listPtr) - register Listbox *listPtr; /* Information about widget. */ +ListboxUpdateVScrollbar( + register Listbox *listPtr) /* Information about widget. */ { - char string[TCL_DOUBLE_SPACE * 2]; + char firstStr[TCL_DOUBLE_SPACE+1], lastStr[TCL_DOUBLE_SPACE+1]; double first, last; int result; Tcl_Interp *interp; - + if (listPtr->yScrollCmd == NULL) { return; } @@ -3209,30 +3259,32 @@ ListboxUpdateVScrollbar(listPtr) first = 0.0; last = 1.0; } else { - first = listPtr->topIndex/((double) listPtr->nElements); - last = (listPtr->topIndex+listPtr->fullLines) - /((double) listPtr->nElements); + first = listPtr->topIndex / (double) listPtr->nElements; + last = (listPtr->topIndex + listPtr->fullLines) + / (double) listPtr->nElements; if (last > 1.0) { last = 1.0; } } - sprintf(string, " %g %g", first, last); + firstStr[0] = lastStr[0] = ' '; + Tcl_PrintDouble(NULL, first, firstStr+1); + Tcl_PrintDouble(NULL, last, lastStr+1); /* - * We must hold onto the interpreter from the listPtr because the data - * at listPtr might be freed as a result of the Tcl_VarEval. + * We must hold onto the interpreter from the listPtr because the data at + * listPtr might be freed as a result of the Tcl_VarEval. */ - + interp = listPtr->interp; - Tcl_Preserve((ClientData) interp); - result = Tcl_VarEval(interp, listPtr->yScrollCmd, string, - (char *) NULL); + Tcl_Preserve(interp); + result = Tcl_VarEval(interp, listPtr->yScrollCmd, firstStr, lastStr, + NULL); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (vertical scrolling command executed by listbox)"); Tcl_BackgroundError(interp); } - Tcl_Release((ClientData) interp); + Tcl_Release(interp); } /* @@ -3240,26 +3292,26 @@ ListboxUpdateVScrollbar(listPtr) * * ListboxUpdateHScrollbar -- * - * This procedure is invoked whenever information has changed in - * a listbox in a way that would invalidate a horizontal scrollbar - * display. If there is an associated horizontal scrollbar, then - * this command updates it by invoking a Tcl command. + * This procedure is invoked whenever information has changed in a + * listbox in a way that would invalidate a horizontal scrollbar display. + * If there is an associated horizontal scrollbar, then this command + * updates it by invoking a Tcl command. * * Results: * None. * * Side effects: - * A Tcl command is invoked, and an additional command may be - * invoked to process errors in the command. + * A Tcl command is invoked, and an additional command may be invoked to + * process errors in the command. * *---------------------------------------------------------------------- */ static void -ListboxUpdateHScrollbar(listPtr) - register Listbox *listPtr; /* Information about widget. */ +ListboxUpdateHScrollbar( + register Listbox *listPtr) /* Information about widget. */ { - char string[TCL_DOUBLE_SPACE * 2]; + char firstStr[TCL_DOUBLE_SPACE+1], lastStr[TCL_DOUBLE_SPACE+1]; int result, windowWidth; double first, last; Tcl_Interp *interp; @@ -3273,30 +3325,33 @@ ListboxUpdateHScrollbar(listPtr) first = 0; last = 1.0; } else { - first = listPtr->xOffset/((double) listPtr->maxWidth); - last = (listPtr->xOffset + windowWidth) - /((double) listPtr->maxWidth); + register double maxWide = (double) listPtr->maxWidth; + + first = listPtr->xOffset / maxWide; + last = (listPtr->xOffset + windowWidth) / maxWide; if (last > 1.0) { last = 1.0; } } - sprintf(string, " %g %g", first, last); + firstStr[0] = lastStr[0] = ' '; + Tcl_PrintDouble(NULL, first, firstStr+1); + Tcl_PrintDouble(NULL, last, lastStr+1); /* * We must hold onto the interpreter because the data referred to at * listPtr might be freed as a result of the call to Tcl_VarEval. */ - + interp = listPtr->interp; - Tcl_Preserve((ClientData) interp); - result = Tcl_VarEval(interp, listPtr->xScrollCmd, string, - (char *) NULL); + Tcl_Preserve(interp); + result = Tcl_VarEval(interp, listPtr->xScrollCmd, firstStr, lastStr, + NULL); if (result != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (horizontal scrolling command executed by listbox)"); Tcl_BackgroundError(interp); } - Tcl_Release((ClientData) interp); + Tcl_Release(interp); } /* @@ -3304,60 +3359,72 @@ ListboxUpdateHScrollbar(listPtr) * * ListboxListVarProc -- * - * Called whenever the trace on the listbox list var fires. + * Called whenever the trace on the listbox list var fires. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ static char * -ListboxListVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about button. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Not used. */ - CONST char *name2; /* Not used. */ - int flags; /* Information about what happened. */ +ListboxListVarProc( + ClientData clientData, /* Information about button. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + const char *name1, /* Not used. */ + const char *name2, /* Not used. */ + int flags) /* Information about what happened. */ { Listbox *listPtr = (Listbox *)clientData; Tcl_Obj *oldListObj, *varListObj; - int oldLength; - int i; + int oldLength, i; Tcl_HashEntry *entry; - - /* Bwah hahahaha -- puny mortal, you can't unset a -listvar'd variable! */ + + /* + * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable! + */ + if (flags & TCL_TRACE_UNSETS) { if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) { - Tcl_SetVar2Ex(interp, listPtr->listVarName, - (char *)NULL, listPtr->listObj, TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, + listPtr->listObj, TCL_GLOBAL_ONLY); Tcl_TraceVar(interp, listPtr->listVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ListboxListVarProc, clientData); - return (char *)NULL; + return NULL; } } else { oldListObj = listPtr->listObj; varListObj = Tcl_GetVar2Ex(listPtr->interp, listPtr->listVarName, - (char *)NULL, TCL_GLOBAL_ONLY); + NULL, TCL_GLOBAL_ONLY); + /* - * Make sure the new value is a good list; if it's not, disallow - * the change -- the fact that it is a listvar means that it must - * always be a valid list -- and return an error message. + * Make sure the new value is a good list; if it's not, disallow the + * change - the fact that it is a listvar means that it must always be + * a valid list - and return an error message. */ + if (Tcl_ListObjLength(listPtr->interp, varListObj, &i) != TCL_OK) { - Tcl_SetVar2Ex(interp, listPtr->listVarName, (char *)NULL, - oldListObj, TCL_GLOBAL_ONLY); - return("invalid listvar value"); + Tcl_SetVar2Ex(interp, listPtr->listVarName, NULL, oldListObj, + TCL_GLOBAL_ONLY); + return (char *) "invalid listvar value"; } - + listPtr->listObj = varListObj; - /* Incr the obj ref count so it doesn't vanish if the var is unset */ + + /* + * Incr the obj ref count so it doesn't vanish if the var is unset. + */ + Tcl_IncrRefCount(listPtr->listObj); - /* Clean up the ref to our old list obj */ + + /* + * Clean up the ref to our old list obj. + */ + Tcl_DecrRefCount(oldListObj); } @@ -3365,21 +3432,29 @@ ListboxListVarProc(clientData, interp, name1, name2, flags) * If the list length has decreased, then we should clean up selection and * attributes information for elements past the end of the new list */ + oldLength = listPtr->nElements; Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements); if (listPtr->nElements < oldLength) { for (i = listPtr->nElements; i < oldLength; i++) { - /* Clean up selection */ - entry = Tcl_FindHashEntry(listPtr->selection, (char *)i); + /* + * Clean up selection. + */ + + entry = Tcl_FindHashEntry(listPtr->selection, (char *) INT2PTR(i)); if (entry != NULL) { listPtr->numSelected--; Tcl_DeleteHashEntry(entry); } - /* Clean up attributes */ - entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *)i); + /* + * Clean up attributes. + */ + + entry = Tcl_FindHashEntry(listPtr->itemAttrTable, + (char *) INT2PTR(i)); if (entry != NULL) { - ckfree((char *)Tcl_GetHashValue(entry)); + ckfree((char *) Tcl_GetHashValue(entry)); Tcl_DeleteHashEntry(entry); } } @@ -3398,14 +3473,15 @@ ListboxListVarProc(clientData, interp, name1, name2, flags) /* * The computed maxWidth may have changed as a result of this operation. * However, we don't want to recompute it every time this trace fires - * (imagine the user doing 1000 lappends to the listvar). Therefore, set + * (imagine the user doing 1000 lappends to the listvar). Therefore, set * the MAXWIDTH_IS_STALE flag, which will cause the width to be recomputed * next time the list is redrawn. */ + listPtr->flags |= MAXWIDTH_IS_STALE; - + EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1); - return (char*)NULL; + return NULL; } /* @@ -3413,10 +3489,10 @@ ListboxListVarProc(clientData, interp, name1, name2, flags) * * MigrateHashEntries -- * - * Given a hash table with entries keyed by a single integer value, - * move all entries in a given range by a fixed amount, so that - * if in the original table there was an entry with key n and - * the offset was i, in the new table that entry would have key n + i. + * Given a hash table with entries keyed by a single integer value, move + * all entries in a given range by a fixed amount, so that if in the + * original table there was an entry with key n and the offset was i, in + * the new table that entry would have key n + i. * * Results: * None. @@ -3428,39 +3504,45 @@ ListboxListVarProc(clientData, interp, name1, name2, flags) */ static void -MigrateHashEntries(table, first, last, offset) - Tcl_HashTable *table; - int first; - int last; - int offset; +MigrateHashEntries( + Tcl_HashTable *table, + int first, + int last, + int offset) { - int i, new; + int i, isNew; Tcl_HashEntry *entry; ClientData clientData; if (offset == 0) { return; } - /* It's more efficient to do one if/else and nest the for loops inside, + + /* + * It's more efficient to do one if/else and nest the for loops inside, * although we could avoid some code duplication if we nested the if/else - * inside the for loops */ + * inside the for loops. + */ + if (offset > 0) { for (i = last; i >= first; i--) { - entry = Tcl_FindHashEntry(table, (char *)i); + entry = Tcl_FindHashEntry(table, (char *) INT2PTR(i)); if (entry != NULL) { clientData = Tcl_GetHashValue(entry); Tcl_DeleteHashEntry(entry); - entry = Tcl_CreateHashEntry(table, (char *)(i + offset), &new); + entry = Tcl_CreateHashEntry(table, + (char *) INT2PTR(i + offset), &isNew); Tcl_SetHashValue(entry, clientData); } } } else { for (i = first; i <= last; i++) { - entry = Tcl_FindHashEntry(table, (char *)i); + entry = Tcl_FindHashEntry(table, (char *) INT2PTR(i)); if (entry != NULL) { clientData = Tcl_GetHashValue(entry); Tcl_DeleteHashEntry(entry); - entry = Tcl_CreateHashEntry(table, (char *)(i + offset), &new); + entry = Tcl_CreateHashEntry(table, + (char *) INT2PTR(i + offset), &isNew); Tcl_SetHashValue(entry, clientData); } } @@ -3468,3 +3550,10 @@ MigrateHashEntries(table, first, last, offset) return; } +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkMacWinMenu.c b/generic/tkMacWinMenu.c index 7138c7d..9351de1 100644 --- a/generic/tkMacWinMenu.c +++ b/generic/tkMacWinMenu.c @@ -1,4 +1,4 @@ -/* +/* * tkMacWinMenu.c -- * * This module implements the common elements of the Mac and Windows @@ -6,10 +6,11 @@ * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkMenu.h" typedef struct ThreadSpecificData { @@ -17,9 +18,7 @@ typedef struct ThreadSpecificData { } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; - -static int PreprocessMenu _ANSI_ARGS_((TkMenu *menuPtr)); - +static int PreprocessMenu(TkMenu *menuPtr); /* *---------------------------------------------------------------------- @@ -29,8 +28,8 @@ static int PreprocessMenu _ANSI_ARGS_((TkMenu *menuPtr)); * The guts of the preprocessing. Recursive. * * Results: - * The return value is a standard Tcl result (errors can occur - * while the postcommands are being processed). + * The return value is a standard Tcl result (errors can occur while the + * postcommands are being processed). * * Side effects: * Since commands can get executed while this routine is being executed, @@ -40,61 +39,59 @@ static int PreprocessMenu _ANSI_ARGS_((TkMenu *menuPtr)); */ static int -PreprocessMenu(menuPtr) - TkMenu *menuPtr; +PreprocessMenu( + TkMenu *menuPtr) { int index, result, finished; - TkMenu *cascadeMenuPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_Preserve((ClientData) menuPtr); - + /* * First, let's process the post command on ourselves. If this command * destroys this menu, or if there was an error, we are done. */ - + result = TkPostCommand(menuPtr); if ((result != TCL_OK) || (menuPtr->tkwin == NULL)) { - goto done; + goto done; } - + /* - * Now, we go through structure and process all of the commands. - * Since the structure is changing, we stop after we do one command, - * and start over. When we get through without doing any, we are done. + * Now, we go through structure and process all of the commands. Since the + * structure is changing, we stop after we do one command, and start over. + * When we get through without doing any, we are done. */ - - + do { - finished = 1; - for (index = 0; index < menuPtr->numEntries; index++) { - if ((menuPtr->entries[index]->type == CASCADE_ENTRY) - && (menuPtr->entries[index]->namePtr != NULL)) { - if ((menuPtr->entries[index]->childMenuRefPtr != NULL) - && (menuPtr->entries[index]->childMenuRefPtr->menuPtr - != NULL)) { - cascadeMenuPtr = - menuPtr->entries[index]->childMenuRefPtr->menuPtr; - if (cascadeMenuPtr->postCommandGeneration != - tsdPtr->postCommandGeneration) { - cascadeMenuPtr->postCommandGeneration = - tsdPtr->postCommandGeneration; - result = PreprocessMenu(cascadeMenuPtr); - if (result != TCL_OK) { - goto done; - } - finished = 0; - break; - } - } - } - } + finished = 1; + for (index = 0; index < menuPtr->numEntries; index++) { + register TkMenuEntry *entryPtr = menuPtr->entries[index]; + + if ((entryPtr->type == CASCADE_ENTRY) + && (entryPtr->namePtr != NULL) + && (entryPtr->childMenuRefPtr != NULL) + && (entryPtr->childMenuRefPtr->menuPtr != NULL)) { + TkMenu *cascadeMenuPtr = entryPtr->childMenuRefPtr->menuPtr; + + if (cascadeMenuPtr->postCommandGeneration != + tsdPtr->postCommandGeneration) { + cascadeMenuPtr->postCommandGeneration = + tsdPtr->postCommandGeneration; + result = PreprocessMenu(cascadeMenuPtr); + if (result != TCL_OK) { + goto done; + } + finished = 0; + break; + } + } + } } while (!finished); - - done: - Tcl_Release((ClientData)menuPtr); + + done: + Tcl_Release((ClientData) menuPtr); return result; } @@ -103,23 +100,23 @@ PreprocessMenu(menuPtr) * * TkPreprocessMenu -- * - * On the Mac and on Windows, all of the postcommand processing has - * to be done on the entire tree underneath the main window to be - * posted. This means that we have to traverse the menu tree and - * issue the postcommands for all of the menus that have cascades - * attached. Since the postcommands can change the menu structure while - * we are traversing, we have to be extremely careful. Basically, the - * idea is to traverse the structure until we succesfully process - * one postcommand. Then we start over, and do it again until - * we traverse the whole structure without processing any postcommands. + * On the Mac and on Windows, all of the postcommand processing has to be + * done on the entire tree underneath the main window to be posted. This + * means that we have to traverse the menu tree and issue the + * postcommands for all of the menus that have cascades attached. Since + * the postcommands can change the menu structure while we are + * traversing, we have to be extremely careful. Basically, the idea is to + * traverse the structure until we succesfully process one postcommand. + * Then we start over, and do it again until we traverse the whole + * structure without processing any postcommands. * - * We are also going to set up the cascade back pointers in here - * since we have to traverse the entire structure underneath the menu - * anyway, We can clear the postcommand marks while we do that. + * We are also going to set up the cascade back pointers in here since we + * have to traverse the entire structure underneath the menu anyway. We + * can clear the postcommand marks while we do that. * * Results: - * The return value is a standard Tcl result (errors can occur - * while the postcommands are being processed). + * The return value is a standard Tcl result (errors can occur while the + * postcommands are being processed). * * Side effects: * Since commands can get executed while this routine is being executed, @@ -129,13 +126,21 @@ PreprocessMenu(menuPtr) */ int -TkPreprocessMenu(menuPtr) - TkMenu *menuPtr; +TkPreprocessMenu( + TkMenu *menuPtr) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); tsdPtr->postCommandGeneration++; menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration; return PreprocessMenu(menuPtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkMain.c b/generic/tkMain.c index 65a42a6..69c7d25 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -1,31 +1,21 @@ -/* +/* * tkMain.c -- * * This file contains a generic main program for Tk-based applications. * It can be used as-is for many applications, just by supplying a - * different appInitProc procedure for each specific application. - * Or, it can be used as a template for creating new main programs - * for Tk applications. + * different appInitProc function for each specific application. Or, it + * can be used as a template for creating new main programs for Tk + * applications. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include <tcl.h> -#include <tclInt.h> -#include <tk.h> +#include "tclInt.h" #include "tkInt.h" -#ifdef NO_STDLIB_H -# include "../compat/stdlib.h" -#else -# include <stdlib.h> -#endif #ifdef __WIN32__ #include "tkWinInt.h" #endif @@ -35,42 +25,36 @@ typedef struct ThreadSpecificData { - Tcl_Interp *interp; /* Interpreter for this thread. */ - Tcl_DString command; /* Used to assemble lines of terminal input + Tcl_Interp *interp; /* Interpreter for this thread. */ + Tcl_DString command; /* Used to assemble lines of terminal input * into Tcl commands. */ - Tcl_DString line; /* Used to read the next line from the + Tcl_DString line; /* Used to read the next line from the * terminal input. */ - int tty; /* Non-zero means standard input is a - * terminal-like device. Zero means it's - * a file. */ + int tty; /* Non-zero means standard input is a + * terminal-like device. Zero means it's a + * file. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Declarations for various library procedures and variables (don't want - * to include tkInt.h or tkPort.h here, because people might copy this - * file out of the Tk source directory to make their own modified versions). - * Note: don't declare "exit" here even though a declaration is really - * needed, because it will conflict with a declaration elsewhere on - * some systems. + * Declarations for various library functions and variables (don't want to + * include tkInt.h or tkPort.h here, because people might copy this file out + * of the Tk source directory to make their own modified versions). Note: do + * not declare "exit" here even though a declaration is really needed, because + * it will conflict with a declaration elsewhere on some systems. */ #if !defined(__WIN32__) && !defined(_WIN32) -#if !defined(MAC_TCL) -extern int isatty _ANSI_ARGS_((int fd)); -#else -#include <unistd.h> -#endif -extern char * strrchr _ANSI_ARGS_((CONST char *string, int c)); +extern int isatty(int fd); +extern char * strrchr(CONST char *string, int c); #endif /* - * Forward declarations for procedures defined later in this file. + * Forward declarations for functions defined later in this file. */ -static void Prompt _ANSI_ARGS_((Tcl_Interp *interp, int partial)); -static void StdinProc _ANSI_ARGS_((ClientData clientData, - int mask)); +static void Prompt(Tcl_Interp *interp, int partial); +static void StdinProc(ClientData clientData, int mask); /* *---------------------------------------------------------------------- @@ -80,98 +64,113 @@ static void StdinProc _ANSI_ARGS_((ClientData clientData, * Main program for Wish and most other Tk-based applications. * * Results: - * None. This procedure never returns (it exits the process when - * it's done. + * None. This function never returns (it exits the process when it's + * done. * * Side effects: - * This procedure initializes the Tk world and then starts - * interpreting commands; almost anything could happen, depending - * on the script being interpreted. + * This function initializes the Tk world and then starts interpreting + * commands; almost anything could happen, depending on the script being + * interpreted. * *---------------------------------------------------------------------- */ + void -Tk_MainEx(argc, argv, appInitProc, interp) - int argc; /* Number of arguments. */ - char **argv; /* Array of argument strings. */ - Tcl_AppInitProc *appInitProc; /* Application-specific initialization - * procedure to call after most - * initialization but before starting - * to execute commands. */ - Tcl_Interp *interp; +Tk_MainEx( + int argc, /* Number of arguments. */ + char **argv, /* Array of argument strings. */ + Tcl_AppInitProc *appInitProc, + /* Application-specific initialization + * function to call after most initialization + * but before starting to execute commands. */ + Tcl_Interp *interp) { - Tcl_Obj *argvPtr; + Tcl_Obj *path, *argvPtr; + CONST char *encodingName; int code, nullStdin = 0; - size_t length; Tcl_Channel inChannel, outChannel; - Tcl_DString appName; ThreadSpecificData *tsdPtr; #ifdef __WIN32__ HANDLE handle; #endif + Tcl_DString appName; /* - * Ensure that we are getting the matching version of Tcl. This is - * really only an issue when Tk is loaded dynamically. + * Ensure that we are getting the matching version of Tcl. This is really + * only an issue when Tk is loaded dynamically. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) { + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { abort(); } - tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_FindExecutable(argv[0]); tsdPtr->interp = interp; Tcl_Preserve((ClientData) interp); -#if ((defined(__WIN32__) && !defined(__CYGWIN__)) || defined(MAC_TCL)) +#if defined(__WIN32__) && !defined(__CYGWIN__) Tk_InitConsoleChannels(interp); #endif #ifdef MAC_OSX_TK - if (TclGetStartupScriptFileName() == NULL) { - TkMacOSXDefaultStartupScript(); + if (Tcl_GetStartupScript(NULL) == NULL) { + TkMacOSXDefaultStartupScript(); } #endif - + #ifdef TCL_MEM_DEBUG Tcl_InitMemory(interp); #endif /* - * Parse command-line arguments. A leading "-file" argument is - * ignored (a historical relic from the distant past). If the - * next argument doesn't start with a "-" then strip it off and - * use it as the name of a script file to process. + * If the application has not already set a startup script, parse the + * first few command line arguments to determine the script path and + * encoding. */ - if (argc > 1) { - length = strlen(argv[1]); - if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) { - argc--; - argv++; - } - } - if (TclGetStartupScriptFileName() == NULL) { - if ((argc > 1) && (argv[1][0] != '-')) { - TclSetStartupScriptFileName(argv[1]); + if (NULL == Tcl_GetStartupScript(NULL)) { + size_t length; + + /* + * Check whether first 3 args (argv[1] - argv[3]) look like + * -encoding ENCODING FILENAME + * or like + * FILENAME + * or like + * -file FILENAME (ancient history support only) + */ + + if ((argc > 3) && (0 == strcmp("-encoding", argv[1])) + && ('-' != argv[3][0])) { + Tcl_SetStartupScript(Tcl_NewStringObj(argv[3], -1), argv[2]); + argc -= 3; + argv += 3; + } else if ((argc > 1) && ('-' != argv[1][0])) { + Tcl_SetStartupScript(Tcl_NewStringObj(argv[1], -1), NULL); argc--; argv++; + } else if ((argc > 2) && (length = strlen(argv[1])) + && (length > 1) && (0 == strncmp("-file", argv[1], length)) + && ('-' != argv[2][0])) { + Tcl_SetStartupScript(Tcl_NewStringObj(argv[2], -1), NULL); + argc -= 2; + argv += 2; } } - - /* - * Make command-line arguments available in the Tcl variables "argc" - * and "argv". - */ - if (TclGetStartupScriptFileName() == NULL) { + path = Tcl_GetStartupScript(&encodingName); + if (NULL == path) { Tcl_ExternalToUtfDString(NULL, argv[0], -1, &appName); } else { - TclSetStartupScriptFileName(Tcl_ExternalToUtfDString(NULL, - TclGetStartupScriptFileName(), -1, &appName)); + int numBytes; + CONST char *pathName = Tcl_GetStringFromObj(path, &numBytes); + + Tcl_ExternalToUtfDString(NULL, pathName, numBytes, &appName); + path = Tcl_NewStringObj(Tcl_DStringValue(&appName), -1); + Tcl_SetStartupScript(path, encodingName); } Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&appName), TCL_GLOBAL_ONLY); Tcl_DStringFree(&appName); @@ -183,6 +182,7 @@ Tk_MainEx(argc, argv, appInitProc, interp) argvPtr = Tcl_NewListObj(0, NULL); while (argc--) { Tcl_DString ds; + Tcl_ExternalToUtfDString(NULL, *argv++, -1, &ds); Tcl_ListObjAppendElement(NULL, argvPtr, Tcl_NewStringObj( Tcl_DStringValue(&ds), Tcl_DStringLength(&ds))); @@ -197,18 +197,18 @@ Tk_MainEx(argc, argv, appInitProc, interp) #ifdef __WIN32__ /* * For now, under Windows, we assume we are not running as a console mode - * app, so we need to use the GUI console. In order to enable this, we - * always claim to be running on a tty. This probably isn't the right - * way to do it. + * app, so we need to use the GUI console. In order to enable this, we + * always claim to be running on a tty. This probably isn't the right way + * to do it. */ handle = GetStdHandle(STD_INPUT_HANDLE); - if ((handle == INVALID_HANDLE_VALUE) || (handle == 0) + if ((handle == INVALID_HANDLE_VALUE) || (handle == 0) || (GetFileType(handle) == FILE_TYPE_UNKNOWN)) { /* - * If it's a bad or closed handle, then it's been connected - * to a wish console window. + * If it's a bad or closed handle, then it's been connected to a wish + * console window. */ tsdPtr->tty = 1; @@ -239,8 +239,8 @@ Tk_MainEx(argc, argv, appInitProc, interp) } #endif Tcl_SetVar(interp, "tcl_interactive", - ((TclGetStartupScriptFileName() == NULL) && (tsdPtr->tty - || nullStdin)) ? "1" : "0", TCL_GLOBAL_ONLY); + ((path == NULL) && (tsdPtr->tty || nullStdin)) ? "1" : "0", + TCL_GLOBAL_ONLY); /* * Invoke application-specific initialization. @@ -252,16 +252,18 @@ Tk_MainEx(argc, argv, appInitProc, interp) } /* - * Invoke the script specified on the command line, if any. + * Invoke the script specified on the command line, if any. Must fetch it + * again, as the appInitProc might have reset it. */ - if (TclGetStartupScriptFileName() != NULL) { + path = Tcl_GetStartupScript(&encodingName); + if (path != NULL) { Tcl_ResetResult(interp); - code = Tcl_EvalFile(interp, TclGetStartupScriptFileName()); + code = Tcl_FSEvalFileEx(interp, path, encodingName); if (code != TCL_OK) { /* - * The following statement guarantees that the errorInfo - * variable is set properly. + * The following statement guarantees that the errorInfo variable + * is set properly. */ Tcl_AddErrorInfo(interp, ""); @@ -302,13 +304,14 @@ Tk_MainEx(argc, argv, appInitProc, interp) Tcl_ResetResult(interp); /* - * Loop infinitely, waiting for commands to execute. When there - * are no windows left, Tk_MainLoop returns and we exit. + * Loop infinitely, waiting for commands to execute. When there are no + * windows left, Tk_MainLoop returns and we exit. */ Tk_MainLoop(); Tcl_DeleteInterp(interp); Tcl_Release((ClientData) interp); + Tcl_SetStartupScript(NULL, NULL); Tcl_Exit(0); } @@ -317,69 +320,65 @@ Tk_MainEx(argc, argv, appInitProc, interp) * * StdinProc -- * - * This procedure is invoked by the event dispatcher whenever - * standard input becomes readable. It grabs the next line of - * input characters, adds them to a command being assembled, and - * executes the command if it's complete. + * This function is invoked by the event dispatcher whenever standard + * input becomes readable. It grabs the next line of input characters, + * adds them to a command being assembled, and executes the command if + * it's complete. * * Results: * None. * * Side effects: - * Could be almost arbitrary, depending on the command that's - * typed. + * Could be almost arbitrary, depending on the command that's typed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void -StdinProc(clientData, mask) - ClientData clientData; /* Not used. */ - int mask; /* Not used. */ +StdinProc( + ClientData clientData, /* Not used. */ + int mask) /* Not used. */ { static int gotPartial = 0; char *cmd; int code, count; Tcl_Channel chan = (Tcl_Channel) clientData; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_Interp *interp = tsdPtr->interp; count = Tcl_Gets(chan, &tsdPtr->line); - if (count < 0) { - if (!gotPartial) { - if (tsdPtr->tty) { - Tcl_Exit(0); - } else { - Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan); - } - return; - } + if (count < 0 && !gotPartial) { + if (tsdPtr->tty) { + Tcl_Exit(0); + } else { + Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan); + } + return; } (void) Tcl_DStringAppend(&tsdPtr->command, Tcl_DStringValue( - &tsdPtr->line), -1); + &tsdPtr->line), -1); cmd = Tcl_DStringAppend(&tsdPtr->command, "\n", -1); Tcl_DStringFree(&tsdPtr->line); if (!Tcl_CommandComplete(cmd)) { - gotPartial = 1; - goto prompt; + gotPartial = 1; + goto prompt; } gotPartial = 0; /* * Disable the stdin channel handler while evaluating the command; - * otherwise if the command re-enters the event loop we might - * process commands from stdin before the current command is - * finished. Among other things, this will trash the text of the - * command being evaluated. + * otherwise if the command re-enters the event loop we might process + * commands from stdin before the current command is finished. Among other + * things, this will trash the text of the command being evaluated. */ Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan); code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL); - + chan = Tcl_GetStdChannel(TCL_STDIN); if (chan) { Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, @@ -400,7 +399,7 @@ StdinProc(clientData, mask) * Output a prompt. */ - prompt: + prompt: if (tsdPtr->tty) { Prompt(interp, gotPartial); } @@ -412,25 +411,24 @@ StdinProc(clientData, mask) * * Prompt -- * - * Issue a prompt on standard output, or invoke a script - * to issue the prompt. + * Issue a prompt on standard output, or invoke a script to issue the + * prompt. * * Results: * None. * * Side effects: - * A prompt gets output, and a Tcl script may be evaluated - * in interp. + * A prompt gets output, and a Tcl script may be evaluated in interp. * *---------------------------------------------------------------------- */ static void -Prompt(interp, partial) - Tcl_Interp *interp; /* Interpreter to use for prompting. */ - int partial; /* Non-zero means there already - * exists a partial command, so use - * the secondary prompt. */ +Prompt( + Tcl_Interp *interp, /* Interpreter to use for prompting. */ + int partial) /* Non-zero means there already exists a + * partial command, so use the secondary + * prompt. */ { Tcl_Obj *promptCmd; int code; @@ -439,41 +437,49 @@ Prompt(interp, partial) promptCmd = Tcl_GetVar2Ex(interp, partial ? "tcl_prompt2" : "tcl_prompt1", NULL, TCL_GLOBAL_ONLY); if (promptCmd == NULL) { -defaultPrompt: + defaultPrompt: if (!partial) { - - /* - * We must check that outChannel is a real channel - it - * is possible that someone has transferred stdout out of - * this interpreter with "interp transfer". - */ + /* + * We must check that outChannel is a real channel - it is + * possible that someone has transferred stdout out of this + * interpreter with "interp transfer". + */ outChannel = Tcl_GetChannel(interp, "stdout", NULL); - if (outChannel != (Tcl_Channel) NULL) { - Tcl_WriteChars(outChannel, "% ", 2); - } + if (outChannel != (Tcl_Channel) NULL) { + Tcl_WriteChars(outChannel, "% ", 2); + } } } else { code = Tcl_EvalObjEx(interp, promptCmd, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); - /* - * We must check that errChannel is a real channel - it - * is possible that someone has transferred stderr out of - * this interpreter with "interp transfer". - */ - + + /* + * We must check that errChannel is a real channel - it is + * possible that someone has transferred stderr out of this + * interpreter with "interp transfer". + */ + errChannel = Tcl_GetChannel(interp, "stderr", NULL); - if (errChannel != (Tcl_Channel) NULL) { - Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); - Tcl_WriteChars(errChannel, "\n", 1); - } + if (errChannel != (Tcl_Channel) NULL) { + Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); + Tcl_WriteChars(errChannel, "\n", 1); + } goto defaultPrompt; } } outChannel = Tcl_GetChannel(interp, "stdout", NULL); if (outChannel != (Tcl_Channel) NULL) { - Tcl_Flush(outChannel); + Tcl_Flush(outChannel); } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkMenu.c b/generic/tkMenu.c index 19031c5..e7e6bb8 100755..100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -1,16 +1,16 @@ -/* +/* * tkMenu.c -- * * This file contains most of the code for implementing menus in Tk. It takes - * care of all of the generic (platform-independent) parts of menus, and - * is supplemented by platform-specific files. The geometry calculation - * and drawing code for menus is in the file tkMenuDraw.c + * care of all of the generic (platform-independent) parts of menus, and is + * supplemented by platform-specific files. The geometry calculation and + * drawing code for menus is in the file tkMenuDraw.c * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* @@ -18,52 +18,49 @@ * * Menus can be used in three ways: * - as a popup menu, either as part of a menubutton or standalone. - * - as a menubar. The menu's cascade items are arranged according to - * the specific platform to provide the user access to the menus at all - * times + * - as a menubar. The menu's cascade items are arranged according to the + * specific platform to provide the user access to the menus at all times * - as a tearoff palette. This is a window with the menu's items in it. * - * The goal is to provide the Tk developer with a way to use a common - * set of menus for all of these tasks. + * The goal is to provide the Tk developer with a way to use a common set of + * menus for all of these tasks. * * In order to make the bindings for cascade menus work properly under Unix, - * the cascade menus' pathnames must be proper children of the menu that - * they are cascade from. So if there is a menu .m, and it has two - * cascades labelled "File" and "Edit", the cascade menus might have - * the pathnames .m.file and .m.edit. Another constraint is that the menus - * used for menubars must be children of the toplevel widget that they - * are attached to. And on the Macintosh, the platform specific menu handle - * for cascades attached to a menu bar must have a title that matches the - * label for the cascade menu. + * the cascade menus' pathnames must be proper children of the menu that they + * are cascade from. So if there is a menu .m, and it has two cascades + * labelled "File" and "Edit", the cascade menus might have the pathnames + * .m.file and .m.edit. Another constraint is that the menus used for menubars + * must be children of the toplevel widget that they are attached to. And on + * the Macintosh, the platform specific menu handle for cascades attached to a + * menu bar must have a title that matches the label for the cascade menu. * * To handle all of the constraints, Tk menubars and tearoff menus are * implemented using menu clones. Menu clones are full menus in their own - * right; they have a Tk window and pathname associated with them; they have - * a TkMenu structure and array of entries. However, they are linked with the - * original menu that they were cloned from. The reflect the attributes of - * the original, or "master", menu. So if an item is added to a menu, and - * that menu has clones, then the item must be added to all of its clones - * also. Menus are cloned when a menu is torn-off or when a menu is assigned - * as a menubar using the "-menu" option of the toplevel's pathname configure + * 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, or "master", menu. So if an item is added to a menu, and that + * menu has clones, then the item must be added to all of its clones also. + * Menus are cloned when a menu is torn-off or when a menu is assigned as a + * menubar using the "-menu" option of the toplevel's pathname configure * subcommand. When a clone is destroyed, only the clone is destroyed, but * when the master menu is destroyed, all clones are also destroyed. This - * allows the developer to just deal with one set of menus when creating - * and destroying. + * allows the developer to just deal with one set of menus when creating and + * destroying. * * Clones are rather tricky when a menu with cascade entries is cloned (such * as a menubar). Not only does the menu have to be cloned, but each cascade * entry's corresponding menu must also be cloned. This maintains the pathname - * parent-child hierarchy necessary for menubars and toplevels to work. - * This leads to several special cases: + * parent-child hierarchy necessary for menubars and toplevels to work. This + * leads to several special cases: * * 1. When a new menu is created, and it is pointed to by cascade entries in * cloned menus, the new menu has to be cloned to parallel the cascade * structure. * 2. When a cascade item is added to a menu that has been cloned, and the * menu that the cascade item points to exists, that menu has to be cloned. - * 3. When the menu that a cascade entry points to is changed, the old - * cloned cascade menu has to be discarded, and the new one has to be cloned. - * + * 3. When the menu that a cascade entry points to is changed, the old cloned + * cascade menu has to be discarded, and the new one has to be cloned. */ #if 0 @@ -75,22 +72,21 @@ #define __NO_OLD_CONFIG #endif -#include "tkPort.h" +#include "tkInt.h" #include "tkMenu.h" #define MENU_HASH_KEY "tkMenus" typedef struct ThreadSpecificData { - int menusInitialized; /* Flag indicates whether thread-specific - * elements of the Windows Menu module - * have been initialized. */ + int menusInitialized; /* Flag indicates whether thread-specific + * elements of the Windows Menu module have + * been initialized. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * The following flag indicates whether the process-wide state for - * the Menu module has been intialized. The Mutex protects access to - * that flag. + * The following flag indicates whether the process-wide state for the Menu + * module has been intialized. The Mutex protects access to that flag. */ static int menusInitialized; @@ -101,170 +97,171 @@ TCL_DECLARE_MUTEX(menuMutex) * to update code in TkpMenuInit that changes the font string entry. */ -CONST char *tkMenuStateStrings[] = {"active", "normal", "disabled", (char *) NULL}; +const char *tkMenuStateStrings[] = {"active", "normal", "disabled", NULL}; -static CONST char *menuEntryTypeStrings[] = { - "cascade", "checkbutton", "command", "radiobutton", "separator", - (char *) NULL +static const char *menuEntryTypeStrings[] = { + "cascade", "checkbutton", "command", "radiobutton", "separator", NULL }; /* - * The following table defines the legal values for the -compound option. - * It is used with the "enum compound" declaration in tkMenu.h + * The following table defines the legal values for the -compound option. It + * is used with the "enum compound" declaration in tkMenu.h */ static const char *compoundStrings[] = { - "bottom", "center", "left", "none", "right", "top", (char *) NULL + "bottom", "center", "left", "none", "right", "top", NULL }; -static Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = { - {TK_OPTION_BORDER, "-activebackground", (char *) NULL, (char *) NULL, - DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1, +static const Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = { + {TK_OPTION_BORDER, "-activebackground", NULL, NULL, + DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_COLOR, "-activeforeground", (char *) NULL, (char *) NULL, + {TK_OPTION_COLOR, "-activeforeground", NULL, NULL, DEF_MENU_ENTRY_ACTIVE_FG, Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-accelerator", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-accelerator", NULL, NULL, DEF_MENU_ENTRY_ACCELERATOR, Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL, + {TK_OPTION_BORDER, "-background", NULL, NULL, DEF_MENU_ENTRY_BG, Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL, + {TK_OPTION_BITMAP, "-bitmap", NULL, NULL, DEF_MENU_ENTRY_BITMAP, Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL, + {TK_OPTION_BOOLEAN, "-columnbreak", NULL, NULL, DEF_MENU_ENTRY_COLUMN_BREAK, -1, Tk_Offset(TkMenuEntry, columnBreak)}, - {TK_OPTION_STRING, "-command", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-command", NULL, NULL, DEF_MENU_ENTRY_COMMAND, Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0, + DEF_MENU_ENTRY_COMPOUND, -1, Tk_Offset(TkMenuEntry, compound), 0, (ClientData) compoundStrings, 0}, - {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL, + {TK_OPTION_FONT, "-font", NULL, NULL, DEF_MENU_ENTRY_FONT, Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_COLOR, "-foreground", (char *) NULL, (char *) NULL, + {TK_OPTION_COLOR, "-foreground", NULL, NULL, DEF_MENU_ENTRY_FG, Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL, + {TK_OPTION_BOOLEAN, "-hidemargin", NULL, NULL, DEF_MENU_ENTRY_HIDE_MARGIN, -1, Tk_Offset(TkMenuEntry, hideMargin)}, - {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-image", NULL, NULL, DEF_MENU_ENTRY_IMAGE, Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-label", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-label", NULL, NULL, DEF_MENU_ENTRY_LABEL, Tk_Offset(TkMenuEntry, labelPtr), -1, 0}, - {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING_TABLE, "-state", NULL, NULL, DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0, (ClientData) tkMenuStateStrings}, - {TK_OPTION_INT, "-underline", (char *) NULL, (char *) NULL, + {TK_OPTION_INT, "-underline", NULL, NULL, DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline)}, {TK_OPTION_END} }; -static Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = { - {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL, +static const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = { + {TK_OPTION_BORDER, "-background", NULL, NULL, DEF_MENU_ENTRY_BG, Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK}, {TK_OPTION_END} }; -static Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = { - {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL, +static const Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = { + {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL, DEF_MENU_ENTRY_INDICATOR, -1, Tk_Offset(TkMenuEntry, indicatorOn)}, - {TK_OPTION_STRING, "-offvalue", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-offvalue", NULL, NULL, DEF_MENU_ENTRY_OFF_VALUE, Tk_Offset(TkMenuEntry, offValuePtr), -1}, - {TK_OPTION_STRING, "-onvalue", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-onvalue", NULL, NULL, DEF_MENU_ENTRY_ON_VALUE, Tk_Offset(TkMenuEntry, onValuePtr), -1}, - {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL, + {TK_OPTION_COLOR, "-selectcolor", NULL, NULL, DEF_MENU_ENTRY_SELECT, Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-selectimage", NULL, NULL, DEF_MENU_ENTRY_SELECT_IMAGE, Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-variable", NULL, NULL, DEF_MENU_ENTRY_CHECK_VARIABLE, Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs} + {TK_OPTION_END, NULL, NULL, NULL, + NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs} }; -static Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = { - {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL, +static const Tk_OptionSpec tkRadioButtonEntryConfigSpecs[] = { + {TK_OPTION_BOOLEAN, "-indicatoron", NULL, NULL, DEF_MENU_ENTRY_INDICATOR, -1, Tk_Offset(TkMenuEntry, indicatorOn)}, - {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) NULL, + {TK_OPTION_COLOR, "-selectcolor", NULL, NULL, DEF_MENU_ENTRY_SELECT, Tk_Offset(TkMenuEntry, indicatorFgPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-selectimage", (char *) NULL, (char *) NULL, - DEF_MENU_ENTRY_SELECT_IMAGE, + {TK_OPTION_STRING, "-selectimage", NULL, NULL, + DEF_MENU_ENTRY_SELECT_IMAGE, Tk_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-value", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-value", NULL, NULL, DEF_MENU_ENTRY_VALUE, Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING, "-variable", NULL, NULL, DEF_MENU_ENTRY_RADIO_VARIABLE, Tk_Offset(TkMenuEntry, namePtr), -1, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs} + {TK_OPTION_END, NULL, NULL, NULL, + NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs} }; -static Tk_OptionSpec tkCascadeEntryConfigSpecs[] = { - {TK_OPTION_STRING, "-menu", (char *) NULL, (char *) NULL, +static const Tk_OptionSpec tkCascadeEntryConfigSpecs[] = { + {TK_OPTION_STRING, "-menu", NULL, NULL, DEF_MENU_ENTRY_MENU, Tk_Offset(TkMenuEntry, namePtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs} + {TK_OPTION_END, NULL, NULL, NULL, + NULL, 0, -1, 0, (ClientData) tkBasicMenuEntryConfigSpecs} }; -static Tk_OptionSpec tkTearoffEntryConfigSpecs[] = { - {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL, +static const Tk_OptionSpec tkTearoffEntryConfigSpecs[] = { + {TK_OPTION_BORDER, "-background", NULL, NULL, DEF_MENU_ENTRY_BG, Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK}, - {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL, + {TK_OPTION_STRING_TABLE, "-state", NULL, NULL, DEF_MENU_ENTRY_STATE, -1, Tk_Offset(TkMenuEntry, state), 0, (ClientData) tkMenuStateStrings}, {TK_OPTION_END} }; -static Tk_OptionSpec *specsArray[] = { +static const Tk_OptionSpec *specsArray[] = { tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs, tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs, - tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs}; - + tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs +}; + /* * Menu type strings for use with Tcl_GetIndexFromObj. */ -static CONST char *menuTypeStrings[] = {"normal", "tearoff", "menubar", - (char *) NULL}; +static const char *menuTypeStrings[] = { + "normal", "tearoff", "menubar", NULL +}; -static Tk_OptionSpec tkMenuConfigSpecs[] = { - {TK_OPTION_BORDER, "-activebackground", "activeBackground", - "Foreground", DEF_MENU_ACTIVE_BG_COLOR, +static const Tk_OptionSpec tkMenuConfigSpecs[] = { + {TK_OPTION_BORDER, "-activebackground", "activeBackground", + "Foreground", DEF_MENU_ACTIVE_BG_COLOR, Tk_Offset(TkMenu, activeBorderPtr), -1, 0, (ClientData) DEF_MENU_ACTIVE_BG_MONO}, {TK_OPTION_PIXELS, "-activeborderwidth", "activeBorderWidth", - "BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH, - Tk_Offset(TkMenu, activeBorderWidthPtr), -1}, - {TK_OPTION_COLOR, "-activeforeground", "activeForeground", - "Background", DEF_MENU_ACTIVE_FG_COLOR, + "BorderWidth", DEF_MENU_ACTIVE_BORDER_WIDTH, + Tk_Offset(TkMenu, activeBorderWidthPtr), -1}, + {TK_OPTION_COLOR, "-activeforeground", "activeForeground", + "Background", DEF_MENU_ACTIVE_FG_COLOR, Tk_Offset(TkMenu, activeFgPtr), -1, 0, (ClientData) DEF_MENU_ACTIVE_FG_MONO}, {TK_OPTION_BORDER, "-background", "background", "Background", DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, borderPtr), -1, 0, (ClientData) DEF_MENU_BG_MONO}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background"}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth"}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background"}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_MENU_BORDER_WIDTH, Tk_Offset(TkMenu, borderWidthPtr), -1, 0}, @@ -275,14 +272,14 @@ static Tk_OptionSpec tkMenuConfigSpecs[] = { "DisabledForeground", DEF_MENU_DISABLED_FG_COLOR, Tk_Offset(TkMenu, disabledFgPtr), -1, TK_OPTION_NULL_OK, (ClientData) DEF_MENU_DISABLED_FG_MONO}, - {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground"}, + {TK_OPTION_SYNONYM, "-fg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-foreground"}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_MENU_FONT, Tk_Offset(TkMenu, fontPtr), -1}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", DEF_MENU_FG, Tk_Offset(TkMenu, fgPtr), -1}, {TK_OPTION_STRING, "-postcommand", "postCommand", "Command", - DEF_MENU_POST_COMMAND, + DEF_MENU_POST_COMMAND, Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1}, @@ -294,11 +291,11 @@ static Tk_OptionSpec tkMenuConfigSpecs[] = { Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK}, {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff", DEF_MENU_TEAROFF, -1, Tk_Offset(TkMenu, tearoff)}, - {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand", + {TK_OPTION_STRING, "-tearoffcommand", "tearOffCommand", "TearOffCommand", DEF_MENU_TEAROFF_CMD, Tk_Offset(TkMenu, tearoffCommandPtr), -1, TK_OPTION_NULL_OK}, {TK_OPTION_STRING, "-title", "title", "Title", - DEF_MENU_TITLE, Tk_Offset(TkMenu, titlePtr), -1, + DEF_MENU_TITLE, Tk_Offset(TkMenu, titlePtr), -1, TK_OPTION_NULL_OK}, {TK_OPTION_STRING_TABLE, "-type", "type", "Type", DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK, @@ -307,73 +304,70 @@ static Tk_OptionSpec tkMenuConfigSpecs[] = { }; /* - * Command line options. Put here because MenuCmd has to look at them - * along with MenuWidgetObjCmd. + * Command line options. Put here because MenuCmd has to look at them along + * with MenuWidgetObjCmd. */ static CONST char *menuOptions[] = { "activate", "add", "cget", "clone", "configure", "delete", "entrycget", "entryconfigure", "index", "insert", "invoke", "post", "postcascade", - "type", "unpost", "yposition", (char *) NULL + "type", "unpost", "xposition", "yposition", NULL }; enum options { MENU_ACTIVATE, MENU_ADD, MENU_CGET, MENU_CLONE, MENU_CONFIGURE, MENU_DELETE, MENU_ENTRYCGET, MENU_ENTRYCONFIGURE, MENU_INDEX, MENU_INSERT, MENU_INVOKE, MENU_POST, MENU_POSTCASCADE, MENU_TYPE, - MENU_UNPOST, MENU_YPOSITION + MENU_UNPOST, MENU_XPOSITION, MENU_YPOSITION }; /* - * Prototypes for static procedures in this file: + * Prototypes for static functions in this file: */ -static int CloneMenu _ANSI_ARGS_((TkMenu *menuPtr, - Tcl_Obj *newMenuName, Tcl_Obj *newMenuTypeString)); -static int ConfigureMenu _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, int objc, Tcl_Obj *CONST objv[])); -static int ConfigureMenuCloneEntries _ANSI_ARGS_(( - Tcl_Interp *interp, TkMenu *menuPtr, int index, - int objc, Tcl_Obj *CONST objv[])); -static int ConfigureMenuEntry _ANSI_ARGS_((TkMenuEntry *mePtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeleteMenuCloneEntries _ANSI_ARGS_((TkMenu *menuPtr, - int first, int last)); -static void DestroyMenuHashTable _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); -static void DestroyMenuInstance _ANSI_ARGS_((TkMenu *menuPtr)); -static void DestroyMenuEntry _ANSI_ARGS_((char *memPtr)); -static int GetIndexFromCoords - _ANSI_ARGS_((Tcl_Interp *interp, TkMenu *menuPtr, - char *string, int *indexPtr)); -static int MenuDoYPosition _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, Tcl_Obj *objPtr)); -static int MenuAddOrInsert _ANSI_ARGS_((Tcl_Interp *interp, +static int CloneMenu(TkMenu *menuPtr, Tcl_Obj *newMenuName, + Tcl_Obj *newMenuTypeString); +static int ConfigureMenu(Tcl_Interp *interp, TkMenu *menuPtr, + int objc, Tcl_Obj *CONST objv[]); +static int ConfigureMenuCloneEntries(Tcl_Interp *interp, + TkMenu *menuPtr, int index, + int objc, Tcl_Obj *CONST objv[]); +static int ConfigureMenuEntry(TkMenuEntry *mePtr, + int objc, Tcl_Obj *CONST objv[]); +static void DeleteMenuCloneEntries(TkMenu *menuPtr, + int first, int last); +static void DestroyMenuHashTable(ClientData clientData, + Tcl_Interp *interp); +static void DestroyMenuInstance(TkMenu *menuPtr); +static void DestroyMenuEntry(char *memPtr); +static int GetIndexFromCoords(Tcl_Interp *interp, TkMenu *menuPtr, + char *string, int *indexPtr); +static int MenuDoYPosition(Tcl_Interp *interp, + TkMenu *menuPtr, Tcl_Obj *objPtr); +static int MenuDoXPosition(Tcl_Interp *interp, + TkMenu *menuPtr, Tcl_Obj *objPtr); +static int MenuAddOrInsert(Tcl_Interp *interp, TkMenu *menuPtr, Tcl_Obj *indexPtr, int objc, - Tcl_Obj *CONST objv[])); -static int MenuCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static void MenuCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static TkMenuEntry * MenuNewEntry _ANSI_ARGS_((TkMenu *menuPtr, int index, - int type)); -static char * MenuVarProc _ANSI_ARGS_((ClientData clientData, + Tcl_Obj *CONST objv[]); +static int MenuCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static void MenuCmdDeletedProc(ClientData clientData); +static TkMenuEntry * MenuNewEntry(TkMenu *menuPtr, int index, int type); +static char * MenuVarProc(ClientData clientData, Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static int MenuWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static void MenuWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static int PostProcessEntry _ANSI_ARGS_((TkMenuEntry *mePtr)); -static void RecursivelyDeleteMenu _ANSI_ARGS_((TkMenu *menuPtr)); -static void UnhookCascadeEntry _ANSI_ARGS_((TkMenuEntry *mePtr)); -static Tcl_ExitProc TkMenuCleanup; + CONST char *name2, int flags); +static int MenuWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static void MenuWorldChanged(ClientData instanceData); +static int PostProcessEntry(TkMenuEntry *mePtr); +static void RecursivelyDeleteMenu(TkMenu *menuPtr); +static void UnhookCascadeEntry(TkMenuEntry *mePtr); +static void TkMenuCleanup(ClientData unused); /* * The structure below is a list of procs that respond to certain window - * manager events. One of these includes a font change, which forces - * the geometry proc to be called. + * manager events. One of these includes a font change, which forces the + * geometry proc to be called. */ static Tk_ClassProcs menuClass = { @@ -386,8 +380,7 @@ static Tk_ClassProcs menuClass = { * * TkCreateMenuCmd -- * - * Called by Tk at initialization time to create the menu - * command. + * Called by Tk at initialization time to create the menu command. * * Results: * A standard Tcl result. @@ -407,14 +400,14 @@ FreeOptionTables( } int -TkCreateMenuCmd(interp) - Tcl_Interp *interp; /* Interpreter we are creating the - * command in. */ +TkCreateMenuCmd( + Tcl_Interp *interp) /* Interpreter we are creating the command + * in. */ { - TkMenuOptionTables *optionTablesPtr = + TkMenuOptionTables *optionTablesPtr = (TkMenuOptionTables *) ckalloc(sizeof(TkMenuOptionTables)); - optionTablesPtr->menuOptionTable = + optionTablesPtr->menuOptionTable = Tk_CreateOptionTable(interp, tkMenuConfigSpecs); optionTablesPtr->entryOptionTables[TEAROFF_ENTRY] = Tk_CreateOptionTable(interp, specsArray[TEAROFF_ENTRY]); @@ -444,9 +437,8 @@ TkCreateMenuCmd(interp) * * MenuCmd -- * - * This procedure is invoked to process the "menu" Tcl - * command. See the user documentation for details on - * what it does. + * This function is invoked to process the "menu" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -458,21 +450,19 @@ TkCreateMenuCmd(interp) */ static int -MenuCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +MenuCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { Tk_Window tkwin = Tk_MainWindow(interp); - Tk_Window new; + Tk_Window newWin; register TkMenu *menuPtr; TkMenuReferences *menuRefPtr; - int i, index; - int toplevel; + int i, index, toplevel; char *windowName; - static CONST char *typeStringList[] = {"-type", (char *) NULL}; + static CONST char *typeStringList[] = {"-type", NULL}; TkMenuOptionTables *optionTablesPtr = (TkMenuOptionTables *) clientData; if (objc < 2) { @@ -494,23 +484,23 @@ MenuCmd(clientData, interp, objc, objv) } } - windowName = Tcl_GetStringFromObj(objv[1], NULL); - new = Tk_CreateWindowFromPath(interp, tkwin, windowName, toplevel ? "" - : NULL); - if (new == NULL) { + windowName = Tcl_GetString(objv[1]); + newWin = Tk_CreateWindowFromPath(interp, tkwin, windowName, + toplevel ? "" : NULL); + if (newWin == NULL) { return TCL_ERROR; } /* - * Initialize the data structure for the menu. Note that the - * menuPtr is eventually freed in 'TkMenuEventProc' in tkMenuDraw.c, - * when Tcl_EventuallyFree is called. + * Initialize the data structure for the menu. Note that the menuPtr is + * eventually freed in 'TkMenuEventProc' in tkMenuDraw.c, when + * Tcl_EventuallyFree is called. */ menuPtr = (TkMenu *) ckalloc(sizeof(TkMenu)); memset(menuPtr, 0, sizeof(TkMenu)); - menuPtr->tkwin = new; - menuPtr->display = Tk_Display(new); + menuPtr->tkwin = newWin; + menuPtr->display = Tk_Display(newWin); menuPtr->interp = interp; menuPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd, @@ -524,7 +514,8 @@ MenuCmd(clientData, interp, objc, objv) Tk_SetClass(menuPtr->tkwin, "Menu"); Tk_SetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr); - Tk_CreateEventHandler(new, ExposureMask|StructureNotifyMask|ActivateMask, + Tk_CreateEventHandler(newWin, + ExposureMask|StructureNotifyMask|ActivateMask, TkMenuEventProc, (ClientData) menuPtr); if (Tk_InitOptions(interp, (char *) menuPtr, menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin) @@ -550,38 +541,36 @@ MenuCmd(clientData, interp, objc, objv) /* * If a menu has a parent menu pointing to it as a cascade entry, the - * parent menu needs to be told that this menu now exists so that - * the platform-part of the menu is correctly updated. + * parent menu needs to be told that this menu now exists so that the + * platform-part of the menu is correctly updated. * * If a menu has an instance and has cascade entries, then each cascade - * menu must also have a parallel instance. This is especially true on - * the Mac, where each menu has to have a separate title everytime it is in - * a menubar. For instance, say you have a menu .m1 with a cascade entry - * for .m2, where .m2 does not exist yet. You then put .m1 into a menubar. + * menu must also have a parallel instance. This is especially true on the + * Mac, where each menu has to have a separate title everytime it is in a + * menubar. For instance, say you have a menu .m1 with a cascade entry for + * .m2, where .m2 does not exist yet. You then put .m1 into a menubar. * This creates a menubar instance for .m1, but since .m2 is not there, * nothing else happens. When we go to create .m2, we hook it up properly * with .m1. However, we now need to clone .m2 and assign the clone of .m2 - * to be the cascade entry for the clone of .m1. This is special case - * #1 listed in the introductory comment. + * to be the cascade entry for the clone of .m1. This is special case #1 + * listed in the introductory comment. */ if (menuRefPtr->parentEntryPtr != NULL) { - TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr; - TkMenuEntry *nextCascadePtr; - Tcl_Obj *newMenuName; - Tcl_Obj *newObjv[2]; - - while (cascadeListPtr != NULL) { + TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr; + TkMenuEntry *nextCascadePtr; + Tcl_Obj *newMenuName, *newObjv[2]; + while (cascadeListPtr != NULL) { nextCascadePtr = cascadeListPtr->nextCascadePtr; /* - * If we have a new master menu, and an existing cloned menu - * points to this menu in a cascade entry, we have to clone - * the new menu and point the entry to the clone instead - * of the menu we are creating. Otherwise, ConfigureMenuEntry - * will hook up the platform-specific cascade linkages now - * that the menu we are creating exists. + * If we have a new master menu, and an existing cloned menu + * points to this menu in a cascade entry, we have to clone the + * new menu and point the entry to the clone instead of the menu + * we are creating. Otherwise, ConfigureMenuEntry will hook up the + * platform-specific cascade linkages now that the menu we are + * creating exists. */ if ((menuPtr->masterMenuPtr != menuPtr) @@ -602,50 +591,50 @@ MenuCmd(clientData, interp, objc, objv) Tcl_IncrRefCount(normalPtr); Tcl_IncrRefCount(windowNamePtr); - newMenuName = TkNewMenuName(menuPtr->interp, + newMenuName = TkNewMenuName(menuPtr->interp, windowNamePtr, menuPtr); Tcl_IncrRefCount(newMenuName); - CloneMenu(menuPtr, newMenuName, normalPtr); + CloneMenu(menuPtr, newMenuName, normalPtr); - /* - * Now we can set the new menu instance to be the cascade entry - * of the parent's instance. - */ + /* + * Now we can set the new menu instance to be the cascade + * entry of the parent's instance. + */ newObjv[0] = Tcl_NewStringObj("-menu", -1); newObjv[1] = newMenuName; Tcl_IncrRefCount(newObjv[0]); - ConfigureMenuEntry(cascadeListPtr, 2, newObjv); + ConfigureMenuEntry(cascadeListPtr, 2, newObjv); Tcl_DecrRefCount(normalPtr); Tcl_DecrRefCount(newObjv[0]); Tcl_DecrRefCount(newObjv[1]); Tcl_DecrRefCount(windowNamePtr); - } - cascadeListPtr = nextCascadePtr; - } + } + cascadeListPtr = nextCascadePtr; + } } /* - * If there already exist toplevel widgets that refer to this menu, - * find them and notify them so that they can reconfigure their - * geometry to reflect the menu. + * If there already exist toplevel widgets that refer to this menu, find + * them and notify them so that they can reconfigure their geometry to + * reflect the menu. */ if (menuRefPtr->topLevelListPtr != NULL) { TkMenuTopLevelList *topLevelListPtr = menuRefPtr->topLevelListPtr; TkMenuTopLevelList *nextPtr; Tk_Window listtkwin; - while (topLevelListPtr != NULL) { + while (topLevelListPtr != NULL) { /* - * Need to get the next pointer first. TkSetWindowMenuBar - * changes the list, so that the next pointer is different - * after calling it. + * Need to get the next pointer first. TkSetWindowMenuBar changes + * the list, so that the next pointer is different after calling + * it. */ nextPtr = topLevelListPtr->nextPtr; listtkwin = topLevelListPtr->tkwin; - TkSetWindowMenuBar(menuPtr->interp, listtkwin, + TkSetWindowMenuBar(menuPtr->interp, listtkwin, Tk_PathName(menuPtr->tkwin), Tk_PathName(menuPtr->tkwin)); topLevelListPtr = nextPtr; } @@ -660,9 +649,9 @@ MenuCmd(clientData, interp, objc, objv) * * MenuWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -674,11 +663,11 @@ MenuCmd(clientData, interp, objc, objv) */ static int -MenuWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about menu widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +MenuWidgetObjCmd( + ClientData clientData, /* Information about menu widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { register TkMenu *menuPtr = (TkMenu *) clientData; register TkMenuEntry *mePtr; @@ -696,335 +685,331 @@ MenuWidgetObjCmd(clientData, interp, objc, objv) Tcl_Preserve((ClientData) menuPtr); switch ((enum options) option) { - case MENU_ACTIVATE: { - int index; + case MENU_ACTIVATE: { + int index; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "activate index"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if (menuPtr->active == index) { - goto done; - } - if ((index >= 0) - && ((menuPtr->entries[index]->type == SEPARATOR_ENTRY) - || (menuPtr->entries[index]->state - == ENTRY_DISABLED))) { - index = -1; - } - result = TkActivateMenuEntry(menuPtr, index); - break; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; + } + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; + } + if (menuPtr->active == index) { + goto done; + } + if ((index >= 0) && ((menuPtr->entries[index]->type==SEPARATOR_ENTRY) + || (menuPtr->entries[index]->state == ENTRY_DISABLED))) { + index = -1; + } + result = TkActivateMenuEntry(menuPtr, index); + break; + } + case MENU_ADD: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "type ?options?"); + goto error; } - case MENU_ADD: - if (objc < 3) { - Tcl_WrongNumArgs(interp, 1, objv, "add type ?options?"); - goto error; - } - if (MenuAddOrInsert(interp, menuPtr, (Tcl_Obj *) NULL, - objc - 2, objv + 2) != TCL_OK) { - goto error; - } - break; - case MENU_CGET: { - Tcl_Obj *resultPtr; + if (MenuAddOrInsert(interp, menuPtr, NULL, objc-2, objv+2) != TCL_OK) { + goto error; + } + break; + case MENU_CGET: { + Tcl_Obj *resultPtr; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "cget option"); - goto error; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + goto error; + } + resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr, + menuPtr->optionTablesPtr->menuOptionTable, objv[2], + menuPtr->tkwin); + if (resultPtr == NULL) { + goto error; + } + Tcl_SetObjResult(interp, resultPtr); + break; + } + case MENU_CLONE: + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "newMenuName ?menuType?"); + goto error; + } + result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]); + break; + case MENU_CONFIGURE: { + Tcl_Obj *resultPtr; + + if (objc == 2) { + resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, + menuPtr->optionTablesPtr->menuOptionTable, NULL, + menuPtr->tkwin); + if (resultPtr == NULL) { + result = TCL_ERROR; + } else { + result = TCL_OK; + Tcl_SetObjResult(interp, resultPtr); } - resultPtr = Tk_GetOptionValue(interp, (char *) menuPtr, + } else if (objc == 3) { + resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, menuPtr->optionTablesPtr->menuOptionTable, objv[2], menuPtr->tkwin); if (resultPtr == NULL) { - goto error; - } - Tcl_SetObjResult(interp, resultPtr); - break; - } - case MENU_CLONE: - if ((objc < 3) || (objc > 4)) { - Tcl_WrongNumArgs(interp, 1, objv, - "clone newMenuName ?menuType?"); - goto error; - } - result = CloneMenu(menuPtr, objv[2], (objc == 3) ? NULL : objv[3]); - break; - case MENU_CONFIGURE: { - Tcl_Obj *resultPtr; - - if (objc == 2) { - resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, - (Tcl_Obj *) NULL, menuPtr->tkwin); - if (resultPtr == NULL) { - result = TCL_ERROR; - } else { - result = TCL_OK; - Tcl_SetObjResult(interp, resultPtr); - } - } else if (objc == 3) { - resultPtr = Tk_GetOptionInfo(interp, (char *) menuPtr, - menuPtr->optionTablesPtr->menuOptionTable, - objv[2], menuPtr->tkwin); - if (resultPtr == NULL) { - result = TCL_ERROR; - } else { - result = TCL_OK; - Tcl_SetObjResult(interp, resultPtr); - } + result = TCL_ERROR; } else { - result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2); + result = TCL_OK; + Tcl_SetObjResult(interp, resultPtr); } - if (result != TCL_OK) { - goto error; - } - break; + } else { + result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2); } - case MENU_DELETE: { - int first, last; - - if ((objc != 3) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 1, objv, "delete first ?last?"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first) - != TCL_OK) { - goto error; - } - if (objc == 3) { - last = first; - } else { - if (TkGetMenuIndex(interp, menuPtr, objv[3], 0, &last) - != TCL_OK) { - goto error; - } - } - if (menuPtr->tearoff && (first == 0)) { + if (result != TCL_OK) { + goto error; + } + break; + } + case MENU_DELETE: { + int first, last; - /* - * Sorry, can't delete the tearoff entry; must reconfigure - * the menu. - */ - - first = 1; - } - if ((first < 0) || (last < first)) { + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "first ?last?"); + goto error; + } + + /* + * If 'first' explicitly refers to past the end of the menu, we don't + * do anything. [Bug 220950] + */ + + if (isdigit(UCHAR(Tcl_GetString(objv[2])[0])) + && Tcl_GetIntFromObj(NULL, objv[2], &first) == TCL_OK) { + if (first >= menuPtr->numEntries) { goto done; } - DeleteMenuCloneEntries(menuPtr, first, last); - break; + } else if (TkGetMenuIndex(interp,menuPtr,objv[2],0,&first) != TCL_OK){ + goto error; + } + if (objc == 3) { + last = first; + } else if (TkGetMenuIndex(interp,menuPtr,objv[3],0,&last) != TCL_OK) { + goto error; } - case MENU_ENTRYCGET: { - int index; - Tcl_Obj *resultPtr; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 1, objv, "entrycget index option"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if (index < 0) { - goto done; + if (menuPtr->tearoff && (first == 0)) { + /* + * Sorry, can't delete the tearoff entry; must reconfigure the + * menu. + */ + + first = 1; + } + if ((first < 0) || (last < first)) { + goto done; + } + DeleteMenuCloneEntries(menuPtr, first, last); + break; + } + case MENU_ENTRYCGET: { + int index; + Tcl_Obj *resultPtr; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "index option"); + goto error; + } + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; + } + if (index < 0) { + goto done; + } + mePtr = menuPtr->entries[index]; + Tcl_Preserve((ClientData) mePtr); + resultPtr = Tk_GetOptionValue(interp, (char *) mePtr, + mePtr->optionTable, objv[3], menuPtr->tkwin); + Tcl_Release((ClientData) mePtr); + if (resultPtr == NULL) { + goto error; + } + Tcl_SetObjResult(interp, resultPtr); + break; + } + case MENU_ENTRYCONFIGURE: { + int index; + Tcl_Obj *resultPtr; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index ?option value ...?"); + goto error; + } + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; + } + if (index < 0) { + goto done; + } + mePtr = menuPtr->entries[index]; + Tcl_Preserve((ClientData) mePtr); + if (objc == 3) { + resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr, + mePtr->optionTable, NULL, menuPtr->tkwin); + if (resultPtr == NULL) { + result = TCL_ERROR; + } else { + result = TCL_OK; + Tcl_SetObjResult(interp, resultPtr); } - mePtr = menuPtr->entries[index]; - Tcl_Preserve((ClientData) mePtr); - resultPtr = Tk_GetOptionValue(interp, (char *) mePtr, + } else if (objc == 4) { + resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr, mePtr->optionTable, objv[3], menuPtr->tkwin); - Tcl_Release((ClientData) mePtr); if (resultPtr == NULL) { - goto error; + result = TCL_ERROR; + } else { + result = TCL_OK; + Tcl_SetObjResult(interp, resultPtr); } - Tcl_SetObjResult(interp, resultPtr); - break; + } else { + result = ConfigureMenuCloneEntries(interp, menuPtr, index, + objc-3, objv+3); } - case MENU_ENTRYCONFIGURE: { - int index; - Tcl_Obj *resultPtr; + Tcl_Release((ClientData) mePtr); + break; + } + case MENU_INDEX: { + int index; - if (objc < 3) { - Tcl_WrongNumArgs(interp, 1, objv, - "entryconfigure index ?option value ...?"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if (index < 0) { - goto done; - } - mePtr = menuPtr->entries[index]; - Tcl_Preserve((ClientData) mePtr); - if (objc == 3) { - resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr, - mePtr->optionTable, (Tcl_Obj *) NULL, menuPtr->tkwin); - if (resultPtr == NULL) { - result = TCL_ERROR; - } else { - result = TCL_OK; - Tcl_SetObjResult(interp, resultPtr); - } - } else if (objc == 4) { - resultPtr = Tk_GetOptionInfo(interp, (char *) mePtr, - mePtr->optionTable, objv[3], menuPtr->tkwin); - if (resultPtr == NULL) { - result = TCL_ERROR; - } else { - result = TCL_OK; - Tcl_SetObjResult(interp, resultPtr); - } - } else { - result = ConfigureMenuCloneEntries(interp, menuPtr, index, - objc - 3, objv + 3); - } - Tcl_Release((ClientData) mePtr); - break; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "string"); + goto error; + } + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; } - case MENU_INDEX: { - int index; + if (index < 0) { + Tcl_SetResult(interp, "none", TCL_STATIC); + } else { + Tcl_SetIntObj(Tcl_GetObjResult(interp), index); + } + break; + } + case MENU_INSERT: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, "index type ?options?"); + goto error; + } + if (MenuAddOrInsert(interp,menuPtr,objv[2],objc-3,objv+3) != TCL_OK) { + goto error; + } + break; + case MENU_INVOKE: { + int index; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "index string"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if (index < 0) { - Tcl_SetResult(interp, "none", TCL_STATIC); - } else { - Tcl_SetIntObj(Tcl_GetObjResult(interp), index); - } - break; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; } - case MENU_INSERT: - if (objc < 4) { - Tcl_WrongNumArgs(interp, 1, objv, - "insert index type ?options?"); - goto error; - } - if (MenuAddOrInsert(interp, menuPtr, objv[2], objc - 3, - objv + 3) != TCL_OK) { - goto error; - } - break; - case MENU_INVOKE: { - int index; + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; + } + if (index < 0) { + goto done; + } + result = TkInvokeMenu(interp, menuPtr, index); + break; + } + case MENU_POST: { + int x, y; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "invoke index"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if (index < 0) { - goto done; - } - result = TkInvokeMenu(interp, menuPtr, index); - break; + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "x y"); + goto error; + } + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { + goto error; } - case MENU_POST: { - int x, y; - if (objc != 4) { - Tcl_WrongNumArgs(interp, 1, objv, "post x y"); - goto error; - } - if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { - goto error; - } + /* + * Tearoff menus are posted differently on Mac and Windows than + * non-tearoffs. TkpPostMenu does not actually map the menu's window + * on those platforms, and popup menus have to be handled specially. + */ - /* - * Tearoff menus are posted differently on Mac and Windows than - * non-tearoffs. TkpPostMenu does not actually map the menu's - * window on those platforms, and popup menus have to be - * handled specially. - */ - - if (menuPtr->menuType != TEAROFF_MENU) { - result = TkpPostMenu(interp, menuPtr, x, y); - } else { - result = TkPostTearoffMenu(interp, menuPtr, x, y); - } - break; + if (menuPtr->menuType != TEAROFF_MENU) { + result = TkpPostMenu(interp, menuPtr, x, y); + } else { + result = TkPostTearoffMenu(interp, menuPtr, x, y); } - case MENU_POSTCASCADE: { - int index; + break; + } + case MENU_POSTCASCADE: { + int index; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "postcascade index"); - goto error; - } + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; + } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if ((index < 0) || (menuPtr->entries[index]->type - != CASCADE_ENTRY)) { - result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL); - } else { - result = TkPostSubmenu(interp, menuPtr, - menuPtr->entries[index]); - } - break; + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; + } + if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) { + result = TkPostSubmenu(interp, menuPtr, NULL); + } else { + result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]); } - case MENU_TYPE: { - int index; + break; + } + case MENU_TYPE: { + int index; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "type index"); - goto error; - } - if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) - != TCL_OK) { - goto error; - } - if (index < 0) { - goto done; - } - if (menuPtr->entries[index]->type == TEAROFF_ENTRY) { - Tcl_SetResult(interp, "tearoff", TCL_STATIC); - } else { - Tcl_SetStringObj(Tcl_GetObjResult(interp), - menuEntryTypeStrings[menuPtr->entries[index]->type], - -1); - } - break; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; } - case MENU_UNPOST: - if (objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "unpost"); - goto error; - } - Tk_UnmapWindow(menuPtr->tkwin); - result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL); - break; - case MENU_YPOSITION: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "yposition index"); - goto error; - } - result = MenuDoYPosition(interp, menuPtr, objv[2]); - break; + if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { + goto error; + } + if (index < 0) { + goto done; + } + if (menuPtr->entries[index]->type == TEAROFF_ENTRY) { + Tcl_SetResult(interp, "tearoff", TCL_STATIC); + } else { + Tcl_SetStringObj(Tcl_GetObjResult(interp), + menuEntryTypeStrings[menuPtr->entries[index]->type], -1); + } + break; } - done: + case MENU_UNPOST: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + goto error; + } + Tk_UnmapWindow(menuPtr->tkwin); + result = TkPostSubmenu(interp, menuPtr, NULL); + break; + case MENU_XPOSITION: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; + } + result = MenuDoXPosition(interp, menuPtr, objv[2]); + break; + case MENU_YPOSITION: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + goto error; + } + result = MenuDoYPosition(interp, menuPtr, objv[2]); + break; + } + done: Tcl_Release((ClientData) menuPtr); return result; - error: + error: Tcl_Release((ClientData) menuPtr); return TCL_ERROR; } @@ -1034,29 +1019,29 @@ MenuWidgetObjCmd(clientData, interp, objc, objv) * * TkInvokeMenu -- * - * Given a menu and an index, takes the appropriate action for the - * entry associated with that index. + * Given a menu and an index, takes the appropriate action for the entry + * associated with that index. * * Results: * Standard Tcl result. * * Side effects: - * Commands may get excecuted; variables may get set; sub-menus may - * get posted. + * Commands may get excecuted; variables may get set; sub-menus may get + * posted. * *---------------------------------------------------------------------- */ int -TkInvokeMenu(interp, menuPtr, index) - Tcl_Interp *interp; /* The interp that the menu lives in. */ - TkMenu *menuPtr; /* The menu we are invoking. */ - int index; /* The zero based index of the item we - * are invoking */ +TkInvokeMenu( + Tcl_Interp *interp, /* The interp that the menu lives in. */ + TkMenu *menuPtr, /* The menu we are invoking. */ + int index) /* The zero based index of the item we are + * invoking. */ { int result = TCL_OK; TkMenuEntry *mePtr; - + if (index < 0) { goto done; } @@ -1104,11 +1089,13 @@ TkInvokeMenu(interp, menuPtr, index) } Tcl_DecrRefCount(valuePtr); } + /* - * We check numEntries in addition to whether the menu entry - * has a command because that goes to zero if the menu gets - * deleted (e.g., during command evaluation). + * We check numEntries in addition to whether the menu entry has a command + * because that goes to zero if the menu gets deleted (e.g., during + * command evaluation). */ + if ((menuPtr->numEntries != 0) && (result == TCL_OK) && (mePtr->commandPtr != NULL)) { Tcl_Obj *commandPtr = mePtr->commandPtr; @@ -1118,7 +1105,7 @@ TkInvokeMenu(interp, menuPtr, index) Tcl_DecrRefCount(commandPtr); } Tcl_Release((ClientData) mePtr); - done: + done: return result; } @@ -1127,10 +1114,9 @@ TkInvokeMenu(interp, menuPtr, index) * * DestroyMenuInstance -- * - * This procedure is invoked by TkDestroyMenu - * to clean up the internal structure of a menu at a safe time - * (when no-one is using it anymore). Only takes care of one instance - * of the menu. + * This function is invoked by TkDestroyMenu to clean up the internal + * structure of a menu at a safe time (when no-one is using it anymore). + * Only takes care of one instance of the menu. * * Results: * None. @@ -1142,8 +1128,8 @@ TkInvokeMenu(interp, menuPtr, index) */ static void -DestroyMenuInstance(menuPtr) - TkMenu *menuPtr; /* Info about menu widget. */ +DestroyMenuInstance( + TkMenu *menuPtr) /* Info about menu widget. */ { int i; TkMenu *menuInstancePtr; @@ -1151,19 +1137,19 @@ DestroyMenuInstance(menuPtr) Tcl_Obj *newObjv[2]; TkMenu *parentMasterMenuPtr; TkMenuEntry *parentMasterEntryPtr; - + /* * If the menu has any cascade menu entries pointing to it, the cascade * entries need to be told that the menu is going away. We need to clear - * the menu ptr field in the menu reference at this point in the code - * so that everything else can forget about this menu properly. We also - * need to reset -menu field of all entries that are not master menus - * back to this entry name if this is a master menu pointed to by another - * master menu. If there is a clone menu that points to this menu, - * then this menu is itself a clone, so when this menu goes away, - * the -menu field of the pointing entry must be set back to this - * menu's master menu name so that later if another menu is created - * the cascade hierarchy can be maintained. + * the menu ptr field in the menu reference at this point in the code so + * that everything else can forget about this menu properly. We also need + * to reset -menu field of all entries that are not master menus back to + * this entry name if this is a master menu pointed to by another master + * menu. If there is a clone menu that points to this menu, then this menu + * is itself a clone, so when this menu goes away, the -menu field of the + * pointing entry must be set back to this menu's master menu name so that + * later if another menu is created the cascade hierarchy can be + * maintained. */ TkpDestroyMenu(menuPtr); @@ -1178,7 +1164,7 @@ DestroyMenuInstance(menuPtr) for (; cascadePtr != NULL; cascadePtr = nextCascadePtr) { nextCascadePtr = cascadePtr->nextCascadePtr; - + if (menuPtr->masterMenuPtr != menuPtr) { Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1); @@ -1187,10 +1173,12 @@ DestroyMenuInstance(menuPtr) parentMasterMenuPtr->entries[cascadePtr->index]; newObjv[0] = menuNamePtr; newObjv[1] = parentMasterEntryPtr->namePtr; + /* - * It is possible that the menu info is out of sync, and - * these things point to NULL, so verify existence [Bug: 3402] + * It is possible that the menu info is out of sync, and these + * things point to NULL, so verify existence [Bug: 3402] */ + if (newObjv[0] && newObjv[1]) { Tcl_IncrRefCount(newObjv[0]); Tcl_IncrRefCount(newObjv[1]); @@ -1199,38 +1187,37 @@ DestroyMenuInstance(menuPtr) Tcl_DecrRefCount(newObjv[1]); } } else { - ConfigureMenuEntry(cascadePtr, 0, (Tcl_Obj **) NULL); + ConfigureMenuEntry(cascadePtr, 0, NULL); } } - + if (menuPtr->masterMenuPtr != menuPtr) { - for (menuInstancePtr = menuPtr->masterMenuPtr; - menuInstancePtr != NULL; - menuInstancePtr = menuInstancePtr->nextInstancePtr) { - if (menuInstancePtr->nextInstancePtr == menuPtr) { - menuInstancePtr->nextInstancePtr = - menuInstancePtr->nextInstancePtr->nextInstancePtr; - break; - } - } - } else if (menuPtr->nextInstancePtr != NULL) { - panic("Attempting to delete master menu when there are still clones."); - } + for (menuInstancePtr = menuPtr->masterMenuPtr; + menuInstancePtr != NULL; + menuInstancePtr = menuInstancePtr->nextInstancePtr) { + if (menuInstancePtr->nextInstancePtr == menuPtr) { + menuInstancePtr->nextInstancePtr = + menuInstancePtr->nextInstancePtr->nextInstancePtr; + break; + } + } + } else if (menuPtr->nextInstancePtr != NULL) { + Tcl_Panic("Attempting to delete master menu when there are still clones."); + } /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeConfigOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeConfigOptions handle all the standard option-related stuff. */ for (i = menuPtr->numEntries; --i >= 0; ) { /* - * As each menu entry is deleted from the end of the array of - * entries, decrement menuPtr->numEntries. Otherwise, the act of - * deleting menu entry i will dereference freed memory attempting - * to queue a redraw for menu entries (i+1)...numEntries. + * As each menu entry is deleted from the end of the array of entries, + * decrement menuPtr->numEntries. Otherwise, the act of deleting menu + * entry i will dereference freed memory attempting to queue a redraw + * for menu entries (i+1)...numEntries. */ - + DestroyMenuEntry((char *) menuPtr->entries[i]); menuPtr->numEntries = i; } @@ -1238,7 +1225,7 @@ DestroyMenuInstance(menuPtr) ckfree((char *) menuPtr->entries); } TkMenuFreeDrawOptions(menuPtr); - Tk_FreeConfigOptions((char *) menuPtr, + Tk_FreeConfigOptions((char *) menuPtr, menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin); if (menuPtr->tkwin != NULL) { Tk_Window tkwin = menuPtr->tkwin; @@ -1252,11 +1239,11 @@ DestroyMenuInstance(menuPtr) * * TkDestroyMenu -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a menu at a safe time - * (when no-one is using it anymore). If called on a master instance, - * destroys all of the slave instances. If called on a non-master - * instance, just destroys that instance. + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of a menu at a safe time (when no-one is + * using it anymore). If called on a master instance, destroys all of the + * slave instances. If called on a non-master instance, just destroys + * that instance. * * Results: * None. @@ -1268,8 +1255,8 @@ DestroyMenuInstance(menuPtr) */ void -TkDestroyMenu(menuPtr) - TkMenu *menuPtr; /* Info about menu widget. */ +TkDestroyMenu( + TkMenu *menuPtr) /* Info about menu widget. */ { TkMenu *menuInstancePtr; TkMenuTopLevelList *topLevelListPtr, *nextTopLevelPtr; @@ -1279,20 +1266,21 @@ TkDestroyMenu(menuPtr) } Tcl_Preserve(menuPtr); - + /* - * Now destroy all non-tearoff instances of this menu if this is a - * parent menu. Is this loop safe enough? Are there going to be - * destroy bindings on child menus which kill the parent? If not, - * we have to do a slightly more complex scheme. + * Now destroy all non-tearoff instances of this menu if this is a parent + * menu. Is this loop safe enough? Are there going to be destroy bindings + * on child menus which kill the parent? If not, we have to do a slightly + * more complex scheme. */ menuPtr->menuFlags |= MENU_DELETION_PENDING; if (menuPtr->menuRefPtr != NULL) { /* - * If any toplevel widgets have this menu as their menubar, - * the geometry of the window may have to be recalculated. + * If any toplevel widgets have this menu as their menubar, the + * geometry of the window may have to be recalculated. */ + topLevelListPtr = menuPtr->menuRefPtr->topLevelListPtr; while (topLevelListPtr != NULL) { nextTopLevelPtr = topLevelListPtr->nextPtr; @@ -1306,11 +1294,13 @@ TkDestroyMenu(menuPtr) menuPtr->nextInstancePtr = menuInstancePtr->nextInstancePtr; if (menuInstancePtr->tkwin != NULL) { Tk_Window tkwin = menuInstancePtr->tkwin; - /* - * Note: it may be desirable to NULL out the tkwin - * field of menuInstancePtr here: + + /* + * Note: it may be desirable to NULL out the tkwin field of + * menuInstancePtr here: * menuInstancePtr->tkwin = NULL; */ + Tk_DestroyWindow(tkwin); } } @@ -1327,12 +1317,12 @@ TkDestroyMenu(menuPtr) * UnhookCascadeEntry -- * * This entry is removed from the list of entries that point to the - * cascade menu. This is done in preparation for changing the menu - * that this entry points to. - * - * At the end of this function, the menu entry no longer contains - * a reference to a 'TkMenuReferences' structure, and therefore - * no such structure contains a reference to this menu entry either. + * cascade menu. This is done in preparation for changing the menu that + * this entry points to. + * + * At the end of this function, the menu entry no longer contains a + * reference to a 'TkMenuReferences' structure, and therefore no such + * structure contains a reference to this menu entry either. * * Results: * None @@ -1344,9 +1334,9 @@ TkDestroyMenu(menuPtr) */ static void -UnhookCascadeEntry(mePtr) - TkMenuEntry *mePtr; /* The cascade entry we are removing - * from the cascade list. */ +UnhookCascadeEntry( + TkMenuEntry *mePtr) /* The cascade entry we are removing from the + * cascade list. */ { TkMenuEntry *cascadeEntryPtr; TkMenuEntry *prevCascadePtr; @@ -1354,35 +1344,34 @@ UnhookCascadeEntry(mePtr) menuRefPtr = mePtr->childMenuRefPtr; if (menuRefPtr == NULL) { - return; + return; } - + cascadeEntryPtr = menuRefPtr->parentEntryPtr; if (cascadeEntryPtr == NULL) { TkFreeMenuReferences(menuRefPtr); mePtr->childMenuRefPtr = NULL; return; } - + /* - * Singularly linked list deletion. The two special cases are - * 1. one element; 2. The first element is the one we want. + * Singularly linked list deletion. The two special cases are 1. one + * element; 2. The first element is the one we want. */ if (cascadeEntryPtr == mePtr) { if (cascadeEntryPtr->nextCascadePtr == NULL) { - /* - * This is the last menu entry which points to this - * menu, so we need to clear out the list pointer in the - * cascade itself. + * This is the last menu entry which points to this menu, so we + * need to clear out the list pointer in the cascade itself. */ menuRefPtr->parentEntryPtr = NULL; - /* - * The original field is set to zero below, after it is - * freed. + + /* + * The original field is set to zero below, after it is freed. */ + TkFreeMenuReferences(menuRefPtr); } else { menuRefPtr->parentEntryPtr = cascadeEntryPtr->nextCascadePtr; @@ -1392,15 +1381,15 @@ UnhookCascadeEntry(mePtr) for (prevCascadePtr = cascadeEntryPtr, cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr; cascadeEntryPtr != NULL; - prevCascadePtr = cascadeEntryPtr, + prevCascadePtr = cascadeEntryPtr, cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { if (cascadeEntryPtr == mePtr){ prevCascadePtr->nextCascadePtr = - cascadeEntryPtr->nextCascadePtr; + cascadeEntryPtr->nextCascadePtr; cascadeEntryPtr->nextCascadePtr = NULL; break; } - } + } mePtr->nextCascadePtr = NULL; } mePtr->childMenuRefPtr = NULL; @@ -1411,9 +1400,9 @@ UnhookCascadeEntry(mePtr) * * DestroyMenuEntry -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a menu entry at a safe time - * (when no-one is using it anymore). + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of a menu entry at a safe time (when no-one + * is using it anymore). * * Results: * None. @@ -1425,56 +1414,57 @@ UnhookCascadeEntry(mePtr) */ static void -DestroyMenuEntry(memPtr) - char *memPtr; /* Pointer to entry to be freed. */ +DestroyMenuEntry( + char *memPtr) /* Pointer to entry to be freed. */ { register TkMenuEntry *mePtr = (TkMenuEntry *) memPtr; TkMenu *menuPtr = mePtr->menuPtr; if (menuPtr->postedCascade == mePtr) { /* - * Ignore errors while unposting the menu, since it's possible - * that the menu has already been deleted and the unpost will - * generate an error. + * Ignore errors while unposting the menu, since it's possible that + * the menu has already been deleted and the unpost will generate an + * error. */ - TkPostSubmenu(menuPtr->interp, menuPtr, (TkMenuEntry *) NULL); + TkPostSubmenu(menuPtr->interp, menuPtr, NULL); } /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeConfigOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeConfigOptions handle all the standard option-related stuff. */ if (mePtr->type == CASCADE_ENTRY) { if (menuPtr->masterMenuPtr != menuPtr) { TkMenu *destroyThis = NULL; - /* - * The menu as a whole is a clone. We must delete the clone - * of the cascaded menu for the particular entry we are - * destroying. + /* + * The menu as a whole is a clone. We must delete the clone of the + * cascaded menu for the particular entry we are destroying. */ + TkMenuReferences *menuRefPtr = mePtr->childMenuRefPtr; + if (menuRefPtr != NULL) { destroyThis = menuRefPtr->menuPtr; - /* - * But only if it is a clone. What can happen is that - * we are in the middle of deleting a menu and this - * menu pointer has already been reset to point to the - * original menu. In that case we have nothing special - * to do. + + /* + * But only if it is a clone. What can happen is that we are + * in the middle of deleting a menu and this menu pointer has + * already been reset to point to the original menu. In that + * case we have nothing special to do. */ - if ((destroyThis != NULL) - && (destroyThis->masterMenuPtr == destroyThis)) { + + if ((destroyThis != NULL) + && (destroyThis->masterMenuPtr == destroyThis)) { destroyThis = NULL; } } UnhookCascadeEntry(mePtr); if (menuRefPtr != NULL) { - if (menuRefPtr->menuPtr == destroyThis) { - menuRefPtr->menuPtr = NULL; - } + if (menuRefPtr->menuPtr == destroyThis) { + menuRefPtr->menuPtr = NULL; + } if (destroyThis != NULL) { TkDestroyMenu(destroyThis); } @@ -1489,10 +1479,11 @@ DestroyMenuEntry(memPtr) if (mePtr->selectImage != NULL) { Tk_FreeImage(mePtr->selectImage); } - if (((mePtr->type == CHECK_BUTTON_ENTRY) + if (((mePtr->type == CHECK_BUTTON_ENTRY) || (mePtr->type == RADIO_BUTTON_ENTRY)) && (mePtr->namePtr != NULL)) { - char *varName = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + char *varName = Tcl_GetString(mePtr->namePtr); + Tcl_UntraceVar(menuPtr->interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, (ClientData) mePtr); @@ -1508,22 +1499,22 @@ DestroyMenuEntry(memPtr) * * MenuWorldChanged -- * - * This procedure is called when the world has changed in some - * way (such as the fonts in the system changing) and the widget needs - * to recompute all its graphics contexts and determine its new geometry. + * This function is called when the world has changed in some way (such + * as the fonts in the system changing) and the widget needs to recompute + * all its graphics contexts and determine its new geometry. * * Results: - * None. + * None. * * Side effects: - * Menu will be relayed out and redisplayed. + * Menu will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ static void -MenuWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +MenuWorldChanged( + ClientData instanceData) /* Information about widget. */ { TkMenu *menuPtr = (TkMenu *) instanceData; int i; @@ -1542,40 +1533,39 @@ MenuWorldChanged(instanceData) * * ConfigureMenu -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a menu widget. + * This function is called to process an argv/argc list, plus the Tk + * option database, in order to configure (or reconfigure) a menu widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, font, etc. get set - * for menuPtr; old resources get freed, if there were any. + * Configuration information, such as colors, font, etc. get set for + * menuPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureMenu(interp, menuPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - register TkMenu *menuPtr; /* Information about widget; may or may - * not already have values for some fields. */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ +ConfigureMenu( + Tcl_Interp *interp, /* Used for error reporting. */ + register TkMenu *menuPtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *CONST objv[]) /* Arguments. */ { int i; TkMenu *menuListPtr, *cleanupPtr; int result; - + for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { menuListPtr->errorStructPtr = (Tk_SavedOptions *) ckalloc(sizeof(Tk_SavedOptions)); result = Tk_SetOptions(interp, (char *) menuListPtr, - menuListPtr->optionTablesPtr->menuOptionTable, objc, objv, - menuListPtr->tkwin, menuListPtr->errorStructPtr, (int *) NULL); + menuListPtr->optionTablesPtr->menuOptionTable, objc, objv, + menuListPtr->tkwin, menuListPtr->errorStructPtr, NULL); if (result != TCL_OK) { for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != menuListPtr; @@ -1593,25 +1583,24 @@ ConfigureMenu(interp, menuPtr, objc, objv) } /* - * When a menu is created, the type is in all of the arguments - * to the menu command. Let Tk_ConfigureWidget take care of - * parsing them, and then set the type after we can look at - * the type string. Once set, a menu's type cannot be changed + * When a menu is created, the type is in all of the arguments to the + * menu command. Let Tk_ConfigureWidget take care of parsing them, and + * then set the type after we can look at the type string. Once set, a + * menu's type cannot be changed */ - + if (menuListPtr->menuType == UNKNOWN_TYPE) { Tcl_GetIndexFromObj(NULL, menuListPtr->menuTypePtr, menuTypeStrings, NULL, 0, &menuListPtr->menuType); /* - * Configure the new window to be either a pop-up menu - * or a tear-off menu. - * We don't do this for menubars since they are not toplevel - * windows. Also, since this gets called before CloneMenu has - * a chance to set the menuType field, we have to look at the + * Configure the new window to be either a pop-up menu or a + * tear-off menu. We don't do this for menubars since they are not + * toplevel windows. Also, since this gets called before CloneMenu + * has a chance to set the menuType field, we have to look at the * menuTypeName field to tell that this is a menu bar. */ - + if (menuListPtr->menuType == MASTER_MENU) { TkpMakeMenuWindow(menuListPtr->tkwin, 1); } else if (menuListPtr->menuType == TEAROFF_MENU) { @@ -1621,10 +1610,10 @@ ConfigureMenu(interp, menuPtr, objc, objv) /* - * Depending on the -tearOff option, make sure that there is or - * isn't an initial tear-off entry at the beginning of the menu. + * Depending on the -tearOff option, make sure that there is or isn't + * an initial tear-off entry at the beginning of the menu. */ - + if (menuListPtr->tearoff) { if ((menuListPtr->numEntries == 0) || (menuListPtr->entries[0]->type != TEAROFF_ENTRY)) { @@ -1647,7 +1636,7 @@ ConfigureMenu(interp, menuPtr, objc, objv) } else if ((menuListPtr->numEntries > 0) && (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) { int i; - + Tcl_EventuallyFree((ClientData) menuListPtr->entries[0], DestroyMenuEntry); @@ -1663,21 +1652,21 @@ ConfigureMenu(interp, menuPtr, objc, objv) } TkMenuConfigureDrawOptions(menuListPtr); - + /* * After reconfiguring a menu, we need to reconfigure all of the - * entries in the menu, since some of the things in the children - * (such as graphics contexts) may have to change to reflect changes - * in the parent. + * entries in the menu, since some of the things in the children (such + * as graphics contexts) may have to change to reflect changes in the + * parent. */ - + for (i = 0; i < menuListPtr->numEntries; i++) { TkMenuEntry *mePtr; - + mePtr = menuListPtr->entries[i]; - ConfigureMenuEntry(mePtr, 0, (Tcl_Obj **) NULL); + ConfigureMenuEntry(mePtr, 0, NULL); } - + TkEventuallyRecomputeMenu(menuListPtr); } @@ -1690,7 +1679,6 @@ ConfigureMenu(interp, menuPtr, objc, objv) return TCL_OK; } - /* *---------------------------------------------------------------------- @@ -1698,23 +1686,23 @@ ConfigureMenu(interp, menuPtr, objc, objv) * PostProcessEntry -- * * This is called by ConfigureMenuEntry to do all of the configuration - * after Tk_SetOptions is called. This is separate - * so that error handling is easier. + * after Tk_SetOptions is called. This is separate so that error handling + * is easier. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information such as label and accelerator get - * set for mePtr; old resources get freed, if there were any. + * Configuration information such as label and accelerator get set for + * mePtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -PostProcessEntry(mePtr) - TkMenuEntry *mePtr; /* The entry we are configuring. */ +PostProcessEntry( + TkMenuEntry *mePtr) /* The entry we are configuring. */ { TkMenu *menuPtr = mePtr->menuPtr; int index = mePtr->index; @@ -1722,9 +1710,9 @@ PostProcessEntry(mePtr) Tk_Image image; /* - * The code below handles special configuration stuff not taken - * care of by Tk_ConfigureWidget, such as special processing for - * defaults, sizing strings, graphics contexts, etc. + * The code below handles special configuration stuff not taken care of by + * Tk_ConfigureWidget, such as special processing for defaults, sizing + * strings, graphics contexts, etc. */ if (mePtr->labelPtr == NULL) { @@ -1752,16 +1740,15 @@ PostProcessEntry(mePtr) * prevent compiler warning. */ /* - * This is a cascade entry. If the menu that the cascade entry - * is pointing to has changed, we need to remove this entry - * from the list of entries pointing to the old menu, and add a - * cascade reference to the list of entries pointing to the - * new menu. + * This is a cascade entry. If the menu that the cascade entry is + * pointing to has changed, we need to remove this entry from the list + * of entries pointing to the old menu, and add a cascade reference to + * the list of entries pointing to the new menu. * * BUG: We are not recloning for special case #3 yet. */ - - name = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + + name = Tcl_GetString(mePtr->namePtr); if (mePtr->childMenuRefPtr != NULL) { oldHashKey = Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp), mePtr->childMenuRefPtr->hashEntryPtr); @@ -1770,7 +1757,7 @@ PostProcessEntry(mePtr) } } - if ((mePtr->childMenuRefPtr == NULL) + if ((mePtr->childMenuRefPtr == NULL) || (strcmp(oldHashKey, name) != 0)) { menuRefPtr = TkCreateMenuReferences(menuPtr->interp, name); mePtr->childMenuRefPtr = menuRefPtr; @@ -1788,11 +1775,11 @@ PostProcessEntry(mePtr) break; } } - + /* * Put the item at the front of the list. */ - + if (!alreadyThere) { mePtr->nextCascadePtr = menuRefPtr->parentEntryPtr; menuRefPtr->parentEntryPtr = mePtr; @@ -1800,23 +1787,20 @@ PostProcessEntry(mePtr) } } } - + if (TkMenuConfigureEntryDrawOptions(mePtr, index) != TCL_OK) { return TCL_ERROR; } - if (TkpConfigureMenuEntry(mePtr) != TCL_OK) { - return TCL_ERROR; - } - /* - * Get the images for the entry, if there are any. Allocate the - * new images before freeing the old ones, so that the reference - * counts don't go to zero and cause image data to be discarded. + * Get the images for the entry, if there are any. Allocate the new images + * before freeing the old ones, so that the reference counts don't go to + * zero and cause image data to be discarded. */ if (mePtr->imagePtr != NULL) { - char *imageString = Tcl_GetStringFromObj(mePtr->imagePtr, NULL); + char *imageString = Tcl_GetString(mePtr->imagePtr); + image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, imageString, TkMenuImageProc, (ClientData) mePtr); if (image == NULL) { @@ -1830,8 +1814,8 @@ PostProcessEntry(mePtr) } mePtr->image = image; if (mePtr->selectImagePtr != NULL) { - char *selectImageString = Tcl_GetStringFromObj( - mePtr->selectImagePtr, NULL); + char *selectImageString = Tcl_GetString(mePtr->selectImagePtr); + image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, selectImageString, TkMenuSelectImageProc, (ClientData) mePtr); if (image == NULL) { @@ -1868,12 +1852,11 @@ PostProcessEntry(mePtr) } /* - * Select the entry if the associated variable has the - * appropriate value, initialize the variable if it doesn't - * exist, then set a trace on the variable to monitor future - * changes to its value. + * Select the entry if the associated variable has the appropriate + * value, initialize the variable if it doesn't exist, then set a + * trace on the variable to monitor future changes to its value. */ - + if (mePtr->namePtr != NULL) { valuePtr = Tcl_ObjGetVar2(menuPtr->interp, mePtr->namePtr, NULL, TCL_GLOBAL_ONLY); @@ -1883,10 +1866,8 @@ PostProcessEntry(mePtr) mePtr->entryFlags &= ~ENTRY_SELECTED; if (valuePtr != NULL) { if (mePtr->onValuePtr != NULL) { - char *value = Tcl_GetStringFromObj(valuePtr, NULL); - char *onValue = Tcl_GetStringFromObj(mePtr->onValuePtr, - NULL); - + char *value = Tcl_GetString(valuePtr); + char *onValue = Tcl_GetString(mePtr->onValuePtr); if (strcmp(value, onValue) == 0) { mePtr->entryFlags |= ENTRY_SELECTED; @@ -1896,19 +1877,21 @@ PostProcessEntry(mePtr) if (mePtr->namePtr != NULL) { Tcl_ObjSetVar2(menuPtr->interp, mePtr->namePtr, NULL, (mePtr->type == CHECK_BUTTON_ENTRY) - ? mePtr->offValuePtr - : Tcl_NewObj(), - TCL_GLOBAL_ONLY); + ? mePtr->offValuePtr : Tcl_NewObj(), TCL_GLOBAL_ONLY); } } if (mePtr->namePtr != NULL) { - name = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + name = Tcl_GetString(mePtr->namePtr); Tcl_TraceVar(menuPtr->interp, name, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, (ClientData) mePtr); } } - + + if (TkpConfigureMenuEntry(mePtr) != TCL_OK) { + return TCL_ERROR; + } + return TCL_OK; } @@ -1917,41 +1900,41 @@ PostProcessEntry(mePtr) * * ConfigureMenuEntry -- * - * This procedure is called to process an argv/argc list in order - * to configure (or reconfigure) one entry in a menu. + * This function is called to process an argv/argc list in order to + * configure (or reconfigure) one entry in a menu. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information such as label and accelerator get - * set for mePtr; old resources get freed, if there were any. + * Configuration information such as label and accelerator get set for + * mePtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureMenuEntry(mePtr, objc, objv) - register TkMenuEntry *mePtr; /* Information about menu entry; may - * or may not already have values for - * some fields. */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ +ConfigureMenuEntry( + register TkMenuEntry *mePtr,/* Information about menu entry; may or may + * not already have values for some fields. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *CONST objv[]) /* Arguments. */ { TkMenu *menuPtr = mePtr->menuPtr; Tk_SavedOptions errorStruct; int result; /* - * If this entry is a check button or radio button, then remove - * its old trace procedure. + * If this entry is a check button or radio button, then remove its old + * trace function. */ if ((mePtr->namePtr != NULL) && ((mePtr->type == CHECK_BUTTON_ENTRY) || (mePtr->type == RADIO_BUTTON_ENTRY))) { - char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + char *name = Tcl_GetString(mePtr->namePtr); + Tcl_UntraceVar(menuPtr->interp, name, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuVarProc, (ClientData) mePtr); @@ -1961,7 +1944,7 @@ ConfigureMenuEntry(mePtr, objc, objv) if (menuPtr->tkwin != NULL) { if (Tk_SetOptions(menuPtr->interp, (char *) mePtr, mePtr->optionTable, objc, objv, menuPtr->tkwin, - &errorStruct, (int *) NULL) != TCL_OK) { + &errorStruct, NULL) != TCL_OK) { return TCL_ERROR; } result = PostProcessEntry(mePtr); @@ -1973,7 +1956,7 @@ ConfigureMenuEntry(mePtr, objc, objv) } TkEventuallyRecomputeMenu(menuPtr); - + return result; } @@ -1985,39 +1968,38 @@ ConfigureMenuEntry(mePtr, objc, objv) * Calls ConfigureMenuEntry for each menu in the clone chain. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information such as label and accelerator get - * set for mePtr; old resources get freed, if there were any. + * Configuration information such as label and accelerator get set for + * mePtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - TkMenu *menuPtr; /* Information about whole menu. */ - int index; /* Index of mePtr within menuPtr's - * entries. */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ +ConfigureMenuCloneEntries( + Tcl_Interp *interp, /* Used for error reporting. */ + TkMenu *menuPtr, /* Information about whole menu. */ + int index, /* Index of mePtr within menuPtr's entries. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *CONST objv[]) /* Arguments. */ { TkMenuEntry *mePtr; TkMenu *menuListPtr; int cascadeEntryChanged = 0; - TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL; + TkMenuReferences *oldCascadeMenuRefPtr, *cascadeMenuRefPtr = NULL; Tcl_Obj *oldCascadePtr = NULL; char *newCascadeName; /* - * Cascades are kind of tricky here. This is special case #3 in the comment - * at the top of this file. Basically, if a menu is the master menu of a - * clone chain, and has an entry with a cascade menu, the clones of - * the menu will point to clones of the cascade menu. We have - * to destroy the clones of the cascades, clone the new cascade - * menu, and configure the entry to point to the new clone. + * Cascades are kind of tricky here. This is special case #3 in the + * comment at the top of this file. Basically, if a menu is the master + * menu of a clone chain, and has an entry with a cascade menu, the clones + * of the menu will point to clones of the cascade menu. We have to + * destroy the clones of the cascades, clone the new cascade menu, and + * configure the entry to point to the new clone. */ mePtr = menuPtr->masterMenuPtr->entries[index]; @@ -2036,21 +2018,20 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) char *oldCascadeName; if (mePtr->namePtr != NULL) { - newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + newCascadeName = Tcl_GetString(mePtr->namePtr); } else { newCascadeName = NULL; } - + if ((oldCascadePtr == NULL) && (mePtr->namePtr == NULL)) { cascadeEntryChanged = 0; } else if (((oldCascadePtr == NULL) && (mePtr->namePtr != NULL)) - || ((oldCascadePtr != NULL) + || ((oldCascadePtr != NULL) && (mePtr->namePtr == NULL))) { cascadeEntryChanged = 1; } else { - oldCascadeName = Tcl_GetStringFromObj(oldCascadePtr, - NULL); - cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName) + oldCascadeName = Tcl_GetString(oldCascadePtr); + cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName) != 0); } if (oldCascadePtr != NULL) { @@ -2060,20 +2041,20 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) if (cascadeEntryChanged) { if (mePtr->namePtr != NULL) { - newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + newCascadeName = Tcl_GetString(mePtr->namePtr); cascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp, newCascadeName); } } - for (menuListPtr = menuPtr->masterMenuPtr->nextInstancePtr; + for (menuListPtr = menuPtr->masterMenuPtr->nextInstancePtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { - + mePtr = menuListPtr->entries[index]; if (cascadeEntryChanged && (mePtr->namePtr != NULL)) { - oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, + oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, mePtr->namePtr); if ((oldCascadeMenuRefPtr != NULL) @@ -2085,7 +2066,7 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) { return TCL_ERROR; } - + if (cascadeEntryChanged && (mePtr->namePtr != NULL)) { if (cascadeMenuRefPtr->menuPtr != NULL) { Tcl_Obj *newObjv[2]; @@ -2097,7 +2078,7 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) Tcl_IncrRefCount(pathNamePtr); newCloneNamePtr = TkNewMenuName(menuPtr->interp, - pathNamePtr, + pathNamePtr, cascadeMenuRefPtr->menuPtr); Tcl_IncrRefCount(newCloneNamePtr); Tcl_IncrRefCount(normalPtr); @@ -2123,14 +2104,14 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) * * TkGetMenuIndex -- * - * Parse a textual index into a menu and return the numerical - * index of the indicated entry. + * Parse a textual index into a menu and return the numerical index of + * the indicated entry. * * Results: - * A standard Tcl result. If all went well, then *indexPtr is - * filled in with the entry index corresponding to string - * (ranges from -1 to the number of entries in the menu minus - * one). Otherwise an error message is left in the interp's result. + * A standard Tcl result. If all went well, then *indexPtr is filled in + * with the entry index corresponding to string (ranges from -1 to the + * number of entries in the menu minus one). Otherwise an error message + * is left in the interp's result. * * Side effects: * None. @@ -2139,18 +2120,18 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, objc, objv) */ int -TkGetMenuIndex(interp, menuPtr, objPtr, lastOK, indexPtr) - Tcl_Interp *interp; /* For error messages. */ - TkMenu *menuPtr; /* Menu for which the index is being +TkGetMenuIndex( + Tcl_Interp *interp, /* For error messages. */ + TkMenu *menuPtr, /* Menu for which the index is being * specified. */ - Tcl_Obj *objPtr; /* Specification of an entry in menu. See + Tcl_Obj *objPtr, /* Specification of an entry in menu. See * manual entry for valid .*/ - int lastOK; /* Non-zero means its OK to return index - * just *after* last entry. */ - int *indexPtr; /* Where to store converted index. */ + int lastOK, /* Non-zero means its OK to return index just + * *after* last entry. */ + int *indexPtr) /* Where to store converted index. */ { int i; - char *string = Tcl_GetStringFromObj(objPtr, NULL); + char *string = Tcl_GetString(objPtr); if ((string[0] == 'a') && (strcmp(string, "active") == 0)) { *indexPtr = menuPtr->active; @@ -2176,7 +2157,7 @@ TkGetMenuIndex(interp, menuPtr, objPtr, lastOK, indexPtr) } if (isdigit(UCHAR(string[0]))) { - if (Tcl_GetInt(interp, string, &i) == TCL_OK) { + if (Tcl_GetInt(interp, string, &i) == TCL_OK) { if (i >= menuPtr->numEntries) { if (lastOK) { i = menuPtr->numEntries; @@ -2189,26 +2170,23 @@ TkGetMenuIndex(interp, menuPtr, objPtr, lastOK, indexPtr) *indexPtr = i; goto success; } - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + Tcl_SetResult(interp, NULL, TCL_STATIC); } for (i = 0; i < menuPtr->numEntries; i++) { Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr; - char *label = (labelPtr == NULL) ? NULL - : Tcl_GetStringFromObj(labelPtr, NULL); - - if ((label != NULL) - && (Tcl_StringMatch(label, string))) { + char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr); + + if ((label != NULL) && (Tcl_StringMatch(label, string))) { *indexPtr = i; goto success; } } - Tcl_AppendResult(interp, "bad menu entry index \"", - string, "\"", (char *) NULL); + Tcl_AppendResult(interp, "bad menu entry index \"", string, "\"", NULL); return TCL_ERROR; -success: + success: return TCL_OK; } @@ -2217,9 +2195,9 @@ success: * * MenuCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -2231,25 +2209,26 @@ success: */ static void -MenuCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +MenuCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkMenu *menuPtr = (TkMenu *) clientData; Tk_Window tkwin = menuPtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (tkwin != NULL) { - /* - * Note: it may be desirable to NULL out the tkwin - * field of menuPtr here: + /* + * Note: it may be desirable to NULL out the tkwin field of menuPtr + * here: * menuPtr->tkwin = NULL; */ + Tk_DestroyWindow(tkwin); } } @@ -2259,12 +2238,12 @@ MenuCmdDeletedProc(clientData) * * MenuNewEntry -- * - * This procedure allocates and initializes a new menu entry. + * This function allocates and initializes a new menu entry. * * Results: - * The return value is a pointer to a new menu entry structure, - * which has been malloc-ed, initialized, and entered into the - * entry array for the menu. + * The return value is a pointer to a new menu entry structure, which has + * been malloc-ed, initialized, and entered into the entry array for the + * menu. * * Side effects: * Storage gets allocated. @@ -2273,19 +2252,18 @@ MenuCmdDeletedProc(clientData) */ static TkMenuEntry * -MenuNewEntry(menuPtr, index, type) - TkMenu *menuPtr; /* Menu that will hold the new entry. */ - int index; /* Where in the menu the new entry is to +MenuNewEntry( + TkMenu *menuPtr, /* Menu that will hold the new entry. */ + int index, /* Where in the menu the new entry is to * go. */ - int type; /* The type of the new entry. */ + int type) /* The type of the new entry. */ { TkMenuEntry *mePtr; TkMenuEntry **newEntries; int i; /* - * Create a new array of entries with an empty slot for the - * new entry. + * Create a new array of entries with an empty slot for the new entry. */ newEntries = (TkMenuEntry **) ckalloc((unsigned) @@ -2293,7 +2271,7 @@ MenuNewEntry(menuPtr, index, type) for (i = 0; i < index; i++) { newEntries[i] = menuPtr->entries[i]; } - for ( ; i < menuPtr->numEntries; i++) { + for (; i < menuPtr->numEntries; i++) { newEntries[i+1] = menuPtr->entries[i]; newEntries[i+1]->index = i + 1; } @@ -2356,8 +2334,8 @@ MenuNewEntry(menuPtr, index, type) * * MenuAddOrInsert -- * - * This procedure does all of the work of the "add" and "insert" - * widget commands, allowing the code for these to be shared. + * This function does all of the work of the "add" and "insert" widget + * commands, allowing the code for these to be shared. * * Results: * A standard Tcl return value. @@ -2369,34 +2347,29 @@ MenuNewEntry(menuPtr, index, type) */ static int -MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - TkMenu *menuPtr; /* Widget in which to create new - * entry. */ - Tcl_Obj *indexPtr; /* Object describing index at which - * to insert. NULL means insert at - * end. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments to command: first arg - * is type of entry, others are - * config options. */ +MenuAddOrInsert( + Tcl_Interp *interp, /* Used for error reporting. */ + TkMenu *menuPtr, /* Widget in which to create new entry. */ + Tcl_Obj *indexPtr, /* Object describing index at which to insert. + * NULL means insert at end. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments to command: first arg is type of + * entry, others are config options. */ { int type, index; TkMenuEntry *mePtr; TkMenu *menuListPtr; if (indexPtr != NULL) { - if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index) - != TCL_OK) { + if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index) != TCL_OK) { return TCL_ERROR; } } else { index = menuPtr->numEntries; } if (index < 0) { - char *indexString = Tcl_GetStringFromObj(indexPtr, NULL); - Tcl_AppendResult(interp, "bad index \"", indexString, "\"", - (char *) NULL); + char *indexString = Tcl_GetString(indexPtr); + Tcl_AppendResult(interp, "bad index \"", indexString, "\"", NULL); return TCL_ERROR; } if (menuPtr->tearoff && (index == 0)) { @@ -2416,9 +2389,9 @@ MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv) * Now we have to add an entry for every instance related to this menu. */ - for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; + for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL; menuListPtr = menuListPtr->nextInstancePtr) { - + mePtr = MenuNewEntry(menuListPtr, index, type); if (mePtr == NULL) { return TCL_ERROR; @@ -2447,48 +2420,46 @@ MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv) } return TCL_ERROR; } - + /* - * If a menu has cascades, then every instance of the menu has - * to have its own parallel cascade structure. So adding an - * entry to a menu with clones means that the menu that the - * entry points to has to be cloned for every clone the - * master menu has. This is special case #2 in the comment - * at the top of this file. + * If a menu has cascades, then every instance of the menu has to have + * its own parallel cascade structure. So adding an entry to a menu + * with clones means that the menu that the entry points to has to be + * cloned for every clone the master menu has. This is special case #2 + * in the comment at the top of this file. */ - - if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) { + + if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) { if ((mePtr->namePtr != NULL) && (mePtr->childMenuRefPtr != NULL) && (mePtr->childMenuRefPtr->menuPtr != NULL)) { - TkMenu *cascadeMenuPtr = + TkMenu *cascadeMenuPtr = mePtr->childMenuRefPtr->menuPtr->masterMenuPtr; - Tcl_Obj *newCascadePtr; + Tcl_Obj *newCascadePtr, *newObjv[2]; Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1); - Tcl_Obj *windowNamePtr = + Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), -1); Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1); - Tcl_Obj *newObjv[2]; TkMenuReferences *menuRefPtr; - + Tcl_IncrRefCount(windowNamePtr); newCascadePtr = TkNewMenuName(menuListPtr->interp, windowNamePtr, cascadeMenuPtr); Tcl_IncrRefCount(newCascadePtr); Tcl_IncrRefCount(normalPtr); CloneMenu(cascadeMenuPtr, newCascadePtr, normalPtr); - + menuRefPtr = TkFindMenuReferencesObj(menuListPtr->interp, newCascadePtr); if (menuRefPtr == NULL) { - panic("CloneMenu failed inside of MenuAddOrInsert."); + Tcl_Panic("CloneMenu failed inside of MenuAddOrInsert."); } newObjv[0] = menuNamePtr; newObjv[1] = newCascadePtr; Tcl_IncrRefCount(menuNamePtr); Tcl_IncrRefCount(newCascadePtr); - ConfigureMenuEntry(mePtr, 2, newObjv); - Tcl_DecrRefCount(newCascadePtr); + ConfigureMenuEntry(mePtr, 2, newObjv); + Tcl_DecrRefCount(newCascadePtr); Tcl_DecrRefCount(menuNamePtr); Tcl_DecrRefCount(windowNamePtr); Tcl_DecrRefCount(normalPtr); @@ -2503,10 +2474,9 @@ MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv) * * MenuVarProc -- * - * This procedure is invoked when someone changes the - * state variable associated with a radiobutton or checkbutton - * menu entry. The entry's selected state is set to match - * the value of the variable. + * This function is invoked when someone changes the state variable + * associated with a radiobutton or checkbutton menu entry. The entry's + * selected state is set to match the value of the variable. * * Results: * NULL is always returned. @@ -2518,12 +2488,12 @@ MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv) */ static char * -MenuVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about menu entry. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* First part of variable's name. */ - CONST char *name2; /* Second part of variable's name. */ - int flags; /* Describes what just happened. */ +MenuVarProc( + ClientData clientData, /* Information about menu entry. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + CONST char *name1, /* First part of variable's name. */ + CONST char *name2, /* Second part of variable's name. */ + int flags) /* Describes what just happened. */ { TkMenuEntry *mePtr = (TkMenuEntry *) clientData; TkMenu *menuPtr; @@ -2536,11 +2506,11 @@ MenuVarProc(clientData, interp, name1, name2, flags) * Do nothing if the interpreter is going away. */ - return (char *) NULL; + return NULL; } menuPtr = mePtr->menuPtr; - name = Tcl_GetStringFromObj(mePtr->namePtr, NULL); + name = Tcl_GetString(mePtr->namePtr); /* * If the variable is being unset, then re-establish the trace. @@ -2554,13 +2524,13 @@ MenuVarProc(clientData, interp, name1, name2, flags) MenuVarProc, clientData); } TkpConfigureMenuEntry(mePtr); - TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL); - return (char *) NULL; + TkEventuallyRedrawMenu(menuPtr, NULL); + return NULL; } /* - * Use the value of the variable to update the selected status of - * the menu entry. + * Use the value of the variable to update the selected status of the menu + * entry. */ value = Tcl_GetVar(interp, name, TCL_GLOBAL_ONLY); @@ -2568,23 +2538,23 @@ MenuVarProc(clientData, interp, name1, name2, flags) value = ""; } if (mePtr->onValuePtr != NULL) { - onValue = Tcl_GetStringFromObj(mePtr->onValuePtr, NULL); + onValue = Tcl_GetString(mePtr->onValuePtr); if (strcmp(value, onValue) == 0) { if (mePtr->entryFlags & ENTRY_SELECTED) { - return (char *) NULL; + return NULL; } mePtr->entryFlags |= ENTRY_SELECTED; } else if (mePtr->entryFlags & ENTRY_SELECTED) { mePtr->entryFlags &= ~ENTRY_SELECTED; } else { - return (char *) NULL; + return NULL; } } else { - return (char *) NULL; + return NULL; } TkpConfigureMenuEntry(mePtr); TkEventuallyRedrawMenu(menuPtr, mePtr); - return (char *) NULL; + return NULL; } /* @@ -2592,26 +2562,25 @@ MenuVarProc(clientData, interp, name1, name2, flags) * * TkActivateMenuEntry -- * - * This procedure is invoked to make a particular menu entry - * the active one, deactivating any other entry that might - * currently be active. + * This function is invoked to make a particular menu entry the active + * one, deactivating any other entry that might currently be active. * * Results: - * The return value is a standard Tcl result (errors can occur - * while posting and unposting submenus). + * The return value is a standard Tcl result (errors can occur while + * posting and unposting submenus). * * Side effects: - * Menu entries get redisplayed, and the active entry changes. - * Submenus may get posted and unposted. + * Menu entries get redisplayed, and the active entry changes. Submenus + * may get posted and unposted. * *---------------------------------------------------------------------- */ int -TkActivateMenuEntry(menuPtr, index) - register TkMenu *menuPtr; /* Menu in which to activate. */ - int index; /* Index of entry to activate, or - * -1 to deactivate all entries. */ +TkActivateMenuEntry( + register TkMenu *menuPtr, /* Menu in which to activate. */ + int index) /* Index of entry to activate, or -1 to + * deactivate all entries. */ { register TkMenuEntry *mePtr; int result = TCL_OK; @@ -2620,8 +2589,8 @@ TkActivateMenuEntry(menuPtr, index) mePtr = menuPtr->entries[menuPtr->active]; /* - * Don't change the state unless it's currently active (state - * might already have been changed to disabled). + * Don't change the state unless it's currently active (state might + * already have been changed to disabled). */ if (mePtr->state == ENTRY_ACTIVE) { @@ -2646,8 +2615,8 @@ TkActivateMenuEntry(menuPtr, index) * Execute the postcommand for the given menu. * * Results: - * The return value is a standard Tcl result (errors can occur - * while the postcommands are being processed). + * The return value is a standard Tcl result (errors can occur while the + * postcommands are being processed). * * Side effects: * Since commands can get executed while this routine is being executed, @@ -2655,17 +2624,17 @@ TkActivateMenuEntry(menuPtr, index) * *---------------------------------------------------------------------- */ - + int -TkPostCommand(menuPtr) - TkMenu *menuPtr; +TkPostCommand( + TkMenu *menuPtr) { int result; /* - * If there is a command for the menu, execute it. This - * may change the size of the menu, so be sure to recompute - * the menu's geometry if needed. + * If there is a command for the menu, execute it. This may change the + * size of the menu, so be sure to recompute the menu's geometry if + * needed. */ if (menuPtr->postCommandPtr != NULL) { @@ -2688,37 +2657,36 @@ TkPostCommand(menuPtr) * * CloneMenu -- * - * Creates a child copy of the menu. It will be inserted into - * the menu's instance chain. All attributes and entry - * attributes will be duplicated. + * Creates a child copy of the menu. It will be inserted into the menu's + * instance chain. All attributes and entry attributes will be + * duplicated. * * Results: * A standard Tcl result. * * Side effects: - * Allocates storage. After the menu is created, any - * configuration done with this menu or any related one - * will be reflected in all of them. + * Allocates storage. After the menu is created, any configuration done + * with this menu or any related one will be reflected in all of them. * *-------------------------------------------------------------- */ static int -CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr) - TkMenu *menuPtr; /* The menu we are going to clone */ - Tcl_Obj *newMenuNamePtr; /* The name to give the new menu */ - Tcl_Obj *newMenuTypePtr; /* What kind of menu is this, a normal menu - * a menubar, or a tearoff? */ +CloneMenu( + TkMenu *menuPtr, /* The menu we are going to clone. */ + Tcl_Obj *newMenuNamePtr, /* The name to give the new menu. */ + Tcl_Obj *newMenuTypePtr) /* What kind of menu is this, a normal menu a + * menubar, or a tearoff? */ { int returnResult; int menuType, i; TkMenuReferences *menuRefPtr; Tcl_Obj *menuDupCommandArray[4]; - + if (newMenuTypePtr == NULL) { - menuType = MASTER_MENU; + menuType = MASTER_MENU; } else { - if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr, + if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr, menuTypeStrings, "menu type", 0, &menuType) != TCL_OK) { return TCL_ERROR; } @@ -2744,12 +2712,12 @@ CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr) /* * Make sure the tcl command actually created the clone. */ - + if ((returnResult == TCL_OK) && - ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, - newMenuNamePtr)) != (TkMenuReferences *) NULL) + ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp, + newMenuNamePtr)) != NULL) && (menuPtr->numEntries == menuRefPtr->menuPtr->numEntries)) { - TkMenu *newMenuPtr = menuRefPtr->menuPtr; + TkMenu *newMenuPtr = menuRefPtr->menuPtr; Tcl_Obj *newObjv[3]; int i, numElements; @@ -2763,83 +2731,85 @@ CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr) newMenuPtr->masterMenuPtr = menuPtr->masterMenuPtr; } else { TkMenu *masterMenuPtr; - + masterMenuPtr = menuPtr->masterMenuPtr; newMenuPtr->nextInstancePtr = masterMenuPtr->nextInstancePtr; masterMenuPtr->nextInstancePtr = newMenuPtr; newMenuPtr->masterMenuPtr = masterMenuPtr; } - - /* - * Add the master menu's window to the bind tags for this window - * after this window's tag. This is so the user can bind to either - * this clone (which may not be easy to do) or the entire menu - * clone structure. - */ - + + /* + * Add the master menu's window to the bind tags for this window after + * this window's tag. This is so the user can bind to either this + * clone (which may not be easy to do) or the entire menu clone + * structure. + */ + newObjv[0] = Tcl_NewStringObj("bindtags", -1); - newObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1); + newObjv[1] = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1); Tcl_IncrRefCount(newObjv[0]); Tcl_IncrRefCount(newObjv[1]); - if (Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin, - newMenuPtr->interp, 2, newObjv) == TCL_OK) { - char *windowName; - Tcl_Obj *bindingsPtr = + if (Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin, + newMenuPtr->interp, 2, newObjv) == TCL_OK) { + char *windowName; + Tcl_Obj *bindingsPtr = Tcl_DuplicateObj(Tcl_GetObjResult(newMenuPtr->interp)); - Tcl_Obj *elementPtr; - + Tcl_Obj *elementPtr; + Tcl_IncrRefCount(bindingsPtr); - Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements); - for (i = 0; i < numElements; i++) { - Tcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i, + Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements); + for (i = 0; i < numElements; i++) { + Tcl_ListObjIndex(newMenuPtr->interp, bindingsPtr, i, &elementPtr); - windowName = Tcl_GetStringFromObj(elementPtr, NULL); - if (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin)) - == 0) { - Tcl_Obj *newElementPtr = Tcl_NewStringObj( - Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1); - /* + windowName = Tcl_GetString(elementPtr); + if (strcmp(windowName, Tk_PathName(newMenuPtr->tkwin)) + == 0) { + Tcl_Obj *newElementPtr = Tcl_NewStringObj( + Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1); + + /* * The newElementPtr will have its refCount incremented * here, so we don't need to worry about it any more. */ - Tcl_ListObjReplace(menuPtr->interp, bindingsPtr, - i + 1, 0, 1, &newElementPtr); + + Tcl_ListObjReplace(menuPtr->interp, bindingsPtr, + i + 1, 0, 1, &newElementPtr); newObjv[2] = bindingsPtr; Tk_BindtagsObjCmd((ClientData)newMenuPtr->tkwin, menuPtr->interp, 3, newObjv); - break; - } - } - Tcl_DecrRefCount(bindingsPtr); - } + break; + } + } + Tcl_DecrRefCount(bindingsPtr); + } Tcl_DecrRefCount(newObjv[0]); Tcl_DecrRefCount(newObjv[1]); - Tcl_ResetResult(menuPtr->interp); - - /* - * Clone all of the cascade menus that this menu points to. - */ - - for (i = 0; i < menuPtr->numEntries; i++) { - TkMenuReferences *cascadeRefPtr; - TkMenu *oldCascadePtr; - - if ((menuPtr->entries[i]->type == CASCADE_ENTRY) + Tcl_ResetResult(menuPtr->interp); + + /* + * Clone all of the cascade menus that this menu points to. + */ + + for (i = 0; i < menuPtr->numEntries; i++) { + TkMenuReferences *cascadeRefPtr; + TkMenu *oldCascadePtr; + + if ((menuPtr->entries[i]->type == CASCADE_ENTRY) && (menuPtr->entries[i]->namePtr != NULL)) { - cascadeRefPtr = + cascadeRefPtr = TkFindMenuReferencesObj(menuPtr->interp, menuPtr->entries[i]->namePtr); - if ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) { - Tcl_Obj *windowNamePtr = + if ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) { + Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin), -1); Tcl_Obj *newCascadePtr; - - oldCascadePtr = cascadeRefPtr->menuPtr; + + oldCascadePtr = cascadeRefPtr->menuPtr; Tcl_IncrRefCount(windowNamePtr); - newCascadePtr = TkNewMenuName(menuPtr->interp, - windowNamePtr, oldCascadePtr); + newCascadePtr = TkNewMenuName(menuPtr->interp, + windowNamePtr, oldCascadePtr); Tcl_IncrRefCount(newCascadePtr); CloneMenu(oldCascadePtr, newCascadePtr, NULL); @@ -2850,13 +2820,13 @@ CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr) Tcl_DecrRefCount(newObjv[0]); Tcl_DecrRefCount(newCascadePtr); Tcl_DecrRefCount(windowNamePtr); - } - } - } - - returnResult = TCL_OK; + } + } + } + + returnResult = TCL_OK; } else { - returnResult = TCL_ERROR; + returnResult = TCL_ERROR; } Tcl_Release((ClientData) menuPtr); return returnResult; @@ -2865,6 +2835,43 @@ CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr) /* *---------------------------------------------------------------------- * + * MenuDoXPosition -- + * + * Given arguments from an option command line, returns the X position. + * + * Results: + * Returns TCL_OK or TCL_Error + * + * Side effects: + * xPosition is set to the X-position of the menu entry. + * + *---------------------------------------------------------------------- + */ + +static int +MenuDoXPosition( + Tcl_Interp *interp, + TkMenu *menuPtr, + Tcl_Obj *objPtr) +{ + int index; + + TkRecomputeMenu(menuPtr); + if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) { + return TCL_ERROR; + } + Tcl_ResetResult(interp); + if (index < 0) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); + } else { + Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->x)); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * MenuDoYPosition -- * * Given arguments from an option command line, returns the Y position. @@ -2877,18 +2884,18 @@ CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr) * *---------------------------------------------------------------------- */ - + static int -MenuDoYPosition(interp, menuPtr, objPtr) - Tcl_Interp *interp; - TkMenu *menuPtr; - Tcl_Obj *objPtr; +MenuDoYPosition( + Tcl_Interp *interp, + TkMenu *menuPtr, + Tcl_Obj *objPtr) { int index; - + TkRecomputeMenu(menuPtr); if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) { - goto error; + goto error; } Tcl_ResetResult(interp); if (index < 0) { @@ -2898,8 +2905,8 @@ MenuDoYPosition(interp, menuPtr, objPtr) } return TCL_OK; - -error: + + error: return TCL_ERROR; } @@ -2908,36 +2915,39 @@ error: * * GetIndexFromCoords -- * - * Given a string of the form "@int", return the menu item corresponding - * to int. + * Given a string of the form "@integer", return the menu item + * corresponding to the provided y-coordinate in the menu window. * * Results: - * If int is a valid number, *indexPtr will be the number of the menuentry - * that is the correct height. If int is invaled, *indexPtr will be - * unchanged. Returns appropriate Tcl error number. + * If int is a valid number, *indexPtr will be the number of the + * menuentry that is the correct height. If int is invalid, *indexPtr + * will be unchanged. Returns appropriate Tcl error number. * * Side effects: - * If int is invalid, interp's result will set to NULL. + * If int is invalid, interp's result will be set to NULL. * *---------------------------------------------------------------------- */ static int -GetIndexFromCoords(interp, menuPtr, string, indexPtr) - Tcl_Interp *interp; /* interp of menu */ - TkMenu *menuPtr; /* the menu we are searching */ - char *string; /* The @string we are parsing */ - int *indexPtr; /* The index of the item that matches */ +GetIndexFromCoords( + Tcl_Interp *interp, /* Interpreter of menu. */ + TkMenu *menuPtr, /* The menu we are searching. */ + char *string, /* The @string we are parsing. */ + int *indexPtr) /* The index of the item that matches. */ { int x, y, i; char *p, *end; - + int x2, borderwidth, max; + TkRecomputeMenu(menuPtr); p = string + 1; y = strtol(p, &end, 0); if (end == p) { goto error; } + Tk_GetPixelsFromObj(interp, menuPtr->tkwin, + menuPtr->borderWidthPtr, &borderwidth); if (*end == ',') { x = y; p = end + 1; @@ -2946,27 +2956,36 @@ GetIndexFromCoords(interp, menuPtr, string, indexPtr) goto error; } } else { - Tk_GetPixelsFromObj(interp, menuPtr->tkwin, - menuPtr->borderWidthPtr, &x); + x = borderwidth; } - + + *indexPtr = -1; + + /* set the width of the final column to the remainder of the window + * being aware of windows that may not be mapped yet. + */ + max = Tk_IsMapped(menuPtr->tkwin) + ? Tk_Width(menuPtr->tkwin) : Tk_ReqWidth(menuPtr->tkwin); + max -= borderwidth; + for (i = 0; i < menuPtr->numEntries; i++) { + if (menuPtr->entries[i]->entryFlags & ENTRY_LAST_COLUMN) { + x2 = max; + } else { + x2 = menuPtr->entries[i]->x + menuPtr->entries[i]->width; + } if ((x >= menuPtr->entries[i]->x) && (y >= menuPtr->entries[i]->y) - && (x < (menuPtr->entries[i]->x + menuPtr->entries[i]->width)) + && (x < x2) && (y < (menuPtr->entries[i]->y + menuPtr->entries[i]->height))) { + *indexPtr = i; break; } } - if (i >= menuPtr->numEntries) { - /* i = menuPtr->numEntries - 1; */ - i = -1; - } - *indexPtr = i; return TCL_OK; - error: - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + error: + Tcl_SetResult(interp, NULL, TCL_STATIC); return TCL_ERROR; } @@ -2976,8 +2995,8 @@ GetIndexFromCoords(interp, menuPtr, string, indexPtr) * RecursivelyDeleteMenu -- * * Deletes a menu and any cascades underneath it. Used for deleting - * instances when a menu is no longer being used as a menubar, - * for instance. + * instances when a menu is no longer being used as a menubar, for + * instance. * * Results: * None. @@ -2989,19 +3008,19 @@ GetIndexFromCoords(interp, menuPtr, string, indexPtr) */ static void -RecursivelyDeleteMenu(menuPtr) - TkMenu *menuPtr; /* The menubar instance we are deleting */ +RecursivelyDeleteMenu( + TkMenu *menuPtr) /* The menubar instance we are deleting. */ { int i; TkMenuEntry *mePtr; - - /* - * It is not 100% clear that this preserve/release pair is - * required, but we have added them for safety in this - * very complex code. + + /* + * It is not 100% clear that this preserve/release pair is required, but + * we have added them for safety in this very complex code. */ + Tcl_Preserve(menuPtr); - + for (i = 0; i < menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; if ((mePtr->type == CASCADE_ENTRY) @@ -3013,7 +3032,7 @@ RecursivelyDeleteMenu(menuPtr) if (menuPtr->tkwin != NULL) { Tk_DestroyWindow(menuPtr->tkwin); } - + Tcl_Release(menuPtr); } @@ -3022,8 +3041,7 @@ RecursivelyDeleteMenu(menuPtr) * * TkNewMenuName -- * - * Makes a new unique name for a cloned menu. Will be a child - * of oldName. + * Makes a new unique name for a cloned menu. Will be a child of oldName. * * Results: * Returns a char * which has been allocated; caller must free. @@ -3035,10 +3053,10 @@ RecursivelyDeleteMenu(menuPtr) */ Tcl_Obj * -TkNewMenuName(interp, parentPtr, menuPtr) - Tcl_Interp *interp; /* The interp the new name has to live in.*/ - Tcl_Obj *parentPtr; /* The prefix path of the new name. */ - TkMenu *menuPtr; /* The menu we are cloning. */ +TkNewMenuName( + Tcl_Interp *interp, /* The interp the new name has to live in.*/ + Tcl_Obj *parentPtr, /* The prefix path of the new name. */ + TkMenu *menuPtr) /* The menu we are cloning. */ { Tcl_Obj *resultPtr = NULL; /* Initialization needed only to prevent * compiler warning. */ @@ -3049,7 +3067,7 @@ TkNewMenuName(interp, parentPtr, menuPtr) Tcl_CmdInfo cmdInfo; Tcl_HashTable *nameTablePtr = NULL; TkWindow *winPtr = (TkWindow *) menuPtr->tkwin; - char *parentName = Tcl_GetStringFromObj(parentPtr, NULL); + char *parentName = Tcl_GetString(parentPtr); if (winPtr->mainPtr != NULL) { nameTablePtr = &(winPtr->mainPtr->nameTable); @@ -3058,13 +3076,13 @@ TkNewMenuName(interp, parentPtr, menuPtr) doDot = parentName[strlen(parentName) - 1] != '.'; childPtr = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1); - for (destString = Tcl_GetStringFromObj(childPtr, NULL); + for (destString = Tcl_GetString(childPtr); *destString != '\0'; destString++) { if (*destString == '.') { *destString = '#'; } } - + for (i = 0; ; i++) { if (i == 0) { resultPtr = Tcl_DuplicateObj(parentPtr); @@ -3085,7 +3103,7 @@ TkNewMenuName(interp, parentPtr, menuPtr) Tcl_AppendObjToObj(resultPtr, intPtr); Tcl_DecrRefCount(intPtr); } - destString = Tcl_GetStringFromObj(resultPtr, NULL); + destString = Tcl_GetString(resultPtr); if ((Tcl_GetCommandInfo(interp, destString, &cmdInfo) == 0) && ((nameTablePtr == NULL) || (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) { @@ -3101,76 +3119,73 @@ TkNewMenuName(interp, parentPtr, menuPtr) * * TkSetWindowMenuBar -- * - * Associates a menu with a window. Called by ConfigureFrame in - * in response to a "-menu .foo" configuration option for a top - * level. + * Associates a menu with a window. Called by ConfigureFrame in in + * response to a "-menu .foo" configuration option for a top level. * * Results: * None. * * Side effects: - * The old menu clones for the menubar are thrown away, and a - * handler is set up to allocate the new ones. + * The old menu clones for the menubar are thrown away, and a handler is + * set up to allocate the new ones. * *---------------------------------------------------------------------- */ + void -TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName) - Tcl_Interp *interp; /* The interpreter the toplevel lives in. */ - Tk_Window tkwin; /* The toplevel window */ - char *oldMenuName; /* The name of the menubar previously set in - * this toplevel. NULL means no menu was - * set previously. */ - char *menuName; /* The name of the new menubar that the +TkSetWindowMenuBar( + Tcl_Interp *interp, /* The interpreter the toplevel lives in. */ + Tk_Window tkwin, /* The toplevel window. */ + char *oldMenuName, /* The name of the menubar previously set in + * this toplevel. NULL means no menu was set + * previously. */ + char *menuName) /* The name of the new menubar that the * toplevel needs to be set to. NULL means * that their is no menu now. */ { TkMenuTopLevelList *topLevelListPtr, *prevTopLevelPtr; TkMenu *menuPtr; TkMenuReferences *menuRefPtr; - - TkMenuInit(); /* - * Destroy the menubar instances of the old menu. Take this window - * out of the old menu's top level reference list. + * Destroy the menubar instances of the old menu. Take this window out of + * the old menu's top level reference list. */ - - if (oldMenuName != NULL) { - menuRefPtr = TkFindMenuReferences(interp, oldMenuName); - if (menuRefPtr != NULL) { + if (oldMenuName != NULL) { + menuRefPtr = TkFindMenuReferences(interp, oldMenuName); + if (menuRefPtr != NULL) { /* - * Find the menubar instance that is to be removed. Destroy - * it and all of the cascades underneath it. + * Find the menubar instance that is to be removed. Destroy it and + * all of the cascades underneath it. */ - if (menuRefPtr->menuPtr != NULL) { - TkMenu *instancePtr; - - menuPtr = menuRefPtr->menuPtr; - - for (instancePtr = menuPtr->masterMenuPtr; - instancePtr != NULL; - instancePtr = instancePtr->nextInstancePtr) { - if (instancePtr->menuType == MENUBAR - && instancePtr->parentTopLevelPtr == tkwin) { - RecursivelyDeleteMenu(instancePtr); - break; - } - } - } - - /* - * Now we need to remove this toplevel from the list of toplevels + if (menuRefPtr->menuPtr != NULL) { + TkMenu *instancePtr; + + menuPtr = menuRefPtr->menuPtr; + + for (instancePtr = menuPtr->masterMenuPtr; + instancePtr != NULL; + instancePtr = instancePtr->nextInstancePtr) { + if (instancePtr->menuType == MENUBAR + && instancePtr->parentTopLevelPtr == tkwin) { + RecursivelyDeleteMenu(instancePtr); + break; + } + } + } + + /* + * Now we need to remove this toplevel from the list of toplevels * that reference this menu. - */ - + */ + topLevelListPtr = menuRefPtr->topLevelListPtr; prevTopLevelPtr = NULL; - - while ((topLevelListPtr != NULL) - && (topLevelListPtr->tkwin != tkwin)) { + + while ((topLevelListPtr != NULL) + && (topLevelListPtr->tkwin != tkwin)) { prevTopLevelPtr = topLevelListPtr; topLevelListPtr = topLevelListPtr->nextPtr; } @@ -3181,54 +3196,54 @@ TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName) */ if (topLevelListPtr != NULL) { - if (prevTopLevelPtr == NULL) { + if (prevTopLevelPtr == NULL) { menuRefPtr->topLevelListPtr = menuRefPtr->topLevelListPtr->nextPtr; } else { - prevTopLevelPtr->nextPtr = topLevelListPtr->nextPtr; - } - ckfree((char *) topLevelListPtr); - TkFreeMenuReferences(menuRefPtr); - } - } + prevTopLevelPtr->nextPtr = topLevelListPtr->nextPtr; + } + ckfree((char *) topLevelListPtr); + TkFreeMenuReferences(menuRefPtr); + } + } } /* * Now, add the clone references for the new menu. */ - + if (menuName != NULL && menuName[0] != 0) { - TkMenu *menuBarPtr = NULL; - - menuRefPtr = TkCreateMenuReferences(interp, menuName); - - menuPtr = menuRefPtr->menuPtr; - if (menuPtr != NULL) { - Tcl_Obj *cloneMenuPtr; - TkMenuReferences *cloneMenuRefPtr; + TkMenu *menuBarPtr = NULL; + + menuRefPtr = TkCreateMenuReferences(interp, menuName); + + menuPtr = menuRefPtr->menuPtr; + if (menuPtr != NULL) { + Tcl_Obj *cloneMenuPtr; + TkMenuReferences *cloneMenuRefPtr; Tcl_Obj *newObjv[4]; - Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin), + Tcl_Obj *windowNamePtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1); Tcl_Obj *menubarPtr = Tcl_NewStringObj("menubar", -1); - - /* - * Clone the menu and all of the cascades underneath it. - */ + + /* + * Clone the menu and all of the cascades underneath it. + */ Tcl_IncrRefCount(windowNamePtr); - cloneMenuPtr = TkNewMenuName(interp, windowNamePtr, - menuPtr); + cloneMenuPtr = TkNewMenuName(interp, windowNamePtr, + menuPtr); Tcl_IncrRefCount(cloneMenuPtr); Tcl_IncrRefCount(menubarPtr); - CloneMenu(menuPtr, cloneMenuPtr, menubarPtr); - - cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr); - if ((cloneMenuRefPtr != NULL) + CloneMenu(menuPtr, cloneMenuPtr, menubarPtr); + + cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr); + if ((cloneMenuRefPtr != NULL) && (cloneMenuRefPtr->menuPtr != NULL)) { Tcl_Obj *cursorPtr = Tcl_NewStringObj("-cursor", -1); Tcl_Obj *nullPtr = Tcl_NewObj(); - cloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin; - menuBarPtr = cloneMenuRefPtr->menuPtr; + cloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin; + menuBarPtr = cloneMenuRefPtr->menuPtr; newObjv[0] = cursorPtr; newObjv[1] = nullPtr; Tcl_IncrRefCount(cursorPtr); @@ -3237,27 +3252,26 @@ TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName) 2, newObjv); Tcl_DecrRefCount(cursorPtr); Tcl_DecrRefCount(nullPtr); - } + } TkpSetWindowMenuBar(tkwin, menuBarPtr); Tcl_DecrRefCount(cloneMenuPtr); Tcl_DecrRefCount(menubarPtr); Tcl_DecrRefCount(windowNamePtr); - } else { - TkpSetWindowMenuBar(tkwin, NULL); + } else { + TkpSetWindowMenuBar(tkwin, NULL); } - - /* - * Add this window to the menu's list of windows that refer - * to this menu. - */ + /* + * Add this window to the menu's list of windows that refer to this + * menu. + */ - topLevelListPtr = (TkMenuTopLevelList *) + topLevelListPtr = (TkMenuTopLevelList *) ckalloc(sizeof(TkMenuTopLevelList)); - topLevelListPtr->tkwin = tkwin; - topLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr; - menuRefPtr->topLevelListPtr = topLevelListPtr; + topLevelListPtr->tkwin = tkwin; + topLevelListPtr->nextPtr = menuRefPtr->topLevelListPtr; + menuRefPtr->topLevelListPtr = topLevelListPtr; } else { TkpSetWindowMenuBar(tkwin, NULL); } @@ -3269,8 +3283,8 @@ TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName) * * DestroyMenuHashTable -- * - * Called when an interp is deleted and a menu hash table has - * been set in it. + * Called when an interp is deleted and a menu hash table has been set in + * it. * * Results: * None. @@ -3282,9 +3296,9 @@ TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName) */ static void -DestroyMenuHashTable(clientData, interp) - ClientData clientData; /* The menu hash table we are destroying */ - Tcl_Interp *interp; /* The interpreter we are destroying */ +DestroyMenuHashTable( + ClientData clientData, /* The menu hash table we are destroying. */ + Tcl_Interp *interp) /* The interpreter we are destroying. */ { Tcl_DeleteHashTable((Tcl_HashTable *) clientData); ckfree((char *) clientData); @@ -3295,8 +3309,8 @@ DestroyMenuHashTable(clientData, interp) * * TkGetMenuHashTable -- * - * For a given interp, give back the menu hash table that goes with - * it. If the hash table does not exist, it is created. + * For a given interp, give back the menu hash table that goes with it. + * If the hash table does not exist, it is created. * * Results: * Returns a hash table pointer. @@ -3309,13 +3323,13 @@ DestroyMenuHashTable(clientData, interp) */ Tcl_HashTable * -TkGetMenuHashTable(interp) - Tcl_Interp *interp; /* The interp we need the hash table in.*/ +TkGetMenuHashTable( + Tcl_Interp *interp) /* The interp we need the hash table in.*/ { Tcl_HashTable *menuTablePtr; - menuTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, MENU_HASH_KEY, - NULL); + menuTablePtr = (Tcl_HashTable *) + Tcl_GetAssocData(interp, MENU_HASH_KEY, NULL); if (menuTablePtr == NULL) { menuTablePtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable)); Tcl_InitHashTable(menuTablePtr, TCL_STRING_KEYS); @@ -3330,25 +3344,26 @@ TkGetMenuHashTable(interp) * * TkCreateMenuReferences -- * - * Given a pathname, gives back a pointer to a TkMenuReferences structure. - * If a reference is not already in the hash table, one is created. + * Given a pathname, gives back a pointer to a TkMenuReferences + * structure. If a reference is not already in the hash table, one is + * created. * * Results: - * Returns a pointer to a menu reference structure. Should not - * be freed by calller; when a field of the reference is cleared, + * Returns a pointer to a menu reference structure. Should not be freed + * by calller; when a field of the reference is cleared, * TkFreeMenuReferences should be called. * * Side effects: - * A new hash table entry is created if there were no references - * to the menu originally. + * A new hash table entry is created if there were no references to the + * menu originally. * *---------------------------------------------------------------------- */ TkMenuReferences * -TkCreateMenuReferences(interp, pathName) - Tcl_Interp *interp; - char *pathName; /* The path of the menu widget */ +TkCreateMenuReferences( + Tcl_Interp *interp, + char *pathName) /* The path of the menu widget. */ { Tcl_HashEntry *hashEntryPtr; TkMenuReferences *menuRefPtr; @@ -3378,8 +3393,8 @@ TkCreateMenuReferences(interp, pathName) * structure. * * Results: - * Returns a pointer to a menu reference structure. Should not - * be freed by calller; when a field of the reference is cleared, + * Returns a pointer to a menu reference structure. Should not be freed + * by calller; when a field of the reference is cleared, * TkFreeMenuReferences should be called. Returns NULL if no reference * with this pathname exists. * @@ -3390,9 +3405,9 @@ TkCreateMenuReferences(interp, pathName) */ TkMenuReferences * -TkFindMenuReferences(interp, pathName) - Tcl_Interp *interp; /* The interp the menu is living in. */ - char *pathName; /* The path of the menu widget */ +TkFindMenuReferences( + Tcl_Interp *interp, /* The interp the menu is living in. */ + char *pathName) /* The path of the menu widget. */ { Tcl_HashEntry *hashEntryPtr; TkMenuReferences *menuRefPtr = NULL; @@ -3415,8 +3430,8 @@ TkFindMenuReferences(interp, pathName) * structure. * * Results: - * Returns a pointer to a menu reference structure. Should not - * be freed by calller; when a field of the reference is cleared, + * Returns a pointer to a menu reference structure. Should not be freed + * by calller; when a field of the reference is cleared, * TkFreeMenuReferences should be called. Returns NULL if no reference * with this pathname exists. * @@ -3427,11 +3442,11 @@ TkFindMenuReferences(interp, pathName) */ TkMenuReferences * -TkFindMenuReferencesObj(interp, objPtr) - Tcl_Interp *interp; /* The interp the menu is living in. */ - Tcl_Obj *objPtr; /* The path of the menu widget */ +TkFindMenuReferencesObj( + Tcl_Interp *interp, /* The interp the menu is living in. */ + Tcl_Obj *objPtr) /* The path of the menu widget. */ { - char *pathName = Tcl_GetStringFromObj(objPtr, NULL); + char *pathName = Tcl_GetString(objPtr); return TkFindMenuReferences(interp, pathName); } @@ -3440,26 +3455,25 @@ TkFindMenuReferencesObj(interp, objPtr) * * TkFreeMenuReferences -- * - * This is called after one of the fields in a menu reference - * is cleared. It cleans up the ref if it is now empty. + * This is called after one of the fields in a menu reference is cleared. + * It cleans up the ref if it is now empty. * * Results: - * Returns 1 if the references structure was freed, and 0 - * otherwise. + * Returns 1 if the references structure was freed, and 0 otherwise. * * Side effects: - * If this is the last field to be cleared, the menu ref is - * taken out of the hash table. + * If this is the last field to be cleared, the menu ref is taken out of + * the hash table. * *---------------------------------------------------------------------- */ int -TkFreeMenuReferences(menuRefPtr) - TkMenuReferences *menuRefPtr; /* The menu reference to - * free */ +TkFreeMenuReferences( + TkMenuReferences *menuRefPtr) + /* The menu reference to free. */ { - if ((menuRefPtr->menuPtr == NULL) + if ((menuRefPtr->menuPtr == NULL) && (menuRefPtr->parentEntryPtr == NULL) && (menuRefPtr->topLevelListPtr == NULL)) { Tcl_DeleteHashEntry(menuRefPtr->hashEntryPtr); @@ -3474,8 +3488,8 @@ TkFreeMenuReferences(menuRefPtr) * * DeleteMenuCloneEntries -- * - * For every clone in this clone chain, delete the menu entries - * given by the parameters. + * For every clone in this clone chain, delete the menu entries given by + * the parameters. * * Results: * None. @@ -3487,13 +3501,12 @@ TkFreeMenuReferences(menuRefPtr) */ static void -DeleteMenuCloneEntries(menuPtr, first, last) - TkMenu *menuPtr; /* the menu the command was issued with */ - int first; /* the zero-based first entry in the set - * of entries to delete. */ - int last; /* the zero-based last entry */ +DeleteMenuCloneEntries( + TkMenu *menuPtr, /* The menu the command was issued with. */ + int first, /* The zero-based first entry in the set of + * entries to delete. */ + int last) /* The zero-based last entry. */ { - TkMenu *menuListPtr; int numDeleted, i, j; @@ -3508,13 +3521,13 @@ DeleteMenuCloneEntries(menuPtr, first, last) j = i - numDeleted; menuListPtr->entries[j] = menuListPtr->entries[i]; menuListPtr->entries[j]->index = j; - } + } menuListPtr->numEntries -= numDeleted; if (menuListPtr->numEntries == 0) { ckfree((char *) menuListPtr->entries); menuListPtr->entries = NULL; } - if ((menuListPtr->active >= first) + if ((menuListPtr->active >= first) && (menuListPtr->active <= last)) { menuListPtr->active = -1; } else if (menuListPtr->active > last) { @@ -3524,28 +3537,29 @@ DeleteMenuCloneEntries(menuPtr, first, last) } } -/* - *---------------------------------------------------------------------- - * - * TkMenuCleanup -- - * - * Resets menusInitialized to allow Tk to be finalized and reused - * without the DLL being unloaded. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static void -TkMenuCleanup(ClientData unused) -{ - menusInitialized = 0; -} +/* + *---------------------------------------------------------------------- + * + * TkMenuCleanup -- + * + * Resets menusInitialized to allow Tk to be finalized and reused without + * the DLL being unloaded. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +TkMenuCleanup( + ClientData unused) +{ + menusInitialized = 0; +} /* *---------------------------------------------------------------------- @@ -3565,21 +3579,23 @@ TkMenuCleanup(ClientData unused) */ void -TkMenuInit() +TkMenuInit(void) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + if (!menusInitialized) { Tcl_MutexLock(&menuMutex); if (!menusInitialized) { TkpMenuInit(); menusInitialized = 1; } - /* - * Make sure we cleanup on finalize. - */ - TkCreateExitHandler(TkMenuCleanup, NULL); + + /* + * Make sure we cleanup on finalize. + */ + + TkCreateExitHandler((Tcl_ExitProc *) TkMenuCleanup, NULL); Tcl_MutexUnlock(&menuMutex); } if (!tsdPtr->menusInitialized) { @@ -3587,3 +3603,11 @@ TkMenuInit() tsdPtr->menusInitialized = 1; } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkMenu.h b/generic/tkMenu.h index a428d4c..e8470ca 100644 --- a/generic/tkMenu.h +++ b/generic/tkMenu.h @@ -1,12 +1,13 @@ /* * tkMenu.h -- * - * Declarations shared among all of the files that implement menu widgets. + * Declarations shared among all of the files that implement menu + * widgets. * * Copyright (c) 1996-1998 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKMENU @@ -37,26 +38,41 @@ typedef struct TkMenuPlatformData_ *TkMenuPlatformData; typedef struct TkMenuPlatformEntryData_ *TkMenuPlatformEntryData; /* - * Legal values for the "compound" field of TkMenuEntry and TkMenuButton records. + * Legal values for the "compound" field of TkMenuEntry and TkMenuButton + * records. */ enum compound { COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE, - COMPOUND_RIGHT, COMPOUND_TOP + COMPOUND_RIGHT, COMPOUND_TOP }; /* - * One of the following data structures is kept for each entry of each - * menu managed by this file: + * Additional menu entry drawing parameters for Windows platform. + * DRAW_MENU_ENTRY_ARROW makes TkpDrawMenuEntry draw the arrow + * itself when cascade entry is disabled. + * DRAW_MENU_ENTRY_NOUNDERLINE forbids underline when ODS_NOACCEL + * is set, thus obeying the system-wide Windows UI setting. + */ + +enum drawingParameters { + DRAW_MENU_ENTRY_ARROW = (1<<0), + DRAW_MENU_ENTRY_NOUNDERLINE = (1<<1) +}; + +/* + * One of the following data structures is kept for each entry of each menu + * managed by this file: */ typedef struct TkMenuEntry { - int type; /* Type of menu entry; see below for - * valid types. */ - struct TkMenu *menuPtr; /* Menu with which this entry is associated. */ + int type; /* Type of menu entry; see below for valid + * types. */ + struct TkMenu *menuPtr; /* Menu with which this entry is + * associated. */ Tk_OptionTable optionTable; /* Option table for this menu entry. */ - Tcl_Obj *labelPtr; /* Main text label displayed in entry (NULL - * if no label). */ + Tcl_Obj *labelPtr; /* Main text label displayed in entry (NULL if + * no label). */ int labelLength; /* Number of non-NULL characters in label. */ int state; /* State of button for display purposes: * normal, active, or disabled. */ @@ -66,19 +82,18 @@ typedef struct TkMenuEntry { Tcl_Obj *underlinePtr; /* Index of character to underline. */ Tcl_Obj *bitmapPtr; /* Bitmap to display in menu entry, or None. * If not None then label is ignored. */ - Tcl_Obj *imagePtr; /* Name of image to display, or - * NULL. If non-NULL, bitmap, text, and - * textVarName are ignored. */ + Tcl_Obj *imagePtr; /* Name of image to display, or NULL. If not + * NULL, bitmap, text, and textVarName are + * ignored. */ Tk_Image image; /* Image to display in menu entry, or NULL if * none. */ - Tcl_Obj *selectImagePtr; /* Name of image to display when selected, or + Tcl_Obj *selectImagePtr; /* Name of image to display when selected, or * NULL. */ - Tk_Image selectImage; /* Image to display in entry when selected, - * or NULL if none. Ignored if image is - * NULL. */ - Tcl_Obj *accelPtr; /* Accelerator string displayed at right - * of menu entry. NULL means no such - * accelerator. Malloc'ed. */ + Tk_Image selectImage; /* Image to display in entry when selected, or + * NULL if none. Ignored if image is NULL. */ + Tcl_Obj *accelPtr; /* Accelerator string displayed at right of + * menu entry. NULL means no such accelerator. + * Malloc'ed. */ int accelLength; /* Number of non-NULL characters in * accelerator. */ int indicatorOn; /* True means draw indicator, false means @@ -89,42 +104,43 @@ typedef struct TkMenuEntry { */ Tcl_Obj *borderPtr; /* Structure used to draw background for - * entry. NULL means use overall border - * for menu. */ - Tcl_Obj *fgPtr; /* Foreground color to use for entry. NULL + * entry. NULL means use overall border for + * menu. */ + Tcl_Obj *fgPtr; /* Foreground color to use for entry. NULL * means use foreground color from menu. */ Tcl_Obj *activeBorderPtr; /* Used to draw background and border when - * element is active. NULL means use + * element is active. NULL means use * activeBorder from menu. */ Tcl_Obj *activeFgPtr; /* Foreground color to use when entry is - * active. NULL means use active foreground + * active. NULL means use active foreground * from menu. */ Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check - * button entries. NULL means use indicatorFg + * button entries. NULL means use indicatorFg * GC from menu. */ - Tcl_Obj *fontPtr; /* Text font for menu entries. NULL means - * use overall font for menu. */ - int columnBreak; /* If this is 0, this item appears below - * the item in front of it. If this is - * 1, this item starts a new column. This - * field is always 0 for tearoff and separator + Tcl_Obj *fontPtr; /* Text font for menu entries. NULL means use + * overall font for menu. */ + int columnBreak; /* If this is 0, this item appears below the + * item in front of it. If this is 1, this + * item starts a new column. This field is + * always 0 for tearoff and separator * entries. */ int hideMargin; /* If this is 0, then the item has enough * margin to accomodate a standard check mark * and a default right margin. If this is 1, - * then the item has no such margins. and + * then the item has no such margins, and * checkbuttons and radiobuttons with this set - * will have a rectangle drawn in the indicator - * around the item if the item is checked. This - * is useful for palette menus. This field is - * ignored for separators and tearoffs. */ + * will have a rectangle drawn in the + * indicator around the item if the item is + * checked. This is useful for palette menus. + * This field is ignored for separators and + * tearoffs. */ int indicatorSpace; /* The width of the indicator space for this * entry. */ int labelWidth; /* Number of pixels to allow for displaying * labels in menu entries. */ - int compound; /* Value of -compound option; specifies whether - * the entry should show both an image and - * text, and, if so, how. */ + int compound; /* Value of -compound option; specifies + * whether the entry should show both an image + * and text, and, if so, how. */ /* * Information used to implement this entry's action: @@ -134,78 +150,76 @@ typedef struct TkMenuEntry { * Malloc'ed. */ Tcl_Obj *namePtr; /* Name of variable (for check buttons and * radio buttons) or menu (for cascade - * entries). Malloc'ed.*/ + * entries). Malloc'ed. */ Tcl_Obj *onValuePtr; /* Value to store in variable when selected * (only for radio and check buttons). * Malloc'ed. */ Tcl_Obj *offValuePtr; /* Value to store in variable when not * selected (only for check buttons). * Malloc'ed. */ - + /* * Information used for drawing this menu entry. */ - + int width; /* Number of pixels occupied by entry in - * horizontal dimension. Not used except - * in menubars. The width of norma menus - * is dependent on the rest of the menu. */ - int x; /* X-coordinate of leftmost pixel in entry */ + * horizontal dimension. Not used except in + * menubars. The width of norma menus is + * dependent on the rest of the menu. */ + int x; /* X-coordinate of leftmost pixel in entry. */ int height; /* Number of pixels occupied by entry in - * vertical dimension, including raised - * border drawn around entry when active. */ + * vertical dimension, including raised border + * drawn around entry when active. */ int y; /* Y-coordinate of topmost pixel in entry. */ - GC textGC; /* GC for drawing text in entry. NULL means + GC textGC; /* GC for drawing text in entry. NULL means * use overall textGC for menu. */ GC activeGC; /* GC for drawing text in entry when active. * NULL means use overall activeGC for * menu. */ GC disabledGC; /* Used to produce disabled effect for entry. - * NULL means use overall disabledGC from - * menu structure. See comments for - * disabledFg in menu structure for more - * information. */ - GC indicatorGC; /* For drawing indicators. None means use - * GC from menu. */ + * NULL means use overall disabledGC from menu + * structure. See comments for disabledFg in + * menu structure for more information. */ + GC indicatorGC; /* For drawing indicators. None means use GC + * from menu. */ /* * Miscellaneous fields. */ - - int entryFlags; /* Various flags. See below for - definitions. */ - int index; /* Need to know which index we are. This - * is zero-based. This is the top-left entry - * of the menu. */ - + + int entryFlags; /* Various flags. See below for + * definitions. */ + int index; /* Need to know which index we are. This is + * zero-based. This is the top-left entry of + * the menu. */ + /* * Bookeeping for master menus and cascade menus. */ - + struct TkMenuReferences *childMenuRefPtr; - /* A pointer to the hash table entry for - * the child menu. Stored here when the menu - * entry is configured so that a hash lookup - * is not necessary later.*/ + /* A pointer to the hash table entry for the + * child menu. Stored here when the menu entry + * is configured so that a hash lookup is not + * necessary later.*/ struct TkMenuEntry *nextCascadePtr; /* The next cascade entry that is a parent of - * this entry's child cascade menu. NULL - * end of list, this is not a cascade entry, - * or the menu that this entry point to - * does not yet exist. */ + * this entry's child cascade menu. NULL end + * of list, this is not a cascade entry, or + * the menu that this entry point to does not + * yet exist. */ TkMenuPlatformEntryData platformEntryData; /* The data for the specific type of menu. - * Depends on platform and menu type what - * kind of options are in this structure. - */ + * Depends on platform and menu type what kind + * of options are in this structure. */ } TkMenuEntry; /* * Flag values defined for menu entries: * - * ENTRY_SELECTED: Non-zero means this is a radio or check - * button and that it should be drawn in - * the "selected" state. + * ENTRY_SELECTED: Non-zero means this is a radio or check button + * and that it should be drawn in the "selected" + * state. * ENTRY_NEEDS_REDISPLAY: Non-zero means the entry should be redisplayed. * ENTRY_LAST_COLUMN: Used by the drawing code. If the entry is in * the last column, the space to its right needs @@ -238,44 +252,43 @@ typedef struct TkMenuEntry { * Menu states */ -EXTERN CONST char *tkMenuStateStrings[]; +MODULE_SCOPE const char *tkMenuStateStrings[]; #define ENTRY_ACTIVE 0 #define ENTRY_NORMAL 1 #define ENTRY_DISABLED 2 /* - * A data structure of the following type is kept for each - * menu widget: + * A data structure of the following type is kept for each menu widget: */ typedef struct TkMenu { - Tk_Window tkwin; /* Window that embodies the pane. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display containing widget. Needed, among + Tk_Window tkwin; /* Window that embodies the pane. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up. */ + Display *display; /* Display containing widget. Needed, among * other things, so that resources can be * freed up even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with menu. */ Tcl_Command widgetCmd; /* Token for menu's widget command. */ - TkMenuEntry **entries; /* Array of pointers to all the entries - * in the menu. NULL means no entries. */ + TkMenuEntry **entries; /* Array of pointers to all the entries in the + * menu. NULL means no entries. */ int numEntries; /* Number of elements in entries. */ - int active; /* Index of active entry. -1 means - * nothing active. */ - int menuType; /* MASTER_MENU, TEAROFF_MENU, or MENUBAR. - * See below for definitions. */ - Tcl_Obj *menuTypePtr; /* Used to control whether created tkwin - * is a toplevel or not. "normal", "menubar", - * or "toplevel" */ + int active; /* Index of active entry. -1 means nothing + * active. */ + int menuType; /* MASTER_MENU, TEAROFF_MENU, or MENUBAR. See + * below for definitions. */ + Tcl_Obj *menuTypePtr; /* Used to control whether created tkwin is a + * toplevel or not. "normal", "menubar", or + * "toplevel" */ /* * Information used when displaying widget: */ - Tcl_Obj *borderPtr; /* Structure used to draw 3-D - * border and background for menu. */ + Tcl_Obj *borderPtr; /* Structure used to draw 3-D border and + * background for menu. */ Tcl_Obj *borderWidthPtr; /* Width of border around whole menu. */ Tcl_Obj *activeBorderPtr; /* Used to draw background and border for * active element (if any). */ @@ -284,18 +297,17 @@ typedef struct TkMenu { Tcl_Obj *reliefPtr; /* 3-d effect: TK_RELIEF_RAISED, etc. */ Tcl_Obj *fontPtr; /* Text font for menu entries. */ Tcl_Obj *fgPtr; /* Foreground color for entries. */ - Tcl_Obj *disabledFgPtr; /* Foreground color when disabled. NULL - * means use normalFg with a 50% stipple - * instead. */ + Tcl_Obj *disabledFgPtr; /* Foreground color when disabled. NULL means + * use normalFg with a 50% stipple instead. */ Tcl_Obj *activeFgPtr; /* Foreground color for active entry. */ Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check * button entries. */ - Pixmap gray; /* Bitmap for drawing disabled entries in - * a stippled fashion. None means not - * allocated yet. */ - GC textGC; /* GC for drawing text and other features - * of menu entries. */ - GC disabledGC; /* Used to produce disabled effect. If + Pixmap gray; /* Bitmap for drawing disabled entries in a + * stippled fashion. None means not allocated + * yet. */ + GC textGC; /* GC for drawing text and other features of + * menu entries. */ + GC disabledGC; /* Used to produce disabled effect. If * disabledFg isn't NULL, this GC is used to * draw text and icons for disabled entries. * Otherwise text and icons are drawn with @@ -303,52 +315,51 @@ typedef struct TkMenu { * background across them. */ GC activeGC; /* GC for drawing active entry. */ GC indicatorGC; /* For drawing indicators. */ - GC disabledImageGC; /* Used for drawing disabled images. They - * have to be stippled. This is created - * when the image is about to be drawn the - * first time. */ + GC disabledImageGC; /* Used for drawing disabled images. They have + * to be stippled. This is created when the + * image is about to be drawn the first + * time. */ /* * Information about geometry of menu. */ - - int totalWidth; /* Width of entire menu */ - int totalHeight; /* Height of entire menu */ - + + int totalWidth; /* Width of entire menu. */ + int totalHeight; /* Height of entire menu. */ + /* * Miscellaneous information: */ int tearoff; /* 1 means this menu can be torn off. On some - * platforms, the user can drag an outline - * of the menu by just dragging outside of - * the menu, and the tearoff is created where - * the mouse is released. On others, an - * indicator (such as a dashed stripe) is - * drawn, and when the menu is selected, the - * tearoff is created. */ + * platforms, the user can drag an outline of + * the menu by just dragging outside of the + * menu, and the tearoff is created where the + * mouse is released. On others, an indicator + * (such as a dashed stripe) is drawn, and + * when the menu is selected, the tearoff is + * created. */ Tcl_Obj *titlePtr; /* The title to use when this menu is torn - * off. If this is NULL, a default scheme - * will be used to generate a title for - * tearoff. */ - Tcl_Obj *tearoffCommandPtr; /* If non-NULL, points to a command to - * run whenever the menu is torn-off. */ - Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ + * off. If this is NULL, a default scheme will + * be used to generate a title for tearoff. */ + Tcl_Obj *tearoffCommandPtr; /* If non-NULL, points to a command to run + * whenever the menu is torn-off. */ + Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ Tcl_Obj *cursorPtr; /* Current cursor for window, or None. */ Tcl_Obj *postCommandPtr; /* Used to detect cycles in cascade hierarchy - * trees when preprocessing postcommands - * on some platforms. See PostMenu for - * more details. */ + * trees when preprocessing postcommands on + * some platforms. See PostMenu for more + * details. */ int postCommandGeneration; /* Need to do pre-invocation post command - * traversal */ + * traversal. */ int menuFlags; /* Flags for use by X; see below for - definition */ + * definition. */ TkMenuEntry *postedCascade; /* Points to menu entry for cascaded submenu * that is currently posted or NULL if no * submenu posted. */ - struct TkMenu *nextInstancePtr; + struct TkMenu *nextInstancePtr; /* The next instance of this menu in the * chain. */ struct TkMenu *masterMenuPtr; @@ -356,29 +367,26 @@ typedef struct TkMenu { * clone chain. Points back to this structure * if this menu is a master menu. */ struct TkMenuOptionTables *optionTablesPtr; - /* A pointer to the collection of option tables - * that work with menus and menu entries. */ + /* A pointer to the collection of option + * tables that work with menus and menu + * entries. */ Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the - * toplevel that owns the menu. Only applicable - * for menubar clones. - */ - struct TkMenuReferences *menuRefPtr; + * toplevel that owns the menu. Only + * applicable for menubar clones. */ + struct TkMenuReferences *menuRefPtr; /* Each menu is hashed into a table with the - * name of the menu's window as the key. - * The information in this hash table includes - * a pointer to the menu (so that cascades - * can find this menu), a pointer to the - * list of toplevel widgets that have this - * menu as its menubar, and a list of menu - * entries that have this menu specified - * as a cascade. */ + * name of the menu's window as the key. The + * information in this hash table includes a + * pointer to the menu (so that cascades can + * find this menu), a pointer to the list of + * toplevel widgets that have this menu as its + * menubar, and a list of menu entries that + * have this menu specified as a cascade. */ TkMenuPlatformData platformData; /* The data for the specific type of menu. - * Depends on platform and menu type what - * kind of options are in this structure. - */ - Tk_OptionSpec *extensionPtr; - /* Needed by the configuration package for + * Depends on platform and menu type what kind + * of options are in this structure. */ + Tk_OptionSpec *extensionPtr;/* Needed by the configuration package for * this widget to be extended. */ Tk_SavedOptions *errorStructPtr; /* We actually have to allocate these because @@ -388,95 +396,94 @@ typedef struct TkMenu { /* * When the toplevel configure -menu command is executed, the menu may not - * exist yet. We need to keep a linked list of windows that reference - * a particular menu. + * exist yet. We need to keep a linked list of windows that reference a + * particular menu. */ typedef struct TkMenuTopLevelList { struct TkMenuTopLevelList *nextPtr; - /* The next window in the list */ + /* The next window in the list. */ Tk_Window tkwin; /* The window that has this menu as its * menubar. */ } TkMenuTopLevelList; /* - * The following structure is used to keep track of things which - * reference a menu. It is created when: + * The following structure is used to keep track of things which reference a + * menu. It is created when: * - a menu is created. * - a cascade entry is added to a menu with a non-null name - * - the "-menu" configuration option is used on a toplevel widget - * with a non-null parameter. + * - the "-menu" configuration option is used on a toplevel widget with a + * non-null parameter. * - * One of these three fields must be non-NULL, but any of the fields may - * be NULL. This structure makes it easy to determine whether or not - * anything like recalculating platform data or geometry is necessary - * when one of the three actions above is performed. + * One of these three fields must be non-NULL, but any of the fields may be + * NULL. This structure makes it easy to determine whether or not anything + * like recalculating platform data or geometry is necessary when one of the + * three actions above is performed. */ typedef struct TkMenuReferences { - struct TkMenu *menuPtr; /* The menu data structure. This is NULL - * if the menu does not exist. */ + struct TkMenu *menuPtr; /* The menu data structure. This is NULL if + * the menu does not exist. */ TkMenuTopLevelList *topLevelListPtr; - /* First in the list of all toplevels that - * have this menu as its menubar. NULL if no + /* First in the list of all toplevels that + * have this menu as its menubar. NULL if no * toplevel widgets have this menu as its * menubar. */ - TkMenuEntry *parentEntryPtr;/* First in the list of all cascade menu + TkMenuEntry *parentEntryPtr;/* First in the list of all cascade menu * entries that have this menu as their child. * NULL means no cascade entries. */ Tcl_HashEntry *hashEntryPtr;/* This is needed because the pathname of the * window (which is what we hash on) may not - * be around when we are deleting. - */ + * be around when we are deleting. */ } TkMenuReferences; /* - * This structure contains all of the option tables that are needed - * by menus. + * This structure contains all of the option tables that are needed by menus. */ typedef struct TkMenuOptionTables { - Tk_OptionTable menuOptionTable; /* The option table for menus. */ - Tk_OptionTable entryOptionTables[6];/* The tables for menu entries. */ + Tk_OptionTable menuOptionTable; + /* The option table for menus. */ + Tk_OptionTable entryOptionTables[6]; + /* The tables for menu entries. */ } TkMenuOptionTables; /* * Flag bits for menus: * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler - * has already been queued to redraw - * this window. + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has + * already been queued to redraw this window. * RESIZE_PENDING: Non-zero means a call to ComputeMenuGeometry * has already been scheduled. - * MENU_DELETION_PENDING Non-zero means that we are currently destroying - * this menu's internal structures. This is useful - * when we are in the middle of cleaning - * this master menu's chain of menus up when - * TkDestroyMenu was called again on this + * MENU_DELETION_PENDING Non-zero means that we are currently + * destroying this menu's internal structures. + * This is useful when we are in the middle of + * cleaning this master menu's chain of menus up + * when TkDestroyMenu was called again on this * menu (via a destroy binding or somesuch). - * MENU_WIN_DESTRUCTION_PENDING Non-zero means we are in the middle of - * destroying this menu's Tk_Window. + * MENU_WIN_DESTRUCTION_PENDING Non-zero means we are in the middle of + * destroying this menu's Tk_Window. * MENU_PLATFORM_FLAG1... Reserved for use by the platform-specific menu * code. */ -#define REDRAW_PENDING 1 -#define RESIZE_PENDING 2 -#define MENU_DELETION_PENDING 4 +#define REDRAW_PENDING 1 +#define RESIZE_PENDING 2 +#define MENU_DELETION_PENDING 4 #define MENU_WIN_DESTRUCTION_PENDING 8 #define MENU_PLATFORM_FLAG1 (1 << 30) #define MENU_PLATFORM_FLAG2 (1 << 29) #define MENU_PLATFORM_FLAG3 (1 << 28) /* - * Each menu created by the user is a MASTER_MENU. When a menu is torn off, - * a TEAROFF_MENU instance is created. When a menu is assigned to a toplevel - * as a menu bar, a MENUBAR instance is created. All instances have the same + * Each menu created by the user is a MASTER_MENU. When a menu is torn off, a + * TEAROFF_MENU instance is created. When a menu is assigned to a toplevel as + * a menu bar, a MENUBAR instance is created. All instances have the same * configuration information. If the master instance is deleted, all instances * are deleted. If one of the other instances is deleted, only that instance * is deleted. */ - + #define UNKNOWN_TYPE -1 #define MASTER_MENU 0 #define TEAROFF_MENU 1 @@ -486,101 +493,81 @@ typedef struct TkMenuOptionTables { * Various geometry definitions: */ -#define CASCADE_ARROW_HEIGHT 10 -#define CASCADE_ARROW_WIDTH 8 -#define DECORATION_BORDER_WIDTH 2 +#define CASCADE_ARROW_HEIGHT 10 +#define CASCADE_ARROW_WIDTH 8 +#define DECORATION_BORDER_WIDTH 2 /* - * Menu-related procedures that are shared among Tk modules but not exported - * to the outside world: + * Menu-related functions that are shared among Tk modules but not exported to + * the outside world: */ -EXTERN int TkActivateMenuEntry _ANSI_ARGS_((TkMenu *menuPtr, - int index)); -EXTERN void TkBindMenu _ANSI_ARGS_(( - Tk_Window tkwin, TkMenu *menuPtr)); -EXTERN TkMenuReferences * - TkCreateMenuReferences _ANSI_ARGS_((Tcl_Interp *interp, - char *name)); -EXTERN void TkDestroyMenu _ANSI_ARGS_((TkMenu *menuPtr)); -EXTERN void TkEventuallyRecomputeMenu _ANSI_ARGS_(( - TkMenu *menuPtr)); -EXTERN void TkEventuallyRedrawMenu _ANSI_ARGS_(( - TkMenu *menuPtr, TkMenuEntry *mePtr)); -EXTERN TkMenuReferences * - TkFindMenuReferences _ANSI_ARGS_((Tcl_Interp *interp, - char *name)); -EXTERN TkMenuReferences * - TkFindMenuReferencesObj _ANSI_ARGS_(( - Tcl_Interp *interp, Tcl_Obj *namePtr)); -EXTERN int TkFreeMenuReferences _ANSI_ARGS_(( - TkMenuReferences *menuRefPtr)); -EXTERN Tcl_HashTable * TkGetMenuHashTable _ANSI_ARGS_((Tcl_Interp *interp)); -EXTERN int TkGetMenuIndex _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, Tcl_Obj *objPtr, int lastOK, - int *indexPtr)); -EXTERN void TkMenuInitializeDrawingFields _ANSI_ARGS_(( - TkMenu *menuPtr)); -EXTERN void TkMenuInitializeEntryDrawingFields _ANSI_ARGS_(( - TkMenuEntry *mePtr)); -EXTERN int TkInvokeMenu _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, int index)); -EXTERN void TkMenuConfigureDrawOptions _ANSI_ARGS_(( - TkMenu *menuPtr)); -EXTERN int TkMenuConfigureEntryDrawOptions _ANSI_ARGS_(( - TkMenuEntry *mePtr, int index)); -EXTERN void TkMenuFreeDrawOptions _ANSI_ARGS_((TkMenu *menuPtr)); -EXTERN void TkMenuEntryFreeDrawOptions _ANSI_ARGS_(( - TkMenuEntry *mePtr)); -EXTERN void TkMenuEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -EXTERN void TkMenuImageProc _ANSI_ARGS_(( - ClientData clientData, int x, int y, int width, - int height, int imgWidth, int imgHeight)); -EXTERN void TkMenuInit _ANSI_ARGS_((void)); -EXTERN void TkMenuSelectImageProc _ANSI_ARGS_ - ((ClientData clientData, int x, int y, +MODULE_SCOPE int TkActivateMenuEntry(TkMenu *menuPtr, int index); +MODULE_SCOPE void TkBindMenu(Tk_Window tkwin, TkMenu *menuPtr); +MODULE_SCOPE TkMenuReferences*TkCreateMenuReferences(Tcl_Interp *interp, + char *name); +MODULE_SCOPE void TkDestroyMenu(TkMenu *menuPtr); +MODULE_SCOPE void TkEventuallyRecomputeMenu(TkMenu *menuPtr); +MODULE_SCOPE void TkEventuallyRedrawMenu(TkMenu *menuPtr, + TkMenuEntry *mePtr); +MODULE_SCOPE TkMenuReferences*TkFindMenuReferences(Tcl_Interp *interp, char *name); +MODULE_SCOPE TkMenuReferences*TkFindMenuReferencesObj(Tcl_Interp *interp, + Tcl_Obj *namePtr); +MODULE_SCOPE int TkFreeMenuReferences(TkMenuReferences *menuRefPtr); +MODULE_SCOPE Tcl_HashTable *TkGetMenuHashTable(Tcl_Interp *interp); +MODULE_SCOPE int TkGetMenuIndex(Tcl_Interp *interp, TkMenu *menuPtr, + Tcl_Obj *objPtr, int lastOK, int *indexPtr); +MODULE_SCOPE void TkMenuInitializeDrawingFields(TkMenu *menuPtr); +MODULE_SCOPE void TkMenuInitializeEntryDrawingFields(TkMenuEntry *mePtr); +MODULE_SCOPE int TkInvokeMenu(Tcl_Interp *interp, TkMenu *menuPtr, + int index); +MODULE_SCOPE void TkMenuConfigureDrawOptions(TkMenu *menuPtr); +MODULE_SCOPE int TkMenuConfigureEntryDrawOptions( + TkMenuEntry *mePtr, int index); +MODULE_SCOPE void TkMenuFreeDrawOptions(TkMenu *menuPtr); +MODULE_SCOPE void TkMenuEntryFreeDrawOptions(TkMenuEntry *mePtr); +MODULE_SCOPE void TkMenuEventProc(ClientData clientData, + XEvent *eventPtr); +MODULE_SCOPE void TkMenuImageProc(ClientData clientData, int x, int y, int width, int height, int imgWidth, - int imgHeight)); -EXTERN Tcl_Obj * TkNewMenuName _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *parentNamePtr, TkMenu *menuPtr)); -EXTERN int TkPostCommand _ANSI_ARGS_((TkMenu *menuPtr)); -EXTERN int TkPostSubmenu _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, TkMenuEntry *mePtr)); -EXTERN int TkPostTearoffMenu _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, int x, int y)); -EXTERN int TkPreprocessMenu _ANSI_ARGS_((TkMenu *menuPtr)); -EXTERN void TkRecomputeMenu _ANSI_ARGS_((TkMenu *menuPtr)); + int imgHeight); +MODULE_SCOPE void TkMenuInit(void); +MODULE_SCOPE void TkMenuSelectImageProc(ClientData clientData, int x, + int y, int width, int height, int imgWidth, + int imgHeight); +MODULE_SCOPE Tcl_Obj * TkNewMenuName(Tcl_Interp *interp, + Tcl_Obj *parentNamePtr, TkMenu *menuPtr); +MODULE_SCOPE int TkPostCommand(TkMenu *menuPtr); +MODULE_SCOPE int TkPostSubmenu(Tcl_Interp *interp, TkMenu *menuPtr, + TkMenuEntry *mePtr); +MODULE_SCOPE int TkPostTearoffMenu(Tcl_Interp *interp, TkMenu *menuPtr, + int x, int y); +MODULE_SCOPE int TkPreprocessMenu(TkMenu *menuPtr); +MODULE_SCOPE void TkRecomputeMenu(TkMenu *menuPtr); /* - * These routines are the platform-dependent routines called by the - * common code. + * These routines are the platform-dependent routines called by the common + * code. */ -EXTERN void TkpComputeMenubarGeometry _ANSI_ARGS_(( - TkMenu *menuPtr)); -EXTERN void TkpComputeStandardMenuGeometry _ANSI_ARGS_ - ((TkMenu *menuPtr)); -EXTERN int TkpConfigureMenuEntry - _ANSI_ARGS_((TkMenuEntry *mePtr)); -EXTERN void TkpDestroyMenu _ANSI_ARGS_((TkMenu *menuPtr)); -EXTERN void TkpDestroyMenuEntry - _ANSI_ARGS_((TkMenuEntry *mEntryPtr)); -EXTERN void TkpDrawMenuEntry _ANSI_ARGS_((TkMenuEntry *mePtr, - Drawable d, Tk_Font tkfont, - CONST Tk_FontMetrics *menuMetricsPtr, int x, +MODULE_SCOPE void TkpComputeMenubarGeometry(TkMenu *menuPtr); +MODULE_SCOPE void TkpComputeStandardMenuGeometry(TkMenu *menuPtr); +MODULE_SCOPE int TkpConfigureMenuEntry(TkMenuEntry *mePtr); +MODULE_SCOPE void TkpDestroyMenu(TkMenu *menuPtr); +MODULE_SCOPE void TkpDestroyMenuEntry(TkMenuEntry *mEntryPtr); +MODULE_SCOPE void TkpDrawMenuEntry(TkMenuEntry *mePtr, + Drawable d, Tk_Font tkfont, + const Tk_FontMetrics *menuMetricsPtr, int x, int y, int width, int height, int strictMotif, - int drawArrow)); -EXTERN void TkpMenuInit _ANSI_ARGS_((void)); -EXTERN int TkpMenuNewEntry _ANSI_ARGS_((TkMenuEntry *mePtr)); -EXTERN int TkpNewMenu _ANSI_ARGS_((TkMenu *menuPtr)); -EXTERN int TkpPostMenu _ANSI_ARGS_((Tcl_Interp *interp, - TkMenu *menuPtr, int x, int y)); -EXTERN void TkpSetWindowMenuBar _ANSI_ARGS_((Tk_Window tkwin, - TkMenu *menuPtr)); + int drawingParameters); +MODULE_SCOPE void TkpMenuInit(void); +MODULE_SCOPE int TkpMenuNewEntry(TkMenuEntry *mePtr); +MODULE_SCOPE int TkpNewMenu(TkMenu *menuPtr); +MODULE_SCOPE int TkpPostMenu(Tcl_Interp *interp, TkMenu *menuPtr, + int x, int y); +MODULE_SCOPE void TkpSetWindowMenuBar(Tk_Window tkwin, TkMenu *menuPtr); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TKMENU */ - diff --git a/generic/tkMenuDraw.c b/generic/tkMenuDraw.c index 33dadc1..d2a66d3 100644 --- a/generic/tkMenuDraw.c +++ b/generic/tkMenuDraw.c @@ -1,35 +1,34 @@ -/* +/* * tkMenuDraw.c -- * - * This module implements the platform-independent drawing and - * geometry calculations of menu widgets. + * This module implements the platform-independent drawing and geometry + * calculations of menu widgets. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkMenu.h" /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void AdjustMenuCoords _ANSI_ARGS_ ((TkMenu *menuPtr, - TkMenuEntry *mePtr, int *xPtr, int *yPtr, - char *string)); -static void ComputeMenuGeometry _ANSI_ARGS_(( - ClientData clientData)); -static void DisplayMenu _ANSI_ARGS_((ClientData clientData)); +static void AdjustMenuCoords(TkMenu *menuPtr, TkMenuEntry *mePtr, + int *xPtr, int *yPtr); +static void ComputeMenuGeometry(ClientData clientData); +static void DisplayMenu(ClientData clientData); /* *---------------------------------------------------------------------- * * TkMenuInitializeDrawingFields -- * - * Fills in drawing fields of a new menu. Called when new menu is - * created by MenuCmd. + * Fills in drawing fields of a new menu. Called when new menu is created + * by MenuCmd. * * Results: * None. @@ -41,8 +40,8 @@ static void DisplayMenu _ANSI_ARGS_((ClientData clientData)); */ void -TkMenuInitializeDrawingFields(menuPtr) - TkMenu *menuPtr; /* The menu we are initializing. */ +TkMenuInitializeDrawingFields( + TkMenu *menuPtr) /* The menu we are initializing. */ { menuPtr->textGC = None; menuPtr->gray = None; @@ -58,8 +57,8 @@ TkMenuInitializeDrawingFields(menuPtr) * * TkMenuInitializeEntryDrawingFields -- * - * Fills in drawing fields of a new menu entry. Called when an - * entry is created. + * Fills in drawing fields of a new menu entry. Called when an entry is + * created. * * Results: * None. @@ -71,8 +70,8 @@ TkMenuInitializeDrawingFields(menuPtr) */ void -TkMenuInitializeEntryDrawingFields(mePtr) - TkMenuEntry *mePtr; /* The menu we are initializing. */ +TkMenuInitializeEntryDrawingFields( + TkMenuEntry *mePtr) /* The menu we are initializing. */ { mePtr->width = 0; mePtr->height = 0; @@ -91,8 +90,8 @@ TkMenuInitializeEntryDrawingFields(mePtr) * * TkMenuFreeDrawOptions -- * - * Frees up any structures allocated for the drawing of a menu. - * Called when menu is deleted. + * Frees up any structures allocated for the drawing of a menu. Called + * when menu is deleted. * * Results: * None. @@ -104,8 +103,8 @@ TkMenuInitializeEntryDrawingFields(mePtr) */ void -TkMenuFreeDrawOptions(menuPtr) - TkMenu *menuPtr; +TkMenuFreeDrawOptions( + TkMenu *menuPtr) { if (menuPtr->textGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->textGC); @@ -132,8 +131,8 @@ TkMenuFreeDrawOptions(menuPtr) * * TkMenuEntryFreeDrawOptions -- * - * Frees up drawing structures for a menu entry. Called when - * menu entry is freed. + * Frees up drawing structures for a menu entry. Called when menu entry + * is freed. * * RESULTS: * None. @@ -145,8 +144,8 @@ TkMenuFreeDrawOptions(menuPtr) */ void -TkMenuEntryFreeDrawOptions(mePtr) - TkMenuEntry *mePtr; +TkMenuEntryFreeDrawOptions( + TkMenuEntry *mePtr) { if (mePtr->textGC != None) { Tk_FreeGC(mePtr->menuPtr->display, mePtr->textGC); @@ -167,8 +166,8 @@ TkMenuEntryFreeDrawOptions(mePtr) * * TkMenuConfigureDrawOptions -- * - * Sets the menu's drawing attributes in preparation for drawing - * the menu. + * Sets the menu's drawing attributes in preparation for drawing the + * menu. * * RESULTS: * None. @@ -180,8 +179,8 @@ TkMenuEntryFreeDrawOptions(mePtr) */ void -TkMenuConfigureDrawOptions(menuPtr) - TkMenu *menuPtr; /* The menu we are configuring. */ +TkMenuConfigureDrawOptions( + TkMenu *menuPtr) /* The menu we are configuring. */ { XGCValues gcValues; GC newGC; @@ -189,11 +188,11 @@ TkMenuConfigureDrawOptions(menuPtr) Tk_3DBorder border, activeBorder; Tk_Font tkfont; XColor *fg, *activeFg, *indicatorFg; - + /* - * A few options need special processing, such as setting the - * background from a 3-D border, or filling in complicated - * defaults that couldn't be specified to Tk_ConfigureWidget. + * A few options need special processing, such as setting the background + * from a 3-D border, or filling in complicated defaults that couldn't be + * specified to Tk_ConfigureWidget. */ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); @@ -216,7 +215,7 @@ TkMenuConfigureDrawOptions(menuPtr) if (menuPtr->disabledFgPtr != NULL) { XColor *disabledFg; - disabledFg = Tk_GetColorFromObj(menuPtr->tkwin, + disabledFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->disabledFgPtr); gcValues.foreground = disabledFg->pixel; mask = GCForeground|GCBackground|GCFont; @@ -247,7 +246,7 @@ TkMenuConfigureDrawOptions(menuPtr) if (menuPtr->gray != None) { gcValues.fill_style = FillStippled; gcValues.stipple = menuPtr->gray; - newGC = Tk_GetGC(menuPtr->tkwin, + newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCFillStyle|GCStipple, &gcValues); } if (menuPtr->disabledImageGC != None) { @@ -258,7 +257,7 @@ TkMenuConfigureDrawOptions(menuPtr) gcValues.font = Tk_FontId(tkfont); activeFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->activeFgPtr); gcValues.foreground = activeFg->pixel; - activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, + activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->activeBorderPtr); gcValues.background = Tk_3DBorderColor(activeBorder)->pixel; newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont, @@ -268,7 +267,7 @@ TkMenuConfigureDrawOptions(menuPtr) } menuPtr->activeGC = newGC; - indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin, + indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->indicatorFgPtr); gcValues.foreground = indicatorFg->pixel; gcValues.background = Tk_3DBorderColor(border)->pixel; @@ -285,8 +284,7 @@ TkMenuConfigureDrawOptions(menuPtr) * * TkMenuConfigureEntryDrawOptions -- * - * Calculates any entry-specific draw options for the given menu - * entry. + * Calculates any entry-specific draw options for the given menu entry. * * Results: * Returns a standard Tcl error. @@ -298,11 +296,10 @@ TkMenuConfigureDrawOptions(menuPtr) */ int -TkMenuConfigureEntryDrawOptions(mePtr, index) - TkMenuEntry *mePtr; - int index; +TkMenuConfigureEntryDrawOptions( + TkMenuEntry *mePtr, + int index) { - XGCValues gcValues; GC newGC, newActiveGC, newDisabledGC, newIndicatorGC; unsigned long mask; @@ -311,7 +308,7 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) tkfont = Tk_GetFontFromObj(menuPtr->tkwin, (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr); - + if (mePtr->state == ENTRY_ACTIVE) { if (index != menuPtr->active) { TkActivateMenuEntry(menuPtr, index); @@ -330,21 +327,21 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) || (mePtr->indicatorFgPtr != NULL)) { XColor *fg, *indicatorFg, *activeFg; Tk_3DBorder border, activeBorder; - + fg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->fgPtr != NULL) ? mePtr->fgPtr : menuPtr->fgPtr); gcValues.foreground = fg->pixel; - border = Tk_Get3DBorderFromObj(menuPtr->tkwin, - (mePtr->borderPtr != NULL) ? mePtr->borderPtr + border = Tk_Get3DBorderFromObj(menuPtr->tkwin, + (mePtr->borderPtr != NULL) ? mePtr->borderPtr : menuPtr->borderPtr); gcValues.background = Tk_3DBorderColor(border)->pixel; gcValues.font = Tk_FontId(tkfont); /* - * Note: disable GraphicsExpose events; we know there won't be - * obscured areas when copying from an off-screen pixmap to the - * screen and this gets rid of unnecessary events. + * Note: disable GraphicsExpose events; we know there won't be + * obscured areas when copying from an off-screen pixmap to the screen + * and this gets rid of unnecessary events. */ gcValues.graphics_exposures = False; @@ -352,7 +349,7 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) GCForeground|GCBackground|GCFont|GCGraphicsExposures, &gcValues); - indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin, + indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->indicatorFgPtr != NULL) ? mePtr->indicatorFgPtr : menuPtr->indicatorFgPtr); gcValues.foreground = indicatorFg->pixel; @@ -363,7 +360,7 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) if ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) { XColor *disabledFg; - disabledFg = Tk_GetColorFromObj(menuPtr->tkwin, + disabledFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->disabledFgPtr); gcValues.foreground = disabledFg->pixel; mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures; @@ -375,13 +372,13 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) } newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues); - activeFg = Tk_GetColorFromObj(menuPtr->tkwin, + activeFg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->activeFgPtr != NULL) ? mePtr->activeFgPtr : menuPtr->activeFgPtr); - activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, - (mePtr->activeBorderPtr != NULL) ? mePtr->activeBorderPtr + activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, + (mePtr->activeBorderPtr != NULL) ? mePtr->activeBorderPtr : menuPtr->activeBorderPtr); - + gcValues.foreground = activeFg->pixel; gcValues.background = Tk_3DBorderColor(activeBorder)->pixel; newActiveGC = Tk_GetGC(menuPtr->tkwin, @@ -394,15 +391,15 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) newIndicatorGC = None; } if (mePtr->textGC != None) { - Tk_FreeGC(menuPtr->display, mePtr->textGC); + Tk_FreeGC(menuPtr->display, mePtr->textGC); } mePtr->textGC = newGC; if (mePtr->activeGC != None) { - Tk_FreeGC(menuPtr->display, mePtr->activeGC); + Tk_FreeGC(menuPtr->display, mePtr->activeGC); } mePtr->activeGC = newActiveGC; if (mePtr->disabledGC != None) { - Tk_FreeGC(menuPtr->display, mePtr->disabledGC); + Tk_FreeGC(menuPtr->display, mePtr->disabledGC); } mePtr->disabledGC = newDisabledGC; if (mePtr->indicatorGC != None) { @@ -430,8 +427,8 @@ TkMenuConfigureEntryDrawOptions(mePtr, index) */ void -TkEventuallyRecomputeMenu(menuPtr) - TkMenu *menuPtr; +TkEventuallyRecomputeMenu( + TkMenu *menuPtr) { if (!(menuPtr->menuFlags & RESIZE_PENDING)) { menuPtr->menuFlags |= RESIZE_PENDING; @@ -444,8 +441,8 @@ TkEventuallyRecomputeMenu(menuPtr) * * TkRecomputeMenu -- * - * Tells Tcl to redo the geometry because this menu has changed. - * Does it now; removes any ComputeMenuGeometries from the idler. + * Tells Tcl to redo the geometry because this menu has changed. Does it + * now; removes any ComputeMenuGeometries from the idler. * * Results: * None. @@ -457,9 +454,9 @@ TkEventuallyRecomputeMenu(menuPtr) */ void -TkRecomputeMenu(menuPtr) - TkMenu *menuPtr; -{ +TkRecomputeMenu( + TkMenu *menuPtr) +{ if (menuPtr->menuFlags & RESIZE_PENDING) { Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr); ComputeMenuGeometry((ClientData) menuPtr); @@ -471,27 +468,27 @@ TkRecomputeMenu(menuPtr) * * TkEventuallyRedrawMenu -- * - * Arrange for an entry of a menu, or the whole menu, to be - * redisplayed at some point in the future. + * Arrange for an entry of a menu, or the whole menu, to be redisplayed + * at some point in the future. * * Results: * None. * * Side effects: - * A when-idle hander is scheduled to do the redisplay, if there - * isn't one already scheduled. + * A when-idle hander is scheduled to do the redisplay, if there isn't + * one already scheduled. * *---------------------------------------------------------------------- */ void -TkEventuallyRedrawMenu(menuPtr, mePtr) - register TkMenu *menuPtr; /* Information about menu to redraw. */ - register TkMenuEntry *mePtr;/* Entry to redraw. NULL means redraw - * all the entries in the menu. */ +TkEventuallyRedrawMenu( + register TkMenu *menuPtr, /* Information about menu to redraw. */ + register TkMenuEntry *mePtr)/* Entry to redraw. NULL means redraw all the + * entries in the menu. */ { int i; - + if (menuPtr->tkwin == NULL) { return; } @@ -515,25 +512,23 @@ TkEventuallyRedrawMenu(menuPtr, mePtr) * * ComputeMenuGeometry -- * - * This procedure is invoked to recompute the size and - * layout of a menu. It is called as a when-idle handler so - * that it only gets done once, even if a group of changes is - * made to the menu. + * This function is invoked to recompute the size and layout of a menu. + * It is called as a when-idle handler so that it only gets done once, + * even if a group of changes is made to the menu. * * Results: * None. * * Side effects: - * Fields of menu entries are changed to reflect their - * current positions, and the size of the menu window - * itself may be changed. + * Fields of menu entries are changed to reflect their current positions, + * and the size of the menu window itself may be changed. * *-------------------------------------------------------------- */ static void -ComputeMenuGeometry(clientData) - ClientData clientData; /* Structure describing menu. */ +ComputeMenuGeometry( + ClientData clientData) /* Structure describing menu. */ { TkMenu *menuPtr = (TkMenu *) clientData; @@ -552,16 +547,15 @@ ComputeMenuGeometry(clientData) Tk_GeometryRequest(menuPtr->tkwin, menuPtr->totalWidth, menuPtr->totalHeight); } - + /* - * Must always force a redisplay here if the window is mapped - * (even if the size didn't change, something else might have - * changed in the menu, such as a label or accelerator). The - * resize will force a redisplay above. + * Must always force a redisplay here if the window is mapped (even if the + * size didn't change, something else might have changed in the menu, such + * as a label or accelerator). The resize will force a redisplay above. */ - - TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL); - + + TkEventuallyRedrawMenu(menuPtr, NULL); + menuPtr->menuFlags &= ~RESIZE_PENDING; } @@ -570,9 +564,9 @@ ComputeMenuGeometry(clientData) * * TkMenuSelectImageProc -- * - * This procedure is invoked by the image code whenever the manager - * for an image does something that affects the size of contents - * of an image displayed in a menu entry when it is selected. + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size of contents of an image + * displayed in a menu entry when it is selected. * * Results: * None. @@ -584,20 +578,18 @@ ComputeMenuGeometry(clientData) */ void -TkMenuSelectImageProc(clientData, x, y, width, height, imgWidth, - imgHeight) - ClientData clientData; /* Pointer to widget record. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +TkMenuSelectImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (may be + * <=0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { register TkMenuEntry *mePtr = (TkMenuEntry *) clientData; if ((mePtr->entryFlags & ENTRY_SELECTED) - && !(mePtr->menuPtr->menuFlags & - REDRAW_PENDING)) { + && !(mePtr->menuPtr->menuFlags & REDRAW_PENDING)) { mePtr->menuPtr->menuFlags |= REDRAW_PENDING; Tcl_DoWhenIdle(DisplayMenu, (ClientData) mePtr->menuPtr); } @@ -608,21 +600,20 @@ TkMenuSelectImageProc(clientData, x, y, width, height, imgWidth, * * DisplayMenu -- * - * This procedure is invoked to display a menu widget. + * This function is invoked to display a menu widget. * * Results: * None. * * Side effects: - * Commands are output to X to display the menu in its - * current mode. + * Commands are output to X to display the menu in its current mode. * *---------------------------------------------------------------------- */ static void -DisplayMenu(clientData) - ClientData clientData; /* Information about widget. */ +DisplayMenu( + ClientData clientData) /* Information about widget. */ { register TkMenu *menuPtr = (TkMenu *) clientData; register TkMenuEntry *mePtr; @@ -649,8 +640,8 @@ DisplayMenu(clientData) menuPtr->activeBorderWidthPtr, &activeBorderWidth); if (menuPtr->menuType == MENUBAR) { - Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth, - borderWidth, Tk_Width(tkwin) - 2 * borderWidth, + Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth, + borderWidth, Tk_Width(tkwin) - 2 * borderWidth, Tk_Height(tkwin) - 2 * borderWidth, 0, TK_RELIEF_FLAT); } @@ -688,15 +679,15 @@ DisplayMenu(clientData) } } TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont, - &menuMetrics, mePtr->x, mePtr->y, width, + &menuMetrics, mePtr->x, mePtr->y, 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->x, mePtr->y + mePtr->height, mePtr->width, - Tk_Height(tkwin) - mePtr->y - mePtr->height - + Tk_Height(tkwin) - mePtr->y - mePtr->height - activeBorderWidth, 0, TK_RELIEF_FLAT); } @@ -712,7 +703,7 @@ DisplayMenu(clientData) } else { mePtr = menuPtr->entries[menuPtr->numEntries - 1]; Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), - border, mePtr->x, mePtr->y + mePtr->height, mePtr->width, + border, mePtr->x, mePtr->y + mePtr->height, mePtr->width, Tk_Height(tkwin) - mePtr->y - mePtr->height - activeBorderWidth, 0, TK_RELIEF_FLAT); @@ -721,13 +712,13 @@ DisplayMenu(clientData) width = Tk_Width(tkwin) - x - activeBorderWidth; height = Tk_Height(tkwin) - y - activeBorderWidth; } - Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y, + Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, x, y, width, height, 0, TK_RELIEF_FLAT); } Tk_GetReliefFromObj(NULL, menuPtr->reliefPtr, &relief); Tk_Draw3DRectangle(menuPtr->tkwin, Tk_WindowId(tkwin), - border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth, + border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth, relief); } @@ -736,31 +727,31 @@ DisplayMenu(clientData) * * TkMenuEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on menus. + * This function is invoked by the Tk dispatcher for various events on + * menus. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ void -TkMenuEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +TkMenuEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkMenu *menuPtr = (TkMenu *) clientData; - + if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) { - TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL); + TkEventuallyRedrawMenu(menuPtr, NULL); } else if (eventPtr->type == ConfigureNotify) { TkEventuallyRecomputeMenu(menuPtr); - TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL); + TkEventuallyRedrawMenu(menuPtr, NULL); } else if (eventPtr->type == ActivateNotify) { if (menuPtr->menuType == TEAROFF_MENU) { TkpSetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL); @@ -797,9 +788,9 @@ TkMenuEventProc(clientData, eventPtr) * * TkMenuImageProc -- * - * This procedure is invoked by the image code whenever the manager - * for an image does something that affects the size of contents - * of an image displayed in a menu entry. + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size of contents of an image + * displayed in a menu entry. * * Results: * None. @@ -811,19 +802,17 @@ TkMenuEventProc(clientData, eventPtr) */ void -TkMenuImageProc(clientData, x, y, width, height, imgWidth, - imgHeight) - ClientData clientData; /* Pointer to widget record. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +TkMenuImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (may be + * <=0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { register TkMenu *menuPtr = ((TkMenuEntry *)clientData)->menuPtr; - if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags - & RESIZE_PENDING)) { + if ((menuPtr->tkwin != NULL) && !(menuPtr->menuFlags & RESIZE_PENDING)) { menuPtr->menuFlags |= RESIZE_PENDING; Tcl_DoWhenIdle(ComputeMenuGeometry, (ClientData) menuPtr); } @@ -834,9 +823,9 @@ TkMenuImageProc(clientData, x, y, width, height, imgWidth, * * TkPostTearoffMenu -- * - * Posts a menu on the screen. Used to post tearoff menus. On Unix, - * all menus are posted this way. Adjusts the menu's position - * so that it fits on the screen, and maps and raises the menu. + * Posts a menu on the screen. Used to post tearoff menus. On Unix, all + * menus are posted this way. Adjusts the menu's position so that it fits + * on the screen, and maps and raises the menu. * * Results: * Returns a standard Tcl Error. @@ -848,13 +837,11 @@ TkMenuImageProc(clientData, x, y, width, height, imgWidth, */ int -TkPostTearoffMenu(interp, menuPtr, x, y) - Tcl_Interp *interp; /* The interpreter of the menu */ - TkMenu *menuPtr; /* The menu we are posting */ - int x; /* The root X coordinate where we - * are posting */ - int y; /* The root Y coordinate where we - * are posting */ +TkPostTearoffMenu( + Tcl_Interp *interp, /* The interpreter of the menu */ + TkMenu *menuPtr, /* The menu we are posting */ + int x, int y) /* The root X,Y coordinates where we are + * posting */ { int vRootX, vRootY, vRootWidth, vRootHeight; int tmp, result; @@ -867,8 +854,8 @@ TkPostTearoffMenu(interp, menuPtr, x, y) } /* - * The post commands could have deleted the menu, which means - * we are dead and should go away. + * The post commands could have deleted the menu, which means we are dead + * and should go away. */ if (menuPtr->tkwin == NULL) { @@ -876,27 +863,24 @@ TkPostTearoffMenu(interp, menuPtr, x, y) } /* - * Adjust the position of the menu if necessary to keep it - * visible on the screen. There are two special tricks to - * make this work right: + * Adjust the position of the menu if necessary to keep it visible on the + * screen. There are two special tricks to make this work right: * - * 1. If a virtual root window manager is being used then - * the coordinates are in the virtual root window of - * menuPtr's parent; since the menu uses override-redirect - * mode it will be in the *real* root window for the screen, - * so we have to map the coordinates from the virtual root - * (if any) to the real root. Can't get the virtual root - * from the menu itself (it will never be seen by the wm) - * so use its parent instead (it would be better to have an - * an option that names a window to use for this...). - * 2. The menu may not have been mapped yet, so its current size - * might be the default 1x1. To compute how much space it - * needs, use its requested size, not its actual size. + * 1. If a virtual root window manager is being used then the coordinates + * are in the virtual root window of menuPtr's parent; since the menu + * uses override-redirect mode it will be in the *real* root window for + * the screen, so we have to map the coordinates from the virtual root + * (if any) to the real root. Can't get the virtual root from the menu + * itself (it will never be seen by the wm) so use its parent instead + * (it would be better to have an an option that names a window to use + * for this...). + * 2. The menu may not have been mapped yet, so its current size might be + * the default 1x1. To compute how much space it needs, use its + * requested size, not its actual size. * - * Note that this code assumes square screen regions and all - * positive coordinates. This does not work on a Mac with - * multiple monitors. But then again, Tk has other problems - * with this. + * Note that this code assumes square screen regions and all positive + * coordinates. This does not work on a Mac with multiple monitors. But + * then again, Tk has other problems with this. */ Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY, @@ -932,59 +916,58 @@ TkPostTearoffMenu(interp, menuPtr, x, y) * * TkPostSubmenu -- * - * This procedure arranges for a particular submenu (i.e. the - * menu corresponding to a given cascade entry) to be - * posted. + * This function arranges for a particular submenu (i.e. the menu + * corresponding to a given cascade entry) to be posted. * * Results: - * A standard Tcl return result. Errors may occur in the - * Tcl commands generated to post and unpost submenus. + * A standard Tcl return result. Errors may occur in the Tcl commands + * generated to post and unpost submenus. * * Side effects: - * If there is already a submenu posted, it is unposted. - * The new submenu is then posted. + * If there is already a submenu posted, it is unposted. The new submenu + * is then posted. * *-------------------------------------------------------------- */ int -TkPostSubmenu(interp, menuPtr, mePtr) - Tcl_Interp *interp; /* Used for invoking sub-commands and +TkPostSubmenu( + Tcl_Interp *interp, /* Used for invoking sub-commands and * reporting errors. */ - register TkMenu *menuPtr; /* Information about menu as a whole. */ - register TkMenuEntry *mePtr; /* Info about submenu that is to be - * posted. NULL means make sure that - * no submenu is posted. */ + register TkMenu *menuPtr, /* Information about menu as a whole. */ + register TkMenuEntry *mePtr)/* Info about submenu that is to be posted. + * NULL means make sure that no submenu is + * posted. */ { int result, x, y; + Tcl_Obj *subary[4]; if (mePtr == menuPtr->postedCascade) { return TCL_OK; } if (menuPtr->postedCascade != NULL) { - char *name = Tcl_GetStringFromObj(menuPtr->postedCascade->namePtr, - NULL); - /* - * Note: when unposting a submenu, we have to redraw the entire - * parent menu. This is because of a combination of the following - * things: + * Note: when unposting a submenu, we have to redraw the entire parent + * menu. This is because of a combination of the following things: * (a) the submenu partially overlaps the parent. - * (b) the submenu specifies "save under", which causes the X - * server to make a copy of the information under it when it - * is posted. When the submenu is unposted, the X server - * copies this data back and doesn't generate any Expose - * events for the parent. - * (c) the parent may have redisplayed itself after the submenu - * was posted, in which case the saved information is no - * longer correct. - * The simplest solution is just force a complete redisplay of - * the parent. + * (b) the submenu specifies "save under", which causes the X server + * to make a copy of the information under it when it is posted. + * When the submenu is unposted, the X server copies this data + * back and doesn't generate any Expose events for the parent. + * (c) the parent may have redisplayed itself after the submenu was + * posted, in which case the saved information is no longer + * correct. + * The simplest solution is just force a complete redisplay of the + * parent. */ - TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL); - result = Tcl_VarEval(interp, "{", name, "} unpost", (char *) NULL); + subary[0] = menuPtr->postedCascade->namePtr; + subary[1] = Tcl_NewStringObj("unpost", -1); + Tcl_IncrRefCount(subary[1]); + TkEventuallyRedrawMenu(menuPtr, NULL); + result = Tcl_EvalObjv(interp, 2, subary, 0); + Tcl_DecrRefCount(subary[1]); menuPtr->postedCascade = NULL; if (result != TCL_OK) { return result; @@ -994,21 +977,31 @@ TkPostSubmenu(interp, menuPtr, mePtr) if ((mePtr != NULL) && (mePtr->namePtr != NULL) && Tk_IsMapped(menuPtr->tkwin)) { /* - * Position the cascade with its upper left corner slightly - * below and to the left of the upper right corner of the - * menu entry (this is an attempt to match Motif behavior). + * Position the cascade with its upper left corner slightly below and + * to the left of the upper right corner of the menu entry (this is an + * attempt to match Motif behavior). * * The menu has to redrawn so that the entry can change relief. + * + * Set postedCascade early to ensure tear-off submenus work on + * Windows. [Bug 873613] */ - char string[TCL_INTEGER_SPACE * 2]; - char *name; - - name = Tcl_GetStringFromObj(mePtr->namePtr, NULL); Tk_GetRootCoords(menuPtr->tkwin, &x, &y); - AdjustMenuCoords(menuPtr, mePtr, &x, &y, string); + AdjustMenuCoords(menuPtr, mePtr, &x, &y); + menuPtr->postedCascade = mePtr; - result = Tcl_VarEval(interp, "{", name, "} post ", string, (char *) NULL); + subary[0] = mePtr->namePtr; + subary[1] = Tcl_NewStringObj("post", -1); + subary[2] = Tcl_NewIntObj(x); + subary[3] = Tcl_NewIntObj(y); + Tcl_IncrRefCount(subary[1]); + Tcl_IncrRefCount(subary[2]); + Tcl_IncrRefCount(subary[3]); + result = Tcl_EvalObjv(interp, 4, subary, 0); + Tcl_DecrRefCount(subary[1]); + Tcl_DecrRefCount(subary[2]); + Tcl_DecrRefCount(subary[3]); if (result != TCL_OK) { menuPtr->postedCascade = NULL; return result; @@ -1023,8 +1016,7 @@ TkPostSubmenu(interp, menuPtr, mePtr) * * AdjustMenuCoords -- * - * Adjusts the given coordinates down and the left to give a Motif - * look. + * Adjusts the given coordinates down and the left to give a Motif look. * * Results: * None. @@ -1036,12 +1028,11 @@ TkPostSubmenu(interp, menuPtr, mePtr) */ static void -AdjustMenuCoords(menuPtr, mePtr, xPtr, yPtr, string) - TkMenu *menuPtr; - TkMenuEntry *mePtr; - int *xPtr; - int *yPtr; - char *string; +AdjustMenuCoords( + TkMenu *menuPtr, + TkMenuEntry *mePtr, + int *xPtr, + int *yPtr) { if (menuPtr->menuType == MENUBAR) { *xPtr += mePtr->x; @@ -1051,11 +1042,18 @@ AdjustMenuCoords(menuPtr, mePtr, xPtr, yPtr, string) Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, &borderWidth); - Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, &activeBorderWidth); - *xPtr += Tk_Width(menuPtr->tkwin) - borderWidth - activeBorderWidth + *xPtr += Tk_Width(menuPtr->tkwin) - borderWidth - activeBorderWidth - 2; *yPtr += mePtr->y + activeBorderWidth + 2; } - sprintf(string, "%d %d", *xPtr, *yPtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c index 8292b32..b19c7aa 100644 --- a/generic/tkMenubutton.c +++ b/generic/tkMenubutton.c @@ -1,115 +1,114 @@ -/* +/* * tkMenubutton.c -- * - * This module implements button-like widgets that are used - * to invoke pull-down menus. + * This module implements button-like widgets that are used to invoke + * pull-down menus. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkMenubutton.h" -#include "tkPort.h" #include "default.h" /* - * The following table defines the legal values for the -direction - * option. It is used together with the "enum direction" declaration - * in tkMenubutton.h. + * The following table defines the legal values for the -direction option. It + * is used together with the "enum direction" declaration in tkMenubutton.h. */ static char *directionStrings[] = { - "above", "below", "flush", "left", "right", (char *) NULL + "above", "below", "flush", "left", "right", NULL }; /* - * The following table defines the legal values for the -state option. - * It is used together with the "enum state" declaration in tkMenubutton.h. + * The following table defines the legal values for the -state option. It is + * used together with the "enum state" declaration in tkMenubutton.h. */ static char *stateStrings[] = { - "active", "disabled", "normal", (char *) NULL + "active", "disabled", "normal", NULL }; /* - * The following table defines the legal values for the -compound option. - * It is used with the "enum compound" declaration in tkMenuButton.h + * The following table defines the legal values for the -compound option. It + * is used with the "enum compound" declaration in tkMenuButton.h */ static char *compoundStrings[] = { - "bottom", "center", "left", "none", "right", "top", (char *) NULL + "bottom", "center", "left", "none", "right", "top", NULL }; /* * Information used for parsing configuration specs: */ -static Tk_OptionSpec optionSpecs[] = { +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", - DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1, - Tk_Offset(TkMenuButton, activeBorder), 0, - (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0}, + DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1, + Tk_Offset(TkMenuButton, activeBorder), 0, + (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0}, {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background", - DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1, - Tk_Offset(TkMenuButton, activeFg), - 0, (ClientData) DEF_MENUBUTTON_ACTIVE_FG_MONO, 0}, + DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1, + Tk_Offset(TkMenuButton, activeFg), + 0, (ClientData) DEF_MENUBUTTON_ACTIVE_FG_MONO, 0}, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", - DEF_MENUBUTTON_ANCHOR, -1, - Tk_Offset(TkMenuButton, anchor), 0, 0, 0}, + DEF_MENUBUTTON_ANCHOR, -1, + Tk_Offset(TkMenuButton, anchor), 0, 0, 0}, {TK_OPTION_BORDER, "-background", "background", "Background", DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder), - 0, (ClientData) DEF_MENUBUTTON_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + 0, (ClientData) DEF_MENUBUTTON_BG_MONO, 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, + (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, + (ClientData) "-background", 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_MENUBUTTON_BORDER_WIDTH, -1, - Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0}, + DEF_MENUBUTTON_BORDER_WIDTH, -1, + Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction", - DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction), + DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction), 0, (ClientData) directionStrings, 0}, {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground", "DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR, -1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK, (ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, NULL, 0, -1, 0, + (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0}, {TK_OPTION_STRING, "-height", "height", "Height", - DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString), - 0, 0, 0}, + DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString), + 0, 0, 0}, {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR, -1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_MENUBUTTON_HIGHLIGHT, -1, - Tk_Offset(TkMenuButton, highlightColorPtr), 0, 0, 0}, + DEF_MENUBUTTON_HIGHLIGHT, -1, + Tk_Offset(TkMenuButton, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH, -1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-image", "image", "Image", - DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString), + DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn", DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn), - 0, 0, 0}, + 0, 0, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", - DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0}, + DEF_MENUBUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0}, {TK_OPTION_STRING, "-menu", "menu", "Menu", - DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName), + DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-padx", "padX", "Pad", DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX), @@ -118,43 +117,42 @@ static Tk_OptionSpec optionSpecs[] = { DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY), 0, 0, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", - DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief), - 0, 0, 0}, + DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief), + 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", - DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkMenuButton, compound), 0, - (ClientData) compoundStrings, 0}, + DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkMenuButton, compound), 0, + (ClientData) compoundStrings, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state), 0, (ClientData) stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_MENUBUTTON_TAKE_FOCUS, -1, - Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0}, + DEF_MENUBUTTON_TAKE_FOCUS, -1, + Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-text", "text", "Text", DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", - DEF_MENUBUTTON_TEXT_VARIABLE, -1, - Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0}, + DEF_MENUBUTTON_TEXT_VARIABLE, -1, + Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_INT, "-underline", "underline", "Underline", DEF_MENUBUTTON_UNDERLINE, -1, Tk_Offset(TkMenuButton, underline), - 0, 0, 0}, + 0, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", - DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString), - 0, 0, 0}, + DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString), + 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength), - 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + 0, 0, 0}, + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * The following tables define the menubutton widget commands and map the - * indexes into the string tables into a single enumerated type used - * to dispatch the scale widget command. + * The following tables define the menubutton widget commands and map the + * indexes into the string tables into a single enumerated type used to + * dispatch the scale widget command. */ static CONST char *commandNames[] = { - "cget", "configure", (char *) NULL + "cget", "configure", NULL }; enum command { @@ -162,35 +160,34 @@ enum command { }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void MenuButtonCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void MenuButtonEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void MenuButtonImageProc _ANSI_ARGS_((ClientData clientData, +static void MenuButtonCmdDeletedProc(ClientData clientData); +static void MenuButtonEventProc(ClientData clientData, + XEvent *eventPtr); +static void MenuButtonImageProc(ClientData clientData, int x, int y, int width, int height, int imgWidth, - int imgHeight)); -static char * MenuButtonTextVarProc _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - CONST char *name1, CONST char *name2, int flags)); -static int MenuButtonWidgetObjCmd _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp, - int objc, Tcl_Obj *CONST objv[])); -static int ConfigureMenuButton _ANSI_ARGS_((Tcl_Interp *interp, - TkMenuButton *mbPtr, int objc, - Tcl_Obj *CONST objv[])); -static void DestroyMenuButton _ANSI_ARGS_((char *memPtr)); + int imgHeight); +static char * MenuButtonTextVarProc(ClientData clientData, + Tcl_Interp *interp, CONST char *name1, + CONST char *name2, int flags); +static int MenuButtonWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int ConfigureMenuButton(Tcl_Interp *interp, + TkMenuButton *mbPtr, int objc, + Tcl_Obj *CONST objv[]); +static void DestroyMenuButton(char *memPtr); /* *-------------------------------------------------------------- * * Tk_MenubuttonObjCmd -- * - * This procedure is invoked to process the "button", "label", - * "radiobutton", and "checkbutton" Tcl commands. See the - * user documentation for details on what it does. + * This function is invoked to process the "button", "label", + * "radiobutton", and "checkbutton" Tcl commands. See the user + * documentation for details on what it does. * * Results: * A standard Tcl result. @@ -202,11 +199,11 @@ static void DestroyMenuButton _ANSI_ARGS_((char *memPtr)); */ int -Tk_MenubuttonObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_MenubuttonObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register TkMenuButton *mbPtr; Tk_OptionTable optionTable; @@ -222,14 +219,14 @@ Tk_MenubuttonObjCmd(clientData, interp, objc, objv) */ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, the cached pointer will be returned. + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); @@ -246,9 +243,9 @@ Tk_MenubuttonObjCmd(clientData, interp, objc, objv) mbPtr->tkwin = tkwin; mbPtr->display = Tk_Display (tkwin); mbPtr->interp = interp; - mbPtr->widgetCmd = Tcl_CreateObjCommand(interp, - Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd, - (ClientData) mbPtr, MenuButtonCmdDeletedProc); + mbPtr->widgetCmd = Tcl_CreateObjCommand(interp, + Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd, + (ClientData) mbPtr, MenuButtonCmdDeletedProc); mbPtr->optionTable = optionTable; mbPtr->menuName = NULL; mbPtr->text = NULL; @@ -318,9 +315,9 @@ Tk_MenubuttonObjCmd(clientData, interp, objc, objv) * * MenuButtonWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -332,66 +329,62 @@ Tk_MenubuttonObjCmd(clientData, interp, objc, objv) */ static int -MenuButtonWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about button widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +MenuButtonWidgetObjCmd( + ClientData clientData, /* Information about button widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register TkMenuButton *mbPtr = (TkMenuButton *) clientData; int result, index; Tcl_Obj *objPtr; if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } - result = Tcl_GetIndexFromObj(interp, objv[1], - commandNames, "option", 0, &index); + result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, "option", 0, + &index); if (result != TCL_OK) { - return result; + return result; } Tcl_Preserve((ClientData) mbPtr); switch (index) { - case COMMAND_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "cget option"); + case COMMAND_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "cget option"); goto error; - } + } - objPtr = Tk_GetOptionValue(interp, (char *) mbPtr, - mbPtr->optionTable, objv[2], mbPtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } - break; + objPtr = Tk_GetOptionValue(interp, (char *) mbPtr, + mbPtr->optionTable, objv[2], mbPtr->tkwin); + if (objPtr == NULL) { + goto error; + } else { + Tcl_SetObjResult(interp, objPtr); } + break; - case COMMAND_CONFIGURE: { - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr, - mbPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - mbPtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } + case COMMAND_CONFIGURE: + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr, + mbPtr->optionTable, (objc == 3) ? objv[2] : NULL, + mbPtr->tkwin); + if (objPtr == NULL) { + goto error; } else { - result = ConfigureMenuButton(interp, mbPtr, objc-2, - objv+2); + Tcl_SetObjResult(interp, objPtr); } - break; + } else { + result = ConfigureMenuButton(interp, mbPtr, objc-2, objv+2); } + break; } Tcl_Release((ClientData) mbPtr); return result; - error: + error: Tcl_Release((ClientData) mbPtr); return TCL_ERROR; } @@ -401,10 +394,10 @@ MenuButtonWidgetObjCmd(clientData, interp, objc, objv) * * DestroyMenuButton -- * - * This procedure is invoked to recycle all of the resources - * associated with a menubutton widget. It is invoked as a - * when-idle handler in order to make sure that there is no - * other use of the menubutton pending at the time of the deletion. + * This function is invoked to recycle all of the resources associated + * with a menubutton widget. It is invoked as a when-idle handler in + * order to make sure that there is no other use of the menubutton + * pending at the time of the deletion. * * Results: * None. @@ -416,20 +409,19 @@ MenuButtonWidgetObjCmd(clientData, interp, objc, objv) */ static void -DestroyMenuButton(memPtr) - char *memPtr; /* Info about button widget. */ +DestroyMenuButton( + char *memPtr) /* Info about button widget. */ { register TkMenuButton *mbPtr = (TkMenuButton *) memPtr; TkpDestroyMenuButton(mbPtr); if (mbPtr->flags & REDRAW_PENDING) { - Tcl_CancelIdleCall(TkpDisplayMenuButton, (ClientData) mbPtr); + Tcl_CancelIdleCall(TkpDisplayMenuButton, (ClientData) mbPtr); } /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd); @@ -457,7 +449,7 @@ DestroyMenuButton(memPtr) Tk_FreeBitmap(mbPtr->display, mbPtr->gray); } if (mbPtr->textLayout != NULL) { - Tk_FreeTextLayout(mbPtr->textLayout); + Tk_FreeTextLayout(mbPtr->textLayout); } Tk_FreeConfigOptions((char *) mbPtr, mbPtr->optionTable, mbPtr->tkwin); mbPtr->tkwin = NULL; @@ -469,31 +461,30 @@ DestroyMenuButton(memPtr) * * ConfigureMenuButton -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a menubutton widget. + * This function is called to process an argv/argc list, plus the Tk + * option database, in order to configure (or reconfigure) a menubutton + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as text string, colors, font, - * etc. get set for mbPtr; old resources get freed, if there - * were any. The menubutton is redisplayed. + * Configuration information, such as text string, colors, font, etc. get + * set for mbPtr; old resources get freed, if there were any. The + * menubutton is redisplayed. * *---------------------------------------------------------------------- */ static int -ConfigureMenuButton(interp, mbPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - register TkMenuButton *mbPtr; - /* Information about widget; may or may - * not already have values for some - * fields. */ - int objc; /* Number of valid entries in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ +ConfigureMenuButton( + Tcl_Interp *interp, /* Used for error reporting. */ + register TkMenuButton *mbPtr, + /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments. */ { Tk_SavedOptions savedOptions; Tcl_Obj *errorResult = NULL; @@ -501,21 +492,20 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) Tk_Image image; /* - * Eliminate any existing trace on variables monitored by the - * menubutton. + * Eliminate any existing trace on variables monitored by the menubutton. */ if (mbPtr->textVarName != NULL) { - Tcl_UntraceVar(interp, mbPtr->textVarName, + Tcl_UntraceVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, (ClientData) mbPtr); } /* - * The following loop is potentially executed twice. During the - * first pass configuration options get set to their new values. - * If there is an error in this pass, we execute a second pass - * to restore all the options to their previous values. + * The following loop is potentially executed twice. During the first pass + * configuration options get set to their new values. If there is an error + * in this pass, we execute a second pass to restore all the options to + * their previous values. */ for (error = 0; error <= 1; error++) { @@ -526,7 +516,7 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) if (Tk_SetOptions(interp, (char *) mbPtr, mbPtr->optionTable, objc, objv, - mbPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { + mbPtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -541,8 +531,8 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) /* * A few options need special processing, such as setting the - * background from a 3-D border, or filling in complicated - * defaults that couldn't be specified to Tk_SetOptions. + * background from a 3-D border, or filling in complicated defaults + * that couldn't be specified to Tk_SetOptions. */ if ((mbPtr->state == STATE_ACTIVE) @@ -564,17 +554,17 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) } /* - * Get the image for the widget, if there is one. Allocate the - * new image before freeing the old one, so that the reference - * count doesn't go to zero and cause image data to be discarded. + * Get the image for the widget, if there is one. Allocate the new + * image before freeing the old one, so that the reference count + * doesn't go to zero and cause image data to be discarded. */ if (mbPtr->imageString != NULL) { image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin, - mbPtr->imageString, MenuButtonImageProc, + mbPtr->imageString, MenuButtonImageProc, (ClientData) mbPtr); if (image == NULL) { - return TCL_ERROR; + return TCL_ERROR; } } else { image = NULL; @@ -590,32 +580,32 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) { if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString, - &mbPtr->width) != TCL_OK) { - widthError: - Tcl_AddErrorInfo(interp, "\n (processing -width option)"); + &mbPtr->width) != TCL_OK) { + widthError: + Tcl_AddErrorInfo(interp, "\n (processing -width option)"); continue; } if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString, &mbPtr->height) != TCL_OK) { - heightError: - Tcl_AddErrorInfo(interp, "\n (processing -height option)"); + heightError: + Tcl_AddErrorInfo(interp, "\n (processing -height option)"); continue; } } else { if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width) != TCL_OK) { - goto widthError; + goto widthError; } if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height) != TCL_OK) { - goto heightError; + goto heightError; } } break; } if (!error) { - Tk_FreeSavedOptions(&savedOptions); + Tk_FreeSavedOptions(&savedOptions); } if (mbPtr->textVarName != NULL) { @@ -646,10 +636,9 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) if (error) { Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); - return TCL_ERROR; - } else { - return TCL_OK; + return TCL_ERROR; } + return TCL_OK; } /* @@ -657,22 +646,22 @@ ConfigureMenuButton(interp, mbPtr, objc, objv) * * TkMenuButtonWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: - * None. + * None. * * Side effects: - * TkMenuButton will be relayed out and redisplayed. + * TkMenuButton will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ - + void -TkMenuButtonWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +TkMenuButtonWorldChanged( + ClientData instanceData) /* Information about widget. */ { XGCValues gcValues; GC gc; @@ -686,9 +675,9 @@ TkMenuButtonWorldChanged(instanceData) gcValues.background = Tk_3DBorderColor(mbPtr->normalBorder)->pixel; /* - * Note: GraphicsExpose events are disabled in GC's because they're - * used to copy stuff from an off-screen pixmap onto the screen (we know - * that there's no problem with obscured areas). + * Note: GraphicsExpose events are disabled in GC's because they're used + * to copy stuff from an off-screen pixmap onto the screen (we know that + * there's no problem with obscured areas). */ gcValues.graphics_exposures = False; @@ -729,8 +718,8 @@ TkMenuButtonWorldChanged(instanceData) } /* - * Allocate the disabled graphics context, for drawing text in - * its disabled state. + * Allocate the disabled graphics context, for drawing text in its + * disabled state. */ mask = GCForeground | GCBackground | GCFont; @@ -762,36 +751,36 @@ TkMenuButtonWorldChanged(instanceData) * * MenuButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This function is invoked by the Tk dispatcher for various events on + * buttons. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -MenuButtonEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +MenuButtonEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkMenuButton *mbPtr = (TkMenuButton *) clientData; if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) { goto redraw; } else if (eventPtr->type == ConfigureNotify) { /* - * Must redraw after size changes, since layout could have changed - * and borders will need to be redrawn. + * Must redraw after size changes, since layout could have changed and + * borders will need to be redrawn. */ goto redraw; } else if (eventPtr->type == DestroyNotify) { - DestroyMenuButton((char *) mbPtr); + DestroyMenuButton((char *) mbPtr); } else if (eventPtr->type == FocusIn) { if (eventPtr->xfocus.detail != NotifyInferior) { mbPtr->flags |= GOT_FOCUS; @@ -809,7 +798,7 @@ MenuButtonEventProc(clientData, eventPtr) } return; - redraw: + redraw: if ((mbPtr->tkwin != NULL) && !(mbPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr); mbPtr->flags |= REDRAW_PENDING; @@ -821,9 +810,9 @@ MenuButtonEventProc(clientData, eventPtr) * * MenuButtonCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -835,17 +824,17 @@ MenuButtonEventProc(clientData, eventPtr) */ static void -MenuButtonCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +MenuButtonCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkMenuButton *mbPtr = (TkMenuButton *) clientData; Tk_Window tkwin = mbPtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (tkwin != NULL) { @@ -858,8 +847,8 @@ MenuButtonCmdDeletedProc(clientData) * * MenuButtonTextVarProc -- * - * This procedure is invoked when someone changes the variable - * whose contents are to be displayed in a menu button. + * This function is invoked when someone changes the variable whose + * contents are to be displayed in a menu button. * * Results: * NULL is always returned. @@ -873,19 +862,20 @@ MenuButtonCmdDeletedProc(clientData) /* ARGSUSED */ static char * -MenuButtonTextVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about button. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Name of variable. */ - CONST char *name2; /* Second part of variable name. */ - int flags; /* Information about what happened. */ +MenuButtonTextVarProc( + ClientData clientData, /* Information about button. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + CONST char *name1, /* Name of variable. */ + CONST char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ { register TkMenuButton *mbPtr = (TkMenuButton *) clientData; CONST char *value; + unsigned len; /* - * If the variable is unset, then immediately recreate it unless - * the whole interpreter is going away. + * If the variable is unset, then immediately recreate it unless the whole + * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { @@ -896,7 +886,7 @@ MenuButtonTextVarProc(clientData, interp, name1, name2, flags) TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MenuButtonTextVarProc, clientData); } - return (char *) NULL; + return NULL; } value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY); @@ -906,8 +896,9 @@ MenuButtonTextVarProc(clientData, interp, name1, name2, flags) if (mbPtr->text != NULL) { ckfree(mbPtr->text); } - mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1)); - strcpy(mbPtr->text, value); + len = 1 + (unsigned) strlen(value); + mbPtr->text = (char *) ckalloc(len); + memcpy(mbPtr->text, value, len); TkpComputeMenuButtonGeometry(mbPtr); if ((mbPtr->tkwin != NULL) && Tk_IsMapped(mbPtr->tkwin) @@ -915,7 +906,7 @@ MenuButtonTextVarProc(clientData, interp, name1, name2, flags) Tcl_DoWhenIdle(TkpDisplayMenuButton, (ClientData) mbPtr); mbPtr->flags |= REDRAW_PENDING; } - return (char *) NULL; + return NULL; } /* @@ -923,9 +914,9 @@ MenuButtonTextVarProc(clientData, interp, name1, name2, flags) * * MenuButtonImageProc -- * - * This procedure is invoked by the image code whenever the manager - * for an image does something that affects the size of contents - * of an image displayed in a button. + * This function is invoked by the image code whenever the manager for an + * image does something that affects the size of contents of an image + * displayed in a button. * * Results: * None. @@ -937,13 +928,13 @@ MenuButtonTextVarProc(clientData, interp, name1, name2, flags) */ static void -MenuButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight) - ClientData clientData; /* Pointer to widget record. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +MenuButtonImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (may be <= + * 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { register TkMenuButton *mbPtr = (TkMenuButton *) clientData; @@ -955,3 +946,11 @@ MenuButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight) } } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkMenubutton.h b/generic/tkMenubutton.h index 7e36fe6..41af675 100644 --- a/generic/tkMenubutton.h +++ b/generic/tkMenubutton.h @@ -1,13 +1,13 @@ /* * tkMenubutton.h -- * - * Declarations of types and functions used to implement - * the menubutton widget. + * Declarations of types and functions used to implement the menubutton + * widget. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKMENUBUTTON @@ -31,7 +31,7 @@ */ enum direction { - DIRECTION_ABOVE, DIRECTION_BELOW, DIRECTION_FLUSH, + DIRECTION_ABOVE, DIRECTION_BELOW, DIRECTION_FLUSH, DIRECTION_LEFT, DIRECTION_RIGHT }; @@ -44,16 +44,16 @@ enum state { }; /* - * A data structure of the following type is kept for each - * widget managed by this file: + * A data structure of the following type is kept for each widget managed by + * this file: */ typedef struct { - Tk_Window tkwin; /* Window that embodies the widget. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display containing widget. Needed, among + Tk_Window tkwin; /* Window that embodies the widget. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up. */ + Display *display; /* Display containing widget. Needed, among * other things, so that resources can bee * freed up even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with menubutton. */ @@ -67,17 +67,17 @@ typedef struct { * Information about what's displayed in the menu button: */ - char *text; /* Text to display in button (malloc'ed) - * or NULL. */ + char *text; /* Text to display in button (malloc'ed) or + * NULL. */ int underline; /* Index of character to underline. */ - char *textVarName; /* Name of variable (malloc'ed) or NULL. - * If non-NULL, button displays the contents - * of this variable. */ - Pixmap bitmap; /* Bitmap to display or None. If not None - * then text and textVar and underline - * are ignored. */ + char *textVarName; /* Name of variable (malloc'ed) or NULL. If + * non-NULL, button displays the contents of + * this variable. */ + Pixmap bitmap; /* Bitmap to display or None. If not None then + * text and textVar and underline are + * ignored. */ char *imageString; /* Name of image to display (malloc'ed), or - * NULL. If non-NULL, bitmap, text, and + * NULL. If non-NULL, bitmap, text, and * textVarName are ignored. */ Tk_Image image; /* Image to display in window, or NULL if * none. */ @@ -86,115 +86,113 @@ typedef struct { * Information used when displaying widget: */ - enum state state; /* State of button for display purposes: + enum state state; /* State of button for display purposes: * normal, active, or disabled. */ - Tk_3DBorder normalBorder; /* Structure used to draw 3-D - * border and background when window - * isn't active. NULL means no such - * border exists. */ - Tk_3DBorder activeBorder; /* Structure used to draw 3-D - * border and background when window - * is active. NULL means no such - * border exists. */ + Tk_3DBorder normalBorder; /* Structure used to draw 3-D border and + * background when window isn't active. NULL + * means no such border exists. */ + Tk_3DBorder activeBorder; /* Structure used to draw 3-D border and + * background when window is active. NULL + * means no such border exists. */ int borderWidth; /* Width of border. */ int relief; /* 3-d effect: TK_RELIEF_RAISED, etc. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ - XColor *highlightBgColorPtr; - /* Color for drawing traversal highlight - * area when highlight is off. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ + XColor *highlightBgColorPtr;/* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. - * Indicates how much interior stuff must - * be offset from outside edges to leave - * room for borders. */ + * Indicates how much interior stuff must be + * offset from outside edges to leave room for + * borders. */ Tk_Font tkfont; /* Information about text font, or NULL. */ XColor *normalFg; /* Foreground color in normal mode. */ - XColor *activeFg; /* Foreground color in active mode. NULL - * means use normalFg instead. */ - XColor *disabledFg; /* Foreground color when disabled. NULL - * means use normalFg with a 50% stipple - * instead. */ + XColor *activeFg; /* Foreground color in active mode. NULL means + * use normalFg instead. */ + XColor *disabledFg; /* Foreground color when disabled. NULL means + * use normalFg with a 50% stipple instead. */ GC normalTextGC; /* GC for drawing text in normal mode. */ GC activeTextGC; /* GC for drawing text in active mode (NULL * means use normalTextGC). */ Pixmap gray; /* Pixmap for displaying disabled text/icon if * disabledFg is NULL. */ - GC disabledGC; /* Used to produce disabled effect for text. */ - GC stippleGC; /* Used to produce disabled stipple effect - * for images when disabled. */ + GC disabledGC; /* Used to produce disabled effect for + * text. */ + GC stippleGC; /* Used to produce disabled stipple effect for + * images when disabled. */ int leftBearing; /* Distance from text origin to leftmost drawn * pixel (positive means to right). */ - int rightBearing; /* Amount text sticks right from its origin. */ - char *widthString; /* Value of -width option. Malloc'ed. */ - char *heightString; /* Value of -height option. Malloc'ed. */ + int rightBearing; /* Amount text sticks right from its + * origin. */ + char *widthString; /* Value of -width option. Malloc'ed. */ + char *heightString; /* Value of -height option. Malloc'ed. */ int width, height; /* If > 0, these specify dimensions to request * for window, in characters for text and in - * pixels for bitmaps. In this case the actual + * pixels for bitmaps. In this case the actual * size of the text string or bitmap is - * ignored in computing desired window size. */ + * ignored in computing desired window + * size. */ int wrapLength; /* Line length (in pixels) at which to wrap - * onto next line. <= 0 means don't wrap + * onto next line. <= 0 means don't wrap * except at newlines. */ int padX, padY; /* Extra space around text or bitmap (pixels * on each side). */ Tk_Anchor anchor; /* Where text/bitmap should be displayed * inside window region. */ - Tk_Justify justify; /* Justification to use for multi-line text. */ + Tk_Justify justify; /* Justification to use for multi-line + * text. */ int textWidth; /* Width needed to display text as requested, * in pixels. */ int textHeight; /* Height needed to display text as requested, * in pixels. */ Tk_TextLayout textLayout; /* Saved text layout information. */ - int indicatorOn; /* Non-zero means display indicator; 0 means + int indicatorOn; /* Non-zero means display indicator; 0 means * don't display. */ - int indicatorHeight; /* Height of indicator in pixels. This same + int indicatorHeight; /* Height of indicator in pixels. This same * amount of extra space is also left on each - * side of the indicator. 0 if no indicator. */ + * side of the indicator. 0 if no + * indicator. */ int indicatorWidth; /* Width of indicator in pixels, including - * indicatorHeight in padding on each side. - * 0 if no indicator. */ + * indicatorHeight in padding on each side. 0 + * if no indicator. */ /* * Miscellaneous information: */ - int compound; /* Value of -compound option; specifies whether - * the menubutton should show both an image and - * text, and, if so, how. */ - - enum direction direction; /* Direction for where to pop the menu. - * Valid directions are "above", "below", - * "left", "right", and "flush". "flush" - * means that the upper left corner of the - * menubutton is where the menu pops up. - * "above" and "below" will attempt to pop - * the menu compleletly above or below - * the menu respectively. - * "left" and "right" will pop the menu - * left or right, and the active item - * will be next to the button. */ + int compound; /* Value of -compound option; specifies + * whether the menubutton should show both an + * image and text, and, if so, how. */ + enum direction direction; /* Direction for where to pop the menu. Valid + * directions are "above", "below", "left", + * "right", and "flush". "flush" means that + * the upper left corner of the menubutton is + * where the menu pops up. "above" and "below" + * will attempt to pop the menu compleletly + * above or below the menu respectively. + * "left" and "right" will pop the menu left + * or right, and the active item will be next + * to the button. */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ - int flags; /* Various flags; see below for + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + int flags; /* Various flags; see below for * definitions. */ } TkMenuButton; /* * Flag bits for buttons: * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler - * has already been queued to redraw - * this window. - * POSTED: Non-zero means that the menu associated - * with this button has been posted (typically - * because of an active button press). - * GOT_FOCUS: Non-zero means this button currently - * has the input focus. + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has + * already been queued to redraw this window. + * POSTED: Non-zero means that the menu associated with + * this button has been posted (typically because + * of an active button press). + * GOT_FOCUS: Non-zero means this button currently has the + * input focus. */ #define REDRAW_PENDING 1 @@ -203,7 +201,7 @@ typedef struct { /* * The following constants define the dimensions of the cascade indicator, - * which is displayed if the "-indicatoron" option is true. The units for + * which is displayed if the "-indicatoron" option is true. The units for * these options are 1/10 millimeters. */ @@ -214,22 +212,17 @@ typedef struct { * Declaration of variables shared between the files in the button module. */ -extern Tk_ClassProcs tkpMenubuttonClass; +MODULE_SCOPE Tk_ClassProcs tkpMenubuttonClass; /* - * Declaration of procedures used in the implementation of the button - * widget. + * Declaration of procedures used in the implementation of the button widget. */ -EXTERN void TkpComputeMenuButtonGeometry _ANSI_ARGS_(( - TkMenuButton *mbPtr)); -EXTERN TkMenuButton * TkpCreateMenuButton _ANSI_ARGS_((Tk_Window tkwin)); -EXTERN void TkpDisplayMenuButton _ANSI_ARGS_(( - ClientData clientData)); -EXTERN void TkpDestroyMenuButton _ANSI_ARGS_(( - TkMenuButton *mbPtr)); -EXTERN void TkMenuButtonWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); +MODULE_SCOPE void TkpComputeMenuButtonGeometry(TkMenuButton *mbPtr); +MODULE_SCOPE TkMenuButton *TkpCreateMenuButton(Tk_Window tkwin); +MODULE_SCOPE void TkpDisplayMenuButton(ClientData clientData); +MODULE_SCOPE void TkpDestroyMenuButton(TkMenuButton *mbPtr); +MODULE_SCOPE void TkMenuButtonWorldChanged(ClientData instanceData); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tkMessage.c b/generic/tkMessage.c index 8fb5c36..0fd57a9 100644 --- a/generic/tkMessage.c +++ b/generic/tkMessage.c @@ -1,35 +1,34 @@ -/* +/* * tkMessage.c -- * - * This module implements a message widgets for the Tk - * toolkit. A message widget displays a multi-line string - * in a window according to a particular aspect ratio. + * This module implements a message widgets for the Tk toolkit. A message + * widget displays a multi-line string in a window according to a + * particular aspect ratio. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 by Ajuba Solutions. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "default.h" #include "tkInt.h" /* - * A data structure of the following type is kept for each message - * widget managed by this file: + * A data structure of the following type is kept for each message widget + * managed by this file: */ typedef struct { - Tk_Window tkwin; /* Window that embodies the message. NULL + Tk_Window tkwin; /* Window that embodies the message. NULL * means that the window has been destroyed * but the data structures haven't yet been * cleaned up.*/ Tk_OptionTable optionTable; /* Table that defines options available for * this widget. */ - Display *display; /* Display containing widget. Used, among + Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with message. */ @@ -46,8 +45,8 @@ typedef struct { * If non-NULL, message displays the contents * of this variable. */ Tk_3DBorder border; /* Structure used to draw 3-D border and - * background. NULL means a border hasn't - * been created yet. */ + * background. NULL means a border hasn't been + * created yet. */ int borderWidth; /* Width of border. */ int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ int highlightWidth; /* Width in pixels of highlight to draw @@ -61,7 +60,7 @@ typedef struct { XColor *fgColorPtr; /* Foreground color in normal mode. */ Tcl_Obj *padXPtr, *padYPtr; /* Tcl_Obj rep's of padX, padY values. */ int padX, padY; /* User-requested extra space around text. */ - int width; /* User-requested width, in pixels. 0 means + int width; /* User-requested width, in pixels. 0 means * compute width using aspect ratio below. */ int aspect; /* Desired aspect ratio for window * (100*width/height). */ @@ -82,10 +81,10 @@ typedef struct { */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ - int flags; /* Various flags; see below for + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + int flags; /* Various flags; see below for * definitions. */ } Message; @@ -108,7 +107,7 @@ typedef struct { * Information used for argv parsing. */ -static Tk_OptionSpec optionSpecs[] = { +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MESSAGE_ANCHOR, -1, Tk_Offset(Message, anchor), 0, 0, 0}, {TK_OPTION_INT, "-aspect", "aspect", "Aspect", DEF_MESSAGE_ASPECT, @@ -116,9 +115,9 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_MESSAGE_BG_COLOR, -1, Tk_Offset(Message, border), 0, (ClientData) DEF_MESSAGE_BG_MONO, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, (char *) NULL, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, (char *) NULL, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_MESSAGE_BORDER_WIDTH, -1, @@ -126,7 +125,7 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_MESSAGE_CURSOR, -1, Tk_Offset(Message, cursor), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL, (char *) NULL, + {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_MESSAGE_FONT, -1, Tk_Offset(Message, tkfont), 0, 0, 0}, @@ -161,35 +160,31 @@ static Tk_OptionSpec optionSpecs[] = { TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-width", "width", "Width", DEF_MESSAGE_WIDTH, -1, Tk_Offset(Message, width), 0, 0 ,0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0} }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void MessageCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void MessageEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static char * MessageTextVarProc _ANSI_ARGS_((ClientData clientData, +static void MessageCmdDeletedProc(ClientData clientData); +static void MessageEventProc(ClientData clientData, + XEvent *eventPtr); +static char * MessageTextVarProc(ClientData clientData, Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static int MessageWidgetObjCmd _ANSI_ARGS_((ClientData clientData, + CONST char *name2, int flags); +static int MessageWidgetObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static void MessageWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static void ComputeMessageGeometry _ANSI_ARGS_((Message *msgPtr)); -static int ConfigureMessage _ANSI_ARGS_((Tcl_Interp *interp, - Message *msgPtr, int objc, Tcl_Obj *CONST objv[], - int flags)); -static void DestroyMessage _ANSI_ARGS_((char *memPtr)); -static void DisplayMessage _ANSI_ARGS_((ClientData clientData)); + Tcl_Obj *CONST objv[]); +static void MessageWorldChanged(ClientData instanceData); +static void ComputeMessageGeometry(Message *msgPtr); +static int ConfigureMessage(Tcl_Interp *interp, Message *msgPtr, + int objc, Tcl_Obj *CONST objv[], int flags); +static void DestroyMessage(char *memPtr); +static void DisplayMessage(ClientData clientData); /* - * The structure below defines message class behavior by means of procedures + * The structure below defines message class behavior by means of functions * that can be invoked from generic window code. */ @@ -197,16 +192,14 @@ static Tk_ClassProcs messageClass = { sizeof(Tk_ClassProcs), /* size */ MessageWorldChanged, /* worldChangedProc */ }; - /* *-------------------------------------------------------------- * * Tk_MessageObjCmd -- * - * This procedure is invoked to process the "message" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "message" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -218,11 +211,11 @@ static Tk_ClassProcs messageClass = { */ int -Tk_MessageObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +Tk_MessageObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { register Message *msgPtr; Tk_OptionTable optionTable; @@ -234,14 +227,14 @@ Tk_MessageObjCmd(clientData, interp, objc, objv) } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, the cached pointer will be returned. + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); @@ -252,19 +245,20 @@ Tk_MessageObjCmd(clientData, interp, objc, objv) /* * Set values for those fields that don't take a 0 or NULL value. */ - msgPtr->tkwin = tkwin; - msgPtr->display = Tk_Display(tkwin); - msgPtr->interp = interp; - msgPtr->widgetCmd = Tcl_CreateObjCommand(interp, + + msgPtr->tkwin = tkwin; + msgPtr->display = Tk_Display(tkwin); + msgPtr->interp = interp; + msgPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(msgPtr->tkwin), MessageWidgetObjCmd, (ClientData) msgPtr, MessageCmdDeletedProc); - msgPtr->optionTable = optionTable; - msgPtr->relief = TK_RELIEF_FLAT; - msgPtr->textGC = None; - msgPtr->anchor = TK_ANCHOR_CENTER; - msgPtr->aspect = 150; - msgPtr->justify = TK_JUSTIFY_LEFT; - msgPtr->cursor = None; + msgPtr->optionTable = optionTable; + msgPtr->relief = TK_RELIEF_FLAT; + msgPtr->textGC = None; + msgPtr->anchor = TK_ANCHOR_CENTER; + msgPtr->aspect = 150; + msgPtr->justify = TK_JUSTIFY_LEFT; + msgPtr->cursor = None; Tk_SetClass(msgPtr->tkwin, "Message"); Tk_SetClassProcs(msgPtr->tkwin, &messageClass, (ClientData) msgPtr); @@ -290,9 +284,9 @@ Tk_MessageObjCmd(clientData, interp, objc, objv) * * MessageWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -304,19 +298,19 @@ Tk_MessageObjCmd(clientData, interp, objc, objv) */ static int -MessageWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about message widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +MessageWidgetObjCmd( + ClientData clientData, /* Information about message widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { register Message *msgPtr = (Message *) clientData; - static CONST char *optionStrings[] = { "cget", "configure", (char *) NULL }; + static CONST char *optionStrings[] = { "cget", "configure", NULL }; enum options { MESSAGE_CGET, MESSAGE_CONFIGURE }; int index; int result = TCL_OK; Tcl_Obj *objPtr; - + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; @@ -328,43 +322,40 @@ MessageWidgetObjCmd(clientData, interp, objc, objv) } Tcl_Preserve((ClientData) msgPtr); - + switch ((enum options) index) { - case MESSAGE_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); + case MESSAGE_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + result = TCL_ERROR; + } else { + objPtr = Tk_GetOptionValue(interp, (char *) msgPtr, + msgPtr->optionTable, objv[2], msgPtr->tkwin); + if (objPtr == NULL) { result = TCL_ERROR; } else { - objPtr = Tk_GetOptionValue(interp, (char *) msgPtr, - msgPtr->optionTable, objv[2], msgPtr->tkwin); - if (objPtr == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, objPtr); - result = TCL_OK; - } + Tcl_SetObjResult(interp, objPtr); + result = TCL_OK; } - break; } - case MESSAGE_CONFIGURE: { - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) msgPtr, - msgPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - msgPtr->tkwin); - if (objPtr == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, objPtr); - result = TCL_OK; - } + break; + case MESSAGE_CONFIGURE: + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) msgPtr, + msgPtr->optionTable, (objc == 3) ? objv[2] : NULL, + msgPtr->tkwin); + if (objPtr == NULL) { + result = TCL_ERROR; } else { - result = ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0); + Tcl_SetObjResult(interp, objPtr); + result = TCL_OK; } - break; + } else { + result = ConfigureMessage(interp, msgPtr, objc-2, objv+2, 0); } + break; } - + Tcl_Release((ClientData) msgPtr); return result; } @@ -374,9 +365,9 @@ MessageWidgetObjCmd(clientData, interp, objc, objv) * * DestroyMessage -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a message at a safe time - * (when no-one is using it anymore). + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of a message at a safe time (when no-one is + * using it anymore). * * Results: * None. @@ -388,8 +379,8 @@ MessageWidgetObjCmd(clientData, interp, objc, objv) */ static void -DestroyMessage(memPtr) - char *memPtr; /* Info about message widget. */ +DestroyMessage( + char *memPtr) /* Info about message widget. */ { register Message *msgPtr = (Message *) memPtr; @@ -399,11 +390,10 @@ DestroyMessage(memPtr) if (msgPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayMessage, (ClientData) msgPtr); } - + /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeConfigOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeConfigOptions handle all the standard option-related stuff. */ if (msgPtr->textGC != None) { @@ -427,30 +417,29 @@ DestroyMessage(memPtr) * * ConfigureMessage -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a message widget. + * This function is called to process an argv/argc list, plus the Tk + * option database, in order to configure (or reconfigure) a message + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as text string, colors, font, - * etc. get set for msgPtr; old resources get freed, if there - * were any. + * Configuration information, such as text string, colors, font, etc. get + * set for msgPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureMessage(interp, msgPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - register Message *msgPtr; /* Information about widget; may or may - * not already have values for some fields. */ - int objc; /* Number of valid entries in argv. */ - Tcl_Obj *CONST objv[]; /* Arguments. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureMessage( + Tcl_Interp *interp, /* Used for error reporting. */ + register Message *msgPtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in argv. */ + Tcl_Obj *CONST objv[], /* Arguments. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { Tk_SavedOptions savedOptions; @@ -459,22 +448,21 @@ ConfigureMessage(interp, msgPtr, objc, objv, flags) */ if (msgPtr->textVarName != NULL) { - Tcl_UntraceVar(interp, msgPtr->textVarName, + Tcl_UntraceVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, (ClientData) msgPtr); } if (Tk_SetOptions(interp, (char *) msgPtr, msgPtr->optionTable, objc, objv, - msgPtr->tkwin, &savedOptions, (int *)NULL) != TCL_OK) { + msgPtr->tkwin, &savedOptions, NULL) != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } - - + /* - * If the message is to display the value of a variable, then set up - * a trace on the variable's value, create the variable if it doesn't - * exist, and fetch its current value. + * If the message is to display the value of a variable, then set up a + * trace on the variable's value, create the variable if it doesn't exist, + * and fetch its current value. */ if (msgPtr->textVarName != NULL) { @@ -496,9 +484,9 @@ ConfigureMessage(interp, msgPtr, objc, objv, flags) } /* - * A few other options need special processing, such as setting - * the background from a 3-D border or handling special defaults - * that couldn't be specified to Tk_ConfigureWidget. + * A few other options need special processing, such as setting the + * background from a 3-D border or handling special defaults that couldn't + * be specified to Tk_ConfigureWidget. */ msgPtr->numChars = Tcl_NumUtfChars(msgPtr->string, -1); @@ -517,22 +505,22 @@ ConfigureMessage(interp, msgPtr, objc, objv, flags) * * MessageWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: - * None. + * None. * * Side effects: - * Message will be relayed out and redisplayed. + * Message will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ - + static void -MessageWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +MessageWorldChanged( + ClientData instanceData) /* Information about widget. */ { XGCValues gcValues; GC gc = None; @@ -562,8 +550,8 @@ MessageWorldChanged(instanceData) } /* - * Recompute the desired geometry for the window, and arrange for - * the window to be redisplayed. + * Recompute the desired geometry for the window, and arrange for the + * window to be redisplayed. */ ComputeMessageGeometry(msgPtr); @@ -579,23 +567,22 @@ MessageWorldChanged(instanceData) * * ComputeMessageGeometry -- * - * Compute the desired geometry for a message window, - * taking into account the desired aspect ratio for the - * window. + * Compute the desired geometry for a message window, taking into account + * the desired aspect ratio for the window. * * Results: * None. * * Side effects: - * Tk_GeometryRequest is called to inform the geometry - * manager of the desired geometry for this window. + * Tk_GeometryRequest is called to inform the geometry manager of the + * desired geometry for this window. * *-------------------------------------------------------------- */ static void -ComputeMessageGeometry(msgPtr) - register Message *msgPtr; /* Information about window. */ +ComputeMessageGeometry( + register Message *msgPtr) /* Information about window. */ { int width, inc, height; int thisWidth, thisHeight, maxWidth; @@ -617,12 +604,11 @@ ComputeMessageGeometry(msgPtr) upperBound = msgPtr->aspect + aspect; /* - * Do the computation in multiple passes: start off with - * a very wide window, and compute its height. Then change - * the width and try again. Reduce the size of the change - * and iterate until dimensions are found that approximate - * the desired aspect ratio. Or, if the user gave an explicit - * width then just use that. + * Do the computation in multiple passes: start off with a very wide + * window, and compute its height. Then change the width and try again. + * Reduce the size of the change and iterate until dimensions are found + * that approximate the desired aspect ratio. Or, if the user gave an + * explicit width then just use that. */ if (msgPtr->width > 0) { @@ -665,7 +651,7 @@ ComputeMessageGeometry(msgPtr) * * DisplayMessage -- * - * This procedure redraws the contents of a message window. + * This function redraws the contents of a message window. * * Results: * None. @@ -677,8 +663,8 @@ ComputeMessageGeometry(msgPtr) */ static void -DisplayMessage(clientData) - ClientData clientData; /* Information about window. */ +DisplayMessage( + ClientData clientData) /* Information about window. */ { register Message *msgPtr = (Message *) clientData; register Tk_Window tkwin = msgPtr->tkwin; @@ -702,8 +688,8 @@ DisplayMessage(clientData) 0, TK_RELIEF_FLAT); /* - * Compute starting y-location for message based on message size - * and anchor option. + * Compute starting y-location for message based on message size and + * anchor option. */ TkComputeAnchor(msgPtr->anchor, tkwin, msgPtr->padX, msgPtr->padY, @@ -723,7 +709,7 @@ DisplayMessage(clientData) bgGC = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin)); if (msgPtr->flags & GOT_FOCUS) { - fgGC = Tk_GCForColor(msgPtr->highlightColorPtr, Tk_WindowId(tkwin)); + fgGC = Tk_GCForColor(msgPtr->highlightColorPtr,Tk_WindowId(tkwin)); TkpDrawHighlightBorder(tkwin, fgGC, bgGC, msgPtr->highlightWidth, Tk_WindowId(tkwin)); } else { @@ -738,23 +724,23 @@ DisplayMessage(clientData) * * MessageEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on messages. + * This function is invoked by the Tk dispatcher for various events on + * messages. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -MessageEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +MessageEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { Message *msgPtr = (Message *) clientData; @@ -780,7 +766,7 @@ MessageEventProc(clientData, eventPtr) } return; - redraw: + redraw: if ((msgPtr->tkwin != NULL) && !(msgPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr); msgPtr->flags |= REDRAW_PENDING; @@ -792,9 +778,9 @@ MessageEventProc(clientData, eventPtr) * * MessageCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -806,16 +792,16 @@ MessageEventProc(clientData, eventPtr) */ static void -MessageCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +MessageCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { Message *msgPtr = (Message *) clientData; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (!(msgPtr->flags & MESSAGE_DELETED)) { @@ -828,34 +814,33 @@ MessageCmdDeletedProc(clientData) * * MessageTextVarProc -- * - * This procedure is invoked when someone changes the variable - * whose contents are to be displayed in a message. + * This function is invoked when someone changes the variable whose + * contents are to be displayed in a message. * * Results: * NULL is always returned. * * Side effects: - * The text displayed in the message will change to match the - * variable. + * The text displayed in the message will change to match the variable. * *-------------------------------------------------------------- */ /* ARGSUSED */ static char * -MessageTextVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about message. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Name of variable. */ - CONST char *name2; /* Second part of variable name. */ - int flags; /* Information about what happened. */ +MessageTextVarProc( + ClientData clientData, /* Information about message. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + CONST char *name1, /* Name of variable. */ + CONST char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ { register Message *msgPtr = (Message *) clientData; CONST char *value; /* - * If the variable is unset, then immediately recreate it unless - * the whole interpreter is going away. + * If the variable is unset, then immediately recreate it unless the whole + * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { @@ -866,7 +851,7 @@ MessageTextVarProc(clientData, interp, name1, name2, flags) TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, MessageTextVarProc, clientData); } - return (char *) NULL; + return NULL; } value = Tcl_GetVar(interp, msgPtr->textVarName, TCL_GLOBAL_ONLY); @@ -886,5 +871,13 @@ MessageTextVarProc(clientData, interp, name1, name2, flags) Tcl_DoWhenIdle(DisplayMessage, (ClientData) msgPtr); msgPtr->flags |= REDRAW_PENDING; } - return (char *) NULL; + return NULL; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkObj.c b/generic/tkObj.c index 291c70d..7672240 100644 --- a/generic/tkObj.c +++ b/generic/tkObj.c @@ -1,13 +1,12 @@ -/* +/* * tkObj.c -- * - * This file contains procedures that implement the common Tk object - * types + * This file contains functions that implement the common Tk object types * * Copyright (c) 1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" @@ -15,7 +14,7 @@ /* * The following structure is the internal representation for pixel objects. */ - + typedef struct PixelRep { double value; int units; @@ -27,11 +26,11 @@ typedef struct PixelRep { ((objPtr)->internalRep.twoPtrValue.ptr2 == 0) #define SET_SIMPLEPIXEL(objPtr, intval) \ - (objPtr)->internalRep.twoPtrValue.ptr1 = (VOID *) (intval); \ + (objPtr)->internalRep.twoPtrValue.ptr1 = INT2PTR(intval); \ (objPtr)->internalRep.twoPtrValue.ptr2 = 0 #define GET_SIMPLEPIXEL(objPtr) \ - ((int) (objPtr)->internalRep.twoPtrValue.ptr1) + (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr1)) #define SET_COMPLEXPIXEL(objPtr, repPtr) \ (objPtr)->internalRep.twoPtrValue.ptr1 = 0; \ @@ -40,11 +39,24 @@ typedef struct PixelRep { #define GET_COMPLEXPIXEL(objPtr) \ ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2) +/* + * One of these structures is created per thread to store thread-specific + * data. In this case, it is used to contain references to selected + * Tcl_ObjTypes that we can use as screen distances without conversion. The + * "dataKey" below is used to locate the ThreadSpecificData for the current + * thread. + */ + +typedef struct ThreadSpecificData { + const Tcl_ObjType *doubleTypePtr; + const Tcl_ObjType *intTypePtr; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * The following structure is the internal representation for mm objects. */ - + typedef struct MMRep { double value; int units; @@ -54,41 +66,37 @@ typedef struct MMRep { /* * The following structure is the internal representation for window objects. - * A WindowRep caches name-to-window lookups. The cache is invalid - * if tkwin is NULL or if mainPtr->deletionEpoch does not match epoch. + * A WindowRep caches name-to-window lookups. The cache is invalid if tkwin is + * NULL or if mainPtr->deletionEpoch does not match epoch. */ + typedef struct WindowRep { - Tk_Window tkwin; /* Cached window; NULL if not found */ - TkMainInfo *mainPtr; /* MainWindow associated with tkwin */ + Tk_Window tkwin; /* Cached window; NULL if not found. */ + TkMainInfo *mainPtr; /* MainWindow associated with tkwin. */ long epoch; /* Value of mainPtr->deletionEpoch at last - * successful lookup. */ + * successful lookup. */ } WindowRep; /* - * Prototypes for procedures defined later in this file: + * Prototypes for functions defined later in this file: */ -static void DupMMInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void DupPixelInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void DupWindowInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr, - Tcl_Obj *copyPtr)); -static void FreeMMInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); -static void FreePixelInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); -static void FreeWindowInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr)); -static void UpdateStringOfMM _ANSI_ARGS_((Tcl_Obj *objPtr)); -static int SetMMFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); -static int SetPixelFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); -static int SetWindowFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); +static void DupMMInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); +static void DupPixelInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); +static void DupWindowInternalRep(Tcl_Obj *srcPtr,Tcl_Obj *copyPtr); +static void FreeMMInternalRep(Tcl_Obj *objPtr); +static void FreePixelInternalRep(Tcl_Obj *objPtr); +static void FreeWindowInternalRep(Tcl_Obj *objPtr); +static ThreadSpecificData *GetTypeCache(void); +static void UpdateStringOfMM(Tcl_Obj *objPtr); +static int SetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static int SetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static int SetWindowFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* - * The following structure defines the implementation of the "pixel" - * Tcl object, used for measuring distances. The pixel object remembers - * its initial display-independant settings. + * The following structure defines the implementation of the "pixel" Tcl + * object, used for measuring distances. The pixel object remembers its + * initial display-independant settings. */ static Tcl_ObjType pixelObjType = { @@ -100,9 +108,9 @@ static Tcl_ObjType pixelObjType = { }; /* - * The following structure defines the implementation of the "pixel" - * Tcl object, used for measuring distances. The pixel object remembers - * its initial display-independant settings. + * The following structure defines the implementation of the "pixel" Tcl + * object, used for measuring distances. The pixel object remembers its + * initial display-independant settings. */ static Tcl_ObjType mmObjType = { @@ -119,23 +127,46 @@ static Tcl_ObjType mmObjType = { */ static Tcl_ObjType windowObjType = { - "window", /* name */ - FreeWindowInternalRep, /* freeIntRepProc */ - DupWindowInternalRep, /* dupIntRepProc */ - NULL, /* updateStringProc */ - SetWindowFromAny /* setFromAnyProc */ + "window", /* name */ + FreeWindowInternalRep, /* freeIntRepProc */ + DupWindowInternalRep, /* dupIntRepProc */ + NULL, /* updateStringProc */ + SetWindowFromAny /* setFromAnyProc */ }; + +/* + *---------------------------------------------------------------------- + * + * GetTypeCache -- + * + * Get (and build if necessary) the cache of useful Tcl object types for + * comparisons in the conversion functions. This allows optimized checks + * for standard cases. + * + *---------------------------------------------------------------------- + */ +static ThreadSpecificData * +GetTypeCache() +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + if (tsdPtr->doubleTypePtr == NULL) { + tsdPtr->doubleTypePtr = Tcl_GetObjType("double"); + tsdPtr->intTypePtr = Tcl_GetObjType("int"); + } + return tsdPtr; +} /* *---------------------------------------------------------------------- * - * Tk_GetPixelsFromObj -- + * GetPixelsFromObjEx -- * * Attempt to return a pixel value from the Tcl object "objPtr". If the - * object is not already a pixel value, an attempt will be made to convert - * it to one. + * object is not already a pixel value, an attempt will be made to + * convert it to one. * * Results: * The return value is a standard Tcl object result. If an error occurs @@ -143,51 +174,94 @@ static Tcl_ObjType windowObjType = { * result unless "interp" is NULL. * * Side effects: - * If the object is not already a pixel, the conversion will free - * any old internal representation. + * If the object is not already a pixel, the conversion will free any old + * internal representation. * *---------------------------------------------------------------------- */ +static int -Tk_GetPixelsFromObj(interp, tkwin, objPtr, intPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tk_Window tkwin; - Tcl_Obj *objPtr; /* The object from which to get pixels. */ - int *intPtr; /* Place to store resulting pixels. */ +GetPixelsFromObjEx( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tk_Window tkwin, + Tcl_Obj *objPtr, /* The object from which to get pixels. */ + int *intPtr, + double *dblPtr) /* Places to store resulting pixels. */ { - int result; + int result,fresh; double d; PixelRep *pixelPtr; static double bias[] = { - 1.0, 10.0, 25.4, 25.4 / 72.0 + 1.0, 10.0, 25.4, 0.35278 /*25.4 / 72.0*/ }; + /* + * Special hacks where the type of the object is known to be something + * that is just numeric and cannot require distance conversion. This pokes + * holes in Tcl's abstractions, but they are just for optimization, not + * semantics. + */ + + if (objPtr->typePtr != &pixelObjType) { + ThreadSpecificData *tsdPtr = GetTypeCache(); + + if (objPtr->typePtr == tsdPtr->doubleTypePtr) { + (void) Tcl_GetDoubleFromObj(interp, objPtr, &d); + if (dblPtr != NULL) { + *dblPtr = d; + } + *intPtr = (int) (d<0 ? d-0.5 : d+0.5); + return TCL_OK; + } else if (objPtr->typePtr == tsdPtr->intTypePtr) { + (void) Tcl_GetIntFromObj(interp, objPtr, intPtr); + if (dblPtr) { + *dblPtr = (double) (*intPtr); + } + return TCL_OK; + } + } + + retry: if (objPtr->typePtr != &pixelObjType) { result = SetPixelFromAny(interp, objPtr); if (result != TCL_OK) { return result; } + fresh = 1; + } else { + fresh = 0; } if (SIMPLE_PIXELREP(objPtr)) { *intPtr = GET_SIMPLEPIXEL(objPtr); + if (dblPtr) { + *dblPtr = (double) (*intPtr); + } } else { pixelPtr = GET_COMPLEXPIXEL(objPtr); - if (pixelPtr->tkwin != tkwin) { + if ((!fresh) && (pixelPtr->tkwin != tkwin)) { + /* + * In case of exo-screen conversions of non-pixels we force a + * recomputation from the string. + */ + + FreePixelInternalRep(objPtr); + goto retry; + } + if ((pixelPtr->tkwin != tkwin)||dblPtr) { d = pixelPtr->value; if (pixelPtr->units >= 0) { d *= bias[pixelPtr->units] * WidthOfScreen(Tk_Screen(tkwin)); d /= WidthMMOfScreen(Tk_Screen(tkwin)); } - if (d < 0) { - pixelPtr->returnValue = (int) (d - 0.5); - } else { - pixelPtr->returnValue = (int) (d + 0.5); - } + pixelPtr->returnValue = (int) (d<0 ? d-0.5 : d+0.5); pixelPtr->tkwin = tkwin; + if (dblPtr) { + *dblPtr = d; + } } - *intPtr = pixelPtr->returnValue; + *intPtr = pixelPtr->returnValue; } return TCL_OK; } @@ -195,6 +269,88 @@ Tk_GetPixelsFromObj(interp, tkwin, objPtr, intPtr) /* *---------------------------------------------------------------------- * + * Tk_GetPixelsFromObj -- + * + * Attempt to return a pixel value from the Tcl object "objPtr". If the + * object is not already a pixel value, an attempt will be made to + * convert it to one. + * + * Results: + * The return value is a standard Tcl object result. If an error occurs + * during conversion, an error message is left in the interpreter's + * result unless "interp" is NULL. + * + * Side effects: + * If the object is not already a pixel, the conversion will free any old + * internal representation. + * + *---------------------------------------------------------------------- + */ + +int +Tk_GetPixelsFromObj( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tk_Window tkwin, + Tcl_Obj *objPtr, /* The object from which to get pixels. */ + int *intPtr) /* Place to store resulting pixels. */ +{ + return GetPixelsFromObjEx(interp,tkwin,objPtr,intPtr,NULL); +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetDoublePixelsFromObj -- + * + * Attempt to return a double pixel value from the Tcl object + * "objPtr". If the object is not already a pixel value, an attempt will + * be made to convert it to one, the internal unit being pixels. + * + * Results: + * The return value is a standard Tcl object result. If an error occurs + * during conversion, an error message is left in the interpreter's + * result unless "interp" is NULL. + * + * Side effects: + * If the object is not already a pixel, the conversion will free any old + * internal representation. + * + *---------------------------------------------------------------------- + */ + +int +Tk_GetDoublePixelsFromObj( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tk_Window tkwin, + Tcl_Obj *objPtr, /* The object from which to get pixels. */ + double *doublePtr) /* Place to store resulting pixels. */ +{ + double d; + int result,val; + + result = GetPixelsFromObjEx(interp, tkwin, objPtr, &val, &d); + if (result != TCL_OK) { + return result; + } + if (objPtr->typePtr == &pixelObjType && !SIMPLE_PIXELREP(objPtr)) { + PixelRep *pixelPtr = GET_COMPLEXPIXEL(objPtr); + + if (pixelPtr->units >= 0) { + /* + * Internally "shimmer" to pixel units. + */ + + pixelPtr->units = -1; + pixelPtr->value = d; + } + } + *doublePtr = d; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * FreePixelInternalRep -- * * Deallocate the storage associated with a pixel object's internal @@ -204,20 +360,19 @@ Tk_GetPixelsFromObj(interp, tkwin, objPtr, intPtr) * None. * * Side effects: - * Frees objPtr's internal representation and sets objPtr's - * internalRep to NULL. + * Frees objPtr's internal representation and sets objPtr's internalRep + * to NULL. * *---------------------------------------------------------------------- */ static void -FreePixelInternalRep(objPtr) - Tcl_Obj *objPtr; /* Pixel object with internal rep to free. */ +FreePixelInternalRep( + Tcl_Obj *objPtr) /* Pixel object with internal rep to free. */ { - PixelRep *pixelPtr; - if (!SIMPLE_PIXELREP(objPtr)) { - pixelPtr = GET_COMPLEXPIXEL(objPtr); + PixelRep *pixelPtr = GET_COMPLEXPIXEL(objPtr); + ckfree((char *) pixelPtr); } SET_SIMPLEPIXEL(objPtr, 0); @@ -229,31 +384,31 @@ FreePixelInternalRep(objPtr) * * DupPixelInternalRep -- * - * Initialize the internal representation of a pixel Tcl_Obj to a - * copy of the internal representation of an existing pixel object. + * Initialize the internal representation of a pixel Tcl_Obj to a copy of + * the internal representation of an existing pixel object. * * Results: * None. * * Side effects: - * copyPtr's internal rep is set to the pixel corresponding to - * srcPtr's internal rep. + * copyPtr's internal rep is set to the pixel corresponding to srcPtr's + * internal rep. * *---------------------------------------------------------------------- */ static void -DupPixelInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr; /* Object with internal rep to set. */ +DupPixelInternalRep( + register Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ + register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { - PixelRep *oldPtr, *newPtr; - copyPtr->typePtr = srcPtr->typePtr; if (SIMPLE_PIXELREP(srcPtr)) { SET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr)); } else { + PixelRep *oldPtr, *newPtr; + oldPtr = GET_COMPLEXPIXEL(srcPtr); newPtr = (PixelRep *) ckalloc(sizeof(PixelRep)); newPtr->value = oldPtr->value; @@ -269,8 +424,7 @@ DupPixelInternalRep(srcPtr, copyPtr) * * SetPixelFromAny -- * - * Attempt to generate a pixel internal form for the Tcl object - * "objPtr". + * Attempt to generate a pixel internal form for the Tcl object "objPtr". * * Results: * The return value is a standard Tcl result. If an error occurs during @@ -278,70 +432,54 @@ DupPixelInternalRep(srcPtr, copyPtr) * unless "interp" is NULL. * * Side effects: - * If no error occurs, a pixel representation of the object is - * stored internally and the type of "objPtr" is set to pixel. + * If no error occurs, a pixel representation of the object is stored + * internally and the type of "objPtr" is set to pixel. * *---------------------------------------------------------------------- */ static int -SetPixelFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tcl_Obj *objPtr; /* The object to convert. */ +SetPixelFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; char *string, *rest; double d; int i, units; - PixelRep *pixelPtr; string = Tcl_GetStringFromObj(objPtr, NULL); d = strtod(string, &rest); if (rest == string) { - /* - * Must copy string before resetting the result in case a caller - * is trying to convert the interpreter's result to pixels. - */ - - char buf[100]; - - error: - sprintf(buf, "bad screen distance \"%.50s\"", string); - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, buf, NULL); - return TCL_ERROR; + goto error; } while ((*rest != '\0') && isspace(UCHAR(*rest))) { rest++; } - switch (*rest) { - case '\0': - units = -1; - break; - case 'm': - units = 0; - break; - - case 'c': - units = 1; - break; - - case 'i': - units = 2; - break; - - case 'p': - units = 3; - break; - - default: - goto error; + switch (*rest) { + case '\0': + units = -1; + break; + case 'm': + units = 0; + break; + case 'c': + units = 1; + break; + case 'i': + units = 2; + break; + case 'p': + units = 3; + break; + default: + goto error; } /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ typePtr = objPtr->typePtr; @@ -355,7 +493,8 @@ SetPixelFromAny(interp, objPtr) if ((units < 0) && (i == d)) { SET_SIMPLEPIXEL(objPtr, i); } else { - pixelPtr = (PixelRep *) ckalloc(sizeof(PixelRep)); + PixelRep *pixelPtr = (PixelRep *) ckalloc(sizeof(PixelRep)); + pixelPtr->value = d; pixelPtr->units = units; pixelPtr->tkwin = NULL; @@ -363,6 +502,21 @@ SetPixelFromAny(interp, objPtr) SET_COMPLEXPIXEL(objPtr, pixelPtr); } return TCL_OK; + + error: + if (interp != NULL) { + /* + * Must copy string before resetting the result in case a caller is + * trying to convert the interpreter's result to pixels. + */ + + char buf[100]; + + sprintf(buf, "bad screen distance \"%.50s\"", string); + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, buf, NULL); + } + return TCL_ERROR; } /* @@ -380,24 +534,24 @@ SetPixelFromAny(interp, objPtr) * result unless "interp" is NULL. * * Side effects: - * If the object is not already a pixel, the conversion will free - * any old internal representation. + * If the object is not already a pixel, the conversion will free any old + * internal representation. * *---------------------------------------------------------------------- */ int -Tk_GetMMFromObj(interp, tkwin, objPtr, doublePtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tk_Window tkwin; - Tcl_Obj *objPtr; /* The object from which to get mms. */ - double *doublePtr; /* Place to store resulting millimeters. */ +Tk_GetMMFromObj( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tk_Window tkwin, + Tcl_Obj *objPtr, /* The object from which to get mms. */ + double *doublePtr) /* Place to store resulting millimeters. */ { int result; double d; MMRep *mmPtr; static double bias[] = { - 10.0, 25.4, 1.0, 25.4 / 72.0 + 10.0, 25.4, 1.0, 0.35278 /*25.4 / 72.0*/ }; if (objPtr->typePtr != &mmObjType) { @@ -436,15 +590,15 @@ Tk_GetMMFromObj(interp, tkwin, objPtr, doublePtr) * None. * * Side effects: - * Frees objPtr's internal representation and sets objPtr's - * internalRep to NULL. + * Frees objPtr's internal representation and sets objPtr's internalRep + * to NULL. * *---------------------------------------------------------------------- */ static void -FreeMMInternalRep(objPtr) - Tcl_Obj *objPtr; /* MM object with internal rep to free. */ +FreeMMInternalRep( + Tcl_Obj *objPtr) /* MM object with internal rep to free. */ { ckfree((char *) objPtr->internalRep.otherValuePtr); objPtr->internalRep.otherValuePtr = NULL; @@ -456,26 +610,26 @@ FreeMMInternalRep(objPtr) * * DupMMInternalRep -- * - * Initialize the internal representation of a pixel Tcl_Obj to a - * copy of the internal representation of an existing pixel object. + * Initialize the internal representation of a pixel Tcl_Obj to a copy of + * the internal representation of an existing pixel object. * * Results: * None. * * Side effects: - * copyPtr's internal rep is set to the pixel corresponding to - * srcPtr's internal rep. + * copyPtr's internal rep is set to the pixel corresponding to srcPtr's + * internal rep. * *---------------------------------------------------------------------- */ static void -DupMMInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */ - register Tcl_Obj *copyPtr; /* Object with internal rep to set. */ +DupMMInternalRep( + register Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ + register Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { MMRep *oldPtr, *newPtr; - + copyPtr->typePtr = srcPtr->typePtr; oldPtr = (MMRep *) srcPtr->internalRep.otherValuePtr; newPtr = (MMRep *) ckalloc(sizeof(MMRep)); @@ -491,24 +645,23 @@ DupMMInternalRep(srcPtr, copyPtr) * * UpdateStringOfMM -- * - * Update the string representation for a pixel Tcl_Obj - * this function is only called, if the pixel Tcl_Obj has no unit, - * because with units the string representation is created by - * SetMMFromAny + * Update the string representation for a pixel Tcl_Obj this function is + * only called, if the pixel Tcl_Obj has no unit, because with units the + * string representation is created by SetMMFromAny * * Results: - * None. + * None. * * Side effects: - * The object's string is set to a valid string that results from - * the double-to-string conversion. + * The object's string is set to a valid string that results from the + * double-to-string conversion. * *---------------------------------------------------------------------- */ static void -UpdateStringOfMM(objPtr) - register Tcl_Obj *objPtr; /* pixel obj with string rep to update. */ +UpdateStringOfMM( + register Tcl_Obj *objPtr) /* pixel obj with string rep to update. */ { MMRep *mmPtr; char buffer[TCL_DOUBLE_SPACE]; @@ -517,11 +670,11 @@ UpdateStringOfMM(objPtr) mmPtr = (MMRep *) objPtr->internalRep.otherValuePtr; /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */ if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) { - panic("UpdateStringOfMM: false precondition"); + Tcl_Panic("UpdateStringOfMM: false precondition"); } - Tcl_PrintDouble((Tcl_Interp *) NULL, mmPtr->value, buffer); - len = strlen(buffer); + Tcl_PrintDouble(NULL, mmPtr->value, buffer); + len = (int)strlen(buffer); objPtr->bytes = (char *) ckalloc((unsigned) len + 1); strcpy(objPtr->bytes, buffer); @@ -533,8 +686,7 @@ UpdateStringOfMM(objPtr) * * SetMMFromAny -- * - * Attempt to generate a mm internal form for the Tcl object - * "objPtr". + * Attempt to generate a mm internal form for the Tcl object "objPtr". * * Results: * The return value is a standard Tcl result. If an error occurs during @@ -542,49 +694,38 @@ UpdateStringOfMM(objPtr) * unless "interp" is NULL. * * Side effects: - * If no error occurs, a mm representation of the object is - * stored internally and the type of "objPtr" is set to mm. + * If no error occurs, a mm representation of the object is stored + * internally and the type of "objPtr" is set to mm. * *---------------------------------------------------------------------- */ static int -SetMMFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tcl_Obj *objPtr; /* The object to convert. */ +SetMMFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + ThreadSpecificData *tsdPtr = GetTypeCache(); + const Tcl_ObjType *typePtr; char *string, *rest; double d; int units; MMRep *mmPtr; - static Tcl_ObjType *tclDoubleObjType = NULL; - static Tcl_ObjType *tclIntObjType = NULL; - - if (tclDoubleObjType == NULL) { - /* - * Cache the object types for comaprison below. - * This allows optimized checks for standard cases. - */ - - tclDoubleObjType = Tcl_GetObjType("double"); - tclIntObjType = Tcl_GetObjType("int"); - } - - if (objPtr->typePtr == tclDoubleObjType) { + if (objPtr->typePtr == tsdPtr->doubleTypePtr) { Tcl_GetDoubleFromObj(interp, objPtr, &d); units = -1; - } else if (objPtr->typePtr == tclIntObjType) { + } else if (objPtr->typePtr == tsdPtr->intTypePtr) { Tcl_GetIntFromObj(interp, objPtr, &units); d = (double) units; units = -1; /* - * In the case of ints, we need to ensure that a valid - * string exists in order for int-but-not-string objects - * to be converted back to ints again from mm obj types. + * In the case of ints, we need to ensure that a valid string exists + * in order for int-but-not-string objects to be converted back to + * ints again from mm obj types. */ + (void) Tcl_GetStringFromObj(objPtr, NULL); } else { /* @@ -600,42 +741,38 @@ SetMMFromAny(interp, objPtr) * is trying to convert the interpreter's result to mms. */ - error: - Tcl_AppendResult(interp, "bad screen distance \"", string, - "\"", (char *) NULL); - return TCL_ERROR; - } - while ((*rest != '\0') && isspace(UCHAR(*rest))) { - rest++; - } - switch (*rest) { - case '\0': - units = -1; - break; - - case 'c': - units = 0; - break; - - case 'i': - units = 1; - break; - - case 'm': - units = 2; - break; - - case 'p': - units = 3; - break; - - default: - goto error; + error: + Tcl_AppendResult(interp, "bad screen distance \"", string, + "\"", NULL); + return TCL_ERROR; + } + while ((*rest != '\0') && isspace(UCHAR(*rest))) { + rest++; + } + + switch (*rest) { + case '\0': + units = -1; + break; + case 'c': + units = 0; + break; + case 'i': + units = 1; + break; + case 'm': + units = 2; + break; + case 'p': + units = 3; + break; + default: + goto error; } } /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ typePtr = objPtr->typePtr; @@ -671,18 +808,18 @@ SetMMFromAny(interp, objPtr) * result unless "interp" is NULL. * * Side effects: - * If the object is not already a Tk_Window, the conversion will free - * any old internal representation. + * If the object is not already a Tk_Window, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ int -TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tk_Window tkwin; /* A token to get the main window from. */ - Tcl_Obj *objPtr; /* The object from which to get window. */ - Tk_Window *windowPtr; /* Place to store resulting window. */ +TkGetWindowFromObj( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tk_Window tkwin, /* A token to get the main window from. */ + Tcl_Obj *objPtr, /* The object from which to get window. */ + Tk_Window *windowPtr) /* Place to store resulting window. */ { TkMainInfo *mainPtr = ((TkWindow *)tkwin)->mainPtr; register WindowRep *winPtr; @@ -696,11 +833,13 @@ TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr) winPtr = (WindowRep *) objPtr->internalRep.otherValuePtr; if ( winPtr->tkwin == NULL || winPtr->mainPtr == NULL - || winPtr->mainPtr != mainPtr - || winPtr->epoch != mainPtr->deletionEpoch) + || winPtr->mainPtr != mainPtr + || winPtr->epoch != mainPtr->deletionEpoch) { - /* Cache is invalid. + /* + * Cache is invalid. */ + winPtr->tkwin = Tk_NameToWindow(interp, Tcl_GetStringFromObj(objPtr, NULL), tkwin); winPtr->mainPtr = mainPtr; @@ -720,14 +859,15 @@ TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr) *---------------------------------------------------------------------- * * SetWindowFromAny -- + * * Generate a windowObj internal form for the Tcl object "objPtr". * * Results: - * Always returns TCL_OK. + * Always returns TCL_OK. * * Side effects: - * Sets objPtr's internal representation to an uninitialized - * windowObj. Frees the old internal representation, if any. + * Sets objPtr's internal representation to an uninitialized windowObj. + * Frees the old internal representation, if any. * * See also: * TkGetWindowFromObj, which initializes the WindowRep cache. @@ -736,15 +876,15 @@ TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr) */ static int -SetWindowFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - register Tcl_Obj *objPtr; /* The object to convert. */ +SetWindowFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + register Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; + const Tcl_ObjType *typePtr; WindowRep *winPtr; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ Tcl_GetStringFromObj(objPtr, NULL); @@ -769,23 +909,23 @@ SetWindowFromAny(interp, objPtr) * * DupWindowInternalRep -- * - * Initialize the internal representation of a window Tcl_Obj to a - * copy of the internal representation of an existing window object. + * Initialize the internal representation of a window Tcl_Obj to a copy + * of the internal representation of an existing window object. * * Results: * None. * * Side effects: - * copyPtr's internal rep is set to refer to the same window as - * srcPtr's internal rep. + * copyPtr's internal rep is set to refer to the same window as srcPtr's + * internal rep. * *---------------------------------------------------------------------- */ static void -DupWindowInternalRep(srcPtr, copyPtr) - register Tcl_Obj *srcPtr; - register Tcl_Obj *copyPtr; +DupWindowInternalRep( + register Tcl_Obj *srcPtr, + register Tcl_Obj *copyPtr) { register WindowRep *oldPtr, *newPtr; @@ -810,15 +950,15 @@ DupWindowInternalRep(srcPtr, copyPtr) * None. * * Side effects: - * Frees objPtr's internal representation and sets objPtr's - * internalRep to NULL. + * Frees objPtr's internal representation and sets objPtr's internalRep + * to NULL. * *---------------------------------------------------------------------- */ static void -FreeWindowInternalRep(objPtr) - Tcl_Obj *objPtr; /* Window object with internal rep to free. */ +FreeWindowInternalRep( + Tcl_Obj *objPtr) /* Window object with internal rep to free. */ { ckfree((char *) objPtr->internalRep.otherValuePtr); objPtr->internalRep.otherValuePtr = NULL; @@ -830,39 +970,39 @@ FreeWindowInternalRep(objPtr) * * TkParsePadAmount -- * - * This procedure parses a padding specification and returns - * the appropriate padding values. A padding specification can - * be either a single pixel width, or a list of two pixel widths. - * If a single pixel width, the amount specified is used for - * padding on both sides. If two amounts are specified, then - * they specify the left/right or top/bottom padding. + * This function parses a padding specification and returns the + * appropriate padding values. A padding specification can be either a + * single pixel width, or a list of two pixel widths. If a single pixel + * width, the amount specified is used for padding on both sides. If two + * amounts are specified, then they specify the left/right or top/bottom + * padding. * * Results: * A standard Tcl return value. * * Side effects: - * An error message is written to the interpreter is something - * is not right. + * An error message is written to the interpreter if something is not + * right. * *-------------------------------------------------------------- */ int -TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* A window. Needed by Tk_GetPixels() */ - Tcl_Obj *specObj; /* The argument to "-padx", "-pady", "-ipadx", - * or "-ipady". The thing to be parsed. */ - int *halfPtr; /* Write the left/top part of padding here */ - int *allPtr; /* Write the total padding here */ +TkParsePadAmount( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* A window. Needed by Tk_GetPixels() */ + Tcl_Obj *specObj, /* The argument to "-padx", "-pady", "-ipadx", + * or "-ipady". The thing to be parsed. */ + int *halfPtr, /* Write the left/top part of padding here */ + int *allPtr) /* Write the total padding here */ { int firstInt, secondInt; /* The two components of the padding */ int objc; /* The length of the list (should be 1 or 2) */ Tcl_Obj **objv; /* The objects in the list */ /* - * Check for a common case where a single object would otherwise - * be shimmered between a list and a pixel spec. + * Check for a common case where a single object would otherwise be + * shimmered between a list and a pixel spec. */ if (specObj->typePtr == &pixelObjType) { @@ -870,7 +1010,7 @@ TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr) Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad pad value \"", Tcl_GetString(specObj), - "\": must be positive screen distance", (char *) NULL); + "\": must be positive screen distance", NULL); return TCL_ERROR; } secondInt = firstInt; @@ -878,8 +1018,8 @@ TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr) } /* - * Pad specifications are a list of one or two elements, each of - * which is a pixel specification. + * Pad specifications are a list of one or two elements, each of which is + * a pixel specification. */ if (Tcl_ListObjGetElements(interp, specObj, &objc, &objv) != TCL_OK) { @@ -899,13 +1039,13 @@ TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr) (firstInt < 0)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad pad value \"", Tcl_GetString(objv[0]), - "\": must be positive screen distance", (char *) NULL); + "\": must be positive screen distance", NULL); return TCL_ERROR; } /* - * Parse the second part if it exists, otherwise it is as if it - * was the same as the first part. + * Parse the second part if it exists, otherwise it is as if it was the + * same as the first part. */ if (objc == 1) { @@ -915,7 +1055,7 @@ TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr) Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad 2nd pad value \"", Tcl_GetString(objv[1]), - "\": must be positive screen distance", (char *) NULL); + "\": must be positive screen distance", NULL); return TCL_ERROR; } @@ -942,14 +1082,14 @@ TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr) * None * * Side effects: - * All instances of Tcl_ObjType structues used in Tk are registered - * with Tcl. + * All instances of Tcl_ObjType structues used in Tk are registered with + * Tcl. * *---------------------------------------------------------------------- */ void -TkRegisterObjTypes() +TkRegisterObjTypes(void) { Tcl_RegisterObjType(&tkBorderObjType); Tcl_RegisterObjType(&tkBitmapObjType); @@ -961,4 +1101,13 @@ TkRegisterObjTypes() Tcl_RegisterObjType(&pixelObjType); Tcl_RegisterObjType(&tkStateKeyObjType); Tcl_RegisterObjType(&windowObjType); + Tcl_RegisterObjType(&tkTextIndexType); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkOldConfig.c b/generic/tkOldConfig.c index bbb673f..97ad5cb 100644 --- a/generic/tkOldConfig.c +++ b/generic/tkOldConfig.c @@ -1,106 +1,101 @@ -/* +/* * tkOldConfig.c -- * - * This file contains the Tk_ConfigureWidget procedure. THIS FILE - * IS HERE FOR BACKWARD COMPATIBILITY; THE NEW CONFIGURATION - * PACKAGE SHOULD BE USED FOR NEW PROJECTS. + * This file contains the Tk_ConfigureWidget function. THIS FILE IS HERE + * FOR BACKWARD COMPATIBILITY; THE NEW CONFIGURATION PACKAGE SHOULD BE + * USED FOR NEW PROJECTS. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkPort.h" -#include "tk.h" /* - * Values for "flags" field of Tk_ConfigSpec structures. Be sure - * to coordinate these values with those defined in tk.h - * (TK_CONFIG_COLOR_ONLY, etc.). There must not be overlap! + * Values for "flags" field of Tk_ConfigSpec structures. Be sure to coordinate + * these values with those defined in tk.h (TK_CONFIG_COLOR_ONLY, etc.) There + * must not be overlap! * - * INIT - Non-zero means (char *) things have been - * converted to Tk_Uid's. + * INIT - Non-zero means (char *) things have been converted to + * Tk_Uid's. */ #define INIT 0x20 /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int DoConfig _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_ConfigSpec *specPtr, - Tk_Uid value, int valueIsUid, char *widgRec)); -static Tk_ConfigSpec * FindConfigSpec _ANSI_ARGS_((Tcl_Interp *interp, +static int DoConfig(Tcl_Interp *interp, Tk_Window tkwin, + Tk_ConfigSpec *specPtr, Tk_Uid value, + int valueIsUid, char *widgRec); +static Tk_ConfigSpec * FindConfigSpec(Tcl_Interp *interp, Tk_ConfigSpec *specs, CONST char *argvName, - int needFlags, int hateFlags)); -static char * FormatConfigInfo _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_ConfigSpec *specPtr, - char *widgRec)); -static CONST char * FormatConfigValue _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_ConfigSpec *specPtr, - char *widgRec, char *buffer, - Tcl_FreeProc **freeProcPtr)); -static Tk_ConfigSpec * GetCachedSpecs _ANSI_ARGS_((Tcl_Interp *interp, - const Tk_ConfigSpec *staticSpecs)); -static void DeleteSpecCacheTable _ANSI_ARGS_(( - ClientData clientData, Tcl_Interp *interp)); + int needFlags, int hateFlags); +static char * FormatConfigInfo(Tcl_Interp *interp, Tk_Window tkwin, + Tk_ConfigSpec *specPtr, char *widgRec); +static CONST char * FormatConfigValue(Tcl_Interp *interp, Tk_Window tkwin, + Tk_ConfigSpec *specPtr, char *widgRec, + char *buffer, Tcl_FreeProc **freeProcPtr); +static Tk_ConfigSpec * GetCachedSpecs(Tcl_Interp *interp, + const Tk_ConfigSpec *staticSpecs); +static void DeleteSpecCacheTable(ClientData clientData, + Tcl_Interp *interp); /* *-------------------------------------------------------------- * * Tk_ConfigureWidget -- * - * Process command-line options and database options to - * fill in fields of a widget record with resources and - * other parameters. + * Process command-line options and database options to fill in fields of + * a widget record with resources and other parameters. * * Results: - * A standard Tcl return value. In case of an error, - * the interp's result will hold an error message. + * A standard Tcl return value. In case of an error, the interp's result + * will hold an error message. * * Side effects: - * The fields of widgRec get filled in with information from - * argc/argv and the option database. Old information in - * widgRec's fields gets recycled. A copy of the spec-table is - * taken with (some of) the char* *fields converted into Tk_Uid - * fields; this copy will be released when *the interpreter - * terminates. + * The fields of widgRec get filled in with information from argc/argv + * and the option database. Old information in widgRec's fields gets + * recycled. A copy of the spec-table is taken with (some of) the char* + * fields converted into Tk_Uid fields; this copy will be released when + * the interpreter terminates. * *-------------------------------------------------------------- */ int -Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Window containing widget (needed to - * set up X resources). */ - Tk_ConfigSpec *origSpecs; /* Describes legal options. */ - int argc; /* Number of elements in argv. */ - CONST char **argv; /* Command-line options. */ - char *widgRec; /* Record whose fields are to be - * modified. Values must be properly - * initialized. */ - int flags; /* Used to specify additional flags - * that must be present in config specs - * for them to be considered. Also, - * may have TK_CONFIG_ARGV_ONLY set. */ +Tk_ConfigureWidget( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Window containing widget (needed to set up + * X resources). */ + Tk_ConfigSpec *specs, /* Describes legal options. */ + int argc, /* Number of elements in argv. */ + CONST char **argv, /* Command-line options. */ + char *widgRec, /* Record whose fields are to be modified. + * Values must be properly initialized. */ + int flags) /* Used to specify additional flags that must + * be present in config specs for them to be + * considered. Also, may have + * TK_CONFIG_ARGV_ONLY set. */ { - register Tk_ConfigSpec *specs, *specPtr, *origSpecPtr; + register Tk_ConfigSpec *specPtr; Tk_Uid value; /* Value of option from database. */ - int needFlags; /* Specs must contain this set of flags - * or else they are not considered. */ - int hateFlags; /* If a spec contains any bits here, it's - * not considered. */ + int needFlags; /* Specs must contain this set of flags or + * else they are not considered. */ + int hateFlags; /* If a spec contains any bits here, it's not + * considered. */ if (tkwin == NULL) { /* * Either we're not really in Tk, or the main window was destroyed and * we're on our way out of the application */ - Tcl_AppendResult(interp, "NULL main window", (char *)NULL); + + Tcl_AppendResult(interp, "NULL main window", NULL); return TCL_ERROR; } @@ -112,19 +107,14 @@ Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) } /* - * Get the build of the config for this interpreter and reset any - * indication of changed options. + * Get the build of the config for this interpreter. */ - specs = GetCachedSpecs(interp, origSpecs); - - for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) { - specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED; - } + specs = GetCachedSpecs(interp, specs); /* - * Pass one: scan through all of the arguments, processing those - * that match entries in the specs. + * Pass one: scan through all of the arguments, processing those that + * match entries in the specs. */ for ( ; argc > 0; argc -= 2, argv += 2) { @@ -145,8 +135,7 @@ Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) */ if (argc < 2) { - Tcl_AppendResult(interp, "value for \"", arg, - "\" missing", (char *) NULL); + Tcl_AppendResult(interp, "value for \"", arg, "\" missing", NULL); return TCL_ERROR; } if (flags & TK_CONFIG_OBJS) { @@ -162,25 +151,15 @@ Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) Tcl_AddErrorInfo(interp, msg); return TCL_ERROR; } - specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED; - } - - /* - * Thread Unsafe! For compatibility through 8.4.x, we set the original - * specPtr flags to indicate changed options. This has been removed - * from 8.5. Switch to Tcl_Obj-based options instead. [Bug 749908] - */ - - for (origSpecPtr = origSpecs, specPtr = specs; - specPtr->type != TK_CONFIG_END; origSpecPtr++, specPtr++) { - origSpecPtr->specFlags = specPtr->specFlags; + if (!(flags & TK_CONFIG_ARGV_ONLY)) { + specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED; + } } /* - * Pass two: scan through all of the specs again; if no - * command-line argument matched a spec, then check for info - * in the option database. If there was nothing in the - * database, then use the default. + * Pass two: scan through all of the specs again; if no command-line + * argument matched a spec, then check for info in the option database. + * If there was nothing in the database, then use the default. */ if (!(flags & TK_CONFIG_ARGV_ONLY)) { @@ -188,6 +167,7 @@ Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED) || (specPtr->argvName == NULL) || (specPtr->type == TK_CONFIG_SYNONYM)) { + specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED; continue; } if (((specPtr->specFlags & needFlags) != needFlags) @@ -241,13 +221,13 @@ Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) * * FindConfigSpec -- * - * Search through a table of configuration specs, looking for - * one that matches a given argvName. + * Search through a table of configuration specs, looking for one that + * matches a given argvName. * * Results: - * The return value is a pointer to the matching entry, or NULL - * if nothing matched. In that case an error message is left - * in the interp's result. + * The return value is a pointer to the matching entry, or NULL if + * nothing matched. In that case an error message is left in the interp's + * result. * * Side effects: * None. @@ -256,16 +236,16 @@ Tk_ConfigureWidget(interp, tkwin, origSpecs, argc, argv, widgRec, flags) */ static Tk_ConfigSpec * -FindConfigSpec(interp, specs, argvName, needFlags, hateFlags) - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_ConfigSpec *specs; /* Pointer to table of configuration +FindConfigSpec( + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_ConfigSpec *specs, /* Pointer to table of configuration * specifications for a widget. */ - CONST char *argvName; /* Name (suitable for use in a "config" + CONST char *argvName, /* Name (suitable for use in a "config" * command) identifying particular option. */ - int needFlags; /* Flags that must be present in matching + int needFlags, /* Flags that must be present in matching + * entry. */ + int hateFlags) /* Flags that must NOT be present in matching * entry. */ - int hateFlags; /* Flags that must NOT be present in - * matching entry. */ { register Tk_ConfigSpec *specPtr; register char c; /* First character of current argument. */ @@ -293,34 +273,32 @@ FindConfigSpec(interp, specs, argvName, needFlags, hateFlags) } if (matchPtr != NULL) { Tcl_AppendResult(interp, "ambiguous option \"", argvName, - "\"", (char *) NULL); - return (Tk_ConfigSpec *) NULL; + "\"", NULL); + return NULL; } matchPtr = specPtr; } if (matchPtr == NULL) { - Tcl_AppendResult(interp, "unknown option \"", argvName, - "\"", (char *) NULL); - return (Tk_ConfigSpec *) NULL; + Tcl_AppendResult(interp, "unknown option \"", argvName, "\"", NULL); + return NULL; } /* - * Found a matching entry. If it's a synonym, then find the - * entry that it's a synonym for. + * Found a matching entry. If it's a synonym, then find the entry that + * it's a synonym for. */ - gotMatch: + gotMatch: specPtr = matchPtr; if (specPtr->type == TK_CONFIG_SYNONYM) { for (specPtr = specs; ; specPtr++) { if (specPtr->type == TK_CONFIG_END) { - Tcl_AppendResult(interp, - "couldn't find synonym for option \"", - argvName, "\"", (char *) NULL); - return (Tk_ConfigSpec *) NULL; + Tcl_AppendResult(interp, "couldn't find synonym for option \"", + argvName, "\"", NULL); + return NULL; } - if ((specPtr->dbName == matchPtr->dbName) + if ((specPtr->dbName == matchPtr->dbName) && (specPtr->type != TK_CONFIG_SYNONYM) && ((specPtr->specFlags & needFlags) == needFlags) && !(specPtr->specFlags & hateFlags)) { @@ -336,32 +314,30 @@ FindConfigSpec(interp, specs, argvName, needFlags, hateFlags) * * DoConfig -- * - * This procedure applies a single configuration option - * to a widget record. + * This function applies a single configuration option to a widget + * record. * * Results: * A standard Tcl return value. * * Side effects: - * WidgRec is modified as indicated by specPtr and value. - * The old value is recycled, if that is appropriate for - * the value type. + * WidgRec is modified as indicated by specPtr and value. The old value + * is recycled, if that is appropriate for the value type. * *-------------------------------------------------------------- */ static int -DoConfig(interp, tkwin, specPtr, value, valueIsUid, widgRec) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Window containing widget (needed to - * set up X resources). */ - Tk_ConfigSpec *specPtr; /* Specifier to apply. */ - Tk_Uid value; /* Value to use to fill in widgRec. */ - int valueIsUid; /* Non-zero means value is a Tk_Uid; - * zero means it's an ordinary string. */ - char *widgRec; /* Record whose fields are to be - * modified. Values must be properly - * initialized. */ +DoConfig( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Window containing widget (needed to set up + * X resources). */ + Tk_ConfigSpec *specPtr, /* Specifier to apply. */ + Tk_Uid value, /* Value to use to fill in widgRec. */ + int valueIsUid, /* Non-zero means value is a Tk_Uid; zero + * means it's an ordinary string. */ + char *widgRec) /* Record whose fields are to be modified. + * Values must be properly initialized. */ { char *ptr; Tk_Uid uid; @@ -375,211 +351,209 @@ DoConfig(interp, tkwin, specPtr, value, valueIsUid, widgRec) do { ptr = widgRec + specPtr->offset; switch (specPtr->type) { - case TK_CONFIG_BOOLEAN: - if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) { - return TCL_ERROR; - } - break; - case TK_CONFIG_INT: - if (Tcl_GetInt(interp, value, (int *) ptr) != TCL_OK) { - return TCL_ERROR; - } - break; - case TK_CONFIG_DOUBLE: - if (Tcl_GetDouble(interp, value, (double *) ptr) != TCL_OK) { - return TCL_ERROR; - } - break; - case TK_CONFIG_STRING: { - char *old, *new; - - if (nullValue) { - new = NULL; - } else { - new = (char *) ckalloc((unsigned) (strlen(value) + 1)); - strcpy(new, value); - } - old = *((char **) ptr); - if (old != NULL) { - ckfree(old); - } - *((char **) ptr) = new; - break; + case TK_CONFIG_BOOLEAN: + if (Tcl_GetBoolean(interp, value, (int *) ptr) != TCL_OK) { + return TCL_ERROR; } - case TK_CONFIG_UID: - if (nullValue) { - *((Tk_Uid *) ptr) = NULL; - } else { - uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - *((Tk_Uid *) ptr) = uid; - } - break; - case TK_CONFIG_COLOR: { - XColor *newPtr, *oldPtr; - - if (nullValue) { - newPtr = NULL; - } else { - uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - newPtr = Tk_GetColor(interp, tkwin, uid); - if (newPtr == NULL) { - return TCL_ERROR; - } - } - oldPtr = *((XColor **) ptr); - if (oldPtr != NULL) { - Tk_FreeColor(oldPtr); - } - *((XColor **) ptr) = newPtr; - break; + break; + case TK_CONFIG_INT: + if (Tcl_GetInt(interp, value, (int *) ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_DOUBLE: + if (Tcl_GetDouble(interp, value, (double *) ptr) != TCL_OK) { + return TCL_ERROR; } - case TK_CONFIG_FONT: { - Tk_Font new; + break; + case TK_CONFIG_STRING: { + char *oldStr, *newStr; - if (nullValue) { - new = NULL; - } else { - new = Tk_GetFont(interp, tkwin, value); - if (new == NULL) { - return TCL_ERROR; - } - } - Tk_FreeFont(*((Tk_Font *) ptr)); - *((Tk_Font *) ptr) = new; - break; + if (nullValue) { + newStr = NULL; + } else { + newStr = (char *) ckalloc((unsigned) (strlen(value) + 1)); + strcpy(newStr, value); } - case TK_CONFIG_BITMAP: { - Pixmap new, old; - - if (nullValue) { - new = None; - } else { - uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - new = Tk_GetBitmap(interp, tkwin, uid); - if (new == None) { - return TCL_ERROR; - } - } - old = *((Pixmap *) ptr); - if (old != None) { - Tk_FreeBitmap(Tk_Display(tkwin), old); - } - *((Pixmap *) ptr) = new; - break; + oldStr = *((char **) ptr); + if (oldStr != NULL) { + ckfree(oldStr); } - case TK_CONFIG_BORDER: { - Tk_3DBorder new, old; - - if (nullValue) { - new = NULL; - } else { - uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - new = Tk_Get3DBorder(interp, tkwin, uid); - if (new == NULL) { - return TCL_ERROR; - } - } - old = *((Tk_3DBorder *) ptr); - if (old != NULL) { - Tk_Free3DBorder(old); - } - *((Tk_3DBorder *) ptr) = new; - break; + *((char **) ptr) = newStr; + break; + } + case TK_CONFIG_UID: + if (nullValue) { + *((Tk_Uid *) ptr) = NULL; + } else { + uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); + *((Tk_Uid *) ptr) = uid; } - case TK_CONFIG_RELIEF: + break; + case TK_CONFIG_COLOR: { + XColor *newPtr, *oldPtr; + + if (nullValue) { + newPtr = NULL; + } else { uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - if (Tk_GetRelief(interp, uid, (int *) ptr) != TCL_OK) { + newPtr = Tk_GetColor(interp, tkwin, uid); + if (newPtr == NULL) { return TCL_ERROR; } - break; - case TK_CONFIG_CURSOR: - case TK_CONFIG_ACTIVE_CURSOR: { - Tk_Cursor new, old; - - if (nullValue) { - new = None; - } else { - uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - new = Tk_GetCursor(interp, tkwin, uid); - if (new == None) { - return TCL_ERROR; - } - } - old = *((Tk_Cursor *) ptr); - if (old != None) { - Tk_FreeCursor(Tk_Display(tkwin), old); - } - *((Tk_Cursor *) ptr) = new; - if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) { - Tk_DefineCursor(tkwin, new); - } - break; } - case TK_CONFIG_JUSTIFY: - uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - if (Tk_GetJustify(interp, uid, (Tk_Justify *) ptr) != TCL_OK) { + oldPtr = *((XColor **) ptr); + if (oldPtr != NULL) { + Tk_FreeColor(oldPtr); + } + *((XColor **) ptr) = newPtr; + break; + } + case TK_CONFIG_FONT: { + Tk_Font newFont; + + if (nullValue) { + newFont = NULL; + } else { + newFont = Tk_GetFont(interp, tkwin, value); + if (newFont == NULL) { return TCL_ERROR; } - break; - case TK_CONFIG_ANCHOR: + } + Tk_FreeFont(*((Tk_Font *) ptr)); + *((Tk_Font *) ptr) = newFont; + break; + } + case TK_CONFIG_BITMAP: { + Pixmap newBmp, oldBmp; + + if (nullValue) { + newBmp = None; + } else { uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - if (Tk_GetAnchor(interp, uid, (Tk_Anchor *) ptr) != TCL_OK) { + newBmp = Tk_GetBitmap(interp, tkwin, uid); + if (newBmp == None) { return TCL_ERROR; } - break; - case TK_CONFIG_CAP_STYLE: + } + oldBmp = *((Pixmap *) ptr); + if (oldBmp != None) { + Tk_FreeBitmap(Tk_Display(tkwin), oldBmp); + } + *((Pixmap *) ptr) = newBmp; + break; + } + case TK_CONFIG_BORDER: { + Tk_3DBorder newBorder, oldBorder; + + if (nullValue) { + newBorder = NULL; + } else { uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - if (Tk_GetCapStyle(interp, uid, (int *) ptr) != TCL_OK) { + newBorder = Tk_Get3DBorder(interp, tkwin, uid); + if (newBorder == NULL) { return TCL_ERROR; } - break; - case TK_CONFIG_JOIN_STYLE: + } + oldBorder = *((Tk_3DBorder *) ptr); + if (oldBorder != NULL) { + Tk_Free3DBorder(oldBorder); + } + *((Tk_3DBorder *) ptr) = newBorder; + break; + } + case TK_CONFIG_RELIEF: + uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); + if (Tk_GetRelief(interp, uid, (int *) ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_CURSOR: + case TK_CONFIG_ACTIVE_CURSOR: { + Tk_Cursor newCursor, oldCursor; + + if (nullValue) { + newCursor = None; + } else { uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); - if (Tk_GetJoinStyle(interp, uid, (int *) ptr) != TCL_OK) { - return TCL_ERROR; - } - break; - case TK_CONFIG_PIXELS: - if (Tk_GetPixels(interp, tkwin, value, (int *) ptr) - != TCL_OK) { - return TCL_ERROR; - } - break; - case TK_CONFIG_MM: - if (Tk_GetScreenMM(interp, tkwin, value, (double *) ptr) - != TCL_OK) { + newCursor = Tk_GetCursor(interp, tkwin, uid); + if (newCursor == None) { return TCL_ERROR; } - break; - case TK_CONFIG_WINDOW: { - Tk_Window tkwin2; - - if (nullValue) { - tkwin2 = NULL; - } else { - tkwin2 = Tk_NameToWindow(interp, value, tkwin); - if (tkwin2 == NULL) { - return TCL_ERROR; - } - } - *((Tk_Window *) ptr) = tkwin2; - break; } - case TK_CONFIG_CUSTOM: - if ((*specPtr->customPtr->parseProc)( - specPtr->customPtr->clientData, interp, tkwin, - value, widgRec, specPtr->offset) != TCL_OK) { + oldCursor = *((Tk_Cursor *) ptr); + if (oldCursor != None) { + Tk_FreeCursor(Tk_Display(tkwin), oldCursor); + } + *((Tk_Cursor *) ptr) = newCursor; + if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) { + Tk_DefineCursor(tkwin, newCursor); + } + break; + } + case TK_CONFIG_JUSTIFY: + uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); + if (Tk_GetJustify(interp, uid, (Tk_Justify *) ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_ANCHOR: + uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); + if (Tk_GetAnchor(interp, uid, (Tk_Anchor *) ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_CAP_STYLE: + uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); + if (Tk_GetCapStyle(interp, uid, (int *) ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_JOIN_STYLE: + uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value); + if (Tk_GetJoinStyle(interp, uid, (int *) ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_PIXELS: + if (Tk_GetPixels(interp, tkwin, value, (int *) ptr) + != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_MM: + if (Tk_GetScreenMM(interp, tkwin, value, (double*)ptr) != TCL_OK) { + return TCL_ERROR; + } + break; + case TK_CONFIG_WINDOW: { + Tk_Window tkwin2; + + if (nullValue) { + tkwin2 = NULL; + } else { + tkwin2 = Tk_NameToWindow(interp, value, tkwin); + if (tkwin2 == NULL) { return TCL_ERROR; } - break; - default: { - char buf[64 + TCL_INTEGER_SPACE]; - - sprintf(buf, "bad config table: unknown type %d", - specPtr->type); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + *((Tk_Window *) ptr) = tkwin2; + break; + } + case TK_CONFIG_CUSTOM: + if ((*specPtr->customPtr->parseProc)( + specPtr->customPtr->clientData, interp, tkwin, value, + widgRec, specPtr->offset) != TCL_OK) { return TCL_ERROR; } + break; + default: { + char buf[64 + TCL_INTEGER_SPACE]; + + sprintf(buf, "bad config table: unknown type %d", specPtr->type); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_ERROR; + } } specPtr++; } while ((specPtr->argvName == NULL) && (specPtr->type != TK_CONFIG_END)); @@ -591,24 +565,22 @@ DoConfig(interp, tkwin, specPtr, value, valueIsUid, widgRec) * * Tk_ConfigureInfo -- * - * Return information about the configuration options - * for a window, and their current values. + * Return information about the configuration options for a window, and + * their current values. * * Results: - * Always returns TCL_OK. The interp's result will be modified - * hold a description of either a single configuration option - * available for "widgRec" via "specs", or all the configuration - * options available. In the "all" case, the result will - * available for "widgRec" via "specs". The result will - * be a list, each of whose entries describes one option. - * Each entry will itself be a list containing the option's - * name for use on command lines, database name, database - * class, default value, and current value (empty string - * if none). For options that are synonyms, the list will - * contain only two values: name and synonym name. If the - * "name" argument is non-NULL, then the only information - * returned is that for the named argument (i.e. the corresponding - * entry in the overall list is returned). + * Always returns TCL_OK. The interp's result will be modified hold a + * description of either a single configuration option available for + * "widgRec" via "specs", or all the configuration options available. In + * the "all" case, the result will available for "widgRec" via "specs". + * The result will be a list, each of whose entries describes one option. + * Each entry will itself be a list containing the option's name for use + * on command lines, database name, database class, default value, and + * current value (empty string if none). For options that are synonyms, + * the list will contain only two values: name and synonym name. If the + * "name" argument is non-NULL, then the only information returned is + * that for the named argument (i.e. the corresponding entry in the + * overall list is returned). * * Side effects: * None. @@ -617,18 +589,18 @@ DoConfig(interp, tkwin, specPtr, value, valueIsUid, widgRec) */ int -Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Window corresponding to widgRec. */ - Tk_ConfigSpec *specs; /* Describes legal options. */ - char *widgRec; /* Record whose fields contain current - * values for options. */ - CONST char *argvName; /* If non-NULL, indicates a single option - * whose info is to be returned. Otherwise +Tk_ConfigureInfo( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Window corresponding to widgRec. */ + Tk_ConfigSpec *specs, /* Describes legal options. */ + char *widgRec, /* Record whose fields contain current values + * for options. */ + CONST char *argvName, /* If non-NULL, indicates a single option + * whose info is to be returned. Otherwise * info is returned for all options. */ - int flags; /* Used to specify additional flags - * that must be present in config specs - * for them to be considered. */ + int flags) /* Used to specify additional flags that must + * be present in config specs for them to be + * considered. */ { register Tk_ConfigSpec *specPtr; int needFlags, hateFlags; @@ -649,11 +621,11 @@ Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags) specs = GetCachedSpecs(interp, specs); /* - * If information is only wanted for a single configuration - * spec, then handle that one spec specially. + * If information is only wanted for a single configuration spec, then + * handle that one spec specially. */ - Tcl_SetResult(interp, (char *) NULL, TCL_STATIC); + Tcl_SetResult(interp, NULL, TCL_STATIC); if (argvName != NULL) { specPtr = FindConfigSpec(interp, specs, argvName, needFlags,hateFlags); if (specPtr == NULL) { @@ -666,8 +638,8 @@ Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags) } /* - * Loop through all the specs, creating a big list with all - * their information. + * Loop through all the specs, creating a big list with all their + * information. */ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) { @@ -682,7 +654,7 @@ Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags) continue; } list = FormatConfigInfo(interp, tkwin, specPtr, widgRec); - Tcl_AppendResult(interp, leader, list, "}", (char *) NULL); + Tcl_AppendResult(interp, leader, list, "}", NULL); ckfree(list); leader = " {"; } @@ -694,12 +666,12 @@ Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags) * * FormatConfigInfo -- * - * Create a valid Tcl list holding the configuration information - * for a single configuration option. + * Create a valid Tcl list holding the configuration information for a + * single configuration option. * * Results: - * A Tcl list, dynamically allocated. The caller is expected to - * arrange for this list to be freed eventually. + * A Tcl list, dynamically allocated. The caller is expected to arrange + * for this list to be freed eventually. * * Side effects: * Memory is allocated. @@ -708,19 +680,20 @@ Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags) */ static char * -FormatConfigInfo(interp, tkwin, specPtr, widgRec) - Tcl_Interp *interp; /* Interpreter to use for things - * like floating-point precision. */ - Tk_Window tkwin; /* Window corresponding to widget. */ - register Tk_ConfigSpec *specPtr; /* Pointer to information describing - * option. */ - char *widgRec; /* Pointer to record holding current - * values of info for widget. */ +FormatConfigInfo( + Tcl_Interp *interp, /* Interpreter to use for things like + * floating-point precision. */ + Tk_Window tkwin, /* Window corresponding to widget. */ + register Tk_ConfigSpec *specPtr, + /* Pointer to information describing + * option. */ + char *widgRec) /* Pointer to record holding current values of + * info for widget. */ { CONST char *argv[6]; char *result; char buffer[200]; - Tcl_FreeProc *freeProc = (Tcl_FreeProc *) NULL; + Tcl_FreeProc *freeProc = NULL; argv[0] = specPtr->argvName; argv[1] = specPtr->dbName; @@ -759,16 +732,14 @@ FormatConfigInfo(interp, tkwin, specPtr, widgRec) * * FormatConfigValue -- * - * This procedure formats the current value of a configuration - * option. + * This function formats the current value of a configuration option. * * Results: - * The return value is the formatted value of the option given - * by specPtr and widgRec. If the value is static, so that it - * need not be freed, *freeProcPtr will be set to NULL; otherwise - * *freeProcPtr will be set to the address of a procedure to - * free the result, and the caller must invoke this procedure - * when it is finished with the result. + * The return value is the formatted value of the option given by specPtr + * and widgRec. If the value is static, so that it need not be freed, + * *freeProcPtr will be set to NULL; otherwise *freeProcPtr will be set + * to the address of a function to free the result, and the caller must + * invoke this function when it is finished with the result. * * Side effects: * None. @@ -777,18 +748,18 @@ FormatConfigInfo(interp, tkwin, specPtr, widgRec) */ static CONST char * -FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr) - Tcl_Interp *interp; /* Interpreter for use in real conversions. */ - Tk_Window tkwin; /* Window corresponding to widget. */ - Tk_ConfigSpec *specPtr; /* Pointer to information describing option. +FormatConfigValue( + Tcl_Interp *interp, /* Interpreter for use in real conversions. */ + Tk_Window tkwin, /* Window corresponding to widget. */ + Tk_ConfigSpec *specPtr, /* Pointer to information describing option. * Must not point to a synonym option. */ - char *widgRec; /* Pointer to record holding current - * values of info for widget. */ - char *buffer; /* Static buffer to use for small values. + char *widgRec, /* Pointer to record holding current values of + * info for widget. */ + char *buffer, /* Static buffer to use for small values. * Must have at least 200 bytes of storage. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to word to fill in with address - * of procedure to free the result, or NULL - * if result is static. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to word to fill in with address of + * function to free the result, or NULL if + * result is static. */ { CONST char *ptr, *result; @@ -796,109 +767,115 @@ FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr) ptr = widgRec + specPtr->offset; result = ""; switch (specPtr->type) { - case TK_CONFIG_BOOLEAN: - if (*((int *) ptr) == 0) { - result = "0"; - } else { - result = "1"; - } - break; - case TK_CONFIG_INT: - sprintf(buffer, "%d", *((int *) ptr)); - result = buffer; - break; - case TK_CONFIG_DOUBLE: - Tcl_PrintDouble(interp, *((double *) ptr), buffer); - result = buffer; - break; - case TK_CONFIG_STRING: - result = (*(char **) ptr); - if (result == NULL) { - result = ""; - } - break; - case TK_CONFIG_UID: { - Tk_Uid uid = *((Tk_Uid *) ptr); - if (uid != NULL) { - result = uid; - } - break; + case TK_CONFIG_BOOLEAN: + if (*((int *) ptr) == 0) { + result = "0"; + } else { + result = "1"; } - case TK_CONFIG_COLOR: { - XColor *colorPtr = *((XColor **) ptr); - if (colorPtr != NULL) { - result = Tk_NameOfColor(colorPtr); - } - break; + break; + case TK_CONFIG_INT: + sprintf(buffer, "%d", *((int *) ptr)); + result = buffer; + break; + case TK_CONFIG_DOUBLE: + Tcl_PrintDouble(interp, *((double *) ptr), buffer); + result = buffer; + break; + case TK_CONFIG_STRING: + result = (*(char **) ptr); + if (result == NULL) { + result = ""; } - case TK_CONFIG_FONT: { - Tk_Font tkfont = *((Tk_Font *) ptr); - if (tkfont != NULL) { - result = Tk_NameOfFont(tkfont); - } - break; + break; + case TK_CONFIG_UID: { + Tk_Uid uid = *((Tk_Uid *) ptr); + + if (uid != NULL) { + result = uid; } - case TK_CONFIG_BITMAP: { - Pixmap pixmap = *((Pixmap *) ptr); - if (pixmap != None) { - result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap); - } - break; + break; + } + case TK_CONFIG_COLOR: { + XColor *colorPtr = *((XColor **) ptr); + + if (colorPtr != NULL) { + result = Tk_NameOfColor(colorPtr); } - case TK_CONFIG_BORDER: { - Tk_3DBorder border = *((Tk_3DBorder *) ptr); - if (border != NULL) { - result = Tk_NameOf3DBorder(border); - } - break; + break; + } + case TK_CONFIG_FONT: { + Tk_Font tkfont = *((Tk_Font *) ptr); + + if (tkfont != NULL) { + result = Tk_NameOfFont(tkfont); } - case TK_CONFIG_RELIEF: - result = Tk_NameOfRelief(*((int *) ptr)); - break; - case TK_CONFIG_CURSOR: - case TK_CONFIG_ACTIVE_CURSOR: { - Tk_Cursor cursor = *((Tk_Cursor *) ptr); - if (cursor != None) { - result = Tk_NameOfCursor(Tk_Display(tkwin), cursor); - } - break; + break; + } + case TK_CONFIG_BITMAP: { + Pixmap pixmap = *((Pixmap *) ptr); + + if (pixmap != None) { + result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap); } - case TK_CONFIG_JUSTIFY: - result = Tk_NameOfJustify(*((Tk_Justify *) ptr)); - break; - case TK_CONFIG_ANCHOR: - result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr)); - break; - case TK_CONFIG_CAP_STYLE: - result = Tk_NameOfCapStyle(*((int *) ptr)); - break; - case TK_CONFIG_JOIN_STYLE: - result = Tk_NameOfJoinStyle(*((int *) ptr)); - break; - case TK_CONFIG_PIXELS: - sprintf(buffer, "%d", *((int *) ptr)); - result = buffer; - break; - case TK_CONFIG_MM: - Tcl_PrintDouble(interp, *((double *) ptr), buffer); - result = buffer; - break; - case TK_CONFIG_WINDOW: { - Tk_Window tkwin; + break; + } + case TK_CONFIG_BORDER: { + Tk_3DBorder border = *((Tk_3DBorder *) ptr); - tkwin = *((Tk_Window *) ptr); - if (tkwin != NULL) { - result = Tk_PathName(tkwin); - } - break; + if (border != NULL) { + result = Tk_NameOf3DBorder(border); } - case TK_CONFIG_CUSTOM: - result = (*specPtr->customPtr->printProc)( - specPtr->customPtr->clientData, tkwin, widgRec, - specPtr->offset, freeProcPtr); - break; - default: - result = "?? unknown type ??"; + break; + } + case TK_CONFIG_RELIEF: + result = Tk_NameOfRelief(*((int *) ptr)); + break; + case TK_CONFIG_CURSOR: + case TK_CONFIG_ACTIVE_CURSOR: { + Tk_Cursor cursor = *((Tk_Cursor *) ptr); + + if (cursor != None) { + result = Tk_NameOfCursor(Tk_Display(tkwin), cursor); + } + break; + } + case TK_CONFIG_JUSTIFY: + result = Tk_NameOfJustify(*((Tk_Justify *) ptr)); + break; + case TK_CONFIG_ANCHOR: + result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr)); + break; + case TK_CONFIG_CAP_STYLE: + result = Tk_NameOfCapStyle(*((int *) ptr)); + break; + case TK_CONFIG_JOIN_STYLE: + result = Tk_NameOfJoinStyle(*((int *) ptr)); + break; + case TK_CONFIG_PIXELS: + sprintf(buffer, "%d", *((int *) ptr)); + result = buffer; + break; + case TK_CONFIG_MM: + Tcl_PrintDouble(interp, *((double *) ptr), buffer); + result = buffer; + break; + case TK_CONFIG_WINDOW: { + Tk_Window tkwin; + + tkwin = *((Tk_Window *) ptr); + if (tkwin != NULL) { + result = Tk_PathName(tkwin); + } + break; + } + case TK_CONFIG_CUSTOM: + result = (*specPtr->customPtr->printProc)( + specPtr->customPtr->clientData, tkwin, widgRec, + specPtr->offset, freeProcPtr); + break; + default: + result = "?? unknown type ??"; } return result; } @@ -908,14 +885,14 @@ FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr) * * Tk_ConfigureValue -- * - * This procedure returns the current value of a configuration - * option for a widget. + * This function returns the current value of a configuration option for + * a widget. * * Results: * The return value is a standard Tcl completion code (TCL_OK or - * TCL_ERROR). The interp's result will be set to hold either the value - * of the option given by argvName (if TCL_OK is returned) or - * an error message (if TCL_ERROR is returned). + * TCL_ERROR). The interp's result will be set to hold either the value + * of the option given by argvName (if TCL_OK is returned) or an error + * message (if TCL_ERROR is returned). * * Side effects: * None. @@ -924,17 +901,17 @@ FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, freeProcPtr) */ int -Tk_ConfigureValue(interp, tkwin, specs, widgRec, argvName, flags) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Window corresponding to widgRec. */ - Tk_ConfigSpec *specs; /* Describes legal options. */ - char *widgRec; /* Record whose fields contain current - * values for options. */ - CONST char *argvName; /* Gives the command-line name for the - * option whose value is to be returned. */ - int flags; /* Used to specify additional flags - * that must be present in config specs - * for them to be considered. */ +Tk_ConfigureValue( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Window corresponding to widgRec. */ + Tk_ConfigSpec *specs, /* Describes legal options. */ + char *widgRec, /* Record whose fields contain current values + * for options. */ + CONST char *argvName, /* Gives the command-line name for the option + * whose value is to be returned. */ + int flags) /* Used to specify additional flags that must + * be present in config specs for them to be + * considered. */ { Tk_ConfigSpec *specPtr; int needFlags, hateFlags; @@ -959,7 +936,8 @@ Tk_ConfigureValue(interp, tkwin, specs, widgRec, argvName, flags) if (specPtr == NULL) { return TCL_ERROR; } - result = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, &freeProc); + result = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer, + &freeProc); Tcl_SetResult(interp, (char *) result, TCL_VOLATILE); if (freeProc != NULL) { if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) { @@ -982,24 +960,27 @@ Tk_ConfigureValue(interp, tkwin, specs, widgRec, argvName, flags) * None. * * Side effects: - * Any resource in widgRec that is controlled by a configuration - * option (e.g. a Tk_3DBorder or XColor) is freed in the appropriate - * fashion. + * Any resource in widgRec that is controlled by a configuration option + * (e.g. a Tk_3DBorder or XColor) is freed in the appropriate fashion. + * + * Notes: + * Since this is not looking anything up, this uses the static version of + * the config specs. * *---------------------------------------------------------------------- */ /* ARGSUSED */ void -Tk_FreeOptions(specs, widgRec, display, needFlags) - Tk_ConfigSpec *specs; /* Describes legal options. */ - char *widgRec; /* Record whose fields contain current - * values for options. */ - Display *display; /* X display; needed for freeing some +Tk_FreeOptions( + Tk_ConfigSpec *specs, /* Describes legal options. */ + char *widgRec, /* Record whose fields contain current values + * for options. */ + Display *display, /* X display; needed for freeing some * resources. */ - int needFlags; /* Used to specify additional flags - * that must be present in config specs - * for them to be considered. */ + int needFlags) /* Used to specify additional flags that must + * be present in config specs for them to be + * considered. */ { register Tk_ConfigSpec *specPtr; char *ptr; @@ -1010,40 +991,40 @@ Tk_FreeOptions(specs, widgRec, display, needFlags) } ptr = widgRec + specPtr->offset; switch (specPtr->type) { - case TK_CONFIG_STRING: - if (*((char **) ptr) != NULL) { - ckfree(*((char **) ptr)); - *((char **) ptr) = NULL; - } - break; - case TK_CONFIG_COLOR: - if (*((XColor **) ptr) != NULL) { - Tk_FreeColor(*((XColor **) ptr)); - *((XColor **) ptr) = NULL; - } - break; - case TK_CONFIG_FONT: - Tk_FreeFont(*((Tk_Font *) ptr)); - *((Tk_Font *) ptr) = NULL; - break; - case TK_CONFIG_BITMAP: - if (*((Pixmap *) ptr) != None) { - Tk_FreeBitmap(display, *((Pixmap *) ptr)); - *((Pixmap *) ptr) = None; - } - break; - case TK_CONFIG_BORDER: - if (*((Tk_3DBorder *) ptr) != NULL) { - Tk_Free3DBorder(*((Tk_3DBorder *) ptr)); - *((Tk_3DBorder *) ptr) = NULL; - } - break; - case TK_CONFIG_CURSOR: - case TK_CONFIG_ACTIVE_CURSOR: - if (*((Tk_Cursor *) ptr) != None) { - Tk_FreeCursor(display, *((Tk_Cursor *) ptr)); - *((Tk_Cursor *) ptr) = None; - } + case TK_CONFIG_STRING: + if (*((char **) ptr) != NULL) { + ckfree(*((char **) ptr)); + *((char **) ptr) = NULL; + } + break; + case TK_CONFIG_COLOR: + if (*((XColor **) ptr) != NULL) { + Tk_FreeColor(*((XColor **) ptr)); + *((XColor **) ptr) = NULL; + } + break; + case TK_CONFIG_FONT: + Tk_FreeFont(*((Tk_Font *) ptr)); + *((Tk_Font *) ptr) = NULL; + break; + case TK_CONFIG_BITMAP: + if (*((Pixmap *) ptr) != None) { + Tk_FreeBitmap(display, *((Pixmap *) ptr)); + *((Pixmap *) ptr) = None; + } + break; + case TK_CONFIG_BORDER: + if (*((Tk_3DBorder *) ptr) != NULL) { + Tk_Free3DBorder(*((Tk_3DBorder *) ptr)); + *((Tk_3DBorder *) ptr) = NULL; + } + break; + case TK_CONFIG_CURSOR: + case TK_CONFIG_ACTIVE_CURSOR: + if (*((Tk_Cursor *) ptr) != None) { + Tk_FreeCursor(display, *((Tk_Cursor *) ptr)); + *((Tk_Cursor *) ptr) = None; + } } } } @@ -1053,28 +1034,28 @@ Tk_FreeOptions(specs, widgRec, display, needFlags) * * GetCachedSpecs -- * - *Returns a writable per-interpreter (and hence thread-local) copy of - *the given spec-table with (some of) the char* fields converted into - *Tk_Uid fields; this copy will be released when the interpreter - *terminates (during AssocData cleanup). + * Returns a writable per-interpreter (and hence thread-local) copy of + * the given spec-table with (some of) the char* fields converted into + * Tk_Uid fields; this copy will be released when the interpreter + * terminates (during AssocData cleanup). * * Results: - *A pointer to the copied table. + * A pointer to the copied table. * * Notes: - *The conversion to Tk_Uid is only done the first time, when the table - *copy is taken. After that, the table is assumed to have Tk_Uids where - *they are needed. The time of deletion of the caches isn't very - *important unless you've got a lot of code that uses Tk_ConfigureWidget - *(or *Info or *Value} when the interpreter is being deleted. + * The conversion to Tk_Uid is only done the first time, when the table + * copy is taken. After that, the table is assumed to have Tk_Uids where + * they are needed. The time of deletion of the caches isn't very + * important unless you've got a lot of code that uses Tk_ConfigureWidget + * (or *Info or *Value} when the interpreter is being deleted. * *-------------------------------------------------------------- */ static Tk_ConfigSpec * -GetCachedSpecs(interp, staticSpecs) - Tcl_Interp *interp; /* Interpreter in which to store the cache. */ - const Tk_ConfigSpec *staticSpecs; +GetCachedSpecs( + Tcl_Interp *interp, /* Interpreter in which to store the cache. */ + const Tk_ConfigSpec *staticSpecs) /* Value to cache a copy of; it is also used * as a key into the cache. */ { @@ -1126,7 +1107,7 @@ GetCachedSpecs(interp, staticSpecs) */ cachedSpecs = (Tk_ConfigSpec *) ckalloc(entrySpace); - memcpy((void *) cachedSpecs, (void *) staticSpecs, entrySpace); + memcpy(cachedSpecs, staticSpecs, entrySpace); Tcl_SetHashValue(entryPtr, (ClientData) cachedSpecs); /* @@ -1147,6 +1128,7 @@ GetCachedSpecs(interp, staticSpecs) specPtr->defValue = Tk_GetUid(specPtr->defValue); } } + specPtr->specFlags &= ~TK_CONFIG_OPTION_SPECIFIED; } } else { cachedSpecs = (Tk_ConfigSpec *) Tcl_GetHashValue(entryPtr); @@ -1167,15 +1149,15 @@ GetCachedSpecs(interp, staticSpecs) * None * * Side effects: - * None + * None (does *not* use any Tk API). * *-------------------------------------------------------------- */ static void -DeleteSpecCacheTable(clientData, interp) - ClientData clientData; - Tcl_Interp *interp; +DeleteSpecCacheTable( + ClientData clientData, + Tcl_Interp *interp) { Tcl_HashTable *tablePtr = (Tcl_HashTable *) clientData; Tcl_HashEntry *entryPtr; @@ -1192,3 +1174,11 @@ DeleteSpecCacheTable(clientData, interp) Tcl_DeleteHashTable(tablePtr); ckfree((char *) tablePtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkOldTest.c b/generic/tkOldTest.c new file mode 100644 index 0000000..cfbce23 --- /dev/null +++ b/generic/tkOldTest.c @@ -0,0 +1,404 @@ +/* + * tkOldTest.c -- + * + * This file contains C command functions for additional Tcl + * commands that are used to test Tk's support for legacy + * interfaces. These commands are not normally included in Tcl/Tk + * applications; they're only used for testing. + * + * Copyright (c) 1993-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 1998-1999 by Scriptics Corporation. + * Contributions by Don Porter, NIST, 2007. (not subject to US copyright) + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#define USE_OLD_IMAGE +#include "tkInt.h" + +/* + * The following data structure represents the master for a test image: + */ + +typedef struct TImageMaster { + Tk_ImageMaster master; /* Tk's token for image master. */ + Tcl_Interp *interp; /* Interpreter for application. */ + int width, height; /* Dimensions of image. */ + char *imageName; /* Name of image (malloc-ed). */ + char *varName; /* Name of variable in which to log events for + * image (malloc-ed). */ +} TImageMaster; + +/* + * The following data structure represents a particular use of a particular + * test image. + */ + +typedef struct TImageInstance { + TImageMaster *masterPtr; /* Pointer to master for image. */ + XColor *fg; /* Foreground color for drawing in image. */ + GC gc; /* Graphics context for drawing in image. */ +} TImageInstance; + +/* + * The type record for test images: + */ + +static int ImageCreate(Tcl_Interp *interp, + char *name, int argc, char **argv, + Tk_ImageType *typePtr, Tk_ImageMaster master, + ClientData *clientDataPtr); +static ClientData ImageGet(Tk_Window tkwin, ClientData clientData); +static void ImageDisplay(ClientData clientData, + Display *display, Drawable drawable, + int imageX, int imageY, int width, + int height, int drawableX, + int drawableY); +static void ImageFree(ClientData clientData, Display *display); +static void ImageDelete(ClientData clientData); + +static Tk_ImageType imageType = { + "oldtest", /* name */ + (Tk_ImageCreateProc *) ImageCreate, /* createProc */ + ImageGet, /* getProc */ + ImageDisplay, /* displayProc */ + ImageFree, /* freeProc */ + ImageDelete, /* deleteProc */ + NULL, /* postscriptPtr */ + NULL /* nextPtr */ +}; + +/* + * Forward declarations for functions defined later in this file: + */ + +static int ImageCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); +MODULE_SCOPE int TkOldTestInit(Tcl_Interp *interp); + + +/* + *---------------------------------------------------------------------- + * + * TkOldTestInit -- + * + * This function performs intialization for the Tk test suite + * extensions for testing support for legacy interfaces. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error message in + * the interp's result if an error occurs. + * + * Side effects: + * Creates several test commands. + * + *---------------------------------------------------------------------- + */ + +int +TkOldTestInit( + Tcl_Interp *interp) +{ + static int initialized = 0; + + if (!initialized) { + initialized = 1; + Tk_CreateImageType(&imageType); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ImageCreate -- + * + * This function is called by the Tk image code to create "oldtest" images. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * The data structure for a new image is allocated. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +ImageCreate( + Tcl_Interp *interp, /* Interpreter for application containing + * image. */ + char *name, /* Name to use for image. */ + int argc, /* Number of arguments. */ + char **argv, /* Argument strings for options (doesn't + * include image name or type). */ + Tk_ImageType *typePtr, /* Pointer to our type record (not used). */ + Tk_ImageMaster master, /* Token for image, to be used by us in later + * callbacks. */ + ClientData *clientDataPtr) /* Store manager's token for image here; it + * will be returned in later callbacks. */ +{ + TImageMaster *timPtr; + char *varName; + int i; + + varName = "log"; + for (i = 0; i < argc; i += 2) { + if (strcmp(argv[i], "-variable") != 0) { + Tcl_AppendResult(interp, "bad option name \"", + argv[i], "\"", NULL); + return TCL_ERROR; + } + if ((i+1) == argc) { + Tcl_AppendResult(interp, "no value given for \"", + argv[i], "\" option", NULL); + return TCL_ERROR; + } + varName = argv[i+1]; + } + + timPtr = (TImageMaster *) ckalloc(sizeof(TImageMaster)); + timPtr->master = master; + timPtr->interp = interp; + timPtr->width = 30; + timPtr->height = 15; + timPtr->imageName = (char *) ckalloc((unsigned) (strlen(name) + 1)); + strcpy(timPtr->imageName, name); + timPtr->varName = (char *) ckalloc((unsigned) (strlen(varName) + 1)); + strcpy(timPtr->varName, varName); + Tcl_CreateCommand(interp, name, ImageCmd, (ClientData) timPtr, NULL); + *clientDataPtr = (ClientData) timPtr; + Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ImageCmd -- + * + * This function implements the commands corresponding to individual + * images. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Forces windows to be created. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static int +ImageCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ +{ + TImageMaster *timPtr = (TImageMaster *) clientData; + int x, y, width, height; + + if (argc < 2) { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], "option ?arg arg ...?", NULL); + return TCL_ERROR; + } + if (strcmp(argv[1], "changed") == 0) { + if (argc != 8) { + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " changed x y width height imageWidth imageHeight", NULL); + return TCL_ERROR; + } + if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) + || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) + || (Tcl_GetInt(interp, argv[4], &width) != TCL_OK) + || (Tcl_GetInt(interp, argv[5], &height) != TCL_OK) + || (Tcl_GetInt(interp, argv[6], &timPtr->width) != TCL_OK) + || (Tcl_GetInt(interp, argv[7], &timPtr->height) != TCL_OK)) { + return TCL_ERROR; + } + Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width, + timPtr->height); + } else { + Tcl_AppendResult(interp, "bad option \"", argv[1], + "\": must be changed", NULL); + return TCL_ERROR; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * ImageGet -- + * + * This function is called by Tk to set things up for using a test image + * in a particular widget. + * + * Results: + * The return value is a token for the image instance, which is used in + * future callbacks to ImageDisplay and ImageFree. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static ClientData +ImageGet( + Tk_Window tkwin, /* Token for window in which image will be + * used. */ + ClientData clientData) /* Pointer to TImageMaster for image. */ +{ + TImageMaster *timPtr = (TImageMaster *) clientData; + TImageInstance *instPtr; + char buffer[100]; + XGCValues gcValues; + + sprintf(buffer, "%s get", timPtr->imageName); + Tcl_SetVar(timPtr->interp, timPtr->varName, buffer, + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + + instPtr = (TImageInstance *) ckalloc(sizeof(TImageInstance)); + instPtr->masterPtr = timPtr; + instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000"); + gcValues.foreground = instPtr->fg->pixel; + instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues); + return (ClientData) instPtr; +} + +/* + *---------------------------------------------------------------------- + * + * ImageDisplay -- + * + * This function is invoked to redisplay part or all of an image in a + * given drawable. + * + * Results: + * None. + * + * Side effects: + * The image gets partially redrawn, as an "X" that shows the exact + * redraw area. + * + *---------------------------------------------------------------------- + */ + +static void +ImageDisplay( + ClientData clientData, /* Pointer to TImageInstance for image. */ + Display *display, /* Display to use for drawing. */ + Drawable drawable, /* Where to redraw image. */ + int imageX, int imageY, /* Origin of area to redraw, relative to + * origin of image. */ + int width, int height, /* Dimensions of area to redraw. */ + int drawableX, int drawableY) + /* Coordinates in drawable corresponding to + * imageX and imageY. */ +{ + TImageInstance *instPtr = (TImageInstance *) clientData; + 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); + Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer, + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + if (width > (instPtr->masterPtr->width - imageX)) { + width = instPtr->masterPtr->width - imageX; + } + if (height > (instPtr->masterPtr->height - imageY)) { + height = instPtr->masterPtr->height - imageY; + } + XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY, + (unsigned) (width-1), (unsigned) (height-1)); + XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY, + (int) (drawableX + width - 1), (int) (drawableY + height - 1)); + XDrawLine(display, drawable, instPtr->gc, drawableX, + (int) (drawableY + height - 1), + (int) (drawableX + width - 1), drawableY); +} + +/* + *---------------------------------------------------------------------- + * + * ImageFree -- + * + * This function is called when an instance of an image is no longer + * used. + * + * Results: + * None. + * + * Side effects: + * Information related to the instance is freed. + * + *---------------------------------------------------------------------- + */ + +static void +ImageFree( + ClientData clientData, /* Pointer to TImageInstance for instance. */ + Display *display) /* Display where image was to be drawn. */ +{ + TImageInstance *instPtr = (TImageInstance *) clientData; + char buffer[200]; + + sprintf(buffer, "%s free", instPtr->masterPtr->imageName); + Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer, + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + Tk_FreeColor(instPtr->fg); + Tk_FreeGC(display, instPtr->gc); + ckfree((char *) instPtr); +} + +/* + *---------------------------------------------------------------------- + * + * ImageDelete -- + * + * This function is called to clean up a test image when an application + * goes away. + * + * Results: + * None. + * + * Side effects: + * Information about the image is deleted. + * + *---------------------------------------------------------------------- + */ + +static void +ImageDelete( + ClientData clientData) /* Pointer to TImageMaster for image. When + * this function is called, no more instances + * exist. */ +{ + TImageMaster *timPtr = (TImageMaster *) clientData; + char buffer[100]; + + sprintf(buffer, "%s delete", timPtr->imageName); + Tcl_SetVar(timPtr->interp, timPtr->varName, buffer, + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + + Tcl_DeleteCommand(timPtr->interp, timPtr->imageName); + ckfree(timPtr->imageName); + ckfree(timPtr->varName); + ckfree((char *) timPtr); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkOption.c b/generic/tkOption.c index 0df3f8d..de92627 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.c @@ -1,93 +1,90 @@ -/* +/* * tkOption.c -- * - * This module contains procedures to manage the option - * database, which allows various strings to be associated - * with windows either by name or by class or both. + * This module contains functions to manage the option database, which + * allows various strings to be associated with windows either by name or + * by class or both. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" /* - * The option database is stored as one tree for each main window. - * Each name or class field in an option is associated with a node or - * leaf of the tree. For example, the options "x.y.z" and "x.y*a" - * each correspond to three nodes in the tree; they share the nodes - * "x" and "x.y", but have different leaf nodes. One of the following - * structures exists for each node or leaf in the option tree. It is - * actually stored as part of the parent node, and describes a particular - * child of the parent. - * - * The structure of the option db tree is a little confusing. There are - * four different kinds of nodes in the tree: + * The option database is stored as one tree for each main window. Each name + * or class field in an option is associated with a node or leaf of the tree. + * For example, the options "x.y.z" and "x.y*a" each correspond to three nodes + * in the tree; they share the nodes "x" and "x.y", but have different leaf + * nodes. One of the following structures exists for each node or leaf in the + * option tree. It is actually stored as part of the parent node, and + * describes a particular child of the parent. + * + * The structure of the option db tree is a little confusing. There are four + * different kinds of nodes in the tree: * interior class nodes * interior name nodes * leaf class nodes * leaf name nodes * * All interior nodes refer to _window_ classes and names; all leaf nodes - * refer to _option_ classes and names. When looking for a particular option, + * refer to _option_ classes and names. When looking for a particular option, * therefore, you must compare interior node values to corresponding window * values, and compare leaf node values to corresponding option values. * * The tree is actually stored in a collection of arrays; there is one each - * combination of WILDCARD/EXACT and CLASS/NAME and NODE/LEAF. The NODE arrays + * combination of WILDCARD/EXACT and CLASS/NAME and NODE/LEAF. The NODE arrays * contain the interior nodes of the tree; each element has a pointer to an - * array of elements which are the leaves of the tree. The LEAF arrays, rather + * array of elements which are the leaves of the tree. The LEAF arrays, rather * than holding the leaves of the tree, hold a cached subset of the option * database, consisting of the values of all defined options for a single * window, and some additional information about each ancestor of the window - * (since some options may be inherited from a parent), all the way back to the - * root window. + * (since some options may be inherited from a parent), all the way back to + * the root window. * * Each time a call is made to Tk_GetOption, Tk will attempt to use the cached - * information to satisfy the lookup. If the call is for a window other than + * information to satisfy the lookup. If the call is for a window other than * that for which options are currently cached, the portion of the cache that - * contains information for common ancestors of the two windows is retained and - * the remainder is discarded and rebuilt with new information for the new + * contains information for common ancestors of the two windows is retained + * and the remainder is discarded and rebuilt with new information for the new * window. */ typedef struct Element { - Tk_Uid nameUid; /* Name or class from one element of - * an option spec. */ + Tk_Uid nameUid; /* Name or class from one element of an option + * spec. */ union { - struct ElArray *arrayPtr; /* If this is an intermediate node, - * a pointer to a structure describing - * the remaining elements of all - * options whose prefixes are the - * same up through this element. */ - Tk_Uid valueUid; /* For leaf nodes, this is the string - * value of the option. */ + struct ElArray *arrayPtr; + /* If this is an intermediate node, a pointer + * to a structure describing the remaining + * elements of all options whose prefixes are + * the same up through this element. */ + Tk_Uid valueUid; /* For leaf nodes, this is the string value of + * the option. */ } child; - int priority; /* Used to select among matching - * options. Includes both the - * priority level and a serial #. - * Greater value means higher - * priority. Irrelevant except in - * leaf nodes. */ - int flags; /* OR-ed combination of bits. See - * below for values. */ + int priority; /* Used to select among matching options. + * Includes both the priority level and a + * serial #. Greater value means higher + * priority. Irrelevant except in leaf + * nodes. */ + int flags; /* OR-ed combination of bits. See below for + * values. */ } Element; /* * Flags in Element structures: * - * CLASS - Non-zero means this element refers to a class, - * Zero means this element refers to a name. - * NODE - Zero means this is a leaf element (the child - * field is a value, not a pointer to another node). - * One means this is a node element. - * WILDCARD - Non-zero means this there was a star in the - * original specification just before this element. - * Zero means there was a dot. + * CLASS - Non-zero means this element refers to a class, zero + * means this element refers to a name. + * NODE - Zero means this is a leaf element (the child field is + * a value, not a pointer to another node). One means + * this is a node element. + * WILDCARD - Non-zero means this there was a star in the original + * specification just before this element. Zero means + * there was a dot. */ #define TYPE_MASK 0x7 @@ -106,25 +103,22 @@ typedef struct Element { #define WILDCARD_NODE_CLASS 0x7 /* - * The following structure is used to manage a dynamic array of - * Elements. These structures are used for two purposes: to store - * the contents of a node in the option tree, and for the option - * stacks described below. + * The following structure is used to manage a dynamic array of Elements. + * These structures are used for two purposes: to store the contents of a node + * in the option tree, and for the option stacks described below. */ typedef struct ElArray { - int arraySize; /* Number of elements actually - * allocated in the "els" array. */ - int numUsed; /* Number of elements currently in - * use out of els. */ + int arraySize; /* Number of elements actually allocated in + * the "els" array. */ + int numUsed; /* Number of elements currently in use out of + * els. */ Element *nextToUse; /* Pointer to &els[numUsed]. */ - Element els[1]; /* Array of structures describing - * children of this node. The - * array will actually contain enough - * elements for all of the children - * (and even a few extras, perhaps). - * This must be the last field in - * the structure. */ + Element els[1]; /* Array of structures describing children of + * this node. The array will actually contain + * enough elements for all of the children + * (and even a few extras, perhaps). This must + * be the last field in the structure. */ } ElArray; #define EL_ARRAY_SIZE(numEls) ((unsigned) (sizeof(ElArray) \ @@ -133,114 +127,104 @@ typedef struct ElArray { /* * In addition to the option tree, which is a relatively static structure, - * there are eight additional structures called "stacks", which are used - * to speed up queries into the option database. The stack structures - * are designed for the situation where an individual widget makes repeated - * requests for its particular options. The requests differ only in - * their last name/class, so during the first request we extract all - * the options pertaining to the particular widget and save them in a - * stack-like cache; subsequent requests for the same widget can search - * the cache relatively quickly. In fact, the cache is a hierarchical - * one, storing a list of relevant options for this widget and all of - * its ancestors up to the application root; hence the name "stack". - * - * Each of the eight stacks consists of an array of Elements, ordered in - * terms of levels in the window hierarchy. All the elements relevant - * for the top-level widget appear first in the array, followed by all - * those from the next-level widget on the path to the current widget, - * etc. down to those for the current widget. - * - * Cached information is divided into eight stacks according to the - * CLASS, NODE, and WILDCARD flags. Leaf and non-leaf information is - * kept separate to speed up individual probes (non-leaf information is - * only relevant when building the stacks, but isn't relevant when - * making probes; similarly, only non-leaf information is relevant - * when the stacks are being extended to the next widget down in the - * widget hierarchy). Wildcard elements are handled separately from - * "exact" elements because once they appear at a particular level in - * the stack they remain active for all deeper levels; exact elements - * are only relevant at a particular level. For example, when searching - * for options relevant in a particular window, the entire wildcard - * stacks get checked, but only the portions of the exact stacks that - * pertain to the window's parent. Lastly, name and class stacks are - * kept separate because different search keys are used when searching - * them; keeping them separate speeds up the searches. + * there are eight additional structures called "stacks", which are used to + * speed up queries into the option database. The stack structures are + * designed for the situation where an individual widget makes repeated + * requests for its particular options. The requests differ only in their last + * name/class, so during the first request we extract all the options + * pertaining to the particular widget and save them in a stack-like cache; + * subsequent requests for the same widget can search the cache relatively + * quickly. In fact, the cache is a hierarchical one, storing a list of + * relevant options for this widget and all of its ancestors up to the + * application root; hence the name "stack". + * + * Each of the eight stacks consists of an array of Elements, ordered in terms + * of levels in the window hierarchy. All the elements relevant for the + * top-level widget appear first in the array, followed by all those from the + * next-level widget on the path to the current widget, etc. down to those for + * the current widget. + * + * Cached information is divided into eight stacks according to the CLASS, + * NODE, and WILDCARD flags. Leaf and non-leaf information is kept separate to + * speed up individual probes (non-leaf information is only relevant when + * building the stacks, but isn't relevant when making probes; similarly, only + * non-leaf information is relevant when the stacks are being extended to the + * next widget down in the widget hierarchy). Wildcard elements are handled + * separately from "exact" elements because once they appear at a particular + * level in the stack they remain active for all deeper levels; exact elements + * are only relevant at a particular level. For example, when searching for + * options relevant in a particular window, the entire wildcard stacks get + * checked, but only the portions of the exact stacks that pertain to the + * window's parent. Lastly, name and class stacks are kept separate because + * different search keys are used when searching them; keeping them separate + * speeds up the searches. */ #define NUM_STACKS 8 /* - * One of the following structures is used to keep track of each - * level in the stacks. + * One of the following structures is used to keep track of each level in the + * stacks. */ typedef struct StackLevel { TkWindow *winPtr; /* Window corresponding to this stack * level. */ - int bases[NUM_STACKS]; /* For each stack, index of first - * element on stack corresponding to - * this level (used to restore "numUsed" - * fields when popping out of a level. */ + int bases[NUM_STACKS]; /* For each stack, index of first element on + * stack corresponding to this level (used to + * restore "numUsed" fields when popping out + * of a level. */ } StackLevel; typedef struct ThreadSpecificData { - int initialized; /* 0 means the ThreadSpecific Data structure + int initialized; /* 0 means the ThreadSpecific Data structure * for the current thread needs to be * initialized. */ ElArray *stacks[NUM_STACKS]; - TkWindow *cachedWindow; - /* Lowest-level window currently - * loaded in stacks at present. - * NULL means stacks have never - * been used, or have been - * invalidated because of a change - * to the database. */ + TkWindow *cachedWindow; /* Lowest-level window currently loaded in + * stacks at present. NULL means stacks have + * never been used, or have been invalidated + * because of a change to the database. */ /* - * Information about all of the stack levels that are currently - * active. This array grows dynamically to become as large as needed. + * Information about all of the stack levels that are currently active. + * This array grows dynamically to become as large as needed. */ - StackLevel *levels; /* Array describing current stack. */ - int numLevels; /* Total space allocated. */ - int curLevel; /* Highest level currently in use. Note: - * curLevel is never 0! (I don't remember - * why anymore...) */ - /* - * The variable below is a serial number for all options entered into - * the database so far. It increments on each addition to the option - * database. It is used in computing option priorities, so that the - * most recent entry wins when choosing between options at the same - * priority level. - */ - - int serial; - Element defaultMatch; /* Special "no match" Element to use as + StackLevel *levels; /* Array describing current stack. */ + int numLevels; /* Total space allocated. */ + int curLevel; /* Highest level currently in use. Note: + * curLevel is never 0! (I don't remember why + * anymore...) */ + int serial; /* A serial number for all options entered + * into the database so far. It increments on + * each addition to the option database. It is + * used in computing option priorities, so + * that the most recent entry wins when + * choosing between options at the same + * priority level. */ + Element defaultMatch; /* Special "no match" Element to use as * default for searches.*/ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static int AddFromString _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, char *string, int priority)); -static void ClearOptionTree _ANSI_ARGS_((ElArray *arrayPtr)); -static ElArray * ExtendArray _ANSI_ARGS_((ElArray *arrayPtr, - Element *elPtr)); -static void ExtendStacks _ANSI_ARGS_((ElArray *arrayPtr, - int leaf)); -static int GetDefaultOptions _ANSI_ARGS_((Tcl_Interp *interp, - TkWindow *winPtr)); -static ElArray * NewArray _ANSI_ARGS_((int numEls)); -static void OptionThreadExitProc _ANSI_ARGS_(( - ClientData clientData)); -static void OptionInit _ANSI_ARGS_((TkMainInfo *mainPtr)); -static int ParsePriority _ANSI_ARGS_((Tcl_Interp *interp, - char *string)); -static int ReadOptionFile _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, char *fileName, int priority)); -static void SetupStacks _ANSI_ARGS_((TkWindow *winPtr, int leaf)); +static int AddFromString(Tcl_Interp *interp, Tk_Window tkwin, + char *string, int priority); +static void ClearOptionTree(ElArray *arrayPtr); +static ElArray * ExtendArray(ElArray *arrayPtr, Element *elPtr); +static void ExtendStacks(ElArray *arrayPtr, int leaf); +static int GetDefaultOptions(Tcl_Interp *interp, + TkWindow *winPtr); +static ElArray * NewArray(int numEls); +static void OptionThreadExitProc(ClientData clientData); +static void OptionInit(TkMainInfo *mainPtr); +static int ParsePriority(Tcl_Interp *interp, char *string); +static int ReadOptionFile(Tcl_Interp *interp, Tk_Window tkwin, + char *fileName, int priority); +static void SetupStacks(TkWindow *winPtr, int leaf); /* *-------------------------------------------------------------- @@ -259,15 +243,15 @@ static void SetupStacks _ANSI_ARGS_((TkWindow *winPtr, int leaf)); */ void -Tk_AddOption(tkwin, name, value, priority) - Tk_Window tkwin; /* Window token; option will be associated +Tk_AddOption( + Tk_Window tkwin, /* Window token; option will be associated * with main window for this window. */ - CONST char *name; /* Multi-element name of option. */ - CONST char *value; /* String value for option. */ - int priority; /* Overall priority level to use for - * this option, such as TK_USER_DEFAULT_PRIO - * or TK_INTERACTIVE_PRIO. Must be between - * 0 and TK_MAX_PRIO. */ + CONST char *name, /* Multi-element name of option. */ + CONST char *value, /* String value for option. */ + int priority) /* Overall priority level to use for this + * option, such as TK_USER_DEFAULT_PRIO or + * TK_INTERACTIVE_PRIO. Must be between 0 and + * TK_MAX_PRIO. */ { TkWindow *winPtr = ((TkWindow *) tkwin)->mainPtr->winPtr; register ElArray **arrayPtrPtr; @@ -275,21 +259,21 @@ Tk_AddOption(tkwin, name, value, priority) Element newEl; register CONST char *p; CONST char *field; - int count, firstField, length; + int count, firstField; + ptrdiff_t length; #define TMP_SIZE 100 char tmp[TMP_SIZE+1]; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->mainPtr->optionRootPtr == NULL) { OptionInit(winPtr->mainPtr); } - tsdPtr->cachedWindow = NULL; /* Invalidate the cache. */ + tsdPtr->cachedWindow = NULL;/* Invalidate the cache. */ /* - * Compute the priority for the new element, including both the - * overall level and the serial number (to disambiguate with the - * level). + * Compute the priority for the new element, including both the overall + * level and the serial number (to disambiguate with the level). */ if (priority < 0) { @@ -307,11 +291,10 @@ Tk_AddOption(tkwin, name, value, priority) arrayPtrPtr = &(((TkWindow *) tkwin)->mainPtr->optionRootPtr); p = name; for (firstField = 1; ; firstField = 0) { - /* - * Scan the next field from the name and convert it to a Tk_Uid. - * Must copy the field before calling Tk_Uid, so that a terminating - * NULL may be added without modifying the source string. + * Scan the next field from the name and convert it to a Tk_Uid. Must + * copy the field before calling Tk_Uid, so that a terminating NULL + * may be added without modifying the source string. */ if (*p == '*') { @@ -336,12 +319,10 @@ Tk_AddOption(tkwin, name, value, priority) } if (*p != 0) { - /* - * New element will be a node. If this option can't possibly - * apply to this main window, then just skip it. Otherwise, - * add it to the parent, if it isn't already there, and descend - * into it. + * New element will be a node. If this option can't possibly apply + * to this main window, then just skip it. Otherwise, add it to + * the parent, if it isn't already there, and descend into it. */ newEl.flags |= NODE; @@ -355,7 +336,8 @@ Tk_AddOption(tkwin, name, value, priority) if (count == 0) { newEl.child.arrayPtr = NewArray(5); *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl); - arrayPtrPtr = &((*arrayPtrPtr)->nextToUse[-1].child.arrayPtr); + arrayPtrPtr = &((*arrayPtrPtr) + ->nextToUse[-1].child.arrayPtr); break; } if ((elPtr->nameUid == newEl.nameUid) @@ -368,11 +350,10 @@ Tk_AddOption(tkwin, name, value, priority) p++; } } else { - /* - * New element is a leaf. Add it to the parent, if it isn't - * already there. If it exists already, keep whichever value - * has highest priority. + * New element is a leaf. Add it to the parent, if it isn't + * already there. If it exists already, keep whichever value has + * highest priority. */ newEl.child.valueUid = Tk_GetUid(value); @@ -403,27 +384,26 @@ Tk_AddOption(tkwin, name, value, priority) * Retrieve an option from the option database. * * Results: - * The return value is the value specified in the option - * database for the given name and class on the given - * window. If there is nothing specified in the database - * for that option, then NULL is returned. + * The return value is the value specified in the option database for the + * given name and class on the given window. If there is nothing + * specified in the database for that option, then NULL is returned. * * Side effects: - * The internal caches used to speed up option mapping - * may be modified, if this tkwin is different from the - * last tkwin used for option retrieval. + * The internal caches used to speed up option mapping may be modified, + * if this tkwin is different from the last tkwin used for option + * retrieval. * *-------------------------------------------------------------- */ Tk_Uid -Tk_GetOption(tkwin, name, className) - Tk_Window tkwin; /* Token for window that option is - * associated with. */ - CONST char *name; /* Name of option. */ - CONST char *className; /* Class of option. NULL means there - * is no class for this option: just - * check for name. */ +Tk_GetOption( + Tk_Window tkwin, /* Token for window that option is associated + * with. */ + CONST char *name, /* Name of option. */ + CONST char *className) /* Class of option. NULL means there is no + * class for this option: just check for + * name. */ { Tk_Uid nameId, classId = NULL; char *masqName; @@ -431,12 +411,12 @@ Tk_GetOption(tkwin, name, className) register int count; StackLevel *levelPtr; int stackDepth[NUM_STACKS]; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * Note: no need to call OptionInit here: it will be done by - * the SetupStacks call below (squeeze out those nanoseconds). + * Note: no need to call OptionInit here: it will be done by the + * SetupStacks call below (squeeze out those nanoseconds). */ if (tkwin != (Tk_Window) tsdPtr->cachedWindow) { @@ -446,32 +426,33 @@ Tk_GetOption(tkwin, name, className) /* * Get a default "best" match. */ - + bestPtr = &tsdPtr->defaultMatch; /* * For megawidget support, we want to have some widget options masquerade - * as options for other widgets. For example, a combobox has a button in + * as options for other widgets. For example, a combobox has a button in * it; this button ought to pick up the *Button.background, etc., options. * But because the class of the widget is Combobox, our normal search * won't get that option. * * To work around this, the option name field syntax was extended to allow * for a "." in the name; if this character occurs in the name, then it - * indicates that this name contains a new window class and an option name, - * ie, "Button.foreground". If we see this form in the name field, we - * query the option database directly (since the option stacks will not + * indicates that this name contains a new window class and an option + * name, ie, "Button.foreground". If we see this form in the name field, + * we query the option database directly (since the option stacks will not * have the information we need). */ masqName = strchr(name, (int)'.'); if (masqName != NULL) { /* - * This option is masquerading with a different window class. - * Search the stack to the depth it was before the current window's + * This option is masquerading with a different window class. Search + * the stack to the depth it was before the current window's * information was pushed (the value for which is stored in the bases * field). */ + levelPtr = &tsdPtr->levels[tsdPtr->curLevel]; nameId = Tk_GetUid(masqName+1); for (count = 0; count < NUM_STACKS; count++) { @@ -479,9 +460,10 @@ Tk_GetOption(tkwin, name, className) } } else { /* - * No option masquerading here. Just use the current level to get the + * No option masquerading here. Just use the current level to get the * stack depths. */ + nameId = Tk_GetUid(name); for (count = 0; count < NUM_STACKS; count++) { stackDepth[count] = tsdPtr->stacks[count]->numUsed; @@ -528,11 +510,11 @@ Tk_GetOption(tkwin, name, className) } } } - + /* - * If this option was masquerading with a different window class, - * probe the option database now. Note that this will be inefficient - * if the option database is densely populated, or if the widget has many + * If this option was masquerading with a different window class, probe + * the option database now. Note that this will be inefficient if the + * option database is densely populated, or if the widget has many * masquerading options. */ @@ -541,43 +523,42 @@ Tk_GetOption(tkwin, name, className) Tk_Uid nodeId, winClassId, winNameId; unsigned int classNameLength; register Element *nodePtr, *leafPtr; - static int searchOrder[] = { EXACT_NODE_NAME, - WILDCARD_NODE_NAME, - EXACT_NODE_CLASS, - WILDCARD_NODE_CLASS, - -1 }; + static int searchOrder[] = { + EXACT_NODE_NAME, WILDCARD_NODE_NAME, EXACT_NODE_CLASS, + WILDCARD_NODE_CLASS, -1 + }; int *currentPtr, currentStack, leafCount; - + /* * Extract the masquerade class name from the name field. */ - + classNameLength = (unsigned int)(masqName - name); - masqClass = (char *)ckalloc(classNameLength + 1); + masqClass = (char *) ckalloc(classNameLength + 1); strncpy(masqClass, name, classNameLength); masqClass[classNameLength] = '\0'; - - winClassId = Tk_GetUid(masqClass); + + winClassId = Tk_GetUid(masqClass); ckfree(masqClass); - winNameId = ((TkWindow *)tkwin)->nameUid; + winNameId = ((TkWindow *)tkwin)->nameUid; levelPtr = &tsdPtr->levels[tsdPtr->curLevel]; for (currentPtr = searchOrder; *currentPtr != -1; currentPtr++) { currentStack = *currentPtr; - nodePtr = tsdPtr->stacks[currentStack]->els; - count = levelPtr->bases[currentStack]; + nodePtr = tsdPtr->stacks[currentStack]->els; + count = levelPtr->bases[currentStack]; /* - * For wildcard stacks, check all entries; for non-wildcard + * For wildcard stacks, check all entries; for non-wildcard * stacks, only check things that matched in the parent. */ - + if (!(currentStack & WILDCARD)) { nodePtr += levelPtr[-1].bases[currentStack]; count -= levelPtr[-1].bases[currentStack]; } - + if (currentStack && CLASS) { nodeId = winClassId; } else { @@ -586,8 +567,8 @@ Tk_GetOption(tkwin, name, className) for ( ; count > 0; nodePtr++, count--) { if (nodePtr->nameUid == nodeId) { - leafPtr = nodePtr->child.arrayPtr->els; - leafCount = nodePtr->child.arrayPtr->numUsed; + leafPtr = nodePtr->child.arrayPtr->els; + leafCount = nodePtr->child.arrayPtr->numUsed; for ( ; leafCount > 0; leafPtr++, leafCount--) { if (leafPtr->flags & CLASS && className != NULL) { if (leafPtr->nameUid == classId && @@ -605,7 +586,7 @@ Tk_GetOption(tkwin, name, className) } } } - + return bestPtr->child.valueUid; } @@ -614,8 +595,8 @@ Tk_GetOption(tkwin, name, className) * * Tk_OptionObjCmd -- * - * This procedure is invoked to process the "option" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "option" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -627,17 +608,16 @@ Tk_GetOption(tkwin, name, className) */ int -Tk_OptionObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of Tcl_Obj arguments. */ - Tcl_Obj *CONST objv[]; /* Tcl_Obj arguments. */ +Tk_OptionObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of Tcl_Obj arguments. */ + Tcl_Obj *CONST objv[]) /* Tcl_Obj arguments. */ { Tk_Window tkwin = (Tk_Window) clientData; int index, result; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); static CONST char *optionCmds[] = { "add", "clear", "get", "readfile", NULL @@ -657,85 +637,85 @@ Tk_OptionObjCmd(clientData, interp, objc, objv) if (result != TCL_OK) { return result; } - + result = TCL_OK; switch ((enum optionVals) index) { - case OPTION_ADD: { - int priority; - if ((objc != 4) && (objc != 5)) { - Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?"); + case OPTION_ADD: { + int priority; + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?"); + return TCL_ERROR; + } + + if (objc == 4) { + priority = TK_INTERACTIVE_PRIO; + } else { + priority = ParsePriority(interp, Tcl_GetString(objv[4])); + if (priority < 0) { return TCL_ERROR; } + } + Tk_AddOption(tkwin, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]), + priority); + break; + } - if (objc == 4) { - priority = TK_INTERACTIVE_PRIO; - } else { - priority = ParsePriority(interp, Tcl_GetString(objv[4])); - if (priority < 0) { - return TCL_ERROR; - } - } - Tk_AddOption(tkwin, Tcl_GetString(objv[2]), - Tcl_GetString(objv[3]), priority); - break; + case OPTION_CLEAR: { + TkMainInfo *mainPtr; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + mainPtr = ((TkWindow *) tkwin)->mainPtr; + if (mainPtr->optionRootPtr != NULL) { + ClearOptionTree(mainPtr->optionRootPtr); + mainPtr->optionRootPtr = NULL; } + tsdPtr->cachedWindow = NULL; + break; + } - case OPTION_CLEAR: { - TkMainInfo *mainPtr; + case OPTION_GET: { + Tk_Window window; + Tk_Uid value; - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - mainPtr = ((TkWindow *) tkwin)->mainPtr; - if (mainPtr->optionRootPtr != NULL) { - ClearOptionTree(mainPtr->optionRootPtr); - mainPtr->optionRootPtr = NULL; - } - tsdPtr->cachedWindow = NULL; - break; + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "window name class"); + return TCL_ERROR; + } + window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); + if (window == NULL) { + return TCL_ERROR; } + value = Tk_GetOption(window, Tcl_GetString(objv[3]), + Tcl_GetString(objv[4])); + if (value != NULL) { + Tcl_SetResult(interp, (char *)value, TCL_STATIC); + } + break; + } - case OPTION_GET: { - Tk_Window window; - Tk_Uid value; - - if (objc != 5) { - Tcl_WrongNumArgs(interp, 2, objv, "window name class"); - return TCL_ERROR; - } - window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); - if (window == NULL) { - return TCL_ERROR; - } - value = Tk_GetOption(window, Tcl_GetString(objv[3]), - Tcl_GetString(objv[4])); - if (value != NULL) { - Tcl_SetResult(interp, (char *)value, TCL_STATIC); - } - break; + case OPTION_READFILE: { + int priority; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?"); + return TCL_ERROR; } - case OPTION_READFILE: { - int priority; - - if ((objc != 3) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?"); + if (objc == 4) { + priority = ParsePriority(interp, Tcl_GetString(objv[3])); + if (priority < 0) { return TCL_ERROR; } - - if (objc == 4) { - priority = ParsePriority(interp, Tcl_GetString(objv[3])); - if (priority < 0) { - return TCL_ERROR; - } - } else { - priority = TK_INTERACTIVE_PRIO; - } - result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]), - priority); - break; + } else { + priority = TK_INTERACTIVE_PRIO; } + result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]), + priority); + break; + } } return result; } @@ -745,33 +725,31 @@ Tk_OptionObjCmd(clientData, interp, objc, objv) * * TkOptionDeadWindow -- * - * This procedure is called whenever a window is deleted. - * It cleans up any option-related stuff associated with - * the window. + * This function is called whenever a window is deleted. It cleans up any + * option-related stuff associated with the window. * * Results: * None. * * Side effects: - * Option-related resources are freed. See code below - * for details. + * Option-related resources are freed. See code below for details. * *-------------------------------------------------------------- */ void -TkOptionDeadWindow(winPtr) - register TkWindow *winPtr; /* Window to be cleaned up. */ +TkOptionDeadWindow( + register TkWindow *winPtr) /* Window to be cleaned up. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * If this window is in the option stacks, then clear the stacks. * * XXX: OptionThreadExitProc will be invoked before DeleteWindowsExitProc * XXX: if it is thread-specific (which it should be), invalidating the - * XXX: tsd. Tk shutdown needs to be verified to handle this correctly. + * XXX: tsd. Tk shutdown needs to be verified to handle this correctly. */ if (tsdPtr->initialized && (winPtr->optionLevel != -1)) { @@ -785,8 +763,7 @@ TkOptionDeadWindow(winPtr) } /* - * If this window was a main window, then delete its option - * database. + * If this window was a main window, then delete its option database. */ if ((winPtr->mainPtr != NULL) && (winPtr->mainPtr->winPtr == winPtr) @@ -801,10 +778,9 @@ TkOptionDeadWindow(winPtr) * * TkOptionClassChanged -- * - * This procedure is invoked when a window's class changes. If - * the window is on the option cache, this procedure flushes - * any information for the window, since the new class could change - * what is relevant. + * This function is invoked when a window's class changes. If the window + * is on the option cache, this function flushes any information for the + * window, since the new class could change what is relevant. * * Results: * None. @@ -816,21 +792,21 @@ TkOptionDeadWindow(winPtr) */ void -TkOptionClassChanged(winPtr) - TkWindow *winPtr; /* Window whose class changed. */ +TkOptionClassChanged( + TkWindow *winPtr) /* Window whose class changed. */ { int i, j, *basePtr; ElArray *arrayPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->optionLevel == -1) { return; } /* - * Find the lowest stack level that refers to this window, then - * flush all of the levels above the matching one. + * Find the lowest stack level that refers to this window, then flush all + * of the levels above the matching one. */ for (i = 1; i <= tsdPtr->curLevel; i++) { @@ -863,9 +839,9 @@ TkOptionClassChanged(winPtr) * Parse a string priority value. * * Results: - * The return value is the integer priority level corresponding - * to string, or -1 if string doesn't point to a valid priority level. - * In this case, an error message is left in the interp's result. + * The return value is the integer priority level corresponding to + * string, or -1 if string doesn't point to a valid priority level. In + * this case, an error message is left in the interp's result. * * Side effects: * None. @@ -874,9 +850,9 @@ TkOptionClassChanged(winPtr) */ static int -ParsePriority(interp, string) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - char *string; /* Describes a priority level, either +ParsePriority( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + char *string) /* Describes a priority level, either * symbolically or numerically. */ { int priority, c; @@ -902,10 +878,9 @@ ParsePriority(interp, string) priority = strtoul(string, &end, 0); if ((end == string) || (*end != 0) || (priority < 0) || (priority > 100)) { - Tcl_AppendResult(interp, "bad priority level \"", string, + Tcl_AppendResult(interp, "bad priority level \"", string, "\": must be widgetDefault, startupFile, userDefault, ", - "interactive, or a number between 0 and 100", - (char *) NULL); + "interactive, or a number between 0 and 100", NULL); return -1; } } @@ -917,17 +892,17 @@ ParsePriority(interp, string) * * AddFromString -- * - * Given a string containing lines in the standard format for - * X resources (see other documentation for details on what this - * is), parse the resource specifications and enter them as options - * for tkwin's main window. + * Given a string containing lines in the standard format for X resources + * (see other documentation for details on what this is), parse the + * resource specifications and enter them as options for tkwin's main + * window. * * Results: - * The return value is a standard Tcl return code. In the case of - * an error in parsing string, TCL_ERROR will be returned and an - * error message will be left in the interp's result. The memory at - * string is totally trashed by this procedure. If you care about - * its contents, make a copy before calling here. + * The return value is a standard Tcl return code. In the case of an + * error in parsing string, TCL_ERROR will be returned and an error + * message will be left in the interp's result. The memory at string is + * totally trashed by this function. If you care about its contents, make + * a copy before calling here. * * Side effects: * None. @@ -936,15 +911,15 @@ ParsePriority(interp, string) */ static int -AddFromString(interp, tkwin, string, priority) - Tcl_Interp *interp; /* Interpreter to use for reporting results. */ - Tk_Window tkwin; /* Token for window: options are entered - * for this window's main window. */ - char *string; /* String containing option specifiers. */ - int priority; /* Priority level to use for options in - * this string, such as TK_USER_DEFAULT_PRIO - * or TK_INTERACTIVE_PRIO. Must be between - * 0 and TK_MAX_PRIO. */ +AddFromString( + Tcl_Interp *interp, /* Interpreter to use for reporting results. */ + Tk_Window tkwin, /* Token for window: options are entered for + * this window's main window. */ + char *string, /* String containing option specifiers. */ + int priority) /* Priority level to use for options in this + * string, such as TK_USER_DEFAULT_PRIO or + * TK_INTERACTIVE_PRIO. Must be between 0 and + * TK_MAX_PRIO. */ { register char *src, *dst; char *name, *value; @@ -975,7 +950,7 @@ AddFromString(interp, tkwin, string, priority) src++; lineNum++; continue; - } + } if (*src == '\0') { break; } @@ -989,7 +964,7 @@ AddFromString(interp, tkwin, string, priority) while (*src != ':') { if ((*src == '\0') || (*src == '\n')) { char buf[32 + TCL_INTEGER_SPACE]; - + sprintf(buf, "missing colon on line %d", lineNum); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -1024,7 +999,7 @@ AddFromString(interp, tkwin, string, priority) } if (*src == '\0') { char buf[32 + TCL_INTEGER_SPACE]; - + sprintf(buf, "missing value on line %d", lineNum); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -1039,7 +1014,7 @@ AddFromString(interp, tkwin, string, priority) while (*src != '\n') { if (*src == '\0') { char buf[32 + TCL_INTEGER_SPACE]; - + sprintf(buf, "missing newline on line %d", lineNum); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; @@ -1071,13 +1046,13 @@ AddFromString(interp, tkwin, string, priority) * * ReadOptionFile -- * - * Read a file of options ("resources" in the old X terminology) - * and load them into the option database. + * Read a file of options ("resources" in the old X terminology) and load + * them into the option database. * * Results: - * The return value is a standard Tcl return code. In the case of - * an error in parsing string, TCL_ERROR will be returned and an - * error message will be left in the interp's result. + * The return value is a standard Tcl return code. In the case of an + * error in parsing string, TCL_ERROR will be returned and an error + * message will be left in the interp's result. * * Side effects: * None. @@ -1086,15 +1061,15 @@ AddFromString(interp, tkwin, string, priority) */ static int -ReadOptionFile(interp, tkwin, fileName, priority) - Tcl_Interp *interp; /* Interpreter to use for reporting results. */ - Tk_Window tkwin; /* Token for window: options are entered - * for this window's main window. */ - char *fileName; /* Name of file containing options. */ - int priority; /* Priority level to use for options in - * this file, such as TK_USER_DEFAULT_PRIO - * or TK_INTERACTIVE_PRIO. Must be between - * 0 and TK_MAX_PRIO. */ +ReadOptionFile( + Tcl_Interp *interp, /* Interpreter to use for reporting results. */ + Tk_Window tkwin, /* Token for window: options are entered for + * this window's main window. */ + char *fileName, /* Name of file containing options. */ + int priority) /* Priority level to use for options in this + * file, such as TK_USER_DEFAULT_PRIO or + * TK_INTERACTIVE_PRIO. Must be between 0 and + * TK_MAX_PRIO. */ { CONST char *realName; char *buffer; @@ -1105,13 +1080,13 @@ ReadOptionFile(interp, tkwin, fileName, priority) /* * Prevent file system access in a safe interpreter. */ - + if (Tcl_IsSafe(interp)) { - Tcl_AppendResult(interp, "can't read options from a file in a", - " safe interpreter", (char *) NULL); - return TCL_ERROR; + Tcl_AppendResult(interp, "can't read options from a file in a", + " safe interpreter", NULL); + return TCL_ERROR; } - + realName = Tcl_TranslateFileName(interp, fileName, &newName); if (realName == NULL) { return TCL_ERROR; @@ -1119,23 +1094,23 @@ ReadOptionFile(interp, tkwin, fileName, priority) chan = Tcl_OpenFileChannel(interp, realName, "r", 0); Tcl_DStringFree(&newName); if (chan == NULL) { - Tcl_ResetResult(interp); + Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't open \"", fileName, - "\": ", Tcl_PosixError(interp), (char *) NULL); + "\": ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } /* - * Compute size of file by seeking to the end of the file. This will + * Compute size of file by seeking to the end of the file. This will * overallocate if we are performing CRLF translation. */ - + bufferSize = (int) Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_END); (void) Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_SET); if (bufferSize < 0) { Tcl_AppendResult(interp, "error seeking to end of file \"", - fileName, "\":", Tcl_PosixError(interp), (char *) NULL); + fileName, "\":", Tcl_PosixError(interp), NULL); Tcl_Close(NULL, chan); return TCL_ERROR; @@ -1144,7 +1119,7 @@ ReadOptionFile(interp, tkwin, fileName, priority) bufferSize = Tcl_Read(chan, buffer, bufferSize); if (bufferSize < 0) { Tcl_AppendResult(interp, "error reading file \"", fileName, "\":", - Tcl_PosixError(interp), (char *) NULL); + Tcl_PosixError(interp), NULL); Tcl_Close(NULL, chan); return TCL_ERROR; } @@ -1163,9 +1138,8 @@ ReadOptionFile(interp, tkwin, fileName, priority) * Create a new ElArray structure of a given size. * * Results: - * The return value is a pointer to a properly initialized - * element array with "numEls" space. The array is marked - * as having no active elements. + * The return value is a pointer to a properly initialized element array + * with "numEls" space. The array is marked as having no active elements. * * Side effects: * Memory is allocated. @@ -1174,8 +1148,8 @@ ReadOptionFile(interp, tkwin, fileName, priority) */ static ElArray * -NewArray(numEls) - int numEls; /* How many elements of space to allocate. */ +NewArray( + int numEls) /* How many elements of space to allocate. */ { register ElArray *arrayPtr; @@ -1191,12 +1165,11 @@ NewArray(numEls) * * ExtendArray -- * - * Add a new element to an array, extending the array if - * necessary. + * Add a new element to an array, extending the array if necessary. * * Results: - * The return value is a pointer to the new array, which - * will be different from arrayPtr if the array got expanded. + * The return value is a pointer to the new array, which will be + * different from arrayPtr if the array got expanded. * * Side effects: * Memory may be allocated or freed. @@ -1205,9 +1178,9 @@ NewArray(numEls) */ static ElArray * -ExtendArray(arrayPtr, elPtr) - register ElArray *arrayPtr; /* Array to be extended. */ - register Element *elPtr; /* Element to be copied into array. */ +ExtendArray( + register ElArray *arrayPtr, /* Array to be extended. */ + register Element *elPtr) /* Element to be copied into array. */ { /* * If the current array has filled up, make it bigger. @@ -1220,8 +1193,8 @@ ExtendArray(arrayPtr, elPtr) newPtr->arraySize = 2*arrayPtr->arraySize; newPtr->numUsed = arrayPtr->numUsed; newPtr->nextToUse = &newPtr->els[newPtr->numUsed]; - memcpy((VOID *) newPtr->els, (VOID *) arrayPtr->els, - (arrayPtr->arraySize*sizeof(Element))); + memcpy(newPtr->els, arrayPtr->els, + arrayPtr->arraySize * sizeof(Element)); ckfree((char *) arrayPtr); arrayPtr = newPtr; } @@ -1237,40 +1210,40 @@ ExtendArray(arrayPtr, elPtr) * * SetupStacks -- * - * Arrange the stacks so that they cache all the option - * information for a particular window. + * Arrange the stacks so that they cache all the option information for a + * particular window. * * Results: * None. * * Side effects: - * The stacks are modified to hold information for tkwin - * and all its ancestors in the window hierarchy. + * The stacks are modified to hold information for tkwin and all its + * ancestors in the window hierarchy. * *-------------------------------------------------------------- */ static void -SetupStacks(winPtr, leaf) - TkWindow *winPtr; /* Window for which information is to - * be cached. */ - int leaf; /* Non-zero means this is the leaf - * window being probed. Zero means this - * is an ancestor of the desired leaf. */ +SetupStacks( + TkWindow *winPtr, /* Window for which information is to be + * cached. */ + int leaf) /* Non-zero means this is the leaf window + * being probed. Zero means this is an + * ancestor of the desired leaf. */ { int level, i, *iPtr; register StackLevel *levelPtr; register ElArray *arrayPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * The following array defines the order in which the current - * stacks are searched to find matching entries to add to the - * stacks. Given the current priority-based scheme, the order - * below is no longer relevant; all that matters is that an - * element is on the list *somewhere*. The ordering is a relic - * of the old days when priorities were determined differently. + * The following array defines the order in which the current stacks are + * searched to find matching entries to add to the stacks. Given the + * current priority-based scheme, the order below is no longer relevant; + * all that matters is that an element is on the list *somewhere*. The + * ordering is a relic of the old days when priorities were determined + * differently. */ static int searchOrder[] = {WILDCARD_NODE_CLASS, WILDCARD_NODE_NAME, @@ -1281,8 +1254,7 @@ SetupStacks(winPtr, leaf) } /* - * Step 1: make sure that options are cached for this window's - * parent. + * Step 1: make sure that options are cached for this window's parent. */ if (winPtr->parentPtr != NULL) { @@ -1297,8 +1269,8 @@ SetupStacks(winPtr, leaf) } /* - * Step 2: pop extra unneeded information off the stacks and - * mark those windows as no longer having cached information. + * Step 2: pop extra unneeded information off the stacks and mark those + * windows as no longer having cached information. */ if (tsdPtr->curLevel >= level) { @@ -1316,9 +1288,9 @@ SetupStacks(winPtr, leaf) tsdPtr->curLevel = winPtr->optionLevel = level; /* - * Step 3: if the root database information isn't loaded or - * isn't valid, initialize level 0 of the stack from the - * database root (this only happens if winPtr is a main window). + * Step 3: if the root database information isn't loaded or isn't valid, + * initialize level 0 of the stack from the database root (this only + * happens if winPtr is a main window). */ if ((tsdPtr->curLevel == 1) @@ -1333,19 +1305,18 @@ SetupStacks(winPtr, leaf) } /* - * Step 4: create a new stack level; grow the level array if - * we've run out of levels. Clear the stacks for EXACT_LEAF_NAME - * and EXACT_LEAF_CLASS (anything that was there is of no use - * any more). + * Step 4: create a new stack level; grow the level array if we've run out + * of levels. Clear the stacks for EXACT_LEAF_NAME and EXACT_LEAF_CLASS + * (anything that was there is of no use any more). */ if (tsdPtr->curLevel >= tsdPtr->numLevels) { StackLevel *newLevels; newLevels = (StackLevel *) ckalloc((unsigned) - (tsdPtr->numLevels*2*sizeof(StackLevel))); - memcpy((VOID *) newLevels, (VOID *) tsdPtr->levels, - (tsdPtr->numLevels*sizeof(StackLevel))); + (tsdPtr->numLevels * 2 * sizeof(StackLevel))); + memcpy(newLevels, tsdPtr->levels, + tsdPtr->numLevels * sizeof(StackLevel)); ckfree((char *) tsdPtr->levels); tsdPtr->numLevels *= 2; tsdPtr->levels = newLevels; @@ -1361,10 +1332,10 @@ SetupStacks(winPtr, leaf) for (i = 0; i < NUM_STACKS; i++) { levelPtr->bases[i] = tsdPtr->stacks[i]->numUsed; } + /* * Step 5: scan the current stack level looking for matches to this - * window's name or class; where found, add new information to the - * stacks. + * window's name or class; where found, add new information to the stacks. */ for (iPtr = searchOrder; *iPtr != -1; iPtr++) { @@ -1382,8 +1353,8 @@ SetupStacks(winPtr, leaf) count = levelPtr->bases[i]; /* - * For wildcard stacks, check all entries; for non-wildcard - * stacks, only check things that matched in the parent. + * For wildcard stacks, check all entries; for non-wildcard stacks, + * only check things that matched in the parent. */ if (!(i & WILDCARD)) { @@ -1405,9 +1376,8 @@ SetupStacks(winPtr, leaf) * * ExtendStacks -- * - * Given an element array, copy all the elements from the - * array onto the system stacks (except for irrelevant leaf - * elements). + * Given an element array, copy all the elements from the array onto the + * system stacks (except for irrelevant leaf elements). * * Results: * None. @@ -1419,23 +1389,23 @@ SetupStacks(winPtr, leaf) */ static void -ExtendStacks(arrayPtr, leaf) - ElArray *arrayPtr; /* Array of elements to copy onto stacks. */ - int leaf; /* If zero, then don't copy exact leaf +ExtendStacks( + ElArray *arrayPtr, /* Array of elements to copy onto stacks. */ + int leaf) /* If zero, then don't copy exact leaf * elements. */ { register int count; register Element *elPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (elPtr = arrayPtr->els, count = arrayPtr->numUsed; count > 0; elPtr++, count--) { if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) { continue; } - tsdPtr->stacks[elPtr->flags] = ExtendArray( - tsdPtr->stacks[elPtr->flags], elPtr); + tsdPtr->stacks[elPtr->flags] = + ExtendArray(tsdPtr->stacks[elPtr->flags], elPtr); } } @@ -1456,14 +1426,15 @@ ExtendStacks(arrayPtr, leaf) */ static void -OptionThreadExitProc(clientData) - ClientData clientData; /* not used */ +OptionThreadExitProc( + ClientData clientData) /* not used */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (tsdPtr->initialized) { int i; + for (i = 0; i < NUM_STACKS; i++) { ckfree((char *) tsdPtr->stacks[i]); } @@ -1489,35 +1460,35 @@ OptionThreadExitProc(clientData) */ static void -OptionInit(mainPtr) - register TkMainInfo *mainPtr; /* Top-level information about - * window that isn't initialized - * yet. */ +OptionInit( + register TkMainInfo *mainPtr) + /* Top-level information about window that + * isn't initialized yet. */ { int i; Tcl_Interp *interp; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Element *defaultMatchPtr = &tsdPtr->defaultMatch; /* * First, once-only initialization. */ - + if (tsdPtr->initialized == 0) { - tsdPtr->initialized = 1; - tsdPtr->cachedWindow = NULL; + tsdPtr->initialized = 1; + tsdPtr->cachedWindow = NULL; tsdPtr->numLevels = 5; tsdPtr->curLevel = -1; tsdPtr->serial = 0; - tsdPtr->levels = (StackLevel *) ckalloc((unsigned) - (5*sizeof(StackLevel))); + tsdPtr->levels = (StackLevel *) + ckalloc((unsigned) (5*sizeof(StackLevel))); for (i = 0; i < NUM_STACKS; i++) { tsdPtr->stacks[i] = NewArray(10); tsdPtr->levels[0].bases[i] = 0; } - + defaultMatchPtr->nameUid = NULL; defaultMatchPtr->child.valueUid = NULL; defaultMatchPtr->priority = -1; @@ -1526,7 +1497,7 @@ OptionInit(mainPtr) } /* - * Then, per-main-window initialization. Create and delete dummy + * Then, per-main-window initialization. Create and delete dummy * interpreter for message logging. */ @@ -1541,23 +1512,22 @@ OptionInit(mainPtr) * * ClearOptionTree -- * - * This procedure is called to erase everything in a - * hierarchical option database. + * This function is called to erase everything in a hierarchical option + * database. * * Results: * None. * * Side effects: - * All the options associated with arrayPtr are deleted, - * along with all option subtrees. The space pointed to - * by arrayPtr is freed. + * All the options associated with arrayPtr are deleted, along with all + * option subtrees. The space pointed to by arrayPtr is freed. * *-------------------------------------------------------------- */ static void -ClearOptionTree(arrayPtr) - ElArray *arrayPtr; /* Array of options; delete everything +ClearOptionTree( + ElArray *arrayPtr) /* Array of options; delete everything * referred to recursively by this. */ { register Element *elPtr; @@ -1577,28 +1547,27 @@ ClearOptionTree(arrayPtr) * * GetDefaultOptions -- * - * This procedure is invoked to load the default set of options - * for a window. + * This function is invoked to load the default set of options for a + * window. * * Results: * None. * * Side effects: - * Options are added to those for winPtr's main window. If - * there exists a RESOURCE_MANAGER proprety for winPtr's - * display, that is used. Otherwise, the .Xdefaults file in - * the user's home directory is used. + * Options are added to those for winPtr's main window. If there exists a + * RESOURCE_MANAGER proprety for winPtr's display, that is used. + * Otherwise, the .Xdefaults file in the user's home directory is used. * *-------------------------------------------------------------- */ static int -GetDefaultOptions(interp, winPtr) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - TkWindow *winPtr; /* Fetch option defaults for main window +GetDefaultOptions( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + TkWindow *winPtr) /* Fetch option defaults for main window * associated with this. */ { - char *regProp; + char *regProp, **regPropPtr = ®Prop; int result, actualFormat; unsigned long numItems, bytesAfter; Atom actualType; @@ -1609,10 +1578,9 @@ GetDefaultOptions(interp, winPtr) regProp = NULL; result = XGetWindowProperty(winPtr->display, - RootWindow(winPtr->display, 0), - XA_RESOURCE_MANAGER, 0, 100000, - False, XA_STRING, &actualType, &actualFormat, - &numItems, &bytesAfter, (unsigned char **) ®Prop); + RootWindow(winPtr->display, 0), XA_RESOURCE_MANAGER, 0, 100000, + False, XA_STRING, &actualType, &actualFormat, &numItems, + &bytesAfter, (unsigned char **) regPropPtr); if ((result == Success) && (actualType == XA_STRING) && (actualFormat == 8)) { @@ -1623,8 +1591,7 @@ GetDefaultOptions(interp, winPtr) } /* - * No luck there. Try a .Xdefaults file in the user's home - * directory. + * No luck there. Try a .Xdefaults file in the user's home directory. */ if (regProp != NULL) { @@ -1634,3 +1601,11 @@ GetDefaultOptions(interp, winPtr) TK_USER_DEFAULT_PRIO); return result; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkPack.c b/generic/tkPack.c index 8498df6..47eddd6 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -1,22 +1,21 @@ -/* +/* * tkPack.c -- * - * This file contains code to implement the "packer" - * geometry manager for Tk. + * This file contains code to implement the "packer" geometry manager for + * Tk. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side; static CONST char *sideNames[] = { - "top", "bottom", "left", "right", (char *) NULL + "top", "bottom", "left", "right", NULL }; /* For each window that the packer cares about (either because @@ -26,70 +25,68 @@ static CONST char *sideNames[] = { */ typedef struct Packer { - Tk_Window tkwin; /* Tk token for window. NULL means that - * the window has been deleted, but the - * packet hasn't had a chance to clean up - * yet because the structure is still in - * use. */ - struct Packer *masterPtr; /* Master window within which this window - * is packed (NULL means this window - * isn't managed by the packer). */ - struct Packer *nextPtr; /* Next window packed within same - * parent. List is priority-ordered: - * first on list gets packed first. */ - struct Packer *slavePtr; /* First in list of slaves packed - * inside this window (NULL means - * no packed slaves). */ - Side side; /* Side of parent against which - * this window is packed. */ + Tk_Window tkwin; /* Tk token for window. NULL means that the + * window has been deleted, but the packet + * hasn't had a chance to clean up yet because + * the structure is still in use. */ + struct Packer *masterPtr; /* Master window within which this window is + * packed (NULL means this window isn't + * managed by the packer). */ + struct Packer *nextPtr; /* Next window packed within same master. + * List is priority-ordered: first on list + * gets packed first. */ + struct Packer *slavePtr; /* First in list of slaves packed inside this + * window (NULL means no packed slaves). */ + Side side; /* Side of master against which this window is + * packed. */ Tk_Anchor anchor; /* If frame allocated for window is larger - * than window needs, this indicates how - * where to position window in frame. */ + * than window needs, this indicates how where + * to position window in frame. */ int padX, padY; /* Total additional pixels to leave around the - * window. Some is of this space is on each - * side. This is space *outside* the window: + * window. Some is of this space is on each + * side. This is space *outside* the window: * we'll allocate extra space in frame but * won't enlarge window). */ - int padLeft, padTop; /* The part of padX or padY to use on the - * left or top of the widget, respectively. - * By default, this is half of padX or padY. */ + int padLeft, padTop; /* The part of padX or padY to use on the left + * or top of the widget, respectively. By + * default, this is half of padX or padY. */ int iPadX, iPadY; /* Total extra pixels to allocate inside the * window (half of this amount will appear on * each side). */ - int doubleBw; /* Twice the window's last known border - * width. If this changes, the window - * must be repacked within its parent. */ - int *abortPtr; /* If non-NULL, it means that there is a nested - * call to ArrangePacking already working on - * this window. *abortPtr may be set to 1 to - * abort that nested call. This happens, for - * example, if tkwin or any of its slaves - * is deleted. */ - int flags; /* Miscellaneous flags; see below - * for definitions. */ + int doubleBw; /* Twice the window's last known border width. + * If this changes, the window must be + * repacked within its master. */ + int *abortPtr; /* If non-NULL, it means that there is a + * nested call to ArrangePacking already + * working on this window. *abortPtr may be + * set to 1 to abort that nested call. This + * happens, for example, if tkwin or any of + * its slaves is deleted. */ + int flags; /* Miscellaneous flags; see below for + * definitions. */ } Packer; /* * Flag values for Packer structures: * - * REQUESTED_REPACK: 1 means a Tcl_DoWhenIdle request - * has already been made to repack - * all the slaves of this window. - * FILLX: 1 means if frame allocated for window - * is wider than window needs, expand window - * to fill frame. 0 means don't make window - * any larger than needed. + * REQUESTED_REPACK: 1 means a Tcl_DoWhenIdle request has already + * been made to repack all the slaves of this + * window. + * FILLX: 1 means if frame allocated for window is wider + * than window needs, expand window to fill + * frame. 0 means don't make window any larger + * than needed. * FILLY: Same as FILLX, except for height. * EXPAND: 1 means this window's frame will absorb any - * extra space in the parent window. - * OLD_STYLE: 1 means this window is being managed with - * the old-style packer algorithms (before - * Tk version 3.3). The main difference is - * that padding and filling are done differently. + * extra space in the master window. + * OLD_STYLE: 1 means this window is being managed with the + * old-style packer algorithms (before Tk version + * 3.3). The main difference is that padding and + * filling are done differently. * DONT_PROPAGATE: 1 means don't set this window's requested - * size. 0 means if this window is a master - * then Tk will set its requested size to fit - * the needs of its slaves. + * size. 0 means if this window is a master then + * Tk will set its requested size to fit the + * needs of its slaves. */ #define REQUESTED_REPACK 1 @@ -100,52 +97,44 @@ typedef struct Packer { #define DONT_PROPAGATE 32 /* - * The following structure is the official type record for the - * packer: + * The following structure is the official type record for the packer: */ -static void PackReqProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void PackLostSlaveProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); +static void PackReqProc(ClientData clientData, Tk_Window tkwin); +static void PackLostSlaveProc(ClientData clientData, + Tk_Window tkwin); -static Tk_GeomMgr packerType = { +static const Tk_GeomMgr packerType = { "pack", /* name */ PackReqProc, /* requestProc */ PackLostSlaveProc, /* lostSlaveProc */ }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void ArrangePacking _ANSI_ARGS_((ClientData clientData)); -static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, int objc, Tcl_Obj *CONST objv[])); -static void DestroyPacker _ANSI_ARGS_((char *memPtr)); -static Packer * GetPacker _ANSI_ARGS_((Tk_Window tkwin)); -static int PackAfter _ANSI_ARGS_((Tcl_Interp *interp, - Packer *prevPtr, Packer *masterPtr, int objc, - Tcl_Obj *CONST objv[])); -static void PackReqProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void PackStructureProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void Unlink _ANSI_ARGS_((Packer *packPtr)); -static int XExpansion _ANSI_ARGS_((Packer *slavePtr, - int cavityWidth)); -static int YExpansion _ANSI_ARGS_((Packer *slavePtr, - int cavityHeight)); +static void ArrangePacking(ClientData clientData); +static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, + int objc, Tcl_Obj *CONST objv[]); +static void DestroyPacker(char *memPtr); +static Packer * GetPacker(Tk_Window tkwin); +static int PackAfter(Tcl_Interp *interp, Packer *prevPtr, + Packer *masterPtr, int objc,Tcl_Obj *CONST objv[]); +static void PackStructureProc(ClientData clientData, + XEvent *eventPtr); +static void Unlink(Packer *packPtr); +static int XExpansion(Packer *slavePtr, int cavityWidth); +static int YExpansion(Packer *slavePtr, int cavityHeight); /* *-------------------------------------------------------------- * * TkPrintPadAmount -- * - * This procedure generates a text value that describes one - * of the -padx, -pady, -ipadx, or -ipady configuration options. - * The text value generated is appended to the interpreter - * result. + * This function generates a text value that describes one of the -padx, + * -pady, -ipadx, or -ipady configuration options. The text value + * generated is appended to the interpreter result. * * Results: * None. @@ -155,13 +144,14 @@ static int YExpansion _ANSI_ARGS_((Packer *slavePtr, * *-------------------------------------------------------------- */ -void -TkPrintPadAmount(interp, switchName, halfSpace, allSpace) - Tcl_Interp *interp; /* The interpreter into which the result - * is written. */ - char *switchName; /* One of "padx", "pady", "ipadx" or "ipady" */ - int halfSpace; /* The left or top padding amount */ - int allSpace; /* The total amount of padding */ + +void +TkPrintPadAmount( + Tcl_Interp *interp, /* The interpreter into which the result is + * written. */ + char *switchName, /* One of "padx", "pady", "ipadx" or "ipady" */ + int halfSpace, /* The left or top padding amount */ + int allSpace) /* The total amount of padding */ { char buffer[60 + 2*TCL_INTEGER_SPACE]; if (halfSpace*2 == allSpace) { @@ -170,17 +160,16 @@ TkPrintPadAmount(interp, switchName, halfSpace, allSpace) sprintf(buffer, " -%.10s {%d %d}", switchName, halfSpace, allSpace - halfSpace); } - Tcl_AppendResult(interp, buffer, (char *)NULL); + Tcl_AppendResult(interp, buffer, NULL); } - /* *-------------------------------------------------------------- * * Tk_PackCmd -- * - * This procedure is invoked to process the "pack" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "pack" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -192,19 +181,18 @@ TkPrintPadAmount(interp, switchName, halfSpace, allSpace) */ int -Tk_PackObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_PackObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; char *argv2; static CONST char *optionStrings[] = { /* after, append, before and unpack are deprecated */ "after", "append", "before", "unpack", - "configure", "forget", "info", "propagate", "slaves", (char *) NULL }; + "configure", "forget", "info", "propagate", "slaves", NULL }; enum options { PACK_AFTER, PACK_APPEND, PACK_BEFORE, PACK_UNPACK, PACK_CONFIGURE, PACK_FORGET, PACK_INFO, PACK_PROPAGATE, PACK_SLAVES }; @@ -224,9 +212,8 @@ Tk_PackObjCmd(clientData, interp, objc, objv) if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { /* - * Call it again without the deprecated ones to get a proper - * error message. - * This works well since there can't be any ambiguity between + * Call it again without the deprecated ones to get a proper error + * message. This works well since there can't be any ambiguity between * deprecated and new options. */ @@ -237,7 +224,8 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } argv2 = Tcl_GetString(objv[2]); - if (index == PACK_AFTER) { + switch ((enum options) index) { + case PACK_AFTER: { Packer *prevPtr; Tk_Window tkwin2; @@ -247,11 +235,12 @@ Tk_PackObjCmd(clientData, interp, objc, objv) prevPtr = GetPacker(tkwin2); if (prevPtr->masterPtr == NULL) { Tcl_AppendResult(interp, "window \"", argv2, - "\" isn't packed", (char *) NULL); + "\" isn't packed", NULL); return TCL_ERROR; } return PackAfter(interp, prevPtr, prevPtr->masterPtr, objc-3, objv+3); - } else if (index == PACK_APPEND) { + } + case PACK_APPEND: { Packer *masterPtr; register Packer *prevPtr; Tk_Window tkwin2; @@ -267,7 +256,8 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } } return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3); - } else if (index == PACK_BEFORE) { + } + case PACK_BEFORE: { Packer *packPtr, *masterPtr; register Packer *prevPtr; Tk_Window tkwin2; @@ -278,7 +268,7 @@ Tk_PackObjCmd(clientData, interp, objc, objv) packPtr = GetPacker(tkwin2); if (packPtr->masterPtr == NULL) { Tcl_AppendResult(interp, "window \"", argv2, - "\" isn't packed", (char *) NULL); + "\" isn't packed", NULL); return TCL_ERROR; } masterPtr = packPtr->masterPtr; @@ -288,7 +278,7 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } else { for ( ; ; prevPtr = prevPtr->nextPtr) { if (prevPtr == NULL) { - panic("\"pack before\" couldn't find predecessor"); + Tcl_Panic("\"pack before\" couldn't find predecessor"); } if (prevPtr->nextPtr == packPtr) { break; @@ -296,14 +286,15 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } } return PackAfter(interp, prevPtr, masterPtr, objc-3, objv+3); - } else if (index == PACK_CONFIGURE) { + } + case PACK_CONFIGURE: if (argv2[0] != '.') { Tcl_AppendResult(interp, "bad argument \"", argv2, - "\": must be name of window", (char *) NULL); + "\": must be name of window", NULL); return TCL_ERROR; } return ConfigureSlaves(interp, tkwin, objc-2, objv+2); - } else if (index == PACK_FORGET) { + case PACK_FORGET: { Tk_Window slave; Packer *slavePtr; int i; @@ -314,7 +305,7 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } slavePtr = GetPacker(slave); if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) { - Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, + Tk_ManageGeometry(slave, NULL, (ClientData) NULL); if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, @@ -324,7 +315,9 @@ Tk_PackObjCmd(clientData, interp, objc, objv) Tk_UnmapWindow(slavePtr->tkwin); } } - } else if (index == PACK_INFO) { + break; + } + case PACK_INFO: { register Packer *slavePtr; Tk_Window slave; @@ -338,7 +331,7 @@ Tk_PackObjCmd(clientData, interp, objc, objv) slavePtr = GetPacker(slave); if (slavePtr->masterPtr == NULL) { Tcl_AppendResult(interp, "window \"", argv2, - "\" isn't packed", (char *) NULL); + "\" isn't packed", NULL); return TCL_ERROR; } Tcl_AppendElement(interp, "-in"); @@ -346,29 +339,29 @@ Tk_PackObjCmd(clientData, interp, objc, objv) Tcl_AppendElement(interp, "-anchor"); Tcl_AppendElement(interp, Tk_NameOfAnchor(slavePtr->anchor)); Tcl_AppendResult(interp, " -expand ", - (slavePtr->flags & EXPAND) ? "1" : "0", " -fill ", - (char *) NULL); + (slavePtr->flags & EXPAND) ? "1" : "0", " -fill ", NULL); switch (slavePtr->flags & (FILLX|FILLY)) { - case 0: - Tcl_AppendResult(interp, "none", (char *) NULL); - break; - case FILLX: - Tcl_AppendResult(interp, "x", (char *) NULL); - break; - case FILLY: - Tcl_AppendResult(interp, "y", (char *) NULL); - break; - case FILLX|FILLY: - Tcl_AppendResult(interp, "both", (char *) NULL); - break; + case 0: + Tcl_AppendResult(interp, "none", NULL); + break; + case FILLX: + Tcl_AppendResult(interp, "x", NULL); + break; + case FILLY: + Tcl_AppendResult(interp, "y", NULL); + break; + case FILLX|FILLY: + Tcl_AppendResult(interp, "both", NULL); + break; } - TkPrintPadAmount(interp, "ipadx", slavePtr->iPadX/2, slavePtr->iPadX); - TkPrintPadAmount(interp, "ipady", slavePtr->iPadY/2, slavePtr->iPadY); - TkPrintPadAmount(interp, "padx", slavePtr->padLeft, slavePtr->padX); - TkPrintPadAmount(interp, "pady", slavePtr->padTop, slavePtr->padY); - Tcl_AppendResult(interp, " -side ", sideNames[slavePtr->side], - (char *) NULL); - } else if (index == PACK_PROPAGATE) { + TkPrintPadAmount(interp, "ipadx", slavePtr->iPadX/2, slavePtr->iPadX); + TkPrintPadAmount(interp, "ipady", slavePtr->iPadY/2, slavePtr->iPadY); + TkPrintPadAmount(interp, "padx", slavePtr->padLeft, slavePtr->padX); + TkPrintPadAmount(interp, "pady", slavePtr->padTop, slavePtr->padY); + Tcl_AppendResult(interp, " -side ", sideNames[slavePtr->side], NULL); + break; + } + case PACK_PROPAGATE: { Tk_Window master; Packer *masterPtr; int propagate; @@ -407,7 +400,9 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } else { masterPtr->flags |= DONT_PROPAGATE; } - } else if (index == PACK_SLAVES) { + break; + } + case PACK_SLAVES: { Tk_Window master; Packer *masterPtr, *slavePtr; @@ -423,7 +418,9 @@ Tk_PackObjCmd(clientData, interp, objc, objv) slavePtr = slavePtr->nextPtr) { Tcl_AppendElement(interp, Tk_PathName(slavePtr->tkwin)); } - } else if (index == PACK_UNPACK) { + break; + } + case PACK_UNPACK: { Tk_Window tkwin2; Packer *packPtr; @@ -436,7 +433,7 @@ Tk_PackObjCmd(clientData, interp, objc, objv) } packPtr = GetPacker(tkwin2); if ((packPtr != NULL) && (packPtr->masterPtr != NULL)) { - Tk_ManageGeometry(tkwin2, (Tk_GeomMgr *) NULL, + Tk_ManageGeometry(tkwin2, NULL, (ClientData) NULL); if (packPtr->masterPtr->tkwin != Tk_Parent(packPtr->tkwin)) { Tk_UnmaintainGeometry(packPtr->tkwin, @@ -445,6 +442,8 @@ Tk_PackObjCmd(clientData, interp, objc, objv) Unlink(packPtr); Tk_UnmapWindow(packPtr->tkwin); } + break; + } } return TCL_OK; @@ -455,27 +454,26 @@ Tk_PackObjCmd(clientData, interp, objc, objv) * * PackReqProc -- * - * This procedure is invoked by Tk_GeometryRequest for - * windows managed by the packer. + * This function is invoked by Tk_GeometryRequest for windows managed by + * the packer. * * Results: * None. * * Side effects: - * Arranges for tkwin, and all its managed siblings, to - * be re-packed at the next idle point. + * Arranges for tkwin, and all its managed siblings, to be re-packed at + * the next idle point. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -PackReqProc(clientData, tkwin) - ClientData clientData; /* Packer's information about - * window that got new preferred - * geometry. */ - Tk_Window tkwin; /* Other Tk-related information - * about the window. */ +PackReqProc( + ClientData clientData, /* Packer's information about window that got + * new preferred geometry. */ + Tk_Window tkwin) /* Other Tk-related information about the + * window. */ { register Packer *packPtr = (Packer *) clientData; @@ -491,8 +489,8 @@ PackReqProc(clientData, tkwin) * * PackLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This function is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. @@ -505,10 +503,10 @@ PackReqProc(clientData, tkwin) /* ARGSUSED */ static void -PackLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Packer structure for slave window that - * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ +PackLostSlaveProc( + ClientData clientData, /* Packer structure for slave window that was + * stolen away. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { register Packer *slavePtr = (Packer *) clientData; @@ -524,38 +522,36 @@ PackLostSlaveProc(clientData, tkwin) * * ArrangePacking -- * - * This procedure is invoked (using the Tcl_DoWhenIdle - * mechanism) to re-layout a set of windows managed by - * the packer. It is invoked at idle time so that a - * series of packer requests can be merged into a single - * layout operation. + * This function is invoked (using the Tcl_DoWhenIdle mechanism) to + * re-layout a set of windows managed by the packer. It is invoked at + * idle time so that a series of packer requests can be merged into a + * single layout operation. * * Results: * None. * * Side effects: - * The packed slaves of masterPtr may get resized or - * moved. + * The packed slaves of masterPtr may get resized or moved. * *-------------------------------------------------------------- */ static void -ArrangePacking(clientData) - ClientData clientData; /* Structure describing parent whose slaves +ArrangePacking( + ClientData clientData) /* Structure describing master whose slaves * are to be re-layed out. */ { register Packer *masterPtr = (Packer *) clientData; - register Packer *slavePtr; + register Packer *slavePtr; int cavityX, cavityY, cavityWidth, cavityHeight; /* These variables keep track of the - * as-yet-unallocated space remaining in - * the middle of the parent window. */ + * as-yet-unallocated space remaining in the + * middle of the master window. */ int frameX, frameY, frameWidth, frameHeight; /* These variables keep track of the frame * allocated to the current window. */ - int x, y, width, height; /* These variables are used to hold the - * actual geometry of the current window. */ + int x, y, width, height; /* These variables are used to hold the actual + * geometry of the current window. */ int abort; /* May get set to non-zero to abort this * repacking operation. */ int borderX, borderY; @@ -566,8 +562,8 @@ ArrangePacking(clientData) masterPtr->flags &= ~REQUESTED_REPACK; /* - * If the parent has no slaves anymore, then don't do anything - * at all: just leave the parent's size as-is. + * If the master has no slaves anymore, then don't do anything at all: + * just leave the master's size as-is. */ if (masterPtr->slavePtr == NULL) { @@ -575,9 +571,9 @@ ArrangePacking(clientData) } /* - * Abort any nested call to ArrangePacking for this window, since - * we'll do everything necessary here, and set up so this call - * can be aborted if necessary. + * Abort any nested call to ArrangePacking for this window, since we'll do + * everything necessary here, and set up so this call can be aborted if + * necessary. */ if (masterPtr->abortPtr != NULL) { @@ -588,22 +584,19 @@ ArrangePacking(clientData) Tcl_Preserve((ClientData) masterPtr); /* - * Pass #1: scan all the slaves to figure out the total amount - * of space needed. Two separate width and height values are - * computed: + * Pass #1: scan all the slaves to figure out the total amount of space + * needed. Two separate width and height values are computed: * - * width - Holds the sum of the widths (plus padding) of - * all the slaves seen so far that were packed LEFT - * or RIGHT. - * height - Holds the sum of the heights (plus padding) of - * all the slaves seen so far that were packed TOP - * or BOTTOM. + * width - Holds the sum of the widths (plus padding) of all the + * slaves seen so far that were packed LEFT or RIGHT. + * height - Holds the sum of the heights (plus padding) of all the + * slaves seen so far that were packed TOP or BOTTOM. * - * maxWidth - Gradually builds up the width needed by the master - * to just barely satisfy all the slave's needs. For - * each slave, the code computes the width needed for - * all the slaves so far and updates maxWidth if the - * new value is greater. + * maxWidth - Gradually builds up the width needed by the master to + * just barely satisfy all the slave's needs. For each + * slave, the code computes the width needed for all the + * slaves so far and updates maxWidth if the new value is + * greater. * maxHeight - Same as maxWidth, except keeps height info. */ @@ -646,11 +639,10 @@ ArrangePacking(clientData) } /* - * If the total amount of space needed in the parent window has - * changed, and if we're propagating geometry information, then - * notify the next geometry manager up and requeue ourselves to - * start again after the parent has had a chance to - * resize us. + * If the total amount of space needed in the master window has changed, + * and if we're propagating geometry information, then notify the next + * geometry manager up and requeue ourselves to start again after the + * master has had a chance to resize us. */ if (((maxWidth != Tk_ReqWidth(masterPtr->tkwin)) @@ -663,14 +655,12 @@ ArrangePacking(clientData) } /* - * Pass #2: scan the slaves a second time assigning - * new sizes. The "cavity" variables keep track of the - * unclaimed space in the cavity of the window; this - * shrinks inward as we allocate windows around the - * edges. The "frame" variables keep track of the space - * allocated to the current window and its frame. The - * current window is then placed somewhere inside the - * frame, depending on anchor. + * Pass #2: scan the slaves a second time assigning new sizes. The + * "cavity" variables keep track of the unclaimed space in the cavity of + * the window; this shrinks inward as we allocate windows around the + * edges. The "frame" variables keep track of the space allocated to the + * current window and its frame. The current window is then placed + * somewhere inside the frame, depending on anchor. */ cavityX = x = Tk_InternalBorderLeft(masterPtr->tkwin); @@ -724,13 +714,12 @@ ArrangePacking(clientData) } /* - * Now that we've got the size of the frame for the window, - * compute the window's actual size and location using the - * fill, padding, and frame factors. The variables "borderX" - * and "borderY" are used to handle the differences between - * old-style packing and the new style (in old-style, iPadX - * and iPadY are always zero and padding is completely ignored - * except when computing frame size). + * Now that we've got the size of the frame for the window, compute + * the window's actual size and location using the fill, padding, and + * frame factors. The variables "borderX" and "borderY" are used to + * handle the differences between old-style packing and the new style + * (in old-style, iPadX and iPadY are always zero and padding is + * completely ignored except when computing frame size). */ if (slavePtr->flags & OLD_STYLE) { @@ -758,52 +747,52 @@ ArrangePacking(clientData) height = frameHeight - borderY; } switch (slavePtr->anchor) { - case TK_ANCHOR_N: - x = frameX + (borderLeft + frameWidth - width - borderRight)/2; - y = frameY + borderTop; - break; - case TK_ANCHOR_NE: - x = frameX + frameWidth - width - borderRight; - y = frameY + borderTop; - break; - case TK_ANCHOR_E: - x = frameX + frameWidth - width - borderRight; - y = frameY + (borderTop + frameHeight - height - borderBtm)/2; - break; - case TK_ANCHOR_SE: - x = frameX + frameWidth - width - borderRight; - y = frameY + frameHeight - height - borderBtm; - break; - case TK_ANCHOR_S: - x = frameX + (borderLeft + frameWidth - width - borderRight)/2; - y = frameY + frameHeight - height - borderBtm; - break; - case TK_ANCHOR_SW: - x = frameX + borderLeft; - y = frameY + frameHeight - height - borderBtm; - break; - case TK_ANCHOR_W: - x = frameX + borderLeft; - y = frameY + (borderTop + frameHeight - height - borderBtm)/2; - break; - case TK_ANCHOR_NW: - x = frameX + borderLeft; - y = frameY + borderTop; - break; - case TK_ANCHOR_CENTER: - x = frameX + (borderLeft + frameWidth - width - borderRight)/2; - y = frameY + (borderTop + frameHeight - height - borderBtm)/2; - break; - default: - panic("bad frame factor in ArrangePacking"); + case TK_ANCHOR_N: + x = frameX + (borderLeft + frameWidth - width - borderRight)/2; + y = frameY + borderTop; + break; + case TK_ANCHOR_NE: + x = frameX + frameWidth - width - borderRight; + y = frameY + borderTop; + break; + case TK_ANCHOR_E: + x = frameX + frameWidth - width - borderRight; + y = frameY + (borderTop + frameHeight - height - borderBtm)/2; + break; + case TK_ANCHOR_SE: + x = frameX + frameWidth - width - borderRight; + y = frameY + frameHeight - height - borderBtm; + break; + case TK_ANCHOR_S: + x = frameX + (borderLeft + frameWidth - width - borderRight)/2; + y = frameY + frameHeight - height - borderBtm; + break; + case TK_ANCHOR_SW: + x = frameX + borderLeft; + y = frameY + frameHeight - height - borderBtm; + break; + case TK_ANCHOR_W: + x = frameX + borderLeft; + y = frameY + (borderTop + frameHeight - height - borderBtm)/2; + break; + case TK_ANCHOR_NW: + x = frameX + borderLeft; + y = frameY + borderTop; + break; + case TK_ANCHOR_CENTER: + x = frameX + (borderLeft + frameWidth - width - borderRight)/2; + y = frameY + (borderTop + frameHeight - height - borderBtm)/2; + break; + default: + Tcl_Panic("bad frame factor in ArrangePacking"); } width -= slavePtr->doubleBw; height -= slavePtr->doubleBw; /* * The final step is to set the position, size, and mapped/unmapped - * state of the slave. If the slave is a child of the master, then - * do this here. Otherwise let Tk_MaintainGeometry do the work. + * state of the slave. If the slave is a child of the master, then do + * this here. Otherwise let Tk_MaintainGeometry do the work. */ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { @@ -821,8 +810,8 @@ ArrangePacking(clientData) } /* - * Don't map the slave if the master isn't mapped: wait - * until the master gets mapped later. + * Don't map the slave if the master isn't mapped: wait until + * the master gets mapped later. */ if (Tk_IsMapped(masterPtr->tkwin)) { @@ -840,9 +829,9 @@ ArrangePacking(clientData) } /* - * Changes to the window's structure could cause almost anything - * to happen, including deleting the parent or child. If this - * happens, we'll be told to abort. + * Changes to the window's structure could cause almost anything to + * happen, including deleting the parent or child. If this happens, + * we'll be told to abort. */ if (abort) { @@ -850,7 +839,7 @@ ArrangePacking(clientData) } } - done: + done: masterPtr->abortPtr = NULL; Tcl_Release((ClientData) masterPtr); } @@ -860,13 +849,12 @@ ArrangePacking(clientData) * * XExpansion -- * - * Given a list of packed slaves, the first of which is packed - * on the left or right and is expandable, compute how much to - * expand the child. + * Given a list of packed slaves, the first of which is packed on the + * left or right and is expandable, compute how much to expand the child. * * Results: - * The return value is the number of additional pixels to give to - * the child. + * The return value is the number of additional pixels to give to the + * child. * * Side effects: * None. @@ -875,24 +863,23 @@ ArrangePacking(clientData) */ static int -XExpansion(slavePtr, cavityWidth) - register Packer *slavePtr; /* First in list of remaining - * slaves. */ - int cavityWidth; /* Horizontal space left for all - * remaining slaves. */ +XExpansion( + register Packer *slavePtr, /* First in list of remaining slaves. */ + int cavityWidth) /* Horizontal space left for all remaining + * slaves. */ { int numExpand, minExpand, curExpand; int childWidth; /* - * This procedure is tricky because windows packed top or bottom can - * be interspersed among expandable windows packed left or right. - * Scan through the list, keeping a running sum of the widths of - * all left and right windows (actually, count the cavity space not - * allocated) and a running count of all expandable left and right - * windows. At each top or bottom window, and at the end of the - * list, compute the expansion factor that seems reasonable at that - * point. Return the smallest factor seen at any of these points. + * This function is tricky because windows packed top or bottom can be + * interspersed among expandable windows packed left or right. Scan + * through the list, keeping a running sum of the widths of all left and + * right windows (actually, count the cavity space not allocated) and a + * running count of all expandable left and right windows. At each top or + * bottom window, and at the end of the list, compute the expansion factor + * that seems reasonable at that point. Return the smallest factor seen at + * any of these points. */ minExpand = cavityWidth; @@ -924,13 +911,12 @@ XExpansion(slavePtr, cavityWidth) * * YExpansion -- * - * Given a list of packed slaves, the first of which is packed - * on the top or bottom and is expandable, compute how much to - * expand the child. + * Given a list of packed slaves, the first of which is packed on the top + * or bottom and is expandable, compute how much to expand the child. * * Results: - * The return value is the number of additional pixels to give to - * the child. + * The return value is the number of additional pixels to give to the + * child. * * Side effects: * None. @@ -939,11 +925,10 @@ XExpansion(slavePtr, cavityWidth) */ static int -YExpansion(slavePtr, cavityHeight) - register Packer *slavePtr; /* First in list of remaining - * slaves. */ - int cavityHeight; /* Vertical space left for all - * remaining slaves. */ +YExpansion( + register Packer *slavePtr, /* First in list of remaining slaves. */ + int cavityHeight) /* Vertical space left for all remaining + * slaves. */ { int numExpand, minExpand, curExpand; int childHeight; @@ -981,30 +966,28 @@ YExpansion(slavePtr, cavityHeight) * * GetPacker -- * - * This internal procedure is used to locate a Packer - * structure for a given window, creating one if one - * doesn't exist already. + * This internal function is used to locate a Packer structure for a + * given window, creating one if one doesn't exist already. * * Results: - * The return value is a pointer to the Packer structure - * corresponding to tkwin. + * The return value is a pointer to the Packer structure corresponding to + * tkwin. * * Side effects: - * A new packer structure may be created. If so, then - * a callback is set up to clean things up when the - * window is deleted. + * A new packer structure may be created. If so, then a callback is set + * up to clean things up when the window is deleted. * *-------------------------------------------------------------- */ static Packer * -GetPacker(tkwin) - Tk_Window tkwin; /* Token for window for which - * packer structure is desired. */ +GetPacker( + Tk_Window tkwin) /* Token for window for which packer structure + * is desired. */ { register Packer *packPtr; Tcl_HashEntry *hPtr; - int new; + int isNew; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->packInit) { @@ -1013,13 +996,13 @@ GetPacker(tkwin) } /* - * See if there's already packer for this window. If not, - * then create a new one. + * See if there's already packer for this window. If not, then create a + * new one. */ - hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin, - &new); - if (!new) { + hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin, + &isNew); + if (!isNew) { return (Packer *) Tcl_GetHashValue(hPtr); } packPtr = (Packer *) ckalloc(sizeof(Packer)); @@ -1046,30 +1029,30 @@ GetPacker(tkwin) * * PackAfter -- * - * This procedure does most of the real work of adding - * one or more windows into the packing order for its parent. + * This function does most of the real work of adding one or more windows + * into the packing order for its master. * * Results: * A standard Tcl return value. * * Side effects: - * The geometry of the specified windows may change, both now and - * again in the future. + * The geometry of the specified windows may change, both now and again + * in the future. * *-------------------------------------------------------------- */ static int -PackAfter(interp, prevPtr, masterPtr, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Packer *prevPtr; /* Pack windows in argv just after this - * window; NULL means pack as first - * child of masterPtr. */ - Packer *masterPtr; /* Master in which to pack windows. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Array of lists, each containing 2 - * elements: window name and side - * against which to pack. */ +PackAfter( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Packer *prevPtr, /* Pack windows in argv just after this + * window; NULL means pack as first child of + * masterPtr. */ + Packer *masterPtr, /* Master in which to pack windows. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[]) /* Array of lists, each containing 2 elements: + * window name and side against which to + * pack. */ { register Packer *packPtr; Tk_Window tkwin, ancestor, parent; @@ -1078,24 +1061,23 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) int index, optionCount, c; /* - * Iterate over all of the window specifiers, each consisting of - * two arguments. The first argument contains the window name and - * the additional arguments contain options such as "top" or - * "padx 20". + * Iterate over all of the window specifiers, each consisting of two + * arguments. The first argument contains the window name and the + * additional arguments contain options such as "top" or "padx 20". */ for ( ; objc > 0; objc -= 2, objv += 2, prevPtr = packPtr) { if (objc < 2) { Tcl_AppendResult(interp, "wrong # args: window \"", Tcl_GetString(objv[0]), "\" should be followed by options", - (char *) NULL); + NULL); return TCL_ERROR; } /* - * Find the packer for the window to be packed, and make sure - * that the window in which it will be packed is either its - * or a descendant of its parent. + * Find the packer for the window to be packed, and make sure that the + * window in which it will be packed is either its or a descendant of + * its parent. */ if (TkGetWindowFromObj(interp, masterPtr->tkwin, objv[0], &tkwin) @@ -1109,10 +1091,9 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) break; } if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) { - badWindow: + badWindow: Tcl_AppendResult(interp, "can't pack ", Tcl_GetString(objv[0]), - " inside ", Tk_PathName(masterPtr->tkwin), - (char *) NULL); + " inside ", Tk_PathName(masterPtr->tkwin), NULL); return TCL_ERROR; } } @@ -1146,19 +1127,19 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) c = curOpt[0]; if ((c == 't') - && (strncmp(curOpt, "top", (unsigned) length)) == 0) { + && (strncmp(curOpt, "top", (size_t) length)) == 0) { packPtr->side = TOP; } else if ((c == 'b') - && (strncmp(curOpt, "bottom", (unsigned) length)) == 0) { + && (strncmp(curOpt, "bottom", (size_t) length)) == 0) { packPtr->side = BOTTOM; } else if ((c == 'l') - && (strncmp(curOpt, "left", (unsigned) length)) == 0) { + && (strncmp(curOpt, "left", (size_t) length)) == 0) { packPtr->side = LEFT; } else if ((c == 'r') - && (strncmp(curOpt, "right", (unsigned) length)) == 0) { + && (strncmp(curOpt, "right", (size_t) length)) == 0) { packPtr->side = RIGHT; } else if ((c == 'e') - && (strncmp(curOpt, "expand", (unsigned) length)) == 0) { + && (strncmp(curOpt, "expand", (size_t) length)) == 0) { packPtr->flags |= EXPAND; } else if ((c == 'f') && (strcmp(curOpt, "fill")) == 0) { @@ -1169,10 +1150,10 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) packPtr->flags |= FILLY; } else if ((c == 'p') && (strcmp(curOpt, "padx")) == 0) { if (optionCount < (index+2)) { - missingPad: + missingPad: Tcl_AppendResult(interp, "wrong # args: \"", curOpt, "\" option must be followed by screen distance", - (char *) NULL); + NULL); return TCL_ERROR; } if (TkParsePadAmount(interp, tkwin, options[index+1], @@ -1196,11 +1177,10 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) packPtr->iPadY = 0; index++; } else if ((c == 'f') && (length > 1) - && (strncmp(curOpt, "frame", (unsigned) length) == 0)) { + && (strncmp(curOpt, "frame", (size_t) length) == 0)) { if (optionCount < (index+2)) { Tcl_AppendResult(interp, "wrong # args: \"frame\" ", - "option must be followed by anchor point", - (char *) NULL); + "option must be followed by anchor point", NULL); return TCL_ERROR; } if (Tk_GetAnchorFromObj(interp, options[index+1], @@ -1210,9 +1190,8 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) index++; } else { Tcl_AppendResult(interp, "bad option \"", curOpt, - "\": should be top, bottom, left, right, ", - "expand, fill, fillx, filly, padx, pady, or frame", - (char *) NULL); + "\": should be top, bottom, left, right, expand, ", + "fill, fillx, filly, padx, pady, or frame", NULL); return TCL_ERROR; } } @@ -1232,11 +1211,10 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) } Unlink(packPtr); } - + /* - * Add the window in the correct place in its parent's - * packing order, then make sure that the window is - * managed by us. + * Add the window in the correct place in its master's packing + * order, then make sure that the window is managed by us. */ packPtr->masterPtr = masterPtr; @@ -1252,8 +1230,7 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) } /* - * Arrange for the parent to be re-packed at the first - * idle moment. + * Arrange for the master to be re-packed at the first idle moment. */ if (masterPtr->abortPtr != NULL) { @@ -1271,20 +1248,20 @@ PackAfter(interp, prevPtr, masterPtr, objc, objv) * * Unlink -- * - * Remove a packer from its parent's list of slaves. + * Remove a packer from its master's list of slaves. * * Results: * None. * * Side effects: - * The parent will be scheduled for repacking. + * The master will be scheduled for repacking. * *---------------------------------------------------------------------- */ static void -Unlink(packPtr) - register Packer *packPtr; /* Window to unlink. */ +Unlink( + register Packer *packPtr) /* Window to unlink. */ { register Packer *masterPtr, *packPtr2; @@ -1297,7 +1274,7 @@ Unlink(packPtr) } else { for (packPtr2 = masterPtr->slavePtr; ; packPtr2 = packPtr2->nextPtr) { if (packPtr2 == NULL) { - panic("Unlink couldn't find previous window"); + Tcl_Panic("Unlink couldn't find previous window"); } if (packPtr2->nextPtr == packPtr) { packPtr2->nextPtr = packPtr->nextPtr; @@ -1321,9 +1298,9 @@ Unlink(packPtr) * * DestroyPacker -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a packer at a safe time - * (when no-one is using it anymore). + * This function is invoked by Tcl_EventuallyFree or Tcl_Release to clean + * up the internal structure of a packer at a safe time (when no-one is + * using it anymore). * * Results: * None. @@ -1335,9 +1312,9 @@ Unlink(packPtr) */ static void -DestroyPacker(memPtr) - char *memPtr; /* Info about packed window that - * is now dead. */ +DestroyPacker( + char *memPtr) /* Info about packed window that is now + * dead. */ { register Packer *packPtr = (Packer *) memPtr; ckfree((char *) packPtr); @@ -1348,25 +1325,24 @@ DestroyPacker(memPtr) * * PackStructureProc -- * - * This procedure is invoked by the Tk event dispatcher in response - * to StructureNotify events. + * This function is invoked by the Tk event dispatcher in response to + * StructureNotify events. * * Results: * None. * * Side effects: * If a window was just deleted, clean up all its packer-related - * information. If it was just resized, repack its slaves, if - * any. + * information. If it was just resized, repack its slaves, if any. * *---------------------------------------------------------------------- */ static void -PackStructureProc(clientData, eventPtr) - ClientData clientData; /* Our information about window - * referred to by eventPtr. */ - XEvent *eventPtr; /* Describes what just happened. */ +PackStructureProc( + ClientData clientData, /* Our information about window referred to by + * eventPtr. */ + XEvent *eventPtr) /* Describes what just happened. */ { register Packer *packPtr = (Packer *) clientData; @@ -1376,9 +1352,9 @@ PackStructureProc(clientData, eventPtr) packPtr->flags |= REQUESTED_REPACK; Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr); } - if (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width) { - if ((packPtr->masterPtr != NULL) - && !(packPtr->masterPtr->flags & REQUESTED_REPACK)) { + if ((packPtr->masterPtr != NULL) + && (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width)) { + if (!(packPtr->masterPtr->flags & REQUESTED_REPACK)) { packPtr->doubleBw = 2*Tk_Changes(packPtr->tkwin)->border_width; packPtr->masterPtr->flags |= REQUESTED_REPACK; Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr->masterPtr); @@ -1390,20 +1366,23 @@ PackStructureProc(clientData, eventPtr) if (packPtr->masterPtr != NULL) { Unlink(packPtr); } + for (slavePtr = packPtr->slavePtr; slavePtr != NULL; slavePtr = nextPtr) { - Tk_ManageGeometry(slavePtr->tkwin, (Tk_GeomMgr *) NULL, + Tk_ManageGeometry(slavePtr->tkwin, NULL, (ClientData) NULL); Tk_UnmapWindow(slavePtr->tkwin); slavePtr->masterPtr = NULL; nextPtr = slavePtr->nextPtr; slavePtr->nextPtr = NULL; } + if (packPtr->tkwin != NULL) { TkDisplay *dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr; Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable, (char *) packPtr->tkwin)); } + if (packPtr->flags & REQUESTED_REPACK) { Tcl_CancelIdleCall(ArrangePacking, (ClientData) packPtr); } @@ -1411,8 +1390,8 @@ PackStructureProc(clientData, eventPtr) Tcl_EventuallyFree((ClientData) packPtr, DestroyPacker); } else if (eventPtr->type == MapNotify) { /* - * When a master gets mapped, must redo the geometry computation - * so that all of its slaves get remapped. + * When a master gets mapped, must redo the geometry computation so + * that all of its slaves get remapped. */ if ((packPtr->slavePtr != NULL) @@ -1424,10 +1403,10 @@ PackStructureProc(clientData, eventPtr) register Packer *packPtr2; /* - * Unmap all of the slaves when the master gets unmapped, - * so that they don't bother to keep redisplaying - * themselves. + * Unmap all of the slaves when the master gets unmapped, so that they + * don't bother to keep redisplaying themselves. */ + for (packPtr2 = packPtr->slavePtr; packPtr2 != NULL; packPtr2 = packPtr2->nextPtr) { Tk_UnmapWindow(packPtr2->tkwin); @@ -1440,13 +1419,13 @@ PackStructureProc(clientData, eventPtr) * * ConfigureSlaves -- * - * This implements the guts of the "pack configure" command. Given - * a list of slaves and configuration options, it arranges for the - * packer to manage the slaves and sets the specified options. + * This implements the guts of the "pack configure" command. Given a list + * of slaves and configuration options, it arranges for the packer to + * manage the slaves and sets the specified options. * * Results: - * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is - * returned and the interp's result is set to contain an error message. + * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned + * and the interp's result is set to contain an error message. * * Side effects: * Slave windows get taken over by the packer. @@ -1455,16 +1434,15 @@ PackStructureProc(clientData, eventPtr) */ static int -ConfigureSlaves(interp, tkwin, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Any window in application containing - * slaves. Used to look up slave names. */ - int objc; /* Number of elements in argv. */ - Tcl_Obj *CONST objv[]; /* Argument objects: contains one or more - * window names followed by any number - * of "option value" pairs. Caller must - * make sure that there is at least one - * window name. */ +ConfigureSlaves( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Any window in application containing + * slaves. Used to look up slave names. */ + int objc, /* Number of elements in argv. */ + Tcl_Obj *CONST objv[]) /* Argument objects: contains one or more + * window names followed by any number of + * "option value" pairs. Caller must make sure + * that there is at least one window name. */ { Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr; Tk_Window other, slave, parent, ancestor; @@ -1472,7 +1450,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) char *string; static CONST char *optionStrings[] = { "-after", "-anchor", "-before", "-expand", "-fill", - "-in", "-ipadx", "-ipady", "-padx", "-pady", "-side", (char *) NULL }; + "-in", "-ipadx", "-ipady", "-padx", "-pady", "-side", NULL }; enum options { CONF_AFTER, CONF_ANCHOR, CONF_BEFORE, CONF_EXPAND, CONF_FILL, CONF_IN, CONF_IPADX, CONF_IPADY, CONF_PADX, CONF_PADY, CONF_SIDE }; @@ -1491,13 +1469,12 @@ ConfigureSlaves(interp, tkwin, objc, objv) /* * Iterate over all of the slave windows, parsing the configuration - * options for each slave. It's a bit wasteful to re-parse the - * options for each slave, but things get too messy if we try to - * parse the arguments just once at the beginning. For example, - * if a slave already is packed we want to just change a few - * existing values without resetting everything. If there are - * multiple windows, the -after, -before, and -in options only - * get processed for the first window. + * options for each slave. It's a bit wasteful to re-parse the options for + * each slave, but things get too messy if we try to parse the arguments + * just once at the beginning. For example, if a slave already is packed + * we want to just change a few existing values without resetting + * everything. If there are multiple windows, the -after, -before, and -in + * options only get processed for the first window. */ masterPtr = NULL; @@ -1509,16 +1486,16 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (Tk_TopWinHierarchy(slave)) { Tcl_AppendResult(interp, "can't pack \"", Tcl_GetString(objv[j]), - "\": it's a top-level window", (char *) NULL); + "\": it's a top-level window", NULL); return TCL_ERROR; } slavePtr = GetPacker(slave); slavePtr->flags &= ~OLD_STYLE; /* - * If the slave isn't currently packed, reset all of its - * configuration information to default values (there could - * be old values left from a previous packing). + * If the slave isn't currently packed, reset all of its configuration + * information to default values (there could be old values left from + * a previous packing). */ if (slavePtr->masterPtr == NULL) { @@ -1534,14 +1511,16 @@ ConfigureSlaves(interp, tkwin, objc, objv) if ((i+2) > objc) { Tcl_AppendResult(interp, "extra option \"", Tcl_GetString(objv[i]), - "\" (option with no value?)", (char *) NULL); + "\" (option with no value?)", NULL); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - if (index == CONF_AFTER) { + + switch ((enum options) index) { + case CONF_AFTER: if (j == 0) { if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != TCL_OK) { @@ -1549,21 +1528,23 @@ ConfigureSlaves(interp, tkwin, objc, objv) } prevPtr = GetPacker(other); if (prevPtr->masterPtr == NULL) { - notPacked: + notPacked: Tcl_AppendResult(interp, "window \"", Tcl_GetString(objv[i+1]), - "\" isn't packed", (char *) NULL); + "\" isn't packed", NULL); return TCL_ERROR; } masterPtr = prevPtr->masterPtr; positionGiven = 1; } - } else if (index == CONF_ANCHOR) { + break; + case CONF_ANCHOR: if (Tk_GetAnchorFromObj(interp, objv[i+1], &slavePtr->anchor) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_BEFORE) { + break; + case CONF_BEFORE: if (j == 0) { if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != TCL_OK) { @@ -1584,7 +1565,8 @@ ConfigureSlaves(interp, tkwin, objc, objv) } positionGiven = 1; } - } else if (index == CONF_EXPAND) { + break; + case CONF_EXPAND: if (Tcl_GetBooleanFromObj(interp, objv[i+1], &tmp) != TCL_OK) { return TCL_ERROR; } @@ -1592,7 +1574,8 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (tmp) { slavePtr->flags |= EXPAND; } - } else if (index == CONF_FILL) { + break; + case CONF_FILL: string = Tcl_GetString(objv[i+1]); if (strcmp(string, "none") == 0) { slavePtr->flags &= ~(FILLX|FILLY); @@ -1604,10 +1587,11 @@ ConfigureSlaves(interp, tkwin, objc, objv) slavePtr->flags |= FILLX|FILLY; } else { Tcl_AppendResult(interp, "bad fill style \"", string, - "\": must be none, x, y, or both", (char *) NULL); + "\": must be none, x, y, or both", NULL); return TCL_ERROR; } - } else if (index == CONF_IN) { + break; + case CONF_IN: if (j == 0) { if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != TCL_OK) { @@ -1622,53 +1606,57 @@ ConfigureSlaves(interp, tkwin, objc, objv) } positionGiven = 1; } - } else if (index == CONF_IPADX) { + break; + case CONF_IPADX: if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) != TCL_OK) || (tmp < 0)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad ipadx value \"", Tcl_GetString(objv[i+1]), - "\": must be positive screen distance", - (char *) NULL); + "\": must be positive screen distance", NULL); return TCL_ERROR; } slavePtr->iPadX = tmp * 2; - } else if (index == CONF_IPADY) { + break; + case CONF_IPADY: if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) != TCL_OK) || (tmp < 0)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad ipady value \"", Tcl_GetString(objv[i+1]), - "\": must be positive screen distance", - (char *) NULL); + "\": must be positive screen distance", NULL); return TCL_ERROR; } slavePtr->iPadY = tmp * 2; - } else if (index == CONF_PADX) { + break; + case CONF_PADX: if (TkParsePadAmount(interp, slave, objv[i+1], &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_PADY) { + break; + case CONF_PADY: if (TkParsePadAmount(interp, slave, objv[i+1], &slavePtr->padTop, &slavePtr->padY) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_SIDE) { + break; + case CONF_SIDE: if (Tcl_GetIndexFromObj(interp, objv[i+1], sideNames, "side", TCL_EXACT, &side) != TCL_OK) { return TCL_ERROR; } slavePtr->side = (Side) side; + break; } } /* - * If no position in a packing list was specified and the slave - * is already packed, then leave it in its current location in - * its current packing list. + * If no position in a packing list was specified and the slave is + * already packed, then leave it in its current location in its + * current packing list. */ if (!positionGiven && (slavePtr->masterPtr != NULL)) { @@ -1677,21 +1665,22 @@ ConfigureSlaves(interp, tkwin, objc, objv) } /* - * If the slave is going to be put back after itself then - * skip the whole operation, since it won't work anyway. + * If the slave is going to be put back after itself or the same -in + * window is passed in again, then just skip the whole operation, + * since it won't work anyway. */ if (prevPtr == slavePtr) { masterPtr = slavePtr->masterPtr; goto scheduleLayout; } - + /* - * If none of the "-in", "-before", or "-after" options has - * been specified, arrange for the slave to go at the end of - * the order for its parent. + * If none of the "-in", "-before", or "-after" options has been + * specified, arrange for the slave to go at the end of the order for + * its parent. */ - + if (!positionGiven) { masterPtr = GetPacker(Tk_Parent(slave)); prevPtr = masterPtr->slavePtr; @@ -1703,11 +1692,11 @@ ConfigureSlaves(interp, tkwin, objc, objv) } /* - * Make sure that the slave's parent is either the master or - * an ancestor of the master, and that the master and slave - * aren't the same. + * Make sure that the slave's parent is either the master or an + * ancestor of the master, and that the master and slave aren't the + * same. */ - + parent = Tk_Parent(slave); for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { @@ -1715,20 +1704,19 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (Tk_TopWinHierarchy(ancestor)) { Tcl_AppendResult(interp, "can't pack ", Tcl_GetString(objv[j]), - " inside ", Tk_PathName(masterPtr->tkwin), - (char *) NULL); + " inside ", Tk_PathName(masterPtr->tkwin), NULL); return TCL_ERROR; } } if (slave == masterPtr->tkwin) { Tcl_AppendResult(interp, "can't pack ", Tcl_GetString(objv[j]), - " inside itself", (char *) NULL); + " inside itself", NULL); return TCL_ERROR; } /* - * Unpack the slave if it's currently packed, then position it - * after prevPtr. + * Unpack the slave if it's currently packed, then position it after + * prevPtr. */ if (slavePtr->masterPtr != NULL) { @@ -1752,11 +1740,10 @@ ConfigureSlaves(interp, tkwin, objc, objv) prevPtr = slavePtr; /* - * Arrange for the parent to be re-packed at the first - * idle moment. + * Arrange for the master to be re-packed at the first idle moment. */ - scheduleLayout: + scheduleLayout: if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } @@ -1767,3 +1754,11 @@ ConfigureSlaves(interp, tkwin, objc, objv) } return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkPanedWindow.c b/generic/tkPanedWindow.c index 57670ba..68d62d7 100644 --- a/generic/tkPanedWindow.c +++ b/generic/tkPanedWindow.c @@ -1,23 +1,23 @@ -/* +/* * tkPanedWindow.c -- * - * This module implements "paned window" widgets that are object - * based. A "paned window" is a widget that manages the geometry for - * some number of other widgets, placing a movable "sash" between them, - * which can be used to alter the relative sizes of adjacent widgets. + * This module implements "paned window" widgets that are object based. A + * "paned window" is a widget that manages the geometry for some number + * of other widgets, placing a movable "sash" between them, which can be + * used to alter the relative sizes of adjacent widgets. * * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 2000 Ajuba Solutions. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "default.h" #include "tkInt.h" -/* Flag values for "sticky"ness The 16 combinations subsume the packer's +/* + * Flag values for "sticky"ness. The 16 combinations subsume the packer's * notion of anchor and fill. * * STICK_NORTH This window sticks to the top of its cavity. @@ -30,16 +30,44 @@ #define STICK_EAST 2 #define STICK_SOUTH 4 #define STICK_WEST 8 + /* * The following table defines the legal values for the -orient option. */ static char *orientStrings[] = { - "horizontal", "vertical", (char *) NULL + "horizontal", "vertical", NULL }; enum orient { ORIENT_HORIZONTAL, ORIENT_VERTICAL }; +/* + * The following table defines the legal values for the -stretch option. + */ + +static char *stretchStrings[] = { + "always", "first", "last", "middle", "never", NULL +}; + +enum stretch { + STRETCH_ALWAYS, /* Always give extra space to this pane. */ + STRETCH_FIRST, /* Give extra space to pane if it is first. */ + STRETCH_LAST, /* Give extra space to pane if it is last. */ + STRETCH_MIDDLE, /* Give extra space to pane only if it is + * neither first nor last. */ + STRETCH_NEVER /* Never give extra space to this pane. */ +}; + +/* + * Codify the stretchiness rule in one place. + */ + +#define IsStretchable(stretch,index,first,last) \ + (((stretch) == STRETCH_ALWAYS) || \ + ((stretch) == STRETCH_FIRST && (index) == (first)) || \ + ((stretch) == STRETCH_LAST && (index) == (last)) || \ + ((stretch) == STRETCH_MIDDLE && (index) != (first) && (index) != (last))) + typedef struct { Tk_OptionTable pwOptions; /* Token for paned window option table. */ Tk_OptionTable slaveOpts; /* Token for slave cget option table. */ @@ -51,35 +79,38 @@ typedef struct { */ typedef struct Slave { - Tk_Window tkwin; /* Window being managed. */ - - int minSize; /* Minimum size of this pane, on the - * relevant axis, in pixels. */ - int padx; /* Additional padding requested for - * slave, in the x dimension. */ - int pady; /* Additional padding requested for - * slave, in the y dimension. */ - Tcl_Obj *widthPtr, *heightPtr; /* Tcl_Obj rep's of slave width/height, - * to allow for null values. */ - int width; /* Slave width. */ - int height; /* Slave height. */ - int sticky; /* Sticky string. */ - int x, y; /* Coordinates of the widget. */ - int paneWidth, paneHeight; /* Pane dimensions (may be different - * from slave width/height). */ - int sashx, sashy; /* Coordinates of the sash of the - * right or bottom of this pane. */ - int markx, marky; /* Coordinates of the last mark set - * for the sash. */ - int handlex, handley; /* Coordinates of the sash handle. */ - struct PanedWindow *masterPtr; /* Paned window managing the window. */ - Tk_Window after; /* Placeholder for parsing options. */ - Tk_Window before; /* Placeholder for parsing options. */ + Tk_Window tkwin; /* Window being managed. */ + int minSize; /* Minimum size of this pane, on the relevant + * axis, in pixels. */ + int padx; /* Additional padding requested for slave, in + * the x dimension. */ + int pady; /* Additional padding requested for slave, in + * the y dimension. */ + Tcl_Obj *widthPtr, *heightPtr; + /* Tcl_Obj rep's of slave width/height, to + * allow for null values. */ + int width; /* Slave width. */ + int height; /* Slave height. */ + int sticky; /* Sticky string. */ + int x, y; /* Coordinates of the widget. */ + int paneWidth, paneHeight; /* Pane dimensions (may be different from + * slave width/height). */ + int sashx, sashy; /* Coordinates of the sash of the right or + * bottom of this pane. */ + int markx, marky; /* Coordinates of the last mark set for the + * sash. */ + int handlex, handley; /* Coordinates of the sash handle. */ + enum stretch stretch; /* Controls how slave grows/shrinks */ + int hide; /* Controls visibility of pane */ + struct PanedWindow *masterPtr; + /* Paned window managing the window. */ + Tk_Window after; /* Placeholder for parsing options. */ + Tk_Window before; /* Placeholder for parsing options. */ } Slave; /* - * A data structure of the following type is kept for each paned window - * widget managed by this file: + * A data structure of the following type is kept for each paned window widget + * managed by this file: */ typedef struct PanedWindow { @@ -101,7 +132,6 @@ typedef struct PanedWindow { Tk_Cursor cursor; /* Current cursor for window, or None. */ int resizeOpaque; /* Boolean indicating whether resize should be * opaque or rubberband style. */ - int sashRelief; /* Relief used to draw sash. */ int sashWidth; /* Width of each sash, in pixels. */ Tcl_Obj *sashWidthPtr; /* Tcl_Obj rep for sash width. */ @@ -114,7 +144,6 @@ typedef struct PanedWindow { int handlePad; /* Distance from border to draw handle. */ Tcl_Obj *handleSizePtr; /* Tcl_Obj rep for handle size. */ Tk_Cursor sashCursor; /* Cursor used when mouse is above a sash. */ - GC gc; /* Graphics context for copying from * off-screen pixmap onto screen. */ int proxyx, proxyy; /* Proxy x,y coordinates. */ @@ -127,11 +156,11 @@ typedef struct PanedWindow { /* * Flags used for paned windows: * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has - * been queued to redraw this window. + * REDRAW_PENDING: Non-zero means a DoWhenIdle handler has been + * queued to redraw this window. * - * WIDGET_DELETED: Non-zero means that the paned window has - * been, or is in the process of being, deleted. + * WIDGET_DELETED: Non-zero means that the paned window has been, + * or is in the process of being, deleted. * * RESIZE_PENDING: Non-zero means that the window might need to * change its size (or the size of its panes) @@ -147,59 +176,63 @@ typedef struct PanedWindow { #define RESIZE_PENDING 0x0020 /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -int Tk_PanedWindowObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[])); -static void PanedWindowCmdDeletedProc _ANSI_ARGS_((ClientData clientData)); -static int ConfigurePanedWindow _ANSI_ARGS_((Tcl_Interp *interp, - PanedWindow *pwPtr, int objc, Tcl_Obj *CONST objv[])); -static void DestroyPanedWindow _ANSI_ARGS_((PanedWindow *pwPtr)); -static void DisplayPanedWindow _ANSI_ARGS_((ClientData clientData)); -static void PanedWindowEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void ProxyWindowEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void DisplayProxyWindow _ANSI_ARGS_((ClientData clientData)); -static void PanedWindowWorldChanged _ANSI_ARGS_((ClientData instanceData)); -static int PanedWindowWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *, int objc, Tcl_Obj * CONST objv[])); -static void PanedWindowLostSlaveProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void PanedWindowReqProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void ArrangePanes _ANSI_ARGS_((ClientData clientData)); -static void Unlink _ANSI_ARGS_((Slave *slavePtr)); -static Slave * GetPane _ANSI_ARGS_((PanedWindow *pwPtr, Tk_Window tkwin)); -static void SlaveStructureProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int PanedWindowSashCommand _ANSI_ARGS_((PanedWindow *pwPtr, - Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[])); -static int PanedWindowProxyCommand _ANSI_ARGS_((PanedWindow *pwPtr, - Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[])); -static void ComputeGeometry _ANSI_ARGS_((PanedWindow *pwPtr)); -static int ConfigureSlaves _ANSI_ARGS_((PanedWindow *pwPtr, - Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[])); -static void DestroyOptionTables _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp)); -static int SetSticky _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, Tk_Window tkwin, - Tcl_Obj **value, char *recordPtr, int internalOffset, - char *oldInternalPtr, int flags)); -static Tcl_Obj *GetSticky _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, - char *recordPtr, int internalOffset)); -static void RestoreSticky _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *internalPtr, - char *oldInternalPtr)); -static void AdjustForSticky _ANSI_ARGS_((int sticky, int cavityWidth, - int cavityHeight, int *xPtr, int *yPtr, - int *slaveWidthPtr, int *slaveHeightPtr)); -static void MoveSash _ANSI_ARGS_((PanedWindow *pwPtr, int sash, int diff)); -static int ObjectIsEmpty _ANSI_ARGS_((Tcl_Obj *objPtr)); -static char * ComputeSlotAddress _ANSI_ARGS_((char *recordPtr, int offset)); -static int PanedWindowIdentifyCoords _ANSI_ARGS_((PanedWindow *pwPtr, - Tcl_Interp *interp, int x, int y)); +int Tk_PanedWindowObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static void PanedWindowCmdDeletedProc(ClientData clientData); +static int ConfigurePanedWindow(Tcl_Interp *interp, + PanedWindow *pwPtr, int objc, + Tcl_Obj *CONST objv[]); +static void DestroyPanedWindow(PanedWindow *pwPtr); +static void DisplayPanedWindow(ClientData clientData); +static void PanedWindowEventProc(ClientData clientData, + XEvent *eventPtr); +static void ProxyWindowEventProc(ClientData clientData, + XEvent *eventPtr); +static void DisplayProxyWindow(ClientData clientData); +static void PanedWindowWorldChanged(ClientData instanceData); +static int PanedWindowWidgetObjCmd(ClientData clientData, + Tcl_Interp *, int objc, Tcl_Obj * CONST objv[]); +static void PanedWindowLostSlaveProc(ClientData clientData, + Tk_Window tkwin); +static void PanedWindowReqProc(ClientData clientData, + Tk_Window tkwin); +static void ArrangePanes(ClientData clientData); +static void Unlink(Slave *slavePtr); +static Slave * GetPane(PanedWindow *pwPtr, Tk_Window tkwin); +static void SlaveStructureProc(ClientData clientData, + XEvent *eventPtr); +static int PanedWindowSashCommand(PanedWindow *pwPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj * CONST objv[]); +static int PanedWindowProxyCommand(PanedWindow *pwPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj * CONST objv[]); +static void ComputeGeometry(PanedWindow *pwPtr); +static int ConfigureSlaves(PanedWindow *pwPtr, + Tcl_Interp *interp, int objc, + Tcl_Obj * CONST objv[]); +static void DestroyOptionTables(ClientData clientData, + Tcl_Interp *interp); +static int SetSticky(ClientData clientData, Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj **value, char *recordPtr, + int internalOffset, char *oldInternalPtr, + int flags); +static Tcl_Obj * GetSticky(ClientData clientData, Tk_Window tkwin, + char *recordPtr, int internalOffset); +static void RestoreSticky(ClientData clientData, Tk_Window tkwin, + char *internalPtr, char *oldInternalPtr); +static void AdjustForSticky(int sticky, int cavityWidth, + int cavityHeight, int *xPtr, int *yPtr, + int *slaveWidthPtr, int *slaveHeightPtr); +static void MoveSash(PanedWindow *pwPtr, int sash, int diff); +static int ObjectIsEmpty(Tcl_Obj *objPtr); +static char * ComputeSlotAddress(char *recordPtr, int offset); +static int PanedWindowIdentifyCoords(PanedWindow *pwPtr, + Tcl_Interp *interp, int x, int y); /* * Sashes are between panes only, so there is one less sash than slaves @@ -208,7 +241,7 @@ static int PanedWindowIdentifyCoords _ANSI_ARGS_((PanedWindow *pwPtr, #define ValidSashIndex(pwPtr, sash) \ (((sash) >= 0) && ((sash) < ((pwPtr)->numSlaves-1))) -static Tk_GeomMgr panedWindowMgrType = { +static const Tk_GeomMgr panedWindowMgrType = { "panedwindow", /* name */ PanedWindowReqProc, /* requestProc */ PanedWindowLostSlaveProc, /* lostSlaveProc */ @@ -226,31 +259,31 @@ static Tk_GeomMgr panedWindowMgrType = { */ static Tk_ObjCustomOption stickyOption = { - "sticky", /* name */ - SetSticky, /* setProc */ - GetSticky, /* getProc */ - RestoreSticky, /* restoreProc */ - (Tk_CustomOptionFreeProc *)NULL, /* freeProc */ + "sticky", /* name */ + SetSticky, /* setProc */ + GetSticky, /* getProc */ + RestoreSticky, /* restoreProc */ + NULL, /* freeProc */ 0 }; -static Tk_OptionSpec optionSpecs[] = { +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", DEF_PANEDWINDOW_BG_COLOR, -1, Tk_Offset(PanedWindow, background), 0, (ClientData) DEF_PANEDWINDOW_BG_MONO}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background"}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth"}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background"}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_PANEDWINDOW_BORDERWIDTH, -1, Tk_Offset(PanedWindow, borderWidth), - 0, 0, GEOMETRY}, + 0, 0, GEOMETRY}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_PANEDWINDOW_CURSOR, -1, Tk_Offset(PanedWindow, cursor), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-handlepad", "handlePad", "HandlePad", DEF_PANEDWINDOW_HANDLEPAD, -1, Tk_Offset(PanedWindow, handlePad), - 0, 0, GEOMETRY}, + 0, 0, GEOMETRY}, {TK_OPTION_PIXELS, "-handlesize", "handleSize", "HandleSize", DEF_PANEDWINDOW_HANDLESIZE, Tk_Offset(PanedWindow, handleSizePtr), Tk_Offset(PanedWindow, handleSize), 0, 0, GEOMETRY}, @@ -259,9 +292,9 @@ static Tk_OptionSpec optionSpecs[] = { Tk_Offset(PanedWindow, height), TK_OPTION_NULL_OK, 0, GEOMETRY}, {TK_OPTION_BOOLEAN, "-opaqueresize", "opaqueResize", "OpaqueResize", DEF_PANEDWINDOW_OPAQUERESIZE, -1, - Tk_Offset(PanedWindow, resizeOpaque), 0, 0, 0}, + Tk_Offset(PanedWindow, resizeOpaque), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", - DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient), + DEF_PANEDWINDOW_ORIENT, -1, Tk_Offset(PanedWindow, orient), 0, (ClientData) orientStrings, GEOMETRY}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_PANEDWINDOW_RELIEF, -1, Tk_Offset(PanedWindow, relief), 0, 0, 0}, @@ -270,55 +303,59 @@ static Tk_OptionSpec optionSpecs[] = { TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-sashpad", "sashPad", "SashPad", DEF_PANEDWINDOW_SASHPAD, -1, Tk_Offset(PanedWindow, sashPad), - 0, 0, GEOMETRY}, + 0, 0, GEOMETRY}, {TK_OPTION_RELIEF, "-sashrelief", "sashRelief", "Relief", DEF_PANEDWINDOW_SASHRELIEF, -1, Tk_Offset(PanedWindow, sashRelief), - 0, 0, 0}, + 0, 0, 0}, {TK_OPTION_PIXELS, "-sashwidth", "sashWidth", "Width", DEF_PANEDWINDOW_SASHWIDTH, Tk_Offset(PanedWindow, sashWidthPtr), Tk_Offset(PanedWindow, sashWidth), 0, 0, GEOMETRY}, {TK_OPTION_BOOLEAN, "-showhandle", "showHandle", "ShowHandle", DEF_PANEDWINDOW_SHOWHANDLE, -1, Tk_Offset(PanedWindow, showHandle), - 0, 0, GEOMETRY}, + 0, 0, GEOMETRY}, {TK_OPTION_PIXELS, "-width", "width", "Width", DEF_PANEDWINDOW_WIDTH, Tk_Offset(PanedWindow, widthPtr), Tk_Offset(PanedWindow, width), TK_OPTION_NULL_OK, 0, GEOMETRY}, {TK_OPTION_END} }; -static Tk_OptionSpec slaveOptionSpecs[] = { - {TK_OPTION_WINDOW, "-after", (char *) NULL, (char *) NULL, +static const Tk_OptionSpec slaveOptionSpecs[] = { + {TK_OPTION_WINDOW, "-after", NULL, NULL, DEF_PANEDWINDOW_PANE_AFTER, -1, Tk_Offset(Slave, after), - TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_WINDOW, "-before", (char *) NULL, (char *) NULL, - DEF_PANEDWINDOW_PANE_BEFORE, -1, Tk_Offset(Slave, before), - TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_PIXELS, "-height", (char *) NULL, (char *) NULL, + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_WINDOW, "-before", NULL, NULL, + DEF_PANEDWINDOW_PANE_BEFORE, -1, Tk_Offset(Slave, before), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_PIXELS, "-height", NULL, NULL, DEF_PANEDWINDOW_PANE_HEIGHT, Tk_Offset(Slave, heightPtr), - Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_PIXELS, "-minsize", (char *) NULL, (char *) NULL, + Tk_Offset(Slave, height), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide", + DEF_PANEDWINDOW_PANE_HIDE, -1, Tk_Offset(Slave, hide), 0,0,GEOMETRY}, + {TK_OPTION_PIXELS, "-minsize", NULL, NULL, DEF_PANEDWINDOW_PANE_MINSIZE, -1, Tk_Offset(Slave, minSize), 0, 0, 0}, - {TK_OPTION_PIXELS, "-padx", (char *) NULL, (char *) NULL, + {TK_OPTION_PIXELS, "-padx", NULL, NULL, DEF_PANEDWINDOW_PANE_PADX, -1, Tk_Offset(Slave, padx), 0, 0, 0}, - {TK_OPTION_PIXELS, "-pady", (char *) NULL, (char *) NULL, + {TK_OPTION_PIXELS, "-pady", NULL, NULL, DEF_PANEDWINDOW_PANE_PADY, -1, Tk_Offset(Slave, pady), 0, 0, 0}, - {TK_OPTION_CUSTOM, "-sticky", (char *) NULL, (char *) NULL, + {TK_OPTION_CUSTOM, "-sticky", NULL, NULL, DEF_PANEDWINDOW_PANE_STICKY, -1, Tk_Offset(Slave, sticky), 0, - (ClientData) &stickyOption, 0}, - {TK_OPTION_PIXELS, "-width", (char *) NULL, (char *) NULL, + (ClientData) &stickyOption, 0}, + {TK_OPTION_STRING_TABLE, "-stretch", "stretch", "Stretch", + DEF_PANEDWINDOW_PANE_STRETCH, -1, Tk_Offset(Slave, stretch), 0, + (ClientData) stretchStrings, 0}, + {TK_OPTION_PIXELS, "-width", NULL, NULL, DEF_PANEDWINDOW_PANE_WIDTH, Tk_Offset(Slave, widthPtr), - Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0}, + Tk_Offset(Slave, width), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_END} }; - /* *-------------------------------------------------------------- * * Tk_PanedWindowObjCmd -- * - * This procedure is invoked to process the "panedwindow" Tcl - * command. It creates a new "panedwindow" widget. + * This function is invoked to process the "panedwindow" Tcl command. It + * creates a new "panedwindow" widget. * * Results: * A standard Tcl result. @@ -330,11 +367,11 @@ static Tk_OptionSpec slaveOptionSpecs[] = { */ int -Tk_PanedWindowObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +Tk_PanedWindowObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj * CONST objv[]) /* Argument objects. */ { PanedWindow *pwPtr; Tk_Window tkwin, parent; @@ -346,27 +383,35 @@ Tk_PanedWindowObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } - tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), + tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), Tcl_GetStringFromObj(objv[1], NULL), NULL); if (tkwin == NULL) { return TCL_ERROR; } pwOpts = (OptionTables *) - Tcl_GetAssocData(interp, "PanedWindowOptionTables", NULL); + Tcl_GetAssocData(interp, "PanedWindowOptionTables", NULL); if (pwOpts == NULL) { /* - * The first time this procedure is invoked, the option tables will - * be NULL. We then create the option tables from the templates - * and store a pointer to the tables as the command's clinical so - * we'll have easy access to it in the future. + * The first time this function is invoked, the option tables will be + * NULL. We then create the option tables from the templates and store + * a pointer to the tables as the command's clinical so we'll have + * easy access to it in the future. */ + pwOpts = (OptionTables *) ckalloc(sizeof(OptionTables)); - /* Set up an exit handler to free the optionTables struct */ + + /* + * Set up an exit handler to free the optionTables struct. + */ + Tcl_SetAssocData(interp, "PanedWindowOptionTables", DestroyOptionTables, (ClientData) pwOpts); - /* Create the paned window option tables. */ + /* + * Create the paned window option tables. + */ + pwOpts->pwOptions = Tk_CreateOptionTable(interp, optionSpecs); pwOpts->slaveOpts = Tk_CreateOptionTable(interp, slaveOptionSpecs); } @@ -379,18 +424,18 @@ Tk_PanedWindowObjCmd(clientData, interp, objc, objv) pwPtr = (PanedWindow *) ckalloc(sizeof(PanedWindow)); memset((void *)pwPtr, 0, (sizeof(PanedWindow))); - pwPtr->tkwin = tkwin; - pwPtr->display = Tk_Display(tkwin); - pwPtr->interp = interp; - pwPtr->widgetCmd = Tcl_CreateObjCommand(interp, + pwPtr->tkwin = tkwin; + pwPtr->display = Tk_Display(tkwin); + pwPtr->interp = interp; + pwPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(pwPtr->tkwin), PanedWindowWidgetObjCmd, (ClientData) pwPtr, PanedWindowCmdDeletedProc); - pwPtr->optionTable = pwOpts->pwOptions; - pwPtr->slaveOpts = pwOpts->slaveOpts; - pwPtr->relief = TK_RELIEF_RAISED; - pwPtr->gc = None; - pwPtr->cursor = None; - pwPtr->sashCursor = None; + pwPtr->optionTable = pwOpts->pwOptions; + pwPtr->slaveOpts = pwOpts->slaveOpts; + pwPtr->relief = TK_RELIEF_RAISED; + pwPtr->gc = None; + pwPtr->cursor = None; + pwPtr->sashCursor = None; /* * Keep a hold of the associated tkwin until we destroy the widget, @@ -409,10 +454,11 @@ Tk_PanedWindowObjCmd(clientData, interp, objc, objv) PanedWindowEventProc, (ClientData) pwPtr); /* - * Find the toplevel ancestor of the panedwindow, and make a proxy - * win as a child of that window; this way the proxy can always float - * above slaves in the panedwindow. + * Find the toplevel ancestor of the panedwindow, and make a proxy win as + * a child of that window; this way the proxy can always float above + * slaves in the panedwindow. */ + parent = Tk_Parent(pwPtr->tkwin); while (!(Tk_IsTopLevel(parent))) { parent = Tk_Parent(parent); @@ -422,15 +468,16 @@ Tk_PanedWindowObjCmd(clientData, interp, objc, objv) } } - pwPtr->proxywin = Tk_CreateAnonymousWindow(interp, parent, (char *) NULL); + pwPtr->proxywin = Tk_CreateAnonymousWindow(interp, parent, NULL); + /* - * The proxy window has to be able to share GCs with the main - * panedwindow despite being children of windows with potentially - * different characteristics, and it looks better that way too. - * [Bug 702230] - * Also Set the X window save under attribute to avoid expose events as - * the proxy sash is dragged across the panes. [Bug 1036963] + * The proxy window has to be able to share GCs with the main panedwindow + * despite being children of windows with potentially different + * characteristics, and it looks better that way too. [Bug 702230] Also + * set the X window save under attribute to avoid expose events as the + * proxy sash is dragged across the panes. [Bug 1036963] */ + Tk_SetWindowVisual(pwPtr->proxywin, Tk_Visual(tkwin), Tk_Depth(tkwin), Tk_Colormap(tkwin)); Tk_CreateEventHandler(pwPtr->proxywin, ExposureMask, ProxyWindowEventProc, @@ -453,9 +500,9 @@ Tk_PanedWindowObjCmd(clientData, interp, objc, objv) * * PanedWindowWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -467,26 +514,27 @@ Tk_PanedWindowObjCmd(clientData, interp, objc, objv) */ static int -PanedWindowWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about square widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +PanedWindowWidgetObjCmd( + ClientData clientData, /* Information about square widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj * CONST objv[]) /* Argument objects. */ { PanedWindow *pwPtr = (PanedWindow *) clientData; int result = TCL_OK; - static CONST char *optionStrings[] = {"add", "cget", "configure", "forget", - "identify", "panecget", - "paneconfigure", "panes", - "proxy", "sash", (char *) NULL}; - enum options { PW_ADD, PW_CGET, PW_CONFIGURE, PW_FORGET, PW_IDENTIFY, - PW_PANECGET, PW_PANECONFIGURE, PW_PANES, PW_PROXY, - PW_SASH }; + static CONST char *optionStrings[] = { + "add", "cget", "configure", "forget", "identify", "panecget", + "paneconfigure", "panes", "proxy", "sash", NULL + }; + enum options { + PW_ADD, PW_CGET, PW_CONFIGURE, PW_FORGET, PW_IDENTIFY, PW_PANECGET, + PW_PANECONFIGURE, PW_PANES, PW_PROXY, PW_SASH + }; Tcl_Obj *resultObj; int index, count, i, x, y; Tk_Window tkwin; Slave *slavePtr; - + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?"); return TCL_ERROR; @@ -498,196 +546,177 @@ PanedWindowWidgetObjCmd(clientData, interp, objc, objv) } Tcl_Preserve((ClientData) pwPtr); - + switch ((enum options) index) { - case PW_ADD: { - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?"); - result = TCL_ERROR; - break; - } - - result = ConfigureSlaves(pwPtr, interp, objc, objv); + case PW_ADD: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?"); + result = TCL_ERROR; break; } - - case PW_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); - result = TCL_ERROR; - break; - } - resultObj = Tk_GetOptionValue(interp, (char *) pwPtr, - pwPtr->optionTable, objv[2], pwPtr->tkwin); + result = ConfigureSlaves(pwPtr, interp, objc, objv); + break; + + case PW_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + result = TCL_ERROR; + break; + } + resultObj = Tk_GetOptionValue(interp, (char *) pwPtr, + pwPtr->optionTable, objv[2], pwPtr->tkwin); + if (resultObj == NULL) { + result = TCL_ERROR; + } else { + Tcl_SetObjResult(interp, resultObj); + } + break; + + case PW_CONFIGURE: + resultObj = NULL; + if (objc <= 3) { + resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr, + pwPtr->optionTable, + (objc == 3) ? objv[2] : NULL, pwPtr->tkwin); if (resultObj == NULL) { result = TCL_ERROR; } else { Tcl_SetObjResult(interp, resultObj); } + } else { + result = ConfigurePanedWindow(interp, pwPtr, objc - 2, objv + 2); + } + break; + + case PW_FORGET: { + int i; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?"); + result = TCL_ERROR; break; } - - case PW_CONFIGURE: { - resultObj = NULL; - if (objc <= 3) { - resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr, - pwPtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - pwPtr->tkwin); - if (resultObj == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, resultObj); - } - } else { - result = ConfigurePanedWindow(interp, pwPtr, objc - 2, - objv + 2); + + /* + * Clean up each window named in the arg list. + */ + for (count = 0, i = 2; i < objc; i++) { + Tk_Window slave = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), + pwPtr->tkwin); + if (slave == NULL) { + continue; + } + slavePtr = GetPane(pwPtr, slave); + if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) { + count++; + Tk_ManageGeometry(slave, NULL, (ClientData)NULL); + Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin); + Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask, + SlaveStructureProc, (ClientData) slavePtr); + Tk_UnmapWindow(slavePtr->tkwin); + Unlink(slavePtr); + } + if (count != 0) { + ComputeGeometry(pwPtr); } + } + break; + } + + case PW_IDENTIFY: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "x y"); + result = TCL_ERROR; break; } - - case PW_FORGET: { - Tk_Window slave; - int i; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, "widget ?widget ...?"); - result = TCL_ERROR; - break; - } - /* - * Clean up each window named in the arg list. - */ - for (count = 0, i = 2; i < objc; i++) { - slave = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), - pwPtr->tkwin); - if (slave == NULL) { - continue; - } - slavePtr = GetPane(pwPtr, slave); - if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) { - count++; - Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, - (ClientData) NULL); - Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin); - Tk_DeleteEventHandler(slavePtr->tkwin, StructureNotifyMask, - SlaveStructureProc, (ClientData) slavePtr); - Tk_UnmapWindow(slavePtr->tkwin); - Unlink(slavePtr); - } - if (count != 0) { - ComputeGeometry(pwPtr); - } - } + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { + result = TCL_ERROR; break; } + result = PanedWindowIdentifyCoords(pwPtr, interp, x, y); + break; - case PW_IDENTIFY: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "x y"); - result = TCL_ERROR; - break; + case PW_PANECGET: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "pane option"); + result = TCL_ERROR; + break; + } + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), pwPtr->tkwin); + if (tkwin == NULL) { + result = TCL_ERROR; + break; + } + resultObj = NULL; + for (i = 0; i < pwPtr->numSlaves; i++) { + if (pwPtr->slaves[i]->tkwin == tkwin) { + resultObj = Tk_GetOptionValue(interp, + (char *) pwPtr->slaves[i], pwPtr->slaveOpts, + objv[3], tkwin); } + } + if (i == pwPtr->numSlaves) { + Tcl_SetResult(interp, "not managed by this window", TCL_STATIC); + } + if (resultObj == NULL) { + result = TCL_ERROR; + } else { + Tcl_SetObjResult(interp, resultObj); + } + break; - if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { - result = TCL_ERROR; - break; - } - - result = PanedWindowIdentifyCoords(pwPtr, interp, x, y); + case PW_PANECONFIGURE: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "pane ?option? ?value option value ...?"); + result = TCL_ERROR; break; } - - case PW_PANECGET: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 2, objv, "pane option"); - result = TCL_ERROR; - break; - } + resultObj = NULL; + if (objc <= 4) { tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), pwPtr->tkwin); - if (tkwin == NULL) { - result = TCL_ERROR; - break; - } - resultObj = NULL; for (i = 0; i < pwPtr->numSlaves; i++) { if (pwPtr->slaves[i]->tkwin == tkwin) { - resultObj = Tk_GetOptionValue(interp, + resultObj = Tk_GetOptionInfo(interp, (char *) pwPtr->slaves[i], pwPtr->slaveOpts, - objv[3], tkwin); - } - } - if (i == pwPtr->numSlaves) { - Tcl_SetResult(interp, "not managed by this window", - TCL_STATIC); - } - if (resultObj == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, resultObj); - } - break; - } - - case PW_PANECONFIGURE: { - if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, - "pane ?option? ?value option value ...?"); - result = TCL_ERROR; - break; - } - resultObj = NULL; - if (objc <= 4) { - tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), - pwPtr->tkwin); - for (i = 0; i < pwPtr->numSlaves; i++) { - if (pwPtr->slaves[i]->tkwin == tkwin) { - resultObj = Tk_GetOptionInfo(interp, - (char *) pwPtr->slaves[i], - pwPtr->slaveOpts, - (objc == 4) ? objv[3] : (Tcl_Obj *) NULL, - pwPtr->tkwin); - if (resultObj == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, resultObj); - } - break; + (objc == 4) ? objv[3] : NULL, + pwPtr->tkwin); + if (resultObj == NULL) { + result = TCL_ERROR; + } else { + Tcl_SetObjResult(interp, resultObj); } + break; } - } else { - result = ConfigureSlaves(pwPtr, interp, objc, objv); } - break; + } else { + result = ConfigureSlaves(pwPtr, interp, objc, objv); } - - case PW_PANES: { - resultObj = Tcl_NewObj(); + break; - Tcl_IncrRefCount(resultObj); + case PW_PANES: + resultObj = Tcl_NewObj(); - for (i = 0; i < pwPtr->numSlaves; i++) { - Tcl_ListObjAppendElement(interp, resultObj, - Tcl_NewStringObj(Tk_PathName(pwPtr->slaves[i]->tkwin), - -1)); - } - Tcl_SetObjResult(interp, resultObj); - Tcl_DecrRefCount(resultObj); - break; - } + Tcl_IncrRefCount(resultObj); - case PW_PROXY: { - result = PanedWindowProxyCommand(pwPtr, interp, objc, objv); - break; + for (i = 0; i < pwPtr->numSlaves; i++) { + Tcl_ListObjAppendElement(interp, resultObj, + Tcl_NewStringObj(Tk_PathName(pwPtr->slaves[i]->tkwin),-1)); } + Tcl_SetObjResult(interp, resultObj); + Tcl_DecrRefCount(resultObj); + break; - case PW_SASH: { - result = PanedWindowSashCommand(pwPtr, interp, objc, objv); - break; - } + case PW_PROXY: + result = PanedWindowProxyCommand(pwPtr, interp, objc, objv); + break; + + case PW_SASH: + result = PanedWindowSashCommand(pwPtr, interp, objc, objv); + break; } Tcl_Release((ClientData) pwPtr); return result; @@ -698,39 +727,38 @@ PanedWindowWidgetObjCmd(clientData, interp, objc, objv) * * ConfigureSlaves -- * - * Add or alter the configuration options of a slave in a paned - * window. + * Add or alter the configuration options of a slave in a paned window. * * Results: * Standard Tcl result. * * Side effects: - * Depends on options; may add a slave to the paned window, may - * alter the geometry management options of a slave. + * Depends on options; may add a slave to the paned window, may alter the + * geometry management options of a slave. * *---------------------------------------------------------------------- */ static int -ConfigureSlaves(pwPtr, interp, objc, objv) - PanedWindow *pwPtr; /* Information about paned window. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +ConfigureSlaves( + PanedWindow *pwPtr, /* Information about paned window. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { int i, firstOptionArg, j, found, doubleBw, index, numNewSlaves, haveLoc; int insertIndex; Tk_Window tkwin = NULL, ancestor, parent; - Slave *slavePtr, **inserts, **new; + Slave *slavePtr, **inserts, **newSlaves; Slave options; char *arg; - + /* - * Find the non-window name arguments; these are the configure options - * for the slaves. Also validate that the window names given are - * legitimate (ie, they are real windows, they are not the panedwindow - * itself, etc.). + * Find the non-window name arguments; these are the configure options for + * the slaves. Also validate that the window names given are legitimate + * (ie, they are real windows, they are not the panedwindow itself, etc.). */ + for (i = 2; i < objc; i++) { arg = Tcl_GetString(objv[i]); if (arg[0] == '-') { @@ -742,28 +770,32 @@ ConfigureSlaves(pwPtr, interp, objc, objv) * Just a plain old bad window; Tk_NameToWindow filled in an * error message for us. */ + return TCL_ERROR; } else if (tkwin == pwPtr->tkwin) { /* * A panedwindow cannot manage itself. */ + Tcl_ResetResult(interp); Tcl_AppendResult(interp, "can't add ", arg, " to itself", - (char *) NULL); + NULL); return TCL_ERROR; } else if (Tk_IsTopLevel(tkwin)) { /* * A panedwindow cannot manage a toplevel. */ + Tcl_ResetResult(interp); Tcl_AppendResult(interp, "can't add toplevel ", arg, " to ", - Tk_PathName(pwPtr->tkwin), (char *) NULL); + Tk_PathName(pwPtr->tkwin), NULL); return TCL_ERROR; } else { /* * Make sure the panedwindow is the parent of the slave, * or a descendant of the slave's parent. */ + parent = Tk_Parent(tkwin); for (ancestor = pwPtr->tkwin;;ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { @@ -771,9 +803,8 @@ ConfigureSlaves(pwPtr, interp, objc, objv) } if (Tk_IsTopLevel(ancestor)) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "can't add ", arg, - " to ", Tk_PathName(pwPtr->tkwin), - (char *) NULL); + Tcl_AppendResult(interp, "can't add ", arg, " to ", + Tk_PathName(pwPtr->tkwin), NULL); return TCL_ERROR; } } @@ -784,10 +815,11 @@ ConfigureSlaves(pwPtr, interp, objc, objv) /* * Pre-parse the configuration options, to get the before/after specifiers - * into an easy-to-find location (a local variable). Also, check the + * into an easy-to-find location (a local variable). Also, check the * return from Tk_SetOptions once, here, so we can save a little bit of * extra testing in the for loop below. */ + memset((void *)&options, 0, sizeof(Slave)); if (Tk_SetOptions(interp, (char *) &options, pwPtr->slaveOpts, objc - firstOptionArg, objv + firstOptionArg, @@ -797,9 +829,10 @@ ConfigureSlaves(pwPtr, interp, objc, objv) /* * If either -after or -before was given, find the numerical index that - * corresponds to the given window. If both -after and -before are - * given, the option precedence is: -after, then -before. + * corresponds to the given window. If both -after and -before are given, + * the option precedence is: -after, then -before. */ + index = -1; haveLoc = 0; if (options.after != None) { @@ -823,14 +856,14 @@ ConfigureSlaves(pwPtr, interp, objc, objv) } /* - * If a window was given for -after/-before, but it's not a window - * managed by the panedwindow, throw an error + * If a window was given for -after/-before, but it's not a window managed + * by the panedwindow, throw an error */ + if (haveLoc && index == -1) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "window \"", Tk_PathName(tkwin), - "\" is not managed by ", Tk_PathName(pwPtr->tkwin), - (char *) NULL); + "\" is not managed by ", Tk_PathName(pwPtr->tkwin), NULL); Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts, pwPtr->tkwin); return TCL_ERROR; @@ -838,23 +871,26 @@ ConfigureSlaves(pwPtr, interp, objc, objv) /* * Allocate an array to hold, in order, the pointers to the slave - * structures corresponding to the windows specified. Some of those + * structures corresponding to the windows specified. Some of those * structures may already have existed, some may be new. */ + inserts = (Slave **)ckalloc(sizeof(Slave *) * (firstOptionArg - 2)); insertIndex = 0; - + /* * Populate the inserts array, creating new slave structures as necessary, * applying the options to each structure as we go, and, if necessary, - * marking the spot in the original slaves array as empty (for pre-existing - * slave structures). + * marking the spot in the original slaves array as empty (for + * pre-existing slave structures). */ + for (i = 0, numNewSlaves = 0; i < firstOptionArg - 2; i++) { /* * We don't check that tkwin is NULL here, because the pre-pass above * guarantees that the input at this stage is good. */ + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i + 2]), pwPtr->tkwin); @@ -888,8 +924,8 @@ ConfigureSlaves(pwPtr, interp, objc, objv) /* * Make sure this slave wasn't already put into the inserts array, - * ie, when the user specifies the same window multiple times in - * a single add commaned. + * i.e., when the user specifies the same window multiple times in a + * single add commaned. */ for (j = 0; j < insertIndex; j++) { if (inserts[j]->tkwin == tkwin) { @@ -900,12 +936,12 @@ ConfigureSlaves(pwPtr, interp, objc, objv) if (found) { continue; } - + /* - * Create a new slave structure and initialize it. All slaves - * start out with their "natural" dimensions. + * Create a new slave structure and initialize it. All slaves start + * out with their "natural" dimensions. */ - + slavePtr = (Slave *) ckalloc(sizeof(Slave)); memset(slavePtr, 0, sizeof(Slave)); Tk_InitOptions(interp, (char *)slavePtr, pwPtr->slaveOpts, @@ -913,8 +949,8 @@ ConfigureSlaves(pwPtr, interp, objc, objv) Tk_SetOptions(interp, (char *)slavePtr, pwPtr->slaveOpts, objc - firstOptionArg, objv + firstOptionArg, pwPtr->tkwin, NULL, NULL); - slavePtr->tkwin = tkwin; - slavePtr->masterPtr = pwPtr; + slavePtr->tkwin = tkwin; + slavePtr->masterPtr = pwPtr; doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width; if (slavePtr->width > 0) { slavePtr->paneWidth = slavePtr->width; @@ -943,43 +979,44 @@ ConfigureSlaves(pwPtr, interp, objc, objv) } /* - * Allocate the new slaves array, then copy the slaves into it, in - * order. + * Allocate the new slaves array, then copy the slaves into it, in order. */ + i = sizeof(Slave *) * (pwPtr->numSlaves+numNewSlaves); - new = (Slave **)ckalloc((unsigned) i); - memset(new, 0, (size_t) i); + newSlaves = (Slave **)ckalloc((unsigned) i); + memset(newSlaves, 0, (size_t) i); if (index == -1) { /* * If none of the existing slaves have to be moved, just copy the old * and append the new. */ - memcpy((void *)&(new[0]), pwPtr->slaves, + memcpy((void *)&(newSlaves[0]), pwPtr->slaves, sizeof(Slave *) * pwPtr->numSlaves); - memcpy((void *)&(new[pwPtr->numSlaves]), inserts, + memcpy((void *)&(newSlaves[pwPtr->numSlaves]), inserts, sizeof(Slave *) * numNewSlaves); } else { /* * If some of the existing slaves were moved, the old slaves array * will be partially populated, with some valid and some invalid - * entries. Walk through it, copying valid entries to the new slaves + * entries. Walk through it, copying valid entries to the new slaves * array as we go; when we get to the insert location for the new * slaves, copy the inserts array over, then finish off the old slaves * array. */ + for (i = 0, j = 0; i < index; i++) { if (pwPtr->slaves[i] != NULL) { - new[j] = pwPtr->slaves[i]; + newSlaves[j] = pwPtr->slaves[i]; j++; } } - - memcpy((void *)&(new[j]), inserts, sizeof(Slave *) * (insertIndex)); + + memcpy((void *)&(newSlaves[j]), inserts, sizeof(Slave *)*insertIndex); j += firstOptionArg - 2; - + for (i = index; i < pwPtr->numSlaves; i++) { if (pwPtr->slaves[i] != NULL) { - new[j] = pwPtr->slaves[i]; + newSlaves[j] = pwPtr->slaves[i]; j++; } } @@ -988,17 +1025,19 @@ ConfigureSlaves(pwPtr, interp, objc, objv) /* * Make the new slaves array the paned window's slave array, and clean up. */ + ckfree((void *)pwPtr->slaves); ckfree((void *)inserts); - pwPtr->slaves = new; + pwPtr->slaves = newSlaves; /* * Set the paned window's slave count to the new value. */ + pwPtr->numSlaves += numNewSlaves; Tk_FreeConfigOptions((char *) &options, pwPtr->slaveOpts, pwPtr->tkwin); - + ComputeGeometry(pwPtr); return TCL_OK; } @@ -1008,7 +1047,7 @@ ConfigureSlaves(pwPtr, interp, objc, objv) * * PanedWindowSashCommand -- * - * Implementation of the panedwindow sash subcommand. See the user + * Implementation of the panedwindow sash subcommand. See the user * documentation for details on what it does. * * Results: @@ -1021,133 +1060,132 @@ ConfigureSlaves(pwPtr, interp, objc, objv) */ static int -PanedWindowSashCommand(pwPtr, interp, objc, objv) - PanedWindow *pwPtr; /* Pointer to paned window information. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +PanedWindowSashCommand( + PanedWindow *pwPtr, /* Pointer to paned window information. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - static CONST char *sashOptionStrings[] = { "coord", "dragto", "mark", - "place", (char *) NULL }; - enum sashOptions { SASH_COORD, SASH_DRAGTO, SASH_MARK, SASH_PLACE }; + static CONST char *sashOptionStrings[] = { + "coord", "dragto", "mark", "place", NULL + }; + enum sashOptions { + SASH_COORD, SASH_DRAGTO, SASH_MARK, SASH_PLACE + }; int index, sash, x, y, diff; Tcl_Obj *coords[2]; Slave *slavePtr; - + if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?"); return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[2], sashOptionStrings, - "option", 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[2], sashOptionStrings, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult(interp); switch ((enum sashOptions) index) { - case SASH_COORD: { - if (objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index"); - return TCL_ERROR; - } + case SASH_COORD: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); + return TCL_ERROR; + } - if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) { - return TCL_ERROR; - } + if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) { + return TCL_ERROR; + } - if (!ValidSashIndex(pwPtr, sash)) { - Tcl_ResetResult(interp); - Tcl_SetResult(interp, "invalid sash index", TCL_STATIC); - return TCL_ERROR; - } - slavePtr = pwPtr->slaves[sash]; - - coords[0] = Tcl_NewIntObj(slavePtr->sashx); - coords[1] = Tcl_NewIntObj(slavePtr->sashy); - Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords); - break; + if (!ValidSashIndex(pwPtr, sash)) { + Tcl_ResetResult(interp); + Tcl_SetResult(interp, "invalid sash index", TCL_STATIC); + return TCL_ERROR; } + slavePtr = pwPtr->slaves[sash]; - case SASH_MARK: { - if (objc != 6 && objc != 4) { - Tcl_WrongNumArgs(interp, 3, objv, "index ?x y?"); - return TCL_ERROR; - } - - if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) { + coords[0] = Tcl_NewIntObj(slavePtr->sashx); + coords[1] = Tcl_NewIntObj(slavePtr->sashy); + Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords); + break; + + case SASH_MARK: + if (objc != 6 && objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?x y?"); + return TCL_ERROR; + } + + if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) { + return TCL_ERROR; + } + + if (!ValidSashIndex(pwPtr, sash)) { + Tcl_ResetResult(interp); + Tcl_SetResult(interp, "invalid sash index", TCL_STATIC); + return TCL_ERROR; + } + + if (objc == 6) { + if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) { return TCL_ERROR; } - if (!ValidSashIndex(pwPtr, sash)) { - Tcl_ResetResult(interp); - Tcl_SetResult(interp, "invalid sash index", TCL_STATIC); + if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) { return TCL_ERROR; } - if (objc == 6) { - if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) { - return TCL_ERROR; - } - - if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) { - return TCL_ERROR; - } + pwPtr->slaves[sash]->markx = x; + pwPtr->slaves[sash]->marky = y; + } else { + coords[0] = Tcl_NewIntObj(pwPtr->slaves[sash]->markx); + coords[1] = Tcl_NewIntObj(pwPtr->slaves[sash]->marky); + Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords); + } + break; - pwPtr->slaves[sash]->markx = x; - pwPtr->slaves[sash]->marky = y; - } else { - coords[0] = Tcl_NewIntObj(pwPtr->slaves[sash]->markx); - coords[1] = Tcl_NewIntObj(pwPtr->slaves[sash]->marky); - Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords); - } + case SASH_DRAGTO: + case SASH_PLACE: + if (objc != 6) { + Tcl_WrongNumArgs(interp, 3, objv, "index x y"); + return TCL_ERROR; + } - break; + if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) { + return TCL_ERROR; } - - case SASH_DRAGTO: - case SASH_PLACE: { - if (objc != 6) { - Tcl_WrongNumArgs(interp, 3, objv, "index x y"); - return TCL_ERROR; - } - - if (Tcl_GetIntFromObj(interp, objv[3], &sash) != TCL_OK) { - return TCL_ERROR; - } - if (!ValidSashIndex(pwPtr, sash)) { - Tcl_ResetResult(interp); - Tcl_SetResult(interp, "invalid sash index", TCL_STATIC); - return TCL_ERROR; - } + if (!ValidSashIndex(pwPtr, sash)) { + Tcl_ResetResult(interp); + Tcl_SetResult(interp, "invalid sash index", TCL_STATIC); + return TCL_ERROR; + } - if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) { - return TCL_ERROR; - } + if (Tcl_GetIntFromObj(interp, objv[4], &x) != TCL_OK) { + return TCL_ERROR; + } - if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) { - return TCL_ERROR; + if (Tcl_GetIntFromObj(interp, objv[5], &y) != TCL_OK) { + return TCL_ERROR; + } + + slavePtr = pwPtr->slaves[sash]; + if (pwPtr->orient == ORIENT_HORIZONTAL) { + if (index == SASH_PLACE) { + diff = x - pwPtr->slaves[sash]->sashx; + } else { + diff = x - pwPtr->slaves[sash]->markx; } - - slavePtr = pwPtr->slaves[sash]; - if (pwPtr->orient == ORIENT_HORIZONTAL) { - if (index == SASH_PLACE) { - diff = x - pwPtr->slaves[sash]->sashx; - } else { - diff = x - pwPtr->slaves[sash]->markx; - } + } else { + if (index == SASH_PLACE) { + diff = y - pwPtr->slaves[sash]->sashy; } else { - if (index == SASH_PLACE) { - diff = y - pwPtr->slaves[sash]->sashy; - } else { - diff = y - pwPtr->slaves[sash]->marky; - } + diff = y - pwPtr->slaves[sash]->marky; } - - MoveSash(pwPtr, sash, diff); - ComputeGeometry(pwPtr); } + + MoveSash(pwPtr, sash, diff); + ComputeGeometry(pwPtr); } return TCL_OK; } @@ -1157,32 +1195,31 @@ PanedWindowSashCommand(pwPtr, interp, objc, objv) * * ConfigurePanedWindow -- * - * This procedure is called to process an argv/argc list in - * conjunction with the Tk option database to configure (or - * reconfigure) a paned window widget. + * This function is called to process an argv/argc list in conjunction + * with the Tk option database to configure (or reconfigure) a paned + * window widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for pwPtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for pwPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigurePanedWindow(interp, pwPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - PanedWindow *pwPtr; /* Information about widget. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +ConfigurePanedWindow( + Tcl_Interp *interp, /* Used for error reporting. */ + PanedWindow *pwPtr, /* Information about widget. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument values. */ { Tk_SavedOptions savedOptions; int typemask = 0; - + if (Tk_SetOptions(interp, (char *) pwPtr, pwPtr->optionTable, objc, objv, pwPtr->tkwin, &savedOptions, &typemask) != TCL_OK) { Tk_RestoreSavedOptions(&savedOptions); @@ -1194,14 +1231,14 @@ ConfigurePanedWindow(interp, pwPtr, objc, objv) PanedWindowWorldChanged((ClientData) pwPtr); /* - * If an option that affects geometry has changed, make a relayout + * If an option that affects geometry has changed, make a re-layout * request. */ if (typemask & GEOMETRY) { ComputeGeometry(pwPtr); } - + return TCL_OK; } @@ -1210,9 +1247,9 @@ ConfigurePanedWindow(interp, pwPtr, objc, objv) * * PanedWindowWorldChanged -- * - * This procedure is invoked anytime a paned window's world has - * changed in some way that causes the widget to have to recompute - * graphics contexts and geometry. + * This function is invoked anytime a paned window's world has changed in + * some way that causes the widget to have to recompute graphics contexts + * and geometry. * * Results: * None. @@ -1224,8 +1261,8 @@ ConfigurePanedWindow(interp, pwPtr, objc, objv) */ static void -PanedWindowWorldChanged(instanceData) - ClientData instanceData; /* Information about the paned window. */ +PanedWindowWorldChanged( + ClientData instanceData) /* Information about the paned window. */ { XGCValues gcValues; GC newGC; @@ -1235,7 +1272,7 @@ PanedWindowWorldChanged(instanceData) * Allocated a graphics context for drawing the paned window widget * elements (background, sashes, etc.) and set the window background. */ - + gcValues.background = Tk_3DBorderColor(pwPtr->background)->pixel; newGC = Tk_GetGC(pwPtr->tkwin, GCBackground, &gcValues); if (pwPtr->gc != None) { @@ -1268,23 +1305,23 @@ PanedWindowWorldChanged(instanceData) * * PanedWindowEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on paned windows. + * This function is invoked by the Tk dispatcher for various events on + * paned windows. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -PanedWindowEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +PanedWindowEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { PanedWindow *pwPtr = (PanedWindow *) clientData; @@ -1309,9 +1346,9 @@ PanedWindowEventProc(clientData, eventPtr) * * PanedWindowCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -1323,16 +1360,16 @@ PanedWindowEventProc(clientData, eventPtr) */ static void -PanedWindowCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +PanedWindowCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { PanedWindow *pwPtr = (PanedWindow *) clientData; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted or because the command was - * deleted, and then this procedure destroys the widget. The - * WIDGET_DELETED flag distinguishes these cases. + * This function could be invoked either because the window was destroyed + * and the command was then deleted or because the command was deleted, + * and then this function destroys the widget. The WIDGET_DELETED flag + * distinguishes these cases. */ if (!(pwPtr->flags & WIDGET_DELETED)) { @@ -1346,9 +1383,9 @@ PanedWindowCmdDeletedProc(clientData) * * DisplayPanedWindow -- * - * This procedure redraws the contents of a paned window widget. - * It is invoked as a do-when-idle handler, so it only runs - * when there's nothing else for the application to do. + * This function redraws the contents of a paned window widget. It is + * invoked as a do-when-idle handler, so it only runs when there's + * nothing else for the application to do. * * Results: * None. @@ -1360,8 +1397,8 @@ PanedWindowCmdDeletedProc(clientData) */ static void -DisplayPanedWindow(clientData) - ClientData clientData; /* Information about window. */ +DisplayPanedWindow( + ClientData clientData) /* Information about window. */ { PanedWindow *pwPtr = (PanedWindow *) clientData; Slave *slavePtr; @@ -1417,9 +1454,14 @@ DisplayPanedWindow(clientData) for (i = 0; i < pwPtr->numSlaves - 1; i++) { slavePtr = pwPtr->slaves[i]; - Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, - slavePtr->sashx, slavePtr->sashy, - sashWidth, sashHeight, 1, pwPtr->sashRelief); + if (slavePtr->hide) { + continue; + } + if (sashWidth > 0 && sashHeight > 0) { + Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, + slavePtr->sashx, slavePtr->sashy, sashWidth, sashHeight, + 1, pwPtr->sashRelief); + } if (pwPtr->showHandle) { Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, slavePtr->handlex, slavePtr->handley, @@ -1430,13 +1472,12 @@ DisplayPanedWindow(clientData) #ifndef TK_NO_DOUBLE_BUFFERING /* - * Copy the information from the off-screen pixmap onto the screen, - * then delete the pixmap. + * Copy the information from the off-screen pixmap onto the screen, then + * delete the pixmap. */ - XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, - 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), - 0, 0); + XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, 0, 0, + (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); Tk_FreePixmap(Tk_Display(tkwin), pixmap); #endif /* TK_NO_DOUBLE_BUFFERING */ } @@ -1446,8 +1487,8 @@ DisplayPanedWindow(clientData) * * DestroyPanedWindow -- * - * This procedure is invoked by PanedWindowEventProc to free the - * internal structure of a paned window. + * This function is invoked by PanedWindowEventProc to free the internal + * structure of a paned window. * * Results: * None. @@ -1459,23 +1500,23 @@ DisplayPanedWindow(clientData) */ static void -DestroyPanedWindow(pwPtr) - PanedWindow *pwPtr; /* Info about paned window widget. */ +DestroyPanedWindow( + PanedWindow *pwPtr) /* Info about paned window widget. */ { int i; - + /* - * First mark the widget as in the process of being deleted, - * so that any code that causes calls to other paned window procedures - * will abort. + * First mark the widget as in the process of being deleted, so that any + * code that causes calls to other paned window functions will abort. */ pwPtr->flags |= WIDGET_DELETED; /* - * Cancel idle callbacks for redrawing the widget and for rearranging - * the panes. + * Cancel idle callbacks for redrawing the widget and for rearranging the + * panes. */ + if (pwPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayPanedWindow, (ClientData) pwPtr); } @@ -1489,7 +1530,7 @@ DestroyPanedWindow(pwPtr) * o Cancel geometry management for the slave. * o Free memory for the slave */ - + for (i = 0; i < pwPtr->numSlaves; i++) { Tk_DeleteEventHandler(pwPtr->slaves[i]->tkwin, StructureNotifyMask, SlaveStructureProc, (ClientData) pwPtr->slaves[i]); @@ -1525,26 +1566,25 @@ DestroyPanedWindow(pwPtr) * * PanedWindowReqProc -- * - * This procedure is invoked by Tk_GeometryRequest for - * windows managed by a paned window. + * This function is invoked by Tk_GeometryRequest for windows managed by + * a paned window. * * Results: * None. * * Side effects: - * Arranges for tkwin, and all its managed siblings, to - * be re-arranged at the next idle point. + * Arranges for tkwin, and all its managed siblings, to be re-arranged at + * the next idle point. * *-------------------------------------------------------------- */ static void -PanedWindowReqProc(clientData, tkwin) - ClientData clientData; /* Paned window's information about - * window that got new preferred - * geometry. */ - Tk_Window tkwin; /* Other Tk-related information - * about the window. */ +PanedWindowReqProc( + ClientData clientData, /* Paned window's information about window + * that got new preferred geometry. */ + Tk_Window tkwin) /* Other Tk-related information about the + * window. */ { Slave *slavePtr = (Slave *) clientData; PanedWindow *pwPtr = (PanedWindow *) (slavePtr->masterPtr); @@ -1555,6 +1595,7 @@ PanedWindowReqProc(clientData, tkwin) } } else { int doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width; + if (slavePtr->width <= 0) { slavePtr->paneWidth = Tk_ReqWidth(slavePtr->tkwin) + doubleBw; } @@ -1570,27 +1611,28 @@ PanedWindowReqProc(clientData, tkwin) * * PanedWindowLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This function is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. * * Side effects: - * Forgets all information about the slave. Causes geometry to - * be recomputed for the panedwindow. + * Forgets all information about the slave. Causes geometry to be + * recomputed for the panedwindow. * *-------------------------------------------------------------- */ static void -PanedWindowLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Grid structure for slave window that - * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ +PanedWindowLostSlaveProc( + ClientData clientData, /* Grid structure for slave window that was + * stolen away. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { register Slave *slavePtr = (Slave *) clientData; PanedWindow *pwPtr = (PanedWindow *) (slavePtr->masterPtr); + if (pwPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin); } @@ -1608,11 +1650,10 @@ PanedWindowLostSlaveProc(clientData, tkwin) * * ArrangePanes -- * - * This procedure is invoked (using the Tcl_DoWhenIdle - * mechanism) to re-layout a set of windows managed by - * a paned window. It is invoked at idle time so that a - * series of pane requests can be merged into a single - * layout operation. + * This function is invoked (using the Tcl_DoWhenIdle mechanism) to + * re-layout a set of windows managed by a paned window. It is invoked at + * idle time so that a series of pane requests can be merged into a + * single layout operation. * * Results: * None. @@ -1624,8 +1665,8 @@ PanedWindowLostSlaveProc(clientData, tkwin) */ static void -ArrangePanes(clientData) - ClientData clientData; /* Structure describing parent whose slaves +ArrangePanes( + ClientData clientData) /* Structure describing parent whose slaves * are to be re-layed out. */ { register PanedWindow *pwPtr = (PanedWindow *) clientData; @@ -1638,16 +1679,17 @@ ArrangePanes(clientData) int sashReserve, sxReserve, syReserve; int internalBW; int paneDynSize, paneDynMinSize, pwHeight, pwWidth, pwSize; + int first, last; int stretchReserve, stretchAmount; const int horizontal = (pwPtr->orient == ORIENT_HORIZONTAL); pwPtr->flags &= ~(REQUESTED_RELAYOUT|RESIZE_PENDING); /* - * If the parent has no slaves anymore, then don't do anything - * at all: just leave the parent's size as-is. Otherwise there is - * no way to "relinquish" control over the parent so another geometry - * manager can take over. + * If the parent has no slaves anymore, then don't do anything at all: + * just leave the parent's size as-is. Otherwise there is no way to + * "relinquish" control over the parent so another geometry manager can + * take over. */ if (pwPtr->numSlaves == 0) { @@ -1657,6 +1699,19 @@ ArrangePanes(clientData) Tcl_Preserve((ClientData) pwPtr); /* + * Find index of last visible pane. + */ + + for (i = 0, last = 0, first = -1; i < pwPtr->numSlaves; i++) { + if (pwPtr->slaves[i]->hide == 0) { + if (first < 0) { + first = i; + } + last = i; + } + } + + /* * First pass; compute sizes */ @@ -1668,8 +1723,8 @@ ArrangePanes(clientData) stretchReserve = (horizontal ? pwWidth : pwHeight); /* - * Calculate the sash width, including handle and padding, - * and the sash and handle offsets. + * Calculate the sash width, including handle and padding, and the sash + * and handle offsets. */ sashOffset = handleOffset = pwPtr->sashPad; @@ -1682,14 +1737,17 @@ ArrangePanes(clientData) handleOffset = ((pwPtr->sashWidth - pwPtr->handleSize) / 2) + pwPtr->sashPad; } - sashCount = pwPtr->numSlaves - 1; - for (i = 0; i < pwPtr->numSlaves; i++) { + for (i = sashCount = 0; i < pwPtr->numSlaves; i++) { slavePtr = pwPtr->slaves[i]; + if (slavePtr->hide) { + continue; + } + /* - * Compute the total size needed by all the slaves and the - * left-over, or shortage of space available. + * Compute the total size needed by all the slaves and the left-over, + * or shortage of space available. */ if (horizontal) { @@ -1699,11 +1757,14 @@ ArrangePanes(clientData) paneSize = slavePtr->paneHeight; stretchReserve -= paneSize + (2 * slavePtr->pady); } - if (i == sashCount) { + if (IsStretchable(slavePtr->stretch,i,first,last) + && Tk_IsMapped(pwPtr->tkwin)) { paneDynSize += paneSize; paneDynMinSize += slavePtr->minSize; - } else { + } + if (i != last) { stretchReserve -= sashWidth; + sashCount++; } } @@ -1714,16 +1775,21 @@ ArrangePanes(clientData) for (i = 0; i < pwPtr->numSlaves; i++) { slavePtr = pwPtr->slaves[i]; + if (slavePtr->hide) { + Tk_UnmaintainGeometry(slavePtr->tkwin, pwPtr->tkwin); + Tk_UnmapWindow(slavePtr->tkwin); + continue; + } + /* - * Compute the size of this slave. The algorithm (assuming a + * Compute the size of this slave. The algorithm (assuming a * horizontal paned window) is: * - * 1. Get "base" dimensions. If a width or height is specified - * for this slave, use those values; else use the - * ReqWidth/ReqHeight. + * 1. Get "base" dimensions. If a width or height is specified for + * this slave, use those values; else use the ReqWidth/ReqHeight. * 2. Using base dimensions, pane dimensions, and sticky values, - * determine the x and y, and actual width and height of the - * widget. + * determine the x and y, and actual width and height of the + * widget. */ doubleBw = 2 * Tk_Changes(slavePtr->tkwin)->border_width; @@ -1744,37 +1810,37 @@ ArrangePanes(clientData) paneSize = slavePtr->paneHeight; pwSize = pwHeight; } - if (Tk_IsMapped(pwPtr->tkwin)) { - if (i == pwPtr->numSlaves - 1) { - double frac; - if (paneDynSize > 0) { - frac = (double)paneSize / (double)paneDynSize; - } else { - frac = (double)paneSize / (double)pwSize; - } - paneDynSize -= paneSize; - paneDynMinSize -= slavePtr->minSize; - stretchAmount = (int) (frac * stretchReserve); - if (paneSize + stretchAmount >= paneMinSize) { - stretchReserve -= stretchAmount; - paneSize += stretchAmount; - } else { - stretchReserve += paneSize - paneMinSize; - paneSize = paneMinSize; - } - if (stretchReserve > 0) { - paneSize += stretchReserve; - stretchReserve = 0; - } - } else if (paneDynSize - paneDynMinSize + stretchReserve < 0) { - if (paneSize + paneDynSize - paneDynMinSize + stretchReserve - <= paneMinSize) { - stretchReserve += paneSize - paneMinSize; - paneSize = paneMinSize; - } else { - paneSize += paneDynSize - paneDynMinSize + stretchReserve; - stretchReserve = paneDynMinSize - paneDynSize; - } + if (IsStretchable(slavePtr->stretch, i, first, last)) { + double frac; + + if (paneDynSize > 0) { + frac = (double)paneSize / (double)paneDynSize; + } else { + frac = (double)paneSize / (double)pwSize; + } + + paneDynSize -= paneSize; + paneDynMinSize -= slavePtr->minSize; + stretchAmount = (int) (frac * stretchReserve); + if (paneSize + stretchAmount >= paneMinSize) { + stretchReserve -= stretchAmount; + paneSize += stretchAmount; + } else { + stretchReserve += paneSize - paneMinSize; + paneSize = paneMinSize; + } + if (i == last && stretchReserve > 0) { + paneSize += stretchReserve; + stretchReserve = 0; + } + } else if (paneDynSize - paneDynMinSize + stretchReserve < 0) { + if (paneSize + paneDynSize - paneDynMinSize + stretchReserve + <= paneMinSize) { + stretchReserve += paneSize - paneMinSize; + paneSize = paneMinSize; + } else { + paneSize += paneDynSize - paneDynMinSize + stretchReserve; + stretchReserve = paneDynMinSize - paneDynSize; } } if (horizontal) { @@ -1829,8 +1895,8 @@ ArrangePanes(clientData) if (x < internalBW) { x = internalBW; } - slavePtr->sashx = x + sashOffset; - slavePtr->sashy = y; + slavePtr->sashx = x + sashOffset; + slavePtr->sashy = y; slavePtr->handlex = x + handleOffset; slavePtr->handley = y + pwPtr->handlePad; x += sashWidth; @@ -1839,8 +1905,8 @@ ArrangePanes(clientData) if (y < internalBW) { y = internalBW; } - slavePtr->sashx = x; - slavePtr->sashy = y + sashOffset; + slavePtr->sashx = x; + slavePtr->sashy = y + sashOffset; slavePtr->handlex = x + pwPtr->handlePad; slavePtr->handley = y + handleOffset; y += sashWidth; @@ -1893,12 +1959,12 @@ ArrangePanes(clientData) */ static void -Unlink(slavePtr) - register Slave *slavePtr; /* Window to unlink. */ +Unlink( + register Slave *slavePtr) /* Window to unlink. */ { register PanedWindow *masterPtr; int i, j; - + masterPtr = slavePtr->masterPtr; if (masterPtr == NULL) { return; @@ -1921,6 +1987,7 @@ Unlink(slavePtr) /* * Clean out any -after or -before references to this slave */ + for (i = 0; i < masterPtr->numSlaves; i++) { if (masterPtr->slaves[i]->before == slavePtr->tkwin) { masterPtr->slaves[i]->before = None; @@ -1937,9 +2004,10 @@ Unlink(slavePtr) } /* - * Set the slave's masterPtr to NULL, so that we can tell that the - * slave is no longer attached to any panedwindow. + * Set the slave's masterPtr to NULL, so that we can tell that the slave + * is no longer attached to any panedwindow. */ + slavePtr->masterPtr = NULL; masterPtr->numSlaves--; @@ -1950,12 +2018,12 @@ Unlink(slavePtr) * * GetPane -- * - * Given a token to a Tk window, find the pane that corresponds to - * that token in a given paned window. + * Given a token to a Tk window, find the pane that corresponds to that + * token in a given paned window. * * Results: - * Pointer to the slave structure, or NULL if the window is not - * managed by this paned window. + * Pointer to the slave structure, or NULL if the window is not managed + * by this paned window. * * Side effects: * None. @@ -1964,11 +2032,12 @@ Unlink(slavePtr) */ static Slave * -GetPane(pwPtr, tkwin) - PanedWindow *pwPtr; /* Pointer to the paned window info. */ - Tk_Window tkwin; /* Window to search for. */ +GetPane( + PanedWindow *pwPtr, /* Pointer to the paned window info. */ + Tk_Window tkwin) /* Window to search for. */ { int i; + for (i = 0; i < pwPtr->numSlaves; i++) { if (pwPtr->slaves[i]->tkwin == tkwin) { return pwPtr->slaves[i]; @@ -1982,10 +2051,9 @@ GetPane(pwPtr, tkwin) * * SlaveStructureProc -- * - * This procedure is invoked whenever StructureNotify events - * occur for a window that's managed by a paned window. This - * procedure's only purpose is to clean up when windows are - * deleted. + * This function is invoked whenever StructureNotify events occur for a + * window that's managed by a paned window. This function's only purpose + * is to clean up when windows are deleted. * * Results: * None. @@ -1999,13 +2067,13 @@ GetPane(pwPtr, tkwin) */ static void -SlaveStructureProc(clientData, eventPtr) - ClientData clientData; /* Pointer to record describing window item. */ - XEvent *eventPtr; /* Describes what just happened. */ +SlaveStructureProc( + ClientData clientData, /* Pointer to record describing window item. */ + XEvent *eventPtr) /* Describes what just happened. */ { Slave *slavePtr = (Slave *) clientData; PanedWindow *pwPtr = slavePtr->masterPtr; - + if (eventPtr->type == DestroyNotify) { Unlink(slavePtr); slavePtr->tkwin = NULL; @@ -2019,8 +2087,8 @@ SlaveStructureProc(clientData, eventPtr) * * ComputeGeometry -- * - * Compute geometry for the paned window, including coordinates of - * all slave windows and each sash. + * Compute geometry for the paned window, including coordinates of all + * slave windows and each sash. * * Results: * None. @@ -2032,8 +2100,8 @@ SlaveStructureProc(clientData, eventPtr) */ static void -ComputeGeometry(pwPtr) - PanedWindow *pwPtr; /* Pointer to the Paned Window structure. */ +ComputeGeometry( + PanedWindow *pwPtr) /* Pointer to the Paned Window structure. */ { int i, x, y, doubleBw, internalBw; int sashWidth, sashOffset, handleOffset; @@ -2047,10 +2115,10 @@ ComputeGeometry(pwPtr) reqWidth = reqHeight = 0; /* - * Sashes and handles share space on the display. To simplify - * processing below, precompute the x and y offsets of the handles and - * sashes within the space occupied by their combination; later, just add - * those offsets blindly (avoiding the extra showHandle, etc, checks). + * Sashes and handles share space on the display. To simplify processing + * below, precompute the x and y offsets of the handles and sashes within + * the space occupied by their combination; later, just add those offsets + * blindly (avoiding the extra showHandle, etc, checks). */ sashOffset = handleOffset = pwPtr->sashPad; @@ -2067,6 +2135,10 @@ ComputeGeometry(pwPtr) for (i = 0; i < pwPtr->numSlaves; i++) { slavePtr = pwPtr->slaves[i]; + if (slavePtr->hide) { + continue; + } + /* * First set the coordinates for the top left corner of the slave's * parcel. @@ -2076,9 +2148,9 @@ ComputeGeometry(pwPtr) slavePtr->y = y; /* - * Make sure the pane's paned dimension is at least minsize. - * This check may be redundant, since the only way to change a pane's - * size is by moving a sash, and that code checks the minsize. + * Make sure the pane's paned dimension is at least minsize. This + * check may be redundant, since the only way to change a pane's size + * is by moving a sash, and that code checks the minsize. */ if (horizontal) { @@ -2098,15 +2170,15 @@ ComputeGeometry(pwPtr) if (horizontal) { x += slavePtr->paneWidth + (2 * slavePtr->padx); - slavePtr->sashx = x + sashOffset; - slavePtr->sashy = y; + slavePtr->sashx = x + sashOffset; + slavePtr->sashy = y; slavePtr->handlex = x + handleOffset; slavePtr->handley = y + pwPtr->handlePad; x += sashWidth; } else { y += slavePtr->paneHeight + (2 * slavePtr->pady); - slavePtr->sashx = x; - slavePtr->sashy = y + sashOffset; + slavePtr->sashx = x; + slavePtr->sashy = y + sashOffset; slavePtr->handlex = x + pwPtr->handlePad; slavePtr->handley = y + handleOffset; y += sashWidth; @@ -2118,7 +2190,6 @@ ComputeGeometry(pwPtr) */ if (horizontal) { - /* * If the slave has an explicit height set, use that; otherwise, * use the slave's requested height. @@ -2135,10 +2206,9 @@ ComputeGeometry(pwPtr) reqHeight = dim; } } else { - /* - * If the slave has an explicit width set use that; otherwise, - * use the slave's requested width. + * If the slave has an explicit width set use that; otherwise, use + * the slave's requested width. */ if (slavePtr->width > 0) { @@ -2155,21 +2225,21 @@ ComputeGeometry(pwPtr) } /* - * The loop above should have left x (or y) equal to the sum of the - * widths (or heights) of the widgets, plus the size of one sash and - * the sash padding for each widget, plus the width of the left (or top) - * border of the paned window. + * The loop above should have left x (or y) equal to the sum of the widths + * (or heights) of the widgets, plus the size of one sash and the sash + * padding for each widget, plus the width of the left (or top) border of + * the paned window. * * The requested width (or height) is therefore x (or y) minus the size of - * one sash and padding, plus the width of the right (or bottom) border - * of the paned window. + * one sash and padding, plus the width of the right (or bottom) border of + * the paned window. * - * The height (or width) is equal to the maximum height (or width) of - * the slaves, plus the width of the border of the top and bottom (or left - * and right) of the paned window. + * The height (or width) is equal to the maximum height (or width) of the + * slaves, plus the width of the border of the top and bottom (or left and + * right) of the paned window. * - * If the panedwindow has an explicit width/height set use that; otherwise, - * use the requested width/height. + * If the panedwindow has an explicit width/height set use that; + * otherwise, use the requested width/height. */ if (horizontal) { @@ -2195,8 +2265,8 @@ ComputeGeometry(pwPtr) * * DestroyOptionTables -- * - * This procedure is registered as an exit callback when the paned window - * command is first called. It cleans up the OptionTables structure + * This function is registered as an exit callback when the paned window + * command is first called. It cleans up the OptionTables structure * allocated by that command. * * Results: @@ -2209,9 +2279,9 @@ ComputeGeometry(pwPtr) */ static void -DestroyOptionTables(clientData, interp) - ClientData clientData; /* Pointer to the OptionTables struct */ - Tcl_Interp *interp; /* Pointer to the calling interp */ +DestroyOptionTables( + ClientData clientData, /* Pointer to the OptionTables struct */ + Tcl_Interp *interp) /* Pointer to the calling interp */ { ckfree((char *)clientData); return; @@ -2222,8 +2292,8 @@ DestroyOptionTables(clientData, interp) * * GetSticky - * - * Converts an internal boolean combination of "sticky" bits into a - * a Tcl string obj containing zero or mor of n, s, e, or w. + * Converts an internal boolean combination of "sticky" bits into a Tcl + * string obj containing zero or more of n, s, e, or w. * * Results: * Tcl_Obj containing the string representation of the sticky value. @@ -2235,11 +2305,11 @@ DestroyOptionTables(clientData, interp) */ static Tcl_Obj * -GetSticky(clientData, tkwin, recordPtr, internalOffset) - ClientData clientData; - Tk_Window tkwin; - char *recordPtr; /* Pointer to widget record. */ - int internalOffset; /* Offset within *recordPtr containing the +GetSticky( + ClientData clientData, + Tk_Window tkwin, + char *recordPtr, /* Pointer to widget record. */ + int internalOffset) /* Offset within *recordPtr containing the * sticky value. */ { int sticky = *(int *)(recordPtr + internalOffset); @@ -2247,16 +2317,16 @@ GetSticky(clientData, tkwin, recordPtr, internalOffset) int count = 0; if (sticky & STICK_NORTH) { - buffer[count++] = 'n'; + buffer[count++] = 'n'; } if (sticky & STICK_EAST) { - buffer[count++] = 'e'; + buffer[count++] = 'e'; } if (sticky & STICK_SOUTH) { - buffer[count++] = 's'; + buffer[count++] = 's'; } if (sticky & STICK_WEST) { - buffer[count++] = 'w'; + buffer[count++] = 'w'; } buffer[count] = '\0'; @@ -2268,64 +2338,70 @@ GetSticky(clientData, tkwin, recordPtr, internalOffset) * * SetSticky -- * - * Converts a Tcl_Obj representing a widgets stickyness into an - * integer value. + * Converts a Tcl_Obj representing a widgets stickyness into an integer + * value. * * Results: * Standard Tcl result. * * Side effects: - * May store the integer value into the internal representation - * pointer. May change the pointer to the Tcl_Obj to NULL to indicate - * that the specified string was empty and that is acceptable. + * May store the integer value into the internal representation pointer. + * May change the pointer to the Tcl_Obj to NULL to indicate that the + * specified string was empty and that is acceptable. * *---------------------------------------------------------------------- */ static int -SetSticky(clientData, interp, tkwin, value, recordPtr, internalOffset, - oldInternalPtr, flags) - ClientData clientData; - Tcl_Interp *interp; /* Current interp; may be used for errors. */ - Tk_Window tkwin; /* Window for which option is being set. */ - Tcl_Obj **value; /* Pointer to the pointer to the value object. - * We use a pointer to the pointer because - * we may need to return a value (NULL). */ - char *recordPtr; /* Pointer to storage for the widget record. */ - int internalOffset; /* Offset within *recordPtr at which the - internal value is to be stored. */ - char *oldInternalPtr; /* Pointer to storage for the old value. */ - int flags; /* Flags for the option, set Tk_SetOptions. */ +SetSticky( + ClientData clientData, + Tcl_Interp *interp, /* Current interp; may be used for errors. */ + Tk_Window tkwin, /* Window for which option is being set. */ + Tcl_Obj **value, /* Pointer to the pointer to the value object. + * We use a pointer to the pointer because we + * may need to return a value (NULL). */ + char *recordPtr, /* Pointer to storage for the widget record. */ + int internalOffset, /* Offset within *recordPtr at which the + * internal value is to be stored. */ + char *oldInternalPtr, /* Pointer to storage for the old value. */ + int flags) /* Flags for the option, set Tk_SetOptions. */ { int sticky = 0; char c, *string, *internalPtr; internalPtr = ComputeSlotAddress(recordPtr, internalOffset); - + if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) { *value = NULL; } else { /* * Convert the sticky specifier into an integer value. */ - + string = Tcl_GetString(*value); - + while ((c = *string++) != '\0') { switch (c) { - case 'n': case 'N': sticky |= STICK_NORTH; break; - case 'e': case 'E': sticky |= STICK_EAST; break; - case 's': case 'S': sticky |= STICK_SOUTH; break; - case 'w': case 'W': sticky |= STICK_WEST; break; - case ' ': case ',': case '\t': case '\r': case '\n': break; - default: { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad stickyness value \"", - Tcl_GetString(*value), "\": must be a string ", - "containing zero or more of n, e, s, and w", - (char *)NULL); - return TCL_ERROR; - } + case 'n': case 'N': + sticky |= STICK_NORTH; + break; + case 'e': case 'E': + sticky |= STICK_EAST; + break; + case 's': case 'S': + sticky |= STICK_SOUTH; + break; + case 'w': case 'W': + sticky |= STICK_WEST; + break; + case ' ': case ',': case '\t': case '\r': case '\n': + break; + default: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "bad stickyness value \"", + Tcl_GetString(*value), "\": must be a string ", + "containing zero or more of n, e, s, and w", NULL); + return TCL_ERROR; } } } @@ -2335,7 +2411,7 @@ SetSticky(clientData, interp, tkwin, value, recordPtr, internalOffset, *((int *) internalPtr) = sticky; } return TCL_OK; -} +} /* *---------------------------------------------------------------------- @@ -2354,11 +2430,11 @@ SetSticky(clientData, interp, tkwin, value, recordPtr, internalOffset, */ static void -RestoreSticky(clientData, tkwin, internalPtr, oldInternalPtr) - ClientData clientData; - Tk_Window tkwin; - char *internalPtr; /* Pointer to storage for value. */ - char *oldInternalPtr; /* Pointer to old value. */ +RestoreSticky( + ClientData clientData, + Tk_Window tkwin, + char *internalPtr, /* Pointer to storage for value. */ + char *oldInternalPtr) /* Pointer to old value. */ { *(int *)internalPtr = *(int *)oldInternalPtr; } @@ -2368,14 +2444,13 @@ RestoreSticky(clientData, tkwin, internalPtr, oldInternalPtr) * * AdjustForSticky -- * - * Given the x,y coords of the top-left corner of a pane, the - * dimensions of that pane, and the dimensions of a slave, compute - * the x,y coords and actual dimensions of the slave based on the slave's - * sticky value. + * Given the x,y coords of the top-left corner of a pane, the dimensions + * of that pane, and the dimensions of a slave, compute the x,y coords + * and actual dimensions of the slave based on the slave's sticky value. * * Results: - * No direct return; sets the x, y, slaveWidth and slaveHeight to - * correct values. + * No direct return; sets the x, y, slaveWidth and slaveHeight to correct + * values. * * Side effects: * None. @@ -2384,19 +2459,19 @@ RestoreSticky(clientData, tkwin, internalPtr, oldInternalPtr) */ static void -AdjustForSticky(sticky, cavityWidth, cavityHeight, xPtr, yPtr, - slaveWidthPtr, slaveHeightPtr) - int sticky; /* Sticky value; see top of file for definition. */ - int cavityWidth; /* Width of the cavity. */ - int cavityHeight; /* Height of the cavity. */ - int *xPtr, *yPtr; /* Initially, coordinates of the top-left +AdjustForSticky( + int sticky, /* Sticky value; see top of file for + * definition. */ + int cavityWidth, /* Width of the cavity. */ + int cavityHeight, /* Height of the cavity. */ + int *xPtr, int *yPtr, /* Initially, coordinates of the top-left * corner of cavity; also return values for * actual x, y coords of slave. */ - int *slaveWidthPtr; /* Slave width. */ - int *slaveHeightPtr; /* Slave height. */ + int *slaveWidthPtr, /* Slave width. */ + int *slaveHeightPtr) /* Slave height. */ { - int diffx=0; /* Cavity width - slave width. */ - int diffy=0; /* Cavity hight - slave height. */ + int diffx = 0; /* Cavity width - slave width. */ + int diffy = 0; /* Cavity hight - slave height. */ if (cavityWidth > *slaveWidthPtr) { diffx = cavityWidth - *slaveWidthPtr; @@ -2413,10 +2488,10 @@ AdjustForSticky(sticky, cavityWidth, cavityHeight, xPtr, yPtr, *slaveHeightPtr += diffy; } if (!(sticky & STICK_WEST)) { - *xPtr += (sticky & STICK_EAST) ? diffx : diffx/2; + *xPtr += (sticky & STICK_EAST) ? diffx : diffx/2; } if (!(sticky & STICK_NORTH)) { - *yPtr += (sticky & STICK_SOUTH) ? diffy : diffy/2; + *yPtr += (sticky & STICK_SOUTH) ? diffy : diffy/2; } } @@ -2437,10 +2512,10 @@ AdjustForSticky(sticky, cavityWidth, cavityHeight, xPtr, yPtr, */ static void -MoveSash(pwPtr, sash, diff) - PanedWindow *pwPtr; - int sash; - int diff; +MoveSash( + PanedWindow *pwPtr, + int sash, + int diff) { int i; int expandPane, reduceFirst, reduceLast, reduceIncr, slaveSize, sashOffset; @@ -2464,6 +2539,9 @@ MoveSash(pwPtr, sash, diff) } for (i = 0; i < pwPtr->numSlaves; i++) { slavePtr = pwPtr->slaves[i]; + if (slavePtr->hide) { + continue; + } if (horizontal) { slavePtr->paneWidth = slavePtr->width = slavePtr->sashx - sashOffset - slavePtr->x - (2 * slavePtr->padx); @@ -2474,6 +2552,16 @@ MoveSash(pwPtr, sash, diff) } /* + * There must be a next sash since it is only possible to enter this + * routine when moving an actual sash which implies there exists a visible + * pane to either side of the sash. + */ + + while (nextSash < pwPtr->numSlaves-1 && pwPtr->slaves[nextSash]->hide) { + nextSash++; + } + + /* * Consolidate +/-diff variables to reduce duplicate code. */ @@ -2491,12 +2579,15 @@ MoveSash(pwPtr, sash, diff) } /* - * Calculate how much room we have to stretch in - * and adjust diff value accordingly. + * Calculate how much room we have to stretch in and adjust diff value + * accordingly. */ for (i = reduceFirst; i != reduceLast; i += reduceIncr) { slavePtr = pwPtr->slaves[i]; + if (slavePtr->hide) { + continue; + } if (horizontal) { stretchReserve += slavePtr->width - slavePtr->minSize; } else { @@ -2527,6 +2618,9 @@ MoveSash(pwPtr, sash, diff) for (i = reduceFirst; i != reduceLast; i += reduceIncr) { slavePtr = pwPtr->slaves[i]; + if (slavePtr->hide) { + continue; + } if (horizontal) { slaveSize = slavePtr->width; } else { @@ -2552,23 +2646,23 @@ MoveSash(pwPtr, sash, diff) * * ProxyWindowEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on paned window proxy windows. + * This function is invoked by the Tk dispatcher for various events on + * paned window proxy windows. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. Whena + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -ProxyWindowEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +ProxyWindowEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { PanedWindow *pwPtr = (PanedWindow *) clientData; @@ -2585,9 +2679,9 @@ ProxyWindowEventProc(clientData, eventPtr) * * DisplayProxyWindow -- * - * This procedure redraws a paned window proxy window. - * It is invoked as a do-when-idle handler, so it only runs - * when there's nothing else for the application to do. + * This function redraws a paned window proxy window. It is invoked as a + * do-when-idle handler, so it only runs when there's nothing else for + * the application to do. * * Results: * None. @@ -2599,8 +2693,8 @@ ProxyWindowEventProc(clientData, eventPtr) */ static void -DisplayProxyWindow(clientData) - ClientData clientData; /* Information about window. */ +DisplayProxyWindow( + ClientData clientData) /* Information about window. */ { PanedWindow *pwPtr = (PanedWindow *) clientData; Pixmap pixmap; @@ -2624,6 +2718,7 @@ DisplayProxyWindow(clientData) /* * Redraw the widget's background and border. */ + Tk_Fill3DRectangle(tkwin, pixmap, pwPtr->background, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 2, pwPtr->sashRelief); @@ -2631,9 +2726,9 @@ DisplayProxyWindow(clientData) /* * Copy the pixmap to the display. */ - XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, - 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), - 0, 0); + + XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin), pwPtr->gc, 0, 0, + (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); Tk_FreePixmap(Tk_Display(tkwin), pixmap); #endif /* TK_NO_DOUBLE_BUFFERING */ } @@ -2643,8 +2738,8 @@ DisplayProxyWindow(clientData) * * PanedWindowProxyCommand -- * - * Handles the panedwindow proxy subcommand. See the user - * documentation for details. + * Handles the panedwindow proxy subcommand. See the user documentation + * for details. * * Results: * Standard Tcl result. @@ -2656,18 +2751,21 @@ DisplayProxyWindow(clientData) */ static int -PanedWindowProxyCommand(pwPtr, interp, objc, objv) - PanedWindow *pwPtr; /* Pointer to paned window information. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +PanedWindowProxyCommand( + PanedWindow *pwPtr, /* Pointer to paned window information. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - static CONST char *optionStrings[] = { "coord", "forget", "place", - (char *) NULL }; - enum options { PROXY_COORD, PROXY_FORGET, PROXY_PLACE }; + static CONST char *optionStrings[] = { + "coord", "forget", "place", NULL + }; + enum options { + PROXY_COORD, PROXY_FORGET, PROXY_PLACE + }; int index, x, y, sashWidth, sashHeight; Tcl_Obj *coords[2]; - + if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "option ?arg ...?"); return TCL_ERROR; @@ -2679,85 +2777,92 @@ PanedWindowProxyCommand(pwPtr, interp, objc, objv) } switch ((enum options) index) { - case PROXY_COORD: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, NULL); - return TCL_ERROR; - } + case PROXY_COORD: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } - coords[0] = Tcl_NewIntObj(pwPtr->proxyx); - coords[1] = Tcl_NewIntObj(pwPtr->proxyy); - Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords); - break; + coords[0] = Tcl_NewIntObj(pwPtr->proxyx); + coords[1] = Tcl_NewIntObj(pwPtr->proxyy); + Tcl_SetListObj(Tcl_GetObjResult(interp), 2, coords); + break; - case PROXY_FORGET: - if (objc != 3) { - Tcl_WrongNumArgs(interp, 3, objv, NULL); - return TCL_ERROR; - } - if (Tk_IsMapped(pwPtr->proxywin)) { - Tk_UnmapWindow(pwPtr->proxywin); - Tk_UnmaintainGeometry(pwPtr->proxywin, pwPtr->tkwin); - } - break; + case PROXY_FORGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + if (Tk_IsMapped(pwPtr->proxywin)) { + Tk_UnmapWindow(pwPtr->proxywin); + Tk_UnmaintainGeometry(pwPtr->proxywin, pwPtr->tkwin); + } + break; - case PROXY_PLACE: { - if (objc != 5) { - Tcl_WrongNumArgs(interp, 3, objv, "x y"); - return TCL_ERROR; - } + case PROXY_PLACE: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "x y"); + return TCL_ERROR; + } - if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { - return TCL_ERROR; - } + if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { + return TCL_ERROR; + } - if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) { - return TCL_ERROR; - } + if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) { + return TCL_ERROR; + } - if (pwPtr->orient == ORIENT_HORIZONTAL) { - if (x < 0) { - x = 0; - } - y = Tk_InternalBorderWidth(pwPtr->tkwin); - sashWidth = pwPtr->sashWidth; - sashHeight = Tk_Height(pwPtr->tkwin) - - (2 * Tk_InternalBorderWidth(pwPtr->tkwin)); - } else { - if (y < 0) { - y = 0; - } - x = Tk_InternalBorderWidth(pwPtr->tkwin); - sashHeight = pwPtr->sashWidth; - sashWidth = Tk_Width(pwPtr->tkwin) - + if (pwPtr->orient == ORIENT_HORIZONTAL) { + if (x < 0) { + x = 0; + } + y = Tk_InternalBorderWidth(pwPtr->tkwin); + sashWidth = pwPtr->sashWidth; + sashHeight = Tk_Height(pwPtr->tkwin) - (2 * Tk_InternalBorderWidth(pwPtr->tkwin)); + } else { + if (y < 0) { + y = 0; } + x = Tk_InternalBorderWidth(pwPtr->tkwin); + sashHeight = pwPtr->sashWidth; + sashWidth = Tk_Width(pwPtr->tkwin) - + (2 * Tk_InternalBorderWidth(pwPtr->tkwin)); + } - /* - * Stash the proxy coordinates for future "proxy coord" calls. - */ + if (sashWidth < 1) { + sashWidth = 1; + } + if (sashHeight < 1) { + sashHeight = 1; + } - pwPtr->proxyx = x; - pwPtr->proxyy = y; - - /* - * Make sure the proxy window is higher in the stacking order - * than the slaves, so that it will be visible when drawn. - * It would be more correct to push the proxy window just high - * enough to appear above the highest slave, but it's much easier - * to just force it all the way to the top of the stacking order. - */ - - Tk_RestackWindow(pwPtr->proxywin, Above, NULL); - - /* - * Let Tk_MaintainGeometry take care of placing the window at - * the right coordinates. - */ - Tk_MaintainGeometry(pwPtr->proxywin, pwPtr->tkwin, - x, y, sashWidth, sashHeight); - break; - } + /* + * Stash the proxy coordinates for future "proxy coord" calls. + */ + + pwPtr->proxyx = x; + pwPtr->proxyy = y; + + /* + * Make sure the proxy window is higher in the stacking order than the + * slaves, so that it will be visible when drawn. It would be more + * correct to push the proxy window just high enough to appear above + * the highest slave, but it's much easier to just force it all the + * way to the top of the stacking order. + */ + + Tk_RestackWindow(pwPtr->proxywin, Above, NULL); + + /* + * Let Tk_MaintainGeometry take care of placing the window at the + * right coordinates. + */ + + Tk_MaintainGeometry(pwPtr->proxywin, pwPtr->tkwin, x, y, + sashWidth, sashHeight); + break; } return TCL_OK; @@ -2768,12 +2873,11 @@ PanedWindowProxyCommand(pwPtr, interp, objc, objv) * * ObjectIsEmpty -- * - * This procedure tests whether the string value of an object is - * empty. + * This function tests whether the string value of an object is empty. * * Results: - * The return value is 1 if the string value of objPtr has length - * zero, and 0 otherwise. + * The return value is 1 if the string value of objPtr has length zero, + * and 0 otherwise. * * Side effects: * May cause object shimmering, since this function can force a @@ -2783,8 +2887,8 @@ PanedWindowProxyCommand(pwPtr, interp, objc, objv) */ static int -ObjectIsEmpty(objPtr) - Tcl_Obj *objPtr; /* Object to test. May be NULL. */ +ObjectIsEmpty( + Tcl_Obj *objPtr) /* Object to test. May be NULL. */ { int length; @@ -2807,8 +2911,8 @@ ObjectIsEmpty(objPtr) * within that record, compute the address of that slot. * * Results: - * If offset is non-negative, returns the computed address; else, - * returns NULL. + * If offset is non-negative, returns the computed address; else, returns + * NULL. * * Side effects: * None. @@ -2817,9 +2921,9 @@ ObjectIsEmpty(objPtr) */ static char * -ComputeSlotAddress(recordPtr, offset) - char *recordPtr; /* Pointer to the start of a record. */ - int offset; /* Offset of a slot within that record; may be < 0. */ +ComputeSlotAddress( + char *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; @@ -2833,25 +2937,25 @@ ComputeSlotAddress(recordPtr, offset) * * PanedWindowIdentifyCoords -- * - * Given a pair of x,y coordinates, identify the panedwindow component - * at that point, if any. + * Given a pair of x,y coordinates, identify the panedwindow component at + * that point, if any. * * Results: * Standard Tcl result. * * Side effects: - * Modifies the interpreter's result to contain either an empty list, - * or a two element list of the form {sash n} or {handle n} to indicate - * that the point lies within the n'th sash or handle. + * Modifies the interpreter's result to contain either an empty list, or + * a two element list of the form {sash n} or {handle n} to indicate that + * the point lies within the n'th sash or handle. * *---------------------------------------------------------------------- */ static int -PanedWindowIdentifyCoords(pwPtr, interp, x, y) - PanedWindow *pwPtr; /* Information about the widget. */ - Tcl_Interp *interp; /* Interpreter in which to store result. */ - int x, y; /* Coordinates of the point to identify. */ +PanedWindowIdentifyCoords( + PanedWindow *pwPtr, /* Information about the widget. */ + Tcl_Interp *interp, /* Interpreter in which to store result. */ + int x, int y) /* Coordinates of the point to identify. */ { Tcl_Obj *list; int i, sashHeight, sashWidth, thisx, thisy; @@ -2860,45 +2964,48 @@ PanedWindowIdentifyCoords(pwPtr, interp, x, y) if (pwPtr->orient == ORIENT_HORIZONTAL) { if (Tk_IsMapped(pwPtr->tkwin)) { - sashHeight = Tk_Height(pwPtr->tkwin); + sashHeight = Tk_Height(pwPtr->tkwin); } else { - sashHeight = Tk_ReqHeight(pwPtr->tkwin); + sashHeight = Tk_ReqHeight(pwPtr->tkwin); } - sashHeight -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); + sashHeight -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) { - sashWidth = pwPtr->handleSize; - lpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2; - rpad = pwPtr->handleSize - lpad; - lpad += pwPtr->sashPad; - rpad += pwPtr->sashPad; + sashWidth = pwPtr->handleSize; + lpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2; + rpad = pwPtr->handleSize - lpad; + lpad += pwPtr->sashPad; + rpad += pwPtr->sashPad; } else { - sashWidth = pwPtr->sashWidth; + sashWidth = pwPtr->sashWidth; lpad = rpad = pwPtr->sashPad; } - tpad = bpad = 0; + tpad = bpad = 0; } else { if (pwPtr->showHandle && pwPtr->handleSize > pwPtr->sashWidth) { - sashHeight = pwPtr->handleSize; - tpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2; - bpad = pwPtr->handleSize - tpad; - tpad += pwPtr->sashPad; - bpad += pwPtr->sashPad; + sashHeight = pwPtr->handleSize; + tpad = (pwPtr->handleSize - pwPtr->sashWidth) / 2; + bpad = pwPtr->handleSize - tpad; + tpad += pwPtr->sashPad; + bpad += pwPtr->sashPad; } else { - sashHeight = pwPtr->sashWidth; + sashHeight = pwPtr->sashWidth; tpad = bpad = pwPtr->sashPad; } if (Tk_IsMapped(pwPtr->tkwin)) { - sashWidth = Tk_Width(pwPtr->tkwin); + sashWidth = Tk_Width(pwPtr->tkwin); } else { - sashWidth = Tk_ReqWidth(pwPtr->tkwin); + sashWidth = Tk_ReqWidth(pwPtr->tkwin); } - sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); - lpad = rpad = 0; + sashWidth -= 2 * Tk_InternalBorderWidth(pwPtr->tkwin); + lpad = rpad = 0; } - + isHandle = 0; found = -1; for (i = 0; i < pwPtr->numSlaves - 1; i++) { + if (pwPtr->slaves[i]->hide) { + continue; + } thisx = pwPtr->slaves[i]->sashx; thisy = pwPtr->slaves[i]->sashy; @@ -2909,6 +3016,7 @@ PanedWindowIdentifyCoords(pwPtr, interp, x, y) /* * Determine if the point is over the handle or the sash. */ + if (pwPtr->showHandle) { thisx = pwPtr->slaves[i]->handlex; thisy = pwPtr->slaves[i]->handley; @@ -2929,17 +3037,21 @@ PanedWindowIdentifyCoords(pwPtr, interp, x, y) /* * Set results. */ + if (found != -1) { Tcl_ListObjAppendElement(interp, list, Tcl_NewIntObj(found)); - if (isHandle) { - Tcl_ListObjAppendElement(interp, list, - Tcl_NewStringObj("handle", -1)); - } else { - Tcl_ListObjAppendElement(interp, list, - Tcl_NewStringObj("sash", -1)); - } + Tcl_ListObjAppendElement(interp, list, Tcl_NewStringObj( + (isHandle ? "handle" : "sash"), -1)); } - + Tcl_SetObjResult(interp, list); return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkPlace.c b/generic/tkPlace.c index b239947..951cd8f 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -1,85 +1,86 @@ -/* +/* * tkPlace.c -- * - * This file contains code to implement a simple geometry manager - * for Tk based on absolute placement or "rubber-sheet" placement. + * This file contains code to implement a simple geometry manager for Tk + * based on absolute placement or "rubber-sheet" placement. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" - /* * Border modes for relative placement: * - * BM_INSIDE: relative distances computed using area inside - * all borders of master window. - * BM_OUTSIDE: relative distances computed using outside area - * that includes all borders of master. - * BM_IGNORE: border issues are ignored: place relative to - * master's actual window size. + * BM_INSIDE: relative distances computed using area inside all + * borders of master window. + * BM_OUTSIDE: relative distances computed using outside area that + * includes all borders of master. + * BM_IGNORE: border issues are ignored: place relative to master's + * actual window size. */ static char *borderModeStrings[] = { - "inside", "outside", "ignore", (char *) NULL + "inside", "outside", "ignore", NULL }; typedef enum {BM_INSIDE, BM_OUTSIDE, BM_IGNORE} BorderMode; /* - * For each window whose geometry is managed by the placer there is - * a structure of the following type: + * For each window whose geometry is managed by the placer there is a + * structure of the following type: */ typedef struct Slave { Tk_Window tkwin; /* Tk's token for window. */ Tk_Window inTkwin; /* Token for the -in window. */ - struct Master *masterPtr; /* Pointer to information for window - * relative to which tkwin is placed. - * This isn't necessarily the logical - * parent of tkwin. NULL means the - * master was deleted or never assigned. */ - struct Slave *nextPtr; /* Next in list of windows placed relative - * to same master (NULL for end of list). */ + struct Master *masterPtr; /* Pointer to information for window relative + * to which tkwin is placed. This isn't + * necessarily the logical parent of tkwin. + * NULL means the master was deleted or never + * assigned. */ + struct Slave *nextPtr; /* Next in list of windows placed relative to + * same master (NULL for end of list). */ Tk_OptionTable optionTable; /* Table that defines configuration options * available for this command. */ /* - * Geometry information for window; where there are both relative - * and absolute values for the same attribute (e.g. x and relX) only - * one of them is actually used, depending on flags. + * Geometry information for window; where there are both relative and + * absolute values for the same attribute (e.g. x and relX) only one of + * them is actually used, depending on flags. */ int x, y; /* X and Y pixel coordinates for tkwin. */ - Tcl_Obj *xPtr, *yPtr; /* Tcl_Obj rep's of x, y coords, to keep - * pixel spec. information */ + Tcl_Obj *xPtr, *yPtr; /* Tcl_Obj rep's of x, y coords, to keep pixel + * spec. information. */ double relX, relY; /* X and Y coordinates relative to size of * master. */ int width, height; /* Absolute dimensions for tkwin. */ - Tcl_Obj *widthPtr; /* Tcl_Obj rep of width, to keep pixel spec */ - Tcl_Obj *heightPtr; /* Tcl_Obj rep of height, to keep pixel spec */ + Tcl_Obj *widthPtr; /* Tcl_Obj rep of width, to keep pixel + * spec. */ + Tcl_Obj *heightPtr; /* Tcl_Obj rep of height, to keep pixel + * spec. */ double relWidth, relHeight; /* Dimensions for tkwin relative to size of * master. */ Tcl_Obj *relWidthPtr; Tcl_Obj *relHeightPtr; - Tk_Anchor anchor; /* Which point on tkwin is placed at the - * given position. */ + Tk_Anchor anchor; /* Which point on tkwin is placed at the given + * position. */ BorderMode borderMode; /* How to treat borders of master window. */ - int flags; /* Various flags; see below for bit + int flags; /* Various flags; see below for bit * definitions. */ } Slave; /* * Type masks for options: */ + #define IN_MASK 1 -static Tk_OptionSpec optionSpecs[] = { +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_ANCHOR, "-anchor", NULL, NULL, "nw", -1, Tk_Offset(Slave, anchor), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-bordermode", NULL, NULL, "inside", -1, @@ -104,10 +105,9 @@ static Tk_OptionSpec optionSpecs[] = { Tk_Offset(Slave, x), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-y", NULL, NULL, "0", Tk_Offset(Slave, yPtr), Tk_Offset(Slave, y), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; - + /* * Flag definitions for Slave structures: * @@ -123,14 +123,14 @@ static Tk_OptionSpec optionSpecs[] = { #define CHILD_REL_HEIGHT 8 /* - * For each master window that has a slave managed by the placer there - * is a structure of the following form: + * For each master window that has a slave managed by the placer there is a + * structure of the following form: */ typedef struct Master { Tk_Window tkwin; /* Tk's token for master window. */ - struct Slave *slavePtr; /* First in linked list of slaves - * placed relative to this master. */ + struct Slave *slavePtr; /* First in linked list of slaves placed + * relative to this master. */ int *abortPtr; /* If non-NULL, it means that there is a nested * call to RecomputePlacement already working on * this window. *abortPtr may be set to 1 to @@ -143,58 +143,54 @@ typedef struct Master { /* * Flag definitions for masters: * - * PARENT_RECONFIG_PENDING - 1 means that a call to RecomputePlacement - * is already pending via a Do_When_Idle handler. + * PARENT_RECONFIG_PENDING - 1 means that a call to RecomputePlacement is + * already pending via a Do_When_Idle handler. */ #define PARENT_RECONFIG_PENDING 1 /* - * The following structure is the official type record for the - * placer: + * The following structure is the official type record for the placer: */ -static void PlaceRequestProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void PlaceLostSlaveProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); +static void PlaceRequestProc(ClientData clientData, + Tk_Window tkwin); +static void PlaceLostSlaveProc(ClientData clientData, + Tk_Window tkwin); -static Tk_GeomMgr placerType = { - "place", /* name */ - PlaceRequestProc, /* requestProc */ - PlaceLostSlaveProc, /* lostSlaveProc */ +static const Tk_GeomMgr placerType = { + "place", /* name */ + PlaceRequestProc, /* requestProc */ + PlaceLostSlaveProc, /* lostSlaveProc */ }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void SlaveStructureProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int ConfigureSlave _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Tk_OptionTable table, - int objc, Tcl_Obj *CONST objv[])); -static int PlaceInfoCommand _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin)); -static Slave * CreateSlave _ANSI_ARGS_((Tk_Window tkwin, - Tk_OptionTable table)); -static void FreeSlave _ANSI_ARGS_((Slave *slavePtr)); -static Slave * FindSlave _ANSI_ARGS_((Tk_Window tkwin)); -static Master * CreateMaster _ANSI_ARGS_((Tk_Window tkwin)); -static Master * FindMaster _ANSI_ARGS_((Tk_Window tkwin)); -static void MasterStructureProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void RecomputePlacement _ANSI_ARGS_((ClientData clientData)); -static void UnlinkSlave _ANSI_ARGS_((Slave *slavePtr)); +static void SlaveStructureProc(ClientData clientData, + XEvent *eventPtr); +static int ConfigureSlave(Tcl_Interp *interp, Tk_Window tkwin, + Tk_OptionTable table, int objc, + Tcl_Obj *CONST objv[]); +static int PlaceInfoCommand(Tcl_Interp *interp, Tk_Window tkwin); +static Slave * CreateSlave(Tk_Window tkwin, Tk_OptionTable table); +static void FreeSlave(Slave *slavePtr); +static Slave * FindSlave(Tk_Window tkwin); +static Master * CreateMaster(Tk_Window tkwin); +static Master * FindMaster(Tk_Window tkwin); +static void MasterStructureProc(ClientData clientData, + XEvent *eventPtr); +static void RecomputePlacement(ClientData clientData); +static void UnlinkSlave(Slave *slavePtr); /* *-------------------------------------------------------------- * * Tk_PlaceObjCmd -- * - * This procedure is invoked to process the "place" Tcl - * commands. See the user documentation for details on - * what it does. + * This function is invoked to process the "place" Tcl commands. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -206,11 +202,11 @@ static void UnlinkSlave _ANSI_ARGS_((Slave *slavePtr)); */ int -Tk_PlaceObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +Tk_PlaceObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window tkwin; Slave *slavePtr; @@ -218,23 +214,22 @@ Tk_PlaceObjCmd(clientData, interp, objc, objv) TkDisplay *dispPtr; Tk_OptionTable optionTable; static CONST char *optionStrings[] = { - "configure", "forget", "info", "slaves", (char *) NULL + "configure", "forget", "info", "slaves", NULL }; enum options { PLACE_CONFIGURE, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES }; int index; - - + if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option|pathName args"); return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, the cached pointer will be returned. + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. */ - optionTable = Tk_CreateOptionTable(interp, optionSpecs); + optionTable = Tk_CreateOptionTable(interp, optionSpecs); /* * Handle special shortcut where window name is first argument. @@ -262,8 +257,8 @@ Tk_PlaceObjCmd(clientData, interp, objc, objv) } /* - * Handle more general case of option followed by window name followed - * by possible additional arguments. + * Handle more general case of option followed by window name followed by + * possible additional arguments. */ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), @@ -289,81 +284,74 @@ Tk_PlaceObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case PLACE_CONFIGURE: { + case PLACE_CONFIGURE: + if (objc == 3 || objc == 4) { Tcl_Obj *objPtr; - if (objc == 3 || objc == 4) { - slavePtr = FindSlave(tkwin); - if (slavePtr == NULL) { - return TCL_OK; - } - objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, - optionTable, - (objc == 4) ? objv[3] : (Tcl_Obj *) NULL, tkwin); - if (objPtr == NULL) { - return TCL_ERROR; - } else { - Tcl_SetObjResult(interp, objPtr); - return TCL_OK; - } - } else { - return ConfigureSlave(interp, tkwin, optionTable, objc-3, - objv+3); - } - } - - case PLACE_FORGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "pathName"); - return TCL_ERROR; - } + slavePtr = FindSlave(tkwin); if (slavePtr == NULL) { return TCL_OK; } - if ((slavePtr->masterPtr != NULL) && - (slavePtr->masterPtr->tkwin != - Tk_Parent(slavePtr->tkwin))) { - Tk_UnmaintainGeometry(slavePtr->tkwin, - slavePtr->masterPtr->tkwin); - } - UnlinkSlave(slavePtr); - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, - (char *) tkwin)); - Tk_DeleteEventHandler(tkwin, StructureNotifyMask, - SlaveStructureProc, (ClientData) slavePtr); - Tk_ManageGeometry(tkwin, (Tk_GeomMgr *) NULL, (ClientData) NULL); - Tk_UnmapWindow(tkwin); - FreeSlave(slavePtr); - break; - } - - case PLACE_INFO: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "pathName"); + objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, optionTable, + (objc == 4) ? objv[3] : NULL, tkwin); + if (objPtr == NULL) { return TCL_ERROR; } - return PlaceInfoCommand(interp, tkwin); + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; } + return ConfigureSlave(interp, tkwin, optionTable, objc-3, objv+3); - case PLACE_SLAVES: { - Master *masterPtr; - Tcl_Obj *listPtr; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "pathName"); - return TCL_ERROR; - } - masterPtr = FindMaster(tkwin); - if (masterPtr != NULL) { - listPtr = Tcl_NewObj(); - for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - Tcl_ListObjAppendElement(interp, listPtr, - Tcl_NewStringObj(Tk_PathName(slavePtr->tkwin),-1)); - } - Tcl_SetObjResult(interp, listPtr); + case PLACE_FORGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "pathName"); + return TCL_ERROR; + } + slavePtr = FindSlave(tkwin); + if (slavePtr == NULL) { + return TCL_OK; + } + if ((slavePtr->masterPtr != NULL) && + (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) { + Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); + } + UnlinkSlave(slavePtr); + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, + (char *) tkwin)); + Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, + (ClientData) slavePtr); + Tk_ManageGeometry(tkwin, NULL, (ClientData) NULL); + Tk_UnmapWindow(tkwin); + FreeSlave(slavePtr); + break; + + case PLACE_INFO: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "pathName"); + return TCL_ERROR; + } + return PlaceInfoCommand(interp, tkwin); + + case PLACE_SLAVES: { + Master *masterPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "pathName"); + return TCL_ERROR; + } + masterPtr = FindMaster(tkwin); + if (masterPtr != NULL) { + Tcl_Obj *listPtr = Tcl_NewObj(); + + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + Tcl_ListObjAppendElement(interp, listPtr, + Tcl_NewStringObj(Tk_PathName(slavePtr->tkwin),-1)); } - break; + Tcl_SetObjResult(interp, listPtr); } + break; + } } return TCL_OK; @@ -374,8 +362,8 @@ Tk_PlaceObjCmd(clientData, interp, objc, objv) * * CreateSlave -- * - * Given a Tk_Window token, find the Slave structure corresponding - * to that token, creating a new one if necessary. + * Given a Tk_Window token, find the Slave structure corresponding to + * that token, creating a new one if necessary. * * Results: * Pointer to the Slave structure. @@ -387,34 +375,37 @@ Tk_PlaceObjCmd(clientData, interp, objc, objv) */ static Slave * -CreateSlave(tkwin, table) - Tk_Window tkwin; /* Token for desired slave. */ - Tk_OptionTable table; +CreateSlave( + Tk_Window tkwin, /* Token for desired slave. */ + Tk_OptionTable table) { Tcl_HashEntry *hPtr; register Slave *slavePtr; - int new; - TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr; - - hPtr = Tcl_CreateHashEntry(&dispPtr->slaveTable, (char *) tkwin, &new); - if (new) { - slavePtr = (Slave *) ckalloc(sizeof(Slave)); - memset(slavePtr, 0, sizeof(Slave)); - slavePtr->tkwin = tkwin; - slavePtr->inTkwin = None; - slavePtr->anchor = TK_ANCHOR_NW; - slavePtr->borderMode = BM_INSIDE; - slavePtr->optionTable = table; - Tcl_SetHashValue(hPtr, slavePtr); - Tk_CreateEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, - (ClientData) slavePtr); - Tk_ManageGeometry(tkwin, &placerType, (ClientData) slavePtr); - } else { - slavePtr = (Slave *) Tcl_GetHashValue(hPtr); + int isNew; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + + hPtr = Tcl_CreateHashEntry(&dispPtr->slaveTable, (char *) tkwin, &isNew); + if (!isNew) { + return (Slave *) Tcl_GetHashValue(hPtr); } + + /* + * No preexisting slave structure for that window, so make a new one and + * populate it with some default values. + */ + + slavePtr = (Slave *) ckalloc(sizeof(Slave)); + memset(slavePtr, 0, sizeof(Slave)); + slavePtr->tkwin = tkwin; + slavePtr->inTkwin = None; + slavePtr->anchor = TK_ANCHOR_NW; + slavePtr->borderMode = BM_INSIDE; + slavePtr->optionTable = table; + Tcl_SetHashValue(hPtr, slavePtr); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, + (ClientData) slavePtr); return slavePtr; } - /* *---------------------------------------------------------------------- @@ -433,22 +424,22 @@ CreateSlave(tkwin, table) */ static void -FreeSlave(Slave *slavePtr) +FreeSlave( + Slave *slavePtr) { Tk_FreeConfigOptions((char *) slavePtr, slavePtr->optionTable, slavePtr->tkwin); ckfree((char *) slavePtr); } - /* *---------------------------------------------------------------------- * * FindSlave -- * - * Given a Tk_Window token, find the Slave structure corresponding - * to that token. This is purely a lookup function; it will not - * create a record if one does not yet exist. + * Given a Tk_Window token, find the Slave structure corresponding to + * that token. This is purely a lookup function; it will not create a + * record if one does not yet exist. * * Results: * Pointer to Slave structure; NULL if none exists. @@ -460,12 +451,12 @@ FreeSlave(Slave *slavePtr) */ static Slave * -FindSlave(tkwin) - Tk_Window tkwin; /* Token for desired slave. */ +FindSlave( + Tk_Window tkwin) /* Token for desired slave. */ { Tcl_HashEntry *hPtr; register Slave *slavePtr; - TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin); if (hPtr == NULL) { @@ -480,8 +471,8 @@ FindSlave(tkwin) * * UnlinkSlave -- * - * This procedure removes a slave window from the chain of slaves - * in its master. + * This function removes a slave window from the chain of slaves in its + * master. * * Results: * None. @@ -493,8 +484,8 @@ FindSlave(tkwin) */ static void -UnlinkSlave(slavePtr) - Slave *slavePtr; /* Slave structure to be unlinked. */ +UnlinkSlave( + Slave *slavePtr) /* Slave structure to be unlinked. */ { register Master *masterPtr; register Slave *prevPtr; @@ -506,10 +497,9 @@ UnlinkSlave(slavePtr) if (masterPtr->slavePtr == slavePtr) { masterPtr->slavePtr = slavePtr->nextPtr; } else { - for (prevPtr = masterPtr->slavePtr; ; - prevPtr = prevPtr->nextPtr) { + for (prevPtr = masterPtr->slavePtr; ; prevPtr = prevPtr->nextPtr) { if (prevPtr == NULL) { - panic("UnlinkSlave couldn't find slave to unlink"); + Tcl_Panic("UnlinkSlave couldn't find slave to unlink"); } if (prevPtr->nextPtr == slavePtr) { prevPtr->nextPtr = slavePtr->nextPtr; @@ -529,8 +519,8 @@ UnlinkSlave(slavePtr) * * CreateMaster -- * - * Given a Tk_Window token, find the Master structure corresponding - * to that token, creating a new one if necessary. + * Given a Tk_Window token, find the Master structure corresponding to + * that token, creating a new one if necessary. * * Results: * Pointer to the Master structure. @@ -542,21 +532,21 @@ UnlinkSlave(slavePtr) */ static Master * -CreateMaster(tkwin) - Tk_Window tkwin; /* Token for desired master. */ +CreateMaster( + Tk_Window tkwin) /* Token for desired master. */ { Tcl_HashEntry *hPtr; register Master *masterPtr; - int new; - TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr; + int isNew; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - hPtr = Tcl_CreateHashEntry(&dispPtr->masterTable, (char *) tkwin, &new); - if (new) { + hPtr = Tcl_CreateHashEntry(&dispPtr->masterTable, (char *) tkwin, &isNew); + if (isNew) { masterPtr = (Master *) ckalloc(sizeof(Master)); - masterPtr->tkwin = tkwin; - masterPtr->slavePtr = NULL; - masterPtr->abortPtr = NULL; - masterPtr->flags = 0; + masterPtr->tkwin = tkwin; + masterPtr->slavePtr = NULL; + masterPtr->abortPtr = NULL; + masterPtr->flags = 0; Tcl_SetHashValue(hPtr, masterPtr); Tk_CreateEventHandler(masterPtr->tkwin, StructureNotifyMask, MasterStructureProc, (ClientData) masterPtr); @@ -571,13 +561,13 @@ CreateMaster(tkwin) * * FindMaster -- * - * Given a Tk_Window token, find the Master structure corresponding - * to that token. This is simply a lookup procedure; a new record - * will not be created if one does not already exist. + * Given a Tk_Window token, find the Master structure corresponding to + * that token. This is simply a lookup function; a new record will not be + * created if one does not already exist. * * Results: - * Pointer to the Master structure; NULL if one does not exist for - * the given Tk_Window token. + * Pointer to the Master structure; NULL if one does not exist for the + * given Tk_Window token. * * Side effects: * None. @@ -586,12 +576,12 @@ CreateMaster(tkwin) */ static Master * -FindMaster(tkwin) - Tk_Window tkwin; /* Token for desired master. */ +FindMaster( + Tk_Window tkwin) /* Token for desired master. */ { Tcl_HashEntry *hPtr; register Master *masterPtr; - TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, (char *) tkwin); if (hPtr == NULL) { @@ -606,38 +596,37 @@ FindMaster(tkwin) * * ConfigureSlave -- * - * This procedure is called to process an argv/argc list to - * reconfigure the placement of a window. + * This function is called to process an argv/argc list to reconfigure + * the placement of a window. * * Results: - * A standard Tcl result. If an error occurs then a message is - * left in the interp's result. + * A standard Tcl result. If an error occurs then a message is left in + * the interp's result. * * Side effects: - * Information in slavePtr may change, and slavePtr's master is - * scheduled for reconfiguration. + * Information in slavePtr may change, and slavePtr's master is scheduled + * for reconfiguration. * *---------------------------------------------------------------------- */ static int -ConfigureSlave(interp, tkwin, table, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Window tkwin; /* Token for the window to manipulate. */ - Tk_OptionTable table; /* Token for option table. */ - int objc; /* Number of config arguments. */ - Tcl_Obj *CONST objv[]; /* Object values for arguments. */ +ConfigureSlave( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Window tkwin, /* Token for the window to manipulate. */ + Tk_OptionTable table, /* Token for option table. */ + int objc, /* Number of config arguments. */ + Tcl_Obj *CONST objv[]) /* Object values for arguments. */ { register Master *masterPtr; Tk_SavedOptions savedOptions; int mask; - int result = TCL_OK; Slave *slavePtr; - + Tk_Window masterWin = (Tk_Window) NULL; + if (Tk_TopWinHierarchy(tkwin)) { Tcl_AppendResult(interp, "can't use placer on top-level window \"", - Tk_PathName(tkwin), "\"; use wm command instead", - (char *) NULL); + Tk_PathName(tkwin), "\"; use wm command instead", NULL); return TCL_ERROR; } @@ -645,24 +634,51 @@ ConfigureSlave(interp, tkwin, table, objc, objv) if (Tk_SetOptions(interp, (char *) slavePtr, table, objc, objv, slavePtr->tkwin, &savedOptions, &mask) != TCL_OK) { - Tk_RestoreSavedOptions(&savedOptions); - result = TCL_ERROR; - goto done; + goto error; + } + + /* + * Set slave flags. First clear the field, then add bits as needed. + */ + + slavePtr->flags = 0; + if (slavePtr->heightPtr) { + slavePtr->flags |= CHILD_HEIGHT; + } + + if (slavePtr->relHeightPtr) { + slavePtr->flags |= CHILD_REL_HEIGHT; + } + + if (slavePtr->relWidthPtr) { + slavePtr->flags |= CHILD_REL_WIDTH; + } + + if (slavePtr->widthPtr) { + slavePtr->flags |= CHILD_WIDTH; } - if (mask & IN_MASK) { + if (((mask & IN_MASK) == 0) && (slavePtr->masterPtr != NULL)) { + /* + * If no -in option was passed and the slave is already placed then + * just recompute the placement. + */ + + masterPtr = slavePtr->masterPtr; + goto scheduleLayout; + } else if (mask & IN_MASK) { /* -in changed */ Tk_Window tkwin; Tk_Window ancestor; - + tkwin = slavePtr->inTkwin; - + /* - * Make sure that the new master is either the logical parent - * of the slave or a descendant of that window, and that the - * master and slave aren't the same. + * Make sure that the new master is either the logical parent of the + * slave or a descendant of that window, and that the master and slave + * aren't the same. */ - + for (ancestor = tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == Tk_Parent(slavePtr->tkwin)) { break; @@ -670,80 +686,72 @@ ConfigureSlave(interp, tkwin, table, objc, objv) if (Tk_TopWinHierarchy(ancestor)) { Tcl_AppendResult(interp, "can't place ", Tk_PathName(slavePtr->tkwin), " relative to ", - Tk_PathName(tkwin), (char *) NULL); - result = TCL_ERROR; - Tk_RestoreSavedOptions(&savedOptions); - goto done; + Tk_PathName(tkwin), NULL); + goto error; } } if (slavePtr->tkwin == tkwin) { Tcl_AppendResult(interp, "can't place ", Tk_PathName(slavePtr->tkwin), " relative to itself", - (char *) NULL); - result = TCL_ERROR; - Tk_RestoreSavedOptions(&savedOptions); - goto done; + NULL); + goto error; } if ((slavePtr->masterPtr != NULL) && (slavePtr->masterPtr->tkwin == tkwin)) { /* - * Re-using same old master. Nothing to do. + * Re-using same old master. Nothing to do. */ - } else { - if ((slavePtr->masterPtr != NULL) - && (slavePtr->masterPtr->tkwin - != Tk_Parent(slavePtr->tkwin))) { - Tk_UnmaintainGeometry(slavePtr->tkwin, - slavePtr->masterPtr->tkwin); - } - UnlinkSlave(slavePtr); - slavePtr->masterPtr = CreateMaster(tkwin); - slavePtr->nextPtr = slavePtr->masterPtr->slavePtr; - slavePtr->masterPtr->slavePtr = slavePtr; + + masterPtr = slavePtr->masterPtr; + goto scheduleLayout; + } + if ((slavePtr->masterPtr != NULL) && + (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) { + Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } + UnlinkSlave(slavePtr); + masterWin = tkwin; } /* - * Set slave flags. First clear the field, then add bits as needed. + * If there's no master specified for this slave, use its Tk_Parent. */ - slavePtr->flags = 0; - if (slavePtr->heightPtr) { - slavePtr->flags |= CHILD_HEIGHT; - } - - if (slavePtr->relHeightPtr) { - slavePtr->flags |= CHILD_REL_HEIGHT; + if (masterWin == NULL) { + masterWin = Tk_Parent(slavePtr->tkwin); + slavePtr->inTkwin = masterWin; } - if (slavePtr->relWidthPtr) { - slavePtr->flags |= CHILD_REL_WIDTH; - } + /* + * Manage the slave window in this master. + */ - if (slavePtr->widthPtr) { - slavePtr->flags |= CHILD_WIDTH; - } + masterPtr = CreateMaster(masterWin); + slavePtr->masterPtr = masterPtr; + slavePtr->nextPtr = masterPtr->slavePtr; + masterPtr->slavePtr = slavePtr; + Tk_ManageGeometry(slavePtr->tkwin, &placerType, (ClientData) slavePtr); /* - * If there's no master specified for this slave, use its Tk_Parent. - * Then arrange for a placement recalculation in the master. + * Arrange for the master to be re-arranged at the first idle moment. */ + scheduleLayout: Tk_FreeSavedOptions(&savedOptions); - done: - masterPtr = slavePtr->masterPtr; - if (masterPtr == NULL) { - masterPtr = CreateMaster(Tk_Parent(slavePtr->tkwin)); - slavePtr->masterPtr = masterPtr; - slavePtr->nextPtr = masterPtr->slavePtr; - masterPtr->slavePtr = slavePtr; - } - slavePtr->inTkwin = masterPtr->tkwin; + if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) { masterPtr->flags |= PARENT_RECONFIG_PENDING; Tcl_DoWhenIdle(RecomputePlacement, (ClientData) masterPtr); } - return result; + return TCL_OK; + + /* + * Error while processing some option, cleanup and return. + */ + + error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; } /* @@ -751,27 +759,27 @@ ConfigureSlave(interp, tkwin, table, objc, objv) * * PlaceInfoCommand -- * - * Implementation of the [place info] subcommand. See the user + * Implementation of the [place info] subcommand. See the user * documentation for information on what it does. * * Results: * Standard Tcl result. * * Side effects: - * If the given tkwin is managed by the placer, this function will - * put information about that placement in the interp's result. + * If the given tkwin is managed by the placer, this function will put + * information about that placement in the interp's result. * *---------------------------------------------------------------------- */ static int -PlaceInfoCommand(interp, tkwin) - Tcl_Interp *interp; /* Interp into which to place result. */ - Tk_Window tkwin; /* Token for the window to get info on. */ +PlaceInfoCommand( + Tcl_Interp *interp, /* Interp into which to place result. */ + Tk_Window tkwin) /* Token for the window to get info on. */ { char buffer[32 + TCL_INTEGER_SPACE]; Slave *slavePtr; - + slavePtr = FindSlave(tkwin); if (slavePtr == NULL) { return TCL_OK; @@ -781,38 +789,38 @@ PlaceInfoCommand(interp, tkwin) Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin)); } sprintf(buffer, " -x %d", slavePtr->x); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); sprintf(buffer, " -relx %.4g", slavePtr->relX); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); sprintf(buffer, " -y %d", slavePtr->y); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); sprintf(buffer, " -rely %.4g", slavePtr->relY); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); if (slavePtr->flags & CHILD_WIDTH) { sprintf(buffer, " -width %d", slavePtr->width); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); } else { - Tcl_AppendResult(interp, " -width {}", (char *) NULL); + Tcl_AppendResult(interp, " -width {}", NULL); } if (slavePtr->flags & CHILD_REL_WIDTH) { sprintf(buffer, " -relwidth %.4g", slavePtr->relWidth); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); } else { - Tcl_AppendResult(interp, " -relwidth {}", (char *) NULL); + Tcl_AppendResult(interp, " -relwidth {}", NULL); } if (slavePtr->flags & CHILD_HEIGHT) { sprintf(buffer, " -height %d", slavePtr->height); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); } else { - Tcl_AppendResult(interp, " -height {}", (char *) NULL); + Tcl_AppendResult(interp, " -height {}", NULL); } if (slavePtr->flags & CHILD_REL_HEIGHT) { sprintf(buffer, " -relheight %.4g", slavePtr->relHeight); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); } else { - Tcl_AppendResult(interp, " -relheight {}", (char *) NULL); + Tcl_AppendResult(interp, " -relheight {}", NULL); } - + Tcl_AppendElement(interp, "-anchor"); Tcl_AppendElement(interp, Tk_NameOfAnchor(slavePtr->anchor)); Tcl_AppendElement(interp, "-bordermode"); @@ -825,8 +833,8 @@ PlaceInfoCommand(interp, tkwin) * * RecomputePlacement -- * - * This procedure is called as a when-idle handler. It recomputes - * the geometries of all the slaves of a given master. + * This function is called as a when-idle handler. It recomputes the + * geometries of all the slaves of a given master. * * Results: * None. @@ -838,8 +846,8 @@ PlaceInfoCommand(interp, tkwin) */ static void -RecomputePlacement(clientData) - ClientData clientData; /* Pointer to Master record. */ +RecomputePlacement( + ClientData clientData) /* Pointer to Master record. */ { register Master *masterPtr = (Master *) clientData; register Slave *slavePtr; @@ -866,18 +874,17 @@ RecomputePlacement(clientData) Tcl_Preserve((ClientData) masterPtr); /* - * Iterate over all the slaves for the master. Each slave's - * geometry can be computed independently of the other slaves. - * Changes to the window's structure could cause almost anything - * to happen, including deleting the parent or child. If this - * happens, we'll be told to abort. + * Iterate over all the slaves for the master. Each slave's geometry can + * be computed independently of the other slaves. Changes to the window's + * structure could cause almost anything to happen, including deleting the + * parent or child. If this happens, we'll be told to abort. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; - slavePtr = slavePtr->nextPtr) { + slavePtr = slavePtr->nextPtr) { /* - * Step 1: compute size and borderwidth of master, taking into - * account desired border mode. + * Step 1: compute size and borderwidth of master, taking into account + * desired border mode. */ masterX = masterY = 0; @@ -886,18 +893,18 @@ RecomputePlacement(clientData) if (slavePtr->borderMode == BM_INSIDE) { masterX = Tk_InternalBorderLeft(masterPtr->tkwin); masterY = Tk_InternalBorderTop(masterPtr->tkwin); - masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin); - masterHeight -= masterY + + masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin); + masterHeight -= masterY + Tk_InternalBorderBottom(masterPtr->tkwin); } else if (slavePtr->borderMode == BM_OUTSIDE) { masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width; - masterWidth -= 2 * masterX; - masterHeight -= 2 * masterY; + masterWidth -= 2 * masterX; + masterHeight -= 2 * masterY; } /* - * Step 2: compute size of slave (outside dimensions including - * border) and location of anchor point within master. + * Step 2: compute size of slave (outside dimensions including border) + * and location of anchor point within master. */ x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth); @@ -911,11 +918,11 @@ RecomputePlacement(clientData) } if (slavePtr->flags & CHILD_REL_WIDTH) { /* - * The code below is a bit tricky. In order to round - * correctly when both relX and relWidth are specified, - * compute the location of the right edge and round that, - * then compute width. If we compute the width and round - * it, rounding errors in relX and relWidth accumulate. + * The code below is a bit tricky. In order to round correctly + * when both relX and relWidth are specified, compute the + * location of the right edge and round that, then compute + * width. If we compute the width and round it, rounding + * errors in relX and relWidth accumulate. */ x2 = x1 + (slavePtr->relWidth*masterWidth); @@ -932,7 +939,7 @@ RecomputePlacement(clientData) height += slavePtr->height; } if (slavePtr->flags & CHILD_REL_HEIGHT) { - /* + /* * See note above for rounding errors in width computation. */ @@ -946,47 +953,47 @@ RecomputePlacement(clientData) } /* - * Step 3: adjust the x and y positions so that the desired - * anchor point on the slave appears at that position. Also - * adjust for the border mode and master's border. + * Step 3: adjust the x and y positions so that the desired anchor + * point on the slave appears at that position. Also adjust for the + * border mode and master's border. */ switch (slavePtr->anchor) { - case TK_ANCHOR_N: - x -= width/2; - break; - case TK_ANCHOR_NE: - x -= width; - break; - case TK_ANCHOR_E: - x -= width; - y -= height/2; - break; - case TK_ANCHOR_SE: - x -= width; - y -= height; - break; - case TK_ANCHOR_S: - x -= width/2; - y -= height; - break; - case TK_ANCHOR_SW: - y -= height; - break; - case TK_ANCHOR_W: - y -= height/2; - break; - case TK_ANCHOR_NW: - break; - case TK_ANCHOR_CENTER: - x -= width/2; - y -= height/2; - break; + case TK_ANCHOR_N: + x -= width/2; + break; + case TK_ANCHOR_NE: + x -= width; + break; + case TK_ANCHOR_E: + x -= width; + y -= height/2; + break; + case TK_ANCHOR_SE: + x -= width; + y -= height; + break; + case TK_ANCHOR_S: + x -= width/2; + y -= height; + break; + case TK_ANCHOR_SW: + y -= height; + break; + case TK_ANCHOR_W: + y -= height/2; + break; + case TK_ANCHOR_NW: + break; + case TK_ANCHOR_CENTER: + x -= width/2; + y -= height/2; + break; } /* * Step 4: adjust width and height again to reflect inside dimensions - * of window rather than outside. Also make sure that the width and + * of window rather than outside. Also make sure that the width and * height aren't zero. */ @@ -1000,11 +1007,10 @@ RecomputePlacement(clientData) } /* - * Step 5: reconfigure the window and map it if needed. If the - * slave is a child of the master, we do this ourselves. If the - * slave isn't a child of the master, let Tk_MaintainGeometry do - * the work (it will re-adjust things as relevant windows map, - * unmap, and move). + * Step 5: reconfigure the window and map it if needed. If the slave + * is a child of the master, we do this ourselves. If the slave isn't + * a child of the master, let Tk_MaintainGeometry do the work (it will + * re-adjust things as relevant windows map, unmap, and move). */ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { @@ -1019,8 +1025,8 @@ RecomputePlacement(clientData) } /* - * Don't map the slave unless the master is mapped: the slave - * will get mapped later, when the master is mapped. + * Don't map the slave unless the master is mapped: the slave will + * get mapped later, when the master is mapped. */ if (Tk_IsMapped(masterPtr->tkwin)) { @@ -1046,24 +1052,24 @@ RecomputePlacement(clientData) * * MasterStructureProc -- * - * This procedure is invoked by the Tk event handler when - * StructureNotify events occur for a master window. + * This function is invoked by the Tk event handler when StructureNotify + * events occur for a master window. * * Results: * None. * * Side effects: - * Structures get cleaned up if the window was deleted. If the - * window was resized then slave geometries get recomputed. + * Structures get cleaned up if the window was deleted. If the window was + * resized then slave geometries get recomputed. * *---------------------------------------------------------------------- */ static void -MasterStructureProc(clientData, eventPtr) - ClientData clientData; /* Pointer to Master structure for window +MasterStructureProc( + ClientData clientData, /* Pointer to Master structure for window * referred to by eventPtr. */ - XEvent *eventPtr; /* Describes what just happened. */ + XEvent *eventPtr) /* Describes what just happened. */ { register Master *masterPtr = (Master *) clientData; register Slave *slavePtr, *nextPtr; @@ -1094,8 +1100,8 @@ MasterStructureProc(clientData, eventPtr) Tcl_EventuallyFree((ClientData) masterPtr, TCL_DYNAMIC); } else if (eventPtr->type == MapNotify) { /* - * When a master gets mapped, must redo the geometry computation - * so that all of its slaves get remapped. + * When a master gets mapped, must redo the geometry computation so + * that all of its slaves get remapped. */ if ((masterPtr->slavePtr != NULL) @@ -1105,8 +1111,8 @@ MasterStructureProc(clientData, eventPtr) } } else if (eventPtr->type == UnmapNotify) { /* - * Unmap all of the slaves when the master gets unmapped, - * so that they don't keep redisplaying themselves. + * Unmap all of the slaves when the master gets unmapped, so that they + * don't keep redisplaying themselves. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; @@ -1121,8 +1127,8 @@ MasterStructureProc(clientData, eventPtr) * * SlaveStructureProc -- * - * This procedure is invoked by the Tk event handler when - * StructureNotify events occur for a slave window. + * This function is invoked by the Tk event handler when StructureNotify + * events occur for a slave window. * * Results: * None. @@ -1134,16 +1140,18 @@ MasterStructureProc(clientData, eventPtr) */ static void -SlaveStructureProc(clientData, eventPtr) - ClientData clientData; /* Pointer to Slave structure for window +SlaveStructureProc( + ClientData clientData, /* Pointer to Slave structure for window * referred to by eventPtr. */ - XEvent *eventPtr; /* Describes what just happened. */ + XEvent *eventPtr) /* Describes what just happened. */ { register Slave *slavePtr = (Slave *) clientData; - TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; + TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; if (eventPtr->type == DestroyNotify) { - UnlinkSlave(slavePtr); + if (slavePtr->masterPtr != NULL) { + UnlinkSlave(slavePtr); + } Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) slavePtr->tkwin)); FreeSlave(slavePtr); @@ -1155,25 +1163,24 @@ SlaveStructureProc(clientData, eventPtr) * * PlaceRequestProc -- * - * This procedure is invoked by Tk whenever a slave managed by us - * changes its requested geometry. + * This function is invoked by Tk whenever a slave managed by us changes + * its requested geometry. * * Results: * None. * * Side effects: - * The window will get relayed out, if its requested size has - * anything to do with its actual size. + * The window will get relayed out, if its requested size has anything to + * do with its actual size. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void -PlaceRequestProc(clientData, tkwin) - ClientData clientData; /* Pointer to our record for slave. */ - Tk_Window tkwin; /* Window that changed its desired - * size. */ +PlaceRequestProc( + ClientData clientData, /* Pointer to our record for slave. */ + Tk_Window tkwin) /* Window that changed its desired size. */ { Slave *slavePtr = (Slave *) clientData; Master *masterPtr; @@ -1197,8 +1204,8 @@ PlaceRequestProc(clientData, tkwin) * * PlaceLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This function is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. @@ -1211,22 +1218,30 @@ PlaceRequestProc(clientData, tkwin) /* ARGSUSED */ static void -PlaceLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Slave structure for slave window that - * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ +PlaceLostSlaveProc( + ClientData clientData, /* Slave structure for slave window that was + * stolen away. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { register Slave *slavePtr = (Slave *) clientData; - TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; + TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } Tk_UnmapWindow(tkwin); UnlinkSlave(slavePtr); - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, - (char *) tkwin)); + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, + (char *) tkwin)); Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, (ClientData) slavePtr); FreeSlave(slavePtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkPlatDecls.h b/generic/tkPlatDecls.h index ecc5919..5b386ee 100644 --- a/generic/tkPlatDecls.h +++ b/generic/tkPlatDecls.h @@ -29,128 +29,129 @@ * Exported function declarations: */ -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ +#ifndef Tk_AttachHWND_TCL_DECLARED +#define Tk_AttachHWND_TCL_DECLARED /* 0 */ -EXTERN Window Tk_AttachHWND _ANSI_ARGS_((Tk_Window tkwin, - HWND hwnd)); -/* 1 */ -EXTERN HINSTANCE Tk_GetHINSTANCE _ANSI_ARGS_((void)); -/* 2 */ -EXTERN HWND Tk_GetHWND _ANSI_ARGS_((Window window)); -/* 3 */ -EXTERN Tk_Window Tk_HWNDToWindow _ANSI_ARGS_((HWND hwnd)); -/* 4 */ -EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd, int x, int y)); -/* 5 */ -EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd, - UINT message, WPARAM wParam, LPARAM lParam, - LRESULT *result)); -#endif /* __WIN32__ */ -#ifdef MAC_TCL -/* 0 */ -EXTERN void Tk_MacSetEmbedHandler _ANSI_ARGS_(( - Tk_MacEmbedRegisterWinProc *registerWinProcPtr, - Tk_MacEmbedGetGrafPortProc *getPortProcPtr, - Tk_MacEmbedMakeContainerExistProc *containerExistProcPtr, - Tk_MacEmbedGetClipProc *getClipProc, - Tk_MacEmbedGetOffsetInParentProc *getOffsetProc)); +EXTERN Window Tk_AttachHWND(Tk_Window tkwin, HWND hwnd); +#endif +#ifndef Tk_GetHINSTANCE_TCL_DECLARED +#define Tk_GetHINSTANCE_TCL_DECLARED /* 1 */ -EXTERN void Tk_MacTurnOffMenus _ANSI_ARGS_((void)); +EXTERN HINSTANCE Tk_GetHINSTANCE(void); +#endif +#ifndef Tk_GetHWND_TCL_DECLARED +#define Tk_GetHWND_TCL_DECLARED /* 2 */ -EXTERN void Tk_MacTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt)); +EXTERN HWND Tk_GetHWND(Window window); +#endif +#ifndef Tk_HWNDToWindow_TCL_DECLARED +#define Tk_HWNDToWindow_TCL_DECLARED /* 3 */ -EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN Tk_Window Tk_HWNDToWindow(HWND hwnd); +#endif +#ifndef Tk_PointerEvent_TCL_DECLARED +#define Tk_PointerEvent_TCL_DECLARED /* 4 */ -EXTERN void TkMacInitAppleEvents _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void Tk_PointerEvent(HWND hwnd, int x, int y); +#endif +#ifndef Tk_TranslateWinEvent_TCL_DECLARED +#define Tk_TranslateWinEvent_TCL_DECLARED /* 5 */ -EXTERN int TkMacConvertEvent _ANSI_ARGS_((EventRecord *eventPtr)); -/* 6 */ -EXTERN int TkMacConvertTkEvent _ANSI_ARGS_(( - EventRecord *eventPtr, Window window)); -/* 7 */ -EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, - int x, int y, int width, int height, - int flags)); -/* 8 */ -EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow *winPtr)); -/* 9 */ -EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void)); -/* 10 */ -EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable)); -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +EXTERN int Tk_TranslateWinEvent(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam, + LRESULT *result); +#endif +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ +#ifndef Tk_MacOSXSetEmbedHandler_TCL_DECLARED +#define Tk_MacOSXSetEmbedHandler_TCL_DECLARED /* 0 */ -EXTERN void Tk_MacOSXSetEmbedHandler _ANSI_ARGS_(( +EXTERN void Tk_MacOSXSetEmbedHandler( Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr, Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr, Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr, Tk_MacOSXEmbedGetClipProc *getClipProc, - Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc)); + Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc); +#endif +#ifndef Tk_MacOSXTurnOffMenus_TCL_DECLARED +#define Tk_MacOSXTurnOffMenus_TCL_DECLARED /* 1 */ -EXTERN void Tk_MacOSXTurnOffMenus _ANSI_ARGS_((void)); +EXTERN void Tk_MacOSXTurnOffMenus(void); +#endif +#ifndef Tk_MacOSXTkOwnsCursor_TCL_DECLARED +#define Tk_MacOSXTkOwnsCursor_TCL_DECLARED /* 2 */ -EXTERN void Tk_MacOSXTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt)); +EXTERN void Tk_MacOSXTkOwnsCursor(int tkOwnsIt); +#endif +#ifndef TkMacOSXInitMenus_TCL_DECLARED +#define TkMacOSXInitMenus_TCL_DECLARED /* 3 */ -EXTERN void TkMacOSXInitMenus _ANSI_ARGS_((Tcl_Interp *interp)); +EXTERN void TkMacOSXInitMenus(Tcl_Interp *interp); +#endif +#ifndef TkMacOSXInitAppleEvents_TCL_DECLARED +#define TkMacOSXInitAppleEvents_TCL_DECLARED /* 4 */ -EXTERN void TkMacOSXInitAppleEvents _ANSI_ARGS_(( - Tcl_Interp *interp)); +EXTERN void TkMacOSXInitAppleEvents(Tcl_Interp *interp); +#endif +#ifndef TkGenWMConfigureEvent_TCL_DECLARED +#define TkGenWMConfigureEvent_TCL_DECLARED /* 5 */ -EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin, - int x, int y, int width, int height, - int flags)); +EXTERN void TkGenWMConfigureEvent(Tk_Window tkwin, int x, int y, + int width, int height, int flags); +#endif +#ifndef TkMacOSXInvalClipRgns_TCL_DECLARED +#define TkMacOSXInvalClipRgns_TCL_DECLARED /* 6 */ -EXTERN void TkMacOSXInvalClipRgns _ANSI_ARGS_((Tk_Window tkwin)); +EXTERN void TkMacOSXInvalClipRgns(Tk_Window tkwin); +#endif +#ifndef TkMacOSXGetDrawablePort_TCL_DECLARED +#define TkMacOSXGetDrawablePort_TCL_DECLARED /* 7 */ -EXTERN GWorldPtr TkMacOSXGetDrawablePort _ANSI_ARGS_(( - Drawable drawable)); +EXTERN GWorldPtr TkMacOSXGetDrawablePort(Drawable drawable); +#endif +#ifndef TkMacOSXGetRootControl_TCL_DECLARED +#define TkMacOSXGetRootControl_TCL_DECLARED /* 8 */ -EXTERN ControlRef TkMacOSXGetRootControl _ANSI_ARGS_(( - Drawable drawable)); +EXTERN ControlRef TkMacOSXGetRootControl(Drawable drawable); +#endif +#ifndef Tk_MacOSXSetupTkNotifier_TCL_DECLARED +#define Tk_MacOSXSetupTkNotifier_TCL_DECLARED /* 9 */ -EXTERN void Tk_MacOSXSetupTkNotifier _ANSI_ARGS_((void)); +EXTERN void Tk_MacOSXSetupTkNotifier(void); +#endif +#ifndef Tk_MacOSXIsAppInFront_TCL_DECLARED +#define Tk_MacOSXIsAppInFront_TCL_DECLARED /* 10 */ -EXTERN int Tk_MacOSXIsAppInFront _ANSI_ARGS_((void)); -#endif /* MAC_OSX_TK */ +EXTERN int Tk_MacOSXIsAppInFront(void); +#endif +#endif /* AQUA */ typedef struct TkPlatStubs { int magic; struct TkPlatStubHooks *hooks; -#ifdef __WIN32__ - Window (*tk_AttachHWND) _ANSI_ARGS_((Tk_Window tkwin, HWND hwnd)); /* 0 */ - HINSTANCE (*tk_GetHINSTANCE) _ANSI_ARGS_((void)); /* 1 */ - HWND (*tk_GetHWND) _ANSI_ARGS_((Window window)); /* 2 */ - Tk_Window (*tk_HWNDToWindow) _ANSI_ARGS_((HWND hwnd)); /* 3 */ - void (*tk_PointerEvent) _ANSI_ARGS_((HWND hwnd, int x, int y)); /* 4 */ - int (*tk_TranslateWinEvent) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)); /* 5 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - void (*tk_MacSetEmbedHandler) _ANSI_ARGS_((Tk_MacEmbedRegisterWinProc *registerWinProcPtr, Tk_MacEmbedGetGrafPortProc *getPortProcPtr, Tk_MacEmbedMakeContainerExistProc *containerExistProcPtr, Tk_MacEmbedGetClipProc *getClipProc, Tk_MacEmbedGetOffsetInParentProc *getOffsetProc)); /* 0 */ - void (*tk_MacTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */ - void (*tk_MacTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */ - void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp *interp)); /* 3 */ - void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp *interp)); /* 4 */ - int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord *eventPtr)); /* 5 */ - int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord *eventPtr, Window window)); /* 6 */ - void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 7 */ - void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow *winPtr)); /* 8 */ - int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 9 */ - GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 10 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - void (*tk_MacOSXSetEmbedHandler) _ANSI_ARGS_((Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr, Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr, Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr, Tk_MacOSXEmbedGetClipProc *getClipProc, Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc)); /* 0 */ - void (*tk_MacOSXTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */ - void (*tk_MacOSXTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */ - void (*tkMacOSXInitMenus) _ANSI_ARGS_((Tcl_Interp *interp)); /* 3 */ - void (*tkMacOSXInitAppleEvents) _ANSI_ARGS_((Tcl_Interp *interp)); /* 4 */ - void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 5 */ - void (*tkMacOSXInvalClipRgns) _ANSI_ARGS_((Tk_Window tkwin)); /* 6 */ - GWorldPtr (*tkMacOSXGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 7 */ - ControlRef (*tkMacOSXGetRootControl) _ANSI_ARGS_((Drawable drawable)); /* 8 */ - void (*tk_MacOSXSetupTkNotifier) _ANSI_ARGS_((void)); /* 9 */ - int (*tk_MacOSXIsAppInFront) _ANSI_ARGS_((void)); /* 10 */ -#endif /* MAC_OSX_TK */ +#ifdef __WIN32__ /* WIN */ + Window (*tk_AttachHWND) (Tk_Window tkwin, HWND hwnd); /* 0 */ + HINSTANCE (*tk_GetHINSTANCE) (void); /* 1 */ + HWND (*tk_GetHWND) (Window window); /* 2 */ + Tk_Window (*tk_HWNDToWindow) (HWND hwnd); /* 3 */ + void (*tk_PointerEvent) (HWND hwnd, int x, int y); /* 4 */ + int (*tk_TranslateWinEvent) (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); /* 5 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + void (*tk_MacOSXSetEmbedHandler) (Tk_MacOSXEmbedRegisterWinProc *registerWinProcPtr, Tk_MacOSXEmbedGetGrafPortProc *getPortProcPtr, Tk_MacOSXEmbedMakeContainerExistProc *containerExistProcPtr, Tk_MacOSXEmbedGetClipProc *getClipProc, Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc); /* 0 */ + void (*tk_MacOSXTurnOffMenus) (void); /* 1 */ + void (*tk_MacOSXTkOwnsCursor) (int tkOwnsIt); /* 2 */ + void (*tkMacOSXInitMenus) (Tcl_Interp *interp); /* 3 */ + void (*tkMacOSXInitAppleEvents) (Tcl_Interp *interp); /* 4 */ + void (*tkGenWMConfigureEvent) (Tk_Window tkwin, int x, int y, int width, int height, int flags); /* 5 */ + void (*tkMacOSXInvalClipRgns) (Tk_Window tkwin); /* 6 */ + GWorldPtr (*tkMacOSXGetDrawablePort) (Drawable drawable); /* 7 */ + ControlRef (*tkMacOSXGetRootControl) (Drawable drawable); /* 8 */ + void (*tk_MacOSXSetupTkNotifier) (void); /* 9 */ + int (*tk_MacOSXIsAppInFront) (void); /* 10 */ +#endif /* AQUA */ } TkPlatStubs; #ifdef __cplusplus @@ -167,7 +168,7 @@ extern TkPlatStubs *tkPlatStubsPtr; * Inline function declarations: */ -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ #ifndef Tk_AttachHWND #define Tk_AttachHWND \ (tkPlatStubsPtr->tk_AttachHWND) /* 0 */ @@ -192,54 +193,8 @@ extern TkPlatStubs *tkPlatStubsPtr; #define Tk_TranslateWinEvent \ (tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */ #endif -#endif /* __WIN32__ */ -#ifdef MAC_TCL -#ifndef Tk_MacSetEmbedHandler -#define Tk_MacSetEmbedHandler \ - (tkPlatStubsPtr->tk_MacSetEmbedHandler) /* 0 */ -#endif -#ifndef Tk_MacTurnOffMenus -#define Tk_MacTurnOffMenus \ - (tkPlatStubsPtr->tk_MacTurnOffMenus) /* 1 */ -#endif -#ifndef Tk_MacTkOwnsCursor -#define Tk_MacTkOwnsCursor \ - (tkPlatStubsPtr->tk_MacTkOwnsCursor) /* 2 */ -#endif -#ifndef TkMacInitMenus -#define TkMacInitMenus \ - (tkPlatStubsPtr->tkMacInitMenus) /* 3 */ -#endif -#ifndef TkMacInitAppleEvents -#define TkMacInitAppleEvents \ - (tkPlatStubsPtr->tkMacInitAppleEvents) /* 4 */ -#endif -#ifndef TkMacConvertEvent -#define TkMacConvertEvent \ - (tkPlatStubsPtr->tkMacConvertEvent) /* 5 */ -#endif -#ifndef TkMacConvertTkEvent -#define TkMacConvertTkEvent \ - (tkPlatStubsPtr->tkMacConvertTkEvent) /* 6 */ -#endif -#ifndef TkGenWMConfigureEvent -#define TkGenWMConfigureEvent \ - (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 7 */ -#endif -#ifndef TkMacInvalClipRgns -#define TkMacInvalClipRgns \ - (tkPlatStubsPtr->tkMacInvalClipRgns) /* 8 */ -#endif -#ifndef TkMacHaveAppearance -#define TkMacHaveAppearance \ - (tkPlatStubsPtr->tkMacHaveAppearance) /* 9 */ -#endif -#ifndef TkMacGetDrawablePort -#define TkMacGetDrawablePort \ - (tkPlatStubsPtr->tkMacGetDrawablePort) /* 10 */ -#endif -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ #ifndef Tk_MacOSXSetEmbedHandler #define Tk_MacOSXSetEmbedHandler \ (tkPlatStubsPtr->tk_MacOSXSetEmbedHandler) /* 0 */ @@ -284,7 +239,7 @@ extern TkPlatStubs *tkPlatStubsPtr; #define Tk_MacOSXIsAppInFront \ (tkPlatStubsPtr->tk_MacOSXIsAppInFront) /* 10 */ #endif -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ #endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */ diff --git a/generic/tkPointer.c b/generic/tkPointer.c index 17c7424..4051552 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -1,15 +1,15 @@ -/* +/* * tkPointer.c -- * - * This file contains functions for emulating the X server - * pointer and grab state machine. This file is used by the - * Mac and Windows platforms to generate appropriate enter/leave - * events, and to update the global grab window information. + * This file contains functions for emulating the X server pointer and + * grab state machine. This file is used by the Mac and Windows platforms + * to generate appropriate enter/leave events, and to update the global + * grab window information. * * Copyright (c) 1996 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" @@ -18,19 +18,14 @@ #include "tkWinInt.h" #endif -#if defined(MAC_TCL) -#include "tkMacInt.h" -#define Cursor XCursor -#endif - #if defined(MAC_OSX_TK) #include "tkMacOSXInt.h" #define Cursor XCursor #endif /* - * Mask that selects any of the state bits corresponding to buttons, - * plus masks that select individual buttons' bits: + * Mask that selects any of the state bits corresponding to buttons, plus + * masks that select individual buttons' bits: */ #define ALL_BUTTONS \ @@ -41,15 +36,15 @@ static unsigned int buttonMasks[] = { #define ButtonMask(b) (buttonMasks[(b)-Button1]) typedef struct ThreadSpecificData { - TkWindow *grabWinPtr; /* Window that defines the top of the - * grab tree in a global grab. */ - int lastState; /* Last known state flags. */ - XPoint lastPos; /* Last reported mouse position. */ - TkWindow *lastWinPtr; /* Last reported mouse window. */ - TkWindow *restrictWinPtr; /* Window to which all mouse events - * will be reported. */ - TkWindow *cursorWinPtr; /* Window that is currently - * controlling the global cursor. */ + TkWindow *grabWinPtr; /* Window that defines the top of the grab + * tree in a global grab. */ + int lastState; /* Last known state flags. */ + XPoint lastPos; /* Last reported mouse position. */ + TkWindow *lastWinPtr; /* Last reported mouse window. */ + TkWindow *restrictWinPtr; /* Window to which all mouse events will be + * reported. */ + TkWindow *cursorWinPtr; /* Window that is currently controlling the + * global cursor. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -57,12 +52,11 @@ static Tcl_ThreadDataKey dataKey; * Forward declarations of procedures used in this file. */ -static int GenerateEnterLeave _ANSI_ARGS_((TkWindow *winPtr, - int x, int y, int state)); -static void InitializeEvent _ANSI_ARGS_((XEvent* eventPtr, - TkWindow *winPtr, int type, int x, int y, - int state, int detail)); -static void UpdateCursor _ANSI_ARGS_((TkWindow *winPtr)); +static int GenerateEnterLeave(TkWindow *winPtr, int x, int y, + int state); +static void InitializeEvent(XEvent* eventPtr, TkWindow *winPtr, + int type, int x, int y, int state, int detail); +static void UpdateCursor(TkWindow *winPtr); /* *---------------------------------------------------------------------- @@ -81,13 +75,13 @@ static void UpdateCursor _ANSI_ARGS_((TkWindow *winPtr)); */ static void -InitializeEvent(eventPtr, winPtr, type, x, y, state, detail) - XEvent* eventPtr; /* Event structure to initialize. */ - TkWindow *winPtr; /* Window to make event relative to. */ - int type; /* Message type. */ - int x, y; /* Root coords of event. */ - int state; /* State flags. */ - int detail; /* Detail value. */ +InitializeEvent( + XEvent *eventPtr, /* Event structure to initialize. */ + TkWindow *winPtr, /* Window to make event relative to. */ + int type, /* Message type. */ + int x, int y, /* Root coords of event. */ + int state, /* State flags. */ + int detail) /* Detail value. */ { eventPtr->type = type; eventPtr->xany.serial = LastKnownRequestProcessed(winPtr->display); @@ -100,22 +94,22 @@ InitializeEvent(eventPtr, winPtr, type, x, y, state, detail) eventPtr->xcrossing.y_root = y; switch (type) { - case EnterNotify: - case LeaveNotify: - eventPtr->xcrossing.mode = NotifyNormal; - eventPtr->xcrossing.state = state; - eventPtr->xcrossing.detail = detail; - eventPtr->xcrossing.focus = False; - break; - case MotionNotify: - eventPtr->xmotion.state = state; - eventPtr->xmotion.is_hint = detail; - break; - case ButtonPress: - case ButtonRelease: - eventPtr->xbutton.state = state; - eventPtr->xbutton.button = detail; - break; + case EnterNotify: + case LeaveNotify: + eventPtr->xcrossing.mode = NotifyNormal; + eventPtr->xcrossing.state = state; + eventPtr->xcrossing.detail = detail; + eventPtr->xcrossing.focus = False; + break; + case MotionNotify: + eventPtr->xmotion.state = state; + eventPtr->xmotion.is_hint = detail; + break; + case ButtonPress: + case ButtonRelease: + eventPtr->xbutton.state = state; + eventPtr->xbutton.button = detail; + break; } TkChangeEventWindow(eventPtr, winPtr); } @@ -125,8 +119,8 @@ InitializeEvent(eventPtr, winPtr, type, x, y, state, detail) * * GenerateEnterLeave -- * - * Update the current mouse window and position, and generate - * any enter/leave events that are needed. + * Update the current mouse window and position, and generate any + * enter/leave events that are needed. * * Results: * Returns 1 if enter/leave events were generated. @@ -138,14 +132,14 @@ InitializeEvent(eventPtr, winPtr, type, x, y, state, detail) */ static int -GenerateEnterLeave(winPtr, x, y, state) - TkWindow *winPtr; /* Current Tk window (or NULL). */ - int x,y; /* Current mouse position in root coords. */ - int state; /* State flags. */ +GenerateEnterLeave( + TkWindow *winPtr, /* Current Tk window (or NULL). */ + int x, int y, /* Current mouse position in root coords. */ + int state) /* State flags. */ { int crossed = 0; /* 1 if mouse crossed a window boundary */ - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); TkWindow *restrictWinPtr = tsdPtr->restrictWinPtr; TkWindow *lastWinPtr = tsdPtr->lastWinPtr; @@ -157,8 +151,8 @@ GenerateEnterLeave(winPtr, x, y, state) oldPos = TkPositionInTree(lastWinPtr, restrictWinPtr); /* - * Check if the mouse crossed into or out of the restrict - * window. If so, we need to generate an Enter or Leave event. + * Check if the mouse crossed into or out of the restrict window. + * If so, we need to generate an Enter or Leave event. */ if ((newPos != oldPos) && ((newPos == TK_GRAB_IN_TREE) @@ -218,8 +212,8 @@ GenerateEnterLeave(winPtr, x, y, state) * * Tk_UpdatePointer -- * - * This function updates the pointer state machine given an - * the current window, position and modifier state. + * This function updates the pointer state machine given an the current + * window, position and modifier state. * * Results: * None. @@ -231,14 +225,14 @@ GenerateEnterLeave(winPtr, x, y, state) */ void -Tk_UpdatePointer(tkwin, x, y, state) - Tk_Window tkwin; /* Window to which pointer event - * is reported. May be NULL. */ - int x, y; /* Pointer location in root coords. */ - int state; /* Modifier state mask. */ +Tk_UpdatePointer( + Tk_Window tkwin, /* Window to which pointer event is reported. + * May be NULL. */ + int x, int y, /* Pointer location in root coords. */ + int state) /* Modifier state mask. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); TkWindow *winPtr = (TkWindow *)tkwin; TkWindow *targetWinPtr; XPoint pos; @@ -250,15 +244,15 @@ Tk_UpdatePointer(tkwin, x, y, state) pos.y = y; /* - * Use the current keyboard state, but the old mouse button - * state since we haven't generated the button events yet. + * Use the current keyboard state, but the old mouse button state since we + * haven't generated the button events yet. */ tsdPtr->lastState = (state & ~ALL_BUTTONS) | (tsdPtr->lastState & ALL_BUTTONS); /* - * Generate Enter/Leave events. If the pointer has crossed window + * Generate Enter/Leave events. If the pointer has crossed window * boundaries, update the current mouse position so we don't generate * redundant motion events. */ @@ -272,20 +266,19 @@ Tk_UpdatePointer(tkwin, x, y, state) * between the current button state and the last known button state. */ - for (b = Button1; b <= Button3; b++) { + for (b = Button1; b <= Button5; b++) { mask = ButtonMask(b); if (changes & mask) { - if (state & mask) { + if (state & mask) { type = ButtonPress; - /* + /* * ButtonPress - Set restrict window if we aren't grabbed, or * if this is the first button down. */ if (!tsdPtr->restrictWinPtr) { if (!tsdPtr->grabWinPtr) { - /* * Mouse is not grabbed, so set a button grab. */ @@ -294,10 +287,9 @@ Tk_UpdatePointer(tkwin, x, y, state) TkpSetCapture(tsdPtr->restrictWinPtr); } else if ((tsdPtr->lastState & ALL_BUTTONS) == 0) { - /* - * Mouse is in a non-button grab, so ensure - * the button grab is inside the grab tree. + * Mouse is in a non-button grab, so ensure the button + * grab is inside the grab tree. */ if (TkPositionInTree(winPtr, tsdPtr->grabWinPtr) @@ -313,7 +305,7 @@ Tk_UpdatePointer(tkwin, x, y, state) } else { type = ButtonRelease; - /* + /* * ButtonRelease - Release the mouse capture and clear the * restrict window when the last button is released. If we * are in a global grab, restore the grab window capture. @@ -324,9 +316,9 @@ Tk_UpdatePointer(tkwin, x, y, state) } /* - * If we are releasing a restrict window, then we need - * to send the button event followed by mouse motion from - * the restrict window to the current mouse position. + * If we are releasing a restrict window, then we need to send + * the button event followed by mouse motion from the restrict + * window to the current mouse position. */ if (tsdPtr->restrictWinPtr) { @@ -340,14 +332,14 @@ Tk_UpdatePointer(tkwin, x, y, state) GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState); tsdPtr->lastPos = pos; continue; - } + } } /* - * If a restrict window is set, make sure the pointer event - * is reported relative to that window. Otherwise, if a - * global grab is in effect then events outside of windows - * managed by Tk should be reported to the grab window. + * If a restrict window is set, make sure the pointer event is + * reported relative to that window. Otherwise, if a global grab + * is in effect then events outside of windows managed by Tk + * should be reported to the grab window. */ if (tsdPtr->restrictWinPtr) { @@ -362,7 +354,7 @@ Tk_UpdatePointer(tkwin, x, y, state) * If we still have a target window, send the event. */ - if (winPtr != NULL) { + if (targetWinPtr != NULL) { InitializeEvent(&event, targetWinPtr, type, x, y, tsdPtr->lastState, b); Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); @@ -373,7 +365,7 @@ Tk_UpdatePointer(tkwin, x, y, state) */ tsdPtr->lastState = (type == ButtonPress) - ? (tsdPtr->lastState | mask) : (tsdPtr->lastState & ~mask); + ? (tsdPtr->lastState | mask) : (tsdPtr->lastState & ~mask); tsdPtr->lastPos = pos; } } @@ -393,8 +385,8 @@ Tk_UpdatePointer(tkwin, x, y, state) UpdateCursor(targetWinPtr); /* - * If no other events caused the position to be updated, - * generate a motion event. + * If no other events caused the position to be updated, generate a motion + * event. */ if (tsdPtr->lastPos.x != pos.x || tsdPtr->lastPos.y != pos.y) { @@ -418,42 +410,41 @@ Tk_UpdatePointer(tkwin, x, y, state) * * XGrabPointer -- * - * Capture the mouse so event are reported outside of toplevels. - * Note that this is a very limited implementation that only - * supports GrabModeAsync and owner_events True. + * Capture the mouse so event are reported outside of toplevels. Note + * that this is a very limited implementation that only supports + * GrabModeAsync and owner_events True. * * Results: * Always returns GrabSuccess. * * Side effects: - * Turns on mouse capture, sets the global grab pointer, and - * clears any window restrictions. + * Turns on mouse capture, sets the global grab pointer, and clears any + * window restrictions. * *---------------------------------------------------------------------- */ int -XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, - keyboard_mode, confine_to, cursor, time) - Display* display; - Window grab_window; - Bool owner_events; - unsigned int event_mask; - int pointer_mode; - int keyboard_mode; - Window confine_to; - Cursor cursor; - Time time; +XGrabPointer( + Display *display, + Window grab_window, + Bool owner_events, + unsigned int event_mask, + int pointer_mode, + int keyboard_mode, + Window confine_to, + Cursor cursor, + Time time) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); display->request++; tsdPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window); tsdPtr->restrictWinPtr = NULL; TkpSetCapture(tsdPtr->grabWinPtr); - if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr) - != TK_GRAB_IN_TREE) { + if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr) + != TK_GRAB_IN_TREE) { UpdateCursor(tsdPtr->grabWinPtr); } return GrabSuccess; @@ -476,12 +467,12 @@ XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, */ void -XUngrabPointer(display, time) - Display* display; - Time time; +XUngrabPointer( + Display *display, + Time time) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); display->request++; tsdPtr->grabWinPtr = NULL; @@ -507,11 +498,11 @@ XUngrabPointer(display, time) */ void -TkPointerDeadWindow(winPtr) - TkWindow *winPtr; +TkPointerDeadWindow( + TkWindow *winPtr) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr == tsdPtr->lastWinPtr) { tsdPtr->lastWinPtr = NULL; @@ -532,8 +523,8 @@ TkPointerDeadWindow(winPtr) * * UpdateCursor -- * - * Set the windows global cursor to the cursor associated with - * the given Tk window. + * Set the windows global cursor to the cursor associated with the given + * Tk window. * * Results: * None. @@ -545,17 +536,16 @@ TkPointerDeadWindow(winPtr) */ static void -UpdateCursor(winPtr) - TkWindow *winPtr; +UpdateCursor( + TkWindow *winPtr) { Cursor cursor = None; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * A window inherits its cursor from its parent if it doesn't - * have one of its own. Top level windows inherit the default - * cursor. + * A window inherits its cursor from its parent if it doesn't have one of + * its own. Top level windows inherit the default cursor. */ tsdPtr->cursorWinPtr = winPtr; @@ -576,10 +566,9 @@ UpdateCursor(winPtr) * * XDefineCursor -- * - * This function is called to update the cursor on a window. - * Since the mouse might be in the specified window, we need to - * check the specified window against the current mouse position - * and grab state. + * This function is called to update the cursor on a window. Since the + * mouse might be in the specified window, we need to check the specified + * window against the current mouse position and grab state. * * Results: * None. @@ -591,14 +580,14 @@ UpdateCursor(winPtr) */ void -XDefineCursor(display, w, cursor) - Display* display; - Window w; - Cursor cursor; +XDefineCursor( + Display *display, + Window w, + Cursor cursor) { TkWindow *winPtr = (TkWindow *)Tk_IdToWindow(display, w); - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (tsdPtr->cursorWinPtr == winPtr) { UpdateCursor(winPtr); @@ -611,10 +600,10 @@ XDefineCursor(display, w, cursor) * * TkGenerateActivateEvents -- * - * This function is called by the Mac and Windows window manager - * routines when a toplevel window is activated or deactivated. - * Activate/Deactivate events will be sent to every subwindow of - * the toplevel followed by a FocusIn/FocusOut message. + * This function is called by the Mac and Windows window manager routines + * when a toplevel window is activated or deactivated. + * Activate/Deactivate events will be sent to every subwindow of the + * toplevel followed by a FocusIn/FocusOut message. * * Results: * None. @@ -626,16 +615,16 @@ XDefineCursor(display, w, cursor) */ void -TkGenerateActivateEvents(winPtr, active) - TkWindow *winPtr; /* Toplevel to activate. */ - int active; /* Non-zero if the window is being - * activated, else 0.*/ +TkGenerateActivateEvents( + TkWindow *winPtr, /* Toplevel to activate. */ + int active) /* Non-zero if the window is being activated, + * else 0.*/ { XEvent event; - - /* - * Generate Activate and Deactivate events. This event - * is sent to every subwindow in a toplevel window. + + /* + * Generate Activate and Deactivate events. This event is sent to every + * subwindow in a toplevel window. */ event.xany.serial = winPtr->display->request++; @@ -645,5 +634,12 @@ TkGenerateActivateEvents(winPtr, active) event.xany.type = active ? ActivateNotify : DeactivateNotify; TkQueueEventForAllChildren(winPtr, &event); - } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkPort.h b/generic/tkPort.h index ca592d1..00c49fd 100644 --- a/generic/tkPort.h +++ b/generic/tkPort.h @@ -24,9 +24,7 @@ #if defined(__WIN32__) || defined(_WIN32) # include "tkWinPort.h" #else -# if defined(MAC_TCL) -# include "tkMacPort.h" -# elif defined(MAC_OSX_TK) +# if defined(MAC_OSX_TK) # include "tkMacOSXPort.h" # else # include "tkUnixPort.h" diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c index b7ab331..c9cd7cb 100644 --- a/generic/tkRectOval.c +++ b/generic/tkRectOval.c @@ -1,20 +1,17 @@ -/* +/* * tkRectOval.c -- * - * This file implements rectangle and oval items for canvas - * widgets. + * This file implements rectangle and oval items for canvas widgets. * * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> -#include "tk.h" #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" /* @@ -23,18 +20,22 @@ typedef struct RectOvalItem { Tk_Item header; /* Generic stuff that's the same for all - * types. MUST BE FIRST IN STRUCTURE. */ + * types. MUST BE FIRST IN STRUCTURE. */ Tk_Outline outline; /* Outline structure */ double bbox[4]; /* Coordinates of bounding box for rectangle - * or oval (x1, y1, x2, y2). Item includes - * x1 and x2 but not y1 and y2. */ + * or oval (x1, y1, x2, y2). Item includes x1 + * and x2 but not y1 and y2. */ Tk_TSOffset tsoffset; XColor *fillColor; /* Color for filling rectangle/oval. */ - XColor *activeFillColor; /* Color for filling rectangle/oval if state is active. */ - XColor *disabledFillColor; /* Color for filling rectangle/oval if state is disabled. */ + XColor *activeFillColor; /* Color for filling rectangle/oval if state + * is active. */ + XColor *disabledFillColor; /* Color for filling rectangle/oval if state + * is disabled. */ Pixmap fillStipple; /* Stipple bitmap for filling item. */ - Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is active. */ - Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is disabled. */ + Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is + * active. */ + Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is + * disabled. */ GC fillGC; /* Graphics context for filling item. */ } RectOvalItem; @@ -64,160 +65,150 @@ static Tk_CustomOption pixelOption = { }; static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.activeDash), + {TK_CONFIG_CUSTOM, "-activedash", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.activeDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, activeFillColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.activeColor), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.activeStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, activeFillStipple), + {TK_CONFIG_COLOR, "-activefill", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, activeFillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-activeoutline", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.activeColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_BITMAP, "-activeoutlinestipple", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.activeStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, activeFillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL, "0.0", Tk_Offset(RectOvalItem, outline.activeWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.dash), + {TK_CONFIG_CUSTOM, "-dash", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.dash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL, + {TK_CONFIG_PIXELS, "-dashoffset", NULL, NULL, "0", Tk_Offset(RectOvalItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledDash), + {TK_CONFIG_CUSTOM, "-disableddash", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.disabledDash), TK_CONFIG_NULL_OK, &dashOption}, - {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, disabledFillColor), + {TK_CONFIG_COLOR, "-disabledfill", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, disabledFillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_COLOR, "-disabledoutline", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.disabledColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledColor), + {TK_CONFIG_BITMAP, "-disabledoutlinestipple", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.disabledStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, disabledFillStipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_PIXELS, "-disabledwidth", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, disabledFillStipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_PIXELS, "-disabledwidth", NULL, NULL, "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-fill", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-offset", NULL, NULL, "0,0", Tk_Offset(RectOvalItem, tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, - {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL, + {TK_CONFIG_COLOR, "-outline", NULL, NULL, "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL, + {TK_CONFIG_CUSTOM, "-outlineoffset", NULL, NULL, "0,0", Tk_Offset(RectOvalItem, outline.tsoffset), TK_CONFIG_DONT_SET_DEFAULT, &offsetOption}, - {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, outline.stipple), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK, - &stateOption}, - {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, - (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, - {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL, + {TK_CONFIG_BITMAP, "-outlinestipple", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, outline.stipple), TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-state", NULL, NULL, + NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK, &stateOption}, + {TK_CONFIG_BITMAP, "-stipple", NULL, NULL, + NULL, Tk_Offset(RectOvalItem, fillStipple),TK_CONFIG_NULL_OK}, + {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, + NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, + {TK_CONFIG_CUSTOM, "-width", NULL, NULL, "1.0", Tk_Offset(RectOvalItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT, &pixelOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static void ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas canvas, - RectOvalItem *rectOvalPtr)); -static int ConfigureRectOval _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[], int flags)); -static int CreateRectOval _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, struct Tk_Item *itemPtr, - int objc, Tcl_Obj *CONST objv[])); -static void DeleteRectOval _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display)); -static void DisplayRectOval _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, Display *display, Drawable dst, - int x, int y, int width, int height)); -static int OvalToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *areaPtr)); -static double OvalToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *pointPtr)); -static int RectOvalCoords _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int objc, - Tcl_Obj *CONST objv[])); -static int RectOvalToPostscript _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); -static int RectToArea _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *areaPtr)); -static double RectToPoint _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double *pointPtr)); -static void ScaleRectOval _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double originX, double originY, - double scaleX, double scaleY)); -static void TranslateRectOval _ANSI_ARGS_((Tk_Canvas canvas, - Tk_Item *itemPtr, double deltaX, double deltaY)); +static void ComputeRectOvalBbox(Tk_Canvas canvas, + RectOvalItem *rectOvalPtr); +static int ConfigureRectOval(Tcl_Interp *interp, Tk_Canvas canvas, + Tk_Item *itemPtr, int objc, Tcl_Obj *CONST objv[], + int flags); +static int CreateRectOval(Tcl_Interp *interp, Tk_Canvas canvas, + Tk_Item *itemPtr, int objc, Tcl_Obj *CONST objv[]); +static void DeleteRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, + Display *display); +static void DisplayRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, + Display *display, Drawable dst, int x, int y, + int width, int height); +static int OvalToArea(Tk_Canvas canvas, Tk_Item *itemPtr, + double *areaPtr); +static double OvalToPoint(Tk_Canvas canvas, Tk_Item *itemPtr, + double *pointPtr); +static int RectOvalCoords(Tcl_Interp *interp, Tk_Canvas canvas, + Tk_Item *itemPtr, int objc, Tcl_Obj *CONST objv[]); +static int RectOvalToPostscript(Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass); +static int RectToArea(Tk_Canvas canvas, Tk_Item *itemPtr, + double *areaPtr); +static double RectToPoint(Tk_Canvas canvas, Tk_Item *itemPtr, + double *pointPtr); +static void ScaleRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, + double originX, double originY, + double scaleX, double scaleY); +static void TranslateRectOval(Tk_Canvas canvas, Tk_Item *itemPtr, + double deltaX, double deltaY); /* - * The structures below defines the rectangle and oval item types - * by means of procedures that can be invoked by generic item code. + * The structures below defines the rectangle and oval item types by means of + * functions that can be invoked by generic item code. */ Tk_ItemType tkRectangleType = { - "rectangle", /* name */ - sizeof(RectOvalItem), /* itemSize */ - CreateRectOval, /* createProc */ - configSpecs, /* configSpecs */ - ConfigureRectOval, /* configureProc */ - RectOvalCoords, /* coordProc */ - DeleteRectOval, /* deleteProc */ - DisplayRectOval, /* displayProc */ - TK_CONFIG_OBJS, /* flags */ - RectToPoint, /* pointProc */ - RectToArea, /* areaProc */ - RectOvalToPostscript, /* postscriptProc */ - ScaleRectOval, /* scaleProc */ - TranslateRectOval, /* translateProc */ - (Tk_ItemIndexProc *) NULL, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* icursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ - (Tk_ItemInsertProc *) NULL, /* insertProc */ - (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + "rectangle", /* name */ + sizeof(RectOvalItem), /* itemSize */ + CreateRectOval, /* createProc */ + configSpecs, /* configSpecs */ + ConfigureRectOval, /* configureProc */ + RectOvalCoords, /* coordProc */ + DeleteRectOval, /* deleteProc */ + DisplayRectOval, /* displayProc */ + TK_CONFIG_OBJS, /* flags */ + RectToPoint, /* pointProc */ + RectToArea, /* areaProc */ + RectOvalToPostscript, /* postscriptProc */ + ScaleRectOval, /* scaleProc */ + TranslateRectOval, /* translateProc */ + NULL, /* indexProc */ + NULL, /* icursorProc */ + NULL, /* selectionProc */ + NULL, /* insertProc */ + NULL, /* dTextProc */ + NULL, /* nextPtr */ }; Tk_ItemType tkOvalType = { - "oval", /* name */ - sizeof(RectOvalItem), /* itemSize */ - CreateRectOval, /* createProc */ - configSpecs, /* configSpecs */ - ConfigureRectOval, /* configureProc */ - RectOvalCoords, /* coordProc */ - DeleteRectOval, /* deleteProc */ - DisplayRectOval, /* displayProc */ - TK_CONFIG_OBJS, /* flags */ - OvalToPoint, /* pointProc */ - OvalToArea, /* areaProc */ - RectOvalToPostscript, /* postscriptProc */ - ScaleRectOval, /* scaleProc */ - TranslateRectOval, /* translateProc */ - (Tk_ItemIndexProc *) NULL, /* indexProc */ - (Tk_ItemCursorProc *) NULL, /* cursorProc */ - (Tk_ItemSelectionProc *) NULL, /* selectionProc */ - (Tk_ItemInsertProc *) NULL, /* insertProc */ - (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL, /* nextPtr */ + "oval", /* name */ + sizeof(RectOvalItem), /* itemSize */ + CreateRectOval, /* createProc */ + configSpecs, /* configSpecs */ + ConfigureRectOval, /* configureProc */ + RectOvalCoords, /* coordProc */ + DeleteRectOval, /* deleteProc */ + DisplayRectOval, /* displayProc */ + TK_CONFIG_OBJS, /* flags */ + OvalToPoint, /* pointProc */ + OvalToArea, /* areaProc */ + RectOvalToPostscript, /* postscriptProc */ + ScaleRectOval, /* scaleProc */ + TranslateRectOval, /* translateProc */ + NULL, /* indexProc */ + NULL, /* cursorProc */ + NULL, /* selectionProc */ + NULL, /* insertProc */ + NULL, /* dTextProc */ + NULL, /* nextPtr */ }; /* @@ -225,14 +216,14 @@ Tk_ItemType tkOvalType = { * * CreateRectOval -- * - * This procedure is invoked to create a new rectangle - * or oval item in a canvas. + * This function is invoked to create a new rectangle or oval item in a + * canvas. * * Results: - * A standard Tcl return value. If an error occurred in - * creating the item, then an error message is left in - * the interp's result; in this case itemPtr is left uninitialized, - * so it can be safely freed by the caller. + * A standard Tcl return value. If an error occurred in creating the + * item, then an error message is left in the interp's result; in this + * case itemPtr is left uninitialized, so it can be safely freed by the + * caller. * * Side effects: * A new rectangle or oval item is created. @@ -241,24 +232,24 @@ Tk_ItemType tkOvalType = { */ static int -CreateRectOval(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* For error reporting. */ - Tk_Canvas canvas; /* Canvas to hold new item. */ - Tk_Item *itemPtr; /* Record to hold new item; header - * has been initialized by caller. */ - int objc; /* Number of arguments in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing rectangle. */ +CreateRectOval( + Tcl_Interp *interp, /* For error reporting. */ + Tk_Canvas canvas, /* Canvas to hold new item. */ + Tk_Item *itemPtr, /* Record to hold new item; header has been + * initialized by caller. */ + int objc, /* Number of arguments in objv. */ + Tcl_Obj *CONST objv[]) /* Arguments describing rectangle. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; int i; if (objc == 0) { - panic("canvas did not pass any coords\n"); + Tcl_Panic("canvas did not pass any coords\n"); } /* - * Carry out initialization that is needed in order to clean - * up after errors during the the remainder of this procedure. + * Carry out initialization that is needed in order to clean up after + * errors during the the remainder of this function. */ Tk_CreateOutline(&(rectOvalPtr->outline)); @@ -279,6 +270,7 @@ CreateRectOval(interp, canvas, itemPtr, objc, objv) for (i = 1; i < objc; i++) { char *arg = Tcl_GetString(objv[i]); + if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { break; } @@ -291,7 +283,7 @@ CreateRectOval(interp, canvas, itemPtr, objc, objv) return TCL_OK; } - error: + error: DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; } @@ -301,9 +293,9 @@ CreateRectOval(interp, canvas, itemPtr, objc, objv) * * RectOvalCoords -- * - * This procedure is invoked to process the "coords" widget - * command on rectangles and ovals. See the user documentation - * for details on what it does. + * This function is invoked to process the "coords" widget command on + * rectangles and ovals. See the user documentation for details on what + * it does. * * Results: * Returns TCL_OK or TCL_ERROR, and sets the interp's result. @@ -315,60 +307,73 @@ CreateRectOval(interp, canvas, itemPtr, objc, objv) */ static int -RectOvalCoords(interp, canvas, itemPtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item whose coordinates are to be - * read or modified. */ - int objc; /* Number of coordinates supplied in - * objv. */ - Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1, - * x2, y2, ... */ +RectOvalCoords( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item whose coordinates are to be read or + * modified. */ + int objc, /* Number of coordinates supplied in objv. */ + Tcl_Obj *CONST objv[]) /* Array of coordinates: x1,y1,x2,y2,... */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; + /* + * If no coordinates, return the current coordinates (i.e. bounding box). + */ + if (objc == 0) { Tcl_Obj *obj = Tcl_NewObj(); - Tcl_Obj *subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]); - Tcl_ListObjAppendElement(interp, obj, subobj); - subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]); - Tcl_ListObjAppendElement(interp, obj, subobj); - subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]); - Tcl_ListObjAppendElement(interp, obj, subobj); - subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]); - Tcl_ListObjAppendElement(interp, obj, subobj); + + Tcl_ListObjAppendElement(NULL, obj, + Tcl_NewDoubleObj(rectOvalPtr->bbox[0])); + Tcl_ListObjAppendElement(NULL, obj, + Tcl_NewDoubleObj(rectOvalPtr->bbox[1])); + Tcl_ListObjAppendElement(NULL, obj, + Tcl_NewDoubleObj(rectOvalPtr->bbox[2])); + Tcl_ListObjAppendElement(NULL, obj, + Tcl_NewDoubleObj(rectOvalPtr->bbox[3])); Tcl_SetObjResult(interp, obj); - } else if ((objc == 1)||(objc == 4)) { - if (objc==1) { - if (Tcl_ListObjGetElements(interp, objv[0], &objc, - (Tcl_Obj ***) &objv) != TCL_OK) { - return TCL_ERROR; - } else if (objc != 4) { - char buf[64 + TCL_INTEGER_SPACE]; + return TCL_OK; + } - sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", objc); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - return TCL_ERROR; - } - } - if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], - &rectOvalPtr->bbox[0]) != TCL_OK) - || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1], - &rectOvalPtr->bbox[1]) != TCL_OK) - || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2], - &rectOvalPtr->bbox[2]) != TCL_OK) - || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3], - &rectOvalPtr->bbox[3]) != TCL_OK)) { + /* + * If one "coordinate", treat as list of coordinates. + */ + + if (objc == 1) { + if (Tcl_ListObjGetElements(interp, objv[0], &objc, + (Tcl_Obj ***) &objv) != TCL_OK) { return TCL_ERROR; } - ComputeRectOvalBbox(canvas, rectOvalPtr); - } else { + } + + /* + * Better have four coordinates now. Spit out an error message otherwise. + */ + + if (objc != 4) { char buf[64 + TCL_INTEGER_SPACE]; - + sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", objc); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; } + + /* + * Parse the coordinates and update our bounding box. + */ + + if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], + &rectOvalPtr->bbox[0]) != TCL_OK) + || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1], + &rectOvalPtr->bbox[1]) != TCL_OK) + || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[2], + &rectOvalPtr->bbox[2]) != TCL_OK) + || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[3], + &rectOvalPtr->bbox[3]) != TCL_OK)) { + return TCL_ERROR; + } + ComputeRectOvalBbox(canvas, rectOvalPtr); return TCL_OK; } @@ -377,29 +382,28 @@ RectOvalCoords(interp, canvas, itemPtr, objc, objv) * * ConfigureRectOval -- * - * This procedure is invoked to configure various aspects - * of a rectangle or oval item, such as its border and - * background colors. + * This function is invoked to configure various aspects of a rectangle + * or oval item, such as its border and background colors. * * Results: - * A standard Tcl result code. If an error occurs, then - * an error message is left in the interp's result. + * A standard Tcl result code. If an error occurs, then an error message + * is left in the interp's result. * * Side effects: - * Configuration information, such as colors and stipple - * patterns, may be set for itemPtr. + * Configuration information, such as colors and stipple patterns, may be + * set for itemPtr. * *-------------------------------------------------------------- */ static int -ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Canvas canvas; /* Canvas containing itemPtr. */ - Tk_Item *itemPtr; /* Rectangle item to reconfigure. */ - int objc; /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureRectOval( + Tcl_Interp *interp, /* Used for error reporting. */ + Tk_Canvas canvas, /* Canvas containing itemPtr. */ + Tk_Item *itemPtr, /* Rectangle item to reconfigure. */ + int objc, /* Number of elements in objv. */ + Tcl_Obj *CONST objv[], /* Arguments describing things to configure. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; XGCValues gcValues; @@ -414,14 +418,14 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) tkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc, - (CONST char **) objv, (char *) rectOvalPtr, flags|TK_CONFIG_OBJS)) { + (CONST char **)objv, (char *) rectOvalPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } state = itemPtr->state; /* - * A few of the options require additional processing, such as - * graphics contexts. + * A few of the options require additional processing, such as graphics + * contexts. */ if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width || @@ -440,27 +444,28 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) if (flags & TK_OFFSET_LEFT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5); } else if (flags & TK_OFFSET_CENTER) { - tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2); + tsoffset->xoffset = (int) + ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2); } else if (flags & TK_OFFSET_RIGHT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5); } if (flags & TK_OFFSET_TOP) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5); } else if (flags & TK_OFFSET_MIDDLE) { - tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2); + tsoffset->yoffset = (int) + ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2); } else if (flags & TK_OFFSET_BOTTOM) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5); } /* - * Configure the outline graphics context. If mask is non-zero, - * the gc has changed and must be reallocated, provided that the - * new settings specify a valid outline (non-zero width and non-NULL - * color) + * Configure the outline graphics context. If mask is non-zero, the gc has + * changed and must be reallocated, provided that the new settings specify + * a valid outline (non-zero width and non-NULL color) */ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, - &(rectOvalPtr->outline)); + &(rectOvalPtr->outline)); if (mask && \ rectOvalPtr->outline.width != 0 && \ rectOvalPtr->outline.color != NULL) { @@ -475,10 +480,10 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) } rectOvalPtr->outline.gc = newGC; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } - if (state==TK_STATE_HIDDEN) { + if (state == TK_STATE_HIDDEN) { ComputeRectOvalBbox(canvas, rectOvalPtr); return TCL_OK; } @@ -492,7 +497,7 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) if (rectOvalPtr->activeFillStipple!=None) { stipple = rectOvalPtr->activeFillStipple; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (rectOvalPtr->disabledFillColor!=NULL) { color = rectOvalPtr->disabledFillColor; } @@ -533,14 +538,16 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) if (flags & TK_OFFSET_LEFT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5); } else if (flags & TK_OFFSET_CENTER) { - tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2); + tsoffset->xoffset = (int) + ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2); } else if (flags & TK_OFFSET_RIGHT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5); } if (flags & TK_OFFSET_TOP) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5); } else if (flags & TK_OFFSET_MIDDLE) { - tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2); + tsoffset->yoffset = (int) + ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2); } else if (flags & TK_OFFSET_BOTTOM) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5); } @@ -555,8 +562,8 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) * * DeleteRectOval -- * - * This procedure is called to clean up the data structure - * associated with a rectangle or oval item. + * This function is called to clean up the data structure associated with + * a rectangle or oval item. * * Results: * None. @@ -568,11 +575,10 @@ ConfigureRectOval(interp, canvas, itemPtr, objc, objv, flags) */ static void -DeleteRectOval(canvas, itemPtr, display) - Tk_Canvas canvas; /* Info about overall widget. */ - Tk_Item *itemPtr; /* Item that is being deleted. */ - Display *display; /* Display containing window for - * canvas. */ +DeleteRectOval( + Tk_Canvas canvas, /* Info about overall widget. */ + Tk_Item *itemPtr, /* Item that is being deleted. */ + Display *display) /* Display containing window for canvas. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; @@ -605,37 +611,34 @@ DeleteRectOval(canvas, itemPtr, display) * * ComputeRectOvalBbox -- * - * This procedure is invoked to compute the bounding box of - * all the pixels that may be drawn as part of a rectangle - * or oval. + * This function is invoked to compute the bounding box of all the pixels + * that may be drawn as part of a rectangle or oval. * * Results: * None. * * Side effects: - * The fields x1, y1, x2, and y2 are updated in the header - * for itemPtr. + * The fields x1, y1, x2, and y2 are updated in the header for itemPtr. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -ComputeRectOvalBbox(canvas, rectOvalPtr) - Tk_Canvas canvas; /* Canvas that contains item. */ - RectOvalItem *rectOvalPtr; /* Item whose bbox is to be - * recomputed. */ +ComputeRectOvalBbox( + Tk_Canvas canvas, /* Canvas that contains item. */ + RectOvalItem *rectOvalPtr) /* Item whose bbox is to be recomputed. */ { int bloat, tmp; double dtmp, width; Tk_State state = rectOvalPtr->header.state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } width = rectOvalPtr->outline.width; - if (state==TK_STATE_HIDDEN) { + if (state == TK_STATE_HIDDEN) { rectOvalPtr->header.x1 = rectOvalPtr->header.y1 = rectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1; return; @@ -644,7 +647,7 @@ ComputeRectOvalBbox(canvas, rectOvalPtr) if (rectOvalPtr->outline.activeWidth>width) { width = rectOvalPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (rectOvalPtr->outline.disabledWidth>0) { width = rectOvalPtr->outline.disabledWidth; } @@ -655,24 +658,25 @@ ComputeRectOvalBbox(canvas, rectOvalPtr) */ if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) { - double tmp; - tmp = rectOvalPtr->bbox[3]; + double tmpY = rectOvalPtr->bbox[3]; + rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1]; - rectOvalPtr->bbox[1] = tmp; + rectOvalPtr->bbox[1] = tmpY; } if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) { - double tmp; - tmp = rectOvalPtr->bbox[2]; + double tmpX = rectOvalPtr->bbox[2]; + rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0]; - rectOvalPtr->bbox[0] = tmp; + rectOvalPtr->bbox[0] = tmpX; } if (rectOvalPtr->outline.gc == None) { /* - * The Win32 switch was added for 8.3 to solve a problem - * with ovals leaving traces on bottom and right of 1 pixel. - * This may not be the correct place to solve it, but it works. + * The Win32 switch was added for 8.3 to solve a problem with ovals + * leaving traces on bottom and right of 1 pixel. This may not be the + * correct place to solve it, but it works. */ + #ifdef __WIN32__ bloat = 1; #else @@ -680,9 +684,12 @@ ComputeRectOvalBbox(canvas, rectOvalPtr) #endif } else { #ifdef MAC_OSX_TK - /* Mac OS X CoreGraphics needs correct rounding here - * otherwise it will draw outside the bounding box. - * Probably correct on other platforms as well? */ + /* + * Mac OS X CoreGraphics needs correct rounding here otherwise it will + * draw outside the bounding box. Probably correct on other platforms + * as well? + */ + bloat = (int) (width+1.5)/2; #else bloat = (int) (width+1)/2; @@ -690,9 +697,9 @@ ComputeRectOvalBbox(canvas, rectOvalPtr) } /* - * Special note: the rectangle is always drawn at least 1x1 in - * size, so round up the upper coordinates to be at least 1 unit - * greater than the lower ones. + * Special note: the rectangle is always drawn at least 1x1 in size, so + * round up the upper coordinates to be at least 1 unit greater than the + * lower ones. */ tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5 @@ -720,28 +727,28 @@ ComputeRectOvalBbox(canvas, rectOvalPtr) * * DisplayRectOval -- * - * This procedure is invoked to draw a rectangle or oval - * item in a given drawable. + * This function is invoked to draw a rectangle or oval item in a given + * drawable. * * Results: * None. * * Side effects: - * ItemPtr is drawn in drawable using the transformation - * information in canvas. + * ItemPtr is drawn in drawable using the transformation information in + * canvas. * *-------------------------------------------------------------- */ static void -DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) - Tk_Canvas canvas; /* Canvas that contains item. */ - Tk_Item *itemPtr; /* Item to be displayed. */ - Display *display; /* Display on which to draw item. */ - Drawable drawable; /* Pixmap or window in which to draw - * item. */ - int x, y, width, height; /* Describes region of canvas that - * must be redisplayed (not used). */ +DisplayRectOval( + Tk_Canvas canvas, /* Canvas that contains item. */ + Tk_Item *itemPtr, /* Item to be displayed. */ + Display *display, /* Display on which to draw item. */ + Drawable drawable, /* Pixmap or window in which to draw item. */ + int x, int y, int width, int height) + /* Describes region of canvas that must be + * redisplayed (not used). */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; short x1, y1, x2, y2; @@ -749,9 +756,9 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) Tk_State state = itemPtr->state; /* - * Compute the screen coordinates of the bounding box for the item. - * Make sure that the bbox is at least one pixel large, since some - * X servers will die if it isn't. + * Compute the screen coordinates of the bounding box for the item. Make + * sure that the bbox is at least one pixel large, since some X servers + * will die if it isn't. */ Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0], rectOvalPtr->bbox[1], @@ -766,22 +773,21 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) } /* - * Display filled part first (if wanted), then outline. If we're - * stippling, then modify the stipple offset in the GC. Be sure to - * reset the offset when done, since the GC is supposed to be - * read-only. + * Display filled part first (if wanted), then outline. If we're + * stippling, then modify the stipple offset in the GC. Be sure to reset + * the offset when done, since the GC is supposed to be read-only. */ - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } fillStipple = rectOvalPtr->fillStipple; if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) { - if (rectOvalPtr->activeFillStipple!=None) { + if (rectOvalPtr->activeFillStipple != None) { fillStipple = rectOvalPtr->activeFillStipple; } - } else if (state==TK_STATE_DISABLED) { - if (rectOvalPtr->disabledFillStipple!=None) { + } else if (state == TK_STATE_DISABLED) { + if (rectOvalPtr->disabledFillStipple != None) { fillStipple = rectOvalPtr->disabledFillStipple; } } @@ -789,10 +795,12 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) if (rectOvalPtr->fillGC != None) { if (fillStipple != None) { Tk_TSOffset *tsoffset; - int w=0; int h=0; + int w = 0, h = 0; + tsoffset = &rectOvalPtr->tsoffset; if (tsoffset) { int flags = tsoffset->flags; + if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) { Tk_SizeOfBitmap(display, fillStipple, &w, &h); if (flags & TK_OFFSET_CENTER) { @@ -827,6 +835,7 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0); } } + if (rectOvalPtr->outline.gc != None) { Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline)); if (rectOvalPtr->header.typePtr == &tkRectangleType) { @@ -845,17 +854,16 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) * * RectToPoint -- * - * Computes the distance from a given point to a given - * rectangle, in canvas units. + * Computes the distance from a given point to a given rectangle, in + * canvas units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are coordPtr[0] and coordPtr[1] is inside the rectangle. If the - * point isn't inside the rectangle then the return value is the - * distance from the point to the rectangle. If itemPtr is filled, - * then anywhere in the interior is considered "inside"; if - * itemPtr isn't filled, then "inside" means only the area - * occupied by the outline. + * The return value is 0 if the point whose x and y coordinates are + * coordPtr[0] and coordPtr[1] is inside the rectangle. If the point + * isn't inside the rectangle then the return value is the distance from + * the point to the rectangle. If itemPtr is filled, then anywhere in the + * interior is considered "inside"; if itemPtr isn't filled, then + * "inside" means only the area occupied by the outline. * * Side effects: * None. @@ -865,17 +873,17 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height) /* ARGSUSED */ static double -RectToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +RectToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { RectOvalItem *rectPtr = (RectOvalItem *) itemPtr; double xDiff, yDiff, x1, y1, x2, y2, inc, tmp; double width; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -884,15 +892,15 @@ RectToPoint(canvas, itemPtr, pointPtr) if (rectPtr->outline.activeWidth>width) { width = rectPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (rectPtr->outline.disabledWidth>0) { width = rectPtr->outline.disabledWidth; } } /* - * Generate a new larger rectangle that includes the border - * width, if there is one. + * Generate a new larger rectangle that includes the border width, if + * there is one. */ x1 = rectPtr->bbox[0]; @@ -908,14 +916,13 @@ RectToPoint(canvas, itemPtr, pointPtr) } /* - * If the point is inside the rectangle, handle specially: - * distance is 0 if rectangle is filled, otherwise compute - * distance to nearest edge of rectangle and subtract width - * of edge. + * If the point is inside the rectangle, handle specially: distance is 0 + * if rectangle is filled, otherwise compute distance to nearest edge of + * rectangle and subtract width of edge. */ if ((pointPtr[0] >= x1) && (pointPtr[0] < x2) - && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) { + && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) { if ((rectPtr->fillGC != None) || (rectPtr->outline.gc == None)) { return 0.0; } @@ -967,17 +974,16 @@ RectToPoint(canvas, itemPtr, pointPtr) * * OvalToPoint -- * - * Computes the distance from a given point to a given - * oval, in canvas units. + * Computes the distance from a given point to a given oval, in canvas + * units. * * Results: - * The return value is 0 if the point whose x and y coordinates - * are coordPtr[0] and coordPtr[1] is inside the oval. If the - * point isn't inside the oval then the return value is the - * distance from the point to the oval. If itemPtr is filled, - * then anywhere in the interior is considered "inside"; if - * itemPtr isn't filled, then "inside" means only the area - * occupied by the outline. + * The return value is 0 if the point whose x and y coordinates are + * coordPtr[0] and coordPtr[1] is inside the oval. If the point isn't + * inside the oval then the return value is the distance from the point + * to the oval. If itemPtr is filled, then anywhere in the interior is + * considered "inside"; if itemPtr isn't filled, then "inside" means only + * the area occupied by the outline. * * Side effects: * None. @@ -987,17 +993,17 @@ RectToPoint(canvas, itemPtr, pointPtr) /* ARGSUSED */ static double -OvalToPoint(canvas, itemPtr, pointPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against point. */ - double *pointPtr; /* Pointer to x and y coordinates. */ +OvalToPoint( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against point. */ + double *pointPtr) /* Pointer to x and y coordinates. */ { RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr; double width; int filled; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -1006,7 +1012,7 @@ OvalToPoint(canvas, itemPtr, pointPtr) if (ovalPtr->outline.activeWidth>width) { width = (double) ovalPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (ovalPtr->outline.disabledWidth>0) { width = (double) ovalPtr->outline.disabledWidth; } @@ -1026,14 +1032,13 @@ OvalToPoint(canvas, itemPtr, pointPtr) * * RectToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangle. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangle. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -1043,19 +1048,18 @@ OvalToPoint(canvas, itemPtr, pointPtr) /* ARGSUSED */ static int -RectToArea(canvas, itemPtr, areaPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against rectangle. */ - double *areaPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +RectToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against rectangle. */ + double *areaPtr) /* Pointer to array of four coordinates (x1, + * y1, x2, y2) describing rectangular area. */ { RectOvalItem *rectPtr = (RectOvalItem *) itemPtr; double halfWidth; double width; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -1064,7 +1068,7 @@ RectToArea(canvas, itemPtr, areaPtr) if (rectPtr->outline.activeWidth>width) { width = rectPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (rectPtr->outline.disabledWidth>0) { width = rectPtr->outline.disabledWidth; } @@ -1102,14 +1106,13 @@ RectToArea(canvas, itemPtr, areaPtr) * * OvalToArea -- * - * This procedure is called to determine whether an item - * lies entirely inside, entirely outside, or overlapping - * a given rectangular area. + * This function is called to determine whether an item lies entirely + * inside, entirely outside, or overlapping a given rectangular area. * * Results: - * -1 is returned if the item is entirely outside the area - * given by rectPtr, 0 if it overlaps, and 1 if it is entirely - * inside the given area. + * -1 is returned if the item is entirely outside the area given by + * rectPtr, 0 if it overlaps, and 1 if it is entirely inside the given + * area. * * Side effects: * None. @@ -1119,12 +1122,11 @@ RectToArea(canvas, itemPtr, areaPtr) /* ARGSUSED */ static int -OvalToArea(canvas, itemPtr, areaPtr) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item to check against oval. */ - double *areaPtr; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) describing rectangular - * area. */ +OvalToArea( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item to check against oval. */ + double *areaPtr) /* Pointer to array of four coordinates (x1, + * y1, x2, y2) describing rectangular area. */ { RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr; double oval[4], halfWidth; @@ -1132,7 +1134,7 @@ OvalToArea(canvas, itemPtr, areaPtr) double width; Tk_State state = itemPtr->state; - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } @@ -1141,7 +1143,7 @@ OvalToArea(canvas, itemPtr, areaPtr) if (ovalPtr->outline.activeWidth>width) { width = ovalPtr->outline.activeWidth; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (ovalPtr->outline.disabledWidth>0) { width = ovalPtr->outline.disabledWidth; } @@ -1163,10 +1165,10 @@ OvalToArea(canvas, itemPtr, areaPtr) result = TkOvalToArea(oval, areaPtr); /* - * If the rectangle appears to overlap the oval and the oval - * isn't filled, do one more check to see if perhaps all four - * of the rectangle's corners are totally inside the oval's - * unfilled center, in which case we should return "outside". + * If the rectangle appears to overlap the oval and the oval isn't filled, + * do one more check to see if perhaps all four of the rectangle's corners + * are totally inside the oval's unfilled center, in which case we should + * return "outside". */ if ((result == 0) && (ovalPtr->outline.gc != None) @@ -1201,16 +1203,14 @@ OvalToArea(canvas, itemPtr, areaPtr) * * ScaleRectOval -- * - * This procedure is invoked to rescale a rectangle or oval - * item. + * This function is invoked to rescale a rectangle or oval item. * * Results: * None. * * Side effects: - * The rectangle or oval referred to by itemPtr is rescaled - * so that the following transformation is applied to all - * point coordinates: + * The rectangle or oval referred to by itemPtr is rescaled so that the + * following transformation is applied to all point coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * @@ -1218,12 +1218,13 @@ OvalToArea(canvas, itemPtr, areaPtr) */ static void -ScaleRectOval(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing rectangle. */ - Tk_Item *itemPtr; /* Rectangle to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ - double scaleX; /* Amount to scale in X direction. */ - double scaleY; /* Amount to scale in Y direction. */ +ScaleRectOval( + Tk_Canvas canvas, /* Canvas containing rectangle. */ + Tk_Item *itemPtr, /* Rectangle to be scaled. */ + double originX, double originY, + /* Origin about which to scale rect. */ + double scaleX, /* Amount to scale in X direction. */ + double scaleY) /* Amount to scale in Y direction. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; @@ -1239,26 +1240,25 @@ ScaleRectOval(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateRectOval -- * - * This procedure is called to move a rectangle or oval by a - * given amount. + * This function is called to move a rectangle or oval by a given amount. * * Results: * None. * * Side effects: - * The position of the rectangle or oval is offset by - * (xDelta, yDelta), and the bounding box is updated in the - * generic part of the item structure. + * The position of the rectangle or oval is offset by (xDelta, yDelta), + * and the bounding box is updated in the generic part of the item + * structure. * *-------------------------------------------------------------- */ static void -TranslateRectOval(canvas, itemPtr, deltaX, deltaY) - Tk_Canvas canvas; /* Canvas containing item. */ - Tk_Item *itemPtr; /* Item that is being moved. */ - double deltaX, deltaY; /* Amount by which item is to be - * moved. */ +TranslateRectOval( + Tk_Canvas canvas, /* Canvas containing item. */ + Tk_Item *itemPtr, /* Item that is being moved. */ + double deltaX, double deltaY) + /* Amount by which item is to be moved. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; @@ -1274,15 +1274,14 @@ TranslateRectOval(canvas, itemPtr, deltaX, deltaY) * * RectOvalToPostscript -- * - * This procedure is called to generate Postscript for - * rectangle and oval items. + * This function is called to generate Postscript for rectangle and oval + * items. * * Results: - * The return value is a standard Tcl result. If an error - * occurs in generating Postscript then an error message is - * left in the interp's result, replacing whatever used to be there. - * If no error occurs, then Postscript for the rectangle is - * appended to the result. + * The return value is a standard Tcl result. If an error occurs in + * generating Postscript then an error message is left in the interp's + * result, replacing whatever used to be there. If no error occurs, then + * Postscript for the rectangle is appended to the result. * * Side effects: * None. @@ -1291,14 +1290,13 @@ TranslateRectOval(canvas, itemPtr, deltaX, deltaY) */ static int -RectOvalToPostscript(interp, canvas, itemPtr, prepass) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Canvas canvas; /* Information about overall canvas. */ - Tk_Item *itemPtr; /* Item for which Postscript is - * wanted. */ - int prepass; /* 1 means this is a prepass to - * collect font information; 0 means - * final Postscript is being created. */ +RectOvalToPostscript( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Canvas canvas, /* Information about overall canvas. */ + Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ + int prepass) /* 1 means this is a prepass to collect font + * information; 0 means final Postscript is + * being created. */ { char pathCmd[500]; RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; @@ -1312,12 +1310,10 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass) y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]); /* - * Generate a string that creates a path for the rectangle or oval. - * This is the only part of the procedure's code that is type- - * specific. + * Generate a string that creates a path for the rectangle or oval. This + * is the only part of the function's code that is type-specific. */ - if (rectOvalPtr->header.typePtr == &tkRectangleType) { sprintf(pathCmd, "%.15g %.15g moveto %.15g 0 rlineto 0 %.15g rlineto %.15g 0 rlineto closepath\n", rectOvalPtr->bbox[0], y1, @@ -1329,7 +1325,7 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass) (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2); } - if(state == TK_STATE_NULL) { + if (state == TK_STATE_NULL) { state = ((TkCanvas *)canvas)->canvas_state; } color = rectOvalPtr->outline.color; @@ -1345,7 +1341,7 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass) if (rectOvalPtr->activeFillStipple!=None) { fillStipple = rectOvalPtr->activeFillStipple; } - } else if (state==TK_STATE_DISABLED) { + } else if (state == TK_STATE_DISABLED) { if (rectOvalPtr->outline.disabledColor!=NULL) { color = rectOvalPtr->outline.disabledColor; } @@ -1362,22 +1358,20 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass) */ if (fillColor != NULL) { - Tcl_AppendResult(interp, pathCmd, (char *) NULL); - if (Tk_CanvasPsColor(interp, canvas, fillColor) - != TCL_OK) { + Tcl_AppendResult(interp, pathCmd, NULL); + if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) { return TCL_ERROR; } if (fillStipple != None) { - Tcl_AppendResult(interp, "clip ", (char *) NULL); - if (Tk_CanvasPsStipple(interp, canvas, fillStipple) - != TCL_OK) { + Tcl_AppendResult(interp, "clip ", NULL); + if (Tk_CanvasPsStipple(interp, canvas, fillStipple) != TCL_OK) { return TCL_ERROR; } if (color != NULL) { - Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); + Tcl_AppendResult(interp, "grestore gsave\n", NULL); } } else { - Tcl_AppendResult(interp, "fill\n", (char *) NULL); + Tcl_AppendResult(interp, "fill\n", NULL); } } @@ -1387,7 +1381,7 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass) if (color != NULL) { Tcl_AppendResult(interp, pathCmd, "0 setlinejoin 2 setlinecap\n", - (char *) NULL); + NULL); if (Tk_CanvasPsOutline(canvas, itemPtr, &(rectOvalPtr->outline))!= TCL_OK) { return TCL_ERROR; @@ -1395,3 +1389,11 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass) } return TCL_OK; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkScale.c b/generic/tkScale.c index 676f84b..103f39c 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -1,49 +1,45 @@ -/* +/* * tkScale.c -- * - * This module implements a scale widgets for the Tk toolkit. - * A scale displays a slider that can be adjusted to change a - * value; it also displays numeric labels and a textual label, - * if desired. - * - * The modifications to use floating-point values are based on - * an implementation by Paul Mackerras. The -variable option - * is due to Henning Schulzrinne. All of these are used with - * permission. + * This module implements a scale widgets for the Tk toolkit. A scale + * displays a slider that can be adjusted to change a value; it also + * displays numeric labels and a textual label, if desired. + * + * The modifications to use floating-point values are based on an + * implementation by Paul Mackerras. The -variable option is due to + * Henning Schulzrinne. All of these are used with permission. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "default.h" #include "tkInt.h" -#include "tclMath.h" #include "tkScale.h" /* - * The following table defines the legal values for the -orient option. - * It is used together with the "enum orient" declaration in tkScale.h. + * The following table defines the legal values for the -orient option. It is + * used together with the "enum orient" declaration in tkScale.h. */ static char *orientStrings[] = { - "horizontal", "vertical", (char *) NULL + "horizontal", "vertical", NULL }; /* - * The following table defines the legal values for the -state option. - * It is used together with the "enum state" declaration in tkScale.h. + * The following table defines the legal values for the -state option. It is + * used together with the "enum state" declaration in tkScale.h. */ static char *stateStrings[] = { - "active", "disabled", "normal", (char *) NULL + "active", "disabled", "normal", NULL }; -static Tk_OptionSpec optionSpecs[] = { +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground", DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder), 0, (ClientData) DEF_SCALE_ACTIVE_BG_MONO, 0}, @@ -51,42 +47,42 @@ static Tk_OptionSpec optionSpecs[] = { DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder), 0, (ClientData) DEF_SCALE_BG_MONO, 0}, {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement", - DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement), - 0, 0, 0}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background", 0}, + DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement), + 0, 0, 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", 0}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth), - 0, 0, 0}, + DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth), + 0, 0, 0}, {TK_OPTION_STRING, "-command", "command", "Command", DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command), TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_INT, "-digits", "digits", "Digits", - DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits), - 0, 0, 0}, - {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_INT, "-digits", "digits", "Digits", + DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits), + 0, 0, 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, {TK_OPTION_FONT, "-font", "font", "Font", DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0, - (ClientData) DEF_SCALE_FG_MONO, 0}, - {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1, - Tk_Offset(TkScale, fromValue), 0, 0, 0}, + DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0, + (ClientData) DEF_SCALE_FG_MONO, 0}, + {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1, + Tk_Offset(TkScale, fromValue), 0, 0, 0}, {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR, - -1, Tk_Offset(TkScale, highlightBorder), - 0, (ClientData) DEF_SCALE_HIGHLIGHT_BG_MONO, 0}, + -1, Tk_Offset(TkScale, highlightBorder), + 0, (ClientData) DEF_SCALE_HIGHLIGHT_BG_MONO, 0}, {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr), 0, 0, 0}, {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", - "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1, + "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1, Tk_Offset(TkScale, highlightWidth), 0, 0, 0}, {TK_OPTION_STRING, "-label", "label", "Label", DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label), @@ -94,59 +90,58 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_PIXELS, "-length", "length", "Length", DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", - DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient), - 0, (ClientData) orientStrings, 0}, + DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient), + 0, (ClientData) orientStrings, 0}, {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0}, {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay", - DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay), - 0, 0, 0}, + DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay), + 0, 0, 0}, {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval", - DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval), - 0, 0, 0}, + DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval), + 0, 0, 0}, {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution", - DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution), - 0, 0, 0}, + DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution), + 0, 0, 0}, {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue", - DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue), - 0, 0, 0}, + DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue), + 0, 0, 0}, {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength", - DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength), - 0, 0, 0}, + DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength), + 0, 0, 0}, {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief", - DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief), - 0, 0, 0}, + DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief), + 0, 0, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", - DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state), - 0, (ClientData) stateStrings, 0}, + DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state), + 0, (ClientData) stateStrings, 0}, {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval", - DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval), - 0, 0, 0}, + DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval), + 0, 0, 0}, {TK_OPTION_DOUBLE, "-to", "to", "To", - DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0}, + DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0}, {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background", - DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr), - 0, (ClientData) DEF_SCALE_TROUGH_MONO, 0}, + DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr), + 0, (ClientData) DEF_SCALE_TROUGH_MONO, 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_PIXELS, "-width", "width", "Width", DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, 0, 0} + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0} }; /* - * The following tables define the scale widget commands and map the - * indexes into the string tables into a single enumerated type used - * to dispatch the scale widget command. + * The following tables define the scale widget commands and map the indexes + * into the string tables into a single enumerated type used to dispatch the + * scale widget command. */ static CONST char *commandNames[] = { - "cget", "configure", "coords", "get", "identify", "set", (char *) NULL + "cget", "configure", "coords", "get", "identify", "set", NULL }; enum command { @@ -158,25 +153,22 @@ enum command { * Forward declarations for procedures defined later in this file: */ -static void ComputeFormat _ANSI_ARGS_((TkScale *scalePtr)); -static void ComputeScaleGeometry _ANSI_ARGS_((TkScale *scalePtr)); -static int ConfigureScale _ANSI_ARGS_((Tcl_Interp *interp, - TkScale *scalePtr, int objc, - Tcl_Obj *CONST objv[])); -static void DestroyScale _ANSI_ARGS_((char *memPtr)); -static void ScaleCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void ScaleEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static char * ScaleVarProc _ANSI_ARGS_((ClientData clientData, +static void ComputeFormat(TkScale *scalePtr); +static void ComputeScaleGeometry(TkScale *scalePtr); +static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr, + int objc, Tcl_Obj *CONST objv[]); +static void DestroyScale(char *memPtr); +static void ScaleCmdDeletedProc(ClientData clientData); +static void ScaleEventProc(ClientData clientData, + XEvent *eventPtr); +static char * ScaleVarProc(ClientData clientData, Tcl_Interp *interp, CONST char *name1, - CONST char *name2, int flags)); -static int ScaleWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static void ScaleWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static void ScaleSetVariable _ANSI_ARGS_((TkScale *scalePtr)); + CONST char *name2, int flags); +static int ScaleWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static void ScaleWorldChanged(ClientData instanceData); +static void ScaleSetVariable(TkScale *scalePtr); /* * The structure below defines scale class behavior by means of procedures @@ -187,16 +179,14 @@ static Tk_ClassProcs scaleClass = { sizeof(Tk_ClassProcs), /* size */ ScaleWorldChanged, /* worldChangedProc */ }; - /* *-------------------------------------------------------------- * * Tk_ScaleObjCmd -- * - * This procedure is invoked to process the "scale" Tcl - * command. See the user documentation for details on what - * it does. + * This procedure is invoked to process the "scale" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -208,11 +198,11 @@ static Tk_ClassProcs scaleClass = { */ int -Tk_ScaleObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +Tk_ScaleObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument values. */ { register TkScale *scalePtr; Tk_OptionTable optionTable; @@ -224,14 +214,14 @@ Tk_ScaleObjCmd(clientData, interp, objc, objv) } tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetString(objv[1]), (char *) NULL); + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } /* - * Create the option table for this widget class. If it has already - * been created, the cached pointer will be returned. + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); @@ -240,9 +230,9 @@ Tk_ScaleObjCmd(clientData, interp, objc, objv) scalePtr = TkpCreateScale(tkwin); /* - * Initialize fields that won't be initialized by ConfigureScale, - * or which ConfigureScale expects to have reasonable values - * (e.g. resource pointers). + * Initialize fields that won't be initialized by ConfigureScale, or which + * ConfigureScale expects to have reasonable values (e.g. resource + * pointers). */ scalePtr->tkwin = tkwin; @@ -320,9 +310,9 @@ Tk_ScaleObjCmd(clientData, interp, objc, objv) * * ScaleWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This procedure is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -334,157 +324,151 @@ Tk_ScaleObjCmd(clientData, interp, objc, objv) */ static int -ScaleWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about scale - * widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings. */ +ScaleWidgetObjCmd( + ClientData clientData, /* Information about scale widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument strings. */ { TkScale *scalePtr = (TkScale *) clientData; Tcl_Obj *objPtr; int index, result; if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } result = Tcl_GetIndexFromObj(interp, objv[1], commandNames, - "option", 0, &index); + "option", 0, &index); if (result != TCL_OK) { return result; } Tcl_Preserve((ClientData) scalePtr); switch (index) { - case COMMAND_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "cget option"); - goto error; - } - objPtr = Tk_GetOptionValue(interp, (char *) scalePtr, - scalePtr->optionTable, objv[2], scalePtr->tkwin); + case COMMAND_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "cget option"); + goto error; + } + objPtr = Tk_GetOptionValue(interp, (char *) scalePtr, + scalePtr->optionTable, objv[2], scalePtr->tkwin); + if (objPtr == NULL) { + goto error; + } else { + Tcl_SetObjResult(interp, objPtr); + } + break; + case COMMAND_CONFIGURE: + if (objc <= 3) { + objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr, + scalePtr->optionTable, + (objc == 3) ? objv[2] : NULL, scalePtr->tkwin); if (objPtr == NULL) { - goto error; + goto error; } else { Tcl_SetObjResult(interp, objPtr); } - break; + } else { + result = ConfigureScale(interp, scalePtr, objc-2, objv+2); } - case COMMAND_CONFIGURE: { - if (objc <= 3) { - objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr, - scalePtr->optionTable, - (objc == 3) ? objv[2] : (Tcl_Obj *) NULL, - scalePtr->tkwin); - if (objPtr == NULL) { - goto error; - } else { - Tcl_SetObjResult(interp, objPtr); - } - } else { - result = ConfigureScale(interp, scalePtr, objc-2, objv+2); - } - break; + break; + case COMMAND_COORDS: { + int x, y ; + double value; + char buf[TCL_INTEGER_SPACE * 2]; + + if ((objc != 2) && (objc != 3)) { + Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?"); + goto error; } - case COMMAND_COORDS: { - int x, y ; - double value; - char buf[TCL_INTEGER_SPACE * 2]; - - if ((objc != 2) && (objc != 3)) { - Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?"); - goto error; - } - if (objc == 3) { - if (Tcl_GetDoubleFromObj(interp, objv[2], &value) - != TCL_OK) { - goto error; - } - } else { - value = scalePtr->value; - } - if (scalePtr->orient == ORIENT_VERTICAL) { - x = scalePtr->vertTroughX + scalePtr->width/2 - + scalePtr->borderWidth; - y = TkScaleValueToPixel(scalePtr, value); - } else { - x = TkScaleValueToPixel(scalePtr, value); - y = scalePtr->horizTroughY + scalePtr->width/2 - + scalePtr->borderWidth; - } - sprintf(buf, "%d %d", x, y); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - break; - } - case COMMAND_GET: { - double value; - int x, y; - char buf[TCL_DOUBLE_SPACE]; - - if ((objc != 2) && (objc != 4)) { - Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?"); + if (objc == 3) { + if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) { goto error; } - if (objc == 2) { - value = scalePtr->value; - } else { - if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[3], &y) - != TCL_OK)) { - goto error; - } - value = TkScalePixelToValue(scalePtr, x, y); - } - sprintf(buf, scalePtr->format, value); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - break; - } - case COMMAND_IDENTIFY: { - int x, y, thing; - - if (objc != 4) { - Tcl_WrongNumArgs(interp, 1, objv, "identify x y"); + } else { + value = scalePtr->value; + } + if (scalePtr->orient == ORIENT_VERTICAL) { + x = scalePtr->vertTroughX + scalePtr->width/2 + + scalePtr->borderWidth; + y = TkScaleValueToPixel(scalePtr, value); + } else { + x = TkScaleValueToPixel(scalePtr, value); + y = scalePtr->horizTroughY + scalePtr->width/2 + + scalePtr->borderWidth; + } + sprintf(buf, "%d %d", x, y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + break; + } + case COMMAND_GET: { + double value; + int x, y; + char buf[TCL_DOUBLE_SPACE]; + + if ((objc != 2) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?"); + goto error; + } + if (objc == 2) { + value = scalePtr->value; + } else { + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) || + (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { goto error; } - if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) - || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { - goto error; - } - thing = TkpScaleElement(scalePtr, x,y); - switch (thing) { - case TROUGH1: - Tcl_SetResult(interp, "trough1", TCL_STATIC); - break; - case SLIDER: - Tcl_SetResult(interp, "slider", TCL_STATIC); - break; - case TROUGH2: - Tcl_SetResult(interp, "trough2", TCL_STATIC); - break; - } - break; - } - case COMMAND_SET: { - double value; + value = TkScalePixelToValue(scalePtr, x, y); + } + sprintf(buf, scalePtr->format, value); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + break; + } + case COMMAND_IDENTIFY: { + int x, y, thing; - if (objc != 3) { - Tcl_WrongNumArgs(interp, 1, objv, "set value"); - goto error; - } - if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) { - goto error; - } - if (scalePtr->state != STATE_DISABLED) { - TkScaleSetValue(scalePtr, value, 1, 1); - } + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "identify x y"); + goto error; + } + if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) { + goto error; + } + thing = TkpScaleElement(scalePtr, x,y); + switch (thing) { + case TROUGH1: + Tcl_SetResult(interp, "trough1", TCL_STATIC); + break; + case SLIDER: + Tcl_SetResult(interp, "slider", TCL_STATIC); break; - } + case TROUGH2: + Tcl_SetResult(interp, "trough2", TCL_STATIC); + break; + } + break; + } + case COMMAND_SET: { + double value; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "set value"); + goto error; + } + if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) { + goto error; + } + if (scalePtr->state != STATE_DISABLED) { + TkScaleSetValue(scalePtr, value, 1, 1); + } + break; + } } Tcl_Release((ClientData) scalePtr); return result; - error: + error: Tcl_Release((ClientData) scalePtr); return TCL_ERROR; } @@ -494,9 +478,9 @@ ScaleWidgetObjCmd(clientData, interp, objc, objv) * * DestroyScale -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a button at a safe time - * (when no-one is using it anymore). + * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to + * clean up the internal structure of a button at a safe time (when + * no-one is using it anymore). * * Results: * None. @@ -508,8 +492,8 @@ ScaleWidgetObjCmd(clientData, interp, objc, objv) */ static void -DestroyScale(memPtr) - char *memPtr; /* Info about scale widget. */ +DestroyScale( + char *memPtr) /* Info about scale widget. */ { register TkScale *scalePtr = (TkScale *) memPtr; @@ -521,9 +505,8 @@ DestroyScale(memPtr) } /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ if (scalePtr->varNamePtr != NULL) { @@ -551,29 +534,28 @@ DestroyScale(memPtr) * * ConfigureScale -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a scale widget. + * This procedure is called to process an argv/argc list, plus the Tk + * option database, in order to configure (or reconfigure) a scale + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for scalePtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for scalePtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureScale(interp, scalePtr, objc, objv) - Tcl_Interp *interp; /* Used for error reporting. */ - register TkScale *scalePtr; /* Information about widget; may or may - * not already have values for some fields. */ - int objc; /* Number of valid entries in objv. */ - Tcl_Obj *CONST objv[]; /* Argument values. */ +ConfigureScale( + Tcl_Interp *interp, /* Used for error reporting. */ + register TkScale *scalePtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of valid entries in objv. */ + Tcl_Obj *CONST objv[]) /* Argument values. */ { Tk_SavedOptions savedOptions; Tcl_Obj *errorResult = NULL; @@ -598,7 +580,7 @@ ConfigureScale(interp, scalePtr, objc, objv) if (Tk_SetOptions(interp, (char *) scalePtr, scalePtr->optionTable, objc, objv, - scalePtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) { + scalePtr->tkwin, &savedOptions, NULL) != TCL_OK) { continue; } } else { @@ -612,9 +594,9 @@ ConfigureScale(interp, scalePtr, objc, objv) } /* - * If the scale is tied to the value of a variable, then set - * the scale's value from the value of the variable, if it exists - * and it holds a valid double value. + * If the scale is tied to the value of a variable, then set the + * scale's value from the value of the variable, if it exists and it + * holds a valid double value. */ if (scalePtr->varNamePtr != NULL) { @@ -634,11 +616,11 @@ ConfigureScale(interp, scalePtr, objc, objv) * orientation and creating GCs. */ - scalePtr->fromValue = TkRoundToResolution(scalePtr, - scalePtr->fromValue); + scalePtr->fromValue = TkRoundToResolution(scalePtr, + scalePtr->fromValue); scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue); scalePtr->tickInterval = TkRoundToResolution(scalePtr, - scalePtr->tickInterval); + scalePtr->tickInterval); /* * Make sure that the tick interval has the right sign so that @@ -646,13 +628,13 @@ ConfigureScale(interp, scalePtr, objc, objv) */ if ((scalePtr->tickInterval < 0) - ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) { - scalePtr->tickInterval = -scalePtr->tickInterval; + ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) { + scalePtr->tickInterval = -scalePtr->tickInterval; } ComputeFormat(scalePtr); - scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0; + scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0; Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder); @@ -663,14 +645,14 @@ ConfigureScale(interp, scalePtr, objc, objv) break; } if (!error) { - Tk_FreeSavedOptions(&savedOptions); + Tk_FreeSavedOptions(&savedOptions); } /* - * Set the scale value to itself; all this does is to make sure - * that the scale's value is within the new acceptable range for - * the scale. We don't set the var here because we need to make - * special checks for possibly changed varNamePtr. + * Set the scale value to itself; all this does is to make sure that the + * scale's value is within the new acceptable range for the scale. We + * don't set the var here because we need to make special checks for + * possibly changed varNamePtr. */ TkScaleSetValue(scalePtr, scalePtr->value, 0, 1); @@ -683,36 +665,36 @@ ConfigureScale(interp, scalePtr, objc, objv) Tcl_Obj *valuePtr; /* - * Set the associated variable only when the new value differs - * from the current value, or the variable doesn't yet exist + * Set the associated variable only when the new value differs from + * the current value, or the variable doesn't yet exist. */ + valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL, TCL_GLOBAL_ONLY); if ((valuePtr == NULL) || (Tcl_GetDoubleFromObj(NULL, valuePtr, &varValue) != TCL_OK)) { ScaleSetVariable(scalePtr); } else { - char varString[TCL_DOUBLE_SPACE]; - char scaleString[TCL_DOUBLE_SPACE]; + char varString[TCL_DOUBLE_SPACE], scaleString[TCL_DOUBLE_SPACE]; + sprintf(varString, scalePtr->format, varValue); sprintf(scaleString, scalePtr->format, scalePtr->value); if (strcmp(varString, scaleString)) { ScaleSetVariable(scalePtr); } } - Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr), - TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, - ScaleVarProc, (ClientData) scalePtr); + Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + ScaleVarProc, (ClientData) scalePtr); } ScaleWorldChanged((ClientData) scalePtr); if (error) { - Tcl_SetObjResult(interp, errorResult); + Tcl_SetObjResult(interp, errorResult); Tcl_DecrRefCount(errorResult); return TCL_ERROR; - } else { - return TCL_OK; } + return TCL_OK; } /* @@ -720,22 +702,22 @@ ConfigureScale(interp, scalePtr, objc, objv) * * ScaleWorldChanged -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This procedure is called when the world has changed in some way and + * the widget needs to recompute all its graphics contexts and determine + * its new geometry. * * Results: - * None. + * None. * * Side effects: - * Scale will be relayed out and redisplayed. + * Scale will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ - + static void -ScaleWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +ScaleWorldChanged( + ClientData instanceData) /* Information about widget. */ { XGCValues gcValues; GC gc; @@ -761,13 +743,13 @@ ScaleWorldChanged(instanceData) if (scalePtr->copyGC == None) { gcValues.graphics_exposures = False; scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures, - &gcValues); + &gcValues); } scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth; /* - * Recompute display-related information, and let the geometry - * manager know how much space is needed now. + * Recompute display-related information, and let the geometry manager + * know how much space is needed now. */ ComputeScaleGeometry(scalePtr); @@ -780,9 +762,9 @@ ScaleWorldChanged(instanceData) * * ComputeFormat -- * - * This procedure is invoked to recompute the "format" field - * of a scale's widget record, which determines how the value - * of the scale is converted to a string. + * This procedure is invoked to recompute the "format" field of a scale's + * widget record, which determines how the value of the scale is + * converted to a string. * * Results: * None. @@ -794,16 +776,16 @@ ScaleWorldChanged(instanceData) */ static void -ComputeFormat(scalePtr) - TkScale *scalePtr; /* Information about scale widget. */ +ComputeFormat( + TkScale *scalePtr) /* Information about scale widget. */ { double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; int eDigits, fDigits; /* - * Compute the displacement from the decimal of the most significant - * digit required for any number in the scale's range. + * Compute the displacement from the decimal of the most significant digit + * required for any number in the scale's range. */ maxValue = fabs(scalePtr->fromValue); @@ -818,17 +800,16 @@ ComputeFormat(scalePtr) /* * If the number of significant digits wasn't specified explicitly, - * compute it. It's the difference between the most significant - * digit needed to represent any number on the scale and the - * most significant digit of the smallest difference between - * numbers on the scale. In other words, display enough digits so - * that at least one digit will be different between any two adjacent - * positions of the scale. + * compute it. It's the difference between the most significant digit + * needed to represent any number on the scale and the most significant + * digit of the smallest difference between numbers on the scale. In other + * words, display enough digits so that at least one digit will be + * different between any two adjacent positions of the scale. */ numDigits = scalePtr->digits; if (numDigits <= 0) { - if (scalePtr->resolution > 0) { + if (scalePtr->resolution > 0) { /* * A resolution was specified for the scale, so just use it. */ @@ -836,9 +817,9 @@ ComputeFormat(scalePtr) leastSigDigit = (int) floor(log10(scalePtr->resolution)); } else { /* - * No resolution was specified, so compute the difference - * in value between adjacent pixels and use it for the least - * significant digit. + * No resolution was specified, so compute the difference in value + * between adjacent pixels and use it for the least significant + * digit. */ x = fabs(scalePtr->fromValue - scalePtr->toValue); @@ -858,8 +839,8 @@ ComputeFormat(scalePtr) } /* - * Compute the number of characters required using "e" format and - * "f" format, and then choose whichever one takes fewer characters. + * Compute the number of characters required using "e" format and "f" + * format, and then choose whichever one takes fewer characters. */ eDigits = numDigits + 4; @@ -889,23 +870,23 @@ ComputeFormat(scalePtr) * * ComputeScaleGeometry -- * - * This procedure is called to compute various geometrical - * information for a scale, such as where various things get - * displayed. It's called when the window is reconfigured. + * This procedure is called to compute various geometrical information + * for a scale, such as where various things get displayed. It's called + * when the window is reconfigured. * * Results: * None. * * Side effects: - * Display-related numbers get changed in *scalePtr. The - * geometry manager gets told about the window's preferred size. + * Display-related numbers get changed in *scalePtr. The geometry manager + * gets told about the window's preferred size. * *---------------------------------------------------------------------- */ static void -ComputeScaleGeometry(scalePtr) - register TkScale *scalePtr; /* Information about widget. */ +ComputeScaleGeometry( + register TkScale *scalePtr) /* Information about widget. */ { char valueString[PRINT_CHARS]; int tmp, valuePixels, x, y, extraSpace; @@ -915,9 +896,9 @@ ComputeScaleGeometry(scalePtr) scalePtr->fontHeight = fm.linespace + SPACING; /* - * Horizontal scales are simpler than vertical ones because - * all sizes are the same (the height of a line of text); - * handle them first and then quit. + * Horizontal scales are simpler than vertical ones because all sizes are + * the same (the height of a line of text); handle them first and then + * quit. */ if (scalePtr->orient == ORIENT_HORIZONTAL) { @@ -949,9 +930,9 @@ ComputeScaleGeometry(scalePtr) } /* - * Vertical scale: compute the amount of space needed to display - * the scales value by formatting strings for the two end points; - * use whichever length is longer. + * Vertical scale: compute the amount of space needed to display the + * scales value by formatting strings for the two end points; use + * whichever length is longer. */ sprintf(valueString, scalePtr->format, scalePtr->fromValue); @@ -964,8 +945,8 @@ ComputeScaleGeometry(scalePtr) } /* - * Assign x-locations to the elements of the scale, working from - * left to right. + * Assign x-locations to the elements of the scale, working from left to + * right. */ x = scalePtr->inset; @@ -1006,23 +987,23 @@ ComputeScaleGeometry(scalePtr) * * ScaleEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on scales. + * This procedure is invoked by the Tk dispatcher for various events on + * scales. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -ScaleEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +ScaleEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkScale *scalePtr = (TkScale *) clientData; @@ -1055,9 +1036,9 @@ ScaleEventProc(clientData, eventPtr) * * ScaleCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This procedure is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -1069,17 +1050,17 @@ ScaleEventProc(clientData, eventPtr) */ static void -ScaleCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +ScaleCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkScale *scalePtr = (TkScale *) clientData; Tk_Window tkwin = scalePtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This procedure could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this procedure destroys the + * widget. */ if (!(scalePtr->flags & SCALE_DELETED)) { @@ -1093,25 +1074,25 @@ ScaleCmdDeletedProc(clientData) * * TkEventuallyRedrawScale -- * - * Arrange for part or all of a scale widget to redrawn at - * the next convenient time in the future. + * Arrange for part or all of a scale widget to redrawn at the next + * convenient time in the future. * * Results: * None. * * Side effects: - * If "what" is REDRAW_SLIDER then just the slider and the - * value readout will be redrawn; if "what" is REDRAW_ALL - * then the entire widget will be redrawn. + * If "what" is REDRAW_SLIDER then just the slider and the value readout + * will be redrawn; if "what" is REDRAW_ALL then the entire widget will + * be redrawn. * *-------------------------------------------------------------- */ void -TkEventuallyRedrawScale(scalePtr, what) - register TkScale *scalePtr; /* Information about widget. */ - int what; /* What to redraw: REDRAW_SLIDER - * or REDRAW_ALL. */ +TkEventuallyRedrawScale( + register TkScale *scalePtr, /* Information about widget. */ + int what) /* What to redraw: REDRAW_SLIDER or + * REDRAW_ALL. */ { if ((what == 0) || (scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) { @@ -1129,8 +1110,8 @@ TkEventuallyRedrawScale(scalePtr, what) * * TkRoundToResolution -- * - * Round a given floating-point value to the nearest multiple - * of the scale's resolution. + * Round a given floating-point value to the nearest multiple of the + * scale's resolution. * * Results: * The return value is the rounded result. @@ -1142,28 +1123,28 @@ TkEventuallyRedrawScale(scalePtr, what) */ double -TkRoundToResolution(scalePtr, value) - TkScale *scalePtr; /* Information about scale widget. */ - double value; /* Value to round. */ +TkRoundToResolution( + TkScale *scalePtr, /* Information about scale widget. */ + double value) /* Value to round. */ { - double rem, new, tick; + double rem, rounded, tick; if (scalePtr->resolution <= 0) { return value; } tick = floor(value/scalePtr->resolution); - new = scalePtr->resolution * tick; - rem = value - new; + rounded = scalePtr->resolution * tick; + rem = value - rounded; if (rem < 0) { if (rem <= -scalePtr->resolution/2) { - new = (tick - 1.0) * scalePtr->resolution; + rounded = (tick - 1.0) * scalePtr->resolution; } } else { if (rem >= scalePtr->resolution/2) { - new = (tick + 1.0) * scalePtr->resolution; + rounded = (tick + 1.0) * scalePtr->resolution; } } - return new; + return rounded; } /* @@ -1171,28 +1152,28 @@ TkRoundToResolution(scalePtr, value) * * ScaleVarProc -- * - * This procedure is invoked by Tcl whenever someone modifies a - * variable associated with a scale widget. + * This procedure is invoked by Tcl whenever someone modifies a variable + * associated with a scale widget. * * Results: * NULL is always returned. * * Side effects: - * The value displayed in the scale will change to match the - * variable's new value. If the variable has a bogus value then - * it is reset to the value of the scale. + * The value displayed in the scale will change to match the variable's + * new value. If the variable has a bogus value then it is reset to the + * value of the scale. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static char * -ScaleVarProc(clientData, interp, name1, name2, flags) - ClientData clientData; /* Information about button. */ - Tcl_Interp *interp; /* Interpreter containing variable. */ - CONST char *name1; /* Name of variable. */ - CONST char *name2; /* Second part of variable name. */ - int flags; /* Information about what happened. */ +ScaleVarProc( + ClientData clientData, /* Information about button. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + CONST char *name1, /* Name of variable. */ + CONST char *name2, /* Second part of variable name. */ + int flags) /* Information about what happened. */ { register TkScale *scalePtr = (TkScale *) clientData; char *resultStr; @@ -1201,8 +1182,8 @@ ScaleVarProc(clientData, interp, name1, name2, flags) int result; /* - * If the variable is unset, then immediately recreate it unless - * the whole interpreter is going away. + * If the variable is unset, then immediately recreate it unless the whole + * interpreter is going away. */ if (flags & TCL_TRACE_UNSETS) { @@ -1213,34 +1194,33 @@ ScaleVarProc(clientData, interp, name1, name2, flags) scalePtr->flags |= NEVER_SET; TkScaleSetValue(scalePtr, scalePtr->value, 1, 0); } - return (char *) NULL; + return NULL; } /* * If we came here because we updated the variable (in TkScaleSetValue), - * then ignore the trace. Otherwise update the scale with the value - * of the variable. + * then ignore the trace. Otherwise update the scale with the value of the + * variable. */ if (scalePtr->flags & SETTING_VAR) { - return (char *) NULL; + return NULL; } resultStr = NULL; - valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL, - TCL_GLOBAL_ONLY); + valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL, + TCL_GLOBAL_ONLY); result = Tcl_GetDoubleFromObj(interp, valuePtr, &value); if (result != TCL_OK) { - resultStr = "can't assign non-numeric value to scale variable"; + resultStr = "can't assign non-numeric value to scale variable"; ScaleSetVariable(scalePtr); } else { scalePtr->value = TkRoundToResolution(scalePtr, value); /* * This code is a bit tricky because it sets the scale's value before - * calling TkScaleSetValue. This way, TkScaleSetValue won't bother - * to set the variable again or to invoke the -command. However, it - * also won't redisplay the scale, so we have to ask for that - * explicitly. + * calling TkScaleSetValue. This way, TkScaleSetValue won't bother to + * set the variable again or to invoke the -command. However, it also + * won't redisplay the scale, so we have to ask for that explicitly. */ TkScaleSetValue(scalePtr, scalePtr->value, 1, 0); @@ -1255,28 +1235,28 @@ ScaleVarProc(clientData, interp, name1, name2, flags) * * TkScaleSetValue -- * - * This procedure changes the value of a scale and invokes - * a Tcl command to reflect the current position of a scale + * This procedure changes the value of a scale and invokes a Tcl command + * to reflect the current position of a scale * * Results: * None. * * Side effects: - * A Tcl command is invoked, and an additional error-processing - * command may also be invoked. The scale's slider is redrawn. + * A Tcl command is invoked, and an additional error-processing command + * may also be invoked. The scale's slider is redrawn. * *-------------------------------------------------------------- */ void -TkScaleSetValue(scalePtr, value, setVar, invokeCommand) - register TkScale *scalePtr; /* Info about widget. */ - double value; /* New value for scale. Gets adjusted - * if it's off the scale. */ - int setVar; /* Non-zero means reflect new value through - * to associated variable, if any. */ - int invokeCommand; /* Non-zero means invoked -command option - * to notify of new value, 0 means don't. */ +TkScaleSetValue( + register TkScale *scalePtr, /* Info about widget. */ + double value, /* New value for scale. Gets adjusted if it's + * off the scale. */ + int setVar, /* Non-zero means reflect new value through to + * associated variable, if any. */ + int invokeCommand) /* Non-zero means invoked -command option to + * notify of new value, 0 means don't. */ { value = TkRoundToResolution(scalePtr, value); if ((value < scalePtr->fromValue) @@ -1320,11 +1300,12 @@ TkScaleSetValue(scalePtr, value, setVar, invokeCommand) */ static void -ScaleSetVariable(scalePtr) - register TkScale *scalePtr; /* Info about widget. */ +ScaleSetVariable( + register TkScale *scalePtr) /* Info about widget. */ { if (scalePtr->varNamePtr != NULL) { char string[PRINT_CHARS]; + sprintf(string, scalePtr->format, scalePtr->value); scalePtr->flags |= SETTING_VAR; Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL, @@ -1338,13 +1319,12 @@ ScaleSetVariable(scalePtr) * * TkScalePixelToValue -- * - * Given a pixel within a scale window, return the scale - * reading corresponding to that pixel. + * Given a pixel within a scale window, return the scale reading + * corresponding to that pixel. * * Results: - * A double-precision scale reading. If the value is outside - * the legal range for the scale then it's rounded to the nearest - * end of the scale. + * A double-precision scale reading. If the value is outside the legal + * range for the scale then it's rounded to the nearest end of the scale. * * Side effects: * None. @@ -1353,10 +1333,9 @@ ScaleSetVariable(scalePtr) */ double -TkScalePixelToValue(scalePtr, x, y) - register TkScale *scalePtr; /* Information about widget. */ - int x, y; /* Coordinates of point within - * window. */ +TkScalePixelToValue( + register TkScale *scalePtr, /* Information about widget. */ + int x, int y) /* Coordinates of point within window. */ { double value, pixelRange; @@ -1372,14 +1351,14 @@ TkScalePixelToValue(scalePtr, x, y) if (pixelRange <= 0) { /* - * Not enough room for the slider to actually slide: just return - * the scale's current value. + * Not enough room for the slider to actually slide: just return the + * scale's current value. */ return scalePtr->value; } value -= scalePtr->sliderLength/2 + scalePtr->inset - + scalePtr->borderWidth; + + scalePtr->borderWidth; value /= pixelRange; if (value < 0) { value = 0; @@ -1397,14 +1376,13 @@ TkScalePixelToValue(scalePtr, x, y) * * TkScaleValueToPixel -- * - * Given a reading of the scale, return the x-coordinate or - * y-coordinate corresponding to that reading, depending on - * whether the scale is vertical or horizontal, respectively. + * Given a reading of the scale, return the x-coordinate or y-coordinate + * corresponding to that reading, depending on whether the scale is + * vertical or horizontal, respectively. * * Results: - * An integer value giving the pixel location corresponding - * to reading. The value is restricted to lie within the - * defined range for the scale. + * An integer value giving the pixel location corresponding to reading. + * The value is restricted to lie within the defined range for the scale. * * Side effects: * None. @@ -1413,9 +1391,9 @@ TkScalePixelToValue(scalePtr, x, y) */ int -TkScaleValueToPixel(scalePtr, value) - register TkScale *scalePtr; /* Information about widget. */ - double value; /* Reading of the widget. */ +TkScaleValueToPixel( + register TkScale *scalePtr, /* Information about widget. */ + double value) /* Reading of the widget. */ { int y, pixelRange; double valueRange; @@ -1428,7 +1406,7 @@ TkScaleValueToPixel(scalePtr, value) y = 0; } else { y = (int) ((value - scalePtr->fromValue) * pixelRange - / valueRange + 0.5); + / valueRange + 0.5); if (y < 0) { y = 0; } else if (y > pixelRange) { @@ -1438,3 +1416,11 @@ TkScaleValueToPixel(scalePtr, value) y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth; return y; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkScale.h b/generic/tkScale.h index 71d5d53..f406bf6 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -1,21 +1,21 @@ /* * tkScale.h -- * - * Declarations of types and functions used to implement - * the scale widget. + * Declarations of types and functions used to implement the scale + * widget. * * Copyright (c) 1996 by Sun Microsystems, Inc. * Copyright (c) 1999-2000 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKSCALE #define _TKSCALE -#ifndef _TK -#include "tk.h" +#ifndef _TKINT +#include "tkInt.h" #endif #ifdef BUILD_tk @@ -40,16 +40,16 @@ enum state { }; /* - * A data structure of the following type is kept for each scale - * widget managed by this file: + * A data structure of the following type is kept for each scale widget + * managed by this file: */ typedef struct TkScale { - Tk_Window tkwin; /* Window that embodies the scale. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display containing widget. Used, among + Tk_Window tkwin; /* Window that embodies the scale. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up.*/ + Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with scale. */ @@ -58,42 +58,41 @@ typedef struct TkScale { * available for this widget. */ enum orient orient; /* Orientation for window (vertical or * horizontal). */ - int width; /* Desired narrow dimension of scale, - * in pixels. */ - int length; /* Desired long dimension of scale, - * in pixels. */ + int width; /* Desired narrow dimension of scale, in + * pixels. */ + int length; /* Desired long dimension of scale, in + * pixels. */ double value; /* Current value of scale. */ - Tcl_Obj *varNamePtr; /* Name of variable or NULL. - * If non-NULL, scale's value tracks - * the contents of this variable and - * vice versa. */ + Tcl_Obj *varNamePtr; /* Name of variable or NULL. If non-NULL, + * scale's value tracks the contents of this + * variable and vice versa. */ double fromValue; /* Value corresponding to left or top of * scale. */ - double toValue; /* Value corresponding to right or bottom - * of scale. */ - double tickInterval; /* Distance between tick marks; - * 0 means don't display any tick marks. */ - double resolution; /* If > 0, all values are rounded to an - * even multiple of this value. */ - int digits; /* Number of significant digits to print - * in values. 0 means we get to choose the - * number based on resolution and/or the - * range of the scale. */ + double toValue; /* Value corresponding to right or bottom of + * scale. */ + double tickInterval; /* Distance between tick marks; 0 means don't + * display any tick marks. */ + double resolution; /* If > 0, all values are rounded to an even + * multiple of this value. */ + int digits; /* Number of significant digits to print in + * values. 0 means we get to choose the number + * based on resolution and/or the range of the + * scale. */ char format[10]; /* 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). */ + double bigIncrement; /* Amount to use for large increments to scale + * value. (0 means we pick a value). */ char *command; /* Command prefix to use when invoking Tcl * commands because the scale value changed. * NULL means don't invoke commands. */ - int repeatDelay; /* How long to wait before auto-repeating - * on scrolling actions (in ms). */ + int repeatDelay; /* How long to wait before auto-repeating on + * scrolling actions (in ms). */ int repeatInterval; /* Interval between autorepeats (in ms). */ char *label; /* Label to display above or to right of - * scale; NULL means don't display a label. */ + * scale; NULL means don't display a label. */ int labelLength; /* Number of non-NULL chars. in label. */ enum state state; /* Values are active, normal, or disabled. - * Value of scale cannot be changed when + * Value of scale cannot be changed when * disabled. */ /* @@ -104,19 +103,19 @@ typedef struct TkScale { Tk_3DBorder bgBorder; /* Used for drawing slider and other * background areas. */ Tk_3DBorder activeBorder; /* For drawing the slider when active. */ - int sliderRelief; /* Is slider to be drawn raised, sunken, + int sliderRelief; /* Is slider to be drawn raised, sunken, * etc. */ XColor *troughColorPtr; /* Color for drawing trough. */ GC troughGC; /* For drawing trough. */ - GC copyGC; /* Used for copying from pixmap onto screen. */ + GC copyGC; /* Used for copying from pixmap onto screen */ Tk_Font tkfont; /* Information about text font, or NULL. */ XColor *textColorPtr; /* Color for drawing text. */ GC textGC; /* GC for drawing text in normal mode. */ int relief; /* Indicates whether window as a whole is * raised, sunken, or flat. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ Tk_3DBorder highlightBorder;/* Value of -highlightbackground option: * specifies background with which to draw 3-D * default ring and focus highlight area when @@ -124,18 +123,18 @@ typedef struct TkScale { XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. - * Indicates how much interior stuff must - * be offset from outside edges to leave - * room for borders. */ + * Indicates how much interior stuff must be + * offset from outside edges to leave room for + * borders. */ int sliderLength; /* Length of slider, measured in pixels along * long dimension of scale. */ int showValue; /* Non-zero means to display the scale value - * below or to the left of the slider; zero + * below or to the left of the slider; zero * means don't display the value. */ /* - * Layout information for horizontal scales, assuming that window - * gets the size it requested: + * Layout information for horizontal scales, assuming that window gets the + * size it requested: */ int horizLabelY; /* Y-coord at which to draw label. */ @@ -143,8 +142,8 @@ typedef struct TkScale { int horizTroughY; /* Y-coord of top of slider trough. */ int horizTickY; /* Y-coord at which to draw tick text. */ /* - * Layout information for vertical scales, assuming that window - * gets the size it requested: + * Layout information for vertical scales, assuming that window gets the + * size it requested: */ int vertTickRightX; /* X-location of right side of tick-marks. */ @@ -158,37 +157,37 @@ typedef struct TkScale { int fontHeight; /* Height of scale font. */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. May be NULL. */ - int flags; /* Various flags; see below for + Tcl_Obj *takeFocusPtr; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. May be NULL. */ + int flags; /* Various flags; see below for * definitions. */ } TkScale; /* * Flag bits for scales: * - * REDRAW_SLIDER - 1 means slider (and numerical readout) need - * to be redrawn. + * REDRAW_SLIDER - 1 means slider (and numerical readout) need to + * be redrawn. * REDRAW_OTHER - 1 means other stuff besides slider and value * need to be redrawn. * REDRAW_ALL - 1 means the entire widget needs to be redrawn. * REDRAW_PENDING - 1 means any sort of redraw is pending - * ACTIVE - 1 means the widget is active (the mouse is - * in its window). + * ACTIVE - 1 means the widget is active (the mouse is in + * its window). * INVOKE_COMMAND - 1 means the scale's command needs to be - * invoked during the next redisplay (the - * value of the scale has changed since the - * last time the command was invoked). - * SETTING_VAR - 1 means that the associated variable is - * being set by us, so there's no need for - * ScaleVarProc to do anything. - * NEVER_SET - 1 means that the scale's value has never - * been set before (so must invoke -command and - * set associated variable even if the value - * doesn't appear to have changed). - * GOT_FOCUS - 1 means that the focus is currently in - * this widget. + * invoked during the next redisplay (the value + * of the scale has changed since the last time + * the command was invoked). + * SETTING_VAR - 1 means that the associated variable is being + * set by us, so there's no need for ScaleVarProc + * to do anything. + * NEVER_SET - 1 means that the scale's value has never been + * set before (so must invoke -command and set + * associated variable even if the value doesn't + * appear to have changed). + * GOT_FOCUS - 1 means that the focus is currently in this + * widget. * SCALE_DELETED - 1 means the scale widget is being deleted */ @@ -204,8 +203,8 @@ typedef struct TkScale { #define SCALE_DELETED (1<<8) /* - * Symbolic values for the active parts of a slider. These are - * the values that may be returned by the ScaleElement procedure. + * Symbolic values for the active parts of a slider. These are the values that + * may be returned by the ScaleElement procedure. */ #define OTHER 0 @@ -214,39 +213,32 @@ typedef struct TkScale { #define TROUGH2 3 /* - * Space to leave between scale area and text, and between text and - * edge of window. + * Space to leave between scale area and text, and between text and edge of + * window. */ #define SPACING 2 /* - * How many characters of space to provide when formatting the - * scale's value: + * How many characters of space to provide when formatting the scale's value: */ #define PRINT_CHARS 150 /* - * Declaration of procedures used in the implementation of the scale - * widget. + * Declaration of procedures used in the implementation of the scale widget. */ -EXTERN void TkEventuallyRedrawScale _ANSI_ARGS_((TkScale *scalePtr, - int what)); -EXTERN double TkRoundToResolution _ANSI_ARGS_((TkScale *scalePtr, - double value)); -EXTERN TkScale * TkpCreateScale _ANSI_ARGS_((Tk_Window tkwin)); -EXTERN void TkpDestroyScale _ANSI_ARGS_((TkScale *scalePtr)); -EXTERN void TkpDisplayScale _ANSI_ARGS_((ClientData clientData)); -EXTERN int TkpScaleElement _ANSI_ARGS_((TkScale *scalePtr, - int x, int y)); -EXTERN void TkScaleSetValue _ANSI_ARGS_((TkScale *scalePtr, - double value, int setVar, int invokeCommand)); -EXTERN double TkScalePixelToValue _ANSI_ARGS_((TkScale *scalePtr, - int x, int y)); -EXTERN int TkScaleValueToPixel _ANSI_ARGS_((TkScale *scalePtr, - double value)); +MODULE_SCOPE void TkEventuallyRedrawScale(TkScale *scalePtr, int what); +MODULE_SCOPE double TkRoundToResolution(TkScale *scalePtr, double value); +MODULE_SCOPE TkScale * TkpCreateScale(Tk_Window tkwin); +MODULE_SCOPE void TkpDestroyScale(TkScale *scalePtr); +MODULE_SCOPE void TkpDisplayScale(ClientData clientData); +MODULE_SCOPE int TkpScaleElement(TkScale *scalePtr, int x, int y); +MODULE_SCOPE void TkScaleSetValue(TkScale *scalePtr, double value, + int setVar, int invokeCommand); +MODULE_SCOPE double TkScalePixelToValue(TkScale *scalePtr, int x, int y); +MODULE_SCOPE int TkScaleValueToPixel(TkScale *scalePtr, double value); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tkScrollbar.c b/generic/tkScrollbar.c index d4f3d88..f19671c 100644 --- a/generic/tkScrollbar.c +++ b/generic/tkScrollbar.c @@ -1,19 +1,18 @@ -/* +/* * tkScrollbar.c -- * - * This module implements a scrollbar widgets for the Tk - * toolkit. A scrollbar displays a slider and two arrows; - * mouse clicks on features within the scrollbar cause - * scrolling commands to be invoked. + * This module implements a scrollbar widgets for the Tk toolkit. A + * scrollbar displays a slider and two arrows; mouse clicks on features + * within the scrollbar cause scrolling commands to be invoked. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" +#include "tkInt.h" #include "tkScrollbar.h" #include "default.h" @@ -46,10 +45,8 @@ Tk_ConfigSpec tkpScrollbarConfigSpecs[] = { {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_SCROLLBAR_BG_MONO, Tk_Offset(TkScrollbar, bgBorder), TK_CONFIG_MONO_ONLY}, - {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, - (char *) NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bd", "borderWidth", NULL, NULL, 0, 0}, + {TK_CONFIG_SYNONYM, "-bg", "background", NULL, NULL, 0, 0}, {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_SCROLLBAR_BORDER_WIDTH, Tk_Offset(TkScrollbar, borderWidth), 0}, {TK_CONFIG_STRING, "-command", "command", "Command", @@ -91,30 +88,27 @@ Tk_ConfigSpec tkpScrollbarConfigSpecs[] = { TK_CONFIG_MONO_ONLY}, {TK_CONFIG_PIXELS, "-width", "width", "Width", DEF_SCROLLBAR_WIDTH, Tk_Offset(TkScrollbar, width), 0}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} + {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0} }; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int ConfigureScrollbar _ANSI_ARGS_((Tcl_Interp *interp, - TkScrollbar *scrollPtr, int argc, CONST char **argv, - int flags)); -static void ScrollbarCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static int ScrollbarWidgetCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *, int argc, CONST char **argv)); +static int ConfigureScrollbar(Tcl_Interp *interp, + TkScrollbar *scrollPtr, int argc, + CONST char **argv, int flags); +static void ScrollbarCmdDeletedProc(ClientData clientData); +static int ScrollbarWidgetCmd(ClientData clientData, + Tcl_Interp *, int argc, CONST char **argv); /* *-------------------------------------------------------------- * * Tk_ScrollbarCmd -- * - * This procedure is invoked to process the "scrollbar" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "scrollbar" Tcl command. See + * the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -126,41 +120,40 @@ static int ScrollbarWidgetCmd _ANSI_ARGS_((ClientData clientData, */ int -Tk_ScrollbarCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +Tk_ScrollbarCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { Tk_Window tkwin = (Tk_Window) clientData; register TkScrollbar *scrollPtr; - Tk_Window new; + Tk_Window newWin; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " pathName ?options?\"", (char *) NULL); + argv[0], " pathName ?options?\"", NULL); return TCL_ERROR; } - new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL); - if (new == NULL) { + newWin = Tk_CreateWindowFromPath(interp, tkwin, argv[1], NULL); + if (newWin == NULL) { return TCL_ERROR; } - Tk_SetClass(new, "Scrollbar"); - scrollPtr = TkpCreateScrollbar(new); + Tk_SetClass(newWin, "Scrollbar"); + scrollPtr = TkpCreateScrollbar(newWin); - Tk_SetClassProcs(new, &tkpScrollbarProcs, (ClientData) scrollPtr); + Tk_SetClassProcs(newWin, &tkpScrollbarProcs, (ClientData) scrollPtr); /* - * Initialize fields that won't be initialized by ConfigureScrollbar, - * or which ConfigureScrollbar expects to have reasonable values - * (e.g. resource pointers). + * Initialize fields that won't be initialized by ConfigureScrollbar, or + * which ConfigureScrollbar expects to have reasonable values (e.g. + * resource pointers). */ - scrollPtr->tkwin = new; - scrollPtr->display = Tk_Display(new); + scrollPtr->tkwin = newWin; + scrollPtr->display = Tk_Display(newWin); scrollPtr->interp = interp; scrollPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetCmd, @@ -210,9 +203,9 @@ Tk_ScrollbarCmd(clientData, interp, argc, argv) * * ScrollbarWidgetCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -224,12 +217,11 @@ Tk_ScrollbarCmd(clientData, interp, argc, argv) */ static int -ScrollbarWidgetCmd(clientData, interp, argc, argv) - ClientData clientData; /* Information about scrollbar - * widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +ScrollbarWidgetCmd( + ClientData clientData, /* Information about scrollbar widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { register TkScrollbar *scrollPtr = (TkScrollbar *) clientData; int result = TCL_OK; @@ -238,7 +230,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " option ?arg arg ...?\"", (char *) NULL); + argv[0], " option ?arg arg ...?\"", NULL); return TCL_ERROR; } Tcl_Preserve((ClientData) scrollPtr); @@ -248,21 +240,21 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) int oldActiveField; if (argc == 2) { switch (scrollPtr->activeField) { - case TOP_ARROW: - Tcl_SetResult(interp, "arrow1", TCL_STATIC); - break; - case SLIDER: - Tcl_SetResult(interp, "slider", TCL_STATIC); - break; - case BOTTOM_ARROW: - Tcl_SetResult(interp, "arrow2", TCL_STATIC); - break; + case TOP_ARROW: + Tcl_SetResult(interp, "arrow1", TCL_STATIC); + break; + case SLIDER: + Tcl_SetResult(interp, "slider", TCL_STATIC); + break; + case BOTTOM_ARROW: + Tcl_SetResult(interp, "arrow2", TCL_STATIC); + break; } goto done; } if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " activate element\"", (char *) NULL); + argv[0], " activate element\"", NULL); goto error; } c = argv[2][0]; @@ -285,7 +277,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cget option\"", - (char *) NULL); + NULL); goto error; } result = Tk_ConfigureValue(interp, scrollPtr->tkwin, @@ -294,8 +286,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) && (length >= 2)) { if (argc == 2) { result = Tk_ConfigureInfo(interp, scrollPtr->tkwin, - tkpScrollbarConfigSpecs, (char *) scrollPtr, - (char *) NULL, 0); + tkpScrollbarConfigSpecs, (char *) scrollPtr, NULL, 0); } else if (argc == 3) { result = Tk_ConfigureInfo(interp, scrollPtr->tkwin, tkpScrollbarConfigSpecs, (char *) scrollPtr, argv[2], 0); @@ -310,7 +301,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " delta xDelta yDelta\"", (char *) NULL); + argv[0], " delta xDelta yDelta\"", NULL); goto error; } if ((Tcl_GetInt(interp, argv[2], &xDelta) != TCL_OK) @@ -331,7 +322,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) } else { fraction = ((double) pixels / (double) length); } - sprintf(buf, "%g", fraction); + Tcl_PrintDouble(NULL, fraction, buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if ((c == 'f') && (strncmp(argv[1], "fraction", length) == 0)) { int x, y, pos, length; @@ -340,7 +331,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " fraction x y\"", (char *) NULL); + argv[0], " fraction x y\"", NULL); goto error; } if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) @@ -366,12 +357,12 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) } else if (fraction > 1.0) { fraction = 1.0; } - sprintf(buf, "%g", fraction); + Tcl_PrintDouble(NULL, fraction, buf); Tcl_SetResult(interp, buf, TCL_VOLATILE); } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " get\"", (char *) NULL); + argv[0], " get\"", NULL); goto error; } if (scrollPtr->flags & NEW_STYLE_COMMANDS) { @@ -379,7 +370,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) Tcl_PrintDouble(interp, scrollPtr->firstFraction, first); Tcl_PrintDouble(interp, scrollPtr->lastFraction, last); - Tcl_AppendResult(interp, first, " ", last, (char *) NULL); + Tcl_AppendResult(interp, first, " ", last, NULL); } else { char buf[TCL_INTEGER_SPACE * 4]; @@ -393,7 +384,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) if (argc != 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " identify x y\"", (char *) NULL); + argv[0], " identify x y\"", NULL); goto error; } if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) @@ -402,21 +393,21 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) } thing = TkpScrollbarPosition(scrollPtr, x,y); switch (thing) { - case TOP_ARROW: - Tcl_SetResult(interp, "arrow1", TCL_STATIC); - break; - case TOP_GAP: - Tcl_SetResult(interp, "trough1", TCL_STATIC); - break; - case SLIDER: - Tcl_SetResult(interp, "slider", TCL_STATIC); - break; - case BOTTOM_GAP: - Tcl_SetResult(interp, "trough2", TCL_STATIC); - break; - case BOTTOM_ARROW: - Tcl_SetResult(interp, "arrow2", TCL_STATIC); - break; + case TOP_ARROW: + Tcl_SetResult(interp, "arrow1", TCL_STATIC); + break; + case TOP_GAP: + Tcl_SetResult(interp, "trough1", TCL_STATIC); + break; + case SLIDER: + Tcl_SetResult(interp, "slider", TCL_STATIC); + break; + case BOTTOM_GAP: + Tcl_SetResult(interp, "trough2", TCL_STATIC); + break; + case BOTTOM_ARROW: + Tcl_SetResult(interp, "arrow2", TCL_STATIC); + break; } } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) { int totalUnits, windowUnits, firstUnit, lastUnit; @@ -487,8 +478,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " set firstFraction lastFraction\" or \"", argv[0], - " set totalUnits windowUnits firstUnit lastUnit\"", - (char *) NULL); + " set totalUnits windowUnits firstUnit lastUnit\"", NULL); goto error; } TkpComputeScrollbarGeometry(scrollPtr); @@ -496,14 +486,15 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be activate, cget, configure, delta, fraction, ", - "get, identify, or set", (char *) NULL); + "get, identify, or set", NULL); goto error; } - done: + + done: Tcl_Release((ClientData) scrollPtr); return result; - error: + error: Tcl_Release((ClientData) scrollPtr); return TCL_ERROR; } @@ -513,32 +504,30 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv) * * ConfigureScrollbar -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a scrollbar widget. + * This function is called to process an argv/argc list, plus the Tk + * option database, in order to configure (or reconfigure) a scrollbar + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for scrollPtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for scrollPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureScrollbar(interp, scrollPtr, argc, argv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - register TkScrollbar *scrollPtr; /* Information about widget; may or - * may not already have values for - * some fields. */ - int argc; /* Number of valid entries in argv. */ - CONST char **argv; /* Arguments. */ - int flags; /* Flags to pass to - * Tk_ConfigureWidget. */ +ConfigureScrollbar( + Tcl_Interp *interp, /* Used for error reporting. */ + register TkScrollbar *scrollPtr, + /* Information about widget; may or may not + * already have values for some fields. */ + int argc, /* Number of valid entries in argv. */ + CONST char **argv, /* Arguments. */ + int flags) /* Flags to pass to Tk_ConfigureWidget. */ { if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, tkpScrollbarConfigSpecs, argc, argv, (char *) scrollPtr, flags) != TCL_OK) { @@ -546,12 +535,12 @@ ConfigureScrollbar(interp, scrollPtr, argc, argv, flags) } /* - * A few options need special processing, such as setting the - * background from a 3-D border. + * A few options need special processing, such as setting the background + * from a 3-D border. */ if (scrollPtr->command != NULL) { - scrollPtr->commandSize = strlen(scrollPtr->command); + scrollPtr->commandSize = (int)strlen(scrollPtr->command); } else { scrollPtr->commandSize = 0; } @@ -563,10 +552,9 @@ ConfigureScrollbar(interp, scrollPtr, argc, argv, flags) TkpConfigureScrollbar(scrollPtr); /* - * Register the desired geometry for the window (leave enough space - * for the two arrows plus a minimum-size slider, plus border around - * the whole window, if any). Then arrange for the window to be - * redisplayed. + * Register the desired geometry for the window (leave enough space for + * the two arrows plus a minimum-size slider, plus border around the whole + * window, if any). Then arrange for the window to be redisplayed. */ TkpComputeScrollbarGeometry(scrollPtr); @@ -579,23 +567,23 @@ ConfigureScrollbar(interp, scrollPtr, argc, argv, flags) * * TkScrollbarEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on scrollbars. + * This function is invoked by the Tk dispatcher for various events on + * scrollbars. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ void -TkScrollbarEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +TkScrollbarEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkScrollbar *scrollPtr = (TkScrollbar *) clientData; @@ -606,17 +594,16 @@ TkScrollbarEventProc(clientData, eventPtr) if (scrollPtr->tkwin != NULL) { scrollPtr->tkwin = NULL; Tcl_DeleteCommandFromToken(scrollPtr->interp, - scrollPtr->widgetCmd); + scrollPtr->widgetCmd); } if (scrollPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(TkpDisplayScrollbar, (ClientData) scrollPtr); } /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. + * Free up all the stuff that requires special handling, then let + * Tk_FreeOptions handle all the standard option-related stuff. */ - + Tk_FreeOptions(tkpScrollbarConfigSpecs, (char *) scrollPtr, scrollPtr->display, 0); Tcl_EventuallyFree((ClientData) scrollPtr, TCL_DYNAMIC); @@ -645,9 +632,9 @@ TkScrollbarEventProc(clientData, eventPtr) * * ScrollbarCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -659,17 +646,17 @@ TkScrollbarEventProc(clientData, eventPtr) */ static void -ScrollbarCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +ScrollbarCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkScrollbar *scrollPtr = (TkScrollbar *) clientData; Tk_Window tkwin = scrollPtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this function destroys the + * widget. */ if (tkwin != NULL) { @@ -683,8 +670,7 @@ ScrollbarCmdDeletedProc(clientData) * * TkScrollbarEventuallyRedraw -- * - * Arrange for one or more of the fields of a scrollbar - * to be redrawn. + * Arrange for one or more of the fields of a scrollbar to be redrawn. * * Results: * None. @@ -696,8 +682,8 @@ ScrollbarCmdDeletedProc(clientData) */ void -TkScrollbarEventuallyRedraw(scrollPtr) - register TkScrollbar *scrollPtr; /* Information about widget. */ +TkScrollbarEventuallyRedraw( + TkScrollbar *scrollPtr) /* Information about widget. */ { if ((scrollPtr->tkwin == NULL) || (!Tk_IsMapped(scrollPtr->tkwin))) { return; @@ -707,3 +693,11 @@ TkScrollbarEventuallyRedraw(scrollPtr) scrollPtr->flags |= REDRAW_PENDING; } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkScrollbar.h b/generic/tkScrollbar.h index 6b7f2dc..e2890f4 100644 --- a/generic/tkScrollbar.h +++ b/generic/tkScrollbar.h @@ -1,13 +1,13 @@ /* * tkScrollbar.h -- * - * Declarations of types and functions used to implement - * the scrollbar widget. + * Declarations of types and functions used to implement the scrollbar + * widget. * * Copyright (c) 1996 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKSCROLLBAR @@ -23,30 +23,29 @@ #endif /* - * A data structure of the following type is kept for each scrollbar - * widget. + * A data structure of the following type is kept for each scrollbar widget. */ typedef struct TkScrollbar { - Tk_Window tkwin; /* Window that embodies the scrollbar. NULL + Tk_Window tkwin; /* Window that embodies the scrollbar. NULL * means that the window has been destroyed * but the data structures haven't yet been * cleaned up.*/ - Display *display; /* Display containing widget. Used, among + Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with scrollbar. */ Tcl_Command widgetCmd; /* Token for scrollbar's widget command. */ int vertical; /* Non-zero means vertical orientation * requested, zero means horizontal. */ - int width; /* Desired narrow dimension of scrollbar, - * in pixels. */ + int width; /* Desired narrow dimension of scrollbar, in + * pixels. */ char *command; /* Command prefix to use when invoking - * scrolling commands. NULL means don't - * invoke commands. Malloc'ed. */ + * scrolling commands. NULL means don't invoke + * commands. Malloc'ed. */ int commandSize; /* Number of non-NULL bytes in command. */ - int repeatDelay; /* How long to wait before auto-repeating - * on scrolling actions (in ms). */ + int repeatDelay; /* How long to wait before auto-repeating on + * scrolling actions (in ms). */ int repeatInterval; /* Interval between autorepeats (in ms). */ int jump; /* Value of -jump option. */ @@ -62,60 +61,58 @@ typedef struct TkScrollbar { XColor *troughColorPtr; /* Color for drawing trough. */ int relief; /* Indicates whether window as a whole is * raised, sunken, or flat. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ XColor *highlightBgColorPtr; - /* Color for drawing traversal highlight - * area when highlight is off. */ + /* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. - * Indicates how much interior stuff must - * be offset from outside edges to leave - * room for borders. */ + * Indicates how much interior stuff must be + * offset from outside edges to leave room for + * borders. */ int elementBorderWidth; /* Width of border to draw around elements - * inside scrollbar (arrows and slider). - * -1 means use borderWidth. */ + * inside scrollbar (arrows and slider). -1 + * means use borderWidth. */ int arrowLength; /* Length of arrows along long dimension of * scrollbar, including space for a small gap * between the arrow and the slider. * Recomputed on window size changes. */ - int sliderFirst; /* Pixel coordinate of top or left edge - * of slider area, including border. */ - int sliderLast; /* Coordinate of pixel just after bottom - * or right edge of slider area, including + int sliderFirst; /* Pixel coordinate of top or left edge of + * slider area, including border. */ + int sliderLast; /* Coordinate of pixel just after bottom or + * right edge of slider area, including * border. */ int activeField; /* Names field to be displayed in active - * colors, such as TOP_ARROW, or 0 for - * no field. */ - int activeRelief; /* Value of -activeRelief option: relief - * to use for active element. */ + * colors, such as TOP_ARROW, or 0 for no + * field. */ + int activeRelief; /* Value of -activeRelief option: relief to + * use for active element. */ /* - * Information describing the application related to the scrollbar. - * This information is provided by the application by invoking the - * "set" widget command. This information can now be provided in - * two ways: the "old" form (totalUnits, windowUnits, firstUnit, - * and lastUnit), or the "new" form (firstFraction and lastFraction). - * FirstFraction and lastFraction will always be valid, but - * the old-style information is only valid if the NEW_STYLE_COMMANDS - * flag is 0. + * Information describing the application related to the scrollbar. This + * information is provided by the application by invoking the "set" widget + * command. This information can now be provided in two ways: the "old" + * form (totalUnits, windowUnits, firstUnit, and lastUnit), or the "new" + * form (firstFraction and lastFraction). FirstFraction and lastFraction + * will always be valid, but the old-style information is only valid if + * the NEW_STYLE_COMMANDS flag is 0. */ - int totalUnits; /* Total dimension of application, in - * units. Valid only if the NEW_STYLE_COMMANDS - * flag isn't set. */ + int totalUnits; /* Total dimension of application, in units. + * Valid only if the NEW_STYLE_COMMANDS flag + * isn't 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. */ + * displayed in the window at once. Valid only + * if the NEW_STYLE_COMMANDS flag isn't set. */ int firstUnit; /* Number of last unit visible in - * application's window. Valid only if the + * application's window. Valid only if the * NEW_STYLE_COMMANDS flag isn't set. */ int lastUnit; /* Index of last unit visible in window. - * Valid only if the NEW_STYLE_COMMANDS - * flag isn't set. */ + * Valid only if the NEW_STYLE_COMMANDS flag + * isn't set. */ double firstFraction; /* Position of first visible thing in window, * specified as a fraction between 0 and * 1.0. */ @@ -128,16 +125,16 @@ typedef struct TkScrollbar { */ Tk_Cursor cursor; /* Current cursor for window, or None. */ - char *takeFocus; /* Value of -takefocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ - int flags; /* Various flags; see below for + char *takeFocus; /* Value of -takefocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ + int flags; /* Various flags; see below for * definitions. */ } TkScrollbar; /* - * Legal values for "activeField" field of Scrollbar structures. These - * are also the return values from the ScrollbarPosition procedure. + * Legal values for "activeField" field of Scrollbar structures. These are + * also the return values from the ScrollbarPosition function. */ #define OUTSIDE 0 @@ -149,14 +146,13 @@ typedef struct TkScrollbar { /* * Flag bits for scrollbars: - * - * REDRAW_PENDING: Non-zero means a DoWhenIdle handler - * has already been queued to redraw - * this window. + * + * 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 - * should be used to communicate with the - * widget: ".t yview scroll 2 lines", instead - * of ".t yview 40", for example. + * should be used to communicate with the widget: + * ".t yview scroll 2 lines", instead of + * ".t yview 40", for example. * GOT_FOCUS: Non-zero means this window has the input * focus. */ @@ -166,37 +162,32 @@ typedef struct TkScrollbar { #define GOT_FOCUS 4 /* - * Declaration of scrollbar class procedures structure. + * Declaration of scrollbar class functions structure. */ -extern Tk_ClassProcs tkpScrollbarProcs; +MODULE_SCOPE Tk_ClassProcs tkpScrollbarProcs; /* * Declaration of scrollbar configuration options. */ -extern Tk_ConfigSpec tkpScrollbarConfigSpecs[]; +MODULE_SCOPE Tk_ConfigSpec tkpScrollbarConfigSpecs[]; /* - * Declaration of procedures used in the implementation of the scrollbar - * widget. + * Declaration of functions used in the implementation of the scrollbar + * widget. */ -EXTERN void TkScrollbarEventProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -EXTERN void TkScrollbarEventuallyRedraw _ANSI_ARGS_(( - TkScrollbar *scrollPtr)); -EXTERN void TkpComputeScrollbarGeometry _ANSI_ARGS_(( - TkScrollbar *scrollPtr)); -EXTERN TkScrollbar * TkpCreateScrollbar _ANSI_ARGS_((Tk_Window tkwin)); -EXTERN void TkpDestroyScrollbar _ANSI_ARGS_(( - TkScrollbar *scrollPtr)); -EXTERN void TkpDisplayScrollbar _ANSI_ARGS_(( - ClientData clientData)); -EXTERN void TkpConfigureScrollbar _ANSI_ARGS_(( - TkScrollbar *scrollPtr)); -EXTERN int TkpScrollbarPosition _ANSI_ARGS_(( - TkScrollbar *scrollPtr, int x, int y)); +MODULE_SCOPE void TkScrollbarEventProc(ClientData clientData, + XEvent *eventPtr); +MODULE_SCOPE void TkScrollbarEventuallyRedraw(TkScrollbar *scrollPtr); +MODULE_SCOPE void TkpComputeScrollbarGeometry(TkScrollbar *scrollPtr); +MODULE_SCOPE TkScrollbar *TkpCreateScrollbar(Tk_Window tkwin); +MODULE_SCOPE void TkpDestroyScrollbar(TkScrollbar *scrollPtr); +MODULE_SCOPE void TkpDisplayScrollbar(ClientData clientData); +MODULE_SCOPE void TkpConfigureScrollbar(TkScrollbar *scrollPtr); +MODULE_SCOPE int TkpScrollbarPosition(TkScrollbar *scrollPtr, + int x, int y); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tkSelect.c b/generic/tkSelect.c index 2ac3424..7c96b94 100644 --- a/generic/tkSelect.c +++ b/generic/tkSelect.c @@ -1,24 +1,23 @@ -/* +/* * tkSelect.c -- * - * This file manages the selection for the Tk toolkit, - * translating between the standard X ICCCM conventions - * and Tcl commands. + * This file manages the selection for the Tk toolkit, translating + * between the standard X ICCCM conventions and Tcl commands. * * Copyright (c) 1990-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkSelect.h" /* - * When a selection handler is set up by invoking "selection handle", - * one of the following data structures is set up to hold information - * about the command to invoke and its interpreter. + * When a selection handler is set up by invoking "selection handle", one of + * the following data structures is set up to hold information about the + * command to invoke and its interpreter. */ typedef struct { @@ -28,109 +27,105 @@ typedef struct { int byteOffset; /* The expected byte offset of the next * chunk. */ char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character - * that is split across chunks.*/ - char command[4]; /* Command to invoke. Actual space is - * allocated as large as necessary. This - * must be the last entry in the structure. */ + * that is split across chunks. */ + char command[4]; /* Command to invoke. Actual space is + * allocated as large as necessary. This must + * be the last entry in the structure. */ } CommandInfo; /* * When selection ownership is claimed with the "selection own" Tcl command, - * one of the following structures is created to record the Tcl command - * to be executed when the selection is lost again. + * one of the following structures is created to record the Tcl command to be + * executed when the selection is lost again. */ typedef struct LostCommand { Tcl_Interp *interp; /* Interpreter in which to invoke command. */ - char command[4]; /* Command to invoke. Actual space is - * allocated as large as necessary. This - * must be the last entry in the structure. */ + char command[4]; /* Command to invoke. Actual space is + * allocated as large as necessary. This must + * be the last entry in the structure. */ } LostCommand; /* - * The structure below is used to keep each thread's pending list - * separate. + * The structure below is used to keep each thread's pending list separate. */ typedef struct ThreadSpecificData { TkSelInProgress *pendingPtr; - /* Topmost search in progress, or - * NULL if none. */ + /* Topmost search in progress, or NULL if + * none. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Forward declarations for procedures defined in this file: + * Forward declarations for functions defined in this file: */ -static int HandleTclCommand _ANSI_ARGS_((ClientData clientData, - int offset, char *buffer, int maxBytes)); -static void LostSelection _ANSI_ARGS_((ClientData clientData)); -static int SelGetProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, char *portion)); +static int HandleTclCommand(ClientData clientData, + int offset, char *buffer, int maxBytes); +static void LostSelection(ClientData clientData); +static int SelGetProc(ClientData clientData, + Tcl_Interp *interp, char *portion); /* *-------------------------------------------------------------- * * Tk_CreateSelHandler -- * - * This procedure is called to register a procedure - * as the handler for selection requests of a particular - * target type on a particular window for a particular - * selection. + * This function is called to register a function as the handler for + * selection requests of a particular target type on a particular window + * for a particular selection. * * Results: * None. * * Side effects: - * In the future, whenever the selection is in tkwin's - * window and someone requests the selection in the - * form given by target, proc will be invoked to provide - * part or all of the selection in the given form. If - * there was already a handler declared for the given - * window, target and selection type, then it is replaced. - * Proc should have the following form: + + * In the future, whenever the selection is in tkwin's window and someone + * requests the selection in the form given by target, proc will be + * invoked to provide part or all of the selection in the given form. If + * there was already a handler declared for the given window, target and + * selection type, then it is replaced. Proc should have the following + * form: * * int - * proc(clientData, offset, buffer, maxBytes) - * ClientData clientData; - * int offset; - * char *buffer; - * int maxBytes; + * proc( + * ClientData clientData, + * int offset, + * char *buffer, + * int maxBytes) * { * } * - * The clientData argument to proc will be the same as - * the clientData argument to this procedure. The offset - * argument indicates which portion of the selection to - * return: skip the first offset bytes. Buffer is a - * pointer to an area in which to place the converted - * selection, and maxBytes gives the number of bytes - * available at buffer. Proc should place the selection - * in buffer as a string, and return a count of the number - * of bytes of selection actually placed in buffer (not - * including the terminating NULL character). If the - * return value equals maxBytes, this is a sign that there - * is probably still more selection information available. + * The clientData argument to proc will be the same as the clientData + * argument to this function. The offset argument indicates which portion + * of the selection to return: skip the first offset bytes. Buffer is a + * pointer to an area in which to place the converted selection, and + * maxBytes gives the number of bytes available at buffer. Proc should + * place the selection in buffer as a string, and return a count of the + * number of bytes of selection actually placed in buffer (not including + * the terminating NULL character). If the return value equals maxBytes, + * this is a sign that there is probably still more selection information + * available. * *-------------------------------------------------------------- */ void -Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) - Tk_Window tkwin; /* Token for window. */ - Atom selection; /* Selection to be handled. */ - Atom target; /* The kind of selection conversions - * that can be handled by proc, - * e.g. TARGETS or STRING. */ - Tk_SelectionProc *proc; /* Procedure to invoke to convert - * selection to type "target". */ - ClientData clientData; /* Value to pass to proc. */ - Atom format; /* Format in which the selection - * information should be returned to - * the requestor. XA_STRING is best by - * far, but anything listed in the ICCCM - * will be tolerated (blech). */ +Tk_CreateSelHandler( + Tk_Window tkwin, /* Token for window. */ + Atom selection, /* Selection to be handled. */ + Atom target, /* The kind of selection conversions that can + * be handled by proc, e.g. TARGETS or + * STRING. */ + Tk_SelectionProc *proc, /* Function to invoke to convert selection to + * type "target". */ + ClientData clientData, /* Value to pass to proc. */ + Atom format) /* Format in which the selection information + * should be returned to the requestor. + * XA_STRING is best by far, but anything + * listed in the ICCCM will be tolerated + * (blech). */ { register TkSelHandler *selPtr; TkWindow *winPtr = (TkWindow *) tkwin; @@ -140,8 +135,8 @@ Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) } /* - * See if there's already a handler for this target and selection on - * this window. If so, re-use it. If not, create a new one. + * See if there's already a handler for this target and selection on this + * window. If so, re-use it. If not, create a new one. */ for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) { @@ -152,11 +147,10 @@ Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) break; } if ((selPtr->selection == selection) && (selPtr->target == target)) { - /* - * Special case: when replacing handler created by - * "selection handle", free up memory. Should there be a - * callback to allow other clients to do this too? + * Special case: when replacing handler created by "selection + * handle", free up memory. Should there be a callback to allow + * other clients to do this too? */ if (selPtr->proc == HandleTclCommand) { @@ -176,15 +170,14 @@ Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) selPtr->size = 32; } - if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) NULL)) { + if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) 0)) { /* * If the user asked for a STRING handler and we understand * UTF8_STRING, we implicitly create a UTF8_STRING handler for them. */ target = winPtr->dispPtr->utf8Atom; - for (selPtr = winPtr->selHandlerList; ; - selPtr = selPtr->nextPtr) { + for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) { if (selPtr == NULL) { selPtr = (TkSelHandler *) ckalloc(sizeof(TkSelHandler)); selPtr->nextPtr = winPtr->selHandlerList; @@ -195,11 +188,13 @@ Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) selPtr->proc = proc; if (selPtr->proc == HandleTclCommand) { /* - * The clientData is selection controlled memory, so - * we should make a copy for this selPtr. + * The clientData is selection controlled memory, so we + * should make a copy for this selPtr. */ - unsigned cmdInfoLen = sizeof(CommandInfo) + + + unsigned cmdInfoLen = sizeof(CommandInfo) + ((CommandInfo*)clientData)->cmdLength - 3; + selPtr->clientData = (ClientData)ckalloc(cmdInfoLen); memcpy(selPtr->clientData, clientData, cmdInfoLen); } else { @@ -208,10 +203,9 @@ Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) selPtr->size = 8; break; } - if ((selPtr->selection == selection) - && (selPtr->target == target)) { + if (selPtr->selection==selection && selPtr->target==target) { /* - * Looks like we had a utf-8 target already. Leave it alone. + * Looks like we had a utf-8 target already. Leave it alone. */ break; @@ -232,30 +226,30 @@ Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format) * None. * * Side effects: - * The selection handler for tkwin and target is removed. If there - * is no such handler then nothing happens. + * The selection handler for tkwin and target is removed. If there is no + * such handler then nothing happens. * *---------------------------------------------------------------------- */ void -Tk_DeleteSelHandler(tkwin, selection, target) - Tk_Window tkwin; /* Token for window. */ - Atom selection; /* The selection whose handler - * is to be removed. */ - Atom target; /* The target whose selection - * handler is to be removed. */ +Tk_DeleteSelHandler( + Tk_Window tkwin, /* Token for window. */ + Atom selection, /* The selection whose handler is to be + * removed. */ + Atom target) /* The target whose selection handler is to be + * removed. */ { TkWindow *winPtr = (TkWindow *) tkwin; register TkSelHandler *selPtr, *prevPtr; register TkSelInProgress *ipPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Find the selection handler to be deleted, or return if it doesn't * exist. - */ + */ for (selPtr = winPtr->selHandlerList, prevPtr = NULL; ; prevPtr = selPtr, selPtr = selPtr->nextPtr) { @@ -272,8 +266,8 @@ Tk_DeleteSelHandler(tkwin, selection, target) * handler is dead. */ - for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; - ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; + ipPtr = ipPtr->nextPtr) { if (ipPtr->selPtr == selPtr) { ipPtr->selPtr = NULL; } @@ -289,17 +283,18 @@ Tk_DeleteSelHandler(tkwin, selection, target) prevPtr->nextPtr = selPtr->nextPtr; } - if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) NULL)) { + if ((target == XA_STRING) && (winPtr->dispPtr->utf8Atom != (Atom) 0)) { /* * If the user asked for a STRING handler and we understand * UTF8_STRING, we may have implicitly created a UTF8_STRING handler - * for them. Look for it and delete it as necessary. + * for them. Look for it and delete it as necessary. */ + TkSelHandler *utf8selPtr; target = winPtr->dispPtr->utf8Atom; for (utf8selPtr = winPtr->selHandlerList; utf8selPtr != NULL; - utf8selPtr = utf8selPtr->nextPtr) { + utf8selPtr = utf8selPtr->nextPtr) { if ((utf8selPtr->selection == selection) && (utf8selPtr->target == target)) { break; @@ -310,9 +305,10 @@ Tk_DeleteSelHandler(tkwin, selection, target) && (utf8selPtr->proc == selPtr->proc) && (utf8selPtr->size == selPtr->size)) { /* - * This recursive call is OK, because we've - * changed the value of 'target' + * This recursive call is OK, because we've changed the value + * of 'target'. */ + Tk_DeleteSelHandler(tkwin, selection, target); } } @@ -340,49 +336,45 @@ Tk_DeleteSelHandler(tkwin, selection, target) * None. * * Side effects: - * From now on, requests for the selection will be directed - * to procedures associated with tkwin (they must have been - * declared with calls to Tk_CreateSelHandler). When the - * selection is lost by this window, proc will be invoked - * (see the manual entry for details). This procedure may - * invoke callbacks, including Tcl scripts, so any calling - * function should be reentrant at the point where - * Tk_OwnSelection is invoked. + * From now on, requests for the selection will be directed to functions + * associated with tkwin (they must have been declared with calls to + * Tk_CreateSelHandler). When the selection is lost by this window, proc + * will be invoked (see the manual entry for details). This function may + * invoke callbacks, including Tcl scripts, so any calling function + * should be reentrant at the point where Tk_OwnSelection is invoked. * *-------------------------------------------------------------- */ void -Tk_OwnSelection(tkwin, selection, proc, clientData) - Tk_Window tkwin; /* Window to become new selection - * owner. */ - Atom selection; /* Selection that window should own. */ - Tk_LostSelProc *proc; /* Procedure to call when selection - * is taken away from tkwin. */ - ClientData clientData; /* Arbitrary one-word argument to - * pass to proc. */ +Tk_OwnSelection( + Tk_Window tkwin, /* Window to become new selection owner. */ + Atom selection, /* Selection that window should own. */ + Tk_LostSelProc *proc, /* Function to call when selection is taken + * away from tkwin. */ + ClientData clientData) /* Arbitrary one-word argument to pass to + * proc. */ { register TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; Tk_LostSelProc *clearProc = NULL; - ClientData clearData = NULL; /* Initialization needed only to - * prevent compiler warning. */ - - + ClientData clearData = NULL;/* Initialization needed only to prevent + * compiler warning. */ + if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); } Tk_MakeWindowExist(tkwin); /* - * This code is somewhat tricky. First, we find the specified selection - * on the selection list. If the previous owner is in this process, and - * is a different window, then we need to invoke the clearProc. However, - * it's dangerous to call the clearProc right now, because it could - * invoke a Tcl script that wrecks the current state (e.g. it could - * delete the window). To be safe, defer the call until the end of the - * procedure when we no longer care about the state. + * This code is somewhat tricky. First, we find the specified selection on + * the selection list. If the previous owner is in this process, and is a + * different window, then we need to invoke the clearProc. However, it's + * dangerous to call the clearProc right now, because it could invoke a + * Tcl script that wrecks the current state (e.g. it could delete the + * window). To be safe, defer the call until the end of the function when + * we no longer care about the state. */ for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL; @@ -402,9 +394,9 @@ Tk_OwnSelection(tkwin, selection, proc, clientData) clearData = infoPtr->clearData; } else if (infoPtr->clearProc == LostSelection) { /* - * If the selection handler is one created by "selection own", - * be sure to free the record for it; otherwise there will be - * a memory leak. + * If the selection handler is one created by "selection own", be + * sure to free the record for it; otherwise there will be a + * memory leak. */ ckfree((char *) infoPtr->clearData); @@ -417,10 +409,10 @@ Tk_OwnSelection(tkwin, selection, proc, clientData) infoPtr->clearData = clientData; /* - * Note that we are using CurrentTime, even though ICCCM recommends against - * this practice (the problem is that we don't necessarily have a valid - * time to use). We will not be able to retrieve a useful timestamp for - * the TIMESTAMP target later. + * Note that we are using CurrentTime, even though ICCCM recommends + * against this practice (the problem is that we don't necessarily have a + * valid time to use). We will not be able to retrieve a useful timestamp + * for the TIMESTAMP target later. */ infoPtr->time = CurrentTime; @@ -456,18 +448,19 @@ Tk_OwnSelection(tkwin, selection, proc, clientData) * None. * * Side effects: - * The specified selection is cleared, so that future requests to retrieve - * it will fail until some application owns it again. This procedure - * invokes callbacks, possibly including Tcl scripts, so any calling - * function should be reentrant at the point Tk_ClearSelection is invoked. + * The specified selection is cleared, so that future requests to + * retrieve it will fail until some application owns it again. This + * function invokes callbacks, possibly including Tcl scripts, so any + * calling function should be reentrant at the point Tk_ClearSelection is + * invoked. * *---------------------------------------------------------------------- */ void -Tk_ClearSelection(tkwin, selection) - Tk_Window tkwin; /* Window that selects a display. */ - Atom selection; /* Selection to be cancelled. */ +Tk_ClearSelection( + Tk_Window tkwin, /* Window that selects a display. */ + Atom selection) /* Selection to be cancelled. */ { register TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; @@ -475,15 +468,15 @@ Tk_ClearSelection(tkwin, selection) TkSelectionInfo *prevPtr; TkSelectionInfo *nextPtr; Tk_LostSelProc *clearProc = NULL; - ClientData clearData = NULL; /* Initialization needed only to - * prevent compiler warning. */ + ClientData clearData = NULL;/* Initialization needed only to prevent + * compiler warning. */ if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); } for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL; - infoPtr != NULL; infoPtr = nextPtr) { + infoPtr != NULL; infoPtr = nextPtr) { nextPtr = infoPtr->nextPtr; if (infoPtr->selection == selection) { if (prevPtr == NULL) { @@ -495,7 +488,7 @@ Tk_ClearSelection(tkwin, selection) } prevPtr = infoPtr; } - + if (infoPtr != NULL) { clearProc = infoPtr->clearProc; clearData = infoPtr->clearData; @@ -513,80 +506,77 @@ Tk_ClearSelection(tkwin, selection) * * Tk_GetSelection -- * - * Retrieve the value of a selection and pass it off (in - * pieces, possibly) to a given procedure. + * Retrieve the value of a selection and pass it off (in pieces, + * possibly) to a given function. * * Results: - * The return value is a standard Tcl return value. - * If an error occurs (such as no selection exists) - * then an error message is left in the interp's result. + * The return value is a standard Tcl return value. If an error occurs + * (such as no selection exists) then an error message is left in the + * interp's result. * * Side effects: - * The standard X11 protocols are used to retrieve the - * selection. When it arrives, it is passed to proc. If - * the selection is very large, it will be passed to proc - * in several pieces. Proc should have the following + * The standard X11 protocols are used to retrieve the selection. When it + * arrives, it is passed to proc. If the selection is very large, it will + * be passed to proc in several pieces. Proc should have the following * structure: * * int - * proc(clientData, interp, portion) - * ClientData clientData; - * Tcl_Interp *interp; - * char *portion; + * proc( + * ClientData clientData, + * Tcl_Interp *interp, + * char *portion) * { * } * - * The interp and clientData arguments to proc will be the - * same as the corresponding arguments to Tk_GetSelection. - * The portion argument points to a character string - * containing part of the selection, and numBytes indicates - * the length of the portion, not including the terminating - * NULL character. If the selection arrives in several pieces, - * the "portion" arguments in separate calls will contain - * successive parts of the selection. Proc should normally - * return TCL_OK. If it detects an error then it should return - * TCL_ERROR and leave an error message in the interp's result; the - * remainder of the selection retrieval will be aborted. + * The interp and clientData arguments to proc will be the same as the + * corresponding arguments to Tk_GetSelection. The portion argument + * points to a character string containing part of the selection, and + * numBytes indicates the length of the portion, not including the + * terminating NULL character. If the selection arrives in several + * pieces, the "portion" arguments in separate calls will contain + * successive parts of the selection. Proc should normally return TCL_OK. + * If it detects an error then it should return TCL_ERROR and leave an + * error message in the interp's result; the remainder of the selection + * retrieval will be aborted. * *-------------------------------------------------------------- */ int -Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) - Tcl_Interp *interp; /* Interpreter to use for reporting - * errors. */ - Tk_Window tkwin; /* Window on whose behalf to retrieve - * the selection (determines display - * from which to retrieve). */ - Atom selection; /* Selection to retrieve. */ - Atom target; /* Desired form in which selection - * is to be returned. */ - Tk_GetSelProc *proc; /* Procedure to call to process the - * selection, once it has been retrieved. */ - ClientData clientData; /* Arbitrary value to pass to proc. */ +Tk_GetSelection( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tk_Window tkwin, /* Window on whose behalf to retrieve the + * selection (determines display from which to + * retrieve). */ + Atom selection, /* Selection to retrieve. */ + Atom target, /* Desired form in which selection is to be + * returned. */ + Tk_GetSelProc *proc, /* Function to call to process the selection, + * once it has been retrieved. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ { TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); } /* - * If the selection is owned by a window managed by this - * process, then call the retrieval procedure directly, - * rather than going through the X server (it's dangerous - * to go through the X server in this case because it could - * result in deadlock if an INCR-style selection results). + * If the selection is owned by a window managed by this process, then + * call the retrieval function directly, rather than going through the X + * server (it's dangerous to go through the X server in this case because + * it could result in deadlock if an INCR-style selection results). */ for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { - if (infoPtr->selection == selection) + if (infoPtr->selection == selection) { break; + } } if (infoPtr != NULL) { register TkSelHandler *selPtr; @@ -595,9 +585,8 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) TkSelInProgress ip; for (selPtr = ((TkWindow *) infoPtr->owner)->selHandlerList; - selPtr != NULL; selPtr = selPtr->nextPtr) { - if ((selPtr->target == target) - && (selPtr->selection == selection)) { + selPtr != NULL; selPtr = selPtr->nextPtr) { + if (selPtr->target==target && selPtr->selection==selection) { break; } } @@ -607,7 +596,7 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) count = TkSelDefaultSelection(infoPtr, target, buffer, TK_SEL_BYTES_AT_ONCE, &type); if (count > TK_SEL_BYTES_AT_ONCE) { - panic("selection handler returned too many bytes"); + Tcl_Panic("selection handler returned too many bytes"); } if (count < 0) { goto cantget; @@ -628,7 +617,7 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) goto cantget; } if (count > TK_SEL_BYTES_AT_ONCE) { - panic("selection handler returned too many bytes"); + Tcl_Panic("selection handler returned too many bytes"); } buffer[count] = '\0'; result = (*proc)(clientData, interp, buffer); @@ -650,10 +639,10 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) return TkSelGetSelection(interp, tkwin, selection, target, proc, clientData); - cantget: + cantget: Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), - " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target), - "\" not defined", (char *) NULL); + " selection doesn't exist or form \"", + Tk_GetAtomName(tkwin, target), "\" not defined", NULL); return TCL_ERROR; } @@ -662,9 +651,8 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) * * Tk_SelectionObjCmd -- * - * This procedure is invoked to process the "selection" Tcl - * command. See the user documentation for details on what - * it does. + * This function is invoked to process the "selection" Tcl command. See + * the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -676,12 +664,12 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) */ int -Tk_SelectionObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with +Tk_SelectionObjCmd( + ClientData clientData, /* Main window associated with * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; char *path = NULL; @@ -690,11 +678,12 @@ Tk_SelectionObjCmd(clientData, interp, objc, objv) int count, index; Tcl_Obj **objs; static CONST char *optionStrings[] = { - "clear", "get", "handle", "own", (char *) NULL + "clear", "get", "handle", "own", NULL }; - enum options { SELECTION_CLEAR, SELECTION_GET, SELECTION_HANDLE, - SELECTION_OWN }; - + enum options { + SELECTION_CLEAR, SELECTION_GET, SELECTION_HANDLE, SELECTION_OWN + }; + if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; @@ -706,319 +695,323 @@ Tk_SelectionObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case SELECTION_CLEAR: { - static CONST char *clearOptionStrings[] = { - "-displayof", "-selection", (char *) NULL - }; - enum clearOptions { CLEAR_DISPLAYOF, CLEAR_SELECTION }; - int clearIndex; - - for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0; - count-=2, objs+=2) { - string = Tcl_GetString(objs[0]); - if (string[0] != '-') { - break; - } - if (count < 2) { - Tcl_AppendResult(interp, "value for \"", string, - "\" missing", (char *) NULL); - return TCL_ERROR; - } - - if (Tcl_GetIndexFromObj(interp, objs[0], clearOptionStrings, - "option", 0, &clearIndex) != TCL_OK) { - return TCL_ERROR; - } - switch ((enum clearOptions) clearIndex) { - case CLEAR_DISPLAYOF: - path = Tcl_GetString(objs[1]); - break; - case CLEAR_SELECTION: - selName = Tcl_GetString(objs[1]); - break; - } + case SELECTION_CLEAR: { + static CONST char *clearOptionStrings[] = { + "-displayof", "-selection", NULL + }; + enum clearOptions { CLEAR_DISPLAYOF, CLEAR_SELECTION }; + int clearIndex; + + for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0; + count-=2, objs+=2) { + string = Tcl_GetString(objs[0]); + if (string[0] != '-') { + break; } - if (count == 1) { - path = Tcl_GetString(objs[0]); - } else if (count > 1) { - Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + if (count < 2) { + Tcl_AppendResult(interp, "value for \"", string, + "\" missing", NULL); return TCL_ERROR; } - if (path != NULL) { - tkwin = Tk_NameToWindow(interp, path, tkwin); - } - if (tkwin == NULL) { + + if (Tcl_GetIndexFromObj(interp, objs[0], clearOptionStrings, + "option", 0, &clearIndex) != TCL_OK) { return TCL_ERROR; } - if (selName != NULL) { - selection = Tk_InternAtom(tkwin, selName); - } else { - selection = XA_PRIMARY; + switch ((enum clearOptions) clearIndex) { + case CLEAR_DISPLAYOF: + path = Tcl_GetString(objs[1]); + break; + case CLEAR_SELECTION: + selName = Tcl_GetString(objs[1]); + break; } - - Tk_ClearSelection(tkwin, selection); - break; } - case SELECTION_GET: { - Atom target; - char *targetName = NULL; - Tcl_DString selBytes; - int result; - static CONST char *getOptionStrings[] = { - "-displayof", "-selection", "-type", (char *) NULL - }; - enum getOptions { GET_DISPLAYOF, GET_SELECTION, GET_TYPE }; - int getIndex; - - for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count>0; - count-=2, objs+=2) { - string = Tcl_GetString(objs[0]); - if (string[0] != '-') { - break; - } - if (count < 2) { - Tcl_AppendResult(interp, "value for \"", string, - "\" missing", (char *) NULL); - return TCL_ERROR; - } - - if (Tcl_GetIndexFromObj(interp, objs[0], getOptionStrings, - "option", 0, &getIndex) != TCL_OK) { - return TCL_ERROR; - } + if (count == 1) { + path = Tcl_GetString(objs[0]); + } else if (count > 1) { + Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + return TCL_ERROR; + } + if (path != NULL) { + tkwin = Tk_NameToWindow(interp, path, tkwin); + } + if (tkwin == NULL) { + return TCL_ERROR; + } + if (selName != NULL) { + selection = Tk_InternAtom(tkwin, selName); + } else { + selection = XA_PRIMARY; + } - switch ((enum getOptions) getIndex) { - case GET_DISPLAYOF: - path = Tcl_GetString(objs[1]); - break; - case GET_SELECTION: - selName = Tcl_GetString(objs[1]); - break; - case GET_TYPE: - targetName = Tcl_GetString(objs[1]); - break; - } - } - if (path != NULL) { - tkwin = Tk_NameToWindow(interp, path, tkwin); + Tk_ClearSelection(tkwin, selection); + break; + } + + case SELECTION_GET: { + Atom target; + char *targetName = NULL; + Tcl_DString selBytes; + int result; + static CONST char *getOptionStrings[] = { + "-displayof", "-selection", "-type", NULL + }; + enum getOptions { GET_DISPLAYOF, GET_SELECTION, GET_TYPE }; + int getIndex; + + for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count>0; + count-=2, objs+=2) { + string = Tcl_GetString(objs[0]); + if (string[0] != '-') { + break; } - if (tkwin == NULL) { + if (count < 2) { + Tcl_AppendResult(interp, "value for \"", string, + "\" missing", NULL); return TCL_ERROR; } - if (selName != NULL) { - selection = Tk_InternAtom(tkwin, selName); - } else { - selection = XA_PRIMARY; - } - if (count > 1) { - Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + + if (Tcl_GetIndexFromObj(interp, objs[0], getOptionStrings, + "option", 0, &getIndex) != TCL_OK) { return TCL_ERROR; - } else if (count == 1) { - target = Tk_InternAtom(tkwin, Tcl_GetString(objs[0])); - } else if (targetName != NULL) { - target = Tk_InternAtom(tkwin, targetName); - } else { - target = XA_STRING; } - Tcl_DStringInit(&selBytes); - result = Tk_GetSelection(interp, tkwin, selection, target, - SelGetProc, (ClientData) &selBytes); - if (result == TCL_OK) { - Tcl_DStringResult(interp, &selBytes); - } else { - Tcl_DStringFree(&selBytes); + switch ((enum getOptions) getIndex) { + case GET_DISPLAYOF: + path = Tcl_GetString(objs[1]); + break; + case GET_SELECTION: + selName = Tcl_GetString(objs[1]); + break; + case GET_TYPE: + targetName = Tcl_GetString(objs[1]); + break; } - return result; } - case SELECTION_HANDLE: { - Atom target, format; - char *targetName = NULL; - char *formatName = NULL; - register CommandInfo *cmdInfoPtr; - int cmdLength; - static CONST char *handleOptionStrings[] = { - "-format", "-selection", "-type", (char *) NULL - }; - enum handleOptions { HANDLE_FORMAT, HANDLE_SELECTION, - HANDLE_TYPE }; - int handleIndex; - - for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0; - count-=2, objs+=2) { - string = Tcl_GetString(objs[0]); - if (string[0] != '-') { - break; - } - if (count < 2) { - Tcl_AppendResult(interp, "value for \"", string, - "\" missing", (char *) NULL); - return TCL_ERROR; - } + if (path != NULL) { + tkwin = Tk_NameToWindow(interp, path, tkwin); + } + if (tkwin == NULL) { + return TCL_ERROR; + } + if (selName != NULL) { + selection = Tk_InternAtom(tkwin, selName); + } else { + selection = XA_PRIMARY; + } + if (count > 1) { + Tcl_WrongNumArgs(interp, 2, objv, "?options?"); + return TCL_ERROR; + } else if (count == 1) { + target = Tk_InternAtom(tkwin, Tcl_GetString(objs[0])); + } else if (targetName != NULL) { + target = Tk_InternAtom(tkwin, targetName); + } else { + target = XA_STRING; + } - if (Tcl_GetIndexFromObj(interp, objs[0],handleOptionStrings, - "option", 0, &handleIndex) != TCL_OK) { - return TCL_ERROR; - } + Tcl_DStringInit(&selBytes); + result = Tk_GetSelection(interp, tkwin, selection, target, + SelGetProc, (ClientData) &selBytes); + if (result == TCL_OK) { + Tcl_DStringResult(interp, &selBytes); + } else { + Tcl_DStringFree(&selBytes); + } + return result; + } - switch ((enum handleOptions) handleIndex) { - case HANDLE_FORMAT: - formatName = Tcl_GetString(objs[1]); - break; - case HANDLE_SELECTION: - selName = Tcl_GetString(objs[1]); - break; - case HANDLE_TYPE: - targetName = Tcl_GetString(objs[1]); - break; - } + case SELECTION_HANDLE: { + Atom target, format; + char *targetName = NULL; + char *formatName = NULL; + register CommandInfo *cmdInfoPtr; + int cmdLength; + static CONST char *handleOptionStrings[] = { + "-format", "-selection", "-type", NULL + }; + enum handleOptions { + HANDLE_FORMAT, HANDLE_SELECTION, HANDLE_TYPE + }; + int handleIndex; + + for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0; + count-=2, objs+=2) { + string = Tcl_GetString(objs[0]); + if (string[0] != '-') { + break; } - - if ((count < 2) || (count > 4)) { - Tcl_WrongNumArgs(interp, 2, objv, "?options? window command"); + if (count < 2) { + Tcl_AppendResult(interp, "value for \"", string, + "\" missing", NULL); return TCL_ERROR; } - tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin); - if (tkwin == NULL) { + + if (Tcl_GetIndexFromObj(interp, objs[0],handleOptionStrings, + "option", 0, &handleIndex) != TCL_OK) { return TCL_ERROR; } - if (selName != NULL) { - selection = Tk_InternAtom(tkwin, selName); - } else { - selection = XA_PRIMARY; - } - - if (count > 2) { - target = Tk_InternAtom(tkwin, Tcl_GetString(objs[2])); - } else if (targetName != NULL) { - target = Tk_InternAtom(tkwin, targetName); - } else { - target = XA_STRING; - } - if (count > 3) { - format = Tk_InternAtom(tkwin, Tcl_GetString(objs[3])); - } else if (formatName != NULL) { - format = Tk_InternAtom(tkwin, formatName); - } else { - format = XA_STRING; - } - string = Tcl_GetStringFromObj(objs[1], &cmdLength); - if (cmdLength == 0) { - Tk_DeleteSelHandler(tkwin, selection, target); - } else { - cmdInfoPtr = (CommandInfo *) ckalloc((unsigned) ( - sizeof(CommandInfo) - 3 + cmdLength)); - cmdInfoPtr->interp = interp; - cmdInfoPtr->charOffset = 0; - cmdInfoPtr->byteOffset = 0; - cmdInfoPtr->buffer[0] = '\0'; - cmdInfoPtr->cmdLength = cmdLength; - memcpy(cmdInfoPtr->command, string, cmdLength + 1); - Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand, - (ClientData) cmdInfoPtr, format); + + switch ((enum handleOptions) handleIndex) { + case HANDLE_FORMAT: + formatName = Tcl_GetString(objs[1]); + break; + case HANDLE_SELECTION: + selName = Tcl_GetString(objs[1]); + break; + case HANDLE_TYPE: + targetName = Tcl_GetString(objs[1]); + break; } - return TCL_OK; } - - case SELECTION_OWN: { - register LostCommand *lostPtr; - char *script = NULL; - int cmdLength; - static CONST char *ownOptionStrings[] = { - "-command", "-displayof", "-selection", (char *) NULL - }; - enum ownOptions { OWN_COMMAND, OWN_DISPLAYOF, OWN_SELECTION }; - int ownIndex; - - for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0; - count-=2, objs+=2) { - string = Tcl_GetString(objs[0]); - if (string[0] != '-') { - break; - } - if (count < 2) { - Tcl_AppendResult(interp, "value for \"", string, - "\" missing", (char *) NULL); - return TCL_ERROR; - } - if (Tcl_GetIndexFromObj(interp, objs[0], ownOptionStrings, - "option", 0, &ownIndex) != TCL_OK) { - return TCL_ERROR; - } + if ((count < 2) || (count > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "?options? window command"); + return TCL_ERROR; + } + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + if (selName != NULL) { + selection = Tk_InternAtom(tkwin, selName); + } else { + selection = XA_PRIMARY; + } - switch ((enum ownOptions) ownIndex) { - case OWN_COMMAND: - script = Tcl_GetString(objs[1]); - break; - case OWN_DISPLAYOF: - path = Tcl_GetString(objs[1]); - break; - case OWN_SELECTION: - selName = Tcl_GetString(objs[1]); - break; - } + if (count > 2) { + target = Tk_InternAtom(tkwin, Tcl_GetString(objs[2])); + } else if (targetName != NULL) { + target = Tk_InternAtom(tkwin, targetName); + } else { + target = XA_STRING; + } + if (count > 3) { + format = Tk_InternAtom(tkwin, Tcl_GetString(objs[3])); + } else if (formatName != NULL) { + format = Tk_InternAtom(tkwin, formatName); + } else { + format = XA_STRING; + } + string = Tcl_GetStringFromObj(objs[1], &cmdLength); + if (cmdLength == 0) { + Tk_DeleteSelHandler(tkwin, selection, target); + } else { + cmdInfoPtr = (CommandInfo *) ckalloc((unsigned) ( + sizeof(CommandInfo) - 3 + cmdLength)); + cmdInfoPtr->interp = interp; + cmdInfoPtr->charOffset = 0; + cmdInfoPtr->byteOffset = 0; + cmdInfoPtr->buffer[0] = '\0'; + cmdInfoPtr->cmdLength = cmdLength; + memcpy(cmdInfoPtr->command, string, cmdLength + 1); + Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand, + (ClientData) cmdInfoPtr, format); + } + return TCL_OK; + } + + case SELECTION_OWN: { + register LostCommand *lostPtr; + char *script = NULL; + int cmdLength; + static CONST char *ownOptionStrings[] = { + "-command", "-displayof", "-selection", NULL + }; + enum ownOptions { OWN_COMMAND, OWN_DISPLAYOF, OWN_SELECTION }; + int ownIndex; + + for (count = objc-2, objs = ((Tcl_Obj **)objv)+2; count > 0; + count-=2, objs+=2) { + string = Tcl_GetString(objs[0]); + if (string[0] != '-') { + break; } - - if (count > 2) { - Tcl_WrongNumArgs(interp, 2, objv, "?options? ?window?"); + if (count < 2) { + Tcl_AppendResult(interp, "value for \"", string, + "\" missing", NULL); return TCL_ERROR; } - if (selName != NULL) { - selection = Tk_InternAtom(tkwin, selName); - } else { - selection = XA_PRIMARY; + + if (Tcl_GetIndexFromObj(interp, objs[0], ownOptionStrings, + "option", 0, &ownIndex) != TCL_OK) { + return TCL_ERROR; } - if (count == 0) { - TkSelectionInfo *infoPtr; - TkWindow *winPtr; - if (path != NULL) { - tkwin = Tk_NameToWindow(interp, path, tkwin); - } - if (tkwin == NULL) { - return TCL_ERROR; - } - winPtr = (TkWindow *)tkwin; - for (infoPtr = winPtr->dispPtr->selectionInfoPtr; - infoPtr != NULL; infoPtr = infoPtr->nextPtr) { - if (infoPtr->selection == selection) - break; - } - - /* - * Ignore the internal clipboard window. - */ - - if ((infoPtr != NULL) - && (infoPtr->owner != winPtr->dispPtr->clipWindow)) { - Tcl_SetResult(interp, Tk_PathName(infoPtr->owner), - TCL_STATIC); - } - return TCL_OK; + + switch ((enum ownOptions) ownIndex) { + case OWN_COMMAND: + script = Tcl_GetString(objs[1]); + break; + case OWN_DISPLAYOF: + path = Tcl_GetString(objs[1]); + break; + case OWN_SELECTION: + selName = Tcl_GetString(objs[1]); + break; + } + } + + if (count > 2) { + Tcl_WrongNumArgs(interp, 2, objv, "?options? ?window?"); + return TCL_ERROR; + } + if (selName != NULL) { + selection = Tk_InternAtom(tkwin, selName); + } else { + selection = XA_PRIMARY; + } + + if (count == 0) { + TkSelectionInfo *infoPtr; + TkWindow *winPtr; + + if (path != NULL) { + tkwin = Tk_NameToWindow(interp, path, tkwin); } - tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin); if (tkwin == NULL) { return TCL_ERROR; } - if (count == 2) { - script = Tcl_GetString(objs[1]); + winPtr = (TkWindow *)tkwin; + for (infoPtr = winPtr->dispPtr->selectionInfoPtr; + infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + if (infoPtr->selection == selection) { + break; + } } - if (script == NULL) { - Tk_OwnSelection(tkwin, selection, (Tk_LostSelProc *) NULL, - (ClientData) NULL); - return TCL_OK; + + /* + * Ignore the internal clipboard window. + */ + + if ((infoPtr != NULL) + && (infoPtr->owner != winPtr->dispPtr->clipWindow)) { + Tcl_SetResult(interp, Tk_PathName(infoPtr->owner), TCL_STATIC); } - cmdLength = strlen(script); - lostPtr = (LostCommand *) ckalloc((unsigned) (sizeof(LostCommand) - -3 + cmdLength)); - lostPtr->interp = interp; - memcpy(lostPtr->command, script, cmdLength + 1); - Tk_OwnSelection(tkwin, selection, LostSelection, - (ClientData) lostPtr); return TCL_OK; } + + tkwin = Tk_NameToWindow(interp, Tcl_GetString(objs[0]), tkwin); + if (tkwin == NULL) { + return TCL_ERROR; + } + if (count == 2) { + script = Tcl_GetString(objs[1]); + } + if (script == NULL) { + Tk_OwnSelection(tkwin, selection, NULL, (ClientData) NULL); + return TCL_OK; + } + cmdLength = strlen(script); + lostPtr = (LostCommand *) ckalloc((unsigned) (sizeof(LostCommand) + -3 + cmdLength)); + lostPtr->interp = interp; + strcpy(lostPtr->command, script); + Tk_OwnSelection(tkwin, selection, LostSelection, (ClientData) lostPtr); + return TCL_OK; + } } return TCL_OK; } @@ -1028,12 +1021,12 @@ Tk_SelectionObjCmd(clientData, interp, objc, objv) * * TkSelGetInProgress -- * - * This procedure returns a pointer to the thread-local - * list of pending searches. + * This function returns a pointer to the thread-local list of pending + * searches. * * Results: - * The return value is a pointer to the first search in progress, - * or NULL if there are none. + * The return value is a pointer to the first search in progress, or NULL + * if there are none. * * Side effects: * None. @@ -1042,10 +1035,10 @@ Tk_SelectionObjCmd(clientData, interp, objc, objv) */ TkSelInProgress * -TkSelGetInProgress _ANSI_ARGS_((void)) +TkSelGetInProgress(void) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); return tsdPtr->pendingPtr; } @@ -1055,9 +1048,9 @@ TkSelGetInProgress _ANSI_ARGS_((void)) * * TkSelSetInProgress -- * - * This procedure is used to set the thread-local list of pending - * searches. It is required because the pending list is kept - * in thread local storage. + * This function is used to set the thread-local list of pending + * searches. It is required because the pending list is kept in thread + * local storage. * * Results: * None. @@ -1068,13 +1061,13 @@ TkSelGetInProgress _ANSI_ARGS_((void)) *---------------------------------------------------------------------- */ void -TkSelSetInProgress(pendingPtr) - TkSelInProgress *pendingPtr; +TkSelSetInProgress( + TkSelInProgress *pendingPtr) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - tsdPtr->pendingPtr = pendingPtr; + tsdPtr->pendingPtr = pendingPtr; } /* @@ -1082,8 +1075,8 @@ TkSelSetInProgress(pendingPtr) * * TkSelDeadWindow -- * - * This procedure is invoked just before a TkWindow is deleted. - * It performs selection-related cleanup. + * This function is invoked just before a TkWindow is deleted. It + * performs selection-related cleanup. * * Results: * None. @@ -1095,14 +1088,14 @@ TkSelSetInProgress(pendingPtr) */ void -TkSelDeadWindow(winPtr) - register TkWindow *winPtr; /* Window that's being deleted. */ +TkSelDeadWindow( + register TkWindow *winPtr) /* Window that's being deleted. */ { register TkSelHandler *selPtr; register TkSelInProgress *ipPtr; TkSelectionInfo *infoPtr, *prevPtr, *nextPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * While deleting all the handlers, be careful to check whether @@ -1113,8 +1106,8 @@ TkSelDeadWindow(winPtr) while (winPtr->selHandlerList != NULL) { selPtr = winPtr->selHandlerList; winPtr->selHandlerList = selPtr->nextPtr; - for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; - ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; + ipPtr = ipPtr->nextPtr) { if (ipPtr->selPtr == selPtr) { ipPtr->selPtr = NULL; } @@ -1135,7 +1128,7 @@ TkSelDeadWindow(winPtr) */ for (infoPtr = winPtr->dispPtr->selectionInfoPtr, prevPtr = NULL; - infoPtr != NULL; infoPtr = nextPtr) { + infoPtr != NULL; infoPtr = nextPtr) { nextPtr = infoPtr->nextPtr; if (infoPtr->owner == (Tk_Window) winPtr) { if (infoPtr->clearProc == LostSelection) { @@ -1170,9 +1163,9 @@ TkSelDeadWindow(winPtr) */ void -TkSelInit(tkwin) - Tk_Window tkwin; /* Window token (used to find - * display to initialize). */ +TkSelInit( + Tk_Window tkwin) /* Window token (used to find display to + * initialize). */ { register TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; @@ -1191,17 +1184,16 @@ TkSelInit(tkwin) dispPtr->clipboardAtom = Tk_InternAtom(tkwin, "CLIPBOARD"); /* - * Using UTF8_STRING instead of the XA_UTF8_STRING macro allows us - * to support older X servers that didn't have UTF8_STRING yet. - * This is necessary on Unix systems. - * For more information, see: - * http://www.cl.cam.ac.uk/~mgk25/unicode.html#x11 + * Using UTF8_STRING instead of the XA_UTF8_STRING macro allows us to + * support older X servers that didn't have UTF8_STRING yet. This is + * necessary on Unix systems. For more information, see: + * http://www.cl.cam.ac.uk/~mgk25/unicode.html#x11 */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) dispPtr->utf8Atom = Tk_InternAtom(tkwin, "UTF8_STRING"); #else - dispPtr->utf8Atom = (Atom) NULL; + dispPtr->utf8Atom = (Atom) 0; #endif } @@ -1210,22 +1202,22 @@ TkSelInit(tkwin) * * TkSelClearSelection -- * - * This procedure is invoked to process a SelectionClear event. + * This function is invoked to process a SelectionClear event. * * Results: * None. * * Side effects: - * Invokes the clear procedure for the window which lost the + * Invokes the clear function for the window which lost the * selection. * *---------------------------------------------------------------------- */ void -TkSelClearSelection(tkwin, eventPtr) - Tk_Window tkwin; /* Window for which event was targeted. */ - register XEvent *eventPtr; /* X SelectionClear event. */ +TkSelClearSelection( + Tk_Window tkwin, /* Window for which event was targeted. */ + register XEvent *eventPtr) /* X SelectionClear event. */ { register TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; @@ -1233,24 +1225,24 @@ TkSelClearSelection(tkwin, eventPtr) TkSelectionInfo *prevPtr; /* - * Invoke clear procedure for window that just lost the selection. This + * Invoke clear function for window that just lost the selection. This * code is a bit tricky, because any callbacks due to selection changes - * between windows managed by the process have already been made. Thus, + * between windows managed by the process have already been made. Thus, * ignore the event unless it refers to the window that's currently the * selection owner and the event was generated after the server saw the * SetSelectionOwner request. */ for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL; - infoPtr != NULL; infoPtr = infoPtr->nextPtr) { + infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->selection == eventPtr->xselectionclear.selection) { break; } prevPtr = infoPtr; } - if (infoPtr != NULL && (infoPtr->owner == tkwin) - && (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) { + if (infoPtr != NULL && (infoPtr->owner == tkwin) && + (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) { if (prevPtr == NULL) { dispPtr->selectionInfoPtr = infoPtr->nextPtr; } else { @@ -1259,9 +1251,9 @@ TkSelClearSelection(tkwin, eventPtr) /* * Because of reentrancy problems, calling clearProc must be done - * after the infoPtr has been removed from the selectionInfoPtr - * list (clearProc could modify the list, e.g. by creating - * a new selection). + * after the infoPtr has been removed from the selectionInfoPtr list + * (clearProc could modify the list, e.g. by creating a new + * selection). */ if (infoPtr->clearProc != NULL) { @@ -1276,27 +1268,27 @@ TkSelClearSelection(tkwin, eventPtr) * * SelGetProc -- * - * This procedure is invoked to process pieces of the selection - * as they arrive during "selection get" commands. + * This function is invoked to process pieces of the selection as they + * arrive during "selection get" commands. * * Results: * Always returns TCL_OK. * * Side effects: - * Bytes get appended to the dynamic string pointed to by the - * clientData argument. + * Bytes get appended to the dynamic string pointed to by the clientData + * argument. * *-------------------------------------------------------------- */ /* ARGSUSED */ static int -SelGetProc(clientData, interp, portion) - ClientData clientData; /* Dynamic string holding partially - * assembled selection. */ - Tcl_Interp *interp; /* Interpreter used for error - * reporting (not used). */ - char *portion; /* New information to be appended. */ +SelGetProc( + ClientData clientData, /* Dynamic string holding partially assembled + * selection. */ + Tcl_Interp *interp, /* Interpreter used for error reporting (not + * used). */ + char *portion) /* New information to be appended. */ { Tcl_DStringAppend((Tcl_DString *) clientData, portion, -1); return TCL_OK; @@ -1307,14 +1299,14 @@ SelGetProc(clientData, interp, portion) * * HandleTclCommand -- * - * This procedure acts as selection handler for handlers created - * by the "selection handle" command. It invokes a Tcl command to - * retrieve the selection. + * This function acts as selection handler for handlers created by the + * "selection handle" command. It invokes a Tcl command to retrieve the + * selection. * * Results: - * The return value is a count of the number of bytes actually - * stored at buffer, or -1 if an error occurs while executing - * the Tcl command to retrieve the selection. + * The return value is a count of the number of bytes actually stored at + * buffer, or -1 if an error occurs while executing the Tcl command to + * retrieve the selection. * * Side effects: * None except for things done by the Tcl command. @@ -1323,12 +1315,12 @@ SelGetProc(clientData, interp, portion) */ static int -HandleTclCommand(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Information about command to execute. */ - int offset; /* Return selection bytes starting at this +HandleTclCommand( + ClientData clientData, /* Information about command to execute. */ + int offset, /* Return selection bytes starting at this * offset. */ - char *buffer; /* Place to store converted selection. */ - int maxBytes; /* Maximum # of bytes to store at buffer. */ + char *buffer, /* Place to store converted selection. */ + int maxBytes) /* Maximum # of bytes to store at buffer. */ { CommandInfo *cmdInfoPtr = (CommandInfo *) clientData; int spaceNeeded, length; @@ -1342,16 +1334,16 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) CONST char *p; /* - * We must also protect the interpreter and the command from being - * deleted too soon. + * We must also protect the interpreter and the command from being deleted + * too soon. */ Tcl_Preserve(clientData); Tcl_Preserve((ClientData) interp); /* - * Compute the proper byte offset in the case where the last chunk - * split a character. + * Compute the proper byte offset in the case where the last chunk split a + * character. */ if (offset == cmdInfoPtr->byteOffset) { @@ -1370,8 +1362,8 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) } /* - * First, generate a command by taking the command string - * and appending the offset and maximum # of bytes. + * First, generate a command by taking the command string and appending + * the offset and maximum # of bytes. */ spaceNeeded = cmdInfoPtr->cmdLength + 30; @@ -1383,8 +1375,8 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) sprintf(command, "%s %d %d", cmdInfoPtr->command, charOffset, maxBytes); /* - * Execute the command. Be sure to restore the state of the - * interpreter after executing the command. + * Execute the command. Be sure to restore the state of the interpreter + * after executing the command. */ Tcl_DStringInit(&oldResult); @@ -1393,12 +1385,12 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) objPtr = Tcl_GetObjResult(interp); string = Tcl_GetStringFromObj(objPtr, &length); count = (length > maxBytes) ? maxBytes : length; - memcpy((VOID *) buffer, (VOID *) string, (size_t) count); + memcpy(buffer, string, (size_t) count); buffer[count] = '\0'; /* - * Update the partial character information for the next - * retrieval if the command has not been deleted. + * Update the partial character information for the next retrieval if + * the command has not been deleted. */ if (cmdInfoPtr->interp != NULL) { @@ -1419,7 +1411,7 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) strncpy(cmdInfoPtr->buffer, string, (size_t) length); } cmdInfoPtr->buffer[length] = '\0'; - } + } cmdInfoPtr->byteOffset += count + extraBytes; } count += extraBytes; @@ -1432,7 +1424,6 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) ckfree(command); } - Tcl_Release(clientData); Tcl_Release((ClientData) interp); return count; @@ -1443,20 +1434,18 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) * * TkSelDefaultSelection -- * - * This procedure is called to generate selection information - * for a few standard targets such as TIMESTAMP and TARGETS. - * It is invoked only if no handler has been declared by the - * application. + * This function is called to generate selection information for a few + * standard targets such as TIMESTAMP and TARGETS. It is invoked only if + * no handler has been declared by the application. * * Results: - * If "target" is a standard target understood by this procedure, - * the selection is converted to that form and stored as a - * character string in buffer. The type of the selection (e.g. - * STRING or ATOM) is stored in *typePtr, and the return value is - * a count of the # of non-NULL bytes at buffer. If the target - * wasn't understood, or if there isn't enough space at buffer - * to hold the entire selection (no INCR-mode transfers for this - * stuff!), then -1 is returned. + * If "target" is a standard target understood by this function, the + * selection is converted to that form and stored as a character string + * in buffer. The type of the selection (e.g. STRING or ATOM) is stored + * in *typePtr, and the return value is a count of the # of non-NULL + * bytes at buffer. If the target wasn't understood, or if there isn't + * enough space at buffer to hold the entire selection (no INCR-mode + * transfers for this stuff!), then -1 is returned. * * Side effects: * None. @@ -1465,13 +1454,13 @@ HandleTclCommand(clientData, offset, buffer, maxBytes) */ int -TkSelDefaultSelection(infoPtr, target, buffer, maxBytes, typePtr) - TkSelectionInfo *infoPtr; /* Info about selection being retrieved. */ - Atom target; /* Desired form of selection. */ - char *buffer; /* Place to put selection characters. */ - int maxBytes; /* Maximum # of bytes to store at buffer. */ - Atom *typePtr; /* Store here the type of the selection, - * for use in converting to proper X format. */ +TkSelDefaultSelection( + TkSelectionInfo *infoPtr, /* Info about selection being retrieved. */ + Atom target, /* Desired form of selection. */ + char *buffer, /* Place to put selection characters. */ + int maxBytes, /* Maximum # of bytes to store at buffer. */ + Atom *typePtr) /* Store here the type of the selection, for + * use in converting to proper X format. */ { register TkWindow *winPtr = (TkWindow *) infoPtr->owner; TkDisplay *dispPtr = winPtr->dispPtr; @@ -1551,22 +1540,22 @@ TkSelDefaultSelection(infoPtr, target, buffer, maxBytes, typePtr) * * LostSelection -- * - * This procedure is invoked when a window has lost ownership of - * the selection and the ownership was claimed with the command - * "selection own". + * This function is invoked when a window has lost ownership of the + * selection and the ownership was claimed with the command "selection + * own". * * Results: * None. * * Side effects: - * A Tcl script is executed; it can do almost anything. + * A Tcl script is executed; it can do almost anything. * *---------------------------------------------------------------------- */ static void -LostSelection(clientData) - ClientData clientData; /* Pointer to LostCommand structure. */ +LostSelection( + ClientData clientData) /* Pointer to LostCommand structure. */ { LostCommand *lostPtr = (LostCommand *) clientData; Tcl_Obj *objPtr; @@ -1574,10 +1563,10 @@ LostSelection(clientData) interp = lostPtr->interp; Tcl_Preserve((ClientData) interp); - + /* - * Execute the command. Save the interpreter's result, if any, and - * restore it after executing the command. + * Execute the command. Save the interpreter's result, if any, and restore + * it after executing the command. */ objPtr = Tcl_GetObjResult(interp); @@ -1592,10 +1581,18 @@ LostSelection(clientData) Tcl_DecrRefCount(objPtr); Tcl_Release((ClientData) interp); - + /* * Free the storage for the command, since we're done with it now. */ ckfree((char *) lostPtr); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkSelect.h b/generic/tkSelect.h index 4d1c9d0..b9d7d2d 100644 --- a/generic/tkSelect.h +++ b/generic/tkSelect.h @@ -1,13 +1,13 @@ /* * tkSelect.h -- * - * Declarations of types shared among the files that implement - * selection support. + * Declarations of types shared among the files that implement selection + * support. * * Copyright (c) 1995 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKSELECT @@ -16,142 +16,134 @@ /* * When a selection is owned by a window on a given display, one of the * following structures is present on a list of current selections in the - * display structure. The structure is used to record the current owner of - * a selection for use in later retrieval requests. There is a list of - * such structures because a display can have multiple different selections - * active at the same time. + * display structure. The structure is used to record the current owner of a + * selection for use in later retrieval requests. There is a list of such + * structures because a display can have multiple different selections active + * at the same time. */ typedef struct TkSelectionInfo { Atom selection; /* Selection name, e.g. XA_PRIMARY. */ Tk_Window owner; /* Current owner of this selection. */ int serial; /* Serial number of last XSelectionSetOwner - * request made to server for this - * selection (used to filter out redundant + * request made to server for this selection + * (used to filter out redundant * SelectionClear events). */ Time time; /* Timestamp used to acquire selection. */ Tk_LostSelProc *clearProc; /* Procedure to call when owner loses * selection. */ ClientData clearData; /* Info to pass to clearProc. */ struct TkSelectionInfo *nextPtr; - /* Next in list of current selections on - * this display. NULL means end of list */ + /* Next in list of current selections on this + * display. NULL means end of list. */ } TkSelectionInfo; /* - * One of the following structures exists for each selection handler - * created for a window by calling Tk_CreateSelHandler. The handlers - * are linked in a list rooted in the TkWindow structure. + * One of the following structures exists for each selection handler created + * for a window by calling Tk_CreateSelHandler. The handlers are linked in a + * list rooted in the TkWindow structure. */ typedef struct TkSelHandler { - Atom selection; /* Selection name, e.g. XA_PRIMARY */ - Atom target; /* Target type for selection - * conversion, such as TARGETS or - * STRING. */ - Atom format; /* Format in which selection - * info will be returned, such - * as STRING or ATOM. */ - Tk_SelectionProc *proc; /* Procedure to generate selection - * in this format. */ + Atom selection; /* Selection name, e.g. XA_PRIMARY. */ + Atom target; /* Target type for selection conversion, such + * as TARGETS or STRING. */ + Atom format; /* Format in which selection info will be + * returned, such as STRING or ATOM. */ + Tk_SelectionProc *proc; /* Procedure to generate selection in this + * format. */ ClientData clientData; /* Argument to pass to proc. */ - int size; /* Size of units returned by proc - * (8 for STRING, 32 for almost - * anything else). */ + int size; /* Size of units returned by proc (8 for + * STRING, 32 for almost anything else). */ struct TkSelHandler *nextPtr; - /* Next selection handler associated - * with same window (NULL for end of - * list). */ + /* Next selection handler associated with same + * window (NULL for end of list). */ } TkSelHandler; /* - * When the selection is being retrieved, one of the following - * structures is present on a list of pending selection retrievals. - * The structure is used to communicate between the background - * procedure that requests the selection and the foreground - * event handler that processes the events in which the selection - * is returned. There is a list of such structures so that there - * can be multiple simultaneous selection retrievals (e.g. on - * different displays). + * When the selection is being retrieved, one of the following structures is + * present on a list of pending selection retrievals. The structure is used to + * communicate between the background procedure that requests the selection + * and the foreground event handler that processes the events in which the + * selection is returned. There is a list of such structures so that there can + * be multiple simultaneous selection retrievals (e.g. on different displays). */ typedef struct TkSelRetrievalInfo { Tcl_Interp *interp; /* Interpreter for error reporting. */ - TkWindow *winPtr; /* Window used as requestor for - * selection. */ + TkWindow *winPtr; /* Window used as requestor for selection. */ Atom selection; /* Selection being requested. */ Atom property; /* Property where selection will appear. */ Atom target; /* Desired form for selection. */ int (*proc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, - char *portion)); /* Procedure to call to handle pieces - * of selection. */ + char *portion)); /* Procedure to call to handle pieces of + * selection. */ ClientData clientData; /* Argument for proc. */ - int result; /* Initially -1. Set to a Tcl - * return value once the selection - * has been retrieved. */ + int result; /* Initially -1. Set to a Tcl return value + * once the selection has been retrieved. */ Tcl_TimerToken timeout; /* Token for current timeout procedure. */ - int idleTime; /* Number of seconds that have gone by - * without hearing anything from the - * selection owner. */ + int idleTime; /* Number of seconds that have gone by without + * hearing anything from the selection + * owner. */ Tcl_EncodingState encState; /* Holds intermediate state during translations * of data that cross buffer boundaries. */ int encFlags; /* Encoding translation state flags. */ Tcl_DString buf; /* Buffer to hold translation data. */ struct TkSelRetrievalInfo *nextPtr; - /* Next in list of all pending - * selection retrievals. NULL means - * end of list. */ + /* Next in list of all pending selection + * retrievals. NULL means end of list. */ } TkSelRetrievalInfo; /* - * The clipboard contains a list of buffers of various types and formats. - * All of the buffers of a given type will be returned in sequence when the - * CLIPBOARD selection is retrieved. All buffers of a given type on the - * same clipboard must have the same format. The TkClipboardTarget structure - * is used to record the information about a chain of buffers of the same - * type. + * The clipboard contains a list of buffers of various types and formats. All + * of the buffers of a given type will be returned in sequence when the + * CLIPBOARD selection is retrieved. All buffers of a given type on the same + * clipboard must have the same format. The TkClipboardTarget structure is + * used to record the information about a chain of buffers of the same type. */ typedef struct TkClipboardBuffer { - char *buffer; /* Null terminated data buffer. */ - long length; /* Length of string in buffer. */ - struct TkClipboardBuffer *nextPtr; /* Next in list of buffers. NULL - * means end of list . */ + char *buffer; /* Null terminated data buffer. */ + long length; /* Length of string in buffer. */ + struct TkClipboardBuffer *nextPtr; + /* Next in list of buffers. NULL means end of + * list . */ } TkClipboardBuffer; typedef struct TkClipboardTarget { - Atom type; /* Type conversion supported. */ - Atom format; /* Representation used for data. */ - TkClipboardBuffer *firstBufferPtr; /* First in list of data buffers. */ - TkClipboardBuffer *lastBufferPtr; /* Last in list of clipboard buffers. - * Used to speed up appends. */ - struct TkClipboardTarget *nextPtr; /* Next in list of targets on - * clipboard. NULL means end of - * list. */ + Atom type; /* Type conversion supported. */ + Atom format; /* Representation used for data. */ + TkClipboardBuffer *firstBufferPtr; + /* First in list of data buffers. */ + TkClipboardBuffer *lastBufferPtr; + /* Last in list of clipboard buffers. Used to + * speed up appends. */ + struct TkClipboardTarget *nextPtr; + /* Next in list of targets on clipboard. NULL + * means end of list. */ } TkClipboardTarget; /* * It is possible for a Tk_SelectionProc to delete the handler that it - * represents. If this happens, the code that is retrieving the selection - * needs to know about it so it doesn't use the now-defunct handler - * structure. One structure of the following form is created for each - * retrieval in progress, so that the retriever can find out if its - * handler is deleted. All of the pending retrievals (if there are more - * than one) are linked into a list. + * represents. If this happens, the code that is retrieving the selection + * needs to know about it so it doesn't use the now-defunct handler structure. + * One structure of the following form is created for each retrieval in + * progress, so that the retriever can find out if its handler is deleted. All + * of the pending retrievals (if there are more than one) are linked into a + * list. */ typedef struct TkSelInProgress { - TkSelHandler *selPtr; /* Handler being executed. If this handler - * is deleted, the field is set to NULL. */ + TkSelHandler *selPtr; /* Handler being executed. If this handler is + * deleted, the field is set to NULL. */ struct TkSelInProgress *nextPtr; /* Next higher nested search. */ } TkSelInProgress; /* - * Chunk size for retrieving selection. It's defined both in - * words and in bytes; the word size is used to allocate - * buffer space that's guaranteed to be word-aligned and that - * has an extra character for the terminating NULL. + * Chunk size for retrieving selection. It's defined both in words and in + * bytes; the word size is used to allocate buffer space that's guaranteed to + * be word-aligned and that has an extra character for the terminating NULL. */ #define TK_SEL_BYTES_AT_ONCE 4000 @@ -162,22 +154,18 @@ typedef struct TkSelInProgress { * but shouldn't be used anywhere else in Tk (or by Tk clients): */ -extern TkSelInProgress * - TkSelGetInProgress _ANSI_ARGS_((void)); -extern void TkSelSetInProgress _ANSI_ARGS_(( - TkSelInProgress *pendingPtr)); - -extern void TkSelClearSelection _ANSI_ARGS_((Tk_Window tkwin, - XEvent *eventPtr)); -extern int TkSelDefaultSelection _ANSI_ARGS_(( - TkSelectionInfo *infoPtr, Atom target, - char *buffer, int maxBytes, Atom *typePtr)); -extern int TkSelGetSelection _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, Atom selection, Atom target, - Tk_GetSelProc *proc, ClientData clientData)); +MODULE_SCOPE TkSelInProgress *TkSelGetInProgress(void); +MODULE_SCOPE void TkSelSetInProgress(TkSelInProgress *pendingPtr); +MODULE_SCOPE void TkSelClearSelection(Tk_Window tkwin, XEvent *eventPtr); +MODULE_SCOPE int TkSelDefaultSelection(TkSelectionInfo *infoPtr, + Atom target, char *buffer, int maxBytes, + Atom *typePtr); +MODULE_SCOPE int TkSelGetSelection(Tcl_Interp *interp, Tk_Window tkwin, + Atom selection, Atom target, Tk_GetSelProc *proc, + ClientData clientData); #ifndef TkSelUpdateClipboard -extern void TkSelUpdateClipboard _ANSI_ARGS_((TkWindow *winPtr, - TkClipboardTarget *targetPtr)); +MODULE_SCOPE void TkSelUpdateClipboard(TkWindow *winPtr, + TkClipboardTarget *targetPtr); #endif #endif /* _TKSELECT */ diff --git a/generic/tkSquare.c b/generic/tkSquare.c index 435b841..a35832a 100644 --- a/generic/tkSquare.c +++ b/generic/tkSquare.c @@ -1,32 +1,32 @@ -/* +/* * tkSquare.c -- * - * This module implements "square" widgets that are object - * based. A "square" is a widget that displays a single square that can - * be moved around and resized. This file is intended as an example - * of how to build a widget; it isn't included in the - * normal wish, but it is included in "tktest". + * This module implements "square" widgets that are object based. A + * "square" is a widget that displays a single square that can be moved + * around and resized. This file is intended as an example of how to + * build a widget; it isn't included in the normal wish, but it is + * included in "tktest". * * Copyright (c) 1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" +#if 0 #define __NO_OLD_CONFIG -#include "tk.h" +#endif #include "tkInt.h" /* - * A data structure of the following type is kept for each square - * widget managed by this file: + * A data structure of the following type is kept for each square widget + * managed by this file: */ typedef struct { - Tk_Window tkwin; /* Window that embodies the square. NULL - * means window has been deleted but - * widget record hasn't been cleaned up yet. */ + Tk_Window tkwin; /* Window that embodies the square. NULL means + * window has been deleted but widget record + * hasn't been cleaned up yet. */ Display *display; /* X's token for the window's display. */ Tcl_Interp *interp; /* Interpreter associated with widget. */ Tcl_Command widgetCmd; /* Token for square's widget command. */ @@ -47,31 +47,31 @@ typedef struct { Tcl_Obj *reliefPtr; GC gc; /* Graphics context for copying from * off-screen pixmap onto screen. */ - Tcl_Obj *doubleBufferPtr; /* Non-zero means double-buffer redisplay - * with pixmap; zero means draw straight - * onto the display. */ - int updatePending; /* Non-zero means a call to SquareDisplay - * has already been scheduled. */ + Tcl_Obj *doubleBufferPtr; /* Non-zero means double-buffer redisplay with + * pixmap; zero means draw straight onto the + * display. */ + int updatePending; /* Non-zero means a call to SquareDisplay has + * already been scheduled. */ } Square; /* * Information used for argv parsing. */ -static Tk_OptionSpec optionSpecs[] = { +static const Tk_OptionSpec optionSpecs[] = { {TK_OPTION_BORDER, "-background", "background", "Background", "#d9d9d9", Tk_Offset(Square, bgBorderPtr), -1, 0, (ClientData) "white"}, - {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth"}, - {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-background"}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, NULL, 0, -1, 0, + (ClientData) "-borderwidth"}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, NULL, 0, -1, 0, + (ClientData) "-background"}, {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", "2", Tk_Offset(Square, borderWidthPtr), -1}, {TK_OPTION_BOOLEAN, "-dbl", "doubleBuffer", "DoubleBuffer", "1", Tk_Offset(Square, doubleBufferPtr), -1}, - {TK_OPTION_SYNONYM, "-fg", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-foreground"}, + {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, 0, -1, 0, + (ClientData) "-foreground"}, {TK_OPTION_BORDER, "-foreground", "foreground", "Foreground", "#b03060", Tk_Offset(Square, fgBorderPtr), -1, 0, (ClientData) "black"}, @@ -90,28 +90,26 @@ static Tk_OptionSpec optionSpecs[] = { * Forward declarations for procedures defined later in this file: */ -int SquareObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static void SquareDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static int SquareConfigure _ANSI_ARGS_((Tcl_Interp *interp, - Square *squarePtr)); -static void SquareDestroy _ANSI_ARGS_((char *memPtr)); -static void SquareDisplay _ANSI_ARGS_((ClientData clientData)); -static void KeepInWindow _ANSI_ARGS_((Square *squarePtr)); -static void SquareObjEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int SquareWidgetObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *, int objc, Tcl_Obj * CONST objv[])); +int SquareObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj * CONST objv[]); +static void SquareDeletedProc(ClientData clientData); +static int SquareConfigure(Tcl_Interp *interp, Square *squarePtr); +static void SquareDestroy(char *memPtr); +static void SquareDisplay(ClientData clientData); +static void KeepInWindow(Square *squarePtr); +static void SquareObjEventProc(ClientData clientData, + XEvent *eventPtr); +static int SquareWidgetObjCmd(ClientData clientData, + Tcl_Interp *, int objc, Tcl_Obj * CONST objv[]); /* *-------------------------------------------------------------- * * SquareCmd -- * - * This procedure is invoked to process the "square" Tcl - * command. It creates a new "square" widget. + * This procedure is invoked to process the "square" Tcl command. It + * creates a new "square" widget. * * Results: * A standard Tcl result. @@ -123,11 +121,11 @@ static int SquareWidgetObjCmd _ANSI_ARGS_((ClientData clientData, */ int -SquareObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* NULL. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +SquareObjCmd( + ClientData clientData, /* NULL. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Square *squarePtr; Tk_Window tkwin; @@ -138,39 +136,38 @@ SquareObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } - tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), - Tcl_GetStringFromObj(objv[1], NULL), (char *) NULL); + tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp), + Tcl_GetString(objv[1]), NULL); if (tkwin == NULL) { return TCL_ERROR; } Tk_SetClass(tkwin, "Square"); /* - * Create the option table for this widget class. If it has - * already been created, the refcount will get bumped and just - * the pointer will be returned. The refcount getting bumped - * does not concern us, because Tk will ensure the table is - * deleted when the interpreter is destroyed. + * Create the option table for this widget class. If it has already been + * created, the refcount will get bumped and just the pointer will be + * returned. The refcount getting bumped does not concern us, because Tk + * will ensure the table is deleted when the interpreter is destroyed. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); /* - * Allocate and initialize the widget record. The memset allows - * us to set just the non-NULL/0 items. + * Allocate and initialize the widget record. The memset allows us to set + * just the non-NULL/0 items. */ - squarePtr = (Square *) ckalloc(sizeof(Square)); + squarePtr = (Square *) ckalloc(sizeof(Square)); memset((void *) squarePtr, 0, (sizeof(Square))); - squarePtr->tkwin = tkwin; - squarePtr->display = Tk_Display(tkwin); - squarePtr->interp = interp; - squarePtr->widgetCmd = Tcl_CreateObjCommand(interp, + squarePtr->tkwin = tkwin; + squarePtr->display = Tk_Display(tkwin); + squarePtr->interp = interp; + squarePtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(squarePtr->tkwin), SquareWidgetObjCmd, (ClientData) squarePtr, SquareDeletedProc); - squarePtr->gc = None; - squarePtr->optionTable = optionTable; + squarePtr->gc = None; + squarePtr->optionTable = optionTable; if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin) != TCL_OK) { @@ -182,7 +179,7 @@ SquareObjCmd(clientData, interp, objc, objv) Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask, SquareObjEventProc, (ClientData) squarePtr); if (Tk_SetOptions(interp, (char *) squarePtr, optionTable, objc - 2, - objv + 2, tkwin, NULL, (int *) NULL) != TCL_OK) { + objv + 2, tkwin, NULL, NULL) != TCL_OK) { goto error; } if (SquareConfigure(interp, squarePtr) != TCL_OK) { @@ -193,7 +190,7 @@ SquareObjCmd(clientData, interp, objc, objv) Tcl_NewStringObj(Tk_PathName(squarePtr->tkwin), -1)); return TCL_OK; -error: + error: Tk_DestroyWindow(squarePtr->tkwin); return TCL_ERROR; } @@ -203,9 +200,9 @@ error: * * SquareWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a widget managed by this module. - * See the user documentation for details on what it does. + * This procedure is invoked to process the Tcl command that corresponds + * to a widget managed by this module. See the user documentation for + * details on what it does. * * Results: * A standard Tcl result. @@ -217,15 +214,15 @@ error: */ static int -SquareWidgetObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Information about square widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj * CONST objv[]; /* Argument objects. */ +SquareWidgetObjCmd( + ClientData clientData, /* Information about square widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj * CONST objv[]) /* Argument objects. */ { Square *squarePtr = (Square *) clientData; int result = TCL_OK; - static CONST char *squareOptions[] = {"cget", "configure", (char *) NULL}; + static CONST char *squareOptions[] = {"cget", "configure", NULL}; enum { SQUARE_CGET, SQUARE_CONFIGURE }; @@ -243,58 +240,55 @@ SquareWidgetObjCmd(clientData, interp, objc, objv) } Tcl_Preserve((ClientData) squarePtr); - + switch (index) { - case SQUARE_CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); - goto error; + case SQUARE_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + goto error; + } + resultObjPtr = Tk_GetOptionValue(interp, (char *) squarePtr, + squarePtr->optionTable, objv[2], squarePtr->tkwin); + if (resultObjPtr == NULL) { + result = TCL_ERROR; + } else { + Tcl_SetObjResult(interp, resultObjPtr); + } + break; + case SQUARE_CONFIGURE: + resultObjPtr = NULL; + if (objc == 2) { + resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr, + squarePtr->optionTable, NULL, squarePtr->tkwin); + if (resultObjPtr == NULL) { + result = TCL_ERROR; } - resultObjPtr = Tk_GetOptionValue(interp, (char *) squarePtr, + } else if (objc == 3) { + resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr, squarePtr->optionTable, objv[2], squarePtr->tkwin); if (resultObjPtr == NULL) { result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, resultObjPtr); } - break; - } - case SQUARE_CONFIGURE: { - resultObjPtr = NULL; - if (objc == 2) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr, - squarePtr->optionTable, (Tcl_Obj *) NULL, - squarePtr->tkwin); - if (resultObjPtr == NULL) { - result = TCL_ERROR; - } - } else if (objc == 3) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) squarePtr, - squarePtr->optionTable, objv[2], squarePtr->tkwin); - if (resultObjPtr == NULL) { - result = TCL_ERROR; - } - } else { - result = Tk_SetOptions(interp, (char *) squarePtr, - squarePtr->optionTable, objc - 2, objv + 2, - squarePtr->tkwin, NULL, (int *) NULL); - if (result == TCL_OK) { - result = SquareConfigure(interp, squarePtr); - } - if (!squarePtr->updatePending) { - Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr); - squarePtr->updatePending = 1; - } + } else { + result = Tk_SetOptions(interp, (char *) squarePtr, + squarePtr->optionTable, objc - 2, objv + 2, + squarePtr->tkwin, NULL, NULL); + if (result == TCL_OK) { + result = SquareConfigure(interp, squarePtr); } - if (resultObjPtr != NULL) { - Tcl_SetObjResult(interp, resultObjPtr); + if (!squarePtr->updatePending) { + Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr); + squarePtr->updatePending = 1; } } + if (resultObjPtr != NULL) { + Tcl_SetObjResult(interp, resultObjPtr); + } } Tcl_Release((ClientData) squarePtr); return result; - error: + error: Tcl_Release((ClientData) squarePtr); return TCL_ERROR; } @@ -304,37 +298,36 @@ SquareWidgetObjCmd(clientData, interp, objc, objv) * * SquareConfigure -- * - * This procedure is called to process an argv/argc list in - * conjunction with the Tk option database to configure (or - * reconfigure) a square widget. + * This procedure is called to process an argv/argc list in conjunction + * with the Tk option database to configure (or reconfigure) a square + * widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as colors, border width, - * etc. get set for squarePtr; old resources get freed, - * if there were any. + * Configuration information, such as colors, border width, etc. get set + * for squarePtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -SquareConfigure(interp, squarePtr) - Tcl_Interp *interp; /* Used for error reporting. */ - Square *squarePtr; /* Information about widget. */ +SquareConfigure( + Tcl_Interp *interp, /* Used for error reporting. */ + Square *squarePtr) /* Information about widget. */ { int borderWidth; Tk_3DBorder bgBorder; int doubleBuffer; /* - * Set the background for the window and create a graphics context - * for use during redisplay. + * Set the background for the window and create a graphics context for use + * during redisplay. */ - bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, + bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, squarePtr->bgBorderPtr); Tk_SetWindowBackground(squarePtr->tkwin, Tk_3DBorderColor(bgBorder)->pixel); @@ -348,8 +341,8 @@ SquareConfigure(interp, squarePtr) } /* - * Register the desired geometry for the window. Then arrange for - * the window to be redisplayed. + * Register the desired geometry for the window. Then arrange for the + * window to be redisplayed. */ Tk_GeometryRequest(squarePtr->tkwin, 200, 150); @@ -369,23 +362,23 @@ SquareConfigure(interp, squarePtr) * * SquareObjEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on squares. + * This procedure is invoked by the Tk dispatcher for various events on + * squares. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. When + * it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -SquareObjEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +SquareObjEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { Square *squarePtr = (Square *) clientData; @@ -423,9 +416,9 @@ SquareObjEventProc(clientData, eventPtr) * * SquareDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This procedure is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -437,17 +430,17 @@ SquareObjEventProc(clientData, eventPtr) */ static void -SquareDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +SquareDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { Square *squarePtr = (Square *) clientData; Tk_Window tkwin = squarePtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This procedure could be invoked either because the window was destroyed + * and the command was then deleted (in which case tkwin is NULL) or + * because the command was deleted, and then this procedure destroys the + * widget. */ if (tkwin != NULL) { @@ -460,9 +453,9 @@ SquareDeletedProc(clientData) * * SquareDisplay -- * - * This procedure redraws the contents of a square window. - * It is invoked as a do-when-idle handler, so it only runs - * when there's nothing else for the application to do. + * This procedure redraws the contents of a square window. It is invoked + * as a do-when-idle handler, so it only runs when there's nothing else + * for the application to do. * * Results: * None. @@ -474,8 +467,8 @@ SquareDeletedProc(clientData) */ static void -SquareDisplay(clientData) - ClientData clientData; /* Information about window. */ +SquareDisplay( + ClientData clientData) /* Information about window. */ { Square *squarePtr = (Square *) clientData; Tk_Window tkwin = squarePtr->tkwin; @@ -510,7 +503,7 @@ SquareDisplay(clientData) Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr, &borderWidth); - bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, + bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, squarePtr->bgBorderPtr); Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief); Tk_Fill3DRectangle(tkwin, d, bgBorder, 0, 0, Tk_Width(tkwin), @@ -521,9 +514,9 @@ SquareDisplay(clientData) */ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size); - fgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, + fgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin, squarePtr->fgBorderPtr); - Tk_Fill3DRectangle(tkwin, d, fgBorder, squarePtr->x, squarePtr->y, size, + Tk_Fill3DRectangle(tkwin, d, fgBorder, squarePtr->x, squarePtr->y, size, size, borderWidth, TK_RELIEF_RAISED); /* @@ -543,9 +536,9 @@ SquareDisplay(clientData) * * SquareDestroy -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a square at a safe time - * (when no-one is using it anymore). + * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to + * clean up the internal structure of a square at a safe time (when + * no-one is using it anymore). * * Results: * None. @@ -557,11 +550,11 @@ SquareDisplay(clientData) */ static void -SquareDestroy(memPtr) - char *memPtr; /* Info about square widget. */ +SquareDestroy( + char *memPtr) /* Info about square widget. */ { Square *squarePtr = (Square *) memPtr; - + ckfree((char *) squarePtr); } @@ -570,31 +563,31 @@ SquareDestroy(memPtr) * * KeepInWindow -- * - * Adjust the position of the square if necessary to keep it in - * the widget's window. + * Adjust the position of the square if necessary to keep it in the + * widget's window. * * Results: * None. * * Side effects: - * The x and y position of the square are adjusted if necessary - * to keep the square in the window. + * The x and y position of the square are adjusted if necessary to keep + * the square in the window. * *---------------------------------------------------------------------- */ static void -KeepInWindow(squarePtr) - register Square *squarePtr; /* Pointer to widget record. */ +KeepInWindow( + register Square *squarePtr) /* Pointer to widget record. */ { int i, bd, relief; int borderWidth, size; Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr, &borderWidth); - Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr, + Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr, &squarePtr->x); - Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->yPtr, + Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->yPtr, &squarePtr->y); Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size); Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief); @@ -617,3 +610,11 @@ KeepInWindow(squarePtr) squarePtr->y = bd; } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkStubImg.c b/generic/tkStubImg.c deleted file mode 100644 index 608d627..0000000 --- a/generic/tkStubImg.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * tkStubImg.c -- - * - * Stub object that will be statically linked into extensions that wish - * to access Tk. - * - * Copyright (c) 1999 Jan Nijtmans. - * Copyright (c) 1998-1999 by Scriptics Corporation. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - */ - -#include "tcl.h" - - -/* - *---------------------------------------------------------------------- - * - * Tk_InitImageArgs -- - * - * Performs the necessary conversion from Tcl_Obj's to strings - * in the createProc for Tcl_CreateImageType. If running under - * Tk 8.2 or earlier without the Img-patch, this function has - * no effect. - * - * Results: - * argvPtr will point to an argument list which is guaranteed to - * contain strings, no matter what Tk version is running. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -#ifdef Tk_InitImageArgs -#undef Tk_InitImageArgs -#endif - -void -Tk_InitImageArgs(interp, argc, argvPtr) - Tcl_Interp *interp; - int argc; - char ***argvPtr; -{ - static int useNewImage = -1; - static char **argv = NULL; - - if (argv) { - tclStubsPtr->tcl_Free((char *) argv); - argv = NULL; - } - - if (useNewImage < 0) { - Tcl_CmdInfo cmdInfo; - if (!tclStubsPtr->tcl_GetCommandInfo(interp,"image", &cmdInfo)) { - tclStubsPtr->tcl_Panic("cannot find the \"image\" command"); - } - if (cmdInfo.isNativeObjectProc == 1) { - useNewImage = 1; /* Tk uses the new image interface */ - } else { - useNewImage = 0; /* Tk uses old image interface */ - } - } - if (useNewImage && (argc > 0)) { - int i; - argv = (char **) tclStubsPtr->tcl_Alloc(argc * sizeof(char *)); - for (i = 0; i < argc; i++) { - argv[i] = tclStubsPtr->tcl_GetString((Tcl_Obj *)(*argvPtr)[i]); - } - *argvPtr = (char **) argv; - } -} diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index a82e044..170ada7 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -1,50 +1,49 @@ -/* +/* * tkStubInit.c -- * * This file contains the initializers for the Tk stub vectors. * * Copyright (c) 1998-1999 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" -#if !(defined(__WIN32__) && defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* UNIX */ #define UNIX_TK +#include "tkUnixInt.h" #endif #ifdef __WIN32__ #include "tkWinInt.h" #endif -#if defined(MAC_TCL) -/* set this locally .. we could have used _TKMACINT */ -#define MAC_TK -#include "tkMacInt.h" -#endif #if defined(MAC_OSX_TK) -/* set this locally .. we could have used _TKMACINT */ +/* we could have used _TKMACINT */ #include "tkMacOSXInt.h" #endif -#include "tkDecls.h" +/* TODO: These ought to come in some other way */ #include "tkPlatDecls.h" -#include "tkIntDecls.h" -#include "tkIntPlatDecls.h" #include "tkIntXlibDecls.h" /* * Remove macros that will interfere with the definitions below. */ -#define Tk_CreateCanvasVisitor ((void (*) _ANSI_ARGS_((Tcl_Interp * interp, \ - VOID * typePtr))) NULL) -#define Tk_GetCanvasVisitor ((VOID * (*) _ANSI_ARGS_((Tcl_Interp * interp, \ - CONST char * name))) NULL) +#define Tk_CreateCanvasVisitor \ + ((void (*)(Tcl_Interp * interp, VOID * typePtr)) NULL) +#define Tk_GetCanvasVisitor \ + ((VOID * (*)(Tcl_Interp * interp, CONST char * name)) NULL) + +MODULE_SCOPE TkIntStubs tkIntStubs; +MODULE_SCOPE TkIntPlatStubs tkIntPlatStubs; +MODULE_SCOPE TkIntXlibStubs tkIntXlibStubs; +MODULE_SCOPE TkPlatStubs tkPlatStubs; +MODULE_SCOPE TkStubs tkStubs; #ifndef __WIN32__ /* Make sure that extensions which call XParseColor through @@ -176,128 +175,108 @@ TkIntStubs tkIntStubs = { TkpGetSubFonts, /* 110 */ TkpGetSystemDefault, /* 111 */ TkpMenuThreadInit, /* 112 */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 113 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkClipBox, /* 113 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkClipBox, /* 113 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 113 */ /* Dummy entry for stubs table backwards compatibility */ TkClipBox, /* 113 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 114 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkCreateRegion, /* 114 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkCreateRegion, /* 114 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 114 */ /* Dummy entry for stubs table backwards compatibility */ TkCreateRegion, /* 114 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 115 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkDestroyRegion, /* 115 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkDestroyRegion, /* 115 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 115 */ /* Dummy entry for stubs table backwards compatibility */ TkDestroyRegion, /* 115 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 116 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkIntersectRegion, /* 116 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkIntersectRegion, /* 116 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 116 */ /* Dummy entry for stubs table backwards compatibility */ TkIntersectRegion, /* 116 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 117 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkRectInRegion, /* 117 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkRectInRegion, /* 117 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 117 */ /* Dummy entry for stubs table backwards compatibility */ TkRectInRegion, /* 117 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 118 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkSetRegion, /* 118 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkSetRegion, /* 118 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 118 */ /* Dummy entry for stubs table backwards compatibility */ TkSetRegion, /* 118 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 119 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkUnionRectWithRegion, /* 119 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkUnionRectWithRegion, /* 119 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 119 */ /* Dummy entry for stubs table backwards compatibility */ TkUnionRectWithRegion, /* 119 */ -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ NULL, /* 120 */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 121 */ -#endif /* UNIX */ -#ifdef __WIN32__ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ NULL, /* 121 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 121 */ /* Dummy entry for stubs table backwards compatibility */ TkpCreateNativeBitmap, /* 121 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - TkpCreateNativeBitmap, /* 121 */ -#endif /* MAC_OSX_TK */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 122 */ -#endif /* UNIX */ -#ifdef __WIN32__ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ NULL, /* 122 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - TkpDefineNativeBitmaps, /* 122 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 122 */ /* Dummy entry for stubs table backwards compatibility */ TkpDefineNativeBitmaps, /* 122 */ -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ NULL, /* 123 */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 124 */ -#endif /* UNIX */ -#ifdef __WIN32__ +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ NULL, /* 124 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 124 */ /* Dummy entry for stubs table backwards compatibility */ TkpGetNativeAppBitmap, /* 124 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK - TkpGetNativeAppBitmap, /* 124 */ -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ NULL, /* 125 */ NULL, /* 126 */ NULL, /* 127 */ @@ -318,31 +297,57 @@ TkIntStubs tkIntStubs = { TkFocusFree, /* 142 */ TkClipCleanup, /* 143 */ TkGCCleanup, /* 144 */ -#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ NULL, /* 145 */ -#endif /* UNIX */ -#ifdef __WIN32__ - TkSubtractRegion, /* 145 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL +#endif /* X11 */ +#ifdef __WIN32__ /* WIN */ TkSubtractRegion, /* 145 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ + NULL, /* 145 */ /* Dummy entry for stubs table backwards compatibility */ TkSubtractRegion, /* 145 */ -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ TkStylePkgInit, /* 146 */ TkStylePkgFree, /* 147 */ TkToplevelWindowForCommand, /* 148 */ TkGetOptionSpec, /* 149 */ - NULL, /* 150 */ - NULL, /* 151 */ + TkMakeRawCurve, /* 150 */ + TkMakeRawCurvePostscript, /* 151 */ TkpDrawFrame, /* 152 */ + TkCreateThreadExitHandler, /* 153 */ + TkDeleteThreadExitHandler, /* 154 */ + NULL, /* 155 */ + TkpTestembedCmd, /* 156 */ + TkpTesttextCmd, /* 157 */ + NULL, /* 158 */ + NULL, /* 159 */ + NULL, /* 160 */ + NULL, /* 161 */ + NULL, /* 162 */ + NULL, /* 163 */ + NULL, /* 164 */ + NULL, /* 165 */ + NULL, /* 166 */ + NULL, /* 167 */ + NULL, /* 168 */ + TkStateParseProc, /* 169 */ + TkStatePrintProc, /* 170 */ + TkCanvasDashParseProc, /* 171 */ + TkCanvasDashPrintProc, /* 172 */ + TkOffsetParseProc, /* 173 */ + TkOffsetPrintProc, /* 174 */ + TkPixelParseProc, /* 175 */ + TkPixelPrintProc, /* 176 */ + TkOrientParseProc, /* 177 */ + TkOrientPrintProc, /* 178 */ + TkSmoothParseProc, /* 179 */ + TkSmoothPrintProc, /* 180 */ }; TkIntPlatStubs tkIntPlatStubs = { TCL_STUB_MAGIC, NULL, -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ TkAlignImageData, /* 0 */ NULL, /* 1 */ TkGenerateActivateEvents, /* 2 */ @@ -379,77 +384,9 @@ TkIntPlatStubs tkIntPlatStubs = { TkWinGetPlatformId, /* 33 */ TkWinSetHINSTANCE, /* 34 */ TkWinGetPlatformTheme, /* 35 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - TkGenerateActivateEvents, /* 0 */ - NULL, /* 1 */ - NULL, /* 2 */ - TkpGetMS, /* 3 */ - NULL, /* 4 */ - TkPointerDeadWindow, /* 5 */ - TkpSetCapture, /* 6 */ - TkpSetCursor, /* 7 */ - TkpWmSetState, /* 8 */ - NULL, /* 9 */ - TkAboutDlg, /* 10 */ - NULL, /* 11 */ - NULL, /* 12 */ - TkGetTransientMaster, /* 13 */ - TkGenerateButtonEvent, /* 14 */ - NULL, /* 15 */ - TkGenWMDestroyEvent, /* 16 */ - NULL, /* 17 */ - TkMacButtonKeyState, /* 18 */ - TkMacClearMenubarActive, /* 19 */ - NULL, /* 20 */ - TkMacDispatchMenuEvent, /* 21 */ - TkMacInstallCursor, /* 22 */ - NULL, /* 23 */ - TkMacHandleTearoffMenu, /* 24 */ - NULL, /* 25 */ - NULL, /* 26 */ - TkMacDoHLEvent, /* 27 */ - NULL, /* 28 */ - TkMacGenerateTime, /* 29 */ - NULL, /* 30 */ - TkMacGetScrollbarGrowWindow, /* 31 */ - TkMacGetXWindow, /* 32 */ - TkMacGrowToplevel, /* 33 */ - TkMacHandleMenuSelect, /* 34 */ - NULL, /* 35 */ - NULL, /* 36 */ - NULL, /* 37 */ - TkMacInvalidateWindow, /* 38 */ - TkMacIsCharacterMissing, /* 39 */ - TkMacMakeRealWindowExist, /* 40 */ - TkMacMakeStippleMap, /* 41 */ - TkMacMenuClick, /* 42 */ - TkMacRegisterOffScreenWindow, /* 43 */ - TkMacResizable, /* 44 */ - NULL, /* 45 */ - TkMacSetHelpMenuItemCount, /* 46 */ - TkMacSetScrollbarGrow, /* 47 */ - TkMacSetUpClippingRgn, /* 48 */ - TkMacSetUpGraphicsPort, /* 49 */ - TkMacUpdateClipRgn, /* 50 */ - TkMacUnregisterMacWindow, /* 51 */ - TkMacUseMenuID, /* 52 */ - TkMacVisableClipRgn, /* 53 */ - TkMacWinBounds, /* 54 */ - TkMacWindowOffset, /* 55 */ - NULL, /* 56 */ - TkSetMacColor, /* 57 */ - TkSetWMName, /* 58 */ - TkSuspendClipboard, /* 59 */ - NULL, /* 60 */ - TkMacZoomToplevel, /* 61 */ - Tk_TopCoordsToWindow, /* 62 */ - TkMacContainerId, /* 63 */ - TkMacGetHostToplevel, /* 64 */ - TkMacPreprocessMenu, /* 65 */ - TkpIsWindowFloating, /* 66 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK + TkWinChildProc, /* 36 */ +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ TkGenerateActivateEvents, /* 0 */ NULL, /* 1 */ NULL, /* 2 */ @@ -504,8 +441,8 @@ TkIntPlatStubs tkIntPlatStubs = { TkGenWMDestroyEvent, /* 51 */ NULL, /* 52 */ TkpGetMS, /* 53 */ -#endif /* MAC_OSX_TK */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) /* X11 */ +#endif /* AQUA */ +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */ TkCreateXEventSource, /* 0 */ TkFreeWindowId, /* 1 */ TkInitXId, /* 2 */ @@ -519,13 +456,14 @@ TkIntPlatStubs tkIntPlatStubs = { TkSendCleanup, /* 10 */ TkFreeXId, /* 11 */ TkpWmSetState, /* 12 */ + TkpTestsendCmd, /* 13 */ #endif /* X11 */ }; TkIntXlibStubs tkIntXlibStubs = { TCL_STUB_MAGIC, NULL, -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ XSetDashes, /* 0 */ XGetModifierMapping, /* 1 */ XCreateImage, /* 2 */ @@ -633,101 +571,8 @@ TkIntXlibStubs tkIntXlibStubs = { XDrawLine, /* 104 */ XWarpPointer, /* 105 */ XFillRectangle, /* 106 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - XSetDashes, /* 0 */ - XGetModifierMapping, /* 1 */ - XCreateImage, /* 2 */ - XGetImage, /* 3 */ - XGetAtomName, /* 4 */ - XKeysymToString, /* 5 */ - XCreateColormap, /* 6 */ - XGContextFromGC, /* 7 */ - XKeycodeToKeysym, /* 8 */ - XStringToKeysym, /* 9 */ - XRootWindow, /* 10 */ - XSetErrorHandler, /* 11 */ - XAllocColor, /* 12 */ - XBell, /* 13 */ - XChangeProperty, /* 14 */ - XChangeWindowAttributes, /* 15 */ - XConfigureWindow, /* 16 */ - XCopyArea, /* 17 */ - XCopyPlane, /* 18 */ - XCreateBitmapFromData, /* 19 */ - XDefineCursor, /* 20 */ - XDestroyWindow, /* 21 */ - XDrawArc, /* 22 */ - XDrawLines, /* 23 */ - XDrawRectangle, /* 24 */ - XFillArc, /* 25 */ - XFillPolygon, /* 26 */ - XFillRectangles, /* 27 */ - XFreeColormap, /* 28 */ - XFreeColors, /* 29 */ - XFreeModifiermap, /* 30 */ - XGetGeometry, /* 31 */ - XGetWindowProperty, /* 32 */ - XGrabKeyboard, /* 33 */ - XGrabPointer, /* 34 */ - XKeysymToKeycode, /* 35 */ - XMapWindow, /* 36 */ - XMoveResizeWindow, /* 37 */ - XMoveWindow, /* 38 */ - XQueryPointer, /* 39 */ - XRaiseWindow, /* 40 */ - XRefreshKeyboardMapping, /* 41 */ - XResizeWindow, /* 42 */ - XSelectInput, /* 43 */ - XSendEvent, /* 44 */ - XSetIconName, /* 45 */ - XSetInputFocus, /* 46 */ - XSetSelectionOwner, /* 47 */ - XSetWindowBackground, /* 48 */ - XSetWindowBackgroundPixmap, /* 49 */ - XSetWindowBorder, /* 50 */ - XSetWindowBorderPixmap, /* 51 */ - XSetWindowBorderWidth, /* 52 */ - XSetWindowColormap, /* 53 */ - XUngrabKeyboard, /* 54 */ - XUngrabPointer, /* 55 */ - XUnmapWindow, /* 56 */ - TkPutImage, /* 57 */ - XParseColor, /* 58 */ - XCreateGC, /* 59 */ - XFreeGC, /* 60 */ - XInternAtom, /* 61 */ - XSetBackground, /* 62 */ - XSetForeground, /* 63 */ - XSetClipMask, /* 64 */ - XSetClipOrigin, /* 65 */ - XSetTSOrigin, /* 66 */ - XChangeGC, /* 67 */ - XSetFont, /* 68 */ - XSetArcMode, /* 69 */ - XSetStipple, /* 70 */ - XSetFillRule, /* 71 */ - XSetFillStyle, /* 72 */ - XSetFunction, /* 73 */ - XSetLineAttributes, /* 74 */ - _XInitImageFuncPtrs, /* 75 */ - XCreateIC, /* 76 */ - XGetVisualInfo, /* 77 */ - XSetWMClientMachine, /* 78 */ - XStringListToTextProperty, /* 79 */ - XDrawSegments, /* 80 */ - XForceScreenSaver, /* 81 */ - XDrawLine, /* 82 */ - XFillRectangle, /* 83 */ - XClearWindow, /* 84 */ - XDrawPoint, /* 85 */ - XDrawPoints, /* 86 */ - XWarpPointer, /* 87 */ - XQueryColor, /* 88 */ - XQueryColors, /* 89 */ - XQueryTree, /* 90 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ XSetDashes, /* 0 */ XGetModifierMapping, /* 1 */ XCreateImage, /* 2 */ @@ -820,34 +665,21 @@ TkIntXlibStubs tkIntXlibStubs = { XQueryColors, /* 89 */ XQueryTree, /* 90 */ XSync, /* 91 */ -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ }; TkPlatStubs tkPlatStubs = { TCL_STUB_MAGIC, NULL, -#ifdef __WIN32__ +#ifdef __WIN32__ /* WIN */ Tk_AttachHWND, /* 0 */ Tk_GetHINSTANCE, /* 1 */ Tk_GetHWND, /* 2 */ Tk_HWNDToWindow, /* 3 */ Tk_PointerEvent, /* 4 */ Tk_TranslateWinEvent, /* 5 */ -#endif /* __WIN32__ */ -#ifdef MAC_TCL - Tk_MacSetEmbedHandler, /* 0 */ - Tk_MacTurnOffMenus, /* 1 */ - Tk_MacTkOwnsCursor, /* 2 */ - TkMacInitMenus, /* 3 */ - TkMacInitAppleEvents, /* 4 */ - TkMacConvertEvent, /* 5 */ - TkMacConvertTkEvent, /* 6 */ - TkGenWMConfigureEvent, /* 7 */ - TkMacInvalClipRgns, /* 8 */ - TkMacHaveAppearance, /* 9 */ - TkMacGetDrawablePort, /* 10 */ -#endif /* MAC_TCL */ -#ifdef MAC_OSX_TK +#endif /* WIN */ +#ifdef MAC_OSX_TK /* AQUA */ Tk_MacOSXSetEmbedHandler, /* 0 */ Tk_MacOSXTurnOffMenus, /* 1 */ Tk_MacOSXTkOwnsCursor, /* 2 */ @@ -859,7 +691,7 @@ TkPlatStubs tkPlatStubs = { TkMacOSXGetRootControl, /* 8 */ Tk_MacOSXSetupTkNotifier, /* 9 */ Tk_MacOSXIsAppInFront, /* 10 */ -#endif /* MAC_OSX_TK */ +#endif /* AQUA */ }; static TkStubHooks tkStubHooks = { @@ -1020,9 +852,9 @@ TkStubs tkStubs = { Tk_PhotoPutZoomedBlock_NoComposite, /* 145 */ Tk_PhotoGetImage, /* 146 */ Tk_PhotoBlank, /* 147 */ - Tk_PhotoExpand, /* 148 */ + Tk_PhotoExpand_Panic, /* 148 */ Tk_PhotoGetSize, /* 149 */ - Tk_PhotoSetSize, /* 150 */ + Tk_PhotoSetSize_Panic, /* 150 */ Tk_PointToChar, /* 151 */ Tk_PostscriptFontName, /* 152 */ Tk_PreserveColormap, /* 153 */ @@ -1118,8 +950,8 @@ TkStubs tkStubs = { Tk_SetInternalBorderEx, /* 243 */ Tk_SetMinimumRequestSize, /* 244 */ Tk_SetCaretPos, /* 245 */ - Tk_PhotoPutBlock, /* 246 */ - Tk_PhotoPutZoomedBlock, /* 247 */ + Tk_PhotoPutBlock_Panic, /* 246 */ + Tk_PhotoPutZoomedBlock_Panic, /* 247 */ Tk_CollapseMotionEvents, /* 248 */ Tk_RegisterStyleEngine, /* 249 */ Tk_GetStyleEngine, /* 250 */ @@ -1137,10 +969,18 @@ TkStubs tkStubs = { Tk_GetElementBox, /* 262 */ Tk_GetElementBorderWidth, /* 263 */ Tk_DrawElement, /* 264 */ + Tk_PhotoExpand, /* 265 */ + Tk_PhotoPutBlock, /* 266 */ + Tk_PhotoPutZoomedBlock, /* 267 */ + Tk_PhotoSetSize, /* 268 */ + Tk_GetUserInactiveTime, /* 269 */ + Tk_ResetUserInactiveTime, /* 270 */ + Tk_Interp, /* 271 */ + Tk_CreateOldImageType, /* 272 */ + Tk_CreateOldPhotoImageFormat, /* 273 */ }; /* !END!: Do not edit above this line. */ #undef UNIX_TK -#undef MAC_TK #undef MAC_OSX_TK diff --git a/generic/tkStubLib.c b/generic/tkStubLib.c index 29c4851..5349a0b 100644 --- a/generic/tkStubLib.c +++ b/generic/tkStubLib.c @@ -1,4 +1,4 @@ -/* +/* * tkStubLib.c -- * * Stub object that will be statically linked into extensions that wish @@ -7,15 +7,14 @@ * Copyright (c) 1998 Paul Duffin. * Copyright (c) 1998-1999 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ - /* - * We need to ensure that we use the stub macros so that this file contains - * no references to any of the stub functions. This will make it possible - * to build an extension that references Tk_InitStubs but doesn't end up + * We need to ensure that we use the stub macros so that this file contains no + * references to any of the stub functions. This will make it possible to + * build an extension that references Tk_InitStubs but doesn't end up * including the rest of the stub functions. */ @@ -29,53 +28,50 @@ #endif #undef USE_TK_STUB_PROCS -#include "tkPort.h" #include "tkInt.h" #ifdef __WIN32__ #include "tkWinInt.h" #endif -#ifdef MAC_TCL -#include "tkMacInt.h" -#endif - #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #endif -#include "tkDecls.h" -#include "tkIntDecls.h" +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +#include "tkUnixInt.h" +#endif + +/* TODO: These ought to come in some other way */ #include "tkPlatDecls.h" -#include "tkIntPlatDecls.h" #include "tkIntXlibDecls.h" +TkStubs *tkStubsPtr = NULL; +TkPlatStubs *tkPlatStubsPtr = NULL; +TkIntStubs *tkIntStubsPtr = NULL; +TkIntPlatStubs *tkIntPlatStubsPtr = NULL; +TkIntXlibStubs *tkIntXlibStubsPtr = NULL; + /* - * Ensure that Tk_InitStubs is built as an exported symbol. The other stub - * functions should be built as non-exported symbols. + * Use our own isdigit to avoid linking to libc on windows */ -#undef TCL_STORAGE_CLASS -#define TCL_STORAGE_CLASS DLLEXPORT - -TkStubs *tkStubsPtr; -TkPlatStubs *tkPlatStubsPtr; -TkIntStubs *tkIntStubsPtr; -TkIntPlatStubs *tkIntPlatStubsPtr; -TkIntXlibStubs *tkIntXlibStubsPtr; - +static int isDigit(const int c) +{ + return (c >= '0' && c <= '9'); +} /* *---------------------------------------------------------------------- * * Tk_InitStubs -- * - * Checks that the correct version of Tk is loaded and that it - * supports stubs. It then initialises the stub table pointers. + * Checks that the correct version of Tk is loaded and that it supports + * stubs. It then initialises the stub table pointers. * * Results: - * The actual version of Tk that satisfies the request, or - * NULL to indicate that an error occurred. + * The actual version of Tk that satisfies the request, or NULL to + * indicate that an error occurred. * * Side effects: * Sets the stub table pointers. @@ -88,18 +84,46 @@ TkIntXlibStubs *tkIntXlibStubsPtr; #endif CONST char * -Tk_InitStubs(interp, version, exact) - Tcl_Interp *interp; - char *version; - int exact; +Tk_InitStubs( + Tcl_Interp *interp, + CONST char *version, + int exact) { CONST char *actualVersion; + TkStubs **stubsPtrPtr = &tkStubsPtr; /* squelch warning */ - actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, exact, - (ClientData *) &tkStubsPtr); + actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 0, + (ClientData *) stubsPtrPtr); if (!actualVersion) { return NULL; } + if (exact) { + CONST char *p = version; + int count = 0; + + while (*p) { + count += !isDigit(*p++); + } + if (count == 1) { + CONST char *q = actualVersion; + + p = version; + while (*p && (*p == *q)) { + p++; q++; + } + if (*p) { + /* Construct error message */ + Tcl_PkgRequireEx(interp, "Tk", version, 1, NULL); + return NULL; + + } + } else { + actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 1, NULL); + if (actualVersion == NULL) { + return NULL; + } + } + } if (!tkStubsPtr) { Tcl_SetResult(interp, @@ -107,11 +131,19 @@ Tk_InitStubs(interp, version, exact) TCL_STATIC); return NULL; } - + tkPlatStubsPtr = tkStubsPtr->hooks->tkPlatStubs; tkIntStubsPtr = tkStubsPtr->hooks->tkIntStubs; tkIntPlatStubsPtr = tkStubsPtr->hooks->tkIntPlatStubs; tkIntXlibStubsPtr = tkStubsPtr->hooks->tkIntXlibStubs; - + return actualVersion; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkStyle.c b/generic/tkStyle.c index e802dde..80d4e59 100644 --- a/generic/tkStyle.c +++ b/generic/tkStyle.c @@ -1,4 +1,4 @@ -/* +/* * tkStyle.c -- * * This file implements the widget styles and themes support. @@ -6,96 +6,91 @@ * Copyright (c) 1990-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" /* - * The following structure is used to cache widget option specs matching an + * The following structure is used to cache widget option specs matching an * element's required options defined by Tk_ElementOptionSpecs. It also holds * information behind Tk_StyledElement opaque tokens. */ typedef struct StyledWidgetSpec { - struct StyledElement *elementPtr; /* Pointer to the element holding this - * structure. */ - Tk_OptionTable optionTable; /* Option table for the widget class - * using the element. */ - CONST Tk_OptionSpec **optionsPtr; /* Table of option spec pointers, - * matching the option list provided - * during element registration. - * Malloc'd. */ + struct StyledElement *elementPtr; + /* Pointer to the element holding this + * structure. */ + Tk_OptionTable optionTable; /* Option table for the widget class using the + * element. */ + CONST Tk_OptionSpec **optionsPtr; + /* Table of option spec pointers, matching the + * option list provided during element + * registration. Malloc'd. */ } StyledWidgetSpec; /* - * Elements are declared using static templates. But static - * information must be completed by dynamic information only - * accessible at runtime. For each registered element, an instance of - * the following structure is stored in each style engine and used to - * cache information about the widget types (identified by their - * optionTable) that use the given element. + * Elements are declared using static templates. But static information must + * be completed by dynamic information only accessible at runtime. For each + * registered element, an instance of the following structure is stored in + * each style engine and used to cache information about the widget types + * (identified by their optionTable) that use the given element. */ typedef struct StyledElement { - struct Tk_ElementSpec *specPtr; - /* Filled with template provided during - * registration. NULL means no implementation - * is available for the current engine. */ - int nbWidgetSpecs; /* Size of the array below. Number of distinct - * widget classes (actually, distinct option + struct Tk_ElementSpec *specPtr; + /* Filled with template provided during + * registration. NULL means no implementation + * is available for the current engine. */ + int nbWidgetSpecs; /* Size of the array below. Number of distinct + * widget classes (actually, distinct option * tables) that used the element so far. */ - StyledWidgetSpec *widgetSpecs; + StyledWidgetSpec *widgetSpecs; /* See above for the structure definition. - * Table grows dynamically as new widgets - * use the element. Malloc'd. */ + * Table grows dynamically as new widgets use + * the element. Malloc'd. */ } StyledElement; /* - * The following structure holds information behind Tk_StyleEngine opaque + * The following structure holds information behind Tk_StyleEngine opaque * tokens. */ typedef struct StyleEngine { CONST char *name; /* Name of engine. Points to a hash key. */ - StyledElement *elements; /* Table of widget element descriptors. Each - * element is indexed by a unique system-wide - * ID. Table grows dynamically as new elements + StyledElement *elements; /* Table of widget element descriptors. Each + * element is indexed by a unique system-wide + * ID. Table grows dynamically as new elements * are registered. Malloc'd*/ - struct StyleEngine *parentPtr; - /* Parent engine. Engines may be layered to form - * a fallback chain, terminated by the default - * system engine. */ + struct StyleEngine *parentPtr; + /* Parent engine. Engines may be layered to + * form a fallback chain, terminated by the + * default system engine. */ } StyleEngine; /* - * Styles are instances of style engines. The following structure holds + * Styles are instances of style engines. The following structure holds * information behind Tk_Style opaque tokens. */ typedef struct Style { - int refCount; /* Number of active uses of this style. - * If this count is 0, then this Style - * structure is no longer valid. */ - Tcl_HashEntry *hashPtr; /* Entry in style table for this structure, - * used when deleting it. */ CONST char *name; /* Name of style. Points to a hash key. */ - StyleEngine *enginePtr; /* Style engine of which the style is an + StyleEngine *enginePtr; /* Style engine of which the style is an * instance. */ ClientData clientData; /* Data provided during registration. */ } Style; /* - * Each registered element uses an instance of the following structure. + * Each registered element uses an instance of the following structure. */ typedef struct Element { CONST char *name; /* Name of element. Points to a hash key. */ int id; /* Id of element. */ int genericId; /* Id of generic element. */ - int created; /* Boolean, whether the element was created - * explicitly (was registered) or implicitly + int created; /* Boolean, whether the element was created + * explicitly (was registered) or implicitly * (by a derived element). */ } Element; @@ -105,66 +100,54 @@ typedef struct Element { typedef struct ThreadSpecificData { int nbInit; /* Number of calls to the init proc. */ - Tcl_HashTable engineTable; /* Map a name to a style engine. Keys are - * strings, values are Tk_StyleEngine + Tcl_HashTable engineTable; /* Map a name to a style engine. Keys are + * strings, values are Tk_StyleEngine * pointers. */ - StyleEngine *defaultEnginePtr; - /* Default, core-defined style engine. Global + StyleEngine *defaultEnginePtr; + /* Default, core-defined style engine. Global * fallback for all engines. */ - Tcl_HashTable styleTable; /* Map a name to a style. Keys are strings, + Tcl_HashTable styleTable; /* Map a name to a style. Keys are strings, * values are Tk_Style pointers.*/ int nbElements; /* Size of the below tables. */ - Tcl_HashTable elementTable; /* Map a name to an element Id. Keys are + Tcl_HashTable elementTable; /* Map a name to an element Id. Keys are * strings, values are integer element IDs. */ - Element *elements; /* Array of Elements. */ + Element *elements; /* Array of Elements. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -/* TODO: sort alpha. */ -static int CreateElement _ANSI_ARGS_((CONST char *name, - int create)); -static void DupStyleObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, - Tcl_Obj *dupObjPtr)); -static void FreeElement _ANSI_ARGS_((Element *elementPtr)); -static void FreeStyle _ANSI_ARGS_((Style *stylePtr)); -static void FreeStyledElement _ANSI_ARGS_(( - StyledElement *elementPtr)); -static void FreeStyleEngine _ANSI_ARGS_(( - StyleEngine *enginePtr)); -static void FreeStyleObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); -static void FreeWidgetSpec _ANSI_ARGS_(( - StyledWidgetSpec *widgetSpecPtr)); -static StyledElement * GetStyledElement _ANSI_ARGS_(( - StyleEngine *enginePtr, int elementId)); -static StyledWidgetSpec * GetWidgetSpec _ANSI_ARGS_((StyledElement *elementPtr, - Tk_OptionTable optionTable)); -static void InitElement _ANSI_ARGS_((Element *elementPtr, - CONST char *name, int id, int genericId, - int created)); -static void InitStyle _ANSI_ARGS_((Style *stylePtr, - Tcl_HashEntry *hashPtr, CONST char *name, - StyleEngine *enginePtr, ClientData clientData)); -static void InitStyledElement _ANSI_ARGS_(( - StyledElement *elementPtr)); -static void InitStyleEngine _ANSI_ARGS_((StyleEngine *enginePtr, - CONST char *name, StyleEngine *parentPtr)); -static void InitWidgetSpec _ANSI_ARGS_(( - StyledWidgetSpec *widgetSpecPtr, - StyledElement *elementPtr, - Tk_OptionTable optionTable)); -static int SetStyleFromAny _ANSI_ARGS_((Tcl_Interp *interp, - Tcl_Obj *objPtr)); +static int CreateElement(CONST char *name, int create); +static void DupStyleObjProc(Tcl_Obj *srcObjPtr, + Tcl_Obj *dupObjPtr); +static void FreeElement(Element *elementPtr); +static void FreeStyledElement(StyledElement *elementPtr); +static void FreeStyleEngine(StyleEngine *enginePtr); +static void FreeStyleObjProc(Tcl_Obj *objPtr); +static void FreeWidgetSpec(StyledWidgetSpec *widgetSpecPtr); +static StyledElement * GetStyledElement(StyleEngine *enginePtr, + int elementId); +static StyledWidgetSpec*GetWidgetSpec(StyledElement *elementPtr, + Tk_OptionTable optionTable); +static void InitElement(Element *elementPtr, CONST char *name, + int id, int genericId, int created); +static void InitStyle(Style *stylePtr, CONST char *name, + StyleEngine *enginePtr, ClientData clientData); +static void InitStyledElement(StyledElement *elementPtr); +static void InitStyleEngine(StyleEngine *enginePtr, + CONST char *name, StyleEngine *parentPtr); +static void InitWidgetSpec(StyledWidgetSpec *widgetSpecPtr, + StyledElement *elementPtr, + Tk_OptionTable optionTable); +static int SetStyleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); /* * The following structure defines the implementation of the "style" Tcl - * object, used for drawing. The internalRep.otherValuePtr field of - * each style object points to the Style structure for the stylefont, or - * NULL. + * object, used for drawing. The internalRep.otherValuePtr field of each style + * object points to the Style structure for the stylefont, or NULL. */ static Tcl_ObjType styleObjType = { @@ -180,9 +163,9 @@ static Tcl_ObjType styleObjType = { * * TkStylePkgInit -- * - * This procedure is called when an application is created. It - * initializes all the structures that are used by the style - * package on a per application basis. + * This function is called when an application is created. It initializes + * all the structures that are used by the style package on a per + * application basis. * * Results: * Stores data in thread-local storage. @@ -194,13 +177,15 @@ static Tcl_ObjType styleObjType = { */ void -TkStylePkgInit(mainPtr) - TkMainInfo *mainPtr; /* The application being created. */ +TkStylePkgInit( + TkMainInfo *mainPtr) /* The application being created. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (tsdPtr->nbInit != 0) return; + if (tsdPtr->nbInit != 0) { + return; + } /* * Initialize tables. @@ -215,15 +200,15 @@ TkStylePkgInit(mainPtr) /* * Create the default system engine. */ - - tsdPtr->defaultEnginePtr = - (StyleEngine *) Tk_RegisterStyleEngine(NULL, NULL); + + tsdPtr->defaultEnginePtr = (StyleEngine *) + Tk_RegisterStyleEngine(NULL, NULL); /* * Create the default system style. */ - Tk_CreateStyle(NULL, (Tk_StyleEngine) tsdPtr->defaultEnginePtr, + Tk_CreateStyle(NULL, (Tk_StyleEngine) tsdPtr->defaultEnginePtr, (ClientData) 0); tsdPtr->nbInit++; @@ -234,9 +219,9 @@ TkStylePkgInit(mainPtr) * * TkStylePkgFree -- * - * This procedure is called when an application is deleted. It - * deletes all the structures that were used by the style package - * for this application. + * This function is called when an application is deleted. It deletes all + * the structures that were used by the style package for this + * application. * * Results: * None. @@ -248,18 +233,20 @@ TkStylePkgInit(mainPtr) */ void -TkStylePkgFree(mainPtr) - TkMainInfo *mainPtr; /* The application being deleted. */ +TkStylePkgFree( + TkMainInfo *mainPtr) /* The application being deleted. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashSearch search; Tcl_HashEntry *entryPtr; StyleEngine *enginePtr; int i; tsdPtr->nbInit--; - if (tsdPtr->nbInit != 0) return; + if (tsdPtr->nbInit != 0) { + return; + } /* * Free styles. @@ -301,11 +288,12 @@ TkStylePkgFree(mainPtr) * * Tk_RegisterStyleEngine -- * - * This procedure is called to register a new style engine. Style engines + * This function is called to register a new style engine. Style engines * are stored in thread-local space. * * Results: - * The newly allocated engine. + * The newly allocated engine, or NULL if an engine with the same name + * exists. * * Side effects: * Memory allocated. Data added to thread-local table. @@ -314,24 +302,24 @@ TkStylePkgFree(mainPtr) */ Tk_StyleEngine -Tk_RegisterStyleEngine(name, parent) - CONST char *name; /* Name of the engine to create. NULL or empty +Tk_RegisterStyleEngine( + CONST char *name, /* Name of the engine to create. NULL or empty * means the default system engine. */ - Tk_StyleEngine parent; /* The engine's parent. NULL means the default + Tk_StyleEngine parent) /* The engine's parent. NULL means the default * system engine. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashEntry *entryPtr; int newEntry; StyleEngine *enginePtr; /* - * Attempt to create a new entry in the engine table. + * Attempt to create a new entry in the engine table. */ - entryPtr = Tcl_CreateHashEntry(&tsdPtr->engineTable, (name?name:""), - &newEntry); + entryPtr = Tcl_CreateHashEntry(&tsdPtr->engineTable, + (name != NULL ? name : ""), &newEntry); if (!newEntry) { /* * An engine was already registered by that name. @@ -369,16 +357,16 @@ Tk_RegisterStyleEngine(name, parent) */ static void -InitStyleEngine(enginePtr, name, parentPtr) - StyleEngine *enginePtr; /* Points to an uninitialized engine. */ - CONST char *name; /* Name of the registered engine. NULL or empty +InitStyleEngine( + StyleEngine *enginePtr, /* Points to an uninitialized engine. */ + CONST char *name, /* Name of the registered engine. NULL or empty * means the default system engine. Usually * points to the hash key. */ - StyleEngine *parentPtr; /* The engine's parent. NULL means the default + StyleEngine *parentPtr) /* The engine's parent. NULL means the default * system engine. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); int elementId; if (name == NULL || *name == '\0') { @@ -399,8 +387,8 @@ InitStyleEngine(enginePtr, name, parentPtr) enginePtr->parentPtr = parentPtr; } - /* - * Allocate and initialize elements array. + /* + * Allocate and initialize elements array. */ if (tsdPtr->nbElements > 0) { @@ -431,11 +419,11 @@ InitStyleEngine(enginePtr, name, parentPtr) */ static void -FreeStyleEngine(enginePtr) - StyleEngine *enginePtr; /* The style engine to free. */ +FreeStyleEngine( + StyleEngine *enginePtr) /* The style engine to free. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); int elementId; /* @@ -465,19 +453,19 @@ FreeStyleEngine(enginePtr) */ Tk_StyleEngine -Tk_GetStyleEngine(name) - CONST char *name; /* Name of the engine to retrieve. NULL or +Tk_GetStyleEngine( + CONST char *name) /* Name of the engine to retrieve. NULL or * empty means the default system engine. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashEntry *entryPtr; if (name == NULL) { return (Tk_StyleEngine) tsdPtr->defaultEnginePtr; } - entryPtr = Tcl_FindHashEntry(&tsdPtr->engineTable, (name?name:"")); + entryPtr = Tcl_FindHashEntry(&tsdPtr->engineTable, (name!=NULL?name:"")); if (!entryPtr) { return NULL; } @@ -502,14 +490,14 @@ Tk_GetStyleEngine(name) */ static void -InitElement(elementPtr, name, id, genericId, created) - Element *elementPtr; /* Points to an uninitialized element.*/ - CONST char *name; /* Name of the registered element. Usually +InitElement( + Element *elementPtr, /* Points to an uninitialized element.*/ + CONST char *name, /* Name of the registered element. Usually * points to the hash key. */ - int id; /* Unique element ID. */ - int genericId; /* ID of generic element. -1 means none. */ - int created; /* Boolean, whether the element was created - * explicitly (was registered) or implicitly + int id, /* Unique element ID. */ + int genericId, /* ID of generic element. -1 means none. */ + int created) /* Boolean, whether the element was created + * explicitly (was registered) or implicitly * (by a derived element). */ { elementPtr->name = name; @@ -535,8 +523,8 @@ InitElement(elementPtr, name, id, genericId, created) */ static void -FreeElement(elementPtr) - Element *elementPtr; /* The element to free. */ +FreeElement( + Element *elementPtr) /* The element to free. */ { /* Nothing to do. */ } @@ -558,8 +546,8 @@ FreeElement(elementPtr) */ static void -InitStyledElement(elementPtr) - StyledElement *elementPtr; /* Points to an uninitialized element.*/ +InitStyledElement( + StyledElement *elementPtr) /* Points to an uninitialized element.*/ { memset(elementPtr, 0, sizeof(StyledElement)); } @@ -581,8 +569,8 @@ InitStyledElement(elementPtr) */ static void -FreeStyledElement(elementPtr) - StyledElement *elementPtr; /* The styled element to free. */ +FreeStyledElement( + StyledElement *elementPtr) /* The styled element to free. */ { int i; @@ -613,14 +601,14 @@ FreeStyledElement(elementPtr) */ static int -CreateElement(name, create) - CONST char *name; /* Name of the element. */ - int create; /* Boolean, whether the element is being created - * explicitly (being registered) or implicitly (by a +CreateElement( + CONST char *name, /* Name of the element. */ + int create) /* Boolean, whether the element is being created + * explicitly (being registered) or implicitly (by a * derived element). */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashEntry *entryPtr, *engineEntryPtr; Tcl_HashSearch search; int newEntry; @@ -634,7 +622,7 @@ CreateElement(name, create) entryPtr = Tcl_CreateHashEntry(&tsdPtr->elementTable, name, &newEntry); if (!newEntry) { - elementId = (int) Tcl_GetHashValue(entryPtr); + elementId = PTR2INT(Tcl_GetHashValue(entryPtr)); if (create) { tsdPtr->elements[elementId].created = 1; } @@ -642,8 +630,8 @@ CreateElement(name, create) } /* - * The element didn't exist. If it's a derived element, find or - * create its generic element ID. + * The element didn't exist. If it's a derived element, find or create its + * generic element ID. */ dot = strchr(name, '.'); @@ -652,15 +640,15 @@ CreateElement(name, create) } elementId = tsdPtr->nbElements++; - Tcl_SetHashValue(entryPtr, (ClientData) elementId); + Tcl_SetHashValue(entryPtr, (ClientData) INT2PTR(elementId)); /* * Reallocate element table. */ - tsdPtr->elements = (Element *) ckrealloc((char *) tsdPtr->elements, + tsdPtr->elements = (Element *) ckrealloc((char *) tsdPtr->elements, sizeof(Element) * tsdPtr->nbElements); - InitElement(tsdPtr->elements+elementId, + InitElement(tsdPtr->elements+elementId, Tcl_GetHashKey(&tsdPtr->elementTable, entryPtr), elementId, genericId, create); @@ -673,7 +661,7 @@ CreateElement(name, create) enginePtr = (StyleEngine *) Tcl_GetHashValue(engineEntryPtr); enginePtr->elements = (StyledElement *) ckrealloc( - (char *) enginePtr->elements, + (char *) enginePtr->elements, sizeof(StyledElement) * tsdPtr->nbElements); InitStyledElement(enginePtr->elements+elementId); @@ -700,11 +688,11 @@ CreateElement(name, create) */ int -Tk_GetElementId(name) - CONST char *name; /* Name of the element. */ +Tk_GetElementId( + CONST char *name) /* Name of the element. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashEntry *entryPtr; int genericId = -1; char *dot; @@ -715,11 +703,11 @@ Tk_GetElementId(name) entryPtr = Tcl_FindHashEntry(&tsdPtr->elementTable, name); if (entryPtr) { - return (int) Tcl_GetHashValue(entryPtr); + return PTR2INT(Tcl_GetHashValue(entryPtr)); } /* - * Element not found. If the given name was derived, then first search for + * Element not found. If the given name was derived, then first search for * the generic element. If found, create the new derived element. */ @@ -732,7 +720,7 @@ Tk_GetElementId(name) return -1; } if (!tsdPtr->elements[genericId].created) { - /* + /* * The generic element was created implicitly and thus has no real * existence. */ @@ -753,8 +741,8 @@ Tk_GetElementId(name) * * Tk_RegisterStyledElement -- * - * Register an implementation of a new or existing element for the - * given style engine. + * Register an implementation of a new or existing element for the given + * style engine. * * Results: * The unique ID for the created or found element. @@ -766,11 +754,11 @@ Tk_GetElementId(name) */ int -Tk_RegisterStyledElement(engine, templatePtr) - Tk_StyleEngine engine; /* Style engine providing the - * implementation. */ - Tk_ElementSpec *templatePtr; /* Static template information about - * the element. */ +Tk_RegisterStyledElement( + Tk_StyleEngine engine, /* Style engine providing the + * implementation. */ + Tk_ElementSpec *templatePtr)/* Static template information about the + * element. */ { int elementId; StyledElement *elementPtr; @@ -791,7 +779,7 @@ Tk_RegisterStyledElement(engine, templatePtr) } /* - * Register the element, allocating storage in the various engines if + * Register the element, allocating storage in the various engines if * necessary. */ @@ -809,13 +797,13 @@ Tk_RegisterStyledElement(engine, templatePtr) strcpy(specPtr->name, templatePtr->name); nbOptions = 0; for (nbOptions = 0, srcOptions = templatePtr->options; - srcOptions->name != NULL; - nbOptions++, srcOptions++); - specPtr->options = (Tk_ElementOptionSpec *) ckalloc( - sizeof(Tk_ElementOptionSpec) * (nbOptions+1)); + srcOptions->name != NULL; nbOptions++, srcOptions++) { + /* empty body */ + } + specPtr->options = (Tk_ElementOptionSpec *) + ckalloc(sizeof(Tk_ElementOptionSpec) * (nbOptions+1)); for (srcOptions = templatePtr->options, dstOptions = specPtr->options; - /* End condition within loop */; - srcOptions++, dstOptions++) { + /* End condition within loop */; srcOptions++, dstOptions++) { if (srcOptions->name == NULL) { dstOptions->name = NULL; break; @@ -842,8 +830,8 @@ Tk_RegisterStyledElement(engine, templatePtr) * * GetStyledElement -- * - * Get a registered implementation of an existing element for the - * given style engine. + * Get a registered implementation of an existing element for the given + * style engine. * * Results: * The styled element descriptor, or NULL if not found. @@ -855,12 +843,13 @@ Tk_RegisterStyledElement(engine, templatePtr) */ static StyledElement * -GetStyledElement(enginePtr, elementId) - StyleEngine *enginePtr; /* Style engine providing the implementation. +GetStyledElement( + StyleEngine *enginePtr, /* Style engine providing the implementation. * NULL means the default system engine. */ - int elementId; /* Unique element ID */{ + int elementId) /* Unique element ID */ +{ StyledElement *elementPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); StyleEngine *enginePtr2; @@ -913,11 +902,11 @@ GetStyledElement(enginePtr, elementId) */ static void -InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable) - StyledWidgetSpec *widgetSpecPtr; /* Points to an uninitialized widget - * spec. */ - StyledElement *elementPtr; /* Styled element descriptor. */ - Tk_OptionTable optionTable; /* The widget's option table. */ +InitWidgetSpec( + StyledWidgetSpec *widgetSpecPtr, + /* Points to an uninitialized widget spec. */ + StyledElement *elementPtr, /* Styled element descriptor. */ + Tk_OptionTable optionTable) /* The widget's option table. */ { int i, nbOptions; Tk_ElementOptionSpec *elementOptionPtr; @@ -925,33 +914,32 @@ InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable) widgetSpecPtr->elementPtr = elementPtr; widgetSpecPtr->optionTable = optionTable; - + /* * Count the number of options. */ - for (nbOptions = 0, elementOptionPtr = elementPtr->specPtr->options; - elementOptionPtr->name != NULL; - nbOptions++, elementOptionPtr++) { + for (nbOptions = 0, elementOptionPtr = elementPtr->specPtr->options; + elementOptionPtr->name != NULL; nbOptions++, elementOptionPtr++) { + /* empty body */ } /* * Build the widget option list. */ - widgetSpecPtr->optionsPtr = (CONST Tk_OptionSpec **) ckalloc( - sizeof(Tk_OptionSpec *) * nbOptions); - for (i = 0, elementOptionPtr = elementPtr->specPtr->options; - i < nbOptions; - i++, elementOptionPtr++) { + widgetSpecPtr->optionsPtr = (CONST Tk_OptionSpec **) + ckalloc(sizeof(Tk_OptionSpec *) * nbOptions); + for (i = 0, elementOptionPtr = elementPtr->specPtr->options; + i < nbOptions; i++, elementOptionPtr++) { widgetOptionPtr = TkGetOptionSpec(elementOptionPtr->name, optionTable); /* - * Check that the widget option type is compatible with one of the + * Check that the widget option type is compatible with one of the * element's required types. */ - if ( elementOptionPtr->type == TK_OPTION_END + if (elementOptionPtr->type == TK_OPTION_END || elementOptionPtr->type == widgetOptionPtr->type) { widgetSpecPtr->optionsPtr[i] = widgetOptionPtr; } else { @@ -977,8 +965,9 @@ InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable) */ static void -FreeWidgetSpec(widgetSpecPtr) - StyledWidgetSpec *widgetSpecPtr; /* The widget spec to free. */ +FreeWidgetSpec( + StyledWidgetSpec *widgetSpecPtr) + /* The widget spec to free. */ { ckfree((char *) widgetSpecPtr->optionsPtr); } @@ -988,8 +977,8 @@ FreeWidgetSpec(widgetSpecPtr) * * GetWidgetSpec -- * - * Return a new or existing widget spec for the given element and - * widget type (identified by its option table). + * Return a new or existing widget spec for the given element and widget + * type (identified by its option table). * * Results: * A pointer to the matching widget spec. @@ -1001,9 +990,9 @@ FreeWidgetSpec(widgetSpecPtr) */ static StyledWidgetSpec * -GetWidgetSpec(elementPtr, optionTable) - StyledElement *elementPtr; /* Styled element descriptor. */ - Tk_OptionTable optionTable; /* The widget's option table. */ +GetWidgetSpec( + StyledElement *elementPtr, /* Styled element descriptor. */ + Tk_OptionTable optionTable) /* The widget's option table. */ { StyledWidgetSpec *widgetSpecPtr; int i; @@ -1025,7 +1014,7 @@ GetWidgetSpec(elementPtr, optionTable) i = elementPtr->nbWidgetSpecs++; elementPtr->widgetSpecs = (StyledWidgetSpec *) ckrealloc( - (char *) elementPtr->widgetSpecs, + (char *) elementPtr->widgetSpecs, sizeof(StyledWidgetSpec) * elementPtr->nbWidgetSpecs); widgetSpecPtr = elementPtr->widgetSpecs+i; InitWidgetSpec(widgetSpecPtr, elementPtr, optionTable); @@ -1038,7 +1027,7 @@ GetWidgetSpec(elementPtr, optionTable) * * Tk_GetStyledElement -- * - * This procedure returns a styled instance of the given element. + * This function returns a styled instance of the given element. * * Results: * None. @@ -1050,10 +1039,10 @@ GetWidgetSpec(elementPtr, optionTable) */ Tk_StyledElement -Tk_GetStyledElement(style, elementId, optionTable) - Tk_Style style; /* The widget style. */ - int elementId; /* Unique element ID. */ - Tk_OptionTable optionTable; /* Option table for the widget. */ +Tk_GetStyledElement( + Tk_Style style, /* The widget style. */ + int elementId, /* Unique element ID. */ + Tk_OptionTable optionTable) /* Option table for the widget. */ { Style *stylePtr = (Style *) style; StyledElement *elementPtr; @@ -1062,7 +1051,7 @@ Tk_GetStyledElement(style, elementId, optionTable) * Get an element implementation and call corresponding hook. */ - elementPtr = GetStyledElement((stylePtr?stylePtr->enginePtr:NULL), + elementPtr = GetStyledElement((stylePtr?stylePtr->enginePtr:NULL), elementId); if (!elementPtr) { return NULL; @@ -1076,7 +1065,7 @@ Tk_GetStyledElement(style, elementId, optionTable) * * Tk_GetElementSize -- * - * This procedure computes the size of the given widget element according + * This function computes the size of the given widget element according * to its style. * * Results: @@ -1089,26 +1078,25 @@ Tk_GetStyledElement(style, elementId, optionTable) */ void -Tk_GetElementSize(style, element, recordPtr, tkwin, width, height, inner, widthPtr, - heightPtr) - Tk_Style style; /* The widget style. */ - Tk_StyledElement element; /* The styled element, previously - * returned by Tk_GetStyledElement. */ - char *recordPtr; /* The widget record. */ - Tk_Window tkwin; /* The widget window. */ - int width, height; /* Requested size. */ - int inner; /* Boolean. If TRUE, compute the outer - * size according to the requested - * minimum inner size. If FALSE, compute - * the inner size according to the - * requested maximum outer size. */ - int *widthPtr, *heightPtr; /* Returned size. */ +Tk_GetElementSize( + Tk_Style style, /* The widget style. */ + Tk_StyledElement element, /* The styled element, previously returned by + * Tk_GetStyledElement. */ + char *recordPtr, /* The widget record. */ + Tk_Window tkwin, /* The widget window. */ + int width, int height, /* Requested size. */ + int inner, /* If TRUE, compute the outer size according + * to the requested minimum inner size. If + * FALSE, compute the inner size according to + * the requested maximum outer size. */ + int *widthPtr, int *heightPtr) + /* Returned size. */ { Style *stylePtr = (Style *) style; StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element; - widgetSpecPtr->elementPtr->specPtr->getSize(stylePtr->clientData, - recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner, + widgetSpecPtr->elementPtr->specPtr->getSize(stylePtr->clientData, + recordPtr, widgetSpecPtr->optionsPtr, tkwin, width, height, inner, widthPtr, heightPtr); } @@ -1117,9 +1105,9 @@ Tk_GetElementSize(style, element, recordPtr, tkwin, width, height, inner, widthP * * Tk_GetElementBox -- * - * This procedure computes the bounding or inscribed box coordinates - * of the given widget element according to its style and within the - * given limits. + * This function computes the bounding or inscribed box coordinates of + * the given widget element according to its style and within the given + * limits. * * Results: * None. @@ -1131,29 +1119,27 @@ Tk_GetElementSize(style, element, recordPtr, tkwin, width, height, inner, widthP */ void -Tk_GetElementBox(style, element, recordPtr, tkwin, x, y, width, height, inner, - xPtr, yPtr, widthPtr, heightPtr) - Tk_Style style; /* The widget style. */ - Tk_StyledElement element; /* The styled element, previously - * returned by Tk_GetStyledElement. */ - char *recordPtr; /* The widget record. */ - Tk_Window tkwin; /* The widget window. */ - int x, y; /* Top left corner of available area. */ - int width, height; /* Size of available area. */ - int inner; /* Boolean. If TRUE, compute the - * bounding box according to the - * requested inscribed box size. If - * FALSE, compute the inscribed box - * according to the requested bounding - * box. */ - int *xPtr, *yPtr; /* Returned top left corner. */ - int *widthPtr, *heightPtr; /* Returned size. */ +Tk_GetElementBox( + Tk_Style style, /* The widget style. */ + Tk_StyledElement element, /* The styled element, previously returned by + * Tk_GetStyledElement. */ + char *recordPtr, /* The widget record. */ + Tk_Window tkwin, /* The widget window. */ + int x, int y, /* Top left corner of available area. */ + int width, int height, /* Size of available area. */ + int inner, /* Boolean. If TRUE, compute the bounding box + * according to the requested inscribed box + * size. If FALSE, compute the inscribed box + * according to the requested bounding box. */ + int *xPtr, int *yPtr, /* Returned top left corner. */ + int *widthPtr, int *heightPtr) + /* Returned size. */ { Style *stylePtr = (Style *) style; StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element; - widgetSpecPtr->elementPtr->specPtr->getBox(stylePtr->clientData, - recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height, + widgetSpecPtr->elementPtr->specPtr->getBox(stylePtr->clientData, + recordPtr, widgetSpecPtr->optionsPtr, tkwin, x, y, width, height, inner, xPtr, yPtr, widthPtr, heightPtr); } @@ -1162,7 +1148,7 @@ Tk_GetElementBox(style, element, recordPtr, tkwin, x, y, width, height, inner, * * Tk_GetElementBorderWidth -- * - * This procedure computes the border widthof the given widget element + * This function computes the border widthof the given widget element * according to its style and within the given limits. * * Results: @@ -1175,12 +1161,12 @@ Tk_GetElementBox(style, element, recordPtr, tkwin, x, y, width, height, inner, */ int -Tk_GetElementBorderWidth(style, element, recordPtr, tkwin) - Tk_Style style; /* The widget style. */ - Tk_StyledElement element; /* The styled element, previously - * returned by Tk_GetStyledElement. */ - char *recordPtr; /* The widget record. */ - Tk_Window tkwin; /* The widget window. */ +Tk_GetElementBorderWidth( + Tk_Style style, /* The widget style. */ + Tk_StyledElement element, /* The styled element, previously returned by + * Tk_GetStyledElement. */ + char *recordPtr, /* The widget record. */ + Tk_Window tkwin) /* The widget window. */ { Style *stylePtr = (Style *) style; StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element; @@ -1194,7 +1180,7 @@ Tk_GetElementBorderWidth(style, element, recordPtr, tkwin) * * Tk_DrawElement -- * - * This procedure draw the given widget element in a given drawable area. + * This function draw the given widget element in a given drawable area. * * Results: * None @@ -1206,22 +1192,22 @@ Tk_GetElementBorderWidth(style, element, recordPtr, tkwin) */ void -Tk_DrawElement(style, element, recordPtr, tkwin, d, x, y, width, height, state) - Tk_Style style; /* The widget style. */ - Tk_StyledElement element; /* The styled element, previously - * returned by Tk_GetStyledElement. */ - char *recordPtr; /* The widget record. */ - Tk_Window tkwin; /* The widget window. */ - Drawable d; /* Where to draw element. */ - int x, y; /* Top left corner of element. */ - int width, height; /* Size of element. */ - int state; /* Drawing state flags. */ +Tk_DrawElement( + Tk_Style style, /* The widget style. */ + Tk_StyledElement element, /* The styled element, previously returned by + * Tk_GetStyledElement. */ + char *recordPtr, /* The widget record. */ + Tk_Window tkwin, /* The widget window. */ + Drawable d, /* Where to draw element. */ + int x, int y, /* Top left corner of element. */ + int width, int height, /* Size of element. */ + int state) /* Drawing state flags. */ { Style *stylePtr = (Style *) style; StyledWidgetSpec *widgetSpecPtr = (StyledWidgetSpec *) element; - widgetSpecPtr->elementPtr->specPtr->draw(stylePtr->clientData, - recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width, + widgetSpecPtr->elementPtr->specPtr->draw(stylePtr->clientData, + recordPtr, widgetSpecPtr->optionsPtr, tkwin, d, x, y, width, height, state); } @@ -1230,37 +1216,36 @@ Tk_DrawElement(style, element, recordPtr, tkwin, d, x, y, width, height, state) * * Tk_CreateStyle -- * - * This procedure is called to create a new style as an instance of the + * This function is called to create a new style as an instance of the * given engine. Styles are stored in thread-local space. * * Results: - * The newly allocated style. + * The newly allocated style, or NULL if the style already exists. * * Side effects: - * Memory allocated. Data added to thread-local table. The style's - * refCount is incremented. + * Memory allocated. Data added to thread-local table. * *--------------------------------------------------------------------------- */ Tk_Style -Tk_CreateStyle(name, engine, clientData) - CONST char *name; /* Name of the style to create. NULL or empty +Tk_CreateStyle( + CONST char *name, /* Name of the style to create. NULL or empty * means the default system style. */ - Tk_StyleEngine engine; /* The style engine. */ - ClientData clientData; /* Private data passed as is to engine code. */ + Tk_StyleEngine engine, /* The style engine. */ + ClientData clientData) /* Private data passed as is to engine code. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashEntry *entryPtr; int newEntry; Style *stylePtr; /* - * Attempt to create a new entry in the style table. + * Attempt to create a new entry in the style table. */ - entryPtr = Tcl_CreateHashEntry(&tsdPtr->styleTable, (name?name:""), + entryPtr = Tcl_CreateHashEntry(&tsdPtr->styleTable, (name?name:""), &newEntry); if (!newEntry) { /* @@ -1275,10 +1260,11 @@ Tk_CreateStyle(name, engine, clientData) */ stylePtr = (Style *) ckalloc(sizeof(Style)); - InitStyle(stylePtr, entryPtr, Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr), - (engine?(StyleEngine *) engine:tsdPtr->defaultEnginePtr), clientData); + InitStyle(stylePtr, Tcl_GetHashKey(&tsdPtr->styleTable, entryPtr), + (engine != NULL ? (StyleEngine *) engine : + tsdPtr->defaultEnginePtr), + clientData); Tcl_SetHashValue(entryPtr, (ClientData) stylePtr); - stylePtr->refCount++; return (Tk_Style) stylePtr; } @@ -1291,9 +1277,9 @@ Tk_CreateStyle(name, engine, clientData) * Given a style, return its registered name. * * Results: - * The return value is the name that was passed to Tk_CreateStyle() to - * create the style. The storage for the returned string is private - * (it points to the corresponding hash key) The caller should not modify + * The return value is the name that was passed to Tk_CreateStyle() to + * create the style. The storage for the returned string is private (it + * points to the corresponding hash key) The caller should not modify * this string. * * Side effects: @@ -1303,8 +1289,8 @@ Tk_CreateStyle(name, engine, clientData) */ CONST char * -Tk_NameOfStyle(style) - Tk_Style style; /* Style whose name is desired. */ +Tk_NameOfStyle( + Tk_Style style) /* Style whose name is desired. */ { Style *stylePtr = (Style *) style; @@ -1328,17 +1314,14 @@ Tk_NameOfStyle(style) */ static void -InitStyle(stylePtr, hashPtr, name, enginePtr, clientData) - Style *stylePtr; /* Points to an uninitialized style. */ - Tcl_HashEntry *hashPtr; /* Hash entry for the registered style. */ - CONST char *name; /* Name of the registered style. NULL or empty +InitStyle( + Style *stylePtr, /* Points to an uninitialized style. */ + CONST char *name, /* Name of the registered style. NULL or empty * means the default system style. Usually * points to the hash key. */ - StyleEngine *enginePtr; /* The style engine. */ - ClientData clientData; /* Private data passed as is to engine code. */ + StyleEngine *enginePtr, /* The style engine. */ + ClientData clientData) /* Private data passed as is to engine code. */ { - stylePtr->refCount = 0; - stylePtr->hashPtr = hashPtr; stylePtr->name = name; stylePtr->enginePtr = enginePtr; stylePtr->clientData = clientData; @@ -1347,36 +1330,13 @@ InitStyle(stylePtr, hashPtr, name, enginePtr, clientData) /* *--------------------------------------------------------------------------- * - * FreeStyle -- - * - * Free a style and its associated data. - * - * Results: - * None - * - * Side effects: - * None. - * - *--------------------------------------------------------------------------- - */ - -static void -FreeStyle(stylePtr) - Style *stylePtr; /* The style to free. */ -{ - /* Nothing to do. */ -} - -/* - *--------------------------------------------------------------------------- - * * Tk_GetStyle -- * * Retrieve a registered style by its name. * * Results: - * A pointer to the style engine, or NULL if none found. In the latter - * case and if the interp is not NULL, an error message is left in the + * A pointer to the style engine, or NULL if none found. In the latter + * case and if the interp is not NULL, an error message is left in the * interp's result. * * Side effects: @@ -1386,29 +1346,29 @@ FreeStyle(stylePtr) */ Tk_Style -Tk_GetStyle(interp, name) - Tcl_Interp *interp; /* Interp for error return. */ - CONST char *name; /* Name of the style to retrieve. NULL or empty +Tk_GetStyle( + Tcl_Interp *interp, /* Interp for error return. */ + CONST char *name) /* Name of the style to retrieve. NULL or empty * means the default system style. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_HashEntry *entryPtr; Style *stylePtr; /* - * Search for a corresponding entry in the style table. + * Search for a corresponding entry in the style table. */ - entryPtr = Tcl_FindHashEntry(&tsdPtr->styleTable, (name?name:"")); + entryPtr = Tcl_FindHashEntry(&tsdPtr->styleTable, (name!=NULL?name:"")); if (entryPtr == NULL) { if (interp != NULL) { - Tcl_AppendResult(interp, "style \"", name, "\" doesn't exist", NULL); + Tcl_AppendResult(interp, "style \"", name, "\" doesn't exist", + NULL); } return (Tk_Style) NULL; } stylePtr = (Style *) Tcl_GetHashValue(entryPtr); - stylePtr->refCount++; return (Tk_Style) stylePtr; } @@ -1418,72 +1378,37 @@ Tk_GetStyle(interp, name) * * Tk_FreeStyle -- * - * Free a style previously created by Tk_CreateStyle. - * - * Results: - * None - * - * Side effects: - * The style's refCount is decremented. If it reaches zero, the style - * is freed. + * No-op. Present only for stubs compatibility. * *--------------------------------------------------------------------------- */ -void -Tk_FreeStyle(style) - Tk_Style style; /* The style to free. */ +void +Tk_FreeStyle( + Tk_Style style) { - Style *stylePtr = (Style *) style; - - if (stylePtr == NULL) { - return; - } - stylePtr->refCount--; - if (stylePtr->refCount > 0) { - return; - } - - /* - * Keep the default style alive. - */ - - if (*stylePtr->name == '\0') { - stylePtr->refCount = 1; - return; - } - - Tcl_DeleteHashEntry(stylePtr->hashPtr); - FreeStyle(stylePtr); - ckfree((char *) stylePtr); } /* *--------------------------------------------------------------------------- * - * Tk_AllocStyleFromObj -- + * Tk_AllocStyleFromObj -- * - * Map the string name of a style to a corresponding Tk_Style. The style + * Map the string name of a style to a corresponding Tk_Style. 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. If NULL is returned, an error message will be - * left in interp's result object. - * - * Side effects: - * The style's reference count is incremented. For each call to this - * procedure, there should eventually be a call to Tk_FreeStyle() or - * Tk_FreeStyleFromObj() so that the database is cleaned up when styles - * aren't in use anymore. + * The return value is a token for the style that matches objPtr, or NULL + * if none found. If NULL is returned, an error message will be left in + * interp's result object. * *--------------------------------------------------------------------------- */ Tk_Style -Tk_AllocStyleFromObj(interp, objPtr) - Tcl_Interp *interp; /* Interp for error return. */ - Tcl_Obj *objPtr; /* Object containing name of the style to +Tk_AllocStyleFromObj( + Tcl_Interp *interp, /* Interp for error return. */ + Tcl_Obj *objPtr) /* Object containing name of the style to * retrieve. */ { Style *stylePtr; @@ -1493,7 +1418,6 @@ Tk_AllocStyleFromObj(interp, objPtr) stylePtr = (Style *) objPtr->internalRep.otherValuePtr; } else { stylePtr = (Style *) objPtr->internalRep.otherValuePtr; - stylePtr->refCount++; } return (Tk_Style) stylePtr; @@ -1504,26 +1428,26 @@ Tk_AllocStyleFromObj(interp, objPtr) * * Tk_GetStyleFromObj -- * - * Find the style that corresponds to a given object. The style must - * have already been created by Tk_CreateStyle. + * 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. + * 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. + * If the object is not already a style ref, the conversion will free any + * old internal representation. * *---------------------------------------------------------------------- */ Tk_Style -Tk_GetStyleFromObj(objPtr) - Tcl_Obj *objPtr; /* The object from which to get the style. */ +Tk_GetStyleFromObj( + Tcl_Obj *objPtr) /* The object from which to get the style. */ { if (objPtr->typePtr != &styleObjType) { - SetStyleFromAny((Tcl_Interp *) NULL, objPtr); + SetStyleFromAny(NULL, objPtr); } return (Tk_Style) objPtr->internalRep.otherValuePtr; @@ -1532,27 +1456,16 @@ Tk_GetStyleFromObj(objPtr) /* *--------------------------------------------------------------------------- * - * Tk_FreeStyleFromObj -- + * Tk_FreeStyleFromObj -- * - * Called to release a style inside a Tcl_Obj *. - * - * Results: - * None. - * - * Side effects: - * If the object is a style ref, the conversion will free its - * internal representation. + * No-op. Present only for stubs compatibility. * *--------------------------------------------------------------------------- */ - void -Tk_FreeStyleFromObj(objPtr) - Tcl_Obj *objPtr; /* The Tcl_Obj * to be freed. */ +Tk_FreeStyleFromObj( + Tcl_Obj *objPtr) { - if (objPtr->typePtr == &styleObjType) { - FreeStyleObjProc(objPtr); - } } /* @@ -1560,31 +1473,29 @@ Tk_FreeStyleFromObj(objPtr) * * SetStyleFromAny -- * - * Convert the internal representation of a Tcl object to the - * style internal form. + * Convert the internal representation of a Tcl object to the style + * internal form. * * Results: - * Always returns TCL_OK. If an error occurs is returned (e.g. the - * style doesn't exist), an error message will be left in interp's - * result. + * 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. * * Side effects: * The object is left with its typePtr pointing to styleObjType. - * The reference count is incremented (in Tk_GetStyle()). * *---------------------------------------------------------------------- */ static int -SetStyleFromAny(interp, objPtr) - Tcl_Interp *interp; /* Used for error reporting if not NULL. */ - Tcl_Obj *objPtr; /* The object to convert. */ +SetStyleFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ { - Tcl_ObjType *typePtr; - char *name; + const Tcl_ObjType *typePtr; + const char *name; /* - * Free the old internalRep before setting the new one. + * Free the old internalRep before setting the new one. */ name = Tcl_GetString(objPtr); @@ -1602,61 +1513,49 @@ SetStyleFromAny(interp, objPtr) /* *--------------------------------------------------------------------------- * - * FreeStyleObjProc -- + * FreeStyleObjProc -- * - * This proc is called to release an object reference to a style. - * Called when the object's internal rep is released. + * This proc is called to release an object reference to a style. Called + * when the object's internal rep is released. * * Results: * None. * - * Side effects: - * The reference count is decremented (in Tk_FreeStyle()). - * *--------------------------------------------------------------------------- */ static void -FreeStyleObjProc(objPtr) - Tcl_Obj *objPtr; /* The object we are releasing. */ +FreeStyleObjProc( + Tcl_Obj *objPtr) /* The object we are releasing. */ { - Style *stylePtr = (Style *) objPtr->internalRep.otherValuePtr; - - if (stylePtr != NULL) { - Tk_FreeStyle((Tk_Style) stylePtr); - objPtr->internalRep.otherValuePtr = NULL; - } + objPtr->internalRep.otherValuePtr = NULL; + objPtr->typePtr = NULL; } /* *--------------------------------------------------------------------------- * - * DupStyleObjProc -- + * DupStyleObjProc -- * - * When a cached style object is duplicated, this is called to - * update the internal reps. - * - * Results: - * None. - * - * Side effects: - * The style's refCount is incremented and the internal rep of the copy - * is set to point to it. + * When a cached style object is duplicated, this is called to update the + * internal reps. * *--------------------------------------------------------------------------- */ static void -DupStyleObjProc(srcObjPtr, dupObjPtr) - Tcl_Obj *srcObjPtr; /* The object we are copying from. */ - Tcl_Obj *dupObjPtr; /* The object we are copying to. */ +DupStyleObjProc( + Tcl_Obj *srcObjPtr, /* The object we are copying from. */ + Tcl_Obj *dupObjPtr) /* The object we are copying to. */ { - Style *stylePtr = (Style *) srcObjPtr->internalRep.otherValuePtr; - dupObjPtr->typePtr = srcObjPtr->typePtr; - dupObjPtr->internalRep.otherValuePtr = (VOID *) stylePtr; - - if (stylePtr != NULL) { - stylePtr->refCount++; - } + dupObjPtr->internalRep.otherValuePtr=srcObjPtr->internalRep.otherValuePtr; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTest.c b/generic/tkTest.c index 0d6657a..639ed8d 100644 --- a/generic/tkTest.c +++ b/generic/tkTest.c @@ -1,28 +1,28 @@ -/* +/* * tkTest.c -- * - * This file contains C command procedures for a bunch of additional - * Tcl commands that are used for testing out Tcl's C interfaces. - * These commands are not normally included in Tcl applications; - * they're only used for testing. + * This file contains C command functions for a bunch of additional Tcl + * commands that are used for testing out Tcl's C interfaces. These + * commands are not normally included in Tcl applications; they're only + * used for testing. * * Copyright (c) 1993-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" #include "tkText.h" #ifdef __WIN32__ #include "tkWinInt.h" #endif -#if defined(MAC_TCL) || defined(MAC_OSX_TK) +#if defined(MAC_OSX_TK) +#include "tkMacOSXInt.h" #include "tkScrollbar.h" #endif @@ -31,8 +31,7 @@ #endif /* - * The following data structure represents the master for a test - * image: + * The following data structure represents the master for a test image: */ typedef struct TImageMaster { @@ -40,13 +39,13 @@ typedef struct TImageMaster { Tcl_Interp *interp; /* Interpreter for application. */ int width, height; /* Dimensions of image. */ char *imageName; /* Name of image (malloc-ed). */ - char *varName; /* Name of variable in which to log - * events for image (malloc-ed). */ + char *varName; /* Name of variable in which to log events for + * image (malloc-ed). */ } TImageMaster; /* - * The following data structure represents a particular use of a - * particular test image. + * The following data structure represents a particular use of a particular + * test image. */ typedef struct TImageInstance { @@ -59,43 +58,34 @@ typedef struct TImageInstance { * The type record for test images: */ -#ifdef USE_OLD_IMAGE -static int ImageCreate _ANSI_ARGS_((Tcl_Interp *interp, - char *name, int argc, char **argv, - Tk_ImageType *typePtr, Tk_ImageMaster master, - ClientData *clientDataPtr)); -#else -static int ImageCreate _ANSI_ARGS_((Tcl_Interp *interp, +static int ImageCreate(Tcl_Interp *interp, char *name, int argc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr, Tk_ImageMaster master, - ClientData *clientDataPtr)); -#endif -static ClientData ImageGet _ANSI_ARGS_((Tk_Window tkwin, - ClientData clientData)); -static void ImageDisplay _ANSI_ARGS_((ClientData clientData, - Display *display, Drawable drawable, + ClientData *clientDataPtr); +static ClientData ImageGet(Tk_Window tkwin, ClientData clientData); +static void ImageDisplay(ClientData clientData, + Display *display, Drawable drawable, int imageX, int imageY, int width, int height, int drawableX, - int drawableY)); -static void ImageFree _ANSI_ARGS_((ClientData clientData, - Display *display)); -static void ImageDelete _ANSI_ARGS_((ClientData clientData)); + int drawableY); +static void ImageFree(ClientData clientData, Display *display); +static void ImageDelete(ClientData clientData); static Tk_ImageType imageType = { "test", /* name */ - (Tk_ImageCreateProc *) ImageCreate, /* createProc */ + ImageCreate, /* createProc */ ImageGet, /* getProc */ ImageDisplay, /* displayProc */ ImageFree, /* freeProc */ ImageDelete, /* deleteProc */ - (Tk_ImagePostscriptProc *) NULL,/* postscriptPtr */ - (Tk_ImageType *) NULL /* nextPtr */ + NULL, /* postscriptPtr */ + NULL /* nextPtr */ }; /* - * One of the following structures describes each of the interpreters - * created by the "testnewapp" command. This information is used by - * the "testdeleteinterps" command to destroy all of those interpreters. + * One of the following structures describes each of the interpreters created + * by the "testnewapp" command. This information is used by the + * "testdeleteinterps" command to destroy all of those interpreters. */ typedef struct NewApp { @@ -103,15 +93,15 @@ typedef struct NewApp { struct NewApp *nextPtr; /* Next in list of new interpreters. */ } NewApp; -static NewApp *newAppPtr = NULL; - /* First in list of all new interpreters. */ +static NewApp *newAppPtr = NULL;/* First in list of all new interpreters. */ /* - * Declaration for the square widget's class command procedure: + * Declaration for the square widget's class command function: */ -extern int SquareObjCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[])); +extern int SquareObjCmd(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj * CONST objv[]); typedef struct CBinding { Tcl_Interp *interp; @@ -128,118 +118,114 @@ typedef struct CBinding { enum { NONE, - ODD_TYPE, + ODD_TYPE, EVEN_TYPE }; typedef struct TrivialCommandHeader { - Tcl_Interp *interp; /* The interp that this command - * lives in. */ - Tk_OptionTable optionTable; /* The option table that go with - * this command. */ - Tk_Window tkwin; /* For widgets, the window associated - * with this widget. */ - Tcl_Command widgetCmd; /* For widgets, the command associated - * with this widget. */ + Tcl_Interp *interp; /* The interp that this command lives in. */ + Tk_OptionTable optionTable; /* The option table that go with this + * command. */ + Tk_Window tkwin; /* For widgets, the window associated with + * this widget. */ + Tcl_Command widgetCmd; /* For widgets, the command associated with + * this widget. */ } TrivialCommandHeader; - - /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int CBindingEvalProc _ANSI_ARGS_((ClientData clientData, +static int CBindingEvalProc(ClientData clientData, Tcl_Interp *interp, XEvent *eventPtr, - Tk_Window tkwin, KeySym keySym)); -static void CBindingFreeProc _ANSI_ARGS_((ClientData clientData)); -int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp)); -static int ImageCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -static int TestcbindCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -static int TestbitmapObjCmd _ANSI_ARGS_((ClientData dummy, + Tk_Window tkwin, KeySym keySym); +static void CBindingFreeProc(ClientData clientData); +int Tktest_Init(Tcl_Interp *interp); +static int ImageCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); +static int TestcbindCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); +static int TestbitmapObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static int TestborderObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Obj * CONST objv[]); +static int TestborderObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static int TestcolorObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Obj * CONST objv[]); +static int TestcolorObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static int TestcursorObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Obj * CONST objv[]); +static int TestcursorObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static int TestdeleteappsCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -static int TestfontObjCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Obj * CONST objv[]); +static int TestdeleteappsCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); +static int TestfontObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[])); -static int TestmakeexistCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) -static int TestmenubarCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); + Tcl_Obj *CONST objv[]); +static int TestmakeexistCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +static int TestmenubarCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); #endif -#if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK) -static int TestmetricsCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); +#if defined(__WIN32__) || defined(MAC_OSX_TK) +static int TestmetricsCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); #endif -static int TestobjconfigObjCmd _ANSI_ARGS_((ClientData dummy, +static int TestobjconfigObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static int CustomOptionSet _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, Tk_Window tkwin, - Tcl_Obj **value, char *recordPtr, int internalOffset, - char *saveInternalPtr, int flags)); -static Tcl_Obj *CustomOptionGet _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *recordPtr, int internalOffset)); -static void CustomOptionRestore _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *internalPtr, - char *saveInternalPtr)); -static void CustomOptionFree _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *internalPtr)); -static int TestpropCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) -static int TestsendCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -#endif -static int TesttextCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) -static int TestwrapperCmd _ANSI_ARGS_((ClientData dummy, - Tcl_Interp *interp, int argc, CONST char **argv)); + Tcl_Obj * CONST objv[]); +static int CustomOptionSet(ClientData clientData, + Tcl_Interp *interp, Tk_Window tkwin, + Tcl_Obj **value, char *recordPtr, + int internalOffset, char *saveInternalPtr, + int flags); +static Tcl_Obj * CustomOptionGet(ClientData clientData, + Tk_Window tkwin, char *recordPtr, + int internalOffset); +static void CustomOptionRestore(ClientData clientData, + Tk_Window tkwin, char *internalPtr, + char *saveInternalPtr); +static void CustomOptionFree(ClientData clientData, + Tk_Window tkwin, char *internalPtr); +static int TestpropCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) +static int TestwrapperCmd(ClientData dummy, + Tcl_Interp *interp, int argc, CONST char **argv); #endif -static void TrivialCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static int TrivialConfigObjCmd _ANSI_ARGS_((ClientData dummy, +static void TrivialCmdDeletedProc(ClientData clientData); +static int TrivialConfigObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, - Tcl_Obj * CONST objv[])); -static void TrivialEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); + Tcl_Obj * CONST objv[]); +static void TrivialEventProc(ClientData clientData, + XEvent *eventPtr); /* * External (platform specific) initialization routine: */ -extern int TkplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp)); - -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) #define TkplatformtestInit(x) TCL_OK +#else +MODULE_SCOPE int TkplatformtestInit(Tcl_Interp *interp); #endif + +/* + * External legacy testing initialization routine: + */ +MODULE_SCOPE int TkOldTestInit(Tcl_Interp *interp); /* *---------------------------------------------------------------------- * * Tktest_Init -- * - * This procedure performs intialization for the Tk test - * suite exensions. + * This function performs intialization for the Tk test suite exensions. * * Results: - * Returns a standard Tcl completion code, and leaves an error - * message in the interp's result if an error occurs. + * Returns a standard Tcl completion code, and leaves an error message in + * the interp's result if an error occurs. * * Side effects: * Creates several test commands. @@ -248,8 +234,8 @@ extern int TkplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp)); */ int -Tktest_Init(interp) - Tcl_Interp *interp; /* Interpreter for application. */ +Tktest_Init( + Tcl_Interp *interp) /* Interpreter for application. */ { static int initialized = 0; @@ -262,47 +248,43 @@ Tktest_Init(interp) } Tcl_CreateObjCommand(interp, "square", SquareObjCmd, - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + (ClientData) NULL, NULL); Tcl_CreateCommand(interp, "testcbind", TestcbindCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testcursor", TestcursorObjCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateCommand(interp, "testdeleteapps", TestdeleteappsCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateCommand(interp, "testembed", TkpTestembedCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testobjconfig", TestobjconfigObjCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateCommand(interp, "testmakeexist", TestmakeexistCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) - Tcl_CreateCommand(interp, "testmenubar", TestmenubarCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#endif -#if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK) - Tcl_CreateCommand(interp, "testmetrics", TestmetricsCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#endif + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateCommand(interp, "testprop", TestpropCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) - Tcl_CreateCommand(interp, "testsend", TestsendCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#endif - Tcl_CreateCommand(interp, "testtext", TesttextCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) + (ClientData) Tk_MainWindow(interp), NULL); + Tcl_CreateCommand(interp, "testtext", TkpTesttextCmd, + (ClientData) Tk_MainWindow(interp), NULL); + +#if defined(__WIN32__) || defined(MAC_OSX_TK) + Tcl_CreateCommand(interp, "testmetrics", TestmetricsCmd, + (ClientData) Tk_MainWindow(interp), NULL); +#else + Tcl_CreateCommand(interp, "testmenubar", TestmenubarCmd, + (ClientData) Tk_MainWindow(interp), NULL); + Tcl_CreateCommand(interp, "testsend", TkpTestsendCmd, + (ClientData) Tk_MainWindow(interp), NULL); Tcl_CreateCommand(interp, "testwrapper", TestwrapperCmd, - (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL); -#endif + (ClientData) Tk_MainWindow(interp), NULL); +#endif /* __WIN32__ || MAC_OSX_TK */ /* * Create test image type. @@ -314,9 +296,17 @@ Tktest_Init(interp) } /* + * Enable testing of legacy interfaces. + */ + + if (TkOldTestInit(interp) != TCL_OK) { + return TCL_ERROR; + } + + /* * And finally add any platform specific test commands. */ - + return TkplatformtestInit(interp); } @@ -325,34 +315,34 @@ Tktest_Init(interp) * * TestcbindCmd -- * - * This procedure implements the "testcbinding" command. It provides - * a set of functions for testing C bindings in tkBind.c. + * This function implements the "testcbinding" command. It provides a set + * of functions for testing C bindings in tkBind.c. * * Results: * A standard Tcl result. * * Side effects: - * Depends on option; see below. + * Depends on option; see below. * *---------------------------------------------------------------------- */ static int -TestcbindCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestcbindCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { TkWindow *winPtr; Tk_Window tkwin; ClientData object; CBinding *cbindPtr; - - + + if (argc < 4 || argc > 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " bindtag pattern command ?deletecommand?", (char *) NULL); + " bindtag pattern command ?deletecommand?", NULL); return TCL_ERROR; } @@ -399,26 +389,26 @@ TestcbindCmd(clientData, interp, argc, argv) } static int -CBindingEvalProc(clientData, interp, eventPtr, tkwin, keySym) - ClientData clientData; - Tcl_Interp *interp; - XEvent *eventPtr; - Tk_Window tkwin; - KeySym keySym; +CBindingEvalProc( + ClientData clientData, + Tcl_Interp *interp, + XEvent *eventPtr, + Tk_Window tkwin, + KeySym keySym) { CBinding *cbindPtr; cbindPtr = (CBinding *) clientData; - + return Tcl_GlobalEval(interp, cbindPtr->command); } static void -CBindingFreeProc(clientData) - ClientData clientData; +CBindingFreeProc( + ClientData clientData) { CBinding *cbindPtr = (CBinding *) clientData; - + if (cbindPtr->delete != NULL) { Tcl_GlobalEval(cbindPtr->interp, cbindPtr->delete); ckfree((char *) cbindPtr->delete); @@ -432,8 +422,8 @@ CBindingFreeProc(clientData) * * TestbitmapObjCmd -- * - * This procedure implements the "testbitmap" command, which is used - * to test color resource handling in tkBitmap tmp.c. + * This function implements the "testbitmap" command, which is used to + * test color resource handling in tkBitmap tmp.c. * * Results: * A standard Tcl result. @@ -446,11 +436,11 @@ CBindingFreeProc(clientData) /* ARGSUSED */ static int -TestbitmapObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TestbitmapObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { if (objc < 2) { @@ -467,8 +457,8 @@ TestbitmapObjCmd(clientData, interp, objc, objv) * * TestborderObjCmd -- * - * This procedure implements the "testborder" command, which is used - * to test color resource handling in tkBorder.c. + * This function implements the "testborder" command, which is used to + * test color resource handling in tkBorder.c. * * Results: * A standard Tcl result. @@ -481,11 +471,11 @@ TestbitmapObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ static int -TestborderObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TestborderObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { if (objc < 2) { @@ -502,8 +492,8 @@ TestborderObjCmd(clientData, interp, objc, objv) * * TestcolorObjCmd -- * - * This procedure implements the "testcolor" command, which is used - * to test color resource handling in tkColor.c. + * This function implements the "testcolor" command, which is used to + * test color resource handling in tkColor.c. * * Results: * A standard Tcl result. @@ -516,13 +506,12 @@ TestborderObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ static int -TestcolorObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TestcolorObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "color"); return TCL_ERROR; @@ -537,8 +526,8 @@ TestcolorObjCmd(clientData, interp, objc, objv) * * TestcursorObjCmd -- * - * This procedure implements the "testcursor" command, which is used - * to test color resource handling in tkCursor.c. + * This function implements the "testcursor" command, which is used to + * test color resource handling in tkCursor.c. * * Results: * A standard Tcl result. @@ -551,13 +540,12 @@ TestcolorObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ static int -TestcursorObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TestcursorObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "cursor"); return TCL_ERROR; @@ -572,26 +560,26 @@ TestcursorObjCmd(clientData, interp, objc, objv) * * TestdeleteappsCmd -- * - * This procedure implements the "testdeleteapps" command. It cleans - * up all the interpreters left behind by the "testnewapp" command. + * This function implements the "testdeleteapps" command. It cleans up + * all the interpreters left behind by the "testnewapp" command. * * Results: * A standard Tcl result. * * Side effects: - * All the intepreters created by previous calls to "testnewapp" - * get deleted. + * All the intepreters created by previous calls to "testnewapp" get + * deleted. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int -TestdeleteappsCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestdeleteappsCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { NewApp *nextPtr; @@ -610,8 +598,8 @@ TestdeleteappsCmd(clientData, interp, argc, argv) * * TestobjconfigObjCmd -- * - * This procedure implements the "testobjconfig" command, - * which is used to test the procedures in tkConfig.c. + * This function implements the "testobjconfig" command, which is used to + * test the functions in tkConfig.c. * * Results: * A standard Tcl result. @@ -624,46 +612,40 @@ TestdeleteappsCmd(clientData, interp, argc, argv) /* ARGSUSED */ static int -TestobjconfigObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TestobjconfigObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - static CONST char *options[] = {"alltypes", "chain1", "chain2", - "configerror", "delete", "info", "internal", "new", - "notenoughparams", "twowindows", (char *) NULL}; + static CONST char *options[] = { + "alltypes", "chain1", "chain2", "configerror", "delete", "info", + "internal", "new", "notenoughparams", "twowindows", NULL + }; enum { - ALL_TYPES, - CHAIN1, - CHAIN2, - CONFIG_ERROR, + ALL_TYPES, CHAIN1, CHAIN2, CONFIG_ERROR, DEL, /* Can't use DELETE: VC++ compiler barfs. */ - INFO, - INTERNAL, - NEW, - NOT_ENOUGH_PARAMS, - TWO_WINDOWS + INFO, INTERNAL, NEW, NOT_ENOUGH_PARAMS, TWO_WINDOWS }; - static Tk_OptionTable tables[11]; /* Holds pointers to option tables - * created by commands below; indexed - * with same values as "options" - * array. */ + static Tk_OptionTable tables[11]; + /* Holds pointers to option tables created by + * commands below; indexed with same values as + * "options" array. */ static Tk_ObjCustomOption CustomOption = { "custom option", - CustomOptionSet, - CustomOptionGet, - CustomOptionRestore, - CustomOptionFree, - (ClientData) 1 + CustomOptionSet, + CustomOptionGet, + CustomOptionRestore, + CustomOptionFree, + (ClientData) 1 }; Tk_Window mainWin = (Tk_Window) clientData; Tk_Window tkwin; int index, result = TCL_OK; /* - * Structures used by the "chain1" subcommand and also shared by - * the "chain2" subcommand: + * Structures used by the "chain1" subcommand and also shared by the + * "chain2" subcommand: */ typedef struct ExtensionWidgetRecord { @@ -674,12 +656,10 @@ TestobjconfigObjCmd(clientData, interp, objc, objv) Tcl_Obj *extension4ObjPtr; Tcl_Obj *extension5ObjPtr; } ExtensionWidgetRecord; - static Tk_OptionSpec baseSpecs[] = { - {TK_OPTION_STRING, - "-one", "one", "One", "one", + static const Tk_OptionSpec baseSpecs[] = { + {TK_OPTION_STRING, "-one", "one", "One", "one", Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1}, - {TK_OPTION_STRING, - "-two", "two", "Two", "two", + {TK_OPTION_STRING, "-two", "two", "Two", "two", Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1}, {TK_OPTION_END} }; @@ -695,634 +675,551 @@ TestobjconfigObjCmd(clientData, interp, objc, objv) } switch (index) { - case ALL_TYPES: { - typedef struct TypesRecord { - TrivialCommandHeader header; - Tcl_Obj *booleanPtr; - Tcl_Obj *integerPtr; - Tcl_Obj *doublePtr; - Tcl_Obj *stringPtr; - Tcl_Obj *stringTablePtr; - Tcl_Obj *colorPtr; - Tcl_Obj *fontPtr; - Tcl_Obj *bitmapPtr; - Tcl_Obj *borderPtr; - Tcl_Obj *reliefPtr; - Tcl_Obj *cursorPtr; - Tcl_Obj *activeCursorPtr; - Tcl_Obj *justifyPtr; - Tcl_Obj *anchorPtr; - Tcl_Obj *pixelPtr; - Tcl_Obj *mmPtr; - Tcl_Obj *customPtr; - } TypesRecord; - TypesRecord *recordPtr; - static char *stringTable[] = {"one", "two", "three", "four", - (char *) NULL}; - static Tk_OptionSpec typesSpecs[] = { - {TK_OPTION_BOOLEAN, - "-boolean", "boolean", "Boolean", - "1", Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1}, - {TK_OPTION_INT, - "-integer", "integer", "Integer", - "7", Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2}, - {TK_OPTION_DOUBLE, - "-double", "double", "Double", - "3.14159", Tk_Offset(TypesRecord, doublePtr), -1, 0, 0, - 0x4}, - {TK_OPTION_STRING, - "-string", "string", "String", - "foo", Tk_Offset(TypesRecord, stringPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x8}, - {TK_OPTION_STRING_TABLE, - "-stringtable", "StringTable", "stringTable", - "one", Tk_Offset(TypesRecord, stringTablePtr), -1, - TK_CONFIG_NULL_OK, (ClientData) stringTable, 0x10}, - {TK_OPTION_COLOR, - "-color", "color", "Color", - "red", Tk_Offset(TypesRecord, colorPtr), -1, - TK_CONFIG_NULL_OK, (ClientData) "black", 0x20}, - {TK_OPTION_FONT, - "-font", "font", "Font", - "Helvetica 12", - Tk_Offset(TypesRecord, fontPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x40}, - {TK_OPTION_BITMAP, - "-bitmap", "bitmap", "Bitmap", - "gray50", - Tk_Offset(TypesRecord, bitmapPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x80}, - {TK_OPTION_BORDER, - "-border", "border", "Border", - "blue", Tk_Offset(TypesRecord, borderPtr), -1, - TK_CONFIG_NULL_OK, (ClientData) "white", 0x100}, - {TK_OPTION_RELIEF, - "-relief", "relief", "Relief", - "raised", - Tk_Offset(TypesRecord, reliefPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x200}, - {TK_OPTION_CURSOR, - "-cursor", "cursor", "Cursor", - "xterm", - Tk_Offset(TypesRecord, cursorPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x400}, - {TK_OPTION_JUSTIFY, - "-justify", (char *) NULL, (char *) NULL, - "left", - Tk_Offset(TypesRecord, justifyPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x800}, - {TK_OPTION_ANCHOR, - "-anchor", "anchor", "Anchor", - (char *) NULL, - Tk_Offset(TypesRecord, anchorPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x1000}, - {TK_OPTION_PIXELS, - "-pixel", "pixel", "Pixel", - "1", Tk_Offset(TypesRecord, pixelPtr), -1, - TK_CONFIG_NULL_OK, 0, 0x2000}, - {TK_OPTION_CUSTOM, - "-custom", (char *) NULL, (char *) NULL, - "", Tk_Offset(TypesRecord, customPtr), -1, - TK_CONFIG_NULL_OK, (ClientData)&CustomOption, 0x4000}, - {TK_OPTION_SYNONYM, - "-synonym", (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) "-color", - 0x8000}, - {TK_OPTION_END} - }; - Tk_OptionTable optionTable; - Tk_Window tkwin; - optionTable = Tk_CreateOptionTable(interp, - typesSpecs); - tables[index] = optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, - Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL); - if (tkwin == NULL) { - return TCL_ERROR; - } - Tk_SetClass(tkwin, "Test"); - - recordPtr = (TypesRecord *) ckalloc(sizeof(TypesRecord)); - recordPtr->header.interp = interp; - recordPtr->header.optionTable = optionTable; - recordPtr->header.tkwin = tkwin; - recordPtr->booleanPtr = NULL; - recordPtr->integerPtr = NULL; - recordPtr->doublePtr = NULL; - recordPtr->stringPtr = NULL; - recordPtr->colorPtr = NULL; - recordPtr->fontPtr = NULL; - recordPtr->bitmapPtr = NULL; - recordPtr->borderPtr = NULL; - recordPtr->reliefPtr = NULL; - recordPtr->cursorPtr = NULL; - recordPtr->justifyPtr = NULL; - recordPtr->anchorPtr = NULL; - recordPtr->pixelPtr = NULL; - recordPtr->mmPtr = NULL; - recordPtr->stringTablePtr = NULL; - recordPtr->customPtr = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, - tkwin); - if (result == TCL_OK) { - recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, - Tcl_GetStringFromObj(objv[2], NULL), - TrivialConfigObjCmd, (ClientData) recordPtr, - TrivialCmdDeletedProc); - Tk_CreateEventHandler(tkwin, StructureNotifyMask, - TrivialEventProc, (ClientData) recordPtr); - result = Tk_SetOptions(interp, (char *) recordPtr, - optionTable, objc - 3, objv + 3, tkwin, - (Tk_SavedOptions *) NULL, (int *) NULL); - if (result != TCL_OK) { - Tk_DestroyWindow(tkwin); - } - } else { + case ALL_TYPES: { + typedef struct TypesRecord { + TrivialCommandHeader header; + Tcl_Obj *booleanPtr; + Tcl_Obj *integerPtr; + Tcl_Obj *doublePtr; + Tcl_Obj *stringPtr; + Tcl_Obj *stringTablePtr; + Tcl_Obj *colorPtr; + Tcl_Obj *fontPtr; + Tcl_Obj *bitmapPtr; + Tcl_Obj *borderPtr; + Tcl_Obj *reliefPtr; + Tcl_Obj *cursorPtr; + Tcl_Obj *activeCursorPtr; + Tcl_Obj *justifyPtr; + Tcl_Obj *anchorPtr; + Tcl_Obj *pixelPtr; + Tcl_Obj *mmPtr; + Tcl_Obj *customPtr; + } TypesRecord; + TypesRecord *recordPtr; + static char *stringTable[] = { + "one", "two", "three", "four", NULL + }; + static const Tk_OptionSpec typesSpecs[] = { + {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1", + Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1}, + {TK_OPTION_INT, "-integer", "integer", "Integer", "7", + Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2}, + {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159", + Tk_Offset(TypesRecord, doublePtr), -1, 0, 0, 0x4}, + {TK_OPTION_STRING, "-string", "string", "String", + "foo", Tk_Offset(TypesRecord, stringPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x8}, + {TK_OPTION_STRING_TABLE, + "-stringtable", "StringTable", "stringTable", + "one", Tk_Offset(TypesRecord, stringTablePtr), -1, + TK_CONFIG_NULL_OK, (ClientData) stringTable, 0x10}, + {TK_OPTION_COLOR, "-color", "color", "Color", + "red", Tk_Offset(TypesRecord, colorPtr), -1, + TK_CONFIG_NULL_OK, (ClientData) "black", 0x20}, + {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12", + Tk_Offset(TypesRecord, fontPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x40}, + {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50", + Tk_Offset(TypesRecord, bitmapPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x80}, + {TK_OPTION_BORDER, "-border", "border", "Border", + "blue", Tk_Offset(TypesRecord, borderPtr), -1, + TK_CONFIG_NULL_OK, (ClientData) "white", 0x100}, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised", + Tk_Offset(TypesRecord, reliefPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x200}, + {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm", + Tk_Offset(TypesRecord, cursorPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x400}, + {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left", + Tk_Offset(TypesRecord, justifyPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x800}, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL, + Tk_Offset(TypesRecord, anchorPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x1000}, + {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", + "1", Tk_Offset(TypesRecord, pixelPtr), -1, + TK_CONFIG_NULL_OK, 0, 0x2000}, + {TK_OPTION_CUSTOM, "-custom", NULL, NULL, + "", Tk_Offset(TypesRecord, customPtr), -1, + TK_CONFIG_NULL_OK, (ClientData)&CustomOption, 0x4000}, + {TK_OPTION_SYNONYM, "-synonym", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-color", 0x8000}, + {TK_OPTION_END} + }; + Tk_OptionTable optionTable; + Tk_Window tkwin; + + optionTable = Tk_CreateOptionTable(interp, typesSpecs); + tables[index] = optionTable; + tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + Tcl_GetString(objv[2]), NULL); + if (tkwin == NULL) { + return TCL_ERROR; + } + Tk_SetClass(tkwin, "Test"); + + recordPtr = (TypesRecord *) ckalloc(sizeof(TypesRecord)); + recordPtr->header.interp = interp; + recordPtr->header.optionTable = optionTable; + recordPtr->header.tkwin = tkwin; + recordPtr->booleanPtr = NULL; + recordPtr->integerPtr = NULL; + recordPtr->doublePtr = NULL; + recordPtr->stringPtr = NULL; + recordPtr->colorPtr = NULL; + recordPtr->fontPtr = NULL; + recordPtr->bitmapPtr = NULL; + recordPtr->borderPtr = NULL; + recordPtr->reliefPtr = NULL; + recordPtr->cursorPtr = NULL; + recordPtr->justifyPtr = NULL; + recordPtr->anchorPtr = NULL; + recordPtr->pixelPtr = NULL; + recordPtr->mmPtr = NULL; + recordPtr->stringTablePtr = NULL; + recordPtr->customPtr = NULL; + result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, + tkwin); + if (result == TCL_OK) { + recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, + Tcl_GetString(objv[2]), TrivialConfigObjCmd, + (ClientData) recordPtr, TrivialCmdDeletedProc); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + TrivialEventProc, (ClientData) recordPtr); + result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + objc-3, objv+3, tkwin, NULL, NULL); + if (result != TCL_OK) { Tk_DestroyWindow(tkwin); - ckfree((char *) recordPtr); - } - if (result == TCL_OK) { - Tcl_SetObjResult(interp, objv[2]); } - break; + } else { + Tk_DestroyWindow(tkwin); + ckfree((char *) recordPtr); } + if (result == TCL_OK) { + Tcl_SetObjResult(interp, objv[2]); + } + break; + } - case CHAIN1: { - ExtensionWidgetRecord *recordPtr; - Tk_Window tkwin; - Tk_OptionTable optionTable; + case CHAIN1: { + ExtensionWidgetRecord *recordPtr; + Tk_Window tkwin; + Tk_OptionTable optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, - Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL); - if (tkwin == NULL) { - return TCL_ERROR; - } - Tk_SetClass(tkwin, "Test"); - optionTable = Tk_CreateOptionTable(interp, baseSpecs); - tables[index] = optionTable; - - recordPtr = (ExtensionWidgetRecord *) ckalloc( - sizeof(ExtensionWidgetRecord)); - recordPtr->header.interp = interp; - recordPtr->header.optionTable = optionTable; - recordPtr->header.tkwin = tkwin; - recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL; - recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, - tkwin); - if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, - objc - 3, objv + 3, tkwin, (Tk_SavedOptions *) NULL, - (int *) NULL); - if (result != TCL_OK) { - Tk_FreeConfigOptions((char *) recordPtr, optionTable, - tkwin); - } + tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + Tcl_GetString(objv[2]), NULL); + if (tkwin == NULL) { + return TCL_ERROR; + } + Tk_SetClass(tkwin, "Test"); + optionTable = Tk_CreateOptionTable(interp, baseSpecs); + tables[index] = optionTable; + + recordPtr = (ExtensionWidgetRecord *) + ckalloc(sizeof(ExtensionWidgetRecord)); + recordPtr->header.interp = interp; + recordPtr->header.optionTable = optionTable; + recordPtr->header.tkwin = tkwin; + recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL; + recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL; + result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin); + if (result == TCL_OK) { + result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + objc-3, objv+3, tkwin, NULL, NULL); + if (result != TCL_OK) { + Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin); } - if (result == TCL_OK) { - recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, - Tcl_GetStringFromObj(objv[2], NULL), - TrivialConfigObjCmd, (ClientData) recordPtr, - TrivialCmdDeletedProc); - Tk_CreateEventHandler(tkwin, StructureNotifyMask, - TrivialEventProc, (ClientData) recordPtr); - Tcl_SetObjResult(interp, objv[2]); + } + if (result == TCL_OK) { + recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, + Tcl_GetString(objv[2]), TrivialConfigObjCmd, + (ClientData) recordPtr, TrivialCmdDeletedProc); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + TrivialEventProc, (ClientData) recordPtr); + Tcl_SetObjResult(interp, objv[2]); + } + break; + } + + case CHAIN2: { + ExtensionWidgetRecord *recordPtr; + static const Tk_OptionSpec extensionSpecs[] = { + {TK_OPTION_STRING, "-three", "three", "Three", "three", + Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr), -1}, + {TK_OPTION_STRING, "-four", "four", "Four", "four", + Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr), -1}, + {TK_OPTION_STRING, "-two", "two", "Two", "two and a half", + Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1}, + {TK_OPTION_STRING, + "-oneAgain", "oneAgain", "OneAgain", "one again", + Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr), -1}, + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, + (ClientData) baseSpecs} + }; + Tk_Window tkwin; + Tk_OptionTable optionTable; + + tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + Tcl_GetString(objv[2]), NULL); + if (tkwin == NULL) { + return TCL_ERROR; + } + Tk_SetClass(tkwin, "Test"); + optionTable = Tk_CreateOptionTable(interp, extensionSpecs); + tables[index] = optionTable; + + recordPtr = (ExtensionWidgetRecord *) ckalloc( + sizeof(ExtensionWidgetRecord)); + recordPtr->header.interp = interp; + recordPtr->header.optionTable = optionTable; + recordPtr->header.tkwin = tkwin; + recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL; + recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL; + recordPtr->extension5ObjPtr = NULL; + result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin); + if (result == TCL_OK) { + result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + objc-3, objv+3, tkwin, NULL, NULL); + if (result != TCL_OK) { + Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin); } - break; } + if (result == TCL_OK) { + recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, + Tcl_GetString(objv[2]), TrivialConfigObjCmd, + (ClientData) recordPtr, TrivialCmdDeletedProc); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + TrivialEventProc, (ClientData) recordPtr); + Tcl_SetObjResult(interp, objv[2]); + } + break; + } - case CHAIN2: { - ExtensionWidgetRecord *recordPtr; - static Tk_OptionSpec extensionSpecs[] = { - {TK_OPTION_STRING, - "-three", "three", "Three", "three", - Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr), - -1}, - {TK_OPTION_STRING, - "-four", "four", "Four", "four", - Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr), - -1}, - {TK_OPTION_STRING, - "-two", "two", "Two", "two and a half", - Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), - -1}, - {TK_OPTION_STRING, - "-oneAgain", "oneAgain", "OneAgain", "one again", - Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr), - -1}, - {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, -1, 0, (ClientData) baseSpecs} - }; - Tk_Window tkwin; - Tk_OptionTable optionTable; + case CONFIG_ERROR: { + typedef struct ErrorWidgetRecord { + Tcl_Obj *intPtr; + } ErrorWidgetRecord; + ErrorWidgetRecord widgetRecord; + static const Tk_OptionSpec errorSpecs[] = { + {TK_OPTION_INT, "-int", "integer", "Integer", "bogus", + Tk_Offset(ErrorWidgetRecord, intPtr)}, + {TK_OPTION_END} + }; + Tk_OptionTable optionTable; + + widgetRecord.intPtr = NULL; + optionTable = Tk_CreateOptionTable(interp, errorSpecs); + tables[index] = optionTable; + return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable, + (Tk_Window) NULL); + } - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, - Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL); - if (tkwin == NULL) { - return TCL_ERROR; - } - Tk_SetClass(tkwin, "Test"); - optionTable = Tk_CreateOptionTable(interp, extensionSpecs); - tables[index] = optionTable; - - recordPtr = (ExtensionWidgetRecord *) ckalloc( - sizeof(ExtensionWidgetRecord)); - recordPtr->header.interp = interp; - recordPtr->header.optionTable = optionTable; - recordPtr->header.tkwin = tkwin; - recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL; - recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL; - recordPtr->extension5ObjPtr = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, - tkwin); - if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, - objc - 3, objv + 3, tkwin, (Tk_SavedOptions *) NULL, - (int *) NULL); - if (result != TCL_OK) { - Tk_FreeConfigOptions((char *) recordPtr, optionTable, - tkwin); - } - } - if (result == TCL_OK) { - recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, - Tcl_GetStringFromObj(objv[2], NULL), - TrivialConfigObjCmd, (ClientData) recordPtr, - TrivialCmdDeletedProc); - Tk_CreateEventHandler(tkwin, StructureNotifyMask, - TrivialEventProc, (ClientData) recordPtr); - Tcl_SetObjResult(interp, objv[2]); - } - break; + case DEL: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "tableName"); + return TCL_ERROR; } + if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (tables[index] != NULL) { + Tk_DeleteOptionTable(tables[index]); + } + break; - case CONFIG_ERROR: { - typedef struct ErrorWidgetRecord { - Tcl_Obj *intPtr; - } ErrorWidgetRecord; - ErrorWidgetRecord widgetRecord; - static Tk_OptionSpec errorSpecs[] = { - {TK_OPTION_INT, - "-int", "integer", "Integer", - "bogus", Tk_Offset(ErrorWidgetRecord, intPtr)}, - {TK_OPTION_END} - }; - Tk_OptionTable optionTable; - - widgetRecord.intPtr = NULL; - optionTable = Tk_CreateOptionTable(interp, errorSpecs); - tables[index] = optionTable; - return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable, - (Tk_Window) NULL); + case INFO: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "tableName"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0, + &index) != TCL_OK) { + return TCL_ERROR; } + Tcl_SetObjResult(interp, TkDebugConfig(interp, tables[index])); + break; - case DEL: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "tableName"); - return TCL_ERROR; - } - if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0, - &index) != TCL_OK) { - return TCL_ERROR; - } - if (tables[index] != NULL) { - Tk_DeleteOptionTable(tables[index]); + case INTERNAL: { + /* + * This command is similar to the "alltypes" command except that it + * stores all the configuration options as internal forms instead of + * objects. + */ + + typedef struct InternalRecord { + TrivialCommandHeader header; + int boolean; + int integer; + double doubleValue; + char *string; + int index; + XColor *colorPtr; + Tk_Font tkfont; + Pixmap bitmap; + Tk_3DBorder border; + int relief; + Tk_Cursor cursor; + Tk_Justify justify; + Tk_Anchor anchor; + int pixels; + double mm; + Tk_Window tkwin; + char *custom; + } InternalRecord; + InternalRecord *recordPtr; + static char *internalStringTable[] = { + "one", "two", "three", "four", NULL + }; + static const Tk_OptionSpec internalSpecs[] = { + {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1", + -1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1}, + {TK_OPTION_INT, "-integer", "integer", "Integer", "148962237", + -1, Tk_Offset(InternalRecord, integer), 0, 0, 0x2}, + {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159", + -1, Tk_Offset(InternalRecord, doubleValue), 0, 0, 0x4}, + {TK_OPTION_STRING, "-string", "string", "String", "foo", + -1, Tk_Offset(InternalRecord, string), + TK_CONFIG_NULL_OK, 0, 0x8}, + {TK_OPTION_STRING_TABLE, + "-stringtable", "StringTable", "stringTable", "one", + -1, Tk_Offset(InternalRecord, index), + TK_CONFIG_NULL_OK, (ClientData) internalStringTable, 0x10}, + {TK_OPTION_COLOR, "-color", "color", "Color", "red", + -1, Tk_Offset(InternalRecord, colorPtr), + TK_CONFIG_NULL_OK, (ClientData) "black", 0x20}, + {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12", + -1, Tk_Offset(InternalRecord, tkfont), + TK_CONFIG_NULL_OK, 0, 0x40}, + {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50", + -1, Tk_Offset(InternalRecord, bitmap), + TK_CONFIG_NULL_OK, 0, 0x80}, + {TK_OPTION_BORDER, "-border", "border", "Border", "blue", + -1, Tk_Offset(InternalRecord, border), + TK_CONFIG_NULL_OK, (ClientData) "white", 0x100}, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised", + -1, Tk_Offset(InternalRecord, relief), + TK_CONFIG_NULL_OK, 0, 0x200}, + {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm", + -1, Tk_Offset(InternalRecord, cursor), + TK_CONFIG_NULL_OK, 0, 0x400}, + {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left", + -1, Tk_Offset(InternalRecord, justify), + TK_CONFIG_NULL_OK, 0, 0x800}, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL, + -1, Tk_Offset(InternalRecord, anchor), + TK_CONFIG_NULL_OK, 0, 0x1000}, + {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", "1", + -1, Tk_Offset(InternalRecord, pixels), + TK_CONFIG_NULL_OK, 0, 0x2000}, + {TK_OPTION_WINDOW, "-window", "window", "Window", NULL, + -1, Tk_Offset(InternalRecord, tkwin), + TK_CONFIG_NULL_OK, 0, 0}, + {TK_OPTION_CUSTOM, "-custom", NULL, NULL, "", + -1, Tk_Offset(InternalRecord, custom), + TK_CONFIG_NULL_OK, (ClientData)&CustomOption, 0x4000}, + {TK_OPTION_SYNONYM, "-synonym", NULL, NULL, + NULL, -1, -1, 0, (ClientData) "-color", 0x8000}, + {TK_OPTION_END} + }; + Tk_OptionTable optionTable; + Tk_Window tkwin; + + optionTable = Tk_CreateOptionTable(interp, internalSpecs); + tables[index] = optionTable; + tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, + Tcl_GetString(objv[2]), NULL); + if (tkwin == NULL) { + return TCL_ERROR; + } + Tk_SetClass(tkwin, "Test"); + + recordPtr = (InternalRecord *) ckalloc(sizeof(InternalRecord)); + recordPtr->header.interp = interp; + recordPtr->header.optionTable = optionTable; + recordPtr->header.tkwin = tkwin; + recordPtr->boolean = 0; + recordPtr->integer = 0; + recordPtr->doubleValue = 0.0; + recordPtr->string = NULL; + recordPtr->index = 0; + recordPtr->colorPtr = NULL; + recordPtr->tkfont = NULL; + recordPtr->bitmap = None; + recordPtr->border = NULL; + recordPtr->relief = TK_RELIEF_FLAT; + recordPtr->cursor = NULL; + recordPtr->justify = TK_JUSTIFY_LEFT; + recordPtr->anchor = TK_ANCHOR_N; + recordPtr->pixels = 0; + recordPtr->mm = 0.0; + recordPtr->tkwin = NULL; + recordPtr->custom = NULL; + result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, + tkwin); + if (result == TCL_OK) { + recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, + Tcl_GetString(objv[2]), TrivialConfigObjCmd, + (ClientData) recordPtr, TrivialCmdDeletedProc); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + TrivialEventProc, (ClientData) recordPtr); + result = Tk_SetOptions(interp, (char *) recordPtr, optionTable, + objc - 3, objv + 3, tkwin, NULL, NULL); + if (result != TCL_OK) { + Tk_DestroyWindow(tkwin); } - break; + } else { + Tk_DestroyWindow(tkwin); + ckfree((char *) recordPtr); + } + if (result == TCL_OK) { + Tcl_SetObjResult(interp, objv[2]); } + break; + } - case INFO: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "tableName"); - return TCL_ERROR; - } - if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0, - &index) != TCL_OK) { - return TCL_ERROR; - } - Tcl_SetObjResult(interp, TkDebugConfig(interp, tables[index])); - break; + case NEW: { + typedef struct FiveRecord { + TrivialCommandHeader header; + Tcl_Obj *one; + Tcl_Obj *two; + Tcl_Obj *three; + Tcl_Obj *four; + Tcl_Obj *five; + } FiveRecord; + FiveRecord *recordPtr; + static const Tk_OptionSpec smallSpecs[] = { + {TK_OPTION_INT, "-one", "one", "One", "1", + Tk_Offset(FiveRecord, one), -1}, + {TK_OPTION_INT, "-two", "two", "Two", "2", + Tk_Offset(FiveRecord, two), -1}, + {TK_OPTION_INT, "-three", "three", "Three", "3", + Tk_Offset(FiveRecord, three), -1}, + {TK_OPTION_INT, "-four", "four", "Four", "4", + Tk_Offset(FiveRecord, four), -1}, + {TK_OPTION_STRING, "-five", NULL, NULL, NULL, + Tk_Offset(FiveRecord, five), -1}, + {TK_OPTION_END} + }; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "new name ?options?"); + return TCL_ERROR; } - case INTERNAL: { - /* - * This command is similar to the "alltypes" command except - * that it stores all the configuration options as internal - * forms instead of objects. - */ - - typedef struct InternalRecord { - TrivialCommandHeader header; - int boolean; - int integer; - double doubleValue; - char *string; - int index; - XColor *colorPtr; - Tk_Font tkfont; - Pixmap bitmap; - Tk_3DBorder border; - int relief; - Tk_Cursor cursor; - Tk_Justify justify; - Tk_Anchor anchor; - int pixels; - double mm; - Tk_Window tkwin; - char *custom; - } InternalRecord; - InternalRecord *recordPtr; - static char *internalStringTable[] = { - "one", "two", "three", "four", (char *) NULL - }; - static Tk_OptionSpec internalSpecs[] = { - {TK_OPTION_BOOLEAN, - "-boolean", "boolean", "Boolean", - "1", -1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1}, - {TK_OPTION_INT, - "-integer", "integer", "Integer", - "148962237", -1, Tk_Offset(InternalRecord, integer), - 0, 0, 0x2}, - {TK_OPTION_DOUBLE, - "-double", "double", "Double", - "3.14159", -1, Tk_Offset(InternalRecord, doubleValue), - 0, 0, 0x4}, - {TK_OPTION_STRING, - "-string", "string", "String", - "foo", -1, Tk_Offset(InternalRecord, string), - TK_CONFIG_NULL_OK, 0, 0x8}, - {TK_OPTION_STRING_TABLE, - "-stringtable", "StringTable", "stringTable", - "one", -1, Tk_Offset(InternalRecord, index), - TK_CONFIG_NULL_OK, (ClientData) internalStringTable, - 0x10}, - {TK_OPTION_COLOR, - "-color", "color", "Color", - "red", -1, Tk_Offset(InternalRecord, colorPtr), - TK_CONFIG_NULL_OK, (ClientData) "black", 0x20}, - {TK_OPTION_FONT, - "-font", "font", "Font", - "Helvetica 12", -1, Tk_Offset(InternalRecord, tkfont), - TK_CONFIG_NULL_OK, 0, 0x40}, - {TK_OPTION_BITMAP, - "-bitmap", "bitmap", "Bitmap", - "gray50", -1, Tk_Offset(InternalRecord, bitmap), - TK_CONFIG_NULL_OK, 0, 0x80}, - {TK_OPTION_BORDER, - "-border", "border", "Border", - "blue", -1, Tk_Offset(InternalRecord, border), - TK_CONFIG_NULL_OK, (ClientData) "white", 0x100}, - {TK_OPTION_RELIEF, - "-relief", "relief", "Relief", - "raised", -1, Tk_Offset(InternalRecord, relief), - TK_CONFIG_NULL_OK, 0, 0x200}, - {TK_OPTION_CURSOR, - "-cursor", "cursor", "Cursor", - "xterm", -1, Tk_Offset(InternalRecord, cursor), - TK_CONFIG_NULL_OK, 0, 0x400}, - {TK_OPTION_JUSTIFY, - "-justify", (char *) NULL, (char *) NULL, - "left", -1, Tk_Offset(InternalRecord, justify), - TK_CONFIG_NULL_OK, 0, 0x800}, - {TK_OPTION_ANCHOR, - "-anchor", "anchor", "Anchor", - (char *) NULL, -1, Tk_Offset(InternalRecord, anchor), - TK_CONFIG_NULL_OK, 0, 0x1000}, - {TK_OPTION_PIXELS, - "-pixel", "pixel", "Pixel", - "1", -1, Tk_Offset(InternalRecord, pixels), - TK_CONFIG_NULL_OK, 0, 0x2000}, - {TK_OPTION_WINDOW, - "-window", "window", "Window", - (char *) NULL, -1, Tk_Offset(InternalRecord, tkwin), - TK_CONFIG_NULL_OK, 0, 0}, - {TK_OPTION_CUSTOM, - "-custom", (char *) NULL, (char *) NULL, - "", -1, Tk_Offset(InternalRecord, custom), - TK_CONFIG_NULL_OK, (ClientData)&CustomOption, 0x4000}, - {TK_OPTION_SYNONYM, - "-synonym", (char *) NULL, (char *) NULL, - (char *) NULL, -1, -1, 0, (ClientData) "-color", - 0x8000}, - {TK_OPTION_END} - }; - Tk_OptionTable optionTable; - Tk_Window tkwin; - optionTable = Tk_CreateOptionTable(interp, internalSpecs); - tables[index] = optionTable; - tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, - Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL); - if (tkwin == NULL) { - return TCL_ERROR; - } - Tk_SetClass(tkwin, "Test"); - - recordPtr = (InternalRecord *) ckalloc(sizeof(InternalRecord)); - recordPtr->header.interp = interp; - recordPtr->header.optionTable = optionTable; - recordPtr->header.tkwin = tkwin; - recordPtr->boolean = 0; - recordPtr->integer = 0; - recordPtr->doubleValue = 0.0; - recordPtr->string = NULL; - recordPtr->index = 0; - recordPtr->colorPtr = NULL; - recordPtr->tkfont = NULL; - recordPtr->bitmap = None; - recordPtr->border = NULL; - recordPtr->relief = TK_RELIEF_FLAT; - recordPtr->cursor = NULL; - recordPtr->justify = TK_JUSTIFY_LEFT; - recordPtr->anchor = TK_ANCHOR_N; - recordPtr->pixels = 0; - recordPtr->mm = 0.0; - recordPtr->tkwin = NULL; - recordPtr->custom = NULL; - result = Tk_InitOptions(interp, (char *) recordPtr, optionTable, - tkwin); + recordPtr = (FiveRecord *) ckalloc(sizeof(FiveRecord)); + recordPtr->header.interp = interp; + recordPtr->header.optionTable = Tk_CreateOptionTable(interp, + smallSpecs); + tables[index] = recordPtr->header.optionTable; + recordPtr->header.tkwin = NULL; + recordPtr->one = recordPtr->two = recordPtr->three = NULL; + recordPtr->four = recordPtr->five = NULL; + Tcl_SetObjResult(interp, objv[2]); + result = Tk_InitOptions(interp, (char *) recordPtr, + recordPtr->header.optionTable, (Tk_Window) NULL); + if (result == TCL_OK) { + result = Tk_SetOptions(interp, (char *) recordPtr, + recordPtr->header.optionTable, objc - 3, objv + 3, + (Tk_Window) NULL, NULL, NULL); if (result == TCL_OK) { recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, - Tcl_GetStringFromObj(objv[2], NULL), - TrivialConfigObjCmd, (ClientData) recordPtr, - TrivialCmdDeletedProc); - Tk_CreateEventHandler(tkwin, StructureNotifyMask, - TrivialEventProc, (ClientData) recordPtr); - result = Tk_SetOptions(interp, (char *) recordPtr, - optionTable, objc - 3, objv + 3, tkwin, - (Tk_SavedOptions *) NULL, (int *) NULL); - if (result != TCL_OK) { - Tk_DestroyWindow(tkwin); - } + Tcl_GetString(objv[2]), TrivialConfigObjCmd, + (ClientData) recordPtr, TrivialCmdDeletedProc); } else { - Tk_DestroyWindow(tkwin); - ckfree((char *) recordPtr); + Tk_FreeConfigOptions((char *) recordPtr, + recordPtr->header.optionTable, (Tk_Window) NULL); } - if (result == TCL_OK) { - Tcl_SetObjResult(interp, objv[2]); - } - break; + } + if (result != TCL_OK) { + ckfree((char *) recordPtr); } - case NEW: { - typedef struct FiveRecord { - TrivialCommandHeader header; - Tcl_Obj *one; - Tcl_Obj *two; - Tcl_Obj *three; - Tcl_Obj *four; - Tcl_Obj *five; - } FiveRecord; - FiveRecord *recordPtr; - static Tk_OptionSpec smallSpecs[] = { - {TK_OPTION_INT, - "-one", "one", "One", - "1", - Tk_Offset(FiveRecord, one), -1}, - {TK_OPTION_INT, - "-two", "two", "Two", - "2", - Tk_Offset(FiveRecord, two), -1}, - {TK_OPTION_INT, - "-three", "three", "Three", - "3", - Tk_Offset(FiveRecord, three), -1}, - {TK_OPTION_INT, - "-four", "four", "Four", - "4", - Tk_Offset(FiveRecord, four), -1}, - {TK_OPTION_STRING, - "-five", NULL, NULL, - NULL, - Tk_Offset(FiveRecord, five), -1}, - {TK_OPTION_END} - }; - - if (objc < 3) { - Tcl_WrongNumArgs(interp, 1, objv, "new name ?options?"); - return TCL_ERROR; - } + break; + } + case NOT_ENOUGH_PARAMS: { + typedef struct NotEnoughRecord { + Tcl_Obj *fooObjPtr; + } NotEnoughRecord; + NotEnoughRecord record; + static const Tk_OptionSpec errorSpecs[] = { + {TK_OPTION_INT, "-foo", "foo", "Foo", "0", + Tk_Offset(NotEnoughRecord, fooObjPtr)}, + {TK_OPTION_END} + }; + Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1); + Tk_OptionTable optionTable; + + record.fooObjPtr = NULL; + + tkwin = Tk_CreateWindowFromPath(interp, mainWin, ".config", NULL); + Tk_SetClass(tkwin, "Config"); + optionTable = Tk_CreateOptionTable(interp, errorSpecs); + tables[index] = optionTable; + Tk_InitOptions(interp, (char *) &record, optionTable, tkwin); + if (Tk_SetOptions(interp, (char *) &record, optionTable, 1, + &newObjPtr, tkwin, NULL, NULL) != TCL_OK) { + result = TCL_ERROR; + } + Tcl_DecrRefCount(newObjPtr); + Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin); + Tk_DestroyWindow(tkwin); + return result; + } - recordPtr = (FiveRecord *) ckalloc(sizeof(FiveRecord)); - recordPtr->header.interp = interp; - recordPtr->header.optionTable = Tk_CreateOptionTable(interp, - smallSpecs); - tables[index] = recordPtr->header.optionTable; - recordPtr->header.tkwin = NULL; - recordPtr->one = recordPtr->two = recordPtr->three = NULL; - recordPtr->four = recordPtr->five = NULL; - Tcl_SetObjResult(interp, objv[2]); - result = Tk_InitOptions(interp, (char *) recordPtr, - recordPtr->header.optionTable, (Tk_Window) NULL); - if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, - recordPtr->header.optionTable, objc - 3, objv + 3, - (Tk_Window) NULL, (Tk_SavedOptions *) NULL, - (int *) NULL); - if (result == TCL_OK) { - recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, - Tcl_GetStringFromObj(objv[2], NULL), - TrivialConfigObjCmd, (ClientData) recordPtr, - TrivialCmdDeletedProc); - } else { - Tk_FreeConfigOptions((char *) recordPtr, - recordPtr->header.optionTable, (Tk_Window) NULL); - } - } - if (result != TCL_OK) { - ckfree((char *) recordPtr); - } + case TWO_WINDOWS: { + typedef struct SlaveRecord { + TrivialCommandHeader header; + Tcl_Obj *windowPtr; + } SlaveRecord; + SlaveRecord *recordPtr; + static const Tk_OptionSpec slaveSpecs[] = { + {TK_OPTION_WINDOW, "-window", "window", "Window", ".bar", + Tk_Offset(SlaveRecord, windowPtr), -1, TK_CONFIG_NULL_OK}, + {TK_OPTION_END} + }; + Tk_Window tkwin = Tk_CreateWindowFromPath(interp, + (Tk_Window) clientData, Tcl_GetString(objv[2]), NULL); - break; - } - case NOT_ENOUGH_PARAMS: { - typedef struct NotEnoughRecord { - Tcl_Obj *fooObjPtr; - } NotEnoughRecord; - NotEnoughRecord record; - static Tk_OptionSpec errorSpecs[] = { - {TK_OPTION_INT, - "-foo", "foo", "Foo", - "0", Tk_Offset(NotEnoughRecord, fooObjPtr)}, - {TK_OPTION_END} - }; - Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1); - Tk_OptionTable optionTable; - - record.fooObjPtr = NULL; - - tkwin = Tk_CreateWindowFromPath(interp, mainWin, - ".config", (char *) NULL); - Tk_SetClass(tkwin, "Config"); - optionTable = Tk_CreateOptionTable(interp, errorSpecs); - tables[index] = optionTable; - Tk_InitOptions(interp, (char *) &record, optionTable, tkwin); - if (Tk_SetOptions(interp, (char *) &record, optionTable, - 1, &newObjPtr, tkwin, (Tk_SavedOptions *) NULL, - (int *) NULL) - != TCL_OK) { - result = TCL_ERROR; - } - Tcl_DecrRefCount(newObjPtr); - Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin); - Tk_DestroyWindow(tkwin); - return result; + if (tkwin == NULL) { + return TCL_ERROR; } - - case TWO_WINDOWS: { - typedef struct SlaveRecord { - TrivialCommandHeader header; - Tcl_Obj *windowPtr; - } SlaveRecord; - SlaveRecord *recordPtr; - static Tk_OptionSpec slaveSpecs[] = { - {TK_OPTION_WINDOW, - "-window", "window", "Window", - ".bar", Tk_Offset(SlaveRecord, windowPtr), -1, - TK_CONFIG_NULL_OK}, - {TK_OPTION_END} - }; - Tk_Window tkwin = Tk_CreateWindowFromPath(interp, - (Tk_Window) clientData, - Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL); - if (tkwin == NULL) { - return TCL_ERROR; - } - Tk_SetClass(tkwin, "Test"); - - recordPtr = (SlaveRecord *) ckalloc(sizeof(SlaveRecord)); - recordPtr->header.interp = interp; - recordPtr->header.optionTable = Tk_CreateOptionTable(interp, - slaveSpecs); - tables[index] = recordPtr->header.optionTable; - recordPtr->header.tkwin = tkwin; - recordPtr->windowPtr = NULL; - - result = Tk_InitOptions(interp, (char *) recordPtr, - recordPtr->header.optionTable, tkwin); + Tk_SetClass(tkwin, "Test"); + + recordPtr = (SlaveRecord *) ckalloc(sizeof(SlaveRecord)); + recordPtr->header.interp = interp; + recordPtr->header.optionTable = Tk_CreateOptionTable(interp, + slaveSpecs); + tables[index] = recordPtr->header.optionTable; + recordPtr->header.tkwin = tkwin; + recordPtr->windowPtr = NULL; + + result = Tk_InitOptions(interp, (char *) recordPtr, + recordPtr->header.optionTable, tkwin); + if (result == TCL_OK) { + result = Tk_SetOptions(interp, (char *) recordPtr, + recordPtr->header.optionTable, objc - 3, objv + 3, + tkwin, NULL, NULL); if (result == TCL_OK) { - result = Tk_SetOptions(interp, (char *) recordPtr, - recordPtr->header.optionTable, objc - 3, objv + 3, - tkwin, (Tk_SavedOptions *) NULL, (int *) NULL); - if (result == TCL_OK) { - recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, - Tcl_GetStringFromObj(objv[2], NULL), - TrivialConfigObjCmd, (ClientData) recordPtr, - TrivialCmdDeletedProc); - Tk_CreateEventHandler(tkwin, StructureNotifyMask, - TrivialEventProc, (ClientData) recordPtr); - Tcl_SetObjResult(interp, objv[2]); - } else { - Tk_FreeConfigOptions((char *) recordPtr, - recordPtr->header.optionTable, tkwin); - } - } - if (result != TCL_OK) { - Tk_DestroyWindow(tkwin); - ckfree((char *) recordPtr); + recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, + Tcl_GetString(objv[2]), TrivialConfigObjCmd, + (ClientData) recordPtr, TrivialCmdDeletedProc); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + TrivialEventProc, (ClientData) recordPtr); + Tcl_SetObjResult(interp, objv[2]); + } else { + Tk_FreeConfigOptions((char *) recordPtr, + recordPtr->header.optionTable, tkwin); } - + } + if (result != TCL_OK) { + Tk_DestroyWindow(tkwin); + ckfree((char *) recordPtr); } } + } return result; } @@ -1346,15 +1243,15 @@ TestobjconfigObjCmd(clientData, interp, objc, objv) /* ARGSUSED */ static int -TrivialConfigObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TrivialConfigObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { int result = TCL_OK; static CONST char *options[] = { - "cget", "configure", "csave", (char *) NULL + "cget", "configure", "csave", NULL }; enum { CGET, CONFIGURE, CSAVE @@ -1370,69 +1267,66 @@ TrivialConfigObjCmd(clientData, interp, objc, objv) return TCL_ERROR; } - if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", - 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, + &index) != TCL_OK) { return TCL_ERROR; } Tcl_Preserve(clientData); - + switch (index) { - case CGET: { - if (objc != 3) { - Tcl_WrongNumArgs(interp, 2, objv, "option"); + case CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + result = TCL_ERROR; + goto done; + } + resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData, + headerPtr->optionTable, objv[2], tkwin); + if (resultObjPtr != NULL) { + Tcl_SetObjResult(interp, resultObjPtr); + result = TCL_OK; + } else { + result = TCL_ERROR; + } + break; + case CONFIGURE: + if (objc == 2) { + resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, + headerPtr->optionTable, NULL, tkwin); + if (resultObjPtr == NULL) { result = TCL_ERROR; - goto done; + } else { + Tcl_SetObjResult(interp, resultObjPtr); } - resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData, + } else if (objc == 3) { + resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, headerPtr->optionTable, objv[2], tkwin); - if (resultObjPtr != NULL) { - Tcl_SetObjResult(interp, resultObjPtr); - result = TCL_OK; - } else { + if (resultObjPtr == NULL) { result = TCL_ERROR; - } - break; - } - case CONFIGURE: { - if (objc == 2) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, - headerPtr->optionTable, (Tcl_Obj *) NULL, tkwin); - if (resultObjPtr == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, resultObjPtr); - } - } else if (objc == 3) { - resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, - headerPtr->optionTable, objv[2], tkwin); - if (resultObjPtr == NULL) { - result = TCL_ERROR; - } else { - Tcl_SetObjResult(interp, resultObjPtr); - } } else { - result = Tk_SetOptions(interp, (char *) clientData, - headerPtr->optionTable, objc - 2, objv + 2, - tkwin, (Tk_SavedOptions *) NULL, &mask); - if (result == TCL_OK) { - Tcl_SetIntObj(Tcl_GetObjResult(interp), mask); - } + Tcl_SetObjResult(interp, resultObjPtr); } - break; - } - case CSAVE: { + } else { result = Tk_SetOptions(interp, (char *) clientData, - headerPtr->optionTable, objc - 2, objv + 2, - tkwin, &saved, &mask); - Tk_FreeSavedOptions(&saved); + headerPtr->optionTable, objc - 2, objv + 2, + tkwin, NULL, &mask); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), mask); } - break; } + break; + case CSAVE: + result = Tk_SetOptions(interp, (char *) clientData, + headerPtr->optionTable, objc - 2, objv + 2, + tkwin, &saved, &mask); + Tk_FreeSavedOptions(&saved); + if (result == TCL_OK) { + Tcl_SetIntObj(Tcl_GetObjResult(interp), mask); + } + break; } -done: + done: Tcl_Release(clientData); return result; } @@ -1442,9 +1336,9 @@ done: * * TrivialCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -1456,8 +1350,8 @@ done: */ static void -TrivialCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +TrivialCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData; Tk_Window tkwin = headerPtr->tkwin; @@ -1466,9 +1360,9 @@ TrivialCmdDeletedProc(clientData) Tk_DestroyWindow(tkwin); } else if (headerPtr->optionTable != NULL) { /* - * This is a "new" object, which doesn't have a window, so - * we can't depend on cleaning up in the event procedure. - * Free its resources here. + * This is a "new" object, which doesn't have a window, so we can't + * depend on cleaning up in the event function. Free its resources + * here. */ Tk_FreeConfigOptions((char *) clientData, @@ -1488,16 +1382,15 @@ TrivialCmdDeletedProc(clientData) * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. + * When the window gets deleted, internal structures get cleaned up. * *-------------------------------------------------------------- */ static void -TrivialEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - XEvent *eventPtr; /* Information about event. */ +TrivialEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData; @@ -1519,8 +1412,8 @@ TrivialEventProc(clientData, eventPtr) * * TestfontObjCmd -- * - * This procedure implements the "testfont" command, which is used - * to test TkFont objects. + * This function implements the "testfont" command, which is used to test + * TkFont objects. * * Results: * A standard Tcl result. @@ -1533,18 +1426,18 @@ TrivialEventProc(clientData, eventPtr) /* ARGSUSED */ static int -TestfontObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +TestfontObjCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - static CONST char *options[] = {"counts", "subfonts", (char *) NULL}; + static CONST char *options[] = {"counts", "subfonts", NULL}; enum option {COUNTS, SUBFONTS}; int index; Tk_Window tkwin; Tk_Font tkfont; - + tkwin = (Tk_Window) clientData; if (objc < 3) { @@ -1558,20 +1451,18 @@ TestfontObjCmd(clientData, interp, objc, objv) } switch ((enum option) index) { - case COUNTS: { - Tcl_SetObjResult(interp, TkDebugFont(Tk_MainWindow(interp), - Tcl_GetString(objv[2]))); - break; - } - case SUBFONTS: { - tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); - if (tkfont == NULL) { - return TCL_ERROR; - } - TkpGetSubFonts(interp, tkfont); - Tk_FreeFont(tkfont); - break; + case COUNTS: + Tcl_SetObjResult(interp, + TkDebugFont(Tk_MainWindow(interp), Tcl_GetString(objv[2]))); + break; + case SUBFONTS: + tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]); + if (tkfont == NULL) { + return TCL_ERROR; } + TkpGetSubFonts(interp, tkfont); + Tk_FreeFont(tkfont); + break; } return TCL_OK; @@ -1582,8 +1473,7 @@ TestfontObjCmd(clientData, interp, objc, objv) * * ImageCreate -- * - * This procedure is called by the Tk image code to create "test" - * images. + * This function is called by the Tk image code to create "test" images. * * Results: * A standard Tcl result. @@ -1595,54 +1485,19 @@ TestfontObjCmd(clientData, interp, objc, objv) */ /* ARGSUSED */ -#ifdef USE_OLD_IMAGE -static int -ImageCreate(interp, name, argc, argv, typePtr, master, clientDataPtr) - Tcl_Interp *interp; /* Interpreter for application containing - * image. */ - char *name; /* Name to use for image. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings for options (doesn't - * include image name or type). */ - Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ - Tk_ImageMaster master; /* Token for image, to be used by us in - * later callbacks. */ - ClientData *clientDataPtr; /* Store manager's token for image here; - * it will be returned in later callbacks. */ -{ - TImageMaster *timPtr; - char *varName; - int i; - - Tk_InitImageArgs(interp, argc, &argv); - varName = "log"; - for (i = 0; i < argc; i += 2) { - if (strcmp(argv[i], "-variable") != 0) { - Tcl_AppendResult(interp, "bad option name \"", - argv[i], "\"", (char *) NULL); - return TCL_ERROR; - } - if ((i+1) == argc) { - Tcl_AppendResult(interp, "no value given for \"", - argv[i], "\" option", (char *) NULL); - return TCL_ERROR; - } - varName = argv[i+1]; - } -#else static int -ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) - Tcl_Interp *interp; /* Interpreter for application containing +ImageCreate( + Tcl_Interp *interp, /* Interpreter for application containing * image. */ - char *name; /* Name to use for image. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument strings for options (doesn't + char *name, /* Name to use for image. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument strings for options (doesn't * include image name or type). */ - Tk_ImageType *typePtr; /* Pointer to our type record (not used). */ - Tk_ImageMaster master; /* Token for image, to be used by us in - * later callbacks. */ - ClientData *clientDataPtr; /* Store manager's token for image here; - * it will be returned in later callbacks. */ + Tk_ImageType *typePtr, /* Pointer to our type record (not used). */ + Tk_ImageMaster master, /* Token for image, to be used by us in later + * callbacks. */ + ClientData *clientDataPtr) /* Store manager's token for image here; it + * will be returned in later callbacks. */ { TImageMaster *timPtr; char *varName; @@ -1652,17 +1507,17 @@ ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) for (i = 0; i < objc; i += 2) { if (strcmp(Tcl_GetString(objv[i]), "-variable") != 0) { Tcl_AppendResult(interp, "bad option name \"", - Tcl_GetString(objv[i]), "\"", (char *) NULL); + Tcl_GetString(objv[i]), "\"", NULL); return TCL_ERROR; } if ((i+1) == objc) { Tcl_AppendResult(interp, "no value given for \"", - Tcl_GetString(objv[i]), "\" option", (char *) NULL); + Tcl_GetString(objv[i]), "\" option", NULL); return TCL_ERROR; } varName = Tcl_GetString(objv[i+1]); } -#endif + timPtr = (TImageMaster *) ckalloc(sizeof(TImageMaster)); timPtr->master = master; timPtr->interp = interp; @@ -1672,8 +1527,7 @@ ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) strcpy(timPtr->imageName, name); timPtr->varName = (char *) ckalloc((unsigned) (strlen(varName) + 1)); strcpy(timPtr->varName, varName); - Tcl_CreateCommand(interp, name, ImageCmd, (ClientData) timPtr, - (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, name, ImageCmd, (ClientData) timPtr, NULL); *clientDataPtr = (ClientData) timPtr; Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15); return TCL_OK; @@ -1684,8 +1538,8 @@ ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) * * ImageCmd -- * - * This procedure implements the commands corresponding to individual - * images. + * This function implements the commands corresponding to individual + * images. * * Results: * A standard Tcl result. @@ -1698,26 +1552,24 @@ ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr) /* ARGSUSED */ static int -ImageCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +ImageCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { TImageMaster *timPtr = (TImageMaster *) clientData; int x, y, width, height; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], "option ?arg arg ...?", (char *) NULL); + argv[0], "option ?arg arg ...?", NULL); return TCL_ERROR; } if (strcmp(argv[1], "changed") == 0) { if (argc != 8) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], - " changed x y width height imageWidth imageHeight", - (char *) NULL); + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " changed x y width height imageWidth imageHeight", NULL); return TCL_ERROR; } if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) @@ -1732,7 +1584,7 @@ ImageCmd(clientData, interp, argc, argv) timPtr->height); } else { Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be changed", (char *) NULL); + "\": must be changed", NULL); return TCL_ERROR; } return TCL_OK; @@ -1743,12 +1595,12 @@ ImageCmd(clientData, interp, argc, argv) * * ImageGet -- * - * This procedure is called by Tk to set things up for using a - * test image in a particular widget. + * This function is called by Tk to set things up for using a test image + * in a particular widget. * * Results: - * The return value is a token for the image instance, which is - * used in future callbacks to ImageDisplay and ImageFree. + * The return value is a token for the image instance, which is used in + * future callbacks to ImageDisplay and ImageFree. * * Side effects: * None. @@ -1757,10 +1609,10 @@ ImageCmd(clientData, interp, argc, argv) */ static ClientData -ImageGet(tkwin, clientData) - Tk_Window tkwin; /* Token for window in which image will - * be used. */ - ClientData clientData; /* Pointer to TImageMaster for image. */ +ImageGet( + Tk_Window tkwin, /* Token for window in which image will be + * used. */ + ClientData clientData) /* Pointer to TImageMaster for image. */ { TImageMaster *timPtr = (TImageMaster *) clientData; TImageInstance *instPtr; @@ -1784,29 +1636,29 @@ ImageGet(tkwin, clientData) * * ImageDisplay -- * - * This procedure is invoked to redisplay part or all of an - * image in a given drawable. + * This function is invoked to redisplay part or all of an image in a + * given drawable. * * Results: * None. * * Side effects: - * The image gets partially redrawn, as an "X" that shows the - * exact redraw area. + * The image gets partially redrawn, as an "X" that shows the exact + * redraw area. * *---------------------------------------------------------------------- */ static void -ImageDisplay(clientData, display, drawable, imageX, imageY, width, height, - drawableX, drawableY) - ClientData clientData; /* Pointer to TImageInstance for image. */ - Display *display; /* Display to use for drawing. */ - Drawable drawable; /* Where to redraw image. */ - int imageX, imageY; /* Origin of area to redraw, relative to +ImageDisplay( + ClientData clientData, /* Pointer to TImageInstance for image. */ + Display *display, /* Display to use for drawing. */ + Drawable drawable, /* Where to redraw image. */ + int imageX, int imageY, /* Origin of area to redraw, relative to * origin of image. */ - int width, height; /* Dimensions of area to redraw. */ - int drawableX, drawableY; /* Coordinates in drawable corresponding to + int width, int height, /* Dimensions of area to redraw. */ + int drawableX, int drawableY) + /* Coordinates in drawable corresponding to * imageX and imageY. */ { TImageInstance *instPtr = (TImageInstance *) clientData; @@ -1837,8 +1689,8 @@ ImageDisplay(clientData, display, drawable, imageX, imageY, width, height, * * ImageFree -- * - * This procedure is called when an instance of an image is - * no longer used. + * This function is called when an instance of an image is no longer + * used. * * Results: * None. @@ -1850,9 +1702,9 @@ ImageDisplay(clientData, display, drawable, imageX, imageY, width, height, */ static void -ImageFree(clientData, display) - ClientData clientData; /* Pointer to TImageInstance for instance. */ - Display *display; /* Display where image was to be drawn. */ +ImageFree( + ClientData clientData, /* Pointer to TImageInstance for instance. */ + Display *display) /* Display where image was to be drawn. */ { TImageInstance *instPtr = (TImageInstance *) clientData; char buffer[200]; @@ -1870,8 +1722,8 @@ ImageFree(clientData, display) * * ImageDelete -- * - * This procedure is called to clean up a test image when - * an application goes away. + * This function is called to clean up a test image when an application + * goes away. * * Results: * None. @@ -1883,10 +1735,10 @@ ImageFree(clientData, display) */ static void -ImageDelete(clientData) - ClientData clientData; /* Pointer to TImageMaster for image. When - * this procedure is called, no more - * instances exist. */ +ImageDelete( + ClientData clientData) /* Pointer to TImageMaster for image. When + * this function is called, no more instances + * exist. */ { TImageMaster *timPtr = (TImageMaster *) clientData; char buffer[100]; @@ -1906,9 +1758,9 @@ ImageDelete(clientData) * * TestmakeexistCmd -- * - * This procedure implements the "testmakeexist" command. It calls - * Tk_MakeWindowExist on each of its arguments to force the windows - * to be created. + * This function implements the "testmakeexist" command. It calls + * Tk_MakeWindowExist on each of its arguments to force the windows to be + * created. * * Results: * A standard Tcl result. @@ -1921,11 +1773,11 @@ ImageDelete(clientData) /* ARGSUSED */ static int -TestmakeexistCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestmakeexistCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { Tk_Window mainWin = (Tk_Window) clientData; int i; @@ -1947,9 +1799,9 @@ TestmakeexistCmd(clientData, interp, argc, argv) * * TestmenubarCmd -- * - * This procedure implements the "testmenubar" command. It is used - * to test the Unix facilities for creating space above a toplevel - * window for a menubar. + * This function implements the "testmenubar" command. It is used to test + * the Unix facilities for creating space above a toplevel window for a + * menubar. * * Results: * A standard Tcl result. @@ -1961,13 +1813,13 @@ TestmakeexistCmd(clientData, interp, argc, argv) */ /* ARGSUSED */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) static int -TestmenubarCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestmenubarCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { #ifdef __UNIX__ Tk_Window mainWin = (Tk_Window) clientData; @@ -1975,14 +1827,14 @@ TestmenubarCmd(clientData, interp, argc, argv) if (argc < 2) { Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option ?arg ...?\"", (char *) NULL); + " option ?arg ...?\"", NULL); return TCL_ERROR; } if (strcmp(argv[1], "window") == 0) { if (argc != 4) { Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - "window toplevel menubar\"", (char *) NULL); + "window toplevel menubar\"", NULL); return TCL_ERROR; } tkwin = Tk_NameToWindow(interp, argv[2], mainWin); @@ -2000,7 +1852,7 @@ TestmenubarCmd(clientData, interp, argc, argv) } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be window", (char *) NULL); + "\": must be window", NULL); return TCL_ERROR; } @@ -2018,8 +1870,8 @@ TestmenubarCmd(clientData, interp, argc, argv) * * TestmetricsCmd -- * - * This procedure implements the testmetrics command. It provides - * a way to determine the size of various widget components. + * This function implements the testmetrics command. It provides a way to + * determine the size of various widget components. * * Results: * A standard Tcl result. @@ -2030,13 +1882,13 @@ TestmenubarCmd(clientData, interp, argc, argv) *---------------------------------------------------------------------- */ -#if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK) +#if defined(__WIN32__) || defined(MAC_OSX_TK) static int -TestmetricsCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestmetricsCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { char buf[TCL_INTEGER_SPACE]; int val; @@ -2044,7 +1896,7 @@ TestmetricsCmd(clientData, interp, argc, argv) #ifdef __WIN32__ if (argc < 2) { Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option ?arg ...?\"", (char *) NULL); + " option ?arg ...?\"", NULL); return TCL_ERROR; } #else @@ -2053,7 +1905,7 @@ TestmetricsCmd(clientData, interp, argc, argv) if (argc != 3) { Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option window\"", (char *) NULL); + " option window\"", NULL); return TCL_ERROR; } @@ -2077,11 +1929,11 @@ TestmetricsCmd(clientData, interp, argc, argv) #endif } else { Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be cxhscroll or cyvscroll", (char *) NULL); + "\": must be cxhscroll or cyvscroll", NULL); return TCL_ERROR; } sprintf(buf, "%d", val); - Tcl_AppendResult(interp, buf, (char *) NULL); + Tcl_AppendResult(interp, buf, NULL); return TCL_OK; } #endif @@ -2091,8 +1943,8 @@ TestmetricsCmd(clientData, interp, argc, argv) * * TestpropCmd -- * - * This procedure implements the "testprop" command. It fetches - * and prints the value of a property on a window. + * This function implements the "testprop" command. It fetches and prints + * the value of a property on a window. * * Results: * A standard Tcl result. @@ -2105,23 +1957,24 @@ TestmetricsCmd(clientData, interp, argc, argv) /* ARGSUSED */ static int -TestpropCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestpropCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { Tk_Window mainWin = (Tk_Window) clientData; int result, actualFormat; unsigned long bytesAfter, length, value; Atom actualType, propName; - char *property, *p, *end; + unsigned char *property, *p; + char *end; Window w; char buffer[30]; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " window property\"", (char *) NULL); + " window property\"", NULL); return TCL_ERROR; } @@ -2131,7 +1984,7 @@ TestpropCmd(clientData, interp, argc, argv) result = XGetWindowProperty(Tk_Display(mainWin), w, propName, 0, 100000, False, AnyPropertyType, &actualType, &actualFormat, &length, - &bytesAfter, (unsigned char **) &property); + &bytesAfter, &property); if ((result == Success) && (actualType != None)) { if ((actualFormat == 8) && (actualType == XA_STRING)) { for (p = property; ((unsigned long)(p-property)) < length; p++) { @@ -2139,7 +1992,7 @@ TestpropCmd(clientData, interp, argc, argv) *p = '\n'; } } - Tcl_SetResult(interp, property, TCL_VOLATILE); + Tcl_SetResult(interp, (/*!unsigned*/char*)property, TCL_VOLATILE); } else { for (p = property; length > 0; length--) { if (actualFormat == 32) { @@ -2163,209 +2016,15 @@ TestpropCmd(clientData, interp, argc, argv) return TCL_OK; } -/* - *---------------------------------------------------------------------- - * - * TestsendCmd -- - * - * This procedure implements the "testsend" command. It provides - * a set of functions for testing the "send" command and support - * procedure in tkSend.c. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Depends on option; see below. - * - *---------------------------------------------------------------------- - */ - - /* ARGSUSED */ -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) -static int -TestsendCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ -{ - TkWindow *winPtr = (TkWindow *) clientData; - - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " option ?arg ...?\"", (char *) NULL); - return TCL_ERROR; - } - - if (strcmp(argv[1], "bogus") == 0) { - XChangeProperty(winPtr->dispPtr->display, - RootWindow(winPtr->dispPtr->display, 0), - winPtr->dispPtr->registryProperty, XA_INTEGER, 32, - PropModeReplace, - (unsigned char *) "This is bogus information", 6); - } else if (strcmp(argv[1], "prop") == 0) { - int result, actualFormat; - unsigned long length, bytesAfter; - Atom actualType, propName; - char *property, *p, *end; - Window w; - - if ((argc != 4) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " prop window name ?value ?\"", (char *) NULL); - return TCL_ERROR; - } - if (strcmp(argv[2], "root") == 0) { - w = RootWindow(winPtr->dispPtr->display, 0); - } else if (strcmp(argv[2], "comm") == 0) { - w = Tk_WindowId(winPtr->dispPtr->commTkwin); - } else { - w = strtoul(argv[2], &end, 0); - } - propName = Tk_InternAtom((Tk_Window) winPtr, argv[3]); - if (argc == 4) { - property = NULL; - result = XGetWindowProperty(winPtr->dispPtr->display, - w, propName, 0, 100000, False, XA_STRING, - &actualType, &actualFormat, &length, - &bytesAfter, (unsigned char **) &property); - if ((result == Success) && (actualType != None) - && (actualFormat == 8) && (actualType == XA_STRING)) { - for (p = property; (p-property) < length; p++) { - if (*p == 0) { - *p = '\n'; - } - } - Tcl_SetResult(interp, property, TCL_VOLATILE); - } - if (property != NULL) { - XFree(property); - } - } else { - if (argv[4][0] == 0) { - XDeleteProperty(winPtr->dispPtr->display, w, propName); - } else { - Tcl_DString tmp; - - Tcl_DStringInit(&tmp); - for (p = Tcl_DStringAppend(&tmp, argv[4], - (int) strlen(argv[4])); - *p != 0; p++) { - if (*p == '\n') { - *p = 0; - } - } - - XChangeProperty(winPtr->dispPtr->display, - w, propName, XA_STRING, 8, PropModeReplace, - (unsigned char *) Tcl_DStringValue(&tmp), - p-Tcl_DStringValue(&tmp)); - Tcl_DStringFree(&tmp); - } - } - } else if (strcmp(argv[1], "serial") == 0) { - char buf[TCL_INTEGER_SPACE]; - - sprintf(buf, "%d", tkSendSerial+1); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be bogus, prop, or serial", (char *) NULL); - return TCL_ERROR; - } - return TCL_OK; -} -#endif - -/* - *---------------------------------------------------------------------- - * - * TesttextCmd -- - * - * This procedure implements the "testtext" command. It provides - * a set of functions for testing text widgets and the associated - * functions in tkText*.c. - * - * Results: - * A standard Tcl result. - * - * Side effects: - * Depends on option; see below. - * - *---------------------------------------------------------------------- - */ - -static int -TesttextCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ -{ - TkText *textPtr; - size_t len; - int lineIndex, byteIndex, byteOffset; - TkTextIndex index; - char buf[64]; - Tcl_CmdInfo info; - - if (argc < 3) { - return TCL_ERROR; - } - - if (Tcl_GetCommandInfo(interp, argv[1], &info) == 0) { - return TCL_ERROR; - } - textPtr = (TkText *) info.clientData; - len = strlen(argv[2]); - if (strncmp(argv[2], "byteindex", len) == 0) { - if (argc != 5) { - return TCL_ERROR; - } - lineIndex = atoi(argv[3]) - 1; - byteIndex = atoi(argv[4]); - - TkTextMakeByteIndex(textPtr->tree, lineIndex, byteIndex, &index); - } else if (strncmp(argv[2], "forwbytes", len) == 0) { - if (argc != 5) { - return TCL_ERROR; - } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { - return TCL_ERROR; - } - byteOffset = atoi(argv[4]); - TkTextIndexForwBytes(&index, byteOffset, &index); - } else if (strncmp(argv[2], "backbytes", len) == 0) { - if (argc != 5) { - return TCL_ERROR; - } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { - return TCL_ERROR; - } - byteOffset = atoi(argv[4]); - TkTextIndexBackBytes(&index, byteOffset, &index); - } else { - return TCL_ERROR; - } - - TkTextSetMark(textPtr, "insert", &index); - TkTextPrintIndex(&index, buf); - sprintf(buf + strlen(buf), " %d", index.byteIndex); - Tcl_AppendResult(interp, buf, NULL); - - return TCL_OK; -} - -#if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* *---------------------------------------------------------------------- * * TestwrapperCmd -- * - * This procedure implements the "testwrapper" command. It - * provides a way from Tcl to determine the extra window Tk adds - * in between the toplevel window and the window decorations. + * This function implements the "testwrapper" command. It provides a way + * from Tcl to determine the extra window Tk adds in between the toplevel + * window and the window decorations. * * Results: * A standard Tcl result. @@ -2378,21 +2037,21 @@ TesttextCmd(clientData, interp, argc, argv) /* ARGSUSED */ static int -TestwrapperCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window for application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TestwrapperCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { TkWindow *winPtr, *wrapperPtr; Tk_Window tkwin; if (argc != 2) { Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0], - " window\"", (char *) NULL); + " window\"", NULL); return TCL_ERROR; } - + tkwin = (Tk_Window) clientData; winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin); if (winPtr == NULL) { @@ -2415,7 +2074,7 @@ TestwrapperCmd(clientData, interp, argc, argv) * * CustomOptionSet, CustomOptionGet, CustomOptionRestore, CustomOptionFree -- * - * Handlers for object-based custom configuration options. See + * Handlers for object-based custom configuration options. See * Testobjconfigcommand. * * Results: @@ -2437,20 +2096,19 @@ TestwrapperCmd(clientData, interp, argc, argv) */ static int -CustomOptionSet(clientData,interp, tkwin, value, recordPtr, internalOffset, - saveInternalPtr, flags) - ClientData clientData; - Tcl_Interp *interp; - Tk_Window tkwin; - Tcl_Obj **value; - char *recordPtr; - int internalOffset; - char *saveInternalPtr; - int flags; +CustomOptionSet( + ClientData clientData, + Tcl_Interp *interp, + Tk_Window tkwin, + Tcl_Obj **value, + char *recordPtr, + int internalOffset, + char *saveInternalPtr, + int flags) { int objEmpty, length; - char *new, *string, *internalPtr; - + char *newStr, *string, *internalPtr; + objEmpty = 0; if (internalOffset >= 0) { @@ -2458,21 +2116,20 @@ CustomOptionSet(clientData,interp, tkwin, value, recordPtr, internalOffset, } else { internalPtr = NULL; } - + /* * See if the object is empty. */ + if (value == NULL) { objEmpty = 1; + } else if ((*value)->bytes != NULL) { + objEmpty = ((*value)->length == 0); } else { - if ((*value)->bytes != NULL) { - objEmpty = ((*value)->length == 0); - } else { - Tcl_GetStringFromObj((*value), &length); - objEmpty = (length == 0); - } + Tcl_GetStringFromObj((*value), &length); + objEmpty = (length == 0); } - + if ((flags & TK_OPTION_NULL_OK) && objEmpty) { *value = NULL; } else { @@ -2487,47 +2144,54 @@ CustomOptionSet(clientData,interp, tkwin, value, recordPtr, internalOffset, if (internalPtr != NULL) { if ((*value) != NULL) { string = Tcl_GetStringFromObj((*value), &length); - new = ckalloc((size_t) (length + 1)); - strcpy(new, string); + newStr = ckalloc((size_t) (length + 1)); + strcpy(newStr, string); } else { - new = NULL; + newStr = NULL; } *((char **) saveInternalPtr) = *((char **) internalPtr); - *((char **) internalPtr) = new; + *((char **) internalPtr) = newStr; } return TCL_OK; } static Tcl_Obj * -CustomOptionGet(clientData, tkwin, recordPtr, internalOffset) - ClientData clientData; - Tk_Window tkwin; - char *recordPtr; - int internalOffset; +CustomOptionGet( + ClientData clientData, + Tk_Window tkwin, + char *recordPtr, + int internalOffset) { return (Tcl_NewStringObj(*(char **)(recordPtr + internalOffset), -1)); } static void -CustomOptionRestore(clientData, tkwin, internalPtr, saveInternalPtr) - ClientData clientData; - Tk_Window tkwin; - char *internalPtr; - char *saveInternalPtr; +CustomOptionRestore( + ClientData clientData, + Tk_Window tkwin, + char *internalPtr, + char *saveInternalPtr) { *(char **)internalPtr = *(char **)saveInternalPtr; return; } static void -CustomOptionFree(clientData, tkwin, internalPtr) - ClientData clientData; - Tk_Window tkwin; - char *internalPtr; +CustomOptionFree( + ClientData clientData, + Tk_Window tkwin, + char *internalPtr) { if (*(char **)internalPtr != NULL) { ckfree(*(char **)internalPtr); } } - + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkText.c b/generic/tkText.c index 54f148d..6652f3d 100644 --- a/generic/tkText.c +++ b/generic/tkText.c @@ -1,347 +1,431 @@ -/* +/* * tkText.c -- * - * This module provides a big chunk of the implementation of - * multi-line editable text widgets for Tk. Among other things, - * it provides the Tcl command interfaces to text widgets and - * the display code. The B-tree representation of text is - * implemented elsewhere. + * This module provides a big chunk of the implementation of multi-line + * editable text widgets for Tk. Among other things, it provides the Tcl + * command interfaces to text widgets. The B-tree representation of text + * and its actual display are implemented elsewhere. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1996 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "default.h" -#include "tkPort.h" #include "tkInt.h" #include "tkUndo.h" -#if defined(MAC_TCL) || defined(MAC_OSX_TK) +#if defined(MAC_OSX_TK) #define Style TkStyle #define DInfo TkDInfo #endif +/* + * For compatibility with Tk 4.0 through 8.4.x, we allow tabs to be + * mis-specified with non-increasing values. These are converted into tabs + * which are the equivalent of at least a character width apart. + */ + +#if (TK_MAJOR_VERSION < 9) +#define _TK_ALLOW_DECREASING_TABS +#endif + #include "tkText.h" /* - * Custom options for handling "-state" + * Used to avoid having to allocate and deallocate arrays on the fly for + * commonly used functions. Must be > 0. + */ + +#define PIXEL_CLIENTS 5 + +/* + * The 'TkTextState' enum in tkText.h is used to define a type for the -state + * option of the Text widget. These values are used as indices into the string + * table below. */ -static Tk_CustomOption stateOption = { - (Tk_OptionParseProc *) TkStateParseProc, - TkStatePrintProc, (ClientData) NULL /* only "normal" and "disabled" */ +static char *stateStrings[] = { + "disabled", "normal", NULL }; /* - * Information used to parse text configuration options: + * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap + * option of the Text widget. These values are used as indices into the string + * table below. */ -static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_BOOLEAN, "-autoseparators", "autoSeparators", - "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, - Tk_Offset(TkText, autoSeparators), 0}, - {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_TEXT_BG_COLOR, Tk_Offset(TkText, border), TK_CONFIG_COLOR_ONLY}, - {TK_CONFIG_BORDER, "-background", "background", "Background", - DEF_TEXT_BG_MONO, Tk_Offset(TkText, border), TK_CONFIG_MONO_ONLY}, - {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", - DEF_TEXT_BORDER_WIDTH, Tk_Offset(TkText, borderWidth), 0}, - {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", - DEF_TEXT_CURSOR, Tk_Offset(TkText, cursor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection", - "ExportSelection", DEF_TEXT_EXPORT_SELECTION, - Tk_Offset(TkText, exportSelection), 0}, - {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL, - (char *) NULL, 0, 0}, - {TK_CONFIG_FONT, "-font", "font", "Font", - DEF_TEXT_FONT, Tk_Offset(TkText, tkfont), 0}, - {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground", - DEF_TEXT_FG, Tk_Offset(TkText, fgColor), 0}, - {TK_CONFIG_PIXELS, "-height", "height", "Height", - DEF_TEXT_HEIGHT, Tk_Offset(TkText, height), 0}, - {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", - "HighlightBackground", DEF_TEXT_HIGHLIGHT_BG, - Tk_Offset(TkText, highlightBgColorPtr), 0}, - {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", - DEF_TEXT_HIGHLIGHT, Tk_Offset(TkText, highlightColorPtr), 0}, - {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", - "HighlightThickness", - DEF_TEXT_HIGHLIGHT_WIDTH, Tk_Offset(TkText, highlightWidth), 0}, - {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground", - DEF_TEXT_INSERT_BG, Tk_Offset(TkText, insertBorder), 0}, - {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", - DEF_TEXT_INSERT_BD_COLOR, Tk_Offset(TkText, insertBorderWidth), - TK_CONFIG_COLOR_ONLY}, - {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", - DEF_TEXT_INSERT_BD_MONO, Tk_Offset(TkText, insertBorderWidth), - TK_CONFIG_MONO_ONLY}, - {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", - DEF_TEXT_INSERT_OFF_TIME, Tk_Offset(TkText, insertOffTime), 0}, - {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", - DEF_TEXT_INSERT_ON_TIME, Tk_Offset(TkText, insertOnTime), 0}, - {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", - DEF_TEXT_INSERT_WIDTH, Tk_Offset(TkText, insertWidth), 0}, - {TK_CONFIG_INT, "-maxundo", "maxUndo", "MaxUndo", - DEF_TEXT_MAX_UNDO, Tk_Offset(TkText, maxUndo), 0}, - {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", - DEF_TEXT_PADX, Tk_Offset(TkText, padX), 0}, - {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", - DEF_TEXT_PADY, Tk_Offset(TkText, padY), 0}, - {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", - DEF_TEXT_RELIEF, Tk_Offset(TkText, relief), 0}, - {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_TEXT_SELECT_COLOR, Tk_Offset(TkText, selBorder), - TK_CONFIG_COLOR_ONLY}, - {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", - DEF_TEXT_SELECT_MONO, Tk_Offset(TkText, selBorder), - TK_CONFIG_MONO_ONLY}, - {TK_CONFIG_STRING, "-selectborderwidth", "selectBorderWidth", "BorderWidth", - DEF_TEXT_SELECT_BD_COLOR, Tk_Offset(TkText, selBdString), - TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-selectborderwidth", "selectBorderWidth", "BorderWidth", - DEF_TEXT_SELECT_BD_MONO, Tk_Offset(TkText, selBdString), - TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_TEXT_SELECT_FG_COLOR, Tk_Offset(TkText, selFgColorPtr), - TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", - DEF_TEXT_SELECT_FG_MONO, Tk_Offset(TkText, selFgColorPtr), - TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK}, - {TK_CONFIG_BOOLEAN, "-setgrid", "setGrid", "SetGrid", - DEF_TEXT_SET_GRID, Tk_Offset(TkText, setGrid), 0}, - {TK_CONFIG_PIXELS, "-spacing1", "spacing1", "Spacing", - DEF_TEXT_SPACING1, Tk_Offset(TkText, spacing1), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_PIXELS, "-spacing2", "spacing2", "Spacing", - DEF_TEXT_SPACING2, Tk_Offset(TkText, spacing2), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_PIXELS, "-spacing3", "spacing3", "Spacing", - DEF_TEXT_SPACING3, Tk_Offset(TkText, spacing3), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_CUSTOM, "-state", "state", "State", - DEF_TEXT_STATE, Tk_Offset(TkText, state), 0, &stateOption}, - {TK_CONFIG_STRING, "-tabs", "tabs", "Tabs", - DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", - DEF_TEXT_TAKE_FOCUS, Tk_Offset(TkText, takeFocus), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_BOOLEAN, "-undo", "undo", "Undo", - DEF_TEXT_UNDO, Tk_Offset(TkText, undo), 0}, - {TK_CONFIG_INT, "-width", "width", "Width", - DEF_TEXT_WIDTH, Tk_Offset(TkText, width), 0}, - {TK_CONFIG_CUSTOM, "-wrap", "wrap", "Wrap", - DEF_TEXT_WRAP, Tk_Offset(TkText, wrapMode), 0, &TkTextWrapModeOption}, - {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", - DEF_TEXT_XSCROLL_COMMAND, Tk_Offset(TkText, xScrollCmd), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", - DEF_TEXT_YSCROLL_COMMAND, Tk_Offset(TkText, yScrollCmd), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} +static char *wrapStrings[] = { + "char", "none", "word", NULL }; /* - * Boolean variable indicating whether or not special debugging code - * should be executed. + * 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. */ -int tkTextDebug = 0; +static char *tabStyleStrings[] = { + "tabular", "wordprocessor", NULL +}; /* - * Custom options for handling "-wrap": + * The following functions and custom option type are used to define the + * "line" option type, and thereby handle the text widget '-startline', + * '-endline' configuration options which are of that type. + * + * We do not need a 'freeProc' because all changes to these two options are + * handled through the TK_TEXT_LINE_RANGE flag in the optionSpecs list, and + * the internal storage is just a pointer, which therefore doesn't need + * freeing. */ -static int WrapModeParseProc _ANSI_ARGS_((ClientData clientData, +static int SetLineStartEnd(ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, - CONST char *value, char *widgRec, int offset)); -static char * WrapModePrintProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); - -Tk_CustomOption TkTextWrapModeOption = { - WrapModeParseProc, - WrapModePrintProc, - (ClientData) NULL + Tcl_Obj **value, char *recordPtr, + int internalOffset, char *oldInternalPtr, + int flags); +static Tcl_Obj * GetLineStartEnd(ClientData clientData, + Tk_Window tkwin, char *recordPtr, + int internalOffset); +static void RestoreLineStartEnd(ClientData clientData, + Tk_Window tkwin, char *internalPtr, + char *oldInternalPtr); +static int ObjectIsEmpty(Tcl_Obj *objPtr); + +static Tk_ObjCustomOption lineOption = { + "line", /* name */ + SetLineStartEnd, /* setProc */ + GetLineStartEnd, /* getProc */ + RestoreLineStartEnd, /* restoreProc */ + NULL, /* freeProc */ + 0 }; /* - *-------------------------------------------------------------- - * - * WrapModeParseProc -- - * - * This procedure is invoked during option processing to handle - * "-wrap" options for text widgets. - * - * Results: - * A standard Tcl return value. - * - * Side effects: - * The wrap mode for a given item gets replaced by the wrap mode - * indicated in the value argument. - * - *-------------------------------------------------------------- + * Information used to parse text configuration options: */ -static int -WrapModeParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* some flags.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option (list of tag - * names). */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ -{ - int c; - size_t length; +static const Tk_OptionSpec optionSpecs[] = { + {TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators", + "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1, + Tk_Offset(TkText, autoSeparators), 0, 0, 0}, + {TK_OPTION_BORDER, "-background", "background", "Background", + DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border), + 0, (ClientData) DEF_TEXT_BG_MONO, 0}, + {TK_OPTION_SYNONYM, "-bd", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-borderwidth", + TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_SYNONYM, "-bg", NULL, NULL, + NULL, 0, -1, 0, (ClientData) "-background", 0}, + {TK_OPTION_BOOLEAN, "-blockcursor", "blockCursor", + "BlockCursor", DEF_TEXT_BLOCK_CURSOR, -1, + Tk_Offset(TkText, insertCursorType), 0, 0, 0}, + {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", + DEF_TEXT_BORDER_WIDTH, -1, Tk_Offset(TkText, borderWidth), + 0, 0, TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", + DEF_TEXT_CURSOR, -1, Tk_Offset(TkText, cursor), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_CUSTOM, "-endline", NULL, NULL, + NULL, -1, Tk_Offset(TkText, end), TK_OPTION_NULL_OK, + (ClientData) &lineOption, TK_TEXT_LINE_RANGE}, + {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", + "ExportSelection", DEF_TEXT_EXPORT_SELECTION, -1, + Tk_Offset(TkText, exportSelection), 0, 0, 0}, + {TK_OPTION_SYNONYM, "-fg", "foreground", NULL, + NULL, 0, -1, 0, (ClientData) "-foreground", 0}, + {TK_OPTION_FONT, "-font", "font", "Font", + DEF_TEXT_FONT, -1, Tk_Offset(TkText, tkfont), 0, 0, + TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", + DEF_TEXT_FG, -1, Tk_Offset(TkText, fgColor), 0, + 0, 0}, + {TK_OPTION_PIXELS, "-height", "height", "Height", + DEF_TEXT_HEIGHT, -1, Tk_Offset(TkText, height), 0, 0, 0}, + {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground", + "HighlightBackground", DEF_TEXT_HIGHLIGHT_BG, + -1, Tk_Offset(TkText, highlightBgColorPtr), + 0, 0, 0}, + {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", + DEF_TEXT_HIGHLIGHT, -1, Tk_Offset(TkText, highlightColorPtr), + 0, 0, 0}, + {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", + "HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, -1, + Tk_Offset(TkText, highlightWidth), 0, 0, TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_BORDER, "-inactiveselectbackground","inactiveSelectBackground", + "Foreground", + DEF_TEXT_INACTIVE_SELECT_COLOR, + -1, Tk_Offset(TkText, inactiveSelBorder), + TK_OPTION_NULL_OK, (ClientData) DEF_TEXT_SELECT_MONO, 0}, + {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground", + DEF_TEXT_INSERT_BG, + -1, Tk_Offset(TkText, insertBorder), + 0, 0, 0}, + {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", + "BorderWidth", DEF_TEXT_INSERT_BD_COLOR, -1, + Tk_Offset(TkText, insertBorderWidth), 0, + (ClientData) DEF_TEXT_INSERT_BD_MONO, 0}, + {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime", + DEF_TEXT_INSERT_OFF_TIME, -1, Tk_Offset(TkText, insertOffTime), + 0, 0, 0}, + {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime", + DEF_TEXT_INSERT_ON_TIME, -1, Tk_Offset(TkText, insertOnTime), + 0, 0, 0}, + {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", + 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}, + {TK_OPTION_PIXELS, "-padx", "padX", "Pad", + DEF_TEXT_PADX, -1, Tk_Offset(TkText, padX), 0, 0, + TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_PIXELS, "-pady", "padY", "Pad", + DEF_TEXT_PADY, -1, Tk_Offset(TkText, padY), 0, 0, 0}, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", + DEF_TEXT_RELIEF, -1, Tk_Offset(TkText, relief), 0, 0, 0}, + {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground", + DEF_TEXT_SELECT_COLOR, -1, Tk_Offset(TkText, selBorder), + 0, (ClientData) DEF_TEXT_SELECT_MONO, 0}, + {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", + "BorderWidth", DEF_TEXT_SELECT_BD_COLOR, + Tk_Offset(TkText, selBorderWidthPtr), + Tk_Offset(TkText, selBorderWidth), + TK_OPTION_NULL_OK, (ClientData) DEF_TEXT_SELECT_BD_MONO, 0}, + {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background", + DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr), + TK_CONFIG_NULL_OK, (ClientData) DEF_TEXT_SELECT_FG_MONO, 0}, + {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid", + DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0}, + {TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing", + DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1), + TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY }, + {TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing", + DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2), + TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY }, + {TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing", + DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3), + TK_OPTION_DONT_SET_DEFAULT, 0 , TK_TEXT_LINE_GEOMETRY }, + {TK_OPTION_CUSTOM, "-startline", NULL, NULL, + NULL, -1, Tk_Offset(TkText, start), TK_OPTION_NULL_OK, + (ClientData) &lineOption, TK_TEXT_LINE_RANGE}, + {TK_OPTION_STRING_TABLE, "-state", "state", "State", + DEF_TEXT_STATE, -1, Tk_Offset(TkText, state), + 0, (ClientData) stateStrings, 0}, + {TK_OPTION_STRING, "-tabs", "tabs", "Tabs", + DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionPtr), -1, + TK_OPTION_NULL_OK, 0, TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_STRING_TABLE, "-tabstyle", "tabStyle", "TabStyle", + DEF_TEXT_TABSTYLE, -1, Tk_Offset(TkText, tabStyle), + 0, (ClientData) tabStyleStrings, TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", + 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}, + {TK_OPTION_INT, "-width", "width", "Width", + DEF_TEXT_WIDTH, -1, Tk_Offset(TkText, width), 0, 0, + TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_STRING_TABLE, "-wrap", "wrap", "Wrap", + DEF_TEXT_WRAP, -1, Tk_Offset(TkText, wrapMode), + 0, (ClientData) wrapStrings, TK_TEXT_LINE_GEOMETRY}, + {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", + DEF_TEXT_XSCROLL_COMMAND, -1, Tk_Offset(TkText, xScrollCmd), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", + DEF_TEXT_YSCROLL_COMMAND, -1, Tk_Offset(TkText, yScrollCmd), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0} +}; - register TkWrapMode *wrapPtr = (TkWrapMode *) (widgRec + offset); +/* + * These three typedefs, the structure and the SearchPerform, SearchCore + * functions below are used for line-based searches of the text widget, and, + * in particular, to handle multi-line matching even though the text widget is + * a single-line based data structure. They are completely abstracted away + * from the Text widget internals, however, so could easily be re-used with + * any line-based entity to provide multi-line matching. + * + * We have abstracted this code away from the text widget to try to keep Tk as + * modular as possible. + */ - if(value == NULL || *value == 0) { - *wrapPtr = TEXT_WRAPMODE_NULL; - return TCL_OK; - } +struct SearchSpec; /* Forward declaration. */ + +typedef ClientData SearchAddLineProc(int lineNum, + struct SearchSpec *searchSpecPtr, + Tcl_Obj *theLine, int *lenPtr, + int *extraLinesPtr); +typedef int SearchMatchProc(int lineNum, + struct SearchSpec *searchSpecPtr, + ClientData clientData, Tcl_Obj *theLine, + int matchOffset, int matchLength); +typedef int SearchLineIndexProc(Tcl_Interp *interp, + Tcl_Obj *objPtr, struct SearchSpec *searchSpecPtr, + int *linePosPtr, int *offsetPosPtr); + +typedef struct SearchSpec { + int exact; /* Whether search is exact or regexp. */ + int noCase; /* Case-insenstivive? */ + int noLineStop; /* If not set, a regexp search will use the + * TCL_REG_NLSTOP flag. */ + int overlap; /* If set, results from multiple searches + * (-all) are allowed to overlap each + * other. */ + int strictLimits; /* If set, matches must be completely inside + * the from,to range. Otherwise the limits + * only apply to the start of each match. */ + int all; /* Whether all or the first match should be + * reported. */ + int startLine; /* First line to examine. */ + int startOffset; /* Index in first line to start at. */ + int stopLine; /* Last line to examine, or -1 when we search + * all available text. */ + int stopOffset; /* Index to stop at, provided stopLine is not + * -1. */ + int numLines; /* Total lines which are available. */ + int backwards; /* Searching forwards or backwards. */ + Tcl_Obj *varPtr; /* If non-NULL, store length(s) of match(es) + * in this variable. */ + Tcl_Obj *countPtr; /* Keeps track of currently found lengths. */ + Tcl_Obj *resPtr; /* Keeps track of currently found locations */ + int searchElide; /* Search in hidden text as well. */ + SearchAddLineProc *addLineProc; + /* Function to call when we need to add + * another line to the search string so far */ + SearchMatchProc *foundMatchProc; + /* Function to call when we have found a + * match. */ + SearchLineIndexProc *lineIndexProc; + /* Function to call when we have found a + * match. */ + ClientData clientData; /* Information about structure being searched, + * in this case a text widget. */ +} SearchSpec; - c = value[0]; - length = strlen(value); +/* + * The text-widget-independent functions which actually perform the search, + * handling both regexp and exact searches. + */ - if ((c == 'c') && (strncmp(value, "char", length) == 0)) { - *wrapPtr = TEXT_WRAPMODE_CHAR; - return TCL_OK; - } - if ((c == 'n') && (strncmp(value, "none", length) == 0)) { - *wrapPtr = TEXT_WRAPMODE_NONE; - return TCL_OK; - } - if ((c == 'w') && (strncmp(value, "word", length) == 0)) { - *wrapPtr = TEXT_WRAPMODE_WORD; - return TCL_OK; - } - Tcl_AppendResult(interp, "bad wrap mode \"", value, - "\": must be char, none, or word", - (char *) NULL); - *wrapPtr = TEXT_WRAPMODE_CHAR; - return TCL_ERROR; -} +static int SearchCore(Tcl_Interp *interp, + SearchSpec *searchSpecPtr, Tcl_Obj *patObj); +static int SearchPerform(Tcl_Interp *interp, + SearchSpec *searchSpecPtr, Tcl_Obj *patObj, + Tcl_Obj *fromPtr, Tcl_Obj *toPtr); /* - *-------------------------------------------------------------- - * - * WrapModePrintProc -- - * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-wrap" configuration - * option for canvas items. - * - * Results: - * The return value is a string describing the state for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). - * - * Side effects: - * None. - * - *-------------------------------------------------------------- + * Boolean variable indicating whether or not special debugging code should be + * executed. */ -static char * -WrapModePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Ignored. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ -{ - register TkWrapMode *wrapPtr = (TkWrapMode *) (widgRec + offset); - - if (*wrapPtr==TEXT_WRAPMODE_CHAR) { - return "char"; - } else if (*wrapPtr==TEXT_WRAPMODE_NONE) { - return "none"; - } else if (*wrapPtr==TEXT_WRAPMODE_WORD) { - return "word"; - } else { - return ""; - } -} +int tkTextDebug = 0; /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static int ConfigureText _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, int argc, CONST char **argv, - int flags)); -static int DeleteChars _ANSI_ARGS_((TkText *textPtr, - CONST char *index1String, CONST char *index2String, - TkTextIndex *indexPtr1, TkTextIndex *indexPtr2)); -static void DestroyText _ANSI_ARGS_((char *memPtr)); -static void InsertChars _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr, CONST char *string)); -static void TextBlinkProc _ANSI_ARGS_((ClientData clientData)); -static void TextCmdDeletedProc _ANSI_ARGS_(( - ClientData clientData)); -static void TextEventProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static int TextFetchSelection _ANSI_ARGS_((ClientData clientData, - int offset, char *buffer, int maxBytes)); -static int TextIndexSortProc _ANSI_ARGS_((CONST VOID *first, - CONST VOID *second)); -static int TextSearchCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -static int TextEditCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -static int TextWidgetCmd _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, int argc, CONST char **argv)); -static void TextWorldChanged _ANSI_ARGS_(( - ClientData instanceData)); -static int TextDumpCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -static void DumpLine _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, int what, TkTextLine *linePtr, - int start, int end, int lineno, - CONST char *command)); -static int DumpSegment _ANSI_ARGS_((Tcl_Interp *interp, char *key, - char *value, CONST char * command, - TkTextIndex *index, int what)); -static int TextEditUndo _ANSI_ARGS_((TkText *textPtr)); -static int TextEditRedo _ANSI_ARGS_((TkText *textPtr)); -static void TextGetText _ANSI_ARGS_((TkTextIndex * index1, - TkTextIndex * index2, Tcl_DString *dsPtr)); +static int ConfigureText(Tcl_Interp *interp, + TkText *textPtr, int objc, Tcl_Obj *CONST objv[]); +static int DeleteIndexRange(TkSharedText *sharedPtr, + TkText *textPtr, CONST TkTextIndex *indexPtr1, + CONST TkTextIndex *indexPtr2, int viewUpdate); +static int CountIndices(CONST TkText *textPtr, + CONST TkTextIndex *indexPtr1, + CONST TkTextIndex *indexPtr2, + TkTextCountType type); +static void DestroyText(TkText *textPtr); +static int InsertChars(TkSharedText *sharedTextPtr, + TkText *textPtr, TkTextIndex *indexPtr, + Tcl_Obj *stringPtr, int viewUpdate); +static void TextBlinkProc(ClientData clientData); +static void TextCmdDeletedProc(ClientData clientData); +static int CreateWidget(TkSharedText *sharedPtr, Tk_Window tkwin, + Tcl_Interp *interp, CONST TkText *parent, + int objc, Tcl_Obj *CONST objv[]); +static void TextEventProc(ClientData clientData, + XEvent *eventPtr); +static int TextFetchSelection(ClientData clientData, int offset, + char *buffer, int maxBytes); +static int TextIndexSortProc(CONST void *first, + CONST void *second); +static int TextInsertCmd(TkSharedText *sharedTextPtr, + TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[], + CONST TkTextIndex *indexPtr, int viewUpdate); +static int TextReplaceCmd(TkText *textPtr, Tcl_Interp *interp, + CONST TkTextIndex *indexFromPtr, + CONST TkTextIndex *indexToPtr, + int objc, Tcl_Obj *CONST objv[], int viewUpdate); +static int TextSearchCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int TextEditCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int TextWidgetObjCmd(ClientData clientData, + Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int SharedTextObjCmd(ClientData clientData, + Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static void TextWorldChangedCallback(ClientData instanceData); +static void TextWorldChanged(TkText *textPtr, int mask); +static int TextDumpCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int DumpLine(Tcl_Interp *interp, TkText *textPtr, + int what, TkTextLine *linePtr, int start, int end, + int lineno, Tcl_Obj *command); +static int DumpSegment(TkText *textPtr, Tcl_Interp *interp, + CONST char *key, CONST char *value, + Tcl_Obj *command, CONST TkTextIndex *index, + int what); +static int TextEditUndo(TkText *textPtr); +static int TextEditRedo(TkText *textPtr); +static Tcl_Obj * TextGetText(CONST TkText *textPtr, + CONST TkTextIndex *index1, + CONST TkTextIndex *index2, int visibleOnly); static void GenerateModifiedEvent(TkText *textPtr); -static void updateDirtyFlag _ANSI_ARGS_((TkText *textPtr)); +static void UpdateDirtyFlag(TkSharedText *sharedPtr); +static void TextPushUndoAction(TkText *textPtr, + Tcl_Obj *undoString, int insert, + CONST TkTextIndex *index1Ptr, + CONST TkTextIndex *index2Ptr); +static int TextSearchIndexInLine(CONST SearchSpec *searchSpecPtr, + TkTextLine *linePtr, int byteIndex); +static int TextPeerCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static TkUndoProc TextUndoRedoCallback; + +/* + * Declarations of the three search procs required by the multi-line search + * routines. + */ + +static SearchMatchProc TextSearchFoundMatch; +static SearchAddLineProc TextSearchAddNextLine; +static SearchLineIndexProc TextSearchGetLineIndex; /* - * The structure below defines text class behavior by means of procedures - * that can be invoked from generic window code. + * The structure below defines text class behavior by means of functions that + * can be invoked from generic window code. */ static Tk_ClassProcs textClass = { sizeof(Tk_ClassProcs), /* size */ - TextWorldChanged, /* worldChangedProc */ + TextWorldChangedCallback, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ }; - /* *-------------------------------------------------------------- * - * Tk_TextCmd -- + * Tk_TextObjCmd -- * - * This procedure is invoked to process the "text" Tcl command. - * See the user documentation for details on what it does. + * This function is invoked to process the "text" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -353,85 +437,201 @@ static Tk_ClassProcs textClass = { */ int -Tk_TextCmd(clientData, interp, argc, argv) - ClientData clientData; /* Main window associated with - * interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +Tk_TextObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; - Tk_Window new; - register TkText *textPtr; - TkTextIndex startIndex; - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " pathName ?options?\"", (char *) NULL); + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?"); return TCL_ERROR; } + return CreateWidget(NULL, tkwin, interp, NULL, objc, objv); +} + +/* + *-------------------------------------------------------------- + * + * CreateWidget -- + * + * This function is invoked to process the "text" Tcl command, (when + * called by Tk_TextObjCmd) and the "$text peer create" text widget + * sub-command (called from TextPeerCmd). + * + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result, places the name of the widget created into the + * interp's result. + * + * Side effects: + * See the user documentation. + * + *-------------------------------------------------------------- + */ + +static int +CreateWidget( + TkSharedText *sharedPtr, /* Shared widget info, or NULL. */ + Tk_Window tkwin, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + CONST TkText *parent, /* If non-NULL then take default start, end + * from this parent. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + register TkText *textPtr; + Tk_OptionTable optionTable; + TkTextIndex startIndex; + Tk_Window newWin; + /* * Create the window. */ - new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL); - if (new == NULL) { + newWin = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), + NULL); + if (newWin == NULL) { return TCL_ERROR; } /* - * Create the text widget and initialize everything to zero, - * then set the necessary initial (non-NULL) values. + * Create the text widget and initialize everything to zero, then set the + * necessary initial (non-NULL) values. It is important that the 'set' tag + * and 'insert', 'current' mark pointers are all NULL to start. */ textPtr = (TkText *) ckalloc(sizeof(TkText)); - memset((VOID *) textPtr, 0, sizeof(TkText)); + memset(textPtr, 0, sizeof(TkText)); - textPtr->tkwin = new; - textPtr->display = Tk_Display(new); + textPtr->tkwin = newWin; + textPtr->display = Tk_Display(newWin); textPtr->interp = interp; - textPtr->widgetCmd = Tcl_CreateCommand(interp, - Tk_PathName(textPtr->tkwin), TextWidgetCmd, + textPtr->widgetCmd = Tcl_CreateObjCommand(interp, + Tk_PathName(textPtr->tkwin), TextWidgetObjCmd, (ClientData) textPtr, TextCmdDeletedProc); - textPtr->tree = TkBTreeCreate(textPtr); - Tcl_InitHashTable(&textPtr->tagTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&textPtr->markTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&textPtr->windowTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&textPtr->imageTable, TCL_STRING_KEYS); - textPtr->state = TK_STATE_NORMAL; + + if (sharedPtr == NULL) { + sharedPtr = (TkSharedText *) ckalloc(sizeof(TkSharedText)); + memset(sharedPtr, 0, sizeof(TkSharedText)); + + sharedPtr->refCount = 0; + sharedPtr->peers = NULL; + sharedPtr->tree = TkBTreeCreate(sharedPtr); + + Tcl_InitHashTable(&sharedPtr->tagTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&sharedPtr->markTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&sharedPtr->windowTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&sharedPtr->imageTable, TCL_STRING_KEYS); + sharedPtr->undoStack = TkUndoInitStack(interp,0); + sharedPtr->undo = 1; + sharedPtr->isDirty = 0; + sharedPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + sharedPtr->autoSeparators = 1; + sharedPtr->lastEditMode = TK_TEXT_EDIT_OTHER; + sharedPtr->stateEpoch = 0; + } + + /* + * Add the new widget to the shared list. + */ + + textPtr->sharedTextPtr = sharedPtr; + sharedPtr->refCount++; + textPtr->next = sharedPtr->peers; + sharedPtr->peers = textPtr; + + /* + * This refCount will be held until DestroyText is called. Note also that + * the later call to 'TkTextCreateDInfo' will add more refCounts. + */ + + textPtr->refCount = 1; + + /* + * Specify start and end lines in the B-tree. The default is the same as + * the parent, but this can be adjusted to display more or less if the + * start, end where given as configuration options. + */ + + if (parent != NULL) { + textPtr->start = parent->start; + textPtr->end = parent->end; + } else { + textPtr->start = NULL; + textPtr->end = NULL; + } + + /* + * Register with the B-tree. In some sense it would be best if we could do + * this later (after configuration options), so that any changes to + * start,end do not require a total recalculation. + */ + + TkBTreeAddClient(sharedPtr->tree, textPtr, textPtr->charHeight); + + textPtr->state = TK_TEXT_STATE_NORMAL; textPtr->relief = TK_RELIEF_FLAT; textPtr->cursor = None; textPtr->charWidth = 1; + textPtr->charHeight = 10; textPtr->wrapMode = TEXT_WRAPMODE_CHAR; - textPtr->prevWidth = Tk_Width(new); - textPtr->prevHeight = Tk_Height(new); + textPtr->prevWidth = Tk_Width(newWin); + textPtr->prevHeight = Tk_Height(newWin); + + /* + * This will add refCounts to textPtr. + */ + TkTextCreateDInfo(textPtr); - TkTextMakeByteIndex(textPtr->tree, 0, 0, &startIndex); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, + &startIndex); TkTextSetYView(textPtr, &startIndex, 0); textPtr->exportSelection = 1; textPtr->pickEvent.type = LeaveNotify; - textPtr->undoStack = TkUndoInitStack(interp,0); - textPtr->undo = 1; - textPtr->isDirty = 0; - textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; - textPtr->autoSeparators = 1; - textPtr->lastEditMode = TK_TEXT_EDIT_OTHER; + textPtr->undo = textPtr->sharedTextPtr->undo; + textPtr->maxUndo = textPtr->sharedTextPtr->maxUndo; + textPtr->autoSeparators = textPtr->sharedTextPtr->autoSeparators; + textPtr->tabOptionPtr = NULL; /* * Create the "sel" tag and the "current" and "insert" marks. */ - textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel"); - textPtr->selTagPtr->reliefString = - (char *) ckalloc(sizeof(DEF_TEXT_SELECT_RELIEF)); + textPtr->selBorder = NULL; + textPtr->inactiveSelBorder = NULL; + textPtr->selBorderWidth = 0; + textPtr->selBorderWidthPtr = NULL; + textPtr->selFgColorPtr = NULL; + + /* + * Note: it is important that textPtr->selTagPtr is NULL before this + * initial call. + */ + + textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel", NULL); + textPtr->selTagPtr->reliefString = (char *) + ckalloc(sizeof(DEF_TEXT_SELECT_RELIEF)); strcpy(textPtr->selTagPtr->reliefString, DEF_TEXT_SELECT_RELIEF); - Tk_GetRelief(interp, DEF_TEXT_SELECT_RELIEF, &(textPtr->selTagPtr->relief)); + Tk_GetRelief(interp, DEF_TEXT_SELECT_RELIEF, &textPtr->selTagPtr->relief); textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &startIndex); textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &startIndex); + /* + * Create the option table for this widget class. If it has already been + * created, the cached pointer will be returned. + */ + + optionTable = Tk_CreateOptionTable(interp, optionSpecs); + Tk_SetClass(textPtr->tkwin, "Text"); Tk_SetClassProcs(textPtr->tkwin, &textClass, (ClientData) textPtr); + textPtr->optionTable = optionTable; + Tk_CreateEventHandler(textPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, TextEventProc, (ClientData) textPtr); @@ -441,23 +641,30 @@ Tk_TextCmd(clientData, interp, argc, argv) TkTextBindProc, (ClientData) textPtr); Tk_CreateSelHandler(textPtr->tkwin, XA_PRIMARY, XA_STRING, TextFetchSelection, (ClientData) textPtr, XA_STRING); - if (ConfigureText(interp, textPtr, argc-2, argv+2, 0) != TCL_OK) { + + if (Tk_InitOptions(interp, (char *) textPtr, optionTable, textPtr->tkwin) + != TCL_OK) { + Tk_DestroyWindow(textPtr->tkwin); + return TCL_ERROR; + } + if (ConfigureText(interp, textPtr, objc-2, objv+2) != TCL_OK) { Tk_DestroyWindow(textPtr->tkwin); return TCL_ERROR; } - Tcl_SetResult(interp, Tk_PathName(textPtr->tkwin), TCL_STATIC); + Tcl_SetObjResult(interp, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin),-1)); return TCL_OK; } /* *-------------------------------------------------------------- * - * TextWidgetCmd -- + * TextWidgetObjCmd -- * - * This procedure is invoked to process the Tcl command - * that corresponds to a text widget. See the user - * documentation for details on what it does. + * This function is invoked to process the Tcl command that corresponds + * to a text widget. See the user documentation for details on what it + * does. * * Results: * A standard Tcl result. @@ -469,88 +676,118 @@ Tk_TextCmd(clientData, interp, argc, argv) */ static int -TextWidgetCmd(clientData, interp, argc, argv) - ClientData clientData; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TextWidgetObjCmd( + ClientData clientData, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register TkText *textPtr = (TkText *) clientData; - int c, result = TCL_OK; - size_t length; - TkTextIndex index1, index2; + int result = TCL_OK; + int index; + + static CONST char *optionStrings[] = { + "bbox", "cget", "compare", "configure", "count", "debug", "delete", + "dlineinfo", "dump", "edit", "get", "image", "index", "insert", + "mark", "peer", "replace", "scan", "search", "see", "tag", "window", + "xview", "yview", NULL + }; + enum options { + TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT, + TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT, + TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK, + TEXT_PEER, TEXT_REPLACE, TEXT_SCAN, TEXT_SEARCH, TEXT_SEE, + TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW + }; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " option ?arg arg ...?\"", (char *) NULL); + if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } - Tcl_Preserve((ClientData) textPtr); - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) { + textPtr->refCount++; + + switch ((enum options) index) { + case TEXT_BBOX: { int x, y, width, height; + CONST TkTextIndex *indexPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " bbox index\"", (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); result = TCL_ERROR; goto done; } - if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) { + indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]); + if (indexPtr == NULL) { result = TCL_ERROR; goto done; } - if (TkTextCharBbox(textPtr, &index1, &x, &y, &width, &height) == 0) { - char buf[TCL_INTEGER_SPACE * 4]; - - sprintf(buf, "%d %d %d %d", x, y, width, height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } - } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0) - && (length >= 2)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " cget option\"", - (char *) NULL); + if (TkTextIndexBbox(textPtr, indexPtr, &x, &y, &width, &height, + NULL) == 0) { + Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); + + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height)); + + Tcl_SetObjResult(interp, listObj); + } + break; + } + case TEXT_CGET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; goto done; + } else { + Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *) textPtr, + textPtr->optionTable, objv[2], textPtr->tkwin); + if (objPtr == NULL) { + result = TCL_ERROR; + goto done; + } else { + Tcl_SetObjResult(interp, objPtr); + result = TCL_OK; + } } - result = Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs, - (char *) textPtr, argv[2], 0); - } else if ((c == 'c') && (strncmp(argv[1], "compare", length) == 0) - && (length >= 3)) { + break; + case TEXT_COMPARE: { int relation, value; CONST char *p; + CONST TkTextIndex *index1Ptr, *index2Ptr; - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " compare index1 op index2\"", (char *) NULL); + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "index1 op index2"); result = TCL_ERROR; goto done; } - if ((TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) - || (TkTextGetIndex(interp, textPtr, argv[4], &index2) - != TCL_OK)) { + index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[2]); + index2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[4]); + if (index1Ptr == NULL || index2Ptr == NULL) { result = TCL_ERROR; goto done; } - relation = TkTextIndexCmp(&index1, &index2); - p = argv[3]; + relation = TkTextIndexCmp(index1Ptr, index2Ptr); + p = Tcl_GetString(objv[3]); if (p[0] == '<') { - value = (relation < 0); + value = (relation < 0); if ((p[1] == '=') && (p[2] == 0)) { value = (relation <= 0); } else if (p[1] != 0) { - compareError: + compareError: Tcl_AppendResult(interp, "bad comparison operator \"", - argv[3], "\": must be <, <=, ==, >=, >, or !=", - (char *) NULL); + Tcl_GetString(objv[3]), + "\": must be <, <=, ==, >=, >, or !=", NULL); result = TCL_ERROR; goto done; } } else if (p[0] == '>') { - value = (relation > 0); + value = (relation > 0); if ((p[1] == '=') && (p[2] == 0)) { value = (relation >= 0); } else if (p[1] != 0) { @@ -563,104 +800,347 @@ TextWidgetCmd(clientData, interp, argc, argv) } else { goto compareError; } - Tcl_SetResult(interp, ((value) ? "1" : "0"), TCL_STATIC); - } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0) - && (length >= 3)) { - if (argc == 2) { - result = Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs, - (char *) textPtr, (char *) NULL, 0); - } else if (argc == 3) { - result = Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs, - (char *) textPtr, argv[2], 0); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value)); + break; + } + case TEXT_CONFIGURE: + if (objc <= 3) { + Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) textPtr, + textPtr->optionTable, ((objc == 3) ? objv[2] : NULL), + textPtr->tkwin); + if (objPtr == NULL) { + result = TCL_ERROR; + goto done; + } else { + Tcl_SetObjResult(interp, objPtr); + } } else { - result = ConfigureText(interp, textPtr, argc-2, argv+2, - TK_CONFIG_ARGV_ONLY); - } - } else if ((c == 'd') && (strncmp(argv[1], "debug", length) == 0) - && (length >= 3)) { - if (argc > 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " debug boolean\"", (char *) NULL); + result = ConfigureText(interp, textPtr, objc-2, objv+2); + } + break; + case TEXT_COUNT: { + CONST TkTextIndex *indexFromPtr, *indexToPtr; + int i, found = 0, update = 0; + Tcl_Obj *objPtr = NULL; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, "?options? index1 index2"); + result = TCL_ERROR; + goto done; + } + + indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, objv[objc-2]); + if (indexFromPtr == NULL) { + result = TCL_ERROR; + goto done; + } + indexToPtr = TkTextGetIndexFromObj(interp, textPtr, objv[objc-1]); + if (indexToPtr == NULL) { result = TCL_ERROR; goto done; } - if (argc == 2) { - Tcl_SetResult(interp, ((tkBTreeDebug) ? "1" : "0"), TCL_STATIC); + + for (i = 2; i < objc-2; i++) { + int value, length; + CONST char *option = Tcl_GetStringFromObj(objv[i], &length); + char c; + + if (length < 2 || option[0] != '-') { + badOption: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "bad option \"", + Tcl_GetString(objv[i]), + "\" must be -chars, -displaychars, -displayindices, ", + "-displaylines, -indices, -lines, -update, ", + "-xpixels, or -ypixels", NULL); + result = TCL_ERROR; + goto done; + } + c = option[1]; + if (c == 'c' && !strncmp("-chars", option, (unsigned) length)) { + value = CountIndices(textPtr, indexFromPtr, indexToPtr, + COUNT_CHARS); + } else if (c == 'd' && (length > 8) + && !strncmp("-displaychars", option, (unsigned) length)) { + value = CountIndices(textPtr, indexFromPtr, indexToPtr, + COUNT_DISPLAY_CHARS); + } else if (c == 'd' && (length > 8) + && !strncmp("-displayindices", option,(unsigned)length)) { + value = CountIndices(textPtr, indexFromPtr, indexToPtr, + COUNT_DISPLAY_INDICES); + } else if (c == 'd' && (length > 8) + && !strncmp("-displaylines", option, (unsigned) length)) { + TkTextLine *fromPtr, *lastPtr; + TkTextIndex index; + + int compare = TkTextIndexCmp(indexFromPtr, indexToPtr); + value = 0; + + if (compare == 0) { + goto countDone; + } + + if (compare > 0) { + CONST TkTextIndex *tmpPtr = indexFromPtr; + + indexFromPtr = indexToPtr; + indexToPtr = tmpPtr; + } + + lastPtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree,textPtr)); + fromPtr = indexFromPtr->linePtr; + if (fromPtr == lastPtr) { + goto countDone; + } + + /* + * Caution: we must NEVER call TkTextUpdateOneLine with the + * last artificial line in the widget. + */ + + index = *indexFromPtr; + index.byteIndex = 0; + + /* + * 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', and then subtract off what we didn't + * want from 'from' and add on what we didn't count from 'to. + */ + + while (index.linePtr != indexToPtr->linePtr) { + value += TkTextUpdateOneLine(textPtr, fromPtr,0,&index,0); + + /* + * We might have skipped past indexToPtr, if we have + * multiple logical lines in a single display line. + */ + if (TkTextIndexCmp(&index,indexToPtr) > 0) { + break; + } + } + + /* + * Now we need to adjust the count to add on the number of + * display lines in the last logical line, and subtract off + * the number of display lines overcounted in the first + * logical line. This logic is still ok if both indices are in + * the same logical line. + */ + + index.linePtr = indexFromPtr->linePtr; + index.byteIndex = 0; + while (1) { + TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL); + if (index.byteIndex >= indexFromPtr->byteIndex) { + break; + } + TkTextIndexForwBytes(textPtr, &index, 1, &index); + value--; + + } + if (indexToPtr->linePtr != lastPtr) { + index.linePtr = indexToPtr->linePtr; + index.byteIndex = 0; + while (1) { + TkTextFindDisplayLineEnd(textPtr, &index, 1, NULL); + if (index.byteIndex >= indexToPtr->byteIndex) { + break; + } + TkTextIndexForwBytes(textPtr, &index, 1, &index); + value++; + } + } + + if (compare > 0) { + value = -value; + } + } else if (c == 'i' + && !strncmp("-indices", option, (unsigned) length)) { + value = CountIndices(textPtr, indexFromPtr, indexToPtr, + COUNT_INDICES); + } else if (c == 'l' + && !strncmp("-lines", option, (unsigned) length)) { + value = TkBTreeLinesTo(textPtr, indexToPtr->linePtr) + - TkBTreeLinesTo(textPtr, indexFromPtr->linePtr); + } else if (c == 'u' + && !strncmp("-update", option, (unsigned) length)) { + update = 1; + continue; + } else if (c == 'x' + && !strncmp("-xpixels", option, (unsigned) length)) { + int x1, x2; + TkTextIndex index; + + index = *indexFromPtr; + TkTextFindDisplayLineEnd(textPtr, &index, 0, &x1); + index = *indexToPtr; + TkTextFindDisplayLineEnd(textPtr, &index, 0, &x2); + value = x2 - x1; + } else if (c == 'y' + && !strncmp("-ypixels", option, (unsigned) length)) { + if (update) { + TkTextUpdateLineMetrics(textPtr, + TkBTreeLinesTo(textPtr, indexFromPtr->linePtr), + TkBTreeLinesTo(textPtr, indexToPtr->linePtr), -1); + } + value = TkTextIndexYPixels(textPtr, indexToPtr) + - TkTextIndexYPixels(textPtr, indexFromPtr); + } else { + goto badOption; + } + + countDone: + found++; + if (found == 1) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(value)); + } else { + if (found == 2) { + /* + * Move the first item we put into the result into the + * first element of the list object. + */ + + objPtr = Tcl_NewObj(); + Tcl_ListObjAppendElement(NULL, objPtr, + Tcl_GetObjResult(interp)); + } + Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewIntObj(value)); + } + } + + if (found == 0) { + /* + * Use the default '-indices'. + */ + + int value = CountIndices(textPtr, indexFromPtr, indexToPtr, + COUNT_INDICES); + + Tcl_SetObjResult(interp, Tcl_NewIntObj(value)); + } else if (found > 1) { + Tcl_SetObjResult(interp, objPtr); + } + break; + } + case TEXT_DEBUG: + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "boolean"); + result = TCL_ERROR; + goto done; + } + if (objc == 2) { + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(tkBTreeDebug)); } else { - if (Tcl_GetBoolean(interp, argv[2], &tkBTreeDebug) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, objv[2], + &tkBTreeDebug) != TCL_OK) { result = TCL_ERROR; goto done; } tkTextDebug = tkBTreeDebug; } - } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0) - && (length >= 3)) { - int i; - - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " delete index1 ?index2 ...?\"", (char *) NULL); + break; + case TEXT_DELETE: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2 ...?"); result = TCL_ERROR; goto done; } - if (textPtr->state == TK_STATE_NORMAL) { - if (argc < 5) { + if (textPtr->state == TK_TEXT_STATE_NORMAL) { + if (objc < 5) { /* * Simple case requires no predetermination of indices. */ - result = DeleteChars(textPtr, argv[2], - (argc == 4) ? argv[3] : NULL, NULL, NULL); + + CONST TkTextIndex *indexPtr1, *indexPtr2; + + /* + * Parse the starting and stopping indices. + */ + + indexPtr1 = TkTextGetIndexFromObj(textPtr->interp, textPtr, + objv[2]); + if (indexPtr1 == NULL) { + result = TCL_ERROR; + goto done; + } + if (objc == 4) { + indexPtr2 = TkTextGetIndexFromObj(textPtr->interp, + textPtr, objv[3]); + if (indexPtr2 == NULL) { + result = TCL_ERROR; + goto done; + } + } else { + indexPtr2 = NULL; + } + DeleteIndexRange(NULL, textPtr, indexPtr1, indexPtr2, 1); } else { /* * Multi-index pair case requires that we prevalidate the - * indices and sort from last to first so that deletes - * occur in the exact (unshifted) text. It also needs to - * handle partial and fully overlapping ranges. We have to - * do this with multiple passes. + * indices and sort from last to first so that deletes occur + * in the exact (unshifted) text. It also needs to handle + * partial and fully overlapping ranges. We have to do this + * with multiple passes. */ + TkTextIndex *indices, *ixStart, *ixEnd, *lastStart; char *useIdx; + int i; - argc -= 2; - argv += 2; + objc -= 2; + objv += 2; indices = (TkTextIndex *) - ckalloc((argc + 1) * sizeof(TkTextIndex)); + ckalloc((objc + 1) * sizeof(TkTextIndex)); /* * First pass verifies that all indices are valid. */ - for (i = 0; i < argc; i++) { - if (TkTextGetIndex(interp, textPtr, argv[i], - &indices[i]) != TCL_OK) { + + for (i = 0; i < objc; i++) { + CONST TkTextIndex *indexPtr = + TkTextGetIndexFromObj(interp, textPtr, objv[i]); + + if (indexPtr == NULL) { result = TCL_ERROR; ckfree((char *) indices); goto done; } + indices[i] = *indexPtr; } + /* * Pad out the pairs evenly to make later code easier. */ - if (argc & 1) { + + if (objc & 1) { indices[i] = indices[i-1]; - TkTextIndexForwChars(&indices[i], 1, &indices[i]); - argc++; + TkTextIndexForwChars(NULL, &indices[i], 1, &indices[i], + COUNT_INDICES); + objc++; } - useIdx = (char *) ckalloc((unsigned) argc); - memset(useIdx, 0, (unsigned) argc); + useIdx = (char *) ckalloc((unsigned) objc); + memset(useIdx, 0, (unsigned) objc); + /* - * Do a decreasing order sort so that we delete the end - * ranges first to maintain index consistency. + * Do a decreasing order sort so that we delete the end ranges + * first to maintain index consistency. */ - qsort((VOID *) indices, (unsigned) (argc / 2), + + qsort(indices, (unsigned) objc / 2, 2 * sizeof(TkTextIndex), TextIndexSortProc); lastStart = NULL; + /* * Second pass will handle bogus ranges (end < start) and * overlapping ranges. */ - for (i = 0; i < argc; i += 2) { + + for (i = 0; i < objc; i += 2) { ixStart = &indices[i]; - ixEnd = &indices[i+1]; + ixEnd = &indices[i+1]; if (TkTextIndexCmp(ixEnd, ixStart) <= 0) { continue; } @@ -670,13 +1150,15 @@ TextWidgetCmd(clientData, interp, argc, argv) * Start indices were equal, and the sort placed * the longest range first, so skip this one. */ + continue; } else if (TkTextIndexCmp(lastStart, ixEnd) < 0) { /* * The next pair has a start range before the end - * point of the last range. Constrain the delete + * point of the last range. Constrain the delete * range, but use the pointer values. */ + *ixEnd = *lastStart; if (TkTextIndexCmp(ixEnd, ixStart) <= 0) { continue; @@ -684,200 +1166,589 @@ TextWidgetCmd(clientData, interp, argc, argv) } } lastStart = ixStart; - useIdx[i] = 1; + useIdx[i] = 1; } + /* - * Final pass take the input from the previous and deletes - * the ranges which are flagged to be deleted. + * Final pass take the input from the previous and deletes the + * ranges which are flagged to be deleted. */ - for (i = 0; i < argc; i += 2) { + + for (i = 0; i < objc; i += 2) { if (useIdx[i]) { /* * We don't need to check the return value because all * indices are preparsed above. */ - DeleteChars(textPtr, NULL, NULL, - &indices[i], &indices[i+1]); + + DeleteIndexRange(NULL, textPtr, &indices[i], + &indices[i+1], 1); } } ckfree((char *) indices); } } - } else if ((c == 'd') && (strncmp(argv[1], "dlineinfo", length) == 0) - && (length >= 2)) { + break; + case TEXT_DLINEINFO: { int x, y, width, height, base; + CONST TkTextIndex *indexPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " dlineinfo index\"", (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); result = TCL_ERROR; goto done; } - if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) { + indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]); + if (indexPtr == NULL) { result = TCL_ERROR; goto done; } - if (TkTextDLineInfo(textPtr, &index1, &x, &y, &width, &height, &base) - == 0) { - char buf[TCL_INTEGER_SPACE * 5]; - - sprintf(buf, "%d %d %d %d %d", x, y, width, height, base); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + if (TkTextDLineInfo(textPtr, indexPtr, &x, &y, &width, &height, + &base) == 0) { + Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); + + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(x)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(y)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(width)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(height)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewIntObj(base)); + + Tcl_SetObjResult(interp, listObj); } - } else if ((c == 'e') && (strncmp(argv[1], "edit", length) == 0)) { - result = TextEditCmd(textPtr, interp, argc, argv); - } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { + break; + } + case TEXT_DUMP: + result = TextDumpCmd(textPtr, interp, objc, objv); + break; + case TEXT_EDIT: + result = TextEditCmd(textPtr, interp, objc, objv); + break; + case TEXT_GET: { Tcl_Obj *objPtr = NULL; - Tcl_DString ds; - int i, found = 0; + int i, found = 0, visible = 0; + CONST char *name; + int length; - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " get index1 ?index2 ...?\"", (char *) NULL); + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, + "?-displaychars? ?--? index1 ?index2 ...?"); result = TCL_ERROR; goto done; } - for (i = 2; i < argc; i += 2) { - if (TkTextGetIndex(interp, textPtr, argv[i], &index1) != TCL_OK) { - result = TCL_ERROR; - goto done; + + /* + * Simple, restrictive argument parsing. The only options are -- and + * -displaychars (or any unique prefix). + */ + + i = 2; + if (objc > 3) { + name = Tcl_GetStringFromObj(objv[i], &length); + if (length > 1 && name[0] == '-') { + if (strncmp("-displaychars", name, (unsigned)length)==0) { + i++; + visible = 1; + name = Tcl_GetStringFromObj(objv[i], &length); + } + if ((i < objc-1) && (length == 2) && !strcmp("--", name)) { + i++; + } } - if (i+1 == argc) { - index2 = index1; - TkTextIndexForwChars(&index2, 1, &index2); - } else if (TkTextGetIndex(interp, textPtr, argv[i+1], &index2) - != TCL_OK) { + } + + for (; i < objc; i += 2) { + CONST TkTextIndex *index1Ptr, *index2Ptr; + TkTextIndex index2; + + index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i]); + if (index1Ptr == NULL) { if (objPtr) { Tcl_DecrRefCount(objPtr); } result = TCL_ERROR; goto done; } - if (TkTextIndexCmp(&index1, &index2) < 0) { - /* - * Place the text in a DString and move it to the result. - * Since this could in principle be a megabyte or more, we - * want to do it efficiently! + + if (i+1 == objc) { + TkTextIndexForwChars(NULL, index1Ptr, 1, &index2, + COUNT_INDICES); + index2Ptr = &index2; + } else { + index2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i+1]); + if (index2Ptr == NULL) { + if (objPtr) { + Tcl_DecrRefCount(objPtr); + } + result = TCL_ERROR; + goto done; + } + } + + if (TkTextIndexCmp(index1Ptr, index2Ptr) < 0) { + /* + * We want to move the text we get from the window into the + * result, but since this could in principle be a megabyte or + * more, we want to do it efficiently! */ - TextGetText(&index1, &index2, &ds); + + Tcl_Obj *get = TextGetText(textPtr, index1Ptr, index2Ptr, + visible); + found++; if (found == 1) { - Tcl_DStringResult(interp, &ds); + Tcl_SetObjResult(interp, get); } else { if (found == 2) { /* - * Move the first item we put into the result into - * the first element of the list object. + * Move the first item we put into the result into the + * first element of the list object. */ + objPtr = Tcl_NewObj(); Tcl_ListObjAppendElement(NULL, objPtr, Tcl_GetObjResult(interp)); } - Tcl_ListObjAppendElement(NULL, objPtr, - Tcl_NewStringObj(Tcl_DStringValue(&ds), - Tcl_DStringLength(&ds))); + Tcl_ListObjAppendElement(NULL, objPtr, get); } - Tcl_DStringFree(&ds); } } if (found > 1) { Tcl_SetObjResult(interp, objPtr); } - } else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0) - && (length >= 3)) { - char buf[200]; + break; + } + case TEXT_IMAGE: + result = TkTextImageCmd(textPtr, interp, objc, objv); + break; + case TEXT_INDEX: { + CONST TkTextIndex *indexPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " index index\"", - (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); result = TCL_ERROR; goto done; } - if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) { + + indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]); + if (indexPtr == NULL) { result = TCL_ERROR; goto done; } - TkTextPrintIndex(&index1, buf); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0) - && (length >= 3)) { - int i, j, numTags; - CONST char **tagNames; - TkTextTag **oldTagArrayPtr; - - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], - " insert index chars ?tagList chars tagList ...?\"", - (char *) NULL); + Tcl_SetObjResult(interp, TkTextNewIndexObj(textPtr, indexPtr)); + break; + } + case TEXT_INSERT: { + CONST TkTextIndex *indexPtr; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, + "index chars ?tagList chars tagList ...?"); result = TCL_ERROR; goto done; } - if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) { + indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]); + if (indexPtr == NULL) { result = TCL_ERROR; goto done; } - if (textPtr->state == TK_STATE_NORMAL) { - for (j = 3; j < argc; j += 2) { - InsertChars(textPtr, &index1, argv[j]); - if (argc > (j+1)) { - TkTextIndexForwBytes(&index1, (int) strlen(argv[j]), - &index2); - oldTagArrayPtr = TkBTreeGetTags(&index1, &numTags); - if (oldTagArrayPtr != NULL) { - for (i = 0; i < numTags; i++) { - TkBTreeTag(&index1, &index2, oldTagArrayPtr[i], 0); - } - ckfree((char *) oldTagArrayPtr); - } - if (Tcl_SplitList(interp, argv[j+1], &numTags, &tagNames) - != TCL_OK) { - result = TCL_ERROR; - goto done; - } - for (i = 0; i < numTags; i++) { - TkBTreeTag(&index1, &index2, - TkTextCreateTag(textPtr, tagNames[i]), 1); - } - ckfree((char *) tagNames); - index1 = index2; + if (textPtr->state == TK_TEXT_STATE_NORMAL) { + result = TextInsertCmd(NULL, textPtr, interp, objc-3, objv+3, + indexPtr, 1); + } + break; + } + case TEXT_MARK: + result = TkTextMarkCmd(textPtr, interp, objc, objv); + break; + case TEXT_PEER: + result = TextPeerCmd(textPtr, interp, objc, objv); + break; + case TEXT_REPLACE: { + CONST TkTextIndex *indexFromPtr, *indexToPtr; + + if (objc < 5) { + Tcl_WrongNumArgs(interp, 2, objv, + "index1 index2 chars ?tagList chars tagList ...?"); + result = TCL_ERROR; + goto done; + } + indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]); + if (indexFromPtr == NULL) { + result = TCL_ERROR; + goto done; + } + indexToPtr = TkTextGetIndexFromObj(interp, textPtr, objv[3]); + if (indexToPtr == NULL) { + result = TCL_ERROR; + goto done; + } + if (TkTextIndexCmp(indexFromPtr, indexToPtr) > 0) { + Tcl_AppendResult(interp, "Index \"", Tcl_GetString(objv[3]), + "\" before \"", Tcl_GetString(objv[2]), + "\" in the text", NULL); + result = TCL_ERROR; + goto done; + } + if (textPtr->state == TK_TEXT_STATE_NORMAL) { + int lineNum, byteIndex; + TkTextIndex index; + + /* + * The 'replace' operation is quite complex to do correctly, + * because we want a number of criteria to hold: + * + * 1. The insertion point shouldn't move, unless it is within the + * deleted range. In this case it should end up after the new + * text. + * + * 2. The window should not change the text it shows - should not + * scroll vertically - unless the result of the replace is + * that the insertion position which used to be on-screen is + * now off-screen. + */ + + byteIndex = textPtr->topIndex.byteIndex; + lineNum = TkBTreeLinesTo(textPtr, textPtr->topIndex.linePtr); + + TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index); + if ((TkTextIndexCmp(indexFromPtr, &index) < 0) + && (TkTextIndexCmp(indexToPtr, &index) > 0)) { + /* + * The insertion point is inside the range to be replaced, so + * we have to do some calculations to ensure it doesn't move + * unnecessarily. + */ + + int deleteInsertOffset, insertLength, j; + + insertLength = 0; + for (j = 4; j < objc; j += 2) { + insertLength += Tcl_GetCharLength(objv[j]); } + + /* + * Calculate 'deleteInsertOffset' as an offset we will apply + * to the insertion point after this operation. + */ + + deleteInsertOffset = CountIndices(textPtr, indexFromPtr, + &index, COUNT_CHARS); + if (deleteInsertOffset > insertLength) { + deleteInsertOffset = insertLength; + } + + result = TextReplaceCmd(textPtr, interp, indexFromPtr, + indexToPtr, objc, objv, 0); + + if (result == TCL_OK) { + /* + * Move the insertion position to the correct place. + */ + + TkTextIndexForwChars(NULL, indexFromPtr, + deleteInsertOffset, &index, COUNT_INDICES); + TkBTreeUnlinkSegment(textPtr->insertMarkPtr, + textPtr->insertMarkPtr->body.mark.linePtr); + TkBTreeLinkSegment(textPtr->insertMarkPtr, &index); + } + } else { + result = TextReplaceCmd(textPtr, interp, indexFromPtr, + indexToPtr, objc, objv, 1); + } + if (result == TCL_OK) { + /* + * Now ensure the top-line is in the right place. + */ + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineNum, byteIndex, &index); + TkTextSetYView(textPtr, &index, TK_TEXT_NOPIXELADJUST); } } - } else if ((c == 'd') && (strncmp(argv[1], "dump", length) == 0)) { - result = TextDumpCmd(textPtr, interp, argc, argv); - } else if ((c == 'i') && (strncmp(argv[1], "image", length) == 0)) { - result = TkTextImageCmd(textPtr, interp, argc, argv); - } else if ((c == 'm') && (strncmp(argv[1], "mark", length) == 0)) { - result = TkTextMarkCmd(textPtr, interp, argc, argv); - } else if ((c == 's') && (strcmp(argv[1], "scan") == 0) && (length >= 2)) { - result = TkTextScanCmd(textPtr, interp, argc, argv); - } else if ((c == 's') && (strcmp(argv[1], "search") == 0) - && (length >= 3)) { - result = TextSearchCmd(textPtr, interp, argc, argv); - } else if ((c == 's') && (strcmp(argv[1], "see") == 0) && (length >= 3)) { - result = TkTextSeeCmd(textPtr, interp, argc, argv); - } else if ((c == 't') && (strcmp(argv[1], "tag") == 0)) { - result = TkTextTagCmd(textPtr, interp, argc, argv); - } else if ((c == 'w') && (strncmp(argv[1], "window", length) == 0)) { - result = TkTextWindowCmd(textPtr, interp, argc, argv); - } else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) { - result = TkTextXviewCmd(textPtr, interp, argc, argv); - } else if ((c == 'y') && (strncmp(argv[1], "yview", length) == 0) - && (length >= 2)) { - result = TkTextYviewCmd(textPtr, interp, argc, argv); - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be bbox, cget, compare, configure, debug, delete, ", - "dlineinfo, dump, edit, get, image, index, insert, mark, ", - "scan, search, see, tag, window, xview, or yview", - (char *) NULL); - result = TCL_ERROR; + break; + } + case TEXT_SCAN: + result = TkTextScanCmd(textPtr, interp, objc, objv); + break; + case TEXT_SEARCH: + result = TextSearchCmd(textPtr, interp, objc, objv); + break; + case TEXT_SEE: + result = TkTextSeeCmd(textPtr, interp, objc, objv); + break; + case TEXT_TAG: + result = TkTextTagCmd(textPtr, interp, objc, objv); + break; + case TEXT_WINDOW: + result = TkTextWindowCmd(textPtr, interp, objc, objv); + break; + case TEXT_XVIEW: + result = TkTextXviewCmd(textPtr, interp, objc, objv); + break; + case TEXT_YVIEW: + result = TkTextYviewCmd(textPtr, interp, objc, objv); + break; + } + + done: + textPtr->refCount--; + if (textPtr->refCount == 0) { + ckfree((char *) textPtr); + } + return result; +} + +/* + *-------------------------------------------------------------- + * + * SharedTextObjCmd -- + * + * This function is invoked to process commands on the shared portion of + * a text widget. Currently it is not actually exported as a Tcl command, + * and is only used internally to process parts of undo/redo scripts. + * See the user documentation for 'text' for details on what it does - + * the only subcommands it currently supports are 'insert' and 'delete'. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation for "text". + * + *-------------------------------------------------------------- + */ + +static int +SharedTextObjCmd( + ClientData clientData, /* Information about shared test B-tree. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + register TkSharedText *sharedPtr = (TkSharedText *) clientData; + int result = TCL_OK; + int index; + + static CONST char *optionStrings[] = { + "delete", "insert", NULL + }; + enum options { + TEXT_DELETE, TEXT_INSERT + }; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + + switch ((enum options) index) { + case TEXT_DELETE: + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2 ...?"); + return TCL_ERROR; + } + if (objc < 5) { + /* + * Simple case requires no predetermination of indices. + */ + + TkTextIndex index1; + + /* + * Parse the starting and stopping indices. + */ + + result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[2], + &index1); + if (result != TCL_OK) { + return result; + } + if (objc == 4) { + TkTextIndex index2; + + result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[3], + &index2); + if (result != TCL_OK) { + return result; + } + DeleteIndexRange(sharedPtr, NULL, &index1, &index2, 1); + } else { + DeleteIndexRange(sharedPtr, NULL, &index1, NULL, 1); + } + return TCL_OK; + } else { + /* Too many arguments */ + return TCL_ERROR; + } + break; + case TEXT_INSERT: { + TkTextIndex index1; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, + "index chars ?tagList chars tagList ...?"); + return TCL_ERROR; + } + result = TkTextSharedGetObjIndex(interp, sharedPtr, objv[2], + &index1); + if (result != TCL_OK) { + return result; + } + return TextInsertCmd(sharedPtr, NULL, interp, objc-3, objv+3, &index1, + 1); + } + default: + return TCL_OK; + } +} + +/* + *-------------------------------------------------------------- + * + * TextPeerCmd -- + * + * This function is invoked to process the "text peer" Tcl command. See + * the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *-------------------------------------------------------------- + */ + +static int +TextPeerCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + Tk_Window tkwin = textPtr->tkwin; + int index; + + static CONST char *peerOptionStrings[] = { + "create", "names", NULL + }; + enum peerOptions { + PEER_CREATE, PEER_NAMES + }; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObj(interp, objv[2], peerOptionStrings, + "peer option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + + switch ((enum peerOptions)index) { + case PEER_CREATE: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "pathName ?options?"); + return TCL_ERROR; + } + return CreateWidget(textPtr->sharedTextPtr, tkwin, interp, textPtr, + objc-2, objv+2); + case PEER_NAMES: { + TkText *tPtr = textPtr->sharedTextPtr->peers; + + if (objc > 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + while (tPtr != NULL) { + if (tPtr != textPtr) { + Tcl_AppendElement(interp, Tk_PathName(tPtr->tkwin)); + } + tPtr = tPtr->next; + } + } + } + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TextReplaceCmd -- + * + * This function is invoked to process part of the "replace" widget + * command for text widgets. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + * If 'viewUpdate' is false, then textPtr->topIndex may no longer be a + * valid index after this function returns. The caller is responsible for + * ensuring a correct index is in place. + * + *---------------------------------------------------------------------- + */ + +static int +TextReplaceCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + CONST TkTextIndex *indexFromPtr, + /* Index from which to replace. */ + CONST TkTextIndex *indexToPtr, + /* Index to which to replace. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument objects. */ + int viewUpdate) /* Update vertical view if set. */ +{ + /* + * Perform the deletion and insertion, but ensure no undo-separator is + * placed between the two operations. Since we are using the helper + * functions 'DeleteIndexRange' and 'TextInsertCmd' we have to pretend + * that the autoSeparators setting is off, so that we don't get an + * undo-separator between the delete and insert. + */ + + int origAutoSep = textPtr->sharedTextPtr->autoSeparators; + int result, lineNumber; + TkTextIndex indexTmp; + + if (textPtr->sharedTextPtr->undo) { + textPtr->sharedTextPtr->autoSeparators = 0; + if (origAutoSep && + textPtr->sharedTextPtr->lastEditMode!=TK_TEXT_EDIT_REPLACE) { + TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack); + } + } + + /* + * Must save and restore line in indexFromPtr based on line number; can't + * keep the line itself as that might be eliminated/invalidated when + * deleting the range. [Bug 1602537] + */ + + indexTmp = *indexFromPtr; + lineNumber = TkBTreeLinesTo(textPtr, indexFromPtr->linePtr); + DeleteIndexRange(NULL, textPtr, indexFromPtr, indexToPtr, viewUpdate); + indexTmp.linePtr = TkBTreeFindLine(indexTmp.tree, textPtr, lineNumber); + result = TextInsertCmd(NULL, textPtr, interp, objc-4, objv+4, + &indexTmp, viewUpdate); + + if (textPtr->sharedTextPtr->undo) { + textPtr->sharedTextPtr->lastEditMode = TK_TEXT_EDIT_REPLACE; + textPtr->sharedTextPtr->autoSeparators = origAutoSep; } - done: - Tcl_Release((ClientData) textPtr); return result; } @@ -886,13 +1757,13 @@ TextWidgetCmd(clientData, interp, argc, argv) * * TextIndexSortProc -- * - * This procedure is called by qsort when sorting an array of - * indices in *decreasing* order (last to first). + * This function is called by qsort when sorting an array of indices in + * *decreasing* order (last to first). * * Results: - * The return value is -1 if the first argument should be before - * the second element, 0 if it's equivalent, and 1 if it should be - * after the second element. + * The return value is -1 if the first argument should be before the + * second element, 0 if it's equivalent, and 1 if it should be after the + * second element. * * Side effects: * None. @@ -901,8 +1772,9 @@ TextWidgetCmd(clientData, interp, argc, argv) */ static int -TextIndexSortProc(first, second) - CONST VOID *first, *second; /* Elements to be compared. */ +TextIndexSortProc( + CONST void *first, /* Elements to be compared. */ + CONST void *second) { TkTextIndex *pair1 = (TkTextIndex *) first; TkTextIndex *pair2 = (TkTextIndex *) second; @@ -911,9 +1783,10 @@ TextIndexSortProc(first, second) if (cmp == 0) { /* * If the first indices were equal, we want the second index of the - * pair also to be the greater. Use pointer magic to access the - * second index pair. + * pair also to be the greater. Use pointer magic to access the second + * index pair. */ + cmp = TkTextIndexCmp(&pair1[0], &pair2[0]); } if (cmp > 0) { @@ -929,71 +1802,168 @@ TextIndexSortProc(first, second) * * DestroyText -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a text at a safe time - * (when no-one is using it anymore). + * This function is invoked when we receive a destroy event to clean up + * the internal structure of a text widget. We will free up most of the + * internal structure and delete the associated Tcl command. If there are + * no outstanding references to the widget, we also free up the textPtr + * itself. + * + * The widget has already been flagged as deleted. * * Results: * None. * * Side effects: - * Everything associated with the text is freed up. + * Either everything or almost everything associated with the text is + * freed up. * *---------------------------------------------------------------------- */ static void -DestroyText(memPtr) - char *memPtr; /* Info about text widget. */ +DestroyText( + TkText *textPtr) /* Info about text widget. */ { - register TkText *textPtr = (TkText *) memPtr; Tcl_HashSearch search; Tcl_HashEntry *hPtr; TkTextTag *tagPtr; + TkSharedText *sharedTextPtr = textPtr->sharedTextPtr; /* - * Free up all the stuff that requires special handling, then - * let Tk_FreeOptions handle all the standard option-related - * stuff. Special note: free up display-related information - * before deleting the B-tree, since display-related stuff - * may refer to stuff in the B-tree. + * Free up all the stuff that requires special handling. We have already + * called let Tk_FreeConfigOptions to handle all the standard + * option-related stuff (and so none of that exists when we are called). + * Special note: free up display-related information before deleting the + * B-tree, since display-related stuff may refer to stuff in the B-tree. */ TkTextFreeDInfo(textPtr); - TkBTreeDestroy(textPtr->tree); - for (hPtr = Tcl_FirstHashEntry(&textPtr->tagTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr); - TkTextFreeTag(textPtr, tagPtr); - } - Tcl_DeleteHashTable(&textPtr->tagTable); - for (hPtr = Tcl_FirstHashEntry(&textPtr->markTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - ckfree((char *) Tcl_GetHashValue(hPtr)); - } - Tcl_DeleteHashTable(&textPtr->markTable); + textPtr->dInfoPtr = NULL; + + /* + * Remove ourselves from the peer list. + */ + + if (sharedTextPtr->peers == textPtr) { + sharedTextPtr->peers = textPtr->next; + } else { + TkText *nextPtr = sharedTextPtr->peers; + while (nextPtr != NULL) { + if (nextPtr->next == textPtr) { + nextPtr->next = textPtr->next; + break; + } + nextPtr = nextPtr->next; + } + } + + /* + * Always clean up the widget-specific tags first. Common tags (i.e. most) + * will only be cleaned up when the shared structure is cleaned up. + * + * We also need to clean up widget-specific marks ('insert', 'current'), + * since otherwise marks will never disappear from the B-tree. + */ + + TkTextDeleteTag(textPtr, textPtr->selTagPtr); + TkBTreeUnlinkSegment(textPtr->insertMarkPtr, + textPtr->insertMarkPtr->body.mark.linePtr); + ckfree((char *) textPtr->insertMarkPtr); + TkBTreeUnlinkSegment(textPtr->currentMarkPtr, + textPtr->currentMarkPtr->body.mark.linePtr); + ckfree((char *) textPtr->currentMarkPtr); + + /* + * Now we've cleaned up everything of relevance to us in the B-tree, so we + * disassociate outselves from it. + * + * When the refCount reaches zero, it's time to clean up the shared + * portion of the text widget. + */ + + sharedTextPtr->refCount--; + + if (sharedTextPtr->refCount > 0) { + TkBTreeRemoveClient(sharedTextPtr->tree, textPtr); + + /* + * Free up any embedded windows which belong to this widget. + */ + + for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->windowTable, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + TkTextEmbWindowClient *loop; + TkTextSegment *ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + + loop = ewPtr->body.ew.clients; + if (loop->textPtr == textPtr) { + ewPtr->body.ew.clients = loop->next; + TkTextWinFreeClient(hPtr, loop); + } else { + TkTextEmbWindowClient *client = ewPtr->body.ew.clients; + + client = loop->next; + while (client != NULL) { + if (client->textPtr == textPtr) { + loop->next = client->next; + TkTextWinFreeClient(hPtr, client); + break; + } else { + loop = loop->next; + } + client = loop->next; + } + } + } + } else { + /* + * No need to call 'TkBTreeRemoveClient' first, since this will do + * everything in one go, more quickly. + */ + + TkBTreeDestroy(sharedTextPtr->tree); + + for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr); + + /* + * No need to use 'TkTextDeleteTag' since we've already removed + * the B-tree completely. + */ + + TkTextFreeTag(textPtr, tagPtr); + } + Tcl_DeleteHashTable(&sharedTextPtr->tagTable); + for (hPtr = Tcl_FirstHashEntry(&sharedTextPtr->markTable, &search); + hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + ckfree((char *) Tcl_GetHashValue(hPtr)); + } + Tcl_DeleteHashTable(&sharedTextPtr->markTable); + TkUndoFreeStack(sharedTextPtr->undoStack); + + Tcl_DeleteHashTable(&sharedTextPtr->windowTable); + Tcl_DeleteHashTable(&sharedTextPtr->imageTable); + + if (sharedTextPtr->bindingTable != NULL) { + Tk_DeleteBindingTable(sharedTextPtr->bindingTable); + } + ckfree((char *) sharedTextPtr); + } + if (textPtr->tabArrayPtr != NULL) { ckfree((char *) textPtr->tabArrayPtr); } if (textPtr->insertBlinkHandler != NULL) { Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler); } - if (textPtr->bindingTable != NULL) { - Tk_DeleteBindingTable(textPtr->bindingTable); - } - TkUndoFreeStack(textPtr->undoStack); - /* - * NOTE: do NOT free up selBorder, selBdString, or selFgColorPtr: - * they are duplicates of information in the "sel" tag, which was - * freed up as part of deleting the tags above. - */ - - textPtr->selBorder = NULL; - textPtr->selBdString = NULL; - textPtr->selFgColorPtr = NULL; - Tk_FreeOptions(configSpecs, (char *) textPtr, textPtr->display, 0); - ckfree((char *) textPtr); + textPtr->tkwin = NULL; + textPtr->refCount--; + Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd); + if (textPtr->refCount == 0) { + ckfree((char *) textPtr); + } } /* @@ -1001,47 +1971,165 @@ DestroyText(memPtr) * * ConfigureText -- * - * This procedure is called to process an argv/argc list, plus - * the Tk option database, in order to configure (or - * reconfigure) a text widget. + * This function is called to process an objv/objc list, plus the Tk + * option database, in order to configure (or reconfigure) a text widget. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message. * * Side effects: - * Configuration information, such as text string, colors, font, - * etc. get set for textPtr; old resources get freed, if there - * were any. + * Configuration information, such as text string, colors, font, etc. get + * set for textPtr; old resources get freed, if there were any. * *---------------------------------------------------------------------- */ static int -ConfigureText(interp, textPtr, argc, argv, flags) - Tcl_Interp *interp; /* Used for error reporting. */ - register TkText *textPtr; /* Information about widget; may or may - * not already have values for some fields. */ - int argc; /* Number of valid entries in argv. */ - CONST char **argv; /* Arguments. */ - int flags; /* Flags to pass to Tk_ConfigureWidget. */ +ConfigureText( + Tcl_Interp *interp, /* Used for error reporting. */ + register TkText *textPtr, /* Information about widget; may or may not + * already have values for some fields. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { + Tk_SavedOptions savedOptions; int oldExport = textPtr->exportSelection; + int mask = 0; - if (Tk_ConfigureWidget(interp, textPtr->tkwin, configSpecs, - argc, argv, (char *) textPtr, flags) != TCL_OK) { + if (Tk_SetOptions(interp, (char *) textPtr, textPtr->optionTable, + objc, objv, textPtr->tkwin, &savedOptions, &mask) != TCL_OK) { return TCL_ERROR; } - TkUndoSetDepth(textPtr->undoStack, textPtr->maxUndo); + /* + * Copy down shared flags. + */ + + textPtr->sharedTextPtr->undo = textPtr->undo; + textPtr->sharedTextPtr->maxUndo = textPtr->maxUndo; + textPtr->sharedTextPtr->autoSeparators = textPtr->autoSeparators; + + TkUndoSetDepth(textPtr->sharedTextPtr->undoStack, + textPtr->sharedTextPtr->maxUndo); /* - * A few other options also need special processing, such as parsing - * the geometry and setting the background from a 3-D border. + * A few other options also need special processing, such as parsing the + * geometry and setting the background from a 3-D border. */ Tk_SetBackgroundFromBorder(textPtr->tkwin, textPtr->border); + if (mask & TK_TEXT_LINE_RANGE) { + int start, end, current; + TkTextIndex index1, index2, index3; + + /* + * Line start and/or end have been adjusted. We need to validate the + * first displayed line and arrange for re-layout. + */ + + TkBTreeClientRangeChanged(textPtr, textPtr->charHeight); + + if (textPtr->start != NULL) { + start = TkBTreeLinesTo(NULL, textPtr->start); + } else { + start = 0; + } + if (textPtr->end != NULL) { + end = TkBTreeLinesTo(NULL, textPtr->end); + } else { + end = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL); + } + if (start > end) { + Tcl_AppendResult(interp, + "-startline must be less than or equal to -endline", + NULL); + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; + } + current = TkBTreeLinesTo(NULL, textPtr->topIndex.linePtr); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, start, 0, + &index1); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, end, 0, + &index2); + if (current < start || current > end) { + TkTextSearch search; + TkTextIndex first, last; + int selChanged = 0; + + TkTextSetYView(textPtr, &index1, 0); + + /* + * We may need to adjust the selection. So we have to check + * whether the "sel" tag was applied to anything outside the + * current start,end. + */ + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, 0, 0, + &first); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL), + 0, &last); + TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search); + if (!TkBTreeCharTagged(&first, textPtr->selTagPtr) + && !TkBTreeNextTag(&search)) { + /* Nothing tagged with "sel" */ + } else { + int line = TkBTreeLinesTo(NULL, search.curIndex.linePtr); + if (line < start) { + selChanged = 1; + } else { + TkTextLine *linePtr = search.curIndex.linePtr; + + while (TkBTreeNextTag(&search)) { + linePtr = search.curIndex.linePtr; + } + line = TkBTreeLinesTo(NULL, linePtr); + if (line >= end) { + selChanged = 1; + } + } + } + if (selChanged) { + /* + * Send an event that the selection has changed, and abort any + * partial-selections in progress. + */ + + TkTextSelectionEvent(textPtr); + textPtr->abortSelections = 1; + } + } + + /* Indices are potentially obsolete after changing -startline and/or + * -endline, therefore increase the epoch. + * 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. + */ + + textPtr->sharedTextPtr->stateEpoch++; + TkTextMarkNameToIndex(textPtr, "insert", &index3); + if (TkTextIndexCmp(&index3, &index1) < 0) { + textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &index1); + } + if (TkTextIndexCmp(&index3, &index2) > 0) { + textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &index2); + } + TkTextMarkNameToIndex(textPtr, "current", &index3); + if (TkTextIndexCmp(&index3, &index1) < 0) { + textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &index1); + } + if (TkTextIndexCmp(&index3, &index2) > 0) { + textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &index2); + } + } + /* * Don't allow negative spacings. */ @@ -1064,62 +2152,56 @@ ConfigureText(interp, textPtr, argc, argv, flags) ckfree((char *) textPtr->tabArrayPtr); textPtr->tabArrayPtr = NULL; } - if (textPtr->tabOptionString != NULL) { - textPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr->tkwin, - textPtr->tabOptionString); + if (textPtr->tabOptionPtr != NULL) { + textPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr, + textPtr->tabOptionPtr); if (textPtr->tabArrayPtr == NULL) { Tcl_AddErrorInfo(interp,"\n (while processing -tabs option)"); + Tk_RestoreSavedOptions(&savedOptions); return TCL_ERROR; } } /* - * Make sure that configuration options are properly mirrored - * between the widget record and the "sel" tags. NOTE: we don't - * have to free up information during the mirroring; old - * information was freed when it was replaced in the widget - * record. + * Make sure that configuration options are properly mirrored between the + * widget record and the "sel" tags. NOTE: we don't have to free up + * information during the mirroring; old information was freed when it was + * replaced in the widget record. */ textPtr->selTagPtr->border = textPtr->selBorder; - if (textPtr->selTagPtr->bdString != textPtr->selBdString) { - textPtr->selTagPtr->bdString = textPtr->selBdString; - if (textPtr->selBdString != NULL) { - if (Tk_GetPixels(interp, textPtr->tkwin, textPtr->selBdString, - &textPtr->selTagPtr->borderWidth) != TCL_OK) { - return TCL_ERROR; - } - if (textPtr->selTagPtr->borderWidth < 0) { - textPtr->selTagPtr->borderWidth = 0; - } - } + if (textPtr->selTagPtr->borderWidthPtr != textPtr->selBorderWidthPtr) { + textPtr->selTagPtr->borderWidthPtr = textPtr->selBorderWidthPtr; + textPtr->selTagPtr->borderWidth = textPtr->selBorderWidth; } textPtr->selTagPtr->fgColor = textPtr->selFgColorPtr; textPtr->selTagPtr->affectsDisplay = 0; - if ((textPtr->selTagPtr->border != NULL) - || (textPtr->selTagPtr->bdString != NULL) - || (textPtr->selTagPtr->reliefString != NULL) - || (textPtr->selTagPtr->bgStipple != None) - || (textPtr->selTagPtr->fgColor != NULL) + textPtr->selTagPtr->affectsDisplayGeometry = 0; + if ((textPtr->selTagPtr->elideString != NULL) || (textPtr->selTagPtr->tkfont != None) - || (textPtr->selTagPtr->fgStipple != None) || (textPtr->selTagPtr->justifyString != NULL) || (textPtr->selTagPtr->lMargin1String != NULL) || (textPtr->selTagPtr->lMargin2String != NULL) || (textPtr->selTagPtr->offsetString != NULL) - || (textPtr->selTagPtr->overstrikeString != NULL) || (textPtr->selTagPtr->rMarginString != NULL) || (textPtr->selTagPtr->spacing1String != NULL) || (textPtr->selTagPtr->spacing2String != NULL) || (textPtr->selTagPtr->spacing3String != NULL) - || (textPtr->selTagPtr->tabString != NULL) - || (textPtr->selTagPtr->underlineString != NULL) - || (textPtr->selTagPtr->elideString != NULL) + || (textPtr->selTagPtr->tabStringPtr != NULL) || (textPtr->selTagPtr->wrapMode != TEXT_WRAPMODE_NULL)) { textPtr->selTagPtr->affectsDisplay = 1; + textPtr->selTagPtr->affectsDisplayGeometry = 1; } - TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL, - textPtr->selTagPtr, 1); + if ((textPtr->selTagPtr->border != NULL) + || (textPtr->selTagPtr->reliefString != NULL) + || (textPtr->selTagPtr->bgStipple != None) + || (textPtr->selTagPtr->fgColor != NULL) + || (textPtr->selTagPtr->fgStipple != None) + || (textPtr->selTagPtr->overstrikeString != NULL) + || (textPtr->selTagPtr->underlineString != NULL)) { + textPtr->selTagPtr->affectsDisplay = 1; + } + TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, 1); /* * Claim the selection if we've suddenly started exporting it and there @@ -1130,9 +2212,11 @@ ConfigureText(interp, textPtr, argc, argv, flags) TkTextSearch search; TkTextIndex first, last; - TkTextMakeByteIndex(textPtr->tree, 0, 0, &first); - TkTextMakeByteIndex(textPtr->tree, - TkBTreeNumLines(textPtr->tree), 0, &last); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, + &first); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), + 0, &last); TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search); if (TkBTreeCharTagged(&first, textPtr->selTagPtr) || TkBTreeNextTag(&search)) { @@ -1153,8 +2237,8 @@ ConfigureText(interp, textPtr, argc, argv, flags) } /* - * Register the desired geometry for the window, and arrange for - * the window to be redisplayed. + * Register the desired geometry for the window, and arrange for the + * window to be redisplayed. */ if (textPtr->width <= 0) { @@ -1163,60 +2247,97 @@ ConfigureText(interp, textPtr, argc, argv, flags) if (textPtr->height <= 0) { textPtr->height = 1; } - TextWorldChanged((ClientData) textPtr); + Tk_FreeSavedOptions(&savedOptions); + TextWorldChanged(textPtr, mask); return TCL_OK; } /* *--------------------------------------------------------------------------- * - * TextWorldChanged -- + * TextWorldChangedCallback -- * - * This procedure is called when the world has changed in some - * way and the widget needs to recompute all its graphics contexts - * and determine its new geometry. + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. * * Results: - * None. + * None. * * Side effects: - * Configures all tags in the Text with a empty argc/argv, for - * the side effect of causing all the items to recompute their - * geometry and to be redisplayed. + * Configures all tags in the Text with a empty objc/objv, for the side + * effect of causing all the items to recompute their geometry and to be + * redisplayed. * *--------------------------------------------------------------------------- */ - + static void -TextWorldChanged(instanceData) - ClientData instanceData; /* Information about widget. */ +TextWorldChangedCallback( + ClientData instanceData) /* Information about widget. */ { TkText *textPtr; - Tk_FontMetrics fm; textPtr = (TkText *) instanceData; + TextWorldChanged(textPtr, TK_TEXT_LINE_GEOMETRY); +} + +/* + *--------------------------------------------------------------------------- + * + * TextWorldChanged -- + * + * This function is called when the world has changed in some way and the + * widget needs to recompute all its graphics contexts and determine its + * new geometry. + * + * Results: + * None. + * + * Side effects: + * Configures all tags in the Text with a empty objc/objv, for the side + * effect of causing all the items to recompute their geometry and to be + * redisplayed. + * + *--------------------------------------------------------------------------- + */ + +static void +TextWorldChanged( + TkText *textPtr, /* Information about widget. */ + int mask) /* OR'd collection of bits showing what has + * changed. */ +{ + Tk_FontMetrics fm; + int border; textPtr->charWidth = Tk_TextWidth(textPtr->tkfont, "0", 1); if (textPtr->charWidth <= 0) { textPtr->charWidth = 1; } Tk_GetFontMetrics(textPtr->tkfont, &fm); + + textPtr->charHeight = fm.linespace; + if (textPtr->charHeight <= 0) { + textPtr->charHeight = 1; + } + border = textPtr->borderWidth + textPtr->highlightWidth; Tk_GeometryRequest(textPtr->tkwin, - textPtr->width * textPtr->charWidth + 2*textPtr->borderWidth - + 2*textPtr->padX + 2*textPtr->highlightWidth, - textPtr->height * (fm.linespace + textPtr->spacing1 - + textPtr->spacing3) + 2*textPtr->borderWidth - + 2*textPtr->padY + 2*textPtr->highlightWidth); - Tk_SetInternalBorder(textPtr->tkwin, - textPtr->borderWidth + textPtr->highlightWidth); + textPtr->width * textPtr->charWidth + 2*textPtr->padX + 2*border, + textPtr->height*(fm.linespace+textPtr->spacing1+textPtr->spacing3) + + 2*textPtr->padY + 2*border); + + Tk_SetInternalBorderEx(textPtr->tkwin, + border + textPtr->padX, border + textPtr->padX, + border + textPtr->padY, border + textPtr->padY); if (textPtr->setGrid) { Tk_SetGrid(textPtr->tkwin, textPtr->width, textPtr->height, - textPtr->charWidth, fm.linespace); + textPtr->charWidth, textPtr->charHeight); } else { Tk_UnsetGrid(textPtr->tkwin); } - TkTextRelayoutWindow(textPtr); + TkTextRelayoutWindow(textPtr, mask); } /* @@ -1224,24 +2345,24 @@ TextWorldChanged(instanceData) * * TextEventProc -- * - * This procedure is invoked by the Tk dispatcher on - * structure changes to a text. For texts with 3D - * borders, this procedure is also invoked for exposures. + * This function is invoked by the Tk dispatcher on structure changes to + * a text. For texts with 3D borders, this function is also invoked for + * exposures. * * Results: * None. * * Side effects: - * When the window gets deleted, internal structures get - * cleaned up. When it gets exposed, it is redisplayed. + * When the window gets deleted, internal structures get cleaned up. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void -TextEventProc(clientData, eventPtr) - ClientData clientData; /* Information about window. */ - register XEvent *eventPtr; /* Information about event. */ +TextEventProc( + ClientData clientData, /* Information about window. */ + register XEvent *eventPtr) /* Information about event. */ { register TkText *textPtr = (TkText *) clientData; TkTextIndex index, index2; @@ -1253,22 +2374,51 @@ TextEventProc(clientData, eventPtr) } else if (eventPtr->type == ConfigureNotify) { if ((textPtr->prevWidth != Tk_Width(textPtr->tkwin)) || (textPtr->prevHeight != Tk_Height(textPtr->tkwin))) { - TkTextRelayoutWindow(textPtr); + int mask = 0; + + if (textPtr->prevWidth != Tk_Width(textPtr->tkwin)) { + mask = TK_TEXT_LINE_GEOMETRY; + } + TkTextRelayoutWindow(textPtr, mask); textPtr->prevWidth = Tk_Width(textPtr->tkwin); textPtr->prevHeight = Tk_Height(textPtr->tkwin); } } else if (eventPtr->type == DestroyNotify) { - if (textPtr->tkwin != NULL) { - if (textPtr->setGrid) { - Tk_UnsetGrid(textPtr->tkwin); - } - textPtr->tkwin = NULL; - Tcl_DeleteCommandFromToken(textPtr->interp, - textPtr->widgetCmd); + /* + * NOTE: we must zero out selBorder, selBorderWidthPtr and + * selFgColorPtr: they are duplicates of information in the "sel" tag, + * which will be freed up when we delete all tags. Hence we don't want + * the automatic config options freeing process to delete them as + * well. + */ + + textPtr->selBorder = NULL; + textPtr->selBorderWidthPtr = NULL; + textPtr->selBorderWidth = 0; + textPtr->selFgColorPtr = NULL; + if (textPtr->setGrid) { + Tk_UnsetGrid(textPtr->tkwin); + textPtr->setGrid = 0; } - Tcl_EventuallyFree((ClientData) textPtr, DestroyText); + if (!(textPtr->flags & OPTIONS_FREED)) { + Tk_FreeConfigOptions((char *) textPtr, textPtr->optionTable, + textPtr->tkwin); + textPtr->flags |= OPTIONS_FREED; + } + textPtr->flags |= DESTROYED; + + /* + * Call 'DestroyTest' to handle the deletion for us. The actual + * textPtr may still exist after this, if there are some outstanding + * references. But we have flagged it as DESTROYED just above, so + * nothing will try to make use of it very extensively. + */ + + DestroyText(textPtr); } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) { - if (eventPtr->xfocus.detail != NotifyInferior) { + if (eventPtr->xfocus.detail == NotifyInferior + || eventPtr->xfocus.detail == NotifyAncestor + || eventPtr->xfocus.detail == NotifyNonlinear) { Tcl_DeleteTimerHandler(textPtr->insertBlinkHandler); if (eventPtr->type == FocusIn) { textPtr->flags |= GOT_FOCUS | INSERT_ON; @@ -1281,19 +2431,19 @@ TextEventProc(clientData, eventPtr) textPtr->flags &= ~(GOT_FOCUS | INSERT_ON); textPtr->insertBlinkHandler = (Tcl_TimerToken) NULL; } - if ( -#ifndef MAC_OSX_TK - !TkpAlwaysShowSelection(textPtr->tkwin) -#else - /* Don't show inactive selection in disabled widgets. */ - textPtr->state != TK_STATE_DISABLED -#endif - ) { - TkTextRedrawTag(textPtr, NULL, NULL, textPtr->selTagPtr, 1); + if (textPtr->inactiveSelBorder != textPtr->selBorder) { + TkTextRedrawTag(NULL, textPtr, NULL, NULL, textPtr->selTagPtr, + 1); } TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index); - TkTextIndexForwChars(&index, 1, &index2); - TkTextChanged(textPtr, &index, &index2); + TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES); + + /* + * While we wish to redisplay, no heights have changed, so no need + * to call TkTextInvalidateLineMetrics. + */ + + TkTextChanged(NULL, textPtr, &index, &index2); if (textPtr->highlightWidth > 0) { TkTextRedrawRegion(textPtr, 0, 0, textPtr->highlightWidth, textPtr->highlightWidth); @@ -1307,9 +2457,9 @@ TextEventProc(clientData, eventPtr) * * TextCmdDeletedProc -- * - * This procedure is invoked when a widget command is deleted. If - * the widget isn't already in the process of being destroyed, - * this command destroys it. + * This function is invoked when a widget command is deleted. If the + * widget isn't already in the process of being destroyed, this command + * destroys it. * * Results: * None. @@ -1321,24 +2471,25 @@ TextEventProc(clientData, eventPtr) */ static void -TextCmdDeletedProc(clientData) - ClientData clientData; /* Pointer to widget record for widget. */ +TextCmdDeletedProc( + ClientData clientData) /* Pointer to widget record for widget. */ { TkText *textPtr = (TkText *) clientData; Tk_Window tkwin = textPtr->tkwin; /* - * This procedure could be invoked either because the window was - * destroyed and the command was then deleted (in which case tkwin - * is NULL) or because the command was deleted, and then this procedure - * destroys the widget. + * This function could be invoked either because the window was destroyed + * and the command was then deleted (in which this flag is already set) or + * because the command was deleted, and then this function destroys the + * widget. */ - if (tkwin != NULL) { + if (!(textPtr->flags & DESTROYED)) { if (textPtr->setGrid) { Tk_UnsetGrid(textPtr->tkwin); + textPtr->setGrid = 0; } - textPtr->tkwin = NULL; + textPtr->flags |= DESTROYED; Tk_DestroyWindow(tkwin); } } @@ -1348,205 +2499,483 @@ TextCmdDeletedProc(clientData) * * InsertChars -- * - * This procedure implements most of the functionality of the - * "insert" widget command. + * This function implements most of the functionality of the "insert" + * widget command. * * Results: - * None. + * The length of the inserted string. * * Side effects: - * The characters in "string" get added to the text just before - * the character indicated by "indexPtr". + * The characters in "stringPtr" get added to the text just before the + * character indicated by "indexPtr". + * + * If 'viewUpdate' is true, we may adjust the window contents' + * y-position, and scrollbar setting. * *---------------------------------------------------------------------- */ -static void -InsertChars(textPtr, indexPtr, string) - TkText *textPtr; /* Overall information about text widget. */ - TkTextIndex *indexPtr; /* Where to insert new characters. May be - * modified and/or invalidated. */ - CONST char *string; /* Null-terminated string containing new +static int +InsertChars( + TkSharedText *sharedTextPtr, + TkText *textPtr, /* Overall information about text widget. */ + TkTextIndex *indexPtr, /* Where to insert new characters. May be + * modified if the index is not valid for + * insertion (e.g. if at "end"). */ + Tcl_Obj *stringPtr, /* Null-terminated string containing new * information to add to text. */ + int viewUpdate) /* Update the view if set. */ { - int lineIndex, resetView, offset; - TkTextIndex newTop; - char indexBuffer[TK_POS_CHARS]; + int lineIndex, length; + TkText *tPtr; + int *lineAndByteIndex; + int resetViewCount; + int pixels[2*PIXEL_CLIENTS]; - /* - * Don't do anything for an empty string [Bug 1275237] - */ + CONST char *string = Tcl_GetStringFromObj(stringPtr, &length); - if (*string == '\0') { - return; + if (sharedTextPtr == NULL) { + sharedTextPtr = textPtr->sharedTextPtr; } /* - * Don't allow insertions on the last (dummy) line of the text. + * Don't allow insertions on the last (dummy) line of the text. This is + * the only place in this function where the indexPtr is modified. */ - lineIndex = TkBTreeLineIndex(indexPtr->linePtr); - if (lineIndex == TkBTreeNumLines(textPtr->tree)) { + lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr); + if (lineIndex == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) { lineIndex--; - TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, indexPtr); + TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, lineIndex, 1000000, + indexPtr); } /* - * Notify the display module that lines are about to change, then do - * the insertion. If the insertion occurs on the top line of the - * widget (textPtr->topIndex), then we have to recompute topIndex - * after the insertion, since the insertion could invalidate it. + * Notify the display module that lines are about to change, then do the + * insertion. If the insertion occurs on the top line of the widget + * (textPtr->topIndex), then we have to recompute topIndex after the + * insertion, since the insertion could invalidate it. */ - resetView = offset = 0; - if (indexPtr->linePtr == textPtr->topIndex.linePtr) { - resetView = 1; - offset = textPtr->topIndex.byteIndex; - if (offset > indexPtr->byteIndex) { - offset += strlen(string); + resetViewCount = 0; + if (sharedTextPtr->refCount > PIXEL_CLIENTS) { + lineAndByteIndex = (int *) + ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount); + } else { + lineAndByteIndex = pixels; + } + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + lineAndByteIndex[resetViewCount] = -1; + if (indexPtr->linePtr == tPtr->topIndex.linePtr) { + lineAndByteIndex[resetViewCount] = + TkBTreeLinesTo(tPtr, indexPtr->linePtr); + lineAndByteIndex[resetViewCount+1] = tPtr->topIndex.byteIndex; + if (lineAndByteIndex[resetViewCount+1] > indexPtr->byteIndex) { + lineAndByteIndex[resetViewCount+1] += length; + } } + resetViewCount += 2; } - TkTextChanged(textPtr, indexPtr, indexPtr); - TkBTreeInsertChars(indexPtr, string); + + TkTextChanged(sharedTextPtr, NULL, indexPtr, indexPtr); + + sharedTextPtr->stateEpoch++; + + TkBTreeInsertChars(sharedTextPtr->tree, indexPtr, string); /* - * Push the insertion on the undo stack + * Push the insertion on the undo stack, and update the modified status of + * the widget. */ - if (textPtr->undo) { - CONST char *cmdName; - TkTextIndex toIndex; + if (length > 0) { + if (sharedTextPtr->undo) { + TkTextIndex toIndex; + + if (sharedTextPtr->autoSeparators && + sharedTextPtr->lastEditMode != TK_TEXT_EDIT_INSERT) { + TkUndoInsertUndoSeparator(sharedTextPtr->undoStack); + } - Tcl_DString actionCommand; - Tcl_DString revertCommand; + sharedTextPtr->lastEditMode = TK_TEXT_EDIT_INSERT; - if (textPtr->autoSeparators && - textPtr->lastEditMode != TK_TEXT_EDIT_INSERT) { - TkUndoInsertUndoSeparator(textPtr->undoStack); + TkTextIndexForwBytes(textPtr, indexPtr, length, &toIndex); + TextPushUndoAction(textPtr, stringPtr, 1, indexPtr, &toIndex); } - textPtr->lastEditMode = TK_TEXT_EDIT_INSERT; - cmdName = Tcl_GetCommandName(textPtr->interp, textPtr->widgetCmd); + UpdateDirtyFlag(sharedTextPtr); + } + + resetViewCount = 0; + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + if (lineAndByteIndex[resetViewCount] != -1) { + if ((tPtr != textPtr) || viewUpdate) { + TkTextIndex newTop; + + TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, + lineAndByteIndex[resetViewCount], 0, &newTop); + TkTextIndexForwBytes(tPtr, &newTop, + lineAndByteIndex[resetViewCount+1], &newTop); + TkTextSetYView(tPtr, &newTop, 0); + } + } + resetViewCount += 2; + } + if (sharedTextPtr->refCount > PIXEL_CLIENTS) { + ckfree((char *) lineAndByteIndex); + } + + /* + * Invalidate any selection retrievals in progress. + */ + + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + tPtr->abortSelections = 1; + } - Tcl_DStringInit(&actionCommand); - Tcl_DStringInit(&revertCommand); + /* + * For convenience, return the length of the string. + */ - Tcl_DStringAppendElement(&actionCommand, cmdName); - Tcl_DStringAppend(&actionCommand, " insert ", -1); - TkTextPrintIndex(indexPtr,indexBuffer); - Tcl_DStringAppend(&actionCommand, indexBuffer, -1); - Tcl_DStringAppend(&actionCommand, " ", -1); - Tcl_DStringAppendElement(&actionCommand, string); - Tcl_DStringAppend(&actionCommand, ";", -1); - Tcl_DStringAppendElement(&actionCommand, cmdName); - Tcl_DStringAppend(&actionCommand, " mark set insert ", -1); - TkTextIndexForwBytes(indexPtr, (int) strlen(string), &toIndex); - TkTextPrintIndex(&toIndex, indexBuffer); - Tcl_DStringAppend(&actionCommand, indexBuffer,-1); - Tcl_DStringAppend(&actionCommand, "; ", -1); - Tcl_DStringAppendElement(&actionCommand, cmdName); - Tcl_DStringAppend(&actionCommand, " see insert", -1); + return length; +} + +/* + *---------------------------------------------------------------------- + * + * TextPushUndoAction -- + * + * Shared by insert and delete actions. Stores the appropriate scripts + * into our undo stack. We will add a single refCount to the 'undoString' + * object, so, if it previously had a refCount of zero, the caller should + * not free it. + * + * Results: + * None. + * + * Side effects: + * Items pushed onto stack. + * + *---------------------------------------------------------------------- + */ - Tcl_DStringAppendElement(&revertCommand, cmdName); - Tcl_DStringAppend(&revertCommand, " delete ", -1); - TkTextPrintIndex(indexPtr, indexBuffer); - Tcl_DStringAppend(&revertCommand, indexBuffer, -1); - Tcl_DStringAppend(&revertCommand, " ", -1); - TkTextPrintIndex(&toIndex, indexBuffer); - Tcl_DStringAppend(&revertCommand, indexBuffer, -1); - Tcl_DStringAppend(&revertCommand, " ;", -1); - Tcl_DStringAppendElement(&revertCommand, cmdName); - Tcl_DStringAppend(&revertCommand, " mark set insert ", -1); - TkTextPrintIndex(indexPtr,indexBuffer); - Tcl_DStringAppend(&revertCommand, indexBuffer, -1); - Tcl_DStringAppend(&revertCommand, "; ", -1); - Tcl_DStringAppendElement(&revertCommand, cmdName); - Tcl_DStringAppend(&revertCommand," see insert", -1); +static void +TextPushUndoAction( + TkText *textPtr, /* Overall information about text widget. */ + Tcl_Obj *undoString, /* New text. */ + int insert, /* 1 if insert, else delete. */ + CONST TkTextIndex *index1Ptr, + /* Index describing first location. */ + CONST TkTextIndex *index2Ptr) + /* Index describing second location. */ +{ + TkUndoSubAtom *iAtom, *dAtom; - TkUndoPushAction(textPtr->undoStack, &actionCommand, &revertCommand); + /* + * Create the helpers. + */ - Tcl_DStringFree(&actionCommand); - Tcl_DStringFree(&revertCommand); + Tcl_Obj *seeInsertObj = Tcl_NewObj(); + Tcl_Obj *markSet1InsertObj = Tcl_NewObj(); + Tcl_Obj *markSet2InsertObj = NULL; + Tcl_Obj *insertCmdObj = Tcl_NewObj(); + Tcl_Obj *deleteCmdObj = Tcl_NewObj(); + + /* + * Get the index positions. + */ + + Tcl_Obj *index1Obj = TkTextNewIndexObj(NULL, index1Ptr); + Tcl_Obj *index2Obj = TkTextNewIndexObj(NULL, index2Ptr); + + /* + * These need refCounts, because they are used more than once below. + */ + + Tcl_IncrRefCount(seeInsertObj); + Tcl_IncrRefCount(index1Obj); + Tcl_IncrRefCount(index2Obj); + + Tcl_ListObjAppendElement(NULL, seeInsertObj, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1)); + Tcl_ListObjAppendElement(NULL, seeInsertObj, Tcl_NewStringObj("see", 3)); + Tcl_ListObjAppendElement(NULL, seeInsertObj, + Tcl_NewStringObj("insert", 6)); + + Tcl_ListObjAppendElement(NULL, markSet1InsertObj, + Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1)); + Tcl_ListObjAppendElement(NULL, markSet1InsertObj, + Tcl_NewStringObj("mark", 4)); + Tcl_ListObjAppendElement(NULL, markSet1InsertObj, + Tcl_NewStringObj("set", 3)); + Tcl_ListObjAppendElement(NULL, markSet1InsertObj, + Tcl_NewStringObj("insert", 6)); + markSet2InsertObj = Tcl_DuplicateObj(markSet1InsertObj); + Tcl_ListObjAppendElement(NULL, markSet1InsertObj, index1Obj); + Tcl_ListObjAppendElement(NULL, markSet2InsertObj, index2Obj); + + Tcl_ListObjAppendElement(NULL, insertCmdObj, + Tcl_NewStringObj("insert", 6)); + Tcl_ListObjAppendElement(NULL, insertCmdObj, index1Obj); + + /* + * Only use of 'undoString' is here. + */ + + Tcl_ListObjAppendElement(NULL, insertCmdObj, undoString); + + Tcl_ListObjAppendElement(NULL, deleteCmdObj, + Tcl_NewStringObj("delete", 6)); + Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj); + Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj); + + /* + * Note: we don't wish to use textPtr->widgetCmd in these callbacks + * because if we delete the textPtr, but peers still exist, we will then + * have references to a non-existent Tcl_Command in the undo stack, which + * will lead to crashes later. Also, the behaviour of the widget w.r.t. + * bindings (%W substitutions) always uses the widget path name, so there + * is no good reason the undo stack should do otherwise. + * + * For the 'insert' and 'delete' actions, we have to register a functional + * callback, because these actions are defined to operate on the + * underlying data shared by all peers. + */ + + iAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, + (ClientData)textPtr->sharedTextPtr, insertCmdObj, NULL); + TkUndoMakeCmdSubAtom(NULL, markSet2InsertObj, iAtom); + TkUndoMakeCmdSubAtom(NULL, seeInsertObj, iAtom); + + dAtom = TkUndoMakeSubAtom(&TextUndoRedoCallback, + (ClientData)textPtr->sharedTextPtr, deleteCmdObj, NULL); + TkUndoMakeCmdSubAtom(NULL, markSet1InsertObj, dAtom); + TkUndoMakeCmdSubAtom(NULL, seeInsertObj, dAtom); + + Tcl_DecrRefCount(seeInsertObj); + Tcl_DecrRefCount(index1Obj); + Tcl_DecrRefCount(index2Obj); + + /* + * Depending whether the action is to insert or delete, we provide the + * appropriate second and third arguments to TkUndoPushAction. (The first + * is the 'actionCommand', and the second the 'revertCommand'). + */ + + if (insert) { + TkUndoPushAction(textPtr->sharedTextPtr->undoStack, iAtom, dAtom); + } else { + TkUndoPushAction(textPtr->sharedTextPtr->undoStack, dAtom, iAtom); } - updateDirtyFlag(textPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TextUndoRedoCallback -- + * + * This function is registered with the generic undo/redo code to handle + * 'insert' and 'delete' actions on all text widgets. We cannot perform + * those actions on any particular text widget, because that text widget + * might have been deleted by the time we get here. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Will insert or delete text, depending on the first word contained in + * objPtr. + * + *---------------------------------------------------------------------- + */ - if (resetView) { - TkTextMakeByteIndex(textPtr->tree, lineIndex, 0, &newTop); - TkTextIndexForwBytes(&newTop, offset, &newTop); - TkTextSetYView(textPtr, &newTop, 0); +int +TextUndoRedoCallback( + Tcl_Interp *interp, /* Current interpreter. */ + ClientData clientData, /* Passed from undo code, but contains our + * shared text data structure. */ + Tcl_Obj *objPtr) /* Arguments of a command to be handled by the + * shared text data structure. */ +{ + TkSharedText *sharedPtr = (TkSharedText *) clientData; + int res, objc; + Tcl_Obj **objv; + TkText *textPtr; + + res = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv); + if (res != TCL_OK) { + return res; } /* - * Invalidate any selection retrievals in progress. + * If possible, use a real text widget to perform the undo/redo action + * (i.e. insertion or deletion of text). This provides maximum + * compatibility with older versions of Tk, in which the user may rename + * the text widget to allow capture of undo or redo actions. + * + * In particular, this sorting of capture is useful in text editors based + * on the Tk text widget, which need to know which new text needs + * re-coloring. + * + * It would be better if the text widget provided some other mechanism to + * allow capture of this information ("What has just changed in the text + * widget?"). What we have here is not entirely satisfactory under all + * circumstances. + */ + + textPtr = sharedPtr->peers; + while (textPtr != NULL) { + if (textPtr->start == NULL && textPtr->end == NULL) { + Tcl_Obj *cmdNameObj, *evalObj; + + evalObj = Tcl_NewObj(); + Tcl_IncrRefCount(evalObj); + + /* + * We might wish to use the real, current command-name for the + * widget, but this will break any code that has over-ridden the + * widget, and is expecting to observe the insert/delete actions + * which are caused by undo/redo operations. + * + * cmdNameObj = Tcl_NewObj(); + * Tcl_GetCommandFullName(interp, textPtr->widgetCmd, cmdNameObj); + * + * While such interception is not explicitly documented as + * supported, it does occur, and so until we can provide some + * alternative mechanism for such code to do what it needs, we + * allow it to take place here. + */ + + cmdNameObj = Tcl_NewStringObj(Tk_PathName(textPtr->tkwin), -1); + Tcl_ListObjAppendElement(NULL, evalObj, cmdNameObj); + Tcl_ListObjAppendList(NULL, evalObj, objPtr); + res = Tcl_EvalObjEx(interp, evalObj, TCL_EVAL_GLOBAL); + Tcl_DecrRefCount(evalObj); + return res; + } + textPtr = textPtr->next; + } + + /* + * If there's no current text widget which shows everything, then we fall + * back on acting directly. This means there is no way to intercept from + * the Tcl level. */ - textPtr->abortSelections = 1; + return SharedTextObjCmd((ClientData)sharedPtr, interp, objc+1, objv-1); } /* *---------------------------------------------------------------------- * - * DeleteChars -- + * CountIndices -- + * + * This function implements most of the functionality of the "count" + * widget command. * - * This procedure implements most of the functionality of the - * "delete" widget command. + * Note that 'textPtr' is only used if we need to check for elided + * attributes, i.e. if type is COUNT_DISPLAY_INDICES or + * COUNT_DISPLAY_CHARS * * Results: - * Returns a standard Tcl result, and leaves an error message - * in textPtr->interp if there is an error. + * Returns the number of characters in the range. * * Side effects: - * Characters get deleted from the text. + * None. * *---------------------------------------------------------------------- */ static int -DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2) - TkText *textPtr; /* Overall information about text widget. */ - CONST char *index1String; /* String describing location of first - * character to delete. */ - CONST char *index2String; /* String describing location of last - * character to delete. NULL means just - * delete the one character given by - * index1String. */ - TkTextIndex *indexPtr1; /* index describing location of first +CountIndices( + CONST TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *indexPtr1, + /* Index describing location of first * character to delete. */ - TkTextIndex *indexPtr2; /* index describing location of last - * character to delete. NULL means just - * delete the one character given by - * indexPtr1. */ + CONST TkTextIndex *indexPtr2, + /* Index describing location of last character + * to delete. NULL means just delete the one + * character given by indexPtr1. */ + TkTextCountType type) /* The kind of indices to count. */ +{ + /* + * Order the starting and stopping indices. + */ + + int compare = TkTextIndexCmp(indexPtr1, indexPtr2); + + if (compare == 0) { + return 0; + } else if (compare > 0) { + return -TkTextIndexCount(textPtr, indexPtr2, indexPtr1, type); + } else { + return TkTextIndexCount(textPtr, indexPtr1, indexPtr2, type); + } +} + +/* + *---------------------------------------------------------------------- + * + * DeleteIndexRange -- + * + * This function implements most of the functionality of the "delete" + * widget command. + * + * Results: + * Returns a standard Tcl result, currently always TCL_OK. + * + * Side effects: + * Characters and other entities (windows, images) get deleted from the + * text. + * + * 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 + * 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 + * actions to ensure the topIndex is validated before laying out the + * window again. + * + *---------------------------------------------------------------------- + */ + +static int +DeleteIndexRange( + TkSharedText *sharedTextPtr,/* Shared portion of peer widgets. */ + TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *indexPtr1, + /* Index describing location of first + * character (or other entity) to delete. */ + CONST TkTextIndex *indexPtr2, + /* Index describing location of last + * character (or other entity) to delete. + * NULL means just delete the one character + * given by indexPtr1. */ + int viewUpdate) /* Update vertical view if set. */ { - int line1, line2, line, byteIndex, resetView; + int line1, line2; TkTextIndex index1, index2; - char indexBuffer[TK_POS_CHARS]; + TkText *tPtr; + int *lineAndByteIndex; + int resetViewCount; + int pixels[2*PIXEL_CLIENTS]; + + if (sharedTextPtr == NULL) { + sharedTextPtr = textPtr->sharedTextPtr; + } /* - * Parse the starting and stopping indices. + * Prepare the starting and stopping indices. */ - if (index1String != NULL) { - if (TkTextGetIndex(textPtr->interp, textPtr, index1String, &index1) - != TCL_OK) { - return TCL_ERROR; - } - if (index2String != NULL) { - if (TkTextGetIndex(textPtr->interp, textPtr, index2String, &index2) - != TCL_OK) { - return TCL_ERROR; - } - } else { - index2 = index1; - TkTextIndexForwChars(&index2, 1, &index2); - } + index1 = *indexPtr1; + if (indexPtr2 != NULL) { + index2 = *indexPtr2; } else { - index1 = *indexPtr1; - if (indexPtr2 != NULL) { - index2 = *indexPtr2; - } else { - index2 = index1; - TkTextIndexForwChars(&index2, 1, &index2); - } + index2 = index1; + TkTextIndexForwChars(NULL, &index2, 1, &index2, COUNT_INDICES); } /* @@ -1558,32 +2987,33 @@ DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2) } /* - * 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. If - * there is a newline just before the first character being deleted, - * then back up the first index too, so that an even number of lines - * gets deleted. 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). + * 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. If there is a newline just before the first + * character being deleted, then back up the first index too, so that an + * even number of lines gets deleted. 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 = TkBTreeLineIndex(index1.linePtr); - line2 = TkBTreeLineIndex(index2.linePtr); - if (line2 == TkBTreeNumLines(textPtr->tree)) { + line1 = TkBTreeLinesTo(textPtr, index1.linePtr); + line2 = TkBTreeLinesTo(textPtr, index2.linePtr); + if (line2 == TkBTreeNumLines(sharedTextPtr->tree, textPtr)) { TkTextTag **arrayPtr; int arraySize, i; TkTextIndex oldIndex2; oldIndex2 = index2; - TkTextIndexBackChars(&oldIndex2, 1, &index2); + TkTextIndexBackChars(NULL, &oldIndex2, 1, &index2, COUNT_INDICES); line2--; if ((index1.byteIndex == 0) && (line1 != 0)) { - TkTextIndexBackChars(&index1, 1, &index1); + TkTextIndexBackChars(NULL, &index1, 1, &index1, COUNT_INDICES); line1--; } - arrayPtr = TkBTreeGetTags(&index2, &arraySize); + arrayPtr = TkBTreeGetTags(&index2, NULL, &arraySize); if (arrayPtr != NULL) { for (i = 0; i < arraySize; i++) { TkBTreeTag(&index2, &oldIndex2, arrayPtr[i], 0); @@ -1597,144 +3027,206 @@ DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2) * 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. - * [Bug 1456342] */ Tcl_HashSearch search; Tcl_HashEntry *hPtr; + int i; - for (hPtr=Tcl_FirstHashEntry(&textPtr->tagTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + for (i=0, hPtr=Tcl_FirstHashEntry(&sharedTextPtr->tagTable, &search); + hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) { TkTextTag *tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr); 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. + */ + + 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; + } + } } /* - * Tell the display what's about to happen so it can discard - * obsolete display information, then do the deletion. Also, - * if the deletion involves the top line on the screen, then - * we have to reset the view (the deletion will invalidate - * textPtr->topIndex). Compute what the new first character - * will be, then do the deletion, then reset the view. + * Tell the display what's about to happen so it can discard obsolete + * display information, then do the deletion. Also, if the deletion + * involves the top line on the screen, then we have to reset the view + * (the deletion will invalidate textPtr->topIndex). Compute what the new + * first character will be, then do the deletion, then reset the view. */ - TkTextChanged(textPtr, &index1, &index2); - resetView = 0; - line = 0; - byteIndex = 0; - if (TkTextIndexCmp(&index2, &textPtr->topIndex) >= 0) { - if (TkTextIndexCmp(&index1, &textPtr->topIndex) <= 0) { - /* - * Deletion range straddles topIndex: use the beginning - * of the range as the new topIndex. - */ + TkTextChanged(sharedTextPtr, NULL, &index1, &index2); - resetView = 1; - line = line1; - byteIndex = index1.byteIndex; - } else if (index1.linePtr == textPtr->topIndex.linePtr) { + resetViewCount = 0; + if (sharedTextPtr->refCount > PIXEL_CLIENTS) { + lineAndByteIndex = (int *) + ckalloc(sizeof(int) * 2 * sharedTextPtr->refCount); + } else { + lineAndByteIndex = pixels; + } + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + int line = 0; + int byteIndex = 0; + int resetView = 0; + + if (TkTextIndexCmp(&index2, &tPtr->topIndex) >= 0) { + if (TkTextIndexCmp(&index1, &tPtr->topIndex) <= 0) { + /* + * Deletion range straddles topIndex: use the beginning of the + * range as the new topIndex. + */ + + resetView = 1; + line = line1; + byteIndex = index1.byteIndex; + } else if (index1.linePtr == tPtr->topIndex.linePtr) { + /* + * Deletion range starts on top line but after topIndex. Use + * the current topIndex as the new one. + */ + + 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 if (index2.linePtr == tPtr->topIndex.linePtr) { /* - * Deletion range starts on top line but after topIndex. - * Use the current topIndex as the new one. + * Deletion range ends on top line but before topIndex. Figure out + * what will be the new character index for the character + * currently pointed to by topIndex. */ resetView = 1; - line = line1; - byteIndex = textPtr->topIndex.byteIndex; + line = line2; + byteIndex = tPtr->topIndex.byteIndex; + if (index1.linePtr != index2.linePtr) { + byteIndex -= index2.byteIndex; + } 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 if (index2.linePtr == textPtr->topIndex.linePtr) { - /* - * Deletion range ends on top line but before topIndex. - * Figure out what will be the new character index for - * the character currently pointed to by topIndex. - */ - - resetView = 1; - line = line2; - byteIndex = textPtr->topIndex.byteIndex; - if (index1.linePtr != index2.linePtr) { - byteIndex -= index2.byteIndex; + if (resetView) { + lineAndByteIndex[resetViewCount] = line; + lineAndByteIndex[resetViewCount+1] = byteIndex; } else { - byteIndex -= (index2.byteIndex - index1.byteIndex); + lineAndByteIndex[resetViewCount] = -1; } + resetViewCount+=2; } /* - * Push the deletion on the undo stack + * Push the deletion on the undo stack if something was actually deleted. */ - if (textPtr->undo) { - CONST char *cmdName; - Tcl_DString ds; - Tcl_DString actionCommand; - Tcl_DString revertCommand; - - if (textPtr->autoSeparators - && (textPtr->lastEditMode != TK_TEXT_EDIT_DELETE)) { - TkUndoInsertUndoSeparator(textPtr->undoStack); - } - - textPtr->lastEditMode = TK_TEXT_EDIT_DELETE; - cmdName = Tcl_GetCommandName(textPtr->interp, textPtr->widgetCmd); + if (TkTextIndexCmp(&index1, &index2) < 0) { + if (sharedTextPtr->undo) { + Tcl_Obj *get; - Tcl_DStringInit(&actionCommand); - Tcl_DStringInit(&revertCommand); - - Tcl_DStringAppendElement(&actionCommand, cmdName); - Tcl_DStringAppend(&actionCommand, " delete ", -1); - TkTextPrintIndex(&index1, indexBuffer); - Tcl_DStringAppend(&actionCommand, indexBuffer, -1); - Tcl_DStringAppend(&actionCommand, " ", -1); - TkTextPrintIndex(&index2, indexBuffer); - Tcl_DStringAppend(&actionCommand, indexBuffer, -1); - Tcl_DStringAppend(&actionCommand, "; ", -1); - Tcl_DStringAppendElement(&actionCommand, cmdName); - Tcl_DStringAppend(&actionCommand, " mark set insert ", -1); - TkTextPrintIndex(&index1, indexBuffer); - Tcl_DStringAppend(&actionCommand,indexBuffer, -1); - - Tcl_DStringAppend(&actionCommand, "; ", -1); - Tcl_DStringAppendElement(&actionCommand, cmdName); - Tcl_DStringAppend(&actionCommand, " see insert", -1); + if (sharedTextPtr->autoSeparators + && (sharedTextPtr->lastEditMode != TK_TEXT_EDIT_DELETE)) { + TkUndoInsertUndoSeparator(sharedTextPtr->undoStack); + } - TextGetText(&index1, &index2, &ds); + sharedTextPtr->lastEditMode = TK_TEXT_EDIT_DELETE; - Tcl_DStringAppendElement(&revertCommand, cmdName); - Tcl_DStringAppend(&revertCommand, " insert ", -1); - TkTextPrintIndex(&index1, indexBuffer); - Tcl_DStringAppend(&revertCommand, indexBuffer, -1); - Tcl_DStringAppend(&revertCommand, " ", -1); - Tcl_DStringAppendElement(&revertCommand, Tcl_DStringValue(&ds)); - Tcl_DStringAppend(&revertCommand, "; ", -1); - Tcl_DStringAppendElement(&revertCommand, cmdName); - Tcl_DStringAppend(&revertCommand, " mark set insert ", -1); - TkTextPrintIndex(&index2, indexBuffer); - Tcl_DStringAppend(&revertCommand, indexBuffer, -1); - Tcl_DStringAppend(&revertCommand, "; ", -1); - Tcl_DStringAppendElement(&revertCommand, cmdName); - Tcl_DStringAppend(&revertCommand, " see insert", -1); + get = TextGetText(textPtr, &index1, &index2, 0); + TextPushUndoAction(textPtr, get, 0, &index1, &index2); + } + sharedTextPtr->stateEpoch++; - TkUndoPushAction(textPtr->undoStack, &actionCommand, &revertCommand); + TkBTreeDeleteIndexRange(sharedTextPtr->tree, &index1, &index2); - Tcl_DStringFree(&actionCommand); - Tcl_DStringFree(&revertCommand); + UpdateDirtyFlag(sharedTextPtr); } - TkBTreeDeleteChars(&index1, &index2); - - updateDirtyFlag(textPtr); - if (resetView) { - TkTextMakeByteIndex(textPtr->tree, line, byteIndex, &index1); - TkTextSetYView(textPtr, &index1, 0); + resetViewCount = 0; + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + int line = lineAndByteIndex[resetViewCount]; + + if (line != -1) { + int byteIndex = lineAndByteIndex[resetViewCount+1]; + 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. + */ + + TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line, + byteIndex, &indexTmp); + TkTextSetYView(tPtr, &indexTmp, 0); + } + } else { + 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, + 0, &indexStart); + if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) { + indexTmp = indexStart; + } + } + TkTextSetYView(tPtr, &indexTmp, 0); + } + } + resetViewCount += 2; + } + if (sharedTextPtr->refCount > PIXEL_CLIENTS) { + ckfree((char *) lineAndByteIndex); } - /* - * Invalidate any selection retrievals in progress. - */ + if (line1 >= line2) { + /* + * Invalidate any selection retrievals in progress, assuming we didn't + * check for this case above. + */ - textPtr->abortSelections = 1; + for (tPtr = sharedTextPtr->peers; tPtr != NULL ; tPtr = tPtr->next) { + tPtr->abortSelections = 1; + } + } return TCL_OK; } @@ -1744,15 +3236,15 @@ DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2) * * TextFetchSelection -- * - * This procedure is called back by Tk when the selection is - * requested by someone. It returns part or all of the selection - * in a buffer provided by the caller. + * This function is called back by Tk when the selection is requested by + * someone. It returns part or all of the selection in a buffer provided + * by the caller. * * Results: - * The return value is the number of non-NULL bytes stored - * at buffer. Buffer is filled (or partially filled) with a - * NULL-terminated string containing part or all of the selection, - * as given by offset and maxBytes. + * The return value is the number of non-NULL bytes stored at buffer. + * Buffer is filled (or partially filled) with a NULL-terminated string + * containing part or all of the selection, as given by offset and + * maxBytes. * * Side effects: * None. @@ -1761,15 +3253,14 @@ DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2) */ static int -TextFetchSelection(clientData, offset, buffer, maxBytes) - ClientData clientData; /* Information about text widget. */ - int offset; /* Offset within selection of first - * character to be returned. */ - char *buffer; /* Location in which to place - * selection. */ - int maxBytes; /* Maximum number of bytes to place - * at buffer, not including terminating - * NULL character. */ +TextFetchSelection( + ClientData clientData, /* Information about text widget. */ + int offset, /* Offset within selection of first character + * to be returned. */ + char *buffer, /* Location in which to place selection. */ + int maxBytes) /* Maximum number of bytes to place at buffer, + * not including terminating NULL + * character. */ { register TkText *textPtr = (TkText *) clientData; TkTextIndex eof; @@ -1782,20 +3273,21 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) } /* - * Find the beginning of the next range of selected text. Note: if - * the selection is being retrieved in multiple pieces (offset != 0) - * and some modification has been made to the text that affects the - * selection then reject the selection request (make 'em start over - * again). + * Find the beginning of the next range of selected text. Note: if the + * selection is being retrieved in multiple pieces (offset != 0) and some + * modification has been made to the text that affects the selection then + * reject the selection request (make 'em start over again). */ if (offset == 0) { - TkTextMakeByteIndex(textPtr->tree, 0, 0, &textPtr->selIndex); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, + &textPtr->selIndex); textPtr->abortSelections = 0; } else if (textPtr->abortSelections) { return 0; } - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &eof); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &eof); TkBTreeStartSearch(&textPtr->selIndex, &eof, textPtr->selTagPtr, &search); if (!TkBTreeCharTagged(&textPtr->selIndex, textPtr->selTagPtr)) { if (!TkBTreeNextTag(&search)) { @@ -1810,8 +3302,8 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) /* * Each iteration through the outer loop below scans one selected range. - * Each iteration through the inner loop scans one segment in the - * selected range. + * Each iteration through the inner loop scans one segment in the selected + * range. */ count = 0; @@ -1821,18 +3313,18 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) */ if (!TkBTreeNextTag(&search)) { - panic("TextFetchSelection couldn't find end of range"); + Tcl_Panic("TextFetchSelection couldn't find end of range"); } /* - * Copy information from character segments into the buffer - * until either we run out of space in the buffer or we get - * to the end of this range of text. + * Copy information from character segments into the buffer until + * either we run out of space in the buffer or we get to the end of + * this range of text. */ while (1) { if (maxBytes == 0) { - goto done; + goto fetchDone; } segPtr = TkTextIndexToSeg(&textPtr->selIndex, &offsetInSeg); chunkSize = segPtr->size - offsetInSeg; @@ -1852,14 +3344,14 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) } } if ((segPtr->typePtr == &tkTextCharType) - && !TkTextIsElided(textPtr, &textPtr->selIndex)) { - memcpy((VOID *) buffer, (VOID *) (segPtr->body.chars - + offsetInSeg), (size_t) chunkSize); + && !TkTextIsElided(textPtr, &textPtr->selIndex, NULL)) { + memcpy(buffer, segPtr->body.chars + offsetInSeg, + (size_t) chunkSize); buffer += chunkSize; maxBytes -= chunkSize; count += chunkSize; } - TkTextIndexForwBytes(&textPtr->selIndex, chunkSize, + TkTextIndexForwBytes(textPtr, &textPtr->selIndex, chunkSize, &textPtr->selIndex); } @@ -1873,7 +3365,7 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) textPtr->selIndex = search.curIndex; } - done: + fetchDone: *buffer = 0; return count; } @@ -1883,11 +3375,10 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) * * TkTextLostSelection -- * - * This procedure is called back by Tk when the selection is - * grabbed away from a text widget. On Windows and Mac systems, we - * want to remember the selection for the next time the focus - * enters the window. On Unix, just remove the "sel" tag from - * everything in the widget. + * This function is called back by Tk when the selection is grabbed away + * from a text widget. On Windows and Mac systems, we want to remember + * the selection for the next time the focus enters the window. On Unix, + * just remove the "sel" tag from everything in the widget. * * Results: * None. @@ -1899,11 +3390,10 @@ TextFetchSelection(clientData, offset, buffer, maxBytes) */ void -TkTextLostSelection(clientData) - ClientData clientData; /* Information about text widget. */ +TkTextLostSelection( + ClientData clientData) /* Information about text widget. */ { register TkText *textPtr = (TkText *) clientData; - XEvent event; if (TkpAlwaysShowSelection(textPtr->tkwin)) { TkTextIndex start, end; @@ -1913,30 +3403,26 @@ TkTextLostSelection(clientData) } /* - * On Windows and Mac systems, we want to remember the selection - * for the next time the focus enters the window. On Unix, - * just remove the "sel" tag from everything in the widget. + * On Windows and Mac systems, we want to remember the selection for + * the next time the focus enters the window. On Unix, just remove the + * "sel" tag from everything in the widget. */ - TkTextMakeByteIndex(textPtr->tree, 0, 0, &start); - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &end); - TkTextRedrawTag(textPtr, &start, &end, textPtr->selTagPtr, 1); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + 0, 0, &start); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), + 0, &end); + TkTextRedrawTag(NULL, textPtr, &start, &end, textPtr->selTagPtr, 1); TkBTreeTag(&start, &end, textPtr->selTagPtr, 0); } /* - * Send an event that the selection changed. This is equivalent to - * "event generate $textWidget <<Selection>>" + * Send an event that the selection changed. This is equivalent to: + * event generate $textWidget <<Selection>> */ - memset((VOID *) &event, 0, sizeof(event)); - event.xany.type = VirtualEvent; - event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.xany.send_event = False; - event.xany.window = Tk_WindowId(textPtr->tkwin); - event.xany.display = Tk_Display(textPtr->tkwin); - ((XVirtualEvent *) &event)->name = Tk_GetUid("Selection"); - Tk_HandleEvent(&event); + TkTextSelectionEvent(textPtr); textPtr->flags &= ~GOT_SELECTION; } @@ -1944,31 +3430,78 @@ TkTextLostSelection(clientData) /* *---------------------------------------------------------------------- * + * TkTextSelectionEvent -- + * + * When anything relevant to the "sel" tag has been changed, call this + * function to generate a <<Selection>> event. + * + * Results: + * None. + * + * Side effects: + * If <<Selection>> bindings are present, they will trigger. + * + *---------------------------------------------------------------------- + */ + +void +TkTextSelectionEvent( + TkText *textPtr) +{ + /* + * Send an event that the selection changed. This is equivalent to: + * 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); +} + +/* + *---------------------------------------------------------------------- + * * TextBlinkProc -- * - * This procedure is called as a timer handler to blink the - * insertion cursor off and on. + * This function is called as a timer handler to blink the insertion + * cursor off and on. * * Results: * None. * * Side effects: - * The cursor gets turned on or off, redisplay gets invoked, - * and this procedure reschedules itself. + * The cursor gets turned on or off, redisplay gets invoked, and this + * function reschedules itself. * *---------------------------------------------------------------------- */ static void -TextBlinkProc(clientData) - ClientData clientData; /* Pointer to record describing text. */ +TextBlinkProc( + ClientData clientData) /* Pointer to record describing text. */ { register TkText *textPtr = (TkText *) clientData; TkTextIndex index; - int x, y, w, h; + int x, y, w, h, charWidth; - if ((textPtr->state == TK_STATE_DISABLED) || + if ((textPtr->state == TK_TEXT_STATE_DISABLED) || !(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) { + if ((textPtr->insertOffTime == 0) && !(textPtr->flags & INSERT_ON)) { + /* + * The widget was configured to have zero offtime while the + * insertion point was not displayed. We have to display it once. + */ + + textPtr->flags |= INSERT_ON; + goto redrawInsert; + } return; } if (textPtr->flags & INSERT_ON) { @@ -1980,21 +3513,111 @@ TextBlinkProc(clientData) textPtr->insertBlinkHandler = Tcl_CreateTimerHandler( textPtr->insertOnTime, TextBlinkProc, (ClientData) textPtr); } + redrawInsert: TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index); - if (TkTextCharBbox(textPtr, &index, &x, &y, &w, &h) == 0) { - TkTextRedrawRegion(textPtr, x - textPtr->insertWidth / 2, y, - textPtr->insertWidth, h); + if (TkTextIndexBbox(textPtr, &index, &x, &y, &w, &h, &charWidth) == 0) { + if (textPtr->insertCursorType) { + /* Block cursor */ + TkTextRedrawRegion(textPtr, x - textPtr->width / 2, y, + charWidth + textPtr->insertWidth / 2, h); + } else { + /* I-beam cursor */ + TkTextRedrawRegion(textPtr, x - textPtr->insertWidth / 2, y, + textPtr->insertWidth, h); + } } } /* *---------------------------------------------------------------------- * + * TextInsertCmd -- + * + * This function is invoked to process the "insert" and "replace" widget + * commands for text widgets. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + * If 'viewUpdate' is true, we may adjust the window contents' + * y-position, and scrollbar setting. + * + *---------------------------------------------------------------------- + */ + +static int +TextInsertCmd( + TkSharedText *sharedTextPtr,/* Shared portion of peer widgets. */ + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[], /* Argument objects. */ + CONST TkTextIndex *indexPtr,/* Index at which to insert. */ + int viewUpdate) /* Update the view if set. */ +{ + TkTextIndex index1, index2; + int j; + + if (sharedTextPtr == NULL) { + sharedTextPtr = textPtr->sharedTextPtr; + } + + index1 = *indexPtr; + for (j = 0; j < objc; j += 2) { + /* + * Here we rely on this call to modify index1 if it is outside the + * acceptable range. In particular, if index1 is "end", it must be set + * to the last allowable index for insertion, otherwise subsequent tag + * insertions will fail. + */ + + int length = InsertChars(sharedTextPtr, textPtr, &index1, objv[j], + viewUpdate); + + if (objc > (j+1)) { + Tcl_Obj **tagNamePtrs; + TkTextTag **oldTagArrayPtr; + int numTags; + + TkTextIndexForwBytes(textPtr, &index1, length, &index2); + oldTagArrayPtr = TkBTreeGetTags(&index1, NULL, &numTags); + if (oldTagArrayPtr != NULL) { + int i; + + for (i = 0; i < numTags; i++) { + TkBTreeTag(&index1, &index2, oldTagArrayPtr[i], 0); + } + ckfree((char *) oldTagArrayPtr); + } + if (Tcl_ListObjGetElements(interp, objv[j+1], &numTags, + &tagNamePtrs) != TCL_OK) { + return TCL_ERROR; + } else { + int i; + + for (i = 0; i < numTags; i++) { + CONST char *strTag = Tcl_GetString(tagNamePtrs[i]); + + TkBTreeTag(&index1, &index2, + TkTextCreateTag(textPtr, strTag, NULL), 1); + } + index1 = index2; + } + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * TextSearchCmd -- * - * This procedure is invoked to process the "search" widget command - * for text widgets. See the user documentation for details on what - * it does. + * This function is invoked to process the "search" widget command for + * text widgets. See the user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -2006,393 +3629,680 @@ TextBlinkProc(clientData) */ static int -TextSearchCmd(textPtr, interp, argc, argv) - TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TextSearchCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - int backwards, exact, searchElide, c, i, argsLeft, noCase, leftToScan; - size_t length; - int numLines, startingLine, startingByte, lineNum, firstByte, lastByte; - int code, matchLength, matchByte, passes, stopLine, searchWholeText; - int patLength; - CONST char *arg, *pattern, *varName, *p, *startOfLine; - char buffer[20]; - TkTextIndex index, stopIndex; - Tcl_DString line, patDString; - TkTextSegment *segPtr; - TkTextLine *linePtr; - TkTextIndex curIndex; - Tcl_Obj *patObj = NULL; - Tcl_RegExp regexp = NULL; /* Initialization needed only to - * prevent compiler warning. */ + int i, argsLeft, code; + SearchSpec searchSpec; + + static CONST char *switchStrings[] = { + "--", "-all", "-backwards", "-count", "-elide", "-exact", "-forwards", + "-hidden", "-nocase", "-nolinestop", "-overlap", "-regexp", + "-strictlimits", NULL + }; + enum SearchSwitches { + SEARCH_END, SEARCH_ALL, SEARCH_BACK, SEARCH_COUNT, SEARCH_ELIDE, + SEARCH_EXACT, SEARCH_FWD, SEARCH_HIDDEN, SEARCH_NOCASE, + SEARCH_NOLINESTOP, SEARCH_OVERLAP, SEARCH_REGEXP, SEARCH_STRICTLIMITS + }; + + /* + * Set up the search specification, including the last 4 fields which are + * text widget specific. + */ + + searchSpec.exact = 1; + searchSpec.noCase = 0; + searchSpec.all = 0; + searchSpec.backwards = 0; + searchSpec.varPtr = NULL; + searchSpec.countPtr = NULL; + searchSpec.resPtr = NULL; + searchSpec.searchElide = 0; + searchSpec.noLineStop = 0; + searchSpec.overlap = 0; + searchSpec.strictLimits = 0; + searchSpec.numLines = + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + searchSpec.clientData = (ClientData)textPtr; + searchSpec.addLineProc = &TextSearchAddNextLine; + searchSpec.foundMatchProc = &TextSearchFoundMatch; + searchSpec.lineIndexProc = &TextSearchGetLineIndex; /* * Parse switches and other arguments. */ - exact = 1; - searchElide = 0; - curIndex.tree = textPtr->tree; - backwards = 0; - noCase = 0; - varName = NULL; - for (i = 2; i < argc; i++) { - arg = argv[i]; - if (arg[0] != '-') { + for (i=2 ; i<objc ; i++) { + int index; + if (Tcl_GetString(objv[i])[0] != '-') { break; } - length = strlen(arg); - if (length < 2) { - badSwitch: - Tcl_AppendResult(interp, "bad switch \"", arg, - "\": must be --, -backward, -count, -elide, -exact, ", - "-forward, -nocase, or -regexp", (char *) NULL); + + if (Tcl_GetIndexFromObj(interp, objv[i], switchStrings, "switch", 0, + &index) != TCL_OK) { + /* + * Hide the -hidden option. + */ + + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "bad switch \"", Tcl_GetString(objv[i]), + "\": must be --, -all, -backward, -count, -elide, ", + "-exact, -forward, -nocase, -nolinestop, -overlap, ", + "-regexp, or -strictlimits", NULL); return TCL_ERROR; } - c = arg[1]; - if ((c == 'b') && (strncmp(argv[i], "-backwards", length) == 0)) { - backwards = 1; - } else if ((c == 'c') && (strncmp(argv[i], "-count", length) == 0)) { - if (i >= (argc-1)) { + + switch ((enum SearchSwitches) index) { + case SEARCH_END: + i++; + goto endOfSwitchProcessing; + case SEARCH_ALL: + searchSpec.all = 1; + break; + case SEARCH_BACK: + searchSpec.backwards = 1; + break; + case SEARCH_COUNT: + if (i >= objc-1) { Tcl_SetResult(interp, "no value given for \"-count\" option", TCL_STATIC); return TCL_ERROR; } i++; - varName = argv[i]; - } else if ((c == 'e') && (length > 2) - && (strncmp(argv[i], "-exact", length) == 0)) { - exact = 1; - } else if ((c == 'e') && (length > 2) - && (strncmp(argv[i], "-elide", length) == 0)) { - searchElide = 1; - } else if ((c == 'h') && (strncmp(argv[i], "-hidden", length) == 0)) { + /* - * -hidden is kept around for backwards compatibility with - * the dash patch, but -elide is the official option + * Assumption objv[i] isn't going to disappear on us during this + * function, which is fair. */ - searchElide = 1; - } else if ((c == 'f') && (strncmp(argv[i], "-forwards", length) == 0)) { - backwards = 0; - } else if ((c == 'n') && (strncmp(argv[i], "-nocase", length) == 0)) { - noCase = 1; - } else if ((c == 'r') && (strncmp(argv[i], "-regexp", length) == 0)) { - exact = 0; - } else if ((c == '-') && (strncmp(argv[i], "--", length) == 0)) { - i++; + + searchSpec.varPtr = objv[i]; break; - } else { - goto badSwitch; + case SEARCH_ELIDE: + case SEARCH_HIDDEN: + searchSpec.searchElide = 1; + break; + case SEARCH_EXACT: + searchSpec.exact = 1; + break; + case SEARCH_FWD: + searchSpec.backwards = 0; + break; + case SEARCH_NOCASE: + searchSpec.noCase = 1; + break; + case SEARCH_NOLINESTOP: + searchSpec.noLineStop = 1; + break; + case SEARCH_OVERLAP: + searchSpec.overlap = 1; + break; + case SEARCH_STRICTLIMITS: + searchSpec.strictLimits = 1; + break; + case SEARCH_REGEXP: + searchSpec.exact = 0; + break; + default: + Tcl_Panic("unexpected switch fallthrough"); } } - argsLeft = argc - (i+2); + endOfSwitchProcessing: + + argsLeft = objc - (i+2); if ((argsLeft != 0) && (argsLeft != 1)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " search ?switches? pattern index ?stopIndex?\"", - (char *) NULL); + Tcl_WrongNumArgs(interp, 2, objv, + "?switches? pattern index ?stopIndex?"); + return TCL_ERROR; + } + + if (searchSpec.noLineStop && searchSpec.exact) { + Tcl_SetResult(interp, "the \"-nolinestop\" option requires the " + "\"-regexp\" option to be present", TCL_STATIC); + return TCL_ERROR; + } + + if (searchSpec.overlap && !searchSpec.all) { + Tcl_SetResult(interp, "the \"-overlap\" option requires the " + "\"-all\" option to be present", TCL_STATIC); return TCL_ERROR; } - pattern = argv[i]; /* - * Convert the pattern to lower-case if we're supposed to ignore case. + * Scan through all of the lines of the text circularly, starting at the + * given index. 'objv[i]' is the pattern which may be an exact string or a + * regexp pattern depending on the flags set above. */ - if (noCase && exact) { - Tcl_DStringInit(&patDString); - Tcl_DStringAppend(&patDString, pattern, -1); - Tcl_UtfToLower(Tcl_DStringValue(&patDString)); - pattern = Tcl_DStringValue(&patDString); + code = SearchPerform(interp, &searchSpec, objv[i], objv[i+1], + (argsLeft == 1 ? objv[i+2] : NULL)); + if (code != TCL_OK) { + goto cleanup; } - Tcl_DStringInit(&line); - if (TkTextGetIndex(interp, textPtr, argv[i+1], &index) != TCL_OK) { - code = TCL_ERROR; - goto done; - } - numLines = TkBTreeNumLines(textPtr->tree); - startingLine = TkBTreeLineIndex(index.linePtr); - startingByte = index.byteIndex; - if (startingLine >= numLines) { - if (backwards) { - startingLine = TkBTreeNumLines(textPtr->tree) - 1; - startingByte = TkBTreeBytesInLine(TkBTreeFindLine(textPtr->tree, - startingLine)); - } else { - startingLine = 0; - startingByte = 0; - } - } - if (argsLeft == 1) { - if (TkTextGetIndex(interp, textPtr, argv[i+2], &stopIndex) != TCL_OK) { + /* + * Set the '-count' variable, if given. + */ + + if (searchSpec.varPtr != NULL && searchSpec.countPtr != NULL) { + Tcl_IncrRefCount(searchSpec.countPtr); + if (Tcl_ObjSetVar2(interp, searchSpec.varPtr, NULL, + searchSpec.countPtr, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; - goto done; - } - stopLine = TkBTreeLineIndex(stopIndex.linePtr); - if (!backwards && (stopLine == numLines)) { - stopLine = numLines-1; + goto cleanup; } - searchWholeText = 0; - } else { - stopLine = 0; - searchWholeText = 1; } /* - * Scan through all of the lines of the text circularly, starting - * at the given index. + * Set the result. */ - matchLength = patLength = 0; /* Only needed to prevent compiler - * warnings. */ - if (exact) { - patLength = strlen(pattern); - } else { - patObj = Tcl_NewStringObj(pattern, -1); - Tcl_IncrRefCount(patObj); - regexp = Tcl_GetRegExpFromObj(interp, patObj, - (noCase ? TCL_REG_NOCASE : 0) | TCL_REG_ADVANCED); - if (regexp == NULL) { - code = TCL_ERROR; - goto done; - } + if (searchSpec.resPtr != NULL) { + Tcl_SetObjResult(interp, searchSpec.resPtr); + searchSpec.resPtr = NULL; } - lineNum = startingLine; - code = TCL_OK; - for (passes = 0; passes < 2; ) { - if (lineNum >= numLines) { - /* - * Don't search the dummy last line of the text. - */ - goto nextLine; - } + cleanup: + if (searchSpec.countPtr != NULL) { + Tcl_DecrRefCount(searchSpec.countPtr); + } + if (searchSpec.resPtr != NULL) { + Tcl_DecrRefCount(searchSpec.resPtr); + } + return code; +} + +/* + *---------------------------------------------------------------------- + * + * TextSearchGetLineIndex -- + * + * Extract a row, text offset index position from an objPtr + * + * This means we ignore any embedded windows/images and elidden text + * (unless we are searching that). + * + * Results: + * Standard Tcl error code (with a message in the interpreter on error + * conditions). + * + * The offset placed in offsetPosPtr is a utf-8 char* byte index for + * exact searches, and a Unicode character index for regexp searches. + * + * The line number should start at zero (searches which wrap around + * assume the first line is numbered 0). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TextSearchGetLineIndex( + Tcl_Interp *interp, /* For error messages. */ + Tcl_Obj *objPtr, /* Contains a textual index like "1.2" */ + SearchSpec *searchSpecPtr, /* Contains other search parameters. */ + int *linePosPtr, /* For returning the line number. */ + int *offsetPosPtr) /* For returning the text offset in the + * line. */ +{ + CONST TkTextIndex *indexPtr; + int line; + TkText *textPtr = (TkText *) searchSpecPtr->clientData; + + indexPtr = TkTextGetIndexFromObj(interp, textPtr, objPtr); + if (indexPtr == NULL) { + return TCL_ERROR; + } + + line = TkBTreeLinesTo(textPtr, indexPtr->linePtr); + if (line >= searchSpecPtr->numLines) { + TkTextLine *linePtr; + int count = 0; + TkTextSegment *segPtr; + + line = searchSpecPtr->numLines-1; + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, line); /* - * Extract the text from the line. If we're doing regular - * expression matching, drop the newline from the line, so - * that "$" can be used to match the end of the line. + * Count the number of bytes in this line. */ - linePtr = TkBTreeFindLine(textPtr->tree, lineNum); - curIndex.linePtr = linePtr; curIndex.byteIndex = 0; - for (segPtr = linePtr->segPtr; segPtr != NULL; + for (segPtr=linePtr->segPtr ; segPtr!=NULL ; segPtr=segPtr->nextPtr) { + count += segPtr->size; + } + *offsetPosPtr = TextSearchIndexInLine(searchSpecPtr, linePtr, count); + } else { + *offsetPosPtr = TextSearchIndexInLine(searchSpecPtr, + indexPtr->linePtr, indexPtr->byteIndex); + } + + *linePosPtr = line; + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TextSearchIndexInLine -- + * + * Find textual index of 'byteIndex' in the searchable characters of + * 'linePtr'. + * + * This means we ignore any embedded windows/images and elidden text + * (unless we are searching that). + * + * Results: + * The returned index is a utf-8 char* byte index for exact searches, and + * a Unicode character index for regexp searches. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TextSearchIndexInLine( + CONST SearchSpec *searchSpecPtr, + /* Search parameters. */ + TkTextLine *linePtr, /* The line we're looking at. */ + int byteIndex) /* Index into the line. */ +{ + TkTextSegment *segPtr; + TkTextIndex curIndex; + int index, leftToScan; + TkText *textPtr = (TkText *) searchSpecPtr->clientData; + + index = 0; + curIndex.tree = textPtr->sharedTextPtr->tree; + curIndex.linePtr = linePtr; curIndex.byteIndex = 0; + for (segPtr = linePtr->segPtr, leftToScan = byteIndex; + leftToScan > 0; + curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) { + if ((segPtr->typePtr == &tkTextCharType) && + (searchSpecPtr->searchElide + || !TkTextIsElided(textPtr, &curIndex, NULL))) { + if (leftToScan < segPtr->size) { + if (searchSpecPtr->exact) { + index += leftToScan; + } else { + index += Tcl_NumUtfChars(segPtr->body.chars, leftToScan); + } + } else if (searchSpecPtr->exact) { + index += segPtr->size; + } else { + index += Tcl_NumUtfChars(segPtr->body.chars, -1); + } + } + leftToScan -= segPtr->size; + } + return index; +} + +/* + *---------------------------------------------------------------------- + * + * TextSearchAddNextLine -- + * + * Adds a line from the text widget to the object 'theLine'. + * + * Results: + * A pointer to the TkTextLine corresponding to the given line, or NULL + * if there was no available line. + * + * Also 'lenPtr' (if non-NULL) is filled in with the total length of + * 'theLine' (not just what we added to it, but the length including what + * was already in there). This is in bytes for an exact search and in + * chars for a regexp search. + * + * Also 'extraLinesPtr' (if non-NULL) will have its value incremented by + * 1 for each additional logical line we have added because a newline is + * elided (this will only ever happen if we have chosen not to search + * elided text, of course). + * + * Side effects: + * Memory may be allocated or re-allocated for theLine's string + * representation. + * + *---------------------------------------------------------------------- + */ + +static ClientData +TextSearchAddNextLine( + int lineNum, /* Line we must add. */ + SearchSpec *searchSpecPtr, /* Search parameters. */ + Tcl_Obj *theLine, /* Object to append to. */ + int *lenPtr, /* For returning the total length. */ + int *extraLinesPtr) /* If non-NULL, will have its value + * incremented by the number of additional + * logical lines which are merged into this + * one by newlines being elided. */ +{ + TkTextLine *linePtr, *thisLinePtr; + TkTextIndex curIndex; + TkTextSegment *segPtr; + TkText *textPtr = (TkText *) searchSpecPtr->clientData; + int nothingYet = 1; + + /* + * Extract the text from the line. + */ + + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, lineNum); + if (linePtr == NULL) { + return NULL; + } + curIndex.tree = textPtr->sharedTextPtr->tree; + thisLinePtr = linePtr; + + while (thisLinePtr != NULL) { + int elideWraps = 0; + + curIndex.linePtr = thisLinePtr; + curIndex.byteIndex = 0; + for (segPtr = thisLinePtr->segPtr; segPtr != NULL; curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) { - if ((segPtr->typePtr != &tkTextCharType) - || (!searchElide && TkTextIsElided(textPtr, &curIndex))) { + if (!searchSpecPtr->searchElide + && TkTextIsElided(textPtr, &curIndex, NULL)) { + /* + * If we reach the end of the logical line, and if we have at + * least one character in the string, then we continue + * wrapping to the next logical line. If there are no + * characters yet, then the entire line of characters is + * elided and there's no need to complicate matters by + * wrapping - we'll look at the next line in due course. + */ + + if (segPtr->nextPtr == NULL && !nothingYet) { + elideWraps = 1; + } + continue; + } + if (segPtr->typePtr != &tkTextCharType) { continue; } - Tcl_DStringAppend(&line, segPtr->body.chars, segPtr->size); + Tcl_AppendToObj(theLine, segPtr->body.chars, segPtr->size); + nothingYet = 0; } - if (!exact) { - Tcl_DStringSetLength(&line, Tcl_DStringLength(&line)-1); + if (!elideWraps) { + break; + } + lineNum++; + if (lineNum >= searchSpecPtr->numLines) { + break; } - startOfLine = Tcl_DStringValue(&line); + thisLinePtr = TkBTreeNextLine(textPtr, thisLinePtr); + if (thisLinePtr != NULL && extraLinesPtr != NULL) { + /* + * Tell our caller we have an extra line merged in. + */ - /* - * If we're ignoring case, convert the line to lower case. - */ + *extraLinesPtr = (*extraLinesPtr) + 1; + } + } + + /* + * If we're ignoring case, convert the line to lower case. There is no + * need to do this for regexp searches, since they handle a flag for this + * purpose. + */ - if (noCase) { - Tcl_DStringSetLength(&line, - Tcl_UtfToLower(Tcl_DStringValue(&line))); + if (searchSpecPtr->exact && searchSpecPtr->noCase) { + Tcl_SetObjLength(theLine, Tcl_UtfToLower(Tcl_GetString(theLine))); + } + + if (lenPtr != NULL) { + if (searchSpecPtr->exact) { + Tcl_GetStringFromObj(theLine, lenPtr); + } else { + *lenPtr = Tcl_GetCharLength(theLine); } + } + return (ClientData)linePtr; +} + +/* + *---------------------------------------------------------------------- + * + * TextSearchFoundMatch -- + * + * Stores information from a successful search. + * + * Results: + * 1 if the information was stored, 0 if the position at which the match + * was found actually falls outside the allowable search region (and + * therefore the search is actually complete). + * + * Side effects: + * Memory may be allocated in the 'countPtr' and 'resPtr' fields of + * 'searchSpecPtr'. Each of those objects will have refCount zero and + * must eventually be freed or stored elsewhere as appropriate. + * + *---------------------------------------------------------------------- + */ +static int +TextSearchFoundMatch( + int lineNum, /* Line on which match was found. */ + SearchSpec *searchSpecPtr, /* Search parameters. */ + ClientData clientData, /* Token returned by the 'addNextLineProc', + * TextSearchAddNextLine. May be NULL, in + * which we case we must generate it (from + * lineNum). */ + Tcl_Obj *theLine, /* Text from current line, only accessed for + * exact searches, and is allowed to be NULL + * for regexp searches. */ + int matchOffset, /* Offset of found item in utf-8 bytes for + * exact search, Unicode chars for regexp. */ + int matchLength) /* Length also in bytes/chars as per search + * type. */ +{ + int numChars; + int leftToScan; + TkTextIndex curIndex, foundIndex; + TkTextSegment *segPtr; + TkTextLine *linePtr; + TkText *textPtr = (TkText *) searchSpecPtr->clientData; + + if (lineNum == searchSpecPtr->stopLine) { /* - * Check for matches within the current line. If so, and if we're - * searching backwards, repeat the search to find the last match - * in the line. (Note: The lastByte should include the NULL char - * so we can handle searching for end of line easier.) + * If the current index is on the wrong side of the stopIndex, then + * the item we just found is actually outside the acceptable range, + * and the search is over. */ - matchByte = -1; - firstByte = 0; - lastByte = Tcl_DStringLength(&line) + 1; - if (lineNum == startingLine) { - int indexInDString; + if (searchSpecPtr->backwards ^ + (matchOffset >= searchSpecPtr->stopOffset)) { + return 0; + } + } - /* - * The starting line is tricky: the first time we see it - * we check one part of the line, and the second pass through - * we check the other part of the line. We have to be very - * careful here because there could be embedded windows or - * other things that are not in the extracted line. Rescan - * the original line to compute the index in it of the first - * character. - */ + /* + * Calculate the character count, which may need augmenting if there are + * embedded windows or elidden text. + */ + + if (searchSpecPtr->exact) { + CONST char *startOfLine = Tcl_GetString(theLine); + + numChars = Tcl_NumUtfChars(startOfLine + matchOffset, matchLength); + } else { + numChars = matchLength; + } + + /* + * If we're using strict limits checking, ensure that the match with its + * full length fits inside the given range. + */ + + if (searchSpecPtr->strictLimits && lineNum == searchSpecPtr->stopLine) { + if (searchSpecPtr->backwards ^ + ((matchOffset + numChars) > searchSpecPtr->stopOffset)) { + return 0; + } + } + + /* + * The index information returned by the regular expression parser only + * considers textual information: it doesn't account for embedded windows, + * elided text (when we are not searching elided text) or any other + * non-textual info. Scan through the line's segments again to adjust both + * matchChar and matchCount. + * + * We will walk through the segments of this line until we have either + * reached the end of the match or we have reached the end of the line. + */ + + linePtr = (TkTextLine *)clientData; + if (linePtr == NULL) { + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, + lineNum); + } + + curIndex.tree = textPtr->sharedTextPtr->tree; + + /* + * Find the starting point. + */ + + leftToScan = matchOffset; + while (1) { + curIndex.linePtr = linePtr; + curIndex.byteIndex = 0; - indexInDString = startingByte; - for (segPtr = linePtr->segPtr, leftToScan = startingByte; - leftToScan > 0; segPtr = segPtr->nextPtr) { - if (segPtr->typePtr != &tkTextCharType) { - indexInDString -= segPtr->size; + /* + * Note that we allow leftToScan to be zero because we want to skip + * over any preceding non-textual items. + */ + + for (segPtr = linePtr->segPtr; leftToScan >= 0 && segPtr; + segPtr = segPtr->nextPtr) { + if (segPtr->typePtr != &tkTextCharType) { + matchOffset += segPtr->size; + } else if (!searchSpecPtr->searchElide + && TkTextIsElided(textPtr, &curIndex, NULL)) { + if (searchSpecPtr->exact) { + matchOffset += segPtr->size; + } else { + matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1); } + } else { leftToScan -= segPtr->size; } + curIndex.byteIndex += segPtr->size; + } + if (segPtr == NULL && leftToScan >= 0) { + /* + * This will only happen if we are eliding newlines. + */ - passes++; - if ((passes == 1) ^ backwards) { + linePtr = TkBTreeNextLine(textPtr, linePtr); + if (linePtr == NULL) { /* - * Only use the last part of the line. + * If we reach the end of the text, we have a serious problem, + * unless there's actually nothing left to look for. */ - firstByte = indexInDString; - if ((firstByte >= Tcl_DStringLength(&line)) - && !((Tcl_DStringLength(&line) == 0) && !exact)) { - goto nextLine; + if (leftToScan == 0) { + break; + } else { + Tcl_Panic("Reached end of text in a match"); } - } else { - /* - * Use only the first part of the line. - */ - - lastByte = indexInDString; } + + /* + * We've wrapped to the beginning of the next logical line, which + * has been merged with the previous one whose newline was elided. + */ + + lineNum++; + matchOffset = 0; + } else { + break; } - do { - int thisLength; - Tcl_UniChar ch; + } - if (exact) { - p = strstr(startOfLine + firstByte, /* INTL: Native. */ - pattern); - if (p == NULL) { - break; - } - i = p - startOfLine; - thisLength = patLength; - } else { - CONST char *start, *end; - int match; + /* + * Calculate and store the found index in the result. + */ - match = Tcl_RegExpExec(interp, regexp, - startOfLine + firstByte, startOfLine); - if (match < 0) { - code = TCL_ERROR; - goto done; - } - if (!match) { - break; - } - Tcl_RegExpRange(regexp, 0, &start, &end); - i = start - startOfLine; - thisLength = end - start; - } - if (i >= lastByte) { - break; - } - matchByte = i; - matchLength = thisLength; - firstByte = i + Tcl_UtfToUniChar(startOfLine + matchByte, &ch); - } while (backwards); + if (searchSpecPtr->exact) { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineNum, + matchOffset, &foundIndex); + } else { + TkTextMakeCharIndex(textPtr->sharedTextPtr->tree, textPtr, lineNum, + matchOffset, &foundIndex); + } - /* - * If we found a match then we're done. Make sure that - * the match occurred before the stopping index, if one was - * specified. - */ + if (searchSpecPtr->all) { + if (searchSpecPtr->resPtr == NULL) { + searchSpecPtr->resPtr = Tcl_NewObj(); + } + Tcl_ListObjAppendElement(NULL, searchSpecPtr->resPtr, + TkTextNewIndexObj(textPtr, &foundIndex)); + } else { + searchSpecPtr->resPtr = TkTextNewIndexObj(textPtr, &foundIndex); + } - if (matchByte >= 0) { - int numChars; + /* + * Find the end point. Here 'leftToScan' could be negative already as a + * result of the above loop if the segment we reached spanned the start of + * the string. When we add matchLength it will become non-negative. + */ + for (leftToScan += matchLength; leftToScan > 0; + curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) { + if (segPtr == NULL) { /* - * Convert the byte length to a character count. + * We are on the next line - this of course should only ever + * happen with searches which have matched across multiple lines. */ - numChars = Tcl_NumUtfChars(startOfLine + matchByte, - matchLength); - + linePtr = TkBTreeNextLine(textPtr, linePtr); + segPtr = linePtr->segPtr; + curIndex.linePtr = linePtr; curIndex.byteIndex = 0; + } + if (segPtr->typePtr != &tkTextCharType) { /* - * The index information returned by the regular expression - * parser only considers textual information: it doesn't - * account for embedded windows, elided text (when we are not - * searching elided text) or any other non-textual info. - * Scan through the line's segments again to adjust both - * matchChar and matchCount. - * - * We will walk through the segments of this line until we have - * either reached the end of the match or we have reached the end - * of the line. + * Anything we didn't count in the search needs adding. */ - curIndex.linePtr = linePtr; curIndex.byteIndex = 0; - for (segPtr = linePtr->segPtr, leftToScan = matchByte; - leftToScan >= 0 && segPtr; segPtr = segPtr->nextPtr) { - if (segPtr->typePtr != &tkTextCharType || \ - (!searchElide && TkTextIsElided(textPtr, &curIndex))) { - matchByte += segPtr->size; - } else { - leftToScan -= segPtr->size; - } - curIndex.byteIndex += segPtr->size; - } - for (leftToScan += matchLength; leftToScan > 0; - segPtr = segPtr->nextPtr) { - if (segPtr->typePtr != &tkTextCharType) { - numChars += segPtr->size; - continue; - } - leftToScan -= segPtr->size; - } - TkTextMakeByteIndex(textPtr->tree, lineNum, matchByte, &index); - if (!searchWholeText) { - if (!backwards && (TkTextIndexCmp(&index, &stopIndex) >= 0)) { - goto done; - } - if (backwards && (TkTextIndexCmp(&index, &stopIndex) < 0)) { - goto done; - } - } - if (varName != NULL) { - sprintf(buffer, "%d", numChars); - if (Tcl_SetVar(interp, varName, buffer, TCL_LEAVE_ERR_MSG) - == NULL) { - code = TCL_ERROR; - goto done; - } - } - TkTextPrintIndex(&index, buffer); - Tcl_SetResult(interp, buffer, TCL_VOLATILE); - goto done; + numChars += segPtr->size; + continue; + } else if (!searchSpecPtr->searchElide + && TkTextIsElided(textPtr, &curIndex, NULL)) { + numChars += Tcl_NumUtfChars(segPtr->body.chars, -1); + continue; + } + if (searchSpecPtr->exact) { + leftToScan -= segPtr->size; + } else { + leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1); } + } - /* - * Go to the next (or previous) line; - */ + /* + * Now store the count result, if it is wanted. + */ - nextLine: - if (backwards) { - lineNum--; - if (!searchWholeText) { - if (lineNum < stopLine) { - break; - } - } else if (lineNum < 0) { - lineNum = numLines-1; + if (searchSpecPtr->varPtr != NULL) { + Tcl_Obj *tmpPtr = Tcl_NewIntObj(numChars); + if (searchSpecPtr->all) { + if (searchSpecPtr->countPtr == NULL) { + searchSpecPtr->countPtr = Tcl_NewObj(); } + Tcl_ListObjAppendElement(NULL, searchSpecPtr->countPtr, tmpPtr); } else { - lineNum++; - if (!searchWholeText) { - if (lineNum > stopLine) { - break; - } - } else if (lineNum >= numLines) { - lineNum = 0; - } + searchSpecPtr->countPtr = tmpPtr; } - Tcl_DStringSetLength(&line, 0); - } - done: - Tcl_DStringFree(&line); - if (noCase && exact) { - Tcl_DStringFree(&patDString); } - if (patObj != NULL) { - Tcl_DecrRefCount(patObj); - } - return code; + return 1; } /* @@ -2403,105 +4313,158 @@ TextSearchCmd(textPtr, interp, argc, argv) * Parses a string description of a set of tab stops. * * Results: - * The return value is a pointer to a malloc'ed structure holding - * parsed information about the tab stops. If an error occurred - * then the return value is NULL and an error message is left in - * the interp's result. + * The return value is a pointer to a malloc'ed structure holding parsed + * information about the tab stops. If an error occurred then the return + * value is NULL and an error message is left in the interp's result. * * Side effects: - * Memory is allocated for the structure that is returned. It is - * up to the caller to free this structure when it is no longer - * needed. + * Memory is allocated for the structure that is returned. It is up to + * the caller to free this structure when it is no longer needed. * *---------------------------------------------------------------------- */ TkTextTabArray * -TkTextGetTabs(interp, tkwin, string) - Tcl_Interp *interp; /* Used for error reporting. */ - Tk_Window tkwin; /* Window in which the tabs will be - * used. */ - char *string; /* Description of the tab stops. See - * the text manual entry for details. */ +TkTextGetTabs( + Tcl_Interp *interp, /* Used for error reporting. */ + TkText *textPtr, /* Information about the text widget. */ + Tcl_Obj *stringPtr) /* Description of the tab stops. See the text + * manual entry for details. */ { - int argc, i, count, c; - CONST char **argv; + int objc, i, count; + Tcl_Obj **objv; TkTextTabArray *tabArrayPtr; TkTextTab *tabPtr; Tcl_UniChar ch; + double prevStop, lastStop; + /* + * Map these strings to TkTextTabAlign values. + */ + static CONST char *tabOptionStrings[] = { + "left", "right", "center", "numeric", NULL + }; - if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) { + if (Tcl_ListObjGetElements(interp, stringPtr, &objc, &objv) != TCL_OK) { return NULL; } /* - * First find out how many entries we need to allocate in the - * tab array. + * First find out how many entries we need to allocate in the tab array. */ count = 0; - for (i = 0; i < argc; i++) { - c = argv[i][0]; + for (i = 0; i < objc; i++) { + char c = Tcl_GetString(objv[i])[0]; if ((c != 'l') && (c != 'r') && (c != 'c') && (c != 'n')) { count++; } } /* - * Parse the elements of the list one at a time to fill in the - * array. + * Parse the elements of the list one at a time to fill in the array. */ tabArrayPtr = (TkTextTabArray *) ckalloc((unsigned) (sizeof(TkTextTabArray) + (count-1)*sizeof(TkTextTab))); tabArrayPtr->numTabs = 0; - for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < argc; i++, tabPtr++) { - if (Tk_GetPixels(interp, tkwin, argv[i], &tabPtr->location) - != TCL_OK) { + prevStop = 0.0; + lastStop = 0.0; + for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < objc; i++, tabPtr++) { + int index; + + /* + * This will round fractional pixels above 0.5 upwards, and otherwise + * downwards, to find the right integer pixel position. + */ + + if (Tk_GetPixelsFromObj(interp, textPtr->tkwin, objv[i], + &tabPtr->location) != TCL_OK) { + goto error; + } + + if (tabPtr->location <= 0) { + Tcl_AppendResult(interp, "tab stop \"", Tcl_GetString(objv[i]), + "\" is not at a positive distance", NULL); + goto error; + } + + prevStop = lastStop; + if (Tk_GetDoublePixelsFromObj (interp, textPtr->tkwin, objv[i], + &lastStop) != TCL_OK) { goto error; } + + if (i > 0 && (tabPtr->location <= (tabPtr-1)->location)) { + /* + * This tab is actually to the left of the previous one, which is + * illegal. + */ + +#ifdef _TK_ALLOW_DECREASING_TABS + /* + * Force the tab to be a typical character width to the right of + * the previous one, and update the 'lastStop' with the changed + * position. + */ + + if (textPtr->charWidth > 0) { + tabPtr->location = (tabPtr-1)->location + textPtr->charWidth; + } else { + tabPtr->location = (tabPtr-1)->location + 8; + } + lastStop = tabPtr->location; +#else + Tcl_AppendResult(interp, + "tabs must be monotonically increasing, but \"", + Tcl_GetString(objv[i]), + "\" is smaller than or equal to the previous tab", + NULL); + goto error; +#endif /* _TK_ALLOW_DECREASING_TABS */ + } + tabArrayPtr->numTabs++; /* - * See if there is an explicit alignment in the next list - * element. Otherwise just use "left". + * See if there is an explicit alignment in the next list element. + * Otherwise just use "left". */ tabPtr->alignment = LEFT; - if ((i+1) == argc) { + if ((i+1) == objc) { continue; } - Tcl_UtfToUniChar(argv[i+1], &ch); + + /* + * There may be a more efficient way of getting this. + */ + + Tcl_UtfToUniChar(Tcl_GetString(objv[i+1]), &ch); if (!Tcl_UniCharIsAlpha(ch)) { continue; } i += 1; - c = argv[i][0]; - if ((c == 'l') && (strncmp(argv[i], "left", - strlen(argv[i])) == 0)) { - tabPtr->alignment = LEFT; - } else if ((c == 'r') && (strncmp(argv[i], "right", - strlen(argv[i])) == 0)) { - tabPtr->alignment = RIGHT; - } else if ((c == 'c') && (strncmp(argv[i], "center", - strlen(argv[i])) == 0)) { - tabPtr->alignment = CENTER; - } else if ((c == 'n') && (strncmp(argv[i], - "numeric", strlen(argv[i])) == 0)) { - tabPtr->alignment = NUMERIC; - } else { - Tcl_AppendResult(interp, "bad tab alignment \"", - argv[i], "\": must be left, right, center, or numeric", - (char *) NULL); + + if (Tcl_GetIndexFromObj(interp, objv[i], tabOptionStrings, + "tab alignment", 0, &index) != TCL_OK) { goto error; } + tabPtr->alignment = ((TkTextTabAlign)index); } - ckfree((char *) argv); + + /* + * For when we need to interpolate tab stops, store these two so we know + * the tab stop size to very high precision. With the above checks, we can + * guarantee that tabIncrement is strictly positive here. + */ + + tabArrayPtr->lastTab = lastStop; + tabArrayPtr->tabIncrement = lastStop - prevStop; + return tabArrayPtr; - error: + error: ckfree((char *) tabArrayPtr); - ckfree((char *) argv); return NULL; } @@ -2511,8 +4474,8 @@ TkTextGetTabs(interp, tkwin, string) * TextDumpCmd -- * * Return information about the text, tags, marks, and embedded windows - * and images in a text widget. See the man page for the description - * of the text dump operation for all the details. + * and images in a text widget. See the man page for the description of + * the text dump operation for all the details. * * Results: * A standard Tcl result. @@ -2525,21 +4488,21 @@ TkTextGetTabs(interp, tkwin, string) */ static int -TextDumpCmd(textPtr, interp, argc, argv) - register TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TextDumpCmd( + register TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "dump". */ + * objv[1] is "dump". */ { TkTextIndex index1, index2; int arg; - int lineno; /* Current line number */ - int what = 0; /* bitfield to select segment types */ - int atEnd; /* True if dumping up to logical end */ + int lineno; /* Current line number. */ + int what = 0; /* bitfield to select segment types. */ + int atEnd; /* True if dumping up to logical end. */ TkTextLine *linePtr; - CONST char *command = NULL; /* Script callback to apply to segments */ + Tcl_Obj *command = NULL; /* Script callback to apply to segments. */ #define TK_DUMP_TEXT 0x1 #define TK_DUMP_MARK 0x2 #define TK_DUMP_TAG 0x4 @@ -2547,116 +4510,189 @@ TextDumpCmd(textPtr, interp, argc, argv) #define TK_DUMP_IMG 0x10 #define TK_DUMP_ALL (TK_DUMP_TEXT|TK_DUMP_MARK|TK_DUMP_TAG| \ TK_DUMP_WIN|TK_DUMP_IMG) - - for (arg=2 ; argv[arg] != (char *) NULL ; arg++) { - size_t len; - if (argv[arg][0] != '-') { + static CONST char *optStrings[] = { + "-all", "-command", "-image", "-mark", "-tag", "-text", "-window", + NULL + }; + enum opts { + DUMP_ALL, DUMP_CMD, DUMP_IMG, DUMP_MARK, DUMP_TAG, DUMP_TXT, DUMP_WIN + }; + + for (arg=2 ; arg < objc ; arg++) { + int index; + if (Tcl_GetString(objv[arg])[0] != '-') { break; } - len = strlen(argv[arg]); - if (strncmp("-all", argv[arg], len) == 0) { + if (Tcl_GetIndexFromObj(interp, objv[arg], optStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum opts) index) { + case DUMP_ALL: what = TK_DUMP_ALL; - } else if (strncmp("-text", argv[arg], len) == 0) { + break; + case DUMP_TXT: what |= TK_DUMP_TEXT; - } else if (strncmp("-tag", argv[arg], len) == 0) { + break; + case DUMP_TAG: what |= TK_DUMP_TAG; - } else if (strncmp("-mark", argv[arg], len) == 0) { + break; + case DUMP_MARK: what |= TK_DUMP_MARK; - } else if (strncmp("-image", argv[arg], len) == 0) { + break; + case DUMP_IMG: what |= TK_DUMP_IMG; - } else if (strncmp("-window", argv[arg], len) == 0) { + break; + case DUMP_WIN: what |= TK_DUMP_WIN; - } else if (strncmp("-command", argv[arg], len) == 0) { + break; + case DUMP_CMD: arg++; - if (arg >= argc) { - Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL); + if (arg >= objc) { + Tcl_AppendResult(interp, "Usage: ", Tcl_GetString(objv[0]), + " dump ?-all -image -text -mark -tag -window? ", + "?-command script? index ?index2?", NULL); return TCL_ERROR; } - command = argv[arg]; - } else { - Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL); - return TCL_ERROR; + command = objv[arg]; + break; + default: + Tcl_Panic("unexpected switch fallthrough"); } } - if (arg >= argc) { - Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL); + if (arg >= objc || arg+2 < objc) { + Tcl_AppendResult(interp, "Usage: ", Tcl_GetString(objv[0]), + " dump ?-all -image -text -mark -tag -window? ", + "?-command script? index ?index2?", NULL); return TCL_ERROR; } if (what == 0) { what = TK_DUMP_ALL; } - if (TkTextGetIndex(interp, textPtr, argv[arg], &index1) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index1) != TCL_OK) { return TCL_ERROR; } - lineno = TkBTreeLineIndex(index1.linePtr); arg++; atEnd = 0; - if (argc == arg) { - TkTextIndexForwChars(&index1, 1, &index2); + if (objc == arg) { + TkTextIndexForwChars(NULL, &index1, 1, &index2, COUNT_INDICES); } else { - if (TkTextGetIndex(interp, textPtr, argv[arg], &index2) != TCL_OK) { + int length; + char *str; + + if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) { return TCL_ERROR; } - if (strncmp(argv[arg], "end", strlen(argv[arg])) == 0) { + str = Tcl_GetStringFromObj(objv[arg], &length); + if (strncmp(str, "end", (unsigned)length) == 0) { atEnd = 1; } } if (TkTextIndexCmp(&index1, &index2) >= 0) { return TCL_OK; } + lineno = TkBTreeLinesTo(textPtr, index1.linePtr); if (index1.linePtr == index2.linePtr) { DumpLine(interp, textPtr, what, index1.linePtr, - index1.byteIndex, index2.byteIndex, lineno, command); + index1.byteIndex, index2.byteIndex, lineno, command); } else { - DumpLine(interp, textPtr, what, index1.linePtr, + int textChanged; + int lineend = TkBTreeLinesTo(textPtr, index2.linePtr); + int endByteIndex = index2.byteIndex; + + textChanged = DumpLine(interp, textPtr, what, index1.linePtr, index1.byteIndex, 32000000, lineno, command); - linePtr = index1.linePtr; - while ((linePtr = TkBTreeNextLine(linePtr)) != (TkTextLine *)NULL) { + if (textChanged) { + if (textPtr->flags & DESTROYED) { + return TCL_OK; + } + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, lineno); + textChanged = 0; + } else { + linePtr = index1.linePtr; + } + while ((linePtr = TkBTreeNextLine(textPtr, linePtr)) != NULL) { lineno++; - if (linePtr == index2.linePtr) { + if (lineno == lineend) { break; } - DumpLine(interp, textPtr, what, linePtr, 0, 32000000, + textChanged = DumpLine(interp, textPtr, what, linePtr, 0, 32000000, lineno, command); + if (textChanged) { + if (textPtr->flags & DESTROYED) { + return TCL_OK; + } + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, lineno); + textChanged = 0; + } + } + if (linePtr != NULL) { + DumpLine(interp, textPtr, what, linePtr, 0, endByteIndex, lineno, + command); + if (textPtr->flags & DESTROYED) { + return TCL_OK; + } } - DumpLine(interp, textPtr, what, index2.linePtr, 0, - index2.byteIndex, lineno, command); } + /* * Special case to get the leftovers hiding at the end mark. */ + if (atEnd) { - DumpLine(interp, textPtr, what & ~TK_DUMP_TEXT, index2.linePtr, - 0, 1, lineno, command); + if (textPtr->flags & DESTROYED) { + return TCL_OK; + } + + /* + * Re-get the end index, in case it has changed. + */ + if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) { + return TCL_ERROR; + } + DumpLine(interp, textPtr, what & ~TK_DUMP_TEXT, index2.linePtr, + 0, 1, lineno, command); } return TCL_OK; } /* + *---------------------------------------------------------------------- + * * DumpLine - * Return information about a given text line from character - * position "start" up to, but not including, "end". + * + * Return information about a given text line from character position + * "start" up to, but not including, "end". * * Results: - * A standard Tcl result. + * Returns 1 if the command callback made any changes to the text widget + * which will have invalidated internal structures such as TkTextSegment, + * TkTextIndex, pointers. Our caller can then take action to recompute + * such entities. Returns 0 otherwise. * * Side effects: - * None, but see DumpSegment. + * None, but see DumpSegment which can have arbitrary side-effects + * + *---------------------------------------------------------------------- */ -static void -DumpLine(interp, textPtr, what, linePtr, startByte, endByte, lineno, command) - Tcl_Interp *interp; - TkText *textPtr; - int what; /* bit flags to select segment types */ - TkTextLine *linePtr; /* The current line */ - int startByte, endByte; /* Byte range to dump */ - int lineno; /* Line number for indices dump */ - CONST char *command; /* Script to apply to the segment */ + +static int +DumpLine( + Tcl_Interp *interp, + TkText *textPtr, + int what, /* Bit flags to select segment types. */ + TkTextLine *linePtr, /* The current line. */ + int startByte, int endByte, /* Byte range to dump. */ + int lineno, /* Line number for indices dump. */ + Tcl_Obj *command) /* Script to apply to the segment. */ { - int offset; - TkTextSegment *segPtr, *nextPtr; + TkTextSegment *segPtr; TkTextIndex index; + int offset = 0, textChanged = 0; + /* * Must loop through line looking at its segments. * character @@ -2666,335 +4702,485 @@ DumpLine(interp, textPtr, what, linePtr, startByte, endByte, lineno, command) * window */ - for (offset = 0, segPtr = linePtr->segPtr ; - (offset < endByte) && (segPtr != (TkTextSegment *)NULL) ; - offset += segPtr->size, segPtr = nextPtr) { - nextPtr = segPtr->nextPtr; + segPtr = linePtr->segPtr; + while ((offset < endByte) && (segPtr != NULL)) { + int lineChanged = 0; + int currentSize = segPtr->size; + if ((what & TK_DUMP_TEXT) && (segPtr->typePtr == &tkTextCharType) && - (offset + segPtr->size > startByte)) { - char savedChar; /* Last char used in the seg */ - int last = segPtr->size; /* Index of savedChar */ - int first = 0; /* Index of first char in seg */ - if (offset + segPtr->size > endByte) { + (offset + currentSize > startByte)) { + int last = currentSize; /* Index of last char in seg. */ + int first = 0; /* Index of first char in seg. */ + + if (offset + currentSize > endByte) { last = endByte - offset; } if (startByte > offset) { first = startByte - offset; } - savedChar = segPtr->body.chars[last]; - segPtr->body.chars[last] = '\0'; - - TkTextMakeByteIndex(textPtr->tree, lineno, offset + first, &index); - DumpSegment(interp, "text", segPtr->body.chars + first, - command, &index, what); - segPtr->body.chars[last] = savedChar; + if (last != currentSize) { + /* + * To avoid modifying the string in place we copy over just + * the segment that we want. Since DumpSegment can modify the + * text, we could not confidently revert the modification + * here. + */ + + int length = last - first; + char *range = ckalloc((length + 1) * sizeof(char)); + + memcpy(range, segPtr->body.chars + first, + length * sizeof(char)); + range[length] = '\0'; + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset + first, &index); + lineChanged = DumpSegment(textPtr, interp, "text", range, + command, &index, what); + ckfree(range); + } else { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset + first, &index); + lineChanged = DumpSegment(textPtr, interp, "text", + segPtr->body.chars + first, command, &index, what); + } } else if ((offset >= startByte)) { if ((what & TK_DUMP_MARK) && (segPtr->typePtr->name[0] == 'm')) { - TkTextMark *markPtr = (TkTextMark *)&segPtr->body; - char *name = Tcl_GetHashKey(&textPtr->markTable, markPtr->hPtr); - - TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index); - DumpSegment(interp, "mark", name, command, &index, what); + char *name; + TkTextMark *markPtr = (TkTextMark *) &segPtr->body; + + if (segPtr == textPtr->insertMarkPtr) { + name = "insert"; + } else if (segPtr == textPtr->currentMarkPtr) { + name = "current"; + } else if (markPtr->hPtr == NULL) { + name = NULL; + lineChanged = 0; + } else { + name = Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, + markPtr->hPtr); + } + if (name != NULL) { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset, &index); + lineChanged = DumpSegment(textPtr, interp, "mark", name, + command, &index, what); + } } else if ((what & TK_DUMP_TAG) && - (segPtr->typePtr == &tkTextToggleOnType)) { - TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index); - DumpSegment(interp, "tagon", - segPtr->body.toggle.tagPtr->name, - command, &index, what); - } else if ((what & TK_DUMP_TAG) && - (segPtr->typePtr == &tkTextToggleOffType)) { - TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index); - DumpSegment(interp, "tagoff", - segPtr->body.toggle.tagPtr->name, - command, &index, what); - } else if ((what & TK_DUMP_IMG) && - (segPtr->typePtr->name[0] == 'i')) { + (segPtr->typePtr == &tkTextToggleOnType)) { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset, &index); + lineChanged = DumpSegment(textPtr, interp, "tagon", + segPtr->body.toggle.tagPtr->name, command, &index, + what); + } else if ((what & TK_DUMP_TAG) && + (segPtr->typePtr == &tkTextToggleOffType)) { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset, &index); + lineChanged = DumpSegment(textPtr, interp, "tagoff", + segPtr->body.toggle.tagPtr->name, command, &index, + what); + } else if ((what & TK_DUMP_IMG) && + (segPtr->typePtr->name[0] == 'i')) { TkTextEmbImage *eiPtr = (TkTextEmbImage *)&segPtr->body; - char *name = (eiPtr->name == NULL) ? "" : eiPtr->name; - TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index); - DumpSegment(interp, "image", name, + char *name = (eiPtr->name == NULL) ? "" : eiPtr->name; + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset, &index); + lineChanged = DumpSegment(textPtr, interp, "image", name, command, &index, what); - } else if ((what & TK_DUMP_WIN) && - (segPtr->typePtr->name[0] == 'w')) { + } else if ((what & TK_DUMP_WIN) && + (segPtr->typePtr->name[0] == 'w')) { TkTextEmbWindow *ewPtr = (TkTextEmbWindow *)&segPtr->body; char *pathname; + if (ewPtr->tkwin == (Tk_Window) NULL) { pathname = ""; } else { pathname = Tk_PathName(ewPtr->tkwin); } - TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index); - DumpSegment(interp, "window", pathname, + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineno, offset, &index); + lineChanged = DumpSegment(textPtr, interp, "window", pathname, command, &index, what); } } - if (nextPtr != segPtr->nextPtr) { + offset += currentSize; + if (lineChanged) { + TkTextSegment *newSegPtr; + int newOffset = 0; + + textChanged = 1; + /* - * Someone modified the text widget while we were dumping. - * Just stop dumping. [Bug 1414171] + * Our indices are no longer valid. */ - break; + + if (textPtr->flags & DESTROYED) { + return textChanged; + } + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, lineno); + newSegPtr = linePtr->segPtr; + if (segPtr == newSegPtr) { + segPtr = segPtr->nextPtr; + } else { + while ((newOffset < endByte) && (newOffset < offset) + && (newSegPtr != NULL)) { + newOffset += currentSize; + newSegPtr = newSegPtr->nextPtr; + if (segPtr == newSegPtr) { + break; + } + } + if (segPtr != newSegPtr && newOffset == offset + && currentSize == 0) { + TkTextSegment *searchPtr = newSegPtr; + + while (searchPtr != NULL && searchPtr->size == 0) { + if (searchPtr == segPtr) { + newSegPtr = searchPtr; + break; + } + searchPtr = searchPtr->nextPtr; + } + } + segPtr = newSegPtr; + if (segPtr != NULL) { + segPtr = segPtr->nextPtr; + } + } + } else { + segPtr = segPtr->nextPtr; } } + return textChanged; } /* + *---------------------------------------------------------------------- + * * DumpSegment - * Either append information about the current segment to the result, - * or make a script callback with that information as arguments. + * + * Either append information about the current segment to the result, or + * make a script callback with that information as arguments. * * Results: - * None + * Returns 1 if the command callback made any changes to the text widget + * which will have invalidated internal structures such as TkTextSegment, + * TkTextIndex, pointers. Our caller can then take action to recompute + * such entities. Returns 0 otherwise. * * Side effects: * Either evals the callback or appends elements to the result string. + * The callback can have arbitrary side-effects. + * + *---------------------------------------------------------------------- */ + static int -DumpSegment(interp, key, value, command, index, what) - Tcl_Interp *interp; - char *key; /* Segment type key */ - char *value; /* Segment value */ - CONST char *command; /* Script callback */ - TkTextIndex *index; /* index with line/byte position info */ - int what; /* Look for TK_DUMP_INDEX bit */ +DumpSegment( + TkText *textPtr, + Tcl_Interp *interp, + CONST char *key, /* Segment type key. */ + CONST char *value, /* Segment value. */ + Tcl_Obj *command, /* Script callback. */ + CONST TkTextIndex *index, /* index with line/byte position info. */ + int what) /* Look for TK_DUMP_INDEX bit. */ { - char buffer[TCL_INTEGER_SPACE*2]; - TkTextPrintIndex(index, buffer); + char buffer[TK_POS_CHARS]; + + TkTextPrintIndex(textPtr, index, buffer); if (command == NULL) { Tcl_AppendElement(interp, key); Tcl_AppendElement(interp, value); Tcl_AppendElement(interp, buffer); - return TCL_OK; + return 0; } else { CONST char *argv[4]; char *list; - int result; + int oldStateEpoch = TkBTreeEpoch(textPtr->sharedTextPtr->tree); + argv[0] = key; argv[1] = value; argv[2] = buffer; argv[3] = NULL; list = Tcl_Merge(3, argv); - result = Tcl_VarEval(interp, command, " ", list, (char *) NULL); + Tcl_VarEval(interp, Tcl_GetString(command), " ", list, NULL); ckfree(list); - return result; + if ((textPtr->flags & DESTROYED) || + TkBTreeEpoch(textPtr->sharedTextPtr->tree) != oldStateEpoch) { + return 1; + } else { + return 0; + } } } /* + *---------------------------------------------------------------------- + * * TextEditUndo -- - * undo the last change. + * + * Undo the last change. * * Results: - * None + * None. * * Side effects: - * None. + * Apart from manipulating the undo and redo stacks, the state of the + * rest of the widget may also change (due to whatever is being undone). + * + *---------------------------------------------------------------------- */ static int -TextEditUndo(textPtr) - TkText *textPtr; /* Overall information about text widget. */ +TextEditUndo( + TkText *textPtr) /* Overall information about text widget. */ { int status; - if (!textPtr->undo) { + if (!textPtr->sharedTextPtr->undo) { return TCL_OK; } - /* Turn off the undo feature */ - textPtr->undo = 0; + /* + * Turn off the undo feature while we revert a compound action, setting + * the dirty handling mode to undo for the duration (unless it is + * 'fixed'). + */ - /* Set dirty mode to undo, unless it is fixed */ - if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { - textPtr->dirtyMode = TK_TEXT_DIRTY_UNDO; + textPtr->sharedTextPtr->undo = 0; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_UNDO; } - /* revert one compound action */ - status = TkUndoRevert(textPtr->undoStack); + status = TkUndoRevert(textPtr->sharedTextPtr->undoStack); - /* Restore dirty mode */ - if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { - textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } - - /* Turn back on the undo feature */ - textPtr->undo = 1; + textPtr->sharedTextPtr->undo = 1; return status; } /* + *---------------------------------------------------------------------- + * * TextEditRedo -- - * redo the last undone change. + * + * Redo the last undone change. * * Results: - * None + * None. * * Side effects: - * None. + * Apart from manipulating the undo and redo stacks, the state of the + * rest of the widget may also change (due to whatever is being redone). + * + *---------------------------------------------------------------------- */ static int -TextEditRedo(textPtr) - TkText *textPtr; /* Overall information about text widget. */ +TextEditRedo( + TkText *textPtr) /* Overall information about text widget. */ { int status; - if (!textPtr->undo) { + if (!textPtr->sharedTextPtr->undo) { return TCL_OK; } - /* Turn off the undo feature temporarily */ - textPtr->undo = 0; + /* + * Turn off the undo feature temporarily while we revert a previously + * undone compound action, setting the dirty handling mode to redo for the + * duration (unless it is 'fixed'). + */ - /* Set dirty mode to redo, unless it is fixed */ - if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { - textPtr->dirtyMode = TK_TEXT_DIRTY_REDO; + textPtr->sharedTextPtr->undo = 0; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_REDO; } - /* reapply one compound action */ - status = TkUndoApply(textPtr->undoStack); + status = TkUndoApply(textPtr->sharedTextPtr->undoStack); - /* Restore dirty mode */ - if (textPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { - textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + if (textPtr->sharedTextPtr->dirtyMode != TK_TEXT_DIRTY_FIXED) { + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } - - /* Turn back on the undo feature */ - textPtr->undo = 1; - + textPtr->sharedTextPtr->undo = 1; return status; } /* + *---------------------------------------------------------------------- + * * TextEditCmd -- * - * Handle the subcommands to "$text edit ...". - * See documentation for details. + * Handle the subcommands to "$text edit ...". See documentation for + * details. * * Results: - * None + * None * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ static int -TextEditCmd(textPtr, interp, argc, argv) - TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. */ +TextEditCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - int c; - size_t length; + int index; - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " edit option ?arg arg ...?\"", (char *) NULL); + static CONST char *editOptionStrings[] = { + "modified", "redo", "reset", "separator", "undo", NULL + }; + enum editOptions { + EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, EDIT_SEPARATOR, EDIT_UNDO + }; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); return TCL_ERROR; } - c = argv[2][0]; - length = strlen(argv[2]); - if ((c == 'm') && (strncmp(argv[2], "modified", length) == 0)) { - if (argc == 3) { - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(textPtr->isDirty)); - } else if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " edit modified ?boolean?\"", (char *) NULL); + + if (Tcl_GetIndexFromObj(interp, objv[2], editOptionStrings, + "edit option", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + + switch ((enum editOptions) index) { + case EDIT_MODIFIED: + if (objc == 3) { + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(textPtr->sharedTextPtr->isDirty)); + } else if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "?boolean?"); return TCL_ERROR; } else { - int setModified, wasModified = textPtr->isDirty; + int setModified, oldModified; - if (Tcl_GetBoolean(interp, argv[3], &setModified) != TCL_OK) { + if (Tcl_GetBooleanFromObj(interp, objv[3], + &setModified) != TCL_OK) { return TCL_ERROR; } /* - * Set or reset the dirty info, and trigger a Modified event (. + * Set or reset the dirty info, and trigger a Modified event. */ setModified = setModified ? 1 : 0; - textPtr->isDirty = setModified; + oldModified = textPtr->sharedTextPtr->isDirty; + textPtr->sharedTextPtr->isDirty = setModified; if (setModified) { - textPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; } else { - textPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; + textPtr->sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_NORMAL; } - if ((!wasModified) != (!setModified)) { + + /* + * Only issue the <<Modified>> event if the flag actually changed. + * However, degree of modified-ness doesn't matter. [Bug 1799782] + */ + + if ((!oldModified) != (!setModified)) { GenerateModifiedEvent(textPtr); } - } - } else if ((c == 'r') && (strncmp(argv[2], "redo", length) == 0) - && (length >= 3)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " edit redo\"", (char *) NULL); + } + break; + case EDIT_REDO: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - if ( TextEditRedo(textPtr) ) { - Tcl_AppendResult(interp, "nothing to redo", (char *) NULL); + if (TextEditRedo(textPtr)) { + Tcl_AppendResult(interp, "nothing to redo", NULL); return TCL_ERROR; - } - } else if ((c == 'r') && (strncmp(argv[2], "reset", length) == 0) - && (length >= 3)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " edit reset\"", (char *) NULL); + } + break; + case EDIT_RESET: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - TkUndoClearStacks(textPtr->undoStack); - } else if ((c == 's') && (strncmp(argv[2], "separator", length) == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " edit separator\"", (char *) NULL); + TkUndoClearStacks(textPtr->sharedTextPtr->undoStack); + break; + case EDIT_SEPARATOR: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - TkUndoInsertUndoSeparator(textPtr->undoStack); - } else if ((c == 'u') && (strncmp(argv[2], "undo", length) == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " edit undo\"", (char *) NULL); + TkUndoInsertUndoSeparator(textPtr->sharedTextPtr->undoStack); + break; + case EDIT_UNDO: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - if ( TextEditUndo(textPtr) ) { - Tcl_AppendResult(interp, "nothing to undo", - (char *) NULL); + if (TextEditUndo(textPtr)) { + Tcl_AppendResult(interp, "nothing to undo", NULL); return TCL_ERROR; - } - } else { - Tcl_AppendResult(interp, "bad edit option \"", argv[2], - "\": must be modified, redo, reset, separator or undo", - (char *) NULL); - return TCL_ERROR; + } + break; } - return TCL_OK; } /* + *---------------------------------------------------------------------- + * * TextGetText -- - * Returns the text from indexPtr1 to indexPtr2, placing that text - * in the Tcl_DString given. That DString should be free or uninitialized. + * + * Returns the text from indexPtr1 to indexPtr2, placing that text in a + * string object which is returned with a refCount of zero. + * + * Since the amount of text may potentially be several megabytes (e.g. + * in text editors built on the text widget), efficiency is very + * important. We may want to investigate the efficiency of the + * Tcl_AppendToObj more carefully (e.g. if we know we are going to be + * appending several thousand lines, we could attempt to pre-allocate a + * larger space). + * + * Also the result is built up as a utf-8 string, but, if we knew we + * wanted it as Unicode, we could potentially save a huge conversion by + * building it up as Unicode directly. This could be as simple as + * replacing Tcl_NewObj by Tcl_NewUnicodeObj. * * Results: - * None. + * Tcl_Obj of string type containing the specified text. If the + * visibleOnly flag is set to 1, then only those characters which are not + * elided will be returned. Otherwise (flag is 0) all characters in the + * given range are returned. * * Side effects: - * Memory will be allocated for the DString. Remember to free it. + * Memory will be allocated for the new object. Remember to free it if it + * isn't going to be stored appropriately. + * + *---------------------------------------------------------------------- */ -static void -TextGetText(indexPtr1,indexPtr2, dsPtr) - TkTextIndex *indexPtr1; - TkTextIndex *indexPtr2; - Tcl_DString *dsPtr; +static Tcl_Obj * +TextGetText( + CONST TkText *textPtr, /* Information about text widget. */ + CONST TkTextIndex *indexPtr1, + /* Get text from this index... */ + CONST TkTextIndex *indexPtr2, + /* ...to this index. */ + int visibleOnly) /* If non-zero, then only return non-elided + * characters. */ { TkTextIndex tmpIndex; - Tcl_DStringInit(dsPtr); - - TkTextMakeByteIndex(indexPtr1->tree, TkBTreeLineIndex(indexPtr1->linePtr), + Tcl_Obj *resultPtr = Tcl_NewObj(); + + TkTextMakeByteIndex(indexPtr1->tree, textPtr, + TkBTreeLinesTo(textPtr, indexPtr1->linePtr), indexPtr1->byteIndex, &tmpIndex); if (TkTextIndexCmp(indexPtr1, indexPtr2) < 0) { @@ -3005,26 +5191,38 @@ TextGetText(indexPtr1,indexPtr2, dsPtr) segPtr = TkTextIndexToSeg(&tmpIndex, &offset); last = segPtr->size; if (tmpIndex.linePtr == indexPtr2->linePtr) { - int last2; + /* + * The last line that was requested must be handled carefully, + * because we may need to break out of this loop in the middle + * of the line. + */ if (indexPtr2->byteIndex == tmpIndex.byteIndex) { break; - } - last2 = indexPtr2->byteIndex - tmpIndex.byteIndex + offset; - if (last2 < last) { - last = last2; + } else { + int last2 = indexPtr2->byteIndex - tmpIndex.byteIndex + + offset; + + if (last2 < last) { + last = last2; + } } } if (segPtr->typePtr == &tkTextCharType) { - Tcl_DStringAppend(dsPtr, segPtr->body.chars + offset, - last - offset); + if (!visibleOnly || !TkTextIsElided(textPtr,&tmpIndex,NULL)) { + Tcl_AppendToObj(resultPtr, segPtr->body.chars + offset, + last - offset); + } } - TkTextIndexForwBytes(&tmpIndex, last-offset, &tmpIndex); + TkTextIndexForwBytes(textPtr, &tmpIndex, last-offset, &tmpIndex); } } + return resultPtr; } /* + *---------------------------------------------------------------------- + * * GenerateModifiedEvent -- * * Send an event that the text was modified. This is equivalent to @@ -3035,68 +5233,1464 @@ TextGetText(indexPtr1,indexPtr2, dsPtr) * * Side effects: * May force the text window into existence. + * + *---------------------------------------------------------------------- */ static void GenerateModifiedEvent( TkText *textPtr) /* Information about text widget. */ { - XEvent event; + union {XEvent general; XVirtualEvent virtual;} event; Tk_MakeWindowExist(textPtr->tkwin); memset(&event, 0, sizeof(event)); - event.xany.type = VirtualEvent; - event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.xany.send_event = False; - event.xany.window = Tk_WindowId(textPtr->tkwin); - event.xany.display = Tk_Display(textPtr->tkwin); - ((XVirtualEvent *) &event)->name = Tk_GetUid("Modified"); - Tk_HandleEvent(&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); } /* - * updateDirtyFlag -- - * updates the dirtyness of the text widget + *---------------------------------------------------------------------- + * + * UpdateDirtyFlag -- + * + * Updates the dirtyness of the text widget * * Results: - * None + * None * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ static void -updateDirtyFlag(textPtr) - TkText *textPtr; /* Information about text widget. */ +UpdateDirtyFlag( + TkSharedText *sharedTextPtr)/* Information about text widget. */ { int oldDirtyFlag; + TkText *textPtr; + + /* + * If we've been forced to be dirty, we stay dirty (until explicitly + * reset, of course). + */ + + if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_FIXED) { + return; + } + + if (sharedTextPtr->isDirty < 0 + && sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_NORMAL) { + /* + * If dirty flag is negative, only redo operations can make it zero + * again. If we do a normal operation, it can never become zero any + * more (other than by explicit reset). + */ - if (textPtr->dirtyMode == TK_TEXT_DIRTY_FIXED) { + sharedTextPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; return; } + oldDirtyFlag = sharedTextPtr->isDirty; + if (sharedTextPtr->dirtyMode == TK_TEXT_DIRTY_UNDO) { + sharedTextPtr->isDirty--; + } else { + sharedTextPtr->isDirty++; + } + + if (sharedTextPtr->isDirty == 0 || oldDirtyFlag == 0) { + for (textPtr = sharedTextPtr->peers; textPtr != NULL; + textPtr = textPtr->next) { + GenerateModifiedEvent(textPtr); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * SearchPerform -- + * + * Overall control of search process. Is given a pattern, a starting + * index and an ending index, and attempts to perform a search. This + * function is actually completely independent of Tk, and could in the + * future be split off. + * + * Results: + * Standard Tcl result code. In particular, if fromPtr or toPtr are not + * considered valid by the 'lineIndexProc', an error will be thrown and + * no search performed. + * + * Side effects: + * See 'SearchCore'. + * + *---------------------------------------------------------------------- + */ + +static int +SearchPerform( + Tcl_Interp *interp, /* For error messages. */ + SearchSpec *searchSpecPtr, /* Search parameters. */ + Tcl_Obj *patObj, /* Contains an exact string or a regexp + * pattern. Must have a refCount > 0. */ + Tcl_Obj *fromPtr, /* Contains information describing the first + * index. */ + Tcl_Obj *toPtr) /* NULL or information describing the last + * index. */ +{ /* - * If dirty flag is negative, only redo operations can make it zero again. - * If we do a normal operation, it can never become zero anymore. + * Find the starting line and starting offset (measured in Unicode chars + * for regexp search, utf-8 bytes for exact search). */ - if (textPtr->isDirty < 0 && textPtr->dirtyMode == TK_TEXT_DIRTY_NORMAL) { - textPtr->dirtyMode = TK_TEXT_DIRTY_FIXED; - return; + + if ((*searchSpecPtr->lineIndexProc)(interp, fromPtr, searchSpecPtr, + &searchSpecPtr->startLine, + &searchSpecPtr->startOffset) != TCL_OK) { + return TCL_ERROR; } - oldDirtyFlag = textPtr->isDirty; + /* + * Find the optional end location, similarly. + */ - switch (textPtr->dirtyMode) { - case TK_TEXT_DIRTY_UNDO: - textPtr->isDirty--; - break; - default: - textPtr->isDirty++; - break; + if (toPtr != NULL) { + CONST TkTextIndex *indexToPtr, *indexFromPtr; + TkText *textPtr = (TkText *) searchSpecPtr->clientData; + + indexToPtr = TkTextGetIndexFromObj(interp, textPtr, toPtr); + if (indexToPtr == NULL) { + return TCL_ERROR; + } + indexFromPtr = TkTextGetIndexFromObj(interp, textPtr, fromPtr); + + /* + * Check for any empty search range here. It might be better in the + * future to embed that in SearchCore (whose default behaviour is to + * wrap when given a negative search range). + */ + + if (searchSpecPtr->backwards) { + if (TkTextIndexCmp(indexFromPtr, indexToPtr) == -1) { + return TCL_OK; + } + } else { + if (TkTextIndexCmp(indexFromPtr, indexToPtr) == 1) { + return TCL_OK; + } + } + + if ((*searchSpecPtr->lineIndexProc)(interp, toPtr, searchSpecPtr, + &searchSpecPtr->stopLine, + &searchSpecPtr->stopOffset) != TCL_OK) { + return TCL_ERROR; + } + } else { + searchSpecPtr->stopLine = -1; + } + + /* + * Scan through all of the lines of the text circularly, starting at the + * given index. 'patObj' is the pattern which may be an exact string or a + * regexp pattern depending on the flags in searchSpecPtr. + */ + + return SearchCore(interp, searchSpecPtr, patObj); +} + +/* + *---------------------------------------------------------------------- + * + * SearchCore -- + * + * The core of the search function. This function is actually completely + * independent of Tk, and could in the future be split off. + * + * The function assumes regexp-based searches operate on Unicode strings, + * and exact searches on utf-8 strings. Therefore the 'foundMatchProc' + * and 'addLineProc' need to be aware of this distinction. + * + * Results: + * Standard Tcl result code. + * + * Side effects: + * Only those of the 'searchSpecPtr->foundMatchProc' which is called + * whenever a match is found. + * + * Note that the way matching across multiple lines is implemented, we + * start afresh with each line we have available, even though we may + * already have examined the contents of that line (and further ones) if + * we were attempting a multi-line match using the previous line. This + * means there may be ways to speed this up a lot by not throwing away + * all the multi-line information one has accumulated. Profiling should + * be done to see where the bottlenecks lie before attempting this, + * however. We would also need to be very careful such optimisation keep + * within the specified search bounds. + * + *---------------------------------------------------------------------- + */ + +static int +SearchCore( + Tcl_Interp *interp, /* For error messages. */ + SearchSpec *searchSpecPtr, /* Search parameters. */ + Tcl_Obj *patObj) /* Contains an exact string or a regexp + * pattern. Must have a refCount > 0. */ +{ + /* + * For exact searches these are utf-8 char* offsets, for regexp searches + * they are Unicode char offsets. + */ + + int firstOffset, lastOffset, matchOffset, matchLength; + int passes; + int lineNum = searchSpecPtr->startLine; + int code = TCL_OK; + Tcl_Obj *theLine; + int alreadySearchOffset = -1; + + CONST char *pattern = NULL; /* For exact searches only. */ + int firstNewLine = -1; /* For exact searches only. */ + Tcl_RegExp regexp = NULL; /* For regexp searches only. */ + + /* + * These items are for backward regexp searches only. They are for two + * purposes: to allow us to report backwards matches in the correct order, + * even though the implementation uses repeated forward searches; and to + * provide for overlap checking between backwards matches on different + * text lines. + */ + +#define LOTS_OF_MATCHES 20 + int matchNum = LOTS_OF_MATCHES; + int smArray[2 * LOTS_OF_MATCHES]; + int *storeMatch = smArray; + int *storeLength = smArray + LOTS_OF_MATCHES; + int lastBackwardsLineMatch = -1; + int lastBackwardsMatchOffset = -1; + + if (searchSpecPtr->exact) { + /* + * Convert the pattern to lower-case if we're supposed to ignore case. + */ + + if (searchSpecPtr->noCase) { + patObj = Tcl_DuplicateObj(patObj); + + /* + * This can change the length of the string behind the object's + * back, so ensure it is correctly synchronised. + */ + + Tcl_SetObjLength(patObj, Tcl_UtfToLower(Tcl_GetString(patObj))); + } + } else { + /* + * Compile the regular expression. We want '^$' to match after and + * before \n respectively, so use the TCL_REG_NLANCH flag. + */ + + regexp = Tcl_GetRegExpFromObj(interp, patObj, + (searchSpecPtr->noCase ? TCL_REG_NOCASE : 0) + | (searchSpecPtr->noLineStop ? 0 : TCL_REG_NLSTOP) + | TCL_REG_ADVANCED | TCL_REG_CANMATCH | TCL_REG_NLANCH); + if (regexp == NULL) { + return TCL_ERROR; + } + } + + /* + * For exact strings, we want to know where the first newline is, and we + * will also use this as a flag to test whether it is even possible to + * match the pattern on a single line. If not we will have to search + * across multiple lines. + */ + + if (searchSpecPtr->exact) { + CONST char *nl; + + /* + * We only need to set the matchLength once for exact searches, and we + * do it here. It is also used below as the actual pattern length, so + * it has dual purpose. + */ + + pattern = Tcl_GetStringFromObj(patObj, &matchLength); + nl = strchr(pattern, '\n'); + + /* + * If there is no newline, or it is the very end of the string, then + * we don't need any special treatment, since single-line matching + * will work fine. + */ + + if (nl != NULL && nl[1] != '\0') { + firstNewLine = (nl - pattern); + } + } else { + matchLength = 0; /* Only needed to prevent compiler warnings. */ + } + + /* + * Keep a reference here, so that we can be sure the object doesn't + * disappear behind our backs and invalidate its contents which we are + * using. + */ + + Tcl_IncrRefCount(patObj); + + /* + * For building up the current line being checked. + */ + + theLine = Tcl_NewObj(); + Tcl_IncrRefCount(theLine); + + for (passes = 0; passes < 2; ) { + ClientData lineInfo; + int linesSearched = 1; + int extraLinesSearched = 0; + + if (lineNum >= searchSpecPtr->numLines) { + /* + * Don't search the dummy last line of the text. + */ + + goto nextLine; + } + + /* + * Extract the text from the line, storing its length in 'lastOffset' + * (in bytes if exact, chars if regexp), since obviously the length is + * the maximum offset at which it is possible to find something on + * this line, which is what 'lastOffset' represents. + */ + + lineInfo = (*searchSpecPtr->addLineProc)(lineNum, searchSpecPtr, + theLine, &lastOffset, &linesSearched); + + if (lineInfo == NULL) { + /* + * This should not happen, since 'lineNum' should be valid in the + * call above. However, let's try to be flexible and not cause a + * crash below. + */ + + goto nextLine; + } + + if (lineNum == searchSpecPtr->stopLine && searchSpecPtr->backwards) { + firstOffset = searchSpecPtr->stopOffset; + } else { + firstOffset = 0; + } + + if (alreadySearchOffset != -1) { + if (searchSpecPtr->backwards) { + if (alreadySearchOffset < lastOffset) { + lastOffset = alreadySearchOffset; + } + } else { + if (alreadySearchOffset > firstOffset) { + firstOffset = alreadySearchOffset; + } + } + alreadySearchOffset = -1; + } + + if (lineNum == searchSpecPtr->startLine) { + /* + * The starting line is tricky: the first time we see it we check + * one part of the line, and the second pass through we check the + * other part of the line. + */ + + passes++; + if ((passes == 1) ^ searchSpecPtr->backwards) { + /* + * Forward search and first pass, or backward search and + * second pass. + * + * Only use the last part of the line. + */ + + if (searchSpecPtr->startOffset > firstOffset) { + firstOffset = searchSpecPtr->startOffset; + } + if ((firstOffset >= lastOffset) + && ((lastOffset != 0) || searchSpecPtr->exact)) { + goto nextLine; + } + } else { + /* + * Use only the first part of the line. + */ + + if (searchSpecPtr->startOffset < lastOffset) { + lastOffset = searchSpecPtr->startOffset; + } + } + } + + /* + * Check for matches within the current line 'lineNum'. If so, and if + * we're searching backwards or for all matches, repeat the search + * until we find the last match in the line. The 'lastOffset' is one + * beyond the last position in the line at which a match is allowed to + * begin. + */ + + matchOffset = -1; + + if (searchSpecPtr->exact) { + int maxExtraLines = 0; + CONST char *startOfLine = Tcl_GetString(theLine); + + do { + Tcl_UniChar ch; + CONST char *p; + int lastFullLine = lastOffset; + + if (firstNewLine == -1) { + if (searchSpecPtr->strictLimits + && (firstOffset + matchLength > lastOffset)) { + /* + * Not enough characters to match. + */ + + break; + } + + /* + * Single line matching. We want to scan forwards or + * backwards as appropriate. + */ + + if (searchSpecPtr->backwards) { + /* + * Search back either from the previous match or from + * 'startOfLine + lastOffset - 1' until we find a + * match. + */ + + CONST char c = pattern[0]; + + if (alreadySearchOffset != -1) { + p = startOfLine + alreadySearchOffset; + alreadySearchOffset = -1; + } else { + p = startOfLine + lastOffset -1; + } + while (p >= startOfLine + firstOffset) { + if (p[0] == c && !strncmp(p, pattern, + (unsigned)matchLength)) { + goto backwardsMatch; + } + p--; + } + break; + } else { + p = strstr(startOfLine + firstOffset, pattern); + } + if (p == NULL) { + /* + * Single line match failed. + */ + + break; + } + } else if (firstNewLine >= (lastOffset - firstOffset)) { + /* + * Multi-line match, but not enough characters to match. + */ + + break; + } else { + /* + * Multi-line match has only one possible match position, + * because we know where the '\n' is. + */ + + p = startOfLine + lastOffset - firstNewLine - 1; + if (strncmp(p, pattern, (unsigned)(firstNewLine + 1))) { + /* + * No match. + */ + + break; + } else { + int extraLines = 1; + + /* + * If we find a match that overlaps more than one + * line, we will use this value to determine the first + * allowed starting offset for the following search + * (to avoid overlapping results). + */ + + int lastTotal = lastOffset; + int skipFirst = lastOffset - firstNewLine -1; + + /* + * We may be able to match if given more text. The + * following 'while' block handles multi-line exact + * searches. + */ + + while (1) { + lastFullLine = lastTotal; + + if (lineNum+extraLines>=searchSpecPtr->numLines) { + p = NULL; + break; + } + + /* + * Only add the line if we haven't already done so + * already. + */ + + if (extraLines > maxExtraLines) { + if ((*searchSpecPtr->addLineProc)(lineNum + + extraLines, searchSpecPtr, theLine, + &lastTotal, &extraLines) == NULL) { + p = NULL; + if (!searchSpecPtr->backwards) { + extraLinesSearched = extraLines; + } + break; + } + maxExtraLines = extraLines; + } + + startOfLine = Tcl_GetString(theLine); + p = startOfLine + skipFirst; + + /* + * Use the fact that 'matchLength = patLength' for + * exact searches. + */ + + if ((lastTotal - skipFirst) >= matchLength) { + /* + * We now have enough text to match, so we + * make a final test and break whatever the + * result. + */ + + if (strncmp(p,pattern,(unsigned)matchLength)) { + p = NULL; + } + break; + } else { + /* + * Not enough text yet, but check the prefix. + */ + + if (strncmp(p, pattern, + (unsigned)(lastTotal - skipFirst))) { + p = NULL; + break; + } + + /* + * The prefix matches, so keep looking. + */ + } + extraLines++; + } + /* + * If we reach here, with p != NULL, we've found a + * multi-line match, else we started a multi-match but + * didn't finish it off, so we go to the next line. + */ + + if (p == NULL) { + break; + } + + /* + * We've found a multi-line match. + */ + + if (extraLines > 0) { + extraLinesSearched = extraLines - 1; + } + } + } + + backwardsMatch: + if ((p - startOfLine) >= lastOffset) { + break; + } + + /* + * Remember the match. + */ + + matchOffset = p - startOfLine; + + if (searchSpecPtr->all && + !(*searchSpecPtr->foundMatchProc)(lineNum, + searchSpecPtr, lineInfo, theLine, matchOffset, + matchLength)) { + /* + * We reached the end of the search. + */ + + goto searchDone; + } + + if (!searchSpecPtr->overlap) { + if (searchSpecPtr->backwards) { + alreadySearchOffset = p - startOfLine; + if (firstNewLine != -1) { + break; + } else { + alreadySearchOffset -= matchLength; + } + } else { + firstOffset = p - startOfLine + matchLength; + if (firstOffset >= lastOffset) { + /* + * Now, we have to be careful not to find + * overlapping matches either on the same or + * following lines. Assume that if we did find + * something, it goes until the last extra line we + * added. + * + * We can break out of the loop, since we know no + * more will be found. + */ + + if (!searchSpecPtr->backwards) { + alreadySearchOffset = + firstOffset - lastFullLine; + break; + } + } + } + } else { + if (searchSpecPtr->backwards) { + alreadySearchOffset = p - startOfLine - 1; + if (alreadySearchOffset < 0) { + break; + } + } else { + firstOffset = p - startOfLine + + Tcl_UtfToUniChar(startOfLine+matchOffset,&ch); + } + } + } while (searchSpecPtr->all); + } else { + int maxExtraLines = 0; + int matches = 0; + int lastNonOverlap = -1; + + do { + Tcl_RegExpInfo info; + int match; + int lastFullLine = lastOffset; + + match = Tcl_RegExpExecObj(interp, regexp, theLine, + firstOffset, 1, (firstOffset>0 ? TCL_REG_NOTBOL : 0)); + if (match < 0) { + code = TCL_ERROR; + goto searchDone; + } + Tcl_RegExpGetInfo(regexp, &info); + + /* + * If we don't have a match, or if we do, but it extends to + * the end of the line, we must try to add more lines to get a + * full greedy match. + */ + + if (!match || + ((info.extendStart == info.matches[0].start) + && (info.matches[0].end == lastOffset-firstOffset))) { + int extraLines = 0; + int prevFullLine; + + /* + * If we find a match that overlaps more than one line, we + * will use this value to determine the first allowed + * starting offset for the following search (to avoid + * overlapping results). + */ + + int lastTotal = lastOffset; + + if ((lastBackwardsLineMatch != -1) + && (lastBackwardsLineMatch == (lineNum + 1))) { + lastNonOverlap = lastTotal; + } + + if (info.extendStart < 0) { + /* + * No multi-line match is possible. + */ + + break; + } + + /* + * We may be able to match if given more text. The + * following 'while' block handles multi-line regexp + * searches. + */ + + while (1) { + prevFullLine = lastTotal; + + /* + * Move firstOffset to first possible start. + */ + + if (!match) { + firstOffset += info.extendStart; + } + if (firstOffset >= lastOffset) { + /* + * We're being told that the only possible new + * match is starting after the end of the line. + * But, that is the next line which we will handle + * when we look at that line. + */ + + if (!match && !searchSpecPtr->backwards + && (firstOffset == 0)) { + extraLinesSearched = extraLines; + } + break; + } + + if (lineNum + extraLines >= searchSpecPtr->numLines) { + break; + } + + /* + * Add next line, provided we haven't already done so. + */ + + if (extraLines > maxExtraLines) { + if ((*searchSpecPtr->addLineProc)(lineNum + + extraLines, searchSpecPtr, theLine, + &lastTotal, &extraLines) == NULL) { + /* + * There are no more acceptable lines, so we + * can say we have searched all of these. + */ + + if (!match && !searchSpecPtr->backwards) { + extraLinesSearched = extraLines; + } + break; + } + + maxExtraLines = extraLines; + if ((lastBackwardsLineMatch != -1) + && (lastBackwardsLineMatch + == (lineNum + extraLines + 1))) { + lastNonOverlap = lastTotal; + } + } + + match = Tcl_RegExpExecObj(interp, regexp, theLine, + firstOffset, 1, + ((firstOffset > 0) ? TCL_REG_NOTBOL : 0)); + if (match < 0) { + code = TCL_ERROR; + goto searchDone; + } + Tcl_RegExpGetInfo(regexp, &info); + + /* + * Unfortunately there are bugs in Tcl's regexp + * library, which tells us that info.extendStart is + * zero when it should not be (should be -1), which + * makes our task a bit more complicated here. We + * check if there was a match, and the end of the + * match leaves an entire extra line unmatched, then + * we stop searching. Clearly it still might sometimes + * be possible to add more text and match again, but + * Tcl's regexp library doesn't tell us that. + * + * This means we often add and search one more line + * than might be necessary if Tcl were able to give us + * a correct value of info.extendStart under all + * circumstances. + */ + + if ((match && + firstOffset+info.matches[0].end != lastTotal && + firstOffset+info.matches[0].end < prevFullLine) + || info.extendStart < 0) { + break; + } + + /* + * If there is a match, but that match starts after + * the end of the first line, then we'll handle that + * next time around, when we're actually looking at + * that line. + */ + + if (match && (info.matches[0].start >= lastOffset)) { + break; + } + if (match && ((firstOffset + info.matches[0].end) + >= prevFullLine)) { + if (extraLines > 0) { + extraLinesSearched = extraLines - 1; + } + lastFullLine = prevFullLine; + } + + /* + * The prefix matches, so keep looking. + */ + + extraLines++; + } + + /* + * If we reach here with 'match == 1', we've found a + * multi-line match, which we will record in the code + * which follows directly else we started a multi-line + * match but didn't finish it off, so we go to the next + * line. + */ + + if (!match) { + /* + * Here is where we could perform an optimisation, + * since we have already retrieved the contents of the + * next line (perhaps many more), so we shouldn't + * really throw it all away and start again. This + * could be particularly important for complex regexp + * searches. + * + * This 'break' will take us to just before the + * 'nextLine:' below. + */ + + break; + } + + if (lastBackwardsLineMatch != -1) { + if ((lineNum + linesSearched + extraLinesSearched) + == lastBackwardsLineMatch) { + /* + * Possible overlap or inclusion. + */ + + int thisOffset = firstOffset + info.matches[0].end + - info.matches[0].start; + + if (lastNonOverlap != -1) { + /* + * Possible overlap or enclosure. + */ + + if (thisOffset-lastNonOverlap >= + lastBackwardsMatchOffset+matchLength){ + /* + * Totally encloses previous match, so + * forget the previous match. + */ + + lastBackwardsLineMatch = -1; + } else if ((thisOffset - lastNonOverlap) + > lastBackwardsMatchOffset) { + /* + * Overlap. Previous match is ok, and the + * current match is only ok if we are + * searching with -overlap. + */ + + if (searchSpecPtr->overlap) { + goto recordBackwardsMatch; + } else { + match = 0; + break; + } + } else { + /* + * No overlap, although the same line was + * reached. + */ + + goto recordBackwardsMatch; + } + } else { + /* + * No overlap. + */ + + goto recordBackwardsMatch; + } + } else if (lineNum+linesSearched+extraLinesSearched + < lastBackwardsLineMatch) { + /* + * No overlap. + */ + + goto recordBackwardsMatch; + } else { + /* + * Totally enclosed. + */ + + lastBackwardsLineMatch = -1; + } + } + + } else { + /* + * Matched in a single line. + */ + + if (lastBackwardsLineMatch != -1) { + recordBackwardsMatch: + (*searchSpecPtr->foundMatchProc)( + lastBackwardsLineMatch, searchSpecPtr, NULL, + NULL, lastBackwardsMatchOffset, matchLength); + lastBackwardsLineMatch = -1; + if (!searchSpecPtr->all) { + goto searchDone; + } + } + } + + firstOffset += info.matches[0].start; + if (firstOffset >= lastOffset) { + break; + } + + /* + * Update our local variables with the match, if we haven't + * yet found anything, or if we're doing '-all' or + * '-backwards' _and_ this match isn't fully enclosed in the + * previous match. + */ + + if (matchOffset == -1 || + ((searchSpecPtr->all || searchSpecPtr->backwards) + && ((firstOffset < matchOffset) + || ((firstOffset + info.matches[0].end + - info.matches[0].start) + > (matchOffset + matchLength))))) { + + matchOffset = firstOffset; + matchLength = info.matches[0].end - info.matches[0].start; + + if (searchSpecPtr->backwards) { + /* + * To get backwards searches in the correct order, we + * must store them away here. + */ + + if (matches == matchNum) { + /* + * We've run out of space in our normal store, so + * we must allocate space for these backwards + * matches on the heap. + */ + + int *newArray = (int *) + ckalloc(4 * matchNum * sizeof(int)); + memcpy(newArray, storeMatch, matchNum*sizeof(int)); + memcpy(newArray + 2*matchNum, storeLength, + matchNum * sizeof(int)); + if (storeMatch != smArray) { + ckfree((char *) storeMatch); + } + matchNum *= 2; + storeMatch = newArray; + storeLength = newArray + matchNum; + } + storeMatch[matches] = matchOffset; + storeLength[matches] = matchLength; + matches++; + } else { + /* + * Now actually record the match, but only if we are + * doing an '-all' search. + */ + + if (searchSpecPtr->all && + !(*searchSpecPtr->foundMatchProc)(lineNum, + searchSpecPtr, lineInfo, theLine, matchOffset, + matchLength)) { + /* + * We reached the end of the search. + */ + + goto searchDone; + } + } + + /* + * For forward matches, unless we allow overlaps, we move + * this on by the length of the current match so that we + * explicitly disallow overlapping matches. + */ + + if (matchLength > 0 && !searchSpecPtr->overlap + && !searchSpecPtr->backwards) { + firstOffset += matchLength; + if (firstOffset >= lastOffset) { + /* + * Now, we have to be careful not to find + * overlapping matches either on the same or + * following lines. Assume that if we did find + * something, it goes until the last extra line we + * added. + * + * We can break out of the loop, since we know no + * more will be found. + */ + + alreadySearchOffset = firstOffset - lastFullLine; + break; + } + + /* + * We'll add this on again just below. + */ + + firstOffset --; + } + } + + /* + * Move the starting point on, in case we are doing repeated + * or backwards searches (for the latter, we actually do + * repeated forward searches). + */ + + firstOffset++; + } while (searchSpecPtr->backwards || searchSpecPtr->all); + + if (matches > 0) { + /* + * Now we have all the matches in our array, but not stored + * with 'foundMatchProc' yet. + */ + + matches--; + matchOffset = storeMatch[matches]; + matchLength = storeLength[matches]; + while (--matches >= 0) { + if (lineNum == searchSpecPtr->stopLine) { + /* + * It appears as if a condition like: + * + * if (storeMatch[matches]<searchSpecPtr->stopOffset) + * break; + * + * might be needed here, but no test case has been + * found which would exercise such a problem. + */ + } + if (storeMatch[matches] + storeLength[matches] + >= matchOffset + matchLength) { + /* + * The new match totally encloses the previous one, so + * we overwrite the previous one. + */ + + matchOffset = storeMatch[matches]; + matchLength = storeLength[matches]; + continue; + } + if (!searchSpecPtr->overlap) { + if (storeMatch[matches] + storeLength[matches] + > matchOffset) { + continue; + } + } + (*searchSpecPtr->foundMatchProc)(lineNum, searchSpecPtr, + lineInfo, theLine, matchOffset, matchLength); + if (!searchSpecPtr->all) { + goto searchDone; + } + matchOffset = storeMatch[matches]; + matchLength = storeLength[matches]; + } + if (searchSpecPtr->all && matches > 0) { + /* + * We only need to do this for the '-all' case, because + * just below we will call the foundMatchProc for the + * non-all case. + */ + + (*searchSpecPtr->foundMatchProc)(lineNum, searchSpecPtr, + lineInfo, theLine, matchOffset, matchLength); + } else { + lastBackwardsLineMatch = lineNum; + lastBackwardsMatchOffset = matchOffset; + } + } + } + + /* + * If the 'all' flag is set, we will already have stored all matches, + * so we just proceed to the next line. + * + * If not, and there is a match we need to store that information and + * we are done. + */ + + if ((lastBackwardsLineMatch == -1) && (matchOffset >= 0) + && !searchSpecPtr->all) { + (*searchSpecPtr->foundMatchProc)(lineNum, searchSpecPtr, lineInfo, + theLine, matchOffset, matchLength); + goto searchDone; + } + + /* + * Go to the next (or previous) line; + */ + + nextLine: + linesSearched += extraLinesSearched; + + while (linesSearched-- > 0) { + /* + * If we have just completed the 'stopLine', we are done. + */ + + if (lineNum == searchSpecPtr->stopLine) { + goto searchDone; + } + + if (searchSpecPtr->backwards) { + lineNum--; + + if (lastBackwardsLineMatch != -1 + && ((lineNum < 0) + || (lineNum + 2 < lastBackwardsLineMatch))) { + (*searchSpecPtr->foundMatchProc)(lastBackwardsLineMatch, + searchSpecPtr, NULL, NULL, + lastBackwardsMatchOffset, matchLength); + lastBackwardsLineMatch = -1; + if (!searchSpecPtr->all) { + goto searchDone; + } + } + + if (lineNum < 0) { + lineNum = searchSpecPtr->numLines-1; + } + if (!searchSpecPtr->exact) { + /* + * The 'exact' search loops above are designed to give us + * an accurate picture of the number of lines which we can + * skip here. For 'regexp' searches, on the other hand, + * which can match potentially variable lengths, we cannot + * skip multiple lines when searching backwards. Therefore + * we only allow one line to be skipped here. + */ + + break; + } + } else { + lineNum++; + if (lineNum >= searchSpecPtr->numLines) { + lineNum = 0; + } + } + if (lineNum == searchSpecPtr->startLine && linesSearched > 0) { + /* + * We've just searched all the way round and have gone right + * through the start line without finding anything in the last + * attempt. + */ + + break; + } + } + + Tcl_SetObjLength(theLine, 0); } + searchDone: - if (textPtr->isDirty == 0 || oldDirtyFlag == 0) { - GenerateModifiedEvent(textPtr); + if (lastBackwardsLineMatch != -1) { + (*searchSpecPtr->foundMatchProc)(lastBackwardsLineMatch, searchSpecPtr, + NULL, NULL, lastBackwardsMatchOffset, matchLength); } + + /* + * Free up the cached line and pattern. + */ + + Tcl_DecrRefCount(theLine); + Tcl_DecrRefCount(patObj); + + /* + * Free up any extra space we allocated. + */ + + if (storeMatch != smArray) { + ckfree((char *) storeMatch); + } + + return code; } + +/* + *---------------------------------------------------------------------- + * + * GetLineStartEnd - + * + * Converts an internal TkTextLine ptr into a Tcl string obj containing + * the line number. (Handler for the 'line' configuration option type.) + * + * Results: + * Tcl_Obj containing the string representation of the line value. + * + * Side effects: + * Creates a new Tcl_Obj. + * + *---------------------------------------------------------------------- + */ + +static Tcl_Obj * +GetLineStartEnd( + ClientData clientData, + Tk_Window tkwin, + char *recordPtr, /* Pointer to widget record. */ + int internalOffset) /* Offset within *recordPtr containing the + * line value. */ +{ + TkTextLine *linePtr = *(TkTextLine **)(recordPtr + internalOffset); + + if (linePtr == NULL) { + return Tcl_NewObj(); + } else { + return Tcl_NewIntObj(1+TkBTreeLinesTo(NULL, linePtr)); + } +} + +/* + *---------------------------------------------------------------------- + * + * SetLineStartEnd -- + * + * Converts a Tcl_Obj representing a widget's (start or end) line into a + * TkTextLine* value. (Handler for the 'line' configuration option type.) + * + * Results: + * Standard Tcl result. + * + * Side effects: + * May store the TkTextLine* value into the internal representation + * pointer. May change the pointer to the Tcl_Obj to NULL to indicate + * that the specified string was empty and that is acceptable. + * + *---------------------------------------------------------------------- + */ + +static int +SetLineStartEnd( + ClientData clientData, + Tcl_Interp *interp, /* Current interp; may be used for errors. */ + Tk_Window tkwin, /* Window for which option is being set. */ + Tcl_Obj **value, /* Pointer to the pointer to the value object. + * We use a pointer to the pointer because we + * may need to return a value (NULL). */ + char *recordPtr, /* Pointer to storage for the widget record. */ + int internalOffset, /* Offset within *recordPtr at which the + * internal value is to be stored. */ + char *oldInternalPtr, /* Pointer to storage for the old value. */ + int flags) /* Flags for the option, set Tk_SetOptions. */ +{ + TkTextLine *linePtr = NULL; + char *internalPtr; + TkText *textPtr = (TkText *) recordPtr; + + if (internalOffset >= 0) { + internalPtr = recordPtr + internalOffset; + } else { + internalPtr = NULL; + } + + if (flags & TK_OPTION_NULL_OK && ObjectIsEmpty(*value)) { + *value = NULL; + } else { + int line; + + if (Tcl_GetIntFromObj(interp, *value, &line) != TCL_OK) { + return TCL_ERROR; + } + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, NULL, line-1); + } + + if (internalPtr != NULL) { + *((TkTextLine **) oldInternalPtr) = *((TkTextLine **) internalPtr); + *((TkTextLine **) internalPtr) = linePtr; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * RestoreLineStartEnd -- + * + * Restore a line option value from a saved value. (Handler for the + * 'line' configuration option type.) + * + * Results: + * None. + * + * Side effects: + * Restores the old value. + * + *---------------------------------------------------------------------- + */ + +static void +RestoreLineStartEnd( + ClientData clientData, + Tk_Window tkwin, + char *internalPtr, /* Pointer to storage for value. */ + char *oldInternalPtr) /* Pointer to old value. */ +{ + *(TkTextLine **)internalPtr = *(TkTextLine **)oldInternalPtr; +} + +/* + *---------------------------------------------------------------------- + * + * ObjectIsEmpty -- + * + * This function tests whether the string value of an object is empty. + * + * Results: + * The return value is 1 if the string value of objPtr has length zero, + * and 0 otherwise. + * + * Side effects: + * May cause object shimmering, since this function can force a + * conversion to a string object. + * + *---------------------------------------------------------------------- + */ + +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); + } + Tcl_GetStringFromObj(objPtr, &length); + return (length == 0); +} + +/* + *---------------------------------------------------------------------- + * + * TkpTesttextCmd -- + * + * This function implements the "testtext" command. It provides a set of + * functions for testing text widgets and the associated functions in + * tkText*.c. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Depends on option; see below. + * + *---------------------------------------------------------------------- + */ + +int +TkpTesttextCmd( + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ +{ + TkText *textPtr; + size_t len; + int lineIndex, byteIndex, byteOffset; + TkTextIndex index; + char buf[64]; + Tcl_CmdInfo info; + + if (argc < 3) { + return TCL_ERROR; + } + + if (Tcl_GetCommandInfo(interp, argv[1], &info) == 0) { + return TCL_ERROR; + } + if (info.isNativeObjectProc) { + textPtr = (TkText *) info.objClientData; + } else { + textPtr = (TkText *) info.clientData; + } + len = strlen(argv[2]); + if (strncmp(argv[2], "byteindex", len) == 0) { + if (argc != 5) { + return TCL_ERROR; + } + lineIndex = atoi(argv[3]) - 1; + byteIndex = atoi(argv[4]); + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, lineIndex, + byteIndex, &index); + } else if (strncmp(argv[2], "forwbytes", len) == 0) { + if (argc != 5) { + return TCL_ERROR; + } + if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + return TCL_ERROR; + } + byteOffset = atoi(argv[4]); + TkTextIndexForwBytes(textPtr, &index, byteOffset, &index); + } else if (strncmp(argv[2], "backbytes", len) == 0) { + if (argc != 5) { + return TCL_ERROR; + } + if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + return TCL_ERROR; + } + byteOffset = atoi(argv[4]); + TkTextIndexBackBytes(textPtr, &index, byteOffset, &index); + } else { + return TCL_ERROR; + } + + TkTextSetMark(textPtr, "insert", &index); + TkTextPrintIndex(textPtr, &index, buf); + sprintf(buf + strlen(buf), " %d", index.byteIndex); + Tcl_AppendResult(interp, buf, NULL); + + return TCL_OK; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkText.h b/generic/tkText.h index 6331735..4ffdc8a 100644 --- a/generic/tkText.h +++ b/generic/tkText.h @@ -1,14 +1,13 @@ /* * tkText.h -- * - * Declarations shared among the files that implement text - * widgets. + * Declarations shared among the files that implement text widgets. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKTEXT @@ -28,122 +27,142 @@ #endif /* - * Opaque types for structures whose guts are only needed by a single - * file: + * Opaque types for structures whose guts are only needed by a single file. */ typedef struct TkTextBTree_ *TkTextBTree; /* - * The data structure below defines a single line of text (from newline - * to newline, not necessarily what appears on one line of the screen). + * The data structure below defines a single logical line of text (from + * newline to newline, not necessarily what appears on one display line of the + * screen). */ typedef struct TkTextLine { - struct Node *parentPtr; /* Pointer to parent node containing - * line. */ - struct TkTextLine *nextPtr; /* Next in linked list of lines with - * same parent node in B-tree. NULL - * means end of list. */ - struct TkTextSegment *segPtr; /* First in ordered list of segments - * that make up the line. */ + struct Node *parentPtr; /* Pointer to parent node containing line. */ + struct TkTextLine *nextPtr; /* Next in linked list of lines with same + * parent node in B-tree. NULL means end of + * list. */ + struct TkTextSegment *segPtr; + /* First in ordered list of segments that make + * up the line. */ + int *pixels; /* Array containing two integers for each + * referring text widget. The first of these + * is the number of vertical pixels taken up + * by this line, whether currently displayed + * or not. This number is only updated + * asychronously. The second of these is the + * last epoch at which the pixel height was + * recalculated. */ } TkTextLine; /* * ----------------------------------------------------------------------- * Segments: each line is divided into one or more segments, where each - * segment is one of several things, such as a group of characters, a - * tag toggle, a mark, or an embedded widget. Each segment starts with - * a standard header followed by a body that varies from type to type. + * segment is one of several things, such as a group of characters, a tag + * toggle, a mark, or an embedded widget. Each segment starts with a standard + * header followed by a body that varies from type to type. * ----------------------------------------------------------------------- */ /* - * The data structure below defines the body of a segment that represents - * a tag toggle. There is one of these structures at both the beginning - * and end of each tagged range. + * The data structure below defines the body of a segment that represents a + * tag toggle. There is one of these structures at both the beginning and end + * of each tagged range. */ typedef struct TkTextToggle { - struct TkTextTag *tagPtr; /* Tag that starts or ends here. */ - int inNodeCounts; /* 1 means this toggle has been - * accounted for in node toggle - * counts; 0 means it hasn't, yet. */ + struct TkTextTag *tagPtr; /* Tag that starts or ends here. */ + int inNodeCounts; /* 1 means this toggle has been accounted for + * in node toggle counts; 0 means it hasn't, + * yet. */ } TkTextToggle; /* - * The data structure below defines line segments that represent - * marks. There is one of these for each mark in the text. + * The data structure below defines line segments that represent marks. There + * is one of these for each mark in the text. */ typedef struct TkTextMark { - struct TkText *textPtr; /* Overall information about text - * widget. */ - TkTextLine *linePtr; /* Line structure that contains the - * segment. */ - Tcl_HashEntry *hPtr; /* Pointer to hash table entry for mark - * (in textPtr->markTable). */ + struct TkText *textPtr; /* Overall information about text widget. */ + TkTextLine *linePtr; /* Line structure that contains the + * segment. */ + Tcl_HashEntry *hPtr; /* Pointer to hash table entry for mark (in + * sharedTextPtr->markTable). */ } TkTextMark; /* * A structure of the following type holds information for each window - * embedded in a text widget. This information is only used by the - * file tkTextWind.c + * embedded in a text widget. This information is only used by the file + * tkTextWind.c */ +typedef struct TkTextEmbWindowClient { + struct TkText *textPtr; /* Information about the overall text + * widget. */ + Tk_Window tkwin; /* Window for this segment. NULL means that + * the window hasn't been created yet. */ + int chunkCount; /* Number of display chunks that refer to this + * window. */ + int displayed; /* Non-zero means that the window has been + * displayed on the screen recently. */ + struct TkTextSegment *parent; + struct TkTextEmbWindowClient *next; +} TkTextEmbWindowClient; + typedef struct TkTextEmbWindow { - struct TkText *textPtr; /* Information about the overall text - * widget. */ - TkTextLine *linePtr; /* Line structure that contains this - * window. */ - Tk_Window tkwin; /* Window for this segment. NULL - * means that the window hasn't - * been created yet. */ - char *create; /* Script to create window on-demand. - * NULL means no such script. - * Malloc-ed. */ - int align; /* How to align window in vertical - * space. See definitions in - * tkTextWind.c. */ - int padX, padY; /* Padding to leave around each side - * of window, in pixels. */ - int stretch; /* Should window stretch to fill - * vertical space of line (except for - * pady)? 0 or 1. */ - int chunkCount; /* Number of display chunks that - * refer to this window. */ - int displayed; /* Non-zero means that the window - * has been displayed on the screen - * recently. */ + struct TkSharedText *sharedTextPtr; + /* Information about the shared portion of the + * text widget. */ + Tk_Window tkwin; /* Window for this segment. This is just a + * temporary value, copied from 'clients', to + * make option table updating easier. NULL + * means that the window hasn't been created + * yet. */ + TkTextLine *linePtr; /* Line structure that contains this + * window. */ + char *create; /* Script to create window on-demand. NULL + * means no such script. Malloc-ed. */ + int align; /* How to align window in vertical space. See + * definitions in tkTextWind.c. */ + int padX, padY; /* Padding to leave around each side of + * window, in pixels. */ + int stretch; /* Should window stretch to fill vertical + * space of line (except for pady)? 0 or 1. */ + Tk_OptionTable optionTable; /* Token representing the configuration + * specifications. */ + TkTextEmbWindowClient *clients; + /* Linked list of peer-widget specific + * information for this embedded window. */ } TkTextEmbWindow; /* - * A structure of the following type holds information for each image - * embedded in a text widget. This information is only used by the - * file tkTextImage.c + * A structure of the following type holds information for each image embedded + * in a text widget. This information is only used by the file tkTextImage.c */ typedef struct TkTextEmbImage { - struct TkText *textPtr; /* Information about the overall text - * widget. */ - TkTextLine *linePtr; /* Line structure that contains this - * image. */ - char *imageString; /* Name of the image for this segment */ - char *imageName; /* Name used by text widget to identify - * this image. May be unique-ified */ - char *name; /* Name used in the hash table. - * used by "image names" to identify - * this instance of the image */ - Tk_Image image; /* Image for this segment. NULL - * means that the image hasn't - * been created yet. */ - int align; /* How to align image in vertical - * space. See definitions in - * tkTextImage.c. */ - int padX, padY; /* Padding to leave around each side - * of image, in pixels. */ - int chunkCount; /* Number of display chunks that - * refer to this image. */ + struct TkSharedText *sharedTextPtr; + /* Information about the shared portion of the + * text widget. This is used when the image + * changes or is deleted. */ + TkTextLine *linePtr; /* Line structure that contains this image. */ + char *imageString; /* Name of the image for this segment. */ + char *imageName; /* Name used by text widget to identify this + * image. May be unique-ified. */ + char *name; /* Name used in the hash table. Used by + * "image names" to identify this instance of + * the image. */ + Tk_Image image; /* Image for this segment. NULL means that the + * image hasn't been created yet. */ + int align; /* How to align image in vertical space. See + * definitions in tkTextImage.c. */ + int padX, padY; /* Padding to leave around each side of image, + * in pixels. */ + int chunkCount; /* Number of display chunks that refer to this + * image. */ + Tk_OptionTable optionTable; /* Token representing the configuration + * specifications. */ } TkTextEmbImage; /* @@ -151,40 +170,43 @@ typedef struct TkTextEmbImage { */ typedef struct TkTextSegment { - struct Tk_SegType *typePtr; /* Pointer to record describing - * segment's type. */ - struct TkTextSegment *nextPtr; /* Next in list of segments for this - * line, or NULL for end of list. */ - int size; /* Size of this segment (# of bytes - * of index space it occupies). */ + const struct Tk_SegType *typePtr; + /* Pointer to record describing segment's + * type. */ + struct TkTextSegment *nextPtr; + /* Next in list of segments for this line, or + * NULL for end of list. */ + int size; /* Size of this segment (# of bytes of index + * space it occupies). */ union { - char chars[4]; /* Characters that make up character - * info. Actual length varies to - * hold as many characters as needed.*/ - TkTextToggle toggle; /* Information about tag toggle. */ - TkTextMark mark; /* Information about mark. */ - TkTextEmbWindow ew; /* Information about embedded - * window. */ - TkTextEmbImage ei; /* Information about embedded - * image. */ + char chars[4]; /* Characters that make up character info. + * Actual length varies to hold as many + * characters as needed.*/ + TkTextToggle toggle; /* Information about tag toggle. */ + TkTextMark mark; /* Information about mark. */ + TkTextEmbWindow ew; /* Information about embedded window. */ + TkTextEmbImage ei; /* Information about embedded image. */ } body; } TkTextSegment; /* - * Data structures of the type defined below are used during the - * execution of Tcl commands to keep track of various interesting - * places in a text. An index is only valid up until the next - * modification to the character structure of the b-tree so they - * can't be retained across Tcl commands. However, mods to marks - * or tags don't invalidate indices. + * Data structures of the type defined below are used during the execution of + * Tcl commands to keep track of various interesting places in a text. An + * index is only valid up until the next modification to the character + * structure of the b-tree so they can't be retained across Tcl commands. + * However, mods to marks or tags don't invalidate indices. */ typedef struct TkTextIndex { - TkTextBTree tree; /* Tree containing desired position. */ - TkTextLine *linePtr; /* Pointer to line containing position - * of interest. */ - int byteIndex; /* Index within line of desired - * character (0 means first one). */ + TkTextBTree tree; /* Tree containing desired position. */ + TkTextLine *linePtr; /* Pointer to line containing position of + * interest. */ + int byteIndex; /* Index within line of desired character (0 + * means first one). */ + struct TkText *textPtr; /* May be NULL, but otherwise the text widget + * with which this index is associated. If not + * NULL, then we have a refCount on the + * widget. */ } TkTextIndex; /* @@ -193,204 +215,209 @@ typedef struct TkTextIndex { typedef struct TkTextDispChunk TkTextDispChunk; -typedef void Tk_ChunkDisplayProc _ANSI_ARGS_(( +typedef void Tk_ChunkDisplayProc(struct TkText *textPtr, TkTextDispChunk *chunkPtr, int x, int y, int height, int baseline, Display *display, - Drawable dst, int screenY)); -typedef void Tk_ChunkUndisplayProc _ANSI_ARGS_(( - struct TkText *textPtr, - TkTextDispChunk *chunkPtr)); -typedef int Tk_ChunkMeasureProc _ANSI_ARGS_(( - TkTextDispChunk *chunkPtr, int x)); -typedef void Tk_ChunkBboxProc _ANSI_ARGS_(( + Drawable dst, int screenY); +typedef void Tk_ChunkUndisplayProc(struct TkText *textPtr, + TkTextDispChunk *chunkPtr); +typedef int Tk_ChunkMeasureProc(TkTextDispChunk *chunkPtr, int x); +typedef void Tk_ChunkBboxProc(struct TkText *textPtr, TkTextDispChunk *chunkPtr, int index, int y, int lineHeight, int baseline, int *xPtr, - int *yPtr, int *widthPtr, int *heightPtr)); + int *yPtr, int *widthPtr, int *heightPtr); /* - * The structure below represents a chunk of stuff that is displayed - * together on the screen. This structure is allocated and freed by - * generic display code but most of its fields are filled in by - * segment-type-specific code. + * The structure below represents a chunk of stuff that is displayed together + * on the screen. This structure is allocated and freed by generic display + * code but most of its fields are filled in by segment-type-specific code. */ struct TkTextDispChunk { /* - * The fields below are set by the type-independent code before - * calling the segment-type-specific layoutProc. They should not - * be modified by segment-type-specific code. + * The fields below are set by the type-independent code before calling + * the segment-type-specific layoutProc. They should not be modified by + * segment-type-specific code. */ - int x; /* X position of chunk, in pixels. - * This position is measured from the - * left edge of the logical line, - * not from the left edge of the - * window (i.e. it doesn't change - * under horizontal scrolling). */ - struct TkTextDispChunk *nextPtr; /* Next chunk in the display line - * or NULL for the end of the list. */ - struct TextStyle *stylePtr; /* Display information, known only - * to tkTextDisp.c. */ + int x; /* X position of chunk, in pixels. This + * position is measured from the left edge of + * the logical line, not from the left edge of + * the window (i.e. it doesn't change under + * horizontal scrolling). */ + struct TkTextDispChunk *nextPtr; + /* Next chunk in the display line or NULL for + * the end of the list. */ + struct TextStyle *stylePtr; /* Display information, known only to + * tkTextDisp.c. */ /* - * The fields below are set by the layoutProc that creates the - * chunk. + * The fields below are set by the layoutProc that creates the chunk. */ - Tk_ChunkDisplayProc *displayProc; /* Procedure to invoke to draw this - * chunk on the display or an - * off-screen pixmap. */ + Tk_ChunkDisplayProc *displayProc; + /* Procedure to invoke to draw this chunk on + * the display or an off-screen pixmap. */ Tk_ChunkUndisplayProc *undisplayProc; - /* Procedure to invoke when segment - * ceases to be displayed on screen - * anymore. */ - Tk_ChunkMeasureProc *measureProc; /* Procedure to find character under - * a given x-location. */ - Tk_ChunkBboxProc *bboxProc; /* Procedure to find bounding box - * of character in chunk. */ - int numBytes; /* Number of bytes that will be - * displayed in the chunk. */ - int minAscent; /* Minimum space above the baseline - * needed by this chunk. */ - int minDescent; /* Minimum space below the baseline - * needed by this chunk. */ - int minHeight; /* Minimum total line height needed - * by this chunk. */ - int width; /* Width of this chunk, in pixels. - * Initially set by chunk-specific - * code, but may be increased to - * include tab or extra space at end - * of line. */ - int breakIndex; /* Index within chunk of last - * acceptable position for a line - * (break just before this byte index). - * <= 0 means don't break during or - * immediately after this chunk. */ - ClientData clientData; /* Additional information for use - * of displayProc and undisplayProc. */ + /* Procedure to invoke when segment ceases to + * be displayed on screen anymore. */ + Tk_ChunkMeasureProc *measureProc; + /* Procedure to find character under a given + * x-location. */ + Tk_ChunkBboxProc *bboxProc; /* Procedure to find bounding box of character + * in chunk. */ + int numBytes; /* Number of bytes that will be displayed in + * the chunk. */ + int minAscent; /* Minimum space above the baseline needed by + * this chunk. */ + int minDescent; /* Minimum space below the baseline needed by + * this chunk. */ + int minHeight; /* Minimum total line height needed by this + * chunk. */ + int width; /* Width of this chunk, in pixels. Initially + * set by chunk-specific code, but may be + * increased to include tab or extra space at + * end of line. */ + int breakIndex; /* Index within chunk of last acceptable + * position for a line (break just before this + * byte index). <= 0 means don't break during + * or immediately after this chunk. */ + ClientData clientData; /* Additional information for use of + * displayProc and undisplayProc. */ }; /* - * One data structure of the following type is used for each tag in a - * text widget. These structures are kept in textPtr->tagTable and - * referred to in other structures. + * One data structure of the following type is used for each tag in a text + * widget. These structures are kept in sharedTextPtr->tagTable and referred + * to in other structures. */ -typedef enum { TEXT_WRAPMODE_NULL, TEXT_WRAPMODE_NONE, - TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_WORD +typedef enum { + TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, + TEXT_WRAPMODE_NULL } TkWrapMode; -EXTERN Tk_CustomOption TkTextWrapModeOption; - typedef struct TkTextTag { - char *name; /* Name of this tag. This field is actually - * a pointer to the key from the entry in - * textPtr->tagTable, so it needn't be freed - * explicitly. */ - int priority; /* Priority of this tag within widget. 0 - * means lowest priority. Exactly one tag - * has each integer value between 0 and - * numTags-1. */ - struct Node *tagRootPtr; /* Pointer into the B-Tree at the lowest - * node that completely dominates the ranges - * of text occupied by the tag. At this - * node there is no information about the - * tag. One or more children of the node - * do contain information about the tag. */ - int toggleCount; /* Total number of tag toggles */ + const char *name; /* Name of this tag. This field is actually a + * pointer to the key from the entry in + * sharedTextPtr->tagTable, so it needn't be + * freed explicitly. For 'sel' tags this is + * just a static string, so again need not be + * freed. */ + const struct TkText *textPtr; + /* If non-NULL, then this tag only applies to + * the given text widget (when there are peer + * widgets). */ + int priority; /* Priority of this tag within widget. 0 means + * lowest priority. Exactly one tag has each + * integer value between 0 and numTags-1. */ + struct Node *tagRootPtr; /* Pointer into the B-Tree at the lowest node + * that completely dominates the ranges of + * text occupied by the tag. At this node + * there is no information about the tag. One + * or more children of the node do contain + * information about the tag. */ + int toggleCount; /* Total number of tag toggles. */ /* - * Information for displaying text with this tag. The information - * belows acts as an override on information specified by lower-priority - * tags. If no value is specified, then the next-lower-priority tag - * on the text determins the value. The text widget itself provides - * defaults if no tag specifies an override. + * Information for displaying text with this tag. The information belows + * acts as an override on information specified by lower-priority tags. + * If no value is specified, then the next-lower-priority tag on the text + * determins the value. The text widget itself provides defaults if no tag + * specifies an override. */ - Tk_3DBorder border; /* Used for drawing background. NULL means - * no value specified here. */ - char *bdString; /* -borderwidth option string (malloc-ed). - * NULL means option not specified. */ + Tk_3DBorder border; /* Used for drawing background. NULL means no + * value specified here. */ int borderWidth; /* Width of 3-D border for background. */ - char *reliefString; /* -relief option string (malloc-ed). - * NULL means option not specified. */ + Tcl_Obj *borderWidthPtr; /* Width of 3-D border for background. */ + char *reliefString; /* -relief option string (malloc-ed). NULL + * means option not specified. */ int relief; /* 3-D relief for background. */ - Pixmap bgStipple; /* Stipple bitmap for background. None - * means no value specified here. */ - XColor *fgColor; /* Foreground color for text. NULL means - * no value specified here. */ - Tk_Font tkfont; /* Font for displaying text. NULL means + Pixmap bgStipple; /* Stipple bitmap for background. None means * no value specified here. */ + XColor *fgColor; /* Foreground color for text. NULL means no + * value specified here. */ + Tk_Font tkfont; /* Font for displaying text. NULL means no + * value specified here. */ Pixmap fgStipple; /* Stipple bitmap for text and other - * foreground stuff. None means no value + * foreground stuff. None means no value * specified here.*/ - char *justifyString; /* -justify option string (malloc-ed). - * NULL means option not specified. */ + char *justifyString; /* -justify option string (malloc-ed). NULL + * means option not specified. */ Tk_Justify justify; /* How to justify text: TK_JUSTIFY_LEFT, * TK_JUSTIFY_RIGHT, or TK_JUSTIFY_CENTER. * Only valid if justifyString is non-NULL. */ - char *lMargin1String; /* -lmargin1 option string (malloc-ed). - * NULL means option not specified. */ - int lMargin1; /* Left margin for first display line of - * each text line, in pixels. Only valid - * if lMargin1String is non-NULL. */ - char *lMargin2String; /* -lmargin2 option string (malloc-ed). - * NULL means option not specified. */ + char *lMargin1String; /* -lmargin1 option string (malloc-ed). NULL + * means option not specified. */ + int lMargin1; /* Left margin for first display line of each + * text line, in pixels. Only valid if + * lMargin1String is non-NULL. */ + char *lMargin2String; /* -lmargin2 option string (malloc-ed). NULL + * means option not specified. */ int lMargin2; /* Left margin for second and later display - * lines of each text line, in pixels. Only + * lines of each text line, in pixels. Only * valid if lMargin2String is non-NULL. */ - char *offsetString; /* -offset option string (malloc-ed). - * NULL means option not specified. */ + char *offsetString; /* -offset option string (malloc-ed). NULL + * means option not specified. */ int offset; /* Vertical offset of text's baseline from - * baseline of line. Used for superscripts - * and subscripts. Only valid if - * offsetString is non-NULL. */ - char *overstrikeString; /* -overstrike option string (malloc-ed). - * NULL means option not specified. */ + * baseline of line. Used for superscripts and + * subscripts. Only valid if offsetString is + * non-NULL. */ + char *overstrikeString; /* -overstrike option string (malloc-ed). NULL + * means option not specified. */ int overstrike; /* Non-zero means draw horizontal line through - * middle of text. Only valid if + * middle of text. Only valid if * overstrikeString is non-NULL. */ - char *rMarginString; /* -rmargin option string (malloc-ed). - * NULL means option not specified. */ - int rMargin; /* Right margin for text, in pixels. Only + 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. */ - char *spacing1String; /* -spacing1 option string (malloc-ed). - * NULL means option not specified. */ - int spacing1; /* Extra spacing above first display - * line for text line. Only valid if - * spacing1String is non-NULL. */ - char *spacing2String; /* -spacing2 option string (malloc-ed). - * NULL means option not specified. */ - int spacing2; /* Extra spacing between display - * lines for the same text line. Only valid - * if spacing2String is non-NULL. */ - char *spacing3String; /* -spacing2 option string (malloc-ed). - * NULL means option not specified. */ - int spacing3; /* Extra spacing below last display - * line for text line. Only valid if - * spacing3String is non-NULL. */ - char *tabString; /* -tabs option string (malloc-ed). - * NULL means option not specified. */ + char *spacing1String; /* -spacing1 option string (malloc-ed). NULL + * means option not specified. */ + int spacing1; /* Extra spacing above first display line for + * text line. Only valid if spacing1String is + * non-NULL. */ + char *spacing2String; /* -spacing2 option string (malloc-ed). NULL + * means option not specified. */ + int spacing2; /* Extra spacing between display lines for the + * same text line. Only valid if + * spacing2String is non-NULL. */ + char *spacing3String; /* -spacing2 option string (malloc-ed). NULL + * means option not specified. */ + int spacing3; /* Extra spacing below last display line for + * text line. Only valid if spacing3String is + * non-NULL. */ + Tcl_Obj *tabStringPtr; /* -tabs option string. NULL means option not + * specified. */ struct TkTextTabArray *tabArrayPtr; - /* Info about tabs for tag (malloc-ed) - * or NULL. Corresponds to tabString. */ - char *underlineString; /* -underline option string (malloc-ed). - * NULL means option not specified. */ + /* Info about tabs for tag (malloc-ed) or + * NULL. Corresponds to tabString. */ + int tabStyle; /* One of TABULAR or WORDPROCESSOR or NONE (if + * not specified). */ + char *underlineString; /* -underline option string (malloc-ed). NULL + * means option not specified. */ int underline; /* Non-zero means draw underline underneath - * text. Only valid if underlineString is + * text. Only valid if underlineString is * non-NULL. */ TkWrapMode wrapMode; /* How to handle wrap-around for this tag. * Must be TEXT_WRAPMODE_CHAR, - * TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, - * or TEXT_WRAPMODE_NULL to use wrapmode for + * TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD, or + * TEXT_WRAPMODE_NULL to use wrapmode for * whole widget. */ - char *elideString; /* -elide option string (malloc-ed). - * NULL means option not specified. */ + char *elideString; /* -elide option string (malloc-ed). NULL + * means option not specified. */ int elide; /* Non-zero means that data under this tag * should not be displayed. */ int affectsDisplay; /* Non-zero means that this tag affects the * way information is displayed on the screen * (so need to redisplay if tag changes). */ + Tk_OptionTable optionTable; /* Token representing the configuration + * specifications. */ + int affectsDisplayGeometry; /* Non-zero means that this tag affects the + * size with which information is displayed on + * the screen (so need to recalculate line + * dimensions if tag changes). */ } TkTextTag; #define TK_TAG_AFFECTS_DISPLAY 0x1 @@ -399,66 +426,81 @@ typedef struct TkTextTag { #define TK_TAG_OFFSET 0x10 /* - * The data structure below is used for searching a B-tree for transitions - * on a single tag (or for all tag transitions). No code outside of - * tkTextBTree.c should ever modify any of the fields in these structures, - * but it's OK to use them for read-only information. + * The data structure below is used for searching a B-tree for transitions on + * a single tag (or for all tag transitions). No code outside of tkTextBTree.c + * should ever modify any of the fields in these structures, but it's OK to + * use them for read-only information. */ typedef struct TkTextSearch { - TkTextIndex curIndex; /* Position of last tag transition - * returned by TkBTreeNextTag, or - * index of start of segment - * containing starting position for - * search if TkBTreeNextTag hasn't - * been called yet, or same as - * stopIndex if search is over. */ - TkTextSegment *segPtr; /* Actual tag segment returned by last - * call to TkBTreeNextTag, or NULL if - * TkBTreeNextTag hasn't returned - * anything yet. */ - TkTextSegment *nextPtr; /* Where to resume search in next - * call to TkBTreeNextTag. */ - TkTextSegment *lastPtr; /* Stop search before just before - * considering this segment. */ - TkTextTag *tagPtr; /* Tag to search for (or tag found, if - * allTags is non-zero). */ - int linesLeft; /* Lines left to search (including - * curIndex and stopIndex). When - * this becomes <= 0 the search is - * over. */ - int allTags; /* Non-zero means ignore tag check: - * search for transitions on all - * tags. */ + TkTextIndex curIndex; /* Position of last tag transition returned by + * TkBTreeNextTag, or index of start of + * segment containing starting position for + * search if TkBTreeNextTag hasn't been called + * yet, or same as stopIndex if search is + * over. */ + TkTextSegment *segPtr; /* Actual tag segment returned by last call to + * TkBTreeNextTag, or NULL if TkBTreeNextTag + * hasn't returned anything yet. */ + TkTextSegment *nextPtr; /* Where to resume search in next call to + * TkBTreeNextTag. */ + TkTextSegment *lastPtr; /* Stop search before just before considering + * this segment. */ + TkTextTag *tagPtr; /* Tag to search for (or tag found, if allTags + * is non-zero). */ + int linesLeft; /* Lines left to search (including curIndex + * and stopIndex). When this becomes <= 0 the + * search is over. */ + int allTags; /* Non-zero means ignore tag check: search for + * transitions on all tags. */ } TkTextSearch; /* - * The following data structure describes a single tab stop. + * The following data structure describes a single tab stop. It must be kept + * in sync with the 'tabOptionStrings' array in the function 'TkTextGetTabs' */ typedef enum {LEFT, RIGHT, CENTER, NUMERIC} TkTextTabAlign; +/* + * The following are the supported styles of tabbing, used for the -tabstyle + * option of the text widget. The last element is only used for tag options. + */ + +typedef enum { + TK_TEXT_TABSTYLE_TABULAR, + TK_TEXT_TABSTYLE_WORDPROCESSOR, + TK_TEXT_TABSTYLE_NONE +} TkTextTabStyle; + typedef struct TkTextTab { - int location; /* Offset in pixels of this tab stop - * from the left margin (lmargin2) of - * the text. */ - TkTextTabAlign alignment; /* Where the tab stop appears relative - * to the text. */ + int location; /* Offset in pixels of this tab stop from the + * left margin (lmargin2) of the text. */ + TkTextTabAlign alignment; /* Where the tab stop appears relative to the + * text. */ } TkTextTab; typedef struct TkTextTabArray { - int numTabs; /* Number of tab stops. */ - TkTextTab tabs[1]; /* Array of tabs. The actual size - * will be numTabs. THIS FIELD MUST - * BE THE LAST IN THE STRUCTURE. */ + int numTabs; /* Number of tab stops. */ + double lastTab; /* The accurate fractional pixel position of + * the last tab. */ + double tabIncrement; /* The accurate fractional pixel increment + * between interpolated tabs we have to create + * when we exceed numTabs. */ + TkTextTab tabs[1]; /* Array of tabs. The actual size will be + * numTabs. THIS FIELD MUST BE THE LAST IN THE + * STRUCTURE. */ } TkTextTabArray; -/* enum definining the edit modes of */ +/* + * Enumeration definining the edit modes of the widget. + */ typedef enum { - TK_TEXT_EDIT_INSERT, /* insert mode */ - TK_TEXT_EDIT_DELETE, /* delete mode */ - TK_TEXT_EDIT_OTHER /* none of the above */ + TK_TEXT_EDIT_INSERT, /* insert mode */ + TK_TEXT_EDIT_DELETE, /* delete mode */ + TK_TEXT_EDIT_REPLACE, /* replace mode */ + TK_TEXT_EDIT_OTHER /* none of the above */ } TkTextEditMode; /* @@ -475,46 +517,127 @@ typedef enum { } TkTextDirtyMode; /* - * A data structure of the following type is kept for each text widget that - * currently exists for this process: + * The following enum is used to define a type for the -state option of the + * Text widget. */ -typedef struct TkText { - Tk_Window tkwin; /* Window that embodies the text. NULL - * means that the window has been destroyed - * but the data structures haven't yet been - * cleaned up.*/ - Display *display; /* Display for widget. Needed, among other - * things, to allow resources to be freed - * even after tkwin has gone away. */ - Tcl_Interp *interp; /* Interpreter associated with widget. Used - * to delete widget command. */ - Tcl_Command widgetCmd; /* Token for text's widget command. */ +typedef enum { + TK_TEXT_STATE_DISABLED, TK_TEXT_STATE_NORMAL +} TkTextState; + +/* + * A data structure of the following type is shared between each text widget + * that are peers. + */ + +typedef struct TkSharedText { + int refCount; /* Reference count this shared object. */ TkTextBTree tree; /* B-tree representation of text and tags for * widget. */ Tcl_HashTable tagTable; /* Hash table that maps from tag names to - * pointers to TkTextTag structures. */ + * pointers to TkTextTag structures. The "sel" + * tag does not feature in this table, since + * there's one of those for each text peer. */ int numTags; /* Number of tags currently defined for - * widget; needed to keep track of + * widget; needed to keep track of * priorities. */ Tcl_HashTable markTable; /* Hash table that maps from mark names to - * pointers to mark segments. */ - Tcl_HashTable windowTable; /* Hash table that maps from window names - * to pointers to window segments. If a - * window segment doesn't yet have an - * associated window, there is no entry for - * it here. */ - Tcl_HashTable imageTable; /* Hash table that maps from image names - * to pointers to image segments. If an - * image segment doesn't yet have an - * associated image, there is no entry for - * it here. */ + * pointers to mark segments. The special + * "insert" and "current" marks are not stored + * in this table, but directly accessed as + * fields of textPtr. */ + Tcl_HashTable windowTable; /* Hash table that maps from window names to + * pointers to window segments. If a window + * segment doesn't yet have an associated + * window, there is no entry for it here. */ + Tcl_HashTable imageTable; /* Hash table that maps from image names to + * pointers to image segments. If an image + * segment doesn't yet have an associated + * image, there is no entry for it here. */ + Tk_BindingTable bindingTable; + /* Table of all bindings currently defined for + * this widget. NULL means that no bindings + * exist, so the table hasn't been created. + * Each "object" used for this table is the + * name of a tag. */ + int stateEpoch; /* This is incremented each time the B-tree's + * contents change structurally, or when the + * start/end limits change, and means that any + * cached TkTextIndex objects are no longer + * valid. */ + + /* + * Information related to the undo/redo functionality. + */ + + TkUndoRedoStack *undoStack; /* The undo/redo stack. */ + int undo; /* Non-zero means the undo/redo behaviour is + * enabled. */ + int maxUndo; /* The maximum depth of the undo stack + * expressed as the maximum number of compound + * statements. */ + int autoSeparators; /* Non-zero means the separators will be + * inserted automatically. */ + int isDirty; /* Flag indicating the 'dirtyness' of the + * text widget. If the flag is not zero, + * unsaved modifications have been applied to + * the text widget. */ + TkTextDirtyMode dirtyMode; /* The nature of the dirtyness characterized + * by the isDirty flag. */ + TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode + * was. */ + + /* + * Keep track of all the peers + */ + + struct TkText *peers; +} TkSharedText; + +/* + * A data structure of the following type is kept for each text widget that + * currently exists for this process: + */ + +typedef struct TkText { + /* + * Information related to and accessed by widget peers and the + * TkSharedText handling routines. + */ + + TkSharedText *sharedTextPtr;/* Shared section of all peers. */ + struct TkText *next; /* Next in list of linked peers. */ + TkTextLine *start; /* First B-tree line to show, or NULL to start + * at the beginning. */ + TkTextLine *end; /* Last B-tree line to show, or NULL for up to + * the end. */ + int pixelReference; /* Counter into the current tree reference + * index corresponding to this widget. */ + int abortSelections; /* Set to 1 whenever the text is modified in a + * way that interferes with selection + * retrieval: used to abort incremental + * selection retrievals. */ + + /* + * Standard Tk widget information and text-widget specific items + */ + + Tk_Window tkwin; /* Window that embodies the text. NULL means + * that the window has been destroyed but the + * data structures haven't yet been cleaned + * up.*/ + Display *display; /* Display for widget. Needed, among other + * things, to allow resources to be freed even + * after tkwin has gone away. */ + Tcl_Interp *interp; /* Interpreter associated with widget. Used to + * delete widget command. */ + Tcl_Command widgetCmd; /* Token for text's widget command. */ int state; /* Either STATE_NORMAL or STATE_DISABLED. A * text widget is read-only when disabled. */ /* - * Default information for displaying (may be overridden by tags - * applied to ranges of characters). + * Default information for displaying (may be overridden by tags applied + * to ranges of characters). */ Tk_3DBorder border; /* Structure used to draw 3-D border and @@ -522,44 +645,47 @@ typedef struct TkText { int borderWidth; /* Width of 3-D border to draw around entire * widget. */ int padX, padY; /* Padding between text and window border. */ - int relief; /* 3-d effect for border around entire - * widget: TK_RELIEF_RAISED etc. */ - int highlightWidth; /* Width in pixels of highlight to draw - * around widget when it has the focus. - * <= 0 means don't draw a highlight. */ + int relief; /* 3-d effect for border around entire widget: + * TK_RELIEF_RAISED etc. */ + int highlightWidth; /* Width in pixels of highlight to draw around + * widget when it has the focus. <= 0 means + * don't draw a highlight. */ XColor *highlightBgColorPtr; - /* Color for drawing traversal highlight - * area when highlight is off. */ + /* Color for drawing traversal highlight area + * when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ Tk_Cursor cursor; /* Current cursor for window, or None. */ XColor *fgColor; /* Default foreground color for text. */ Tk_Font tkfont; /* Default font for displaying text. */ int charWidth; /* Width of average character in default * font. */ + int charHeight; /* Height of average character in default + * font, including line spacing. */ int spacing1; /* Default extra spacing above first display * line for each text line. */ int spacing2; /* Default extra spacing between display lines * for the same text line. */ int spacing3; /* Default extra spacing below last display * line for each text line. */ - char *tabOptionString; /* Value of -tabs option string (malloc'ed). */ + Tcl_Obj *tabOptionPtr; /* Value of -tabs option string. */ TkTextTabArray *tabArrayPtr; /* Information about tab stops (malloc'ed). * NULL means perform default tabbing * behavior. */ + int tabStyle; /* One of TABULAR or WORDPROCESSOR. */ /* * Additional information used for displaying: */ - TkWrapMode wrapMode; /* How to handle wrap-around. Must be + TkWrapMode wrapMode; /* How to handle wrap-around. Must be * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or * TEXT_WRAPMODE_WORD. */ - int width, height; /* Desired dimensions for window, measured - * in characters. */ - int setGrid; /* Non-zero means pass gridding information - * to window manager. */ - int prevWidth, prevHeight; /* Last known dimensions of window; used to + int width, height; /* Desired dimensions for window, measured in + * characters. */ + int setGrid; /* Non-zero means pass gridding information to + * window manager. */ + int prevWidth, prevHeight; /* Last known dimensions of window; used to * detect changes in size. */ TkTextIndex topIndex; /* Identifies first character in top display * line of window. */ @@ -569,31 +695,27 @@ typedef struct TkText { * Information related to selection. */ - TkTextTag *selTagPtr; /* Pointer to "sel" tag. Used to tell when - * a new selection has been made. */ + TkTextTag *selTagPtr; /* Pointer to "sel" tag. Used to tell when a + * new selection has been made. */ Tk_3DBorder selBorder; /* Border and background for selected - * characters. This is a copy of information - * in *cursorTagPtr, so it shouldn't be - * explicitly freed. */ - char *selBdString; /* Value of -selectborderwidth option, or NULL - * if not specified (malloc'ed). */ - XColor *selFgColorPtr; /* Foreground color for selected text. - * This is a copy of information in - * *cursorTagPtr, so it shouldn't be + * characters. This is a copy of information + * in *selTagPtr, so it shouldn't be * explicitly freed. */ + Tk_3DBorder inactiveSelBorder; + /* Border and background for selected + * characters when they don't have the + * focus. */ + int selBorderWidth; /* Width of border around selection. */ + Tcl_Obj *selBorderWidthPtr; /* Width of border around selection. */ + XColor *selFgColorPtr; /* Foreground color for selected text. This is + * a copy of information in *selTagPtr, so it + * shouldn't be explicitly freed. */ int exportSelection; /* Non-zero means tie "sel" tag to X * selection. */ - TkTextIndex selIndex; /* Used during multi-pass selection retrievals. - * This index identifies the next character - * to be returned from the selection. */ - int abortSelections; /* Set to 1 whenever the text is modified - * in a way that interferes with selection - * retrieval: used to abort incremental - * selection retrievals. */ - int selOffset; /* Offset in selection corresponding to - * selLine and selCh. -1 means neither - * this information nor selIndex is of any - * use. */ + TkTextIndex selIndex; /* Used during multi-pass selection + * retrievals. This index identifies the next + * character to be returned from the + * selection. */ /* * Information related to insertion cursor: @@ -617,58 +739,49 @@ typedef struct TkText { * Information used for event bindings associated with tags: */ - Tk_BindingTable bindingTable; - /* Table of all bindings currently defined - * for this widget. NULL means that no - * bindings exist, so the table hasn't been - * created. Each "object" used for this - * table is the address of a tag. */ TkTextSegment *currentMarkPtr; - /* Pointer to segment for "current" mark, - * or NULL if none. */ + /* Pointer to segment for "current" mark, or + * NULL if none. */ XEvent pickEvent; /* The event from which the current character - * was chosen. Must be saved so that we - * can repick after modifications to the - * text. */ - int numCurTags; /* Number of tags associated with character - * at current mark. */ - TkTextTag **curTagArrayPtr; /* Pointer to array of tags for current - * mark, or NULL if none. */ + * was chosen. Must be saved so that we can + * repick after modifications to the text. */ + int numCurTags; /* Number of tags associated with character at + * current mark. */ + TkTextTag **curTagArrayPtr; /* Pointer to array of tags for current mark, + * or NULL if none. */ /* * Miscellaneous additional information: */ - char *takeFocus; /* Value of -takeFocus option; not used in - * the C code, but used by keyboard traversal - * scripts. Malloc'ed, but may be NULL. */ + char *takeFocus; /* Value of -takeFocus option; not used in the + * C code, but used by keyboard traversal + * scripts. Malloc'ed, but may be NULL. */ char *xScrollCmd; /* Prefix of command to issue to update * horizontal scrollbar when view changes. */ char *yScrollCmd; /* Prefix of command to issue to update * vertical scrollbar when view changes. */ - int flags; /* Miscellaneous flags; see below for + int flags; /* Miscellaneous flags; see below for * definitions. */ + Tk_OptionTable optionTable; /* Token representing the configuration + * specifications. */ + int refCount; /* Number of cached TkTextIndex objects + * refering to us. */ + int insertCursorType; /* 0 = standard insertion cursor, 1 = block + * cursor. */ /* - * Information related to the undo/redo funcitonality + * Copies of information from the shared section relating to the undo/redo + * functonality */ - - TkUndoRedoStack *undoStack; /* The undo/redo stack. */ - int undo; /* non zero means the undo/redo behaviour is + + int undo; /* Non-zero means the undo/redo behaviour is * enabled. */ int maxUndo; /* The maximum depth of the undo stack * expressed as the maximum number of compound * statements. */ - int autoSeparators; /* non zero means the separatorss will be + int autoSeparators; /* Non-zero means the separators will be * inserted automatically. */ - int isDirty; /* Flag indicating the 'dirtynesss' of the - * text widget. If the flag is not zero, - * unsaved modifications have been applied to - * the text widget. */ - TkTextDirtyMode dirtyMode; /* The nature of the dirtyness characterized - * by the isDirty flag. */ - TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode - * was. */ } TkText; /* @@ -680,11 +793,15 @@ typedef struct TkText { * displayed on screen. * GOT_FOCUS: Non-zero means this window has the input * focus. - * BUTTON_DOWN: 1 means that a mouse button is currently - * down; this is used to implement grabs - * for the duration of button presses. + * BUTTON_DOWN: 1 means that a mouse button is currently down; + * this is used to implement grabs for the + * duration of button presses. * UPDATE_SCROLLBARS: Non-zero means scrollbar(s) should be updated * during next redisplay operation. + * NEED_REPICK This appears unused and should probably be + * ignored. + * OPTIONS_FREED The widget's options have been freed. + * DESTROYED The widget is going away. */ #define GOT_SELECTION 1 @@ -693,230 +810,367 @@ typedef struct TkText { #define BUTTON_DOWN 8 #define UPDATE_SCROLLBARS 0x10 #define NEED_REPICK 0x20 +#define OPTIONS_FREED 0x40 +#define DESTROYED 0x80 /* - * Records of the following type define segment types in terms of - * a collection of procedures that may be called to manipulate - * segments of that type. - */ - -typedef TkTextSegment * Tk_SegSplitProc _ANSI_ARGS_(( - struct TkTextSegment *segPtr, int index)); -typedef int Tk_SegDeleteProc _ANSI_ARGS_(( - struct TkTextSegment *segPtr, - TkTextLine *linePtr, int treeGone)); -typedef TkTextSegment * Tk_SegCleanupProc _ANSI_ARGS_(( - struct TkTextSegment *segPtr, TkTextLine *linePtr)); -typedef void Tk_SegLineChangeProc _ANSI_ARGS_(( - struct TkTextSegment *segPtr, TkTextLine *linePtr)); -typedef int Tk_SegLayoutProc _ANSI_ARGS_((struct TkText *textPtr, - struct TkTextIndex *indexPtr, TkTextSegment *segPtr, - int offset, int maxX, int maxChars, - int noCharsYet, TkWrapMode wrapMode, - struct TkTextDispChunk *chunkPtr)); -typedef void Tk_SegCheckProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); + * Records of the following type define segment types in terms of a collection + * of procedures that may be called to manipulate segments of that type. + */ + +typedef TkTextSegment * Tk_SegSplitProc(struct TkTextSegment *segPtr, + int index); +typedef int Tk_SegDeleteProc(struct TkTextSegment *segPtr, + TkTextLine *linePtr, int treeGone); +typedef TkTextSegment * Tk_SegCleanupProc(struct TkTextSegment *segPtr, + TkTextLine *linePtr); +typedef void Tk_SegLineChangeProc(struct TkTextSegment *segPtr, + TkTextLine *linePtr); +typedef int Tk_SegLayoutProc(struct TkText *textPtr, + struct TkTextIndex *indexPtr, + TkTextSegment *segPtr, int offset, int maxX, + int maxChars, int noCharsYet, TkWrapMode wrapMode, + struct TkTextDispChunk *chunkPtr); +typedef void Tk_SegCheckProc(TkTextSegment *segPtr, + TkTextLine *linePtr); typedef struct Tk_SegType { - char *name; /* Name of this kind of segment. */ - int leftGravity; /* If a segment has zero size (e.g. a - * mark or tag toggle), does it - * attach to character to its left - * or right? 1 means left, 0 means - * right. */ - Tk_SegSplitProc *splitProc; /* Procedure to split large segment - * into two smaller ones. */ - Tk_SegDeleteProc *deleteProc; /* Procedure to call to delete - * segment. */ - Tk_SegCleanupProc *cleanupProc; /* After any change to a line, this - * procedure is invoked for all - * segments left in the line to - * perform any cleanup they wish - * (e.g. joining neighboring - * segments). */ + const char *name; /* Name of this kind of segment. */ + int leftGravity; /* If a segment has zero size (e.g. a mark or + * tag toggle), does it attach to character to + * its left or right? 1 means left, 0 means + * right. */ + Tk_SegSplitProc *splitProc; /* Procedure to split large segment into two + * smaller ones. */ + Tk_SegDeleteProc *deleteProc; + /* Procedure to call to delete segment. */ + Tk_SegCleanupProc *cleanupProc; + /* After any change to a line, this procedure + * is invoked for all segments left in the + * line to perform any cleanup they wish + * (e.g. joining neighboring segments). */ Tk_SegLineChangeProc *lineChangeProc; - /* Invoked when a segment is about - * to be moved from its current line - * to an earlier line because of - * a deletion. The linePtr is that - * for the segment's old line. - * CleanupProc will be invoked after - * the deletion is finished. */ - Tk_SegLayoutProc *layoutProc; /* Returns size information when - * figuring out what to display in - * window. */ - Tk_SegCheckProc *checkProc; /* Called during consistency checks - * to check internal consistency of - * segment. */ + /* Invoked when a segment is about to be moved + * from its current line to an earlier line + * because of a deletion. The linePtr is that + * for the segment's old line. CleanupProc + * will be invoked after the deletion is + * finished. */ + Tk_SegLayoutProc *layoutProc; + /* Returns size information when figuring out + * what to display in window. */ + Tk_SegCheckProc *checkProc; /* Called during consistency checks to check + * internal consistency of segment. */ } Tk_SegType; /* - * The constant below is used to specify a line when what is really - * wanted is the entire text. For now, just use a very big number. + * The following type and items describe different flags for text widget items + * to count. They are used in both tkText.c and tkTextIndex.c, in + * 'CountIndices', 'TkTextIndexBackChars', 'TkTextIndexForwChars', and + * 'TkTextIndexCount'. + */ + +typedef int TkTextCountType; + +#define COUNT_CHARS 0 +#define COUNT_INDICES 1 +#define COUNT_DISPLAY 2 +#define COUNT_DISPLAY_CHARS (COUNT_CHARS | COUNT_DISPLAY) +#define COUNT_DISPLAY_INDICES (COUNT_INDICES | COUNT_DISPLAY) + +/* + * The following structure is used to keep track of elided text taking account + * of different tag priorities, it is need for quick calculations of whether a + * single index is elided, and to start at a given index and maintain a + * correct elide state as we move or count forwards or backwards. + */ + +#define LOTSA_TAGS 1000 +typedef struct TkTextElideInfo { + int numTags; /* Total tags in widget. */ + int elide; /* Is the state currently elided. */ + int elidePriority; /* Tag priority controlling elide state. */ + TkTextSegment *segPtr; /* Segment to look at next. */ + int segOffset; /* Offset of segment within line. */ + int deftagCnts[LOTSA_TAGS]; + TkTextTag *deftagPtrs[LOTSA_TAGS]; + int *tagCnts; /* 0 or 1 depending if the tag with that + * priority is on or off. */ + TkTextTag **tagPtrs; /* Only filled with a tagPtr if the + * corresponding tagCnt is 1. */ +} TkTextElideInfo; + +/* + * The constant below is used to specify a line when what is really wanted is + * the entire text. For now, just use a very big number. */ -#define TK_END_OF_TEXT 1000000 +#define TK_END_OF_TEXT 1000000 /* - * The following definition specifies the maximum number of characters - * needed in a string to hold a position specifier. + * The following definition specifies the maximum number of characters needed + * in a string to hold a position specifier. */ -#define TK_POS_CHARS 30 +#define TK_POS_CHARS 30 + +/* + * Mask used for those options which may impact the pixel height calculations + * of individual lines displayed in the widget. + */ + +#define TK_TEXT_LINE_GEOMETRY 1 + +/* + * Mask used for those options which may impact the start and end lines used + * in the widget. + */ + +#define TK_TEXT_LINE_RANGE 2 + +/* + * Used as 'action' values in calls to TkTextInvalidateLineMetrics + */ + +#define TK_TEXT_INVALIDATE_ONLY 0 +#define TK_TEXT_INVALIDATE_INSERT 1 +#define TK_TEXT_INVALIDATE_DELETE 2 + +/* + * Used as special 'pickPlace' values in calls to TkTextSetYView. Zero or + * positive values indicate a number of pixels. + */ + +#define TK_TEXT_PICKPLACE -1 +#define TK_TEXT_NOPIXELADJUST -2 /* * Declarations for variables shared among the text-related files: */ -EXTERN int tkBTreeDebug; -EXTERN int tkTextDebug; -EXTERN Tk_SegType tkTextCharType; -EXTERN Tk_SegType tkTextLeftMarkType; -EXTERN Tk_SegType tkTextRightMarkType; -EXTERN Tk_SegType tkTextToggleOnType; -EXTERN Tk_SegType tkTextToggleOffType; - -/* - * Declarations for procedures that are used by the text-related files - * but shouldn't be used anywhere else in Tk (or by Tk clients): - */ - -EXTERN int TkBTreeCharTagged _ANSI_ARGS_((TkTextIndex *indexPtr, - TkTextTag *tagPtr)); -EXTERN void TkBTreeCheck _ANSI_ARGS_((TkTextBTree tree)); -EXTERN int TkBTreeCharsInLine _ANSI_ARGS_((TkTextLine *linePtr)); -EXTERN int TkBTreeBytesInLine _ANSI_ARGS_((TkTextLine *linePtr)); -EXTERN TkTextBTree TkBTreeCreate _ANSI_ARGS_((TkText *textPtr)); -EXTERN void TkBTreeDestroy _ANSI_ARGS_((TkTextBTree tree)); -EXTERN void TkBTreeDeleteChars _ANSI_ARGS_((TkTextIndex *index1Ptr, - TkTextIndex *index2Ptr)); -EXTERN TkTextLine * TkBTreeFindLine _ANSI_ARGS_((TkTextBTree tree, - int line)); -EXTERN TkTextTag ** TkBTreeGetTags _ANSI_ARGS_((TkTextIndex *indexPtr, - int *numTagsPtr)); -EXTERN void TkBTreeInsertChars _ANSI_ARGS_((TkTextIndex *indexPtr, - CONST char *string)); -EXTERN int TkBTreeLineIndex _ANSI_ARGS_((TkTextLine *linePtr)); -EXTERN void TkBTreeLinkSegment _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextIndex *indexPtr)); -EXTERN TkTextLine * TkBTreeNextLine _ANSI_ARGS_((TkTextLine *linePtr)); -EXTERN int TkBTreeNextTag _ANSI_ARGS_((TkTextSearch *searchPtr)); -EXTERN int TkBTreeNumLines _ANSI_ARGS_((TkTextBTree tree)); -EXTERN TkTextLine * TkBTreePreviousLine _ANSI_ARGS_((TkTextLine *linePtr)); -EXTERN int TkBTreePrevTag _ANSI_ARGS_((TkTextSearch *searchPtr)); -EXTERN void TkBTreeStartSearch _ANSI_ARGS_((TkTextIndex *index1Ptr, +MODULE_SCOPE int tkBTreeDebug; +MODULE_SCOPE int tkTextDebug; +MODULE_SCOPE const Tk_SegType tkTextCharType; +MODULE_SCOPE const Tk_SegType tkTextLeftMarkType; +MODULE_SCOPE const Tk_SegType tkTextRightMarkType; +MODULE_SCOPE const Tk_SegType tkTextToggleOnType; +MODULE_SCOPE const Tk_SegType tkTextToggleOffType; + +/* + * Convenience macros for use by B-tree clients which want to access pixel + * information on each line. Currently only used by TkTextDisp.c + */ + +#define TkBTreeLinePixelCount(text, line) \ + (line)->pixels[2*(text)->pixelReference] +#define TkBTreeLinePixelEpoch(text, line) \ + (line)->pixels[1+2*(text)->pixelReference] + +/* + * Declarations for procedures that are used by the text-related files but + * shouldn't be used anywhere else in Tk (or by Tk clients): + */ + +MODULE_SCOPE int TkBTreeAdjustPixelHeight(const TkText *textPtr, + TkTextLine *linePtr, int newPixelHeight, + int mergedLogicalLines); +MODULE_SCOPE int TkBTreeCharTagged(const TkTextIndex *indexPtr, + TkTextTag *tagPtr); +MODULE_SCOPE void TkBTreeCheck(TkTextBTree tree); +MODULE_SCOPE TkTextBTree TkBTreeCreate(TkSharedText *sharedTextPtr); +MODULE_SCOPE void TkBTreeAddClient(TkTextBTree tree, TkText *textPtr, + int defaultHeight); +MODULE_SCOPE void TkBTreeClientRangeChanged(TkText *textPtr, + int defaultHeight); +MODULE_SCOPE void TkBTreeRemoveClient(TkTextBTree tree, + TkText *textPtr); +MODULE_SCOPE void TkBTreeDestroy(TkTextBTree tree); +MODULE_SCOPE void TkBTreeDeleteIndexRange(TkTextBTree tree, + TkTextIndex *index1Ptr, TkTextIndex *index2Ptr); +MODULE_SCOPE int TkBTreeEpoch(TkTextBTree tree); +MODULE_SCOPE TkTextLine *TkBTreeFindLine(TkTextBTree tree, + const TkText *textPtr, int line); +MODULE_SCOPE TkTextLine *TkBTreeFindPixelLine(TkTextBTree tree, + const TkText *textPtr, int pixels, + int *pixelOffset); +MODULE_SCOPE TkTextTag **TkBTreeGetTags(const TkTextIndex *indexPtr, + const TkText *textPtr, int *numTagsPtr); +MODULE_SCOPE void TkBTreeInsertChars(TkTextBTree tree, + TkTextIndex *indexPtr, const char *string); +MODULE_SCOPE int TkBTreeLinesTo(const TkText *textPtr, + TkTextLine *linePtr); +MODULE_SCOPE int TkBTreePixelsTo(const TkText *textPtr, + TkTextLine *linePtr); +MODULE_SCOPE void TkBTreeLinkSegment(TkTextSegment *segPtr, + TkTextIndex *indexPtr); +MODULE_SCOPE TkTextLine *TkBTreeNextLine(const TkText *textPtr, + TkTextLine *linePtr); +MODULE_SCOPE int TkBTreeNextTag(TkTextSearch *searchPtr); +MODULE_SCOPE int TkBTreeNumLines(TkTextBTree tree, + const TkText *textPtr); +MODULE_SCOPE int TkBTreeNumPixels(TkTextBTree tree, + const TkText *textPtr); +MODULE_SCOPE TkTextLine *TkBTreePreviousLine(TkText *textPtr, + TkTextLine *linePtr); +MODULE_SCOPE int TkBTreePrevTag(TkTextSearch *searchPtr); +MODULE_SCOPE void TkBTreeStartSearch(TkTextIndex *index1Ptr, TkTextIndex *index2Ptr, TkTextTag *tagPtr, - TkTextSearch *searchPtr)); -EXTERN void TkBTreeStartSearchBack _ANSI_ARGS_((TkTextIndex *index1Ptr, + TkTextSearch *searchPtr); +MODULE_SCOPE void TkBTreeStartSearchBack(TkTextIndex *index1Ptr, TkTextIndex *index2Ptr, TkTextTag *tagPtr, - TkTextSearch *searchPtr)); -EXTERN void TkBTreeTag _ANSI_ARGS_((TkTextIndex *index1Ptr, + TkTextSearch *searchPtr); +MODULE_SCOPE int TkBTreeTag(TkTextIndex *index1Ptr, TkTextIndex *index2Ptr, TkTextTag *tagPtr, - int add)); -EXTERN void TkBTreeUnlinkSegment _ANSI_ARGS_((TkTextBTree tree, - TkTextSegment *segPtr, TkTextLine *linePtr)); -EXTERN void TkTextBindProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -EXTERN void TkTextChanged _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *index1Ptr, TkTextIndex *index2Ptr)); -EXTERN int TkTextCharBbox _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr, int *xPtr, int *yPtr, - int *widthPtr, int *heightPtr)); -EXTERN int TkTextCharLayoutProc _ANSI_ARGS_((TkText *textPtr, + int add); +MODULE_SCOPE void TkBTreeUnlinkSegment(TkTextSegment *segPtr, + TkTextLine *linePtr); +MODULE_SCOPE void TkTextBindProc(ClientData clientData, + XEvent *eventPtr); +MODULE_SCOPE void TkTextSelectionEvent(TkText *textPtr); +MODULE_SCOPE void TkTextChanged(TkSharedText *sharedTextPtr, + TkText *textPtr, const TkTextIndex *index1Ptr, + const TkTextIndex *index2Ptr); +MODULE_SCOPE int TkTextIndexBbox(TkText *textPtr, + const TkTextIndex *indexPtr, int *xPtr, int *yPtr, + int *widthPtr, int *heightPtr, int *charWidthPtr); +MODULE_SCOPE int TkTextCharLayoutProc(TkText *textPtr, TkTextIndex *indexPtr, TkTextSegment *segPtr, int offset, int maxX, int maxChars, int noBreakYet, - TkWrapMode wrapMode, TkTextDispChunk *chunkPtr)); -EXTERN void TkTextCreateDInfo _ANSI_ARGS_((TkText *textPtr)); -EXTERN int TkTextDLineInfo _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr, int *xPtr, int *yPtr, - int *widthPtr, int *heightPtr, int *basePtr)); -EXTERN TkTextTag * TkTextCreateTag _ANSI_ARGS_((TkText *textPtr, - CONST char *tagName)); -EXTERN void TkTextFreeDInfo _ANSI_ARGS_((TkText *textPtr)); -EXTERN void TkTextFreeTag _ANSI_ARGS_((TkText *textPtr, - TkTextTag *tagPtr)); -EXTERN int TkTextGetIndex _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, CONST char *string, - TkTextIndex *indexPtr)); -EXTERN TkTextTabArray * TkTextGetTabs _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, char *string)); -EXTERN void TkTextIndexBackBytes _ANSI_ARGS_(( - CONST TkTextIndex *srcPtr, int count, - TkTextIndex *dstPtr)); -EXTERN void TkTextIndexBackChars _ANSI_ARGS_(( - CONST TkTextIndex *srcPtr, int count, - TkTextIndex *dstPtr)); -EXTERN int TkTextIndexCmp _ANSI_ARGS_(( - CONST TkTextIndex *index1Ptr, - CONST TkTextIndex *index2Ptr)); -EXTERN void TkTextIndexForwBytes _ANSI_ARGS_(( - CONST TkTextIndex *srcPtr, int count, - TkTextIndex *dstPtr)); -EXTERN void TkTextIndexForwChars _ANSI_ARGS_(( - CONST TkTextIndex *srcPtr, int count, - TkTextIndex *dstPtr)); -EXTERN TkTextSegment * TkTextIndexToSeg _ANSI_ARGS_(( - CONST TkTextIndex *indexPtr, int *offsetPtr)); -EXTERN void TkTextInsertDisplayProc _ANSI_ARGS_(( - TkTextDispChunk *chunkPtr, int x, int y, int height, - int baseline, Display *display, Drawable dst, - int screenY)); -EXTERN void TkTextLostSelection _ANSI_ARGS_(( - ClientData clientData)); -EXTERN TkTextIndex * TkTextMakeCharIndex _ANSI_ARGS_((TkTextBTree tree, + TkWrapMode wrapMode, TkTextDispChunk *chunkPtr); +MODULE_SCOPE void TkTextCreateDInfo(TkText *textPtr); +MODULE_SCOPE int TkTextDLineInfo(TkText *textPtr, + const TkTextIndex *indexPtr, int *xPtr, int *yPtr, + int *widthPtr, int *heightPtr, int *basePtr); +MODULE_SCOPE void TkTextEmbWinDisplayProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int x, int y, + int lineHeight, int baseline, Display *display, + Drawable dst, int screenY); +MODULE_SCOPE TkTextTag *TkTextCreateTag(TkText *textPtr, + const char *tagName, int *newTag); +MODULE_SCOPE void TkTextFreeDInfo(TkText *textPtr); +MODULE_SCOPE void TkTextDeleteTag(TkText *textPtr, TkTextTag *tagPtr); +MODULE_SCOPE void TkTextFreeTag(TkText *textPtr, TkTextTag *tagPtr); +MODULE_SCOPE int TkTextGetIndex(Tcl_Interp *interp, TkText *textPtr, + const char *string, TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextGetObjIndex(Tcl_Interp *interp, TkText *textPtr, + Tcl_Obj *idxPtr, TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextSharedGetObjIndex(Tcl_Interp *interp, + TkSharedText *sharedTextPtr, Tcl_Obj *idxPtr, + TkTextIndex *indexPtr); +MODULE_SCOPE const TkTextIndex *TkTextGetIndexFromObj(Tcl_Interp *interp, + TkText *textPtr, Tcl_Obj *objPtr); +MODULE_SCOPE TkTextTabArray *TkTextGetTabs(Tcl_Interp *interp, + TkText *textPtr, Tcl_Obj *stringPtr); +MODULE_SCOPE void TkTextFindDisplayLineEnd(TkText *textPtr, + TkTextIndex *indexPtr, int end, int *xOffset); +MODULE_SCOPE int TkTextIndexBackBytes(const TkText *textPtr, + const TkTextIndex *srcPtr, int count, + TkTextIndex *dstPtr); +MODULE_SCOPE void TkTextIndexBackChars(const TkText *textPtr, + const TkTextIndex *srcPtr, int count, + TkTextIndex *dstPtr, TkTextCountType type); +MODULE_SCOPE int TkTextIndexCmp(const TkTextIndex *index1Ptr, + const TkTextIndex *index2Ptr); +MODULE_SCOPE int TkTextIndexCount(const TkText *textPtr, + const TkTextIndex *index1Ptr, + const TkTextIndex *index2Ptr, + TkTextCountType type); +MODULE_SCOPE int TkTextIndexForwBytes(const TkText *textPtr, + const TkTextIndex *srcPtr, int count, + TkTextIndex *dstPtr); +MODULE_SCOPE void TkTextIndexForwChars(const TkText *textPtr, + const TkTextIndex *srcPtr, int count, + TkTextIndex *dstPtr, TkTextCountType type); +MODULE_SCOPE void TkTextIndexOfX(TkText *textPtr, int x, + TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextIndexYPixels(TkText *textPtr, + const TkTextIndex *indexPtr); +MODULE_SCOPE TkTextSegment *TkTextIndexToSeg(const TkTextIndex *indexPtr, + int *offsetPtr); +MODULE_SCOPE void TkTextInsertDisplayProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int x, int y, + int height, int baseline, Display *display, + Drawable dst, int screenY); +MODULE_SCOPE void TkTextLostSelection(ClientData clientData); +MODULE_SCOPE TkTextIndex *TkTextMakeCharIndex(TkTextBTree tree, TkText *textPtr, int lineIndex, int charIndex, - TkTextIndex *indexPtr)); -EXTERN int TkTextIsElided _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr)); -EXTERN TkTextIndex * TkTextMakeByteIndex _ANSI_ARGS_((TkTextBTree tree, - int lineIndex, int byteIndex, - TkTextIndex *indexPtr)); -EXTERN int TkTextMarkCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextMarkNameToIndex _ANSI_ARGS_((TkText *textPtr, - CONST char *name, TkTextIndex *indexPtr)); -EXTERN void TkTextMarkSegToIndex _ANSI_ARGS_((TkText *textPtr, - TkTextSegment *markPtr, TkTextIndex *indexPtr)); -EXTERN void TkTextEventuallyRepick _ANSI_ARGS_((TkText *textPtr)); -EXTERN void TkTextPickCurrent _ANSI_ARGS_((TkText *textPtr, - XEvent *eventPtr)); -EXTERN void TkTextPixelIndex _ANSI_ARGS_((TkText *textPtr, - int x, int y, TkTextIndex *indexPtr)); -EXTERN void TkTextPrintIndex _ANSI_ARGS_(( - CONST TkTextIndex *indexPtr, char *string)); -EXTERN void TkTextRedrawRegion _ANSI_ARGS_((TkText *textPtr, - int x, int y, int width, int height)); -EXTERN void TkTextRedrawTag _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *index1Ptr, TkTextIndex *index2Ptr, - TkTextTag *tagPtr, int withTag)); -EXTERN void TkTextRelayoutWindow _ANSI_ARGS_((TkText *textPtr)); -EXTERN int TkTextScanCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextSeeCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextSegToOffset _ANSI_ARGS_(( - CONST TkTextSegment *segPtr, - CONST TkTextLine *linePtr)); -EXTERN TkTextSegment * TkTextSetMark _ANSI_ARGS_((TkText *textPtr, - CONST char *name, TkTextIndex *indexPtr)); -EXTERN void TkTextSetYView _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr, int pickPlace)); -EXTERN int TkTextTagCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextImageCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextImageIndex _ANSI_ARGS_((TkText *textPtr, - CONST char *name, TkTextIndex *indexPtr)); -EXTERN int TkTextWindowCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextWindowIndex _ANSI_ARGS_((TkText *textPtr, - CONST char *name, TkTextIndex *indexPtr)); -EXTERN int TkTextXviewCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); -EXTERN int TkTextYviewCmd _ANSI_ARGS_((TkText *textPtr, - Tcl_Interp *interp, int argc, CONST char **argv)); + TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextMeasureDown(TkText *textPtr, + TkTextIndex *srcPtr, int distance); +MODULE_SCOPE void TkTextFreeElideInfo(TkTextElideInfo *infoPtr); +MODULE_SCOPE int TkTextIsElided(const TkText *textPtr, + const TkTextIndex *indexPtr, + TkTextElideInfo *infoPtr); +MODULE_SCOPE TkTextIndex *TkTextMakeByteIndex(TkTextBTree tree, + const TkText *textPtr, int lineIndex, + int byteIndex, TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextMakePixelIndex(TkText *textPtr, + int pixelIndex, TkTextIndex *indexPtr); +MODULE_SCOPE void TkTextInvalidateLineMetrics( + TkSharedText *sharedTextPtr, TkText *textPtr, + TkTextLine *linePtr, int lineCount, int action); +MODULE_SCOPE int TkTextUpdateLineMetrics(TkText *textPtr, int lineNum, + int endLine, int doThisMuch); +MODULE_SCOPE int TkTextUpdateOneLine(TkText *textPtr, + TkTextLine *linePtr, int pixelHeight, + TkTextIndex *indexPtr, int partialCalc); +MODULE_SCOPE int TkTextMarkCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextMarkNameToIndex(TkText *textPtr, + const char *name, TkTextIndex *indexPtr); +MODULE_SCOPE void TkTextMarkSegToIndex(TkText *textPtr, + TkTextSegment *markPtr, TkTextIndex *indexPtr); +MODULE_SCOPE void TkTextEventuallyRepick(TkText *textPtr); +MODULE_SCOPE void TkTextPickCurrent(TkText *textPtr, XEvent *eventPtr); +MODULE_SCOPE void TkTextPixelIndex(TkText *textPtr, int x, int y, + TkTextIndex *indexPtr, int *nearest); +MODULE_SCOPE int TkTextPrintIndex(const TkText *textPtr, + const TkTextIndex *indexPtr, char *string); +MODULE_SCOPE Tcl_Obj * TkTextNewIndexObj(TkText *textPtr, + const TkTextIndex *indexPtr); +MODULE_SCOPE void TkTextRedrawRegion(TkText *textPtr, int x, int y, + int width, int height); +MODULE_SCOPE void TkTextRedrawTag(TkSharedText *sharedTextPtr, + TkText *textPtr, TkTextIndex *index1Ptr, + TkTextIndex *index2Ptr, TkTextTag *tagPtr, + int withTag); +MODULE_SCOPE void TkTextRelayoutWindow(TkText *textPtr, int mask); +MODULE_SCOPE int TkTextScanCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextSeeCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextSegToOffset(const TkTextSegment *segPtr, + const TkTextLine *linePtr); +MODULE_SCOPE TkTextSegment *TkTextSetMark(TkText *textPtr, + const char *name, TkTextIndex *indexPtr); +MODULE_SCOPE void TkTextSetYView(TkText *textPtr, + TkTextIndex *indexPtr, int pickPlace); +MODULE_SCOPE int TkTextTagCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextImageCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextImageIndex(TkText *textPtr, + const char *name, TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextWindowCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextWindowIndex(TkText *textPtr, const char *name, + TkTextIndex *indexPtr); +MODULE_SCOPE int TkTextXviewCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE int TkTextYviewCmd(TkText *textPtr, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]); +MODULE_SCOPE void TkTextWinFreeClient(Tcl_HashEntry *hPtr, + TkTextEmbWindowClient *client); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT #endif /* _TKTEXT */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c index 5a5a9b5..67ff79d 100644 --- a/generic/tkTextBTree.c +++ b/generic/tkTextBTree.c @@ -1,33 +1,54 @@ -/* +/* * tkTextBTree.c -- * - * This file contains code that manages the B-tree representation - * of text for Tk's text widget and implements character and - * toggle segment types. + * This file contains code that manages the B-tree representation of text + * for Tk's text widget and implements character and toggle segment + * types. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" #include "tkText.h" /* - * The data structure below keeps summary information about one tag as part - * of the tag information in a node. + * Implementation notes: + * + * Most of this file is independent of the text widget implementation and + * representation now. Without much effort this could be developed further + * into a new Tcl object type of which the Tk text widget is one example of a + * client. + * + * The B-tree is set up with a dummy last line of text which must not be + * displayed, and must _never_ have a non-zero pixel count. This dummy line is + * a historical convenience to avoid other code having to deal with NULL + * TkTextLines. Since Tk 8.5, with pixel line height calculations and peer + * widgets, this dummy line is becoming somewhat of a liability, and special + * case code has been required to deal with it. It is probably a good idea to + * investigate removing the dummy line completely. This could result in an + * overall simplification (although it would require new special case code to + * deal with the fact that '.text index end' would then not really point to a + * valid line, rather it would point to the beginning of a non-existent line + * one beyond all current lines - we could perhaps define that as a + * TkTextIndex with a NULL TkTextLine ptr). + */ + +/* + * The data structure below keeps summary information about one tag as part of + * the tag information in a node. */ typedef struct Summary { - TkTextTag *tagPtr; /* Handle for tag. */ - int toggleCount; /* Number of transitions into or - * out of this tag that occur in - * the subtree rooted at this node. */ - struct Summary *nextPtr; /* Next in list of all tags for same - * node, or NULL if at end of list. */ + TkTextTag *tagPtr; /* Handle for tag. */ + int toggleCount; /* Number of transitions into or out of this + * tag that occur in the subtree rooted at + * this node. */ + struct Summary *nextPtr; /* Next in list of all tags for same node, or + * NULL if at end of list. */ } Summary; /* @@ -35,43 +56,63 @@ typedef struct Summary { */ typedef struct Node { - struct Node *parentPtr; /* Pointer to parent node, or NULL if - * this is the root. */ - struct Node *nextPtr; /* Next in list of siblings with the - * same parent node, or NULL for end - * of list. */ - Summary *summaryPtr; /* First in malloc-ed list of info - * about tags in this subtree (NULL if - * no tag info in the subtree). */ - int level; /* Level of this node in the B-tree. - * 0 refers to the bottom of the tree - * (children are lines, not nodes). */ - union { /* First in linked list of children. */ - struct Node *nodePtr; /* Used if level > 0. */ - TkTextLine *linePtr; /* Used if level == 0. */ + struct Node *parentPtr; /* Pointer to parent node, or NULL if this is + * the root. */ + struct Node *nextPtr; /* Next in list of siblings with the same + * parent node, or NULL for end of list. */ + Summary *summaryPtr; /* First in malloc-ed list of info about tags + * in this subtree (NULL if no tag info in the + * subtree). */ + int level; /* Level of this node in the B-tree. 0 refers + * to the bottom of the tree (children are + * lines, not nodes). */ + union { /* First in linked list of children. */ + struct Node *nodePtr; /* Used if level > 0. */ + TkTextLine *linePtr; /* Used if level == 0. */ } children; - int numChildren; /* Number of children of this node. */ - int numLines; /* Total number of lines (leaves) in - * the subtree rooted here. */ + int numChildren; /* Number of children of this node. */ + int numLines; /* Total number of lines (leaves) in the + * subtree rooted here. */ + int *numPixels; /* Array containing total number of vertical + * display pixels in the subtree rooted here, + * one entry for each peer widget. */ } Node; /* - * Upper and lower bounds on how many children a node may have: - * rebalance when either of these limits is exceeded. MAX_CHILDREN - * should be twice MIN_CHILDREN and MIN_CHILDREN must be >= 2. + * Used to avoid having to allocate and deallocate arrays on the fly for + * commonly used functions. Must be > 0. + */ + +#define PIXEL_CLIENTS 5 + +/* + * Upper and lower bounds on how many children a node may have: rebalance when + * either of these limits is exceeded. MAX_CHILDREN should be twice + * MIN_CHILDREN and MIN_CHILDREN must be >= 2. */ #define MAX_CHILDREN 12 #define MIN_CHILDREN 6 /* - * The data structure below defines an entire B-tree. + * The data structure below defines an entire B-tree. Since text widgets are + * the only current B-tree clients, 'clients' and 'pixelReferences' are + * identical. */ typedef struct BTree { - Node *rootPtr; /* Pointer to root of B-tree. */ - TkText *textPtr; /* Used to find tagTable in consistency - * checking code */ + Node *rootPtr; /* Pointer to root of B-tree. */ + int clients; /* Number of clients of this B-tree. */ + int pixelReferences; /* Number of clients of this B-tree which care + * about pixel heights. */ + int stateEpoch; /* Updated each time any aspect of the B-tree + * changes. */ + TkSharedText *sharedTextPtr;/* Used to find tagTable in consistency + * checking code, and to access list of all + * B-tree clients. */ + int startEndCount; + TkTextLine **startEnd; + TkText **startEndRef; } BTree; /* @@ -80,20 +121,17 @@ typedef struct BTree { */ typedef struct TagInfo { - int numTags; /* Number of tags for which there - * is currently information in - * tags and counts. */ - int arraySize; /* Number of entries allocated for - * tags and counts. */ - TkTextTag **tagPtrs; /* Array of tags seen so far. - * Malloc-ed. */ - int *counts; /* Toggle count (so far) for each - * entry in tags. Malloc-ed. */ + int numTags; /* Number of tags for which there is currently + * information in tags and counts. */ + int arraySize; /* Number of entries allocated for tags and + * counts. */ + TkTextTag **tagPtrs; /* Array of tags seen so far. Malloc-ed. */ + int *counts; /* Toggle count (so far) for each entry in + * tags. Malloc-ed. */ } TagInfo; /* - * Variable that indicates whether to enable consistency checks for - * debugging. + * Variable that indicates whether to enable consistency checks for debugging. */ int tkBTreeDebug = 0; @@ -108,86 +146,98 @@ int tkBTreeDebug = 0; + sizeof(TkTextToggle))) /* - * Forward declarations for procedures defined in this file: - */ - -static void ChangeNodeToggleCount _ANSI_ARGS_((Node *nodePtr, - TkTextTag *tagPtr, int delta)); -static void CharCheckProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static int CharDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr, int treeGone)); -static TkTextSegment * CharCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static TkTextSegment * CharSplitProc _ANSI_ARGS_((TkTextSegment *segPtr, - int index)); -static void CheckNodeConsistency _ANSI_ARGS_((Node *nodePtr)); -static void CleanupLine _ANSI_ARGS_((TkTextLine *linePtr)); -static void DeleteSummaries _ANSI_ARGS_((Summary *tagPtr)); -static void DestroyNode _ANSI_ARGS_((Node *nodePtr)); -static TkTextSegment * FindTagEnd _ANSI_ARGS_((TkTextBTree tree, - TkTextTag *tagPtr, TkTextIndex *indexPtr)); -static void IncCount _ANSI_ARGS_((TkTextTag *tagPtr, int inc, - TagInfo *tagInfoPtr)); -static void Rebalance _ANSI_ARGS_((BTree *treePtr, Node *nodePtr)); -static void RecomputeNodeCounts _ANSI_ARGS_((Node *nodePtr)); -static TkTextSegment * SplitSeg _ANSI_ARGS_((TkTextIndex *indexPtr)); -static void ToggleCheckProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static TkTextSegment * ToggleCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static int ToggleDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr, int treeGone)); -static void ToggleLineChangeProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static TkTextSegment * FindTagStart _ANSI_ARGS_((TkTextBTree tree, - TkTextTag *tagPtr, TkTextIndex *indexPtr)); + * Forward declarations for functions defined in this file: + */ + +static int AdjustPixelClient(BTree *treePtr, int defaultHeight, + Node *nodePtr, TkTextLine *start, TkTextLine *end, + int useReference, int newPixelReferences, + int *counting); +static void ChangeNodeToggleCount(Node *nodePtr, + TkTextTag *tagPtr, int delta); +static void CharCheckProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static int CharDeleteProc(TkTextSegment *segPtr, + TkTextLine *linePtr, int treeGone); +static TkTextSegment * CharCleanupProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static TkTextSegment * CharSplitProc(TkTextSegment *segPtr, int index); +static void CheckNodeConsistency(Node *nodePtr, int references); +static void CleanupLine(TkTextLine *linePtr); +static void DeleteSummaries(Summary *tagPtr); +static void DestroyNode(Node *nodePtr); +static TkTextSegment * FindTagEnd(TkTextBTree tree, TkTextTag *tagPtr, + TkTextIndex *indexPtr); +static void IncCount(TkTextTag *tagPtr, int inc, + TagInfo *tagInfoPtr); +static void Rebalance(BTree *treePtr, Node *nodePtr); +static void RecomputeNodeCounts(BTree *treePtr, Node *nodePtr); +static void RemovePixelClient(BTree *treePtr, Node *nodePtr, + int overwriteWithLast); +static TkTextSegment * SplitSeg(TkTextIndex *indexPtr); +static void ToggleCheckProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static TkTextSegment * ToggleCleanupProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static int ToggleDeleteProc(TkTextSegment *segPtr, + TkTextLine *linePtr, int treeGone); +static void ToggleLineChangeProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static TkTextSegment * FindTagStart(TkTextBTree tree, TkTextTag *tagPtr, + TkTextIndex *indexPtr); +static void AdjustStartEndRefs(BTree *treePtr, TkText *textPtr, + int action); + +/* + * Actions for use by AdjustStartEndRefs + */ + +#define TEXT_ADD_REFS 1 +#define TEXT_REMOVE_REFS 2 /* * Type record for character segments: */ -Tk_SegType tkTextCharType = { - "character", /* name */ - 0, /* leftGravity */ - CharSplitProc, /* splitProc */ - CharDeleteProc, /* deleteProc */ - CharCleanupProc, /* cleanupProc */ - (Tk_SegLineChangeProc *) NULL, /* lineChangeProc */ - TkTextCharLayoutProc, /* layoutProc */ - CharCheckProc /* checkProc */ +const Tk_SegType tkTextCharType = { + "character", /* name */ + 0, /* leftGravity */ + CharSplitProc, /* splitProc */ + CharDeleteProc, /* deleteProc */ + CharCleanupProc, /* cleanupProc */ + NULL, /* lineChangeProc */ + TkTextCharLayoutProc, /* layoutProc */ + CharCheckProc /* checkProc */ }; /* - * Type record for segments marking the beginning of a tagged - * range: + * Type record for segments marking the beginning of a tagged range: */ -Tk_SegType tkTextToggleOnType = { - "toggleOn", /* name */ - 0, /* leftGravity */ - (Tk_SegSplitProc *) NULL, /* splitProc */ - ToggleDeleteProc, /* deleteProc */ - ToggleCleanupProc, /* cleanupProc */ - ToggleLineChangeProc, /* lineChangeProc */ - (Tk_SegLayoutProc *) NULL, /* layoutProc */ - ToggleCheckProc /* checkProc */ +const Tk_SegType tkTextToggleOnType = { + "toggleOn", /* name */ + 0, /* leftGravity */ + NULL, /* splitProc */ + ToggleDeleteProc, /* deleteProc */ + ToggleCleanupProc, /* cleanupProc */ + ToggleLineChangeProc, /* lineChangeProc */ + NULL, /* layoutProc */ + ToggleCheckProc /* checkProc */ }; /* - * Type record for segments marking the end of a tagged - * range: + * Type record for segments marking the end of a tagged range: */ -Tk_SegType tkTextToggleOffType = { - "toggleOff", /* name */ - 1, /* leftGravity */ - (Tk_SegSplitProc *) NULL, /* splitProc */ - ToggleDeleteProc, /* deleteProc */ - ToggleCleanupProc, /* cleanupProc */ - ToggleLineChangeProc, /* lineChangeProc */ - (Tk_SegLayoutProc *) NULL, /* layoutProc */ - ToggleCheckProc /* checkProc */ +const Tk_SegType tkTextToggleOffType = { + "toggleOff", /* name */ + 1, /* leftGravity */ + NULL, /* splitProc */ + ToggleDeleteProc, /* deleteProc */ + ToggleCleanupProc, /* cleanupProc */ + ToggleLineChangeProc, /* lineChangeProc */ + NULL, /* layoutProc */ + ToggleCheckProc /* checkProc */ }; /* @@ -195,11 +245,11 @@ Tk_SegType tkTextToggleOffType = { * * TkBTreeCreate -- * - * This procedure is called to create a new text B-tree. + * This function is called to create a new text B-tree. * * Results: - * The return value is a pointer to a new B-tree containing - * one line with nothing but a newline character. + * The return value is a pointer to a new B-tree containing one line with + * nothing but a newline character. * * Side effects: * Memory is allocated and initialized. @@ -208,8 +258,8 @@ Tk_SegType tkTextToggleOffType = { */ TkTextBTree -TkBTreeCreate(textPtr) - TkText *textPtr; +TkBTreeCreate( + TkSharedText *sharedTextPtr) { register BTree *treePtr; register Node *rootPtr; @@ -217,15 +267,16 @@ TkBTreeCreate(textPtr) register TkTextSegment *segPtr; /* - * The tree will initially have two empty lines. The second line - * isn't actually part of the tree's contents, but its presence - * makes several operations easier. The tree will have one node, - * which is also the root of the tree. + * The tree will initially have two empty lines. The second line isn't + * actually part of the tree's contents, but its presence makes several + * operations easier. The tree will have one node, which is also the root + * of the tree. */ rootPtr = (Node *) ckalloc(sizeof(Node)); linePtr = (TkTextLine *) ckalloc(sizeof(TkTextLine)); linePtr2 = (TkTextLine *) ckalloc(sizeof(TkTextLine)); + rootPtr->parentPtr = NULL; rootPtr->nextPtr = NULL; rootPtr->summaryPtr = NULL; @@ -234,6 +285,15 @@ TkBTreeCreate(textPtr) rootPtr->numChildren = 2; rootPtr->numLines = 2; + /* + * The tree currently has no registered clients, so all pixel count + * pointers are simply NULL. + */ + + rootPtr->numPixels = NULL; + linePtr->pixels = NULL; + linePtr2->pixels = NULL; + linePtr->parentPtr = rootPtr; linePtr->nextPtr = linePtr2; segPtr = (TkTextSegment *) ckalloc(CSEG_SIZE(1)); @@ -255,8 +315,14 @@ TkBTreeCreate(textPtr) segPtr->body.chars[1] = 0; treePtr = (BTree *) ckalloc(sizeof(BTree)); + treePtr->sharedTextPtr = sharedTextPtr; treePtr->rootPtr = rootPtr; - treePtr->textPtr = textPtr; + treePtr->clients = 0; + treePtr->stateEpoch = 0; + treePtr->pixelReferences = 0; + treePtr->startEndCount = 0; + treePtr->startEnd = NULL; + treePtr->startEndRef = NULL; return (TkTextBTree) treePtr; } @@ -264,13 +330,133 @@ TkBTreeCreate(textPtr) /* *---------------------------------------------------------------------- * + * TkBTreeAddClient -- + * + * This function is called to provide a client with access to a given + * B-tree. If the client wishes to make use of the B-tree's pixel height + * storage, caching and calculation mechanisms, then a non-negative + * 'defaultHeight' must be provided. In this case the return value is a + * pixel tree reference which must be provided in all of the B-tree API + * which refers to or modifies pixel heights: + * + * TkBTreeAdjustPixelHeight, + * TkBTreeFindPixelLine, + * TkBTreeNumPixels, + * TkBTreePixelsTo, + * (and two private functions AdjustPixelClient, RemovePixelClient). + * + * If this is not provided, then the above functions must never be called + * for this client. + * + * Results: + * The return value is the pixelReference used by the B-tree to refer to + * pixel counts for the new client. It should be stored by the caller. If + * defaultHeight was negative, then the return value will be -1. + * + * Side effects: + * Memory may be allocated and initialized. + * + *---------------------------------------------------------------------- + */ + +void +TkBTreeAddClient( + TkTextBTree tree, /* B-tree to add a client to. */ + TkText *textPtr, /* Client to add. */ + int defaultHeight) /* Default line height for the new client, or + * -1 if no pixel heights are to be kept. */ +{ + register BTree *treePtr = (BTree *) tree; + + if (treePtr == NULL) { + Tcl_Panic("NULL treePtr in TkBTreeAddClient"); + } + + if (textPtr->start != NULL || textPtr->end != NULL) { + AdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS); + } + + if (defaultHeight >= 0) { + TkTextLine *end; + int counting = (textPtr->start == NULL ? 1 : 0); + int useReference = treePtr->pixelReferences; + + /* + * We must set the 'end' value in AdjustPixelClient so that the last + * dummy line in the B-tree doesn't contain a pixel height. + */ + + end = textPtr->end; + if (end == NULL) { + end = TkBTreeFindLine(tree, NULL, TkBTreeNumLines(tree, NULL)); + } + AdjustPixelClient(treePtr, defaultHeight, treePtr->rootPtr, + textPtr->start, end, useReference, useReference+1, &counting); + + textPtr->pixelReference = useReference; + treePtr->pixelReferences++; + } else { + textPtr->pixelReference = -1; + } + treePtr->clients++; +} + +/* + *---------------------------------------------------------------------- + * + * TkBTreeClientRangeChanged -- + * + * Called when the -startline or -endline options of a text widget client + * of the B-tree have changed. + * + * Results: + * None. + * + * Side effects: + * Lots of processing of the B-tree is done, with potential for memory to + * be allocated and initialized for the pixel heights of the widget. + * + *---------------------------------------------------------------------- + */ + +void +TkBTreeClientRangeChanged( + TkText *textPtr, /* Client whose start, end have changed. */ + int defaultHeight) /* Default line height for the new client, or + * -1 if no pixel heights are to be kept. */ +{ + TkTextLine *end; + BTree *treePtr = (BTree *) textPtr->sharedTextPtr->tree; + + int counting = (textPtr->start == NULL ? 1 : 0); + int useReference = textPtr->pixelReference; + + AdjustStartEndRefs(treePtr, textPtr, TEXT_ADD_REFS | TEXT_REMOVE_REFS); + + /* + * We must set the 'end' value in AdjustPixelClient so that the last dummy + * line in the B-tree doesn't contain a pixel height. + */ + + end = textPtr->end; + if (end == NULL) { + end = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + NULL, TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL)); + } + AdjustPixelClient(treePtr, defaultHeight, treePtr->rootPtr, + textPtr->start, end, useReference, treePtr->pixelReferences, + &counting); +} + +/* + *---------------------------------------------------------------------- + * * TkBTreeDestroy -- * * Delete a B-tree, recycling all of the storage it contains. * * Results: - * The tree given by treePtr is deleted. TreePtr should never - * again be used. + * The tree is deleted, so 'tree' should never again be used. * * Side effects: * Memory is freed. @@ -279,22 +465,382 @@ TkBTreeCreate(textPtr) */ void -TkBTreeDestroy(tree) - TkTextBTree tree; /* Pointer to tree to delete. */ +TkBTreeDestroy( + TkTextBTree tree) /* Tree to clean up. */ { BTree *treePtr = (BTree *) tree; + /* + * There's no need to loop over each client of the tree, calling + * 'TkBTreeRemoveClient', since the 'DestroyNode' will clean everything up + * itself. + */ + DestroyNode(treePtr->rootPtr); + if (treePtr->startEnd != NULL) { + ckfree((char *) treePtr->startEnd); + ckfree((char *) treePtr->startEndRef); + } ckfree((char *) treePtr); } /* *---------------------------------------------------------------------- * + * TkBTreeEpoch -- + * + * Return the epoch for the B-tree. This number is incremented any time + * anything changes in the tree. + * + * Results: + * The epoch number. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkBTreeEpoch( + TkTextBTree tree) /* Tree to get epoch for. */ +{ + BTree *treePtr = (BTree *) tree; + return treePtr->stateEpoch; +} + +/* + *---------------------------------------------------------------------- + * + * TkBTreeRemoveClient -- + * + * Remove a client widget from its B-tree, cleaning up the pixel arrays + * which it uses if necessary. If this is the last such widget, we also + * destroy the whole tree. + * + * Results: + * All tree-specific aspects of the given client are deleted. If no more + * references exist, then the given tree is also deleted (in which case + * 'tree' must not be used again). + * + * Side effects: + * Memory may be freed. + * + *---------------------------------------------------------------------- + */ + +void +TkBTreeRemoveClient( + TkTextBTree tree, /* Tree to remove client from. */ + TkText *textPtr) /* Client to remove. */ +{ + BTree *treePtr = (BTree *) tree; + int pixelReference = textPtr->pixelReference; + + if (treePtr->clients == 1) { + /* + * The last reference to the tree. + */ + + DestroyNode(treePtr->rootPtr); + ckfree((char *) treePtr); + return; + } else if (pixelReference == -1) { + /* + * A client which doesn't care about pixels. + */ + + treePtr->clients--; + } else { + /* + * Clean up pixel data for the given reference. + */ + + if (pixelReference == (treePtr->pixelReferences-1)) { + /* + * The widget we're removing has the last index, so deletion is + * easier. + */ + + RemovePixelClient(treePtr, treePtr->rootPtr, -1); + } else { + TkText *adjustPtr; + + RemovePixelClient(treePtr, treePtr->rootPtr, pixelReference); + + /* + * Now we need to adjust the 'pixelReference' of the peer widget + * whose storage we've just moved. + */ + + adjustPtr = treePtr->sharedTextPtr->peers; + while (adjustPtr != NULL) { + if (adjustPtr->pixelReference == treePtr->pixelReferences-1) { + adjustPtr->pixelReference = pixelReference; + break; + } + adjustPtr = adjustPtr->next; + } + if (adjustPtr == NULL) { + Tcl_Panic("Couldn't find text widget with correct reference"); + } + } + treePtr->pixelReferences--; + treePtr->clients--; + } + + if (textPtr->start != NULL || textPtr->end != NULL) { + AdjustStartEndRefs(treePtr, textPtr, TEXT_REMOVE_REFS); + } +} + +/* + *---------------------------------------------------------------------- + * + * AdjustStartEndRefs -- + * + * Modify B-tree's cache of start, end lines for the given text widget. + * + * Results: + * None. + * + * Side effects: + * The number of cached items may change (treePtr->startEndCount). + * + *---------------------------------------------------------------------- + */ + +static void +AdjustStartEndRefs( + BTree *treePtr, /* The entire B-tree. */ + TkText *textPtr, /* The text widget for which we want to adjust + * it's start and end cache. */ + int action) /* Action to perform. */ +{ + if (action & TEXT_REMOVE_REFS) { + int i = 0; + int count = 0; + + while (i < treePtr->startEndCount) { + if (i != count) { + treePtr->startEnd[count] = treePtr->startEnd[i]; + treePtr->startEndRef[count] = treePtr->startEndRef[i]; + } + if (treePtr->startEndRef[i] != textPtr) { + count++; + } + i++; + } + treePtr->startEndCount = count; + treePtr->startEnd = (TkTextLine **) + ckrealloc((char *) treePtr->startEnd, + sizeof(TkTextLine *) * count); + treePtr->startEndRef = (TkText **) + ckrealloc((char *) treePtr->startEndRef, + sizeof(TkText *) * count); + } + if ((action & TEXT_ADD_REFS) + && (textPtr->start != NULL || textPtr->end != NULL)) { + int count; + + if (textPtr->start != NULL) { + treePtr->startEndCount++; + } + if (textPtr->end != NULL) { + treePtr->startEndCount++; + } + + count = treePtr->startEndCount; + + treePtr->startEnd = (TkTextLine **) + ckrealloc((char *) treePtr->startEnd, + sizeof(TkTextLine *) * count); + treePtr->startEndRef = (TkText **) + ckrealloc((char *) treePtr->startEndRef, + sizeof(TkText *) * count); + + if (textPtr->start != NULL) { + count--; + treePtr->startEnd[count] = textPtr->start; + treePtr->startEndRef[count] = textPtr; + } + if (textPtr->end != NULL) { + count--; + treePtr->startEnd[count] = textPtr->end; + treePtr->startEndRef[count] = textPtr; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * AdjustPixelClient -- + * + * Utility function used to update all data structures for the existence + * of a new peer widget based on this B-tree, or for the modification of + * the start, end lines of an existing peer widget. + * + * Immediately _after_ calling this, treePtr->pixelReferences and + * treePtr->clients should be adjusted if needed (i.e. if this is a new + * peer). + * + * Results: + * None. + * + * Side effects: + * All the storage for Nodes and TkTextLines in the tree may be adjusted. + * + *---------------------------------------------------------------------- + */ + +static int +AdjustPixelClient( + BTree *treePtr, /* Pointer to tree. */ + int defaultHeight, /* Default pixel line height, which can be + * zero. */ + Node *nodePtr, /* Adjust from this node downwards. */ + TkTextLine *start, /* First line for this pixel client. */ + TkTextLine *end, /* Last line for this pixel client. */ + int useReference, /* pixel reference for the client we are + * adding or changing. */ + int newPixelReferences, /* New number of pixel references to this + * B-tree. */ + int *counting) /* References an integer which is zero if + * we're outside the relevant range for this + * client, and 1 if we're inside. */ +{ + int pixelCount = 0; + + /* + * Traverse entire tree down from nodePtr, reallocating pixel structures + * for each Node and TkTextLine, adding room for the new peer's pixel + * information (1 extra int per Node, 2 extra ints per TkTextLine). Also + * copy the information from the last peer into the new space (so it + * contains something sensible). + */ + + if (nodePtr->level != 0) { + Node *loopPtr = nodePtr->children.nodePtr; + + while (loopPtr != NULL) { + pixelCount += AdjustPixelClient(treePtr, defaultHeight, loopPtr, + start, end, useReference, newPixelReferences, counting); + loopPtr = loopPtr->nextPtr; + } + } else { + register TkTextLine *linePtr = nodePtr->children.linePtr; + + while (linePtr != NULL) { + if (!*counting && (linePtr == start)) { + *counting = 1; + } + if (*counting && (linePtr == end)) { + *counting = 0; + } + if (newPixelReferences != treePtr->pixelReferences) { + linePtr->pixels = (int *) ckrealloc((char *) linePtr->pixels, + sizeof(int) * 2 * newPixelReferences); + } + + /* + * Notice that for the very last line, we are never counting and + * therefore this always has a height of 0 and an epoch of 1. + */ + + linePtr->pixels[2*useReference] = (*counting ? defaultHeight : 0); + linePtr->pixels[2*useReference+1] = (*counting ? 0 : 1); + pixelCount += linePtr->pixels[2*useReference]; + + linePtr = linePtr->nextPtr; + } + } + if (newPixelReferences != treePtr->pixelReferences) { + nodePtr->numPixels = (int *) ckrealloc((char *) nodePtr->numPixels, + sizeof(int) * newPixelReferences); + } + nodePtr->numPixels[useReference] = pixelCount; + return pixelCount; +} + +/* + *---------------------------------------------------------------------- + * + * RemovePixelClient -- + * + * Utility function used to update all data structures for the removal of + * a peer widget which used to be based on this B-tree. + * + * Immediately _after_ calling this, treePtr->clients should be + * decremented. + * + * Results: + * None. + * + * Side effects: + * All the storage for Nodes and TkTextLines in the tree may be adjusted. + * + *---------------------------------------------------------------------- + */ + +static void +RemovePixelClient( + BTree *treePtr, /* Pointer to tree. */ + Node *nodePtr, /* Adjust from this node downwards. */ + int overwriteWithLast) /* Over-write this peer widget's information + * with the last one. */ +{ + /* + * Traverse entire tree down from nodePtr, reallocating pixel structures + * for each Node and TkTextLine, removing space allocated for one peer. If + * 'overwriteWithLast' is not -1, then copy the information which was in + * the last slot on top of one of the others (i.e. it's not the last one + * we're deleting). + */ + + if (overwriteWithLast != -1) { + nodePtr->numPixels[overwriteWithLast] = + nodePtr->numPixels[treePtr->pixelReferences-1]; + } + if (treePtr->pixelReferences == 1) { + nodePtr->numPixels = NULL; + } else { + nodePtr->numPixels = (int *) ckrealloc((char *) nodePtr->numPixels, + sizeof(int) * (treePtr->pixelReferences - 1)); + } + if (nodePtr->level != 0) { + nodePtr = nodePtr->children.nodePtr; + while (nodePtr != NULL) { + RemovePixelClient(treePtr, nodePtr, overwriteWithLast); + nodePtr = nodePtr->nextPtr; + } + } else { + register TkTextLine *linePtr = nodePtr->children.linePtr; + while (linePtr != NULL) { + if (overwriteWithLast != -1) { + linePtr->pixels[2*overwriteWithLast] = + linePtr->pixels[2*(treePtr->pixelReferences-1)]; + linePtr->pixels[1+2*overwriteWithLast] = + linePtr->pixels[1+2*(treePtr->pixelReferences-1)]; + } + if (treePtr->pixelReferences == 1) { + linePtr->pixels = NULL; + } else { + linePtr->pixels = (int *) ckrealloc((char *) linePtr->pixels, + sizeof(int) * 2 * (treePtr->pixelReferences-1)); + } + linePtr = linePtr->nextPtr; + } + } +} + +/* + *---------------------------------------------------------------------- + * * DestroyNode -- * - * This is a recursive utility procedure used during the deletion - * of a B-tree. + * This is a recursive utility function used during the deletion of a + * B-tree. * * Results: * None. @@ -306,8 +852,8 @@ TkBTreeDestroy(tree) */ static void -DestroyNode(nodePtr) - register Node *nodePtr; +DestroyNode( + register Node *nodePtr) /* Destroy from this node downwards. */ { if (nodePtr->level == 0) { TkTextLine *linePtr; @@ -321,6 +867,7 @@ DestroyNode(nodePtr) linePtr->segPtr = segPtr->nextPtr; (*segPtr->typePtr->deleteProc)(segPtr, linePtr, 1); } + ckfree((char *) linePtr->pixels); ckfree((char *) linePtr); } } else { @@ -333,6 +880,7 @@ DestroyNode(nodePtr) } } DeleteSummaries(nodePtr->summaryPtr); + ckfree((char *) nodePtr->numPixels); ckfree((char *) nodePtr); } @@ -341,8 +889,8 @@ DestroyNode(nodePtr) * * DeleteSummaries -- * - * Free up all of the memory in a list of tag summaries associated - * with a node. + * Free up all of the memory in a list of tag summaries associated with a + * node. * * Results: * None. @@ -354,11 +902,12 @@ DestroyNode(nodePtr) */ static void -DeleteSummaries(summaryPtr) - register Summary *summaryPtr; /* First in list of node's tag - * summaries. */ +DeleteSummaries( + register Summary *summaryPtr) + /* First in list of node's tag summaries. */ { register Summary *nextPtr; + while (summaryPtr != NULL) { nextPtr = summaryPtr->nextPtr; ckfree((char *) summaryPtr); @@ -369,6 +918,74 @@ DeleteSummaries(summaryPtr) /* *---------------------------------------------------------------------- * + * TkBTreeAdjustPixelHeight -- + * + * Adjust the pixel height of a given logical line to the specified + * value. + * + * Results: + * Total number of valid pixels currently known in the tree. + * + * Side effects: + * Updates overall data structures so pixel height count is consistent. + * + *---------------------------------------------------------------------- + */ + +int +TkBTreeAdjustPixelHeight( + const TkText *textPtr, /* Client of the B-tree. */ + register TkTextLine *linePtr, + /* The logical line to update. */ + int newPixelHeight, /* The line's known height in pixels. */ + int mergedLogicalLines) /* The number of extra logical lines which + * have been merged with this one (due to + * elided eols). They will have their pixel + * height set to zero, and the total pixel + * height associated with the given + * linePtr. */ +{ + register Node *nodePtr; + int changeToPixelCount; /* Counts change to total number of pixels in + * file. */ + int pixelReference = textPtr->pixelReference; + + changeToPixelCount = newPixelHeight - linePtr->pixels[2 * pixelReference]; + + /* + * Increment the pixel counts in all the parent nodes of the current line, + * then rebalance the tree if necessary. + */ + + nodePtr = linePtr->parentPtr; + nodePtr->numPixels[pixelReference] += changeToPixelCount; + + while (nodePtr->parentPtr != NULL) { + nodePtr = nodePtr->parentPtr; + nodePtr->numPixels[pixelReference] += changeToPixelCount; + } + + linePtr->pixels[2 * pixelReference] = newPixelHeight; + + /* + * Any merged logical lines must have their height set to zero. + */ + + while (mergedLogicalLines-- > 0) { + linePtr = TkBTreeNextLine(textPtr, linePtr); + TkBTreeAdjustPixelHeight(textPtr, linePtr, 0, 0); + } + + /* + * Return total number of pixels in the tree. + */ + + return nodePtr->numPixels[pixelReference]; +} + +/* + *---------------------------------------------------------------------- + * * TkBTreeInsertChars -- * * Insert characters at a given position in a B-tree. @@ -377,53 +994,68 @@ DeleteSummaries(summaryPtr) * None. * * Side effects: - * Characters are added to the B-tree at the given position. - * If the string contains newlines, new lines will be added, - * which could cause the structure of the B-tree to change. + * Characters are added to the B-tree at the given position. If the + * string contains newlines, new lines will be added, which could cause + * the structure of the B-tree to change. * *---------------------------------------------------------------------- */ void -TkBTreeInsertChars(indexPtr, string) - register TkTextIndex *indexPtr; /* Indicates where to insert text. - * When the procedure returns, this - * index is no longer valid because - * of changes to the segment - * structure. */ - CONST char *string; /* Pointer to bytes to insert (may - * contain newlines, must be null- - * terminated). */ +TkBTreeInsertChars( + TkTextBTree tree, /* Tree to insert into. */ + register TkTextIndex *indexPtr, + /* Indicates where to insert text. When the + * function returns, this index is no longer + * valid because of changes to the segment + * structure. */ + const char *string) /* Pointer to bytes to insert (may contain + * newlines, must be null-terminated). */ { register Node *nodePtr; - register TkTextSegment *prevPtr; /* The segment just before the first - * new segment (NULL means new segment - * is at beginning of line). */ - TkTextSegment *curPtr; /* Current segment; new characters - * are inserted just after this one. - * NULL means insert at beginning of - * line. */ - TkTextLine *linePtr; /* Current line (new segments are - * added to this line). */ + register TkTextSegment *prevPtr; + /* The segment just before the first new + * segment (NULL means new segment is at + * beginning of line). */ + TkTextSegment *curPtr; /* Current segment; new characters are + * inserted just after this one. NULL means + * insert at beginning of line. */ + TkTextLine *linePtr; /* Current line (new segments are added to + * this line). */ register TkTextSegment *segPtr; TkTextLine *newLinePtr; - int chunkSize; /* # characters in current chunk. */ - register CONST char *eol; /* Pointer to character just after last - * one in current chunk. */ - int changeToLineCount; /* Counts change to total number of - * lines in file. */ + int chunkSize; /* # characters in current chunk. */ + register const char *eol; /* Pointer to character just after last one in + * current chunk. */ + int changeToLineCount; /* Counts change to total number of lines in + * file. */ + int *changeToPixelCount; /* Counts change to total number of pixels in + * file. */ + int ref; + int pixels[PIXEL_CLIENTS]; + BTree *treePtr = (BTree *) tree; + treePtr->stateEpoch++; prevPtr = SplitSeg(indexPtr); linePtr = indexPtr->linePtr; curPtr = prevPtr; /* - * Chop the string up into lines and create a new segment for - * each line, plus a new line for the leftovers from the - * previous line. + * Chop the string up into lines and create a new segment for each line, + * plus a new line for the leftovers from the previous line. */ changeToLineCount = 0; + if (treePtr->pixelReferences > PIXEL_CLIENTS) { + changeToPixelCount = (int *) + ckalloc(sizeof(int) * treePtr->pixelReferences); + } else { + changeToPixelCount = pixels; + } + for (ref = 0; ref < treePtr->pixelReferences; ref++) { + changeToPixelCount[ref] = 0; + } + while (*string != 0) { for (eol = string; *eol != 0; eol++) { if (*eol == '\n') { @@ -450,15 +1082,30 @@ TkBTreeInsertChars(indexPtr, string) } /* - * The chunk ended with a newline, so create a new TkTextLine - * and move the remainder of the old line to it. + * The chunk ended with a newline, so create a new TkTextLine and move + * the remainder of the old line to it. */ newLinePtr = (TkTextLine *) ckalloc(sizeof(TkTextLine)); + newLinePtr->pixels = (int *) + ckalloc(sizeof(int) * 2 * treePtr->pixelReferences); + newLinePtr->parentPtr = linePtr->parentPtr; newLinePtr->nextPtr = linePtr->nextPtr; linePtr->nextPtr = newLinePtr; newLinePtr->segPtr = segPtr->nextPtr; + + /* + * Set up a starting default height, which will be re-adjusted later. + * We need to do this for each referenced widget. + */ + + for (ref = 0; ref < treePtr->pixelReferences; ref++) { + newLinePtr->pixels[2 * ref] = linePtr->pixels[2 * ref]; + newLinePtr->pixels[2 * ref + 1] = 0; + changeToPixelCount[ref] += newLinePtr->pixels[2 * ref]; + } + segPtr->nextPtr = NULL; linePtr = newLinePtr; curPtr = NULL; @@ -468,8 +1115,18 @@ TkBTreeInsertChars(indexPtr, string) } /* - * Cleanup the starting line for the insertion, plus the ending - * line if it's different. + * I don't believe it's possible for either of the two lines passed to + * this function to be the last line of text, but the function is robust + * to that case anyway. (We must never re-calculated the line height of + * the last line). + */ + + TkTextInvalidateLineMetrics(treePtr->sharedTextPtr, NULL, + indexPtr->linePtr, changeToLineCount, TK_TEXT_INVALIDATE_INSERT); + + /* + * Cleanup the starting line for the insertion, plus the ending line if + * it's different. */ CleanupLine(indexPtr->linePtr); @@ -478,18 +1135,25 @@ TkBTreeInsertChars(indexPtr, string) } /* - * Increment the line counts in all the parent nodes of the insertion - * point, then rebalance the tree if necessary. + * Increment the line and pixel counts in all the parent nodes of the + * insertion point, then rebalance the tree if necessary. */ for (nodePtr = linePtr->parentPtr ; nodePtr != NULL; nodePtr = nodePtr->parentPtr) { nodePtr->numLines += changeToLineCount; + for (ref = 0; ref < treePtr->pixelReferences; ref++) { + nodePtr->numPixels[ref] += changeToPixelCount[ref]; + } + } + if (treePtr->pixelReferences > PIXEL_CLIENTS) { + ckfree((char *) changeToPixelCount); } + nodePtr = linePtr->parentPtr; nodePtr->numChildren += changeToLineCount; if (nodePtr->numChildren > MAX_CHILDREN) { - Rebalance((BTree *) indexPtr->tree, nodePtr); + Rebalance(treePtr, nodePtr); } if (tkBTreeDebug) { @@ -502,40 +1166,41 @@ TkBTreeInsertChars(indexPtr, string) * * SplitSeg -- * - * This procedure is called before adding or deleting - * segments. It does three things: (a) it finds the segment - * containing indexPtr; (b) if there are several such - * segments (because some segments have zero length) then - * it picks the first segment that does not have left - * gravity; (c) if the index refers to the middle of - * a segment then it splits the segment so that the - * index now refers to the beginning of a segment. + * This function is called before adding or deleting segments. It does + * three things: (a) it finds the segment containing indexPtr; (b) if + * there are several such segments (because some segments have zero + * length) then it picks the first segment that does not have left + * gravity; (c) if the index refers to the middle of a segment then it + * splits the segment so that the index now refers to the beginning of a + * segment. * * Results: - * The return value is a pointer to the segment just - * before the segment corresponding to indexPtr (as - * described above). If the segment corresponding to - * indexPtr is the first in its line then the return + * The return value is a pointer to the segment just before the segment + * corresponding to indexPtr (as described above). If the segment + * corresponding to indexPtr is the first in its line then the return * value is NULL. * * Side effects: - * The segment referred to by indexPtr is split unless - * indexPtr refers to its first character. + * The segment referred to by indexPtr is split unless indexPtr refers to + * its first character. * *-------------------------------------------------------------- */ static TkTextSegment * -SplitSeg(indexPtr) - TkTextIndex *indexPtr; /* Index identifying position - * at which to split a segment. */ +SplitSeg( + TkTextIndex *indexPtr) /* Index identifying position at which to + * split a segment. */ { TkTextSegment *prevPtr, *segPtr; - int count; + TkTextLine *linePtr; + int count = indexPtr->byteIndex; - for (count = indexPtr->byteIndex, prevPtr = NULL, - segPtr = indexPtr->linePtr->segPtr; segPtr != NULL; - count -= segPtr->size, prevPtr = segPtr, segPtr = segPtr->nextPtr) { + linePtr = indexPtr->linePtr; + prevPtr = NULL; + segPtr = linePtr->segPtr; + + while (segPtr != NULL) { if (segPtr->size > count) { if (count == 0) { return prevPtr; @@ -551,8 +1216,26 @@ SplitSeg(indexPtr) && !segPtr->typePtr->leftGravity) { return prevPtr; } + + count -= segPtr->size; + prevPtr = segPtr; + segPtr = segPtr->nextPtr; + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through eliding + * of a newline. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); + if (linePtr == NULL) { + /* + * Reached end of the text. + */ + } + segPtr = linePtr->segPtr; + } } - panic("SplitSeg reached end of line!"); + Tcl_Panic("SplitSeg reached end of line!"); return NULL; } @@ -561,36 +1244,34 @@ SplitSeg(indexPtr) * * CleanupLine -- * - * This procedure is called after modifications have been - * made to a line. It scans over all of the segments in - * the line, giving each a chance to clean itself up, e.g. - * by merging with the following segments, updating internal - * information, etc. + * This function is called after modifications have been made to a line. + * It scans over all of the segments in the line, giving each a chance to + * clean itself up, e.g. by merging with the following segments, updating + * internal information, etc. * * Results: * None. * * Side effects: - * Depends on what the segment-specific cleanup procedures do. + * Depends on what the segment-specific cleanup functions do. * *-------------------------------------------------------------- */ static void -CleanupLine(linePtr) - TkTextLine *linePtr; /* Line to be cleaned up. */ +CleanupLine( + TkTextLine *linePtr) /* Line to be cleaned up. */ { TkTextSegment *segPtr, **prevPtrPtr; int anyChanges; /* - * Make a pass over all of the segments in the line, giving each - * a chance to clean itself up. This could potentially change - * the structure of the line, e.g. by merging two segments - * together or having two segments cancel themselves; if so, - * then repeat the whole process again, since the first structure - * change might make other structure changes possible. Repeat - * until eventually there are no changes. + * Make a pass over all of the segments in the line, giving each a chance + * to clean itself up. This could potentially change the structure of the + * line, e.g. by merging two segments together or having two segments + * cancel themselves; if so, then repeat the whole process again, since + * the first structure change might make other structure changes possible. + * Repeat until eventually there are no changes. */ while (1) { @@ -614,49 +1295,55 @@ CleanupLine(linePtr) /* *---------------------------------------------------------------------- * - * TkBTreeDeleteChars -- + * TkBTreeDeleteIndexRange -- * - * Delete a range of characters from a B-tree. The caller - * must make sure that the final newline of the B-tree is - * never deleted. + * Delete a range of characters from a B-tree. The caller must make sure + * that the final newline of the B-tree is never deleted. * * Results: * None. * * Side effects: - * Information is deleted from the B-tree. This can cause the - * internal structure of the B-tree to change. Note: because - * of changes to the B-tree structure, the indices pointed - * to by index1Ptr and index2Ptr should not be used after this - * procedure returns. + * Information is deleted from the B-tree. This can cause the internal + * structure of the B-tree to change. Note: because of changes to the + * B-tree structure, the indices pointed to by index1Ptr and index2Ptr + * should not be used after this function returns. * *---------------------------------------------------------------------- */ void -TkBTreeDeleteChars(index1Ptr, index2Ptr) - register TkTextIndex *index1Ptr; /* Indicates first character that is - * to be deleted. */ - register TkTextIndex *index2Ptr; /* Indicates character just after the - * last one that is to be deleted. */ +TkBTreeDeleteIndexRange( + TkTextBTree tree, /* Tree to delete from. */ + register TkTextIndex *index1Ptr, + /* Indicates first character that is to be + * deleted. */ + register TkTextIndex *index2Ptr) + /* Indicates character just after the last one + * that is to be deleted. */ { - TkTextSegment *prevPtr; /* The segment just before the start - * of the deletion range. */ - TkTextSegment *lastPtr; /* The segment just after the end - * of the deletion range. */ + TkTextSegment *prevPtr; /* The segment just before the start of the + * deletion range. */ + TkTextSegment *lastPtr; /* The segment just after the end of the + * deletion range. */ TkTextSegment *segPtr, *nextPtr; TkTextLine *curLinePtr; Node *curNodePtr, *nodePtr; + int changeToLineCount = 0; + int ref; + BTree *treePtr = (BTree *) tree; + + treePtr->stateEpoch++; /* - * Tricky point: split at index2Ptr first; otherwise the split - * at index2Ptr may invalidate segPtr and/or prevPtr. + * Tricky point: split at index2Ptr first; otherwise the split at + * index2Ptr may invalidate segPtr and/or prevPtr. */ lastPtr = SplitSeg(index2Ptr); if (lastPtr != NULL) { lastPtr = lastPtr->nextPtr; - } else { + } else { lastPtr = index2Ptr->linePtr->segPtr; } prevPtr = SplitSeg(index1Ptr); @@ -673,18 +1360,19 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) */ curLinePtr = index1Ptr->linePtr; + curNodePtr = curLinePtr->parentPtr; while (segPtr != lastPtr) { if (segPtr == NULL) { TkTextLine *nextLinePtr; /* - * We just ran off the end of a line. First find the - * next line, then go back to the old line and delete it - * (unless it's the starting line for the range). + * We just ran off the end of a line. First find the next line, + * then go back to the old line and delete it (unless it's the + * starting line for the range). */ - nextLinePtr = TkBTreeNextLine(curLinePtr); + nextLinePtr = TkBTreeNextLine(NULL, curLinePtr); if (curLinePtr != index1Ptr->linePtr) { if (curNodePtr == index1Ptr->linePtr->parentPtr) { index1Ptr->linePtr->nextPtr = curLinePtr->nextPtr; @@ -694,16 +1382,50 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) for (nodePtr = curNodePtr; nodePtr != NULL; nodePtr = nodePtr->parentPtr) { nodePtr->numLines--; + for (ref = 0; ref < treePtr->pixelReferences; ref++) { + nodePtr->numPixels[ref] -= curLinePtr->pixels[2*ref]; + } } + changeToLineCount++; curNodePtr->numChildren--; + + /* + * Check if we need to adjust any partial clients. + */ + + if (treePtr->startEnd != NULL) { + int checkCount = 0; + + while (checkCount < treePtr->startEndCount) { + if (treePtr->startEnd[checkCount] == curLinePtr) { + TkText *peer = treePtr->startEndRef[checkCount]; + + /* + * We're deleting a line which is the start or end + * of a current client. This means we need to + * adjust that client. + */ + + treePtr->startEnd[checkCount] = nextLinePtr; + if (peer->start == curLinePtr) { + peer->start = nextLinePtr; + } + if (peer->end == curLinePtr) { + peer->end = nextLinePtr; + } + } + checkCount++; + } + } + ckfree((char *) curLinePtr->pixels); ckfree((char *) curLinePtr); } curLinePtr = nextLinePtr; segPtr = curLinePtr->segPtr; /* - * If the node is empty then delete it and its parents, - * recursively upwards until a non-empty node is found. + * If the node is empty then delete it and its parents recursively + * upwards until a non-empty node is found. */ while (curNodePtr->numChildren == 0) { @@ -730,8 +1452,8 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) nextPtr = segPtr->nextPtr; if ((*segPtr->typePtr->deleteProc)(segPtr, curLinePtr, 0) != 0) { /* - * This segment refuses to die. Move it to prevPtr and - * advance prevPtr if the segment has left gravity. + * This segment refuses to die. Move it to prevPtr and advance + * prevPtr if the segment has left gravity. */ if (prevPtr == NULL) { @@ -749,8 +1471,8 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) } /* - * If the beginning and end of the deletion range are in different - * lines, join the two lines together and discard the ending line. + * If the beginning and end of the deletion range are in different lines, + * join the two lines together and discard the ending line. */ if (index1Ptr->linePtr != index2Ptr->linePtr) { @@ -766,7 +1488,11 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) for (nodePtr = curNodePtr; nodePtr != NULL; nodePtr = nodePtr->parentPtr) { nodePtr->numLines--; + for (ref = 0; ref < treePtr->pixelReferences; ref++) { + nodePtr->numPixels[ref] -= index2Ptr->linePtr->pixels[2*ref]; + } } + changeToLineCount++; curNodePtr->numChildren--; prevLinePtr = curNodePtr->children.linePtr; if (prevLinePtr == index2Ptr->linePtr) { @@ -777,7 +1503,43 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) } prevLinePtr->nextPtr = index2Ptr->linePtr->nextPtr; } + + /* + * Check if we need to adjust any partial clients. In this case if + * we're deleting the line, we actually move back to the previous line + * for our (start,end) storage. We do this because we still want the + * portion of the second line that still exists to be in the start,end + * range. + */ + + if (treePtr->startEnd != NULL) { + int checkCount = 0; + + while (checkCount < treePtr->startEndCount && + treePtr->startEnd[checkCount] != NULL) { + if (treePtr->startEnd[checkCount] == index2Ptr->linePtr) { + TkText *peer = treePtr->startEndRef[checkCount]; + + /* + * We're deleting a line which is the start or end of a + * current client. This means we need to adjust that + * client. + */ + + treePtr->startEnd[checkCount] = index1Ptr->linePtr; + if (peer->start == index2Ptr->linePtr) { + peer->start = index1Ptr->linePtr; + } + if (peer->end == index2Ptr->linePtr) { + peer->end = index1Ptr->linePtr; + } + } + checkCount++; + } + } + ckfree((char *) index2Ptr->linePtr->pixels); ckfree((char *) index2Ptr->linePtr); + Rebalance((BTree *) index2Ptr->tree, curNodePtr); } @@ -788,6 +1550,19 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) CleanupLine(index1Ptr->linePtr); /* + * This line now needs to have its height recalculated. For safety, ensure + * we don't call this function with the last artificial line of text. I + * _believe_ that it isn't possible to get this far with the last line, + * but it is good to be safe. + */ + + if (TkBTreeNextLine(NULL, index1Ptr->linePtr) != NULL) { + TkTextInvalidateLineMetrics(treePtr->sharedTextPtr, NULL, + index1Ptr->linePtr, changeToLineCount, + TK_TEXT_INVALIDATE_DELETE); + } + + /* * Lastly, rebalance the first node of the range. */ @@ -805,8 +1580,8 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) * Find a particular line in a B-tree based on its line number. * * Results: - * The return value is a pointer to the line structure for the - * line whose index is "line", or NULL if no such line exists. + * The return value is a pointer to the line structure for the line whose + * index is "line", or NULL if no such line exists. * * Side effects: * None. @@ -815,34 +1590,54 @@ TkBTreeDeleteChars(index1Ptr, index2Ptr) */ TkTextLine * -TkBTreeFindLine(tree, line) - TkTextBTree tree; /* B-tree in which to find line. */ - int line; /* Index of desired line. */ +TkBTreeFindLine( + TkTextBTree tree, /* B-tree in which to find line. */ + const TkText *textPtr, /* Relative to this client of the B-tree. */ + int line) /* Index of desired line. */ { BTree *treePtr = (BTree *) tree; register Node *nodePtr; register TkTextLine *linePtr; - int linesLeft; + + if (treePtr == NULL) { + treePtr = (BTree *) textPtr->sharedTextPtr->tree; + } nodePtr = treePtr->rootPtr; - linesLeft = line; if ((line < 0) || (line >= nodePtr->numLines)) { return NULL; } /* - * Work down through levels of the tree until a node is found at - * level 0. + * Check for any start/end offset for this text widget. + */ + + if (textPtr != NULL) { + if (textPtr->start != NULL) { + line += TkBTreeLinesTo(NULL, textPtr->start); + if (line >= nodePtr->numLines) { + return NULL; + } + } + if (textPtr->end != NULL) { + if (line > TkBTreeLinesTo(NULL, textPtr->end)) { + return NULL; + } + } + } + + /* + * Work down through levels of the tree until a node is found at level 0. */ while (nodePtr->level != 0) { for (nodePtr = nodePtr->children.nodePtr; - nodePtr->numLines <= linesLeft; + nodePtr->numLines <= line; nodePtr = nodePtr->nextPtr) { if (nodePtr == NULL) { - panic("TkBTreeFindLine ran out of nodes"); + Tcl_Panic("TkBTreeFindLine ran out of nodes"); } - linesLeft -= nodePtr->numLines; + line -= nodePtr->numLines; } } @@ -850,12 +1645,90 @@ TkBTreeFindLine(tree, line) * Work through the lines attached to the level-0 node. */ - for (linePtr = nodePtr->children.linePtr; linesLeft > 0; + for (linePtr = nodePtr->children.linePtr; line > 0; linePtr = linePtr->nextPtr) { if (linePtr == NULL) { - panic("TkBTreeFindLine ran out of lines"); + Tcl_Panic("TkBTreeFindLine ran out of lines"); } - linesLeft -= 1; + line -= 1; + } + return linePtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkBTreeFindPixelLine -- + * + * Find a particular line in a B-tree based on its pixel count. + * + * Results: + * The return value is a pointer to the line structure for the line which + * contains the pixel "pixels", or NULL if no such line exists. If the + * first line is of height 20, then pixels 0-19 will return it, and + * pixels = 20 will return the next line. + * + * If pixelOffset is non-NULL, it is set to the amount by which 'pixels' + * exceeds the first pixel located on the returned line. This should + * always be non-negative. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkTextLine * +TkBTreeFindPixelLine( + TkTextBTree tree, /* B-tree to use. */ + const TkText *textPtr, /* Relative to this client of the B-tree. */ + int pixels, /* Pixel index of desired line. */ + int *pixelOffset) /* Used to return offset. */ +{ + BTree *treePtr = (BTree *) tree; + register Node *nodePtr; + register TkTextLine *linePtr; + int pixelReference = textPtr->pixelReference; + + nodePtr = treePtr->rootPtr; + + if ((pixels < 0) || (pixels > nodePtr->numPixels[pixelReference])) { + return NULL; + } + + if (nodePtr->numPixels[pixelReference] == 0) { + Tcl_Panic("TkBTreeFindPixelLine called with empty window"); + } + + /* + * Work down through levels of the tree until a node is found at level 0. + */ + + while (nodePtr->level != 0) { + for (nodePtr = nodePtr->children.nodePtr; + nodePtr->numPixels[pixelReference] <= pixels; + nodePtr = nodePtr->nextPtr) { + if (nodePtr == NULL) { + Tcl_Panic("TkBTreeFindPixelLine ran out of nodes"); + } + pixels -= nodePtr->numPixels[pixelReference]; + } + } + + /* + * Work through the lines attached to the level-0 node. + */ + + for (linePtr = nodePtr->children.linePtr; + linePtr->pixels[2 * pixelReference] < pixels; + linePtr = linePtr->nextPtr) { + if (linePtr == NULL) { + Tcl_Panic("TkBTreeFindPixelLine ran out of lines"); + } + pixels -= linePtr->pixels[2 * pixelReference]; + } + if (pixelOffset != NULL && linePtr != NULL) { + *pixelOffset = pixels; } return linePtr; } @@ -865,13 +1738,13 @@ TkBTreeFindLine(tree, line) * * TkBTreeNextLine -- * - * Given an existing line in a B-tree, this procedure locates the - * next line in the B-tree. This procedure is used for scanning - * through the B-tree. + * Given an existing line in a B-tree, this function locates the next + * line in the B-tree. This function is used for scanning through the + * B-tree. * * Results: - * The return value is a pointer to the line that immediately - * follows linePtr, or NULL if there is no such line. + * The return value is a pointer to the line that immediately follows + * linePtr, or NULL if there is no such line. * * Side effects: * None. @@ -880,20 +1753,25 @@ TkBTreeFindLine(tree, line) */ TkTextLine * -TkBTreeNextLine(linePtr) - register TkTextLine *linePtr; /* Pointer to existing line in - * B-tree. */ +TkBTreeNextLine( + const TkText *textPtr, /* Next line in the context of this client. */ + register TkTextLine *linePtr) + /* Pointer to existing line in B-tree. */ { register Node *nodePtr; if (linePtr->nextPtr != NULL) { - return linePtr->nextPtr; + if (textPtr != NULL && (linePtr == textPtr->end)) { + return NULL; + } else { + return linePtr->nextPtr; + } } /* * This was the last line associated with the particular parent node. - * Search up the tree for the next node, then search down from that - * node to find the first line. + * Search up the tree for the next node, then search down from that node + * to find the first line. */ for (nodePtr = linePtr->parentPtr; ; nodePtr = nodePtr->parentPtr) { @@ -902,7 +1780,7 @@ TkBTreeNextLine(linePtr) break; } if (nodePtr->parentPtr == NULL) { - return (TkTextLine *) NULL; + return NULL; } } while (nodePtr->level > 0) { @@ -916,13 +1794,13 @@ TkBTreeNextLine(linePtr) * * TkBTreePreviousLine -- * - * Given an existing line in a B-tree, this procedure locates the - * previous line in the B-tree. This procedure is used for scanning - * through the B-tree in the reverse direction. + * Given an existing line in a B-tree, this function locates the previous + * line in the B-tree. This function is used for scanning through the + * B-tree in the reverse direction. * * Results: - * The return value is a pointer to the line that immediately - * preceeds linePtr, or NULL if there is no such line. + * The return value is a pointer to the line that immediately preceeds + * linePtr, or NULL if there is no such line. * * Side effects: * None. @@ -931,25 +1809,31 @@ TkBTreeNextLine(linePtr) */ TkTextLine * -TkBTreePreviousLine(linePtr) - register TkTextLine *linePtr; /* Pointer to existing line in - * B-tree. */ +TkBTreePreviousLine( + TkText *textPtr, /* Relative to this client of the B-tree. */ + register TkTextLine *linePtr) + /* Pointer to existing line in B-tree. */ { register Node *nodePtr; register Node *node2Ptr; register TkTextLine *prevPtr; + if (textPtr != NULL && textPtr->start == linePtr) { + return NULL; + } + /* * Find the line under this node just before the starting line. */ - prevPtr = linePtr->parentPtr->children.linePtr; /* First line at leaf */ + + prevPtr = linePtr->parentPtr->children.linePtr; /* First line at leaf. */ while (prevPtr != linePtr) { if (prevPtr->nextPtr == linePtr) { return prevPtr; } prevPtr = prevPtr->nextPtr; - if (prevPtr == (TkTextLine *) NULL) { - panic("TkBTreePreviousLine ran out of lines"); + if (prevPtr == NULL) { + Tcl_Panic("TkBTreePreviousLine ran out of lines"); } } @@ -958,15 +1842,16 @@ TkBTreePreviousLine(linePtr) * Search up the tree for the previous node, then search down from that * node to find its last line. */ + for (nodePtr = linePtr->parentPtr; ; nodePtr = nodePtr->parentPtr) { - if (nodePtr == (Node *) NULL || nodePtr->parentPtr == (Node *) NULL) { - return (TkTextLine *) NULL; + if (nodePtr == NULL || nodePtr->parentPtr == NULL) { + return NULL; } if (nodePtr != nodePtr->parentPtr->children.nodePtr) { break; } } - for (node2Ptr = nodePtr->parentPtr->children.nodePtr; ; + for (node2Ptr = nodePtr->parentPtr->children.nodePtr; ; node2Ptr = node2Ptr->children.nodePtr) { while (node2Ptr->nextPtr != nodePtr) { node2Ptr = node2Ptr->nextPtr; @@ -974,10 +1859,10 @@ TkBTreePreviousLine(linePtr) if (node2Ptr->level == 0) { break; } - nodePtr = (Node *)NULL; + nodePtr = NULL; } for (prevPtr = node2Ptr->children.linePtr ; ; prevPtr = prevPtr->nextPtr) { - if (prevPtr->nextPtr == (TkTextLine *) NULL) { + if (prevPtr->nextPtr == NULL) { return prevPtr; } } @@ -986,10 +1871,15 @@ TkBTreePreviousLine(linePtr) /* *---------------------------------------------------------------------- * - * TkBTreeLineIndex -- + * TkBTreePixelsTo -- * - * Given a pointer to a line in a B-tree, return the numerical - * index of that line. + * Given a pointer to a line in a B-tree, return the numerical pixel + * index of the top of that line (i.e. the result does not include the + * height of the given line). + * + * Since the last line of text (the artificial one) has zero height by + * defintion, calling this with the last line will return the total + * number of pixels in the widget. * * Results: * The result is the index of linePtr within the tree, where 0 @@ -1002,17 +1892,78 @@ TkBTreePreviousLine(linePtr) */ int -TkBTreeLineIndex(linePtr) - TkTextLine *linePtr; /* Pointer to existing line in - * B-tree. */ +TkBTreePixelsTo( + const TkText *textPtr, /* Relative to this client of the B-tree. */ + TkTextLine *linePtr) /* Pointer to existing line in B-tree. */ +{ + register TkTextLine *linePtr2; + register Node *nodePtr, *parentPtr; + int index; + int pixelReference = textPtr->pixelReference; + + /* + * First count how many pixels precede this line in its level-0 node. + */ + + nodePtr = linePtr->parentPtr; + index = 0; + for (linePtr2 = nodePtr->children.linePtr; linePtr2 != linePtr; + linePtr2 = linePtr2->nextPtr) { + if (linePtr2 == NULL) { + Tcl_Panic("TkBTreePixelsTo couldn't find line"); + } + index += linePtr2->pixels[2 * pixelReference]; + } + + /* + * Now work up through the levels of the tree one at a time, counting how + * many pixels are in nodes preceding the current node. + */ + + for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL; + nodePtr = parentPtr, parentPtr = parentPtr->parentPtr) { + register Node *nodePtr2; + + for (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr; + nodePtr2 = nodePtr2->nextPtr) { + if (nodePtr2 == NULL) { + Tcl_Panic("TkBTreePixelsTo couldn't find node"); + } + index += nodePtr2->numPixels[pixelReference]; + } + } + return index; +} + +/* + *---------------------------------------------------------------------- + * + * TkBTreeLinesTo -- + * + * Given a pointer to a line in a B-tree, return the numerical index of + * that line. + * + * Results: + * The result is the index of linePtr within the tree, where 0 + * corresponds to the first line in the tree. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkBTreeLinesTo( + const TkText *textPtr, /* Relative to this client of the B-tree. */ + TkTextLine *linePtr) /* Pointer to existing line in B-tree. */ { register TkTextLine *linePtr2; register Node *nodePtr, *parentPtr, *nodePtr2; int index; /* - * First count how many lines precede this one in its level-0 - * node. + * First count how many lines precede this one in its level-0 node. */ nodePtr = linePtr->parentPtr; @@ -1020,15 +1971,14 @@ TkBTreeLineIndex(linePtr) for (linePtr2 = nodePtr->children.linePtr; linePtr2 != linePtr; linePtr2 = linePtr2->nextPtr) { if (linePtr2 == NULL) { - panic("TkBTreeLineIndex couldn't find line"); + Tcl_Panic("TkBTreeLinesTo couldn't find line"); } index += 1; } /* - * Now work up through the levels of the tree one at a time, - * counting how many lines are in nodes preceding the current - * node. + * Now work up through the levels of the tree one at a time, counting how + * many lines are in nodes preceding the current node. */ for (parentPtr = nodePtr->parentPtr ; parentPtr != NULL; @@ -1036,21 +1986,48 @@ TkBTreeLineIndex(linePtr) for (nodePtr2 = parentPtr->children.nodePtr; nodePtr2 != nodePtr; nodePtr2 = nodePtr2->nextPtr) { if (nodePtr2 == NULL) { - panic("TkBTreeLineIndex couldn't find node"); + Tcl_Panic("TkBTreeLinesTo couldn't find node"); } index += nodePtr2->numLines; } } + if (textPtr != NULL) { + /* + * The index to return must be relative to textPtr, not to the entire + * tree. Take care to never return a negative index when linePtr + * denotes a line before -startline, or an index larger than the + * number of lines in textPtr when linePtr is a line past -endline. + */ + + int indexStart, indexEnd; + + if (textPtr->start != NULL) { + indexStart = TkBTreeLinesTo(NULL, textPtr->start); + } else { + indexStart = 0; + } + if (textPtr->end != NULL) { + indexEnd = TkBTreeLinesTo(NULL, textPtr->end); + } else { + indexEnd = TkBTreeNumLines(textPtr->sharedTextPtr->tree, NULL); + } + if (index < indexStart) { + index = 0; + } else if (index > indexEnd) { + index = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + } else { + index -= indexStart; + } + } return index; } - + /* *---------------------------------------------------------------------- * * TkBTreeLinkSegment -- * - * This procedure adds a new segment to a B-tree at a given - * location. + * This function adds a new segment to a B-tree at a given location. * * Results: * None. @@ -1063,13 +2040,12 @@ TkBTreeLineIndex(linePtr) /* ARGSUSED */ void -TkBTreeLinkSegment(segPtr, indexPtr) - TkTextSegment *segPtr; /* Pointer to new segment to be added to - * B-tree. Should be completely initialized - * by caller except for nextPtr field. */ - TkTextIndex *indexPtr; /* Where to add segment: it gets linked - * in just before the segment indicated - * here. */ +TkBTreeLinkSegment( + TkTextSegment *segPtr, /* Pointer to new segment to be added to + * B-tree. Should be completely initialized by + * caller except for nextPtr field. */ + TkTextIndex *indexPtr) /* Where to add segment: it gets linked in + * just before the segment indicated here. */ { register TkTextSegment *prevPtr; @@ -1085,6 +2061,7 @@ TkBTreeLinkSegment(segPtr, indexPtr) if (tkBTreeDebug) { TkBTreeCheck(indexPtr->tree); } + ((BTree *)indexPtr->tree)->stateEpoch++; } /* @@ -1092,34 +2069,42 @@ TkBTreeLinkSegment(segPtr, indexPtr) * * TkBTreeUnlinkSegment -- * - * This procedure unlinks a segment from its line in a B-tree. + * This function unlinks a segment from its line in a B-tree. * * Results: * None. * * Side effects: - * SegPtr will be unlinked from linePtr. The segment itself - * isn't modified by this procedure. + * SegPtr will be unlinked from linePtr. The segment itself isn't + * modified by this function. * *---------------------------------------------------------------------- */ /* ARGSUSED */ void -TkBTreeUnlinkSegment(tree, segPtr, linePtr) - TkTextBTree tree; /* Tree containing segment. */ - TkTextSegment *segPtr; /* Segment to be unlinked. */ - TkTextLine *linePtr; /* Line that currently contains - * segment. */ +TkBTreeUnlinkSegment( + TkTextSegment *segPtr, /* Segment to be unlinked. */ + TkTextLine *linePtr) /* Line that currently contains segment. */ { register TkTextSegment *prevPtr; if (linePtr->segPtr == segPtr) { linePtr->segPtr = segPtr->nextPtr; } else { - for (prevPtr = linePtr->segPtr; prevPtr->nextPtr != segPtr; - prevPtr = prevPtr->nextPtr) { - /* Empty loop body. */ + prevPtr = linePtr->segPtr; + while (prevPtr->nextPtr != segPtr) { + prevPtr = prevPtr->nextPtr; + + if (prevPtr == NULL) { + /* + * Two logical lines merged into one display line through + * eliding of a newline. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); + prevPtr = linePtr->segPtr; + } } prevPtr->nextPtr = segPtr->nextPtr; } @@ -1131,44 +2116,44 @@ TkBTreeUnlinkSegment(tree, segPtr, linePtr) * * TkBTreeTag -- * - * Turn a given tag on or off for a given range of characters in - * a B-tree of text. + * Turn a given tag on or off for a given range of characters in a B-tree + * of text. * * Results: - * None. + * 1 if the tags on any characters in the range were changed, and zero + * otherwise (i.e. if the tag was already absent (add = 0) or present + * (add = 1) on the index range in question). * * Side effects: - * The given tag is added to the given range of characters - * in the tree or removed from all those characters, depending - * on the "add" argument. The structure of the btree is modified - * enough that index1Ptr and index2Ptr are no longer valid after - * this procedure returns, and the indexes may be modified by - * this procedure. + * The given tag is added to the given range of characters in the tree or + * removed from all those characters, depending on the "add" argument. + * The structure of the btree is modified enough that index1Ptr and + * index2Ptr are no longer valid after this function returns, and the + * indexes may be modified by this function. * *---------------------------------------------------------------------- */ -void -TkBTreeTag(index1Ptr, index2Ptr, tagPtr, add) - register TkTextIndex *index1Ptr; /* Indicates first character in - * range. */ - register TkTextIndex *index2Ptr; /* Indicates character just after the - * last one in range. */ - TkTextTag *tagPtr; /* Tag to add or remove. */ - int add; /* One means add tag to the given - * range of characters; zero means - * remove the tag from the range. */ +int +TkBTreeTag( + register TkTextIndex *index1Ptr, + /* Indicates first character in range. */ + register TkTextIndex *index2Ptr, + /* Indicates character just after the last one + * in range. */ + TkTextTag *tagPtr, /* Tag to add or remove. */ + int add) /* One means add tag to the given range of + * characters; zero means remove the tag from + * the range. */ { TkTextSegment *segPtr, *prevPtr; TkTextSearch search; TkTextLine *cleanupLinePtr; - int oldState; - int changed; + int oldState, changed, anyChanges = 0; /* - * See whether the tag is present at the start of the range. If - * the state doesn't already match what we want then add a toggle - * there. + * See whether the tag is present at the start of the range. If the state + * doesn't already match what we want then add a toggle there. */ oldState = TkBTreeCharTagged(index1Ptr, tagPtr); @@ -1186,17 +2171,19 @@ TkBTreeTag(index1Ptr, index2Ptr, tagPtr, add) segPtr->size = 0; segPtr->body.toggle.tagPtr = tagPtr; segPtr->body.toggle.inNodeCounts = 0; + anyChanges = 1; } /* - * Scan the range of characters and delete any internal tag - * transitions. Keep track of what the old state was at the end - * of the range, and add a toggle there if it's needed. + * Scan the range of characters and delete any internal tag transitions. + * Keep track of what the old state was at the end of the range, and add a + * toggle there if it's needed. */ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search); cleanupLinePtr = index1Ptr->linePtr; while (TkBTreeNextTag(&search)) { + anyChanges = 1; oldState ^= 1; segPtr = search.segPtr; prevPtr = search.curIndex.linePtr->segPtr; @@ -1219,24 +2206,24 @@ TkBTreeTag(index1Ptr, index2Ptr, tagPtr, add) ckfree((char *) segPtr); /* - * The code below is a bit tricky. After deleting a toggle - * we eventually have to call CleanupLine, in order to allow - * character segments to be merged together. To do this, we - * remember in cleanupLinePtr a line that needs to be - * cleaned up, but we don't clean it up until we've moved - * on to a different line. That way the cleanup process - * won't goof up segPtr. + * The code below is a bit tricky. After deleting a toggle we + * eventually have to call CleanupLine, in order to allow character + * segments to be merged together. To do this, we remember in + * cleanupLinePtr a line that needs to be cleaned up, but we don't + * clean it up until we've moved on to a different line. That way the + * cleanup process won't goof up segPtr. */ if (cleanupLinePtr != search.curIndex.linePtr) { CleanupLine(cleanupLinePtr); cleanupLinePtr = search.curIndex.linePtr; } + /* - * Quick hack. ChangeNodeToggleCount may move the tag's root - * location around and leave the search in the void. This resets - * the search. + * Quick hack. ChangeNodeToggleCount may move the tag's root location + * around and leave the search in the void. This resets the search. */ + if (changed) { TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search); } @@ -1255,21 +2242,26 @@ TkBTreeTag(index1Ptr, index2Ptr, tagPtr, add) segPtr->size = 0; segPtr->body.toggle.tagPtr = tagPtr; segPtr->body.toggle.inNodeCounts = 0; + anyChanges = 1; } /* - * Cleanup cleanupLinePtr and the last line of the range, if - * these are different. + * Cleanup cleanupLinePtr and the last line of the range, if these are + * different. */ - CleanupLine(cleanupLinePtr); - if (cleanupLinePtr != index2Ptr->linePtr) { - CleanupLine(index2Ptr->linePtr); + if (anyChanges) { + CleanupLine(cleanupLinePtr); + if (cleanupLinePtr != index2Ptr->linePtr) { + CleanupLine(index2Ptr->linePtr); + } + ((BTree *)index1Ptr->tree)->stateEpoch++; } if (tkBTreeDebug) { TkBTreeCheck(index1Ptr->tree); } + return anyChanges; } /* @@ -1277,42 +2269,42 @@ TkBTreeTag(index1Ptr, index2Ptr, tagPtr, add) * * ChangeNodeToggleCount -- * - * This procedure increments or decrements the toggle count for - * a particular tag in a particular node and all its ancestors - * up to the per-tag root node. + * This function increments or decrements the toggle count for a + * particular tag in a particular node and all its ancestors up to the + * per-tag root node. * * Results: * None. * * Side effects: - * The toggle count for tag is adjusted up or down by "delta" in - * nodePtr. This routine maintains the tagRootPtr that identifies - * the root node for the tag, moving it up or down the tree as needed. + * The toggle count for tag is adjusted up or down by "delta" in nodePtr. + * This routine maintains the tagRootPtr that identifies the root node + * for the tag, moving it up or down the tree as needed. * *---------------------------------------------------------------------- */ static void -ChangeNodeToggleCount(nodePtr, tagPtr, delta) - register Node *nodePtr; /* Node whose toggle count for a tag - * must be changed. */ - TkTextTag *tagPtr; /* Information about tag. */ - int delta; /* Amount to add to current toggle - * count for tag (may be negative). */ +ChangeNodeToggleCount( + register Node *nodePtr, /* Node whose toggle count for a tag must be + * changed. */ + TkTextTag *tagPtr, /* Information about tag. */ + int delta) /* Amount to add to current toggle count for + * tag (may be negative). */ { register Summary *summaryPtr, *prevPtr; register Node *node2Ptr; - int rootLevel; /* Level of original tag root */ + int rootLevel; /* Level of original tag root. */ tagPtr->toggleCount += delta; - if (tagPtr->tagRootPtr == (Node *) NULL) { + if (tagPtr->tagRootPtr == NULL) { tagPtr->tagRootPtr = nodePtr; return; } /* - * Note the level of the existing root for the tag so we can detect - * if it needs to be moved because of the toggle count change. + * Note the level of the existing root for the tag so we can detect if it + * needs to be moved because of the toggle count change. */ rootLevel = tagPtr->tagRootPtr->level; @@ -1325,10 +2317,10 @@ ChangeNodeToggleCount(nodePtr, tagPtr, delta) for ( ; nodePtr != tagPtr->tagRootPtr; nodePtr = nodePtr->parentPtr) { /* - * See if there's already an entry for this tag for this node. If so, + * See if there's already an entry for this tag for this node. If so, * perhaps all we have to do is adjust its count. */ - + for (prevPtr = NULL, summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; prevPtr = summaryPtr, summaryPtr = summaryPtr->nextPtr) { @@ -1349,12 +2341,12 @@ ChangeNodeToggleCount(nodePtr, tagPtr, delta) * first place). */ - panic("ChangeNodeToggleCount: bad toggle count (%d) max (%d)", + Tcl_Panic("ChangeNodeToggleCount: bad toggle count (%d) max (%d)", summaryPtr->toggleCount, tagPtr->toggleCount); } - + /* - * Zero toggle count; must remove this tag from the list. + * Zero toggle count; must remove this tag from the list. */ if (prevPtr == NULL) { @@ -1367,21 +2359,20 @@ ChangeNodeToggleCount(nodePtr, tagPtr, delta) /* * This tag isn't currently in the summary information list. */ - + if (rootLevel == nodePtr->level) { - /* * The old tag root is at the same level in the tree as this - * node, but it isn't at this node. Move the tag root up - * a level, in the hopes that it will now cover this node - * as well as the old root (if not, we'll move it up again - * the next time through the loop). To push it up one level - * we copy the original toggle count into the summary - * information at the old root and change the root to its - * parent node. + * node, but it isn't at this node. Move the tag root up a + * level, in the hopes that it will now cover this node as + * well as the old root (if not, we'll move it up again the + * next time through the loop). To push it up one level we + * copy the original toggle count into the summary information + * at the old root and change the root to its parent node. */ - + Node *rootNodePtr = tagPtr->tagRootPtr; + summaryPtr = (Summary *) ckalloc(sizeof(Summary)); summaryPtr->tagPtr = tagPtr; summaryPtr->toggleCount = tagPtr->toggleCount - delta; @@ -1400,26 +2391,26 @@ ChangeNodeToggleCount(nodePtr, tagPtr, delta) } /* - * If we've decremented the toggle count, then it may be necessary - * to push the tag root down one or more levels. + * If we've decremented the toggle count, then it may be necessary to push + * the tag root down one or more levels. */ if (delta >= 0) { return; } if (tagPtr->toggleCount == 0) { - tagPtr->tagRootPtr = (Node *) NULL; + tagPtr->tagRootPtr = NULL; return; } nodePtr = tagPtr->tagRootPtr; while (nodePtr->level > 0) { /* - * See if a single child node accounts for all of the tag's - * toggles. If so, push the root down one level. + * See if a single child node accounts for all of the tag's toggles. + * If so, push the root down one level. */ for (node2Ptr = nodePtr->children.nodePtr; - node2Ptr != (Node *)NULL ; + node2Ptr != NULL ; node2Ptr = node2Ptr->nextPtr) { for (prevPtr = NULL, summaryPtr = node2Ptr->summaryPtr; summaryPtr != NULL; @@ -1464,10 +2455,10 @@ ChangeNodeToggleCount(nodePtr, tagPtr, delta) * Find the start of the first range of a tag. * * Results: - * The return value is a pointer to the first tag toggle segment - * for the tag. This can be either a tagon or tagoff segments because - * of the way TkBTreeAdd removes a tag. - * Sets *indexPtr to be the index of the tag toggle. + * The return value is a pointer to the first tag toggle segment for the + * tag. This can be either a tagon or tagoff segments because of the way + * TkBTreeAdd removes a tag. Sets *indexPtr to be the index of the tag + * toggle. * * Side effects: * None. @@ -1476,10 +2467,10 @@ ChangeNodeToggleCount(nodePtr, tagPtr, delta) */ static TkTextSegment * -FindTagStart(tree, tagPtr, indexPtr) - TkTextBTree tree; /* Tree to search within */ - TkTextTag *tagPtr; /* Tag to search for. */ - TkTextIndex *indexPtr; /* Return - index information */ +FindTagStart( + TkTextBTree tree, /* Tree to search within. */ + TkTextTag *tagPtr, /* Tag to search for. */ + TkTextIndex *indexPtr) /* Return - index information. */ { register Node *nodePtr; register TkTextLine *linePtr; @@ -1488,17 +2479,17 @@ FindTagStart(tree, tagPtr, indexPtr) int offset; nodePtr = tagPtr->tagRootPtr; - if (nodePtr == (Node *) NULL) { + if (nodePtr == NULL) { return NULL; } /* - * Search from the root of the subtree that contains the tag down - * to the level 0 node. + * Search from the root of the subtree that contains the tag down to the + * level 0 node. */ while (nodePtr->level > 0) { - for (nodePtr = nodePtr->children.nodePtr ; nodePtr != (Node *) NULL; + for (nodePtr = nodePtr->children.nodePtr ; nodePtr != NULL; nodePtr = nodePtr->nextPtr) { for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { @@ -1507,7 +2498,7 @@ FindTagStart(tree, tagPtr, indexPtr) } } } - gotNodeWithTag: + gotNodeWithTag: continue; } @@ -1515,7 +2506,7 @@ FindTagStart(tree, tagPtr, indexPtr) * Work through the lines attached to the level-0 node. */ - for (linePtr = nodePtr->children.linePtr; linePtr != (TkTextLine *) NULL; + for (linePtr = nodePtr->children.linePtr; linePtr != NULL; linePtr = linePtr->nextPtr) { for (offset = 0, segPtr = linePtr->segPtr ; segPtr != NULL; offset += segPtr->size, segPtr = segPtr->nextPtr) { @@ -1523,9 +2514,10 @@ FindTagStart(tree, tagPtr, indexPtr) || (segPtr->typePtr == &tkTextToggleOffType)) && (segPtr->body.toggle.tagPtr == tagPtr)) { /* - * It is possible that this is a tagoff tag, but that - * gets cleaned up later. + * It is possible that this is a tagoff tag, but that gets + * cleaned up later. */ + indexPtr->tree = tree; indexPtr->linePtr = linePtr; indexPtr->byteIndex = offset; @@ -1544,10 +2536,10 @@ FindTagStart(tree, tagPtr, indexPtr) * Find the end of the last range of a tag. * * Results: - * The return value is a pointer to the last tag toggle segment - * for the tag. This can be either a tagon or tagoff segments because - * of the way TkBTreeAdd removes a tag. - * Sets *indexPtr to be the index of the tag toggle. + * The return value is a pointer to the last tag toggle segment for the + * tag. This can be either a tagon or tagoff segments because of the way + * TkBTreeAdd removes a tag. Sets *indexPtr to be the index of the tag + * toggle. * * Side effects: * None. @@ -1556,10 +2548,10 @@ FindTagStart(tree, tagPtr, indexPtr) */ static TkTextSegment * -FindTagEnd(tree, tagPtr, indexPtr) - TkTextBTree tree; /* Tree to search within */ - TkTextTag *tagPtr; /* Tag to search for. */ - TkTextIndex *indexPtr; /* Return - index information */ +FindTagEnd( + TkTextBTree tree, /* Tree to search within. */ + TkTextTag *tagPtr, /* Tag to search for. */ + TkTextIndex *indexPtr) /* Return - index information. */ { register Node *nodePtr, *lastNodePtr; register TkTextLine *linePtr ,*lastLinePtr; @@ -1568,18 +2560,18 @@ FindTagEnd(tree, tagPtr, indexPtr) int lastoffset, lastoffset2, offset; nodePtr = tagPtr->tagRootPtr; - if (nodePtr == (Node *) NULL) { + if (nodePtr == NULL) { return NULL; } /* - * Search from the root of the subtree that contains the tag down - * to the level 0 node. + * Search from the root of the subtree that contains the tag down to the + * level 0 node. */ while (nodePtr->level > 0) { for (lastNodePtr = NULL, nodePtr = nodePtr->children.nodePtr ; - nodePtr != (Node *) NULL; nodePtr = nodePtr->nextPtr) { + nodePtr != NULL; nodePtr = nodePtr->nextPtr) { for (summaryPtr = nodePtr->summaryPtr ; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->tagPtr == tagPtr) { @@ -1594,13 +2586,14 @@ FindTagEnd(tree, tagPtr, indexPtr) /* * Work through the lines attached to the level-0 node. */ + last2SegPtr = NULL; lastoffset2 = 0; lastoffset = 0; for (lastLinePtr = NULL, linePtr = nodePtr->children.linePtr; - linePtr != (TkTextLine *) NULL; linePtr = linePtr->nextPtr) { + linePtr != NULL; linePtr = linePtr->nextPtr) { for (offset = 0, lastSegPtr = NULL, segPtr = linePtr->segPtr ; - segPtr != NULL; + segPtr != NULL; offset += segPtr->size, segPtr = segPtr->nextPtr) { if (((segPtr->typePtr == &tkTextToggleOnType) || (segPtr->typePtr == &tkTextToggleOffType)) @@ -1626,51 +2619,50 @@ FindTagEnd(tree, tagPtr, indexPtr) * * TkBTreeStartSearch -- * - * This procedure sets up a search for tag transitions involving - * a given tag (or all tags) in a given range of the text. + * This function sets up a search for tag transitions involving a given + * tag (or all tags) in a given range of the text. * * Results: * None. * * Side effects: - * The information at *searchPtr is set up so that subsequent calls - * to TkBTreeNextTag or TkBTreePrevTag will return information about the - * locations of tag transitions. Note that TkBTreeNextTag or - * TkBTreePrevTag must be called to get the first transition. - * Note: unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not - * guarantee that searchPtr->curIndex is equal to *index1Ptr. It may be + * The information at *searchPtr is set up so that subsequent calls to + * TkBTreeNextTag or TkBTreePrevTag will return information about the + * locations of tag transitions. Note that TkBTreeNextTag or + * TkBTreePrevTag must be called to get the first transition. Note: + * unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not + * guarantee that searchPtr->curIndex is equal to *index1Ptr. It may be * greater than that if *index1Ptr is less than the first tag transition. * *---------------------------------------------------------------------- */ void -TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr) - TkTextIndex *index1Ptr; /* Search starts here. Tag toggles - * at this position will not be - * returned. */ - TkTextIndex *index2Ptr; /* Search stops here. Tag toggles - * at this position *will* be - * returned. */ - TkTextTag *tagPtr; /* Tag to search for. NULL means - * search for any tag. */ - register TkTextSearch *searchPtr; /* Where to store information about - * search's progress. */ +TkBTreeStartSearch( + TkTextIndex *index1Ptr, /* Search starts here. Tag toggles at this + * position will not be returned. */ + TkTextIndex *index2Ptr, /* Search stops here. Tag toggles at this + * position *will* be returned. */ + TkTextTag *tagPtr, /* Tag to search for. NULL means search for + * any tag. */ + register TkTextSearch *searchPtr) + /* Where to store information about search's + * progress. */ { int offset; - TkTextIndex index0; /* First index of the tag */ - TkTextSegment *seg0Ptr; /* First segment of the tag */ + TkTextIndex index0; /* First index of the tag. */ + TkTextSegment *seg0Ptr; /* First segment of the tag. */ /* - * Find the segment that contains the first toggle for the tag. This - * may become the starting point in the search. + * Find the segment that contains the first toggle for the tag. This may + * become the starting point in the search. */ seg0Ptr = FindTagStart(index1Ptr->tree, tagPtr, &index0); - if (seg0Ptr == (TkTextSegment *) NULL) { + if (seg0Ptr == NULL) { /* - * Even though there are no toggles, the display code still - * uses the search curIndex, so initialize that anyway. + * Even though there are no toggles, the display code still uses the + * search curIndex, so initialize that anyway. */ searchPtr->linesLeft = 0; @@ -1681,12 +2673,12 @@ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr) } if (TkTextIndexCmp(index1Ptr, &index0) < 0) { /* - * Adjust start of search up to the first range of the tag + * Adjust start of search up to the first range of the tag. */ searchPtr->curIndex = index0; searchPtr->segPtr = NULL; - searchPtr->nextPtr = seg0Ptr; /* Will be returned by NextTag */ + searchPtr->nextPtr = seg0Ptr; /* Will be returned by NextTag. */ index1Ptr = &index0; } else { searchPtr->curIndex = *index1Ptr; @@ -1694,23 +2686,24 @@ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr) searchPtr->nextPtr = TkTextIndexToSeg(index1Ptr, &offset); searchPtr->curIndex.byteIndex -= offset; } - searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, (int *) NULL); + searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, NULL); searchPtr->tagPtr = tagPtr; - searchPtr->linesLeft = TkBTreeLineIndex(index2Ptr->linePtr) + 1 - - TkBTreeLineIndex(index1Ptr->linePtr); + searchPtr->linesLeft = TkBTreeLinesTo(NULL, index2Ptr->linePtr) + 1 + - TkBTreeLinesTo(NULL, index1Ptr->linePtr); searchPtr->allTags = (tagPtr == NULL); if (searchPtr->linesLeft == 1) { /* * Starting and stopping segments are in the same line; mark the * search as over immediately if the second segment is before the - * first. A search does not return a toggle at the very start of - * the range, unless the range is artificially moved up to index0. + * first. A search does not return a toggle at the very start of the + * range, unless the range is artificially moved up to index0. */ - if (((index1Ptr == &index0) && + + if (((index1Ptr == &index0) && (index1Ptr->byteIndex > index2Ptr->byteIndex)) || - ((index1Ptr != &index0) && + ((index1Ptr != &index0) && (index1Ptr->byteIndex >= index2Ptr->byteIndex))) { - searchPtr->linesLeft = 0; + searchPtr->linesLeft = 0; } } } @@ -1720,55 +2713,53 @@ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr) * * TkBTreeStartSearchBack -- * - * This procedure sets up a search backwards for tag transitions involving - * a given tag (or all tags) in a given range of the text. In the - * normal case the first index (*index1Ptr) is beyond the second - * index (*index2Ptr). - * + * This function sets up a search backwards for tag transitions involving + * a given tag (or all tags) in a given range of the text. In the normal + * case the first index (*index1Ptr) is beyond the second index + * (*index2Ptr). * * Results: * None. * * Side effects: - * The information at *searchPtr is set up so that subsequent calls - * to TkBTreePrevTag will return information about the - * locations of tag transitions. Note that TkBTreePrevTag must be called - * to get the first transition. - * Note: unlike TkBTreeNextTag and TkBTreePrevTag, this routine does not - * guarantee that searchPtr->curIndex is equal to *index1Ptr. It may be - * less than that if *index1Ptr is greater than the last tag transition. + * The information at *searchPtr is set up so that subsequent calls to + * TkBTreePrevTag will return information about the locations of tag + * transitions. Note that TkBTreePrevTag must be called to get the first + * transition. Note: unlike TkBTreeNextTag and TkBTreePrevTag, this + * routine does not guarantee that searchPtr->curIndex is equal to + * *index1Ptr. It may be less than that if *index1Ptr is greater than the + * last tag transition. * *---------------------------------------------------------------------- */ void -TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr) - TkTextIndex *index1Ptr; /* Search starts here. Tag toggles - * at this position will not be - * returned. */ - TkTextIndex *index2Ptr; /* Search stops here. Tag toggles - * at this position *will* be - * returned. */ - TkTextTag *tagPtr; /* Tag to search for. NULL means - * search for any tag. */ - register TkTextSearch *searchPtr; /* Where to store information about - * search's progress. */ +TkBTreeStartSearchBack( + TkTextIndex *index1Ptr, /* Search starts here. Tag toggles at this + * position will not be returned. */ + TkTextIndex *index2Ptr, /* Search stops here. Tag toggles at this + * position *will* be returned. */ + TkTextTag *tagPtr, /* Tag to search for. NULL means search for + * any tag. */ + register TkTextSearch *searchPtr) + /* Where to store information about search's + * progress. */ { int offset; - TkTextIndex index0; /* Last index of the tag */ - TkTextIndex backOne; /* One character before starting index */ - TkTextSegment *seg0Ptr; /* Last segment of the tag */ + TkTextIndex index0; /* Last index of the tag. */ + TkTextIndex backOne; /* One character before starting index. */ + TkTextSegment *seg0Ptr; /* Last segment of the tag. */ /* - * Find the segment that contains the last toggle for the tag. This - * may become the starting point in the search. + * Find the segment that contains the last toggle for the tag. This may + * become the starting point in the search. */ seg0Ptr = FindTagEnd(index1Ptr->tree, tagPtr, &index0); - if (seg0Ptr == (TkTextSegment *) NULL) { + if (seg0Ptr == NULL) { /* - * Even though there are no toggles, the display code still - * uses the search curIndex, so initialize that anyway. + * Even though there are no toggles, the display code still uses the + * search curIndex, so initialize that anyway. */ searchPtr->linesLeft = 0; @@ -1787,28 +2778,29 @@ TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr) searchPtr->curIndex = index0; index1Ptr = &index0; } else { - TkTextIndexBackChars(index1Ptr, 1, &searchPtr->curIndex); + TkTextIndexBackChars(NULL, index1Ptr, 1, &searchPtr->curIndex, + COUNT_INDICES); } searchPtr->segPtr = NULL; searchPtr->nextPtr = TkTextIndexToSeg(&searchPtr->curIndex, &offset); searchPtr->curIndex.byteIndex -= offset; /* - * Adjust the end of the search so it does find toggles that are right - * at the second index specified by the user. + * Adjust the end of the search so it does find toggles that are right at + * the second index specified by the user. */ - if ((TkBTreeLineIndex(index2Ptr->linePtr) == 0) && + if ((TkBTreeLinesTo(NULL, index2Ptr->linePtr) == 0) && (index2Ptr->byteIndex == 0)) { backOne = *index2Ptr; - searchPtr->lastPtr = NULL; /* Signals special case for 1.0 */ + searchPtr->lastPtr = NULL; /* Signals special case for 1.0. */ } else { - TkTextIndexBackChars(index2Ptr, 1, &backOne); - searchPtr->lastPtr = TkTextIndexToSeg(&backOne, (int *) NULL); + TkTextIndexBackChars(NULL, index2Ptr, 1, &backOne, COUNT_INDICES); + searchPtr->lastPtr = TkTextIndexToSeg(&backOne, NULL); } searchPtr->tagPtr = tagPtr; - searchPtr->linesLeft = TkBTreeLineIndex(index1Ptr->linePtr) + 1 - - TkBTreeLineIndex(backOne.linePtr); + searchPtr->linesLeft = TkBTreeLinesTo(NULL, index1Ptr->linePtr) + 1 + - TkBTreeLinesTo(NULL, backOne.linePtr); searchPtr->allTags = (tagPtr == NULL); if (searchPtr->linesLeft == 1) { /* @@ -1828,18 +2820,18 @@ TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr) * * TkBTreeNextTag -- * - * Once a tag search has begun, successive calls to this procedure - * return successive tag toggles. Note: it is NOT SAFE to call this - * procedure if characters have been inserted into or deleted from - * the B-tree since the call to TkBTreeStartSearch. + * Once a tag search has begun, successive calls to this function return + * successive tag toggles. Note: it is NOT SAFE to call this function if + * characters have been inserted into or deleted from the B-tree since + * the call to TkBTreeStartSearch. * * Results: * The return value is 1 if another toggle was found that met the - * criteria specified in the call to TkBTreeStartSearch; in this - * case searchPtr->curIndex gives the toggle's position and - * searchPtr->curTagPtr points to its segment. 0 is returned if - * no more matching tag transitions were found; in this case - * searchPtr->curIndex is the same as searchPtr->stopIndex. + * criteria specified in the call to TkBTreeStartSearch; in this case + * searchPtr->curIndex gives the toggle's position and + * searchPtr->curTagPtr points to its segment. 0 is returned if no more + * matching tag transitions were found; in this case searchPtr->curIndex + * is the same as searchPtr->stopIndex. * * Side effects: * Information in *searchPtr is modified to update the state of the @@ -1849,10 +2841,11 @@ TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr) */ int -TkBTreeNextTag(searchPtr) - register TkTextSearch *searchPtr; /* Information about search in - * progress; must have been set up by - * call to TkBTreeStartSearch. */ +TkBTreeNextTag( + register TkTextSearch *searchPtr) + /* Information about search in progress; must + * have been set up by call to + * TkBTreeStartSearch. */ { register TkTextSegment *segPtr; register Node *nodePtr; @@ -1863,9 +2856,9 @@ TkBTreeNextTag(searchPtr) } /* - * The outermost loop iterates over lines that may potentially contain - * a relevant tag transition, starting from the current segment in - * the current line. + * The outermost loop iterates over lines that may potentially contain a + * relevant tag transition, starting from the current segment in the + * current line. */ segPtr = searchPtr->nextPtr; @@ -1889,11 +2882,10 @@ TkBTreeNextTag(searchPtr) } searchPtr->curIndex.byteIndex += segPtr->size; } - + /* * See if there are more lines associated with the current parent - * node. If so, go back to the top of the loop to search the next - * one. + * node. If so, go back to the top of the loop to search the next one. */ nodePtr = searchPtr->curIndex.linePtr->parentPtr; @@ -1910,14 +2902,14 @@ TkBTreeNextTag(searchPtr) if (nodePtr == searchPtr->tagPtr->tagRootPtr) { goto searchOver; } - + /* * Search across and up through the B-tree's node hierarchy looking * for the next node that has a relevant tag transition somewhere in - * its subtree. Be sure to update linesLeft as we skip over large + * its subtree. Be sure to update linesLeft as we skip over large * chunks of lines. */ - + while (1) { while (nodePtr->nextPtr == NULL) { if (nodePtr->parentPtr == NULL || @@ -1936,14 +2928,14 @@ TkBTreeNextTag(searchPtr) } searchPtr->linesLeft -= nodePtr->numLines; } - + /* * At this point we've found a subtree that has a relevant tag - * transition. Now search down (and across) through that subtree - * to find the first level-0 node that has a relevant tag transition. + * transition. Now search down (and across) through that subtree to + * find the first level-0 node that has a relevant tag transition. */ - - gotNodeWithTag: + + gotNodeWithTag: while (nodePtr->level > 0) { for (nodePtr = nodePtr->children.nodePtr; ; nodePtr = nodePtr->nextPtr) { @@ -1951,21 +2943,25 @@ TkBTreeNextTag(searchPtr) summaryPtr = summaryPtr->nextPtr) { if ((searchPtr->allTags) || (summaryPtr->tagPtr == searchPtr->tagPtr)) { + /* + * Would really like a multi-level continue here... + */ + goto nextChild; } } searchPtr->linesLeft -= nodePtr->numLines; if (nodePtr->nextPtr == NULL) { - panic("TkBTreeNextTag found incorrect tag summary info."); + Tcl_Panic("TkBTreeNextTag found incorrect tag summary info."); } } - nextChild: + nextChild: continue; } - + /* * Now we're down to a level-0 node that contains a line that contains - * a relevant tag transition. Set up line information and go back to + * a relevant tag transition. Set up line information and go back to * the beginning of the loop to search through lines. */ @@ -1978,7 +2974,7 @@ TkBTreeNextTag(searchPtr) continue; } - searchOver: + searchOver: searchPtr->linesLeft = 0; searchPtr->segPtr = NULL; return 0; @@ -1989,19 +2985,18 @@ TkBTreeNextTag(searchPtr) * * TkBTreePrevTag -- * - * Once a tag search has begun, successive calls to this procedure - * return successive tag toggles in the reverse direction. - * Note: it is NOT SAFE to call this - * procedure if characters have been inserted into or deleted from - * the B-tree since the call to TkBTreeStartSearch. + * Once a tag search has begun, successive calls to this function return + * successive tag toggles in the reverse direction. Note: it is NOT SAFE + * to call this function if characters have been inserted into or deleted + * from the B-tree since the call to TkBTreeStartSearch. * * Results: * The return value is 1 if another toggle was found that met the - * criteria specified in the call to TkBTreeStartSearch; in this - * case searchPtr->curIndex gives the toggle's position and - * searchPtr->curTagPtr points to its segment. 0 is returned if - * no more matching tag transitions were found; in this case - * searchPtr->curIndex is the same as searchPtr->stopIndex. + * criteria specified in the call to TkBTreeStartSearch; in this case + * searchPtr->curIndex gives the toggle's position and + * searchPtr->curTagPtr points to its segment. 0 is returned if no more + * matching tag transitions were found; in this case searchPtr->curIndex + * is the same as searchPtr->stopIndex. * * Side effects: * Information in *searchPtr is modified to update the state of the @@ -2011,43 +3006,46 @@ TkBTreeNextTag(searchPtr) */ int -TkBTreePrevTag(searchPtr) - register TkTextSearch *searchPtr; /* Information about search in - * progress; must have been set up by - * call to TkBTreeStartSearch. */ +TkBTreePrevTag( + register TkTextSearch *searchPtr) + /* Information about search in progress; must + * have been set up by call to + * TkBTreeStartSearch. */ { register TkTextSegment *segPtr, *prevPtr; register TkTextLine *linePtr, *prevLinePtr; register Node *nodePtr, *node2Ptr, *prevNodePtr; register Summary *summaryPtr; - int byteIndex; - int pastLast; /* Saw last marker during scan */ - int linesSkipped; + int byteIndex, linesSkipped; + int pastLast; /* Saw last marker during scan. */ if (searchPtr->linesLeft <= 0) { goto searchOver; } /* - * The outermost loop iterates over lines that may potentially contain - * a relevant tag transition, starting from the current segment in - * the current line. "nextPtr" is maintained as the last segment in - * a line that we can look at. + * The outermost loop iterates over lines that may potentially contain a + * relevant tag transition, starting from the current segment in the + * current line. "nextPtr" is maintained as the last segment in a line + * that we can look at. */ while (1) { /* * Check for the last toggle before the current segment on this line. */ + byteIndex = 0; if (searchPtr->lastPtr == NULL) { - /* + /* * Search back to the very beginning, so pastLast is irrelevent. */ - pastLast = 1; + + pastLast = 1; } else { pastLast = 0; } + for (prevPtr = NULL, segPtr = searchPtr->curIndex.linePtr->segPtr ; segPtr != NULL && segPtr != searchPtr->nextPtr; segPtr = segPtr->nextPtr) { @@ -2059,7 +3057,8 @@ TkBTreePrevTag(searchPtr) searchPtr->curIndex.byteIndex = byteIndex; } if (segPtr == searchPtr->lastPtr) { - prevPtr = NULL; /* Segments earlier than last don't count */ + prevPtr = NULL; /* Segments earlier than last don't + * count. */ pastLast = 1; } byteIndex += segPtr->size; @@ -2067,9 +3066,10 @@ TkBTreePrevTag(searchPtr) if (prevPtr != NULL) { if (searchPtr->linesLeft == 1 && !pastLast) { /* - * We found a segment that is before the stopping index. - * Note that it is OK if prevPtr == lastPtr. + * We found a segment that is before the stopping index. Note + * that it is OK if prevPtr == lastPtr. */ + goto searchOver; } searchPtr->segPtr = prevPtr; @@ -2077,7 +3077,7 @@ TkBTreePrevTag(searchPtr) searchPtr->tagPtr = prevPtr->body.toggle.tagPtr; return 1; } - + searchPtr->linesLeft--; if (searchPtr->linesLeft <= 0) { goto searchOver; @@ -2085,7 +3085,7 @@ TkBTreePrevTag(searchPtr) /* * See if there are more lines associated with the current parent - * node. If so, go back to the top of the loop to search the previous + * node. If so, go back to the top of the loop to search the previous * one. */ @@ -2103,17 +3103,17 @@ TkBTreePrevTag(searchPtr) if (nodePtr == searchPtr->tagPtr->tagRootPtr) { goto searchOver; } - + /* * Search across and up through the B-tree's node hierarchy looking - * for the previous node that has a relevant tag transition somewhere in - * its subtree. The search and line counting is trickier with/out - * back pointers. We'll scan all the nodes under a parent up to - * the current node, searching all of them for tag state. The last - * one we find, if any, is recorded in prevNodePtr, and any nodes - * past prevNodePtr that don't have tag state increment linesSkipped. + * for the previous node that has a relevant tag transition somewhere + * in its subtree. The search and line counting is trickier with/out + * back pointers. We'll scan all the nodes under a parent up to the + * current node, searching all of them for tag state. The last one we + * find, if any, is recorded in prevNodePtr, and any nodes past + * prevNodePtr that don't have tag state increment linesSkipped. */ - + while (1) { for (prevNodePtr = NULL, linesSkipped = 0, node2Ptr = nodePtr->parentPtr->children.nodePtr ; @@ -2129,7 +3129,7 @@ TkBTreePrevTag(searchPtr) } linesSkipped += node2Ptr->numLines; - keepLooking: + keepLooking: continue; } if (prevNodePtr != NULL) { @@ -2143,14 +3143,14 @@ TkBTreePrevTag(searchPtr) goto searchOver; } } - + /* * At this point we've found a subtree that has a relevant tag - * transition. Now search down (and across) through that subtree - * to find the last level-0 node that has a relevant tag transition. + * transition. Now search down (and across) through that subtree to + * find the last level-0 node that has a relevant tag transition. */ - - gotNodeWithTag: + + gotNodeWithTag: while (nodePtr->level > 0) { for (linesSkipped = 0, prevNodePtr = NULL, nodePtr = nodePtr->children.nodePtr; nodePtr != NULL ; @@ -2166,20 +3166,20 @@ TkBTreePrevTag(searchPtr) } linesSkipped += nodePtr->numLines; - keepLooking2: + keepLooking2: continue; } if (prevNodePtr == NULL) { - panic("TkBTreePrevTag found incorrect tag summary info."); + Tcl_Panic("TkBTreePrevTag found incorrect tag summary info."); } searchPtr->linesLeft -= linesSkipped; nodePtr = prevNodePtr; } - + /* * Now we're down to a level-0 node that contains a line that contains - * a relevant tag transition. Set up line information and go back to - * the beginning of the loop to search through lines. We start with + * a relevant tag transition. Set up line information and go back to + * the beginning of the loop to search through lines. We start with * the last line below the node. */ @@ -2196,7 +3196,7 @@ TkBTreePrevTag(searchPtr) continue; } - searchOver: + searchOver: searchPtr->linesLeft = 0; searchPtr->segPtr = NULL; return 0; @@ -2210,8 +3210,8 @@ TkBTreePrevTag(searchPtr) * Determine whether a particular character has a particular tag. * * Results: - * The return value is 1 if the given tag is in effect at the - * character given by linePtr and ch, and 0 otherwise. + * The return value is 1 if the given tag is in effect at the character + * given by linePtr and ch, and 0 otherwise. * * Side effects: * None. @@ -2220,10 +3220,10 @@ TkBTreePrevTag(searchPtr) */ int -TkBTreeCharTagged(indexPtr, tagPtr) - TkTextIndex *indexPtr; /* Indicates a character position at - * which to check for a tag. */ - TkTextTag *tagPtr; /* Tag of interest. */ +TkBTreeCharTagged( + const TkTextIndex *indexPtr,/* Indicates a character position at which to + * check for a tag. */ + TkTextTag *tagPtr) /* Tag of interest. */ { register Node *nodePtr; register TkTextLine *siblingLinePtr; @@ -2231,10 +3231,10 @@ TkBTreeCharTagged(indexPtr, tagPtr) TkTextSegment *toggleSegPtr; int toggles, index; - /* - * Check for toggles for the tag in indexPtr's line but before - * indexPtr. If there is one, its type indicates whether or - * not the character is tagged. + /* + * Check for toggles for the tag in indexPtr's line but before indexPtr. + * If there is one, its type indicates whether or not the character is + * tagged. */ toggleSegPtr = NULL; @@ -2252,9 +3252,8 @@ TkBTreeCharTagged(indexPtr, tagPtr) } /* - * No toggle in this line. Look for toggles for the tag in lines - * that are predecessors of indexPtr->linePtr but under the same - * level-0 node. + * No toggle in this line. Look for toggles for the tag in lines that are + * predecessors of indexPtr->linePtr but under the same level-0 node. */ for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr; @@ -2274,9 +3273,9 @@ TkBTreeCharTagged(indexPtr, tagPtr) } /* - * No toggle in this node. Scan upwards through the ancestors of - * this node, counting the number of toggles of the given tag in - * siblings that precede that node. + * No toggle in this node. Scan upwards through the ancestors of this + * node, counting the number of toggles of the given tag in siblings that + * precede that node. */ toggles = 0; @@ -2285,7 +3284,7 @@ TkBTreeCharTagged(indexPtr, tagPtr) register Node *siblingPtr; register Summary *summaryPtr; - for (siblingPtr = nodePtr->parentPtr->children.nodePtr; + for (siblingPtr = nodePtr->parentPtr->children.nodePtr; siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) { for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { @@ -2300,8 +3299,8 @@ TkBTreeCharTagged(indexPtr, tagPtr) } /* - * An odd number of toggles means that the tag is present at the - * given point. + * An odd number of toggles means that the tag is present at the given + * point. */ return toggles & 1; @@ -2312,17 +3311,17 @@ TkBTreeCharTagged(indexPtr, tagPtr) * * TkBTreeGetTags -- * - * Return information about all of the tags that are associated - * with a particular character in a B-tree of text. + * Return information about all of the tags that are associated with a + * particular character in a B-tree of text. * * Results: * The return value is a malloc-ed array containing pointers to - * information for each of the tags that is associated with - * the character at the position given by linePtr and ch. The - * word at *numTagsPtr is filled in with the number of pointers - * in the array. It is up to the caller to free the array by - * passing it to free. If there are no tags at the given character - * then a NULL pointer is returned and *numTagsPtr will be set to 0. + * information for each of the tags that is associated with the character + * at the position given by linePtr and ch. The word at *numTagsPtr is + * filled in with the number of pointers in the array. It is up to the + * caller to free the array by passing it to free. If there are no tags + * at the given character then a NULL pointer is returned and *numTagsPtr + * will be set to 0. * * Side effects: * None. @@ -2332,38 +3331,54 @@ TkBTreeCharTagged(indexPtr, tagPtr) /* ARGSUSED */ TkTextTag ** -TkBTreeGetTags(indexPtr, numTagsPtr) - TkTextIndex *indexPtr; /* Indicates a particular position in - * the B-tree. */ - int *numTagsPtr; /* Store number of tags found at this +TkBTreeGetTags( + const TkTextIndex *indexPtr,/* Indicates a particular position in the + * B-tree. */ + const TkText *textPtr, /* If non-NULL, then only return tags for this + * text widget (when there are peer + * widgets). */ + int *numTagsPtr) /* Store number of tags found at this * location. */ { register Node *nodePtr; register TkTextLine *siblingLinePtr; register TkTextSegment *segPtr; + TkTextLine *linePtr; int src, dst, index; TagInfo tagInfo; #define NUM_TAG_INFOS 10 tagInfo.numTags = 0; tagInfo.arraySize = NUM_TAG_INFOS; - tagInfo.tagPtrs = (TkTextTag **) ckalloc((unsigned) - NUM_TAG_INFOS*sizeof(TkTextTag *)); - tagInfo.counts = (int *) ckalloc((unsigned) - NUM_TAG_INFOS*sizeof(int)); + tagInfo.tagPtrs = (TkTextTag **) + ckalloc((unsigned) NUM_TAG_INFOS * sizeof(TkTextTag *)); + tagInfo.counts = (int *) + ckalloc((unsigned) NUM_TAG_INFOS * sizeof(int)); /* - * Record tag toggles within the line of indexPtr but preceding - * indexPtr. + * Record tag toggles within the line of indexPtr but preceding indexPtr. */ - for (index = 0, segPtr = indexPtr->linePtr->segPtr; - (index + segPtr->size) <= indexPtr->byteIndex; - index += segPtr->size, segPtr = segPtr->nextPtr) { + linePtr = indexPtr->linePtr; + index = 0; + segPtr = linePtr->segPtr; + while ((index + segPtr->size) <= indexPtr->byteIndex) { if ((segPtr->typePtr == &tkTextToggleOnType) || (segPtr->typePtr == &tkTextToggleOffType)) { IncCount(segPtr->body.toggle.tagPtr, 1, &tagInfo); } + index += segPtr->size; + segPtr = segPtr->nextPtr; + + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through eliding + * of a newline. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); + segPtr = linePtr->segPtr; + } } /* @@ -2384,8 +3399,8 @@ TkBTreeGetTags(indexPtr, numTagsPtr) } /* - * For each node in the ancestry of this line, record tag toggles - * for all siblings that precede that node. + * For each node in the ancestry of this line, record tag toggles for all + * siblings that precede that node. */ for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL; @@ -2393,7 +3408,7 @@ TkBTreeGetTags(indexPtr, numTagsPtr) register Node *siblingPtr; register Summary *summaryPtr; - for (siblingPtr = nodePtr->parentPtr->children.nodePtr; + for (siblingPtr = nodePtr->parentPtr->children.nodePtr; siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) { for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { @@ -2406,15 +3421,20 @@ TkBTreeGetTags(indexPtr, numTagsPtr) } /* - * Go through the tag information and squash out all of the tags - * that have even toggle counts (these tags exist before the point - * of interest, but not at the desired character itself). + * Go through the tag information and squash out all of the tags that have + * even toggle counts (these tags exist before the point of interest, but + * not at the desired character itself). Also squash out all tags that + * don't belong to the requested widget. */ for (src = 0, dst = 0; src < tagInfo.numTags; src++) { if (tagInfo.counts[src] & 1) { - tagInfo.tagPtrs[dst] = tagInfo.tagPtrs[src]; - dst++; + const TkText *tagTextPtr = tagInfo.tagPtrs[src]->textPtr; + + if (tagTextPtr==NULL || textPtr==NULL || tagTextPtr==textPtr) { + tagInfo.tagPtrs[dst] = tagInfo.tagPtrs[src]; + dst++; + } } } *numTagsPtr = dst; @@ -2432,14 +3452,25 @@ TkBTreeGetTags(indexPtr, numTagsPtr) * TkTextIsElided -- * * Special case to just return information about elided attribute. - * Specialized from TkBTreeGetTags(indexPtr, numTagsPtr) - * and GetStyle(textPtr, indexPtr). - * Just need to keep track of invisibility settings for each priority, - * pick highest one active at end + * Specialized from TkBTreeGetTags(indexPtr, textPtr, numTagsPtr) and + * GetStyle(textPtr, indexPtr). Just need to keep track of invisibility + * settings for each priority, pick highest one active at end. + * + * Note that this returns all elide information up to and including the + * given index (quite obviously). However, this does mean that if + * indexPtr is a line-start and one then iterates from the beginning of + * that line forwards, one will actually revisit the segPtrs of size zero + * (for tag toggling, for example) which have already been seen here. + * + * For this reason we fill in the fields 'segPtr' and 'segOffset' of + * elideInfo, enabling our caller easily to calculate incremental changes + * from where we left off. * * Results: * Returns whether this text should be elided or not. * + * Optionally returns more detailed information in elideInfo. + * * Side effects: * None. * @@ -2448,93 +3479,129 @@ TkBTreeGetTags(indexPtr, numTagsPtr) /* ARGSUSED */ int -TkTextIsElided(textPtr, indexPtr) - TkText *textPtr; /* Overall information about text widget. */ - TkTextIndex *indexPtr; /* The character in the text for which - * display information is wanted. */ +TkTextIsElided( + const TkText *textPtr, /* Overall information about text widget. */ + const TkTextIndex *indexPtr,/* The character in the text for which display + * information is wanted. */ + TkTextElideInfo *elideInfo) /* NULL or a pointer to a structure in which + * indexPtr's elide state will be stored and + * returned. */ { -#define LOTSA_TAGS 1000 - int elide = 0; /* if nobody says otherwise, it's visible */ - - int deftagCnts[LOTSA_TAGS]; - int *tagCnts = deftagCnts; - TkTextTag *deftagPtrs[LOTSA_TAGS]; - TkTextTag **tagPtrs = deftagPtrs; - int numTags = textPtr->numTags; register Node *nodePtr; register TkTextLine *siblingLinePtr; register TkTextSegment *segPtr; - register TkTextTag *tagPtr = NULL; /* silence gcc 4 warning */ + register TkTextTag *tagPtr = NULL; register int i, index; + register TkTextElideInfo *infoPtr; + TkTextLine *linePtr; + int elide; - /* almost always avoid malloc, so stay out of system calls */ - if (LOTSA_TAGS < numTags) { - tagCnts = (int *)ckalloc((unsigned)sizeof(int) * numTags); - tagPtrs = (TkTextTag **)ckalloc((unsigned)sizeof(TkTextTag *) * numTags); + if (elideInfo == NULL) { + infoPtr = (TkTextElideInfo *) + ckalloc((unsigned) sizeof(TkTextElideInfo)); + } else { + infoPtr = elideInfo; } - - for (i=0; i<numTags; i++) { - tagCnts[i] = 0; + + infoPtr->elide = 0; /* If nobody says otherwise, it's visible. */ + infoPtr->tagCnts = infoPtr->deftagCnts; + infoPtr->tagPtrs = infoPtr->deftagPtrs; + infoPtr->numTags = textPtr->sharedTextPtr->numTags; + + /* + * Almost always avoid malloc, so stay out of system calls. + */ + + if (LOTSA_TAGS < infoPtr->numTags) { + infoPtr->tagCnts = (int *) + ckalloc((unsigned) sizeof(int) * infoPtr->numTags); + infoPtr->tagPtrs = (TkTextTag **) + ckalloc((unsigned) sizeof(TkTextTag *) * infoPtr->numTags); + } + + for (i=0; i<infoPtr->numTags; i++) { + infoPtr->tagCnts[i] = 0; } /* - * Record tag toggles within the line of indexPtr but preceding - * indexPtr. + * Record tag toggles within the line of indexPtr but preceding indexPtr. */ - for (index = 0, segPtr = indexPtr->linePtr->segPtr; - (index + segPtr->size) <= indexPtr->byteIndex; - index += segPtr->size, segPtr = segPtr->nextPtr) { + index = 0; + linePtr = indexPtr->linePtr; + segPtr = linePtr->segPtr; + while ((index + segPtr->size) <= indexPtr->byteIndex) { if ((segPtr->typePtr == &tkTextToggleOnType) || (segPtr->typePtr == &tkTextToggleOffType)) { tagPtr = segPtr->body.toggle.tagPtr; if (tagPtr->elideString != NULL) { - tagPtrs[tagPtr->priority] = tagPtr; - tagCnts[tagPtr->priority]++; + infoPtr->tagPtrs[tagPtr->priority] = tagPtr; + infoPtr->tagCnts[tagPtr->priority]++; } } + + index += segPtr->size; + segPtr = segPtr->nextPtr; + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through eliding + * of a newline. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); + segPtr = linePtr->segPtr; + } } /* + * Store the first segPtr we haven't examined completely so that our + * caller knows where to start. + */ + + infoPtr->segPtr = segPtr; + infoPtr->segOffset = index; + + /* * Record toggles for tags in lines that are predecessors of * indexPtr->linePtr but under the same level-0 node. */ for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr; - siblingLinePtr != indexPtr->linePtr; - siblingLinePtr = siblingLinePtr->nextPtr) { + siblingLinePtr != indexPtr->linePtr; + siblingLinePtr = siblingLinePtr->nextPtr) { for (segPtr = siblingLinePtr->segPtr; segPtr != NULL; - segPtr = segPtr->nextPtr) { + segPtr = segPtr->nextPtr) { if ((segPtr->typePtr == &tkTextToggleOnType) || (segPtr->typePtr == &tkTextToggleOffType)) { tagPtr = segPtr->body.toggle.tagPtr; if (tagPtr->elideString != NULL) { - tagPtrs[tagPtr->priority] = tagPtr; - tagCnts[tagPtr->priority]++; + infoPtr->tagPtrs[tagPtr->priority] = tagPtr; + infoPtr->tagCnts[tagPtr->priority]++; } } } } /* - * For each node in the ancestry of this line, record tag toggles - * for all siblings that precede that node. + * For each node in the ancestry of this line, record tag toggles for all + * siblings that precede that node. */ for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL; - nodePtr = nodePtr->parentPtr) { + nodePtr = nodePtr->parentPtr) { register Node *siblingPtr; register Summary *summaryPtr; - for (siblingPtr = nodePtr->parentPtr->children.nodePtr; - siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) { + for (siblingPtr = nodePtr->parentPtr->children.nodePtr; + siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) { for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL; - summaryPtr = summaryPtr->nextPtr) { + summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->toggleCount & 1) { tagPtr = summaryPtr->tagPtr; if (tagPtr->elideString != NULL) { - tagPtrs[tagPtr->priority] = tagPtr; - tagCnts[tagPtr->priority] += summaryPtr->toggleCount; + infoPtr->tagPtrs[tagPtr->priority] = tagPtr; + infoPtr->tagCnts[tagPtr->priority] += + summaryPtr->toggleCount; } } } @@ -2542,32 +3609,47 @@ TkTextIsElided(textPtr, indexPtr) } /* - * Now traverse from highest priority to lowest, - * take elided value from first odd count (= on) + * Now traverse from highest priority to lowest, take elided value from + * first odd count (= on). */ - for (i = numTags-1; i >=0; i--) { - if (tagCnts[i] & 1) { - /* who would make the selection elided? */ - if ( -#ifndef MAC_OSX_TK - !TkpAlwaysShowSelection(textPtr->tkwin) -#else + infoPtr->elidePriority = -1; + for (i = infoPtr->numTags-1; i >=0; i--) { + if (infoPtr->tagCnts[i] & 1) { + /* + * Who would make the selection elided? + */ + + if ((tagPtr == textPtr->selTagPtr) + && !(textPtr->flags & GOT_FOCUS) + && (textPtr->inactiveSelBorder == NULL +#ifdef MAC_OSX_TK /* Don't show inactive selection in disabled widgets. */ - textPtr->state == TK_STATE_DISABLED + || textPtr->state == TK_TEXT_STATE_DISABLED #endif - && (tagPtr == textPtr->selTagPtr) - && !(textPtr->flags & GOT_FOCUS)) { + )) { continue; } - elide = tagPtrs[i]->elide; + infoPtr->elide = infoPtr->tagPtrs[i]->elide; + + /* + * Note: i == infoPtr->tagPtrs[i]->priority + */ + + infoPtr->elidePriority = i; break; } } - if (LOTSA_TAGS < numTags) { - ckfree((char *) tagCnts); - ckfree((char *) tagPtrs); + elide = infoPtr->elide; + + if (elideInfo == NULL) { + if (LOTSA_TAGS < infoPtr->numTags) { + ckfree((char *) infoPtr->tagCnts); + ckfree((char *) infoPtr->tagPtrs); + } + + ckfree((char *) infoPtr); } return elide; @@ -2576,27 +3658,55 @@ TkTextIsElided(textPtr, indexPtr) /* *---------------------------------------------------------------------- * + * TkTextFreeElideInfo -- + * + * This is a utility function used to free up any memory allocated by the + * TkTextIsElided function above. + * + * Results: + * None. + * + * Side effects: + * Memory may be freed. + * + *---------------------------------------------------------------------- + */ + +void +TkTextFreeElideInfo( + TkTextElideInfo *elideInfo) /* Free any allocated memory in this + * structure. */ +{ + if (LOTSA_TAGS < elideInfo->numTags) { + ckfree((char *) elideInfo->tagCnts); + ckfree((char *) elideInfo->tagPtrs); + } +} + +/* + *---------------------------------------------------------------------- + * * IncCount -- * - * This is a utility procedure used by TkBTreeGetTags. It - * increments the count for a particular tag, adding a new - * entry for that tag if there wasn't one previously. + * This is a utility function used by TkBTreeGetTags. It increments the + * count for a particular tag, adding a new entry for that tag if there + * wasn't one previously. * * Results: * None. * * Side effects: - * The information at *tagInfoPtr may be modified, and the arrays - * may be reallocated to make them larger. + * The information at *tagInfoPtr may be modified, and the arrays may be + * reallocated to make them larger. * *---------------------------------------------------------------------- */ static void -IncCount(tagPtr, inc, tagInfoPtr) - TkTextTag *tagPtr; /* Handle for tag. */ - int inc; /* Amount by which to increment tag count. */ - TagInfo *tagInfoPtr; /* Holds cumulative information about tags; +IncCount( + TkTextTag *tagPtr, /* Handle for tag. */ + int inc, /* Amount by which to increment tag count. */ + TagInfo *tagInfoPtr) /* Holds cumulative information about tags; * increment count here. */ { register TkTextTag **tagPtrPtr; @@ -2611,24 +3721,23 @@ IncCount(tagPtr, inc, tagInfoPtr) } /* - * There isn't currently an entry for this tag, so we have to - * make a new one. If the arrays are full, then enlarge the - * arrays first. + * There isn't currently an entry for this tag, so we have to make a new + * one. If the arrays are full, then enlarge the arrays first. */ if (tagInfoPtr->numTags == tagInfoPtr->arraySize) { TkTextTag **newTags; int *newCounts, newSize; - newSize = 2*tagInfoPtr->arraySize; - newTags = (TkTextTag **) ckalloc((unsigned) - (newSize*sizeof(TkTextTag *))); - memcpy((VOID *) newTags, (VOID *) tagInfoPtr->tagPtrs, + newSize = 2 * tagInfoPtr->arraySize; + newTags = (TkTextTag **) + ckalloc((unsigned) newSize * sizeof(TkTextTag *)); + memcpy(newTags, tagInfoPtr->tagPtrs, tagInfoPtr->arraySize * sizeof(TkTextTag *)); ckfree((char *) tagInfoPtr->tagPtrs); tagInfoPtr->tagPtrs = newTags; - newCounts = (int *) ckalloc((unsigned) (newSize*sizeof(int))); - memcpy((VOID *) newCounts, (VOID *) tagInfoPtr->counts, + newCounts = (int *) ckalloc((unsigned) newSize * sizeof(int)); + memcpy(newCounts, tagInfoPtr->counts, tagInfoPtr->arraySize * sizeof(int)); ckfree((char *) tagInfoPtr->counts); tagInfoPtr->counts = newCounts; @@ -2645,22 +3754,22 @@ IncCount(tagPtr, inc, tagInfoPtr) * * TkBTreeCheck -- * - * This procedure runs a set of consistency checks over a B-tree - * and panics if any inconsistencies are found. + * This function runs a set of consistency checks over a B-tree and + * panics if any inconsistencies are found. * * Results: * None. * * Side effects: - * If a structural defect is found, the procedure panics with an - * error message. + * If a structural defect is found, the function panics with an error + * message. * *---------------------------------------------------------------------- */ void -TkBTreeCheck(tree) - TkTextBTree tree; /* Tree to check. */ +TkBTreeCheck( + TkTextBTree tree) /* Tree to check. */ { BTree *treePtr = (BTree *) tree; register Summary *summaryPtr; @@ -2675,27 +3784,28 @@ TkBTreeCheck(tree) /* * Make sure that the tag toggle counts and the tag root pointers are OK. */ - for (entryPtr = Tcl_FirstHashEntry(&treePtr->textPtr->tagTable, &search); + + for (entryPtr=Tcl_FirstHashEntry(&treePtr->sharedTextPtr->tagTable,&search); entryPtr != NULL ; entryPtr = Tcl_NextHashEntry(&search)) { tagPtr = (TkTextTag *) Tcl_GetHashValue(entryPtr); nodePtr = tagPtr->tagRootPtr; - if (nodePtr == (Node *) NULL) { + if (nodePtr == NULL) { if (tagPtr->toggleCount != 0) { - panic("TkBTreeCheck found \"%s\" with toggles (%d) but no root", - tagPtr->name, tagPtr->toggleCount); + Tcl_Panic("TkBTreeCheck found \"%s\" with toggles (%d) but no root", + tagPtr->name, tagPtr->toggleCount); } - continue; /* no ranges for the tag */ + continue; /* No ranges for the tag. */ } else if (tagPtr->toggleCount == 0) { - panic("TkBTreeCheck found root for \"%s\" with no toggles", + Tcl_Panic("TkBTreeCheck found root for \"%s\" with no toggles", tagPtr->name); } else if (tagPtr->toggleCount & 1) { - panic("TkBTreeCheck found odd toggle count for \"%s\" (%d)", + Tcl_Panic("TkBTreeCheck found odd toggle count for \"%s\" (%d)", tagPtr->name, tagPtr->toggleCount); } for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->tagPtr == tagPtr) { - panic("TkBTreeCheck found root node with summary info"); + Tcl_Panic("TkBTreeCheck found root node with summary info"); } } count = 0; @@ -2723,25 +3833,25 @@ TkBTreeCheck(tree) } } if (count != tagPtr->toggleCount) { - panic("TkBTreeCheck toggleCount (%d) wrong for \"%s\" should be (%d)", - tagPtr->toggleCount, tagPtr->name, count); + Tcl_Panic("TkBTreeCheck toggleCount (%d) wrong for \"%s\" should be (%d)", + tagPtr->toggleCount, tagPtr->name, count); } } /* - * Call a recursive procedure to do the main body of checks. + * Call a recursive function to do the main body of checks. */ nodePtr = treePtr->rootPtr; - CheckNodeConsistency(treePtr->rootPtr); + CheckNodeConsistency(treePtr->rootPtr, treePtr->pixelReferences); /* - * Make sure that there are at least two lines in the text and - * that the last line has no characters except a newline. + * Make sure that there are at least two lines in the text and that the + * last line has no characters except a newline. */ if (nodePtr->numLines < 2) { - panic("TkBTreeCheck: less than 2 lines in tree"); + Tcl_Panic("TkBTreeCheck: less than 2 lines in tree"); } while (nodePtr->level > 0) { nodePtr = nodePtr->children.nodePtr; @@ -2758,25 +3868,24 @@ TkBTreeCheck(tree) || (segPtr->typePtr == &tkTextRightMarkType) || (segPtr->typePtr == &tkTextLeftMarkType)) { /* - * It's OK to toggle a tag off in the last line, but - * not to start a new range. It's also OK to have marks - * in the last line. + * It's OK to toggle a tag off in the last line, but not to start a + * new range. It's also OK to have marks in the last line. */ segPtr = segPtr->nextPtr; } if (segPtr->typePtr != &tkTextCharType) { - panic("TkBTreeCheck: last line has bogus segment type"); + Tcl_Panic("TkBTreeCheck: last line has bogus segment type"); } if (segPtr->nextPtr != NULL) { - panic("TkBTreeCheck: last line has too many segments"); + Tcl_Panic("TkBTreeCheck: last line has too many segments"); } if (segPtr->size != 1) { - panic("TkBTreeCheck: last line has wrong # characters: %d", + Tcl_Panic("TkBTreeCheck: last line has wrong # characters: %d", segPtr->size); } if ((segPtr->body.chars[0] != '\n') || (segPtr->body.chars[1] != 0)) { - panic("TkBTreeCheck: last line had bad value: %s", + Tcl_Panic("TkBTreeCheck: last line had bad value: %s", segPtr->body.chars); } } @@ -2786,54 +3895,66 @@ TkBTreeCheck(tree) * * CheckNodeConsistency -- * - * This procedure is called as part of consistency checking for - * B-trees: it checks several aspects of a node and also runs - * checks recursively on the node's children. + * This function is called as part of consistency checking for B-trees: + * it checks several aspects of a node and also runs checks recursively + * on the node's children. * * Results: * None. * * Side effects: - * If anything suspicious is found in the tree structure, the - * procedure panics. + * If anything suspicious is found in the tree structure, the function + * panics. * *---------------------------------------------------------------------- */ static void -CheckNodeConsistency(nodePtr) - register Node *nodePtr; /* Node whose subtree should be - * checked. */ +CheckNodeConsistency( + register Node *nodePtr, /* Node whose subtree should be checked. */ + int references) /* Number of referring widgets which have + * pixel counts. */ { register Node *childNodePtr; register Summary *summaryPtr, *summaryPtr2; register TkTextLine *linePtr; register TkTextSegment *segPtr; - int numChildren, numLines, toggleCount, minChildren; + int numChildren, numLines, toggleCount, minChildren, i; + int *numPixels; + int pixels[PIXEL_CLIENTS]; if (nodePtr->parentPtr != NULL) { minChildren = MIN_CHILDREN; } else if (nodePtr->level > 0) { minChildren = 2; - } else { + } else { minChildren = 1; } if ((nodePtr->numChildren < minChildren) || (nodePtr->numChildren > MAX_CHILDREN)) { - panic("CheckNodeConsistency: bad child count (%d)", + Tcl_Panic("CheckNodeConsistency: bad child count (%d)", nodePtr->numChildren); } numChildren = 0; numLines = 0; + if (references > PIXEL_CLIENTS) { + numPixels = (int *) ckalloc(sizeof(int) * references); + } else { + numPixels = pixels; + } + for (i = 0; i<references; i++) { + numPixels[i] = 0; + } + if (nodePtr->level == 0) { for (linePtr = nodePtr->children.linePtr; linePtr != NULL; linePtr = linePtr->nextPtr) { if (linePtr->parentPtr != nodePtr) { - panic("CheckNodeConsistency: line doesn't point to parent"); + Tcl_Panic("CheckNodeConsistency: line doesn't point to parent"); } if (linePtr->segPtr == NULL) { - panic("CheckNodeConsistency: line has no segments"); + Tcl_Panic("CheckNodeConsistency: line has no segments"); } for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) { @@ -2844,27 +3965,30 @@ CheckNodeConsistency(nodePtr) && (segPtr->nextPtr != NULL) && (segPtr->nextPtr->size == 0) && (segPtr->nextPtr->typePtr->leftGravity)) { - panic("CheckNodeConsistency: wrong segment order for gravity"); + Tcl_Panic("CheckNodeConsistency: wrong segment order for gravity"); } if ((segPtr->nextPtr == NULL) && (segPtr->typePtr != &tkTextCharType)) { - panic("CheckNodeConsistency: line ended with wrong type"); + Tcl_Panic("CheckNodeConsistency: line ended with wrong type"); } } numChildren++; numLines++; + for (i = 0; i<references; i++) { + numPixels[i] += linePtr->pixels[2 * i]; + } } } else { for (childNodePtr = nodePtr->children.nodePtr; childNodePtr != NULL; childNodePtr = childNodePtr->nextPtr) { if (childNodePtr->parentPtr != nodePtr) { - panic("CheckNodeConsistency: node doesn't point to parent"); + Tcl_Panic("CheckNodeConsistency: node doesn't point to parent"); } if (childNodePtr->level != (nodePtr->level-1)) { - panic("CheckNodeConsistency: level mismatch (%d %d)", + Tcl_Panic("CheckNodeConsistency: level mismatch (%d %d)", nodePtr->level, childNodePtr->level); } - CheckNodeConsistency(childNodePtr); + CheckNodeConsistency(childNodePtr, references); for (summaryPtr = childNodePtr->summaryPtr; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { for (summaryPtr2 = nodePtr->summaryPtr; ; @@ -2873,7 +3997,7 @@ CheckNodeConsistency(nodePtr) if (summaryPtr->tagPtr->tagRootPtr == nodePtr) { break; } - panic("CheckNodeConsistency: node tag \"%s\" not %s", + Tcl_Panic("CheckNodeConsistency: node tag \"%s\" not %s", summaryPtr->tagPtr->name, "present in parent summaries"); } @@ -2884,22 +4008,34 @@ CheckNodeConsistency(nodePtr) } numChildren++; numLines += childNodePtr->numLines; + for (i = 0; i<references; i++) { + numPixels[i] += childNodePtr->numPixels[i]; + } } } if (numChildren != nodePtr->numChildren) { - panic("CheckNodeConsistency: mismatch in numChildren (%d %d)", + Tcl_Panic("CheckNodeConsistency: mismatch in numChildren (%d %d)", numChildren, nodePtr->numChildren); } if (numLines != nodePtr->numLines) { - panic("CheckNodeConsistency: mismatch in numLines (%d %d)", + Tcl_Panic("CheckNodeConsistency: mismatch in numLines (%d %d)", numLines, nodePtr->numLines); } + for (i = 0; i<references; i++) { + if (numPixels[i] != nodePtr->numPixels[i]) { + Tcl_Panic("CheckNodeConsistency: mismatch in numPixels (%d %d) for widget (%d)", + numPixels[i], nodePtr->numPixels[i], i); + } + } + if (references > PIXEL_CLIENTS) { + ckfree((char *) numPixels); + } for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; summaryPtr = summaryPtr->nextPtr) { if (summaryPtr->tagPtr->toggleCount == summaryPtr->toggleCount) { - panic("CheckNodeConsistency: found unpruned root for \"%s\"", - summaryPtr->tagPtr->name); + Tcl_Panic("CheckNodeConsistency: found unpruned root for \"%s\"", + summaryPtr->tagPtr->name); } toggleCount = 0; if (nodePtr->level == 0) { @@ -2912,7 +4048,7 @@ CheckNodeConsistency(nodePtr) continue; } if (segPtr->body.toggle.tagPtr == summaryPtr->tagPtr) { - toggleCount ++; + toggleCount++; } } } @@ -2930,13 +4066,13 @@ CheckNodeConsistency(nodePtr) } } if (toggleCount != summaryPtr->toggleCount) { - panic("CheckNodeConsistency: mismatch in toggleCount (%d %d)", + Tcl_Panic("CheckNodeConsistency: mismatch in toggleCount (%d %d)", toggleCount, summaryPtr->toggleCount); } for (summaryPtr2 = summaryPtr->nextPtr; summaryPtr2 != NULL; summaryPtr2 = summaryPtr2->nextPtr) { if (summaryPtr2->tagPtr == summaryPtr->tagPtr) { - panic("CheckNodeConsistency: duplicated node tag: %s", + Tcl_Panic("CheckNodeConsistency: duplicated node tag: %s", summaryPtr->tagPtr->name); } } @@ -2948,9 +4084,9 @@ CheckNodeConsistency(nodePtr) * * Rebalance -- * - * This procedure is called when a node of a B-tree appears to be - * out of balance (too many children, or too few). It rebalances - * that node and all of its ancestors in the tree. + * This function is called when a node of a B-tree appears to be out of + * balance (too many children, or too few). It rebalances that node and + * all of its ancestors in the tree. * * Results: * None. @@ -2962,14 +4098,13 @@ CheckNodeConsistency(nodePtr) */ static void -Rebalance(treePtr, nodePtr) - BTree *treePtr; /* Tree that is being rebalanced. */ - register Node *nodePtr; /* Node that may be out of balance. */ +Rebalance( + BTree *treePtr, /* Tree that is being rebalanced. */ + register Node *nodePtr) /* Node that may be out of balance. */ { /* - * Loop over the entire ancestral chain of the node, working up - * through the tree one node at a time until the root node has - * been processed. + * Loop over the entire ancestral chain of the node, working up through + * the tree one node at a time until the root node has been processed. */ for ( ; nodePtr != NULL; nodePtr = nodePtr->parentPtr) { @@ -2978,19 +4113,19 @@ Rebalance(treePtr, nodePtr) int i; /* - * Check to see if the node has too many children. If it does, - * then split off all but the first MIN_CHILDREN into a separate - * node following the original one. Then repeat until the - * node has a decent size. + * Check to see if the node has too many children. If it does, then + * split off all but the first MIN_CHILDREN into a separate node + * following the original one. Then repeat until the node has a decent + * size. */ if (nodePtr->numChildren > MAX_CHILDREN) { while (1) { /* - * If the node being split is the root node, then make a - * new root node above it first. + * If the node being split is the root node, then make a new + * root node above it first. */ - + if (nodePtr->parentPtr == NULL) { newPtr = (Node *) ckalloc(sizeof(Node)); newPtr->parentPtr = NULL; @@ -3000,10 +4135,20 @@ Rebalance(treePtr, nodePtr) newPtr->children.nodePtr = nodePtr; newPtr->numChildren = 1; newPtr->numLines = nodePtr->numLines; - RecomputeNodeCounts(newPtr); + newPtr->numPixels = (int *) + ckalloc(sizeof(int) * treePtr->pixelReferences); + for (i=0; i<treePtr->pixelReferences; i++) { + newPtr->numPixels[i] = nodePtr->numPixels[i]; + } + RecomputeNodeCounts(treePtr, newPtr); treePtr->rootPtr = newPtr; } newPtr = (Node *) ckalloc(sizeof(Node)); + newPtr->numPixels = (int *) + ckalloc(sizeof(int) * treePtr->pixelReferences); + for (i=0; i<treePtr->pixelReferences; i++) { + newPtr->numPixels[i] = 0; + } newPtr->parentPtr = nodePtr->parentPtr; newPtr->nextPtr = nodePtr->nextPtr; nodePtr->nextPtr = newPtr; @@ -3027,11 +4172,11 @@ Rebalance(treePtr, nodePtr) newPtr->children.nodePtr = childPtr->nextPtr; childPtr->nextPtr = NULL; } - RecomputeNodeCounts(nodePtr); + RecomputeNodeCounts(treePtr, nodePtr); nodePtr->parentPtr->numChildren++; nodePtr = newPtr; if (nodePtr->numChildren <= MAX_CHILDREN) { - RecomputeNodeCounts(nodePtr); + RecomputeNodeCounts(treePtr, nodePtr); break; } } @@ -3039,16 +4184,16 @@ Rebalance(treePtr, nodePtr) while (nodePtr->numChildren < MIN_CHILDREN) { register Node *otherPtr; - Node *halfwayNodePtr = NULL; /* Initialization needed only */ - TkTextLine *halfwayLinePtr = NULL; /* to prevent cc warnings. */ + Node *halfwayNodePtr = NULL; /* Initialization needed only */ + TkTextLine *halfwayLinePtr = NULL; /* to prevent cc warnings. */ int totalChildren, firstChildren, i; /* - * Too few children for this node. If this is the root then, - * it's OK for it to have less than MIN_CHILDREN children - * as long as it's got at least two. If it has only one - * (and isn't at level 0), then chop the root node out of - * the tree and use its child as the new root. + * Too few children for this node. If this is the root then, it's + * OK for it to have less than MIN_CHILDREN children as long as + * it's got at least two. If it has only one (and isn't at level + * 0), then chop the root node out of the tree and use its child + * as the new root. */ if (nodePtr->parentPtr == NULL) { @@ -3062,8 +4207,8 @@ Rebalance(treePtr, nodePtr) } /* - * Not the root. Make sure that there are siblings to - * balance with. + * Not the root. Make sure that there are siblings to balance + * with. */ if (nodePtr->parentPtr->numChildren < 2) { @@ -3072,8 +4217,8 @@ Rebalance(treePtr, nodePtr) } /* - * Find a sibling neighbor to borrow from, and arrange for - * nodePtr to be the earlier of the pair. + * Find a sibling neighbor to borrow from, and arrange for nodePtr + * to be the earlier of the pair. */ if (nodePtr->nextPtr == NULL) { @@ -3087,11 +4232,10 @@ Rebalance(treePtr, nodePtr) otherPtr = nodePtr->nextPtr; /* - * We're going to either merge the two siblings together - * into one node or redivide the children among them to - * balance their loads. As preparation, join their two - * child lists into a single list and remember the half-way - * point in the list. + * We're going to either merge the two siblings together into one + * node or redivide the children among them to balance their + * loads. As preparation, join their two child lists into a single + * list and remember the half-way point in the list. */ totalChildren = nodePtr->numChildren + otherPtr->numChildren; @@ -3142,7 +4286,7 @@ Rebalance(treePtr, nodePtr) */ if (totalChildren <= MAX_CHILDREN) { - RecomputeNodeCounts(nodePtr); + RecomputeNodeCounts(treePtr, nodePtr); nodePtr->nextPtr = otherPtr->nextPtr; nodePtr->parentPtr->numChildren--; DeleteSummaries(otherPtr->summaryPtr); @@ -3151,8 +4295,8 @@ Rebalance(treePtr, nodePtr) } /* - * The siblings can't be merged, so just divide their - * children evenly between them. + * The siblings can't be merged, so just divide their children + * evenly between them. */ if (nodePtr->level == 0) { @@ -3162,8 +4306,8 @@ Rebalance(treePtr, nodePtr) otherPtr->children.nodePtr = halfwayNodePtr->nextPtr; halfwayNodePtr->nextPtr = NULL; } - RecomputeNodeCounts(nodePtr); - RecomputeNodeCounts(otherPtr); + RecomputeNodeCounts(treePtr, nodePtr); + RecomputeNodeCounts(treePtr, otherPtr); } } } @@ -3173,37 +4317,38 @@ Rebalance(treePtr, nodePtr) * * RecomputeNodeCounts -- * - * This procedure is called to recompute all the counts in a node - * (tags, child information, etc.) by scanning the information in - * its descendants. This procedure is called during rebalancing - * when a node's child structure has changed. + * This function is called to recompute all the counts in a node (tags, + * child information, etc.) by scanning the information in its + * descendants. This function is called during rebalancing when a node's + * child structure has changed. * * Results: * None. * * Side effects: - * The tag counts for nodePtr are modified to reflect its current - * child structure, as are its numChildren and numLines fields. - * Also, all of the childrens' parentPtr fields are made to point - * to nodePtr. + * The tag counts for nodePtr are modified to reflect its current child + * structure, as are its numChildren and numLines fields. Also, all of + * the childrens' parentPtr fields are made to point to nodePtr. * *---------------------------------------------------------------------- */ static void -RecomputeNodeCounts(nodePtr) - register Node *nodePtr; /* Node whose tag summary information - * must be recomputed. */ +RecomputeNodeCounts( + register BTree *treePtr, /* The whole B-tree. */ + register Node *nodePtr) /* Node whose tag summary information must be + * recomputed. */ { register Summary *summaryPtr, *summaryPtr2; register Node *childPtr; register TkTextLine *linePtr; register TkTextSegment *segPtr; TkTextTag *tagPtr; + int ref; /* - * Zero out all the existing counts for the node, but don't delete - * the existing Summary records (most of them will probably be reused). + * Zero out all the existing counts for the node, but don't delete the + * existing Summary records (most of them will probably be reused). */ for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; @@ -3212,11 +4357,13 @@ RecomputeNodeCounts(nodePtr) } nodePtr->numChildren = 0; nodePtr->numLines = 0; + for (ref = 0; ref<treePtr->pixelReferences; ref++) { + nodePtr->numPixels[ref] = 0; + } /* - * Scan through the children, adding the childrens' tag counts into - * the node's tag counts and adding new Summary structures if - * necessary. + * Scan through the children, adding the childrens' tag counts into the + * node's tag counts and adding new Summary structures if necessary. */ if (nodePtr->level == 0) { @@ -3224,6 +4371,9 @@ RecomputeNodeCounts(nodePtr) linePtr = linePtr->nextPtr) { nodePtr->numChildren++; nodePtr->numLines++; + for (ref = 0; ref<treePtr->pixelReferences; ref++) { + nodePtr->numPixels[ref] += linePtr->pixels[2 * ref]; + } linePtr->parentPtr = nodePtr; for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) { @@ -3255,6 +4405,9 @@ RecomputeNodeCounts(nodePtr) childPtr = childPtr->nextPtr) { nodePtr->numChildren++; nodePtr->numLines += childPtr->numLines; + for (ref = 0; ref<treePtr->pixelReferences; ref++) { + nodePtr->numPixels[ref] += childPtr->numPixels[ref]; + } childPtr->parentPtr = nodePtr; for (summaryPtr2 = childPtr->summaryPtr; summaryPtr2 != NULL; summaryPtr2 = summaryPtr2->nextPtr) { @@ -3280,19 +4433,20 @@ RecomputeNodeCounts(nodePtr) /* * Scan through the node's tag records again and delete any Summary * records that still have a zero count, or that have all the toggles. - * The node with the children that account for all the tags toggles - * have no summary information, and they become the tagRootPtr for the tag. + * The node with the children that account for all the tags toggles have + * no summary information, and they become the tagRootPtr for the tag. */ summaryPtr2 = NULL; for (summaryPtr = nodePtr->summaryPtr; summaryPtr != NULL; ) { - if (summaryPtr->toggleCount > 0 && + if (summaryPtr->toggleCount > 0 && summaryPtr->toggleCount < summaryPtr->tagPtr->toggleCount) { if (nodePtr->level == summaryPtr->tagPtr->tagRootPtr->level) { /* - * The tag's root node split and some toggles left. - * The tag root must move up a level. + * The tag's root node split and some toggles left. The tag + * root must move up a level. */ + summaryPtr->tagPtr->tagRootPtr = nodePtr->parentPtr; } summaryPtr2 = summaryPtr; @@ -3301,9 +4455,10 @@ RecomputeNodeCounts(nodePtr) } if (summaryPtr->toggleCount == summaryPtr->tagPtr->toggleCount) { /* - * A node merge has collected all the toggles under one node. - * Push the root down to this level. + * A node merge has collected all the toggles under one node. Push + * the root down to this level. */ + summaryPtr->tagPtr->tagRootPtr = nodePtr; } if (summaryPtr2 != NULL) { @@ -3323,13 +4478,13 @@ RecomputeNodeCounts(nodePtr) * * TkBTreeNumLines -- * - * This procedure returns a count of the number of lines of - * text present in a given B-tree. + * This function returns a count of the number of logical lines of text + * present in a given B-tree. * * Results: - * The return value is a count of the number of usable lines - * in tree (i.e. it doesn't include the dummy line that is just - * used to mark the end of the tree). + * The return value is a count of the number of usable lines in tree + * (i.e. it doesn't include the dummy line that is just used to mark the + * end of the tree). * * Side effects: * None. @@ -3338,11 +4493,53 @@ RecomputeNodeCounts(nodePtr) */ int -TkBTreeNumLines(tree) - TkTextBTree tree; /* Information about tree. */ +TkBTreeNumLines( + TkTextBTree tree, /* Information about tree. */ + const TkText *textPtr) /* Relative to this client of the B-tree. */ { BTree *treePtr = (BTree *) tree; - return treePtr->rootPtr->numLines - 1; + int count; + + if (textPtr != NULL && textPtr->end != NULL) { + count = TkBTreeLinesTo(NULL, textPtr->end); + } else { + count = treePtr->rootPtr->numLines - 1; + } + if (textPtr != NULL && textPtr->start != NULL) { + count -= TkBTreeLinesTo(NULL, textPtr->start); + } + + return count; +} + +/* + *---------------------------------------------------------------------- + * + * TkBTreeNumPixels -- + * + * This function returns a count of the number of pixels of text present + * in a given widget's B-tree representation. + * + * Results: + * The return value is a count of the number of usable pixels in tree + * (since the dummy line used to mark the end of the B-tree is maintained + * with zero height, as are any lines that are before or after the + * '-start -end' range of the text widget in question, the number stored + * at the root is the number we want). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkBTreeNumPixels( + TkTextBTree tree, /* The B-tree. */ + const TkText *textPtr) /* Relative to this client of the B-tree. */ +{ + BTree *treePtr = (BTree *) tree; + return treePtr->rootPtr->numPixels[textPtr->pixelReference]; } /* @@ -3350,12 +4547,11 @@ TkBTreeNumLines(tree) * * CharSplitProc -- * - * This procedure implements splitting for character segments. + * This function implements splitting for character segments. * * Results: - * The return value is a pointer to a chain of two segments - * that have the same characters as segPtr except split - * among the two segments. + * The return value is a pointer to a chain of two segments that have the + * same characters as segPtr except split among the two segments. * * Side effects: * Storage for segPtr is freed. @@ -3364,10 +4560,10 @@ TkBTreeNumLines(tree) */ static TkTextSegment * -CharSplitProc(segPtr, index) - TkTextSegment *segPtr; /* Pointer to segment to split. */ - int index; /* Position within segment at which - * to split. */ +CharSplitProc( + TkTextSegment *segPtr, /* Pointer to segment to split. */ + int index) /* Position within segment at which to + * split. */ { TkTextSegment *newPtr1, *newPtr2; @@ -3384,7 +4580,7 @@ CharSplitProc(segPtr, index) newPtr2->size = segPtr->size - index; memcpy(newPtr2->body.chars, segPtr->body.chars + index, newPtr2->size); newPtr2->body.chars[newPtr2->size] = 0; - ckfree((char*) segPtr); + ckfree((char *) segPtr); return newPtr1; } @@ -3393,12 +4589,12 @@ CharSplitProc(segPtr, index) * * CharCleanupProc -- * - * This procedure merges adjacent character segments into - * a single character segment, if possible. + * This function merges adjacent character segments into a single + * character segment, if possible. * * Results: - * The return value is a pointer to the first segment in - * the (new) list of segments that used to start with segPtr. + * The return value is a pointer to the first segment in the (new) list + * of segments that used to start with segPtr. * * Side effects: * Storage for the segments may be allocated and freed. @@ -3408,11 +4604,10 @@ CharSplitProc(segPtr, index) /* ARGSUSED */ static TkTextSegment * -CharCleanupProc(segPtr, linePtr) - TkTextSegment *segPtr; /* Pointer to first of two adjacent - * segments to join. */ - TkTextLine *linePtr; /* Line containing segments (not - * used). */ +CharCleanupProc( + TkTextSegment *segPtr, /* Pointer to first of two adjacent segments + * to join. */ + TkTextLine *linePtr) /* Line containing segments (not used). */ { TkTextSegment *segPtr2, *newPtr; @@ -3428,8 +4623,8 @@ CharCleanupProc(segPtr, linePtr) memcpy(newPtr->body.chars, segPtr->body.chars, segPtr->size); memcpy(newPtr->body.chars + segPtr->size, segPtr2->body.chars, segPtr2->size); newPtr->body.chars[newPtr->size] = 0; - ckfree((char*) segPtr); - ckfree((char*) segPtr2); + ckfree((char *) segPtr); + ckfree((char *) segPtr2); return newPtr; } @@ -3438,7 +4633,7 @@ CharCleanupProc(segPtr, linePtr) * * CharDeleteProc -- * - * This procedure is invoked to delete a character segment. + * This function is invoked to delete a character segment. * * Results: * Always returns 0 to indicate that the segment was deleted. @@ -3451,14 +4646,14 @@ CharCleanupProc(segPtr, linePtr) /* ARGSUSED */ static int -CharDeleteProc(segPtr, linePtr, treeGone) - TkTextSegment *segPtr; /* Segment to delete. */ - TkTextLine *linePtr; /* Line containing segment. */ - int treeGone; /* Non-zero means the entire tree is - * being deleted, so everything must - * get cleaned up. */ +CharDeleteProc( + TkTextSegment *segPtr, /* Segment to delete. */ + TkTextLine *linePtr, /* Line containing segment. */ + int treeGone) /* Non-zero means the entire tree is being + * deleted, so everything must get cleaned + * up. */ { - ckfree((char*) segPtr); + ckfree((char *) segPtr); return 0; } @@ -3467,47 +4662,43 @@ CharDeleteProc(segPtr, linePtr, treeGone) * * CharCheckProc -- * - * This procedure is invoked to perform consistency checks - * on character segments. + * This function is invoked to perform consistency checks on character + * segments. * * Results: * None. * * Side effects: - * If the segment isn't inconsistent then the procedure - * panics. + * If the segment isn't inconsistent then the function panics. * *-------------------------------------------------------------- */ /* ARGSUSED */ static void -CharCheckProc(segPtr, linePtr) - TkTextSegment *segPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line containing segment. */ +CharCheckProc( + TkTextSegment *segPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line containing segment. */ { /* - * Make sure that the segment contains the number of - * characters indicated by its header, and that the last - * segment in a line ends in a newline. Also make sure - * that there aren't ever two character segments adjacent - * to each other: they should be merged together. + * Make sure that the segment contains the number of characters indicated + * by its header, and that the last segment in a line ends in a newline. + * Also make sure that there aren't ever two character segments adjacent + * to each other: they should be merged together. */ if (segPtr->size <= 0) { - panic("CharCheckProc: segment has size <= 0"); + Tcl_Panic("CharCheckProc: segment has size <= 0"); } if (strlen(segPtr->body.chars) != (size_t) segPtr->size) { - panic("CharCheckProc: segment has wrong size"); + Tcl_Panic("CharCheckProc: segment has wrong size"); } if (segPtr->nextPtr == NULL) { if (segPtr->body.chars[segPtr->size-1] != '\n') { - panic("CharCheckProc: line doesn't end with newline"); - } - } else { - if (segPtr->nextPtr->typePtr == &tkTextCharType) { - panic("CharCheckProc: adjacent character segments weren't merged"); + Tcl_Panic("CharCheckProc: line doesn't end with newline"); } + } else if (segPtr->nextPtr->typePtr == &tkTextCharType) { + Tcl_Panic("CharCheckProc: adjacent character segments weren't merged"); } } @@ -3516,27 +4707,26 @@ CharCheckProc(segPtr, linePtr) * * ToggleDeleteProc -- * - * This procedure is invoked to delete toggle segments. + * This function is invoked to delete toggle segments. * * Results: - * Returns 1 to indicate that the segment may not be deleted, - * unless the entire B-tree is going away. + * Returns 1 to indicate that the segment may not be deleted, unless the + * entire B-tree is going away. * * Side effects: - * If the tree is going away then the toggle's memory is - * freed; otherwise the toggle counts in nodes above the - * segment get updated. + * If the tree is going away then the toggle's memory is freed; otherwise + * the toggle counts in nodes above the segment get updated. * *-------------------------------------------------------------- */ static int -ToggleDeleteProc(segPtr, linePtr, treeGone) - TkTextSegment *segPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line containing segment. */ - int treeGone; /* Non-zero means the entire tree is - * being deleted, so everything must - * get cleaned up. */ +ToggleDeleteProc( + TkTextSegment *segPtr, /* Segment to check. */ + TkTextLine *linePtr, /* Line containing segment. */ + int treeGone) /* Non-zero means the entire tree is being + * deleted, so everything must get cleaned + * up. */ { if (treeGone) { ckfree((char *) segPtr); @@ -3544,11 +4734,11 @@ ToggleDeleteProc(segPtr, linePtr, treeGone) } /* - * This toggle is in the middle of a range of characters that's - * being deleted. Refuse to die. We'll be moved to the end of - * the deleted range and our cleanup procedure will be called - * later. Decrement node toggle counts here, and set a flag - * so we'll re-increment them in the cleanup procedure. + * This toggle is in the middle of a range of characters that's being + * deleted. Refuse to die. We'll be moved to the end of the deleted range + * and our cleanup function will be called later. Decrement node toggle + * counts here, and set a flag so we'll re-increment them in the cleanup + * function. */ if (segPtr->body.toggle.inNodeCounts) { @@ -3564,37 +4754,36 @@ ToggleDeleteProc(segPtr, linePtr, treeGone) * * ToggleCleanupProc -- * - * This procedure is called when a toggle is part of a line that's - * been modified in some way. It's invoked after the - * modifications are complete. + * This function is called when a toggle is part of a line that's been + * modified in some way. It's invoked after the modifications are + * complete. * * Results: - * The return value is the head segment in a new list - * that is to replace the tail of the line that used to - * start at segPtr. This allows the procedure to delete - * or modify segPtr. + * The return value is the head segment in a new list that is to replace + * the tail of the line that used to start at segPtr. This allows the + * function to delete or modify segPtr. * * Side effects: - * Toggle counts in the nodes above the new line will be - * updated if they're not already. Toggles may be collapsed - * if there are duplicate toggles at the same position. + * Toggle counts in the nodes above the new line will be updated if + * they're not already. Toggles may be collapsed if there are duplicate + * toggles at the same position. * *-------------------------------------------------------------- */ static TkTextSegment * -ToggleCleanupProc(segPtr, linePtr) - TkTextSegment *segPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line that now contains segment. */ +ToggleCleanupProc( + TkTextSegment *segPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line that now contains segment. */ { TkTextSegment *segPtr2, *prevPtr; int counts; /* - * If this is a toggle-off segment, look ahead through the next - * segments to see if there's a toggle-on segment for the same tag - * before any segments with non-zero size. If so then the two - * toggles cancel each other; remove them both. + * If this is a toggle-off segment, look ahead through the next segments + * to see if there's a toggle-on segment for the same tag before any + * segments with non-zero size. If so then the two toggles cancel each + * other; remove them both. */ if (segPtr->typePtr == &tkTextToggleOffType) { @@ -3634,8 +4823,8 @@ ToggleCleanupProc(segPtr, linePtr) * * ToggleLineChangeProc -- * - * This procedure is invoked when a toggle segment is about - * to move from one line to another. + * This function is invoked when a toggle segment is about to move from + * one line to another. * * Results: * None. @@ -3647,9 +4836,9 @@ ToggleCleanupProc(segPtr, linePtr) */ static void -ToggleLineChangeProc(segPtr, linePtr) - TkTextSegment *segPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line that used to contain segment. */ +ToggleLineChangeProc( + TkTextSegment *segPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line that used to contain segment. */ { if (segPtr->body.toggle.inNodeCounts) { ChangeNodeToggleCount(linePtr->parentPtr, @@ -3663,45 +4852,45 @@ ToggleLineChangeProc(segPtr, linePtr) * * ToggleCheckProc -- * - * This procedure is invoked to perform consistency checks - * on toggle segments. + * This function is invoked to perform consistency checks on toggle + * segments. * * Results: * None. * * Side effects: - * If a consistency problem is found the procedure panics. + * If a consistency problem is found the function panics. * *-------------------------------------------------------------- */ static void -ToggleCheckProc(segPtr, linePtr) - TkTextSegment *segPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line containing segment. */ +ToggleCheckProc( + TkTextSegment *segPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line containing segment. */ { register Summary *summaryPtr; int needSummary; if (segPtr->size != 0) { - panic("ToggleCheckProc: segment had non-zero size"); + Tcl_Panic("ToggleCheckProc: segment had non-zero size"); } if (!segPtr->body.toggle.inNodeCounts) { - panic("ToggleCheckProc: toggle counts not updated in nodes"); + Tcl_Panic("ToggleCheckProc: toggle counts not updated in nodes"); } - needSummary = (segPtr->body.toggle.tagPtr->tagRootPtr != linePtr->parentPtr); + needSummary = (segPtr->body.toggle.tagPtr->tagRootPtr!=linePtr->parentPtr); for (summaryPtr = linePtr->parentPtr->summaryPtr; ; summaryPtr = summaryPtr->nextPtr) { if (summaryPtr == NULL) { if (needSummary) { - panic("ToggleCheckProc: tag not present in node"); + Tcl_Panic("ToggleCheckProc: tag not present in node"); } else { break; } } if (summaryPtr->tagPtr == segPtr->body.toggle.tagPtr) { if (!needSummary) { - panic("ToggleCheckProc: tag present in root node summary"); + Tcl_Panic("ToggleCheckProc: tag present in root node summary"); } break; } @@ -3709,52 +4898,9 @@ ToggleCheckProc(segPtr, linePtr) } /* - *---------------------------------------------------------------------- - * - * TkBTreeCharsInLine -- - * - * This procedure returns a count of the number of characters - * in a given line. - * - * Results: - * The return value is the character count for linePtr. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: */ - -int -TkBTreeCharsInLine(linePtr) - TkTextLine *linePtr; /* Line whose characters should be - * counted. */ -{ - TkTextSegment *segPtr; - int count; - - count = 0; - for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) { - if (segPtr->typePtr == &tkTextCharType) { - count += Tcl_NumUtfChars(segPtr->body.chars, segPtr->size); - } else { - count += segPtr->size; - } - } - return count; -} - -int -TkBTreeBytesInLine(linePtr) - TkTextLine *linePtr; /* Line whose characters should be - * counted. */ -{ - TkTextSegment *segPtr; - int count; - - count = 0; - for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) { - count += segPtr->size; - } - return count; -} diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c index 1e7ca88..d0cd4d2 100644 --- a/generic/tkTextDisp.c +++ b/generic/tkTextDisp.c @@ -1,18 +1,18 @@ -/* +/* * tkTextDisp.c -- * - * This module provides facilities to display text widgets. It is - * the only place where information is kept about the screen layout - * of text widgets. + * This module provides facilities to display text widgets. It is the + * only place where information is kept about the screen layout of text + * widgets. (Well, strictly, each TkTextLine and B-tree node caches its + * last observed pixel height, but that information originates here). * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" #include "tkText.h" @@ -20,18 +20,102 @@ #include "tkWinInt.h" #endif -#ifdef TK_NO_DOUBLE_BUFFERING #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #endif -#endif /* TK_NO_DOUBLE_BUFFERING */ + +/* + * "Calculations of line pixel heights and the size of the vertical + * scrollbar." + * + * Given that tag, font and elide changes can happen to large numbers of + * diverse chunks in a text widget containing megabytes of text, it is not + * possible to recalculate all affected height information immediately any + * such change takes place and maintain a responsive user-experience. Yet, for + * an accurate vertical scrollbar to be drawn, we must know the total number + * of vertical pixels shown on display versus the number available to be + * displayed. + * + * The way the text widget solves this problem is by maintaining cached line + * pixel heights (in the BTree for each logical line), and having asynchronous + * timer callbacks (i) to iterate through the logical lines recalculating + * their heights, and (ii) to recalculate the vertical scrollbar's position + * and size. + * + * Typically this works well but there are some situations where the overall + * functional design of this file causes some problems. These problems can + * only arise because the calculations used to display lines on screen are not + * connected to those in the iterating-line- recalculation-process. + * + * The reason for this disconnect is that the display calculations operate in + * display lines, and the iteration and cache operates in logical lines. + * Given that the display calculations both need not contain complete logical + * lines (at top or bottom of display), and that they do not actually keep + * track of logical lines (for simplicity of code and historical design), this + * means a line may be known and drawn with a different pixel height to that + * which is cached in the BTree, and this might cause some temporary + * undesirable mismatch between display and the vertical scrollbar. + * + * All such mismatches should be temporary, however, since the asynchronous + * height calculations will always catch up eventually. + * + * For further details see the comments before and within the following + * functions below: LayoutDLine, AsyncUpdateLineMetrics, GetYView, + * GetYPixelCount, TkTextUpdateOneLine, TkTextUpdateLineMetrics. + * + * For details of the way in which the BTree keeps track of pixel heights, see + * tkTextBTree.c. Basically the BTree maintains two pieces of information: the + * logical line indices and the pixel height cache. + */ + +/* + * TK_LAYOUT_WITH_BASE_CHUNKS: + * + * With this macro set, collect all char chunks that have no holes + * between them, that are on the same line and use the same font and font + * size. Allocate the chars of all these chunks, the so-called "stretch", + * in a DString in the first chunk, the so-called "base chunk". Use the + * base chunk string for measuring and drawing, so that these actions are + * always performed with maximum context. + * + * This is necessary for text rendering engines that provide ligatures + * and sub-pixel layout, like ATSU on Mac. If we don't do this, the + * measuring will change all the time, leading to an ugly "tremble and + * shiver" effect. This is because of the continuous splitting and + * re-merging of chunks that goes on in a text widget, when the cursor or + * the selection move. + * + * Side effects: + * + * Memory management changes. Instead of attaching the character data to + * the clientData structures of the char chunks, an additional DString is + * used. The collection process will even lead to resizing this DString + * for large stretches (> TCL_DSTRING_STATIC_SIZE == 200). We could + * reduce the overall memory footprint by copying the result to a plain + * char array after the line breaking process, but that would complicate + * the code and make performance even worse speedwise. See also TODOs. + * + * TODOs: + * + * - Move the character collection process from the LayoutProc into + * LayoutDLine(), so that the collection can be done before actual + * layout. In this way measuring can look at the following text, too, + * right from the beginning. Memory handling can also be improved with + * this. Problem: We don't easily know which chunks are adjacent until + * all the other chunks have calculated their width. Apparently marks + * would return width==0. A separate char collection loop would have to + * know these things. + * + * - Use a new context parameter to pass the context from LayoutDLine() to + * the LayoutProc instead of using a global variable like now. Not + * pressing until the previous point gets implemented. + */ /* * The following structure describes how to display a range of characters. - * The information is generated by scanning all of the tags associated - * with the characters and combining that with default information for - * the overall widget. These structures form the hash keys for - * dInfoPtr->styleTable. + * The information is generated by scanning all of the tags associated with + * the characters and combining that with default information for the overall + * widget. These structures form the hash keys for dInfoPtr->styleTable. */ typedef struct StyleValues { @@ -39,13 +123,12 @@ typedef struct StyleValues { * NULL means use widget background. */ int borderWidth; /* Width of 3-D border for background. */ int relief; /* 3-D relief for background. */ - Pixmap bgStipple; /* Stipple bitmap for background. None - * means draw solid. */ + Pixmap bgStipple; /* Stipple bitmap for background. None means + * draw solid. */ XColor *fgColor; /* Foreground color for text. */ Tk_Font tkfont; /* Font for displaying text. */ Pixmap fgStipple; /* Stipple bitmap for text and other - * foreground stuff. None means draw - * solid.*/ + * foreground stuff. None means draw solid.*/ int justify; /* Justification style for text. */ int lMargin1; /* Left margin, in pixels, for first display * line of each text line. */ @@ -59,11 +142,12 @@ typedef struct StyleValues { 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. */ - TkTextTabArray *tabArrayPtr;/* Locations and types of tab stops (may - * be NULL). */ + TkTextTabArray *tabArrayPtr;/* Locations and types of tab stops (may be + * NULL). */ + int tabStyle; /* One of TABULAR or WORDPROCESSOR. */ int underline; /* Non-zero means draw underline underneath * text. */ - int elide; /* Non-zero means draw text */ + int elide; /* Zero means draw text, otherwise not. */ TkWrapMode wrapMode; /* How to handle wrap-around for this tag. * One of TEXT_WRAPMODE_CHAR, * TEXT_WRAPMODE_NONE or TEXT_WRAPMODE_WORD.*/ @@ -71,128 +155,146 @@ typedef struct StyleValues { /* * The following structure extends the StyleValues structure above with - * graphics contexts used to actually draw the characters. The entries - * in dInfoPtr->styleTable point to structures of this type. + * graphics contexts used to actually draw the characters. The entries in + * dInfoPtr->styleTable point to structures of this type. */ typedef struct TextStyle { int refCount; /* Number of times this structure is * referenced in Chunks. */ - GC bgGC; /* Graphics context for background. None - * means use widget background. */ + GC bgGC; /* Graphics context for background. None means + * use widget background. */ GC fgGC; /* Graphics context for foreground. */ StyleValues *sValuePtr; /* Raw information from which GCs were * derived. */ - Tcl_HashEntry *hPtr; /* Pointer to entry in styleTable. Used - * to delete entry. */ + Tcl_HashEntry *hPtr; /* Pointer to entry in styleTable. Used to + * delete entry. */ } TextStyle; /* - * The following macro determines whether two styles have the same - * background so that, for example, no beveled border should be drawn - * between them. + * The following macro determines whether two styles have the same background + * so that, for example, no beveled border should be drawn between them. */ #define SAME_BACKGROUND(s1, s2) \ (((s1)->sValuePtr->border == (s2)->sValuePtr->border) \ - && ((s1)->sValuePtr->borderWidth == (s2)->sValuePtr->borderWidth) \ - && ((s1)->sValuePtr->relief == (s2)->sValuePtr->relief) \ - && ((s1)->sValuePtr->bgStipple == (s2)->sValuePtr->bgStipple)) + && ((s1)->sValuePtr->borderWidth == (s2)->sValuePtr->borderWidth) \ + && ((s1)->sValuePtr->relief == (s2)->sValuePtr->relief) \ + && ((s1)->sValuePtr->bgStipple == (s2)->sValuePtr->bgStipple)) /* - * The following macro is used to compare two floating-point numbers - * to within a certain degree of scale. Direct comparison fails on - * processors where the processor and memory representations of FP - * numbers of a particular precision is different (e.g. Intel) + * The following macro is used to compare two floating-point numbers to within + * a certain degree of scale. Direct comparison fails on processors where the + * processor and memory representations of FP numbers of a particular + * precision is different (e.g. Intel) */ #define FP_EQUAL_SCALE(double1, double2, scaleFactor) \ (fabs((double1)-(double2))*((scaleFactor)+1.0) < 0.3) /* - * The following structure describes one line of the display, which may - * be either part or all of one line of the text. + * Macro to make debugging/testing logging a little easier. + */ + +#define LOG(toVar,what) \ + Tcl_SetVar2(textPtr->interp, toVar, NULL, (what), \ + TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT) + +/* + * The following structure describes one line of the display, which may be + * either part or all of one line of the text. */ typedef struct DLine { - TkTextIndex index; /* Identifies first character in text - * that is displayed on this line. */ + TkTextIndex index; /* Identifies first character in text that is + * displayed on this line. */ int byteCount; /* Number of bytes accounted for by this - * display line, including a trailing space - * or newline that isn't actually displayed. */ - int y; /* Y-position at which line is supposed to - * be drawn (topmost pixel of rectangular - * area occupied by line). */ - int oldY; /* Y-position at which line currently - * appears on display. -1 means line isn't - * currently visible on display and must be - * redrawn. This is used to move lines by - * scrolling rather than re-drawing. */ + * display line, including a trailing space or + * newline that isn't actually displayed. */ + int logicalLinesMerged; /* Number of extra logical lines merged into + * this one due to elided newlines. */ + int y; /* Y-position at which line is supposed to be + * drawn (topmost pixel of rectangular area + * occupied by line). */ + int oldY; /* Y-position at which line currently appears + * on display. This is used to move lines by + * scrolling rather than re-drawing. If + * 'flags' have the OLD_Y_INVALID bit set, + * then we will never examine this field + * (which means line isn't currently visible + * on display and must be redrawn). */ int height; /* Height of line, in pixels. */ int baseline; /* Offset of text baseline from y, in * pixels. */ - int spaceAbove; /* How much extra space was added to the - * top of the line because of spacing - * options. This is included in height - * and baseline. */ + int spaceAbove; /* How much extra space was added to the top + * of the line because of spacing options. + * This is included in height and baseline. */ int spaceBelow; /* How much extra space was added to the * bottom of the line because of spacing - * options. This is included in height. */ + * options. This is included in height. */ 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 the screen. */ - struct DLine *nextPtr; /* Next in list of all display lines for - * this window. The list is sorted in - * order from top to bottom. Note: the - * next DLine doesn't always correspond - * to the next line of text: (a) can have - * multiple DLines for one text line, and - * (b) can have gaps where DLine's have been - * deleted because they're out of date. */ - int flags; /* Various flag bits: see below for values. */ + TkTextDispChunk *chunkPtr; /* Pointer to first chunk in list of all of + * those that are displayed on this line of + * the screen. */ + struct DLine *nextPtr; /* Next in list of all display lines for this + * window. The list is sorted in order from + * top to bottom. Note: the next DLine doesn't + * always correspond to the next line of text: + * (a) can have multiple DLines for one text + * line, and (b) can have gaps where DLine's + * have been deleted because they're out of + * date. */ + int flags; /* Various flag bits: see below for values. */ } DLine; /* * Flag bits for DLine structures: * - * HAS_3D_BORDER - Non-zero means that at least one of the - * chunks in this line has a 3D border, so - * it potentially interacts with 3D borders - * in neighboring lines (see - * DisplayLineBackground). + * HAS_3D_BORDER - Non-zero means that at least one of the chunks + * in this line has a 3D border, so it + * potentially interacts with 3D borders in + * neighboring lines (see DisplayLineBackground). * NEW_LAYOUT - Non-zero means that the line has been - * re-layed out since the last time the - * display was updated. - * TOP_LINE - Non-zero means that this was the top line + * re-layed out since the last time the display + * was updated. + * TOP_LINE - Non-zero means that this was the top line in * in the window the last time that the window - * was laid out. This is important because - * a line may be displayed differently if its - * at the top or bottom than if it's in the - * middle (e.g. beveled edges aren't displayed - * for middle lines if the adjacent line has - * a similar background). + * was laid out. This is important because a line + * may be displayed differently if its at the top + * or bottom than if it's in the middle + * (e.g. beveled edges aren't displayed for + * middle lines if the adjacent line has a + * similar background). * BOTTOM_LINE - Non-zero means that this was the bottom line * in the window the last time that the window * was laid out. - * IS_DISABLED - This Dline cannot be edited. + * OLD_Y_INVALID - The value of oldY in the structure is not + * valid or useful and should not be examined. + * 'oldY' is only useful when the DLine is + * currently displayed at a different position + * and we wish to re-display it via scrolling, so + * this means the DLine needs redrawing. */ #define HAS_3D_BORDER 1 #define NEW_LAYOUT 2 #define TOP_LINE 4 #define BOTTOM_LINE 8 -#define IS_DISABLED 16 +#define OLD_Y_INVALID 16 /* * Overall display information for a text widget: */ typedef struct TextDInfo { - Tcl_HashTable styleTable; /* Hash table that maps from StyleValues - * to TextStyles for this widget. */ - DLine *dLinePtr; /* First in list of all display lines for - * this widget, in order from top to bottom. */ + Tcl_HashTable styleTable; /* Hash table that maps from StyleValues to + * TextStyles for this widget. */ + DLine *dLinePtr; /* First in list of all display lines for this + * widget, in order from top to bottom. */ + int topPixelOffset; /* Identifies first pixel in top display line + * to display in window. */ + int newTopPixelOffset; /* Desired first pixel in top display line to + * display in window. */ GC copyGC; /* Graphics context for copying from off- * screen pixmaps onto screen. */ GC scrollGC; /* Graphics context for copying from one place @@ -207,12 +309,12 @@ typedef struct TextDInfo { * Leaves space for border, etc. */ int maxX; /* First x-coordinate to right of available * space for displaying lines. */ - int maxY; /* First y-coordinate below available - * space for displaying lines. */ + int maxY; /* First y-coordinate below available space + * for displaying lines. */ int topOfEof; /* Top-most pixel (lowest y-value) that has * been drawn in the appropriate fashion for * the portion of the window after the last - * line of the text. This field is used to + * line of the text. This field is used to * figure out when to redraw part or all of * the eof field. */ @@ -220,34 +322,32 @@ typedef struct TextDInfo { * Information used for scrolling: */ - int newByteOffset; /* Desired x scroll position, measured as the - * number of average-size characters off-screen - * to the left for a line with no left - * margin. */ - int curPixelOffset; /* Actual x scroll position, measured as the + int newXPixelOffset; /* Desired x scroll position, measured as the + * number of pixels off-screen to the left for + * a line with no left margin. */ + int curXPixelOffset; /* Actual x scroll position, measured as the * number of pixels off-screen to the left. */ int maxLength; /* Length in pixels of longest line that's * visible in window (length may exceed window - * size). If there's no wrapping, this will - * be zero. */ + * size). If there's no wrapping, this will be + * zero. */ double xScrollFirst, xScrollLast; /* Most recent values reported to horizontal - * scrollbar; used to eliminate unnecessary + * scrollbar; used to eliminate unnecessary * reports. */ double yScrollFirst, yScrollLast; /* Most recent values reported to vertical - * scrollbar; used to eliminate unnecessary + * scrollbar; used to eliminate unnecessary * reports. */ /* * The following information is used to implement scanning: */ - int scanMarkIndex; /* Byte index of character that was at the - * left edge of the window when the scan - * started. */ + int scanMarkXPixel; /* Pixel index of left edge of the window when + * the scan started. */ int scanMarkX; /* X-position of mouse at time scan started. */ - int scanTotalScroll; /* Total scrolling (in screen lines) that has + int scanTotalYScroll; /* Total scrolling (in screen pixels) that has * occurred since scanMarkY was set. */ int scanMarkY; /* Y-position of mouse at time scan started. */ @@ -257,47 +357,112 @@ typedef struct TextDInfo { int dLinesInvalidated; /* This value is set to 1 whenever something * happens that invalidates information in - * DLine structures; if a redisplay - * is in progress, it will see this and - * abort the redisplay. This is needed - * because, for example, an embedded window - * could change its size when it is first - * displayed, invalidating the DLine that - * is currently being displayed. If redisplay - * continues, it will use freed memory and - * could dump core. */ - int flags; /* Various flag values: see below for + * DLine structures; if a redisplay is in + * progress, it will see this and abort the + * redisplay. This is needed because, for + * example, an embedded window could change + * its size when it is first displayed, + * invalidating the DLine that is currently + * being displayed. If redisplay continues, it + * will use freed memory and could dump + * core. */ + int flags; /* Various flag values: see below for * definitions. */ + /* + * Information used to handle the asynchronous updating of the y-scrollbar + * and the vertical height calculations: + */ + + int lineMetricUpdateEpoch; /* Stores a number which is incremented each + * time the text widget changes in a + * significant way (e.g. resizing or + * geometry-influencing tag changes). */ + int currentMetricUpdateLine;/* Stores a counter which is used to iterate + * over the logical lines contained in the + * widget and update their geometry + * calculations, if they are out of date. */ + TkTextIndex metricIndex; /* If the current metric update line wraps + * into very many display lines, then this is + * used to keep track of what index we've got + * to so far... */ + int metricPixelHeight; /* ...and this is for the height calculation + * so far...*/ + int metricEpoch; /* ...and this for the epoch of the partial + * calculation so it can be cancelled if + * things change once more. This field will be + * -1 if there is no long-line calculation in + * progress, and take a non-negative value if + * there is such a calculation in progress. */ + int lastMetricUpdateLine; /* When the current update line reaches this + * line, we are done and should stop the + * asychronous callback mechanism. */ + Tcl_TimerToken lineUpdateTimer; + /* A token pointing to the current line metric + * update callback. */ + Tcl_TimerToken scrollbarTimer; + /* A token pointing to the current scrollbar + * update callback. */ } TextDInfo; /* - * In TkTextDispChunk structures for character segments, the clientData - * field points to one of the following structures: + * In TkTextDispChunk structures for character segments, the clientData field + * points to one of the following structures: */ +#if !TK_LAYOUT_WITH_BASE_CHUNKS + typedef struct CharInfo { int numBytes; /* Number of bytes to display. */ - char chars[4]; /* UTF characters to display. Actual size - * will be numBytes, not 4. THIS MUST BE - * THE LAST FIELD IN THE STRUCTURE. */ + char chars[4]; /* UTF characters to display. Actual size will + * be numBytes, not 4. THIS MUST BE THE LAST + * FIELD IN THE STRUCTURE. */ +} CharInfo; + +#else /* TK_LAYOUT_WITH_BASE_CHUNKS */ + +typedef struct CharInfo { + TkTextDispChunk *baseChunkPtr; + int baseOffset; /* Starting offset in base chunk + * baseChars. */ + int numBytes; /* Number of bytes that belong to this + * chunk. */ + const char *chars; /* UTF characters to display. Actually points + * into the baseChars of the base chunk. Only + * valid after FinalizeBaseChunk(). */ } CharInfo; /* + * The BaseCharInfo is a CharInfo with some additional data added. + */ + +typedef struct BaseCharInfo { + CharInfo ci; + Tcl_DString baseChars; /* Actual characters for the stretch of text + * represented by this base chunk. */ + int width; /* Width in pixels of the whole string, if + * known, else -1. Valid during + * LayoutDLine(). */ +} BaseCharInfo; + +static TkTextDispChunk *baseCharChunkPtr = NULL; + +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + +/* * Flag values for TextDInfo structures: * - * DINFO_OUT_OF_DATE: Non-zero means that the DLine structures - * for this window are partially or completely - * out of date and need to be recomputed. + * DINFO_OUT_OF_DATE: Non-zero means that the DLine structures for + * this window are partially or completely out of + * date and need to be recomputed. * REDRAW_PENDING: Means that a when-idle handler has been * scheduled to update the display. * REDRAW_BORDERS: Means window border or pad area has * potentially been damaged and must be redrawn. - * REPICK_NEEDED: 1 means that the widget has been modified - * in a way that could change the current - * character (a different character might be - * under the mouse cursor now). Need to - * recompute the current character before - * the next redisplay. + * REPICK_NEEDED: 1 means that the widget has been modified in a + * way that could change the current character (a + * different character might be under the mouse + * cursor now). Need to recompute the current + * character before the next redisplay. */ #define DINFO_OUT_OF_DATE 1 @@ -306,92 +471,140 @@ typedef struct CharInfo { #define REPICK_NEEDED 8 /* - * The following counters keep statistics about redisplay that can be - * checked to see how clever this code is at reducing redisplays. + * Action values for FreeDLines: + * + * DLINE_FREE: Free the lines, but no need to unlink them from the + * current list of actual display lines. + * DLINE_UNLINK: Free and unlink from current display. + * DLINE_FREE_TEMP: Free, but don't unlink, and also don't set + * 'dLinesInvalidated'. + */ + +#define DLINE_FREE 0 +#define DLINE_UNLINK 1 +#define DLINE_FREE_TEMP 2 + +/* + * The following counters keep statistics about redisplay that can be checked + * to see how clever this code is at reducing redisplays. */ static int numRedisplays; /* Number of calls to DisplayText. */ static int linesRedrawn; /* Number of calls to DisplayDLine. */ static int numCopies; /* Number of calls to XCopyArea to copy part * of the screen. */ - +static int lineHeightsRecalculated; + /* Number of line layouts purely for height + * calculation purposes.*/ /* - * Forward declarations for procedures defined later in this file: + * Forward declarations for functions defined later in this file: */ -static void AdjustForTab _ANSI_ARGS_((TkText *textPtr, +static void AdjustForTab(TkText *textPtr, TkTextTabArray *tabArrayPtr, int index, - TkTextDispChunk *chunkPtr)); -static void CharBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int index, int y, int lineHeight, int baseline, - int *xPtr, int *yPtr, int *widthPtr, - int *heightPtr)); -static void CharDisplayProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int x, int y, int height, int baseline, - Display *display, Drawable dst, int screenY)); -static int CharMeasureProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int x)); -static void CharUndisplayProc _ANSI_ARGS_((TkText *textPtr, - TkTextDispChunk *chunkPtr)); + TkTextDispChunk *chunkPtr); +static void CharBboxProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int index, int y, + int lineHeight, int baseline, int *xPtr, + int *yPtr, int *widthPtr, int *heightPtr); +static int CharChunkMeasureChars(TkTextDispChunk *chunkPtr, + const char *chars, int charsLen, + int start, int end, int startX, int maxX, + int flags, int *nextX); +static void CharDisplayProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int x, int y, + int height, int baseline, Display *display, + Drawable dst, int screenY); +static int CharMeasureProc(TkTextDispChunk *chunkPtr, int x); +static void CharUndisplayProc(TkText *textPtr, + TkTextDispChunk *chunkPtr); +#if TK_LAYOUT_WITH_BASE_CHUNKS +static void FinalizeBaseChunk(TkTextDispChunk *additionalChunkPtr); +static void FreeBaseChunk(TkTextDispChunk *baseChunkPtr); +static int IsSameFGStyle(TextStyle *style1, TextStyle *style2); +static void RemoveFromBaseChunk(TkTextDispChunk *chunkPtr); +#endif +/* + * Definitions of elided procs. Compiler can't inline these since we use + * pointers to these functions. ElideDisplayProc and ElideUndisplayProc are + * special-cased for speed, as potentially many elided DLine chunks if large, + * tag toggle-filled elided region. + */ +static void ElideBboxProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int index, int y, + int lineHeight, int baseline, int *xPtr, + int *yPtr, int *widthPtr, int *heightPtr); +static int ElideMeasureProc(TkTextDispChunk *chunkPtr, int x); +static void DisplayDLine(TkText *textPtr, DLine *dlPtr, + DLine *prevPtr, Pixmap pixmap); +static void DisplayLineBackground(TkText *textPtr, DLine *dlPtr, + DLine *prevPtr, Pixmap pixmap); +static void DisplayText(ClientData clientData); +static DLine * FindDLine(DLine *dlPtr, CONST TkTextIndex *indexPtr); +static void FreeDLines(TkText *textPtr, DLine *firstPtr, + DLine *lastPtr, int action); +static void FreeStyle(TkText *textPtr, TextStyle *stylePtr); +static TextStyle * GetStyle(TkText *textPtr, CONST TkTextIndex *indexPtr); +static void GetXView(Tcl_Interp *interp, TkText *textPtr, + int report); +static void GetYView(Tcl_Interp *interp, TkText *textPtr, + int report); +static int GetYPixelCount(TkText *textPtr, DLine *dlPtr); +static DLine * LayoutDLine(TkText *textPtr, + CONST TkTextIndex *indexPtr); +static int MeasureChars(Tk_Font tkfont, CONST char *source, + int maxBytes, int rangeStart, int rangeLength, + int startX, int maxX, int flags, int *nextXPtr); +static void MeasureUp(TkText *textPtr, + CONST TkTextIndex *srcPtr, int distance, + TkTextIndex *dstPtr, int *overlap); +static int NextTabStop(Tk_Font tkfont, int x, int tabOrigin); +static void UpdateDisplayInfo(TkText *textPtr); +static void YScrollByLines(TkText *textPtr, int offset); +static void YScrollByPixels(TkText *textPtr, int offset); +static int SizeOfTab(TkText *textPtr, int tabStyle, + TkTextTabArray *tabArrayPtr, int *indexPtr, int x, + int maxX); +static void TextChanged(TkText *textPtr, + CONST TkTextIndex *index1Ptr, + CONST TkTextIndex *index2Ptr); +static void TextInvalidateRegion(TkText *textPtr, TkRegion region); +static void TextRedrawTag(TkText *textPtr, + TkTextIndex *index1Ptr, TkTextIndex *index2Ptr, + TkTextTag *tagPtr, int withTag); +static void TextInvalidateLineMetrics(TkText *textPtr, + TkTextLine *linePtr, int lineCount, int action); +static int CalculateDisplayLineHeight(TkText *textPtr, + CONST TkTextIndex *indexPtr, int *byteCountPtr, + int *mergedLinePtr); +static void DlineIndexOfX(TkText *textPtr, + DLine *dlPtr, int x, TkTextIndex *indexPtr); +static int DlineXOfIndex(TkText *textPtr, + DLine *dlPtr, int byteIndex); +static int TextGetScrollInfoObj(Tcl_Interp *interp, + TkText *textPtr, int objc, + Tcl_Obj *CONST objv[], double *dblPtr, + int *intPtr); +static void AsyncUpdateLineMetrics(ClientData clientData); +static void AsyncUpdateYScrollbar(ClientData clientData); /* - Definitions of elided procs. - Compiler can't inline these since we use pointers to these functions. - ElideDisplayProc, ElideUndisplayProc special-cased for speed, - as potentially many elided DLine chunks if large, tag toggle-filled - elided region. -*/ -static void ElideBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int index, int y, int lineHeight, int baseline, - int *xPtr, int *yPtr, int *widthPtr, - int *heightPtr)); -static int ElideMeasureProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int x)); - -static void DisplayDLine _ANSI_ARGS_((TkText *textPtr, - DLine *dlPtr, DLine *prevPtr, Pixmap pixmap)); -static void DisplayLineBackground _ANSI_ARGS_((TkText *textPtr, - DLine *dlPtr, DLine *prevPtr, Pixmap pixmap)); -static void DisplayText _ANSI_ARGS_((ClientData clientData)); -static DLine * FindDLine _ANSI_ARGS_((DLine *dlPtr, - TkTextIndex *indexPtr)); -static void FreeDLines _ANSI_ARGS_((TkText *textPtr, - DLine *firstPtr, DLine *lastPtr, int unlink)); -static void FreeStyle _ANSI_ARGS_((TkText *textPtr, - TextStyle *stylePtr)); -static TextStyle * GetStyle _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr)); -static void GetXView _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, int report)); -static void GetYView _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, int report)); -static DLine * LayoutDLine _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr)); -static int MeasureChars _ANSI_ARGS_((Tk_Font tkfont, - CONST char *source, int maxBytes, int startX, - int maxX, int tabOrigin, int *nextXPtr)); -static void MeasureUp _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *srcPtr, int distance, - TkTextIndex *dstPtr)); -static int NextTabStop _ANSI_ARGS_((Tk_Font tkfont, int x, - int tabOrigin)); -static void UpdateDisplayInfo _ANSI_ARGS_((TkText *textPtr)); -static void ScrollByLines _ANSI_ARGS_((TkText *textPtr, - int offset)); -static int SizeOfTab _ANSI_ARGS_((TkText *textPtr, - TkTextTabArray *tabArrayPtr, int index, int x, - int maxX)); -static void TextInvalidateRegion _ANSI_ARGS_((TkText *textPtr, - TkRegion region)); + * Result values returned by TextGetScrollInfoObj: + */ +#define TKTEXT_SCROLL_MOVETO 1 +#define TKTEXT_SCROLL_PAGES 2 +#define TKTEXT_SCROLL_UNITS 3 +#define TKTEXT_SCROLL_ERROR 4 +#define TKTEXT_SCROLL_PIXELS 5 /* *---------------------------------------------------------------------- * * TkTextCreateDInfo -- * - * This procedure is called when a new text widget is created. - * Its job is to set up display-related information for the widget. + * This function is called when a new text widget is created. Its job is + * to set up display-related information for the widget. * * Results: * None. @@ -404,8 +617,8 @@ static void TextInvalidateRegion _ANSI_ARGS_((TkText *textPtr, */ void -TkTextCreateDInfo(textPtr) - TkText *textPtr; /* Overall information for text widget. */ +TkTextCreateDInfo( + TkText *textPtr) /* Overall information for text widget. */ { register TextDInfo *dInfoPtr; XGCValues gcValues; @@ -418,19 +631,39 @@ TkTextCreateDInfo(textPtr) dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues); dInfoPtr->topOfEof = 0; - dInfoPtr->newByteOffset = 0; - dInfoPtr->curPixelOffset = 0; + dInfoPtr->newXPixelOffset = 0; + dInfoPtr->curXPixelOffset = 0; dInfoPtr->maxLength = 0; dInfoPtr->xScrollFirst = -1; dInfoPtr->xScrollLast = -1; dInfoPtr->yScrollFirst = -1; dInfoPtr->yScrollLast = -1; - dInfoPtr->scanMarkIndex = 0; + dInfoPtr->scanMarkXPixel = 0; dInfoPtr->scanMarkX = 0; - dInfoPtr->scanTotalScroll = 0; + dInfoPtr->scanTotalYScroll = 0; dInfoPtr->scanMarkY = 0; dInfoPtr->dLinesInvalidated = 0; dInfoPtr->flags = DINFO_OUT_OF_DATE; + dInfoPtr->topPixelOffset = 0; + dInfoPtr->newTopPixelOffset = 0; + dInfoPtr->currentMetricUpdateLine = -1; + dInfoPtr->lastMetricUpdateLine = -1; + dInfoPtr->lineMetricUpdateEpoch = 1; + dInfoPtr->metricEpoch = -1; + dInfoPtr->metricIndex.textPtr = NULL; + dInfoPtr->metricIndex.linePtr = NULL; + + /* + * Add a refCount for each of the idle call-backs. + */ + + textPtr->refCount++; + dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(0, + AsyncUpdateLineMetrics, (ClientData) textPtr); + textPtr->refCount++; + dInfoPtr->scrollbarTimer = Tcl_CreateTimerHandler(200, + AsyncUpdateYScrollbar, (ClientData) textPtr); + textPtr->dInfoPtr = dInfoPtr; } @@ -439,7 +672,7 @@ TkTextCreateDInfo(textPtr) * * TkTextFreeDInfo -- * - * This procedure is called to free up all of the private display + * This function is called to free up all of the private display * information kept by this file for a text widget. * * Results: @@ -452,19 +685,19 @@ TkTextCreateDInfo(textPtr) */ void -TkTextFreeDInfo(textPtr) - TkText *textPtr; /* Overall information for text widget. */ +TkTextFreeDInfo( + TkText *textPtr) /* Overall information for text widget. */ { register TextDInfo *dInfoPtr = textPtr->dInfoPtr; /* - * Be careful to free up styleTable *after* freeing up all the - * DLines, so that the hash table is still intact to free up the - * style-related information from the lines. Once the lines are - * all free then styleTable will be empty. + * Be careful to free up styleTable *after* freeing up all the DLines, so + * that the hash table is still intact to free up the style-related + * information from the lines. Once the lines are all free then styleTable + * will be empty. */ - FreeDLines(textPtr, dInfoPtr->dLinePtr, (DLine *) NULL, 1); + FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK); Tcl_DeleteHashTable(&dInfoPtr->styleTable); if (dInfoPtr->copyGC != None) { Tk_FreeGC(textPtr->display, dInfoPtr->copyGC); @@ -473,6 +706,16 @@ TkTextFreeDInfo(textPtr) if (dInfoPtr->flags & REDRAW_PENDING) { Tcl_CancelIdleCall(DisplayText, (ClientData) textPtr); } + if (dInfoPtr->lineUpdateTimer != NULL) { + Tcl_DeleteTimerHandler(dInfoPtr->lineUpdateTimer); + textPtr->refCount--; + dInfoPtr->lineUpdateTimer = NULL; + } + if (dInfoPtr->scrollbarTimer != NULL) { + Tcl_DeleteTimerHandler(dInfoPtr->scrollbarTimer); + textPtr->refCount--; + dInfoPtr->scrollbarTimer = NULL; + } ckfree((char *) dInfoPtr); } @@ -481,8 +724,8 @@ TkTextFreeDInfo(textPtr) * * GetStyle -- * - * This procedure creates all the information needed to display - * text at a particular location. + * This function creates all the information needed to display text at a + * particular location. * * Results: * The return value is a pointer to a TextStyle structure that @@ -495,47 +738,44 @@ TkTextFreeDInfo(textPtr) */ static TextStyle * -GetStyle(textPtr, indexPtr) - TkText *textPtr; /* Overall information about text widget. */ - TkTextIndex *indexPtr; /* The character in the text for which - * display information is wanted. */ +GetStyle( + TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *indexPtr)/* The character in the text for which display + * information is wanted. */ { TkTextTag **tagPtrs; register TkTextTag *tagPtr; StyleValues styleValues; TextStyle *stylePtr; Tcl_HashEntry *hPtr; - int numTags, new, i; + int numTags, isNew, i; XGCValues gcValues; unsigned long mask; - /* * The variables below keep track of the highest-priority specification * that has occurred for each of the various fields of the StyleValues. */ - int borderPrio, borderWidthPrio, reliefPrio, bgStipplePrio; int fgPrio, fontPrio, fgStipplePrio; int underlinePrio, elidePrio, justifyPrio, offsetPrio; int lMargin1Prio, lMargin2Prio, rMarginPrio; int spacing1Prio, spacing2Prio, spacing3Prio; - int overstrikePrio, tabPrio, wrapPrio; + int overstrikePrio, tabPrio, tabStylePrio, wrapPrio; /* - * Find out what tags are present for the character, then compute - * a StyleValues structure corresponding to those tags (scan - * through all of the tags, saving information for the highest- - * priority tag). + * Find out what tags are present for the character, then compute a + * StyleValues structure corresponding to those tags (scan through all of + * the tags, saving information for the highest-priority tag). */ - tagPtrs = TkBTreeGetTags(indexPtr, &numTags); + tagPtrs = TkBTreeGetTags(indexPtr, textPtr, &numTags); borderPrio = borderWidthPrio = reliefPrio = bgStipplePrio = -1; fgPrio = fontPrio = fgStipplePrio = -1; underlinePrio = elidePrio = justifyPrio = offsetPrio = -1; lMargin1Prio = lMargin2Prio = rMarginPrio = -1; spacing1Prio = spacing2Prio = spacing3Prio = -1; - overstrikePrio = tabPrio = wrapPrio = -1; - memset((VOID *) &styleValues, 0, sizeof(StyleValues)); + overstrikePrio = tabPrio = tabStylePrio = wrapPrio = -1; + memset(&styleValues, 0, sizeof(StyleValues)); styleValues.relief = TK_RELIEF_FLAT; styleValues.fgColor = textPtr->fgColor; styleValues.tkfont = textPtr->tkfont; @@ -544,33 +784,40 @@ GetStyle(textPtr, indexPtr) styleValues.spacing2 = textPtr->spacing2; styleValues.spacing3 = textPtr->spacing3; styleValues.tabArrayPtr = textPtr->tabArrayPtr; + styleValues.tabStyle = textPtr->tabStyle; styleValues.wrapMode = textPtr->wrapMode; styleValues.elide = 0; + for (i = 0 ; i < numTags; i++) { + Tk_3DBorder border; + tagPtr = tagPtrs[i]; + border = tagPtr->border; /* - * Skip the selection tag if we don't have focus, - * unless we always want to show the selection. + * If this is the selection tag, and inactiveSelBorder is NULL (the + * default on Windows), then we need to skip it if we don't have the + * focus. */ - if ( -#ifndef MAC_OSX_TK - !TkpAlwaysShowSelection(textPtr->tkwin) -#else - /* Don't show inactive selection in disabled widgets. */ - textPtr->state == TK_STATE_DISABLED + if ((tagPtr == textPtr->selTagPtr) && !(textPtr->flags & GOT_FOCUS)) { + if (textPtr->inactiveSelBorder == NULL +#ifdef MAC_OSX_TK + /* Don't show inactive selection in disabled widgets. */ + || textPtr->state == TK_TEXT_STATE_DISABLED #endif - && (tagPtr == textPtr->selTagPtr) - && !(textPtr->flags & GOT_FOCUS)) { - continue; + ) { + continue; + } + border = textPtr->inactiveSelBorder; } - if ((tagPtr->border != NULL) && (tagPtr->priority > borderPrio)) { - styleValues.border = tagPtr->border; + if ((border != NULL) && (tagPtr->priority > borderPrio)) { + styleValues.border = border; borderPrio = tagPtr->priority; } - if ((tagPtr->bdString != NULL) + if ((tagPtr->borderWidthPtr != NULL) + && (Tcl_GetString(tagPtr->borderWidthPtr)[0] != '\0') && (tagPtr->priority > borderWidthPrio)) { styleValues.borderWidth = tagPtr->borderWidth; borderWidthPrio = tagPtr->priority; @@ -646,11 +893,16 @@ GetStyle(textPtr, indexPtr) styleValues.spacing3 = tagPtr->spacing3; spacing3Prio = tagPtr->priority; } - if ((tagPtr->tabString != NULL) + if ((tagPtr->tabStringPtr != NULL) && (tagPtr->priority > tabPrio)) { styleValues.tabArrayPtr = tagPtr->tabArrayPtr; tabPrio = tagPtr->priority; } + if ((tagPtr->tabStyle != TK_TEXT_TABSTYLE_NONE) + && (tagPtr->priority > tabStylePrio)) { + styleValues.tabStyle = tagPtr->tabStyle; + tabStylePrio = tagPtr->priority; + } if ((tagPtr->underlineString != NULL) && (tagPtr->priority > underlinePrio)) { styleValues.underline = tagPtr->underline; @@ -676,15 +928,15 @@ GetStyle(textPtr, indexPtr) */ hPtr = Tcl_CreateHashEntry(&textPtr->dInfoPtr->styleTable, - (char *) &styleValues, &new); - if (!new) { + (char *) &styleValues, &isNew); + if (!isNew) { stylePtr = (TextStyle *) Tcl_GetHashValue(hPtr); stylePtr->refCount++; return stylePtr; } /* - * No existing style matched. Make a new one. + * No existing style matched. Make a new one. */ stylePtr = (TextStyle *) ckalloc(sizeof(TextStyle)); @@ -723,25 +975,25 @@ GetStyle(textPtr, indexPtr) * * FreeStyle -- * - * This procedure is called when a TextStyle structure is no longer - * needed. It decrements the reference count and frees up the - * space for the style structure if the reference count is 0. + * This function is called when a TextStyle structure is no longer + * needed. It decrements the reference count and frees up the space for + * the style structure if the reference count is 0. * * Results: * None. * * Side effects: - * The storage and other resources associated with the style - * are freed up if no-one's still using it. + * The storage and other resources associated with the style are freed up + * if no-one's still using it. * *---------------------------------------------------------------------- */ static void -FreeStyle(textPtr, stylePtr) - TkText *textPtr; /* Information about overall widget. */ - register TextStyle *stylePtr; /* Information about style to free. */ - +FreeStyle( + TkText *textPtr, /* Information about overall widget. */ + register TextStyle *stylePtr) + /* Information about style to free. */ { stylePtr->refCount--; if (stylePtr->refCount == 0) { @@ -761,70 +1013,91 @@ FreeStyle(textPtr, stylePtr) * * LayoutDLine -- * - * This procedure generates a single DLine structure for a display - * line whose leftmost character is given by indexPtr. - * + * This function generates a single DLine structure for a display line + * whose leftmost character is given by indexPtr. + * * Results: * The return value is a pointer to a DLine structure desribing the - * display line. All fields are filled in and correct except for - * y and nextPtr. + * display line. All fields are filled in and correct except for y and + * nextPtr. * * Side effects: * Storage is allocated for the new DLine. * + * See the comments in 'GetYView' for some thoughts on what the side- + * effects of this call (or its callers) should be; the synchronisation + * of TkTextLine->pixelHeight with the sum of the results of this + * function operating on all display lines within each logical line. + * Ideally the code should be refactored to ensure the cached pixel + * height is never behind what is known when this function is called + * elsewhere. + * + * Unfortunately, this function is currently called from many different + * places, not just to layout a display line for actual display, but also + * simply to calculate some metric or other of one or more display lines + * (typically the height). It would be a good idea to do some profiling + * of typical text widget usage and the way in which this is called and + * see if some optimization could or should be done. + * *---------------------------------------------------------------------- */ static DLine * -LayoutDLine(textPtr, indexPtr) - TkText *textPtr; /* Overall information about text widget. */ - TkTextIndex *indexPtr; /* Beginning of display line. May not - * necessarily point to a character segment. */ +LayoutDLine( + TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *indexPtr)/* Beginning of display line. May not + * necessarily point to a character + * segment. */ { - register DLine *dlPtr; /* New display line. */ - TkTextSegment *segPtr; /* Current segment in text. */ - TkTextDispChunk *lastChunkPtr; /* Last chunk allocated so far - * for line. */ - TkTextDispChunk *chunkPtr; /* Current chunk. */ + register DLine *dlPtr; /* New display line. */ + TkTextSegment *segPtr; /* Current segment in text. */ + TkTextDispChunk *lastChunkPtr; + /* Last chunk allocated so far for line. */ + TkTextDispChunk *chunkPtr; /* Current chunk. */ TkTextIndex curIndex; - TkTextDispChunk *breakChunkPtr; /* Chunk containing best word break - * point, if any. */ - TkTextIndex breakIndex; /* Index of first character in - * breakChunkPtr. */ - int breakByteOffset; /* Byte offset of character within - * breakChunkPtr just to right of best - * break point. */ - int noCharsYet; /* Non-zero means that no characters - * have been placed on the line yet. */ - int justify; /* How to justify line: taken from - * style for the first character in - * line. */ - int jIndent; /* Additional indentation (beyond - * margins) due to justification. */ - int rMargin; /* Right margin width for line. */ - TkWrapMode wrapMode; /* Wrap mode to use for this line. */ - int x = 0, maxX = 0; /* Initializations needed only to - * stop compiler warnings. */ - int wholeLine; /* Non-zero means this display line - * runs to the end of the text line. */ - int tabIndex; /* Index of the current tab stop. */ - int gotTab; /* Non-zero means the current chunk - * contains a tab. */ - TkTextDispChunk *tabChunkPtr; /* Pointer to the chunk containing - * the previous tab stop. */ - int maxBytes; /* Maximum number of bytes to - * include in this chunk. */ - TkTextTabArray *tabArrayPtr; /* Tab stops for line; taken from - * style for the first character on - * line. */ - int tabSize; /* Number of pixels consumed by current - * tab stop. */ - TkTextDispChunk *lastCharChunkPtr; /* Pointer to last chunk in display - * lines with numBytes > 0. Used to - * drop 0-sized chunks from the end - * of the line. */ + TkTextDispChunk *breakChunkPtr; + /* Chunk containing best word break point, if + * any. */ + TkTextIndex breakIndex; /* Index of first character in + * breakChunkPtr. */ + int breakByteOffset; /* Byte offset of character within + * breakChunkPtr just to right of best break + * point. */ + int noCharsYet; /* Non-zero means that no characters have been + * placed on the line yet. */ + int paragraphStart; /* Non-zero means that we are on the first + * line of a paragraph (used to choose between + * lmargin1, lmargin2). */ + int justify; /* How to justify line: taken from style for + * the first character in line. */ + int jIndent; /* Additional indentation (beyond margins) due + * to justification. */ + int rMargin; /* Right margin width for line. */ + TkWrapMode wrapMode; /* Wrap mode to use for this line. */ + int x = 0, maxX = 0; /* Initializations needed only to stop + * compiler warnings. */ + int wholeLine; /* Non-zero means this display line runs to + * the end of the text line. */ + int tabIndex; /* Index of the current tab stop. */ + int gotTab; /* Non-zero means the current chunk contains a + * tab. */ + TkTextDispChunk *tabChunkPtr; + /* Pointer to the chunk containing the + * previous tab stop. */ + int maxBytes; /* Maximum number of bytes to include in this + * chunk. */ + TkTextTabArray *tabArrayPtr;/* Tab stops for line; taken from style for + * the first character on line. */ + int tabStyle; /* One of TABULAR or WORDPROCESSOR. */ + int tabSize; /* Number of pixels consumed by current tab + * stop. */ + TkTextDispChunk *lastCharChunkPtr; + /* Pointer to last chunk in display lines with + * numBytes > 0. Used to drop 0-sized chunks + * from the end of the line. */ int byteOffset, ascent, descent, code, elide, elidesize; StyleValues *sValuePtr; + TkTextElideInfo info; /* Keep track of elide state. */ /* * Create and initialize a new DLine structure. @@ -834,33 +1107,91 @@ LayoutDLine(textPtr, indexPtr) dlPtr->index = *indexPtr; dlPtr->byteCount = 0; dlPtr->y = 0; - dlPtr->oldY = -1; + dlPtr->oldY = 0; /* Only set to avoid compiler warnings. */ dlPtr->height = 0; dlPtr->baseline = 0; dlPtr->chunkPtr = NULL; dlPtr->nextPtr = NULL; - dlPtr->flags = NEW_LAYOUT; + dlPtr->flags = NEW_LAYOUT | OLD_Y_INVALID; + dlPtr->logicalLinesMerged = 0; /* - * Special case entirely elide line as there may be 1000s or more + * This is not necessarily totally correct, where we have merged logical + * lines. Fixing this would require a quite significant overhaul, though, + * so currently we make do with this. */ - elide = TkTextIsElided(textPtr, indexPtr); /* save a malloc */ - if (elide && indexPtr->byteIndex==0) { + + paragraphStart = (indexPtr->byteIndex == 0); + + /* + * Special case entirely elide line as there may be 1000s or more. + */ + + elide = TkTextIsElided(textPtr, indexPtr, &info); + if (elide && indexPtr->byteIndex == 0) { maxBytes = 0; - for (segPtr = indexPtr->linePtr->segPtr; - elide && (segPtr != NULL); - segPtr = segPtr->nextPtr) { - if ((elidesize = segPtr->size) > 0) { - maxBytes += elidesize; + for (segPtr = info.segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) { + if (segPtr->size > 0) { + if (elide == 0) { + /* + * We toggled a tag and the elide state changed to + * visible, and we have something of non-zero size. + * Therefore we must bail out. + */ + + break; + } + maxBytes += segPtr->size; + /* - * If have we have a tag toggle, there is a chance - * that invisibility state changed, so bail out + * Reset tag elide priority, since we're on a new character. */ + } else if ((segPtr->typePtr == &tkTextToggleOffType) || (segPtr->typePtr == &tkTextToggleOnType)) { - if (segPtr->body.toggle.tagPtr->elideString != NULL) { - elide = (segPtr->typePtr == &tkTextToggleOffType) - ^ segPtr->body.toggle.tagPtr->elide; + TkTextTag *tagPtr = segPtr->body.toggle.tagPtr; + + /* + * The elide state only changes if this tag is either the + * current highest priority tag (and is therefore being + * toggled off), or it's a new tag with higher priority. + */ + + if (tagPtr->elideString != NULL) { + info.tagCnts[tagPtr->priority]++; + if (info.tagCnts[tagPtr->priority] & 1) { + info.tagPtrs[tagPtr->priority] = tagPtr; + } + if (tagPtr->priority >= info.elidePriority) { + if (segPtr->typePtr == &tkTextToggleOffType) { + /* + * If it is being toggled off, and it has an elide + * string, it must actually be the current highest + * priority tag, so this check is redundant: + */ + + if (tagPtr->priority != info.elidePriority) { + Tcl_Panic("Bad tag priority being toggled off"); + } + + /* + * Find previous elide tag, if any (if not then + * elide will be zero, of course). + */ + + elide = 0; + while (--info.elidePriority > 0) { + if (info.tagCnts[info.elidePriority] & 1) { + elide = info.tagPtrs[info.elidePriority] + ->elide; + break; + } + } + } else { + elide = tagPtr->elide; + info.elidePriority = tagPtr->priority; + } + } } } } @@ -868,15 +1199,31 @@ LayoutDLine(textPtr, indexPtr) if (elide) { dlPtr->byteCount = maxBytes; dlPtr->spaceAbove = dlPtr->spaceBelow = dlPtr->length = 0; + if (dlPtr->index.byteIndex == 0) { + /* + * Elided state goes from beginning to end of an entire + * logical line. This means we can update the line's pixel + * height, and bring its pixel calculation up to date. + */ + + TkBTreeLinePixelEpoch(textPtr, dlPtr->index.linePtr) + = textPtr->dInfoPtr->lineMetricUpdateEpoch; + + if (TkBTreeLinePixelCount(textPtr,dlPtr->index.linePtr) != 0) { + TkBTreeAdjustPixelHeight(textPtr, + dlPtr->index.linePtr, 0, 0); + } + } + TkTextFreeElideInfo(&info); return dlPtr; } } + TkTextFreeElideInfo(&info); /* - * Each iteration of the loop below creates one TkTextDispChunk for - * the new display line. The line will always have at least one - * chunk (for the newline character at the end, if there's nothing - * else available). + * Each iteration of the loop below creates one TkTextDispChunk for the + * new display line. The line will always have at least one chunk (for the + * newline character at the end, if there's nothing else available). */ curIndex = *indexPtr; @@ -890,53 +1237,108 @@ LayoutDLine(textPtr, indexPtr) tabIndex = -1; tabChunkPtr = NULL; tabArrayPtr = NULL; + tabStyle = TK_TEXT_TABSTYLE_TABULAR; rMargin = 0; wrapMode = TEXT_WRAPMODE_CHAR; tabSize = 0; lastCharChunkPtr = NULL; /* - * Find the first segment to consider for the line. Can't call - * TkTextIndexToSeg for this because it won't return a segment - * with zero size (such as the insertion cursor's mark). + * Find the first segment to consider for the line. Can't call + * TkTextIndexToSeg for this because it won't return a segment with zero + * size (such as the insertion cursor's mark). */ - for (byteOffset = curIndex.byteIndex, segPtr = curIndex.linePtr->segPtr; - (byteOffset > 0) && (byteOffset >= segPtr->size); - byteOffset -= segPtr->size, segPtr = segPtr->nextPtr) { - /* Empty loop body. */ + connectNextLogicalLine: + byteOffset = curIndex.byteIndex; + segPtr = curIndex.linePtr->segPtr; + while ((byteOffset > 0) && (byteOffset >= segPtr->size)) { + byteOffset -= segPtr->size; + segPtr = segPtr->nextPtr; + + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through eliding + * of a newline. + */ + + TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr); + if (linePtr != NULL) { + dlPtr->logicalLinesMerged++; + curIndex.byteIndex = 0; + curIndex.linePtr = linePtr; + segPtr = curIndex.linePtr->segPtr; + } else { + break; + } + } } while (segPtr != NULL) { /* - * Every line still gets at least one chunk due to expectations - * in the rest of the code, but we are able to skip elided portions - * of the line quickly. - * If current chunk is elided and last chunk was too, coalese + * Every logical line still gets at least one chunk due to + * expectations in the rest of the code, but we are able to skip + * elided portions of the line quickly. + * + * If current chunk is elided and last chunk was too, coalese. + * + * This also means that each logical line which is entirely elided + * still gets laid out into a DLine, but with zero height. This isn't + * particularly a problem, but it does seem somewhat unnecessary. We + * may wish to redesign the code to remove these zero height DLines in + * the future. */ + if (elide && (lastChunkPtr != NULL) && (lastChunkPtr->displayProc == NULL /*ElideDisplayProc*/)) { - if ((elidesize = segPtr->size - byteOffset) > 0) { + elidesize = segPtr->size - byteOffset; + if (elidesize > 0) { curIndex.byteIndex += elidesize; lastChunkPtr->numBytes += elidesize; - breakByteOffset = lastChunkPtr->breakIndex = lastChunkPtr->numBytes; + breakByteOffset = lastChunkPtr->breakIndex + = lastChunkPtr->numBytes; + /* - * If have we have a tag toggle, there is a chance - * that invisibility state changed, so bail out + * If have we have a tag toggle, there is a chance that + * invisibility state changed, so bail out. */ } else if ((segPtr->typePtr == &tkTextToggleOffType) || (segPtr->typePtr == &tkTextToggleOnType)) { if (segPtr->body.toggle.tagPtr->elideString != NULL) { elide = (segPtr->typePtr == &tkTextToggleOffType) - ^ segPtr->body.toggle.tagPtr->elide; + ^ segPtr->body.toggle.tagPtr->elide; } } byteOffset = 0; segPtr = segPtr->nextPtr; + + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through + * eliding of a newline. + */ + + TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr); + + if (linePtr != NULL) { + dlPtr->logicalLinesMerged++; + curIndex.byteIndex = 0; + curIndex.linePtr = linePtr; + goto connectNextLogicalLine; + } + } + + /* + * Code no longer needed, now that we allow logical lines to merge + * into a single display line. + * if (segPtr == NULL && chunkPtr != NULL) { ckfree((char *) chunkPtr); + chunkPtr = NULL; } + */ + continue; } @@ -948,24 +1350,44 @@ LayoutDLine(textPtr, indexPtr) if (chunkPtr == NULL) { chunkPtr = (TkTextDispChunk *) ckalloc(sizeof(TkTextDispChunk)); chunkPtr->nextPtr = NULL; + chunkPtr->clientData = NULL; } chunkPtr->stylePtr = GetStyle(textPtr, &curIndex); elide = chunkPtr->stylePtr->sValuePtr->elide; /* - * Save style information such as justification and indentation, - * up until the first character is encountered, then retain that + * Save style information such as justification and indentation, up + * until the first character is encountered, then retain that * information for the rest of the line. */ - if (noCharsYet) { + if (!elide && noCharsYet) { tabArrayPtr = chunkPtr->stylePtr->sValuePtr->tabArrayPtr; + tabStyle = chunkPtr->stylePtr->sValuePtr->tabStyle; justify = chunkPtr->stylePtr->sValuePtr->justify; rMargin = chunkPtr->stylePtr->sValuePtr->rMargin; wrapMode = chunkPtr->stylePtr->sValuePtr->wrapMode; - x = ((curIndex.byteIndex == 0) - ? chunkPtr->stylePtr->sValuePtr->lMargin1 - : chunkPtr->stylePtr->sValuePtr->lMargin2); + + /* + * See above - this test may not be entirely correct where we have + * partially elided lines (and therefore merged logical lines). + * In such a case a byteIndex of zero doesn't necessarily mean the + * beginning of a logical line. + */ + + if (paragraphStart) { + /* + * Beginning of logical line. + */ + + x = chunkPtr->stylePtr->sValuePtr->lMargin1; + } else { + /* + * Beginning of display line. + */ + + x = chunkPtr->stylePtr->sValuePtr->lMargin2; + } if (wrapMode == TEXT_WRAPMODE_NONE) { maxX = -1; } else { @@ -977,18 +1399,19 @@ LayoutDLine(textPtr, indexPtr) } } - /* - * See if there is a tab in the current chunk; if so, only - * layout characters up to (and including) the tab. - */ - gotTab = 0; maxBytes = segPtr->size - byteOffset; - if (!elide && justify == TK_JUSTIFY_LEFT) { - if (segPtr->typePtr == &tkTextCharType) { + if (segPtr->typePtr == &tkTextCharType) { + + /* + * See if there is a tab in the current chunk; if so, only layout + * characters up to (and including) the tab. + */ + + if (!elide && justify == TK_JUSTIFY_LEFT) { char *p; - for (p = segPtr->body.chars + byteOffset; *p != 0; p++) { + for (p = segPtr->body.chars + byteOffset; *p != 0; p++) { if (*p == '\t') { maxBytes = (p + 1 - segPtr->body.chars) - byteOffset; gotTab = 1; @@ -996,25 +1419,48 @@ LayoutDLine(textPtr, indexPtr) } } } + +#if TK_LAYOUT_WITH_BASE_CHUNKS + if (baseCharChunkPtr != NULL) { + int expectedX = + ((BaseCharInfo *) baseCharChunkPtr->clientData)->width + + baseCharChunkPtr->x; + + if ((expectedX != x) || !IsSameFGStyle( + baseCharChunkPtr->stylePtr, chunkPtr->stylePtr)) { + FinalizeBaseChunk(NULL); + } + } +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ } chunkPtr->x = x; - if (elide && maxBytes) { - /* don't free style here, as other code expects to be able to do that */ - /*breakByteOffset =*/ chunkPtr->breakIndex = chunkPtr->numBytes = maxBytes; + if (elide /*&& maxBytes*/) { + /* + * Don't free style here, as other code expects to be able to do + * that. + */ + + /* breakByteOffset =*/ + chunkPtr->breakIndex = chunkPtr->numBytes = maxBytes; chunkPtr->width = 0; - chunkPtr->minAscent = chunkPtr->minDescent = chunkPtr->minHeight = 0; + chunkPtr->minAscent = chunkPtr->minDescent + = chunkPtr->minHeight = 0; - /* would just like to point to canonical empty chunk */ - chunkPtr->displayProc = (Tk_ChunkDisplayProc *) NULL; - chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL; + /* + * Would just like to point to canonical empty chunk. + */ + + chunkPtr->displayProc = NULL; + chunkPtr->undisplayProc = NULL; chunkPtr->measureProc = ElideMeasureProc; chunkPtr->bboxProc = ElideBboxProc; code = 1; - } else - code = (*segPtr->typePtr->layoutProc)(textPtr, &curIndex, segPtr, - byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode, - chunkPtr); + } else { + code = (*segPtr->typePtr->layoutProc)(textPtr, &curIndex, segPtr, + byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode, + chunkPtr); + } if (code <= 0) { FreeStyle(textPtr, chunkPtr->stylePtr); if (code < 0) { @@ -1029,8 +1475,8 @@ LayoutDLine(textPtr, indexPtr) } /* - * No characters from this segment fit in the window: this - * means we're at the end of the display line. + * No characters from this segment fit in the window: this means + * we're at the end of the display line. */ if (chunkPtr != NULL) { @@ -1038,7 +1484,19 @@ LayoutDLine(textPtr, indexPtr) } break; } - if (chunkPtr->numBytes > 0) { + + /* + * We currently say we have some characters (and therefore something + * from which to examine tag values for the first character of the + * line) even if those characters are actually elided. This behaviour + * is not well documented, and it might be more consistent to + * completely ignore such elided characters and their tags. To do so + * change this to: + * + * if (!elide && chunkPtr->numBytes > 0). + */ + + if (!elide && chunkPtr->numBytes > 0) { noCharsYet = 0; lastCharChunkPtr = chunkPtr; } @@ -1060,9 +1518,9 @@ LayoutDLine(textPtr, indexPtr) /* * If we're at a new tab, adjust the layout for all the chunks - * pertaining to the previous tab. Also adjust the amount of - * space left in the line to account for space that will be eaten - * up by the tab. + * pertaining to the previous tab. Also adjust the amount of space + * left in the line to account for space that will be eaten up by the + * tab. */ if (gotTab) { @@ -1070,9 +1528,9 @@ LayoutDLine(textPtr, indexPtr) AdjustForTab(textPtr, tabArrayPtr, tabIndex, tabChunkPtr); x = chunkPtr->x + chunkPtr->width; } - tabIndex++; tabChunkPtr = chunkPtr; - tabSize = SizeOfTab(textPtr, tabArrayPtr, tabIndex, x, maxX); + tabSize = SizeOfTab(textPtr, tabStyle, tabArrayPtr, &tabIndex, x, + maxX); if ((maxX >= 0) && (tabSize >= maxX - x)) { break; } @@ -1082,28 +1540,60 @@ LayoutDLine(textPtr, indexPtr) if (byteOffset >= segPtr->size) { byteOffset = 0; segPtr = segPtr->nextPtr; + if (elide && segPtr == NULL) { + /* + * An elided section started on this line, and carries on + * until the newline. Hence the newline is actually elided, + * and we want to merge the display of the next logical line + * with this one. + */ + + TkTextLine *linePtr = TkBTreeNextLine(NULL, curIndex.linePtr); + + if (linePtr != NULL) { + dlPtr->logicalLinesMerged++; + curIndex.byteIndex = 0; + curIndex.linePtr = linePtr; + chunkPtr = NULL; + goto connectNextLogicalLine; + } + } } chunkPtr = NULL; } +#if TK_LAYOUT_WITH_BASE_CHUNKS + FinalizeBaseChunk(NULL); +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ if (noCharsYet) { - panic("LayoutDLine couldn't place any characters on a line"); + dlPtr->spaceAbove = 0; + dlPtr->spaceBelow = 0; + dlPtr->length = 0; + + /* + * We used to Tcl_Panic here, saying that LayoutDLine couldn't place + * any characters on a line, but I believe a more appropriate response + * is to return a DLine with zero height. With elided lines, tag + * transitions and asynchronous line height calculations, it is hard + * to avoid this situation ever arising with the current code design. + */ + + return dlPtr; } wholeLine = (segPtr == NULL); /* - * We're at the end of the display line. Throw away everything - * after the most recent word break, if there is one; this may - * potentially require the last chunk to be layed out again. + * We're at the end of the display line. Throw away everything after the + * most recent word break, if there is one; this may potentially require + * the last chunk to be layed out again. */ if (breakChunkPtr == NULL) { /* - * This code makes sure that we don't accidentally display - * chunks with no characters at the end of the line (such as - * the insertion cursor). These chunks belong on the next - * line. So, throw away everything after the last chunk that - * has characters in it. + * This code makes sure that we don't accidentally display chunks with + * no characters at the end of the line (such as the insertion + * cursor). These chunks belong on the next line. So, throw away + * everything after the last chunk that has characters in it. */ breakChunkPtr = lastCharChunkPtr; @@ -1118,21 +1608,27 @@ LayoutDLine(textPtr, indexPtr) } FreeStyle(textPtr, chunkPtr->stylePtr); breakChunkPtr->nextPtr = chunkPtr->nextPtr; - (*chunkPtr->undisplayProc)(textPtr, chunkPtr); + if (chunkPtr->undisplayProc != NULL) { + (*chunkPtr->undisplayProc)(textPtr, chunkPtr); + } ckfree((char *) chunkPtr); } if (breakByteOffset != breakChunkPtr->numBytes) { - (*breakChunkPtr->undisplayProc)(textPtr, breakChunkPtr); + if (breakChunkPtr->undisplayProc != NULL) { + (*breakChunkPtr->undisplayProc)(textPtr, breakChunkPtr); + } segPtr = TkTextIndexToSeg(&breakIndex, &byteOffset); (*segPtr->typePtr->layoutProc)(textPtr, &breakIndex, - segPtr, byteOffset, maxX, breakByteOffset, 0, + segPtr, byteOffset, maxX, breakByteOffset, 0, wrapMode, breakChunkPtr); +#if TK_LAYOUT_WITH_BASE_CHUNKS + FinalizeBaseChunk(NULL); +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ } lastChunkPtr = breakChunkPtr; wholeLine = 0; } - /* * Make tab adjustments for the last tab stop, if there is one. */ @@ -1142,16 +1638,15 @@ LayoutDLine(textPtr, indexPtr) } /* - * Make one more pass over the line to recompute various things - * like its height, length, and total number of bytes. Also - * modify the x-locations of chunks to reflect justification. - * If we're not wrapping, I'm not sure what is the best way to - * handle left and center justification: should the total length, - * for purposes of justification, be (a) the window width, (b) - * the length of the longest line in the window, or (c) the length - * of the longest line in the text? (c) isn't available, (b) seems - * weird, since it can change with vertical scrolling, so (a) is - * what is implemented below. + * Make one more pass over the line to recompute various things like its + * height, length, and total number of bytes. Also modify the x-locations + * of chunks to reflect justification. If we're not wrapping, I'm not sure + * what is the best way to handle left and center justification: should + * the total length, for purposes of justification, be (a) the window + * width, (b) the length of the longest line in the window, or (c) the + * length of the longest line in the text? (c) isn't available, (b) seems + * weird, since it can change with vertical scrolling, so (a) is what is + * implemented below. */ if (wrapMode == TEXT_WRAPMODE_NONE) { @@ -1206,10 +1701,11 @@ LayoutDLine(textPtr, indexPtr) dlPtr->baseline += dlPtr->spaceAbove; /* - * Recompute line length: may have changed because of justification. + * Recompute line length: may have changed because of justification. */ dlPtr->length = lastChunkPtr->x + lastChunkPtr->width; + return dlPtr; } @@ -1218,38 +1714,37 @@ LayoutDLine(textPtr, indexPtr) * * UpdateDisplayInfo -- * - * This procedure is invoked to recompute some or all of the - * DLine structures for a text widget. At the time it is called - * the DLine structures still left in the widget are guaranteed - * to be correct except that (a) the y-coordinates aren't - * necessarily correct, (b) there may be missing structures - * (the DLine structures get removed as soon as they are potentially - * out-of-date), and (c) DLine structures that don't start at the - * beginning of a line may be incorrect if previous information in - * the same line changed size in a way that moved a line boundary - * (DLines for any info that changed will have been deleted, but - * not DLines for unchanged info in the same text line). + * This function is invoked to recompute some or all of the DLine + * structures for a text widget. At the time it is called the DLine + * structures still left in the widget are guaranteed to be correct + * except that (a) the y-coordinates aren't necessarily correct, (b) + * there may be missing structures (the DLine structures get removed as + * soon as they are potentially out-of-date), and (c) DLine structures + * that don't start at the beginning of a line may be incorrect if + * previous information in the same line changed size in a way that moved + * a line boundary (DLines for any info that changed will have been + * deleted, but not DLines for unchanged info in the same text line). * * Results: * None. * * Side effects: - * Upon return, the DLine information for textPtr correctly reflects - * the positions where characters will be displayed. However, this - * procedure doesn't actually bring the display up-to-date. + * Upon return, the DLine information for textPtr correctly reflects the + * positions where characters will be displayed. However, this function + * doesn't actually bring the display up-to-date. * *---------------------------------------------------------------------- */ static void -UpdateDisplayInfo(textPtr) - TkText *textPtr; /* Text widget to update. */ +UpdateDisplayInfo( + TkText *textPtr) /* Text widget to update. */ { register TextDInfo *dInfoPtr = textPtr->dInfoPtr; register DLine *dlPtr, *prevPtr; TkTextIndex index; TkTextLine *lastLinePtr; - int y, maxY, pixelOffset, maxOffset; + int y, maxY, xPixelOffset, maxOffset, lineHeight; if (!(dInfoPtr->flags & DINFO_OUT_OF_DATE)) { return; @@ -1263,21 +1758,24 @@ UpdateDisplayInfo(textPtr) index = textPtr->topIndex; dlPtr = FindDLine(dInfoPtr->dLinePtr, &index); if ((dlPtr != NULL) && (dlPtr != dInfoPtr->dLinePtr)) { - FreeDLines(textPtr, dInfoPtr->dLinePtr, dlPtr, 1); + FreeDLines(textPtr, dInfoPtr->dLinePtr, dlPtr, DLINE_UNLINK); + } + if (index.byteIndex == 0) { + lineHeight = 0; + } else { + lineHeight = -1; } /* - *-------------------------------------------------------------- - * Scan through the contents of the window from top to bottom, - * recomputing information for lines that are missing. - *-------------------------------------------------------------- + * Scan through the contents of the window from top to bottom, recomputing + * information for lines that are missing. */ - lastLinePtr = TkBTreeFindLine(textPtr->tree, - TkBTreeNumLines(textPtr->tree)); + lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr)); dlPtr = dInfoPtr->dLinePtr; prevPtr = NULL; - y = dInfoPtr->y; + y = dInfoPtr->y - dInfoPtr->newTopPixelOffset; maxY = dInfoPtr->maxY; while (1) { register DLine *newPtr; @@ -1290,22 +1788,20 @@ UpdateDisplayInfo(textPtr) * There are three possibilities right now: * (a) the next DLine (dlPtr) corresponds exactly to the next * information we want to display: just use it as-is. - * (b) the next DLine corresponds to a different line, or to - * a segment that will be coming later in the same line: - * leave this DLine alone in the hopes that we'll be able - * to use it later, then create a new DLine in front of - * it. - * (c) the next DLine corresponds to a segment in the line we - * want, but it's a segment that has already been processed - * or will never be processed. Delete the DLine and try - * again. + * (b) the next DLine corresponds to a different line, or to a segment + * that will be coming later in the same line: leave this DLine + * alone in the hopes that we'll be able to use it later, then + * create a new DLine in front of it. + * (c) the next DLine corresponds to a segment in the line we want, + * but it's a segment that has already been processed or will + * never be processed. Delete the DLine and try again. * - * One other twist on all this. It's possible for 3D borders - * to interact between lines (see DisplayLineBackground) so if - * a line is relayed out and has styles with 3D borders, its - * neighbors have to be redrawn if they have 3D borders too, - * since the interactions could have changed (the neighbors - * don't have to be relayed out, just redrawn). + * One other twist on all this. It's possible for 3D borders to + * interact between lines (see DisplayLineBackground) so if a line is + * relayed out and has styles with 3D borders, its neighbors have to + * be redrawn if they have 3D borders too, since the interactions + * could have changed (the neighbors don't have to be relayed out, + * just redrawn). */ if ((dlPtr == NULL) || (dlPtr->index.linePtr != index.linePtr)) { @@ -1313,20 +1809,17 @@ UpdateDisplayInfo(textPtr) * Case (b) -- must make new DLine. */ - makeNewDLine: + makeNewDLine: if (tkTextDebug) { char string[TK_POS_CHARS]; /* - * Debugging is enabled, so keep a log of all the lines - * that were re-layed out. The test suite uses this - * information. + * Debugging is enabled, so keep a log of all the lines that + * were re-layed out. The test suite uses this information. */ - TkTextPrintIndex(&index, string); - Tcl_SetVar2(textPtr->interp, "tk_textRelayout", (char *) NULL, - string, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + TkTextPrintIndex(textPtr, &index, string); + LOG("tk_textRelayout", string); } newPtr = LayoutDLine(textPtr, &index); if (prevPtr == NULL) { @@ -1334,25 +1827,25 @@ UpdateDisplayInfo(textPtr) } else { prevPtr->nextPtr = newPtr; if (prevPtr->flags & HAS_3D_BORDER) { - prevPtr->oldY = -1; + prevPtr->flags |= OLD_Y_INVALID; } } newPtr->nextPtr = dlPtr; dlPtr = newPtr; } else { /* - * DlPtr refers to the line we want. Next check the - * index within the line. + * DlPtr refers to the line we want. Next check the index within + * the line. */ if (index.byteIndex == dlPtr->index.byteIndex) { /* - * Case (a) -- can use existing display line as-is. + * Case (a) - can use existing display line as-is. */ if ((dlPtr->flags & HAS_3D_BORDER) && (prevPtr != NULL) && (prevPtr->flags & (NEW_LAYOUT))) { - dlPtr->oldY = -1; + dlPtr->flags |= OLD_Y_INVALID; } goto lineOK; } @@ -1361,12 +1854,12 @@ UpdateDisplayInfo(textPtr) } /* - * Case (c) -- dlPtr is useless. Discard it and start - * again with the next display line. + * Case (c) - dlPtr is useless. Discard it and start again with + * the next display line. */ newPtr = dlPtr->nextPtr; - FreeDLines(textPtr, dlPtr, newPtr, 0); + FreeDLines(textPtr, dlPtr, newPtr, DLINE_FREE); dlPtr = newPtr; if (prevPtr != NULL) { prevPtr->nextPtr = newPtr; @@ -1380,16 +1873,19 @@ UpdateDisplayInfo(textPtr) * Advance to the start of the next line. */ - lineOK: + lineOK: dlPtr->y = y; y += dlPtr->height; - TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); + if (lineHeight != -1) { + lineHeight += dlPtr->height; + } + TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, &index); prevPtr = dlPtr; dlPtr = dlPtr->nextPtr; /* - * If we switched text lines, delete any DLines left for the - * old text line. + * If we switched text lines, delete any DLines left for the old text + * line. */ if (index.linePtr != prevPtr->index.linePtr) { @@ -1401,17 +1897,46 @@ UpdateDisplayInfo(textPtr) nextPtr = nextPtr->nextPtr; } if (nextPtr != dlPtr) { - FreeDLines(textPtr, dlPtr, nextPtr, 0); + FreeDLines(textPtr, dlPtr, nextPtr, DLINE_FREE); prevPtr->nextPtr = nextPtr; dlPtr = nextPtr; } + + if ((lineHeight != -1) && (TkBTreeLinePixelCount(textPtr, + prevPtr->index.linePtr) != lineHeight)) { + /* + * The logical line height we just calculated is actually + * differnt to the currently cached height of the text line. + * That is fine (the text line heights are only calculated + * asynchronously), but we must update the cached height so + * that any counts made with DLine pointers are the same as + * counts made through the BTree. This helps to ensure that + * the scrollbar size corresponds accurately to that displayed + * contents, even as the window is re-sized. + */ + + TkBTreeAdjustPixelHeight(textPtr, prevPtr->index.linePtr, + lineHeight, 0); + + /* + * I believe we can be 100% sure that we started at the + * beginning of the logical line, so we can also adjust the + * 'pixelCalculationEpoch' to mark it as being up to date. + * There is a slight concern that we might not have got this + * right for the first line in the re-display. + */ + + TkBTreeLinePixelEpoch(textPtr, prevPtr->index.linePtr) = + dInfoPtr->lineMetricUpdateEpoch; + } + lineHeight = 0; } /* - * It's important to have the following check here rather than in - * the while statement for the loop, so that there's always at least - * one DLine generated, regardless of how small the window is. This - * keeps a lot of other code from breaking. + * It's important to have the following check here rather than in the + * while statement for the loop, so that there's always at least one + * DLine generated, regardless of how small the window is. This keeps + * a lot of other code from breaking. */ if (y >= maxY) { @@ -1423,133 +1948,239 @@ UpdateDisplayInfo(textPtr) * Delete any DLine structures that don't fit on the screen. */ - FreeDLines(textPtr, dlPtr, (DLine *) NULL, 1); + FreeDLines(textPtr, dlPtr, NULL, DLINE_UNLINK); /* - *-------------------------------------------------------------- - * If there is extra space at the bottom of the window (because - * we've hit the end of the text), then bring in more lines at - * the top of the window, if there are any, to fill in the view. - *-------------------------------------------------------------- + * If there is extra space at the bottom of the window (because we've hit + * the end of the text), then bring in more lines at the top of the + * window, if there are any, to fill in the view. + * + * Since the top line may only be partially visible, we try first to + * simply show more pixels from that line (newTopPixelOffset). If that + * isn't enough, we have to layout more lines. */ if (y < maxY) { - int lineNum, spaceLeft, bytesToCount; - DLine *lowestPtr; - /* - * Layout an entire text line (potentially > 1 display line), - * then link in as many display lines as fit without moving - * the bottom line out of the window. Repeat this until - * all the extra space has been used up or we've reached the - * beginning of the text. + * This counts how many vertical pixels we have left to fill by + * pulling in more display pixels either from the first currently + * displayed, or the lines above it. */ - spaceLeft = maxY - y; - lineNum = TkBTreeLineIndex(dInfoPtr->dLinePtr->index.linePtr); - bytesToCount = dInfoPtr->dLinePtr->index.byteIndex; - if (bytesToCount == 0) { - bytesToCount = INT_MAX; - lineNum--; - } - for ( ; (lineNum >= 0) && (spaceLeft > 0); lineNum--) { - index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum); - index.byteIndex = 0; - lowestPtr = NULL; + int spaceLeft = maxY - y; - do { - dlPtr = LayoutDLine(textPtr, &index); - dlPtr->nextPtr = lowestPtr; - lowestPtr = dlPtr; - if (dlPtr->length == 0 && dlPtr->height == 0) { bytesToCount--; break; } /* elide */ - TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); - bytesToCount -= dlPtr->byteCount; - } while ((bytesToCount > 0) - && (index.linePtr == lowestPtr->index.linePtr)); + if (spaceLeft <= dInfoPtr->newTopPixelOffset) { + /* + * We can fill up all the needed space just by showing more of the + * current top line. + */ + + dInfoPtr->newTopPixelOffset -= spaceLeft; + y += spaceLeft; + spaceLeft = 0; + } else { + int lineNum, bytesToCount; + DLine *lowestPtr; /* - * Scan through the display lines from the bottom one up to - * the top one. + * Add in all of the current top line, which won't be enough to + * bring y up to maxY (if it was we would be in the 'if' block + * above). */ - while (lowestPtr != NULL) { - dlPtr = lowestPtr; - spaceLeft -= dlPtr->height; - if (spaceLeft < 0) { - break; + y += dInfoPtr->newTopPixelOffset; + dInfoPtr->newTopPixelOffset = 0; + + /* + * Layout an entire text line (potentially > 1 display line), then + * link in as many display lines as fit without moving the bottom + * line out of the window. Repeat this until all the extra space + * has been used up or we've reached the beginning of the text. + */ + + spaceLeft = maxY - y; + if (dInfoPtr->dLinePtr == NULL) { + /* + * No lines have been laid out. This must be an empty peer + * widget. + */ + + lineNum = -1; + bytesToCount = 0; /* Stop compiler warning. */ + } else { + lineNum = TkBTreeLinesTo(textPtr, + dInfoPtr->dLinePtr->index.linePtr); + bytesToCount = dInfoPtr->dLinePtr->index.byteIndex; + if (bytesToCount == 0) { + bytesToCount = INT_MAX; + lineNum--; + } + } + for ( ; (lineNum >= 0) && (spaceLeft > 0); lineNum--) { + int pixelHeight = 0; + + index.linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, lineNum); + index.byteIndex = 0; + lowestPtr = NULL; + + do { + dlPtr = LayoutDLine(textPtr, &index); + pixelHeight += dlPtr->height; + dlPtr->nextPtr = lowestPtr; + lowestPtr = dlPtr; + if (dlPtr->length == 0 && dlPtr->height == 0) { + bytesToCount--; + break; + } /* elide */ + TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, + &index); + bytesToCount -= dlPtr->byteCount; + } while ((bytesToCount > 0) + && (index.linePtr == lowestPtr->index.linePtr)); + + /* + * We may not have examined the entire line (depending on the + * value of 'bytesToCount', so we only want to set this if it + * is genuinely bigger). + */ + + if (pixelHeight > TkBTreeLinePixelCount(textPtr, + lowestPtr->index.linePtr)) { + TkBTreeAdjustPixelHeight(textPtr, + lowestPtr->index.linePtr, pixelHeight, 0); + if (index.linePtr != lowestPtr->index.linePtr) { + /* + * We examined the entire line, so can update the + * epoch. + */ + + TkBTreeLinePixelEpoch(textPtr, + lowestPtr->index.linePtr) = + dInfoPtr->lineMetricUpdateEpoch; + } } - lowestPtr = dlPtr->nextPtr; - dlPtr->nextPtr = dInfoPtr->dLinePtr; - dInfoPtr->dLinePtr = dlPtr; - if (tkTextDebug) { - char string[TK_POS_CHARS]; - TkTextPrintIndex(&dlPtr->index, string); - Tcl_SetVar2(textPtr->interp, "tk_textRelayout", - (char *) NULL, string, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + /* + * Scan through the display lines from the bottom one up to + * the top one. + */ + + while (lowestPtr != NULL) { + dlPtr = lowestPtr; + spaceLeft -= dlPtr->height; + lowestPtr = dlPtr->nextPtr; + dlPtr->nextPtr = dInfoPtr->dLinePtr; + dInfoPtr->dLinePtr = dlPtr; + if (tkTextDebug) { + char string[TK_POS_CHARS]; + + TkTextPrintIndex(textPtr, &dlPtr->index, string); + LOG("tk_textRelayout", string); + } + if (spaceLeft <= 0) { + break; + } + } + FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE); + bytesToCount = INT_MAX; + } + + /* + * We've either filled in the space we wanted to or we've run out + * of display lines at the top of the text. Note that we already + * set dInfoPtr->newTopPixelOffset to zero above. + */ + + if (spaceLeft < 0) { + /* + * We've laid out a few too many vertical pixels at or above + * the first line. Therefore we only want to show part of the + * first displayed line, so that the last displayed line just + * fits in the window. + */ + + dInfoPtr->newTopPixelOffset = -spaceLeft; + if (dInfoPtr->newTopPixelOffset>=dInfoPtr->dLinePtr->height) { + /* + * Somehow the entire first line we laid out is shorter + * than the new offset. This should not occur and would + * indicate a bad problem in the logic above. + */ + + Tcl_Panic("Error in pixel height consistency while filling in spacesLeft"); } } - FreeDLines(textPtr, lowestPtr, (DLine *) NULL, 0); - bytesToCount = INT_MAX; } /* - * Now we're all done except that the y-coordinates in all the - * DLines are wrong and the top index for the text is wrong. - * Update them. + * Now we're all done except that the y-coordinates in all the DLines + * are wrong and the top index for the text is wrong. Update them. */ - textPtr->topIndex = dInfoPtr->dLinePtr->index; - y = dInfoPtr->y; - for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; - dlPtr = dlPtr->nextPtr) { - if (y > dInfoPtr->maxY) { - panic("Added too many new lines in UpdateDisplayInfo"); + if (dInfoPtr->dLinePtr != NULL) { + textPtr->topIndex = dInfoPtr->dLinePtr->index; + y = dInfoPtr->y - dInfoPtr->newTopPixelOffset; + for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; + dlPtr = dlPtr->nextPtr) { + if (y > dInfoPtr->maxY) { + Tcl_Panic("Added too many new lines in UpdateDisplayInfo"); + } + dlPtr->y = y; + y += dlPtr->height; } - dlPtr->y = y; - y += dlPtr->height; } } /* - *-------------------------------------------------------------- - * If the old top or bottom line has scrolled elsewhere on the - * screen, we may not be able to re-use its old contents by - * copying bits (e.g., a beveled edge that was drawn when it was - * at the top or bottom won't be drawn when the line is in the - * middle and its neighbor has a matching background). Similarly, - * if the new top or bottom line came from somewhere else on the - * screen, we may not be able to copy the old bits. - *-------------------------------------------------------------- + * If the old top or bottom line has scrolled elsewhere on the screen, we + * may not be able to re-use its old contents by copying bits (e.g., a + * beveled edge that was drawn when it was at the top or bottom won't be + * drawn when the line is in the middle and its neighbor has a matching + * background). Similarly, if the new top or bottom line came from + * somewhere else on the screen, we may not be able to copy the old bits. */ dlPtr = dInfoPtr->dLinePtr; - if ((dlPtr->flags & HAS_3D_BORDER) && !(dlPtr->flags & TOP_LINE)) { - dlPtr->oldY = -1; - } - while (1) { - if ((dlPtr->flags & TOP_LINE) && (dlPtr != dInfoPtr->dLinePtr) - && (dlPtr->flags & HAS_3D_BORDER)) { - dlPtr->oldY = -1; - } - if ((dlPtr->flags & BOTTOM_LINE) && (dlPtr->nextPtr != NULL) - && (dlPtr->flags & HAS_3D_BORDER)) { - dlPtr->oldY = -1; + if (dlPtr != NULL) { + if ((dlPtr->flags & HAS_3D_BORDER) && !(dlPtr->flags & TOP_LINE)) { + dlPtr->flags |= OLD_Y_INVALID; } - if (dlPtr->nextPtr == NULL) { - if ((dlPtr->flags & HAS_3D_BORDER) - && !(dlPtr->flags & BOTTOM_LINE)) { - dlPtr->oldY = -1; + while (1) { + if ((dlPtr->flags & TOP_LINE) && (dlPtr != dInfoPtr->dLinePtr) + && (dlPtr->flags & HAS_3D_BORDER)) { + dlPtr->flags |= OLD_Y_INVALID; } - dlPtr->flags &= ~TOP_LINE; - dlPtr->flags |= BOTTOM_LINE; - break; + + /* + * If the old top-line was not completely showing (i.e. the + * pixelOffset is non-zero) and is no longer the top-line, then we + * must re-draw it. + */ + + if ((dlPtr->flags & TOP_LINE) && + dInfoPtr->topPixelOffset!=0 && dlPtr!=dInfoPtr->dLinePtr) { + dlPtr->flags |= OLD_Y_INVALID; + } + if ((dlPtr->flags & BOTTOM_LINE) && (dlPtr->nextPtr != NULL) + && (dlPtr->flags & HAS_3D_BORDER)) { + dlPtr->flags |= OLD_Y_INVALID; + } + if (dlPtr->nextPtr == NULL) { + if ((dlPtr->flags & HAS_3D_BORDER) + && !(dlPtr->flags & BOTTOM_LINE)) { + dlPtr->flags |= OLD_Y_INVALID; + } + dlPtr->flags &= ~TOP_LINE; + dlPtr->flags |= BOTTOM_LINE; + break; + } + dlPtr->flags &= ~(TOP_LINE|BOTTOM_LINE); + dlPtr = dlPtr->nextPtr; } - dlPtr->flags &= ~(TOP_LINE|BOTTOM_LINE); - dlPtr = dlPtr->nextPtr; + dInfoPtr->dLinePtr->flags |= TOP_LINE; + dInfoPtr->topPixelOffset = dInfoPtr->newTopPixelOffset; } - dInfoPtr->dLinePtr->flags |= TOP_LINE; /* * Arrange for scrollbars to be updated. @@ -1558,15 +2189,12 @@ UpdateDisplayInfo(textPtr) textPtr->flags |= UPDATE_SCROLLBARS; /* - *-------------------------------------------------------------- * Deal with horizontal scrolling: - * 1. If there's empty space to the right of the longest line, - * shift the screen to the right to fill in the empty space. - * 2. If the desired horizontal scroll position has changed, - * force a full redisplay of all the lines in the widget. - * 3. If the wrap mode isn't "none" then re-scroll to the base - * position. - *-------------------------------------------------------------- + * 1. If there's empty space to the right of the longest line, shift the + * screen to the right to fill in the empty space. + * 2. If the desired horizontal scroll position has changed, force a full + * redisplay of all the lines in the widget. + * 3. If the wrap mode isn't "none" then re-scroll to the base position. */ dInfoPtr->maxLength = 0; @@ -1576,20 +2204,35 @@ UpdateDisplayInfo(textPtr) dInfoPtr->maxLength = dlPtr->length; } } - maxOffset = (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x) - + textPtr->charWidth - 1)/textPtr->charWidth; - if (dInfoPtr->newByteOffset > maxOffset) { - dInfoPtr->newByteOffset = maxOffset; + maxOffset = dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x); + + xPixelOffset = dInfoPtr->newXPixelOffset; + if (xPixelOffset > maxOffset) { + xPixelOffset = maxOffset; } - if (dInfoPtr->newByteOffset < 0) { - dInfoPtr->newByteOffset = 0; + if (xPixelOffset < 0) { + xPixelOffset = 0; } - pixelOffset = dInfoPtr->newByteOffset * textPtr->charWidth; - if (pixelOffset != dInfoPtr->curPixelOffset) { - dInfoPtr->curPixelOffset = pixelOffset; + + /* + * Here's a problem: see the tests textDisp-29.2.1-4 + * + * If the widget is being created, but has not yet been configured it will + * have a maxY of 1 above, and we we won't have examined all the lines + * (just the first line, in fact), and so maxOffset will not be a true + * reflection of the widget's lines. Therefore we must not overwrite the + * original newXPixelOffset in this case. + */ + + if (!(((Tk_FakeWin *) (textPtr->tkwin))->flags & TK_NEED_CONFIG_NOTIFY)) { + dInfoPtr->newXPixelOffset = xPixelOffset; + } + + if (xPixelOffset != dInfoPtr->curXPixelOffset) { + dInfoPtr->curXPixelOffset = xPixelOffset; for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { - dlPtr->oldY = -1; + dlPtr->flags |= OLD_Y_INVALID; } } } @@ -1599,8 +2242,8 @@ UpdateDisplayInfo(textPtr) * * FreeDLines -- * - * This procedure is called to free up all of the resources - * associated with one or more DLine structures. + * This function is called to free up all of the resources associated + * with one or more DLine structures. * * Results: * None. @@ -1612,27 +2255,43 @@ UpdateDisplayInfo(textPtr) */ static void -FreeDLines(textPtr, firstPtr, lastPtr, unlink) - TkText *textPtr; /* Information about overall text - * widget. */ - register DLine *firstPtr; /* Pointer to first DLine to free up. */ - DLine *lastPtr; /* Pointer to DLine just after last - * one to free (NULL means everything - * starting with firstPtr). */ - int unlink; /* 1 means DLines are currently linked - * into the list rooted at - * textPtr->dInfoPtr->dLinePtr and - * they have to be unlinked. 0 means - * just free without unlinking. */ +FreeDLines( + TkText *textPtr, /* Information about overall text widget. */ + register DLine *firstPtr, /* Pointer to first DLine to free up. */ + DLine *lastPtr, /* Pointer to DLine just after last one to + * free (NULL means everything starting with + * firstPtr). */ + int action) /* DLINE_UNLINK means DLines are currently + * linked into the list rooted at + * textPtr->dInfoPtr->dLinePtr and they have + * to be unlinked. DLINE_FREE means just free + * without unlinking. DLINE_FREE_TEMP means + * the DLine given is just a temporary one and + * we shouldn't invalidate anything for the + * overall widget. */ { register TkTextDispChunk *chunkPtr, *nextChunkPtr; register DLine *nextDLinePtr; - if (unlink) { + if (action == DLINE_FREE_TEMP) { + lineHeightsRecalculated++; + if (tkTextDebug) { + char string[TK_POS_CHARS]; + + /* + * Debugging is enabled, so keep a log of all the lines whose + * height was recalculated. The test suite uses this information. + */ + + TkTextPrintIndex(textPtr, &firstPtr->index, string); + LOG("tk_textHeightCalc", string); + } + } else if (action == DLINE_UNLINK) { if (textPtr->dInfoPtr->dLinePtr == firstPtr) { textPtr->dInfoPtr->dLinePtr = lastPtr; } else { register DLine *prevPtr; + for (prevPtr = textPtr->dInfoPtr->dLinePtr; prevPtr->nextPtr != firstPtr; prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ @@ -1654,7 +2313,9 @@ FreeDLines(textPtr, firstPtr, lastPtr, unlink) ckfree((char *) firstPtr); firstPtr = nextDLinePtr; } - textPtr->dInfoPtr->dLinesInvalidated = 1; + if (action != DLINE_FREE_TEMP) { + textPtr->dInfoPtr->dLinesInvalidated = 1; + } } /* @@ -1662,34 +2323,32 @@ FreeDLines(textPtr, firstPtr, lastPtr, unlink) * * DisplayDLine -- * - * This procedure is invoked to draw a single line on the - * screen. + * This function is invoked to draw a single line on the screen. * * Results: * None. * * Side effects: - * The line given by dlPtr is drawn at its correct position in - * textPtr's window. Note that this is one *display* line, not - * one *text* line. + * The line given by dlPtr is drawn at its correct position in textPtr's + * window. Note that this is one *display* line, not one *text* line. * *---------------------------------------------------------------------- */ static void -DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) - TkText *textPtr; /* Text widget in which to draw line. */ - register DLine *dlPtr; /* Information about line to draw. */ - DLine *prevPtr; /* Line just before one to draw, or NULL - * if dlPtr is the top line. */ - Pixmap pixmap; /* Pixmap to use for double-buffering. - * Caller must make sure it's large enough - * to hold line. */ +DisplayDLine( + TkText *textPtr, /* Text widget in which to draw line. */ + register DLine *dlPtr, /* Information about line to draw. */ + DLine *prevPtr, /* Line just before one to draw, or NULL if + * dlPtr is the top line. */ + Pixmap pixmap) /* Pixmap to use for double-buffering. Caller + * must make sure it's large enough to hold + * line. */ { register TkTextDispChunk *chunkPtr; TextDInfo *dInfoPtr = textPtr->dInfoPtr; Display *display; - int height, x; + int height, y_off; #ifndef TK_NO_DOUBLE_BUFFERING const int y = 0; #else @@ -1704,15 +2363,21 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) if ((height + dlPtr->y) > dInfoPtr->maxY) { height = dInfoPtr->maxY - dlPtr->y; } + if (dlPtr->y < dInfoPtr->y) { + y_off = dInfoPtr->y - dlPtr->y; + height -= y_off; + } else { + y_off = 0; + } #ifdef TK_NO_DOUBLE_BUFFERING - TkpClipDrawableToRect(display, pixmap, dInfoPtr->x, y, + TkpClipDrawableToRect(display, pixmap, dInfoPtr->x, y + y_off, dInfoPtr->maxX - dInfoPtr->x, height); #endif /* TK_NO_DOUBLE_BUFFERING */ /* - * First, clear the area of the line to the background color for the - * text widget. + * First, clear the area of the line to the background color for the text + * widget. */ Tk_Fill3DRectangle(textPtr->tkwin, pixmap, textPtr->border, 0, y, @@ -1725,19 +2390,20 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap); /* - * 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 will obscure the character - * to its left. + * 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 + * will obscure the character to its left. */ - if (textPtr->state == TK_STATE_NORMAL) { + if (textPtr->state == TK_TEXT_STATE_NORMAL) { for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL); chunkPtr = chunkPtr->nextPtr) { - x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curPixelOffset; if (chunkPtr->displayProc == TkTextInsertDisplayProc) { - (*chunkPtr->displayProc)(chunkPtr, x, y + dlPtr->spaceAbove, + int x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset; + + (*chunkPtr->displayProc)(textPtr, chunkPtr, x, + y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, display, pixmap, dlPtr->y + dlPtr->spaceAbove); @@ -1747,49 +2413,49 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) /* * Make yet another pass through all of the chunks to redraw all of - * foreground information. Note: we have to call the displayProc - * even for chunks that are off-screen. This is needed, for - * example, so that embedded windows can be unmapped in this case. - * Conve + * foreground information. Note: we have to call the displayProc even for + * chunks that are off-screen. This is needed, for example, so that + * embedded windows can be unmapped in this case. */ for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL); chunkPtr = chunkPtr->nextPtr) { if (chunkPtr->displayProc == TkTextInsertDisplayProc) { /* - * Already displayed the insertion cursor above. Don't - * do it again here. + * Already displayed the insertion cursor above. Don't do it again + * here. */ continue; } - x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curPixelOffset; - if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) { - /* - * Note: we have to call the displayProc even for chunks - * that are off-screen. This is needed, for example, so - * that embedded windows can be unmapped in this case. - * Display the chunk at a coordinate that can be clearly - * identified by the displayProc as being off-screen to - * the left (the displayProc may not be able to tell if - * something is off to the right). - */ - if (chunkPtr->displayProc != NULL) - (*chunkPtr->displayProc)(chunkPtr, -chunkPtr->width, - y + dlPtr->spaceAbove, - dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, - dlPtr->baseline - dlPtr->spaceAbove, display, pixmap, - dlPtr->y + dlPtr->spaceAbove); - } else { - /* don't call if elide. This tax ok since not very many visible DLine's in - an area, but potentially many elide ones */ - if (chunkPtr->displayProc != NULL) - (*chunkPtr->displayProc)(chunkPtr, x, y + dlPtr->spaceAbove, - dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, - dlPtr->baseline - dlPtr->spaceAbove, display, pixmap, - dlPtr->y + dlPtr->spaceAbove); + /* + * Don't call if elide. This tax OK since not very many visible DLines + * in an area, but potentially many elide ones. + */ + + if (chunkPtr->displayProc != NULL) { + int x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset; + + if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) { + /* + * Note: we have to call the displayProc even for chunks that + * are off-screen. This is needed, for example, so that + * embedded windows can be unmapped in this case. Display the + * chunk at a coordinate that can be clearly identified by the + * displayProc as being off-screen to the left (the + * displayProc may not be able to tell if something is off to + * the right). + */ + + x = -chunkPtr->width; + } + (*chunkPtr->displayProc)(textPtr, chunkPtr, x, + y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - + dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, + display, pixmap, dlPtr->y + dlPtr->spaceAbove); } + if (dInfoPtr->dLinesInvalidated) { return; } @@ -1797,17 +2463,17 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) #ifndef TK_NO_DOUBLE_BUFFERING /* - * Copy the pixmap onto the screen. If this is the last line on - * the screen then copy a piece of the line, so that it doesn't - * overflow into the border area. Another special trick: copy the - * padding area to the left of the line; this is because the - * insertion cursor sometimes overflows onto that area and we want - * to get as much of the cursor as possible. + * Copy the pixmap onto the screen. If this is the first or last line on + * the screen then copy a piece of the line, so that it doesn't overflow + * into the border area. Another special trick: copy the padding area to + * the left of the line; this is because the insertion cursor sometimes + * overflows onto that area and we want to get as much of the cursor as + * possible. */ XCopyArea(display, pixmap, Tk_WindowId(textPtr->tkwin), dInfoPtr->copyGC, - dInfoPtr->x, y, (unsigned) (dInfoPtr->maxX - dInfoPtr->x), - (unsigned) height, dInfoPtr->x, dlPtr->y); + dInfoPtr->x, y + y_off, (unsigned) (dInfoPtr->maxX - dInfoPtr->x), + (unsigned) height, dInfoPtr->x, dlPtr->y + y_off); #else TkpClipDrawableToRect(display, pixmap, 0, 0, -1, -1); #endif /* TK_NO_DOUBLE_BUFFERING */ @@ -1819,14 +2485,13 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) * * DisplayLineBackground -- * - * This procedure is called to fill in the background for - * a display line. It draws 3D borders cleverly so that - * adjacent chunks with the same style (whether on the same - * line or different lines) have a single 3D border around - * the whole region. + * This function is called to fill in the background for a display line. + * It draws 3D borders cleverly so that adjacent chunks with the same + * style (whether on the same line or different lines) have a single 3D + * border around the whole region. * * Results: - * There is no return value. Pixmap is filled in with background + * There is no return value. Pixmap is filled in with background * information for dlPtr. * * Side effects: @@ -1836,39 +2501,38 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap) */ static void -DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) - TkText *textPtr; /* Text widget containing line. */ - register DLine *dlPtr; /* Information about line to draw. */ - DLine *prevPtr; /* Line just above dlPtr, or NULL if dlPtr - * is the top-most line in the window. */ - Pixmap pixmap; /* Pixmap to use for double-buffering. - * Caller must make sure it's large enough - * to hold line. Caller must also have - * filled it with the background color for - * the widget. */ +DisplayLineBackground( + TkText *textPtr, /* Text widget containing line. */ + register DLine *dlPtr, /* Information about line to draw. */ + DLine *prevPtr, /* Line just above dlPtr, or NULL if dlPtr is + * the top-most line in the window. */ + Pixmap pixmap) /* Pixmap to use for double-buffering. Caller + * must make sure it's large enough to hold + * line. Caller must also have filled it with + * the background color for the widget. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - TkTextDispChunk *chunkPtr; /* Pointer to chunk in the current line. */ - TkTextDispChunk *chunkPtr2; /* Pointer to chunk in the line above or - * below the current one. NULL if we're to - * the left of or to the right of the chunks - * in the line. */ + TkTextDispChunk *chunkPtr; /* Pointer to chunk in the current line. */ + TkTextDispChunk *chunkPtr2; /* Pointer to chunk in the line above or below + * the current one. NULL if we're to the left + * of or to the right of the chunks in the + * line. */ TkTextDispChunk *nextPtr2; /* Next chunk after chunkPtr2 (it's not the * same as chunkPtr2->nextPtr in the case - * where chunkPtr2 is NULL because the line - * is indented). */ - int leftX; /* The left edge of the region we're - * currently working on. */ + * where chunkPtr2 is NULL because the line is + * indented). */ + int leftX; /* The left edge of the region we're currently + * working on. */ int leftXIn; /* 1 means beveled edge at leftX slopes right - * as it goes down, 0 means it slopes left - * as it goes down. */ + * as it goes down, 0 means it slopes left as + * it goes down. */ int rightX; /* Right edge of chunkPtr. */ int rightX2; /* Right edge of chunkPtr2. */ - int matchLeft; /* Does the style of this line match that - * of its neighbor just to the left of - * the current x coordinate? */ - int matchRight; /* Does line's style match its neighbor - * just to the right of the current x-coord? */ + int matchLeft; /* Does the style of this line match that of + * its neighbor just to the left of the + * current x coordinate? */ + int matchRight; /* Does line's style match its neighbor just + * to the right of the current x-coord? */ int minX, maxX, xOffset; StyleValues *sValuePtr; Display *display; @@ -1879,32 +2543,29 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) #endif /* TK_NO_DOUBLE_BUFFERING */ /* - * Pass 1: scan through dlPtr from left to right. For each range of - * chunks with the same style, draw the main background for the style - * plus the vertical parts of the 3D borders (the left and right - * edges). + * Pass 1: scan through dlPtr from left to right. For each range of chunks + * with the same style, draw the main background for the style plus the + * vertical parts of the 3D borders (the left and right edges). */ display = Tk_Display(textPtr->tkwin); - minX = dInfoPtr->curPixelOffset; + minX = dInfoPtr->curXPixelOffset; xOffset = dInfoPtr->x - minX; maxX = minX + dInfoPtr->maxX - dInfoPtr->x; chunkPtr = dlPtr->chunkPtr; /* - * Note A: in the following statement, and a few others later in - * this file marked with "See Note A above", the right side of the - * assignment was replaced with 0 on 6/18/97. This has the effect - * of highlighting the empty space to the left of a line whenever - * the leftmost character of the line is highlighted. This way, - * multi-line highlights always line up along their left edges. - * However, this may look funny in the case where a single word is - * highlighted. To undo the change, replace "leftX = 0" with "leftX - * = chunkPtr->x" and "rightX2 = 0" with "rightX2 = nextPtr2->x" - * here and at all the marked points below. This restores the old - * behavior where empty space to the left of a line is not - * highlighted, leaving a ragged left edge for multi-line - * highlights. + * Note A: in the following statement, and a few others later in this file + * marked with "See Note A above", the right side of the assignment was + * replaced with 0 on 6/18/97. This has the effect of highlighting the + * empty space to the left of a line whenever the leftmost character of + * the line is highlighted. This way, multi-line highlights always line up + * along their left edges. However, this may look funny in the case where + * a single word is highlighted. To undo the change, replace "leftX = 0" + * with "leftX = chunkPtr->x" and "rightX2 = 0" with "rightX2 = + * nextPtr2->x" here and at all the marked points below. This restores the + * old behavior where empty space to the left of a line is not + * highlighted, leaving a ragged left edge for multi-line highlights. */ leftX = 0; @@ -1920,9 +2581,12 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) rightX = maxX; } if (chunkPtr->stylePtr->bgGC != None) { - /* Not visible - bail out now */ + /* + * Not visible - bail out now. + */ + if (rightX + xOffset <= 0) { - leftX = rightX; + leftX = rightX; continue; } @@ -1932,11 +2596,12 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) * -32768 (or less) to +something simply does not display * correctly. [Patch #541999] */ + if ((leftX + xOffset) < -(sValuePtr->borderWidth)) { - leftX = -sValuePtr->borderWidth - xOffset; + leftX = -sValuePtr->borderWidth - xOffset; } if ((rightX - leftX) > 32767) { - rightX = leftX + 32767; + rightX = leftX + 32767; } XFillRectangle(display, pixmap, chunkPtr->stylePtr->bgGC, @@ -1956,9 +2621,9 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) } /* - * Pass 2: draw the horizontal bevels along the top of the line. To - * do this, scan through dlPtr from left to right while simultaneously - * scanning through the line just above dlPtr. ChunkPtr2 and nextPtr2 + * Pass 2: draw the horizontal bevels along the top of the line. To do + * this, scan through dlPtr from left to right while simultaneously + * scanning through the line just above dlPtr. ChunkPtr2 and nextPtr2 * refer to two adjacent chunks in the line above. */ @@ -1999,8 +2664,8 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) sValuePtr = chunkPtr->stylePtr->sValuePtr; if (rightX <= rightX2) { /* - * The chunk in our line is about to end. If its style - * changes then draw the bevel for the current style. + * The chunk in our line is about to end. If its style changes + * then draw the bevel for the current style. */ if ((chunkPtr->nextPtr == NULL) @@ -2016,9 +2681,8 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) leftXIn = 1; /* - * If the chunk in the line above is also ending at - * the same point then advance to the next chunk in - * that line. + * If the chunk in the line above is also ending at the same + * point then advance to the next chunk in that line. */ if ((rightX == rightX2) && (chunkPtr2 != NULL)) { @@ -2037,11 +2701,10 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) } /* - * The chunk in the line above is ending at an x-position where - * there is no change in the style of the current line. If the - * style above matches the current line on one side of the change - * but not on the other, we have to draw an L-shaped piece of - * bevel. + * The chunk in the line above is ending at an x-position where there + * is no change in the style of the current line. If the style above + * matches the current line on one side of the change but not on the + * other, we have to draw an L-shaped piece of bevel. */ matchRight = (nextPtr2 != NULL) @@ -2061,12 +2724,12 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) rightX2 + xOffset, y, sValuePtr->borderWidth, sValuePtr->borderWidth, 1, sValuePtr->relief); Tk_3DHorizontalBevel(textPtr->tkwin, pixmap, sValuePtr->border, - leftX + xOffset, y, rightX2 + sValuePtr->borderWidth - + leftX + xOffset, y, rightX2 + sValuePtr->borderWidth - leftX, sValuePtr->borderWidth, leftXIn, 0, 1, sValuePtr->relief); } - nextChunk2: + nextChunk2: chunkPtr2 = nextPtr2; if (chunkPtr2 == NULL) { rightX2 = INT_MAX; @@ -2078,9 +2741,10 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) } } } + /* - * Pass 3: draw the horizontal bevels along the bottom of the line. - * This uses the same approach as pass 2. + * Pass 3: draw the horizontal bevels along the bottom of the line. This + * uses the same approach as pass 2. */ chunkPtr = dlPtr->chunkPtr; @@ -2171,7 +2835,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) sValuePtr->relief); } - nextChunk2b: + nextChunk2b: chunkPtr2 = nextPtr2; if (chunkPtr2 == NULL) { rightX2 = INT_MAX; @@ -2188,11 +2852,1025 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) /* *---------------------------------------------------------------------- * + * AsyncUpdateLineMetrics -- + * + * This function is invoked as a background handler to update the pixel- + * height calculations of individual lines in an asychronous manner. + * + * Currently a timer-handler is used for this purpose, which continuously + * reschedules itself. It may well be better to use some other approach + * (e.g., a background thread). We can't use an idle-callback because of + * a known bug in Tcl/Tk in which idle callbacks are not allowed to + * re-schedule themselves. This just causes an effective infinite loop. + * + * Results: + * None. + * + * Side effects: + * Line heights may be recalculated. + * + *---------------------------------------------------------------------- + */ + +static void +AsyncUpdateLineMetrics( + ClientData clientData) /* Information about widget. */ +{ + register TkText *textPtr = (TkText *) clientData; + TextDInfo *dInfoPtr = textPtr->dInfoPtr; + int lineNum; + + dInfoPtr->lineUpdateTimer = NULL; + + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { + /* + * The widget has been deleted. Don't do anything. + */ + + if (--textPtr->refCount == 0) { + ckfree((char *) textPtr); + } + return; + } + + if (dInfoPtr->flags & REDRAW_PENDING) { + dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, + AsyncUpdateLineMetrics, clientData); + return; + } + + lineNum = dInfoPtr->currentMetricUpdateLine; + if (dInfoPtr->lastMetricUpdateLine == -1) { + dInfoPtr->lastMetricUpdateLine = + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + } + + /* + * Update the lines in blocks of about 24 recalculations, or 250+ lines + * examined, so we pass in 256 for 'doThisMuch'. + */ + + lineNum = TkTextUpdateLineMetrics(textPtr, lineNum, + dInfoPtr->lastMetricUpdateLine, 256); + + if (tkTextDebug) { + char buffer[2 * TCL_INTEGER_SPACE + 1]; + + sprintf(buffer, "%d %d", lineNum, dInfoPtr->lastMetricUpdateLine); + LOG("tk_textInvalidateLine", buffer); + } + + /* + * If we're not in the middle of a long-line calculation (metricEpoch==-1) + * and we've reached the last line, then we're done. + */ + + if (dInfoPtr->metricEpoch == -1 + && lineNum == dInfoPtr->lastMetricUpdateLine) { + /* + * We have looped over all lines, so we're done. We must release our + * refCount on the widget (the timer token was already set to NULL + * above). + */ + + textPtr->refCount--; + if (textPtr->refCount == 0) { + ckfree((char *) textPtr); + } + return; + } + dInfoPtr->currentMetricUpdateLine = lineNum; + + /* + * Re-arm the timer. We already have a refCount on the text widget so no + * need to adjust that. + */ + + dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, + AsyncUpdateLineMetrics, (ClientData) textPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkTextUpdateLineMetrics -- + * + * This function updates the pixel height calculations of a range of + * lines in the widget. The range is from lineNum to endLine, but, if + * doThisMuch is positive, then the function may return earlier, once a + * certain number of lines has been examined. The line counts are from 0. + * + * If doThisMuch is -1, then all lines in the range will be updated. This + * will potentially take quite some time for a large text widget. + * + * Note: with bad input for lineNum and endLine, this function can loop + * indefinitely. + * + * Results: + * The index of the last line examined (or -1 if we are about to wrap + * around from end to beginning of the widget, and the next line will be + * the first line). + * + * Side effects: + * Line heights may be recalculated. + * + *---------------------------------------------------------------------- + */ + +int +TkTextUpdateLineMetrics( + TkText *textPtr, /* Information about widget. */ + int lineNum, /* Start at this line. */ + int endLine, /* Go no further than this line. */ + int doThisMuch) /* How many lines to check, or how many 10s of + * lines to recalculate. If '-1' then do + * everything in the range (which may take a + * while). */ +{ + TkTextLine *linePtr = NULL; + int count = 0; + int totalLines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + + if (totalLines == 0) { + /* + * Empty peer widget. + */ + + return endLine; + } + + while (1) { + /* + * Get a suitable line. + */ + + if (lineNum == -1 && linePtr == NULL) { + lineNum = 0; + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, + lineNum); + } else { + if (lineNum == -1 || linePtr == NULL) { + if (lineNum == -1) { + lineNum = 0; + } + linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, lineNum); + } else { + lineNum++; + linePtr = TkBTreeNextLine(textPtr, linePtr); + } + + /* + * If we're in the middle of a partial-line height calculation, + * then we can't be done. + */ + + if (textPtr->dInfoPtr->metricEpoch == -1 && lineNum == endLine) { + /* + * We have looped over all lines, so we're done. + */ + + break; + } + } + + if (lineNum < totalLines) { + if (tkTextDebug) { + char buffer[4 * TCL_INTEGER_SPACE + 3]; + + sprintf(buffer, "%d %d %d %d", + lineNum, endLine, totalLines, count); + LOG("tk_textInvalidateLine", buffer); + } + + /* + * Now update the line's metrics if necessary. + */ + + if (TkBTreeLinePixelEpoch(textPtr, linePtr) + != textPtr->dInfoPtr->lineMetricUpdateEpoch) { + if (doThisMuch == -1) { + count += 8 * TkTextUpdateOneLine(textPtr, linePtr, 0, + NULL, 0); + } else { + TkTextIndex index; + TkTextIndex *indexPtr; + int pixelHeight; + + /* + * If the metric epoch is the same as the widget's epoch, + * then we know that indexPtrs are still valid, and if the + * cached metricIndex (if any) is for the same line as we + * wish to examine, then we are looking at a long line + * wrapped many times, which we will examine in pieces. + */ + + if (textPtr->dInfoPtr->metricEpoch == + textPtr->sharedTextPtr->stateEpoch && + textPtr->dInfoPtr->metricIndex.linePtr==linePtr) { + indexPtr = &textPtr->dInfoPtr->metricIndex; + pixelHeight = textPtr->dInfoPtr->metricPixelHeight; + } else { + /* + * We must reset the partial line height calculation + * data here, so we don't use it when it is out of + * date. + */ + + textPtr->dInfoPtr->metricEpoch = -1; + index.tree = textPtr->sharedTextPtr->tree; + index.linePtr = linePtr; + index.byteIndex = 0; + index.textPtr = NULL; + indexPtr = &index; + pixelHeight = 0; + } + + /* + * Update the line and update the counter, counting 8 for + * each display line we actually re-layout. + */ + + count += 8 * TkTextUpdateOneLine(textPtr, linePtr, + pixelHeight, indexPtr, 1); + + if (indexPtr->linePtr == linePtr) { + /* + * We didn't complete the logical line, because it + * produced very many display lines - it must be a + * long line wrapped many times. So we must cache as + * far as we got for next time around. + */ + + if (pixelHeight == 0) { + /* + * These have already been stored, unless we just + * started the new line. + */ + + textPtr->dInfoPtr->metricIndex = index; + textPtr->dInfoPtr->metricEpoch = + textPtr->sharedTextPtr->stateEpoch; + } + textPtr->dInfoPtr->metricPixelHeight = + TkBTreeLinePixelCount(textPtr, linePtr); + break; + } else { + /* + * We're done with this long line. + */ + + textPtr->dInfoPtr->metricEpoch = -1; + } + } + } else { + /* + * This line is already up to date. That means there's nothing + * to do here. + */ + } + } else { + /* + * We must never recalculate the height of the last artificial + * line. It must stay at zero, and if we recalculate it, it will + * change. + */ + + if (endLine >= totalLines) { + lineNum = endLine; + break; + } + + /* + * Set things up for the next loop through. + */ + + lineNum = -1; + } + count++; + + if (doThisMuch != -1 && count >= doThisMuch) { + break; + } + } + if (doThisMuch == -1) { + /* + * If we were requested to provide a full update, then also update the + * scrollbar. + */ + + GetYView(textPtr->interp, textPtr, 1); + } + return lineNum; +} + +/* + *---------------------------------------------------------------------- + * + * TkTextInvalidateLineMetrics, TextInvalidateLineMetrics -- + * + * Mark a number of text lines as having invalid line metric + * calculations. Never call this with linePtr as the last (artificial) + * line in the text. Depending on 'action' which indicates whether the + * given lines are simply invalid or have been inserted or deleted, the + * pre-existing asynchronous line update range may need to be adjusted. + * + * If linePtr is NULL then 'lineCount' and 'action' are ignored and all + * lines are invalidated. + * + * Results: + * None. + * + * Side effects: + * May schedule an asychronous callback. + * + *---------------------------------------------------------------------- + */ + +void +TkTextInvalidateLineMetrics( + TkSharedText *sharedTextPtr,/* Shared widget section for all peers, or + * NULL. */ + TkText *textPtr, /* Widget record for text widget. */ + TkTextLine *linePtr, /* Invalidation starts from this line. */ + int lineCount, /* And includes this many following lines. */ + int action) /* Indicates what type of invalidation + * occurred (insert, delete, or simple). */ +{ + if (sharedTextPtr == NULL) { + TextInvalidateLineMetrics(textPtr, linePtr, lineCount, action); + } else { + textPtr = sharedTextPtr->peers; + while (textPtr != NULL) { + TextInvalidateLineMetrics(textPtr, linePtr, lineCount, action); + textPtr = textPtr->next; + } + } +} + +static void +TextInvalidateLineMetrics( + TkText *textPtr, /* Widget record for text widget. */ + TkTextLine *linePtr, /* Invalidation starts from this line. */ + int lineCount, /* And includes this many following lines. */ + int action) /* Indicates what type of invalidation + * occurred (insert, delete, or simple). */ +{ + int fromLine; + TextDInfo *dInfoPtr = textPtr->dInfoPtr; + + if (linePtr != NULL) { + int counter = lineCount; + + fromLine = TkBTreeLinesTo(textPtr, linePtr); + + /* + * Invalidate the height calculations of each line in the given range. + */ + + TkBTreeLinePixelEpoch(textPtr, linePtr) = 0; + while (counter > 0 && linePtr != NULL) { + linePtr = TkBTreeNextLine(textPtr, linePtr); + if (linePtr != NULL) { + TkBTreeLinePixelEpoch(textPtr, linePtr) = 0; + } + counter--; + } + + /* + * Now schedule an examination of each line in the union of the old + * and new update ranges, including the (possibly empty) range in + * between. If that between range is not-empty, then we are examining + * more lines than is strictly necessary (but the examination of the + * extra lines should be quick, since their pixelCalculationEpoch will + * be up to date). However, to keep track of that would require more + * complex record-keeping than what we have. + */ + + if (dInfoPtr->lineUpdateTimer == NULL) { + dInfoPtr->currentMetricUpdateLine = fromLine; + if (action == TK_TEXT_INVALIDATE_DELETE) { + lineCount = 0; + } + dInfoPtr->lastMetricUpdateLine = fromLine + lineCount + 1; + } else { + int toLine = fromLine + lineCount + 1; + + if (action == TK_TEXT_INVALIDATE_DELETE) { + if (toLine <= dInfoPtr->currentMetricUpdateLine) { + dInfoPtr->currentMetricUpdateLine = fromLine; + if (dInfoPtr->lastMetricUpdateLine != -1) { + dInfoPtr->lastMetricUpdateLine -= lineCount; + } + } else if (fromLine <= dInfoPtr->currentMetricUpdateLine) { + dInfoPtr->currentMetricUpdateLine = fromLine; + if (toLine <= dInfoPtr->lastMetricUpdateLine) { + dInfoPtr->lastMetricUpdateLine -= lineCount; + } + } else { + if (dInfoPtr->lastMetricUpdateLine != -1) { + dInfoPtr->lastMetricUpdateLine = toLine; + } + } + } else if (action == TK_TEXT_INVALIDATE_INSERT) { + if (toLine <= dInfoPtr->currentMetricUpdateLine) { + dInfoPtr->currentMetricUpdateLine = fromLine; + if (dInfoPtr->lastMetricUpdateLine != -1) { + dInfoPtr->lastMetricUpdateLine += lineCount; + } + } else if (fromLine <= dInfoPtr->currentMetricUpdateLine) { + dInfoPtr->currentMetricUpdateLine = fromLine; + if (toLine <= dInfoPtr->lastMetricUpdateLine) { + dInfoPtr->lastMetricUpdateLine += lineCount; + } + if (toLine > dInfoPtr->lastMetricUpdateLine) { + dInfoPtr->lastMetricUpdateLine = toLine; + } + } else { + if (dInfoPtr->lastMetricUpdateLine != -1) { + dInfoPtr->lastMetricUpdateLine = toLine; + } + } + } else { + if (fromLine < dInfoPtr->currentMetricUpdateLine) { + dInfoPtr->currentMetricUpdateLine = fromLine; + } + if (dInfoPtr->lastMetricUpdateLine != -1 + && toLine > dInfoPtr->lastMetricUpdateLine) { + dInfoPtr->lastMetricUpdateLine = toLine; + } + } + } + } else { + /* + * This invalidates the height of all lines in the widget. + */ + + if ((++dInfoPtr->lineMetricUpdateEpoch) == 0) { + dInfoPtr->lineMetricUpdateEpoch++; + } + + /* + * This has the effect of forcing an entire new loop of update checks + * on all lines in the widget. + */ + + if (dInfoPtr->lineUpdateTimer == NULL) { + dInfoPtr->currentMetricUpdateLine = -1; + } + dInfoPtr->lastMetricUpdateLine = dInfoPtr->currentMetricUpdateLine; + } + + /* + * Now re-set the current update calculations. + */ + + if (dInfoPtr->lineUpdateTimer == NULL) { + textPtr->refCount++; + dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, + AsyncUpdateLineMetrics, (ClientData) textPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkTextFindDisplayLineEnd -- + * + * This function is invoked to find the index of the beginning or end of + * the particular display line on which the given index sits, whether + * that line is displayed or not. + * + * If 'end' is zero, we look for the start, and if 'end' is one we look + * for the end. + * + * If the beginning of the current display line is elided, and we are + * looking for the start of the line, then the returned index will be the + * first elided index on the display line. + * + * Similarly if the end of the current display line is elided and we are + * looking for the end, then the returned index will be the last elided + * index on the display line. + * + * Results: + * Modifies indexPtr to point to the given end. + * + * If xOffset is non-NULL, it is set to the x-pixel offset of the given + * original index within the given display line. + * + * Side effects: + * The combination of 'LayoutDLine' and 'FreeDLines' seems like a rather + * time-consuming way of gathering the information we need, so this would + * be a good place to look to speed up the calculations. In particular + * these calls will map and unmap embedded windows respectively, which I + * would hope isn't exactly necessary! + * + *---------------------------------------------------------------------- + */ + +void +TkTextFindDisplayLineEnd( + TkText *textPtr, /* Widget record for text widget. */ + TkTextIndex *indexPtr, /* Index we will adjust to the display line + * start or end. */ + int end, /* 0 = start, 1 = end. */ + int *xOffset) /* NULL, or used to store the x-pixel offset + * of the original index within its display + * line. */ +{ + if (!end && indexPtr->byteIndex == 0) { + /* + * Nothing to do. + */ + + if (xOffset != NULL) { + *xOffset = 0; + } + return; + } else { + TkTextIndex index = *indexPtr; + + index.byteIndex = 0; + index.textPtr = NULL; + + while (1) { + TkTextIndex endOfLastLine; + + if (TkTextIndexBackBytes(textPtr, &index, 1, &endOfLastLine)) { + /* + * Reached beginning of text. + */ + + break; + } + + if (!TkTextIsElided(textPtr, &endOfLastLine, NULL)) { + /* + * The eol is not elided, so 'index' points to the start of a + * display line (as well as logical line). + */ + + break; + } + + /* + * indexPtr's logical line is actually merged with the previous + * logical line whose eol is elided. Continue searching back to + * get a real line start. + */ + + index = endOfLastLine; + index.byteIndex = 0; + } + + while (1) { + DLine *dlPtr; + int byteCount; + TkTextIndex nextLineStart; + + dlPtr = LayoutDLine(textPtr, &index); + byteCount = dlPtr->byteCount; + + TkTextIndexForwBytes(textPtr, &index, byteCount, &nextLineStart); + + /* + * 'byteCount' goes up to the beginning of the next display line, + * so equality here says we need one more line. We try to perform + * a quick comparison which is valid for the case where the + * logical line is the same, but otherwise fall back on a full + * TkTextIndexCmp. + */ + + if (((index.linePtr == indexPtr->linePtr) + && (index.byteIndex + byteCount > indexPtr->byteIndex)) + || (dlPtr->logicalLinesMerged > 0 + && TkTextIndexCmp(&nextLineStart, indexPtr) > 0)) { + /* + * It's on this display line. + */ + + if (xOffset != NULL) { + /* + * This call takes a byte index relative to the start of + * the current _display_ line, not logical line. We are + * about to overwrite indexPtr->byteIndex, so we must do + * this now. + */ + + *xOffset = DlineXOfIndex(textPtr, dlPtr, + indexPtr->byteIndex - dlPtr->index.byteIndex); + } + if (end) { + /* + * The index we want is one less than the number of bytes + * in the display line. + */ + + TkTextIndexBackBytes(textPtr, &nextLineStart, 1, indexPtr); + } else { + *indexPtr = index; + } + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + return; + } + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + index = nextLineStart; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * CalculateDisplayLineHeight -- + * + * This function is invoked to recalculate the height of the particular + * display line which starts with the given index, whether that line is + * displayed or not. + * + * This function does not, in itself, update any cached information about + * line heights. That should be done, where necessary, by its callers. + * + * The behaviour of this function is _undefined_ if indexPtr is not + * currently at the beginning of a display line. + * + * Results: + * The number of vertical pixels used by the display line. + * + * If 'byteCountPtr' is non-NULL, then returns in that pointer the number + * of byte indices on the given display line (which can be used to update + * indexPtr in a loop). + * + * If 'mergedLinePtr' is non-NULL, then returns in that pointer the + * number of extra logical lines merged into the given display line. + * + * Side effects: + * The combination of 'LayoutDLine' and 'FreeDLines' seems like a rather + * time-consuming way of gathering the information we need, so this would + * be a good place to look to speed up the calculations. In particular + * these calls will map and unmap embedded windows respectively, which I + * would hope isn't exactly necessary! + * + *---------------------------------------------------------------------- + */ + +static int +CalculateDisplayLineHeight( + TkText *textPtr, /* Widget record for text widget. */ + CONST TkTextIndex *indexPtr,/* The index at the beginning of the display + * line of interest. */ + int *byteCountPtr, /* NULL or used to return the number of byte + * indices on the given display line. */ + int *mergedLinePtr) /* NULL or used to return if the given display + * line merges with a following logical line + * (because the eol is elided). */ +{ + DLine *dlPtr; + int pixelHeight; + + /* + * Special case for artificial last line. May be better to move this + * inside LayoutDLine. + */ + + if (indexPtr->byteIndex == 0 + && TkBTreeNextLine(textPtr, indexPtr->linePtr) == NULL) { + if (byteCountPtr != NULL) { + *byteCountPtr = 0; + } + if (mergedLinePtr != NULL) { + *mergedLinePtr = 0; + } + return 0; + } + + /* + * Layout, find the information we need and then free the display-line we + * laid-out. We must use 'FreeDLines' because it will actually call the + * relevant code to unmap any embedded windows which were mapped in the + * LayoutDLine call! + */ + + dlPtr = LayoutDLine(textPtr, indexPtr); + pixelHeight = dlPtr->height; + if (byteCountPtr != NULL) { + *byteCountPtr = dlPtr->byteCount; + } + if (mergedLinePtr != NULL) { + *mergedLinePtr = dlPtr->logicalLinesMerged; + } + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + + return pixelHeight; +} + +/* + *---------------------------------------------------------------------- + * + * TkTextIndexYPixels -- + * + * This function is invoked to calculate the number of vertical pixels + * between the first index of the text widget and the given index. The + * range from first logical line to given logical line is determined + * using the cached values, and the range inside the given logical line + * is calculated on the fly. + * + * Results: + * The pixel distance between first pixel in the widget and the + * top of the index's current display line (could be zero). + * + * Side effects: + * Just those of 'CalculateDisplayLineHeight'. + * + *---------------------------------------------------------------------- + */ + +int +TkTextIndexYPixels( + TkText *textPtr, /* Widget record for text widget. */ + CONST TkTextIndex *indexPtr)/* The index of which we want the pixel + * distance from top of logical line to top of + * index. */ +{ + int pixelHeight; + TkTextIndex index; + + pixelHeight = TkBTreePixelsTo(textPtr, indexPtr->linePtr); + + /* + * Iterate through all display-lines corresponding to the single logical + * line belonging to indexPtr, adding up the pixel height of each such + * display line as we go along, until we go past 'indexPtr'. + */ + + if (indexPtr->byteIndex == 0) { + return pixelHeight; + } + + index.tree = textPtr->sharedTextPtr->tree; + index.linePtr = indexPtr->linePtr; + index.byteIndex = 0; + index.textPtr = NULL; + + while (1) { + int bytes, height; + + /* + * Currently this call doesn't have many side-effects. However, if in + * the future we change the code so there are side-effects (such as + * adjusting linePtr->pixelHeight), then the code might not quite work + * as intended, specifically the 'linePtr->pixelHeight == pixelHeight' + * test below this while loop. + */ + + height = CalculateDisplayLineHeight(textPtr, &index, &bytes, NULL); + + index.byteIndex += bytes; + + if (index.byteIndex > indexPtr->byteIndex) { + return pixelHeight; + } + + if (height > 0) { + pixelHeight += height; + } + + if (index.byteIndex == indexPtr->byteIndex) { + return pixelHeight; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkTextUpdateOneLine -- + * + * This function is invoked to recalculate the height of a particular + * logical line, whether that line is displayed or not. + * + * It must NEVER be called for the artificial last TkTextLine which is + * used internally for administrative purposes only. That line must + * retain its initial height of 0 otherwise the pixel height calculation + * maintained by the B-tree will be wrong. + * + * Results: + * The number of display lines in the logical line. This could be zero if + * the line is totally elided. + * + * Side effects: + * Line heights may be recalculated, and a timer to update the scrollbar + * may be installed. Also see the called function + * CalculateDisplayLineHeight for its side effects. + * + *---------------------------------------------------------------------- + */ + +int +TkTextUpdateOneLine( + TkText *textPtr, /* Widget record for text widget. */ + TkTextLine *linePtr, /* The line of which to calculate the + * height. */ + int pixelHeight, /* If indexPtr is non-NULL, then this is the + * number of pixels in the logical line + * linePtr, up to the index which has been + * given. */ + TkTextIndex *indexPtr, /* Either NULL or an index at the start of a + * display line belonging to linePtr, at which + * we wish to start (e.g. up to which we have + * already calculated). On return this will be + * set to the first index on the next line. */ + int partialCalc) /* Set to 1 if we are allowed to do partial + * height calculations of long-lines. In this + * case we'll only return what we know so + * far. */ +{ + TkTextIndex index; + int displayLines; + int mergedLines; + + if (indexPtr == NULL) { + index.tree = textPtr->sharedTextPtr->tree; + index.linePtr = linePtr; + index.byteIndex = 0; + index.textPtr = NULL; + indexPtr = &index; + pixelHeight = 0; + } + + /* + * Iterate through all display-lines corresponding to the single logical + * line 'linePtr', adding up the pixel height of each such display line as + * we go along. The final total is, therefore, the height of the logical + * line. + */ + + displayLines = 0; + mergedLines = 0; + + while (1) { + int bytes, height, logicalLines; + + /* + * Currently this call doesn't have many side-effects. However, if in + * the future we change the code so there are side-effects (such as + * adjusting linePtr->pixelHeight), then the code might not quite work + * as intended, specifically the 'linePtr->pixelHeight == pixelHeight' + * test below this while loop. + */ + + height = CalculateDisplayLineHeight(textPtr, indexPtr, &bytes, + &logicalLines); + + if (height > 0) { + pixelHeight += height; + displayLines++; + } + + mergedLines += logicalLines; + + if (TkTextIndexForwBytes(textPtr, indexPtr, bytes, indexPtr)) { + break; + } + + if (logicalLines == 0) { + if (indexPtr->linePtr != linePtr) { + /* + * If we reached the end of the logical line, then either way + * we don't have a partial calculation. + */ + + partialCalc = 0; + break; + } + } else if (indexPtr->byteIndex != 0) { + /* + * We must still be on the same wrapped line. + */ + } else { + /* + * Must check if indexPtr is really a new logical line which is + * not merged with the previous line. The only code that would + * really know this is LayoutDLine, which doesn't pass the + * information on, so we have to check manually here. + */ + + TkTextIndex idx; + + TkTextIndexBackChars(textPtr, indexPtr, 1, &idx, COUNT_INDICES); + if (!TkTextIsElided(textPtr, &idx, NULL)) { + /* + * We've ended a logical line. + */ + + partialCalc = 0; + break; + } + + /* + * We must still be on the same wrapped line. + */ + } + if (partialCalc && displayLines > 50 && mergedLines == 0) { + /* + * Only calculate 50 display lines at a time, to avoid huge + * delays. In any case it is very rare that a single line wraps 50 + * times! + * + * If we have any merged lines, we must complete the full logical + * line layout here and now, because the partial-calculation code + * isn't designed to handle merged logical lines. Hence the + * 'mergedLines == 0' check. + */ + + break; + } + } + + if (!partialCalc) { + int changed = 0; + + /* + * Cancel any partial line height calculation state. + */ + + textPtr->dInfoPtr->metricEpoch = -1; + + /* + * Mark the logical line as being up to date (caution: it isn't yet up + * to date, that will happen in TkBTreeAdjustPixelHeight just below). + */ + + TkBTreeLinePixelEpoch(textPtr, linePtr) + = textPtr->dInfoPtr->lineMetricUpdateEpoch; + if (TkBTreeLinePixelCount(textPtr, linePtr) != pixelHeight) { + changed = 1; + } + + if (mergedLines > 0) { + int i = mergedLines; + TkTextLine *mergedLinePtr; + + /* + * Loop over all merged logical lines, marking them up to date + * (again, the pixel count setting will actually happen in + * TkBTreeAdjustPixelHeight). + */ + + mergedLinePtr = linePtr; + while (i-- > 0) { + mergedLinePtr = TkBTreeNextLine(textPtr, mergedLinePtr); + TkBTreeLinePixelEpoch(textPtr, mergedLinePtr) + = textPtr->dInfoPtr->lineMetricUpdateEpoch; + if (TkBTreeLinePixelCount(textPtr, mergedLinePtr) != 0) { + changed = 1; + } + } + } + + if (!changed) { + /* + * If there's nothing to change, then we can already return. + */ + + return displayLines; + } + } + + /* + * We set the line's height, but the return value is now the height of the + * entire widget, which may be used just below for reporting/debugging + * purposes. + */ + + pixelHeight = TkBTreeAdjustPixelHeight(textPtr, linePtr, pixelHeight, + mergedLines); + + if (tkTextDebug) { + char buffer[2 * TCL_INTEGER_SPACE + 1]; + + if (TkBTreeNextLine(textPtr, linePtr) == NULL) { + Tcl_Panic("Mustn't ever update line height of last artificial line"); + } + + sprintf(buffer, "%d %d", TkBTreeLinesTo(textPtr,linePtr), pixelHeight); + LOG("tk_textNumPixels", buffer); + } + if (textPtr->dInfoPtr->scrollbarTimer == NULL) { + textPtr->refCount++; + textPtr->dInfoPtr->scrollbarTimer = Tcl_CreateTimerHandler(200, + AsyncUpdateYScrollbar, (ClientData) textPtr); + } + return displayLines; +} + +/* + *---------------------------------------------------------------------- + * * DisplayText -- * - * This procedure is invoked as a when-idle handler to update the - * display. It only redisplays the parts of the text widget that - * are out of date. + * This function is invoked as a when-idle handler to update the display. + * It only redisplays the parts of the text widget that are out of date. * * Results: * None. @@ -2204,24 +3882,22 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap) */ static void -DisplayText(clientData) - ClientData clientData; /* Information about widget. */ +DisplayText( + ClientData clientData) /* Information about widget. */ { register TkText *textPtr = (TkText *) clientData; TextDInfo *dInfoPtr = textPtr->dInfoPtr; - Tk_Window tkwin; register DLine *dlPtr; DLine *prevPtr; Pixmap pixmap; int maxHeight, borders; - int bottomY = 0; /* Initialization needed only to stop - * compiler warnings. */ + int bottomY = 0; /* Initialization needed only to stop compiler + * warnings. */ Tcl_Interp *interp; - if (textPtr->tkwin == NULL) { - + 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. */ return; @@ -2231,17 +3907,15 @@ DisplayText(clientData) Tcl_Preserve((ClientData) interp); if (tkTextDebug) { - Tcl_SetVar2(interp, "tk_textRelayout", (char *) NULL, "", - TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "tk_textRelayout", NULL, "", TCL_GLOBAL_ONLY); } - if (textPtr->tkwin == NULL) { - + 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. */ - goto end; + goto end; } if (!Tk_IsMapped(textPtr->tkwin) || (dInfoPtr->maxX <= dInfoPtr->x) @@ -2252,34 +3926,34 @@ DisplayText(clientData) } numRedisplays++; if (tkTextDebug) { - Tcl_SetVar2(interp, "tk_textRedraw", (char *) NULL, "", - TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "tk_textRedraw", NULL, "", TCL_GLOBAL_ONLY); } - if (textPtr->tkwin == NULL) { - + 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. */ goto end; } /* - * Choose a new current item if that is needed (this could cause - * event handlers to be invoked, hence the preserve/release calls - * and the loop, since the handlers could conceivably necessitate - * yet another current item calculation). The tkwin check is because - * the whole window could go away in the Tcl_Release call. + * Choose a new current item if that is needed (this could cause event + * handlers to be invoked, hence the preserve/release calls and the loop, + * since the handlers could conceivably necessitate yet another current + * item calculation). The tkwin check is because the whole window could go + * away in the Tcl_Release call. */ while (dInfoPtr->flags & REPICK_NEEDED) { - Tcl_Preserve((ClientData) textPtr); + textPtr->refCount++; dInfoPtr->flags &= ~REPICK_NEEDED; TkTextPickCurrent(textPtr, &textPtr->pickEvent); - tkwin = textPtr->tkwin; - Tcl_Release((ClientData) textPtr); - if (tkwin == NULL) { + if (--textPtr->refCount == 0) { + ckfree((char *) textPtr); + goto end; + } + if ((textPtr->tkwin == NULL) || (textPtr->flags & DESTROYED)) { goto end; } } @@ -2292,8 +3966,11 @@ DisplayText(clientData) dInfoPtr->dLinesInvalidated = 0; /* - * See if it's possible to bring some parts of the screen up-to-date - * by scrolling (copying from other parts of the screen). + * See if it's possible to bring some parts of the screen up-to-date by + * scrolling (copying from other parts of the screen). We have to be + * particularly careful with the top and bottom lines of the display, + * since these may only be partially visible and therefore not helpful for + * some scrolling purposes. */ for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { @@ -2301,15 +3978,37 @@ DisplayText(clientData) int offset, height, y, oldY; TkRegion damageRgn; - if ((dlPtr->oldY == -1) || (dlPtr->y == dlPtr->oldY) - || ((dlPtr->oldY + dlPtr->height) > dInfoPtr->maxY)) { + /* + * These tests are, in order: + * + * 1. If the line is already marked as invalid + * 2. If the line hasn't moved + * 3. If the line overlaps the bottom of the window and we are + * scrolling up. + * 4. If the line overlaps the top of the window and we are scrolling + * down. + * + * If any of these tests are true, then we can't scroll this line's + * part of the display. + * + * Note that even if tests 3 or 4 aren't true, we may be able to + * scroll the line, but we still need to be sure to call embedded + * window display procs on top and bottom lines if they have any + * portion non-visible (see below). + */ + + if ((dlPtr->flags & OLD_Y_INVALID) + || (dlPtr->y == dlPtr->oldY) + || (((dlPtr->oldY + dlPtr->height) > dInfoPtr->maxY) + && (dlPtr->y < dlPtr->oldY)) + || ((dlPtr->oldY < dInfoPtr->y) && (dlPtr->y > dlPtr->oldY))) { continue; } /* - * This line is already drawn somewhere in the window so it only - * needs to be copied to its new location. See if there's a group - * of lines that can all be copied together. + * This line is already drawn somewhere in the window so it only needs + * to be copied to its new location. See if there's a group of lines + * that can all be copied together. */ offset = dlPtr->y - dlPtr->oldY; @@ -2317,7 +4016,7 @@ DisplayText(clientData) y = dlPtr->y; for (dlPtr2 = dlPtr->nextPtr; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) { - if ((dlPtr2->oldY == -1) + if ((dlPtr2->flags & OLD_Y_INVALID) || ((dlPtr2->oldY + offset) != dlPtr2->y) || ((dlPtr2->oldY + dlPtr2->height) > dInfoPtr->maxY)) { break; @@ -2326,21 +4025,36 @@ DisplayText(clientData) } /* - * Reduce the height of the area being copied if necessary to - * avoid overwriting the border area. + * Reduce the height of the area being copied if necessary to avoid + * overwriting the border area. */ if ((y + height) > dInfoPtr->maxY) { height = dInfoPtr->maxY -y; } oldY = dlPtr->oldY; + if (y < dInfoPtr->y) { + /* + * Adjust if the area being copied is going to overwrite the top + * border of the window (so the top line is only half onscreen). + */ + + int y_off = dInfoPtr->y - dlPtr->y; + height -= y_off; + oldY += y_off; + y = dInfoPtr->y; + } /* - * Update the lines we are going to scroll to show that they - * have been copied. + * Update the lines we are going to scroll to show that they have been + * copied. */ while (1) { + /* + * The DLine already has OLD_Y_INVALID cleared. + */ + dlPtr->oldY = dlPtr->y; if (dlPtr->nextPtr == dlPtr2) { break; @@ -2349,30 +4063,28 @@ DisplayText(clientData) } /* - * Scan through the lines following the copied ones to see if - * we are going to overwrite them with the copy operation. - * If so, mark them for redisplay. + * Scan through the lines following the copied ones to see if we are + * going to overwrite them with the copy operation. If so, mark them + * for redisplay. */ for ( ; dlPtr2 != NULL; dlPtr2 = dlPtr2->nextPtr) { - if ((dlPtr2->oldY != -1) + if ((!(dlPtr2->flags & OLD_Y_INVALID)) && ((dlPtr2->oldY + dlPtr2->height) > y) && (dlPtr2->oldY < (y + height))) { - dlPtr2->oldY = -1; + dlPtr2->flags |= OLD_Y_INVALID; } } /* - * Now scroll the lines. This may generate damage which we - * handle by calling TextInvalidateRegion to mark the display - * blocks as stale. + * Now scroll the lines. This may generate damage which we handle by + * calling TextInvalidateRegion to mark the display blocks as stale. */ damageRgn = TkCreateRegion(); - if (TkScrollWindow(textPtr->tkwin, dInfoPtr->scrollGC, - dInfoPtr->x, oldY, - (dInfoPtr->maxX - dInfoPtr->x), height, - 0, y - oldY, damageRgn)) { + if (TkScrollWindow(textPtr->tkwin, dInfoPtr->scrollGC, dInfoPtr->x, + oldY, dInfoPtr->maxX-dInfoPtr->x, height, 0, y-oldY, + damageRgn)) { TextInvalidateRegion(textPtr, damageRgn); } numCopies++; @@ -2380,14 +4092,13 @@ DisplayText(clientData) } /* - * Clear the REDRAW_PENDING flag here. This is actually pretty - * tricky. We want to wait until *after* doing the scrolling, - * since that could generate more areas to redraw and don't - * want to reschedule a redisplay for them. On the other hand, - * we can't wait until after all the redisplaying, because the - * act of redisplaying could actually generate more redisplays - * (e.g. in the case of a nested window with event bindings triggered - * by redisplay). + * Clear the REDRAW_PENDING flag here. This is actually pretty tricky. We + * want to wait until *after* doing the scrolling, since that could + * generate more areas to redraw and don't want to reschedule a redisplay + * for them. On the other hand, we can't wait until after all the + * redisplaying, because the act of redisplaying could actually generate + * more redisplays (e.g. in the case of a nested window with event + * bindings triggered by redisplay). */ dInfoPtr->flags &= ~REDRAW_PENDING; @@ -2398,18 +4109,16 @@ DisplayText(clientData) if (dInfoPtr->flags & REDRAW_BORDERS) { if (tkTextDebug) { - Tcl_SetVar2(interp, "tk_textRedraw", (char *) NULL, "borders", - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + LOG("tk_textRedraw", "borders"); } - if (textPtr->tkwin == NULL) { - + if (textPtr->tkwin == NULL) { /* - * The widget has been deleted. Don't do anything. - */ + * The widget has been deleted. Don't do anything. + */ - goto end; - } + goto end; + } Tk_Draw3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, textPtr->highlightWidth, @@ -2419,17 +4128,17 @@ DisplayText(clientData) textPtr->borderWidth, textPtr->relief); if (textPtr->highlightWidth != 0) { GC fgGC, bgGC; - + bgGC = Tk_GCForColor(textPtr->highlightBgColorPtr, - Tk_WindowId(textPtr->tkwin)); + Tk_WindowId(textPtr->tkwin)); if (textPtr->flags & GOT_FOCUS) { fgGC = Tk_GCForColor(textPtr->highlightColorPtr, Tk_WindowId(textPtr->tkwin)); - TkpDrawHighlightBorder(textPtr->tkwin, fgGC, bgGC, - textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin)); + TkpDrawHighlightBorder(textPtr->tkwin, fgGC, bgGC, + textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin)); } else { - TkpDrawHighlightBorder(textPtr->tkwin, bgGC, bgGC, - textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin)); + TkpDrawHighlightBorder(textPtr->tkwin, bgGC, bgGC, + textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin)); } } borders = textPtr->borderWidth + textPtr->highlightWidth; @@ -2461,23 +4170,33 @@ DisplayText(clientData) } /* - * Now we have to redraw the lines that couldn't be updated by - * scrolling. First, compute the height of the largest line and - * allocate an off-screen pixmap to use for double-buffered - * displays. + * Now we have to redraw the lines that couldn't be updated by scrolling. + * First, compute the height of the largest line and allocate an off- + * screen pixmap to use for double-buffered displays. */ maxHeight = -1; for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { - if ((dlPtr->height > maxHeight) && (dlPtr->oldY != dlPtr->y)) { + if ((dlPtr->height > maxHeight) && + ((dlPtr->flags&OLD_Y_INVALID) || (dlPtr->oldY != dlPtr->y))) { maxHeight = dlPtr->height; } bottomY = dlPtr->y + dlPtr->height; } - if (maxHeight > dInfoPtr->maxY) { - maxHeight = dInfoPtr->maxY; + + /* + * There used to be a line here which restricted 'maxHeight' to be no + * larger than 'dInfoPtr->maxY', but this is incorrect for the case where + * individual lines may be taller than the widget _and_ we have smooth + * scrolling. What we can do is restrict maxHeight to be no larger than + * 'dInfoPtr->maxY + dInfoPtr->topPixelOffset'. + */ + + if (maxHeight > (dInfoPtr->maxY + dInfoPtr->topPixelOffset)) { + maxHeight = (dInfoPtr->maxY + dInfoPtr->topPixelOffset); } + if (maxHeight > 0) { #ifndef TK_NO_DOUBLE_BUFFERING pixmap = Tk_GetPixmap(Tk_Display(textPtr->tkwin), @@ -2489,14 +4208,15 @@ DisplayText(clientData) for (prevPtr = NULL, dlPtr = textPtr->dInfoPtr->dLinePtr; (dlPtr != NULL) && (dlPtr->y < dInfoPtr->maxY); prevPtr = dlPtr, dlPtr = dlPtr->nextPtr) { - if (dlPtr->chunkPtr == NULL) continue; - if (dlPtr->oldY != dlPtr->y) { + if (dlPtr->chunkPtr == NULL) { + continue; + } + if ((dlPtr->flags & OLD_Y_INVALID) || dlPtr->oldY != dlPtr->y) { if (tkTextDebug) { char string[TK_POS_CHARS]; - TkTextPrintIndex(&dlPtr->index, string); - Tcl_SetVar2(textPtr->interp, "tk_textRedraw", - (char *) NULL, string, - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + + TkTextPrintIndex(textPtr, &dlPtr->index, string); + LOG("tk_textRedraw", string); } DisplayDLine(textPtr, dlPtr, prevPtr, pixmap); if (dInfoPtr->dLinesInvalidated) { @@ -2506,9 +4226,55 @@ DisplayText(clientData) return; } dlPtr->oldY = dlPtr->y; - dlPtr->flags &= ~NEW_LAYOUT; + dlPtr->flags &= ~(NEW_LAYOUT | OLD_Y_INVALID); + } else if (dlPtr->chunkPtr != NULL && ((dlPtr->y < 0) + || (dlPtr->y + dlPtr->height > dInfoPtr->maxY))) { + register TkTextDispChunk *chunkPtr; + + /* + * It's the first or last DLine which are also overlapping the + * top or bottom of the window, but we decided above it wasn't + * necessary to display them (we were able to update them by + * scrolling). This is fine, except that if the lines contain + * any embedded windows, we must still call the display proc + * on them because they might need to be unmapped or they + * might need to be moved to reflect their new position. + * Otherwise, everything else moves, but the embedded window + * doesn't! + * + * So, we loop through all the chunks, calling the display + * proc of embedded windows only. + */ + + for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL); + chunkPtr = chunkPtr->nextPtr) { + int x; + if (chunkPtr->displayProc != TkTextEmbWinDisplayProc) { + continue; + } + x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curXPixelOffset; + if ((x + chunkPtr->width <= 0) || (x >= dInfoPtr->maxX)) { + /* + * Note: we have to call the displayProc even for + * chunks that are off-screen. This is needed, for + * example, so that embedded windows can be unmapped + * in this case. Display the chunk at a coordinate + * that can be clearly identified by the displayProc + * as being off-screen to the left (the displayProc + * may not be able to tell if something is off to the + * right). + */ + + x = -chunkPtr->width; + } + TkTextEmbWinDisplayProc(textPtr, chunkPtr, x, + dlPtr->spaceAbove, + dlPtr->height-dlPtr->spaceAbove-dlPtr->spaceBelow, + dlPtr->baseline - dlPtr->spaceAbove, NULL, + (Drawable) None, dlPtr->y + dlPtr->spaceAbove); + } + } - /*prevPtr = dlPtr;*/ } #ifndef TK_NO_DOUBLE_BUFFERING Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap); @@ -2516,10 +4282,10 @@ DisplayText(clientData) } /* - * See if we need to refresh the part of the window below the - * last line of text (if there is any such area). Refresh the - * padding area on the left too, since the insertion cursor might - * have been displayed there previously). + * See if we need to refresh the part of the window below the last line of + * text (if there is any such area). Refresh the padding area on the left + * too, since the insertion cursor might have been displayed there + * previously). */ if (dInfoPtr->topOfEof > dInfoPtr->maxY) { @@ -2527,19 +4293,16 @@ DisplayText(clientData) } if (bottomY < dInfoPtr->topOfEof) { if (tkTextDebug) { - Tcl_SetVar2(textPtr->interp, "tk_textRedraw", - (char *) NULL, "eof", - TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT); + LOG("tk_textRedraw", "eof"); } - if (textPtr->tkwin == NULL) { - + 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. + */ - goto end; - } + goto end; + } Tk_Fill3DRectangle(textPtr->tkwin, Tk_WindowId(textPtr->tkwin), textPtr->border, dInfoPtr->x - textPtr->padX, bottomY, @@ -2548,28 +4311,26 @@ DisplayText(clientData) } dInfoPtr->topOfEof = bottomY; - doScrollbars: - /* - * Update the vertical scrollbar, if there is one. Note: it's - * important to clear REDRAW_PENDING here, just in case the - * scroll procedure does something that requires redisplay. + * Update the vertical scrollbar, if there is one. Note: it's important to + * clear REDRAW_PENDING here, just in case the scroll function does + * something that requires redisplay. */ - + + doScrollbars: if (textPtr->flags & UPDATE_SCROLLBARS) { textPtr->flags &= ~UPDATE_SCROLLBARS; if (textPtr->yScrollCmd != NULL) { GetYView(textPtr->interp, textPtr, 1); } - if (textPtr->tkwin == NULL) { - + 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. + */ - goto end; - } + goto end; + } /* * Update the horizontal scrollbar, if any. @@ -2580,7 +4341,7 @@ DisplayText(clientData) } } -end: + end: Tcl_Release((ClientData) interp); } @@ -2589,9 +4350,8 @@ end: * * TkTextEventuallyRepick -- * - * This procedure is invoked whenever something happens that - * could change the current character or the tags associated - * with it. + * This function is invoked whenever something happens that could change + * the current character or the tags associated with it. * * Results: * None. @@ -2602,10 +4362,9 @@ end: *---------------------------------------------------------------------- */ - /* ARGSUSED */ void -TkTextEventuallyRepick(textPtr) - TkText *textPtr; /* Widget record for text widget. */ +TkTextEventuallyRepick( + TkText *textPtr) /* Widget record for text widget. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; @@ -2621,9 +4380,9 @@ TkTextEventuallyRepick(textPtr) * * TkTextRedrawRegion -- * - * This procedure is invoked to schedule a redisplay for a given - * region of a text widget. The redisplay itself may not occur - * immediately: it's scheduled as a when-idle handler. + * This function is invoked to schedule a redisplay for a given region of + * a text widget. The redisplay itself may not occur immediately: it's + * scheduled as a when-idle handler. * * Results: * None. @@ -2634,14 +4393,13 @@ TkTextEventuallyRepick(textPtr) *---------------------------------------------------------------------- */ - /* ARGSUSED */ void -TkTextRedrawRegion(textPtr, x, y, width, height) - TkText *textPtr; /* Widget record for text widget. */ - int x, y; /* Coordinates of upper-left corner of area - * to be redrawn, in pixels relative to - * textPtr's window. */ - int width, height; /* Width and height of area to be redrawn. */ +TkTextRedrawRegion( + TkText *textPtr, /* Widget record for text widget. */ + int x, int y, /* Coordinates of upper-left corner of area to + * be redrawn, in pixels relative to textPtr's + * window. */ + int width, int height) /* Width and height of area to be redrawn. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; TkRegion damageRgn = TkCreateRegion(); @@ -2679,9 +4437,9 @@ TkTextRedrawRegion(textPtr, x, y, width, height) */ static void -TextInvalidateRegion(textPtr, region) - TkText *textPtr; /* Widget record for text widget. */ - TkRegion region; /* Region of area to redraw. */ +TextInvalidateRegion( + TkText *textPtr, /* Widget record for text widget. */ + TkRegion region) /* Region of area to redraw. */ { register DLine *dlPtr; TextDInfo *dInfoPtr = textPtr->dInfoPtr; @@ -2697,9 +4455,10 @@ TextInvalidateRegion(textPtr, region) maxY = rect.y + rect.height; for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { - if ((dlPtr->oldY != -1) && (TkRectInRegion(region, rect.x, dlPtr->y, + if ((!(dlPtr->flags & OLD_Y_INVALID)) + && (TkRectInRegion(region, rect.x, dlPtr->y, rect.width, (unsigned int) dlPtr->height) != RectangleOut)) { - dlPtr->oldY = -1; + dlPtr->flags |= OLD_Y_INVALID; } } if (dInfoPtr->topOfEof < maxY) { @@ -2707,8 +4466,7 @@ TextInvalidateRegion(textPtr, region) } /* - * Schedule the redisplay operation if there isn't one already - * scheduled. + * Schedule the redisplay operation if there isn't one already scheduled. */ inset = textPtr->borderWidth + textPtr->highlightWidth; @@ -2724,32 +4482,54 @@ TextInvalidateRegion(textPtr, region) /* *---------------------------------------------------------------------- * - * TkTextChanged -- + * TkTextChanged, TextChanged -- * - * This procedure is invoked when info in a text widget is about - * to be modified in a way that changes how it is displayed (e.g. - * characters were inserted or deleted, or tag information was - * changed). This procedure must be called *before* a change is - * made, so that indexes in the display information are still - * valid. + * This function is invoked when info in a text widget is about to be + * modified in a way that changes how it is displayed (e.g. characters + * were inserted or deleted, or tag information was changed). This + * function must be called *before* a change is made, so that indexes in + * the display information are still valid. + * + * Note: if the range of indices may change geometry as well as simply + * requiring redisplay, then the caller should also call + * TkTextInvalidateLineMetrics. * * Results: * None. * * Side effects: - * The range of character between index1Ptr (inclusive) and - * index2Ptr (exclusive) will be redisplayed at some point in the - * future (the actual redisplay is scheduled as a when-idle handler). + * The range of character between index1Ptr (inclusive) and index2Ptr + * (exclusive) will be redisplayed at some point in the future (the + * actual redisplay is scheduled as a when-idle handler). * *---------------------------------------------------------------------- */ void -TkTextChanged(textPtr, index1Ptr, index2Ptr) - TkText *textPtr; /* Widget record for text widget. */ - TkTextIndex *index1Ptr; /* Index of first character to redisplay. */ - TkTextIndex *index2Ptr; /* Index of character just after last one - * to redisplay. */ +TkTextChanged( + TkSharedText *sharedTextPtr,/* Shared widget section, or NULL. */ + TkText *textPtr, /* Widget record for text widget, or NULL. */ + CONST TkTextIndex*index1Ptr,/* Index of first character to redisplay. */ + CONST TkTextIndex*index2Ptr)/* Index of character just after last one to + * redisplay. */ +{ + if (sharedTextPtr == NULL) { + TextChanged(textPtr, index1Ptr, index2Ptr); + } else { + textPtr = sharedTextPtr->peers; + while (textPtr != NULL) { + TextChanged(textPtr, index1Ptr, index2Ptr); + textPtr = textPtr->next; + } + } +} + +static void +TextChanged( + TkText *textPtr, /* Widget record for text widget, or NULL. */ + CONST TkTextIndex*index1Ptr,/* Index of first character to redisplay. */ + CONST TkTextIndex*index2Ptr)/* Index of character just after last one to + * redisplay. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *firstPtr, *lastPtr; @@ -2757,18 +4537,18 @@ TkTextChanged(textPtr, index1Ptr, index2Ptr) /* * Schedule both a redisplay and a recomputation of display information. - * It's done here rather than the end of the procedure for two reasons: + * It's done here rather than the end of the function for two reasons: * * 1. If there are no display lines to update we'll want to return - * immediately, well before the end of the procedure. + * immediately, well before the end of the function. * 2. It's important to arrange for the redisplay BEFORE calling - * FreeDLines. The reason for this is subtle and has to do with - * embedded windows. The chunk delete procedure for an embedded - * window will schedule an idle handler to unmap the window. - * However, we want the idle handler for redisplay to be called - * first, so that it can put the embedded window back on the screen - * again (if appropriate). This will prevent the window from ever - * being unmapped, and thereby avoid flashing. + * FreeDLines. The reason for this is subtle and has to do with + * embedded windows. The chunk delete function for an embedded window + * will schedule an idle handler to unmap the window. However, we want + * the idle handler for redisplay to be called first, so that it can + * put the embedded window back on the screen again (if appropriate). + * This will prevent the window from ever being unmapped, and thereby + * avoid flashing. */ if (!(dInfoPtr->flags & REDRAW_PENDING)) { @@ -2777,13 +4557,13 @@ TkTextChanged(textPtr, index1Ptr, index2Ptr) dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED; /* - * Find the DLines corresponding to index1Ptr and index2Ptr. There - * is one tricky thing here, which is that we have to relayout in - * units of whole text lines: round index1Ptr back to the beginning - * of its text line, and include all the display lines after index2, - * up to the end of its text line. This is necessary because the - * indices stored in the display lines will no longer be valid. It's - * also needed because any edit could change the way lines wrap. + * Find the DLines corresponding to index1Ptr and index2Ptr. There is one + * tricky thing here, which is that we have to relayout in units of whole + * text lines: round index1Ptr back to the beginning of its text line, and + * include all the display lines after index2, up to the end of its text + * line. This is necessary because the indices stored in the display lines + * will no longer be valid. It's also needed because any edit could change + * the way lines wrap. */ rounded = *index1Ptr; @@ -2802,39 +4582,64 @@ TkTextChanged(textPtr, index1Ptr, index2Ptr) * Delete all the DLines from firstPtr up to but not including lastPtr. */ - FreeDLines(textPtr, firstPtr, lastPtr, 1); + FreeDLines(textPtr, firstPtr, lastPtr, DLINE_UNLINK); } /* *---------------------------------------------------------------------- * - * TkTextRedrawTag -- + * TkTextRedrawTag, TextRedrawTag -- * - * This procedure is invoked to request a redraw of all characters - * in a given range that have a particular tag on or off. It's - * called, for example, when tag options change. + * This function is invoked to request a redraw of all characters in a + * given range that have a particular tag on or off. It's called, for + * example, when tag options change. * * Results: * None. * * Side effects: - * Information on the screen may be redrawn, and the layout of - * the screen may change. + * Information on the screen may be redrawn, and the layout of the screen + * may change. * *---------------------------------------------------------------------- */ void -TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) - TkText *textPtr; /* Widget record for text widget. */ - TkTextIndex *index1Ptr; /* First character in range to consider - * for redisplay. NULL means start at - * beginning of text. */ - TkTextIndex *index2Ptr; /* Character just after last one to consider - * for redisplay. NULL means process all - * the characters in the text. */ - TkTextTag *tagPtr; /* Information about tag. */ - int withTag; /* 1 means redraw characters that have the +TkTextRedrawTag( + TkSharedText *sharedTextPtr,/* Shared widget section, or NULL. */ + TkText *textPtr, /* Widget record for text widget. */ + TkTextIndex *index1Ptr, /* First character in range to consider for + * redisplay. NULL means start at beginning of + * text. */ + TkTextIndex *index2Ptr, /* Character just after last one to consider + * for redisplay. NULL means process all the + * characters in the text. */ + TkTextTag *tagPtr, /* Information about tag. */ + int withTag) /* 1 means redraw characters that have the + * tag, 0 means redraw those without. */ +{ + if (sharedTextPtr == NULL) { + TextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag); + } else { + textPtr = sharedTextPtr->peers; + while (textPtr != NULL) { + TextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag); + textPtr = textPtr->next; + } + } +} + +static void +TextRedrawTag( + TkText *textPtr, /* Widget record for text widget. */ + TkTextIndex *index1Ptr, /* First character in range to consider for + * redisplay. NULL means start at beginning of + * text. */ + TkTextIndex *index2Ptr, /* Character just after last one to consider + * for redisplay. NULL means process all the + * characters in the text. */ + TkTextTag *tagPtr, /* Information about tag. */ + int withTag) /* 1 means redraw characters that have the * tag, 0 means redraw those without. */ { register DLine *dlPtr; @@ -2846,15 +4651,45 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) TkTextIndex endOfText, *endIndexPtr; /* - * Round up the starting position if it's before the first line - * visible on the screen (we only care about what's on the screen). + * Invalidate the pixel calculation of all lines in the given range. This + * may be a bit over-aggressive, so we could consider more subtle + * techniques here in the future. In particular, when we create a tag for + * the first time with '.t tag configure foo -font "Arial 20"', say, even + * though that obviously can't apply to anything at all (the tag didn't + * exist a moment ago), we invalidate every single line in the widget. + */ + + if (tagPtr->affectsDisplayGeometry) { + TkTextLine *startLine, *endLine; + int lineCount; + + if (index2Ptr == NULL) { + endLine = NULL; + lineCount = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + } else { + endLine = index2Ptr->linePtr; + lineCount = TkBTreeLinesTo(textPtr, endLine); + } + if (index1Ptr == NULL) { + startLine = NULL; + } else { + startLine = index1Ptr->linePtr; + lineCount -= TkBTreeLinesTo(textPtr, startLine); + } + TkTextInvalidateLineMetrics(NULL, textPtr, startLine, lineCount, + TK_TEXT_INVALIDATE_ONLY); + } + + /* + * Round up the starting position if it's before the first line visible on + * the screen (we only care about what's on the screen). */ dlPtr = dInfoPtr->dLinePtr; if (dlPtr == NULL) { return; } - if ((index1Ptr == NULL) || (TkTextIndexCmp(&dlPtr->index, index1Ptr) > 0)) { + if ((index1Ptr == NULL) || (TkTextIndexCmp(&dlPtr->index, index1Ptr)>0)) { index1Ptr = &dlPtr->index; } @@ -2863,22 +4698,26 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) */ if (index2Ptr == NULL) { - index2Ptr = TkTextMakeByteIndex(textPtr->tree, - TkBTreeNumLines(textPtr->tree), 0, &endOfText); + int lastLine = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + + index2Ptr = TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lastLine, 0, &endOfText); } - /* - * Initialize a search through all transitions on the tag, starting - * with the first transition where the tag's current state is different - * from what it will eventually be. + /* + * Initialize a search through all transitions on the tag, starting with + * the first transition where the tag's current state is different from + * what it will eventually be. */ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, &search); + /* - * Make our own curIndex because at this point search.curIndex - * may not equal index1Ptr->curIndex in the case the first tag toggle - * comes after index1Ptr (See the use of FindTagStart in TkBTreeStartSearch) + * Make our own curIndex because at this point search.curIndex may not + * equal index1Ptr->curIndex in the case the first tag toggle comes after + * index1Ptr (See the use of FindTagStart in TkBTreeStartSearch). */ + curIndexPtr = index1Ptr; tagOn = TkBTreeCharTagged(index1Ptr, tagPtr); if (tagOn != withTag) { @@ -2889,9 +4728,9 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) } /* - * Schedule a redisplay and layout recalculation if they aren't - * already pending. This has to be done before calling FreeDLines, - * for the reason given in TkTextChanged. + * Schedule a redisplay and layout recalculation if they aren't already + * pending. This has to be done before calling FreeDLines, for the reason + * given in TkTextChanged. */ if (!(dInfoPtr->flags & REDRAW_PENDING)) { @@ -2900,21 +4739,20 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED; /* - * Each loop through the loop below is for one range of characters - * where the tag's current state is different than its eventual - * state. At the top of the loop, search contains information about - * the first character in the range. + * Each loop through the loop below is for one range of characters where + * the tag's current state is different than its eventual state. At the + * top of the loop, search contains information about the first character + * in the range. */ while (1) { /* - * Find the first DLine structure in the range. Note: if the - * desired character isn't the first in its text line, then look - * for the character just before it instead. This is needed to - * handle the case where the first character of a wrapped - * display line just got smaller, so that it now fits on the - * line before: need to relayout the line containing the - * previous character. + * Find the first DLine structure in the range. Note: if the desired + * character isn't the first in its text line, then look for the + * character just before it instead. This is needed to handle the case + * where the first character of a wrapped display line just got + * smaller, so that it now fits on the line before: need to relayout + * the line containing the previous character. */ if (curIndexPtr->byteIndex == 0) { @@ -2947,11 +4785,11 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) } /* - * Delete all of the display lines in the range, so that they'll - * be re-layed out and redrawn. + * Delete all of the display lines in the range, so that they'll be + * re-layed out and redrawn. */ - FreeDLines(textPtr, dlPtr, endPtr, 1); + FreeDLines(textPtr, dlPtr, endPtr, DLINE_UNLINK); dlPtr = endPtr; /* @@ -2969,33 +4807,35 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag) * * TkTextRelayoutWindow -- * - * This procedure is called when something has happened that - * invalidates the whole layout of characters on the screen, such - * as a change in a configuration option for the overall text - * widget or a change in the window size. It causes all display - * information to be recomputed and the window to be redrawn. + * This function is called when something has happened that invalidates + * the whole layout of characters on the screen, such as a change in a + * configuration option for the overall text widget or a change in the + * window size. It causes all display information to be recomputed and + * the window to be redrawn. * * Results: * None. * * Side effects: - * All the display information will be recomputed for the window - * and the window will be redrawn. + * All the display information will be recomputed for the window and the + * window will be redrawn. * *---------------------------------------------------------------------- */ void -TkTextRelayoutWindow(textPtr) - TkText *textPtr; /* Widget record for text widget. */ +TkTextRelayoutWindow( + TkText *textPtr, /* Widget record for text widget. */ + int mask) /* OR'd collection of bits showing what has + * changed. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - GC new; + GC newGC; XGCValues gcValues; /* - * Schedule the window redisplay. See TkTextChanged for the - * reason why this has to be done before any calls to FreeDLines. + * Schedule the window redisplay. See TkTextChanged for the reason why + * this has to be done before any calls to FreeDLines. */ if (!(dInfoPtr->flags & REDRAW_PENDING)) { @@ -3005,28 +4845,27 @@ TkTextRelayoutWindow(textPtr) |REPICK_NEEDED; /* - * (Re-)create the graphics context for drawing the traversal - * highlight. + * (Re-)create the graphics context for drawing the traversal highlight. */ gcValues.graphics_exposures = False; - new = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues); + newGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures, &gcValues); if (dInfoPtr->copyGC != None) { Tk_FreeGC(textPtr->display, dInfoPtr->copyGC); } - dInfoPtr->copyGC = new; + dInfoPtr->copyGC = newGC; /* * Throw away all the current layout information. */ - FreeDLines(textPtr, dInfoPtr->dLinePtr, (DLine *) NULL, 1); + FreeDLines(textPtr, dInfoPtr->dLinePtr, NULL, DLINE_UNLINK); dInfoPtr->dLinePtr = NULL; /* - * Recompute some overall things for the layout. Even if the - * window gets very small, pretend that there's at least one - * pixel of drawing space in it. + * Recompute some overall things for the layout. Even if the window gets + * very small, pretend that there's at least one pixel of drawing space in + * it. */ if (textPtr->highlightWidth < 0) { @@ -3041,6 +4880,11 @@ TkTextRelayoutWindow(textPtr) if (dInfoPtr->maxX <= dInfoPtr->x) { dInfoPtr->maxX = dInfoPtr->x + 1; } + + /* + * This is the only place where dInfoPtr->maxY is set. + */ + dInfoPtr->maxY = Tk_Height(textPtr->tkwin) - textPtr->highlightWidth - textPtr->borderWidth - textPtr->padY; if (dInfoPtr->maxY <= dInfoPtr->y) { @@ -3049,22 +4893,50 @@ TkTextRelayoutWindow(textPtr) dInfoPtr->topOfEof = dInfoPtr->maxY; /* - * If the upper-left character isn't the first in a line, recompute - * it. This is necessary because a change in the window's size - * or options could change the way lines wrap. + * If the upper-left character isn't the first in a line, recompute it. + * This is necessary because a change in the window's size or options + * could change the way lines wrap. */ if (textPtr->topIndex.byteIndex != 0) { - MeasureUp(textPtr, &textPtr->topIndex, 0, &textPtr->topIndex); + TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL); } /* - * Invalidate cached scrollbar positions, so that scrollbars - * sliders will be udpated. + * Invalidate cached scrollbar positions, so that scrollbars sliders will + * be udpated. */ dInfoPtr->xScrollFirst = dInfoPtr->xScrollLast = -1; dInfoPtr->yScrollFirst = dInfoPtr->yScrollLast = -1; + + if (mask & TK_TEXT_LINE_GEOMETRY) { + /* + * Set up line metric recalculation. + * + * Avoid the special zero value, since that is used to mark individual + * lines as being out of date. + */ + + if ((++dInfoPtr->lineMetricUpdateEpoch) == 0) { + dInfoPtr->lineMetricUpdateEpoch++; + } + + dInfoPtr->currentMetricUpdateLine = -1; + + /* + * Also cancel any partial line-height calculations (for long-wrapped + * lines) in progress. + */ + + dInfoPtr->metricEpoch = -1; + + if (dInfoPtr->lineUpdateTimer == NULL) { + textPtr->refCount++; + dInfoPtr->lineUpdateTimer = Tcl_CreateTimerHandler(1, + AsyncUpdateLineMetrics, (ClientData) textPtr); + } + } } /* @@ -3072,68 +4944,84 @@ TkTextRelayoutWindow(textPtr) * * TkTextSetYView -- * - * This procedure is called to specify what lines are to be - * displayed in a text widget. + * This function is called to specify what lines are to be displayed in a + * text widget. * * Results: * None. * * Side effects: - * The display will (eventually) be updated so that the position - * given by "indexPtr" is visible on the screen at the position - * determined by "pickPlace". + * The display will (eventually) be updated so that the position given by + * "indexPtr" is visible on the screen at the position determined by + * "pickPlace". * *---------------------------------------------------------------------- */ void -TkTextSetYView(textPtr, indexPtr, pickPlace) - TkText *textPtr; /* Widget record for text widget. */ - TkTextIndex *indexPtr; /* Position that is to appear somewhere - * in the view. */ - int pickPlace; /* 0 means topLine must appear at top of - * screen. 1 means we get to pick where it - * appears: minimize screen motion or else - * display line at center of screen. */ +TkTextSetYView( + TkText *textPtr, /* Widget record for text widget. */ + TkTextIndex *indexPtr, /* Position that is to appear somewhere in the + * view. */ + int pickPlace) /* 0 means the given index must appear exactly + * at the top of the screen. TK_TEXT_PICKPLACE + * (-1) means we get to pick where it appears: + * minimize screen motion or else display line + * at center of screen. TK_TEXT_NOPIXELADJUST + * (-2) indicates to make the given index the + * top line, but if it is already the top + * line, don't nudge it up or down by a few + * pixels just to make sure it is entirely + * displayed. Positive numbers indicate the + * number of pixels of the index's line which + * are to be off the top of the screen. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; register DLine *dlPtr; int bottomY, close, lineIndex; TkTextIndex tmpIndex, rounded; - Tk_FontMetrics fm; + int lineHeight; /* - * If the specified position is the extra line at the end of the - * text, round it back to the last real line. + * If the specified position is the extra line at the end of the text, + * round it back to the last real line. */ - lineIndex = TkBTreeLineIndex(indexPtr->linePtr); - if (lineIndex == TkBTreeNumLines(indexPtr->tree)) { - TkTextIndexBackChars(indexPtr, 1, &rounded); + lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr); + if (lineIndex == TkBTreeNumLines(indexPtr->tree, textPtr)) { + TkTextIndexBackChars(textPtr, indexPtr, 1, &rounded, COUNT_INDICES); indexPtr = &rounded; } - if (!pickPlace) { + if (pickPlace == TK_TEXT_NOPIXELADJUST) { + if (textPtr->topIndex.linePtr == indexPtr->linePtr + && textPtr->topIndex.byteIndex == indexPtr->byteIndex) { + pickPlace = dInfoPtr->topPixelOffset; + } else { + pickPlace = 0; + } + } + + if (pickPlace != TK_TEXT_PICKPLACE) { /* - * The specified position must go at the top of the screen. - * Just leave all the DLine's alone: we may be able to reuse - * some of the information that's currently on the screen - * without redisplaying it all. + * The specified position must go at the top of the screen. Just leave + * all the DLine's alone: we may be able to reuse some of the + * information that's currently on the screen without redisplaying it + * all. */ - if (indexPtr->byteIndex == 0) { - textPtr->topIndex = *indexPtr; - } else { - MeasureUp(textPtr, indexPtr, 0, &textPtr->topIndex); + textPtr->topIndex = *indexPtr; + if (indexPtr->byteIndex != 0) { + TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL); } + dInfoPtr->newTopPixelOffset = pickPlace; goto scheduleUpdate; } /* - * We have to pick where to display the index. First, bring - * the display information up to date and see if the index will be - * completely visible in the current screen configuration. If so - * then there's nothing to do. + * We have to pick where to display the index. First, bring the display + * information up to date and see if the index will be completely visible + * in the current screen configuration. If so then there's nothing to do. */ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { @@ -3143,68 +5031,92 @@ TkTextSetYView(textPtr, indexPtr, pickPlace) if (dlPtr != NULL) { if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) { /* - * Part of the line hangs off the bottom of the screen; - * pretend the whole line is off-screen. + * Part of the line hangs off the bottom of the screen; pretend + * the whole line is off-screen. */ dlPtr = NULL; } else if ((dlPtr->index.linePtr == indexPtr->linePtr) && (dlPtr->index.byteIndex <= indexPtr->byteIndex)) { + if (dInfoPtr->dLinePtr == dlPtr && dInfoPtr->topPixelOffset != 0) { + /* + * It is on the top line, but that line is hanging off the top + * of the screen. Change the top overlap to zero and update. + */ + + dInfoPtr->newTopPixelOffset = 0; + goto scheduleUpdate; + } return; } } /* - * The desired line isn't already on-screen. Figure out what - * it means to be "close" to the top or bottom of the screen. - * Close means within 1/3 of the screen height or within three - * lines, whichever is greater. Add one extra line also, to - * account for the way MeasureUp rounds. + * The desired line isn't already on-screen. Figure out what it means to + * be "close" to the top or bottom of the screen. Close means within 1/3 + * of the screen height or within three lines, whichever is greater. + * + * If the line is not close, place it in the center of the window. + */ + + lineHeight = CalculateDisplayLineHeight(textPtr, indexPtr, NULL, NULL); + + /* + * It would be better if 'bottomY' were calculated using the actual height + * of the given line, not 'textPtr->charHeight'. */ - Tk_GetFontMetrics(textPtr->tkfont, &fm); - bottomY = (dInfoPtr->y + dInfoPtr->maxY + fm.linespace)/2; + bottomY = (dInfoPtr->y + dInfoPtr->maxY + lineHeight)/2; close = (dInfoPtr->maxY - dInfoPtr->y)/3; - if (close < 3*fm.linespace) { - close = 3*fm.linespace; + if (close < 3*textPtr->charHeight) { + close = 3*textPtr->charHeight; } - close += fm.linespace; if (dlPtr != NULL) { + int overlap; + /* - * The desired line is above the top of screen. If it is - * "close" to the top of the window then make it the top - * line on the screen. + * The desired line is above the top of screen. If it is "close" to + * the top of the window then make it the top line on the screen. + * MeasureUp counts from the bottom of the given index upwards, so we + * add an extra half line to be sure we count far enough. */ - MeasureUp(textPtr, &textPtr->topIndex, close, &tmpIndex); + MeasureUp(textPtr, &textPtr->topIndex, close + textPtr->charHeight/2, + &tmpIndex, &overlap); if (TkTextIndexCmp(&tmpIndex, indexPtr) <= 0) { - MeasureUp(textPtr, indexPtr, 0, &textPtr->topIndex); + textPtr->topIndex = *indexPtr; + TkTextFindDisplayLineEnd(textPtr, &textPtr->topIndex, 0, NULL); + dInfoPtr->newTopPixelOffset = 0; goto scheduleUpdate; } } else { + int overlap; + /* - * The desired line is below the bottom of the screen. If it is - * "close" to the bottom of the screen then position it at the - * bottom of the screen. + * The desired line is below the bottom of the screen. If it is + * "close" to the bottom of the screen then position it at the bottom + * of the screen. */ - MeasureUp(textPtr, indexPtr, close, &tmpIndex); + MeasureUp(textPtr, indexPtr, close + lineHeight + - textPtr->charHeight/2, &tmpIndex, &overlap); if (FindDLine(dInfoPtr->dLinePtr, &tmpIndex) != NULL) { bottomY = dInfoPtr->maxY - dInfoPtr->y; } } /* - * Our job now is to arrange the display so that indexPtr appears - * as low on the screen as possible but with its bottom no lower - * than bottomY. BottomY is the bottom of the window if the - * desired line is just below the current screen, otherwise it - * is a half-line lower than the center of the window. + * Our job now is to arrange the display so that indexPtr appears as low + * on the screen as possible but with its bottom no lower than bottomY. + * BottomY is the bottom of the window if the desired line is just below + * the current screen, otherwise it is a half-line lower than the center + * of the window. */ - MeasureUp(textPtr, indexPtr, bottomY, &textPtr->topIndex); + MeasureUp(textPtr, indexPtr, bottomY, &textPtr->topIndex, + &dInfoPtr->newTopPixelOffset); - scheduleUpdate: + scheduleUpdate: if (!(dInfoPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayText, (ClientData) textPtr); } @@ -3214,21 +5126,78 @@ TkTextSetYView(textPtr, indexPtr, pickPlace) /* *-------------------------------------------------------------- * + * TkTextMeasureDown -- + * + * Given one index, find the index of the first character on the highest + * display line that would be displayed no more than "distance" pixels + * below the top of the given index. + * + * Results: + * The srcPtr is manipulated in place to reflect the new position. We + * return the number of pixels by which 'distance' overlaps the srcPtr. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +int +TkTextMeasureDown( + TkText *textPtr, /* Text widget in which to measure. */ + TkTextIndex *srcPtr, /* Index of character from which to start + * measuring. */ + int distance) /* Vertical distance in pixels measured from + * the top pixel in srcPtr's logical line. */ +{ + TkTextLine *lastLinePtr; + DLine *dlPtr; + TkTextIndex loop; + + lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr)); + + do { + dlPtr = LayoutDLine(textPtr, srcPtr); + dlPtr->nextPtr = NULL; + + if (distance < dlPtr->height) { + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + break; + } + distance -= dlPtr->height; + TkTextIndexForwBytes(textPtr, srcPtr, dlPtr->byteCount, &loop); + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + if (loop.linePtr == lastLinePtr) { + break; + } + *srcPtr = loop; + } while (distance > 0); + + return distance; +} + +/* + *-------------------------------------------------------------- + * * MeasureUp -- * - * Given one index, find the index of the first character - * on the highest display line that would be displayed no more - * than "distance" pixels above the given index. + * Given one index, find the index of the first character on the highest + * display line that would be displayed no more than "distance" pixels + * above the given index. + * + * If this function is called with distance=0, it simply finds the first + * index on the same display line as srcPtr. However, there is a another + * function TkTextFindDisplayLineEnd designed just for that task which is + * probably better to use. * * Results: - * *dstPtr is filled in with the index of the first character - * on a display line. The display line is found by measuring - * up "distance" pixels above the pixel just below an imaginary - * display line that contains srcPtr. If the display line - * that covers this coordinate actually extends above the - * coordinate, then return the index of the next lower line - * instead (i.e. the returned index will be completely visible - * at or below the given y-coordinate). + * *dstPtr is filled in with the index of the first character on a + * display line. The display line is found by measuring up "distance" + * pixels above the pixel just below an imaginary display line that + * contains srcPtr. If the display line that covers this coordinate + * actually extends above the coordinate, then return any excess pixels + * in *overlap, if that is non-NULL. * * Side effects: * None. @@ -3237,83 +5206,87 @@ TkTextSetYView(textPtr, indexPtr, pickPlace) */ static void -MeasureUp(textPtr, srcPtr, distance, dstPtr) - TkText *textPtr; /* Text widget in which to measure. */ - TkTextIndex *srcPtr; /* Index of character from which to start +MeasureUp( + TkText *textPtr, /* Text widget in which to measure. */ + CONST TkTextIndex *srcPtr, /* Index of character from which to start * measuring. */ - int distance; /* Vertical distance in pixels measured - * from the pixel just below the lowest - * one in srcPtr's line. */ - TkTextIndex *dstPtr; /* Index to fill in with result. */ + int distance, /* Vertical distance in pixels measured from + * the pixel just below the lowest one in + * srcPtr's line. */ + TkTextIndex *dstPtr, /* Index to fill in with result. */ + int *overlap) /* Used to store how much of the final index + * returned was not covered by 'distance'. */ { int lineNum; /* Number of current line. */ int bytesToCount; /* Maximum number of bytes to measure in * current line. */ - TkTextIndex bestIndex = {NULL, NULL, 0}; /* Best candidate seen so far for - * result. Silence gcc 4 warning */ TkTextIndex index; DLine *dlPtr, *lowestPtr; - int noBestYet; /* 1 means bestIndex hasn't been set. */ - noBestYet = 1; bytesToCount = srcPtr->byteIndex + 1; index.tree = srcPtr->tree; - for (lineNum = TkBTreeLineIndex(srcPtr->linePtr); lineNum >= 0; + for (lineNum = TkBTreeLinesTo(textPtr, srcPtr->linePtr); lineNum >= 0; lineNum--) { /* * Layout an entire text line (potentially > 1 display line). - * For the first line, which contains srcPtr, only layout the - * part up through srcPtr (bytesToCount is non-infinite to - * accomplish this). Make a list of all the display lines - * in backwards order (the lowest DLine on the screen is first - * in the list). + * + * For the first line, which contains srcPtr, only layout the part up + * through srcPtr (bytesToCount is non-infinite to accomplish this). + * Make a list of all the display lines in backwards order (the lowest + * DLine on the screen is first in the list). */ - index.linePtr = TkBTreeFindLine(srcPtr->tree, lineNum); + index.linePtr = TkBTreeFindLine(srcPtr->tree, textPtr, lineNum); index.byteIndex = 0; lowestPtr = NULL; do { dlPtr = LayoutDLine(textPtr, &index); dlPtr->nextPtr = lowestPtr; lowestPtr = dlPtr; - TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); + TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount, &index); bytesToCount -= dlPtr->byteCount; - } while ((bytesToCount > 0) && (index.linePtr == dlPtr->index.linePtr)); + } while (bytesToCount>0 && index.linePtr==dlPtr->index.linePtr); /* * Scan through the display lines to see if we've covered enough - * vertical distance. If so, save the starting index for the - * line at the desired location. + * vertical distance. If so, save the starting index for the line at + * the desired location. If distance was zero to start with then we + * simply get the first index on the same display line as the original + * index. */ for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) { distance -= dlPtr->height; - if (distance < 0) { - *dstPtr = (noBestYet) ? dlPtr->index : bestIndex; + if (distance <= 0) { + *dstPtr = dlPtr->index; + if (overlap != NULL) { + *overlap = -distance; + } break; } - bestIndex = dlPtr->index; - noBestYet = 0; } /* - * Discard the display lines, then either return or prepare - * for the next display line to lay out. + * Discard the display lines, then either return or prepare for the + * next display line to lay out. */ - FreeDLines(textPtr, lowestPtr, (DLine *) NULL, 0); - if (distance < 0) { + FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE); + if (distance <= 0) { return; } bytesToCount = INT_MAX; /* Consider all chars. in next line. */ } /* - * Ran off the beginning of the text. Return the first character - * in the text. + * Ran off the beginning of the text. Return the first character in the + * text. */ - TkTextMakeByteIndex(textPtr->tree, 0, 0, dstPtr); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, dstPtr); + if (overlap != NULL) { + *overlap = 0; + } } /* @@ -3321,9 +5294,9 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr) * * TkTextSeeCmd -- * - * This procedure is invoked to process the "see" option for - * the widget command for text widgets. See the user documentation - * for details on what it does. + * This function is invoked to process the "see" option for the widget + * command for text widgets. See the user documentation for details on + * what it does. * * Results: * A standard Tcl result. @@ -3335,13 +5308,13 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr) */ int -TkTextSeeCmd(textPtr, interp, argc, argv) - TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextSeeCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "see". */ + * objv[1] is "see". */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; TkTextIndex index; @@ -3349,29 +5322,29 @@ TkTextSeeCmd(textPtr, interp, argc, argv) DLine *dlPtr; TkTextDispChunk *chunkPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " see index\"", (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[2], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[2], &index) != TCL_OK) { return TCL_ERROR; } /* - * If the specified position is the extra line at the end of the - * text, round it back to the last real line. + * If the specified position is the extra line at the end of the text, + * round it back to the last real line. */ - if (TkBTreeLineIndex(index.linePtr) == TkBTreeNumLines(index.tree)) { - TkTextIndexBackChars(&index, 1, &index); + if (TkBTreeLinesTo(textPtr, index.linePtr) + == TkBTreeNumLines(index.tree, textPtr)) { + TkTextIndexBackChars(textPtr, &index, 1, &index, COUNT_INDICES); } /* * First get the desired position into the vertical range of the window. */ - TkTextSetYView(textPtr, &index, 1); + TkTextSetYView(textPtr, &index, TK_TEXT_PICKPLACE); /* * Now make sure that the character is in view horizontally. @@ -3386,8 +5359,8 @@ TkTextSeeCmd(textPtr, interp, argc, argv) } /* - * Find the chunk that contains the desired index. - * dlPtr may be NULL if the widget is not mapped. [Bug #641778] + * Find the chunk that contains the desired index. dlPtr may be NULL if + * the widget is not mapped. [Bug #641778] */ dlPtr = FindDLine(dInfoPtr->dLinePtr, &index); @@ -3397,7 +5370,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv) byteCount = index.byteIndex - dlPtr->index.byteIndex; for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL ; - chunkPtr = chunkPtr->nextPtr) { + chunkPtr = chunkPtr->nextPtr) { if (byteCount < chunkPtr->numBytes) { break; } @@ -3405,36 +5378,32 @@ TkTextSeeCmd(textPtr, interp, argc, argv) } /* - * Call a chunk-specific procedure to find the horizontal range of - * the character within the chunk. - * chunkPtr is NULL if trying to see in elided region. + * Call a chunk-specific function to find the horizontal range of the + * character within the chunk. chunkPtr is NULL if trying to see in elided + * region. */ if (chunkPtr != NULL) { - (*chunkPtr->bboxProc)(chunkPtr, byteCount, + (*chunkPtr->bboxProc)(textPtr, chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width, &height); - delta = x - dInfoPtr->curPixelOffset; + delta = x - dInfoPtr->curXPixelOffset; oneThird = lineWidth/3; if (delta < 0) { if (delta < -oneThird) { - dInfoPtr->newByteOffset = (x - lineWidth/2) - / textPtr->charWidth; + dInfoPtr->newXPixelOffset = (x - lineWidth/2); } else { - dInfoPtr->newByteOffset -= ((-delta) + textPtr->charWidth - 1) - / textPtr->charWidth; + dInfoPtr->newXPixelOffset -= ((-delta) ); } } else { delta -= (lineWidth - width); if (delta > 0) { if (delta > oneThird) { - dInfoPtr->newByteOffset = (x - lineWidth/2) - / textPtr->charWidth; + dInfoPtr->newXPixelOffset = (x - lineWidth/2); } else { - dInfoPtr->newByteOffset += (delta + textPtr->charWidth - 1) - / textPtr->charWidth; + dInfoPtr->newXPixelOffset += (delta ); } } else { return TCL_OK; @@ -3454,9 +5423,9 @@ TkTextSeeCmd(textPtr, interp, argc, argv) * * TkTextXviewCmd -- * - * This procedure is invoked to process the "xview" option for - * the widget command for text widgets. See the user documentation - * for details on what it does. + * This function is invoked to process the "xview" option for the widget + * command for text widgets. See the user documentation for details on + * what it does. * * Results: * A standard Tcl result. @@ -3468,56 +5437,60 @@ TkTextSeeCmd(textPtr, interp, argc, argv) */ int -TkTextXviewCmd(textPtr, interp, argc, argv) - TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextXviewCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "xview". */ + * objv[1] is "xview". */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - int type, charsPerPage, count, newOffset; + int type, count; double fraction; if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { UpdateDisplayInfo(textPtr); } - if (argc == 2) { + if (objc == 2) { GetXView(interp, textPtr, 0); return TCL_OK; } - newOffset = dInfoPtr->newByteOffset; - type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count); + type = TextGetScrollInfoObj(interp, textPtr, objc, objv, + &fraction, &count); switch (type) { - case TK_SCROLL_ERROR: - return TCL_ERROR; - case TK_SCROLL_MOVETO: - if (fraction > 1.0) { - fraction = 1.0; - } - if (fraction < 0) { - fraction = 0; - } - newOffset = (int) (((fraction * dInfoPtr->maxLength) / textPtr->charWidth) - + 0.5); - break; - case TK_SCROLL_PAGES: - charsPerPage = ((dInfoPtr->maxX - dInfoPtr->x) / textPtr->charWidth) - - 2; - if (charsPerPage < 1) { - charsPerPage = 1; - } - newOffset += charsPerPage * count; - break; - case TK_SCROLL_UNITS: - newOffset += count; - break; + case TKTEXT_SCROLL_ERROR: + return TCL_ERROR; + case TKTEXT_SCROLL_MOVETO: + if (fraction > 1.0) { + fraction = 1.0; + } + if (fraction < 0) { + fraction = 0; + } + dInfoPtr->newXPixelOffset = (int) + (fraction * dInfoPtr->maxLength + 0.5); + break; + case TKTEXT_SCROLL_PAGES: { + int pixelsPerPage; + + pixelsPerPage = (dInfoPtr->maxX-dInfoPtr->x) - 2*textPtr->charWidth; + if (pixelsPerPage < 1) { + pixelsPerPage = 1; + } + dInfoPtr->newXPixelOffset += pixelsPerPage * count; + break; + } + case TKTEXT_SCROLL_UNITS: + dInfoPtr->newXPixelOffset += count * textPtr->charWidth; + break; + case TKTEXT_SCROLL_PIXELS: + dInfoPtr->newXPixelOffset += count; + break; } - dInfoPtr->newByteOffset = newOffset; dInfoPtr->flags |= DINFO_OUT_OF_DATE; if (!(dInfoPtr->flags & REDRAW_PENDING)) { dInfoPtr->flags |= REDRAW_PENDING; @@ -3529,56 +5502,141 @@ TkTextXviewCmd(textPtr, interp, argc, argv) /* *---------------------------------------------------------------------- * - * ScrollByLines -- + * YScrollByPixels -- + * + * This function is called to scroll a text widget up or down by a given + * number of pixels. + * + * Results: + * None. + * + * Side effects: + * The view in textPtr's window changes to reflect the value of "offset". + * + *---------------------------------------------------------------------- + */ + +static void +YScrollByPixels( + TkText *textPtr, /* Widget to scroll. */ + int offset) /* Amount by which to scroll, in pixels. + * Positive means that information later in + * text becomes visible, negative means that + * information earlier in the text becomes + * visible. */ +{ + TextDInfo *dInfoPtr = textPtr->dInfoPtr; + + if (offset < 0) { + /* + * Now we want to measure up this number of pixels from the top of the + * screen. But the top line may not be totally visible. Note that + * 'count' is negative here. + */ + + offset -= CalculateDisplayLineHeight(textPtr, + &textPtr->topIndex, NULL, NULL) - dInfoPtr->topPixelOffset; + MeasureUp(textPtr, &textPtr->topIndex, -offset, + &textPtr->topIndex, &dInfoPtr->newTopPixelOffset); + } else if (offset > 0) { + DLine *dlPtr; + TkTextLine *lastLinePtr; + TkTextIndex newIdx; + + /* + * Scrolling down by pixels. Layout lines starting at the top index + * and count through the desired vertical distance. + */ + + lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr)); + offset += dInfoPtr->topPixelOffset; + dInfoPtr->newTopPixelOffset = 0; + while (offset > 0) { + dlPtr = LayoutDLine(textPtr, &textPtr->topIndex); + dlPtr->nextPtr = NULL; + TkTextIndexForwBytes(textPtr, &textPtr->topIndex, + dlPtr->byteCount, &newIdx); + if (offset <= dlPtr->height) { + /* + * Adjust the top overlap accordingly. + */ + + dInfoPtr->newTopPixelOffset = offset; + } + offset -= dlPtr->height; + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + if (newIdx.linePtr == lastLinePtr || offset <= 0) { + break; + } + textPtr->topIndex = newIdx; + } + } else { + /* + * offset = 0, so no scrolling required. + */ + + return; + } + if (!(dInfoPtr->flags & REDRAW_PENDING)) { + Tcl_DoWhenIdle(DisplayText, (ClientData) textPtr); + } + dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED; +} + +/* + *---------------------------------------------------------------------- + * + * YScrollByLines -- * - * This procedure is called to scroll a text widget up or down - * by a given number of lines. + * This function is called to scroll a text widget up or down by a given + * number of lines. * * Results: * None. * * Side effects: - * The view in textPtr's window changes to reflect the value - * of "offset". + * The view in textPtr's window changes to reflect the value of "offset". * *---------------------------------------------------------------------- */ static void -ScrollByLines(textPtr, offset) - TkText *textPtr; /* Widget to scroll. */ - int offset; /* Amount by which to scroll, in *screen* - * lines. Positive means that information +YScrollByLines( + TkText *textPtr, /* Widget to scroll. */ + int offset) /* Amount by which to scroll, in display + * lines. Positive means that information * later in text becomes visible, negative - * means that information earlier in the - * text becomes visible. */ + * means that information earlier in the text + * becomes visible. */ { int i, bytesToCount, lineNum; - TkTextIndex new, index; + TkTextIndex newIdx, index; TkTextLine *lastLinePtr; TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *dlPtr, *lowestPtr; if (offset < 0) { /* - * Must scroll up (to show earlier information in the text). - * The code below is similar to that in MeasureUp, except that - * it counts lines instead of pixels. + * Must scroll up (to show earlier information in the text). The code + * below is similar to that in MeasureUp, except that it counts lines + * instead of pixels. */ bytesToCount = textPtr->topIndex.byteIndex + 1; - index.tree = textPtr->tree; - offset--; /* Skip line containing topIndex. */ - for (lineNum = TkBTreeLineIndex(textPtr->topIndex.linePtr); + index.tree = textPtr->sharedTextPtr->tree; + offset--; /* Skip line containing topIndex. */ + for (lineNum = TkBTreeLinesTo(textPtr, textPtr->topIndex.linePtr); lineNum >= 0; lineNum--) { - index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum); + index.linePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, + textPtr, lineNum); index.byteIndex = 0; lowestPtr = NULL; do { dlPtr = LayoutDLine(textPtr, &index); dlPtr->nextPtr = lowestPtr; lowestPtr = dlPtr; - TkTextIndexForwBytes(&index, dlPtr->byteCount, &index); + TkTextIndexForwBytes(textPtr, &index, dlPtr->byteCount,&index); bytesToCount -= dlPtr->byteCount; } while ((bytesToCount > 0) && (index.linePtr == dlPtr->index.linePtr)); @@ -3592,45 +5650,51 @@ ScrollByLines(textPtr, offset) } /* - * Discard the display lines, then either return or prepare - * for the next display line to lay out. + * Discard the display lines, then either return or prepare for + * the next display line to lay out. */ - - FreeDLines(textPtr, lowestPtr, (DLine *) NULL, 0); + + FreeDLines(textPtr, lowestPtr, NULL, DLINE_FREE); if (offset >= 0) { goto scheduleUpdate; } bytesToCount = INT_MAX; } - + /* - * Ran off the beginning of the text. Return the first character - * in the text. + * Ran off the beginning of the text. Return the first character in + * the text, and make sure we haven't left anything overlapping the + * top window border. */ - TkTextMakeByteIndex(textPtr->tree, 0, 0, &textPtr->topIndex); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, + &textPtr->topIndex); + dInfoPtr->newTopPixelOffset = 0; } else { /* - * Scrolling down, to show later information in the text. - * Just count lines from the current top of the window. + * Scrolling down, to show later information in the text. Just count + * lines from the current top of the window. */ - lastLinePtr = TkBTreeFindLine(textPtr->tree, - TkBTreeNumLines(textPtr->tree)); + lastLinePtr = TkBTreeFindLine(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr)); for (i = 0; i < offset; i++) { dlPtr = LayoutDLine(textPtr, &textPtr->topIndex); - if (dlPtr->length == 0 && dlPtr->height == 0) offset++; + if (dlPtr->length == 0 && dlPtr->height == 0) { + offset++; + } dlPtr->nextPtr = NULL; - TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount, &new); - FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0); - if (new.linePtr == lastLinePtr) { + TkTextIndexForwBytes(textPtr, &textPtr->topIndex, + dlPtr->byteCount, &newIdx); + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE); + if (newIdx.linePtr == lastLinePtr) { break; } - textPtr->topIndex = new; + textPtr->topIndex = newIdx; } } - scheduleUpdate: + scheduleUpdate: if (!(dInfoPtr->flags & REDRAW_PENDING)) { Tcl_DoWhenIdle(DisplayText, (ClientData) textPtr); } @@ -3642,9 +5706,9 @@ ScrollByLines(textPtr, offset) * * TkTextYviewCmd -- * - * This procedure is invoked to process the "yview" option for - * the widget command for text widgets. See the user documentation - * for details on what it does. + * This function is invoked to process the "yview" option for the widget + * command for text widgets. See the user documentation for details on + * what it does. * * Results: * A standard Tcl result. @@ -3656,29 +5720,26 @@ ScrollByLines(textPtr, offset) */ int -TkTextYviewCmd(textPtr, interp, argc, argv) - TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextYviewCmd( + TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "yview". */ + * objv[1] is "yview". */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - int pickPlace, lineNum, type, bytesInLine; - Tk_FontMetrics fm; + int pickPlace, type; int pixels, count; - size_t switchLength; + int switchLength; double fraction; - TkTextIndex index, new; - TkTextLine *lastLinePtr; - DLine *dlPtr; + TkTextIndex index; if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { UpdateDisplayInfo(textPtr); } - if (argc == 2) { + if (objc == 2) { GetYView(interp, textPtr, 0); return TCL_OK; } @@ -3688,117 +5749,135 @@ TkTextYviewCmd(textPtr, interp, argc, argv) */ pickPlace = 0; - if (argv[2][0] == '-') { - switchLength = strlen(argv[2]); - if ((switchLength >= 2) - && (strncmp(argv[2], "-pickplace", switchLength) == 0)) { + if (Tcl_GetString(objv[2])[0] == '-') { + register CONST char *switchStr = + Tcl_GetStringFromObj(objv[2], &switchLength); + + if ((switchLength >= 2) && (strncmp(switchStr, "-pickplace", + (unsigned) switchLength) == 0)) { pickPlace = 1; - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " yview -pickplace lineNum|index\"", - (char *) NULL); + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "lineNum|index"); return TCL_ERROR; } } } - if ((argc == 3) || pickPlace) { - if (Tcl_GetInt(interp, argv[2+pickPlace], &lineNum) == TCL_OK) { - TkTextMakeByteIndex(textPtr->tree, lineNum, 0, &index); + if ((objc == 3) || pickPlace) { + int lineNum; + + if (Tcl_GetIntFromObj(interp, objv[2+pickPlace], &lineNum) == TCL_OK) { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineNum, 0, &index); TkTextSetYView(textPtr, &index, 0); return TCL_OK; } - + /* * The argument must be a regular text index. */ - + Tcl_ResetResult(interp); - if (TkTextGetIndex(interp, textPtr, argv[2+pickPlace], + if (TkTextGetObjIndex(interp, textPtr, objv[2+pickPlace], &index) != TCL_OK) { return TCL_ERROR; } - TkTextSetYView(textPtr, &index, pickPlace); + TkTextSetYView(textPtr, &index, (pickPlace ? TK_TEXT_PICKPLACE : 0)); return TCL_OK; } /* - * New syntax: dispatch based on argv[2]. + * New syntax: dispatch based on objv[2]. */ - type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count); + type = TextGetScrollInfoObj(interp, textPtr, objc,objv, &fraction, &count); switch (type) { - case TK_SCROLL_ERROR: - return TCL_ERROR; - case TK_SCROLL_MOVETO: - if (fraction > 1.0) { - fraction = 1.0; - } - if (fraction < 0) { - fraction = 0; - } - fraction *= TkBTreeNumLines(textPtr->tree); - lineNum = (int) fraction; - TkTextMakeByteIndex(textPtr->tree, lineNum, 0, &index); - bytesInLine = TkBTreeBytesInLine(index.linePtr); - index.byteIndex = (int)((bytesInLine * (fraction-lineNum)) + 0.5); - if (index.byteIndex >= bytesInLine) { - TkTextMakeByteIndex(textPtr->tree, lineNum + 1, 0, &index); - } - TkTextSetYView(textPtr, &index, 0); - break; - case TK_SCROLL_PAGES: + case TKTEXT_SCROLL_ERROR: + return TCL_ERROR; + case TKTEXT_SCROLL_MOVETO: { + int numPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree, + textPtr); + int topMostPixel; + + if (numPixels == 0) { /* - * Scroll up or down by screenfuls. Actually, use the - * window height minus two lines, so that there's some - * overlap between adjacent pages. + * If the window is totally empty no scrolling is needed, and the + * TkTextMakePixelIndex call below will fail. */ - Tk_GetFontMetrics(textPtr->tkfont, &fm); - if (count < 0) { - pixels = (dInfoPtr->maxY - 2*fm.linespace - dInfoPtr->y)*(-count) - + fm.linespace; - MeasureUp(textPtr, &textPtr->topIndex, pixels, &new); - if (TkTextIndexCmp(&textPtr->topIndex, &new) == 0) { - /* - * A page of scrolling ended up being less than one line. - * Scroll one line anyway. - */ + break; + } + if (fraction > 1.0) { + fraction = 1.0; + } + if (fraction < 0) { + fraction = 0; + } - count = -1; - goto scrollByLines; - } - textPtr->topIndex = new; - } else { + /* + * Calculate the pixel count for the new topmost pixel in the topmost + * line of the window. Note that the interpretation of 'fraction' is + * that it counts from 0 (top pixel in buffer) to 1.0 (one pixel past + * the last pixel in buffer). + */ + + topMostPixel = (int) (0.5 + fraction * numPixels); + if (topMostPixel >= numPixels) { + topMostPixel = numPixels -1; + } + + /* + * This function returns the number of pixels by which the given line + * should overlap the top of the visible screen. + * + * This is then used to provide smooth scrolling. + */ + + pixels = TkTextMakePixelIndex(textPtr, topMostPixel, &index); + TkTextSetYView(textPtr, &index, pixels); + break; + } + case TKTEXT_SCROLL_PAGES: { + /* + * Scroll up or down by screenfuls. Actually, use the window height + * minus two lines, so that there's some overlap between adjacent + * pages. + */ + + int height = dInfoPtr->maxY - dInfoPtr->y; + + if (textPtr->charHeight * 4 >= height) { + /* + * A single line is more than a quarter of the display. We choose + * to scroll by 3/4 of the height instead. + */ + + pixels = 3*height/4; + if (pixels < textPtr->charHeight) { /* - * Scrolling down by pages. Layout lines starting at the - * top index and count through the desired vertical distance. + * But, if 3/4 of the height is actually less than a single + * typical character height, then scroll by the minimum of the + * linespace or the total height. */ - pixels = (dInfoPtr->maxY - 2*fm.linespace - dInfoPtr->y)*count; - lastLinePtr = TkBTreeFindLine(textPtr->tree, - TkBTreeNumLines(textPtr->tree)); - do { - dlPtr = LayoutDLine(textPtr, &textPtr->topIndex); - dlPtr->nextPtr = NULL; - TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount, - &new); - pixels -= dlPtr->height; - FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0); - if (new.linePtr == lastLinePtr) { - break; - } - textPtr->topIndex = new; - } while (pixels > 0); - } - if (!(dInfoPtr->flags & REDRAW_PENDING)) { - Tcl_DoWhenIdle(DisplayText, (ClientData) textPtr); + if (textPtr->charHeight < height) { + pixels = textPtr->charHeight; + } else { + pixels = height; + } } - dInfoPtr->flags |= REDRAW_PENDING|DINFO_OUT_OF_DATE|REPICK_NEEDED; - break; - case TK_SCROLL_UNITS: - scrollByLines: - ScrollByLines(textPtr, count); - break; + pixels *= count; + } else { + pixels = (height - 2*textPtr->charHeight)*count; + } + YScrollByPixels(textPtr, pixels); + break; + } + case TKTEXT_SCROLL_PIXELS: + YScrollByPixels(textPtr, count); + break; + case TKTEXT_SCROLL_UNITS: + YScrollByLines(textPtr, count); + break; } return TCL_OK; } @@ -3808,9 +5887,9 @@ TkTextYviewCmd(textPtr, interp, argc, argv) * * TkTextScanCmd -- * - * This procedure is invoked to process the "scan" option for - * the widget command for text widgets. See the user documentation - * for details on what it does. + * This function is invoked to process the "scan" option for the widget + * command for text widgets. See the user documentation for details on + * what it does. * * Results: * A standard Tcl result. @@ -3822,91 +5901,93 @@ TkTextYviewCmd(textPtr, interp, argc, argv) */ int -TkTextScanCmd(textPtr, interp, argc, argv) - register TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextScanCmd( + register TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "scan". */ + * objv[1] is "scan". */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; TkTextIndex index; - int c, x, y, totalScroll, newByte, maxByte, gain=10; - Tk_FontMetrics fm; + int c, x, y, totalScroll, gain=10; size_t length; - if ((argc != 5) && (argc != 6)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " scan mark x y\" or \"", - argv[0], " scan dragto x y ?gain?\"", (char *) NULL); + if ((objc != 5) && (objc != 6)) { + Tcl_WrongNumArgs(interp, 2, objv, "mark x y"); + Tcl_AppendResult(interp, " or \"", Tcl_GetString(objv[0]), + " scan dragto x y ?gain?\"", NULL); + /* + * Ought to be: + * Tcl_WrongNumArgs(interp, 2, objc, "dragto x y ?gain?"); + */ return TCL_ERROR; } - if (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) { return TCL_ERROR; } - if (Tcl_GetInt(interp, argv[4], &y) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) { return TCL_ERROR; } - if ((argc == 6) && (Tcl_GetInt(interp, argv[5], &gain) != TCL_OK)) + if ((objc == 6) && (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) { return TCL_ERROR; - c = argv[2][0]; - length = strlen(argv[2]); - if ((c == 'd') && (strncmp(argv[2], "dragto", length) == 0)) { + } + c = Tcl_GetString(objv[2])[0]; + length = strlen(Tcl_GetString(objv[2])); + if (c=='d' && strncmp(Tcl_GetString(objv[2]), "dragto", length)==0) { + int newX, maxX; + /* - * Amplify the difference between the current position and the - * mark position to compute how much the view should shift, then - * update the mark position to correspond to the new view. If we - * run off the edge of the text, reset the mark point so that the - * current position continues to correspond to the edge of the - * window. This means that the picture will start dragging as - * soon as the mouse reverses direction (without this reset, might - * have to slide mouse a long ways back before the picture starts - * moving again). + * Amplify the difference between the current position and the mark + * position to compute how much the view should shift, then update the + * mark position to correspond to the new view. If we run off the edge + * of the text, reset the mark point so that the current position + * continues to correspond to the edge of the window. This means that + * the picture will start dragging as soon as the mouse reverses + * direction (without this reset, might have to slide mouse a long + * ways back before the picture starts moving again). */ - newByte = dInfoPtr->scanMarkIndex + (gain*(dInfoPtr->scanMarkX - x)) - / (textPtr->charWidth); - maxByte = 1 + (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x) - + textPtr->charWidth - 1)/textPtr->charWidth; - if (newByte < 0) { - newByte = 0; - dInfoPtr->scanMarkIndex = 0; + newX = dInfoPtr->scanMarkXPixel + gain*(dInfoPtr->scanMarkX - x); + maxX = 1 + dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x); + if (newX < 0) { + newX = 0; + dInfoPtr->scanMarkXPixel = 0; dInfoPtr->scanMarkX = x; - } else if (newByte > maxByte) { - newByte = maxByte; - dInfoPtr->scanMarkIndex = maxByte; + } else if (newX > maxX) { + newX = maxX; + dInfoPtr->scanMarkXPixel = maxX; dInfoPtr->scanMarkX = x; } - dInfoPtr->newByteOffset = newByte; + dInfoPtr->newXPixelOffset = newX; - Tk_GetFontMetrics(textPtr->tkfont, &fm); - totalScroll = (gain*(dInfoPtr->scanMarkY - y)) / fm.linespace; - if (totalScroll != dInfoPtr->scanTotalScroll) { + totalScroll = gain*(dInfoPtr->scanMarkY - y); + if (totalScroll != dInfoPtr->scanTotalYScroll) { index = textPtr->topIndex; - ScrollByLines(textPtr, totalScroll-dInfoPtr->scanTotalScroll); - dInfoPtr->scanTotalScroll = totalScroll; + YScrollByPixels(textPtr, totalScroll-dInfoPtr->scanTotalYScroll); + dInfoPtr->scanTotalYScroll = totalScroll; if ((index.linePtr == textPtr->topIndex.linePtr) && (index.byteIndex == textPtr->topIndex.byteIndex)) { - dInfoPtr->scanTotalScroll = 0; + dInfoPtr->scanTotalYScroll = 0; dInfoPtr->scanMarkY = y; } } - } else if ((c == 'm') && (strncmp(argv[2], "mark", length) == 0)) { - dInfoPtr->scanMarkIndex = dInfoPtr->newByteOffset; + dInfoPtr->flags |= DINFO_OUT_OF_DATE; + if (!(dInfoPtr->flags & REDRAW_PENDING)) { + dInfoPtr->flags |= REDRAW_PENDING; + Tcl_DoWhenIdle(DisplayText, (ClientData) textPtr); + } + } else if (c=='m' && strncmp(Tcl_GetString(objv[2]), "mark", length)==0) { + dInfoPtr->scanMarkXPixel = dInfoPtr->newXPixelOffset; dInfoPtr->scanMarkX = x; - dInfoPtr->scanTotalScroll = 0; + dInfoPtr->scanTotalYScroll = 0; dInfoPtr->scanMarkY = y; } else { - Tcl_AppendResult(interp, "bad scan option \"", argv[2], - "\": must be mark or dragto", (char *) NULL); + Tcl_AppendResult(interp, "bad scan option \"", Tcl_GetString(objv[2]), + "\": must be mark or dragto", NULL); return TCL_ERROR; } - dInfoPtr->flags |= DINFO_OUT_OF_DATE; - if (!(dInfoPtr->flags & REDRAW_PENDING)) { - dInfoPtr->flags |= REDRAW_PENDING; - Tcl_DoWhenIdle(DisplayText, (ClientData) textPtr); - } return TCL_OK; } @@ -3915,19 +5996,19 @@ TkTextScanCmd(textPtr, interp, argc, argv) * * GetXView -- * - * This procedure computes the fractions that indicate what's - * visible in a text window and, optionally, evaluates a - * Tcl script to report them to the text's associated scrollbar. + * This function computes the fractions that indicate what's visible in a + * text window and, optionally, evaluates a Tcl script to report them to + * the text's associated scrollbar. * * Results: - * If report is zero, then the interp's result is filled in with - * two real numbers separated by a space, giving the position of - * the left and right edges of the window as fractions from 0 to - * 1, where 0 means the left edge of the text and 1 means the right - * edge. If report is non-zero, then the interp's result isn't modified - * directly, but instead a script is evaluated in interp to report - * the new horizontal scroll position to the scrollbar (if the scroll - * position hasn't changed then no script is invoked). + * If report is zero, then the interp's result is filled in with two real + * numbers separated by a space, giving the position of the left and + * right edges of the window as fractions from 0 to 1, where 0 means the + * left edge of the text and 1 means the right edge. If report is + * non-zero, then the interp's result isn't modified directly, but + * instead a script is evaluated in interp to report the new horizontal + * scroll position to the scrollbar (if the scroll position hasn't + * changed then no script is invoked). * * Side effects: * None. @@ -3936,24 +6017,24 @@ TkTextScanCmd(textPtr, interp, argc, argv) */ static void -GetXView(interp, textPtr, report) - Tcl_Interp *interp; /* If "report" is FALSE, string - * describing visible range gets - * stored in the interp's result. */ - TkText *textPtr; /* Information about text widget. */ - int report; /* Non-zero means report info to - * scrollbar if it has changed. */ +GetXView( + Tcl_Interp *interp, /* If "report" is FALSE, string describing + * visible range gets stored in the interp's + * result. */ + TkText *textPtr, /* Information about text widget. */ + int report) /* Non-zero means report info to scrollbar if + * it has changed. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - char buffer[TCL_DOUBLE_SPACE * 2 + 1]; double first, last; int code; + Tcl_Obj *listObj; if (dInfoPtr->maxLength > 0) { - first = ((double) dInfoPtr->curPixelOffset) - / dInfoPtr->maxLength; - last = first + ((double) (dInfoPtr->maxX - dInfoPtr->x)) + first = ((double) dInfoPtr->curXPixelOffset) / dInfoPtr->maxLength; + last = ((double) (dInfoPtr->curXPixelOffset + dInfoPtr->maxX + - dInfoPtr->x))/dInfoPtr->maxLength; if (last > 1.0) { last = 1.0; } @@ -3962,44 +6043,177 @@ GetXView(interp, textPtr, report) last = 1.0; } if (!report) { - sprintf(buffer, "%g %g", first, last); - Tcl_SetResult(interp, buffer, TCL_VOLATILE); + listObj = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last)); + Tcl_SetObjResult(interp, listObj); return; } if (FP_EQUAL_SCALE(first, dInfoPtr->xScrollFirst, dInfoPtr->maxLength) && - FP_EQUAL_SCALE(last, dInfoPtr->xScrollLast, dInfoPtr->maxLength)) { + FP_EQUAL_SCALE(last, dInfoPtr->xScrollLast, dInfoPtr->maxLength)) { return; } dInfoPtr->xScrollFirst = first; dInfoPtr->xScrollLast = last; - sprintf(buffer, " %g %g", first, last); - code = Tcl_VarEval(interp, textPtr->xScrollCmd, - buffer, (char *) NULL); - if (code != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (horizontal scrolling command executed by text)"); - Tcl_BackgroundError(interp); + if (textPtr->xScrollCmd != NULL) { + char buf1[TCL_DOUBLE_SPACE+1]; + char buf2[TCL_DOUBLE_SPACE+1]; + + buf1[0] = ' '; + buf2[0] = ' '; + Tcl_PrintDouble(NULL, first, buf1+1); + Tcl_PrintDouble(NULL, last, buf2+1); + code = Tcl_VarEval(interp, textPtr->xScrollCmd, buf1, buf2, NULL); + if (code != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n (horizontal scrolling command executed by text)"); + Tcl_BackgroundError(interp); + } } } /* *---------------------------------------------------------------------- * + * GetYPixelCount -- + * + * How many pixels are there between the absolute top of the widget and + * the top of the given DLine. + * + * While this function will work for any valid DLine, it is only ever + * called when dlPtr is the first display line in the widget (by + * 'GetYView'). This means that usually this function is a very quick + * calculation, since it can use the pre-calculated linked-list of DLines + * for height information. + * + * The only situation where this breaks down is if dlPtr's logical line + * wraps enough times to fill the text widget's current view - in this + * case we won't have enough dlPtrs in the linked list to be able to + * subtract off what we want. + * + * Results: + * The number of pixels. + * + * This value has a valid range between '0' (the very top of the widget) + * and the number of pixels in the total widget minus the pixel-height of + * the last line. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +GetYPixelCount( + TkText *textPtr, /* Information about text widget. */ + DLine *dlPtr) /* Information about the layout of a given + * index. */ +{ + TkTextLine *linePtr = dlPtr->index.linePtr; + int count; + + /* + * Get the pixel count to the top of dlPtr's logical line. The rest of the + * function is then concerned with updating 'count' for any difference + * between the top of the logical line and the display line. + */ + + count = TkBTreePixelsTo(textPtr, linePtr); + + /* + * For the common case where this dlPtr is also the start of the logical + * line, we can return right away. Note the implicit assumption here that + * the start of a logical line is always the start of a display line (if + * the 'elide won't elide first newline' bug is fixed, this will no longer + * necessarily be true). + */ + + if (dlPtr->index.byteIndex == 0) { + return count; + } + + /* + * Add on the logical line's height to reach one pixel beyond the bottom + * of the logical line. And then subtract off the heights of all the + * display lines from dlPtr to the end of its logical line. + * + * A different approach would be to lay things out from the start of the + * logical line until we reach dlPtr, but since none of those are + * pre-calculated, it'll usually take a lot longer. (But there are cases + * where it would be more efficient: say if we're on the second of 1000 + * wrapped lines all from a single logical line - but that sort of + * optimization is left for the future). + */ + + count += TkBTreeLinePixelCount(textPtr, linePtr); + + do { + count -= dlPtr->height; + if (dlPtr->nextPtr == NULL) { + /* + * We've run out of pre-calculated display lines, so we have to + * lay them out ourselves until the end of the logical line. Here + * is where we could be clever and ask: what's faster, to layout + * all lines from here to line-end, or all lines from the original + * dlPtr to the line-start? We just assume the former. + */ + + TkTextIndex index; + int notFirst = 0; + + while (1) { + TkTextIndexForwBytes(textPtr, &dlPtr->index, + dlPtr->byteCount, &index); + if (notFirst) { + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); + } + if (index.linePtr != linePtr) { + break; + } + dlPtr = LayoutDLine(textPtr, &index); + + if (tkTextDebug) { + char string[TK_POS_CHARS]; + + /* + * Debugging is enabled, so keep a log of all the lines + * whose height was recalculated. The test suite uses this + * information. + */ + + TkTextPrintIndex(textPtr, &index, string); + LOG("tk_textHeightCalc", string); + } + count -= dlPtr->height; + notFirst = 1; + } + break; + } else { + dlPtr = dlPtr->nextPtr; + } + } while (dlPtr->index.linePtr == linePtr); + + return count; +} + +/* + *---------------------------------------------------------------------- + * * GetYView -- * - * This procedure computes the fractions that indicate what's - * visible in a text window and, optionally, evaluates a - * Tcl script to report them to the text's associated scrollbar. + * This function computes the fractions that indicate what's visible in a + * text window and, optionally, evaluates a Tcl script to report them to + * the text's associated scrollbar. * * Results: - * If report is zero, then the interp's result is filled in with - * two real numbers separated by a space, giving the position of - * the top and bottom of the window as fractions from 0 to 1, where - * 0 means the beginning of the text and 1 means the end. If - * report is non-zero, then the interp's result isn't modified directly, - * but a script is evaluated in interp to report the new scroll - * position to the scrollbar (if the scroll position hasn't changed - * then no script is invoked). + * If report is zero, then the interp's result is filled in with two real + * numbers separated by a space, giving the position of the top and + * bottom of the window as fractions from 0 to 1, where 0 means the + * beginning of the text and 1 means the end. If report is non-zero, then + * the interp's result isn't modified directly, but a script is evaluated + * in interp to report the new scroll position to the scrollbar (if the + * scroll position hasn't changed then no script is invoked). * * Side effects: * None. @@ -4008,62 +6222,171 @@ GetXView(interp, textPtr, report) */ static void -GetYView(interp, textPtr, report) - Tcl_Interp *interp; /* If "report" is FALSE, string - * describing visible range gets - * stored in the interp's result. */ - TkText *textPtr; /* Information about text widget. */ - int report; /* Non-zero means report info to - * scrollbar if it has changed. */ +GetYView( + Tcl_Interp *interp, /* If "report" is FALSE, string describing + * visible range gets stored in the interp's + * result. */ + TkText *textPtr, /* Information about text widget. */ + int report) /* Non-zero means report info to scrollbar if + * it has changed. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - char buffer[TCL_DOUBLE_SPACE * 2 + 1]; double first, last; DLine *dlPtr; - int totalLines, code, count; + int totalPixels, code, count; + Tcl_Obj *listObj; dlPtr = dInfoPtr->dLinePtr; - totalLines = TkBTreeNumLines(textPtr->tree); - first = (double) TkBTreeLineIndex(dlPtr->index.linePtr) - + (double) dlPtr->index.byteIndex - / TkBTreeBytesInLine(dlPtr->index.linePtr); - first /= totalLines; - while (1) { - if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) { + + if (dlPtr == NULL) { + return; + } + + totalPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree, textPtr); + + if (totalPixels == 0) { + first = 0.0; + last = 1.0; + } else { + /* + * Get the pixel count for the first visible pixel of the first + * visible line. If the first visible line is only partially visible, + * then we use 'topPixelOffset' to get the difference. + */ + + count = GetYPixelCount(textPtr, dlPtr); + first = (count + dInfoPtr->topPixelOffset) / (double) totalPixels; + + /* + * Add on the total number of visible pixels to get the count to one + * pixel _past_ the last visible pixel. This is how the 'yview' + * command is documented, and also explains why we are dividing by + * 'totalPixels' and not 'totalPixels-1'. + */ + + while (1) { + int extra; + + count += dlPtr->height; + extra = dlPtr->y + dlPtr->height - dInfoPtr->maxY; + if (extra > 0) { + /* + * This much of the last line is not visible, so don't count + * these pixels. Since we've reached the bottom of the window, + * we break out of the loop. + */ + + count -= extra; + break; + } + if (dlPtr->nextPtr == NULL) { + break; + } + dlPtr = dlPtr->nextPtr; + } + + if (count > totalPixels) { /* - * The last line is only partially visible, so don't - * count its characters in what's visible. + * It can be possible, if we do not update each line's pixelHeight + * cache when we lay out individual DLines that the count + * generated here is more up-to-date than that maintained by the + * BTree. In such a case, the best we can do here is to fix up + * 'count' and continue, which might result in small, temporary + * perturbations to the size of the scrollbar. This is basically + * harmless, but in a perfect world we would not have this + * problem. + * + * For debugging purposes, if anyone wishes to improve the text + * widget further, the following 'panic' can be activated. In + * principle it should be possible to ensure the BTree is always + * at least as up to date as the display, so in the future we + * might be able to leave the 'panic' in permanently when we + * believe we have resolved the cache synchronisation issue. + * + * However, to achieve that goal would, I think, require a fairly + * substantial refactorisation of the code in this file so that + * there is much more obvious and explicit coordination between + * calls to LayoutDLine and updating of each TkTextLine's + * pixelHeight. The complicated bit is that LayoutDLine deals with + * individual display lines, but pixelHeight is for a logical + * line. */ - count = 0; - break; - } - if (dlPtr->nextPtr == NULL) { - count = dlPtr->byteCount; - break; + +#if 0 + Tcl_Panic("Counted more pixels (%d) than expected (%d) total " + "pixels in text widget scroll bar calculation.", count, + totalPixels); +#endif + count = totalPixels; } - dlPtr = dlPtr->nextPtr; + + last = ((double) count)/((double)totalPixels); } - last = ((double) TkBTreeLineIndex(dlPtr->index.linePtr)) - + ((double) (dlPtr->index.byteIndex + count)) - / (TkBTreeBytesInLine(dlPtr->index.linePtr)); - last /= totalLines; + if (!report) { - sprintf(buffer, "%g %g", first, last); - Tcl_SetResult(interp, buffer, TCL_VOLATILE); + listObj = Tcl_NewListObj(0,NULL); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(first)); + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewDoubleObj(last)); + Tcl_SetObjResult(interp, listObj); return; } - if (FP_EQUAL_SCALE(first, dInfoPtr->yScrollFirst, totalLines) && - FP_EQUAL_SCALE(last, dInfoPtr->yScrollLast, totalLines)) { + + if (FP_EQUAL_SCALE(first, dInfoPtr->yScrollFirst, totalPixels) && + FP_EQUAL_SCALE(last, dInfoPtr->yScrollLast, totalPixels)) { return; } + dInfoPtr->yScrollFirst = first; dInfoPtr->yScrollLast = last; - sprintf(buffer, " %g %g", first, last); - code = Tcl_VarEval(interp, textPtr->yScrollCmd, buffer, (char *) NULL); - if (code != TCL_OK) { - Tcl_AddErrorInfo(interp, - "\n (vertical scrolling command executed by text)"); - Tcl_BackgroundError(interp); + if (textPtr->yScrollCmd != NULL) { + char buf1[TCL_DOUBLE_SPACE+1]; + char buf2[TCL_DOUBLE_SPACE+1]; + + buf1[0] = ' '; + buf2[0] = ' '; + Tcl_PrintDouble(NULL, first, buf1+1); + Tcl_PrintDouble(NULL, last, buf2+1); + code = Tcl_VarEval(interp, textPtr->yScrollCmd, buf1, buf2, NULL); + if (code != TCL_OK) { + Tcl_AddErrorInfo(interp, + "\n (vertical scrolling command executed by text)"); + Tcl_BackgroundError(interp); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * AsyncUpdateYScrollbar -- + * + * This function is called to update the vertical scrollbar asychronously + * as the pixel height calculations progress for lines in the widget. + * + * Results: + * None. + * + * Side effects: + * See 'GetYView'. In particular the scrollbar position and size may be + * changed. + * + *---------------------------------------------------------------------- + */ + +static void +AsyncUpdateYScrollbar( + ClientData clientData) /* Information about widget. */ +{ + register TkText *textPtr = (TkText *) clientData; + + textPtr->dInfoPtr->scrollbarTimer = NULL; + + if (!(textPtr->flags & DESTROYED)) { + GetYView(textPtr->interp, textPtr, 1); + } + + if (--textPtr->refCount == 0) { + ckfree((char *) textPtr); } } @@ -4072,14 +6395,13 @@ GetYView(interp, textPtr, report) * * FindDLine -- * - * This procedure is called to find the DLine corresponding to a - * given text index. + * This function is called to find the DLine corresponding to a given + * text index. * * Results: - * The return value is a pointer to the first DLine found in the - * list headed by dlPtr that displays information at or after the - * specified position. If there is no such line in the list then - * NULL is returned. + * The return value is a pointer to the first DLine found in the list + * headed by dlPtr that displays information at or after the specified + * position. If there is no such line in the list then NULL is returned. * * Side effects: * None. @@ -4088,21 +6410,22 @@ GetYView(interp, textPtr, report) */ static DLine * -FindDLine(dlPtr, indexPtr) - register DLine *dlPtr; /* Pointer to first in list of DLines - * to search. */ - TkTextIndex *indexPtr; /* Index of desired character. */ +FindDLine( + register DLine *dlPtr, /* Pointer to first in list of DLines to + * search. */ + CONST TkTextIndex *indexPtr)/* Index of desired character. */ { TkTextLine *linePtr; if (dlPtr == NULL) { return NULL; } - if (TkBTreeLineIndex(indexPtr->linePtr) - < TkBTreeLineIndex(dlPtr->index.linePtr)) { + if (TkBTreeLinesTo(NULL, indexPtr->linePtr) + < TkBTreeLinesTo(NULL, dlPtr->index.linePtr)) { /* * The first display line is already past the desired line. */ + return dlPtr; } @@ -4118,9 +6441,15 @@ FindDLine(dlPtr, indexPtr) return NULL; } } - linePtr = TkBTreeNextLine(linePtr); + + /* + * VMD: some concern here as to whether this logic, or the caller's + * logic will work well with partial peer widgets. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); if (linePtr == NULL) { - panic("FindDLine reached end of text"); + Tcl_Panic("FindDLine reached end of text"); } } if (indexPtr->linePtr != dlPtr->index.linePtr) { @@ -4131,7 +6460,7 @@ FindDLine(dlPtr, indexPtr) * Now get to the right position within the text line. */ - while (indexPtr->byteIndex >= (dlPtr->index.byteIndex + dlPtr->byteCount)) { + while (indexPtr->byteIndex >= (dlPtr->index.byteIndex+dlPtr->byteCount)) { dlPtr = dlPtr->nextPtr; if ((dlPtr == NULL) || (dlPtr->index.linePtr != indexPtr->linePtr)) { break; @@ -4145,12 +6474,12 @@ FindDLine(dlPtr, indexPtr) * * TkTextPixelIndex -- * - * Given an (x,y) coordinate on the screen, find the location of - * the character closest to that location. + * Given an (x,y) coordinate on the screen, find the location of the + * character closest to that location. * * Results: - * The index at *indexPtr is modified to refer to the character - * on the display that is closest to (x,y). + * The index at *indexPtr is modified to refer to the character on the + * display that is closest to (x,y). * * Side effects: * None. @@ -4159,20 +6488,24 @@ FindDLine(dlPtr, indexPtr) */ void -TkTextPixelIndex(textPtr, x, y, indexPtr) - TkText *textPtr; /* Widget record for text widget. */ - int x, y; /* Pixel coordinates of point in widget's +TkTextPixelIndex( + TkText *textPtr, /* Widget record for text widget. */ + int x, int y, /* Pixel coordinates of point in widget's * window. */ - TkTextIndex *indexPtr; /* This index gets filled in with the - * index of the character nearest to (x,y). */ + TkTextIndex *indexPtr, /* This index gets filled in with the index of + * the character nearest to (x,y). */ + int *nearest) /* If non-NULL then gets set to 0 if (x,y) is + * actually over the returned index, and 1 if + * it is just nearby (e.g. if x,y is on the + * border of the widget). */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; - register DLine *dlPtr, *validdlPtr; - register TkTextDispChunk *chunkPtr; + register DLine *dlPtr, *validDlPtr; + int nearby = 0; /* - * Make sure that all of the layout information about what's - * displayed where on the screen is up-to-date. + * Make sure that all of the layout information about what's displayed + * where on the screen is up-to-date. */ if (dInfoPtr->flags & DINFO_OUT_OF_DATE) { @@ -4180,72 +6513,143 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) } /* - * If the coordinates are above the top of the window, then adjust - * them to refer to the upper-right corner of the window. If they're - * off to one side or the other, then adjust to the closest side. + * If the coordinates are above the top of the window, then adjust them to + * refer to the upper-right corner of the window. If they're off to one + * side or the other, then adjust to the closest side. */ if (y < dInfoPtr->y) { y = dInfoPtr->y; x = dInfoPtr->x; + nearby = 1; } if (x >= dInfoPtr->maxX) { x = dInfoPtr->maxX - 1; + nearby = 1; } if (x < dInfoPtr->x) { x = dInfoPtr->x; + nearby = 1; } /* * Find the display line containing the desired y-coordinate. */ - for (dlPtr = validdlPtr = dInfoPtr->dLinePtr; y >= (dlPtr->y + dlPtr->height); - dlPtr = dlPtr->nextPtr) { - if (dlPtr->chunkPtr !=NULL) validdlPtr = dlPtr; - if (dlPtr->nextPtr == NULL) { - /* - * Y-coordinate is off the bottom of the displayed text. - * Use the last character on the last line. - */ + if (dInfoPtr->dLinePtr == NULL) { + if (nearest != NULL) { + *nearest = 1; + } + *indexPtr = textPtr->topIndex; + return; + } else { + for (dlPtr = validDlPtr = dInfoPtr->dLinePtr; + y >= (dlPtr->y + dlPtr->height); + dlPtr = dlPtr->nextPtr) { + if (dlPtr->chunkPtr != NULL) { + validDlPtr = dlPtr; + } + if (dlPtr->nextPtr == NULL) { + /* + * Y-coordinate is off the bottom of the displayed text. Use + * the last character on the last line. + */ - x = dInfoPtr->maxX - 1; - break; + x = dInfoPtr->maxX - 1; + nearby = 1; + break; + } } + if (dlPtr->chunkPtr == NULL) dlPtr = validDlPtr; } - if (dlPtr->chunkPtr == NULL) dlPtr = validdlPtr; - *indexPtr = dlPtr->index; + if (nearest != NULL) { + *nearest = nearby; + } + + DlineIndexOfX(textPtr, dlPtr, x, indexPtr); +} + +/* + *---------------------------------------------------------------------- + * + * DlineIndexOfX -- + * + * Given an x coordinate in a display line, find the index of the + * character closest to that location. + * + * This is effectively the opposite of DlineXOfIndex. + * + * Results: + * The index at *indexPtr is modified to refer to the character on the + * display line that is closest to x. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +DlineIndexOfX( + TkText *textPtr, /* Widget record for text widget. */ + DLine *dlPtr, /* Display information for this display + * line. */ + int x, /* Pixel x coordinate of point in widget's + * window. */ + TkTextIndex *indexPtr) /* This index gets filled in with the index of + * the character nearest to x. */ +{ + TextDInfo *dInfoPtr = textPtr->dInfoPtr; + register TkTextDispChunk *chunkPtr; /* - * If it is still empty, we have nothing to access. [Bug 1442102] + * Scan through the line's chunks to find the one that contains the + * desired x-coordinate. Before doing this, translate the x-coordinate + * from the coordinate system of the window to the coordinate system of + * the line (to take account of x-scrolling). */ - if (dlPtr->chunkPtr == NULL) { + *indexPtr = dlPtr->index; + x = x - dInfoPtr->x + dInfoPtr->curXPixelOffset; + chunkPtr = dlPtr->chunkPtr; + + if (chunkPtr == NULL || x == 0) { + /* + * This may occur if everything is elided, or if we're simply already + * at the beginning of the line. + */ + return; } - /* - * Scan through the line's chunks to find the one that contains - * the desired x-coordinate. Before doing this, translate the - * x-coordinate from the coordinate system of the window to the - * coordinate system of the line (to take account of x-scrolling). - */ + while (x >= (chunkPtr->x + chunkPtr->width)) { + /* + * Note that this forward then backward movement of the index can be + * problematic at the end of the buffer (we can't move forward, and + * then when we move backward, we do, leading to the wrong position). + * Hence when x == 0 we take special action above. + */ - x = x - dInfoPtr->x + dInfoPtr->curPixelOffset; - for (chunkPtr = dlPtr->chunkPtr; x >= (chunkPtr->x + chunkPtr->width); - indexPtr->byteIndex += chunkPtr->numBytes, - chunkPtr = chunkPtr->nextPtr) { + if (TkTextIndexForwBytes(NULL,indexPtr,chunkPtr->numBytes,indexPtr)) { + /* + * We've reached the end of the text. + */ + + return; + } if (chunkPtr->nextPtr == NULL) { - indexPtr->byteIndex += chunkPtr->numBytes; - TkTextIndexBackChars(indexPtr, 1, indexPtr); + TkTextIndexBackChars(NULL, indexPtr, 1, indexPtr, COUNT_INDICES); return; } + chunkPtr = chunkPtr->nextPtr; } /* - * If the chunk has more than one byte in it, ask it which - * character is at the desired location. + * If the chunk has more than one byte in it, ask it which character is at + * the desired location. In this case we can manipulate + * 'indexPtr->byteIndex' directly, because we know we're staying inside a + * single logical line. */ if (chunkPtr->numBytes > 1) { @@ -4256,17 +6660,119 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) /* *---------------------------------------------------------------------- * - * TkTextCharBbox -- + * TkTextIndexOfX -- * - * Given an index, find the bounding box of the screen area - * occupied by that character. + * Given a logical x coordinate (i.e. distance in pixels from the + * beginning of the display line, not taking into account any information + * about the window, scrolling etc.) on the display line starting with + * the given index, adjust that index to refer to the object under the x + * coordinate. * * Results: - * Zero is returned if the character is on the screen. -1 - * means the character isn't on the screen. If the return value - * is 0, then the bounding box of the part of the character that's - * visible on the screen is returned to *xPtr, *yPtr, *widthPtr, - * and *heightPtr. + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkTextIndexOfX( + TkText *textPtr, /* Widget record for text widget. */ + int x, /* The x coordinate for which we want the + * index. */ + TkTextIndex *indexPtr) /* Index of display line start, which will be + * adjusted to the index under the given x + * coordinate. */ +{ + DLine *dlPtr = LayoutDLine(textPtr, indexPtr); + DlineIndexOfX(textPtr, dlPtr, x + textPtr->dInfoPtr->x + - textPtr->dInfoPtr->curXPixelOffset, indexPtr); + FreeDLines(textPtr, dlPtr, NULL, DLINE_FREE_TEMP); +} + +/* + *---------------------------------------------------------------------- + * + * DlineXOfIndex -- + * + * Given a relative byte index on a given display line (i.e. the number + * of byte indices from the beginning of the given display line), find + * the x coordinate of that index within the abstract display line, + * without adjusting for the x-scroll state of the line. + * + * This is effectively the opposite of DlineIndexOfX. + * + * NB. The 'byteIndex' is relative to the display line, NOT the logical + * line. + * + * Results: + * The x coordinate. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +DlineXOfIndex( + TkText *textPtr, /* Widget record for text widget. */ + DLine *dlPtr, /* Display information for this display + * line. */ + int byteIndex) /* The byte index for which we want the + * coordinate. */ +{ + register TkTextDispChunk *chunkPtr = dlPtr->chunkPtr; + int x; + + if (byteIndex == 0 || chunkPtr == NULL) { + return 0; + } + + /* + * Scan through the line's chunks to find the one that contains the + * desired byte index. + */ + + chunkPtr = dlPtr->chunkPtr; + while (byteIndex > 0) { + if (byteIndex < chunkPtr->numBytes) { + int y, width, height; + + (*chunkPtr->bboxProc)(textPtr, chunkPtr, byteIndex, + dlPtr->y + dlPtr->spaceAbove, + dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, + dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width, + &height); + break; + } else { + byteIndex -= chunkPtr->numBytes; + } + if (chunkPtr->nextPtr == NULL || byteIndex == 0) { + x = chunkPtr->x + chunkPtr->width; + break; + } + chunkPtr = chunkPtr->nextPtr; + } + + return x; +} + +/* + *---------------------------------------------------------------------- + * + * TkTextIndexBbox -- + * + * Given an index, find the bounding box of the screen area occupied by + * the entity (character, window, image) at that index. + * + * Results: + * Zero is returned if the index is on the screen. -1 means the index is + * not on the screen. If the return value is 0, then the bounding box of + * the part of the index that's visible on the screen is returned to + * *xPtr, *yPtr, *widthPtr, and *heightPtr. * * Side effects: * None. @@ -4275,13 +6781,17 @@ TkTextPixelIndex(textPtr, x, y, indexPtr) */ int -TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) - TkText *textPtr; /* Widget record for text widget. */ - TkTextIndex *indexPtr; /* Index of character whose bounding - * box is desired. */ - int *xPtr, *yPtr; /* Filled with character's upper-left +TkTextIndexBbox( + TkText *textPtr, /* Widget record for text widget. */ + CONST TkTextIndex *indexPtr,/* Index whose bounding box is desired. */ + int *xPtr, int *yPtr, /* Filled with index's upper-left * coordinate. */ - int *widthPtr, *heightPtr; /* Filled in with character's dimensions. */ + int *widthPtr, int *heightPtr, + /* Filled in with index's dimensions. */ + int *charWidthPtr) /* If the 'index' is at the end of a display + * line and therefore takes up a very large + * width, this is used to return the smaller + * width actually desired by the index. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; DLine *dlPtr; @@ -4306,8 +6816,7 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) } /* - * Find the chunk within the line that contains the desired - * index. + * Find the chunk within the line that contains the desired index. */ byteIndex = indexPtr->byteIndex - dlPtr->index.byteIndex; @@ -4322,31 +6831,52 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) } /* - * Call a chunk-specific procedure to find the horizontal range of - * the character within the chunk, then fill in the vertical range. - * The x-coordinate returned by bboxProc is a coordinate within a - * line, not a coordinate on the screen. Translate it to reflect - * horizontal scrolling. + * Call a chunk-specific function to find the horizontal range of the + * character within the chunk, then fill in the vertical range. The + * x-coordinate returned by bboxProc is a coordinate within a line, not a + * coordinate on the screen. Translate it to reflect horizontal scrolling. */ - (*chunkPtr->bboxProc)(chunkPtr, byteIndex, dlPtr->y + dlPtr->spaceAbove, + (*chunkPtr->bboxProc)(textPtr, chunkPtr, byteIndex, + dlPtr->y + dlPtr->spaceAbove, dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow, dlPtr->baseline - dlPtr->spaceAbove, xPtr, yPtr, widthPtr, heightPtr); - *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curPixelOffset; - if ((byteIndex == (chunkPtr->numBytes - 1)) && (chunkPtr->nextPtr == NULL)) { + *xPtr = *xPtr + dInfoPtr->x - dInfoPtr->curXPixelOffset; + if ((byteIndex == chunkPtr->numBytes-1) && (chunkPtr->nextPtr == NULL)) { /* - * Last character in display line. Give it all the space up to - * the line. + * Last character in display line. Give it all the space up to the + * line. */ + if (charWidthPtr != NULL) { + *charWidthPtr = dInfoPtr->maxX - *xPtr; + if (*charWidthPtr > textPtr->charWidth) { + *charWidthPtr = textPtr->charWidth; + } + } if (*xPtr > dInfoPtr->maxX) { *xPtr = dInfoPtr->maxX; } *widthPtr = dInfoPtr->maxX - *xPtr; + } else { + if (charWidthPtr != NULL) { + *charWidthPtr = *widthPtr; + } } - if ((*xPtr + *widthPtr) <= dInfoPtr->x) { - return -1; + if (*widthPtr == 0) { + /* + * With zero width (e.g. elided text) we just need to make sure it is + * onscreen, where the '=' case here is ok. + */ + + if (*xPtr < dInfoPtr->x) { + return -1; + } + } else { + if ((*xPtr + *widthPtr) <= dInfoPtr->x) { + return -1; + } } if ((*xPtr + *widthPtr) > dInfoPtr->maxX) { *widthPtr = dInfoPtr->maxX - *xPtr; @@ -4368,14 +6898,14 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) * * TkTextDLineInfo -- * - * Given an index, return information about the display line - * containing that character. + * Given an index, return information about the display line containing + * that character. * * Results: - * Zero is returned if the character is on the screen. -1 - * means the character isn't on the screen. If the return value - * is 0, then information is returned in the variables pointed - * to by xPtr, yPtr, widthPtr, heightPtr, and basePtr. + * Zero is returned if the character is on the screen. -1 means the + * character isn't on the screen. If the return value is 0, then + * information is returned in the variables pointed to by xPtr, yPtr, + * widthPtr, heightPtr, and basePtr. * * Side effects: * None. @@ -4384,14 +6914,15 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr) */ int -TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) - TkText *textPtr; /* Widget record for text widget. */ - TkTextIndex *indexPtr; /* Index of character whose bounding - * box is desired. */ - int *xPtr, *yPtr; /* Filled with line's upper-left +TkTextDLineInfo( + TkText *textPtr, /* Widget record for text widget. */ + CONST TkTextIndex *indexPtr,/* Index of character whose bounding box is + * desired. */ + int *xPtr, int *yPtr, /* Filled with line's upper-left * coordinate. */ - int *widthPtr, *heightPtr; /* Filled in with line's dimensions. */ - int *basePtr; /* Filled in with the baseline position, + int *widthPtr, int *heightPtr, + /* Filled in with line's dimensions. */ + int *basePtr) /* Filled in with the baseline position, * measured as an offset down from *yPtr. */ { TextDInfo *dInfoPtr = textPtr->dInfoPtr; @@ -4416,7 +6947,7 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) } dlx = (dlPtr->chunkPtr != NULL? dlPtr->chunkPtr->x: 0); - *xPtr = dInfoPtr->x - dInfoPtr->curPixelOffset + dlx; + *xPtr = dInfoPtr->x - dInfoPtr->curXPixelOffset + dlx; *widthPtr = dlPtr->length - dlx; *yPtr = dlPtr->y; if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) { @@ -4428,37 +6959,43 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr) return 0; } +/* + * Get bounding-box information about an elided chunk. + */ + static void -ElideBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, - widthPtr, heightPtr) - TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */ - int index; /* Index of desired character within - * the chunk. */ - int y; /* Topmost pixel in area allocated - * for this line. */ - int lineHeight; /* Height of line, in pixels. */ - int baseline; /* Location of line's baseline, in - * pixels measured down from y. */ - int *xPtr, *yPtr; /* Gets filled in with coords of - * character's upper-left pixel. - * X-coord is in same coordinate - * system as chunkPtr->x. */ - int *widthPtr; /* Gets filled in with width of - * character, in pixels. */ - int *heightPtr; /* Gets filled in with height of - * character, in pixels. */ +ElideBboxProc( + TkText *textPtr, + TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */ + int index, /* Index of desired character within the + * chunk. */ + int y, /* Topmost pixel in area allocated for this + * line. */ + int lineHeight, /* Height of line, in pixels. */ + int baseline, /* Location of line's baseline, in pixels + * measured down from y. */ + int *xPtr, int *yPtr, /* Gets filled in with coords of character's + * upper-left pixel. X-coord is in same + * coordinate system as chunkPtr->x. */ + int *widthPtr, /* Gets filled in with width of character, in + * pixels. */ + int *heightPtr) /* Gets filled in with height of character, in + * pixels. */ { *xPtr = chunkPtr->x; *yPtr = y; *widthPtr = *heightPtr = 0; } - + +/* + * Measure an elided chunk. + */ static int -ElideMeasureProc(chunkPtr, x) - TkTextDispChunk *chunkPtr; /* Chunk containing desired coord. */ - int x; /* X-coordinate, in same coordinate - * system as chunkPtr->x. */ +ElideMeasureProc( + TkTextDispChunk *chunkPtr, /* Chunk containing desired coord. */ + int x) /* X-coordinate, in same coordinate system as + * chunkPtr->x. */ { return 0 /*chunkPtr->numBytes - 1*/; } @@ -4468,45 +7005,43 @@ ElideMeasureProc(chunkPtr, x) * * TkTextCharLayoutProc -- * - * This procedure is the "layoutProc" for character segments. + * This function is the "layoutProc" for character segments. * * Results: - * If there is something to display for the chunk then a - * non-zero value is returned and the fields of chunkPtr - * will be filled in (see the declaration of TkTextDispChunk - * in tkText.h for details). If zero is returned it means - * that no characters from this chunk fit in the window. - * If -1 is returned it means that this segment just doesn't - * need to be displayed (never happens for text). + * If there is something to display for the chunk then a non-zero value + * is returned and the fields of chunkPtr will be filled in (see the + * declaration of TkTextDispChunk in tkText.h for details). If zero is + * returned it means that no characters from this chunk fit in the + * window. If -1 is returned it means that this segment just doesn't need + * to be displayed (never happens for text). * * Side effects: - * Memory is allocated to hold additional information about - * the chunk. + * Memory is allocated to hold additional information about the chunk. * *-------------------------------------------------------------- */ int -TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, - noCharsYet, wrapMode, chunkPtr) - TkText *textPtr; /* Text widget being layed out. */ - TkTextIndex *indexPtr; /* Index of first character to lay out +TkTextCharLayoutProc( + TkText *textPtr, /* Text widget being layed out. */ + TkTextIndex *indexPtr, /* Index of first character to lay out * (corresponds to segPtr and offset). */ - TkTextSegment *segPtr; /* Segment being layed out. */ - int byteOffset; /* Byte offset within segment of first + TkTextSegment *segPtr, /* Segment being layed out. */ + int byteOffset, /* Byte offset within segment of first * character to consider. */ - int maxX; /* Chunk must not occupy pixels at this + int maxX, /* Chunk must not occupy pixels at this * position or higher. */ - int maxBytes; /* Chunk must not include more than this - * many characters. */ - int noCharsYet; /* Non-zero means no characters have been + int maxBytes, /* Chunk must not include more than this many + * characters. */ + int noCharsYet, /* Non-zero means no characters have been * assigned to this display line yet. */ - TkWrapMode wrapMode; /* How to handle line wrapping: TEXT_WRAPMODE_CHAR, - * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */ - register TkTextDispChunk *chunkPtr; - /* Structure to fill in with information - * about this chunk. The x field has already - * been set by the caller. */ + TkWrapMode wrapMode, /* How to handle line wrapping: + * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or + * TEXT_WRAPMODE_WORD. */ + register TkTextDispChunk *chunkPtr) + /* Structure to fill in with information about + * this chunk. The x field has already been + * set by the caller. */ { Tk_Font tkfont; int nextX, bytesThatFit, count; @@ -4514,36 +7049,80 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, char *p; TkTextSegment *nextPtr; Tk_FontMetrics fm; +#if TK_LAYOUT_WITH_BASE_CHUNKS + const char *line; + int lineOffset; + BaseCharInfo *bciPtr; + Tcl_DString *baseString; +#endif /* - * Figure out how many characters will fit in the space we've got. - * Include the next character, even though it won't fit completely, - * if any of the following is true: - * (a) the chunk contains no characters and the display line contains - * no characters yet (i.e. the line isn't wide enough to hold - * even a single character). - * (b) at least one pixel of the character is visible, we haven't - * already exceeded the character limit, and the next character - * is a white space character. + * Figure out how many characters will fit in the space we've got. Include + * the next character, even though it won't fit completely, if any of the + * following is true: + * (a) the chunk contains no characters and the display line contains no + * characters yet (i.e. the line isn't wide enough to hold even a + * single character). + * (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. */ p = segPtr->body.chars + byteOffset; tkfont = chunkPtr->stylePtr->sValuePtr->tkfont; - bytesThatFit = MeasureChars(tkfont, p, maxBytes, chunkPtr->x, maxX, 0, - &nextX); + +#if TK_LAYOUT_WITH_BASE_CHUNKS + if (baseCharChunkPtr == NULL) { + baseCharChunkPtr = chunkPtr; + bciPtr = (BaseCharInfo *) ckalloc(sizeof(BaseCharInfo)); + baseString = &bciPtr->baseChars; + Tcl_DStringInit(baseString); + bciPtr->width = 0; + + ciPtr = &bciPtr->ci; + } else { + bciPtr = (BaseCharInfo *) baseCharChunkPtr->clientData; + ciPtr = (CharInfo *) ckalloc(sizeof(CharInfo)); + baseString = &bciPtr->baseChars; + } + + lineOffset = Tcl_DStringLength(baseString); + line = Tcl_DStringAppend(baseString,p,maxBytes); + + chunkPtr->clientData = (ClientData) ciPtr; + ciPtr->baseChunkPtr = baseCharChunkPtr; + ciPtr->baseOffset = lineOffset; + ciPtr->chars = NULL; + ciPtr->numBytes = 0; + + bytesThatFit = CharChunkMeasureChars(chunkPtr, line, + lineOffset + maxBytes, lineOffset, -1, chunkPtr->x, maxX, + TK_ISOLATE_END, &nextX); +#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */ + bytesThatFit = CharChunkMeasureChars(chunkPtr, p, maxBytes, 0, -1, + chunkPtr->x, maxX, TK_ISOLATE_END, &nextX); +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + if (bytesThatFit < maxBytes) { if ((bytesThatFit == 0) && noCharsYet) { Tcl_UniChar ch; - - bytesThatFit = MeasureChars(tkfont, p, Tcl_UtfToUniChar(p, &ch), + int chLen = Tcl_UtfToUniChar(p, &ch); + +#if TK_LAYOUT_WITH_BASE_CHUNKS + bytesThatFit = CharChunkMeasureChars(chunkPtr, line, + lineOffset+chLen, lineOffset, -1, chunkPtr->x, -1, 0, + &nextX); +#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */ + bytesThatFit = CharChunkMeasureChars(chunkPtr, p, chLen, 0, -1, chunkPtr->x, -1, 0, &nextX); +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ } if ((nextX < maxX) && ((p[bytesThatFit] == ' ') || (p[bytesThatFit] == '\t'))) { /* - * Space characters are funny, in that they are considered - * to fit if there is at least one pixel of space left on the - * line. Just give the space character whatever space is left. + * Space characters are funny, in that they are considered to fit + * if there is at least one pixel of space left on the line. Just + * give the space character whatever space is left. */ nextX = maxX; @@ -4558,16 +7137,26 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, bytesThatFit++; } if (bytesThatFit == 0) { +#if TK_LAYOUT_WITH_BASE_CHUNKS + chunkPtr->clientData = NULL; + if (chunkPtr == baseCharChunkPtr) { + baseCharChunkPtr = NULL; + Tcl_DStringFree(baseString); + } else { + Tcl_DStringSetLength(baseString,lineOffset); + } + ckfree((char *) ciPtr); +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ return 0; } } - + Tk_GetFontMetrics(tkfont, &fm); /* - * Fill in the chunk structure and allocate and initialize a - * CharInfo structure. If the last character is a newline - * then don't bother to display it. + * Fill in the chunk structure and allocate and initialize a CharInfo + * structure. If the last character is a newline then don't bother to + * display it. */ chunkPtr->displayProc = CharDisplayProc; @@ -4580,20 +7169,41 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, chunkPtr->minHeight = 0; chunkPtr->width = nextX - chunkPtr->x; chunkPtr->breakIndex = -1; - ciPtr = (CharInfo *) ckalloc((unsigned) - (sizeof(CharInfo) - 3 + bytesThatFit)); + +#if !TK_LAYOUT_WITH_BASE_CHUNKS + ciPtr = (CharInfo *) + ckalloc((unsigned) bytesThatFit + Tk_Offset(CharInfo, chars) + 1); chunkPtr->clientData = (ClientData) ciPtr; + memcpy(ciPtr->chars, p, (unsigned) bytesThatFit); +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + ciPtr->numBytes = bytesThatFit; - memcpy(ciPtr->chars, p, (size_t) bytesThatFit); if (p[bytesThatFit - 1] == '\n') { ciPtr->numBytes--; } +#if TK_LAYOUT_WITH_BASE_CHUNKS /* - * Compute a break location. If we're in word wrap mode, a - * break can occur after any space character, or at the end of - * the chunk if the next segment (ignoring those with zero size) - * is not a character segment. + * Final update for the current base chunk data. + */ + + Tcl_DStringSetLength(baseString,lineOffset+ciPtr->numBytes); + bciPtr->width = nextX - baseCharChunkPtr->x; + + /* + * Finalize the base chunk if this chunk ends in a tab, which definitly + * breaks the context and needs to be handled on a higher level. + */ + + if (ciPtr->numBytes > 0 && p[ciPtr->numBytes - 1] == '\t') { + FinalizeBaseChunk(chunkPtr); + } +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + + /* + * Compute a break location. If we're in word wrap mode, a break can occur + * after any space character, or at the end of the chunk if the next + * segment (ignoring those with zero size) is not a character segment. */ if (wrapMode != TEXT_WRAPMODE_WORD) { @@ -4601,7 +7211,7 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, } else { for (count = bytesThatFit, p += bytesThatFit - 1; count > 0; count--, p--) { - if (isspace(UCHAR(*p))) { + if (UCHAR(*p) < 0x80 && isspace(UCHAR(*p))) { chunkPtr->breakIndex = count; break; } @@ -4622,12 +7232,112 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, } /* + *--------------------------------------------------------------------------- + * + * CharChunkMeasureChars -- + * + * Determine the number of characters from a char chunk that will fit in + * the given horizontal span. + * + * This is the same as MeasureChars (which see), but in the context of a + * char chunk, i.e. on a higher level of abstraction. Use this function + * whereever possible instead of plain MeasureChars, so that the right + * context is used automatically. + * + * Results: + * The return value is the number of bytes from the range of start to end + * in source that fit in the span given by startX and maxX. *nextXPtr is + * filled in with the x-coordinate at which the first character that + * didn't fit would be drawn, if it were to be drawn. + * + * Side effects: + * None. + *-------------------------------------------------------------- + */ + +static int +CharChunkMeasureChars( + TkTextDispChunk *chunkPtr, /* Chunk from which to measure. */ + const char *chars, /* Chars to use, instead of the chunk's own. + * Used by the layoutproc during chunk setup. + * All other callers use NULL. Not + * NUL-terminated. */ + int charsLen, /* Length of the "chars" parameter. */ + int start, int end, /* The range of chars to measure inside the + * chunk (or inside the additional chars). */ + int startX, /* Starting x coordinate where the measured + * span will begin. */ + int maxX, /* Maximum pixel width of the span. May be -1 + * for unlimited. */ + int flags, /* Flags to pass to MeasureChars. */ + int *nextXPtr) /* The function puts the newly calculated + * right border x-position of the span + * here. */ +{ + Tk_Font tkfont = chunkPtr->stylePtr->sValuePtr->tkfont; + CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData; + +#if !TK_LAYOUT_WITH_BASE_CHUNKS + if (chars == NULL) { + chars = ciPtr->chars; + charsLen = ciPtr->numBytes; + } + if (end == -1) { + end = charsLen; + } + + return MeasureChars(tkfont, chars, charsLen, start, end-start, + startX, maxX, flags, nextXPtr); +#else + { + int xDisplacement; + int fit, bstart = start, bend = end; + + if (chars == NULL) { + Tcl_DString *baseChars = &((BaseCharInfo *) + ciPtr->baseChunkPtr->clientData)->baseChars; + + chars = Tcl_DStringValue(baseChars); + charsLen = Tcl_DStringLength(baseChars); + bstart += ciPtr->baseOffset; + if (bend == -1) { + bend = ciPtr->baseOffset + ciPtr->numBytes; + } else { + bend += ciPtr->baseOffset; + } + } else if (bend == -1) { + bend = charsLen; + } + + if (bstart == ciPtr->baseOffset) { + xDisplacement = startX - chunkPtr->x; + } else { + int widthUntilStart = 0; + + MeasureChars(tkfont, chars, charsLen, 0, bstart, + 0, -1, 0, &widthUntilStart); + xDisplacement = startX - widthUntilStart - chunkPtr->x; + } + + fit = MeasureChars(tkfont, chars, charsLen, 0, bend, + ciPtr->baseChunkPtr->x + xDisplacement, maxX, flags, nextXPtr); + + if (fit < bstart) { + return 0; + } else { + return fit - bstart; + } + } +#endif +} + +/* *-------------------------------------------------------------- * * CharDisplayProc -- * - * This procedure is called to display a character chunk on - * the screen or in an off-screen pixmap. + * This function is called to display a character chunk on the screen or + * in an off-screen pixmap. * * Results: * None. @@ -4639,26 +7349,29 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes, */ static void -CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) - TkTextDispChunk *chunkPtr; /* Chunk that is to be drawn. */ - int x; /* X-position in dst at which to - * draw this chunk (may differ from - * the x-position in the chunk because - * of scrolling). */ - int y; /* Y-position at which to draw this - * chunk in dst. */ - int height; /* Total height of line. */ - int baseline; /* Offset of baseline from y. */ - Display *display; /* Display to use for drawing. */ - Drawable dst; /* Pixmap or window in which to draw - * chunk. */ - int screenY; /* Y-coordinate in text window that - * corresponds to y. */ +CharDisplayProc( + TkText *textPtr, + TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */ + int x, /* X-position in dst at which to draw this + * chunk (may differ from the x-position in + * the chunk because of scrolling). */ + int y, /* Y-position at which to draw this chunk in + * dst. */ + int height, /* Total height of line. */ + int baseline, /* Offset of baseline from y. */ + Display *display, /* Display to use for drawing. */ + Drawable dst, /* Pixmap or window in which to draw chunk. */ + int screenY) /* Y-coordinate in text window that + * corresponds to y. */ { CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData; + const char *string; TextStyle *stylePtr; StyleValues *sValuePtr; - int offsetBytes, offsetX; + int numBytes, offsetBytes, offsetX; +#if TK_DRAW_IN_CONTEXT + BaseCharInfo *bciPtr; +#endif /* TK_DRAW_IN_CONTEXT */ if ((x + chunkPtr->width) <= 0) { /* @@ -4668,31 +7381,90 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) return; } +#if TK_DRAW_IN_CONTEXT + bciPtr = (BaseCharInfo *) ciPtr->baseChunkPtr->clientData; + numBytes = Tcl_DStringLength(&bciPtr->baseChars); + string = Tcl_DStringValue(&bciPtr->baseChars); + +#elif TK_LAYOUT_WITH_BASE_CHUNKS + if (ciPtr->baseChunkPtr != chunkPtr) { + /* + * Without context drawing only base chunks display their foreground. + */ + + return; + } + + numBytes = Tcl_DStringLength(&((BaseCharInfo *) ciPtr)->baseChars); + string = ciPtr->chars; + +#else /* !TK_LAYOUT_WITH_BASE_CHUNKS */ + numBytes = ciPtr->numBytes; + string = ciPtr->chars; +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + stylePtr = chunkPtr->stylePtr; sValuePtr = stylePtr->sValuePtr; /* - * If the text sticks out way to the left of the window, skip - * over the characters that aren't in the visible part of the - * window. This is essential if x is very negative (such as - * less than 32K); otherwise overflow problems will occur - * in servers that use 16-bit arithmetic, like X. + * If the text sticks out way to the left of the window, skip over the + * characters that aren't in the visible part of the window. This is + * essential if x is very negative (such as less than 32K); otherwise + * overflow problems will occur in servers that use 16-bit arithmetic, + * like X. */ offsetX = x; offsetBytes = 0; if (x < 0) { - offsetBytes = MeasureChars(sValuePtr->tkfont, ciPtr->chars, - ciPtr->numBytes, x, 0, x - chunkPtr->x, &offsetX); + offsetBytes = CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1, + x, 0, 0, &offsetX); } /* * Draw the text, underline, and overstrike for this chunk. */ - if (!sValuePtr->elide && (ciPtr->numBytes > offsetBytes) && (stylePtr->fgGC != None)) { - int numBytes = ciPtr->numBytes - offsetBytes; - char *string = ciPtr->chars + offsetBytes; + if (!sValuePtr->elide && (numBytes > offsetBytes) + && (stylePtr->fgGC != None)) { +#if TK_DRAW_IN_CONTEXT + int start = ciPtr->baseOffset + offsetBytes; + int len = ciPtr->numBytes - offsetBytes; + int xDisplacement = x - chunkPtr->x; + + if ((len > 0) && (string[start + len - 1] == '\t')) { + len--; + } + if (len <= 0) { + return; + } + + TkpDrawCharsInContext(display, dst, stylePtr->fgGC, sValuePtr->tkfont, + string, numBytes, start, len, + ciPtr->baseChunkPtr->x + xDisplacement, + y + baseline - sValuePtr->offset); + + if (sValuePtr->underline) { + TkUnderlineCharsInContext(display, dst, stylePtr->fgGC, + sValuePtr->tkfont, string, numBytes, + ciPtr->baseChunkPtr->x + xDisplacement, + y + baseline - sValuePtr->offset, + start, start+len); + } + if (sValuePtr->overstrike) { + Tk_FontMetrics fm; + + Tk_GetFontMetrics(sValuePtr->tkfont, &fm); + TkUnderlineCharsInContext(display, dst, stylePtr->fgGC, + sValuePtr->tkfont, string, numBytes, + ciPtr->baseChunkPtr->x + xDisplacement, + y + baseline - sValuePtr->offset + - fm.descent - (fm.ascent * 3) / 10, + start, start+len); + } +#else /* !TK_DRAW_IN_CONTEXT */ + string += offsetBytes; + numBytes -= offsetBytes; if ((numBytes > 0) && (string[numBytes - 1] == '\t')) { numBytes--; @@ -4701,20 +7473,22 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) numBytes, offsetX, y + baseline - sValuePtr->offset); if (sValuePtr->underline) { Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, - ciPtr->chars + offsetBytes, offsetX, - y + baseline - sValuePtr->offset, 0, numBytes); + string, offsetX, + y + baseline - sValuePtr->offset, + 0, numBytes); } if (sValuePtr->overstrike) { Tk_FontMetrics fm; - + Tk_GetFontMetrics(sValuePtr->tkfont, &fm); Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, - ciPtr->chars + offsetBytes, offsetX, + string, offsetX, y + baseline - sValuePtr->offset - fm.descent - (fm.ascent * 3) / 10, 0, numBytes); } +#endif /* TK_DRAW_IN_CONTEXT */ } } @@ -4723,9 +7497,9 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) * * CharUndisplayProc -- * - * This procedure is called when a character chunk is no - * longer going to be displayed. It frees up resources - * that were allocated to display the chunk. + * This function is called when a character chunk is no longer going to + * be displayed. It frees up resources that were allocated to display the + * chunk. * * Results: * None. @@ -4737,14 +7511,40 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) */ static void -CharUndisplayProc(textPtr, chunkPtr) - TkText *textPtr; /* Overall information about text - * widget. */ - TkTextDispChunk *chunkPtr; /* Chunk that is about to be freed. */ +CharUndisplayProc( + TkText *textPtr, /* Overall information about text widget. */ + TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */ { CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData; - ckfree((char *) ciPtr); + if (ciPtr) { +#if TK_LAYOUT_WITH_BASE_CHUNKS + if (chunkPtr == ciPtr->baseChunkPtr) { + /* + * Basechunks are undisplayed first, when DLines are freed or + * partially freed, so this makes sure we don't access their data + * any more. + */ + + FreeBaseChunk(chunkPtr); + } else if (ciPtr->baseChunkPtr != NULL) { + /* + * When other char chunks are undisplayed, drop their characters + * from the base chunk. This usually happens, when they are last + * in a line and need to be re-layed out. + */ + + RemoveFromBaseChunk(chunkPtr); + } + + ciPtr->baseChunkPtr = NULL; + ciPtr->chars = NULL; + ciPtr->numBytes = 0; +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + + ckfree((char *) ciPtr); + chunkPtr->clientData = NULL; + } } /* @@ -4752,12 +7552,12 @@ CharUndisplayProc(textPtr, chunkPtr) * * CharMeasureProc -- * - * This procedure is called to determine which character in - * a character chunk lies over a given x-coordinate. + * This function is called to determine which character in a character + * chunk lies over a given x-coordinate. * * Results: - * The return value is the index *within the chunk* of the - * character that covers the position given by "x". + * The return value is the index *within the chunk* of the character that + * covers the position given by "x". * * Side effects: * None. @@ -4766,17 +7566,15 @@ CharUndisplayProc(textPtr, chunkPtr) */ static int -CharMeasureProc(chunkPtr, x) - TkTextDispChunk *chunkPtr; /* Chunk containing desired coord. */ - int x; /* X-coordinate, in same coordinate - * system as chunkPtr->x. */ +CharMeasureProc( + TkTextDispChunk *chunkPtr, /* Chunk containing desired coord. */ + int x) /* X-coordinate, in same coordinate system as + * chunkPtr->x. */ { - CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData; int endX; - return MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars, - chunkPtr->numBytes - 1, chunkPtr->x, x, 0, &endX); - /* CHAR OFFSET */ + return CharChunkMeasureChars(chunkPtr, NULL, 0, 0, chunkPtr->numBytes-1, + chunkPtr->x, x, 0, &endX); /* CHAR OFFSET */ } /* @@ -4784,17 +7582,16 @@ CharMeasureProc(chunkPtr, x) * * CharBboxProc -- * - * This procedure is called to compute the bounding box of - * the area occupied by a single character. + * This function is called to compute the bounding box of the area + * occupied by a single character. * * Results: - * There is no return value. *xPtr and *yPtr are filled in - * with the coordinates of the upper left corner of the - * character, and *widthPtr and *heightPtr are filled in with - * the dimensions of the character in pixels. Note: not all - * of the returned bbox is necessarily visible on the screen - * (the rightmost part might be off-screen to the right, - * and the bottommost part might be off-screen to the bottom). + * There is no return value. *xPtr and *yPtr are filled in with the + * coordinates of the upper left corner of the character, and *widthPtr + * and *heightPtr are filled in with the dimensions of the character in + * pixels. Note: not all of the returned bbox is necessarily visible on + * the screen (the rightmost part might be off-screen to the right, and + * the bottommost part might be off-screen to the bottom). * * Side effects: * None. @@ -4803,51 +7600,50 @@ CharMeasureProc(chunkPtr, x) */ static void -CharBboxProc(chunkPtr, byteIndex, y, lineHeight, baseline, xPtr, yPtr, - widthPtr, heightPtr) - TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */ - int byteIndex; /* Byte offset of desired character - * within the chunk. */ - int y; /* Topmost pixel in area allocated - * for this line. */ - int lineHeight; /* Height of line, in pixels. */ - int baseline; /* Location of line's baseline, in - * pixels measured down from y. */ - int *xPtr, *yPtr; /* Gets filled in with coords of - * character's upper-left pixel. - * X-coord is in same coordinate - * system as chunkPtr->x. */ - int *widthPtr; /* Gets filled in with width of - * character, in pixels. */ - int *heightPtr; /* Gets filled in with height of - * character, in pixels. */ +CharBboxProc( + TkText *textPtr, + TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */ + int byteIndex, /* Byte offset of desired character within the + * chunk. */ + int y, /* Topmost pixel in area allocated for this + * line. */ + int lineHeight, /* Height of line, in pixels. */ + int baseline, /* Location of line's baseline, in pixels + * measured down from y. */ + int *xPtr, int *yPtr, /* Gets filled in with coords of character's + * upper-left pixel. X-coord is in same + * coordinate system as chunkPtr->x. */ + int *widthPtr, /* Gets filled in with width of character, in + * pixels. */ + int *heightPtr) /* Gets filled in with height of character, in + * pixels. */ { CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData; int maxX; maxX = chunkPtr->width + chunkPtr->x; - MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars, - byteIndex, chunkPtr->x, -1, 0, xPtr); + CharChunkMeasureChars(chunkPtr, NULL, 0, 0, byteIndex, + chunkPtr->x, -1, 0, xPtr); if (byteIndex == ciPtr->numBytes) { /* - * This situation only happens if the last character in a line - * is a space character, in which case it absorbs all of the - * extra space in the line (see TkTextCharLayoutProc). + * This situation only happens if the last character in a line is a + * space character, in which case it absorbs all of the extra space in + * the line (see TkTextCharLayoutProc). */ *widthPtr = maxX - *xPtr; } else if ((ciPtr->chars[byteIndex] == '\t') && (byteIndex == ciPtr->numBytes - 1)) { /* - * The desired character is a tab character that terminates a - * chunk; give it all the space left in the chunk. + * The desired character is a tab character that terminates a chunk; + * give it all the space left in the chunk. */ *widthPtr = maxX - *xPtr; } else { - MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, - ciPtr->chars + byteIndex, 1, *xPtr, -1, 0, widthPtr); + CharChunkMeasureChars(chunkPtr, NULL, 0, byteIndex, byteIndex+1, + *xPtr, -1, 0, widthPtr); if (*widthPtr > maxX) { *widthPtr = maxX - *xPtr; } else { @@ -4863,64 +7659,73 @@ CharBboxProc(chunkPtr, byteIndex, y, lineHeight, baseline, xPtr, yPtr, * * AdjustForTab -- * - * This procedure is called to move a series of chunks right - * in order to align them with a tab stop. + * This function is called to move a series of chunks right in order to + * align them with a tab stop. * * Results: * None. * * Side effects: - * The width of chunkPtr gets adjusted so that it absorbs the - * extra space due to the tab. The x locations in all the chunks - * after chunkPtr are adjusted rightward to align with the tab - * stop given by tabArrayPtr and index. + * The width of chunkPtr gets adjusted so that it absorbs the extra space + * due to the tab. The x locations in all the chunks after chunkPtr are + * adjusted rightward to align with the tab stop given by tabArrayPtr and + * index. * *---------------------------------------------------------------------- */ static void -AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) - TkText *textPtr; /* Information about the text widget as - * a whole. */ - TkTextTabArray *tabArrayPtr; /* Information about the tab stops - * that apply to this line. May be - * NULL to indicate default tabbing - * (every 8 chars). */ - int index; /* Index of current tab stop. */ - TkTextDispChunk *chunkPtr; /* Chunk whose last character is - * the tab; the following chunks - * contain information to be shifted - * right. */ - +AdjustForTab( + TkText *textPtr, /* Information about the text widget as a + * whole. */ + TkTextTabArray *tabArrayPtr,/* Information about the tab stops that apply + * to this line. May be NULL to indicate + * default tabbing (every 8 chars). */ + int index, /* Index of current tab stop. */ + TkTextDispChunk *chunkPtr) /* Chunk whose last character is the tab; the + * following chunks contain information to be + * shifted right. */ { int x, desired, delta, width, decimal, i, gotDigit; TkTextDispChunk *chunkPtr2, *decimalChunkPtr; CharInfo *ciPtr; - int tabX, prev, spaceWidth; - char *p; + int tabX, spaceWidth; + const char *p; TkTextTabAlign alignment; if (chunkPtr->nextPtr == NULL) { /* - * Nothing after the actual tab; just return. + * Nothing after the actual tab; just return. */ return; } + x = chunkPtr->nextPtr->x; + /* - * If no tab information has been given, do the usual thing: - * round up to the next boundary of 8 average-sized characters. + * If no tab information has been given, assuming tab stops are at 8 + * average-sized characters. Still ensure we respect the tabular versus + * wordprocessor tab style. */ - x = chunkPtr->nextPtr->x; if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) { /* * No tab information has been given, so use the default * interpretation of tabs. */ - desired = NextTabStop(textPtr->tkfont, x, 0); + if (textPtr->tabStyle == TK_TEXT_TABSTYLE_TABULAR) { + int tabWidth = Tk_TextWidth(textPtr->tkfont, "0", 1) * 8; + if (tabWidth == 0) { + tabWidth = 1; + } + + desired = tabWidth * (index + 1); + } else { + desired = NextTabStop(textPtr->tkfont, x, 0); + } + goto update; } @@ -4929,19 +7734,14 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) tabX = tabArrayPtr->tabs[index].location; } else { /* - * Ran out of tab stops; compute a tab position by extrapolating - * from the last two tab positions. + * Ran out of tab stops; compute a tab position by extrapolating from + * the last two tab positions. */ - if (tabArrayPtr->numTabs > 1) { - prev = tabArrayPtr->tabs[tabArrayPtr->numTabs-2].location; - } else { - prev = 0; - } + tabX = (int) (tabArrayPtr->lastTab + + (index + 1 - tabArrayPtr->numTabs)*tabArrayPtr->tabIncrement + + 0.5); alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment; - tabX = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - + (index + 1 - tabArrayPtr->numTabs) - * (tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - prev); } if (alignment == LEFT) { @@ -4951,8 +7751,8 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) if ((alignment == CENTER) || (alignment == RIGHT)) { /* - * Compute the width of all the information in the tab group, - * then use it to pick a desired location. + * Compute the width of all the information in the tab group, then use + * it to pick a desired location. */ width = 0; @@ -4969,9 +7769,9 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) } /* - * Must be numeric alignment. Search through the text to be - * tabbed, looking for the last , or . before the first character - * that isn't a number, comma, period, or sign. + * Must be numeric alignment. Search through the text to be tabbed, + * looking for the last , or . before the first character that isn't a + * number, comma, period, or sign. */ decimalChunkPtr = NULL; @@ -4997,20 +7797,21 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) } } } - endOfNumber: + + endOfNumber: if (decimalChunkPtr != NULL) { int curX; ciPtr = (CharInfo *) decimalChunkPtr->clientData; - MeasureChars(decimalChunkPtr->stylePtr->sValuePtr->tkfont, - ciPtr->chars, decimal, decimalChunkPtr->x, -1, 0, &curX); + CharChunkMeasureChars(decimalChunkPtr, NULL, 0, 0, decimal, + decimalChunkPtr->x, -1, 0, &curX); desired = tabX - (curX - x); goto update; } else { /* - * There wasn't a decimal point. Right justify the text. + * There wasn't a decimal point. Right justify the text. */ - + width = 0; for (chunkPtr2 = chunkPtr->nextPtr; chunkPtr2 != NULL; chunkPtr2 = chunkPtr2->nextPtr) { @@ -5020,15 +7821,14 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) } /* - * Shift all of the chunks to the right so that the left edge is - * at the desired location, then expand the chunk containing the - * tab. Be sure that the tab occupies at least the width of a - * space character. + * Shift all of the chunks to the right so that the left edge is at the + * desired location, then expand the chunk containing the tab. Be sure + * that the tab occupies at least the width of a space character. */ - update: + update: delta = desired - x; - MeasureChars(textPtr->tkfont, " ", 1, 0, -1, 0, &spaceWidth); + MeasureChars(textPtr->tkfont, " ", 1, 0, 1, 0, -1, 0, &spaceWidth); if (delta < spaceWidth) { delta = spaceWidth; } @@ -5044,15 +7844,18 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) * * SizeOfTab -- * - * This returns an estimate of the amount of white space that will - * be consumed by a tab. + * This returns an estimate of the amount of white space that will be + * consumed by a tab. * * Results: - * The return value is the minimum number of pixels that will - * be occupied by the index'th tab of tabArrayPtr, assuming that - * the current position on the line is x and the end of the - * line is maxX. For numeric tabs, this is a conservative - * estimate. The return value is always >= 0. + * The return value is the minimum number of pixels that will be occupied + * by the next tab of tabArrayPtr, assuming that the current position on + * the line is x and the end of the line is maxX. The 'next tab' is + * determined by a combination of the current position (x) which it must + * be equal to or beyond, and the tab count in indexPtr. + * + * For numeric tabs, this is a conservative estimate. The return value is + * always >= 0. * * Side effects: * None. @@ -5061,50 +7864,88 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr) */ static int -SizeOfTab(textPtr, tabArrayPtr, index, x, maxX) - TkText *textPtr; /* Information about the text widget as - * a whole. */ - TkTextTabArray *tabArrayPtr; /* Information about the tab stops - * that apply to this line. NULL - * means use default tabbing (every - * 8 chars.) */ - int index; /* Index of current tab stop. */ - int x; /* Current x-location in line. Only - * used if tabArrayPtr == NULL. */ - int maxX; /* X-location of pixel just past the - * right edge of the line. */ +SizeOfTab( + TkText *textPtr, /* Information about the text widget as a + * whole. */ + int tabStyle, /* One of TK_TEXT_TABSTYLE_TABULAR + * or TK_TEXT_TABSTYLE_WORDPROCESSOR. */ + TkTextTabArray *tabArrayPtr,/* Information about the tab stops that apply + * to this line. NULL means use default + * tabbing (every 8 chars.) */ + int *indexPtr, /* Contains index of previous tab stop, will + * be updated to reflect the number of stops + * used. */ + int x, /* Current x-location in line. */ + int maxX) /* X-location of pixel just past the right + * edge of the line. */ { - int tabX, prev, result, spaceWidth; + int tabX, result, index, spaceWidth, tabWidth; TkTextTabAlign alignment; + index = *indexPtr; + if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) { - tabX = NextTabStop(textPtr->tkfont, x, 0); - return tabX - x; - } - if (index < tabArrayPtr->numTabs) { - tabX = tabArrayPtr->tabs[index].location; - alignment = tabArrayPtr->tabs[index].alignment; + /* + * We're using a default tab spacing of 8 characters. + */ + + tabWidth = Tk_TextWidth(textPtr->tkfont, "0", 1) * 8; + if (tabWidth == 0) { + tabWidth = 1; + } } else { + tabWidth = 0; /* Avoid compiler error. */ + } + + do { /* - * Ran out of tab stops; compute a tab position by extrapolating - * from the last two tab positions. + * We were given the count before this tab, so increment it first. */ - if (tabArrayPtr->numTabs > 1) { - prev = tabArrayPtr->tabs[tabArrayPtr->numTabs-2].location; + index++; + + if ((tabArrayPtr == NULL) || (tabArrayPtr->numTabs == 0)) { + /* + * We're using a default tab spacing calculated above. + */ + + tabX = tabWidth * (index + 1); + alignment = LEFT; + } else if (index < tabArrayPtr->numTabs) { + tabX = tabArrayPtr->tabs[index].location; + alignment = tabArrayPtr->tabs[index].alignment; } else { - prev = 0; + /* + * Ran out of tab stops; compute a tab position by extrapolating. + */ + + tabX = (int) (tabArrayPtr->lastTab + + (index + 1 - tabArrayPtr->numTabs) + * tabArrayPtr->tabIncrement + 0.5); + alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment; } - tabX = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - + (index + 1 - tabArrayPtr->numTabs) - * (tabArrayPtr->tabs[tabArrayPtr->numTabs-1].location - prev); - alignment = tabArrayPtr->tabs[tabArrayPtr->numTabs-1].alignment; - } + + /* + * If this tab stop is before the current x position, then we have two + * cases: + * + * With 'wordprocessor' style tabs, we must obviously continue until + * we reach the text tab stop. + * + * With 'tabular' style tabs, we always use the index'th tab stop. + */ + } while (tabX <= x && (tabStyle == TK_TEXT_TABSTYLE_WORDPROCESSOR)); + + /* + * Inform our caller of how many tab stops we've used up. + */ + + *indexPtr = index; + if (alignment == CENTER) { /* - * Be very careful in the arithmetic below, because maxX may - * be the largest positive number: watch out for integer - * overflow. + * Be very careful in the arithmetic below, because maxX may be the + * largest positive number: watch out for integer overflow. */ if ((maxX-tabX) < (tabX - x)) { @@ -5120,10 +7961,9 @@ SizeOfTab(textPtr, tabArrayPtr, index, x, maxX) } /* - * Note: this treats NUMERIC alignment the same as LEFT - * alignment, which is somewhat conservative. However, it's - * pretty tricky at this point to figure out exactly where - * the damn decimal point will be. + * Note: this treats NUMERIC alignment the same as LEFT alignment, which + * is somewhat conservative. However, it's pretty tricky at this point to + * figure out exactly where the damn decimal point will be. */ if (tabX > x) { @@ -5132,8 +7972,8 @@ SizeOfTab(textPtr, tabArrayPtr, index, x, maxX) result = 0; } - done: - MeasureChars(textPtr->tkfont, " ", 1, 0, -1, 0, &spaceWidth); + done: + MeasureChars(textPtr->tkfont, " ", 1, 0, 1, 0, -1, 0, &spaceWidth); if (result < spaceWidth) { result = spaceWidth; } @@ -5145,10 +7985,10 @@ SizeOfTab(textPtr, tabArrayPtr, index, x, maxX) * * NextTabStop -- * - * Given the current position, determine where the next default - * tab stop would be located. This procedure is called when the - * current chunk in the text has no tabs defined and so the default - * tab spacing for the font should be used. + * Given the current position, determine where the next default tab stop + * would be located. This function is called when the current chunk in + * the text has no tabs defined and so the default tab spacing for the + * font should be used, provided we are using wordprocessor style tabs. * * Results: * The location in pixels of the next tab stop. @@ -5160,17 +8000,17 @@ SizeOfTab(textPtr, tabArrayPtr, index, x, maxX) */ static int -NextTabStop(tkfont, x, tabOrigin) - Tk_Font tkfont; /* Font in which chunk that contains tab - * stop will be drawn. */ - int x; /* X-position in pixels where last - * character was drawn. The next tab stop - * occurs somewhere after this location. */ - int tabOrigin; /* The origin for tab stops. May be - * non-zero if text has been scrolled. */ +NextTabStop( + Tk_Font tkfont, /* Font in which chunk that contains tab stop + * will be drawn. */ + int x, /* X-position in pixels where last character + * was drawn. The next tab stop occurs + * somewhere after this location. */ + int tabOrigin) /* The origin for tab stops. May be non-zero + * if text has been scrolled. */ { int tabWidth, rem; - + tabWidth = Tk_TextWidth(tkfont, "0", 1) * 8; if (tabWidth == 0) { tabWidth = 1; @@ -5188,26 +8028,24 @@ NextTabStop(tkfont, x, tabOrigin) /* *--------------------------------------------------------------------------- * - * MeasureChars -- + * MeasureChars -- * - * Determine the number of characters from the string that will fit - * in the given horizontal span. The measurement is done under the - * assumption that Tk_DrawTextLayout will be used to actually display - * the characters. + * Determine the number of characters from the string that will fit in + * the given horizontal span. The measurement is done under the + * assumption that Tk_DrawChars will be used to actually display the + * characters. * - * If tabs are encountered in the string, they will be expanded - * to the next tab stop, unless the TK_IGNORE_TABS flag is specified. + * If tabs are encountered in the string, they will be ignored (they + * should only occur as last character of the string anyway). * - * If a newline is encountered in the string, the line will be - * broken at that point, unless the TK_NEWSLINES_NOT_SPECIAL flag - * is specified. + * If a newline is encountered in the string, the line will be broken at + * that point. * * Results: - * The return value is the number of bytes from source - * that fit in the span given by startX and maxX. *nextXPtr - * is filled in with the x-coordinate at which the first - * character that didn't fit would be drawn, if it were to - * be drawn. + * The return value is the number of bytes from the range of start to end + * in source that fit in the span given by startX and maxX. *nextXPtr is + * filled in with the x-coordinate at which the first character that + * didn't fit would be drawn, if it were to be drawn. * * Side effects: * None. @@ -5216,29 +8054,31 @@ NextTabStop(tkfont, x, tabOrigin) */ static int -MeasureChars(tkfont, source, maxBytes, startX, maxX, tabOrigin, nextXPtr) - Tk_Font tkfont; /* Font in which to draw characters. */ - CONST char *source; /* Characters to be displayed. Need not - * be NULL-terminated. */ - int maxBytes; /* Maximum # of bytes to consider from +MeasureChars( + Tk_Font tkfont, /* Font in which to draw characters. */ + CONST char *source, /* Characters to be displayed. Need not be + * NULL-terminated. */ + int maxBytes, /* Maximum # of bytes to consider from * source. */ - int startX; /* X-position at which first character will - * be drawn. */ - int maxX; /* Don't consider any character that would + int rangeStart, int rangeLength, + /* Range of bytes to consider in source.*/ + int startX, /* X-position at which first character will be + * drawn. */ + int maxX, /* Don't consider any character that would * cross this x-position. */ - int tabOrigin; /* X-location that serves as "origin" for - * tab stops. */ - int *nextXPtr; /* Return x-position of terminating - * character here. */ + int flags, /* Flags to pass to Tk_MeasureChars. */ + int *nextXPtr) /* Return x-position of terminating character + * here. */ { int curX, width, ch; CONST char *special, *end, *start; ch = 0; /* lint. */ curX = startX; - special = source; - end = source + maxBytes; - for (start = source; start < end; ) { + start = source + rangeStart; + end = start + rangeLength; + special = start; + while (start < end) { if (start >= special) { /* * Find the next special character in the string. @@ -5254,14 +8094,21 @@ MeasureChars(tkfont, source, maxBytes, startX, maxX, tabOrigin, nextXPtr) /* * Special points at the next special character (or the end of the - * string). Process characters between start and special. + * string). Process characters between start and special. */ if ((maxX >= 0) && (curX >= maxX)) { break; } - start += Tk_MeasureChars(tkfont, start, special - start, maxX - curX, - 0, &width); +#if TK_DRAW_IN_CONTEXT + start += TkpMeasureCharsInContext(tkfont, source, maxBytes, + start - source, special - start, + maxX >= 0 ? maxX - curX : -1, flags, &width); +#else + (void) maxBytes; + start += Tk_MeasureChars(tkfont, start, special - start, + maxX >= 0 ? maxX - curX : -1, flags, &width); +#endif /* TK_DRAW_IN_CONTEXT */ curX += width; if (start < special) { /* @@ -5280,5 +8127,378 @@ MeasureChars(tkfont, source, maxBytes, startX, maxX, tabOrigin, nextXPtr) } *nextXPtr = curX; - return start - source; + return start - (source+rangeStart); } + +/* + *---------------------------------------------------------------------- + * + * TextGetScrollInfoObj -- + * + * This function is invoked to parse "xview" and "yview" scrolling + * commands for text widgets using the new scrolling command syntax + * ("moveto" or "scroll" options). It extends the public + * Tk_GetScrollInfoObj function with the addition of "pixels" as a valid + * unit alongside "pages" and "units". It is a shame the core API isn't + * more flexible in this regard. + * + * Results: + * The return value is either TKTEXT_SCROLL_MOVETO, TKTEXT_SCROLL_PAGES, + * TKTEXT_SCROLL_UNITS, TKTEXT_SCROLL_PIXELS or TKTEXT_SCROLL_ERROR. This + * indicates whether the command was successfully parsed and what form + * the command took. If TKTEXT_SCROLL_MOVETO, *dblPtr is filled in with + * the desired position; if TKTEXT_SCROLL_PAGES, TKTEXT_SCROLL_PIXELS or + * TKTEXT_SCROLL_UNITS, *intPtr is filled in with the number of + * pages/pixels/lines to move (may be negative); if TKTEXT_SCROLL_ERROR, + * the interp's result contains an error message. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +TextGetScrollInfoObj( + Tcl_Interp *interp, /* Used for error reporting. */ + TkText *textPtr, /* Information about the text widget. */ + int objc, /* # arguments for command. */ + Tcl_Obj *CONST objv[], /* Arguments for command. */ + double *dblPtr, /* Filled in with argument "moveto" option, if + * any. */ + int *intPtr) /* Filled in with number of pages or lines or + * pixels to scroll, if any. */ +{ + static CONST char *subcommands[] = { + "moveto", "scroll", NULL + }; + enum viewSubcmds { + VIEW_MOVETO, VIEW_SCROLL + }; + static CONST char *units[] = { + "units", "pages", "pixels", NULL + }; + enum viewUnits { + VIEW_SCROLL_UNITS, VIEW_SCROLL_PAGES, VIEW_SCROLL_PIXELS + }; + int index; + + if (Tcl_GetIndexFromObj(interp, objv[2], subcommands, "option", 0, + &index) != TCL_OK) { + return TKTEXT_SCROLL_ERROR; + } + + switch ((enum viewSubcmds) index) { + case VIEW_MOVETO: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "fraction"); + return TKTEXT_SCROLL_ERROR; + } + if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) { + return TKTEXT_SCROLL_ERROR; + } + return TKTEXT_SCROLL_MOVETO; + case VIEW_SCROLL: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "number units|pages|pixels"); + return TKTEXT_SCROLL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[4], units, "argument", 0, + &index) != TCL_OK) { + return TKTEXT_SCROLL_ERROR; + } + switch ((enum viewUnits) index) { + case VIEW_SCROLL_PAGES: + if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) { + return TKTEXT_SCROLL_ERROR; + } + return TKTEXT_SCROLL_PAGES; + case VIEW_SCROLL_PIXELS: + if (Tk_GetPixelsFromObj(interp, textPtr->tkwin, objv[3], + intPtr) != TCL_OK) { + return TKTEXT_SCROLL_ERROR; + } + return TKTEXT_SCROLL_PIXELS; + case VIEW_SCROLL_UNITS: + if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) { + return TKTEXT_SCROLL_ERROR; + } + return TKTEXT_SCROLL_UNITS; + } + } + Tcl_Panic("unexpected switch fallthrough"); + return TKTEXT_SCROLL_ERROR; +} + +#if TK_LAYOUT_WITH_BASE_CHUNKS +/* + *---------------------------------------------------------------------- + * + * FinalizeBaseChunk -- + * + * This procedure makes sure that all the chunks of the stretch are + * up-to-date. It is invoked when the LayoutProc has been called for all + * chunks and the base chunk is stable. + * + * Results: + * None. + * + * Side effects: + * The CharInfo.chars of all dependent chunks point into + * BaseCharInfo.baseChars for easy access (and compatibility). + * + *---------------------------------------------------------------------- + */ + +static void +FinalizeBaseChunk( + TkTextDispChunk *addChunkPtr) + /* An additional chunk to add to the stretch, + * even though it may not be in the linked + * list yet. Used by the LayoutProc, otherwise + * NULL. */ +{ + const char *baseChars; + TkTextDispChunk *chunkPtr; + CharInfo *ciPtr; +#if TK_DRAW_IN_CONTEXT + int widthAdjust = 0; + int newwidth; +#endif /* TK_DRAW_IN_CONTEXT */ + + if (baseCharChunkPtr == NULL) { + return; + } + + baseChars = Tcl_DStringValue( + &((BaseCharInfo *) baseCharChunkPtr->clientData)->baseChars); + + for (chunkPtr = baseCharChunkPtr; chunkPtr != NULL; + chunkPtr = chunkPtr->nextPtr) { +#if TK_DRAW_IN_CONTEXT + chunkPtr->x += widthAdjust; +#endif /* TK_DRAW_IN_CONTEXT */ + + if (chunkPtr->displayProc != CharDisplayProc) { + continue; + } + ciPtr = (CharInfo *)chunkPtr->clientData; + if (ciPtr->baseChunkPtr != baseCharChunkPtr) { + break; + } + ciPtr->chars = baseChars + ciPtr->baseOffset; + +#if TK_DRAW_IN_CONTEXT + newwidth = 0; + CharChunkMeasureChars(chunkPtr, NULL, 0, 0, -1, 0, -1, 0, &newwidth); + if (newwidth != chunkPtr->width) { + widthAdjust += newwidth - chunkPtr->width; + chunkPtr->width = newwidth; + } +#endif /* TK_DRAW_IN_CONTEXT */ + } + + if (addChunkPtr != NULL) { + ciPtr = (CharInfo *)addChunkPtr->clientData; + ciPtr->chars = baseChars + ciPtr->baseOffset; + +#if TK_DRAW_IN_CONTEXT + addChunkPtr->x += widthAdjust; + CharChunkMeasureChars(addChunkPtr, NULL, 0, 0, -1, 0, -1, 0, + &addChunkPtr->width); +#endif /* TK_DRAW_IN_CONTEXT */ + } + + baseCharChunkPtr = NULL; +} + +/* + *---------------------------------------------------------------------- + * + * FreeBaseChunk -- + * + * This procedure makes sure that all the chunks of the stretch are + * disconnected from the base chunk and the base chunk specific data is + * freed. It is invoked from the UndisplayProc. The procedure doesn't + * ckfree the base chunk clientData itself, that's up to the main + * UndisplayProc. + * + * Results: + * None. + * + * Side effects: + * The CharInfo.chars of all dependent chunks are set to NULL. Memory + * that belongs specifically to the base chunk is freed. + * + *---------------------------------------------------------------------- + */ + +static void +FreeBaseChunk( + TkTextDispChunk *baseChunkPtr) + /* The base chunk of the stretch and head of + * the linked list. */ +{ + TkTextDispChunk *chunkPtr; + CharInfo *ciPtr; + + if (baseCharChunkPtr == baseChunkPtr) { + baseCharChunkPtr = NULL; + } + + for (chunkPtr=baseChunkPtr; chunkPtr!=NULL; chunkPtr=chunkPtr->nextPtr) { + if (chunkPtr->undisplayProc != CharUndisplayProc) { + continue; + } + ciPtr = (CharInfo *) chunkPtr->clientData; + if (ciPtr->baseChunkPtr != baseChunkPtr) { + break; + } + + ciPtr->baseChunkPtr = NULL; + ciPtr->chars = NULL; + } + + Tcl_DStringFree(&((BaseCharInfo *) baseChunkPtr->clientData)->baseChars); +} + +/* + *---------------------------------------------------------------------- + * + * IsSameFGStyle -- + * + * Compare the foreground attributes of two styles. Specifically must + * consider: foreground color, font, font style and font decorations, + * elide, "offset" and foreground stipple. Do *not* consider: background + * color, border, relief or background stipple. + * + * If we use TkpDrawCharsInContext(), we also don't need to check + * foreground color, font decorations, elide, offset and foreground + * stipple, so all that is left is font (including font size and font + * style) and "offset". + * + * Results: + * 1 if the two styles match, 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +IsSameFGStyle( + TextStyle *style1, + TextStyle *style2) +{ + StyleValues *sv1; + StyleValues *sv2; + + if (style1 == style2) { + return 1; + } + +#if !TK_DRAW_IN_CONTEXT + if ( +#ifdef MAC_OSX_TK + !TkMacOSXCompareColors(style1->fgGC->foreground, + style2->fgGC->foreground) +#else + style1->fgGC->foreground != style2->fgGC->foreground +#endif + ) { + return 0; + } +#endif /* !TK_DRAW_IN_CONTEXT */ + + sv1 = style1->sValuePtr; + sv2 = style2->sValuePtr; + +#if TK_DRAW_IN_CONTEXT + return sv1->tkfont == sv2->tkfont && sv1->offset == sv2->offset; +#else + return sv1->tkfont == sv2->tkfont + && sv1->underline == sv2->underline + && sv1->overstrike == sv2->overstrike + && sv1->elide == sv2->elide + && sv1->offset == sv2->offset + && sv1->fgStipple == sv1->fgStipple; +#endif /* TK_DRAW_IN_CONTEXT */ +} + +/* + *---------------------------------------------------------------------- + * + * RemoveFromBaseChunk -- + * + * This procedure removes a chunk from the stretch as a result of + * UndisplayProc. The chunk in question should be the last in a stretch. + * This happens during re-layouting of the break position. + * + * Results: + * None. + * + * Side effects: + * The characters that belong to this chunk are removed from the base + * chunk. It is assumed that LayoutProc and FinalizeBaseChunk are called + * next to repair any damage that this causes to the integrity of the + * stretch and the other chunks. For that reason the base chunk is also + * put into baseCharChunkPtr automatically, so that LayoutProc can resume + * correctly. + * + *---------------------------------------------------------------------- + */ + +static void +RemoveFromBaseChunk( + TkTextDispChunk *chunkPtr) /* The chunk to remove from the end of the + * stretch. */ +{ + CharInfo *ciPtr; + BaseCharInfo *bciPtr; + + if (chunkPtr->displayProc != CharDisplayProc) { +#ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS + fprintf(stderr,"RemoveFromBaseChunk called with wrong chunk type\n"); +#endif + return; + } + + /* + * Reinstitute this base chunk for re-layout. + */ + + ciPtr = (CharInfo *) chunkPtr->clientData; + baseCharChunkPtr = ciPtr->baseChunkPtr; + + /* + * Remove the chunk data from the base chunk data. + */ + + bciPtr = (BaseCharInfo *) baseCharChunkPtr->clientData; + + 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 + } + + Tcl_DStringSetLength(&bciPtr->baseChars, ciPtr->baseOffset); + + /* + * Invalidate the stored pixel width of the base chunk. + */ + + bciPtr->width = -1; +} +#endif /* TK_LAYOUT_WITH_BASE_CHUNKS */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTextImage.c b/generic/tkTextImage.c index 57d444f..5d77c13 100644 --- a/generic/tkTextImage.c +++ b/generic/tkTextImage.c @@ -1,120 +1,111 @@ -/* +/* * tkImage.c -- * - * This file contains code that allows images to be - * nested inside text widgets. It also implements the "image" - * widget command for texts. + * This file contains code that allows images to be nested inside text + * widgets. It also implements the "image" widget command for texts. * * Copyright (c) 1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tk.h" -#include "tkText.h" #include "tkPort.h" - -/* - * Definitions for alignment values: - */ - -#define ALIGN_BOTTOM 0 -#define ALIGN_CENTER 1 -#define ALIGN_TOP 2 -#define ALIGN_BASELINE 3 +#include "tkText.h" /* * Macro that determines the size of an embedded image segment: */ -#define EI_SEG_SIZE ((unsigned) (Tk_Offset(TkTextSegment, body) \ - + sizeof(TkTextEmbImage))) +#define EI_SEG_SIZE \ + ((unsigned) (Tk_Offset(TkTextSegment, body) + sizeof(TkTextEmbImage))) /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static int AlignParseProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, Tk_Window tkwin, - CONST char *value, char *widgRec, int offset)); -static char * AlignPrintProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -static TkTextSegment * EmbImageCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static void EmbImageCheckProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static void EmbImageBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int index, int y, int lineHeight, int baseline, - int *xPtr, int *yPtr, int *widthPtr, - int *heightPtr)); -static int EmbImageConfigure _ANSI_ARGS_((TkText *textPtr, - TkTextSegment *eiPtr, int argc, CONST char **argv)); -static int EmbImageDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr, int treeGone)); -static void EmbImageDisplayProc _ANSI_ARGS_(( +static TkTextSegment * EmbImageCleanupProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static void EmbImageCheckProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static void EmbImageBboxProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int index, int y, + int lineHeight, int baseline, int *xPtr, int *yPtr, + int *widthPtr, int *heightPtr); +static int EmbImageConfigure(TkText *textPtr, + TkTextSegment *eiPtr, int objc, + Tcl_Obj *const objv[]); +static int EmbImageDeleteProc(TkTextSegment *segPtr, + TkTextLine *linePtr, int treeGone); +static void EmbImageDisplayProc(TkText *textPtr, TkTextDispChunk *chunkPtr, int x, int y, int lineHeight, int baseline, Display *display, - Drawable dst, int screenY)); -static int EmbImageLayoutProc _ANSI_ARGS_((TkText *textPtr, + Drawable dst, int screenY); +static int EmbImageLayoutProc(TkText *textPtr, TkTextIndex *indexPtr, TkTextSegment *segPtr, int offset, int maxX, int maxChars, int noCharsYet, TkWrapMode wrapMode, - TkTextDispChunk *chunkPtr)); -static void EmbImageProc _ANSI_ARGS_((ClientData clientData, - int x, int y, int width, int height, - int imageWidth, int imageHeight)); + TkTextDispChunk *chunkPtr); +static void EmbImageProc(ClientData clientData, int x, int y, + int width, int height, int imageWidth, + int imageHeight); /* * The following structure declares the "embedded image" segment type. */ -static Tk_SegType tkTextEmbImageType = { - "image", /* name */ - 0, /* leftGravity */ - (Tk_SegSplitProc *) NULL, /* splitProc */ - EmbImageDeleteProc, /* deleteProc */ - EmbImageCleanupProc, /* cleanupProc */ - (Tk_SegLineChangeProc *) NULL, /* lineChangeProc */ - EmbImageLayoutProc, /* layoutProc */ - EmbImageCheckProc /* checkProc */ +static const Tk_SegType tkTextEmbImageType = { + "image", /* name */ + 0, /* leftGravity */ + NULL, /* splitProc */ + EmbImageDeleteProc, /* deleteProc */ + EmbImageCleanupProc, /* cleanupProc */ + NULL, /* lineChangeProc */ + EmbImageLayoutProc, /* layoutProc */ + EmbImageCheckProc /* checkProc */ +}; + +/* + * Definitions for alignment values: + */ + +static char *alignStrings[] = { + "baseline", "bottom", "center", "top", NULL }; +typedef enum { + ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER, ALIGN_TOP +} alignMode; + /* * Information used for parsing image configuration options: */ -static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc, - (ClientData) NULL}; - -static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL, - "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption}, - {TK_CONFIG_PIXELS, "-padx", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextEmbImage, padX), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_PIXELS, "-pady", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextEmbImage, padY), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextEmbImage, imageString), - TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-name", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextEmbImage, imageName), - TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} +static const Tk_OptionSpec optionSpecs[] = { + {TK_OPTION_STRING_TABLE, "-align", NULL, NULL, + "center", -1, Tk_Offset(TkTextEmbImage, align), + 0, (ClientData) alignStrings, 0}, + {TK_OPTION_PIXELS, "-padx", NULL, NULL, + "0", -1, Tk_Offset(TkTextEmbImage, padX), 0, 0, 0}, + {TK_OPTION_PIXELS, "-pady", NULL, NULL, + "0", -1, Tk_Offset(TkTextEmbImage, padY), 0, 0, 0}, + {TK_OPTION_STRING, "-image", NULL, NULL, + NULL, -1, Tk_Offset(TkTextEmbImage, imageString), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-name", NULL, NULL, + NULL, -1, Tk_Offset(TkTextEmbImage, imageName), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_END} }; + /* *-------------------------------------------------------------- * * TkTextImageCmd -- * - * This procedure implements the "image" widget command - * for text widgets. See the user documentation for details - * on what it does. + * This function implements the "image" widget command for text widgets. + * See the user documentation for details on what it does. * * Results: * A standard Tcl result or error. @@ -126,100 +117,121 @@ static Tk_ConfigSpec configSpecs[] = { */ int -TkTextImageCmd(textPtr, interp, argc, argv) - register TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextImageCmd( + register TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "image". */ + * objv[1] is "image". */ { - size_t length; + int idx; register TkTextSegment *eiPtr; - - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " image option ?arg arg ...?\"", (char *) NULL); + TkTextIndex index; + static const char *optionStrings[] = { + "cget", "configure", "create", "names", NULL + }; + enum opts { + CMD_CGET, CMD_CONF, CMD_CREATE, CMD_NAMES + }; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); return TCL_ERROR; } - length = strlen(argv[2]); - if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) { - TkTextIndex index; - TkTextSegment *eiPtr; - - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " image cget index option\"", - (char *) NULL); + if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, "option", 0, + &idx) != TCL_OK) { + return TCL_ERROR; + } + switch ((enum opts) idx) { + case CMD_CGET: { + Tcl_Obj *objPtr; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "index option"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } - eiPtr = TkTextIndexToSeg(&index, (int *) NULL); + eiPtr = TkTextIndexToSeg(&index, NULL); if (eiPtr->typePtr != &tkTextEmbImageType) { Tcl_AppendResult(interp, "no embedded image at index \"", - argv[3], "\"", (char *) NULL); + Tcl_GetString(objv[3]), "\"", NULL); return TCL_ERROR; } - return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs, - (char *) &eiPtr->body.ei, argv[4], 0); - } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) { - TkTextIndex index; - TkTextSegment *eiPtr; - - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " image configure index ?option value ...?\"", - (char *) NULL); + objPtr = Tk_GetOptionValue(interp, (char *) &eiPtr->body.ei, + eiPtr->body.ei.optionTable, objv[4], textPtr->tkwin); + if (objPtr == NULL) { + return TCL_ERROR; + } else { + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; + } + } + case CMD_CONF: + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } - eiPtr = TkTextIndexToSeg(&index, (int *) NULL); + eiPtr = TkTextIndexToSeg(&index, NULL); if (eiPtr->typePtr != &tkTextEmbImageType) { Tcl_AppendResult(interp, "no embedded image at index \"", - argv[3], "\"", (char *) NULL); + Tcl_GetString(objv[3]), "\"", NULL); return TCL_ERROR; } - if (argc == 4) { - return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs, - (char *) &eiPtr->body.ei, (char *) NULL, 0); - } else if (argc == 5) { - return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs, - (char *) &eiPtr->body.ei, argv[4], 0); + if (objc <= 5) { + Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, + (char *) &eiPtr->body.ei, eiPtr->body.ei.optionTable, + (objc == 5) ? objv[4] : NULL, textPtr->tkwin); + if (objPtr == NULL) { + return TCL_ERROR; + } else { + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; + } } else { - TkTextChanged(textPtr, &index, &index); - return EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4); + TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index); + + /* + * It's probably not true that all window configuration can change + * the line height, so we could be more efficient here and only + * call this when necessary. + */ + + TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); + return EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4); } - } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) { - TkTextIndex index; + case CMD_CREATE: { int lineIndex; /* - * Add a new image. Find where to put the new image, and - * mark that position for redisplay. + * Add a new image. Find where to put the new image, and mark that + * position for redisplay. */ - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " image create index ?option value ...?\"", - (char *) NULL); + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } /* * Don't allow insertions on the last (dummy) line of the text. */ - - lineIndex = TkBTreeLineIndex(index.linePtr); - if (lineIndex == TkBTreeNumLines(textPtr->tree)) { + + lineIndex = TkBTreeLinesTo(textPtr, index.linePtr); + if (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree, + textPtr)) { lineIndex--; - TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineIndex, 1000000, &index); } /* @@ -229,7 +241,7 @@ TkTextImageCmd(textPtr, interp, argc, argv) eiPtr = (TkTextSegment *) ckalloc(EI_SEG_SIZE); eiPtr->typePtr = &tkTextEmbImageType; eiPtr->size = 1; - eiPtr->body.ei.textPtr = textPtr; + eiPtr->body.ei.sharedTextPtr = textPtr->sharedTextPtr; eiPtr->body.ei.linePtr = NULL; eiPtr->body.ei.imageName = NULL; eiPtr->body.ei.imageString = NULL; @@ -238,42 +250,45 @@ TkTextImageCmd(textPtr, interp, argc, argv) eiPtr->body.ei.align = ALIGN_CENTER; eiPtr->body.ei.padX = eiPtr->body.ei.padY = 0; eiPtr->body.ei.chunkCount = 0; + eiPtr->body.ei.optionTable = Tk_CreateOptionTable(interp, optionSpecs); /* - * Link the segment into the text widget, then configure it (delete - * it again if the configuration fails). + * Link the segment into the text widget, then configure it (delete it + * again if the configuration fails). */ - TkTextChanged(textPtr, &index, &index); + TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index); TkBTreeLinkSegment(eiPtr, &index); - if (EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4) != TCL_OK) { + if (EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4) != TCL_OK) { TkTextIndex index2; - TkTextIndexForwChars(&index, 1, &index2); - TkBTreeDeleteChars(&index, &index2); + TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES); + TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index, &index2); return TCL_ERROR; } - } else if (strncmp(argv[2], "names", length) == 0) { + TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); + return TCL_OK; + } + case CMD_NAMES: { Tcl_HashSearch search; Tcl_HashEntry *hPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " image names\"", (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - for (hPtr = Tcl_FirstHashEntry(&textPtr->imageTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable, + &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_AppendElement(interp, - Tcl_GetHashKey(&textPtr->markTable, hPtr)); + Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr)); } - } else { - Tcl_AppendResult(interp, "bad image option \"", argv[2], - "\": must be cget, configure, create, or names", - (char *) NULL); - return TCL_ERROR; + return TCL_OK; } - return TCL_OK; + default: + Tcl_Panic("unexpected switch fallthrough"); + } + return TCL_ERROR; } /* @@ -281,55 +296,54 @@ TkTextImageCmd(textPtr, interp, argc, argv) * * EmbImageConfigure -- * - * This procedure is called to handle configuration options - * for an embedded image, using an argc/argv list. + * This function is called to handle configuration options for an + * embedded image, using an objc/objv list. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message.. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message.. * * Side effects: - * Configuration information for the embedded image changes, - * such as alignment, or name of the image. + * Configuration information for the embedded image changes, such as + * alignment, or name of the image. * *-------------------------------------------------------------- */ static int -EmbImageConfigure(textPtr, eiPtr, argc, argv) - TkText *textPtr; /* Information about text widget that - * contains embedded image. */ - TkTextSegment *eiPtr; /* Embedded image to be configured. */ - int argc; /* Number of strings in argv. */ - CONST char **argv; /* Array of strings describing configuration +EmbImageConfigure( + TkText *textPtr, /* Information about text widget that contains + * embedded image. */ + TkTextSegment *eiPtr, /* Embedded image to be configured. */ + int objc, /* Number of strings in objv. */ + Tcl_Obj *const objv[]) /* Array of strings describing configuration * options. */ { Tk_Image image; Tcl_DString newName; Tcl_HashEntry *hPtr; Tcl_HashSearch search; - int new; char *name; int count = 0; /* The counter for picking a unique name */ int conflict = 0; /* True if we have a name conflict */ - unsigned int len; /* length of image name */ + size_t len; /* length of image name */ - if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs, - argc, argv, (char *) &eiPtr->body.ei,TK_CONFIG_ARGV_ONLY) - != TCL_OK) { + if (Tk_SetOptions(textPtr->interp, (char*)&eiPtr->body.ei, + eiPtr->body.ei.optionTable, + objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) { return TCL_ERROR; } /* - * Create the image. Save the old image around and don't free it - * until after the new one is allocated. This keeps the reference - * count from going to zero so the image doesn't have to be recreated - * if it hasn't changed. + * Create the image. Save the old image around and don't free it until + * after the new one is allocated. This keeps the reference count from + * going to zero so the image doesn't have to be recreated if it hasn't + * changed. */ if (eiPtr->body.ei.imageString != NULL) { - image = Tk_GetImage(textPtr->interp, textPtr->tkwin, eiPtr->body.ei.imageString, - EmbImageProc, (ClientData) eiPtr); + image = Tk_GetImage(textPtr->interp, textPtr->tkwin, + eiPtr->body.ei.imageString, EmbImageProc, (ClientData) eiPtr); if (image == NULL) { return TCL_ERROR; } @@ -345,9 +359,9 @@ EmbImageConfigure(textPtr, eiPtr, argc, argv) return TCL_OK; } - /* - * Find a unique name for this image. Use imageName (or imageString) - * if available, otherwise tack on a #nn and use it. If a name is already + /* + * Find a unique name for this image. Use imageName (or imageString) if + * available, otherwise tack on a #nn and use it. If a name is already * associated with this image, delete the name. */ @@ -356,42 +370,50 @@ EmbImageConfigure(textPtr, eiPtr, argc, argv) name = eiPtr->body.ei.imageString; } if (name == NULL) { - Tcl_AppendResult(textPtr->interp,"Either a \"-name\" ", + Tcl_AppendResult(textPtr->interp, "Either a \"-name\" ", "or a \"-image\" argument must be provided ", - "to the \"image create\" subcommand.", - (char *) NULL); + "to the \"image create\" subcommand.", NULL); return TCL_ERROR; } len = strlen(name); - for (hPtr = Tcl_FirstHashEntry(&textPtr->imageTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - char *haveName = Tcl_GetHashKey(&textPtr->imageTable, hPtr); + for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->imageTable, + &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + char *haveName = + Tcl_GetHashKey(&textPtr->sharedTextPtr->imageTable, hPtr); + if (strncmp(name, haveName, len) == 0) { - new = 0; - sscanf(haveName+len,"#%d",&new); - if (new > count) { - count = new; + int newVal = 0; + + sscanf(haveName+len, "#%d", &newVal); + if (newVal > count) { + count = newVal; } - if (len == (int) strlen(haveName)) { + if (len == strlen(haveName)) { conflict = 1; } } } Tcl_DStringInit(&newName); - Tcl_DStringAppend(&newName,name, -1); + Tcl_DStringAppend(&newName, name, -1); if (conflict) { char buf[4 + TCL_INTEGER_SPACE]; - sprintf(buf, "#%d",count+1); - Tcl_DStringAppend(&newName,buf, -1); + + sprintf(buf, "#%d", count+1); + Tcl_DStringAppend(&newName, buf, -1); } name = Tcl_DStringValue(&newName); - hPtr = Tcl_CreateHashEntry(&textPtr->imageTable, name, &new); + { + int dummy; + + hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->imageTable, name, + &dummy); + } Tcl_SetHashValue(hPtr, eiPtr); - Tcl_AppendResult(textPtr->interp, name , (char *) NULL); + Tcl_AppendResult(textPtr->interp, name, NULL); eiPtr->body.ei.name = ckalloc((unsigned) Tcl_DStringLength(&newName)+1); - strcpy(eiPtr->body.ei.name,name); + strcpy(eiPtr->body.ei.name, name); Tcl_DStringFree(&newName); return TCL_OK; @@ -400,103 +422,10 @@ EmbImageConfigure(textPtr, eiPtr, argc, argv) /* *-------------------------------------------------------------- * - * AlignParseProc -- - * - * This procedure is invoked by Tk_ConfigureWidget during - * option processing to handle "-align" options for embedded - * images. - * - * Results: - * A standard Tcl return value. - * - * Side effects: - * The alignment for the embedded image may change. - * - *-------------------------------------------------------------- - */ - - /* ARGSUSED */ -static int -AlignParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* Not used.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window for text widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to TkTextEmbWindow - * structure. */ - int offset; /* Offset into item (ignored). */ -{ - register TkTextEmbImage *embPtr = (TkTextEmbImage *) widgRec; - - if (strcmp(value, "baseline") == 0) { - embPtr->align = ALIGN_BASELINE; - } else if (strcmp(value, "bottom") == 0) { - embPtr->align = ALIGN_BOTTOM; - } else if (strcmp(value, "center") == 0) { - embPtr->align = ALIGN_CENTER; - } else if (strcmp(value, "top") == 0) { - embPtr->align = ALIGN_TOP; - } else { - Tcl_AppendResult(interp, "bad alignment \"", value, - "\": must be baseline, bottom, center, or top", - (char *) NULL); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *-------------------------------------------------------------- - * - * AlignPrintProc -- - * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-align" configuration - * option for embedded images. - * - * Results: - * The return value is a string describing the embedded - * images's current alignment. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ - - /* ARGSUSED */ -static char * -AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window for text widget. */ - char *widgRec; /* Pointer to TkTextEmbImage - * structure. */ - int offset; /* Ignored. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ -{ - switch (((TkTextEmbImage *) widgRec)->align) { - case ALIGN_BASELINE: - return "baseline"; - case ALIGN_BOTTOM: - return "bottom"; - case ALIGN_CENTER: - return "center"; - case ALIGN_TOP: - return "top"; - default: - return "??"; - } -} - -/* - *-------------------------------------------------------------- - * * EmbImageDeleteProc -- * - * This procedure is invoked by the text B-tree code whenever - * an embedded image lies in a range of characters being deleted. + * This function is invoked by the text B-tree code whenever an embedded + * image lies in a range of characters being deleted. * * Results: * Returns 0 to indicate that the deletion has been accepted. @@ -510,17 +439,17 @@ AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) /* ARGSUSED */ static int -EmbImageDeleteProc(eiPtr, linePtr, treeGone) - TkTextSegment *eiPtr; /* Segment being deleted. */ - TkTextLine *linePtr; /* Line containing segment. */ - int treeGone; /* Non-zero means the entire tree is - * being deleted, so everything must - * get cleaned up. */ +EmbImageDeleteProc( + TkTextSegment *eiPtr, /* Segment being deleted. */ + TkTextLine *linePtr, /* Line containing segment. */ + int treeGone) /* Non-zero means the entire tree is being + * deleted, so everything must get cleaned + * up. */ { Tcl_HashEntry *hPtr; if (eiPtr->body.ei.image != NULL) { - hPtr = Tcl_FindHashEntry(&eiPtr->body.ei.textPtr->imageTable, + hPtr = Tcl_FindHashEntry(&eiPtr->body.ei.sharedTextPtr->imageTable, eiPtr->body.ei.name); if (hPtr != NULL) { /* @@ -533,9 +462,15 @@ EmbImageDeleteProc(eiPtr, linePtr, treeGone) } Tk_FreeImage(eiPtr->body.ei.image); } - Tk_FreeOptions(configSpecs, (char *) &eiPtr->body.ei, - eiPtr->body.ei.textPtr->display, 0); - if (eiPtr->body.ei.name != NULL) { + + /* + * No need to supply a tkwin argument, since we have no window-specific + * options. + */ + + Tk_FreeConfigOptions((char *) &eiPtr->body.ei, eiPtr->body.ei.optionTable, + NULL); + if (eiPtr->body.ei.name) { ckfree(eiPtr->body.ei.name); } ckfree((char *) eiPtr); @@ -547,9 +482,8 @@ EmbImageDeleteProc(eiPtr, linePtr, treeGone) * * EmbImageCleanupProc -- * - * This procedure is invoked by the B-tree code whenever a - * segment containing an embedded image is moved from one - * line to another. + * This function is invoked by the B-tree code whenever a segment + * containing an embedded image is moved from one line to another. * * Results: * None. @@ -561,9 +495,9 @@ EmbImageDeleteProc(eiPtr, linePtr, treeGone) */ static TkTextSegment * -EmbImageCleanupProc(eiPtr, linePtr) - TkTextSegment *eiPtr; /* Mark segment that's being moved. */ - TkTextLine *linePtr; /* Line that now contains segment. */ +EmbImageCleanupProc( + TkTextSegment *eiPtr, /* Mark segment that's being moved. */ + TkTextLine *linePtr) /* Line that now contains segment. */ { eiPtr->body.ei.linePtr = linePtr; return eiPtr; @@ -574,12 +508,11 @@ EmbImageCleanupProc(eiPtr, linePtr) * * EmbImageLayoutProc -- * - * This procedure is the "layoutProc" for embedded image - * segments. + * This function is the "layoutProc" for embedded image segments. * * Results: - * 1 is returned to indicate that the segment should be - * displayed. The chunkPtr structure is filled in. + * 1 is returned to indicate that the segment should be displayed. The + * chunkPtr structure is filled in. * * Side effects: * None, except for filling in chunkPtr. @@ -589,30 +522,30 @@ EmbImageCleanupProc(eiPtr, linePtr) /*ARGSUSED*/ static int -EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars, - noCharsYet, wrapMode, chunkPtr) - TkText *textPtr; /* Text widget being layed out. */ - TkTextIndex *indexPtr; /* Identifies first character in chunk. */ - TkTextSegment *eiPtr; /* Segment corresponding to indexPtr. */ - int offset; /* Offset within segPtr corresponding to +EmbImageLayoutProc( + TkText *textPtr, /* Text widget being layed out. */ + TkTextIndex *indexPtr, /* Identifies first character in chunk. */ + TkTextSegment *eiPtr, /* Segment corresponding to indexPtr. */ + int offset, /* Offset within segPtr corresponding to * indexPtr (always 0). */ - int maxX; /* Chunk must not occupy pixels at this + int maxX, /* Chunk must not occupy pixels at this * position or higher. */ - int maxChars; /* Chunk must not include more than this - * many characters. */ - int noCharsYet; /* Non-zero means no characters have been + int maxChars, /* Chunk must not include more than this many + * characters. */ + int noCharsYet, /* Non-zero means no characters have been * assigned to this line yet. */ - TkWrapMode wrapMode; /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR, - * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */ - register TkTextDispChunk *chunkPtr; - /* Structure to fill in with information - * about this chunk. The x field has already - * been set by the caller. */ + TkWrapMode wrapMode, /* Wrap mode to use for line: + * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or + * TEXT_WRAPMODE_WORD. */ + register TkTextDispChunk *chunkPtr) + /* Structure to fill in with information about + * this chunk. The x field has already been + * set by the caller. */ { int width, height; if (offset != 0) { - panic("Non-zero offset in EmbImageLayoutProc"); + Tcl_Panic("Non-zero offset in EmbImageLayoutProc"); } /* @@ -637,8 +570,8 @@ EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars, */ chunkPtr->displayProc = EmbImageDisplayProc; - chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL; - chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL; + chunkPtr->undisplayProc = NULL; + chunkPtr->measureProc = NULL; chunkPtr->bboxProc = EmbImageBboxProc; chunkPtr->numBytes = 1; if (eiPtr->body.ei.align == ALIGN_BASELINE) { @@ -663,29 +596,30 @@ EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars, * * EmbImageCheckProc -- * - * This procedure is invoked by the B-tree code to perform - * consistency checks on embedded images. + * This function is invoked by the B-tree code to perform consistency + * checks on embedded images. * * Results: * None. * * Side effects: - * The procedure panics if it detects anything wrong with - * the embedded image. + * The function panics if it detects anything wrong with the embedded + * image. * *-------------------------------------------------------------- */ static void -EmbImageCheckProc(eiPtr, linePtr) - TkTextSegment *eiPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line containing segment. */ +EmbImageCheckProc( + TkTextSegment *eiPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line containing segment. */ { if (eiPtr->nextPtr == NULL) { - panic("EmbImageCheckProc: embedded image is last segment in line"); + Tcl_Panic("EmbImageCheckProc: embedded image is last segment in line"); } if (eiPtr->size != 1) { - panic("EmbImageCheckProc: embedded image has size %d", eiPtr->size); + Tcl_Panic("EmbImageCheckProc: embedded image has size %d", + eiPtr->size); } } @@ -694,37 +628,35 @@ EmbImageCheckProc(eiPtr, linePtr) * * EmbImageDisplayProc -- * - * This procedure is invoked by the text displaying code - * when it is time to actually draw an embedded image - * chunk on the screen. + * This function is invoked by the text displaying code when it is time + * to actually draw an embedded image chunk on the screen. * * Results: * None. * * Side effects: - * The embedded image gets moved to the correct location - * and drawn onto the display. + * The embedded image gets moved to the correct location and drawn onto + * the display. * *-------------------------------------------------------------- */ static void -EmbImageDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) - TkTextDispChunk *chunkPtr; /* Chunk that is to be drawn. */ - int x; /* X-position in dst at which to - * draw this chunk (differs from - * the x-position in the chunk because - * of scrolling). */ - int y; /* Top of rectangular bounding box - * for line: tells where to draw this - * chunk in dst (x-position is in - * the chunk itself). */ - int lineHeight; /* Total height of line. */ - int baseline; /* Offset of baseline from y. */ - Display *display; /* Display to use for drawing. */ - Drawable dst; /* Pixmap or window in which to draw */ - int screenY; /* Y-coordinate in text window that - * corresponds to y. */ +EmbImageDisplayProc( + TkText *textPtr, + TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */ + int x, /* X-position in dst at which to draw this + * chunk (differs from the x-position in the + * chunk because of scrolling). */ + int y, /* Top of rectangular bounding box for line: + * tells where to draw this chunk in dst + * (x-position is in the chunk itself). */ + int lineHeight, /* Total height of line. */ + int baseline, /* Offset of baseline from y. */ + Display *display, /* Display to use for drawing. */ + Drawable dst, /* Pixmap or window in which to draw */ + int screenY) /* Y-coordinate in text window that + * corresponds to y. */ { TkTextSegment *eiPtr = (TkTextSegment *) chunkPtr->clientData; int lineX, imageX, imageY, width, height; @@ -739,16 +671,15 @@ EmbImageDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) } /* - * Compute the image's location and size in the text widget, taking - * into account the align value for the image. + * Compute the image's location and size in the text widget, taking into + * account the align value for the image. */ - EmbImageBboxProc(chunkPtr, 0, y, lineHeight, baseline, &lineX, + EmbImageBboxProc(textPtr, chunkPtr, 0, y, lineHeight, baseline, &lineX, &imageY, &width, &height); imageX = lineX - chunkPtr->x + x; - Tk_RedrawImage(image, 0, 0, width, height, dst, - imageX, imageY); + Tk_RedrawImage(image, 0, 0, width, height, dst, imageX, imageY); } /* @@ -756,17 +687,16 @@ EmbImageDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) * * EmbImageBboxProc -- * - * This procedure is called to compute the bounding box of - * the area occupied by an embedded image. + * This function is called to compute the bounding box of the area + * occupied by an embedded image. * * Results: - * There is no return value. *xPtr and *yPtr are filled in - * with the coordinates of the upper left corner of the - * image, and *widthPtr and *heightPtr are filled in with - * the dimensions of the image in pixels. Note: not all - * of the returned bbox is necessarily visible on the screen - * (the rightmost part might be off-screen to the right, - * and the bottommost part might be off-screen to the bottom). + * There is no return value. *xPtr and *yPtr are filled in with the + * coordinates of the upper left corner of the image, and *widthPtr and + * *heightPtr are filled in with the dimensions of the image in pixels. + * Note: not all of the returned bbox is necessarily visible on the + * screen (the rightmost part might be off-screen to the right, and the + * bottommost part might be off-screen to the bottom). * * Side effects: * None. @@ -775,22 +705,22 @@ EmbImageDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) */ static void -EmbImageBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, - widthPtr, heightPtr) - TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */ - int index; /* Index of desired character within - * the chunk. */ - int y; /* Topmost pixel in area allocated - * for this line. */ - int lineHeight; /* Total height of line. */ - int baseline; /* Location of line's baseline, in - * pixels measured down from y. */ - int *xPtr, *yPtr; /* Gets filled in with coords of - * character's upper-left pixel. */ - int *widthPtr; /* Gets filled in with width of - * character, in pixels. */ - int *heightPtr; /* Gets filled in with height of - * character, in pixels. */ +EmbImageBboxProc( + TkText *textPtr, + TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */ + int index, /* Index of desired character within the + * chunk. */ + int y, /* Topmost pixel in area allocated for this + * line. */ + int lineHeight, /* Total height of line. */ + int baseline, /* Location of line's baseline, in pixels + * measured down from y. */ + int *xPtr, int *yPtr, /* Gets filled in with coords of character's + * upper-left pixel. */ + int *widthPtr, /* Gets filled in with width of image, in + * pixels. */ + int *heightPtr) /* Gets filled in with height of image, in + * pixels. */ { TkTextSegment *eiPtr = (TkTextSegment *) chunkPtr->clientData; Tk_Image image; @@ -802,20 +732,22 @@ EmbImageBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, *widthPtr = 0; *heightPtr = 0; } + *xPtr = chunkPtr->x + eiPtr->body.ei.padX; + switch (eiPtr->body.ei.align) { - case ALIGN_BOTTOM: - *yPtr = y + (lineHeight - *heightPtr - eiPtr->body.ei.padY); - break; - case ALIGN_CENTER: - *yPtr = y + (lineHeight - *heightPtr)/2; - break; - case ALIGN_TOP: - *yPtr = y + eiPtr->body.ei.padY; - break; - case ALIGN_BASELINE: - *yPtr = y + (baseline - *heightPtr); - break; + case ALIGN_BOTTOM: + *yPtr = y + (lineHeight - *heightPtr - eiPtr->body.ei.padY); + break; + case ALIGN_CENTER: + *yPtr = y + (lineHeight - *heightPtr)/2; + break; + case ALIGN_TOP: + *yPtr = y + eiPtr->body.ei.padY; + break; + case ALIGN_BASELINE: + *yPtr = y + (baseline - *heightPtr); + break; } } @@ -824,14 +756,13 @@ EmbImageBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, * * TkTextImageIndex -- * - * Given the name of an embedded image within a text widget, - * returns an index corresponding to the image's position - * in the text. + * Given the name of an embedded image within a text widget, returns an + * index corresponding to the image's position in the text. * * Results: - * The return value is 1 if there is an embedded image by - * the given name in the text widget, 0 otherwise. If the - * image exists, *indexPtr is filled in with its index. + * The return value is 1 if there is an embedded image by the given name + * in the text widget, 0 otherwise. If the image exists, *indexPtr is + * filled in with its index. * * Side effects: * None. @@ -840,20 +771,20 @@ EmbImageBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, */ int -TkTextImageIndex(textPtr, name, indexPtr) - TkText *textPtr; /* Text widget containing image. */ - CONST char *name; /* Name of image. */ - TkTextIndex *indexPtr; /* Index information gets stored here. */ +TkTextImageIndex( + TkText *textPtr, /* Text widget containing image. */ + const char *name, /* Name of image. */ + TkTextIndex *indexPtr) /* Index information gets stored here. */ { Tcl_HashEntry *hPtr; TkTextSegment *eiPtr; - hPtr = Tcl_FindHashEntry(&textPtr->imageTable, name); + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name); if (hPtr == NULL) { return 0; } eiPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); - indexPtr->tree = textPtr->tree; + indexPtr->tree = textPtr->sharedTextPtr->tree; indexPtr->linePtr = eiPtr->body.ei.linePtr; indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr); return 1; @@ -864,8 +795,8 @@ TkTextImageIndex(textPtr, name, indexPtr) * * EmbImageProc -- * - * This procedure is called by the image code whenever an - * image or its contents changes. + * This function is called by the image code whenever an image or its + * contents changes. * * Results: * None. @@ -877,20 +808,37 @@ TkTextImageIndex(textPtr, name, indexPtr) */ static void -EmbImageProc(clientData, x, y, width, height, imgWidth, imgHeight) - ClientData clientData; /* Pointer to widget record. */ - int x, y; /* Upper left pixel (within image) - * that must be redisplayed. */ - int width, height; /* Dimensions of area to redisplay - * (may be <= 0). */ - int imgWidth, imgHeight; /* New dimensions of image. */ +EmbImageProc( + ClientData clientData, /* Pointer to widget record. */ + int x, int y, /* Upper left pixel (within image) that must + * be redisplayed. */ + int width, int height, /* Dimensions of area to redisplay (may be + * <= 0). */ + int imgWidth, int imgHeight)/* New dimensions of image. */ { TkTextSegment *eiPtr = (TkTextSegment *) clientData; TkTextIndex index; - index.tree = eiPtr->body.ei.textPtr->tree; + index.tree = eiPtr->body.ei.sharedTextPtr->tree; index.linePtr = eiPtr->body.ei.linePtr; index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr); - TkTextChanged(eiPtr->body.ei.textPtr, &index, &index); + TkTextChanged(eiPtr->body.ei.sharedTextPtr, NULL, &index, &index); + + /* + * It's probably not true that all image changes can change the line + * height, so we could be more efficient here and only call this when + * necessary. + */ + + TkTextInvalidateLineMetrics(eiPtr->body.ei.sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTextIndex.c b/generic/tkTextIndex.c index 7cfeaea..a9b0bed 100644 --- a/generic/tkTextIndex.c +++ b/generic/tkTextIndex.c @@ -1,18 +1,17 @@ -/* +/* * tkTextIndex.c -- * - * This module provides procedures that manipulate indices for - * text widgets. + * This module provides functions that manipulate indices for text + * widgets. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "default.h" -#include "tkPort.h" #include "tkInt.h" #include "tkText.h" @@ -23,21 +22,354 @@ #define LAST_CHAR 1000000 /* - * Forward declarations for procedures defined later in this file: + * Modifiers for index parsing: 'display', 'any' or nothing. + */ + +#define TKINDEX_NONE 0 +#define TKINDEX_DISPLAY 1 +#define TKINDEX_ANY 2 + +/* + * Forward declarations for functions defined later in this file: + */ + +static CONST char * ForwBack(TkText *textPtr, CONST char *string, + TkTextIndex *indexPtr); +static CONST char * StartEnd(TkText *textPtr, CONST char *string, + TkTextIndex *indexPtr); +static int GetIndex(Tcl_Interp *interp, TkSharedText *sharedPtr, + TkText *textPtr, CONST char *string, + TkTextIndex *indexPtr, int *canCachePtr); + +/* + * The "textindex" Tcl_Obj definition: + */ + +static void DupTextIndexInternalRep(Tcl_Obj *srcPtr, + Tcl_Obj *copyPtr); +static void FreeTextIndexInternalRep(Tcl_Obj *listPtr); +static int SetTextIndexFromAny(Tcl_Interp *interp, + Tcl_Obj *objPtr); +static void UpdateStringOfTextIndex(Tcl_Obj *objPtr); + +/* + * Accessor macros for the "textindex" type. + */ + +#define GET_TEXTINDEX(objPtr) \ + ((TkTextIndex *) (objPtr)->internalRep.twoPtrValue.ptr1) +#define GET_INDEXEPOCH(objPtr) \ + (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2)) +#define SET_TEXTINDEX(objPtr, indexPtr) \ + ((objPtr)->internalRep.twoPtrValue.ptr1 = (VOID *) (indexPtr)) +#define SET_INDEXEPOCH(objPtr, epoch) \ + ((objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(epoch)) + +/* + * Define the 'textindex' object type, which Tk uses to represent indices in + * text widgets internally. + */ + +Tcl_ObjType tkTextIndexType = { + "textindex", /* name */ + FreeTextIndexInternalRep, /* freeIntRepProc */ + DupTextIndexInternalRep, /* dupIntRepProc */ + NULL, /* updateStringProc */ + SetTextIndexFromAny /* setFromAnyProc */ +}; + +static void +FreeTextIndexInternalRep( + Tcl_Obj *indexObjPtr) /* TextIndex object with internal rep to + * free. */ +{ + TkTextIndex *indexPtr = GET_TEXTINDEX(indexObjPtr); + if (indexPtr->textPtr != NULL) { + if (--indexPtr->textPtr->refCount == 0) { + /* + * The text widget has been deleted and we need to free it now. + */ + + ckfree((char *) (indexPtr->textPtr)); + } + } + ckfree((char *) indexPtr); +} + +static void +DupTextIndexInternalRep( + Tcl_Obj *srcPtr, /* TextIndex obj with internal rep to copy. */ + Tcl_Obj *copyPtr) /* TextIndex obj with internal rep to set. */ +{ + int epoch; + TkTextIndex *dupIndexPtr, *indexPtr; + + dupIndexPtr = (TkTextIndex *) ckalloc(sizeof(TkTextIndex)); + indexPtr = GET_TEXTINDEX(srcPtr); + epoch = GET_INDEXEPOCH(srcPtr); + + dupIndexPtr->tree = indexPtr->tree; + dupIndexPtr->linePtr = indexPtr->linePtr; + dupIndexPtr->byteIndex = indexPtr->byteIndex; + dupIndexPtr->textPtr = indexPtr->textPtr; + if (dupIndexPtr->textPtr != NULL) { + dupIndexPtr->textPtr->refCount++; + } + SET_TEXTINDEX(copyPtr, dupIndexPtr); + SET_INDEXEPOCH(copyPtr, epoch); + copyPtr->typePtr = &tkTextIndexType; +} + +/* + * This will not be called except by TkTextNewIndexObj below. This is because + * if a TkTextIndex is no longer valid, it is not possible to regenerate the + * string representation. */ -static CONST char * ForwBack _ANSI_ARGS_((CONST char *string, - TkTextIndex *indexPtr)); -static CONST char * StartEnd _ANSI_ARGS_((CONST char *string, - TkTextIndex *indexPtr)); +static void +UpdateStringOfTextIndex( + Tcl_Obj *objPtr) +{ + char buffer[TK_POS_CHARS]; + register int len; + + CONST TkTextIndex *indexPtr = GET_TEXTINDEX(objPtr); + + len = TkTextPrintIndex(indexPtr->textPtr, indexPtr, buffer); + + objPtr->bytes = ckalloc((unsigned) len + 1); + strcpy(objPtr->bytes, buffer); + objPtr->length = len; +} + +static int +SetTextIndexFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + Tcl_Obj *objPtr) /* The object to convert. */ +{ + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "can't convert value to textindex except via TkTextGetIndexFromObj API", + -1); + return TCL_ERROR; +} + +/* + *--------------------------------------------------------------------------- + * + * MakeObjIndex -- + * + * This function generates a Tcl_Obj description of an index, suitable + * for reading in again later. If the 'textPtr' is NULL then we still + * generate an index object, but it's internal description is deemed + * non-cacheable, and therefore effectively useless (apart from as a + * temporary memory storage). This is used for indices whose meaning is + * very temporary (like @0,0 or the name of a mark or tag). The mapping + * from such strings/objects to actual TkTextIndex pointers is not stable + * to minor text widget changes which we do not track (we track + * insertions and deletions). + * + * Results: + * A pointer to an allocated TkTextIndex which will be freed + * automatically when the Tcl_Obj is used for other purposes. + * + * Side effects: + * A small amount of memory is allocated. + * + *--------------------------------------------------------------------------- + */ + +static TkTextIndex * +MakeObjIndex( + TkText *textPtr, /* Information about text widget. */ + Tcl_Obj *objPtr, /* Object containing description of + * position. */ + CONST TkTextIndex *origPtr) /* Pointer to index. */ +{ + TkTextIndex *indexPtr = (TkTextIndex *) ckalloc(sizeof(TkTextIndex)); + + indexPtr->tree = origPtr->tree; + indexPtr->linePtr = origPtr->linePtr; + indexPtr->byteIndex = origPtr->byteIndex; + SET_TEXTINDEX(objPtr, indexPtr); + objPtr->typePtr = &tkTextIndexType; + indexPtr->textPtr = textPtr; + + if (textPtr != NULL) { + textPtr->refCount++; + SET_INDEXEPOCH(objPtr, textPtr->sharedTextPtr->stateEpoch); + } else { + SET_INDEXEPOCH(objPtr, 0); + } + return indexPtr; +} + +CONST TkTextIndex * +TkTextGetIndexFromObj( + Tcl_Interp *interp, /* Use this for error reporting. */ + TkText *textPtr, /* Information about text widget. */ + Tcl_Obj *objPtr) /* Object containing description of + * position. */ +{ + TkTextIndex index; + TkTextIndex *indexPtr = NULL; + int cache; + + if (objPtr->typePtr == &tkTextIndexType) { + int epoch; + + indexPtr = GET_TEXTINDEX(objPtr); + epoch = GET_INDEXEPOCH(objPtr); + + if (epoch == textPtr->sharedTextPtr->stateEpoch) { + if (indexPtr->textPtr == textPtr) { + return indexPtr; + } + } + } + + /* + * The object is either not an index type or referred to a different text + * widget, or referred to the correct widget, but it is out of date (text + * has been added/deleted since). + */ + + if (GetIndex(interp, NULL, textPtr, Tcl_GetString(objPtr), &index, + &cache) != TCL_OK) { + return NULL; + } + + if (objPtr->typePtr != NULL) { + if (objPtr->bytes == NULL) { + objPtr->typePtr->updateStringProc(objPtr); + } + if ((objPtr->typePtr->freeIntRepProc) != NULL) { + (*objPtr->typePtr->freeIntRepProc)(objPtr); + } + } + + return MakeObjIndex((cache ? textPtr : NULL), objPtr, &index); +} + +/* + *--------------------------------------------------------------------------- + * + * TkTextNewIndexObj -- + * + * This function generates a Tcl_Obj description of an index, suitable + * for reading in again later. The index generated is effectively stable + * to all except insertion/deletion operations on the widget. + * + * Results: + * A new Tcl_Obj with refCount zero. + * + * Side effects: + * A small amount of memory is allocated. + * + *--------------------------------------------------------------------------- + */ + +Tcl_Obj * +TkTextNewIndexObj( + TkText *textPtr, /* Text widget for this index */ + CONST TkTextIndex *indexPtr)/* Pointer to index. */ +{ + Tcl_Obj *retVal; + + retVal = Tcl_NewObj(); + retVal->bytes = NULL; + + /* + * Assumption that the above call returns an object with: + * retVal->typePtr == NULL + */ + + MakeObjIndex(textPtr, retVal, indexPtr); + + /* + * Unfortunately, it isn't possible for us to regenerate the string + * representation so we have to create it here, while we can be sure the + * contents of the index are still valid. + */ + + UpdateStringOfTextIndex(retVal); + return retVal; +} + +/* + *--------------------------------------------------------------------------- + * + * TkTextMakePixelIndex -- + * + * Given a pixel index and a byte index, look things up in the B-tree and + * fill in a TkTextIndex structure. + * + * The valid input range for pixelIndex is from 0 to the number of pixels + * in the widget-1. Anything outside that range will be rounded to the + * closest acceptable value. + * + * Results: + * + * The structure at *indexPtr is filled in with information about the + * character at pixelIndex (or the closest existing character, if the + * specified one doesn't exist), and the number of excess pixels is + * returned as a result. This means if the given pixel index is exactly + * correct for the top-edge of the indexPtr, then zero will be returned, + * and otherwise we will return the calculation 'desired pixelIndex' - + * 'actual pixel index of indexPtr'. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkTextMakePixelIndex( + TkText *textPtr, /* The Text Widget */ + int pixelIndex, /* Pixel-index of desired line (0 means first + * pixel of first line of text). */ + TkTextIndex *indexPtr) /* Structure to fill in. */ +{ + int pixelOffset = 0; + + indexPtr->tree = textPtr->sharedTextPtr->tree; + indexPtr->textPtr = textPtr; + + if (pixelIndex < 0) { + pixelIndex = 0; + } + indexPtr->linePtr = TkBTreeFindPixelLine(textPtr->sharedTextPtr->tree, + textPtr, pixelIndex, &pixelOffset); + + /* + * 'pixelIndex' was too large, so we try again, just to find the last + * pixel in the window. + */ + + if (indexPtr->linePtr == NULL) { + int lastMinusOne = TkBTreeNumPixels(textPtr->sharedTextPtr->tree, + textPtr)-1; + + indexPtr->linePtr = TkBTreeFindPixelLine(textPtr->sharedTextPtr->tree, + textPtr, lastMinusOne, &pixelOffset); + indexPtr->byteIndex = 0; + return pixelOffset; + } + indexPtr->byteIndex = 0; + + if (pixelOffset <= 0) { + return 0; + } + return TkTextMeasureDown(textPtr, indexPtr, pixelOffset); +} /* *--------------------------------------------------------------------------- * * TkTextMakeByteIndex -- * - * Given a line index and a byte index, look things up in the B-tree - * and fill in a TkTextIndex structure. + * Given a line index and a byte index, look things up in the B-tree and + * fill in a TkTextIndex structure. * * Results: * The structure at *indexPtr is filled in with information about the @@ -52,13 +384,14 @@ static CONST char * StartEnd _ANSI_ARGS_((CONST char *string, */ TkTextIndex * -TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr) - TkTextBTree tree; /* Tree that lineIndex and charIndex refer +TkTextMakeByteIndex( + TkTextBTree tree, /* Tree that lineIndex and byteIndex refer * to. */ - int lineIndex; /* Index of desired line (0 means first - * line of text). */ - int byteIndex; /* Byte index of desired character. */ - TkTextIndex *indexPtr; /* Structure to fill in. */ + CONST TkText *textPtr, + int lineIndex, /* Index of desired line (0 means first line + * of text). */ + int byteIndex, /* Byte index of desired character. */ + TkTextIndex *indexPtr) /* Structure to fill in. */ { TkTextSegment *segPtr; int index; @@ -73,9 +406,10 @@ TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr) if (byteIndex < 0) { byteIndex = 0; } - indexPtr->linePtr = TkBTreeFindLine(tree, lineIndex); + indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, lineIndex); if (indexPtr->linePtr == NULL) { - indexPtr->linePtr = TkBTreeFindLine(tree, TkBTreeNumLines(tree)); + indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, + TkBTreeNumLines(tree, textPtr)); byteIndex = 0; } if (byteIndex == 0) { @@ -84,19 +418,19 @@ TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr) } /* - * Verify that the index is within the range of the line and points - * to a valid character boundary. + * Verify that the index is within the range of the line and points to a + * valid character boundary. */ index = 0; for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) { if (segPtr == NULL) { /* - * Use the index of the last character in the line. Since - * the last character on the line is guaranteed to be a '\n', - * we can back up a constant sizeof(char) bytes. + * Use the index of the last character in the line. Since the last + * character on the line is guaranteed to be a '\n', we can back + * up a constant sizeof(char) bytes. */ - + indexPtr->byteIndex = index - sizeof(char); break; } @@ -105,7 +439,7 @@ TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr) if ((byteIndex > index) && (segPtr->typePtr == &tkTextCharType)) { /* * Prevent UTF-8 character from being split up by ensuring - * that byteIndex falls on a character boundary. If index + * that byteIndex falls on a character boundary. If index * falls in the middle of a UTF-8 character, it will be * adjusted to the end of that UTF-8 character. */ @@ -127,8 +461,8 @@ TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr) * * TkTextMakeCharIndex -- * - * Given a line index and a character index, look things up in the - * B-tree and fill in a TkTextIndex structure. + * Given a line index and a character index, look things up in the B-tree + * and fill in a TkTextIndex structure. * * Results: * The structure at *indexPtr is filled in with information about the @@ -143,13 +477,14 @@ TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr) */ TkTextIndex * -TkTextMakeCharIndex(tree, lineIndex, charIndex, indexPtr) - TkTextBTree tree; /* Tree that lineIndex and charIndex refer +TkTextMakeCharIndex( + TkTextBTree tree, /* Tree that lineIndex and charIndex refer * to. */ - int lineIndex; /* Index of desired line (0 means first - * line of text). */ - int charIndex; /* Index of desired character. */ - TkTextIndex *indexPtr; /* Structure to fill in. */ + TkText *textPtr, + int lineIndex, /* Index of desired line (0 means first line + * of text). */ + int charIndex, /* Index of desired character. */ + TkTextIndex *indexPtr) /* Structure to fill in. */ { register TkTextSegment *segPtr; char *p, *start, *end; @@ -164,26 +499,27 @@ TkTextMakeCharIndex(tree, lineIndex, charIndex, indexPtr) if (charIndex < 0) { charIndex = 0; } - indexPtr->linePtr = TkBTreeFindLine(tree, lineIndex); + indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, lineIndex); if (indexPtr->linePtr == NULL) { - indexPtr->linePtr = TkBTreeFindLine(tree, TkBTreeNumLines(tree)); + indexPtr->linePtr = TkBTreeFindLine(tree, textPtr, + TkBTreeNumLines(tree, textPtr)); charIndex = 0; } /* - * Verify that the index is within the range of the line. - * If not, just use the index of the last character in the line. + * Verify that the index is within the range of the line. If not, just use + * the index of the last character in the line. */ index = 0; for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) { if (segPtr == NULL) { /* - * Use the index of the last character in the line. Since - * the last character on the line is guaranteed to be a '\n', - * we can back up a constant sizeof(char) bytes. + * Use the index of the last character in the line. Since the last + * character on the line is guaranteed to be a '\n', we can back + * up a constant sizeof(char) bytes. */ - + indexPtr->byteIndex = index - sizeof(char); break; } @@ -220,14 +556,14 @@ TkTextMakeCharIndex(tree, lineIndex, charIndex, indexPtr) * * TkTextIndexToSeg -- * - * Given an index, this procedure returns the segment and offset - * within segment for the index. + * Given an index, this function returns the segment and offset within + * segment for the index. * * Results: - * The return value is a pointer to the segment referred to by - * indexPtr; this will always be a segment with non-zero size. The - * variable at *offsetPtr is set to hold the integer offset within - * the segment of the character given by indexPtr. + * The return value is a pointer to the segment referred to by indexPtr; + * this will always be a segment with non-zero size. The variable at + * *offsetPtr is set to hold the integer offset within the segment of the + * character given by indexPtr. * * Side effects: * None. @@ -236,9 +572,9 @@ TkTextMakeCharIndex(tree, lineIndex, charIndex, indexPtr) */ TkTextSegment * -TkTextIndexToSeg(indexPtr, offsetPtr) - CONST TkTextIndex *indexPtr;/* Text index. */ - int *offsetPtr; /* Where to store offset within segment, or +TkTextIndexToSeg( + CONST TkTextIndex *indexPtr,/* Text index. */ + int *offsetPtr) /* Where to store offset within segment, or * NULL if offset isn't wanted. */ { TkTextSegment *segPtr; @@ -260,7 +596,7 @@ TkTextIndexToSeg(indexPtr, offsetPtr) * * TkTextSegToOffset -- * - * Given a segment pointer and the line containing it, this procedure + * Given a segment pointer and the line containing it, this function * returns the offset of the segment within its line. * * Results: @@ -274,14 +610,13 @@ TkTextIndexToSeg(indexPtr, offsetPtr) */ int -TkTextSegToOffset(segPtr, linePtr) - CONST TkTextSegment *segPtr;/* Segment whose offset is desired. */ - CONST TkTextLine *linePtr; /* Line containing segPtr. */ +TkTextSegToOffset( + CONST TkTextSegment *segPtr,/* Segment whose offset is desired. */ + CONST TkTextLine *linePtr) /* Line containing segPtr. */ { CONST TkTextSegment *segPtr2; - int offset; + int offset = 0; - offset = 0; for (segPtr2 = linePtr->segPtr; segPtr2 != segPtr; segPtr2 = segPtr2->nextPtr) { offset += segPtr2->size; @@ -292,15 +627,73 @@ TkTextSegToOffset(segPtr, linePtr) /* *--------------------------------------------------------------------------- * + * TkTextGetObjIndex -- + * + * Simpler wrapper around the string based function, but could be + * enhanced with a new object type in the future. + * + * Results: + * see TkTextGetIndex + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkTextGetObjIndex( + Tcl_Interp *interp, /* Use this for error reporting. */ + TkText *textPtr, /* Information about text widget. */ + Tcl_Obj *idxObj, /* Object containing textual description of + * position. */ + TkTextIndex *indexPtr) /* Index structure to fill in. */ +{ + return GetIndex(interp, NULL, textPtr, Tcl_GetString(idxObj), indexPtr, + NULL); +} + +/* + *--------------------------------------------------------------------------- + * + * TkTextSharedGetObjIndex -- + * + * Simpler wrapper around the string based function, but could be + * enhanced with a new object type in the future. + * + * Results: + * see TkTextGetIndex + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkTextSharedGetObjIndex( + Tcl_Interp *interp, /* Use this for error reporting. */ + TkSharedText *sharedTextPtr,/* Information about text widget. */ + Tcl_Obj *idxObj, /* Object containing textual description of + * position. */ + TkTextIndex *indexPtr) /* Index structure to fill in. */ +{ + return GetIndex(interp, sharedTextPtr, NULL, Tcl_GetString(idxObj), + indexPtr, NULL); +} + +/* + *--------------------------------------------------------------------------- + * * TkTextGetIndex -- * * Given a string, return the index that is described. * * Results: - * The return value is a standard Tcl return result. If TCL_OK is + * The return value is a standard Tcl return result. If TCL_OK is * returned, then everything went well and the index at *indexPtr is - * filled in; otherwise TCL_ERROR is returned and an error message - * is left in the interp's result. + * filled in; otherwise TCL_ERROR is returned and an error message is + * left in the interp's result. * * Side effects: * None. @@ -309,33 +702,70 @@ TkTextSegToOffset(segPtr, linePtr) */ int -TkTextGetIndex(interp, textPtr, string, indexPtr) - Tcl_Interp *interp; /* Use this for error reporting. */ - TkText *textPtr; /* Information about text widget. */ - CONST char *string; /* Textual description of position. */ - TkTextIndex *indexPtr; /* Index structure to fill in. */ +TkTextGetIndex( + Tcl_Interp *interp, /* Use this for error reporting. */ + TkText *textPtr, /* Information about text widget. */ + CONST char *string, /* Textual description of position. */ + TkTextIndex *indexPtr) /* Index structure to fill in. */ +{ + return GetIndex(interp, NULL, textPtr, string, indexPtr, NULL); +} + +/* + *--------------------------------------------------------------------------- + * + * GetIndex -- + * + * Given a string, return the index that is described. + * + * Results: + * The return value is a standard Tcl return result. If TCL_OK is + * returned, then everything went well and the index at *indexPtr is + * filled in; otherwise TCL_ERROR is returned and an error message is + * left in the interp's result. + * + * If *canCachePtr is non-NULL, and everything went well, the integer it + * points to is set to 1 if the indexPtr is something which can be + * cached, and zero otherwise. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static int +GetIndex( + Tcl_Interp *interp, /* Use this for error reporting. */ + TkSharedText *sharedPtr, + TkText *textPtr, /* Information about text widget. */ + CONST char *string, /* Textual description of position. */ + TkTextIndex *indexPtr, /* Index structure to fill in. */ + int *canCachePtr) /* Pointer to integer to store whether we can + * cache the index (or NULL). */ { char *p, *end, *endOfBase; - Tcl_HashEntry *hPtr; - TkTextTag *tagPtr; - TkTextSearch search; TkTextIndex first, last; int wantLast, result; char c; CONST char *cp; Tcl_DString copy; + int canCache = 0; + + if (sharedPtr == NULL) { + sharedPtr = textPtr->sharedTextPtr; + } /* *--------------------------------------------------------------------- - * Stage 1: check to see if the index consists of nothing but a mark - * name. We do this check now even though it's also done later, in - * order to allow mark names that include funny characters such as - * spaces or "+1c". + * Stage 1: check to see if the index consists of nothing but a mark name. + * We do this check now even though it's also done later, in order to + * allow mark names that include funny characters such as spaces or "+1c". *--------------------------------------------------------------------- */ if (TkTextMarkNameToIndex(textPtr, string, indexPtr) == TCL_OK) { - return TCL_OK; + goto done; } /* @@ -344,19 +774,24 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) *------------------------------------------------ */ - indexPtr->tree = textPtr->tree; + indexPtr->tree = sharedPtr->tree; /* - * First look for the form "tag.first" or "tag.last" where "tag" - * is the name of a valid tag. Try to use up as much as possible - * of the string in this check (strrchr instead of strchr below). - * Doing the check now, and in this way, allows tag names to include - * funny characters like "@" or "+1c". + * First look for the form "tag.first" or "tag.last" where "tag" is the + * name of a valid tag. Try to use up as much as possible of the string in + * this check (strrchr instead of strchr below). Doing the check now, and + * in this way, allows tag names to include funny characters like "@" or + * "+1c". */ Tcl_DStringInit(©); p = strrchr(Tcl_DStringAppend(©, string, -1), '.'); if (p != NULL) { + TkTextSearch search; + TkTextTag *tagPtr; + Tcl_HashEntry *hPtr = NULL; + CONST char *tagName; + if ((p[1] == 'f') && (strncmp(p+1, "first", 5) == 0)) { wantLast = 0; endOfBase = p+6; @@ -366,23 +801,42 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) } else { goto tryxy; } - *p = 0; - hPtr = Tcl_FindHashEntry(&textPtr->tagTable, Tcl_DStringValue(©)); - *p = '.'; - if (hPtr == NULL) { + + tagPtr = NULL; + tagName = Tcl_DStringValue(©); + if (((p - tagName) == 3) && !strncmp(tagName, "sel", 3)) { + /* + * Special case for sel tag which is not stored in the hash table. + */ + + tagPtr = textPtr->selTagPtr; + } else { + *p = 0; + hPtr = Tcl_FindHashEntry(&sharedPtr->tagTable, tagName); + *p = '.'; + if (hPtr != NULL) { + tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr); + } + } + + if (tagPtr == NULL) { goto tryxy; } - tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr); - TkTextMakeByteIndex(textPtr->tree, 0, 0, &first); - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, - &last); + + TkTextMakeByteIndex(sharedPtr->tree, textPtr, 0, 0, &first); + TkTextMakeByteIndex(sharedPtr->tree, textPtr, + TkBTreeNumLines(sharedPtr->tree, textPtr), 0, &last); TkBTreeStartSearch(&first, &last, tagPtr, &search); if (!TkBTreeCharTagged(&first, tagPtr) && !TkBTreeNextTag(&search)) { + if (tagPtr == textPtr->selTagPtr) { + tagName = "sel"; + } else { + tagName = Tcl_GetHashKey(&sharedPtr->tagTable, hPtr); + } Tcl_ResetResult(interp); Tcl_AppendResult(interp, "text doesn't contain any characters tagged with \"", - Tcl_GetHashKey(&textPtr->tagTable, hPtr), "\"", - (char *) NULL); + tagName, "\"", NULL); Tcl_DStringFree(©); return TCL_ERROR; } @@ -395,7 +849,7 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) goto gotBase; } - tryxy: + tryxy: if (string[0] == '@') { /* * Find character at a given x,y location in the window. @@ -413,9 +867,9 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) if (end == cp) { goto error; } - TkTextPixelIndex(textPtr, x, y, indexPtr); + TkTextPixelIndex(textPtr, x, y, indexPtr, NULL); endOfBase = end; - goto gotBase; + goto gotBase; } if (isdigit(UCHAR(string[0])) || (string[0] == '-')) { @@ -440,7 +894,9 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) } endOfBase = end; } - TkTextMakeCharIndex(textPtr->tree, lineIndex, charIndex, indexPtr); + TkTextMakeCharIndex(sharedPtr->tree, textPtr, lineIndex, charIndex, + indexPtr); + canCache = 1; goto gotBase; } @@ -470,8 +926,9 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) * Base position is end of text. */ - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), - 0, indexPtr); + TkTextMakeByteIndex(sharedPtr->tree, textPtr, + TkBTreeNumLines(sharedPtr->tree, textPtr), 0, indexPtr); + canCache = 1; goto gotBase; } else { /* @@ -488,7 +945,7 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) } /* - * See if the base position is the name of an embedded image + * See if the base position is the name of an embedded image. */ c = *endOfBase; @@ -503,14 +960,14 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) /* *------------------------------------------------------------------- - * Stage 3: process zero or more modifiers. Each modifier is either - * a keyword like "wordend" or "linestart", or it has the form - * "op count units" where op is + or -, count is a number, and units - * is "chars" or "lines". + * Stage 3: process zero or more modifiers. Each modifier is either a + * keyword like "wordend" or "linestart", or it has the form "op count + * units" where op is + or -, count is a number, and units is "chars" or + * "lines". *------------------------------------------------------------------- */ - gotBase: + gotBase: cp = endOfBase; while (1) { while (isspace(UCHAR(*cp))) { @@ -519,24 +976,31 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) if (*cp == 0) { break; } - + if ((*cp == '+') || (*cp == '-')) { - cp = ForwBack(cp, indexPtr); + cp = ForwBack(textPtr, cp, indexPtr); } else { - cp = StartEnd(cp, indexPtr); + cp = StartEnd(textPtr, cp, indexPtr); } if (cp == NULL) { goto error; } } Tcl_DStringFree(©); + + done: + if (canCachePtr != NULL) { + *canCachePtr = canCache; + } + if (indexPtr->linePtr == NULL) { + Tcl_Panic("Bad index created"); + } return TCL_OK; - error: + error: Tcl_DStringFree(©); Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad text index \"", string, "\"", - (char *) NULL); + Tcl_AppendResult(interp, "bad text index \"", string, "\"", NULL); return TCL_ERROR; } @@ -544,12 +1008,13 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) *--------------------------------------------------------------------------- * * TkTextPrintIndex -- - * - * This procedure generates a string description of an index, suitable - * for reading in again later. + * + * This function generates a string description of an index, suitable for + * reading in again later. * * Results: - * The characters pointed to by string are modified. + * The characters pointed to by string are modified. Returns the number + * of characters in the string. * * Side effects: * None. @@ -557,18 +1022,31 @@ TkTextGetIndex(interp, textPtr, string, indexPtr) *--------------------------------------------------------------------------- */ -void -TkTextPrintIndex(indexPtr, string) - CONST TkTextIndex *indexPtr;/* Pointer to index. */ - char *string; /* Place to store the position. Must have - * at least TK_POS_CHARS characters. */ +int +TkTextPrintIndex( + CONST TkText *textPtr, + CONST TkTextIndex *indexPtr,/* Pointer to index. */ + char *string) /* Place to store the position. Must have at + * least TK_POS_CHARS characters. */ { TkTextSegment *segPtr; + TkTextLine *linePtr; int numBytes, charIndex; numBytes = indexPtr->byteIndex; charIndex = 0; - for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) { + linePtr = indexPtr->linePtr; + + for (segPtr = linePtr->segPtr; ; segPtr = segPtr->nextPtr) { + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through eliding + * of a newline. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); + segPtr = linePtr->segPtr; + } if (numBytes <= segPtr->size) { break; } @@ -579,13 +1057,15 @@ TkTextPrintIndex(indexPtr, string) } numBytes -= segPtr->size; } + if (segPtr->typePtr == &tkTextCharType) { charIndex += Tcl_NumUtfChars(segPtr->body.chars, numBytes); } else { charIndex += numBytes; } - sprintf(string, "%d.%d", TkBTreeLineIndex(indexPtr->linePtr) + 1, - charIndex); + + return sprintf(string, "%d.%d", + TkBTreeLinesTo(textPtr, indexPtr->linePtr) + 1, charIndex); } /* @@ -607,9 +1087,9 @@ TkTextPrintIndex(indexPtr, string) */ int -TkTextIndexCmp(index1Ptr, index2Ptr) - CONST TkTextIndex *index1Ptr; /* First index. */ - CONST TkTextIndex *index2Ptr; /* Second index. */ +TkTextIndexCmp( + CONST TkTextIndex*index1Ptr,/* First index. */ + CONST TkTextIndex*index2Ptr)/* Second index. */ { int line1, line2; @@ -622,8 +1102,16 @@ TkTextIndexCmp(index1Ptr, index2Ptr) return 0; } } - line1 = TkBTreeLineIndex(index1Ptr->linePtr); - line2 = TkBTreeLineIndex(index2Ptr->linePtr); + + /* + * Assumption here that it is ok for comparisons to reflect the full + * B-tree and not just the portion that is available to any client. This + * should be true because the only indexPtr's we should be given are ones + * which are valid for the current client. + */ + + line1 = TkBTreeLinesTo(NULL, index1Ptr->linePtr); + line2 = TkBTreeLinesTo(NULL, index2Ptr->linePtr); if (line1 < line2) { return -1; } @@ -638,14 +1126,14 @@ TkTextIndexCmp(index1Ptr, index2Ptr) * * ForwBack -- * - * This procedure handles +/- modifiers for indices to adjust the - * index forwards or backwards. + * This function handles +/- modifiers for indices to adjust the index + * forwards or backwards. * * Results: - * If the modifier in string is successfully parsed then the return - * value is the address of the first character after the modifier, - * and *indexPtr is updated to reflect the modifier. If there is a - * syntax error in the modifier then NULL is returned. + * If the modifier in string is successfully parsed then the return value + * is the address of the first character after the modifier, and + * *indexPtr is updated to reflect the modifier. If there is a syntax + * error in the modifier then NULL is returned. * * Side effects: * None. @@ -654,16 +1142,16 @@ TkTextIndexCmp(index1Ptr, index2Ptr) */ static CONST char * -ForwBack(string, indexPtr) - CONST char *string; /* String to parse for additional info - * about modifier (count and units). - * Points to "+" or "-" that starts - * modifier. */ - TkTextIndex *indexPtr; /* Index to update as specified in string. */ +ForwBack( + TkText *textPtr, /* Information about text widget. */ + CONST char *string, /* String to parse for additional info about + * modifier (count and units). Points to "+" + * or "-" that starts modifier. */ + TkTextIndex *indexPtr) /* Index to update as specified in string. */ { register CONST char *p, *units; char *end; - int count, lineIndex; + int count, lineIndex, modifier; size_t length; /* @@ -684,53 +1172,193 @@ ForwBack(string, indexPtr) } /* - * Find the end of this modifier (next space or + or - character), - * then parse the unit specifier and update the position - * accordingly. + * Find the end of this modifier (next space or + or - character), then + * check if there is a textual 'display' or 'any' modifier. These + * modifiers can be their own word (in which case they can be abbreviated) + * or they can follow on to the actual unit in a single word (in which + * case no abbreviation is allowed). So, 'display lines', 'd lines', + * 'displaylin' are all ok, but 'dline' is not. */ - units = p; + units = p; while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '+') && (*p != '-')) { p++; } length = p - units; + if ((*units == 'd') && + (strncmp(units, "display", (length > 7 ? 7 : length)) == 0)) { + modifier = TKINDEX_DISPLAY; + if (length > 7) { + p -= (length - 7); + } + } else if ((*units == 'a') && + (strncmp(units, "any", (length > 3 ? 3 : length)) == 0)) { + modifier = TKINDEX_ANY; + if (length > 3) { + p -= (length - 3); + } + } else { + modifier = TKINDEX_NONE; + } + + /* + * If we had a modifier, which we interpreted ok, so now forward to the + * actual units. + */ + + if (modifier != TKINDEX_NONE) { + while (isspace(UCHAR(*p))) { + p++; + } + units = p; + while (*p!='\0' && !isspace(UCHAR(*p)) && *p!='+' && *p!='-') { + p++; + } + length = p - units; + } + + /* + * Finally parse the units. + */ + if ((*units == 'c') && (strncmp(units, "chars", length) == 0)) { + TkTextCountType type; + + if (modifier == TKINDEX_NONE) { + type = COUNT_INDICES; + } else if (modifier == TKINDEX_ANY) { + type = COUNT_CHARS; + } else { + type = COUNT_DISPLAY_CHARS; + } + if (*string == '+') { - TkTextIndexForwChars(indexPtr, count, indexPtr); + TkTextIndexForwChars(textPtr, indexPtr, count, indexPtr, type); } else { - TkTextIndexBackChars(indexPtr, count, indexPtr); + TkTextIndexBackChars(textPtr, indexPtr, count, indexPtr, type); } - } else if ((*units == 'l') && (strncmp(units, "lines", length) == 0)) { - lineIndex = TkBTreeLineIndex(indexPtr->linePtr); + } else if ((*units == 'i') && (strncmp(units, "indices", length) == 0)) { + TkTextCountType type; + + if (modifier == TKINDEX_DISPLAY) { + type = COUNT_DISPLAY_INDICES; + } else { + type = COUNT_INDICES; + } + if (*string == '+') { - lineIndex += count; + TkTextIndexForwChars(textPtr, indexPtr, count, indexPtr, type); } else { - lineIndex -= count; + TkTextIndexBackChars(textPtr, indexPtr, count, indexPtr, type); + } + } else if ((*units == 'l') && (strncmp(units, "lines", length) == 0)) { + if (modifier == TKINDEX_DISPLAY) { + /* + * Find the appropriate pixel offset of the current position + * within its display line. This also has the side-effect of + * moving indexPtr, but that doesn't matter since we will do it + * again below. + * + * Then find the right display line, and finally calculated the + * index we want in that display line, based on the original pixel + * offset. + */ + + int xOffset, forward; + + if (TkTextIsElided(textPtr, indexPtr, NULL)) { + /* + * Go forward to the first non-elided index. + */ + + TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr, + COUNT_DISPLAY_INDICES); + } /* - * The check below retains the character position, even - * if the line runs off the start of the file. Without - * it, the character position will get reset to 0 by - * TkTextMakeIndex. + * Unlike the Forw/BackChars code, the display line code is + * sensitive to whether we are genuinely going forwards or + * backwards. So, we need to determine that. This is important in + * the case where we have "+ -3 displaylines", for example. */ - if (lineIndex < 0) { - lineIndex = 0; + if ((count < 0) ^ (*string == '-')) { + forward = 0; + } else { + forward = 1; } - } - /* - * This doesn't work quite right if using a proportional font or - * UTF-8 characters with varying numbers of bytes. The cursor will - * bop around, keeping a constant number of bytes (not characters) - * from the left edge (but making sure not to split any UTF-8 - * characters), regardless of the x-position the index corresponds - * to. The proper way to do this is to get the x-position of the - * index and then pick the character at the same x-position in the - * new line. - */ - TkTextMakeByteIndex(indexPtr->tree, lineIndex, indexPtr->byteIndex, - indexPtr); + count = abs(count); + if (count == 0) { + return p; + } + + if (forward) { + TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, &xOffset); + while (count-- > 0) { + /* + * Go to the end of the line, then forward one char/byte + * to get to the beginning of the next line. + */ + + TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, NULL); + TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr, + COUNT_DISPLAY_INDICES); + } + } else { + TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, &xOffset); + while (count-- > 0) { + /* + * Go to the beginning of the line, then backward one + * char/byte to get to the end of the previous line. + */ + + TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL); + TkTextIndexBackChars(textPtr, indexPtr, 1, indexPtr, + COUNT_DISPLAY_INDICES); + } + TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL); + } + + /* + * This call assumes indexPtr is the beginning of a display line + * and moves it to the 'xOffset' position of that line, which is + * just what we want. + */ + + TkTextIndexOfX(textPtr, xOffset, indexPtr); + } else { + lineIndex = TkBTreeLinesTo(textPtr, indexPtr->linePtr); + if (*string == '+') { + lineIndex += count; + } else { + lineIndex -= count; + + /* + * The check below retains the character position, even if the + * line runs off the start of the file. Without it, the + * character position will get reset to 0 by TkTextMakeIndex. + */ + + if (lineIndex < 0) { + lineIndex = 0; + } + } + + /* + * This doesn't work quite right if using a proportional font or + * UTF-8 characters with varying numbers of bytes, or if there are + * embedded windows, images, etc. The cursor will bop around, + * keeping a constant number of bytes (not characters) from the + * left edge (but making sure not to split any UTF-8 characters), + * regardless of the x-position the index corresponds to. The + * proper way to do this is to get the x-position of the index and + * then pick the character at the same x-position in the new line. + */ + + TkTextMakeByteIndex(indexPtr->tree, textPtr, lineIndex, + indexPtr->byteIndex, indexPtr); + } } else { return NULL; } @@ -742,13 +1370,16 @@ ForwBack(string, indexPtr) * * TkTextIndexForwBytes -- * - * Given an index for a text widget, this procedure creates a new - * index that points "count" bytes ahead of the source index. + * Given an index for a text widget, this function creates a new index + * that points "count" bytes ahead of the source index. * * Results: * *dstPtr is modified to refer to the character "count" bytes after - * srcPtr, or to the last character in the TkText if there aren't - * "count" bytes left. + * srcPtr, or to the last character in the TkText if there aren't "count" + * bytes left. + * + * In this latter case, the function returns '1' to indicate that not all + * of 'byteCount' could be used. * * Side effects: * None. @@ -756,20 +1387,21 @@ ForwBack(string, indexPtr) *--------------------------------------------------------------------------- */ -void -TkTextIndexForwBytes(srcPtr, byteCount, dstPtr) - CONST TkTextIndex *srcPtr; /* Source index. */ - int byteCount; /* How many bytes forward to move. May be +int +TkTextIndexForwBytes( + CONST TkText *textPtr, + CONST TkTextIndex *srcPtr, /* Source index. */ + int byteCount, /* How many bytes forward to move. May be * negative. */ - TkTextIndex *dstPtr; /* Destination index: gets modified. */ + TkTextIndex *dstPtr) /* Destination index: gets modified. */ { TkTextLine *linePtr; TkTextSegment *segPtr; int lineLength; if (byteCount < 0) { - TkTextIndexBackBytes(srcPtr, -byteCount, dstPtr); - return; + TkTextIndexBackBytes(textPtr, srcPtr, -byteCount, dstPtr); + return 0; } *dstPtr = *srcPtr; @@ -786,18 +1418,18 @@ TkTextIndexForwBytes(srcPtr, byteCount, dstPtr) } /* - * If the new index is in the same line then we're done. - * Otherwise go on to the next line. + * If the new index is in the same line then we're done. Otherwise go + * on to the next line. */ if (dstPtr->byteIndex < lineLength) { - return; + return 0; } dstPtr->byteIndex -= lineLength; - linePtr = TkBTreeNextLine(dstPtr->linePtr); + linePtr = TkBTreeNextLine(textPtr, dstPtr->linePtr); if (linePtr == NULL) { dstPtr->byteIndex = lineLength - 1; - return; + return 1; } dstPtr->linePtr = linePtr; } @@ -808,13 +1440,18 @@ TkTextIndexForwBytes(srcPtr, byteCount, dstPtr) * * TkTextIndexForwChars -- * - * Given an index for a text widget, this procedure creates a new - * index that points "count" characters ahead of the source index. + * Given an index for a text widget, this function creates a new index + * that points "count" items of type given by "type" ahead of the source + * index. "count" can be zero, which is useful in the case where one + * wishes to move forward by display (non-elided) chars or indices or one + * wishes to move forward by chars, skipping any intervening indices. In + * this case dstPtr will point to the first acceptable index which is + * encountered. * * Results: - * *dstPtr is modified to refer to the character "count" characters - * after srcPtr, or to the last character in the TkText if there - * aren't "count" characters left in the file. + * *dstPtr is modified to refer to the character "count" items after + * srcPtr, or to the last character in the TkText if there aren't + * sufficient items left in the widget. * * Side effects: * None. @@ -823,31 +1460,52 @@ TkTextIndexForwBytes(srcPtr, byteCount, dstPtr) */ void -TkTextIndexForwChars(srcPtr, charCount, dstPtr) - CONST TkTextIndex *srcPtr; /* Source index. */ - int charCount; /* How many characters forward to move. - * May be negative. */ - TkTextIndex *dstPtr; /* Destination index: gets modified. */ +TkTextIndexForwChars( + CONST TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *srcPtr, /* Source index. */ + int charCount, /* How many characters forward to move. May + * be negative. */ + TkTextIndex *dstPtr, /* Destination index: gets modified. */ + TkTextCountType type) /* The type of item to count */ { TkTextLine *linePtr; TkTextSegment *segPtr; + TkTextElideInfo *infoPtr = NULL; int byteOffset; char *start, *end, *p; Tcl_UniChar ch; + int elide = 0; + int checkElided = (type & COUNT_DISPLAY); if (charCount < 0) { - TkTextIndexBackChars(srcPtr, -charCount, dstPtr); + TkTextIndexBackChars(textPtr, srcPtr, -charCount, dstPtr, type); return; } + if (checkElided) { + infoPtr = (TkTextElideInfo *) + ckalloc((unsigned) sizeof(TkTextElideInfo)); + elide = TkTextIsElided(textPtr, srcPtr, infoPtr); + } *dstPtr = *srcPtr; /* - * Find seg that contains src byteIndex. - * Move forward specified number of chars. + * Find seg that contains src byteIndex. Move forward specified number of + * chars. */ - segPtr = TkTextIndexToSeg(dstPtr, &byteOffset); + if (checkElided) { + /* + * In this case we have already calculated the information we need, so + * no need to use TkTextIndexToSeg() + */ + + segPtr = infoPtr->segPtr; + byteOffset = dstPtr->byteIndex - infoPtr->segOffset; + } else { + segPtr = TkTextIndexToSeg(dstPtr, &byteOffset); + } + while (1) { /* * Go through each segment in line looking for specified character @@ -855,76 +1513,341 @@ TkTextIndexForwChars(srcPtr, charCount, dstPtr) */ for ( ; segPtr != NULL; segPtr = segPtr->nextPtr) { - 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)) { - if (charCount == 0) { - dstPtr->byteIndex += (p - start); - return; + /* + * If we do need to pay attention to the visibility of + * characters/indices, check that first. If the current segment + * isn't visible, then we simply continue the loop. + */ + + if (checkElided && ((segPtr->typePtr == &tkTextToggleOffType) + || (segPtr->typePtr == &tkTextToggleOnType))) { + TkTextTag *tagPtr = segPtr->body.toggle.tagPtr; + + /* + * The elide state only changes if this tag is either the + * current highest priority tag (and is therefore being + * toggled off), or it's a new tag with higher priority. + */ + + if (tagPtr->elideString != NULL) { + infoPtr->tagCnts[tagPtr->priority]++; + if (infoPtr->tagCnts[tagPtr->priority] & 1) { + infoPtr->tagPtrs[tagPtr->priority] = tagPtr; + } + + if (tagPtr->priority >= infoPtr->elidePriority) { + if (segPtr->typePtr == &tkTextToggleOffType) { + /* + * If it is being toggled off, and it has an elide + * string, it must actually be the current highest + * priority tag, so this check is redundant: + */ + + if (tagPtr->priority != infoPtr->elidePriority) { + Tcl_Panic("Bad tag priority being toggled off"); + } + + /* + * Find previous elide tag, if any (if not then + * elide will be zero, of course). + */ + + elide = 0; + while (--infoPtr->elidePriority > 0) { + if (infoPtr->tagCnts[infoPtr->elidePriority] + & 1) { + elide = infoPtr->tagPtrs + [infoPtr->elidePriority]->elide; + break; + } + } + } else { + elide = tagPtr->elide; + infoPtr->elidePriority = tagPtr->priority; + } } - charCount--; } - } else { - if (charCount < segPtr->size - byteOffset) { - dstPtr->byteIndex += charCount; - return; + } + + if (!elide) { + 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)) { + if (charCount == 0) { + dstPtr->byteIndex += (p - start); + goto forwardCharDone; + } + charCount--; + } + } else if (type & COUNT_INDICES) { + if (charCount < segPtr->size - byteOffset) { + dstPtr->byteIndex += charCount; + goto forwardCharDone; + } + charCount -= segPtr->size - byteOffset; } - charCount -= segPtr->size - byteOffset; } + dstPtr->byteIndex += segPtr->size - byteOffset; byteOffset = 0; } /* - * Go to the next line. If we are at the end of the text item, - * back up one byte (for the terminal '\n' character) and return - * that index. + * Go to the next line. If we are at the end of the text item, back up + * one byte (for the terminal '\n' character) and return that index. */ - - linePtr = TkBTreeNextLine(dstPtr->linePtr); + + linePtr = TkBTreeNextLine(textPtr, dstPtr->linePtr); if (linePtr == NULL) { dstPtr->byteIndex -= sizeof(char); - return; + goto forwardCharDone; } dstPtr->linePtr = linePtr; dstPtr->byteIndex = 0; segPtr = dstPtr->linePtr->segPtr; } + + forwardCharDone: + if (infoPtr != NULL) { + TkTextFreeElideInfo(infoPtr); + ckfree((char *) infoPtr); + } } /* *--------------------------------------------------------------------------- * + * TkTextIndexCount -- + * + * Given an ordered pair of indices in a text widget, this function + * counts how many characters (not bytes) are between the two indices. + * + * It is illegal to call this function with unordered indices. + * + * Note that 'textPtr' is only used if we need to check for elided + * attributes, i.e. if type is COUNT_DISPLAY_INDICES or + * COUNT_DISPLAY_CHARS. + * + * Results: + * The number of characters in the given range, which meet the + * appropriate 'type' attributes. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkTextIndexCount( + CONST TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *indexPtr1, + /* Index describing location of character from + * which to count. */ + CONST TkTextIndex *indexPtr2, + /* Index describing location of last character + * at which to stop the count. */ + TkTextCountType type) /* The kind of indices to count. */ +{ + TkTextLine *linePtr1; + TkTextSegment *segPtr, *seg2Ptr = NULL; + TkTextElideInfo *infoPtr = NULL; + int byteOffset, maxBytes, count = 0, elide = 0; + int checkElided = (type & COUNT_DISPLAY); + + /* + * Find seg that contains src index, and remember how many bytes not to + * count in the given segment. + */ + + segPtr = TkTextIndexToSeg(indexPtr1, &byteOffset); + linePtr1 = indexPtr1->linePtr; + + seg2Ptr = TkTextIndexToSeg(indexPtr2, &maxBytes); + + if (checkElided) { + infoPtr = (TkTextElideInfo *) + ckalloc((unsigned) sizeof(TkTextElideInfo)); + elide = TkTextIsElided(textPtr, indexPtr1, infoPtr); + } + + while (1) { + /* + * Go through each segment in line adding up the number of characters. + */ + + for ( ; segPtr != NULL; segPtr = segPtr->nextPtr) { + /* + * If we do need to pay attention to the visibility of + * characters/indices, check that first. If the current segment + * isn't visible, then we simply continue the loop. + */ + + if (checkElided) { + if ((segPtr->typePtr == &tkTextToggleOffType) + || (segPtr->typePtr == &tkTextToggleOnType)) { + TkTextTag *tagPtr = segPtr->body.toggle.tagPtr; + + /* + * The elide state only changes if this tag is either the + * current highest priority tag (and is therefore being + * toggled off), or it's a new tag with higher priority. + */ + + if (tagPtr->elideString != NULL) { + infoPtr->tagCnts[tagPtr->priority]++; + if (infoPtr->tagCnts[tagPtr->priority] & 1) { + infoPtr->tagPtrs[tagPtr->priority] = tagPtr; + } + if (tagPtr->priority >= infoPtr->elidePriority) { + if (segPtr->typePtr == &tkTextToggleOffType) { + /* + * If it is being toggled off, and it has an + * elide string, it must actually be the + * current highest priority tag, so this check + * is redundant: + */ + + if (tagPtr->priority!=infoPtr->elidePriority) { + Tcl_Panic("Bad tag priority being toggled off"); + } + + /* + * Find previous elide tag, if any (if not + * then elide will be zero, of course). + */ + + elide = 0; + while (--infoPtr->elidePriority > 0) { + if (infoPtr->tagCnts[ + infoPtr->elidePriority] & 1) { + elide = infoPtr->tagPtrs[ + infoPtr->elidePriority]->elide; + break; + } + } + } else { + elide = tagPtr->elide; + infoPtr->elidePriority = tagPtr->priority; + } + } + } + } + if (elide) { + if (segPtr == seg2Ptr) { + goto countDone; + } + byteOffset = 0; + continue; + } + } + + if (segPtr->typePtr == &tkTextCharType) { + int byteLen = segPtr->size - byteOffset; + register unsigned char *str = (unsigned char *) + segPtr->body.chars + byteOffset; + register int i; + + if (segPtr == seg2Ptr) { + if (byteLen > (maxBytes - byteOffset)) { + byteLen = maxBytes - byteOffset; + } + } + i = byteLen; + + /* + * This is a speed sensitive function, so run specially over + * the string to count continuous ascii characters before + * resorting to the Tcl_NumUtfChars call. This is a long form + * of: + * + * stringPtr->numChars = + * Tcl_NumUtfChars(objPtr->bytes, objPtr->length); + */ + + while (i && (*str < 0xC0)) { + i--; + str++; + } + count += byteLen - i; + if (i) { + count += Tcl_NumUtfChars(segPtr->body.chars + byteOffset + + (byteLen - i), i); + } + } else { + if (type & COUNT_INDICES) { + int byteLen = segPtr->size - byteOffset; + + if (segPtr == seg2Ptr) { + if (byteLen > (maxBytes - byteOffset)) { + byteLen = maxBytes - byteOffset; + } + } + count += byteLen; + } + } + if (segPtr == seg2Ptr) { + goto countDone; + } + byteOffset = 0; + } + + /* + * Go to the next line. If we are at the end of the text item, back up + * one byte (for the terminal '\n' character) and return that index. + */ + + linePtr1 = TkBTreeNextLine(textPtr, linePtr1); + if (linePtr1 == NULL) { + Tcl_Panic("Reached end of text widget when counting characters"); + } + segPtr = linePtr1->segPtr; + } + + countDone: + if (infoPtr != NULL) { + TkTextFreeElideInfo(infoPtr); + ckfree((char *) infoPtr); + } + return count; +} + +/* + *--------------------------------------------------------------------------- + * * TkTextIndexBackBytes -- * - * Given an index for a text widget, this procedure creates a new - * index that points "count" bytes earlier than the source index. + * Given an index for a text widget, this function creates a new index + * that points "count" bytes earlier than the source index. * * Results: * *dstPtr is modified to refer to the character "count" bytes before * srcPtr, or to the first character in the TkText if there aren't * "count" bytes earlier than srcPtr. * + * Returns 1 if we couldn't use all of 'byteCount' because we have run + * into the beginning or end of the text, and zero otherwise. + * * Side effects: * None. * *--------------------------------------------------------------------------- */ -void -TkTextIndexBackBytes(srcPtr, byteCount, dstPtr) - CONST TkTextIndex *srcPtr; /* Source index. */ - int byteCount; /* How many bytes backward to move. May be +int +TkTextIndexBackBytes( + CONST TkText *textPtr, + CONST TkTextIndex *srcPtr, /* Source index. */ + int byteCount, /* How many bytes backward to move. May be * negative. */ - TkTextIndex *dstPtr; /* Destination index: gets modified. */ + TkTextIndex *dstPtr) /* Destination index: gets modified. */ { TkTextSegment *segPtr; int lineIndex; if (byteCount < 0) { - TkTextIndexForwBytes(srcPtr, -byteCount, dstPtr); - return; + return TkTextIndexForwBytes(textPtr, srcPtr, -byteCount, dstPtr); } *dstPtr = *srcPtr; @@ -932,19 +1855,19 @@ TkTextIndexBackBytes(srcPtr, byteCount, dstPtr) lineIndex = -1; while (dstPtr->byteIndex < 0) { /* - * Move back one line in the text. If we run off the beginning - * of the file then just return the first character in the text. + * Move back one line in the text. If we run off the beginning of the + * file then just return the first character in the text. */ if (lineIndex < 0) { - lineIndex = TkBTreeLineIndex(dstPtr->linePtr); + lineIndex = TkBTreeLinesTo(textPtr, dstPtr->linePtr); } if (lineIndex == 0) { dstPtr->byteIndex = 0; - return; + return 1; } lineIndex--; - dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, lineIndex); + dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, textPtr, lineIndex); /* * Compute the length of the line and add that to dstPtr->charIndex. @@ -955,6 +1878,7 @@ TkTextIndexBackBytes(srcPtr, byteCount, dstPtr) dstPtr->byteIndex += segPtr->size; } } + return 0; } /* @@ -962,13 +1886,18 @@ TkTextIndexBackBytes(srcPtr, byteCount, dstPtr) * * TkTextIndexBackChars -- * - * Given an index for a text widget, this procedure creates a new - * index that points "count" characters earlier than the source index. + * Given an index for a text widget, this function creates a new index + * that points "count" items of type given by "type" earlier than the + * source index. "count" can be zero, which is useful in the case where + * one wishes to move backward by display (non-elided) chars or indices + * or one wishes to move backward by chars, skipping any intervening + * indices. In this case the returned index *dstPtr will point just + * _after_ the first acceptable index which is encountered. * * Results: - * *dstPtr is modified to refer to the character "count" characters - * before srcPtr, or to the first character in the file if there - * aren't "count" characters earlier than srcPtr. + * *dstPtr is modified to refer to the character "count" items before + * srcPtr, or to the first index in the window if there aren't sufficient + * items earlier than srcPtr. * * Side effects: * None. @@ -977,57 +1906,145 @@ TkTextIndexBackBytes(srcPtr, byteCount, dstPtr) */ void -TkTextIndexBackChars(srcPtr, charCount, dstPtr) - CONST TkTextIndex *srcPtr; /* Source index. */ - int charCount; /* How many characters backward to move. - * May be negative. */ - TkTextIndex *dstPtr; /* Destination index: gets modified. */ +TkTextIndexBackChars( + CONST TkText *textPtr, /* Overall information about text widget. */ + CONST TkTextIndex *srcPtr, /* Source index. */ + int charCount, /* How many characters backward to move. May + * be negative. */ + TkTextIndex *dstPtr, /* Destination index: gets modified. */ + TkTextCountType type) /* The type of item to count */ { TkTextSegment *segPtr, *oldPtr; + TkTextElideInfo *infoPtr = NULL; int lineIndex, segSize; CONST char *p, *start, *end; + int elide = 0; + int checkElided = (type & COUNT_DISPLAY); - if (charCount <= 0) { - TkTextIndexForwChars(srcPtr, -charCount, dstPtr); + if (charCount < 0) { + TkTextIndexForwChars(textPtr, srcPtr, -charCount, dstPtr, type); return; } + if (checkElided) { + infoPtr = (TkTextElideInfo *) ckalloc(sizeof(TkTextElideInfo)); + elide = TkTextIsElided(textPtr, srcPtr, infoPtr); + } *dstPtr = *srcPtr; /* - * Find offset within seg that contains byteIndex. - * Move backward specified number of chars. + * Find offset within seg that contains byteIndex. Move backward specified + * number of chars. */ lineIndex = -1; - + segSize = dstPtr->byteIndex; - for (segPtr = dstPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) { - if (segSize <= segPtr->size) { - break; + + if (checkElided) { + segPtr = infoPtr->segPtr; + segSize -= infoPtr->segOffset; + } else { + TkTextLine *linePtr = dstPtr->linePtr; + for (segPtr = linePtr->segPtr; ; segPtr = segPtr->nextPtr) { + if (segPtr == NULL) { + /* + * Two logical lines merged into one display line through + * eliding of a newline. + */ + + linePtr = TkBTreeNextLine(NULL, linePtr); + segPtr = linePtr->segPtr; + } + if (segSize <= segPtr->size) { + break; + } + segSize -= segPtr->size; } - segSize -= segPtr->size; } + + /* + * Now segPtr points to the segment containing the starting index. + */ + while (1) { - if (segPtr->typePtr == &tkTextCharType) { - start = segPtr->body.chars; - end = segPtr->body.chars + segSize; - for (p = end; ; p = Tcl_UtfPrev(p, start)) { - if (charCount == 0) { - dstPtr->byteIndex -= (end - p); - return; + /* + * If we do need to pay attention to the visibility of + * characters/indices, check that first. If the current segment isn't + * visible, then we simply continue the loop. + */ + + if (checkElided && ((segPtr->typePtr == &tkTextToggleOffType) + || (segPtr->typePtr == &tkTextToggleOnType))) { + TkTextTag *tagPtr = segPtr->body.toggle.tagPtr; + + /* + * The elide state only changes if this tag is either the current + * highest priority tag (and is therefore being toggled off), or + * it's a new tag with higher priority. + */ + + if (tagPtr->elideString != NULL) { + infoPtr->tagCnts[tagPtr->priority]++; + if (infoPtr->tagCnts[tagPtr->priority] & 1) { + infoPtr->tagPtrs[tagPtr->priority] = tagPtr; } - if (p == start) { - break; + if (tagPtr->priority >= infoPtr->elidePriority) { + if (segPtr->typePtr == &tkTextToggleOnType) { + /* + * If it is being toggled on, and it has an elide + * string, it must actually be the current highest + * priority tag, so this check is redundant: + */ + + if (tagPtr->priority != infoPtr->elidePriority) { + Tcl_Panic("Bad tag priority being toggled on"); + } + + /* + * Find previous elide tag, if any (if not then elide + * will be zero, of course). + */ + + elide = 0; + while (--infoPtr->elidePriority > 0) { + if (infoPtr->tagCnts[infoPtr->elidePriority] & 1) { + elide = infoPtr->tagPtrs[ + infoPtr->elidePriority]->elide; + break; + } + } + } else { + elide = tagPtr->elide; + infoPtr->elidePriority = tagPtr->priority; + } } - charCount--; } - } else { - if (charCount <= segSize) { - dstPtr->byteIndex -= charCount; - return; + } + + if (!elide) { + if (segPtr->typePtr == &tkTextCharType) { + start = segPtr->body.chars; + end = segPtr->body.chars + segSize; + for (p = end; ; p = Tcl_UtfPrev(p, start)) { + if (charCount == 0) { + dstPtr->byteIndex -= (end - p); + goto backwardCharDone; + } + if (p == start) { + break; + } + charCount--; + } + } else { + if (type & COUNT_INDICES) { + if (charCount <= segSize) { + dstPtr->byteIndex -= charCount; + goto backwardCharDone; + } + charCount -= segSize; + } } - charCount -= segSize; } dstPtr->byteIndex -= segSize; @@ -1050,14 +2067,14 @@ TkTextIndexBackChars(srcPtr, charCount, dstPtr) */ if (lineIndex < 0) { - lineIndex = TkBTreeLineIndex(dstPtr->linePtr); + lineIndex = TkBTreeLinesTo(textPtr, dstPtr->linePtr); } if (lineIndex == 0) { dstPtr->byteIndex = 0; - return; + goto backwardCharDone; } lineIndex--; - dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, lineIndex); + dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, textPtr, lineIndex); /* * Compute the length of the line and add that to dstPtr->byteIndex. @@ -1071,6 +2088,12 @@ TkTextIndexBackChars(srcPtr, charCount, dstPtr) segPtr = oldPtr; segSize = segPtr->size; } + + backwardCharDone: + if (infoPtr != NULL) { + TkTextFreeElideInfo(infoPtr); + ckfree((char *) infoPtr); + } } /* @@ -1078,14 +2101,14 @@ TkTextIndexBackChars(srcPtr, charCount, dstPtr) * * StartEnd -- * - * This procedure handles modifiers like "wordstart" and "lineend" - * to adjust indices forwards or backwards. + * This function handles modifiers like "wordstart" and "lineend" to + * adjust indices forwards or backwards. * * Results: - * If the modifier is successfully parsed then the return value - * is the address of the first character after the modifier, and - * *indexPtr is updated to reflect the modifier. If there is a - * syntax error in the modifier then NULL is returned. + * If the modifier is successfully parsed then the return value is the + * address of the first character after the modifier, and *indexPtr is + * updated to reflect the modifier. If there is a syntax error in the + * modifier then NULL is returned. * * Side effects: * None. @@ -1094,17 +2117,17 @@ TkTextIndexBackChars(srcPtr, charCount, dstPtr) */ static CONST char * -StartEnd(string, indexPtr) - CONST char *string; /* String to parse for additional info - * about modifier (count and units). - * Points to first character of modifer - * word. */ - TkTextIndex *indexPtr; /* Index to mdoify based on string. */ +StartEnd( + TkText *textPtr, /* Information about text widget. */ + CONST char *string, /* String to parse for additional info about + * modifier (count and units). Points to first + * character of modifer word. */ + TkTextIndex *indexPtr) /* Index to modify based on string. */ { CONST char *p; - int c, offset; size_t length; register TkTextSegment *segPtr; + int modifier; /* * Find the end of the modifier word. @@ -1113,68 +2136,144 @@ StartEnd(string, indexPtr) for (p = string; isalnum(UCHAR(*p)); p++) { /* Empty loop body. */ } + length = p-string; + if ((*string == 'd') && + (strncmp(string, "display", (length > 7 ? 7 : length)) == 0)) { + modifier = TKINDEX_DISPLAY; + if (length > 7) { + p -= (length - 7); + } + } else if ((*string == 'a') && + (strncmp(string, "any", (length > 3 ? 3 : length)) == 0)) { + modifier = TKINDEX_ANY; + if (length > 3) { + p -= (length - 3); + } + } else { + modifier = TKINDEX_NONE; + } + + /* + * If we had a modifier, which we interpreted ok, so now forward to the + * actual units. + */ + + if (modifier != TKINDEX_NONE) { + while (isspace(UCHAR(*p))) { + p++; + } + string = p; + while ((*p!='\0') && !isspace(UCHAR(*p)) && (*p!='+') && (*p!='-')) { + p++; + } + length = p - string; + } + if ((*string == 'l') && (strncmp(string, "lineend", length) == 0) && (length >= 5)) { - indexPtr->byteIndex = 0; - for (segPtr = indexPtr->linePtr->segPtr; segPtr != NULL; - segPtr = segPtr->nextPtr) { - indexPtr->byteIndex += segPtr->size; + if (modifier == TKINDEX_DISPLAY) { + TkTextFindDisplayLineEnd(textPtr, indexPtr, 1, NULL); + } else { + indexPtr->byteIndex = 0; + for (segPtr = indexPtr->linePtr->segPtr; segPtr != NULL; + segPtr = segPtr->nextPtr) { + indexPtr->byteIndex += segPtr->size; + } + + /* + * We know '\n' is encoded with a single byte index. + */ + + indexPtr->byteIndex -= sizeof(char); } - indexPtr->byteIndex -= sizeof(char); } else if ((*string == 'l') && (strncmp(string, "linestart", length) == 0) && (length >= 5)) { - indexPtr->byteIndex = 0; + if (modifier == TKINDEX_DISPLAY) { + TkTextFindDisplayLineEnd(textPtr, indexPtr, 0, NULL); + } else { + indexPtr->byteIndex = 0; + } } else if ((*string == 'w') && (strncmp(string, "wordend", length) == 0) && (length >= 5)) { int firstChar = 1; + int offset; /* * If the current character isn't part of a word then just move - * forward one character. Otherwise move forward until finding - * a character that isn't part of a word and stop there. + * forward one character. Otherwise move forward until finding a + * character that isn't part of a word and stop there. */ + if (modifier == TKINDEX_DISPLAY) { + TkTextIndexForwChars(textPtr, indexPtr, 0, indexPtr, + COUNT_DISPLAY_INDICES); + } segPtr = TkTextIndexToSeg(indexPtr, &offset); while (1) { + int chSize = 1; + if (segPtr->typePtr == &tkTextCharType) { - c = segPtr->body.chars[offset]; - if (!isalnum(UCHAR(c)) && (c != '_')) { + Tcl_UniChar ch; + + chSize = Tcl_UtfToUniChar(segPtr->body.chars + offset, &ch); + if (!Tcl_UniCharIsWordChar(ch)) { break; } firstChar = 0; } - offset += 1; - indexPtr->byteIndex += sizeof(char); + offset += chSize; + indexPtr->byteIndex += chSize; if (offset >= segPtr->size) { segPtr = TkTextIndexToSeg(indexPtr, &offset); } } if (firstChar) { - TkTextIndexForwChars(indexPtr, 1, indexPtr); + if (modifier == TKINDEX_DISPLAY) { + TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr, + COUNT_DISPLAY_INDICES); + } else { + TkTextIndexForwChars(NULL, indexPtr, 1, indexPtr, + COUNT_INDICES); + } } } else if ((*string == 'w') && (strncmp(string, "wordstart", length) == 0) && (length >= 5)) { int firstChar = 1; + int offset; + + if (modifier == TKINDEX_DISPLAY) { + TkTextIndexForwChars(NULL, indexPtr, 0, indexPtr, + COUNT_DISPLAY_INDICES); + } /* - * Starting with the current character, look for one that's not - * part of a word and keep moving backward until you find one. - * Then if the character found wasn't the first one, move forward - * again one position. + * Starting with the current character, look for one that's not part + * of a word and keep moving backward until you find one. Then if the + * character found wasn't the first one, move forward again one + * position. */ segPtr = TkTextIndexToSeg(indexPtr, &offset); while (1) { + int chSize = 1; + if (segPtr->typePtr == &tkTextCharType) { - c = segPtr->body.chars[offset]; - if (!isalnum(UCHAR(c)) && (c != '_')) { + Tcl_UniChar ch; + + Tcl_UtfToUniChar(segPtr->body.chars + offset, &ch); + if (!Tcl_UniCharIsWordChar(ch)) { break; } + if (offset > 0) { + chSize = (segPtr->body.chars + offset + - Tcl_UtfPrev(segPtr->body.chars + offset, + segPtr->body.chars)); + } firstChar = 0; } - offset -= 1; - indexPtr->byteIndex -= sizeof(char); + offset -= chSize; + indexPtr->byteIndex -= chSize; if (offset < 0) { if (indexPtr->byteIndex < 0) { indexPtr->byteIndex = 0; @@ -1183,12 +2282,28 @@ StartEnd(string, indexPtr) segPtr = TkTextIndexToSeg(indexPtr, &offset); } } + if (!firstChar) { - TkTextIndexForwChars(indexPtr, 1, indexPtr); + if (modifier == TKINDEX_DISPLAY) { + TkTextIndexForwChars(textPtr, indexPtr, 1, indexPtr, + COUNT_DISPLAY_INDICES); + } else { + TkTextIndexForwChars(NULL, indexPtr, 1, indexPtr, + COUNT_INDICES); + } } } else { return NULL; } - done: + + done: return p; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTextMark.c b/generic/tkTextMark.c index c84bc9c..71a7949 100644 --- a/generic/tkTextMark.c +++ b/generic/tkTextMark.c @@ -1,19 +1,18 @@ -/* +/* * tkTextMark.c -- * - * This file contains the procedure that implement marks for - * text widgets. + * This file contains the functions that implement marks for text + * widgets. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkText.h" -#include "tkPort.h" /* * Macro that determines the size of a mark segment: @@ -23,55 +22,53 @@ + sizeof(TkTextMark))) /* - * Forward references for procedures defined in this file: + * Forward references for functions defined in this file: */ -static void InsertUndisplayProc _ANSI_ARGS_((TkText *textPtr, - TkTextDispChunk *chunkPtr)); -static int MarkDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr, int treeGone)); -static TkTextSegment * MarkCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static void MarkCheckProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static int MarkLayoutProc _ANSI_ARGS_((TkText *textPtr, - TkTextIndex *indexPtr, TkTextSegment *segPtr, - int offset, int maxX, int maxChars, - int noCharsYet, TkWrapMode wrapMode, - TkTextDispChunk *chunkPtr)); -static int MarkFindNext _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, CONST char *markName)); -static int MarkFindPrev _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, CONST char *markName)); +static void InsertUndisplayProc(TkText *textPtr, + TkTextDispChunk *chunkPtr); +static int MarkDeleteProc(TkTextSegment *segPtr, + TkTextLine *linePtr, int treeGone); +static TkTextSegment * MarkCleanupProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static void MarkCheckProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static int MarkLayoutProc(TkText *textPtr, TkTextIndex *indexPtr, + TkTextSegment *segPtr, int offset, int maxX, + int maxChars, int noCharsYet, TkWrapMode wrapMode, + TkTextDispChunk *chunkPtr); +static int MarkFindNext(Tcl_Interp *interp, + TkText *textPtr, const char *markName); +static int MarkFindPrev(Tcl_Interp *interp, + TkText *textPtr, const char *markName); /* - * The following structures declare the "mark" segment types. - * There are actually two types for marks, one with left gravity - * and one with right gravity. They are identical except for - * their gravity property. + * The following structures declare the "mark" segment types. There are + * actually two types for marks, one with left gravity and one with right + * gravity. They are identical except for their gravity property. */ -Tk_SegType tkTextRightMarkType = { - "mark", /* name */ - 0, /* leftGravity */ - (Tk_SegSplitProc *) NULL, /* splitProc */ - MarkDeleteProc, /* deleteProc */ - MarkCleanupProc, /* cleanupProc */ - (Tk_SegLineChangeProc *) NULL, /* lineChangeProc */ - MarkLayoutProc, /* layoutProc */ - MarkCheckProc /* checkProc */ +const Tk_SegType tkTextRightMarkType = { + "mark", /* name */ + 0, /* leftGravity */ + NULL, /* splitProc */ + MarkDeleteProc, /* deleteProc */ + MarkCleanupProc, /* cleanupProc */ + NULL, /* lineChangeProc */ + MarkLayoutProc, /* layoutProc */ + MarkCheckProc /* checkProc */ }; -Tk_SegType tkTextLeftMarkType = { - "mark", /* name */ - 1, /* leftGravity */ - (Tk_SegSplitProc *) NULL, /* splitProc */ - MarkDeleteProc, /* deleteProc */ - MarkCleanupProc, /* cleanupProc */ - (Tk_SegLineChangeProc *) NULL, /* lineChangeProc */ - MarkLayoutProc, /* layoutProc */ - MarkCheckProc /* checkProc */ +const Tk_SegType tkTextLeftMarkType = { + "mark", /* name */ + 1, /* leftGravity */ + NULL, /* splitProc */ + MarkDeleteProc, /* deleteProc */ + MarkCleanupProc, /* cleanupProc */ + NULL, /* lineChangeProc */ + MarkLayoutProc, /* layoutProc */ + MarkCheckProc /* checkProc */ }; /* @@ -79,9 +76,9 @@ Tk_SegType tkTextLeftMarkType = { * * TkTextMarkCmd -- * - * This procedure is invoked to process the "mark" options of - * the widget command for text widgets. See the user documentation - * for details on what it does. + * This function is invoked to process the "mark" options of the widget + * command for text widgets. See the user documentation for details on + * what it does. * * Results: * A standard Tcl result. @@ -93,44 +90,62 @@ Tk_SegType tkTextLeftMarkType = { */ int -TkTextMarkCmd(textPtr, interp, argc, argv) - register TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextMarkCmd( + register TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "mark". */ + * objv[1] is "mark". */ { - int c, i; - size_t length; Tcl_HashEntry *hPtr; TkTextSegment *markPtr; Tcl_HashSearch search; TkTextIndex index; - Tk_SegType *newTypePtr; - - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " mark option ?arg arg ...?\"", (char *) NULL); + const Tk_SegType *newTypePtr; + int optionIndex; + static const char *markOptionStrings[] = { + "gravity", "names", "next", "previous", "set", "unset", NULL + }; + enum markOptions { + MARK_GRAVITY, MARK_NAMES, MARK_NEXT, MARK_PREVIOUS, MARK_SET, + MARK_UNSET + }; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[2], markOptionStrings, "mark option", + 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - c = argv[2][0]; - length = strlen(argv[2]); - if ((c == 'g') && (strncmp(argv[2], "gravity", length) == 0)) { - if (argc < 4 || argc > 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " mark gravity markName ?gravity?\"", - (char *) NULL); + + switch ((enum markOptions) optionIndex) { + case MARK_GRAVITY: { + char c; + int length; + char *str; + + if (objc < 4 || objc > 5) { + Tcl_WrongNumArgs(interp, 3, objv, "markName ?gravity?"); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&textPtr->markTable, argv[3]); - if (hPtr == NULL) { - Tcl_AppendResult(interp, "there is no mark named \"", - argv[3], "\"", (char *) NULL); - return TCL_ERROR; + str = Tcl_GetStringFromObj(objv[3],&length); + if (length == 6 && !strcmp(str, "insert")) { + markPtr = textPtr->insertMarkPtr; + } else if (length == 7 && !strcmp(str, "current")) { + markPtr = textPtr->currentMarkPtr; + } else { + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, str); + if (hPtr == NULL) { + Tcl_AppendResult(interp, "there is no mark named \"", + Tcl_GetString(objv[3]), "\"", NULL); + return TCL_ERROR; + } + markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); } - markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); - if (argc == 4) { + if (objc == 4) { if (markPtr->typePtr == &tkTextRightMarkType) { Tcl_SetResult(interp, "right", TCL_STATIC); } else { @@ -138,77 +153,83 @@ TkTextMarkCmd(textPtr, interp, argc, argv) } return TCL_OK; } - length = strlen(argv[4]); - c = argv[4][0]; - if ((c == 'l') && (strncmp(argv[4], "left", length) == 0)) { + str = Tcl_GetStringFromObj(objv[4],&length); + c = str[0]; + if ((c == 'l') && (strncmp(str, "left", (unsigned)length) == 0)) { newTypePtr = &tkTextLeftMarkType; - } else if ((c == 'r') && (strncmp(argv[4], "right", length) == 0)) { + } else if ((c == 'r') && + (strncmp(str, "right", (unsigned)length) == 0)) { newTypePtr = &tkTextRightMarkType; } else { - Tcl_AppendResult(interp, "bad mark gravity \"", - argv[4], "\": must be left or right", (char *) NULL); + Tcl_AppendResult(interp, "bad mark gravity \"", str, + "\": must be left or right", NULL); return TCL_ERROR; } TkTextMarkSegToIndex(textPtr, markPtr, &index); - TkBTreeUnlinkSegment(textPtr->tree, markPtr, - markPtr->body.mark.linePtr); + TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr); markPtr->typePtr = newTypePtr; TkBTreeLinkSegment(markPtr, &index); - } else if ((c == 'n') && (strncmp(argv[2], "names", length) == 0)) { - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " mark names\"", (char *) NULL); + break; + } + case MARK_NAMES: + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - for (hPtr = Tcl_FirstHashEntry(&textPtr->markTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + Tcl_AppendElement(interp, "insert"); + Tcl_AppendElement(interp, "current"); + for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->markTable, + &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_AppendElement(interp, - Tcl_GetHashKey(&textPtr->markTable, hPtr)); + Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr)); } - } else if ((c == 'n') && (strncmp(argv[2], "next", length) == 0)) { - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " mark next index\"", (char *) NULL); + break; + case MARK_NEXT: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); return TCL_ERROR; } - return MarkFindNext(interp, textPtr, argv[3]); - } else if ((c == 'p') && (strncmp(argv[2], "previous", length) == 0)) { - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " mark previous index\"", (char *) NULL); + return MarkFindNext(interp, textPtr, Tcl_GetString(objv[3])); + case MARK_PREVIOUS: + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index"); return TCL_ERROR; } - return MarkFindPrev(interp, textPtr, argv[3]); - } else if ((c == 's') && (strncmp(argv[2], "set", length) == 0)) { - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " mark set markName index\"", (char *) NULL); + return MarkFindPrev(interp, textPtr, Tcl_GetString(objv[3])); + case MARK_SET: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "markName index"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[4], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[4], &index) != TCL_OK) { return TCL_ERROR; } - TkTextSetMark(textPtr, argv[3], &index); - } else if ((c == 'u') && (strncmp(argv[2], "unset", length) == 0)) { - for (i = 3; i < argc; i++) { - hPtr = Tcl_FindHashEntry(&textPtr->markTable, argv[i]); + TkTextSetMark(textPtr, Tcl_GetString(objv[3]), &index); + return TCL_OK; + case MARK_UNSET: { + int i; + + for (i = 3; i < objc; i++) { + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, + Tcl_GetString(objv[i])); if (hPtr != NULL) { markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + + /* + * Special case not needed with peer widgets. + */ + if ((markPtr == textPtr->insertMarkPtr) || (markPtr == textPtr->currentMarkPtr)) { continue; } - TkBTreeUnlinkSegment(textPtr->tree, markPtr, - markPtr->body.mark.linePtr); + TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr); Tcl_DeleteHashEntry(hPtr); ckfree((char *) markPtr); } } - } else { - Tcl_AppendResult(interp, "bad mark option \"", argv[2], - "\": must be gravity, names, next, previous, set, or unset", - (char *) NULL); - return TCL_ERROR; + break; + } } return TCL_OK; } @@ -218,8 +239,8 @@ TkTextMarkCmd(textPtr, interp, argc, argv) * * TkTextSetMark -- * - * Set a mark to a particular position, creating a new mark if - * one doesn't already exist. + * Set a mark to a particular position, creating a new mark if one + * doesn't already exist. * * Results: * The return value is a pointer to the mark that was just set. @@ -231,39 +252,67 @@ TkTextMarkCmd(textPtr, interp, argc, argv) */ TkTextSegment * -TkTextSetMark(textPtr, name, indexPtr) - TkText *textPtr; /* Text widget in which to create mark. */ - CONST char *name; /* Name of mark to set. */ - TkTextIndex *indexPtr; /* Where to set mark. */ +TkTextSetMark( + TkText *textPtr, /* Text widget in which to create mark. */ + const char *name, /* Name of mark to set. */ + TkTextIndex *indexPtr) /* Where to set mark. */ { - Tcl_HashEntry *hPtr; + Tcl_HashEntry *hPtr = NULL; TkTextSegment *markPtr; TkTextIndex insertIndex; - int new; - - hPtr = Tcl_CreateHashEntry(&textPtr->markTable, name, &new); - markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); - if (!new) { + int isNew, widgetSpecific; + + if (!strcmp(name, "insert")) { + widgetSpecific = 1; + markPtr = textPtr->insertMarkPtr; + isNew = (markPtr == NULL ? 1 : 0); + } else if (!strcmp(name, "current")) { + widgetSpecific = 2; + markPtr = textPtr->currentMarkPtr; + isNew = (markPtr == NULL ? 1 : 0); + } else { + widgetSpecific = 0; + hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->markTable, name, + &isNew); + markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + } + if (!isNew) { /* - * If this is the insertion point that's being moved, be sure - * to force a display update at the old position. Also, don't - * let the insertion cursor be after the final newline of the - * file. + * If this is the insertion point that's being moved, be sure to force + * a display update at the old position. Also, don't let the insertion + * cursor be after the final newline of the file. */ if (markPtr == textPtr->insertMarkPtr) { TkTextIndex index, index2; + int nblines; + TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index); - TkTextIndexForwChars(&index, 1, &index2); - TkTextChanged(textPtr, &index, &index2); - if (TkBTreeLineIndex(indexPtr->linePtr) - == TkBTreeNumLines(textPtr->tree)) { - TkTextIndexBackChars(indexPtr, 1, &insertIndex); + TkTextIndexForwChars(NULL,&index, 1, &index2, COUNT_INDICES); + + /* + * While we wish to redisplay, no heights have changed, so no need + * to call TkTextInvalidateLineMetrics. + */ + + TkTextChanged(NULL, textPtr, &index, &index2); + + /* + * The number of lines in the widget is zero if and only if it is + * a partial peer with -startline == -endline, i.e. an empty + * peer. In this case the mark shall be set exactly at the given + * index, and not one character backwards (bug 3487407). + */ + + nblines = TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr); + if ((TkBTreeLinesTo(textPtr, indexPtr->linePtr) == nblines) + && (nblines > 0)) { + TkTextIndexBackChars(NULL,indexPtr, 1, &insertIndex, + COUNT_INDICES); indexPtr = &insertIndex; } } - TkBTreeUnlinkSegment(textPtr->tree, markPtr, - markPtr->body.mark.linePtr); + TkBTreeUnlinkSegment(markPtr, markPtr->body.mark.linePtr); } else { markPtr = (TkTextSegment *) ckalloc(MSEG_SIZE); markPtr->typePtr = &tkTextRightMarkType; @@ -271,7 +320,13 @@ TkTextSetMark(textPtr, name, indexPtr) markPtr->body.mark.textPtr = textPtr; markPtr->body.mark.linePtr = indexPtr->linePtr; markPtr->body.mark.hPtr = hPtr; - Tcl_SetHashValue(hPtr, markPtr); + if (widgetSpecific == 0) { + Tcl_SetHashValue(hPtr, markPtr); + } else if (widgetSpecific == 1) { + textPtr->insertMarkPtr = markPtr; + } else { + textPtr->currentMarkPtr = markPtr; + } } TkBTreeLinkSegment(markPtr, indexPtr); @@ -283,8 +338,14 @@ TkTextSetMark(textPtr, name, indexPtr) if (markPtr == textPtr->insertMarkPtr) { TkTextIndex index2; - TkTextIndexForwChars(indexPtr, 1, &index2); - TkTextChanged(textPtr, indexPtr, &index2); + TkTextIndexForwChars(NULL,indexPtr, 1, &index2, COUNT_INDICES); + + /* + * While we wish to redisplay, no heights have changed, so no need to + * call TkTextInvalidateLineMetrics + */ + + TkTextChanged(NULL, textPtr, indexPtr, &index2); } return markPtr; } @@ -294,9 +355,9 @@ TkTextSetMark(textPtr, name, indexPtr) * * TkTextMarkSegToIndex -- * - * Given a segment that is a mark, create an index that - * refers to the next text character (or other text segment - * with non-zero size) after the mark. + * Given a segment that is a mark, create an index that refers to the + * next text character (or other text segment with non-zero size) after + * the mark. * * Results: * *IndexPtr is filled in with index information. @@ -308,14 +369,14 @@ TkTextSetMark(textPtr, name, indexPtr) */ void -TkTextMarkSegToIndex(textPtr, markPtr, indexPtr) - TkText *textPtr; /* Text widget containing mark. */ - TkTextSegment *markPtr; /* Mark segment. */ - TkTextIndex *indexPtr; /* Index information gets stored here. */ +TkTextMarkSegToIndex( + TkText *textPtr, /* Text widget containing mark. */ + TkTextSegment *markPtr, /* Mark segment. */ + TkTextIndex *indexPtr) /* Index information gets stored here. */ { TkTextSegment *segPtr; - indexPtr->tree = textPtr->tree; + indexPtr->tree = textPtr->sharedTextPtr->tree; indexPtr->linePtr = markPtr->body.mark.linePtr; indexPtr->byteIndex = 0; for (segPtr = indexPtr->linePtr->segPtr; segPtr != markPtr; @@ -329,15 +390,20 @@ TkTextMarkSegToIndex(textPtr, markPtr, indexPtr) * * TkTextMarkNameToIndex -- * - * Given the name of a mark, return an index corresponding - * to the mark name. + * Given the name of a mark, return an index corresponding to the mark + * name. * * Results: - * The return value is TCL_OK if "name" exists as a mark in - * the text widget. In this case *indexPtr is filled in with - * the next segment whose after the mark whose size is - * non-zero. TCL_ERROR is returned if the mark doesn't exist - * in the text widget. + * The return value is TCL_OK if "name" exists as a mark in the text + * widget and is located within its -starline/-endline range. In this + * case *indexPtr is filled in with the next segment who is after the + * mark whose size is non-zero. TCL_ERROR is returned if the mark + * doesn't exist in the text widget, or if it is out of its -starline/ + * -endline range. In this latter case *indexPtr still contains valid + * information, in particular TkTextMarkNameToIndex called with the + * "insert" or "current" mark name may return TCL_ERROR, but *indexPtr + * contains the correct index of this mark before -startline or after + * -endline. * * Side effects: * None. @@ -346,19 +412,55 @@ TkTextMarkSegToIndex(textPtr, markPtr, indexPtr) */ int -TkTextMarkNameToIndex(textPtr, name, indexPtr) - TkText *textPtr; /* Text widget containing mark. */ - CONST char *name; /* Name of mark. */ - TkTextIndex *indexPtr; /* Index information gets stored here. */ +TkTextMarkNameToIndex( + TkText *textPtr, /* Text widget containing mark. */ + const char *name, /* Name of mark. */ + TkTextIndex *indexPtr) /* Index information gets stored here. */ { - Tcl_HashEntry *hPtr; + TkTextSegment *segPtr; + TkTextIndex index; + int start, end; - hPtr = Tcl_FindHashEntry(&textPtr->markTable, name); - if (hPtr == NULL) { - return TCL_ERROR; + if (textPtr == NULL) { + return TCL_ERROR; + } + + if (!strcmp(name, "insert")) { + segPtr = textPtr->insertMarkPtr; + } else if (!strcmp(name, "current")) { + segPtr = textPtr->currentMarkPtr; + } else { + Tcl_HashEntry *hPtr; + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, name); + if (hPtr == NULL) { + return TCL_ERROR; + } + segPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + } + TkTextMarkSegToIndex(textPtr, segPtr, indexPtr); + + /* If indexPtr refers to somewhere outside the -startline/-endline + * range limits of the widget, error out since the mark indeed is not + * reachable from this text widget (it may be reachable from a peer) + * (bug 1630271). + */ + + if (textPtr->start != NULL) { + start = TkBTreeLinesTo(NULL, textPtr->start); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, start, 0, + &index); + if (TkTextIndexCmp(indexPtr, &index) < 0) { + return TCL_ERROR; + } + } + if (textPtr->end != NULL) { + end = TkBTreeLinesTo(NULL, textPtr->end); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, end, 0, + &index); + if (TkTextIndexCmp(indexPtr, &index) > 0) { + return TCL_ERROR; + } } - TkTextMarkSegToIndex(textPtr, (TkTextSegment *) Tcl_GetHashValue(hPtr), - indexPtr); return TCL_OK; } @@ -367,27 +469,27 @@ TkTextMarkNameToIndex(textPtr, name, indexPtr) * * MarkDeleteProc -- * - * This procedure is invoked by the text B-tree code whenever - * a mark lies in a range of characters being deleted. + * This function is invoked by the text B-tree code whenever a mark lies + * in a range of characters being deleted. * * Results: * Returns 1 to indicate that deletion has been rejected. * * Side effects: - * None (even if the whole tree is being deleted we don't - * free up the mark; it will be done elsewhere). + * None (even if the whole tree is being deleted we don't free up the + * mark; it will be done elsewhere). * *-------------------------------------------------------------- */ /* ARGSUSED */ static int -MarkDeleteProc(segPtr, linePtr, treeGone) - TkTextSegment *segPtr; /* Segment being deleted. */ - TkTextLine *linePtr; /* Line containing segment. */ - int treeGone; /* Non-zero means the entire tree is - * being deleted, so everything must - * get cleaned up. */ +MarkDeleteProc( + TkTextSegment *segPtr, /* Segment being deleted. */ + TkTextLine *linePtr, /* Line containing segment. */ + int treeGone) /* Non-zero means the entire tree is being + * deleted, so everything must get cleaned + * up. */ { return 1; } @@ -397,8 +499,8 @@ MarkDeleteProc(segPtr, linePtr, treeGone) * * MarkCleanupProc -- * - * This procedure is invoked by the B-tree code whenever a - * mark segment is moved from one line to another. + * This function is invoked by the B-tree code whenever a mark segment is + * moved from one line to another. * * Results: * None. @@ -410,9 +512,9 @@ MarkDeleteProc(segPtr, linePtr, treeGone) */ static TkTextSegment * -MarkCleanupProc(markPtr, linePtr) - TkTextSegment *markPtr; /* Mark segment that's being moved. */ - TkTextLine *linePtr; /* Line that now contains segment. */ +MarkCleanupProc( + TkTextSegment *markPtr, /* Mark segment that's being moved. */ + TkTextLine *linePtr) /* Line that now contains segment. */ { markPtr->body.mark.linePtr = linePtr; return markPtr; @@ -423,13 +525,13 @@ MarkCleanupProc(markPtr, linePtr) * * MarkLayoutProc -- * - * This procedure is the "layoutProc" for mark segments. + * This function is the "layoutProc" for mark segments. * * Results: - * If the mark isn't the insertion cursor then the return - * value is -1 to indicate that this segment shouldn't be - * displayed. If the mark is the insertion character then - * 1 is returned and the chunkPtr structure is filled in. + * If the mark isn't the insertion cursor then the return value is -1 to + * indicate that this segment shouldn't be displayed. If the mark is the + * insertion character then 1 is returned and the chunkPtr structure is + * filled in. * * Side effects: * None, except for filling in chunkPtr. @@ -437,26 +539,24 @@ MarkCleanupProc(markPtr, linePtr) *-------------------------------------------------------------- */ - /*ARGSUSED*/ static int -MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, - noCharsYet, wrapMode, chunkPtr) - TkText *textPtr; /* Text widget being layed out. */ - TkTextIndex *indexPtr; /* Identifies first character in chunk. */ - TkTextSegment *segPtr; /* Segment corresponding to indexPtr. */ - int offset; /* Offset within segPtr corresponding to +MarkLayoutProc( + TkText *textPtr, /* Text widget being layed out. */ + TkTextIndex *indexPtr, /* Identifies first character in chunk. */ + TkTextSegment *segPtr, /* Segment corresponding to indexPtr. */ + int offset, /* Offset within segPtr corresponding to * indexPtr (always 0). */ - int maxX; /* Chunk must not occupy pixels at this + int maxX, /* Chunk must not occupy pixels at this * position or higher. */ - int maxChars; /* Chunk must not include more than this - * many characters. */ - int noCharsYet; /* Non-zero means no characters have been + int maxChars, /* Chunk must not include more than this many + * characters. */ + int noCharsYet, /* Non-zero means no characters have been * assigned to this line yet. */ - TkWrapMode wrapMode; /* Not used. */ - register TkTextDispChunk *chunkPtr; - /* Structure to fill in with information - * about this chunk. The x field has already - * been set by the caller. */ + TkWrapMode wrapMode, /* Not used. */ + register TkTextDispChunk *chunkPtr) + /* Structure to fill in with information about + * this chunk. The x field has already been + * set by the caller. */ { if (segPtr != textPtr->insertMarkPtr) { return -1; @@ -464,8 +564,8 @@ MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, chunkPtr->displayProc = TkTextInsertDisplayProc; chunkPtr->undisplayProc = InsertUndisplayProc; - chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL; - chunkPtr->bboxProc = (Tk_ChunkBboxProc *) NULL; + chunkPtr->measureProc = NULL; + chunkPtr->bboxProc = NULL; chunkPtr->numBytes = 0; chunkPtr->minAscent = 0; chunkPtr->minDescent = 0; @@ -473,9 +573,8 @@ MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, chunkPtr->width = 0; /* - * Note: can't break a line after the insertion cursor: this - * prevents the insertion cursor from being stranded at the end - * of a line. + * Note: can't break a line after the insertion cursor: this prevents the + * insertion cursor from being stranded at the end of a line. */ chunkPtr->breakIndex = -1; @@ -488,8 +587,7 @@ MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, * * TkTextInsertDisplayProc -- * - * This procedure is called to display the insertion - * cursor. + * This function is called to display the insertion cursor. * * Results: * None. @@ -502,30 +600,43 @@ MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars, /* ARGSUSED */ void -TkTextInsertDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) - TkTextDispChunk *chunkPtr; /* Chunk that is to be drawn. */ - int x; /* X-position in dst at which to - * draw this chunk (may differ from - * the x-position in the chunk because - * of scrolling). */ - int y; /* Y-position at which to draw this - * chunk in dst (x-position is in - * the chunk itself). */ - int height; /* Total height of line. */ - int baseline; /* Offset of baseline from y. */ - Display *display; /* Display to use for drawing. */ - Drawable dst; /* Pixmap or window in which to draw - * chunk. */ - int screenY; /* Y-coordinate in text window that - * corresponds to y. */ +TkTextInsertDisplayProc( + TkText *textPtr, /* The current text widget. */ + TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */ + int x, /* X-position in dst at which to draw this + * chunk (may differ from the x-position in + * the chunk because of scrolling). */ + int y, /* Y-position at which to draw this chunk in + * dst (x-position is in the chunk itself). */ + int height, /* Total height of line. */ + int baseline, /* Offset of baseline from y. */ + Display *display, /* Display to use for drawing. */ + Drawable dst, /* Pixmap or window in which to draw chunk. */ + int screenY) /* Y-coordinate in text window that + * corresponds to y. */ { - TkText *textPtr = (TkText *) chunkPtr->clientData; + /* + * We have no need for the clientData. + */ + + /* TkText *textPtr = (TkText *) chunkPtr->clientData; */ + TkTextIndex index; int halfWidth = textPtr->insertWidth/2; + int rightSideWidth; + int ix = 0, iy = 0, iw = 0, ih = 0, charWidth = 0; + + if(textPtr->insertCursorType) { + TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index); + TkTextIndexBbox(textPtr, &index, &ix, &iy, &iw, &ih, &charWidth); + rightSideWidth = charWidth + halfWidth; + } else { + rightSideWidth = halfWidth; + } - if ((x + halfWidth) < 0) { + if ((x + rightSideWidth) < 0) { /* - * The insertion cursor is off-screen. - * Indicate caret at 0,0 and return. + * The insertion cursor is off-screen. Indicate caret at 0,0 and + * return. */ Tk_SetCaretPos(textPtr->tkwin, 0, 0, height); @@ -535,20 +646,20 @@ TkTextInsertDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) Tk_SetCaretPos(textPtr->tkwin, x - halfWidth, screenY, height); /* - * As a special hack to keep the cursor visible on mono displays - * (or anywhere else that the selection and insertion cursors - * have the same color) write the default background in the cursor - * area (instead of nothing) when the cursor isn't on. Otherwise - * the selection might hide the cursor. + * As a special hack to keep the cursor visible on mono displays (or + * anywhere else that the selection and insertion cursors have the same + * color) write the default background in the cursor area (instead of + * nothing) when the cursor isn't on. Otherwise the selection might hide + * the cursor. */ if (textPtr->flags & INSERT_ON) { Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->insertBorder, - x - halfWidth, y, textPtr->insertWidth, height, + x - halfWidth, y, charWidth + textPtr->insertWidth, height, textPtr->insertBorderWidth, TK_RELIEF_RAISED); } else if (textPtr->selBorder == textPtr->insertBorder) { Tk_Fill3DRectangle(textPtr->tkwin, dst, textPtr->border, - x - halfWidth, y, textPtr->insertWidth, height, + x - halfWidth, y, charWidth + textPtr->insertWidth, height, 0, TK_RELIEF_FLAT); } } @@ -558,9 +669,8 @@ TkTextInsertDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) * * InsertUndisplayProc -- * - * This procedure is called when the insertion cursor is no - * longer at a visible point on the display. It does nothing - * right now. + * This function is called when the insertion cursor is no longer at a + * visible point on the display. It does nothing right now. * * Results: * None. @@ -573,10 +683,9 @@ TkTextInsertDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY) /* ARGSUSED */ static void -InsertUndisplayProc(textPtr, chunkPtr) - TkText *textPtr; /* Overall information about text - * widget. */ - TkTextDispChunk *chunkPtr; /* Chunk that is about to be freed. */ +InsertUndisplayProc( + TkText *textPtr, /* Overall information about text widget. */ + TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */ { return; } @@ -586,41 +695,52 @@ InsertUndisplayProc(textPtr, chunkPtr) * * MarkCheckProc -- * - * This procedure is invoked by the B-tree code to perform - * consistency checks on mark segments. + * This function is invoked by the B-tree code to perform consistency + * checks on mark segments. * * Results: * None. * * Side effects: - * The procedure panics if it detects anything wrong with + * The function panics if it detects anything wrong with * the mark. * *-------------------------------------------------------------- */ static void -MarkCheckProc(markPtr, linePtr) - TkTextSegment *markPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line containing segment. */ +MarkCheckProc( + TkTextSegment *markPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line containing segment. */ { Tcl_HashSearch search; Tcl_HashEntry *hPtr; if (markPtr->body.mark.linePtr != linePtr) { - panic("MarkCheckProc: markPtr->body.mark.linePtr bogus"); + Tcl_Panic("MarkCheckProc: markPtr->body.mark.linePtr bogus"); } /* - * Make sure that the mark is still present in the text's mark - * hash table. + * These two marks are not in the hash table */ - for (hPtr = Tcl_FirstHashEntry(&markPtr->body.mark.textPtr->markTable, + if (markPtr->body.mark.textPtr->insertMarkPtr == markPtr) { + return; + } + if (markPtr->body.mark.textPtr->currentMarkPtr == markPtr) { + return; + } + + /* + * Make sure that the mark is still present in the text's mark hash table. + */ + + for (hPtr = Tcl_FirstHashEntry( + &markPtr->body.mark.textPtr->sharedTextPtr->markTable, &search); hPtr != markPtr->body.mark.hPtr; hPtr = Tcl_NextHashEntry(&search)) { if (hPtr == NULL) { - panic("MarkCheckProc couldn't find hash table entry for mark"); + Tcl_Panic("MarkCheckProc couldn't find hash table entry for mark"); } } } @@ -630,7 +750,7 @@ MarkCheckProc(markPtr, linePtr) * * MarkFindNext -- * - * This procedure searches forward for the next mark. + * This function searches forward for the next mark. * * Results: * A standard Tcl result, which is a mark name or an empty string. @@ -642,56 +762,88 @@ MarkCheckProc(markPtr, linePtr) */ static int -MarkFindNext(interp, textPtr, string) - Tcl_Interp *interp; /* For error reporting */ - TkText *textPtr; /* The widget */ - CONST char *string; /* The starting index or mark name */ +MarkFindNext( + Tcl_Interp *interp, /* For error reporting */ + TkText *textPtr, /* The widget */ + const char *string) /* The starting index or mark name */ { TkTextIndex index; Tcl_HashEntry *hPtr; register TkTextSegment *segPtr; int offset; - - hPtr = Tcl_FindHashEntry(&textPtr->markTable, string); - if (hPtr != NULL) { - /* - * If given a mark name, return the next mark in the list of - * segments, even if it happens to be at the same character position. - */ - segPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + if (!strcmp(string, "insert")) { + segPtr = textPtr->insertMarkPtr; + TkTextMarkSegToIndex(textPtr, segPtr, &index); + segPtr = segPtr->nextPtr; + } else if (!strcmp(string, "current")) { + segPtr = textPtr->currentMarkPtr; TkTextMarkSegToIndex(textPtr, segPtr, &index); segPtr = segPtr->nextPtr; } else { - /* - * For non-mark name indices we want to return any marks that - * are right at the index. - */ - if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) { - return TCL_ERROR; - } - for (offset = 0, segPtr = index.linePtr->segPtr; - segPtr != NULL && offset < index.byteIndex; - offset += segPtr->size, segPtr = segPtr->nextPtr) { - /* Empty loop body */ ; + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string); + if (hPtr != NULL) { + /* + * If given a mark name, return the next mark in the list of + * segments, even if it happens to be at the same character + * position. + */ + + segPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + TkTextMarkSegToIndex(textPtr, segPtr, &index); + segPtr = segPtr->nextPtr; + } else { + /* + * For non-mark name indices we want to return any marks that are + * right at the index. + */ + + if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) { + return TCL_ERROR; + } + for (offset = 0, segPtr = index.linePtr->segPtr; + segPtr != NULL && offset < index.byteIndex; + offset += segPtr->size, segPtr = segPtr->nextPtr) { + /* Empty loop body */ ; + } } } + while (1) { /* - * segPtr points at the first possible candidate, - * or NULL if we ran off the end of the line. + * segPtr points at the first possible candidate, or NULL if we ran + * off the end of the line. */ + for ( ; segPtr != NULL ; segPtr = segPtr->nextPtr) { if (segPtr->typePtr == &tkTextRightMarkType || segPtr->typePtr == &tkTextLeftMarkType) { - Tcl_SetResult(interp, - Tcl_GetHashKey(&textPtr->markTable, segPtr->body.mark.hPtr), - TCL_STATIC); + if (segPtr == textPtr->currentMarkPtr) { + Tcl_SetResult(interp, "current", TCL_STATIC); + } else if (segPtr == textPtr->insertMarkPtr) { + Tcl_SetResult(interp, "insert", TCL_STATIC); + } else if (segPtr->body.mark.hPtr == NULL) { + /* + * Ignore widget-specific marks for the other widgets. + * This is either an insert or a current mark + * (markPtr->body.mark.hPtr actually receives NULL + * for these marks in TkTextSetMark). + * The insert and current marks for textPtr having + * already been tested above, the current segment is + * an insert or current mark from a peer of textPtr, + * which we don't want to return. + */ + continue; + } else { + Tcl_SetResult(interp, + Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, + segPtr->body.mark.hPtr), TCL_STATIC); + } return TCL_OK; } } - index.linePtr = TkBTreeNextLine(index.linePtr); - if (index.linePtr == (TkTextLine *) NULL) { + index.linePtr = TkBTreeNextLine(textPtr, index.linePtr); + if (index.linePtr == NULL) { return TCL_OK; } index.byteIndex = 0; @@ -704,7 +856,7 @@ MarkFindNext(interp, textPtr, string) * * MarkFindPrev -- * - * This procedure searches backwards for the previous mark. + * This function searches backwards for the previous mark. * * Results: * A standard Tcl result, which is a mark name or an empty string. @@ -716,62 +868,111 @@ MarkFindNext(interp, textPtr, string) */ static int -MarkFindPrev(interp, textPtr, string) - Tcl_Interp *interp; /* For error reporting */ - TkText *textPtr; /* The widget */ - CONST char *string; /* The starting index or mark name */ +MarkFindPrev( + Tcl_Interp *interp, /* For error reporting */ + TkText *textPtr, /* The widget */ + const char *string) /* The starting index or mark name */ { TkTextIndex index; Tcl_HashEntry *hPtr; register TkTextSegment *segPtr, *seg2Ptr, *prevPtr; int offset; - - hPtr = Tcl_FindHashEntry(&textPtr->markTable, string); - if (hPtr != NULL) { - /* - * If given a mark name, return the previous mark in the list of - * segments, even if it happens to be at the same character position. - */ - segPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + if (!strcmp(string, "insert")) { + segPtr = textPtr->insertMarkPtr; + TkTextMarkSegToIndex(textPtr, segPtr, &index); + } else if (!strcmp(string, "current")) { + segPtr = textPtr->currentMarkPtr; TkTextMarkSegToIndex(textPtr, segPtr, &index); } else { - /* - * For non-mark name indices we do not return any marks that - * are right at the index. - */ - if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) { - return TCL_ERROR; - } - for (offset = 0, segPtr = index.linePtr->segPtr; - segPtr != NULL && offset < index.byteIndex; - offset += segPtr->size, segPtr = segPtr->nextPtr) { - /* Empty loop body */ ; + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->markTable, string); + if (hPtr != NULL) { + /* + * If given a mark name, return the previous mark in the list of + * segments, even if it happens to be at the same character + * position. + */ + + segPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); + TkTextMarkSegToIndex(textPtr, segPtr, &index); + } else { + /* + * For non-mark name indices we do not return any marks that are + * right at the index. + */ + + if (TkTextGetIndex(interp, textPtr, string, &index) != TCL_OK) { + return TCL_ERROR; + } + for (offset = 0, segPtr = index.linePtr->segPtr; + segPtr != NULL && offset < index.byteIndex; + offset += segPtr->size, segPtr = segPtr->nextPtr) { + /* Empty loop body */ + } } } + while (1) { /* - * segPtr points just past the first possible candidate, - * or at the begining of the line. + * segPtr points just past the first possible candidate, or at the + * beginning of the line. */ - for (prevPtr = NULL, seg2Ptr = index.linePtr->segPtr; + + for (prevPtr = NULL, seg2Ptr = index.linePtr->segPtr; seg2Ptr != NULL && seg2Ptr != segPtr; seg2Ptr = seg2Ptr->nextPtr) { if (seg2Ptr->typePtr == &tkTextRightMarkType || seg2Ptr->typePtr == &tkTextLeftMarkType) { + if (seg2Ptr->body.mark.hPtr == NULL) { + if (seg2Ptr != textPtr->currentMarkPtr && + seg2Ptr != textPtr->insertMarkPtr) { + /* + * This is an insert or current mark from a + * peer of textPtr. + */ + continue; + } + } prevPtr = seg2Ptr; } } if (prevPtr != NULL) { - Tcl_SetResult(interp, - Tcl_GetHashKey(&textPtr->markTable, prevPtr->body.mark.hPtr), - TCL_STATIC); - return TCL_OK; + if (prevPtr == textPtr->currentMarkPtr) { + Tcl_SetResult(interp, "current", TCL_STATIC); + return TCL_OK; + } else if (prevPtr == textPtr->insertMarkPtr) { + Tcl_SetResult(interp, "insert", TCL_STATIC); + return TCL_OK; + } else if (prevPtr->body.mark.hPtr == NULL) { + /* + * Ignore widget-specific marks for the other widgets. + * This is either an insert or a current mark + * (markPtr->body.mark.hPtr actually receives NULL + * for these marks in TkTextSetMark). + * The insert and current marks for textPtr having + * already been tested above, the current segment is + * an insert or current mark from a peer of textPtr, + * which we don't want to return. + */ + } else { + Tcl_SetResult(interp, + Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, + prevPtr->body.mark.hPtr), TCL_STATIC); + return TCL_OK; + } } - index.linePtr = TkBTreePreviousLine(index.linePtr); - if (index.linePtr == (TkTextLine *) NULL) { + index.linePtr = TkBTreePreviousLine(textPtr, index.linePtr); + if (index.linePtr == NULL) { return TCL_OK; } segPtr = NULL; } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c index b05eb8f..b0d33ce 100644 --- a/generic/tkTextTag.c +++ b/generic/tkTextTag.c @@ -1,93 +1,116 @@ -/* +/* * tkTextTag.c -- * - * This module implements the "tag" subcommand of the widget command - * for text widgets, plus most of the other high-level functions - * related to tags. + * This module implements the "tag" subcommand of the widget command for + * text widgets, plus most of the other high-level functions related to + * tags. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "default.h" -#include "tkPort.h" #include "tkInt.h" #include "tkText.h" -static Tk_ConfigSpec tagConfigSpecs[] = { - {TK_CONFIG_BORDER, "-background", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, border), TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-bgstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, bgStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-borderwidth", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextTag, bdString), - TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-elide", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextTag, elideString), - TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK}, - {TK_CONFIG_BITMAP, "-fgstipple", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, fgStipple), TK_CONFIG_NULL_OK}, - {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, tkfont), TK_CONFIG_NULL_OK}, - {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, fgColor), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-justify", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, justifyString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-lmargin1", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, lMargin1String), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-lmargin2", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, lMargin2String), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-offset", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, offsetString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-overstrike", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, overstrikeString), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-relief", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, reliefString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-rmargin", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, rMarginString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-spacing1", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, spacing1String), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-spacing2", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, spacing2String), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-spacing3", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, spacing3String), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-tabs", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, tabString), TK_CONFIG_NULL_OK}, - {TK_CONFIG_STRING, "-underline", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, underlineString), - TK_CONFIG_NULL_OK}, - {TK_CONFIG_CUSTOM, "-wrap", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextTag, wrapMode), - TK_CONFIG_NULL_OK, &TkTextWrapModeOption}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} +/* + * The 'TkWrapMode' enum in tkText.h is used to define a type for the -wrap + * option of tags in a Text widget. These values are used as indices into the + * string table below. Tags are allowed an empty wrap value, but the widget as + * a whole is not. + */ + +static char *wrapStrings[] = { + "char", "none", "word", "", NULL }; /* - * Forward declarations for procedures defined later in this file: + * 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 + * widget as a whole is not. */ -static void ChangeTagPriority _ANSI_ARGS_((TkText *textPtr, - TkTextTag *tagPtr, int prio)); -static TkTextTag * FindTag _ANSI_ARGS_((Tcl_Interp *interp, - TkText *textPtr, CONST char *tagName)); -static void SortTags _ANSI_ARGS_((int numTags, - TkTextTag **tagArrayPtr)); -static int TagSortProc _ANSI_ARGS_((CONST VOID *first, - CONST VOID *second)); +static char *tabStyleStrings[] = { + "tabular", "wordprocessor", "", NULL +}; + +static const Tk_OptionSpec tagOptionSpecs[] = { + {TK_OPTION_BORDER, "-background", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_BITMAP, "-bgstipple", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_PIXELS, "-borderwidth", NULL, NULL, + "0", Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth), + TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-elide", NULL, NULL, + "0", -1, Tk_Offset(TkTextTag, elideString), + TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_BITMAP, "-fgstipple", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_FONT, "-font", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_COLOR, "-foreground", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-justify", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0,0}, + {TK_OPTION_STRING, "-lmargin1", NULL, NULL, + 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_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_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_STRING, "-spacing1", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK,0,0}, + {TK_OPTION_STRING, "-spacing2", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, spacing2String), TK_OPTION_NULL_OK,0,0}, + {TK_OPTION_STRING, "-spacing3", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, spacing3String), TK_OPTION_NULL_OK,0,0}, + {TK_OPTION_STRING, "-tabs", NULL, NULL, + NULL, Tk_Offset(TkTextTag, tabStringPtr), -1, TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING_TABLE, "-tabstyle", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, tabStyle), + TK_OPTION_NULL_OK, (ClientData) tabStyleStrings, 0}, + {TK_OPTION_STRING, "-underline", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, underlineString), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING_TABLE, "-wrap", NULL, NULL, + NULL, -1, Tk_Offset(TkTextTag, wrapMode), + TK_OPTION_NULL_OK, (ClientData) wrapStrings, 0}, + {TK_OPTION_END} +}; + +/* + * Forward declarations for functions defined later in this file: + */ + +static void ChangeTagPriority(TkText *textPtr, TkTextTag *tagPtr, + int prio); +static TkTextTag * FindTag(Tcl_Interp *interp, TkText *textPtr, + Tcl_Obj *tagName); +static void SortTags(int numTags, TkTextTag **tagArrayPtr); +static int TagSortProc(CONST VOID *first, CONST VOID *second); +static void TagBindEvent(TkText *textPtr, XEvent *eventPtr, + int numTags, TkTextTag **tagArrayPtr); /* *-------------------------------------------------------------- * * TkTextTagCmd -- * - * This procedure is invoked to process the "tag" options of - * the widget command for text widgets. See the user documentation - * for details on what it does. + * This function is invoked to process the "tag" options of the widget + * command for text widgets. See the user documentation for details on + * what it does. * * Results: * A standard Tcl result. @@ -99,47 +122,61 @@ static int TagSortProc _ANSI_ARGS_((CONST VOID *first, */ int -TkTextTagCmd(textPtr, interp, argc, argv) - register TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextTagCmd( + register TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "tag". */ + * objv[1] is "tag". */ { - int c, i, addTag; - size_t length; - char *fullOption; + static CONST char *tagOptionStrings[] = { + "add", "bind", "cget", "configure", "delete", "lower", "names", + "nextrange", "prevrange", "raise", "ranges", "remove", NULL + }; + enum tagOptions { + TAG_ADD, TAG_BIND, TAG_CGET, TAG_CONFIGURE, TAG_DELETE, TAG_LOWER, + TAG_NAMES, TAG_NEXTRANGE, TAG_PREVRANGE, TAG_RAISE, TAG_RANGES, + TAG_REMOVE + }; + int optionIndex, i; register TkTextTag *tagPtr; - TkTextIndex first, last, index1, index2; + TkTextIndex index1, index2; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag option ?arg arg ...?\"", (char *) NULL); + if (Tcl_GetIndexFromObj(interp, objv[2], tagOptionStrings, + "tag option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - c = argv[2][0]; - length = strlen(argv[2]); - if ((c == 'a') && (strncmp(argv[2], "add", length) == 0)) { - fullOption = "add"; - addTag = 1; - - addAndRemove: - if (argc < 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag ", fullOption, - " tagName index1 ?index2 index1 index2 ...?\"", - (char *) NULL); + + switch ((enum tagOptions)optionIndex) { + case TAG_ADD: + case TAG_REMOVE: { + int addTag; + + if (((enum tagOptions)optionIndex) == TAG_ADD) { + addTag = 1; + } else { + addTag = 0; + } + if (objc < 5) { + Tcl_WrongNumArgs(interp, 3, objv, + "tagName index1 ?index2 index1 index2 ...?"); return TCL_ERROR; } - tagPtr = TkTextCreateTag(textPtr, argv[3]); - for (i = 4; i < argc; i += 2) { - if (TkTextGetIndex(interp, textPtr, argv[i], &index1) != TCL_OK) { + tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL); + for (i = 4; i < objc; i += 2) { + if (TkTextGetObjIndex(interp, textPtr, objv[i], + &index1) != TCL_OK) { return TCL_ERROR; } - if (argc > (i+1)) { - if (TkTextGetIndex(interp, textPtr, argv[i+1], &index2) - != TCL_OK) { + if (objc > (i+1)) { + if (TkTextGetObjIndex(interp, textPtr, objv[i+1], + &index2) != TCL_OK) { return TCL_ERROR; } if (TkTextIndexCmp(&index1, &index2) >= 0) { @@ -147,85 +184,88 @@ TkTextTagCmd(textPtr, interp, argc, argv) } } else { index2 = index1; - TkTextIndexForwChars(&index2, 1, &index2); + TkTextIndexForwChars(NULL,&index2, 1, &index2, COUNT_INDICES); } if (tagPtr->affectsDisplay) { - TkTextRedrawTag(textPtr, &index1, &index2, tagPtr, !addTag); + TkTextRedrawTag(textPtr->sharedTextPtr, NULL, &index1, &index2, + tagPtr, !addTag); } else { /* - * Still need to trigger enter/leave events on tags that - * have changed. + * Still need to trigger enter/leave events on tags that have + * changed. */ TkTextEventuallyRepick(textPtr); } - TkBTreeTag(&index1, &index2, tagPtr, addTag); - - /* - * If the tag is "sel" then grab the selection if we're supposed - * to export it and don't already have it. Also, invalidate - * partially-completed selection retrievals. - */ - - if (tagPtr == textPtr->selTagPtr) { - XEvent event; + if (TkBTreeTag(&index1, &index2, tagPtr, addTag)) { /* - * Send an event that the selection changed. - * This is equivalent to - * "event generate $textWidget <<Selection>>" + * If the tag is "sel", and we actually adjusted something + * then grab the selection if we're supposed to export it and + * don't already have it. + * + * Also, invalidate partially-completed selection retrievals. + * We only need to check whether the tag is "sel" for this + * textPtr (not for other peer widget's "sel" tags) because we + * cannot reach this code path with a different widget's "sel" + * tag. */ - memset((VOID *) &event, 0, sizeof(event)); - event.xany.type = VirtualEvent; - event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.xany.send_event = False; - event.xany.window = Tk_WindowId(textPtr->tkwin); - event.xany.display = Tk_Display(textPtr->tkwin); - ((XVirtualEvent *) &event)->name = Tk_GetUid("Selection"); - Tk_HandleEvent(&event); - - if (addTag && textPtr->exportSelection - && !(textPtr->flags & GOT_SELECTION)) { - Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY, - TkTextLostSelection, (ClientData) textPtr); - textPtr->flags |= GOT_SELECTION; + if (tagPtr == textPtr->selTagPtr) { + /* + * Send an event that the selection changed. This is + * equivalent to: + * event generate $textWidget <<Selection>> + */ + + TkTextSelectionEvent(textPtr); + + if (addTag && textPtr->exportSelection + && !(textPtr->flags & GOT_SELECTION)) { + Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY, + TkTextLostSelection, (ClientData) textPtr); + textPtr->flags |= GOT_SELECTION; + } + textPtr->abortSelections = 1; } - textPtr->abortSelections = 1; } } - } else if ((c == 'b') && (strncmp(argv[2], "bind", length) == 0)) { - if ((argc < 4) || (argc > 6)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag bind tagName ?sequence? ?command?\"", - (char *) NULL); + break; + } + case TAG_BIND: + if ((objc < 4) || (objc > 6)) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?sequence? ?command?"); return TCL_ERROR; } - tagPtr = TkTextCreateTag(textPtr, argv[3]); + tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), NULL); /* - * Make a binding table if the widget doesn't already have - * one. + * Make a binding table if the widget doesn't already have one. */ - if (textPtr->bindingTable == NULL) { - textPtr->bindingTable = Tk_CreateBindingTable(interp); + if (textPtr->sharedTextPtr->bindingTable == NULL) { + textPtr->sharedTextPtr->bindingTable = + Tk_CreateBindingTable(interp); } - if (argc == 6) { + if (objc == 6) { int append = 0; unsigned long mask; + char *fifth = Tcl_GetString(objv[5]); - if (argv[5][0] == 0) { - return Tk_DeleteBinding(interp, textPtr->bindingTable, - (ClientData) tagPtr, argv[4]); + if (fifth[0] == 0) { + return Tk_DeleteBinding(interp, + textPtr->sharedTextPtr->bindingTable, + (ClientData) tagPtr->name, Tcl_GetString(objv[4])); } - if (argv[5][0] == '+') { - argv[5]++; + if (fifth[0] == '+') { + fifth++; append = 1; } - mask = Tk_CreateBinding(interp, textPtr->bindingTable, - (ClientData) tagPtr, argv[4], argv[5], append); + mask = Tk_CreateBinding(interp, + textPtr->sharedTextPtr->bindingTable, + (ClientData) tagPtr->name, Tcl_GetString(objv[4]), fifth, + append); if (mask == 0) { return TCL_ERROR; } @@ -234,89 +274,97 @@ TkTextTagCmd(textPtr, interp, argc, argv) |Button5MotionMask|ButtonPressMask|ButtonReleaseMask |EnterWindowMask|LeaveWindowMask|KeyPressMask |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) { - Tk_DeleteBinding(interp, textPtr->bindingTable, - (ClientData) tagPtr, argv[4]); + Tk_DeleteBinding(interp, textPtr->sharedTextPtr->bindingTable, + (ClientData) tagPtr->name, Tcl_GetString(objv[4])); Tcl_ResetResult(interp); Tcl_AppendResult(interp, "requested illegal events; ", "only key, button, motion, enter, leave, and virtual ", - "events may be used", (char *) NULL); + "events may be used", NULL); return TCL_ERROR; } - } else if (argc == 5) { + } else if (objc == 5) { CONST char *command; - - command = Tk_GetBinding(interp, textPtr->bindingTable, - (ClientData) tagPtr, argv[4]); + + command = Tk_GetBinding(interp, + textPtr->sharedTextPtr->bindingTable, + (ClientData) tagPtr->name, Tcl_GetString(objv[4])); if (command == NULL) { - CONST char *string = Tcl_GetStringResult(interp); + CONST char *string = Tcl_GetStringResult(interp); /* - * Ignore missing binding errors. This is a special hack - * that relies on the error message returned by FindSequence - * in tkBind.c. + * Ignore missing binding errors. This is a special hack that + * relies on the error message returned by FindSequence in + * tkBind.c. */ if (string[0] != '\0') { return TCL_ERROR; - } else { - Tcl_ResetResult(interp); } + Tcl_ResetResult(interp); } else { Tcl_SetResult(interp, (char *) command, TCL_STATIC); } } else { - Tk_GetAllBindings(interp, textPtr->bindingTable, - (ClientData) tagPtr); - } - } else if ((c == 'c') && (strncmp(argv[2], "cget", length) == 0) - && (length >= 2)) { - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag cget tagName option\"", - (char *) NULL); - return TCL_ERROR; + Tk_GetAllBindings(interp, textPtr->sharedTextPtr->bindingTable, + (ClientData) tagPtr->name); } - tagPtr = FindTag(interp, textPtr, argv[3]); - if (tagPtr == NULL) { + break; + case TAG_CGET: + if (objc != 5) { + Tcl_WrongNumArgs(interp, 1, objv, "tag cget tagName option"); return TCL_ERROR; + } else { + Tcl_Obj *objPtr; + + tagPtr = FindTag(interp, textPtr, objv[3]); + if (tagPtr == NULL) { + return TCL_ERROR; + } + objPtr = Tk_GetOptionValue(interp, (char *) tagPtr, + tagPtr->optionTable, objv[4], textPtr->tkwin); + if (objPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; } - return Tk_ConfigureValue(interp, textPtr->tkwin, tagConfigSpecs, - (char *) tagPtr, argv[4], 0); - } else if ((c == 'c') && (strncmp(argv[2], "configure", length) == 0) - && (length >= 2)) { - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag configure tagName ?option? ?value? ", - "?option value ...?\"", (char *) NULL); + break; + case TAG_CONFIGURE: { + int newTag; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, + "tagName ?option? ?value? ?option value ...?"); return TCL_ERROR; } - tagPtr = TkTextCreateTag(textPtr, argv[3]); - if (argc == 4) { - return Tk_ConfigureInfo(interp, textPtr->tkwin, tagConfigSpecs, - (char *) tagPtr, (char *) NULL, 0); - } else if (argc == 5) { - return Tk_ConfigureInfo(interp, textPtr->tkwin, tagConfigSpecs, - (char *) tagPtr, argv[4], 0); + tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]), &newTag); + if (objc <= 5) { + Tcl_Obj *objPtr = Tk_GetOptionInfo(interp, (char *) tagPtr, + tagPtr->optionTable, + (objc == 5) ? objv[4] : NULL, textPtr->tkwin); + + if (objPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; } else { - int result; + int result = TCL_OK; + + if (Tk_SetOptions(interp, (char*)tagPtr, tagPtr->optionTable, + objc-4, objv+4, textPtr->tkwin, NULL, NULL) != TCL_OK) { + return TCL_ERROR; + } - result = Tk_ConfigureWidget(interp, textPtr->tkwin, tagConfigSpecs, - argc-4, argv+4, (char *) tagPtr, 0); /* - * Some of the configuration options, like -underline - * and -justify, require additional translation (this is - * needed because we need to distinguish a particular value - * of an option from "unspecified"). + * Some of the configuration options, like -underline and + * -justify, require additional translation (this is needed + * because we need to distinguish a particular value of an option + * from "unspecified"). */ - if (tagPtr->bdString != NULL) { - if (Tk_GetPixels(interp, textPtr->tkwin, tagPtr->bdString, - &tagPtr->borderWidth) != TCL_OK) { - return TCL_ERROR; - } - if (tagPtr->borderWidth < 0) { - tagPtr->borderWidth = 0; - } + if (tagPtr->borderWidth < 0) { + tagPtr->borderWidth = 0; } if (tagPtr->reliefString != NULL) { if (Tk_GetRelief(interp, tagPtr->reliefString, @@ -391,9 +439,9 @@ TkTextTagCmd(textPtr, interp, argc, argv) ckfree((char *) tagPtr->tabArrayPtr); tagPtr->tabArrayPtr = NULL; } - if (tagPtr->tabString != NULL) { - tagPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr->tkwin, - tagPtr->tabString); + if (tagPtr->tabStringPtr != NULL) { + tagPtr->tabArrayPtr = + TkTextGetTabs(interp, textPtr, tagPtr->tabStringPtr); if (tagPtr->tabArrayPtr == NULL) { return TCL_ERROR; } @@ -413,55 +461,82 @@ TkTextTagCmd(textPtr, interp, argc, argv) /* * If the "sel" tag was changed, be sure to mirror information - * from the tag back into the text widget record. NOTE: we - * don't have to free up information in the widget record - * before overwriting it, because it was mirrored in the tag - * and hence freed when the tag field was overwritten. + * from the tag back into the text widget record. NOTE: we don't + * have to free up information in the widget record before + * overwriting it, because it was mirrored in the tag and hence + * freed when the tag field was overwritten. */ if (tagPtr == textPtr->selTagPtr) { textPtr->selBorder = tagPtr->border; - textPtr->selBdString = tagPtr->bdString; + textPtr->selBorderWidth = tagPtr->borderWidth; + textPtr->selBorderWidthPtr = tagPtr->borderWidthPtr; textPtr->selFgColorPtr = tagPtr->fgColor; } + tagPtr->affectsDisplay = 0; - if ((tagPtr->border != NULL) - || (tagPtr->bdString != NULL) - || (tagPtr->reliefString != NULL) - || (tagPtr->bgStipple != None) - || (tagPtr->fgColor != NULL) || (tagPtr->tkfont != None) - || (tagPtr->fgStipple != None) + tagPtr->affectsDisplayGeometry = 0; + if ((tagPtr->elideString != NULL) + || (tagPtr->tkfont != None) || (tagPtr->justifyString != NULL) || (tagPtr->lMargin1String != NULL) || (tagPtr->lMargin2String != NULL) || (tagPtr->offsetString != NULL) - || (tagPtr->overstrikeString != NULL) || (tagPtr->rMarginString != NULL) || (tagPtr->spacing1String != NULL) || (tagPtr->spacing2String != NULL) || (tagPtr->spacing3String != NULL) - || (tagPtr->tabString != NULL) - || (tagPtr->underlineString != NULL) - || (tagPtr->elideString != NULL) + || (tagPtr->tabStringPtr != NULL) + || (tagPtr->tabStyle != TK_TEXT_TABSTYLE_NONE) || (tagPtr->wrapMode != TEXT_WRAPMODE_NULL)) { tagPtr->affectsDisplay = 1; + tagPtr->affectsDisplayGeometry = 1; + } + if ((tagPtr->border != NULL) + || (tagPtr->reliefString != NULL) + || (tagPtr->bgStipple != None) + || (tagPtr->fgColor != NULL) + || (tagPtr->fgStipple != None) + || (tagPtr->overstrikeString != NULL) + || (tagPtr->underlineString != NULL)) { + tagPtr->affectsDisplay = 1; + } + if (!newTag) { + /* + * This line is not necessary if this is a new tag, since it + * can't possibly have been applied to anything yet. + */ + + /* + * VMD: If this is the 'sel' tag, then we don't need to call + * this for all peers, unless we actually want to synchronize + * sel-style changes across the peers. + */ + + TkTextRedrawTag(textPtr->sharedTextPtr, NULL, + NULL, NULL, tagPtr, 1); } - TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, - (TkTextIndex *) NULL, tagPtr, 1); return result; } - } else if ((c == 'd') && (strncmp(argv[2], "delete", length) == 0)) { + break; + } + case TAG_DELETE: { Tcl_HashEntry *hPtr; - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag delete tagName tagName ...\"", - (char *) NULL); + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?"); return TCL_ERROR; } - for (i = 3; i < argc; i++) { - hPtr = Tcl_FindHashEntry(&textPtr->tagTable, argv[i]); + for (i = 3; i < objc; i++) { + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable, + Tcl_GetString(objv[i])); if (hPtr == NULL) { + /* + * Either this tag doesn't exist or it's the 'sel' tag (which + * is not in the hash table). Either way we don't want to + * delete it. + */ + continue; } tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr); @@ -469,62 +544,28 @@ TkTextTagCmd(textPtr, interp, argc, argv) continue; } if (tagPtr->affectsDisplay) { - TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, - (TkTextIndex *) NULL, tagPtr, 1); + TkTextRedrawTag(textPtr->sharedTextPtr, NULL, + NULL, NULL, tagPtr, 1); } - TkTextMakeByteIndex(textPtr->tree, 0, 0, &first); - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), - 0, &last), - TkBTreeTag(&first, &last, tagPtr, 0); - - if (tagPtr == textPtr->selTagPtr) { - XEvent event; - /* - * Send an event that the selection changed. - * This is equivalent to - * "event generate $textWidget <<Selection>>" - */ - - memset((VOID *) &event, 0, sizeof(event)); - event.xany.type = VirtualEvent; - event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin)); - event.xany.send_event = False; - event.xany.window = Tk_WindowId(textPtr->tkwin); - event.xany.display = Tk_Display(textPtr->tkwin); - ((XVirtualEvent *) &event)->name = Tk_GetUid("Selection"); - Tk_HandleEvent(&event); - } - + TkTextDeleteTag(textPtr, tagPtr); Tcl_DeleteHashEntry(hPtr); - if (textPtr->bindingTable != NULL) { - Tk_DeleteAllBindings(textPtr->bindingTable, - (ClientData) tagPtr); - } - - /* - * Update the tag priorities to reflect the deletion of this tag. - */ - - ChangeTagPriority(textPtr, tagPtr, textPtr->numTags-1); - textPtr->numTags -= 1; - TkTextFreeTag(textPtr, tagPtr); } - } else if ((c == 'l') && (strncmp(argv[2], "lower", length) == 0)) { + break; + } + case TAG_LOWER: { TkTextTag *tagPtr2; int prio; - if ((argc != 4) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag lower tagName ?belowThis?\"", - (char *) NULL); + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?belowThis?"); return TCL_ERROR; } - tagPtr = FindTag(interp, textPtr, argv[3]); + tagPtr = FindTag(interp, textPtr, objv[3]); if (tagPtr == NULL) { return TCL_ERROR; } - if (argc == 5) { - tagPtr2 = FindTag(interp, textPtr, argv[4]); + if (objc == 5) { + tagPtr2 = FindTag(interp, textPtr, objv[4]); if (tagPtr2 == NULL) { return TCL_ERROR; } @@ -537,81 +578,99 @@ TkTextTagCmd(textPtr, interp, argc, argv) prio = 0; } ChangeTagPriority(textPtr, tagPtr, prio); - TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL, - tagPtr, 1); - } else if ((c == 'n') && (strncmp(argv[2], "names", length) == 0) - && (length >= 2)) { + + /* + * If this is the 'sel' tag, then we don't actually need to call this + * for all peers. + */ + + TkTextRedrawTag(textPtr->sharedTextPtr, NULL, NULL, NULL, tagPtr, 1); + break; + } + case TAG_NAMES: { TkTextTag **arrayPtr; int arraySize; + Tcl_Obj *listObj; - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag names ?index?\"", - (char *) NULL); + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 3, objv, "?index?"); return TCL_ERROR; } - if (argc == 3) { + if (objc == 3) { Tcl_HashSearch search; Tcl_HashEntry *hPtr; arrayPtr = (TkTextTag **) ckalloc((unsigned) - (textPtr->numTags * sizeof(TkTextTag *))); - for (i = 0, hPtr = Tcl_FirstHashEntry(&textPtr->tagTable, &search); + (textPtr->sharedTextPtr->numTags * sizeof(TkTextTag *))); + for (i=0, hPtr = Tcl_FirstHashEntry( + &textPtr->sharedTextPtr->tagTable, &search); hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) { arrayPtr[i] = (TkTextTag *) Tcl_GetHashValue(hPtr); } - arraySize = textPtr->numTags; + + /* + * The 'sel' tag is not in the hash table. + */ + + arrayPtr[i] = textPtr->selTagPtr; + arraySize = ++i; } else { - if (TkTextGetIndex(interp, textPtr, argv[3], &index1) - != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], + &index1) != TCL_OK) { return TCL_ERROR; } - arrayPtr = TkBTreeGetTags(&index1, &arraySize); + arrayPtr = TkBTreeGetTags(&index1, textPtr, &arraySize); if (arrayPtr == NULL) { return TCL_OK; } } + SortTags(arraySize, arrayPtr); + listObj = Tcl_NewListObj(0, NULL); + for (i = 0; i < arraySize; i++) { tagPtr = arrayPtr[i]; - Tcl_AppendElement(interp, tagPtr->name); + Tcl_ListObjAppendElement(interp, listObj, + Tcl_NewStringObj(tagPtr->name,-1)); } + Tcl_SetObjResult(interp, listObj); ckfree((char *) arrayPtr); - } else if ((c == 'n') && (strncmp(argv[2], "nextrange", length) == 0) - && (length >= 2)) { + break; + } + case TAG_NEXTRANGE: { + TkTextIndex last; TkTextSearch tSearch; char position[TK_POS_CHARS]; - if ((argc != 5) && (argc != 6)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag nextrange tagName index1 ?index2?\"", - (char *) NULL); + if ((objc != 5) && (objc != 6)) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?"); return TCL_ERROR; } - tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, argv[3]); + tagPtr = FindTag(NULL, textPtr, objv[3]); if (tagPtr == NULL) { return TCL_OK; } - if (TkTextGetIndex(interp, textPtr, argv[4], &index1) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) { return TCL_ERROR; } - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last); - if (argc == 5) { + if (objc == 5) { index2 = last; - } else if (TkTextGetIndex(interp, textPtr, argv[5], &index2) - != TCL_OK) { + } else if (TkTextGetObjIndex(interp, textPtr, objv[5], + &index2) != TCL_OK) { return TCL_ERROR; } /* - * The search below is a bit tricky. Rather than use the B-tree - * facilities to stop the search at index2, let it search up - * until the end of the file but check for a position past index2 - * ourselves. The reason for doing it this way is that we only - * care whether the *start* of the range is before index2; once - * we find the start, we don't want TkBTreeNextTag to abort the - * search because the end of the range is after index2. + * The search below is a bit tricky. Rather than use the B-tree + * facilities to stop the search at index2, let it search up until the + * end of the file but check for a position past index2 ourselves. + * The reason for doing it this way is that we only care whether the + * *start* of the range is before index2; once we find the start, we + * don't want TkBTreeNextTag to abort the search because the end of + * the range is after index2. */ TkBTreeStartSearch(&index1, &last, tagPtr, &tSearch); @@ -620,12 +679,12 @@ TkTextTagCmd(textPtr, interp, argc, argv) int offset; /* - * The first character is tagged. See if there is an - * on-toggle just before the character. If not, then - * skip to the end of this tagged range. + * The first character is tagged. See if there is an on-toggle + * just before the character. If not, then skip to the end of this + * tagged range. */ - for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex; + for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex; offset >= 0; offset -= segPtr->size, segPtr = segPtr->nextPtr) { if ((offset == 0) && (segPtr->typePtr == &tkTextToggleOnType) @@ -634,7 +693,7 @@ TkTextTagCmd(textPtr, interp, argc, argv) } } if (!TkBTreeNextTag(&tSearch)) { - return TCL_OK; + return TCL_OK; } } @@ -645,87 +704,139 @@ TkTextTagCmd(textPtr, interp, argc, argv) if (!TkBTreeNextTag(&tSearch)) { return TCL_OK; } - gotStart: + + gotStart: if (TkTextIndexCmp(&tSearch.curIndex, &index2) >= 0) { return TCL_OK; } - TkTextPrintIndex(&tSearch.curIndex, position); + TkTextPrintIndex(textPtr, &tSearch.curIndex, position); Tcl_AppendElement(interp, position); TkBTreeNextTag(&tSearch); - TkTextPrintIndex(&tSearch.curIndex, position); + TkTextPrintIndex(textPtr, &tSearch.curIndex, position); Tcl_AppendElement(interp, position); - } else if ((c == 'p') && (strncmp(argv[2], "prevrange", length) == 0) - && (length >= 2)) { + break; + } + case TAG_PREVRANGE: { + TkTextIndex last; TkTextSearch tSearch; char position1[TK_POS_CHARS]; char position2[TK_POS_CHARS]; - if ((argc != 5) && (argc != 6)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag prevrange tagName index1 ?index2?\"", - (char *) NULL); + if ((objc != 5) && (objc != 6)) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?"); return TCL_ERROR; } - tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, argv[3]); + tagPtr = FindTag(NULL, textPtr, objv[3]); if (tagPtr == NULL) { return TCL_OK; } - if (TkTextGetIndex(interp, textPtr, argv[4], &index1) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) { return TCL_ERROR; } - if (argc == 5) { - TkTextMakeByteIndex(textPtr->tree, 0, 0, &index2); - } else if (TkTextGetIndex(interp, textPtr, argv[5], &index2) - != TCL_OK) { + if (objc == 5) { + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, + &index2); + } else if (TkTextGetObjIndex(interp, textPtr, objv[5], + &index2) != TCL_OK) { return TCL_ERROR; } /* - * The search below is a bit weird. The previous toggle can be - * either an on or off toggle. If it is an on toggle, then we - * need to turn around and search forward for the end toggle. - * Otherwise we keep searching backwards. + * The search below is a bit weird. The previous toggle can be either + * an on or off toggle. If it is an on toggle, then we need to turn + * around and search forward for the end toggle. Otherwise we keep + * searching backwards. */ TkBTreeStartSearchBack(&index1, &index2, tagPtr, &tSearch); if (!TkBTreePrevTag(&tSearch)) { + /* + * Special case, there may be a tag off toggle at index1, and a + * tag on toggle before the start of a partial peer widget. In + * this case we missed it. + */ + + if (textPtr->start != NULL && (textPtr->start == index2.linePtr) + && (index2.byteIndex == 0) + && TkBTreeCharTagged(&index2, tagPtr) + && (TkTextIndexCmp(&index2, &index1) < 0)) { + /* + * The first character is tagged, so just add the range from + * the first char to the start of the range. + */ + + TkTextPrintIndex(textPtr, &index2, position1); + TkTextPrintIndex(textPtr, &index1, position2); + Tcl_AppendElement(interp, position1); + Tcl_AppendElement(interp, position2); + } return TCL_OK; } + if (tSearch.segPtr->typePtr == &tkTextToggleOnType) { - TkTextPrintIndex(&tSearch.curIndex, position1); - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), + TkTextPrintIndex(textPtr, &tSearch.curIndex, position1); + if (textPtr->start != NULL) { + /* + * Make sure the first index is not before the first allowed + * text index in this widget. + */ + + TkTextIndex firstIndex; + + firstIndex.linePtr = textPtr->start; + firstIndex.byteIndex = 0; + firstIndex.textPtr = NULL; + if (TkTextIndexCmp(&tSearch.curIndex, &firstIndex) < 0) { + if (TkTextIndexCmp(&firstIndex, &index1) >= 0) { + /* + * But now the new first index is actually too far + * along in the text, so nothing is returned. + */ + + return TCL_OK; + } + TkTextPrintIndex(textPtr, &firstIndex, position1); + } + } + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last); TkBTreeStartSearch(&tSearch.curIndex, &last, tagPtr, &tSearch); TkBTreeNextTag(&tSearch); - TkTextPrintIndex(&tSearch.curIndex, position2); + TkTextPrintIndex(textPtr, &tSearch.curIndex, position2); } else { - TkTextPrintIndex(&tSearch.curIndex, position2); + TkTextPrintIndex(textPtr, &tSearch.curIndex, position2); TkBTreePrevTag(&tSearch); + TkTextPrintIndex(textPtr, &tSearch.curIndex, position1); if (TkTextIndexCmp(&tSearch.curIndex, &index2) < 0) { - return TCL_OK; + if (textPtr->start != NULL && index2.linePtr == textPtr->start + && index2.byteIndex == 0) { + /* It's ok */ + TkTextPrintIndex(textPtr, &index2, position1); + } else { + return TCL_OK; + } } - TkTextPrintIndex(&tSearch.curIndex, position1); } Tcl_AppendElement(interp, position1); Tcl_AppendElement(interp, position2); - } else if ((c == 'r') && (strncmp(argv[2], "raise", length) == 0) - && (length >= 3)) { + break; + } + case TAG_RAISE: { TkTextTag *tagPtr2; int prio; - if ((argc != 4) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag raise tagName ?aboveThis?\"", - (char *) NULL); + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?aboveThis?"); return TCL_ERROR; } - tagPtr = FindTag(interp, textPtr, argv[3]); + tagPtr = FindTag(interp, textPtr, objv[3]); if (tagPtr == NULL) { return TCL_ERROR; } - if (argc == 5) { - tagPtr2 = FindTag(interp, textPtr, argv[4]); + if (objc == 5) { + tagPtr2 = FindTag(interp, textPtr, objv[4]); if (tagPtr2 == NULL) { return TCL_ERROR; } @@ -735,48 +846,61 @@ TkTextTagCmd(textPtr, interp, argc, argv) prio = tagPtr2->priority + 1; } } else { - prio = textPtr->numTags-1; + prio = textPtr->sharedTextPtr->numTags-1; } ChangeTagPriority(textPtr, tagPtr, prio); - TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL, - tagPtr, 1); - } else if ((c == 'r') && (strncmp(argv[2], "ranges", length) == 0) - && (length >= 3)) { + + /* + * If this is the 'sel' tag, then we don't actually need to call this + * for all peers. + */ + + TkTextRedrawTag(textPtr->sharedTextPtr, NULL, NULL, NULL, tagPtr, 1); + break; + } + case TAG_RANGES: { + TkTextIndex first, last; TkTextSearch tSearch; - char position[TK_POS_CHARS]; + Tcl_Obj *listObj = Tcl_NewListObj(0, NULL); + int count = 0; - if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " tag ranges tagName\"", (char *) NULL); + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName"); return TCL_ERROR; } - tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, argv[3]); + tagPtr = FindTag(NULL, textPtr, objv[3]); if (tagPtr == NULL) { return TCL_OK; } - TkTextMakeByteIndex(textPtr->tree, 0, 0, &first); - TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, + &first); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last); TkBTreeStartSearch(&first, &last, tagPtr, &tSearch); if (TkBTreeCharTagged(&first, tagPtr)) { - TkTextPrintIndex(&first, position); - Tcl_AppendElement(interp, position); + Tcl_ListObjAppendElement(interp, listObj, + TkTextNewIndexObj(textPtr, &first)); + count++; } while (TkBTreeNextTag(&tSearch)) { - TkTextPrintIndex(&tSearch.curIndex, position); - Tcl_AppendElement(interp, position); + Tcl_ListObjAppendElement(interp, listObj, + TkTextNewIndexObj(textPtr, &tSearch.curIndex)); + count++; } - } else if ((c == 'r') && (strncmp(argv[2], "remove", length) == 0) - && (length >= 2)) { - fullOption = "remove"; - addTag = 0; - goto addAndRemove; - } else { - Tcl_AppendResult(interp, "bad tag option \"", argv[2], - "\": must be add, bind, cget, configure, delete, lower, ", - "names, nextrange, raise, ranges, or remove", - (char *) NULL); - return TCL_ERROR; + if (count % 2 == 1) { + /* + * If a text widget uses '-end', it won't necessarily run to the + * end of the B-tree, and therefore the tag range might not be + * closed. In this case we add the end of the range. + */ + + Tcl_ListObjAppendElement(interp, listObj, + TkTextNewIndexObj(textPtr, &last)); + } + Tcl_SetObjResult(interp, listObj); + break; + } } return TCL_OK; } @@ -786,46 +910,68 @@ TkTextTagCmd(textPtr, interp, argc, argv) * * TkTextCreateTag -- * - * Find the record describing a tag within a given text widget, - * creating a new record if one doesn't already exist. + * Find the record describing a tag within a given text widget, creating + * a new record if one doesn't already exist. * * Results: * The return value is a pointer to the TkTextTag record for tagName. * * Side effects: - * A new tag record is created if there isn't one already defined - * for tagName. + * A new tag record is created if there isn't one already defined for + * tagName. * *---------------------------------------------------------------------- */ TkTextTag * -TkTextCreateTag(textPtr, tagName) - TkText *textPtr; /* Widget in which tag is being used. */ - CONST char *tagName; /* Name of desired tag. */ +TkTextCreateTag( + TkText *textPtr, /* Widget in which tag is being used. */ + CONST char *tagName, /* Name of desired tag. */ + int *newTag) /* If non-NULL, then return 1 if new, or 0 if + * already exists. */ { register TkTextTag *tagPtr; - Tcl_HashEntry *hPtr; - int new; - - hPtr = Tcl_CreateHashEntry(&textPtr->tagTable, tagName, &new); - if (!new) { - return (TkTextTag *) Tcl_GetHashValue(hPtr); + Tcl_HashEntry *hPtr = NULL; + int isNew; + CONST char *name; + + if (!strcmp(tagName, "sel")) { + if (textPtr->selTagPtr != NULL) { + if (newTag != NULL) { + *newTag = 0; + } + return textPtr->selTagPtr; + } + if (newTag != NULL) { + *newTag = 1; + } + name = "sel"; + } else { + hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->tagTable, + tagName, &isNew); + if (newTag != NULL) { + *newTag = isNew; + } + if (!isNew) { + return (TkTextTag *) Tcl_GetHashValue(hPtr); + } + name = Tcl_GetHashKey(&textPtr->sharedTextPtr->tagTable, hPtr); } /* - * No existing entry. Create a new one, initialize it, and add a - * pointer to it to the hash table entry. + * No existing entry. Create a new one, initialize it, and add a pointer + * to it to the hash table entry. */ tagPtr = (TkTextTag *) ckalloc(sizeof(TkTextTag)); - tagPtr->name = Tcl_GetHashKey(&textPtr->tagTable, hPtr); + tagPtr->name = name; + tagPtr->textPtr = NULL; tagPtr->toggleCount = 0; tagPtr->tagRootPtr = NULL; - tagPtr->priority = textPtr->numTags; + tagPtr->priority = textPtr->sharedTextPtr->numTags; tagPtr->border = NULL; - tagPtr->bdString = NULL; tagPtr->borderWidth = 0; + tagPtr->borderWidthPtr = NULL; tagPtr->reliefString = NULL; tagPtr->relief = TK_RELIEF_FLAT; tagPtr->bgStipple = None; @@ -850,16 +996,25 @@ TkTextCreateTag(textPtr, tagName) tagPtr->spacing2 = 0; tagPtr->spacing3String = NULL; tagPtr->spacing3 = 0; - tagPtr->tabString = NULL; + tagPtr->tabStringPtr = NULL; tagPtr->tabArrayPtr = NULL; + tagPtr->tabStyle = TK_TEXT_TABSTYLE_NONE; tagPtr->underlineString = NULL; tagPtr->underline = 0; tagPtr->elideString = NULL; tagPtr->elide = 0; tagPtr->wrapMode = TEXT_WRAPMODE_NULL; tagPtr->affectsDisplay = 0; - textPtr->numTags++; - Tcl_SetHashValue(hPtr, tagPtr); + tagPtr->affectsDisplayGeometry = 0; + textPtr->sharedTextPtr->numTags++; + if (!strcmp(tagName, "sel")) { + tagPtr->textPtr = textPtr; + textPtr->refCount++; + } else { + Tcl_SetHashValue(hPtr, tagPtr); + } + tagPtr->optionTable = + Tk_CreateOptionTable(textPtr->interp, tagOptionSpecs); return tagPtr; } @@ -871,10 +1026,9 @@ TkTextCreateTag(textPtr, tagName) * See if tag is defined for a given widget. * * Results: - * If tagName is defined in textPtr, a pointer to its TkTextTag - * structure is returned. Otherwise NULL is returned and an - * error message is recorded in the interp's result unless interp - * is NULL. + * If tagName is defined in textPtr, a pointer to its TkTextTag structure + * is returned. Otherwise NULL is returned and an error message is + * recorded in the interp's result unless interp is NULL. * * Side effects: * None. @@ -883,22 +1037,29 @@ TkTextCreateTag(textPtr, tagName) */ static TkTextTag * -FindTag(interp, textPtr, tagName) - Tcl_Interp *interp; /* Interpreter to use for error message; - * if NULL, then don't record an error +FindTag( + Tcl_Interp *interp, /* Interpreter to use for error message; if + * NULL, then don't record an error * message. */ - TkText *textPtr; /* Widget in which tag is being used. */ - CONST char *tagName; /* Name of desired tag. */ + TkText *textPtr, /* Widget in which tag is being used. */ + Tcl_Obj *tagName) /* Name of desired tag. */ { Tcl_HashEntry *hPtr; + int len; + CONST char *str; - hPtr = Tcl_FindHashEntry(&textPtr->tagTable, tagName); + str = Tcl_GetStringFromObj(tagName, &len); + if (len == 3 && !strcmp(str,"sel")) { + return textPtr->selTagPtr; + } + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable, + Tcl_GetString(tagName)); if (hPtr != NULL) { return (TkTextTag *) Tcl_GetHashValue(hPtr); } if (interp != NULL) { - Tcl_AppendResult(interp, "tag \"", tagName, - "\" isn't defined in text widget", (char *) NULL); + Tcl_AppendResult(interp, "tag \"", Tcl_GetString(tagName), + "\" isn't defined in text widget", NULL); } return NULL; } @@ -906,10 +1067,76 @@ FindTag(interp, textPtr, tagName) /* *---------------------------------------------------------------------- * + * TkTextDeleteTag -- + * + * This function is called to carry out most actions associated with the + * 'tag delete' sub-command. It will remove all evidence of the tag from + * the B-tree, and then call TkTextFreeTag to clean up the tag structure + * itself. + * + * The only actions this doesn't carry out it to check if the deletion of + * the tag requires something to be re-displayed, and to remove the tag + * from the tagTable (hash table) if that is necessary (i.e. if it's not + * the 'sel' tag). It is expected that the caller carry out both of these + * actions. + * + * Results: + * None. + * + * Side effects: + * Memory and other resources are freed, the B-tree is manipulated. + * + *---------------------------------------------------------------------- + */ + +void +TkTextDeleteTag( + TkText *textPtr, /* Info about overall widget. */ + register TkTextTag *tagPtr) /* Tag being deleted. */ +{ + TkTextIndex first, last; + + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, 0, 0, &first); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), 0, &last), + TkBTreeTag(&first, &last, tagPtr, 0); + + if (tagPtr == textPtr->selTagPtr) { + /* + * Send an event that the selection changed. This is equivalent to: + * event generate $textWidget <<Selection>> + */ + + TkTextSelectionEvent(textPtr); + } else { + /* + * Since all peer widgets have an independent "sel" tag, we + * don't want removal of one sel tag to remove bindings which + * are still valid in other peer widgets. + */ + + if (textPtr->sharedTextPtr->bindingTable != NULL) { + Tk_DeleteAllBindings(textPtr->sharedTextPtr->bindingTable, + (ClientData) tagPtr->name); + } + } + + /* + * Update the tag priorities to reflect the deletion of this tag. + */ + + ChangeTagPriority(textPtr, tagPtr, textPtr->sharedTextPtr->numTags-1); + textPtr->sharedTextPtr->numTags -= 1; + TkTextFreeTag(textPtr, tagPtr); +} + +/* + *---------------------------------------------------------------------- + * * TkTextFreeTag -- * - * This procedure is called when a tag is deleted to free up the - * memory and other resources associated with the tag. + * This function is called when a tag is deleted to free up the memory + * and other resources associated with the tag. * * Results: * None. @@ -921,65 +1148,62 @@ FindTag(interp, textPtr, tagName) */ void -TkTextFreeTag(textPtr, tagPtr) - TkText *textPtr; /* Info about overall widget. */ - register TkTextTag *tagPtr; /* Tag being deleted. */ +TkTextFreeTag( + TkText *textPtr, /* Info about overall widget. */ + register TkTextTag *tagPtr) /* Tag being deleted. */ { - if (tagPtr->border != None) { - Tk_Free3DBorder(tagPtr->border); - } - if (tagPtr->bdString != NULL) { - ckfree(tagPtr->bdString); - } - if (tagPtr->reliefString != NULL) { - ckfree(tagPtr->reliefString); - } - if (tagPtr->bgStipple != None) { - Tk_FreeBitmap(textPtr->display, tagPtr->bgStipple); - } - if (tagPtr->fgColor != None) { - Tk_FreeColor(tagPtr->fgColor); - } - Tk_FreeFont(tagPtr->tkfont); - if (tagPtr->fgStipple != None) { - Tk_FreeBitmap(textPtr->display, tagPtr->fgStipple); - } - if (tagPtr->justifyString != NULL) { - ckfree(tagPtr->justifyString); - } - if (tagPtr->lMargin1String != NULL) { - ckfree(tagPtr->lMargin1String); - } - if (tagPtr->lMargin2String != NULL) { - ckfree(tagPtr->lMargin2String); - } - if (tagPtr->offsetString != NULL) { - ckfree(tagPtr->offsetString); - } - if (tagPtr->overstrikeString != NULL) { - ckfree(tagPtr->overstrikeString); - } - if (tagPtr->rMarginString != NULL) { - ckfree(tagPtr->rMarginString); - } - if (tagPtr->spacing1String != NULL) { - ckfree(tagPtr->spacing1String); - } - if (tagPtr->spacing2String != NULL) { - ckfree(tagPtr->spacing2String); - } - if (tagPtr->spacing3String != NULL) { - ckfree(tagPtr->spacing3String); - } - if (tagPtr->tabString != NULL) { - ckfree(tagPtr->tabString); - } + int i; + + /* + * Let Tk do most of the hard work for us. + */ + + Tk_FreeConfigOptions((char *) tagPtr, tagPtr->optionTable, + textPtr->tkwin); + + /* + * This associated information is managed by us. + */ + if (tagPtr->tabArrayPtr != NULL) { ckfree((char *) tagPtr->tabArrayPtr); } - if (tagPtr->underlineString != NULL) { - ckfree(tagPtr->underlineString); + + /* + * Make sure this tag isn't referenced from the 'current' tag array. + */ + + for (i = 0; i < textPtr->numCurTags; i++) { + if (textPtr->curTagArrayPtr[i] == tagPtr) { + for (; i < textPtr->numCurTags-1; i++) { + textPtr->curTagArrayPtr[i] = textPtr->curTagArrayPtr[i+1]; + } + textPtr->curTagArrayPtr[textPtr->numCurTags-1] = NULL; + textPtr->numCurTags--; + break; + } + } + + /* + * If this tag is widget-specific (peer widgets) then clean up the + * refCount it holds. + */ + + if (tagPtr->textPtr != NULL) { + if (textPtr != tagPtr->textPtr) { + Tcl_Panic("Tag being deleted from wrong widget"); + } + textPtr->refCount--; + if (textPtr->refCount == 0) { + ckfree((char *) textPtr); + } + tagPtr->textPtr = NULL; } + + /* + * Finally free the tag's memory. + */ + ckfree((char *) tagPtr); } @@ -988,9 +1212,8 @@ TkTextFreeTag(textPtr, tagPtr) * * SortTags -- * - * This procedure sorts an array of tag pointers in increasing - * order of priority, optimizing for the common case where the - * array is small. + * This function sorts an array of tag pointers in increasing order of + * priority, optimizing for the common case where the array is small. * * Results: * None. @@ -1002,9 +1225,9 @@ TkTextFreeTag(textPtr, tagPtr) */ static void -SortTags(numTags, tagArrayPtr) - int numTags; /* Number of tag pointers at *tagArrayPtr. */ - TkTextTag **tagArrayPtr; /* Pointer to array of pointers. */ +SortTags( + int numTags, /* Number of tag pointers at *tagArrayPtr. */ + TkTextTag **tagArrayPtr) /* Pointer to array of pointers. */ { int i, j, prio; register TkTextTag **tagPtrPtr; @@ -1028,8 +1251,7 @@ SortTags(numTags, tagArrayPtr) *tagArrayPtr = tmp; } } else { - qsort((VOID *) tagArrayPtr, (unsigned) numTags, sizeof (TkTextTag *), - TagSortProc); + qsort(tagArrayPtr,(unsigned)numTags,sizeof(TkTextTag *),TagSortProc); } } @@ -1038,14 +1260,14 @@ SortTags(numTags, tagArrayPtr) * * TagSortProc -- * - * This procedure is called by qsort when sorting an array of - * tags in priority order. + * This function is called by qsort() when sorting an array of tags in + * priority order. * * Results: - * The return value is -1 if the first argument should be before - * the second element (i.e. it has lower priority), 0 if it's - * equivalent (this should never happen!), and 1 if it should be - * after the second element. + * The return value is -1 if the first argument should be before the + * second element (i.e. it has lower priority), 0 if it's equivalent + * (this should never happen!), and 1 if it should be after the second + * element. * * Side effects: * None. @@ -1054,8 +1276,9 @@ SortTags(numTags, tagArrayPtr) */ static int -TagSortProc(first, second) - CONST VOID *first, *second; /* Elements to be compared. */ +TagSortProc( + CONST void *first, + CONST void *second) /* Elements to be compared. */ { TkTextTag *tagPtr1, *tagPtr2; @@ -1069,28 +1292,26 @@ TagSortProc(first, second) * * ChangeTagPriority -- * - * This procedure changes the priority of a tag by modifying - * its priority and the priorities of other tags that are affected - * by the change. + * This function changes the priority of a tag by modifying its priority + * and the priorities of other tags that are affected by the change. * * Results: * None. * * Side effects: - * Priorities may be changed for some or all of the tags in - * textPtr. The tags will be arranged so that there is exactly - * one tag at each priority level between 0 and textPtr->numTags-1, - * with tagPtr at priority "prio". + * Priorities may be changed for some or all of the tags in textPtr. The + * tags will be arranged so that there is exactly one tag at each + * priority level between 0 and textPtr->sharedTextPtr->numTags-1, with + * tagPtr at priority "prio". * *---------------------------------------------------------------------- */ static void -ChangeTagPriority(textPtr, tagPtr, prio) - TkText *textPtr; /* Information about text widget. */ - TkTextTag *tagPtr; /* Tag whose priority is to be - * changed. */ - int prio; /* New priority for tag. */ +ChangeTagPriority( + TkText *textPtr, /* Information about text widget. */ + TkTextTag *tagPtr, /* Tag whose priority is to be changed. */ + int prio) /* New priority for tag. */ { int low, high, delta; register TkTextTag *tagPtr2; @@ -1100,12 +1321,13 @@ ChangeTagPriority(textPtr, tagPtr, prio) if (prio < 0) { prio = 0; } - if (prio >= textPtr->numTags) { - prio = textPtr->numTags-1; + if (prio >= textPtr->sharedTextPtr->numTags) { + prio = textPtr->sharedTextPtr->numTags-1; } if (prio == tagPtr->priority) { return; - } else if (prio < tagPtr->priority) { + } + if (prio < tagPtr->priority) { low = prio; high = tagPtr->priority-1; delta = 1; @@ -1114,7 +1336,16 @@ ChangeTagPriority(textPtr, tagPtr, prio) high = prio; delta = -1; } - for (hPtr = Tcl_FirstHashEntry(&textPtr->tagTable, &search); + + /* + * Adjust first the 'sel' tag, then all others from the hash table + */ + + if ((textPtr->selTagPtr->priority >= low) + && (textPtr->selTagPtr->priority <= high)) { + textPtr->selTagPtr->priority += delta; + } + for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->tagTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { tagPtr2 = (TkTextTag *) Tcl_GetHashValue(hPtr); if ((tagPtr2->priority >= low) && (tagPtr2->priority <= high)) { @@ -1129,37 +1360,36 @@ ChangeTagPriority(textPtr, tagPtr, prio) * * TkTextBindProc -- * - * This procedure is invoked by the Tk dispatcher to handle - * events associated with bindings on items. + * This function is invoked by the Tk dispatcher to handle events + * associated with bindings on items. * * Results: * None. * * Side effects: - * Depends on the command invoked as part of the binding - * (if there was any). + * Depends on the command invoked as part of the binding (if there was + * any). * *-------------------------------------------------------------- */ void -TkTextBindProc(clientData, eventPtr) - ClientData clientData; /* Pointer to canvas structure. */ - XEvent *eventPtr; /* Pointer to X event that just - * happened. */ +TkTextBindProc( + ClientData clientData, /* Pointer to canvas structure. */ + XEvent *eventPtr) /* Pointer to X event that just happened. */ { TkText *textPtr = (TkText *) clientData; int repick = 0; -# define AnyButtonMask (Button1Mask|Button2Mask|Button3Mask\ - |Button4Mask|Button5Mask) +# define AnyButtonMask \ + (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask) - Tcl_Preserve((ClientData) textPtr); + textPtr->refCount++; /* - * This code simulates grabs for mouse buttons by keeping track - * of whether a button is pressed and refusing to pick a new current - * character while a button is pressed. + * This code simulates grabs for mouse buttons by keeping track of whether + * a button is pressed and refusing to pick a new current character while + * a button is pressed. */ if (eventPtr->type == ButtonPress) { @@ -1168,24 +1398,24 @@ TkTextBindProc(clientData, eventPtr) int mask; switch (eventPtr->xbutton.button) { - case Button1: - mask = Button1Mask; - break; - case Button2: - mask = Button2Mask; - break; - case Button3: - mask = Button3Mask; - break; - case Button4: - mask = Button4Mask; - break; - case Button5: - mask = Button5Mask; - break; - default: - mask = 0; - break; + case Button1: + mask = Button1Mask; + break; + case Button2: + mask = Button2Mask; + break; + case Button3: + mask = Button3Mask; + break; + case Button4: + mask = Button4Mask; + break; + case Button5: + mask = Button5Mask; + break; + default: + mask = 0; + break; } if ((eventPtr->xbutton.state & AnyButtonMask) == (unsigned) mask) { textPtr->flags &= ~BUTTON_DOWN; @@ -1208,10 +1438,11 @@ TkTextBindProc(clientData, eventPtr) } TkTextPickCurrent(textPtr, eventPtr); } - if ((textPtr->numCurTags > 0) && (textPtr->bindingTable != NULL) - && (textPtr->tkwin != NULL)) { - Tk_BindEvent(textPtr->bindingTable, eventPtr, textPtr->tkwin, - textPtr->numCurTags, (ClientData *) textPtr->curTagArrayPtr); + if ((textPtr->numCurTags > 0) + && (textPtr->sharedTextPtr->bindingTable != NULL) + && (textPtr->tkwin != NULL) && !(textPtr->flags & DESTROYED)) { + TagBindEvent(textPtr, eventPtr, textPtr->numCurTags, + textPtr->curTagArrayPtr); } if (repick) { unsigned int oldState; @@ -1219,12 +1450,16 @@ TkTextBindProc(clientData, eventPtr) oldState = eventPtr->xbutton.state; eventPtr->xbutton.state &= ~(Button1Mask|Button2Mask |Button3Mask|Button4Mask|Button5Mask); - TkTextPickCurrent(textPtr, eventPtr); + if (!(textPtr->flags & DESTROYED)) { + TkTextPickCurrent(textPtr, eventPtr); + } eventPtr->xbutton.state = oldState; } - done: - Tcl_Release((ClientData) textPtr); + done: + if (--textPtr->refCount == 0) { + ckfree((char *) textPtr); + } } /* @@ -1232,57 +1467,55 @@ TkTextBindProc(clientData, eventPtr) * * TkTextPickCurrent -- * - * Find the character containing the coordinates in an event - * and place the "current" mark on that character. If the - * "current" mark has moved then generate a fake leave event - * on the old current character and a fake enter event on the new - * current character. + * Find the character containing the coordinates in an event and place + * the "current" mark on that character. If the "current" mark has moved + * then generate a fake leave event on the old current character and a + * fake enter event on the new current character. * * Results: * None. * * Side effects: - * The current mark for textPtr may change. If it does, - * then the commands associated with character entry and leave - * could do just about anything. For example, the text widget - * might be deleted. It is up to the caller to protect itself - * with calls to Tcl_Preserve and Tcl_Release. + * The current mark for textPtr may change. If it does, then the commands + * associated with character entry and leave could do just about + * anything. For example, the text widget might be deleted. It is up to + * the caller to protect itself by incrementing the refCount of the text + * widget. * *-------------------------------------------------------------- */ void -TkTextPickCurrent(textPtr, eventPtr) - register TkText *textPtr; /* Text widget in which to select - * current character. */ - XEvent *eventPtr; /* Event describing location of - * mouse cursor. Must be EnterWindow, - * LeaveWindow, ButtonRelease, or - * MotionNotify. */ +TkTextPickCurrent( + register TkText *textPtr, /* Text widget in which to select current + * character. */ + XEvent *eventPtr) /* Event describing location of mouse cursor. + * Must be EnterWindow, LeaveWindow, + * ButtonRelease, or MotionNotify. */ { TkTextIndex index; TkTextTag **oldArrayPtr, **newArrayPtr; - TkTextTag **copyArrayPtr = NULL; /* Initialization needed to prevent - * compiler warning. */ - - int numOldTags, numNewTags, i, j, size; + TkTextTag **copyArrayPtr = NULL; + /* Initialization needed to prevent compiler + * warning. */ + int numOldTags, numNewTags, i, j, size, nearby; XEvent event; /* - * If a button is down, then don't do anything at all; we'll be - * called again when all buttons are up, and we can repick then. - * This implements a form of mouse grabbing. + * If a button is down, then don't do anything at all; we'll be called + * again when all buttons are up, and we can repick then. This implements + * a form of mouse grabbing. */ if (textPtr->flags & BUTTON_DOWN) { - if (((eventPtr->type == EnterNotify) || (eventPtr->type == LeaveNotify)) + if (((eventPtr->type == EnterNotify) + || (eventPtr->type == LeaveNotify)) && ((eventPtr->xcrossing.mode == NotifyGrab) || (eventPtr->xcrossing.mode == NotifyUngrab))) { /* - * Special case: the window is being entered or left because - * of a grab or ungrab. In this case, repick after all. - * Furthermore, clear BUTTON_DOWN to release the simulated - * grab. + * Special case: the window is being entered or left because of a + * grab or ungrab. In this case, repick after all. Furthermore, + * clear BUTTON_DOWN to release the simulated grab. */ textPtr->flags &= ~BUTTON_DOWN; @@ -1292,12 +1525,12 @@ TkTextPickCurrent(textPtr, eventPtr) } /* - * Save information about this event in the widget in case we have - * to synthesize more enter and leave events later (e.g. because a - * character was deleted, causing a new character to be underneath - * the mouse cursor). Also translate MotionNotify events into - * EnterNotify events, since that's what gets reported to event - * handlers when the current character changes. + * Save information about this event in the widget in case we have to + * synthesize more enter and leave events later (e.g. because a character + * was deleted, causing a new character to be underneath the mouse + * cursor). Also translate MotionNotify events into EnterNotify events, + * since that's what gets reported to event handlers when the current + * character changes. */ if (eventPtr != &textPtr->pickEvent) { @@ -1328,33 +1561,37 @@ TkTextPickCurrent(textPtr, eventPtr) } /* - * Find the new current character, then find and sort all of the - * tags associated with it. + * Find the new current character, then find and sort all of the tags + * associated with it. */ if (textPtr->pickEvent.type != LeaveNotify) { TkTextPixelIndex(textPtr, textPtr->pickEvent.xcrossing.x, - textPtr->pickEvent.xcrossing.y, &index); - newArrayPtr = TkBTreeGetTags(&index, &numNewTags); - SortTags(numNewTags, newArrayPtr); + textPtr->pickEvent.xcrossing.y, &index, &nearby); + if (nearby) { + newArrayPtr = NULL; + numNewTags = 0; + } else { + newArrayPtr = TkBTreeGetTags(&index, textPtr, &numNewTags); + SortTags(numNewTags, newArrayPtr); + } } else { newArrayPtr = NULL; numNewTags = 0; } /* - * Resort the tags associated with the previous marked character - * (the priorities might have changed), then make a copy of the - * new tags, and compare the old tags to the copy, nullifying - * any tags that are present in both groups (i.e. the tags that - * haven't changed). + * Resort the tags associated with the previous marked character (the + * priorities might have changed), then make a copy of the new tags, and + * compare the old tags to the copy, nullifying any tags that are present + * in both groups (i.e. the tags that haven't changed). */ SortTags(textPtr->numCurTags, textPtr->curTagArrayPtr); if (numNewTags > 0) { size = numNewTags * sizeof(TkTextTag *); copyArrayPtr = (TkTextTag **) ckalloc((unsigned) size); - memcpy((VOID *) copyArrayPtr, (VOID *) newArrayPtr, (size_t) size); + memcpy(copyArrayPtr, newArrayPtr, (size_t) size); for (i = 0; i < textPtr->numCurTags; i++) { for (j = 0; j < numNewTags; j++) { if (textPtr->curTagArrayPtr[i] == copyArrayPtr[j]) { @@ -1367,13 +1604,12 @@ TkTextPickCurrent(textPtr, eventPtr) } /* - * Invoke the binding system with a LeaveNotify event for all of - * the tags that have gone away. We have to be careful here, - * because it's possible that the binding could do something - * (like calling tkwait) that eventually modifies - * textPtr->curTagArrayPtr. To avoid problems in situations like - * this, update curTagArrayPtr to its new value before invoking - * any bindings, and don't use it any more here. + * Invoke the binding system with a LeaveNotify event for all of the tags + * that have gone away. We have to be careful here, because it's possible + * that the binding could do something (like calling tkwait) that + * eventually modifies textPtr->curTagArrayPtr. To avoid problems in + * situations like this, update curTagArrayPtr to its new value before + * invoking any bindings, and don't use it any more here. */ numOldTags = textPtr->numCurTags; @@ -1381,41 +1617,120 @@ TkTextPickCurrent(textPtr, eventPtr) oldArrayPtr = textPtr->curTagArrayPtr; textPtr->curTagArrayPtr = newArrayPtr; if (numOldTags != 0) { - if ((textPtr->bindingTable != NULL) && (textPtr->tkwin != NULL)) { + if ((textPtr->sharedTextPtr->bindingTable != NULL) + && (textPtr->tkwin != NULL) + && !(textPtr->flags & DESTROYED)) { event = textPtr->pickEvent; event.type = LeaveNotify; /* - * Always use a detail of NotifyAncestor. Besides being - * consistent, this avoids problems where the binding code - * will discard NotifyInferior events. + * Always use a detail of NotifyAncestor. Besides being + * consistent, this avoids problems where the binding code will + * discard NotifyInferior events. */ event.xcrossing.detail = NotifyAncestor; - Tk_BindEvent(textPtr->bindingTable, &event, textPtr->tkwin, - numOldTags, (ClientData *) oldArrayPtr); + TagBindEvent(textPtr, &event, numOldTags, oldArrayPtr); } ckfree((char *) oldArrayPtr); } /* - * Reset the "current" mark (be careful to recompute its location, - * since it might have changed during an event binding). Then - * invoke the binding system with an EnterNotify event for all of - * the tags that have just appeared. + * Reset the "current" mark (be careful to recompute its location, since + * it might have changed during an event binding). Then invoke the binding + * system with an EnterNotify event for all of the tags that have just + * appeared. */ TkTextPixelIndex(textPtr, textPtr->pickEvent.xcrossing.x, - textPtr->pickEvent.xcrossing.y, &index); + textPtr->pickEvent.xcrossing.y, &index, &nearby); TkTextSetMark(textPtr, "current", &index); if (numNewTags != 0) { - if ((textPtr->bindingTable != NULL) && (textPtr->tkwin != NULL)) { + if ((textPtr->sharedTextPtr->bindingTable != NULL) + && (textPtr->tkwin != NULL) + && !(textPtr->flags & DESTROYED) && !nearby) { event = textPtr->pickEvent; event.type = EnterNotify; event.xcrossing.detail = NotifyAncestor; - Tk_BindEvent(textPtr->bindingTable, &event, textPtr->tkwin, - numNewTags, (ClientData *) copyArrayPtr); + TagBindEvent(textPtr, &event, numNewTags, copyArrayPtr); } ckfree((char *) copyArrayPtr); } } + +/* + *-------------------------------------------------------------- + * + * TagBindEvent -- + * + * Trigger given events for all tags that match the relevant bindings. + * To handle the "sel" tag correctly in all peer widgets, we must use the + * name of the tags as the binding table element. + * + * Results: + * None. + * + * Side effects: + * Almost anything can be triggered by tag bindings, including deletion + * of the text widget. + * + *-------------------------------------------------------------- + */ + +static void +TagBindEvent( + TkText *textPtr, /* Text widget to fire bindings in. */ + XEvent *eventPtr, /* What actually happened. */ + int numTags, /* Number of relevant tags. */ + TkTextTag **tagArrayPtr) /* Array of relevant tags. */ +{ + #define NUM_BIND_TAGS 10 + CONST char *nameArray[NUM_BIND_TAGS]; + CONST char **nameArrPtr; + int i; + + /* + * Try to avoid allocation unless there are lots of tags. + */ + + if (numTags > NUM_BIND_TAGS) { + nameArrPtr = (CONST char **) ckalloc(numTags * sizeof(CONST char *)); + } else { + nameArrPtr = nameArray; + } + + /* + * We use tag names as keys in the hash table. We do this instead of using + * the actual tagPtr objects because we want one "sel" tag binding for all + * peer widgets, despite the fact that each has its own tagPtr object. + */ + + for (i = 0; i < numTags; i++) { + TkTextTag *tagPtr = tagArrayPtr[i]; + if (tagPtr != NULL) { + nameArrPtr[i] = tagPtr->name; + } else { + /* + * Tag has been deleted elsewhere, and therefore nulled out in + * this array. Tk_BindEvent is clever enough to cope with NULLs + * being thrown at it. + */ + + nameArrPtr[i] = NULL; + } + } + Tk_BindEvent(textPtr->sharedTextPtr->bindingTable, eventPtr, + textPtr->tkwin, numTags, (ClientData *) nameArrPtr); + + if (numTags > NUM_BIND_TAGS) { + ckfree((char *) nameArrPtr); + } +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c index 9f2582e..1758964 100644 --- a/generic/tkTextWind.c +++ b/generic/tkTextWind.c @@ -1,47 +1,37 @@ -/* +/* * tkTextWind.c -- * - * This file contains code that allows arbitrary windows to be - * nested inside text widgets. It also implements the "window" - * widget command for texts. + * This file contains code that allows arbitrary windows to be nested + * inside text widgets. It also implements the "window" widget command + * for texts. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tk.h" -#include "tkText.h" #include "tkPort.h" +#include "tkText.h" /* - * The following structure is the official type record for the - * embedded window geometry manager: + * The following structure is the official type record for the embedded window + * geometry manager: */ -static void EmbWinRequestProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void EmbWinLostSlaveProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); +static void EmbWinRequestProc(ClientData clientData, + Tk_Window tkwin); +static void EmbWinLostSlaveProc(ClientData clientData, + Tk_Window tkwin); -static Tk_GeomMgr textGeomType = { +static const Tk_GeomMgr textGeomType = { "text", /* name */ EmbWinRequestProc, /* requestProc */ EmbWinLostSlaveProc, /* lostSlaveProc */ }; /* - * Definitions for alignment values: - */ - -#define ALIGN_BOTTOM 0 -#define ALIGN_CENTER 1 -#define ALIGN_TOP 2 -#define ALIGN_BASELINE 3 - -/* * Macro that determines the size of an embedded window segment: */ @@ -49,85 +39,79 @@ static Tk_GeomMgr textGeomType = { + sizeof(TkTextEmbWindow))) /* - * Prototypes for procedures defined in this file: + * Prototypes for functions defined in this file: */ -static int AlignParseProc _ANSI_ARGS_((ClientData clientData, - Tcl_Interp *interp, Tk_Window tkwin, - CONST char *value, char *widgRec, int offset)); -static char * AlignPrintProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin, char *widgRec, int offset, - Tcl_FreeProc **freeProcPtr)); -static TkTextSegment * EmbWinCleanupProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static void EmbWinCheckProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr)); -static void EmbWinBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr, - int index, int y, int lineHeight, int baseline, - int *xPtr, int *yPtr, int *widthPtr, - int *heightPtr)); -static int EmbWinConfigure _ANSI_ARGS_((TkText *textPtr, - TkTextSegment *ewPtr, int argc, CONST char **argv)); -static void EmbWinDelayedUnmap _ANSI_ARGS_(( - ClientData clientData)); -static int EmbWinDeleteProc _ANSI_ARGS_((TkTextSegment *segPtr, - TkTextLine *linePtr, int treeGone)); -static void EmbWinDisplayProc _ANSI_ARGS_(( - TkTextDispChunk *chunkPtr, int x, int y, - int lineHeight, int baseline, Display *display, - Drawable dst, int screenY)); -static int EmbWinLayoutProc _ANSI_ARGS_((TkText *textPtr, +static TkTextSegment * EmbWinCleanupProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static void EmbWinCheckProc(TkTextSegment *segPtr, + TkTextLine *linePtr); +static void EmbWinBboxProc(TkText *textPtr, + TkTextDispChunk *chunkPtr, int index, int y, + int lineHeight, int baseline, int *xPtr,int *yPtr, + int *widthPtr, int *heightPtr); +static int EmbWinConfigure(TkText *textPtr, TkTextSegment *ewPtr, + int objc, Tcl_Obj *const objv[]); +static void EmbWinDelayedUnmap(ClientData clientData); +static int EmbWinDeleteProc(TkTextSegment *segPtr, + TkTextLine *linePtr, int treeGone); +static int EmbWinLayoutProc(TkText *textPtr, TkTextIndex *indexPtr, TkTextSegment *segPtr, - int offset, int maxX, int maxChars, - int noCharsYet, TkWrapMode wrapMode, - TkTextDispChunk *chunkPtr)); -static void EmbWinStructureProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void EmbWinUndisplayProc _ANSI_ARGS_((TkText *textPtr, - TkTextDispChunk *chunkPtr)); + int offset, int maxX, int maxChars,int noCharsYet, + TkWrapMode wrapMode, TkTextDispChunk *chunkPtr); +static void EmbWinStructureProc(ClientData clientData, + XEvent *eventPtr); +static void EmbWinUndisplayProc(TkText *textPtr, + TkTextDispChunk *chunkPtr); +static TkTextEmbWindowClient* EmbWinGetClient(const TkText *textPtr, + TkTextSegment *ewPtr); /* * The following structure declares the "embedded window" segment type. */ -static Tk_SegType tkTextEmbWindowType = { - "window", /* name */ - 0, /* leftGravity */ - (Tk_SegSplitProc *) NULL, /* splitProc */ - EmbWinDeleteProc, /* deleteProc */ - EmbWinCleanupProc, /* cleanupProc */ - (Tk_SegLineChangeProc *) NULL, /* lineChangeProc */ - EmbWinLayoutProc, /* layoutProc */ - EmbWinCheckProc /* checkProc */ +static const Tk_SegType tkTextEmbWindowType = { + "window", /* name */ + 0, /* leftGravity */ + NULL, /* splitProc */ + EmbWinDeleteProc, /* deleteProc */ + EmbWinCleanupProc, /* cleanupProc */ + NULL, /* lineChangeProc */ + EmbWinLayoutProc, /* layoutProc */ + EmbWinCheckProc /* checkProc */ +}; + +/* + * Definitions for alignment values: + */ + +static char *alignStrings[] = { + "baseline", "bottom", "center", "top", NULL }; +typedef enum { + ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER, ALIGN_TOP +} alignMode; + /* * Information used for parsing window configuration options: */ -static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc, - (ClientData) NULL}; - -static Tk_ConfigSpec configSpecs[] = { - {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL, - "center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption}, - {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextEmbWindow, create), - TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK}, - {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextEmbWindow, padX), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextEmbWindow, padY), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL, - "0", Tk_Offset(TkTextEmbWindow, stretch), - TK_CONFIG_DONT_SET_DEFAULT}, - {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL, - (char *) NULL, Tk_Offset(TkTextEmbWindow, tkwin), - TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK}, - {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, - (char *) NULL, 0, 0} +static const Tk_OptionSpec optionSpecs[] = { + {TK_OPTION_STRING_TABLE, "-align", NULL, NULL, + "center", -1, Tk_Offset(TkTextEmbWindow, align), + 0, (ClientData) alignStrings, 0}, + {TK_OPTION_STRING, "-create", NULL, NULL, + NULL, -1, Tk_Offset(TkTextEmbWindow, create), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_PIXELS, "-padx", NULL, NULL, + "0", -1, Tk_Offset(TkTextEmbWindow, padX), 0, 0, 0}, + {TK_OPTION_PIXELS, "-pady", NULL, NULL, + "0", -1, Tk_Offset(TkTextEmbWindow, padY), 0, 0, 0}, + {TK_OPTION_BOOLEAN, "-stretch", NULL, NULL, + "0", -1, Tk_Offset(TkTextEmbWindow, stretch), 0, 0, 0}, + {TK_OPTION_WINDOW, "-window", NULL, NULL, + NULL, -1, Tk_Offset(TkTextEmbWindow, tkwin), TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_END} }; /* @@ -135,9 +119,8 @@ static Tk_ConfigSpec configSpecs[] = { * * TkTextWindowCmd -- * - * This procedure implements the "window" widget command - * for text widgets. See the user documentation for details - * on what it does. + * This function implements the "window" widget command for text widgets. + * See the user documentation for details on what it does. * * Results: * A standard Tcl result or error. @@ -149,100 +132,154 @@ static Tk_ConfigSpec configSpecs[] = { */ int -TkTextWindowCmd(textPtr, interp, argc, argv) - register TkText *textPtr; /* Information about text widget. */ - Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - CONST char **argv; /* Argument strings. Someone else has already +TkTextWindowCmd( + register TkText *textPtr, /* Information about text widget. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. Someone else has already * parsed this command enough to know that - * argv[1] is "window". */ + * objv[1] is "window". */ { - size_t length; + int optionIndex; + static const char *windOptionStrings[] = { + "cget", "configure", "create", "names", NULL + }; + enum windOptions { + WIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES + }; register TkTextSegment *ewPtr; - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " window option ?arg arg ...?\"", (char *) NULL); + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?"); + return TCL_ERROR; + } + if (Tcl_GetIndexFromObj(interp, objv[2], windOptionStrings, + "window option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } - length = strlen(argv[2]); - if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) { + switch ((enum windOptions) optionIndex) { + case WIND_CGET: { TkTextIndex index; TkTextSegment *ewPtr; + Tcl_Obj *objPtr; + TkTextEmbWindowClient *client; - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " window cget index option\"", - (char *) NULL); + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "index option"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } - ewPtr = TkTextIndexToSeg(&index, (int *) NULL); + ewPtr = TkTextIndexToSeg(&index, NULL); if (ewPtr->typePtr != &tkTextEmbWindowType) { Tcl_AppendResult(interp, "no embedded window at index \"", - argv[3], "\"", (char *) NULL); + Tcl_GetString(objv[3]), "\"", NULL); + return TCL_ERROR; + } + + /* + * Copy over client specific value before querying. + */ + + client = EmbWinGetClient(textPtr, ewPtr); + if (client != NULL) { + ewPtr->body.ew.tkwin = client->tkwin; + } else { + ewPtr->body.ew.tkwin = NULL; + } + + objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew, + ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin); + if (objPtr == NULL) { return TCL_ERROR; } - return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs, - (char *) &ewPtr->body.ew, argv[4], 0); - } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) { + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; + } + case WIND_CONFIGURE: { TkTextIndex index; TkTextSegment *ewPtr; - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " window configure index ?option value ...?\"", - (char *) NULL); + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } - ewPtr = TkTextIndexToSeg(&index, (int *) NULL); + ewPtr = TkTextIndexToSeg(&index, NULL); if (ewPtr->typePtr != &tkTextEmbWindowType) { Tcl_AppendResult(interp, "no embedded window at index \"", - argv[3], "\"", (char *) NULL); + Tcl_GetString(objv[3]), "\"", NULL); return TCL_ERROR; } - if (argc == 4) { - return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs, - (char *) &ewPtr->body.ew, (char *) NULL, 0); - } else if (argc == 5) { - return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs, - (char *) &ewPtr->body.ew, argv[4], 0); + if (objc <= 5) { + TkTextEmbWindowClient *client; + Tcl_Obj* objPtr; + + /* + * Copy over client specific value before querying. + */ + + client = EmbWinGetClient(textPtr, ewPtr); + if (client != NULL) { + ewPtr->body.ew.tkwin = client->tkwin; + } else { + ewPtr->body.ew.tkwin = NULL; + } + + objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew, + ewPtr->body.ew.optionTable, (objc == 5) ? objv[4] : NULL, + textPtr->tkwin); + if (objPtr == NULL) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, objPtr); + return TCL_OK; } else { - TkTextChanged(textPtr, &index, &index); - return EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4); + TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index); + + /* + * It's probably not true that all window configuration can change + * the line height, so we could be more efficient here and only + * call this when necessary. + */ + + TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); + return EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4); } - } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) { + } + case WIND_CREATE: { TkTextIndex index; int lineIndex; + TkTextEmbWindowClient *client; + int res; /* - * Add a new window. Find where to put the new window, and - * mark that position for redisplay. + * Add a new window. Find where to put the new window, and mark that + * position for redisplay. */ - if (argc < 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " window create index ?option value ...?\"", - (char *) NULL); + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?"); return TCL_ERROR; } - if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) { + if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) { return TCL_ERROR; } /* * Don't allow insertions on the last (dummy) line of the text. */ - - lineIndex = TkBTreeLineIndex(index.linePtr); - if (lineIndex == TkBTreeNumLines(textPtr->tree)) { + + lineIndex = TkBTreeLinesTo(textPtr, index.linePtr); + if (lineIndex == TkBTreeNumLines(textPtr->sharedTextPtr->tree, + textPtr)) { lineIndex--; - TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, textPtr, + lineIndex, 1000000, &index); } /* @@ -252,49 +289,61 @@ TkTextWindowCmd(textPtr, interp, argc, argv) ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE); ewPtr->typePtr = &tkTextEmbWindowType; ewPtr->size = 1; - ewPtr->body.ew.textPtr = textPtr; + ewPtr->body.ew.sharedTextPtr = textPtr->sharedTextPtr; ewPtr->body.ew.linePtr = NULL; ewPtr->body.ew.tkwin = NULL; ewPtr->body.ew.create = NULL; ewPtr->body.ew.align = ALIGN_CENTER; ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0; ewPtr->body.ew.stretch = 0; - ewPtr->body.ew.chunkCount = 0; - ewPtr->body.ew.displayed = 0; + ewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs); + + client = (TkTextEmbWindowClient *) + ckalloc(sizeof(TkTextEmbWindowClient)); + client->next = NULL; + client->textPtr = textPtr; + client->tkwin = NULL; + client->chunkCount = 0; + client->displayed = 0; + client->parent = ewPtr; + ewPtr->body.ew.clients = client; /* - * Link the segment into the text widget, then configure it (delete - * it again if the configuration fails). + * Link the segment into the text widget, then configure it (delete it + * again if the configuration fails). */ - TkTextChanged(textPtr, &index, &index); + TkTextChanged(textPtr->sharedTextPtr, NULL, &index, &index); TkBTreeLinkSegment(ewPtr, &index); - if (EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4) != TCL_OK) { + res = EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4); + client->tkwin = ewPtr->body.ew.tkwin; + if (res != TCL_OK) { TkTextIndex index2; - TkTextIndexForwChars(&index, 1, &index2); - TkBTreeDeleteChars(&index, &index2); + TkTextIndexForwChars(NULL, &index, 1, &index2, COUNT_INDICES); + TkBTreeDeleteIndexRange(textPtr->sharedTextPtr->tree, &index, + &index2); return TCL_ERROR; } - } else if (strncmp(argv[2], "names", length) == 0) { + TkTextInvalidateLineMetrics(textPtr->sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); + break; + } + case WIND_NAMES: { Tcl_HashSearch search; Tcl_HashEntry *hPtr; - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " window names\"", (char *) NULL); + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); return TCL_ERROR; } - for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search); - hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { + for (hPtr = Tcl_FirstHashEntry(&textPtr->sharedTextPtr->windowTable, + &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_AppendElement(interp, - Tcl_GetHashKey(&textPtr->markTable, hPtr)); + Tcl_GetHashKey(&textPtr->sharedTextPtr->markTable, hPtr)); } - } else { - Tcl_AppendResult(interp, "bad window option \"", argv[2], - "\": must be cget, configure, create, or names", - (char *) NULL); - return TCL_ERROR; + break; + } } return TCL_OK; } @@ -304,76 +353,97 @@ TkTextWindowCmd(textPtr, interp, argc, argv) * * EmbWinConfigure -- * - * This procedure is called to handle configuration options - * for an embedded window, using an argc/argv list. + * This function is called to handle configuration options for an + * embedded window, using an objc/objv list. * * Results: - * The return value is a standard Tcl result. If TCL_ERROR is - * returned, then the interp's result contains an error message.. + * The return value is a standard Tcl result. If TCL_ERROR is returned, + * then the interp's result contains an error message.. * * Side effects: - * Configuration information for the embedded window changes, - * such as alignment, stretching, or name of the embedded - * window. + * Configuration information for the embedded window changes, such as + * alignment, stretching, or name of the embedded window. + * + * Note that this function may leave widget specific client information + * with a NULL tkwin attached to ewPtr. While we could choose to clean up + * the client data structure here, there is no need to do so, and it is + * likely that the user is going to adjust the tkwin again soon. * *-------------------------------------------------------------- */ static int -EmbWinConfigure(textPtr, ewPtr, argc, argv) - TkText *textPtr; /* Information about text widget that - * contains embedded window. */ - TkTextSegment *ewPtr; /* Embedded window to be configured. */ - int argc; /* Number of strings in argv. */ - CONST char **argv; /* Array of strings describing configuration +EmbWinConfigure( + TkText *textPtr, /* Information about text widget that contains + * embedded window. */ + TkTextSegment *ewPtr, /* Embedded window to be configured. */ + int objc, /* Number of strings in objv. */ + Tcl_Obj *const objv[]) /* Array of objects describing configuration * options. */ { Tk_Window oldWindow; - Tcl_HashEntry *hPtr; - int new; + TkTextEmbWindowClient *client; + + /* + * Copy over client specific value before querying or setting. + */ + + client = EmbWinGetClient(textPtr, ewPtr); + if (client != NULL) { + ewPtr->body.ew.tkwin = client->tkwin; + } else { + ewPtr->body.ew.tkwin = NULL; + } oldWindow = ewPtr->body.ew.tkwin; - if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs, - argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY) - != TCL_OK) { + if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew, + ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL, + NULL) != TCL_OK) { return TCL_ERROR; } + if (oldWindow != ewPtr->body.ew.tkwin) { if (oldWindow != NULL) { - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&textPtr->windowTable, + Tcl_DeleteHashEntry(Tcl_FindHashEntry( + &textPtr->sharedTextPtr->windowTable, Tk_PathName(oldWindow))); Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, - EmbWinStructureProc, (ClientData) ewPtr); - Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL, - (ClientData) NULL); + EmbWinStructureProc, (ClientData) client); + Tk_ManageGeometry(oldWindow, NULL, (ClientData) NULL); if (textPtr->tkwin != Tk_Parent(oldWindow)) { Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin); } else { Tk_UnmapWindow(oldWindow); } } + if (client != NULL) { + client->tkwin = NULL; + } if (ewPtr->body.ew.tkwin != NULL) { Tk_Window ancestor, parent; + Tcl_HashEntry *hPtr; + int isNew; /* - * Make sure that the text is either the parent of the - * embedded window or a descendant of that parent. Also, - * don't allow a top-level window to be managed inside - * a text. + * Make sure that the text is either the parent of the embedded + * window or a descendant of that parent. Also, don't allow a + * top-level window to be managed inside a text. */ parent = Tk_Parent(ewPtr->body.ew.tkwin); - for (ancestor = textPtr->tkwin; ; - ancestor = Tk_Parent(ancestor)) { + for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (Tk_TopWinHierarchy(ancestor)) { - badMaster: + badMaster: Tcl_AppendResult(textPtr->interp, "can't embed ", Tk_PathName(ewPtr->body.ew.tkwin), " in ", - Tk_PathName(textPtr->tkwin), (char *) NULL); + Tk_PathName(textPtr->tkwin), NULL); ewPtr->body.ew.tkwin = NULL; + if (client != NULL) { + client->tkwin = NULL; + } return TCL_ERROR; } } @@ -382,28 +452,43 @@ EmbWinConfigure(textPtr, ewPtr, argc, argv) goto badMaster; } + if (client == NULL) { + /* + * Have to make the new client. + */ + + client = (TkTextEmbWindowClient *) + ckalloc(sizeof(TkTextEmbWindowClient)); + client->next = ewPtr->body.ew.clients; + client->textPtr = textPtr; + client->tkwin = NULL; + client->chunkCount = 0; + client->displayed = 0; + client->parent = ewPtr; + ewPtr->body.ew.clients = client; + } + client->tkwin = ewPtr->body.ew.tkwin; + /* - * Take over geometry management for the window, plus create - * an event handler to find out when it is deleted. + * Take over geometry management for the window, plus create an + * event handler to find out when it is deleted. */ Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType, - (ClientData) ewPtr); + (ClientData) client); Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask, - EmbWinStructureProc, (ClientData) ewPtr); + EmbWinStructureProc, (ClientData) client); /* - * Special trick! Must enter into the hash table *after* - * calling Tk_ManageGeometry: if the window was already managed - * elsewhere in this text, the Tk_ManageGeometry call will cause - * the entry to be removed, which could potentially lose the new - * entry. + * Special trick! Must enter into the hash table *after* calling + * Tk_ManageGeometry: if the window was already managed elsewhere + * in this text, the Tk_ManageGeometry call will cause the entry + * to be removed, which could potentially lose the new entry. */ - hPtr = Tcl_CreateHashEntry(&textPtr->windowTable, - Tk_PathName(ewPtr->body.ew.tkwin), &new); + hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable, + Tk_PathName(ewPtr->body.ew.tkwin), &isNew); Tcl_SetHashValue(hPtr, ewPtr); - } } return TCL_OK; @@ -412,135 +497,54 @@ EmbWinConfigure(textPtr, ewPtr, argc, argv) /* *-------------------------------------------------------------- * - * AlignParseProc -- - * - * This procedure is invoked by Tk_ConfigureWidget during - * option processing to handle "-align" options for embedded - * windows. - * - * Results: - * A standard Tcl return value. - * - * Side effects: - * The alignment for the embedded window may change. - * - *-------------------------------------------------------------- - */ - - /* ARGSUSED */ -static int -AlignParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* Not used.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window for text widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to TkTextEmbWindow - * structure. */ - int offset; /* Offset into item (ignored). */ -{ - register TkTextEmbWindow *embPtr = (TkTextEmbWindow *) widgRec; - - if (strcmp(value, "baseline") == 0) { - embPtr->align = ALIGN_BASELINE; - } else if (strcmp(value, "bottom") == 0) { - embPtr->align = ALIGN_BOTTOM; - } else if (strcmp(value, "center") == 0) { - embPtr->align = ALIGN_CENTER; - } else if (strcmp(value, "top") == 0) { - embPtr->align = ALIGN_TOP; - } else { - Tcl_AppendResult(interp, "bad alignment \"", value, - "\": must be baseline, bottom, center, or top", - (char *) NULL); - return TCL_ERROR; - } - return TCL_OK; -} - -/* - *-------------------------------------------------------------- - * - * AlignPrintProc -- - * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-align" configuration - * option for embedded windows. - * - * Results: - * The return value is a string describing the embedded - * window's current alignment. - * - * Side effects: - * None. - * - *-------------------------------------------------------------- - */ - - /* ARGSUSED */ -static char * -AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window for text widget. */ - char *widgRec; /* Pointer to TkTextEmbWindow - * structure. */ - int offset; /* Ignored. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ -{ - switch (((TkTextEmbWindow *) widgRec)->align) { - case ALIGN_BASELINE: - return "baseline"; - case ALIGN_BOTTOM: - return "bottom"; - case ALIGN_CENTER: - return "center"; - case ALIGN_TOP: - return "top"; - default: - return "??"; - } -} - -/* - *-------------------------------------------------------------- - * * EmbWinStructureProc -- * - * This procedure is invoked by the Tk event loop whenever - * StructureNotify events occur for a window that's embedded - * in a text widget. This procedure's only purpose is to - * clean up when windows are deleted. + * This function is invoked by the Tk event loop whenever StructureNotify + * events occur for a window that's embedded in a text widget. This + * function's only purpose is to clean up when windows are deleted. * * Results: * None. * * Side effects: - * The window is disassociated from the window segment, and - * the portion of the text is redisplayed. + * The window is disassociated from the window segment, and the portion + * of the text is redisplayed. * *-------------------------------------------------------------- */ static void -EmbWinStructureProc(clientData, eventPtr) - ClientData clientData; /* Pointer to record describing window item. */ - XEvent *eventPtr; /* Describes what just happened. */ +EmbWinStructureProc( + ClientData clientData, /* Pointer to record describing window item. */ + XEvent *eventPtr) /* Describes what just happened. */ { - register TkTextSegment *ewPtr = (TkTextSegment *) clientData; + TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData; + TkTextSegment *ewPtr = client->parent; TkTextIndex index; + Tcl_HashEntry *hPtr; if (eventPtr->type != DestroyNotify) { return; } - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable, - Tk_PathName(ewPtr->body.ew.tkwin))); + hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable, + Tk_PathName(client->tkwin)); + if (hPtr != NULL) { + /* + * This may not exist if the entire widget is being deleted. + */ + + Tcl_DeleteHashEntry(hPtr); + } + ewPtr->body.ew.tkwin = NULL; - index.tree = ewPtr->body.ew.textPtr->tree; + client->tkwin = NULL; + index.tree = ewPtr->body.ew.sharedTextPtr->tree; index.linePtr = ewPtr->body.ew.linePtr; index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr); - TkTextChanged(ewPtr->body.ew.textPtr, &index, &index); + TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index); + TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); } /* @@ -548,8 +552,8 @@ EmbWinStructureProc(clientData, eventPtr) * * EmbWinRequestProc -- * - * This procedure is invoked whenever a window that's associated - * with a window canvas item changes its requested dimensions. + * This function is invoked whenever a window that's associated with a + * window canvas item changes its requested dimensions. * * Results: * None. @@ -563,18 +567,20 @@ EmbWinStructureProc(clientData, eventPtr) /* ARGSUSED */ static void -EmbWinRequestProc(clientData, tkwin) - ClientData clientData; /* Pointer to record for window item. */ - Tk_Window tkwin; /* Window that changed its desired - * size. */ +EmbWinRequestProc( + ClientData clientData, /* Pointer to record for window item. */ + Tk_Window tkwin) /* Window that changed its desired size. */ { - TkTextSegment *ewPtr = (TkTextSegment *) clientData; + TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData; + TkTextSegment *ewPtr = client->parent; TkTextIndex index; - index.tree = ewPtr->body.ew.textPtr->tree; + index.tree = ewPtr->body.ew.sharedTextPtr->tree; index.linePtr = ewPtr->body.ew.linePtr; index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr); - TkTextChanged(ewPtr->body.ew.textPtr, &index, &index); + TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index); + TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); } /* @@ -582,44 +588,126 @@ EmbWinRequestProc(clientData, tkwin) * * EmbWinLostSlaveProc -- * - * This procedure is invoked by the Tk geometry manager when - * a slave window managed by a text widget is claimed away - * by another geometry manager. + * This function is invoked by the Tk geometry manager when a slave + * window managed by a text widget is claimed away by another geometry + * manager. * * Results: * None. * * Side effects: - * The window is disassociated from the window segment, and - * the portion of the text is redisplayed. + * The window is disassociated from the window segment, and the portion + * of the text is redisplayed. * *-------------------------------------------------------------- */ static void -EmbWinLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Pointer to record describing window item. */ - Tk_Window tkwin; /* Window that was claimed away by another +EmbWinLostSlaveProc( + ClientData clientData, /* Pointer to record describing window item. */ + Tk_Window tkwin) /* Window that was claimed away by another * geometry manager. */ { - register TkTextSegment *ewPtr = (TkTextSegment *) clientData; + TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData; + TkTextSegment *ewPtr = client->parent; TkTextIndex index; + Tcl_HashEntry *hPtr; + TkTextEmbWindowClient *loop; - Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask, - EmbWinStructureProc, (ClientData) ewPtr); - Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr); - if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) { - Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin); + Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask, + EmbWinStructureProc, (ClientData) client); + Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) client); + if (client->textPtr->tkwin != Tk_Parent(tkwin)) { + Tk_UnmaintainGeometry(tkwin, client->textPtr->tkwin); } else { Tk_UnmapWindow(tkwin); } - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable, - Tk_PathName(ewPtr->body.ew.tkwin))); + hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable, + Tk_PathName(client->tkwin)); + Tcl_DeleteHashEntry(hPtr); + client->tkwin = NULL; ewPtr->body.ew.tkwin = NULL; - index.tree = ewPtr->body.ew.textPtr->tree; + + /* + * Free up the memory allocation for this client. + */ + + loop = ewPtr->body.ew.clients; + if (loop == client) { + ewPtr->body.ew.clients = client->next; + } else { + while (loop->next != client) { + loop = loop->next; + } + loop->next = client->next; + } + ckfree((char *) client); + + index.tree = ewPtr->body.ew.sharedTextPtr->tree; index.linePtr = ewPtr->body.ew.linePtr; index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr); - TkTextChanged(ewPtr->body.ew.textPtr, &index, &index); + TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index); + TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL, + index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); +} + +/* + *-------------------------------------------------------------- + * + * TkTextWinFreeClient -- + * + * Free up the hash entry and client information for a given embedded + * window. + * + * It is assumed the caller will manage the linked list of clients + * associated with the relevant TkTextSegment. + * + * Results: + * Nothing. + * + * Side effects: + * The embedded window information for a single client is deleted, if it + * exists, and any resources associated with it are released. + * + *-------------------------------------------------------------- + */ + +void +TkTextWinFreeClient( + Tcl_HashEntry *hPtr, /* Hash entry corresponding to this client, or + * NULL */ + TkTextEmbWindowClient *client) + /* Client data structure, with the 'tkwin' + * field to be cleaned up. */ +{ + if (hPtr != NULL) { + /* + * (It's possible for there to be no hash table entry for this window, + * if an error occurred while creating the window segment but before + * the window got added to the table) + */ + + Tcl_DeleteHashEntry(hPtr); + } + + /* + * Delete the event handler for the window before destroying the window, + * so that EmbWinStructureProc doesn't get called (we'll already do + * everything that it would have done, and it will just get confused). + */ + + if (client->tkwin != NULL) { + Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask, + EmbWinStructureProc, (ClientData) client); + Tk_DestroyWindow(client->tkwin); + } + Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) client); + + /* + * Free up this client. + */ + + ckfree((char *) client); } /* @@ -627,8 +715,8 @@ EmbWinLostSlaveProc(clientData, tkwin) * * EmbWinDeleteProc -- * - * This procedure is invoked by the text B-tree code whenever - * an embedded window lies in a range of characters being deleted. + * This function is invoked by the text B-tree code whenever an embedded + * window lies in a range of characters being deleted. * * Results: * Returns 0 to indicate that the deletion has been accepted. @@ -642,42 +730,37 @@ EmbWinLostSlaveProc(clientData, tkwin) /* ARGSUSED */ static int -EmbWinDeleteProc(ewPtr, linePtr, treeGone) - TkTextSegment *ewPtr; /* Segment being deleted. */ - TkTextLine *linePtr; /* Line containing segment. */ - int treeGone; /* Non-zero means the entire tree is - * being deleted, so everything must - * get cleaned up. */ +EmbWinDeleteProc( + TkTextSegment *ewPtr, /* Segment being deleted. */ + TkTextLine *linePtr, /* Line containing segment. */ + int treeGone) /* Non-zero means the entire tree is being + * deleted, so everything must get cleaned + * up. */ { - Tcl_HashEntry *hPtr; + TkTextEmbWindowClient *client; + client = ewPtr->body.ew.clients; - if (ewPtr->body.ew.tkwin != NULL) { - hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.textPtr->windowTable, - Tk_PathName(ewPtr->body.ew.tkwin)); - if (hPtr != NULL) { - /* - * (It's possible for there to be no hash table entry for this - * window, if an error occurred while creating the window segment - * but before the window got added to the table) - */ + while (client != NULL) { + TkTextEmbWindowClient *next = client->next; + Tcl_HashEntry *hPtr = NULL; - Tcl_DeleteHashEntry(hPtr); + if (client->tkwin != NULL) { + hPtr = Tcl_FindHashEntry( + &ewPtr->body.ew.sharedTextPtr->windowTable, + Tk_PathName(client->tkwin)); } + TkTextWinFreeClient(hPtr, client); + client = next; + } + ewPtr->body.ew.clients = NULL; - /* - * Delete the event handler for the window before destroying - * the window, so that EmbWinStructureProc doesn't get called - * (we'll already do everything that it would have done, and - * it will just get confused). - */ + Tk_FreeConfigOptions((char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable, + NULL); + + /* + * Free up all memory allocated. + */ - Tk_DeleteEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask, - EmbWinStructureProc, (ClientData) ewPtr); - Tk_DestroyWindow(ewPtr->body.ew.tkwin); - } - Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) ewPtr); - Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew, - ewPtr->body.ew.textPtr->display, 0); ckfree((char *) ewPtr); return 0; } @@ -687,9 +770,8 @@ EmbWinDeleteProc(ewPtr, linePtr, treeGone) * * EmbWinCleanupProc -- * - * This procedure is invoked by the B-tree code whenever a - * segment containing an embedded window is moved from one - * line to another. + * This function is invoked by the B-tree code whenever a segment + * containing an embedded window is moved from one line to another. * * Results: * None. @@ -701,9 +783,9 @@ EmbWinDeleteProc(ewPtr, linePtr, treeGone) */ static TkTextSegment * -EmbWinCleanupProc(ewPtr, linePtr) - TkTextSegment *ewPtr; /* Mark segment that's being moved. */ - TkTextLine *linePtr; /* Line that now contains segment. */ +EmbWinCleanupProc( + TkTextSegment *ewPtr, /* Mark segment that's being moved. */ + TkTextLine *linePtr) /* Line that now contains segment. */ { ewPtr->body.ew.linePtr = linePtr; return ewPtr; @@ -714,12 +796,11 @@ EmbWinCleanupProc(ewPtr, linePtr) * * EmbWinLayoutProc -- * - * This procedure is the "layoutProc" for embedded window - * segments. + * This function is the "layoutProc" for embedded window segments. * * Results: - * 1 is returned to indicate that the segment should be - * displayed. The chunkPtr structure is filled in. + * 1 is returned to indicate that the segment should be displayed. The + * chunkPtr structure is filled in. * * Side effects: * None, except for filling in chunkPtr. @@ -729,49 +810,105 @@ EmbWinCleanupProc(ewPtr, linePtr) /*ARGSUSED*/ static int -EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, - noCharsYet, wrapMode, chunkPtr) - TkText *textPtr; /* Text widget being layed out. */ - TkTextIndex *indexPtr; /* Identifies first character in chunk. */ - TkTextSegment *ewPtr; /* Segment corresponding to indexPtr. */ - int offset; /* Offset within segPtr corresponding to +EmbWinLayoutProc( + TkText *textPtr, /* Text widget being layed out. */ + TkTextIndex *indexPtr, /* Identifies first character in chunk. */ + TkTextSegment *ewPtr, /* Segment corresponding to indexPtr. */ + int offset, /* Offset within segPtr corresponding to * indexPtr (always 0). */ - int maxX; /* Chunk must not occupy pixels at this + int maxX, /* Chunk must not occupy pixels at this * position or higher. */ - int maxChars; /* Chunk must not include more than this - * many characters. */ - int noCharsYet; /* Non-zero means no characters have been + int maxChars, /* Chunk must not include more than this many + * characters. */ + int noCharsYet, /* Non-zero means no characters have been * assigned to this line yet. */ - TkWrapMode wrapMode; /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR, - * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */ - register TkTextDispChunk *chunkPtr; - /* Structure to fill in with information - * about this chunk. The x field has already - * been set by the caller. */ + TkWrapMode wrapMode, /* Wrap mode to use for line: + * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or + * TEXT_WRAPMODE_WORD. */ + register TkTextDispChunk *chunkPtr) + /* Structure to fill in with information about + * this chunk. The x field has already been + * set by the caller. */ { int width, height; + TkTextEmbWindowClient *client; if (offset != 0) { - panic("Non-zero offset in EmbWinLayoutProc"); + Tcl_Panic("Non-zero offset in EmbWinLayoutProc"); + } + + client = EmbWinGetClient(textPtr, ewPtr); + if (client == NULL) { + ewPtr->body.ew.tkwin = NULL; + } else { + ewPtr->body.ew.tkwin = client->tkwin; } if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) { - int code, new; - Tcl_DString name; + int code, isNew; Tk_Window ancestor; Tcl_HashEntry *hPtr; + const char *before, *string; + Tcl_DString name, buf, *dsPtr = NULL; + + before = ewPtr->body.ew.create; /* - * The window doesn't currently exist. Create it by evaluating - * the creation script. The script must return the window's - * path name: look up that name to get back to the window - * token. Then register ourselves as the geometry manager for - * the window. + * Find everything up to the next % character and append it to the + * result string. */ - code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create); + string = before; + while (*string != 0) { + if ((*string == '%') && (string[1] == '%' || string[1] == 'W')) { + if (dsPtr == NULL) { + Tcl_DStringInit(&buf); + dsPtr = &buf; + } + if (string != before) { + Tcl_DStringAppend(dsPtr, before, (int) (string-before)); + before = string; + } + if (string[1] == '%') { + Tcl_DStringAppend(dsPtr, "%", 1); + } else { + /* + * Substitute string as proper Tcl list element. + */ + + int spaceNeeded, cvtFlags, length; + const char *str = Tk_PathName(textPtr->tkwin); + + spaceNeeded = Tcl_ScanElement(str, &cvtFlags); + length = Tcl_DStringLength(dsPtr); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + spaceNeeded = Tcl_ConvertElement(str, + Tcl_DStringValue(dsPtr) + length, + cvtFlags | TCL_DONT_USE_BRACES); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + } + before += 2; + string++; + } + string++; + } + + /* + * The window doesn't currently exist. Create it by evaluating the + * creation script. The script must return the window's path name: + * look up that name to get back to the window token. Then register + * ourselves as the geometry manager for the window. + */ + + if (dsPtr != NULL) { + Tcl_DStringAppend(dsPtr, before, (int) (string-before)); + code = Tcl_GlobalEval(textPtr->interp, Tcl_DStringValue(dsPtr)); + Tcl_DStringFree(dsPtr); + } else { + code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create); + } if (code != TCL_OK) { - createError: + createError: Tcl_BackgroundError(textPtr->interp); goto gotWindow; } @@ -780,19 +917,19 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, Tcl_ResetResult(textPtr->interp); ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp, Tcl_DStringValue(&name), textPtr->tkwin); + Tcl_DStringFree(&name); if (ewPtr->body.ew.tkwin == NULL) { goto createError; } - for (ancestor = textPtr->tkwin; ; - ancestor = Tk_Parent(ancestor)) { + for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) { break; } if (Tk_TopWinHierarchy(ancestor)) { - badMaster: + badMaster: Tcl_AppendResult(textPtr->interp, "can't embed ", Tk_PathName(ewPtr->body.ew.tkwin), " relative to ", - Tk_PathName(textPtr->tkwin), (char *) NULL); + Tk_PathName(textPtr->tkwin), NULL); Tcl_BackgroundError(textPtr->interp); ewPtr->body.ew.tkwin = NULL; goto gotWindow; @@ -802,21 +939,39 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, || (textPtr->tkwin == ewPtr->body.ew.tkwin)) { goto badMaster; } - Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType, - (ClientData) ewPtr); - Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask, - EmbWinStructureProc, (ClientData) ewPtr); + + if (client == NULL) { + /* + * We just used a '-create' script to make a new window, which we + * now need to add to our client list. + */ + + client = (TkTextEmbWindowClient *) + ckalloc(sizeof(TkTextEmbWindowClient)); + client->next = ewPtr->body.ew.clients; + client->textPtr = textPtr; + client->tkwin = NULL; + client->chunkCount = 0; + client->displayed = 0; + client->parent = ewPtr; + ewPtr->body.ew.clients = client; + } + + client->tkwin = ewPtr->body.ew.tkwin; + Tk_ManageGeometry(client->tkwin, &textGeomType, + (ClientData) client); + Tk_CreateEventHandler(client->tkwin, StructureNotifyMask, + EmbWinStructureProc, (ClientData) client); /* - * Special trick! Must enter into the hash table *after* - * calling Tk_ManageGeometry: if the window was already managed - * elsewhere in this text, the Tk_ManageGeometry call will cause - * the entry to be removed, which could potentially lose the new - * entry. + * Special trick! Must enter into the hash table *after* calling + * Tk_ManageGeometry: if the window was already managed elsewhere in + * this text, the Tk_ManageGeometry call will cause the entry to be + * removed, which could potentially lose the new entry. */ - hPtr = Tcl_CreateHashEntry(&textPtr->windowTable, - Tk_PathName(ewPtr->body.ew.tkwin), &new); + hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable, + Tk_PathName(client->tkwin), &isNew); Tcl_SetHashValue(hPtr, ewPtr); } @@ -824,7 +979,7 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, * See if there's room for this window on this line. */ - gotWindow: + gotWindow: if (ewPtr->body.ew.tkwin == NULL) { width = 0; height = 0; @@ -841,9 +996,9 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, * Fill in the chunk structure. */ - chunkPtr->displayProc = EmbWinDisplayProc; + chunkPtr->displayProc = TkTextEmbWinDisplayProc; chunkPtr->undisplayProc = EmbWinUndisplayProc; - chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL; + chunkPtr->measureProc = NULL; chunkPtr->bboxProc = EmbWinBboxProc; chunkPtr->numBytes = 1; if (ewPtr->body.ew.align == ALIGN_BASELINE) { @@ -859,7 +1014,9 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, chunkPtr->breakIndex = -1; chunkPtr->breakIndex = 1; chunkPtr->clientData = (ClientData) ewPtr; - ewPtr->body.ew.chunkCount += 1; + if (client != NULL) { + client->chunkCount += 1; + } return 1; } @@ -868,84 +1025,89 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars, * * EmbWinCheckProc -- * - * This procedure is invoked by the B-tree code to perform - * consistency checks on embedded windows. + * This function is invoked by the B-tree code to perform consistency + * checks on embedded windows. * * Results: * None. * * Side effects: - * The procedure panics if it detects anything wrong with - * the embedded window. + * The function panics if it detects anything wrong with the embedded + * window. * *-------------------------------------------------------------- */ static void -EmbWinCheckProc(ewPtr, linePtr) - TkTextSegment *ewPtr; /* Segment to check. */ - TkTextLine *linePtr; /* Line containing segment. */ +EmbWinCheckProc( + TkTextSegment *ewPtr, /* Segment to check. */ + TkTextLine *linePtr) /* Line containing segment. */ { if (ewPtr->nextPtr == NULL) { - panic("EmbWinCheckProc: embedded window is last segment in line"); + Tcl_Panic("EmbWinCheckProc: embedded window is last segment in line"); } if (ewPtr->size != 1) { - panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size); + Tcl_Panic("EmbWinCheckProc: embedded window has size %d", ewPtr->size); } } /* *-------------------------------------------------------------- * - * EmbWinDisplayProc -- + * TkTextEmbWinDisplayProc -- * - * This procedure is invoked by the text displaying code - * when it is time to actually draw an embedded window - * chunk on the screen. + * This function is invoked by the text displaying code when it is time + * to actually draw an embedded window chunk on the screen. * * Results: * None. * * Side effects: - * The embedded window gets moved to the correct location - * and mapped onto the screen. + * The embedded window gets moved to the correct location and mapped onto + * the screen. * *-------------------------------------------------------------- */ -static void -EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) - TkTextDispChunk *chunkPtr; /* Chunk that is to be drawn. */ - int x; /* X-position in dst at which to - * draw this chunk (differs from - * the x-position in the chunk because - * of scrolling). */ - int y; /* Top of rectangular bounding box - * for line: tells where to draw this - * chunk in dst (x-position is in - * the chunk itself). */ - int lineHeight; /* Total height of line. */ - int baseline; /* Offset of baseline from y. */ - Display *display; /* Display to use for drawing. */ - Drawable dst; /* Pixmap or window in which to draw */ - int screenY; /* Y-coordinate in text window that - * corresponds to y. */ +void +TkTextEmbWinDisplayProc( + TkText *textPtr, /* Information about text widget. */ + TkTextDispChunk *chunkPtr, /* Chunk that is to be drawn. */ + int x, /* X-position in dst at which to draw this + * chunk (differs from the x-position in the + * chunk because of scrolling). */ + int y, /* Top of rectangular bounding box for line: + * tells where to draw this chunk in dst + * (x-position is in the chunk itself). */ + int lineHeight, /* Total height of line. */ + int baseline, /* Offset of baseline from y. */ + Display *display, /* Display to use for drawing (unused). */ + Drawable dst, /* Pixmap or window in which to draw + * (unused). */ + int screenY) /* Y-coordinate in text window that + * corresponds to y. */ { - TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData; int lineX, windowX, windowY, width, height; Tk_Window tkwin; + TkTextSegment *ewPtr = (TkTextSegment*) chunkPtr->clientData; + TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr); + + if (client == NULL) { + return; + } - tkwin = ewPtr->body.ew.tkwin; + tkwin = client->tkwin; if (tkwin == NULL) { return; } + if ((x + chunkPtr->width) <= 0) { /* - * The window is off-screen; just unmap it. + * The window is off-screen; just unmap it. */ - if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(tkwin)) { - Tk_UnmaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin); + if (textPtr->tkwin != Tk_Parent(tkwin)) { + Tk_UnmaintainGeometry(tkwin, textPtr->tkwin); } else { Tk_UnmapWindow(tkwin); } @@ -953,15 +1115,15 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) } /* - * Compute the window's location and size in the text widget, taking - * into account the align and stretch values for the window. + * Compute the window's location and size in the text widget, taking into + * account the align and stretch values for the window. */ - EmbWinBboxProc(chunkPtr, 0, screenY, lineHeight, baseline, &lineX, - &windowY, &width, &height); + EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline, + &lineX, &windowY, &width, &height); windowX = lineX - chunkPtr->x + x; - if (ewPtr->body.ew.textPtr->tkwin == Tk_Parent(tkwin)) { + if (textPtr->tkwin == Tk_Parent(tkwin)) { if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin)) || (Tk_ReqWidth(tkwin) != Tk_Width(tkwin)) || (height != Tk_Height(tkwin))) { @@ -969,15 +1131,15 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) } Tk_MapWindow(tkwin); } else { - Tk_MaintainGeometry(tkwin, ewPtr->body.ew.textPtr->tkwin, - windowX, windowY, width, height); + Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY, + width, height); } /* * Mark the window as displayed so that it won't get unmapped. */ - ewPtr->body.ew.displayed = 1; + client->displayed = 1; } /* @@ -985,9 +1147,9 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) * * EmbWinUndisplayProc -- * - * This procedure is called when the chunk for an embedded - * window is no longer going to be displayed. It arranges - * for the window associated with the chunk to be unmapped. + * This function is called when the chunk for an embedded window is no + * longer going to be displayed. It arranges for the window associated + * with the chunk to be unmapped. * * Results: * None. @@ -999,25 +1161,29 @@ EmbWinDisplayProc(chunkPtr, x, y, lineHeight, baseline, display, dst, screenY) */ static void -EmbWinUndisplayProc(textPtr, chunkPtr) - TkText *textPtr; /* Overall information about text - * widget. */ - TkTextDispChunk *chunkPtr; /* Chunk that is about to be freed. */ +EmbWinUndisplayProc( + TkText *textPtr, /* Overall information about text widget. */ + TkTextDispChunk *chunkPtr) /* Chunk that is about to be freed. */ { - TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData; + TkTextSegment *ewPtr = (TkTextSegment*) chunkPtr->clientData; + TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr); + + if (client == NULL) { + return; + } - ewPtr->body.ew.chunkCount--; - if (ewPtr->body.ew.chunkCount == 0) { + client->chunkCount--; + if (client->chunkCount == 0) { /* * Don't unmap the window immediately, since there's a good chance - * that it will immediately be redisplayed, perhaps even in the - * same place. Instead, schedule the window to be unmapped later; - * the call to EmbWinDelayedUnmap will be cancelled in the likely - * event that the unmap becomes unnecessary. + * that it will immediately be redisplayed, perhaps even in the same + * place. Instead, schedule the window to be unmapped later; the call + * to EmbWinDelayedUnmap will be cancelled in the likely event that + * the unmap becomes unnecessary. */ - ewPtr->body.ew.displayed = 0; - Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) ewPtr); + client->displayed = 0; + Tcl_DoWhenIdle(EmbWinDelayedUnmap, (ClientData) client); } } @@ -1026,17 +1192,16 @@ EmbWinUndisplayProc(textPtr, chunkPtr) * * EmbWinBboxProc -- * - * This procedure is called to compute the bounding box of - * the area occupied by an embedded window. + * This function is called to compute the bounding box of the area + * occupied by an embedded window. * * Results: - * There is no return value. *xPtr and *yPtr are filled in - * with the coordinates of the upper left corner of the - * window, and *widthPtr and *heightPtr are filled in with - * the dimensions of the window in pixels. Note: not all - * of the returned bbox is necessarily visible on the screen - * (the rightmost part might be off-screen to the right, - * and the bottommost part might be off-screen to the bottom). + * There is no return value. *xPtr and *yPtr are filled in with the + * coordinates of the upper left corner of the window, and *widthPtr and + * *heightPtr are filled in with the dimensions of the window in pixels. + * Note: not all of the returned bbox is necessarily visible on the + * screen (the rightmost part might be off-screen to the right, and the + * bottommost part might be off-screen to the bottom). * * Side effects: * None. @@ -1045,27 +1210,32 @@ EmbWinUndisplayProc(textPtr, chunkPtr) */ static void -EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, - widthPtr, heightPtr) - TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */ - int index; /* Index of desired character within - * the chunk. */ - int y; /* Topmost pixel in area allocated - * for this line. */ - int lineHeight; /* Total height of line. */ - int baseline; /* Location of line's baseline, in - * pixels measured down from y. */ - int *xPtr, *yPtr; /* Gets filled in with coords of - * character's upper-left pixel. */ - int *widthPtr; /* Gets filled in with width of - * character, in pixels. */ - int *heightPtr; /* Gets filled in with height of - * character, in pixels. */ +EmbWinBboxProc( + TkText *textPtr, /* Information about text widget. */ + TkTextDispChunk *chunkPtr, /* Chunk containing desired char. */ + int index, /* Index of desired character within the + * chunk. */ + int y, /* Topmost pixel in area allocated for this + * line. */ + int lineHeight, /* Total height of line. */ + int baseline, /* Location of line's baseline, in pixels + * measured down from y. */ + int *xPtr, int *yPtr, /* Gets filled in with coords of character's + * upper-left pixel. */ + int *widthPtr, /* Gets filled in with width of window, in + * pixels. */ + int *heightPtr) /* Gets filled in with height of window, in + * pixels. */ { - TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData; Tk_Window tkwin; + TkTextSegment *ewPtr = (TkTextSegment *) chunkPtr->clientData; + TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr); - tkwin = ewPtr->body.ew.tkwin; + if (client == NULL) { + tkwin = NULL; + } else { + tkwin = client->tkwin; + } if (tkwin != NULL) { *widthPtr = Tk_ReqWidth(tkwin); *heightPtr = Tk_ReqHeight(tkwin); @@ -1082,18 +1252,18 @@ EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, } } switch (ewPtr->body.ew.align) { - case ALIGN_BOTTOM: - *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY); - break; - case ALIGN_CENTER: - *yPtr = y + (lineHeight - *heightPtr)/2; - break; - case ALIGN_TOP: - *yPtr = y + ewPtr->body.ew.padY; - break; - case ALIGN_BASELINE: - *yPtr = y + (baseline - *heightPtr); - break; + case ALIGN_BOTTOM: + *yPtr = y + (lineHeight - *heightPtr - ewPtr->body.ew.padY); + break; + case ALIGN_CENTER: + *yPtr = y + (lineHeight - *heightPtr)/2; + break; + case ALIGN_TOP: + *yPtr = y + ewPtr->body.ew.padY; + break; + case ALIGN_BASELINE: + *yPtr = y + (baseline - *heightPtr); + break; } } @@ -1102,33 +1272,31 @@ EmbWinBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr, * * EmbWinDelayedUnmap -- * - * This procedure is an idle handler that does the actual - * work of unmapping an embedded window. See the comment - * in EmbWinUndisplayProc for details. + * This function is an idle handler that does the actual work of + * unmapping an embedded window. See the comment in EmbWinUndisplayProc + * for details. * * Results: * None. * * Side effects: - * The window gets unmapped, unless its chunk reference count - * has become non-zero again. + * The window gets unmapped, unless its chunk reference count has become + * non-zero again. * *-------------------------------------------------------------- */ static void -EmbWinDelayedUnmap(clientData) - ClientData clientData; /* Token for the window to - * be unmapped. */ +EmbWinDelayedUnmap( + ClientData clientData) /* Token for the window to be unmapped. */ { - TkTextSegment *ewPtr = (TkTextSegment *) clientData; + TkTextEmbWindowClient *client = (TkTextEmbWindowClient*) clientData; - if (!ewPtr->body.ew.displayed && (ewPtr->body.ew.tkwin != NULL)) { - if (ewPtr->body.ew.textPtr->tkwin != Tk_Parent(ewPtr->body.ew.tkwin)) { - Tk_UnmaintainGeometry(ewPtr->body.ew.tkwin, - ewPtr->body.ew.textPtr->tkwin); + if (!client->displayed && (client->tkwin != NULL)) { + if (client->textPtr->tkwin != Tk_Parent(client->tkwin)) { + Tk_UnmaintainGeometry(client->tkwin, client->textPtr->tkwin); } else { - Tk_UnmapWindow(ewPtr->body.ew.tkwin); + Tk_UnmapWindow(client->tkwin); } } } @@ -1138,14 +1306,13 @@ EmbWinDelayedUnmap(clientData) * * TkTextWindowIndex -- * - * Given the name of an embedded window within a text widget, - * returns an index corresponding to the window's position - * in the text. + * Given the name of an embedded window within a text widget, returns an + * index corresponding to the window's position in the text. * * Results: - * The return value is 1 if there is an embedded window by - * the given name in the text widget, 0 otherwise. If the - * window exists, *indexPtr is filled in with its index. + * The return value is 1 if there is an embedded window by the given name + * in the text widget, 0 otherwise. If the window exists, *indexPtr is + * filled in with its index. * * Side effects: * None. @@ -1154,21 +1321,70 @@ EmbWinDelayedUnmap(clientData) */ int -TkTextWindowIndex(textPtr, name, indexPtr) - TkText *textPtr; /* Text widget containing window. */ - CONST char *name; /* Name of window. */ - TkTextIndex *indexPtr; /* Index information gets stored here. */ +TkTextWindowIndex( + TkText *textPtr, /* Text widget containing window. */ + const char *name, /* Name of window. */ + TkTextIndex *indexPtr) /* Index information gets stored here. */ { Tcl_HashEntry *hPtr; TkTextSegment *ewPtr; - hPtr = Tcl_FindHashEntry(&textPtr->windowTable, name); + hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name); if (hPtr == NULL) { return 0; } + ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr); - indexPtr->tree = textPtr->tree; + indexPtr->tree = textPtr->sharedTextPtr->tree; indexPtr->linePtr = ewPtr->body.ew.linePtr; indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr); return 1; } + +/* + *-------------------------------------------------------------- + * + * EmbWinGetClient -- + * + * Given a text widget and a segment which contains an embedded window, + * find the text-widget specific information about the embedded window, + * if any. + * + * This function performs a completely linear lookup for a matching data + * structure. If we envisage using this code with dozens of peer widgets, + * then performance could become an issue and a more sophisticated lookup + * mechanism might be desirable. + * + * Results: + * NULL if no widget-specific info exists, otherwise the structure is + * returned. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static TkTextEmbWindowClient* +EmbWinGetClient( + const TkText *textPtr, /* Information about text widget. */ + TkTextSegment *ewPtr) /* Segment containing embedded window. */ +{ + TkTextEmbWindowClient *client = ewPtr->body.ew.clients; + + while (client != NULL) { + if (client->textPtr == textPtr) { + return client; + } + client = client->next; + } + return NULL; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkTrig.c b/generic/tkTrig.c index 1e90cf3..d7439b3 100644 --- a/generic/tkTrig.c +++ b/generic/tkTrig.c @@ -1,21 +1,19 @@ -/* +/* * tkTrig.c -- * - * This file contains a collection of trigonometry utility - * routines that are used by Tk and in particular by the - * canvas code. It also has miscellaneous geometry functions - * used by canvases. + * This file contains a collection of trigonometry utility routines that + * are used by Tk and in particular by the canvas code. It also has + * miscellaneous geometry functions used by canvases. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <stdio.h> #include "tkInt.h" -#include "tkPort.h" #include "tkCanvas.h" #undef MIN @@ -34,9 +32,8 @@ * Compute the distance from a point to a finite line segment. * * Results: - * The return value is the distance from the line segment - * whose end-points are *end1Ptr and *end2Ptr to the point - * given by *pointPtr. + * The return value is the distance from the line segment whose + * end-points are *end1Ptr and *end2Ptr to the point given by *pointPtr. * * Side effects: * None. @@ -45,17 +42,17 @@ */ double -TkLineToPoint(end1Ptr, end2Ptr, pointPtr) - double end1Ptr[2]; /* Coordinates of first end-point of line. */ - double end2Ptr[2]; /* Coordinates of second end-point of line. */ - double pointPtr[2]; /* Points to coords for point. */ +TkLineToPoint( + double end1Ptr[2], /* Coordinates of first end-point of line. */ + double end2Ptr[2], /* Coordinates of second end-point of line. */ + double pointPtr[2]) /* Points to coords for point. */ { double x, y; /* - * Compute the point on the line that is closest to the - * point. This must be done separately for vertical edges, - * horizontal edges, and other edges. + * Compute the point on the line that is closest to the point. This must + * be done separately for vertical edges, horizontal edges, and other + * edges. */ if (end1Ptr[0] == end2Ptr[0]) { @@ -90,10 +87,10 @@ TkLineToPoint(end1Ptr, end2Ptr, pointPtr) double m1, b1, m2, b2; /* - * The edge is neither horizontal nor vertical. Convert the - * edge to a line equation of the form y = m1*x + b1. Then - * compute a line perpendicular to this edge but passing - * through the point, also in the form y = m2*x + b2. + * The edge is neither horizontal nor vertical. Convert the edge to a + * line equation of the form y = m1*x + b1. Then compute a line + * perpendicular to this edge but passing through the point, also in + * the form y = m2*x + b2. */ m1 = (end2Ptr[1] - end1Ptr[1])/(end2Ptr[0] - end1Ptr[0]); @@ -133,14 +130,14 @@ TkLineToPoint(end1Ptr, end2Ptr, pointPtr) * * TkLineToArea -- * - * Determine whether a line lies entirely inside, entirely - * outside, or overlapping a given rectangular area. + * Determine whether a line lies entirely inside, entirely outside, or + * overlapping a given rectangular area. * * Results: - * -1 is returned if the line given by end1Ptr and end2Ptr - * is entirely outside the rectangle given by rectPtr. 0 is - * returned if the polygon overlaps the rectangle, and 1 is - * returned if the polygon is entirely inside the rectangle. + * -1 is returned if the line given by end1Ptr and end2Ptr is entirely + * outside the rectangle given by rectPtr. 0 is returned if the polygon + * overlaps the rectangle, and 1 is returned if the polygon is entirely + * inside the rectangle. * * Side effects: * None. @@ -149,20 +146,20 @@ TkLineToPoint(end1Ptr, end2Ptr, pointPtr) */ int -TkLineToArea(end1Ptr, end2Ptr, rectPtr) - double end1Ptr[2]; /* X and y coordinates for one endpoint - * of line. */ - double end2Ptr[2]; /* X and y coordinates for other endpoint - * of line. */ - double rectPtr[4]; /* Points to coords for rectangle, in the - * order x1, y1, x2, y2. X1 must be no - * larger than x2, and y1 no larger than y2. */ +TkLineToArea( + double end1Ptr[2], /* X and y coordinates for one endpoint of + * line. */ + double end2Ptr[2], /* X and y coordinates for other endpoint of + * line. */ + double rectPtr[4]) /* Points to coords for rectangle, in the + * order x1, y1, x2, y2. X1 must be no larger + * than x2, and y1 no larger than y2. */ { int inside1, inside2; /* - * First check the two points individually to see whether they - * are inside the rectangle or not. + * First check the two points individually to see whether they are inside + * the rectangle or not. */ inside1 = (end1Ptr[0] >= rectPtr[0]) && (end1Ptr[0] <= rectPtr[2]) @@ -177,17 +174,16 @@ TkLineToArea(end1Ptr, end2Ptr, rectPtr) } /* - * Both points are outside the rectangle, but still need to check - * for intersections between the line and the rectangle. Horizontal - * and vertical lines are particularly easy, so handle them - * separately. + * Both points are outside the rectangle, but still need to check for + * intersections between the line and the rectangle. Horizontal and + * vertical lines are particularly easy, so handle them separately. */ if (end1Ptr[0] == end2Ptr[0]) { /* * Vertical line. */ - + if (((end1Ptr[1] >= rectPtr[1]) ^ (end2Ptr[1] >= rectPtr[1])) && (end1Ptr[0] >= rectPtr[0]) && (end1Ptr[0] <= rectPtr[2])) { @@ -197,7 +193,7 @@ TkLineToArea(end1Ptr, end2Ptr, rectPtr) /* * Horizontal line. */ - + if (((end1Ptr[0] >= rectPtr[0]) ^ (end2Ptr[0] >= rectPtr[0])) && (end1Ptr[1] >= rectPtr[1]) && (end1Ptr[1] <= rectPtr[3])) { @@ -205,59 +201,63 @@ TkLineToArea(end1Ptr, end2Ptr, rectPtr) } } else { double m, x, y, low, high; - + /* - * Diagonal line. Compute slope of line and use - * for intersection checks against each of the - * sides of the rectangle: left, right, bottom, top. + * Diagonal line. Compute slope of line and use for intersection + * checks against each of the sides of the rectangle: left, right, + * bottom, top. */ - + m = (end2Ptr[1] - end1Ptr[1])/(end2Ptr[0] - end1Ptr[0]); if (end1Ptr[0] < end2Ptr[0]) { - low = end1Ptr[0]; high = end2Ptr[0]; + low = end1Ptr[0]; + high = end2Ptr[0]; } else { - low = end2Ptr[0]; high = end1Ptr[0]; + low = end2Ptr[0]; + high = end1Ptr[0]; } - + /* * Left edge. */ - + y = end1Ptr[1] + (rectPtr[0] - end1Ptr[0])*m; if ((rectPtr[0] >= low) && (rectPtr[0] <= high) && (y >= rectPtr[1]) && (y <= rectPtr[3])) { return 0; } - + /* * Right edge. */ - + y += (rectPtr[2] - rectPtr[0])*m; if ((y >= rectPtr[1]) && (y <= rectPtr[3]) && (rectPtr[2] >= low) && (rectPtr[2] <= high)) { return 0; } - + /* * Bottom edge. */ - + if (end1Ptr[1] < end2Ptr[1]) { - low = end1Ptr[1]; high = end2Ptr[1]; + low = end1Ptr[1]; + high = end2Ptr[1]; } else { - low = end2Ptr[1]; high = end1Ptr[1]; + low = end2Ptr[1]; + high = end1Ptr[1]; } x = end1Ptr[0] + (rectPtr[1] - end1Ptr[1])/m; if ((x >= rectPtr[0]) && (x <= rectPtr[2]) && (rectPtr[1] >= low) && (rectPtr[1] <= high)) { return 0; } - + /* * Top edge. */ - + x += (rectPtr[3] - rectPtr[1])/m; if ((x >= rectPtr[0]) && (x <= rectPtr[2]) && (rectPtr[3] >= low) && (rectPtr[3] <= high)) { @@ -272,14 +272,13 @@ TkLineToArea(end1Ptr, end2Ptr, rectPtr) * * TkThickPolyLineToArea -- * - * This procedure is called to determine whether a connected - * series of line segments lies entirely inside, entirely - * outside, or overlapping a given rectangular area. + * This function is called to determine whether a connected series of + * line segments lies entirely inside, entirely outside, or overlapping a + * given rectangular area. * * Results: - * -1 is returned if the lines are entirely outside the area, - * 0 if they overlap, and 1 if they are entirely inside the - * given area. + * -1 is returned if the lines are entirely outside the area, 0 if they + * overlap, and 1 if they are entirely inside the given area. * * Side effects: * None. @@ -289,28 +288,27 @@ TkLineToArea(end1Ptr, end2Ptr, rectPtr) /* ARGSUSED */ int -TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) - double *coordPtr; /* Points to an array of coordinates for - * the polyline: x0, y0, x1, y1, ... */ - int numPoints; /* Total number of points at *coordPtr. */ - double width; /* Width of each line segment. */ - int capStyle; /* How are end-points of polyline drawn? +TkThickPolyLineToArea( + double *coordPtr, /* Points to an array of coordinates for the + * polyline: x0, y0, x1, y1, ... */ + int numPoints, /* Total number of points at *coordPtr. */ + double width, /* Width of each line segment. */ + int capStyle, /* How are end-points of polyline drawn? * CapRound, CapButt, or CapProjecting. */ - int joinStyle; /* How are joints in polyline drawn? + int joinStyle, /* How are joints in polyline drawn? * JoinMiter, JoinRound, or JoinBevel. */ - double *rectPtr; /* Rectangular area to check against. */ + double *rectPtr) /* Rectangular area to check against. */ { double radius, poly[10]; int count; - int changedMiterToBevel; /* Non-zero means that a mitered corner - * had to be treated as beveled after all - * because the angle was < 11 degrees. */ - int inside; /* Tentative guess about what to return, - * based on all points seen so far: one - * means everything seen so far was - * inside the area; -1 means everything - * was outside the area. 0 means overlap - * has been found. */ + int changedMiterToBevel; /* Non-zero means that a mitered corner had to + * be treated as beveled after all because the + * angle was < 11 degrees. */ + int inside; /* Tentative guess about what to return, based + * on all points seen so far: one means + * everything seen so far was inside the area; + * -1 means everything was outside the area. + * 0 means overlap has been found. */ radius = width/2.0; inside = -1; @@ -321,19 +319,16 @@ TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) } /* - * Iterate through all of the edges of the line, computing a polygon - * for each edge and testing the area against that polygon. In - * addition, there are additional tests to deal with rounded joints - * and caps. + * Iterate through all of the edges of the line, computing a polygon for + * each edge and testing the area against that polygon. In addition, there + * are additional tests to deal with rounded joints and caps. */ changedMiterToBevel = 0; for (count = numPoints; count >= 2; count--, coordPtr += 2) { - /* - * If rounding is done around the first point of the edge - * then test a circular region around the point with the - * area. + * If rounding is done around the first point of the edge then test a + * circular region around the point with the area. */ if (((capStyle == CapRound) && (count == numPoints)) @@ -348,9 +343,9 @@ TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) } /* - * Compute the polygonal shape corresponding to this edge, - * consisting of two points for the first point of the edge - * and two points for the last point of the edge. + * Compute the polygonal shape corresponding to this edge, consisting + * of two points for the first point of the edge and two points for + * the last point of the edge. */ if (count == numPoints) { @@ -365,10 +360,10 @@ TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) TkGetButtPoints(coordPtr+2, coordPtr, width, 0, poly, poly+2); /* - * If the last joint was beveled, then also check a - * polygon comprising the last two points of the previous - * polygon and the first two from this polygon; this checks - * the wedges that fill the beveled joint. + * If the last joint was beveled, then also check a polygon + * comprising the last two points of the previous polygon and the + * first two from this polygon; this checks the wedges that fill + * the beveled joint. */ if ((joinStyle == JoinBevel) || changedMiterToBevel) { @@ -401,8 +396,7 @@ TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) } /* - * If caps are rounded, check the cap around the final point - * of the line. + * If caps are rounded, check the cap around the final point of the line. */ if (capStyle == CapRound) { @@ -426,10 +420,9 @@ TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) * Compute the distance from a point to a polygon. * * Results: - * The return value is 0.0 if the point referred to by - * pointPtr is within the polygon referred to by polyPtr - * and numPoints. Otherwise the return value is the - * distance of the point from the polygon. + * The return value is 0.0 if the point referred to by pointPtr is within + * the polygon referred to by polyPtr and numPoints. Otherwise the return + * value is the distance of the point from the polygon. * * Side effects: * None. @@ -438,15 +431,15 @@ TkThickPolyLineToArea(coordPtr, numPoints, width, capStyle, joinStyle, rectPtr) */ double -TkPolygonToPoint(polyPtr, numPoints, pointPtr) - double *polyPtr; /* Points to an array coordinates for - * closed polygon: x0, y0, x1, y1, ... - * The polygon may be self-intersecting. */ - int numPoints; /* Total number of points at *polyPtr. */ - double *pointPtr; /* Points to coords for point. */ +TkPolygonToPoint( + double *polyPtr, /* Points to an array coordinates for closed + * polygon: x0, y0, x1, y1, ... The polygon + * may be self-intersecting. */ + int numPoints, /* Total number of points at *polyPtr. */ + double *pointPtr) /* Points to coords for point. */ { - double bestDist; /* Closest distance between point and - * any edge in polygon. */ + double bestDist; /* Closest distance between point and any edge + * in polygon. */ int intersections; /* Number of edges in the polygon that * intersect a ray extending vertically * upwards from the point to infinity. */ @@ -454,13 +447,12 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) register double *pPtr; /* - * Iterate through all of the edges in the polygon, updating - * bestDist and intersections. + * Iterate through all of the edges in the polygon, updating bestDist and + * intersections. * - * TRICKY POINT: when computing intersections, include left - * x-coordinate of line within its range, but not y-coordinate. - * Otherwise if the point lies exactly below a vertex we'll - * count it as two intersections. + * TRICKY POINT: when computing intersections, include left x-coordinate + * of line within its range, but not y-coordinate. Otherwise if the point + * lies exactly below a vertex we'll count it as two intersections. */ bestDist = 1.0e36; @@ -470,10 +462,9 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) double x, y, dist; /* - * Compute the point on the current edge closest to the point - * and update the intersection count. This must be done - * separately for vertical edges, horizontal edges, and - * other edges. + * Compute the point on the current edge closest to the point and + * update the intersection count. This must be done separately for + * vertical edges, horizontal edges, and other edges. */ if (pPtr[2] == pPtr[0]) { @@ -514,13 +505,13 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) } } else { double m1, b1, m2, b2; - int lower; /* Non-zero means point below line. */ + int lower; /* Non-zero means point below line. */ /* - * The edge is neither horizontal nor vertical. Convert the - * edge to a line equation of the form y = m1*x + b1. Then - * compute a line perpendicular to this edge but passing - * through the point, also in the form y = m2*x + b2. + * The edge is neither horizontal nor vertical. Convert the edge + * to a line equation of the form y = m1*x + b1. Then compute a + * line perpendicular to this edge but passing through the point, + * also in the form y = m2*x + b2. */ m1 = (pPtr[3] - pPtr[1])/(pPtr[2] - pPtr[0]); @@ -554,8 +545,8 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) } /* - * Compute the distance to the closest point, and see if that - * is the best distance seen so far. + * Compute the distance to the closest point, and see if that is the + * best distance seen so far. */ dist = hypot(pointPtr[0] - x, pointPtr[1] - y); @@ -565,8 +556,8 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) } /* - * We've processed all of the points. If the number of intersections - * is odd, the point is inside the polygon. + * We've processed all of the points. If the number of intersections is + * odd, the point is inside the polygon. */ if (intersections & 0x1) { @@ -580,14 +571,14 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) * * TkPolygonToArea -- * - * Determine whether a polygon lies entirely inside, entirely - * outside, or overlapping a given rectangular area. + * Determine whether a polygon lies entirely inside, entirely outside, or + * overlapping a given rectangular area. * * Results: - * -1 is returned if the polygon given by polyPtr and numPoints - * is entirely outside the rectangle given by rectPtr. 0 is - * returned if the polygon overlaps the rectangle, and 1 is - * returned if the polygon is entirely inside the rectangle. + * -1 is returned if the polygon given by polyPtr and numPoints is + * entirely outside the rectangle given by rectPtr. 0 is returned if the + * polygon overlaps the rectangle, and 1 is returned if the polygon is + * entirely inside the rectangle. * * Side effects: * None. @@ -596,14 +587,14 @@ TkPolygonToPoint(polyPtr, numPoints, pointPtr) */ int -TkPolygonToArea(polyPtr, numPoints, rectPtr) - double *polyPtr; /* Points to an array coordinates for - * closed polygon: x0, y0, x1, y1, ... - * The polygon may be self-intersecting. */ - int numPoints; /* Total number of points at *polyPtr. */ - register double *rectPtr; /* Points to coords for rectangle, in the - * order x1, y1, x2, y2. X1 and y1 must - * be lower-left corner. */ +TkPolygonToArea( + double *polyPtr, /* Points to an array coordinates for closed + * polygon: x0, y0, x1, y1, ... The polygon + * may be self-intersecting. */ + int numPoints, /* Total number of points at *polyPtr. */ + register double *rectPtr) /* Points to coords for rectangle, in the + * order x1, y1, x2, y2. X1 and y1 must be + * lower-left corner. */ { int state; /* State of all edges seen so far (-1 means * outside, 1 means inside, won't ever be @@ -612,9 +603,8 @@ TkPolygonToArea(polyPtr, numPoints, rectPtr) register double *pPtr; /* - * Iterate over all of the edges of the polygon and test them - * against the rectangle. Can quit as soon as the state becomes - * "intersecting". + * Iterate over all of the edges of the polygon and test them against the + * rectangle. Can quit as soon as the state becomes "intersecting". */ state = TkLineToArea(polyPtr, polyPtr+2, rectPtr); @@ -629,10 +619,10 @@ TkPolygonToArea(polyPtr, numPoints, rectPtr) } /* - * If all of the edges were inside the rectangle we're done. - * If all of the edges were outside, then the rectangle could - * still intersect the polygon (if it's entirely enclosed). - * Call TkPolygonToPoint to figure this out. + * If all of the edges were inside the rectangle we're done. If all of the + * edges were outside, then the rectangle could still intersect the + * polygon (if it's entirely enclosed). Call TkPolygonToPoint to figure + * this out. */ if (state == 1) { @@ -649,17 +639,16 @@ TkPolygonToArea(polyPtr, numPoints, rectPtr) * * TkOvalToPoint -- * - * Computes the distance from a given point to a given - * oval, in canvas units. + * Computes the distance from a given point to a given oval, in canvas + * units. * * Results: - * The return value is 0 if the point given by *pointPtr is - * inside the oval. If the point isn't inside the - * oval then the return value is approximately the distance - * from the point to the oval. If the oval is filled, then - * anywhere in the interior is considered "inside"; if - * the oval isn't filled, then "inside" means only the area - * occupied by the outline. + * The return value is 0 if the point given by *pointPtr is inside the + * oval. If the point isn't inside the oval then the return value is + * approximately the distance from the point to the oval. If the oval is + * filled, then anywhere in the interior is considered "inside"; if the + * oval isn't filled, then "inside" means only the area occupied by the + * outline. * * Side effects: * None. @@ -669,22 +658,23 @@ TkPolygonToArea(polyPtr, numPoints, rectPtr) /* ARGSUSED */ double -TkOvalToPoint(ovalPtr, width, filled, pointPtr) - double ovalPtr[4]; /* Pointer to array of four coordinates - * (x1, y1, x2, y2) defining oval's bounding +TkOvalToPoint( + double ovalPtr[4], /* Pointer to array of four coordinates (x1, + * y1, x2, y2) defining oval's bounding * box. */ - double width; /* Width of outline for oval. */ - int filled; /* Non-zero means oval should be treated as - * filled; zero means only consider outline. */ - double pointPtr[2]; /* Coordinates of point. */ + double width, /* Width of outline for oval. */ + int filled, /* Non-zero means oval should be treated as + * filled; zero means only consider + * outline. */ + double pointPtr[2]) /* Coordinates of point. */ { double xDelta, yDelta, scaledDistance, distToOutline, distToCenter; double xDiam, yDiam; /* - * Compute the distance between the center of the oval and the - * point in question, using a coordinate system where the oval - * has been transformed to a circle with unit radius. + * Compute the distance between the center of the oval and the point in + * question, using a coordinate system where the oval has been transformed + * to a circle with unit radius. */ xDelta = (pointPtr[0] - (ovalPtr[0] + ovalPtr[2])/2.0); @@ -693,16 +683,14 @@ TkOvalToPoint(ovalPtr, width, filled, pointPtr) scaledDistance = hypot(xDelta / ((ovalPtr[2] + width - ovalPtr[0])/2.0), yDelta / ((ovalPtr[3] + width - ovalPtr[1])/2.0)); - /* - * If the scaled distance is greater than 1 then it means no - * hit. Compute the distance from the point to the edge of - * the circle, then scale this distance back to the original - * coordinate system. + * If the scaled distance is greater than 1 then it means no hit. Compute + * the distance from the point to the edge of the circle, then scale this + * distance back to the original coordinate system. * - * Note: this distance isn't completely accurate. It's only - * an approximation, and it can overestimate the correct - * distance when the oval is eccentric. + * Note: this distance isn't completely accurate. It's only an + * approximation, and it can overestimate the correct distance when the + * oval is eccentric. */ if (scaledDistance > 1.0) { @@ -710,11 +698,11 @@ TkOvalToPoint(ovalPtr, width, filled, pointPtr) } /* - * Scaled distance less than 1 means the point is inside the - * outer edge of the oval. If this is a filled oval, then we - * have a hit. Otherwise, do the same computation as above - * (scale back to original coordinate system), but also check - * to see if the point is within the width of the outline. + * Scaled distance less than 1 means the point is inside the outer edge of + * the oval. If this is a filled oval, then we have a hit. Otherwise, do + * the same computation as above (scale back to original coordinate + * system), but also check to see if the point is within the width of the + * outline. */ if (filled) { @@ -725,9 +713,9 @@ TkOvalToPoint(ovalPtr, width, filled, pointPtr) - width; } else { /* - * Avoid dividing by a very small number (it could cause an - * arithmetic overflow). This problem occurs if the point is - * very close to the center of the oval. + * Avoid dividing by a very small number (it could cause an arithmetic + * overflow). This problem occurs if the point is very close to the + * center of the oval. */ xDiam = ovalPtr[2] - ovalPtr[0]; @@ -750,14 +738,14 @@ TkOvalToPoint(ovalPtr, width, filled, pointPtr) * * TkOvalToArea -- * - * Determine whether an oval lies entirely inside, entirely - * outside, or overlapping a given rectangular area. + * Determine whether an oval lies entirely inside, entirely outside, or + * overlapping a given rectangular area. * * Results: - * -1 is returned if the oval described by ovalPtr is entirely - * outside the rectangle given by rectPtr. 0 is returned if the - * oval overlaps the rectangle, and 1 is returned if the oval - * is entirely inside the rectangle. + * -1 is returned if the oval described by ovalPtr is entirely outside + * the rectangle given by rectPtr. 0 is returned if the oval overlaps the + * rectangle, and 1 is returned if the oval is entirely inside the + * rectangle. * * Side effects: * None. @@ -766,20 +754,20 @@ TkOvalToPoint(ovalPtr, width, filled, pointPtr) */ int -TkOvalToArea(ovalPtr, rectPtr) - register double *ovalPtr; /* Points to coordinates definining the +TkOvalToArea( + register double *ovalPtr, /* Points to coordinates definining the * bounding rectangle for the oval: x1, y1, - * x2, y2. X1 must be less than x2 and y1 - * less than y2. */ - register double *rectPtr; /* Points to coords for rectangle, in the - * order x1, y1, x2, y2. X1 and y1 must - * be lower-left corner. */ + * x2, y2. X1 must be less than x2 and y1 less + * than y2. */ + register double *rectPtr) /* Points to coords for rectangle, in the + * order x1, y1, x2, y2. X1 and y1 must be + * lower-left corner. */ { double centerX, centerY, radX, radY, deltaX, deltaY; /* - * First, see if oval is entirely inside rectangle or entirely - * outside rectangle. + * First, see if oval is entirely inside rectangle or entirely outside + * rectangle. */ if ((rectPtr[0] <= ovalPtr[0]) && (rectPtr[2] >= ovalPtr[2]) @@ -792,11 +780,10 @@ TkOvalToArea(ovalPtr, rectPtr) } /* - * Next, go through the rectangle side by side. For each side - * of the rectangle, find the point on the side that is closest - * to the oval's center, and see if that point is inside the - * oval. If at least one such point is inside the oval, then - * the rectangle intersects the oval. + * Next, go through the rectangle side by side. For each side of the + * rectangle, find the point on the side that is closest to the oval's + * center, and see if that point is inside the oval. If at least one such + * point is inside the oval, then the rectangle intersects the oval. */ centerX = (ovalPtr[0] + ovalPtr[2])/2; @@ -872,8 +859,8 @@ TkOvalToArea(ovalPtr, rectPtr) * * TkIncludePoint -- * - * Given a point and a generic canvas item header, expand - * the item's bounding box if needed to include the point. + * Given a point and a generic canvas item header, expand the item's + * bounding box if needed to include the point. * * Results: * None. @@ -886,11 +873,11 @@ TkOvalToArea(ovalPtr, rectPtr) /* ARGSUSED */ void -TkIncludePoint(itemPtr, pointPtr) - register Tk_Item *itemPtr; /* Item whose bounding box is - * being calculated. */ - double *pointPtr; /* Address of two doubles giving - * x and y coordinates of point. */ +TkIncludePoint( + register Tk_Item *itemPtr, /* Item whose bounding box is being + * calculated. */ + double *pointPtr) /* Address of two doubles giving x and y + * coordinates of point. */ { int tmp; @@ -915,15 +902,14 @@ TkIncludePoint(itemPtr, pointPtr) * * TkBezierScreenPoints -- * - * Given four control points, create a larger set of XPoints - * for a Bezier spline based on the points. + * Given four control points, create a larger set of XPoints for a Bezier + * curve based on the points. * * Results: * The array at *xPointPtr gets filled in with numSteps XPoints - * corresponding to the Bezier spline defined by the four - * control points. Note: no output point is generated for the - * first input point, but an output point *is* generated for - * the last input point. + * corresponding to the Bezier spline defined by the four control points. + * Note: no output point is generated for the first input point, but an + * output point *is* generated for the last input point. * * Side effects: * None. @@ -932,15 +918,12 @@ TkIncludePoint(itemPtr, pointPtr) */ void -TkBezierScreenPoints(canvas, control, numSteps, xPointPtr) - Tk_Canvas canvas; /* Canvas in which curve is to be - * drawn. */ - double control[]; /* Array of coordinates for four - * control points: x0, y0, x1, y1, - * ... x3 y3. */ - int numSteps; /* Number of curve points to - * generate. */ - register XPoint *xPointPtr; /* Where to put new points. */ +TkBezierScreenPoints( + Tk_Canvas canvas, /* Canvas in which curve is to be drawn. */ + double control[], /* Array of coordinates for four control + * points: x0, y0, x1, y1, ... x3 y3. */ + int numSteps, /* Number of curve points to generate. */ + register XPoint *xPointPtr) /* Where to put new points. */ { int i; double u, u2, u3, t, t2, t3; @@ -966,15 +949,14 @@ TkBezierScreenPoints(canvas, control, numSteps, xPointPtr) * * TkBezierPoints -- * - * Given four control points, create a larger set of points - * for a Bezier spline based on the points. + * Given four control points, create a larger set of points for a Bezier + * curve based on the points. * * Results: - * The array at *coordPtr gets filled in with 2*numSteps - * coordinates, which correspond to the Bezier spline defined - * by the four control points. Note: no output point is - * generated for the first input point, but an output point - * *is* generated for the last input point. + * The array at *coordPtr gets filled in with 2*numSteps coordinates, + * which correspond to the Bezier spline defined by the four control + * points. Note: no output point is generated for the first input point, + * but an output point *is* generated for the last input point. * * Side effects: * None. @@ -983,13 +965,11 @@ TkBezierScreenPoints(canvas, control, numSteps, xPointPtr) */ void -TkBezierPoints(control, numSteps, coordPtr) - double control[]; /* Array of coordinates for four - * control points: x0, y0, x1, y1, - * ... x3 y3. */ - int numSteps; /* Number of curve points to - * generate. */ - register double *coordPtr; /* Where to put new points. */ +TkBezierPoints( + double control[], /* Array of coordinates for four control + * points: x0, y0, x1, y1, ... x3 y3. */ + int numSteps, /* Number of curve points to generate. */ + register double *coordPtr) /* Where to put new points. */ { int i; double u, u2, u3, t, t2, t3; @@ -1013,20 +993,21 @@ TkBezierPoints(control, numSteps, coordPtr) * * TkMakeBezierCurve -- * - * Given a set of points, create a new set of points that fit - * parabolic splines to the line segments connecting the original - * points. Produces output points in either of two forms. + * Given a set of points, create a new set of points that fit parabolic + * splines to the line segments connecting the original points. Produces + * output points in either of two forms. * - * Note: in spite of this procedure's name, it does *not* generate - * Bezier curves. Since only three control points are used for - * each curve segment, not four, the curves are actually just - * parabolic. + * Note: the name of this function should *not* be taken to mean that it + * interprets the input points as directly defining Bezier curves. + * Rather, it internally computes a Bezier curve representation of each + * parabolic spline segment. (These Bezier curves are then flattened to + * produce the points filled into the output arrays.) * * Results: - * Either or both of the xPoints or dblPoints arrays are filled - * in. The return value is the number of points placed in the - * arrays. Note: if the first and last points are the same, then - * a closed curve is generated. + * Either or both of the xPoints or dblPoints arrays are filled in. The + * return value is the number of points placed in the arrays. Note: if + * the first and last points are the same, then a closed curve is + * generated. * * Side effects: * None. @@ -1035,40 +1016,40 @@ TkBezierPoints(control, numSteps, coordPtr) */ int -TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) - Tk_Canvas canvas; /* Canvas in which curve is to be - * drawn. */ - double *pointPtr; /* Array of input coordinates: x0, - * y0, x1, y1, etc.. */ - int numPoints; /* Number of points at pointPtr. */ - int numSteps; /* Number of steps to use for each - * spline segments (determines - * smoothness of curve). */ - XPoint xPoints[]; /* Array of XPoints to fill in (e.g. - * for display. NULL means don't - * fill in any XPoints. */ - double dblPoints[]; /* Array of points to fill in as - * doubles, in the form x0, y0, - * x1, y1, .... NULL means don't - * fill in anything in this form. - * Caller must make sure that this - * array has enough space. */ +TkMakeBezierCurve( + Tk_Canvas canvas, /* Canvas in which curve is to be drawn. */ + double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1, + * etc.. */ + int numPoints, /* Number of points at pointPtr. */ + int numSteps, /* Number of steps to use for each spline + * segments (determines smoothness of + * curve). */ + XPoint xPoints[], /* Array of XPoints to fill in (e.g. for + * display). NULL means don't fill in any + * XPoints. */ + double dblPoints[]) /* Array of points to fill in as doubles, in + * the form x0, y0, x1, y1, .... NULL means + * don't fill in anything in this form. Caller + * must make sure that this array has enough + * space. */ { int closed, outputPoints, i; int numCoords = numPoints*2; double control[8]; /* - * If the curve is a closed one then generate a special spline - * that spans the last points and the first ones. Otherwise - * just put the first point into the output. + * If the curve is a closed one then generate a special spline that spans + * the last points and the first ones. Otherwise just put the first point + * into the output. */ if (!pointPtr) { - /* Of pointPtr == NULL, this function returns an upper limit. - * of the array size to store the coordinates. This can be - * used to allocate storage, before the actual coordinates - * are calculated. */ + /* + * Of pointPtr == NULL, this function returns an upper limit of the + * array size to store the coordinates. This can be used to allocate + * storage, before the actual coordinates are calculated. + */ + return 1 + numPoints * numSteps; } @@ -1114,9 +1095,8 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) for (i = 2; i < numPoints; i++, pointPtr += 2) { /* - * Set up the first two control points. This is done - * differently for the first spline of an open curve - * than for other cases. + * Set up the first two control points. This is done differently for + * the first spline of an open curve than for other cases. */ if ((i == 2) && !closed) { @@ -1132,9 +1112,8 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) } /* - * Set up the last two control points. This is done - * differently for the last spline of an open curve - * than for other cases. + * Set up the last two control points. This is done differently for + * the last spline of an open curve than for other cases. */ if ((i == (numPoints-1)) && !closed) { @@ -1150,10 +1129,9 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) } /* - * If the first two points coincide, or if the last - * two points coincide, then generate a single - * straight-line segment by outputting the last control - * point. + * If the first two points coincide, or if the last two points + * coincide, then generate a single straight-line segment by + * outputting the last control point. */ if (((pointPtr[0] == pointPtr[2]) && (pointPtr[1] == pointPtr[3])) @@ -1194,14 +1172,193 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) /* *-------------------------------------------------------------- * + * TkMakeRawCurve -- + * + * Interpret the given set of points as the raw knots and control points + * defining a sequence of cubic Bezier curves. Create a new set of points + * that fit these Bezier curves. Output points are produced in either of + * two forms. + * + * Results: + * Either or both of the xPoints or dblPoints arrays are filled in. The + * return value is the number of points placed in the arrays. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +int +TkMakeRawCurve( + Tk_Canvas canvas, /* Canvas in which curve is to be drawn. */ + double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1, + * etc.. */ + int numPoints, /* Number of points at pointPtr. */ + int numSteps, /* Number of steps to use for each curve + * segment (determines smoothness of + * curve). */ + XPoint xPoints[], /* Array of XPoints to fill in (e.g. for + * display). NULL means don't fill in any + * XPoints. */ + double dblPoints[]) /* Array of points to fill in as doubles, in + * the form x0, y0, x1, y1, .... NULL means + * don't fill in anything in this form. + * Caller must make sure that this array has + * enough space. */ +{ + int outputPoints, i; + int numSegments = (numPoints+1)/3; + double *segPtr; + + /* + * The input describes a curve with s Bezier curve segments if there are + * 3s+1, 3s, or 3s-1 input points. In the last two cases, 1 or 2 initial + * points from the first curve segment are reused as defining points also + * for the last curve segment. In the case of 3s input points, this will + * automatically close the curve. + */ + + if (!pointPtr) { + /* + * If pointPtr == NULL, this function returns an upper limit of the + * array size to store the coordinates. This can be used to allocate + * storage, before the actual coordinates are calculated. + */ + + return 1 + numSegments * numSteps; + } + + outputPoints = 0; + if (xPoints != NULL) { + Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1], + &xPoints->x, &xPoints->y); + xPoints += 1; + } + if (dblPoints != NULL) { + dblPoints[0] = pointPtr[0]; + dblPoints[1] = pointPtr[1]; + dblPoints += 2; + } + outputPoints += 1; + + /* + * The next loop handles all curve segments except one that overlaps the + * end of the list of coordinates. + */ + + for (i=numPoints,segPtr=pointPtr ; i>=4 ; i-=3,segPtr+=6) { + if (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] && + segPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) { + /* + * The control points on this segment are equal to their + * neighbouring knots, so this segment is just a straight line. A + * single point is sufficient. + */ + + if (xPoints != NULL) { + Tk_CanvasDrawableCoords(canvas, segPtr[6], segPtr[7], + &xPoints->x, &xPoints->y); + xPoints += 1; + } + if (dblPoints != NULL) { + dblPoints[0] = segPtr[6]; + dblPoints[1] = segPtr[7]; + dblPoints += 2; + } + outputPoints += 1; + } else { + /* + * This is a generic Bezier curve segment. + */ + + if (xPoints != NULL) { + TkBezierScreenPoints(canvas, segPtr, numSteps, xPoints); + xPoints += numSteps; + } + if (dblPoints != NULL) { + TkBezierPoints(segPtr, numSteps, dblPoints); + dblPoints += 2*numSteps; + } + outputPoints += numSteps; + } + } + + /* + * If at this point i>1, then there is some point which has not yet been + * used. Make another curve segment. + */ + + if (i > 1) { + int j; + double control[8]; + + /* + * Copy the relevant coordinates to control[], so that it can be + * passed as a unit to e.g. TkBezierPoints. + */ + + for (j=0; j<2*i; j++) { + control[j] = segPtr[j]; + } + for (; j<8; j++) { + control[j] = pointPtr[j-2*i]; + } + + /* + * Then we just do the same things as above. + */ + + if (control[0]==control[2] && control[1]==control[3] && + control[4]==control[6] && control[5]==control[7]) { + /* + * The control points on this segment are equal to their + * neighbouring knots, so this segment is just a straight line. A + * single point is sufficient. + */ + + if (xPoints != NULL) { + Tk_CanvasDrawableCoords(canvas, control[6], control[7], + &xPoints->x, &xPoints->y); + xPoints += 1; + } + if (dblPoints != NULL) { + dblPoints[0] = control[6]; + dblPoints[1] = control[7]; + dblPoints += 2; + } + outputPoints += 1; + } else { + /* + * This is a generic Bezier curve segment. + */ + + if (xPoints != NULL) { + TkBezierScreenPoints(canvas, control, numSteps, xPoints); + xPoints += numSteps; + } + if (dblPoints != NULL) { + TkBezierPoints(control, numSteps, dblPoints); + dblPoints += 2*numSteps; + } + outputPoints += numSteps; + } + } + + return outputPoints; +} + +/* + *-------------------------------------------------------------- + * * TkMakeBezierPostscript -- * - * This procedure generates Postscript commands that create - * a path corresponding to a given Bezier curve. + * This function generates Postscript commands that create a path + * corresponding to a given Bezier curve. * * Results: - * None. Postscript commands to generate the path are appended - * to the interp's result. + * None. Postscript commands to generate the path are appended to the + * interp's result. * * Side effects: * None. @@ -1210,14 +1367,14 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) */ void -TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) - Tcl_Interp *interp; /* Interpreter in whose result the - * Postscript is to be stored. */ - Tk_Canvas canvas; /* Canvas widget for which the - * Postscript is being generated. */ - double *pointPtr; /* Array of input coordinates: x0, - * y0, x1, y1, etc.. */ - int numPoints; /* Number of points at pointPtr. */ +TkMakeBezierPostscript( + Tcl_Interp *interp, /* Interpreter in whose result the Postscript + * is to be stored. */ + Tk_Canvas canvas, /* Canvas widget for which the Postscript is + * being generated. */ + double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1, + * etc.. */ + int numPoints) /* Number of points at pointPtr. */ { int closed, i; int numCoords = numPoints*2; @@ -1225,9 +1382,9 @@ TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) char buffer[200]; /* - * If the curve is a closed one then generate a special spline - * that spans the last points and the first ones. Otherwise - * just put the first point into the path. + * If the curve is a closed one then generate a special spline that spans + * the last points and the first ones. Otherwise just put the first point + * into the path. */ if ((pointPtr[0] == pointPtr[numCoords-2]) @@ -1253,11 +1410,11 @@ TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) sprintf(buffer, "%.15g %.15g moveto\n", control[6], Tk_CanvasPsY(canvas, control[7])); } - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); /* - * Cycle through all the remaining points in the curve, generating - * a curve section for each vertex in the linear path. + * Cycle through all the remaining points in the curve, generating a curve + * section for each vertex in the linear path. */ for (i = numPoints-2, pointPtr += 2; i > 0; i--, pointPtr += 2) { @@ -1265,9 +1422,8 @@ TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) control[3] = 0.333*control[7] + 0.667*pointPtr[1]; /* - * Set up the last two control points. This is done - * differently for the last spline of an open curve - * than for other cases. + * Set up the last two control points. This is done differently for + * the last spline of an open curve than for other cases. */ if ((i == 1) && !closed) { @@ -1284,7 +1440,115 @@ TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) control[2], Tk_CanvasPsY(canvas, control[3]), control[4], Tk_CanvasPsY(canvas, control[5]), control[6], Tk_CanvasPsY(canvas, control[7])); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); + } +} + +/* + *-------------------------------------------------------------- + * + * TkMakeRawCurvePostscript -- + * + * This function interprets the input points as the raw knot and control + * points for a curve composed of Bezier curve segments, just like + * TkMakeRawCurve. It generates Postscript commands that create a path + * corresponding to this given curve. + * + * Results: + * None. Postscript commands to generate the path are appended to the + * interp's result. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void +TkMakeRawCurvePostscript( + Tcl_Interp *interp, /* Interpreter in whose result the Postscript + * is to be stored. */ + Tk_Canvas canvas, /* Canvas widget for which the Postscript is + * being generated. */ + double *pointPtr, /* Array of input coordinates: x0, y0, x1, y1, + * etc.. */ + int numPoints) /* Number of points at pointPtr. */ +{ + int i; + double *segPtr; + char buffer[200]; + + /* + * Put the first point into the path. + */ + + sprintf(buffer, "%.15g %.15g moveto\n", + pointPtr[0], Tk_CanvasPsY(canvas, pointPtr[1])); + Tcl_AppendResult(interp, buffer, NULL); + + /* + * Loop through all the remaining points in the curve, generating a + * straight line or curve section for every three of them. + */ + + for (i=numPoints-1,segPtr=pointPtr ; i>=3 ; i-=3,segPtr+=6) { + if (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] && + segPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) { + /* + * The control points on this segment are equal to their + * neighbouring knots, so this segment is just a straight line. + */ + + sprintf(buffer, "%.15g %.15g lineto\n", + segPtr[6], Tk_CanvasPsY(canvas, segPtr[7])); + } else { + /* + * This is a generic Bezier curve segment. + */ + + sprintf(buffer, "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n", + segPtr[2], Tk_CanvasPsY(canvas, segPtr[3]), + segPtr[4], Tk_CanvasPsY(canvas, segPtr[5]), + segPtr[6], Tk_CanvasPsY(canvas, segPtr[7])); + } + Tcl_AppendResult(interp, buffer, NULL); + } + + /* + * If there are any points left that haven't been used, then build the + * last segment and generate Postscript in the same way for that. + */ + + if (i > 0) { + int j; + double control[8]; + + for (j=0; j<2*i+2; j++) { + control[j] = segPtr[j]; + } + for (; j<8; j++) { + control[j] = pointPtr[j-2*i-2]; + } + + if (control[0]==control[2] && control[1]==control[3] && + control[4]==control[6] && control[5]==control[7]) { + /* + * Straight line. + */ + + sprintf(buffer, "%.15g %.15g lineto\n", + control[6], Tk_CanvasPsY(canvas, control[7])); + } else { + /* + * Bezier curve segment. + */ + + sprintf(buffer, "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n", + control[2], Tk_CanvasPsY(canvas, control[3]), + control[4], Tk_CanvasPsY(canvas, control[5]), + control[6], Tk_CanvasPsY(canvas, control[7])); + } + Tcl_AppendResult(interp, buffer, NULL); } } @@ -1293,16 +1557,14 @@ TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) * * TkGetMiterPoints -- * - * Given three points forming an angle, compute the - * coordinates of the inside and outside points of - * the mitered corner formed by a line of a given - * width at that angle. + * Given three points forming an angle, compute the coordinates of the + * inside and outside points of the mitered corner formed by a line of a + * given width at that angle. * * Results: - * If the angle formed by the three points is less than - * 11 degrees then 0 is returned and m1 and m2 aren't - * modified. Otherwise 1 is returned and the points at - * m1 and m2 are filled in with the positions of the points + * If the angle formed by the three points is less than 11 degrees then 0 + * is returned and m1 and m2 aren't modified. Otherwise 1 is returned and + * the points at m1 and m2 are filled in with the positions of the points * of the mitered corner. * * Side effects: @@ -1312,36 +1574,39 @@ TkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) */ int -TkGetMiterPoints(p1, p2, p3, width, m1, m2) - double p1[]; /* Points to x- and y-coordinates of point +TkGetMiterPoints( + double p1[], /* Points to x- and y-coordinates of point * before vertex. */ - double p2[]; /* Points to x- and y-coordinates of vertex + double p2[], /* Points to x- and y-coordinates of vertex * for mitered joint. */ - double p3[]; /* Points to x- and y-coordinates of point + double p3[], /* Points to x- and y-coordinates of point * after vertex. */ - double width; /* Width of line. */ - double m1[]; /* Points to place to put "left" vertex - * point (see as you face from p1 to p2). */ - double m2[]; /* Points to place to put "right" vertex + double width, /* Width of line. */ + double m1[], /* Points to place to put "left" vertex point + * (see as you face from p1 to p2). */ + double m2[]) /* Points to place to put "right" vertex * point. */ { double theta1; /* Angle of segment p2-p1. */ double theta2; /* Angle of segment p2-p3. */ - double theta; /* Angle between line segments (angle - * of joint). */ - double theta3; /* Angle that bisects theta1 and - * theta2 and points to m1. */ + double theta; /* Angle between line segments (angle of + * joint). */ + double theta3; /* Angle that bisects theta1 and theta2 and + * points to m1. */ double dist; /* Distance of miter points from p2. */ - double deltaX, deltaY; /* X and y offsets cooresponding to - * dist (fudge factors for bounding - * box). */ + double deltaX, deltaY; /* X and y offsets cooresponding to dist + * (fudge factors for bounding box). */ double p1x, p1y, p2x, p2y, p3x, p3y; - static double elevenDegrees = (11.0*2.0*PI)/360.0; +#ifndef _MSC_VER + static const double elevenDegrees = (11.0*2.0*PI)/360.0; +#else /* msvc8 with -fp:strict requires it this way */ + static const double elevenDegrees = 0.19198621771937624; +#endif /* - * Round the coordinates to integers to mimic what happens when the - * line segments are displayed; without this code, the bounding box - * of a mitered line can be miscomputed greatly. + * Round the coordinates to integers to mimic what happens when the line + * segments are displayed; without this code, the bounding box of a + * mitered line can be miscomputed greatly. */ p1x = floor(p1[0]+0.5); @@ -1358,6 +1623,7 @@ TkGetMiterPoints(p1, p2, p3, width, m1, m2) } else { theta1 = atan2(p1y - p2y, p1x - p2x); } + if (p3y == p2y) { theta2 = (p3x > p2x) ? 0 : PI; } else if (p3x == p2x) { @@ -1365,23 +1631,26 @@ TkGetMiterPoints(p1, p2, p3, width, m1, m2) } else { theta2 = atan2(p3y - p2y, p3x - p2x); } + theta = theta1 - theta2; if (theta > PI) { theta -= 2*PI; } else if (theta < -PI) { theta += 2*PI; } + if ((theta < elevenDegrees) && (theta > -elevenDegrees)) { return 0; } + dist = 0.5*width/sin(0.5*theta); if (dist < 0.0) { dist = -dist; } /* - * Compute theta3 (make sure that it points to the left when - * looking from p1 to p2). + * Compute theta3 (make sure that it points to the left when looking from + * p1 to p2). */ theta3 = (theta1 + theta2)/2.0; @@ -1394,6 +1663,7 @@ TkGetMiterPoints(p1, p2, p3, width, m1, m2) deltaY = dist*sin(theta3); m1[1] = p2y + deltaY; m2[1] = p2y - deltaY; + return 1; } @@ -1402,13 +1672,13 @@ TkGetMiterPoints(p1, p2, p3, width, m1, m2) * * TkGetButtPoints -- * - * Given two points forming a line segment, compute the - * coordinates of two endpoints of a rectangle formed by - * bloating the line segment until it is width units wide. + * Given two points forming a line segment, compute the coordinates of + * two endpoints of a rectangle formed by bloating the line segment until + * it is width units wide. * * Results: - * There is no return value. M1 and m2 are filled in to - * correspond to m1 and m2 in the diagram below: + * There is no return value. M1 and m2 are filled in to correspond to m1 + * and m2 in the diagram below: * * ----------------* m1 * | @@ -1416,9 +1686,9 @@ TkGetMiterPoints(p1, p2, p3, width, m1, m2) * | * ----------------* m2 * - * M1 and m2 will be W units apart, with p2 centered between - * them and m1-m2 perpendicular to p1-p2. However, if - * "project" is true then m1 and m2 will be as follows: + * M1 and m2 will be W units apart, with p2 centered between them and + * m1-m2 perpendicular to p1-p2. However, if "project" is true then m1 + * and m2 will be as follows: * * -------------------* m1 * p2 | @@ -1435,17 +1705,17 @@ TkGetMiterPoints(p1, p2, p3, width, m1, m2) */ void -TkGetButtPoints(p1, p2, width, project, m1, m2) - double p1[]; /* Points to x- and y-coordinates of point +TkGetButtPoints( + double p1[], /* Points to x- and y-coordinates of point * before vertex. */ - double p2[]; /* Points to x- and y-coordinates of vertex + double p2[], /* Points to x- and y-coordinates of vertex * for mitered joint. */ - double width; /* Width of line. */ - int project; /* Non-zero means project p2 by an additional + double width, /* Width of line. */ + int project, /* Non-zero means project p2 by an additional * width/2 before computing m1 and m2. */ - double m1[]; /* Points to place to put "left" result - * point, as you face from p1 to p2. */ - double m2[]; /* Points to place to put "right" result + double m1[], /* Points to place to put "left" result point, + * as you face from p1 to p2. */ + double m2[]) /* Points to place to put "right" result * point. */ { double length; /* Length of p1-p2 segment. */ @@ -1471,3 +1741,11 @@ TkGetButtPoints(p1, p2, width, project, m1, m2) } } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkUndo.c b/generic/tkUndo.c index 81c8648..bf2ed7c 100644 --- a/generic/tkUndo.c +++ b/generic/tkUndo.c @@ -1,378 +1,689 @@ -/* +/* * tkUndo.c -- * * This module provides the implementation of an undo stack. * * Copyright (c) 2002 by Ludwig Callewaert. + * Copyright (c) 2003-2004 by Vincent Darley. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkUndo.h" +static int EvaluateActionList(Tcl_Interp *interp, + TkUndoSubAtom *action); /* - * TkUndoPushStack - * Push elem on the stack identified by stack. + *---------------------------------------------------------------------- + * + * TkUndoPushStack -- + * + * Push elem on the stack identified by stack. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -void TkUndoPushStack ( stack, elem ) - TkUndoAtom ** stack; - TkUndoAtom * elem; -{ + +void +TkUndoPushStack( + TkUndoAtom **stack, + TkUndoAtom *elem) +{ elem->next = *stack; *stack = elem; } /* + *---------------------------------------------------------------------- + * * TkUndoPopStack -- - * Remove and return the top element from the stack identified by - * stack. + * + * Remove and return the top element from the stack identified by stack. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -TkUndoAtom * TkUndoPopStack ( stack ) - TkUndoAtom ** stack ; -{ - TkUndoAtom * elem = NULL; - if (*stack != NULL ) { - elem = *stack; - *stack = elem->next; + +TkUndoAtom * +TkUndoPopStack( + TkUndoAtom **stack) +{ + TkUndoAtom *elem = NULL; + + if (*stack != NULL) { + elem = *stack; + *stack = elem->next; } return elem; } /* + *---------------------------------------------------------------------- + * * TkUndoInsertSeparator -- - * insert a separator on the stack, indicating a border for - * an undo/redo chunk. + * + * Insert a separator on the stack, indicating a border for an undo/redo + * chunk. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -int TkUndoInsertSeparator ( stack ) - TkUndoAtom ** stack; + +int +TkUndoInsertSeparator( + TkUndoAtom **stack) { - TkUndoAtom * separator; - - if ( *stack != NULL && (*stack)->type != TK_UNDO_SEPARATOR ) { - separator = (TkUndoAtom *) ckalloc(sizeof(TkUndoAtom)); - separator->type = TK_UNDO_SEPARATOR; - TkUndoPushStack(stack,separator); - return 1; - } else { - return 0; + TkUndoAtom *separator; + + if (*stack!=NULL && (*stack)->type!=TK_UNDO_SEPARATOR) { + separator = (TkUndoAtom *) ckalloc(sizeof(TkUndoAtom)); + separator->type = TK_UNDO_SEPARATOR; + TkUndoPushStack(stack,separator); + return 1; } + return 0; } /* + *---------------------------------------------------------------------- + * * TkUndoClearStack -- - * Clear an entire undo or redo stack and destroy all elements in it. + * + * Clear an entire undo or redo stack and destroy all elements in it. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ -void TkUndoClearStack ( stack ) - TkUndoAtom ** stack; /* An Undo or Redo stack */ +void +TkUndoClearStack( + TkUndoAtom **stack) /* An Undo or Redo stack */ { - TkUndoAtom * elem; - - while ( (elem = TkUndoPopStack(stack)) ) { - if ( elem->type != TK_UNDO_SEPARATOR ) { - Tcl_DecrRefCount(elem->apply); - Tcl_DecrRefCount(elem->revert); - } - ckfree((char *)elem); + TkUndoAtom *elem; + + while ((elem = TkUndoPopStack(stack)) != NULL) { + if (elem->type != TK_UNDO_SEPARATOR) { + TkUndoSubAtom *sub; + + sub = elem->apply; + while (sub != NULL) { + TkUndoSubAtom *next = sub->next; + + if (sub->action != NULL) { + Tcl_DecrRefCount(sub->action); + } + ckfree((char *)sub); + sub = next; + } + + sub = elem->revert; + while (sub != NULL) { + TkUndoSubAtom *next = sub->next; + + if (sub->action != NULL) { + Tcl_DecrRefCount(sub->action); + } + ckfree((char *)sub); + sub = next; + } + } + ckfree((char *)elem); } *stack = NULL; } /* - * TkUndoPushAction - * Push a new elem on the stack identified by stack. - * action and revert are given through Tcl_DStrings + *---------------------------------------------------------------------- + * + * TkUndoPushAction -- + * + * Push a new elem on the stack identified by stack. Action and revert + * are given through Tcl_Obj's to which we will retain a reference. (So + * they can be passed in with a zero refCount if desired). * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -void TkUndoPushAction ( stack, actionScript, revertScript ) - TkUndoRedoStack * stack; /* An Undo or Redo stack */ - Tcl_DString * actionScript; /* The script to get the action (redo) */ - Tcl_DString * revertScript; /* The script to revert the action (undo) */ -{ - TkUndoAtom * atom; + +void +TkUndoPushAction( + TkUndoRedoStack *stack, /* An Undo or Redo stack */ + TkUndoSubAtom *apply, + TkUndoSubAtom *revert) +{ + TkUndoAtom *atom; atom = (TkUndoAtom *) ckalloc(sizeof(TkUndoAtom)); atom->type = TK_UNDO_ACTION; + atom->apply = apply; + atom->revert = revert; - atom->apply = Tcl_NewStringObj(Tcl_DStringValue(actionScript),Tcl_DStringLength(actionScript)); - Tcl_IncrRefCount(atom->apply); + TkUndoPushStack(&stack->undoStack, atom); + TkUndoClearStack(&stack->redoStack); +} + +/* + *---------------------------------------------------------------------- + * + * TkUndoMakeCmdSubAtom -- + * + * Create a new undo/redo step which must later be place into an undo + * stack with TkUndoPushAction. This sub-atom, if evaluated, will take + * the given command (if non-NULL), find its full Tcl command string, and + * then evaluate that command with the list elements of 'actionScript' + * appended. + * + * If 'subAtomList' is non-NULL, the newly created sub-atom is added onto + * the end of the linked list of which 'subAtomList' is a part. This + * makes it easy to build up a sequence of actions which will be pushed + * in one step. + * + * Note: if the undo stack can persist for longer than the Tcl_Command + * provided, the stack will cause crashes when actions are evaluated. In + * this case the 'command' argument should not be used. This is the case + * with peer text widgets, for example. + * + * Results: + * The newly created subAtom is returned. It must be passed to + * TkUndoPushAction otherwise a memory leak will result. + * + * Side effects: + * A refCount is retained on 'actionScript'. + * + *---------------------------------------------------------------------- + */ + +TkUndoSubAtom * +TkUndoMakeCmdSubAtom( + Tcl_Command command, /* Tcl command token for actions, may be NULL + * if not needed. */ + Tcl_Obj *actionScript, /* The script to append to the command to + * perform the action (may be NULL if the + * command is not-null). */ + TkUndoSubAtom *subAtomList) /* Add to the end of this list of actions if + * non-NULL */ +{ + TkUndoSubAtom *atom; - atom->revert = Tcl_NewStringObj(Tcl_DStringValue(revertScript),Tcl_DStringLength(revertScript)); - Tcl_IncrRefCount(atom->revert); + if (command == NULL && actionScript == NULL) { + Tcl_Panic("NULL command and actionScript in TkUndoMakeCmdSubAtom"); + } - TkUndoPushStack(&(stack->undoStack), atom); - TkUndoClearStack(&(stack->redoStack)); + atom = (TkUndoSubAtom *) ckalloc(sizeof(TkUndoSubAtom)); + atom->command = command; + atom->funcPtr = NULL; + atom->clientData = NULL; + atom->next = NULL; + atom->action = actionScript; + if (atom->action != NULL) { + Tcl_IncrRefCount(atom->action); + } + + if (subAtomList != NULL) { + while (subAtomList->next != NULL) { + subAtomList = subAtomList->next; + } + subAtomList->next = atom; + } + return atom; } + +/* + *---------------------------------------------------------------------- + * + * TkUndoMakeSubAtom -- + * + * Create a new undo/redo step which must later be place into an undo + * stack with TkUndoPushAction. This sub-atom, if evaluated, will take + * the given C-funcPtr (which must be non-NULL), and call it with three + * arguments: the undo stack's 'interp', the 'clientData' given and the + * 'actionScript'. The callback should return a standard Tcl return code + * (TCL_OK on success). + * + * If 'subAtomList' is non-NULL, the newly created sub-atom is added onto + * the end of the linked list of which 'subAtomList' is a part. This + * makes it easy to build up a sequence of actions which will be pushed + * in one step. + * + * Results: + * The newly created subAtom is returned. It must be passed to + * TkUndoPushAction otherwise a memory leak will result. + * + * Side effects: + * A refCount is retained on 'actionScript'. + * + *---------------------------------------------------------------------- + */ + +TkUndoSubAtom * +TkUndoMakeSubAtom( + TkUndoProc *funcPtr, /* Callback function to perform the + * undo/redo. */ + ClientData clientData, /* Data to pass to the callback function. */ + Tcl_Obj *actionScript, /* Additional Tcl data to pass to the callback + * function (may be NULL). */ + TkUndoSubAtom *subAtomList) /* Add to the end of this list of actions if + * non-NULL */ +{ + TkUndoSubAtom *atom; + if (funcPtr == NULL) { + Tcl_Panic("NULL funcPtr in TkUndoMakeSubAtom"); + } + + atom = (TkUndoSubAtom *) ckalloc(sizeof(TkUndoSubAtom)); + atom->command = NULL; + atom->funcPtr = funcPtr; + atom->clientData = clientData; + atom->next = NULL; + atom->action = actionScript; + if (atom->action != NULL) { + Tcl_IncrRefCount(atom->action); + } + + if (subAtomList != NULL) { + while (subAtomList->next != NULL) { + subAtomList = subAtomList->next; + } + subAtomList->next = atom; + } + return atom; +} /* - * TkUndoInitStack - * Initialize a new undo/redo stack + *---------------------------------------------------------------------- + * + * TkUndoInitStack -- + * + * Initialize a new undo/redo stack. * * Results: - * un Undo/Redo stack pointer + * An Undo/Redo stack pointer. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -TkUndoRedoStack * TkUndoInitStack ( interp, maxdepth ) - Tcl_Interp * interp; /* The interpreter */ - int maxdepth; /* The maximum stack depth */ -{ - TkUndoRedoStack * stack; /* An Undo/Redo stack */ + +TkUndoRedoStack * +TkUndoInitStack( + Tcl_Interp *interp, /* The interpreter */ + int maxdepth) /* The maximum stack depth */ +{ + TkUndoRedoStack *stack; /* An Undo/Redo stack */ + stack = (TkUndoRedoStack *) ckalloc(sizeof(TkUndoRedoStack)); stack->undoStack = NULL; stack->redoStack = NULL; - stack->interp = interp; - stack->maxdepth = maxdepth; - stack->depth = 0; + stack->interp = interp; + stack->maxdepth = maxdepth; + stack->depth = 0; return stack; } - /* - * TkUndoInitStack - * Initialize a new undo/redo stack + *---------------------------------------------------------------------- + * + * TkUndoSetDepth -- + * + * Set the maximum depth of stack. * * Results: - * un Undo/Redo stack pointer + * None. * * Side effects: - * None. + * May delete elements from the stack if the new maximum depth is smaller + * than the number of elements previously in the stack. + * + *---------------------------------------------------------------------- */ - -void TkUndoSetDepth ( stack, maxdepth ) - TkUndoRedoStack * stack; /* An Undo/Redo stack */ - int maxdepth; /* The maximum stack depth */ + +void +TkUndoSetDepth( + TkUndoRedoStack *stack, /* An Undo/Redo stack */ + int maxdepth) /* The maximum stack depth */ { - TkUndoAtom * elem; - TkUndoAtom * prevelem; - int sepNumber = 0; - stack->maxdepth = maxdepth; - if ((stack->maxdepth > 0) && (stack->depth > stack->maxdepth)) { - /* + if (stack->maxdepth>0 && stack->depth>stack->maxdepth) { + TkUndoAtom *elem, *prevelem; + int sepNumber = 0; + + /* * Maximum stack depth exceeded. We have to remove the last compound * elements on the stack. */ - elem = stack->undoStack; - prevelem = NULL; - while (elem && (sepNumber <= stack->maxdepth)) { - if (elem->type == TK_UNDO_SEPARATOR) { - sepNumber++; - } - prevelem = elem; - elem = elem->next; - } - prevelem->next = NULL; - while ( elem ) { - prevelem = elem; - elem = elem->next; - ckfree((char *) prevelem); - } - stack->depth = stack->maxdepth; + elem = stack->undoStack; + prevelem = NULL; + while ((elem != NULL) && (sepNumber <= stack->maxdepth)) { + if (elem->type == TK_UNDO_SEPARATOR) { + sepNumber++; + } + prevelem = elem; + elem = elem->next; + } + prevelem->next = NULL; + while (elem != NULL) { + prevelem = elem; + if (elem->type != TK_UNDO_SEPARATOR) { + TkUndoSubAtom *sub = elem->apply; + while (sub != NULL) { + TkUndoSubAtom *next = sub->next; + + if (sub->action != NULL) { + Tcl_DecrRefCount(sub->action); + } + ckfree((char *)sub); + sub = next; + } + sub = elem->revert; + while (sub != NULL) { + TkUndoSubAtom *next = sub->next; + + if (sub->action != NULL) { + Tcl_DecrRefCount(sub->action); + } + ckfree((char *)sub); + sub = next; + } + } + elem = elem->next; + ckfree((char *) prevelem); + } + stack->depth = stack->maxdepth; } } - /* - * TkUndoClearStacks - * Clear both the undo and redo stack + *---------------------------------------------------------------------- + * + * TkUndoClearStacks -- + * + * Clear both the undo and redo stack. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -void TkUndoClearStacks ( stack ) - TkUndoRedoStack * stack; /* An Undo/Redo stack */ -{ - TkUndoClearStack(&(stack->undoStack)); - TkUndoClearStack(&(stack->redoStack)); + +void +TkUndoClearStacks( + TkUndoRedoStack *stack) /* An Undo/Redo stack */ +{ + TkUndoClearStack(&stack->undoStack); + TkUndoClearStack(&stack->redoStack); stack->depth = 0; } - /* + *---------------------------------------------------------------------- + * * TkUndoFreeStack - * Clear both the undo and redo stack - * also free the memory allocated to the u/r stack pointer + * + * Clear both the undo and redo stack and free the memory allocated to + * the u/r stack pointer. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -void TkUndoFreeStack ( stack ) - TkUndoRedoStack * stack; /* An Undo/Redo stack */ -{ - TkUndoClearStacks(stack); -/* ckfree((TkUndoRedoStack *) stack); */ - ckfree((char *) stack); -} +void +TkUndoFreeStack( + TkUndoRedoStack *stack) /* An Undo/Redo stack */ +{ + TkUndoClearStacks(stack); + ckfree((char *) stack); +} /* + *---------------------------------------------------------------------- + * * TkUndoInsertUndoSeparator -- - * insert a separator on the undo stack, indicating a border for - * an undo/redo chunk. + * + * Insert a separator on the undo stack, indicating a border for an + * undo/redo chunk. * * Results: - * None + * None. * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -void TkUndoInsertUndoSeparator ( stack ) - TkUndoRedoStack * stack; + +void +TkUndoInsertUndoSeparator( + TkUndoRedoStack *stack) { - if ( TkUndoInsertSeparator(&(stack->undoStack)) ) { - ++(stack->depth); - TkUndoSetDepth(stack,stack->maxdepth); + if (TkUndoInsertSeparator(&stack->undoStack)) { + stack->depth++; + TkUndoSetDepth(stack, stack->maxdepth); } } - /* + *---------------------------------------------------------------------- + * * TkUndoRevert -- - * Undo a compound action on the stack. + * + * Undo a compound action on the stack. * * Results: - * A TCL status code + * A Tcl status code * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -int TkUndoRevert ( stack ) - TkUndoRedoStack * stack; + +int +TkUndoRevert( + TkUndoRedoStack *stack) { - TkUndoAtom * elem; + TkUndoAtom *elem; - /* insert a separator on the undo and the redo stack */ + /* + * Insert a separator on the undo and the redo stack. + */ TkUndoInsertUndoSeparator(stack); - TkUndoInsertSeparator(&(stack->redoStack)); - - /* Pop and skip the first separator if there is one*/ + TkUndoInsertSeparator(&stack->redoStack); - elem = TkUndoPopStack(&(stack->undoStack)); + /* + * Pop and skip the first separator if there is one. + */ - if ( elem == NULL ) { - return TCL_ERROR; + elem = TkUndoPopStack(&stack->undoStack); + if (elem == NULL) { + return TCL_ERROR; } - if ( ( elem != NULL ) && ( elem->type == TK_UNDO_SEPARATOR ) ) { - ckfree((char *) elem); - elem = TkUndoPopStack(&(stack->undoStack)); + if (elem->type == TK_UNDO_SEPARATOR) { + ckfree((char *) elem); + elem = TkUndoPopStack(&stack->undoStack); } - - while ( elem && (elem->type != TK_UNDO_SEPARATOR) ) { - Tcl_EvalObjEx(stack->interp,elem->revert,TCL_EVAL_GLOBAL); - - TkUndoPushStack(&(stack->redoStack),elem); - elem = TkUndoPopStack(&(stack->undoStack)); + + while (elem != NULL && elem->type != TK_UNDO_SEPARATOR) { + /* + * Note that we currently ignore errors thrown here. + */ + + EvaluateActionList(stack->interp, elem->revert); + + TkUndoPushStack(&stack->redoStack, elem); + elem = TkUndoPopStack(&stack->undoStack); } - - /* insert a separator on the redo stack */ - - TkUndoInsertSeparator(&(stack->redoStack)); - - --(stack->depth); - + + /* + * Insert a separator on the redo stack. + */ + + TkUndoInsertSeparator(&stack->redoStack); + stack->depth--; return TCL_OK; } - /* + *---------------------------------------------------------------------- + * * TkUndoApply -- - * Redo a compound action on the stack. + * + * Redo a compound action on the stack. * * Results: - * A TCL status code + * A Tcl status code * * Side effects: - * None. + * None. + * + *---------------------------------------------------------------------- */ - -int TkUndoApply ( stack ) - TkUndoRedoStack * stack; + +int +TkUndoApply( + TkUndoRedoStack *stack) { TkUndoAtom *elem; - /* insert a separator on the undo stack */ + /* + * Insert a separator on the undo stack. + */ - TkUndoInsertSeparator(&(stack->undoStack)); + TkUndoInsertSeparator(&stack->undoStack); - /* Pop and skip the first separator if there is one*/ + /* + * Pop and skip the first separator if there is one. + */ - elem = TkUndoPopStack(&(stack->redoStack)); - - if ( elem == NULL ) { - return TCL_ERROR; + elem = TkUndoPopStack(&stack->redoStack); + if (elem == NULL) { + return TCL_ERROR; } - if ( ( elem != NULL ) && ( elem->type == TK_UNDO_SEPARATOR ) ) { - ckfree((char *) elem); - elem = TkUndoPopStack(&(stack->redoStack)); + if (elem->type == TK_UNDO_SEPARATOR) { + ckfree((char *) elem); + elem = TkUndoPopStack(&stack->redoStack); } - while ( elem && (elem->type != TK_UNDO_SEPARATOR) ) { - Tcl_EvalObjEx(stack->interp,elem->apply,TCL_EVAL_GLOBAL); - - TkUndoPushStack(&(stack->undoStack), elem); - elem = TkUndoPopStack(&(stack->redoStack)); + while (elem != NULL && elem->type != TK_UNDO_SEPARATOR) { + /* + * Note that we currently ignore errors thrown here. + */ + + EvaluateActionList(stack->interp, elem->apply); + + TkUndoPushStack(&stack->undoStack, elem); + elem = TkUndoPopStack(&stack->redoStack); } - /* insert a separator on the undo stack */ - - TkUndoInsertSeparator(&(stack->undoStack)); + /* + * Insert a separator on the undo stack. + */ - ++(stack->depth); - + TkUndoInsertSeparator(&stack->undoStack); + stack->depth++; return TCL_OK; } + +/* + *---------------------------------------------------------------------- + * + * EvaluateActionList -- + * + * Execute a linked list of undo/redo sub-atoms. If any sub-atom returns + * a non TCL_OK value, execution of subsequent sub-atoms is cancelled and + * the error returned immediately. + * + * Results: + * A Tcl status code + * + * Side effects: + * The undo/redo subAtoms can perform arbitrary actions. + * + *---------------------------------------------------------------------- + */ +static int +EvaluateActionList( + Tcl_Interp *interp, /* Interpreter to evaluate the action in. */ + TkUndoSubAtom *action) /* Head of linked list of action steps to + * perform. */ +{ + int result = TCL_OK; + + while (action != NULL) { + if (action->funcPtr != NULL) { + result = (*action->funcPtr)(interp, action->clientData, + action->action); + } else if (action->command != NULL) { + Tcl_Obj *cmdNameObj, *evalObj; + + cmdNameObj = Tcl_NewObj(); + evalObj = Tcl_NewObj(); + Tcl_IncrRefCount(evalObj); + Tcl_GetCommandFullName(interp, action->command, cmdNameObj); + Tcl_ListObjAppendElement(NULL, evalObj, cmdNameObj); + if (action->action != NULL) { + Tcl_ListObjAppendList(NULL, evalObj, action->action); + } + result = Tcl_EvalObjEx(interp, evalObj, TCL_EVAL_GLOBAL); + Tcl_DecrRefCount(evalObj); + } else { + result = Tcl_EvalObjEx(interp, action->action, TCL_EVAL_GLOBAL); + } + if (result != TCL_OK) { + return result; + } + action = action->next; + } + return result; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkUndo.h b/generic/tkUndo.h index 8f0411c..b0e2db0 100644 --- a/generic/tkUndo.h +++ b/generic/tkUndo.h @@ -1,20 +1,19 @@ /* * tkUndo.h -- * - * Declarations shared among the files that implement an undo - * stack. + * Declarations shared among the files that implement an undo stack. * * Copyright (c) 2002 Ludwig Callewaert. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TKUNDO #define _TKUNDO -#ifndef _TK -#include "tk.h" +#ifndef _TKINT +#include "tkInt.h" #endif #ifdef BUILD_tk @@ -22,65 +21,99 @@ # define TCL_STORAGE_CLASS DLLEXPORT #endif -/* enum definining the types used in an undo stack */ +/* + * Enum definining the types used in an undo stack. + */ typedef enum { - TK_UNDO_SEPARATOR, /* Marker */ - TK_UNDO_ACTION /* Command */ + TK_UNDO_SEPARATOR, /* Marker */ + TK_UNDO_ACTION /* Command */ } TkUndoAtomType; -/* struct defining the basic undo/redo stack element */ - -typedef struct TkUndoAtom { - TkUndoAtomType type; /* The type that will trigger the - * required action*/ - Tcl_Obj * apply; /* Command to apply the action that was taken */ - Tcl_Obj * revert; /* The command to undo the action */ - struct TkUndoAtom * next; /* Pointer to the next element in the - * stack */ -} TkUndoAtom; - -/* struct defining the basic undo/redo stack element */ - -typedef struct TkUndoRedoStack { - TkUndoAtom * undoStack; /* The undo stack */ - TkUndoAtom * redoStack; /* The redo stack */ - Tcl_Interp * interp ; /* The interpreter in which to execute the revert and apply scripts */ - int maxdepth; - int depth; -} TkUndoRedoStack; - -/* basic functions */ +/* + * Callback proc type to carry out an undo or redo action via C code. (Actions + * can also be defined by Tcl scripts). + */ -EXTERN void TkUndoPushStack _ANSI_ARGS_((TkUndoAtom ** stack, - TkUndoAtom * elem)); +typedef int (TkUndoProc)(Tcl_Interp *interp, ClientData clientData, + Tcl_Obj *objPtr); -EXTERN TkUndoAtom * TkUndoPopStack _ANSI_ARGS_((TkUndoAtom ** stack)); - -EXTERN int TkUndoInsertSeparator _ANSI_ARGS_((TkUndoAtom ** stack)); +/* + * Struct defining a single action, one or more of which may be defined (and + * stored in a linked list) separately for each undo and redo action of an + * undo atom. + */ -EXTERN void TkUndoClearStack _ANSI_ARGS_((TkUndoAtom ** stack)); +typedef struct TkUndoSubAtom { + Tcl_Command command; /* Tcl token used to get the current Tcl + * command name which will be used to execute + * apply/revert scripts. If NULL then it is + * assumed the apply/revert scripts already + * contain everything. */ + TkUndoProc *funcPtr; /* Function pointer for callback to perform + * undo/redo actions. */ + ClientData clientData; /* Data for 'funcPtr'. */ + Tcl_Obj *action; /* Command to apply the action that was + * taken. */ + struct TkUndoSubAtom *next; /* Pointer to the next element in the linked + * list. */ +} TkUndoSubAtom; -/* functions working on an undo/redo stack */ +/* + * Struct representing a single undo+redo atom to be placed in the stack. + */ -EXTERN TkUndoRedoStack * TkUndoInitStack _ANSI_ARGS_((Tcl_Interp * interp, - int maxdepth)); +typedef struct TkUndoAtom { + TkUndoAtomType type; /* The type that will trigger the required + * action. */ + TkUndoSubAtom *apply; /* Linked list of 'apply' actions to perform + * for this operation. */ + TkUndoSubAtom *revert; /* Linked list of 'revert' actions to perform + * for this operation. */ + struct TkUndoAtom *next; /* Pointer to the next element in the + * stack. */ +} TkUndoAtom; -EXTERN void TkUndoSetDepth _ANSI_ARGS_((TkUndoRedoStack * stack, - int maxdepth)); +/* + * Struct defining a single undo+redo stack. + */ -EXTERN void TkUndoClearStacks _ANSI_ARGS_((TkUndoRedoStack * stack)); +typedef struct TkUndoRedoStack { + TkUndoAtom *undoStack; /* The undo stack. */ + TkUndoAtom *redoStack; /* The redo stack. */ + Tcl_Interp *interp; /* The interpreter in which to execute the + * revert and apply scripts. */ + int maxdepth; + int depth; +} TkUndoRedoStack; -EXTERN void TkUndoFreeStack _ANSI_ARGS_((TkUndoRedoStack * stack)); +/* + * Basic functions. + */ -EXTERN void TkUndoInsertUndoSeparator _ANSI_ARGS_((TkUndoRedoStack * stack)); +MODULE_SCOPE void TkUndoPushStack(TkUndoAtom **stack, TkUndoAtom *elem); +MODULE_SCOPE TkUndoAtom *TkUndoPopStack(TkUndoAtom **stack); +MODULE_SCOPE int TkUndoInsertSeparator(TkUndoAtom **stack); +MODULE_SCOPE void TkUndoClearStack(TkUndoAtom **stack); -EXTERN void TkUndoPushAction _ANSI_ARGS_((TkUndoRedoStack * stack, - Tcl_DString * actionScript, Tcl_DString * revertScript)); +/* + * Functions for working on an undo/redo stack. + */ -EXTERN int TkUndoRevert _ANSI_ARGS_((TkUndoRedoStack * stack)); - -EXTERN int TkUndoApply _ANSI_ARGS_((TkUndoRedoStack * stack)); +MODULE_SCOPE TkUndoRedoStack *TkUndoInitStack(Tcl_Interp *interp, int maxdepth); +MODULE_SCOPE void TkUndoSetDepth(TkUndoRedoStack *stack, int maxdepth); +MODULE_SCOPE void TkUndoClearStacks(TkUndoRedoStack *stack); +MODULE_SCOPE void TkUndoFreeStack(TkUndoRedoStack *stack); +MODULE_SCOPE void TkUndoInsertUndoSeparator(TkUndoRedoStack *stack); +MODULE_SCOPE TkUndoSubAtom *TkUndoMakeCmdSubAtom(Tcl_Command command, + Tcl_Obj *actionScript, TkUndoSubAtom *subAtomList); +MODULE_SCOPE TkUndoSubAtom *TkUndoMakeSubAtom(TkUndoProc *funcPtr, + ClientData clientData, Tcl_Obj *actionScript, + TkUndoSubAtom *subAtomList); +MODULE_SCOPE void TkUndoPushAction(TkUndoRedoStack *stack, + TkUndoSubAtom *apply, TkUndoSubAtom *revert); +MODULE_SCOPE int TkUndoRevert(TkUndoRedoStack *stack); +MODULE_SCOPE int TkUndoApply(TkUndoRedoStack *stack); # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLIMPORT diff --git a/generic/tkUtil.c b/generic/tkUtil.c index 3d04657..bfa5d5c 100644 --- a/generic/tkUtil.c +++ b/generic/tkUtil.c @@ -1,63 +1,60 @@ -/* +/* * tkUtil.c -- * - * This file contains miscellaneous utility procedures that - * are used by the rest of Tk, such as a procedure for drawing - * a focus highlight. + * This file contains miscellaneous utility functions that are used by + * the rest of Tk, such as a function for drawing a focus highlight. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" /* - * The structure below defines the implementation of the "statekey" - * Tcl object, used for quickly finding a mapping in a TkStateMap. + * The structure below defines the implementation of the "statekey" Tcl + * object, used for quickly finding a mapping in a TkStateMap. */ Tcl_ObjType tkStateKeyObjType = { - "statekey", /* name */ - (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */ - (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */ - (Tcl_UpdateStringProc *) NULL, /* updateStringProc */ - (Tcl_SetFromAnyProc *) NULL /* setFromAnyProc */ + "statekey", /* name */ + NULL, /* freeIntRepProc */ + NULL, /* dupIntRepProc */ + NULL, /* updateStringProc */ + NULL /* setFromAnyProc */ }; - /* *-------------------------------------------------------------- * * TkStateParseProc -- * - * This procedure is invoked during option processing to handle - * the "-state" and "-default" options. + * This function is invoked during option processing to handle the + * "-state" and "-default" options. * * Results: * A standard Tcl return value. * * Side effects: - * The state for a given item gets replaced by the state - * indicated in the value argument. + * The state for a given item gets replaced by the state indicated in the + * value argument. * *-------------------------------------------------------------- */ int -TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* some flags.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ +TkStateParseProc( + ClientData clientData, /* some flags.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + const char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item. */ { int c; - int flags = (int)clientData; + int flags = PTR2INT(clientData); size_t length; register Tk_State *statePtr = (Tk_State *) (widgRec + offset); @@ -88,18 +85,17 @@ TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset) } Tcl_AppendResult(interp, "bad ", (flags&4)?"-default" : "state", - " value \"", value, "\": must be normal", - (char *) NULL); + " value \"", value, "\": must be normal", NULL); if (flags&1) { - Tcl_AppendResult(interp, ", active",(char *) NULL); + Tcl_AppendResult(interp, ", active", NULL); } if (flags&2) { - Tcl_AppendResult(interp, ", hidden",(char *) NULL); + Tcl_AppendResult(interp, ", hidden", NULL); } if (flags&3) { - Tcl_AppendResult(interp, ",",(char *) NULL); + Tcl_AppendResult(interp, ",", NULL); } - Tcl_AppendResult(interp, " or disabled",(char *) NULL); + Tcl_AppendResult(interp, " or disabled", NULL); *statePtr = TK_STATE_NORMAL; return TCL_ERROR; } @@ -109,16 +105,15 @@ TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset) * * TkStatePrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-state" - * configuration option. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-state" configuration option. * * Results: - * The return value is a string describing the state for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). + * The return value is a string describing the state for the item + * referred to by "widgRec". In addition, *freeProcPtr is filled in with + * the address of a function to call to free the result string when it's + * no longer needed (or NULL to indicate that the string doesn't need to + * be freed). * * Side effects: * None. @@ -127,26 +122,27 @@ TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset) */ char * -TkStatePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +TkStatePrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Offset into item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { register Tk_State *statePtr = (Tk_State *) (widgRec + offset); - if (*statePtr==TK_STATE_NORMAL) { + switch (*statePtr) { + case TK_STATE_NORMAL: return "normal"; - } else if (*statePtr==TK_STATE_DISABLED) { + case TK_STATE_DISABLED: return "disabled"; - } else if (*statePtr==TK_STATE_HIDDEN) { + case TK_STATE_HIDDEN: return "hidden"; - } else if (*statePtr==TK_STATE_ACTIVE) { + case TK_STATE_ACTIVE: return "active"; - } else { + default: return ""; } } @@ -156,8 +152,8 @@ TkStatePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) * * TkOrientParseProc -- * - * This procedure is invoked during option processing to handle - * the "-orient" option. + * This function is invoked during option processing to handle the + * "-orient" option. * * Results: * A standard Tcl return value. @@ -170,13 +166,13 @@ TkStatePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) */ int -TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* some flags.*/ - Tcl_Interp *interp; /* Used for reporting errors. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - CONST char *value; /* Value of option. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ +TkOrientParseProc( + ClientData clientData, /* some flags.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + const char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + int offset) /* Offset into item. */ { int c; size_t length; @@ -200,8 +196,7 @@ TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset) return TCL_OK; } Tcl_AppendResult(interp, "bad orientation \"", value, - "\": must be vertical or horizontal", - (char *) NULL); + "\": must be vertical or horizontal", NULL); *orientPtr = 0; return TCL_ERROR; } @@ -211,16 +206,15 @@ TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset) * * TkOrientPrintProc -- * - * This procedure is invoked by the Tk configuration code - * to produce a printable string for the "-orient" - * configuration option. + * This function is invoked by the Tk configuration code to produce a + * printable string for the "-orient" configuration option. * * Results: - * The return value is a string describing the orientation for - * the item referred to by "widgRec". In addition, *freeProcPtr - * is filled in with the address of a procedure to call to free - * the result string when it's no longer needed (or NULL to - * indicate that the string doesn't need to be freed). + * The return value is a string describing the orientation for the item + * referred to by "widgRec". In addition, *freeProcPtr is filled in with + * the address of a function to call to free the result string when it's + * no longer needed (or NULL to indicate that the string doesn't need to + * be freed). * * Side effects: * None. @@ -229,14 +223,14 @@ TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset) */ char * -TkOrientPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* Ignored. */ - Tk_Window tkwin; /* Window containing canvas widget. */ - char *widgRec; /* Pointer to record for item. */ - int offset; /* Offset into item. */ - Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with - * information about how to reclaim - * storage for return string. */ +TkOrientPrintProc( + ClientData clientData, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + int offset, /* Offset into item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ { register int *statePtr = (int *) (widgRec + offset); @@ -252,23 +246,24 @@ TkOrientPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) * * TkOffsetParseProc -- * - * Converts the offset of a stipple or tile into the Tk_TSOffset structure. + * Converts the offset of a stipple or tile into the Tk_TSOffset + * structure. * *---------------------------------------------------------------------- */ int -TkOffsetParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* not used */ - Tcl_Interp *interp; /* Interpreter to send results back to */ - Tk_Window tkwin; /* Window on same display as tile */ - CONST char *value; /* Name of image */ - char *widgRec; /* Widget structure record */ - int offset; /* Offset of tile in record */ +TkOffsetParseProc( + ClientData clientData, /* not used */ + Tcl_Interp *interp, /* Interpreter to send results back to */ + Tk_Window tkwin, /* Window on same display as tile */ + const char *value, /* Name of image */ + char *widgRec, /* Widget structure record */ + int offset) /* Offset of tile in record */ { - Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset); + Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset); Tk_TSOffset tsoffset; - CONST char *q, *p; + const char *q, *p; int result; if ((value == NULL) || (*value == 0)) { @@ -279,61 +274,70 @@ TkOffsetParseProc(clientData, interp, tkwin, value, widgRec, offset) p = value; switch(value[0]) { - case '#': - if (((int)clientData) & TK_OFFSET_RELATIVE) { - tsoffset.flags = TK_OFFSET_RELATIVE; - p++; break; - } - goto badTSOffset; - case 'e': - switch(value[1]) { - case '\0': - tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE; - goto goodTSOffset; - case 'n': - if (value[2]!='d' || value[3]!='\0') {goto badTSOffset;} - tsoffset.flags = INT_MAX; - goto goodTSOffset; - } - case 'w': - if (value[1] != '\0') {goto badTSOffset;} - tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE; + case '#': + if (PTR2INT(clientData) & TK_OFFSET_RELATIVE) { + tsoffset.flags = TK_OFFSET_RELATIVE; + p++; + break; + } + goto badTSOffset; + case 'e': + switch(value[1]) { + case '\0': + tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE; goto goodTSOffset; case 'n': - if ((value[1] != '\0') && (value[2] != '\0')) { + if (value[2]!='d' || value[3]!='\0') { goto badTSOffset; } - switch(value[1]) { - case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP; - goto goodTSOffset; - case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP; - goto goodTSOffset; - case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP; - goto goodTSOffset; - } + tsoffset.flags = INT_MAX; + goto goodTSOffset; + } + case 'w': + if (value[1] != '\0') {goto badTSOffset;} + tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE; + goto goodTSOffset; + case 'n': + if ((value[1] != '\0') && (value[2] != '\0')) { goto badTSOffset; - case 's': - if ((value[1] != '\0') && (value[2] != '\0')) { - goto badTSOffset; - } - switch(value[1]) { - case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM; - goto goodTSOffset; - case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM; - goto goodTSOffset; - case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM; - goto goodTSOffset; - } + } + switch(value[1]) { + case '\0': + tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP; + goto goodTSOffset; + case 'w': + tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP; + goto goodTSOffset; + case 'e': + tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP; + goto goodTSOffset; + } + goto badTSOffset; + case 's': + if ((value[1] != '\0') && (value[2] != '\0')) { goto badTSOffset; - case 'c': - if (strncmp(value, "center", strlen(value)) != 0) { - goto badTSOffset; - } - tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE; + } + switch(value[1]) { + case '\0': + tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM; goto goodTSOffset; + case 'w': + tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM; + goto goodTSOffset; + case 'e': + tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM; + goto goodTSOffset; + } + goto badTSOffset; + case 'c': + if (strncmp(value, "center", strlen(value)) != 0) { + goto badTSOffset; + } + tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE; + goto goodTSOffset; } if ((q = strchr(p,',')) == NULL) { - if (((int)clientData) & TK_OFFSET_INDEX) { + if (PTR2INT(clientData) & TK_OFFSET_INDEX) { if (Tcl_GetInt(interp, (char *) p, &tsoffset.flags) != TCL_OK) { Tcl_ResetResult(interp); goto badTSOffset; @@ -349,33 +353,31 @@ TkOffsetParseProc(clientData, interp, tkwin, value, widgRec, offset) if (result != TCL_OK) { return TCL_ERROR; } - if (Tk_GetPixels(interp, tkwin, (char *) q+1, &tsoffset.yoffset) != TCL_OK) { + if (Tk_GetPixels(interp, tkwin, (char*)q+1, &tsoffset.yoffset) != TCL_OK) { return TCL_ERROR; } - -goodTSOffset: - /* below is a hack to allow the stipple/tile offset to be stored - * in the internal tile structure. Most of the times, offsetPtr - * is a pointer to an already existing tile structure. However - * if this structure is not already created, we must do it - * with Tk_GetTile()!!!!; + goodTSOffset: + /* + * Below is a hack to allow the stipple/tile offset to be stored in the + * internal tile structure. Most of the times, offsetPtr is a pointer to + * an already existing tile structure. However if this structure is not + * already created, we must do it with Tk_GetTile()!!!!; */ - memcpy(offsetPtr,&tsoffset, sizeof(Tk_TSOffset)); + memcpy(offsetPtr, &tsoffset, sizeof(Tk_TSOffset)); return TCL_OK; -badTSOffset: + badTSOffset: Tcl_AppendResult(interp, "bad offset \"", value, - "\": expected \"x,y\"", (char *) NULL); - if (((int) clientData) & TK_OFFSET_RELATIVE) { - Tcl_AppendResult(interp, ", \"#x,y\"", (char *) NULL); + "\": expected \"x,y\"", NULL); + if (PTR2INT(clientData) & TK_OFFSET_RELATIVE) { + Tcl_AppendResult(interp, ", \"#x,y\"", NULL); } - if (((int) clientData) & TK_OFFSET_INDEX) { - Tcl_AppendResult(interp, ", <index>", (char *) NULL); + if (PTR2INT(clientData) & TK_OFFSET_INDEX) { + Tcl_AppendResult(interp, ", <index>", NULL); } - Tcl_AppendResult(interp, ", n, ne, e, se, s, sw, w, nw, or center", - (char *) NULL); + Tcl_AppendResult(interp, ", n, ne, e, se, s, sw, w, nw, or center", NULL); return TCL_ERROR; } @@ -393,60 +395,59 @@ badTSOffset: */ char * -TkOffsetPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* not used */ - Tk_Window tkwin; /* not used */ - char *widgRec; /* Widget structure record */ - int offset; /* Offset of tile in record */ - Tcl_FreeProc **freeProcPtr; /* not used */ +TkOffsetPrintProc( + ClientData clientData, /* not used */ + Tk_Window tkwin, /* not used */ + char *widgRec, /* Widget structure record */ + int offset, /* Offset of tile in record */ + Tcl_FreeProc **freeProcPtr) /* not used */ { - Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset); + Tk_TSOffset *offsetPtr = (Tk_TSOffset *) (widgRec + offset); char *p, *q; - if ((offsetPtr->flags) & TK_OFFSET_INDEX) { - if ((offsetPtr->flags) >= INT_MAX) { + if (offsetPtr->flags & TK_OFFSET_INDEX) { + if (offsetPtr->flags >= INT_MAX) { return "end"; } p = (char *) ckalloc(32); - sprintf(p, "%d",(offsetPtr->flags & (~TK_OFFSET_INDEX))); + sprintf(p, "%d", offsetPtr->flags & ~TK_OFFSET_INDEX); *freeProcPtr = TCL_DYNAMIC; return p; } - if ((offsetPtr->flags) & TK_OFFSET_TOP) { - if ((offsetPtr->flags) & TK_OFFSET_LEFT) { + if (offsetPtr->flags & TK_OFFSET_TOP) { + if (offsetPtr->flags & TK_OFFSET_LEFT) { return "nw"; - } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) { + } else if (offsetPtr->flags & TK_OFFSET_CENTER) { return "n"; - } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) { + } else if (offsetPtr->flags & TK_OFFSET_RIGHT) { return "ne"; } - } else if ((offsetPtr->flags) & TK_OFFSET_MIDDLE) { - if ((offsetPtr->flags) & TK_OFFSET_LEFT) { + } else if (offsetPtr->flags & TK_OFFSET_MIDDLE) { + if (offsetPtr->flags & TK_OFFSET_LEFT) { return "w"; - } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) { + } else if (offsetPtr->flags & TK_OFFSET_CENTER) { return "center"; - } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) { + } else if (offsetPtr->flags & TK_OFFSET_RIGHT) { return "e"; } - } else if ((offsetPtr->flags) & TK_OFFSET_BOTTOM) { - if ((offsetPtr->flags) & TK_OFFSET_LEFT) { + } else if (offsetPtr->flags & TK_OFFSET_BOTTOM) { + if (offsetPtr->flags & TK_OFFSET_LEFT) { return "sw"; - } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) { + } else if (offsetPtr->flags & TK_OFFSET_CENTER) { return "s"; - } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) { + } else if (offsetPtr->flags & TK_OFFSET_RIGHT) { return "se"; } - } + } q = p = (char *) ckalloc(32); - if ((offsetPtr->flags) & TK_OFFSET_RELATIVE) { + if (offsetPtr->flags & TK_OFFSET_RELATIVE) { *q++ = '#'; } - sprintf(q, "%d,%d",offsetPtr->xoffset, offsetPtr->yoffset); + sprintf(q, "%d,%d", offsetPtr->xoffset, offsetPtr->yoffset); *freeProcPtr = TCL_DYNAMIC; return p; } - /* *---------------------------------------------------------------------- * @@ -458,23 +459,22 @@ TkOffsetPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) */ int -TkPixelParseProc(clientData, interp, tkwin, value, widgRec, offset) - ClientData clientData; /* if non-NULL, negative values are - * allowed as well */ - Tcl_Interp *interp; /* Interpreter to send results back to */ - Tk_Window tkwin; /* Window on same display as tile */ - CONST char *value; /* Name of image */ - char *widgRec; /* Widget structure record */ - int offset; /* Offset of tile in record */ +TkPixelParseProc( + ClientData clientData, /* If non-NULL, negative values are allowed as + * well */ + Tcl_Interp *interp, /* Interpreter to send results back to */ + Tk_Window tkwin, /* Window on same display as tile */ + const char *value, /* Name of image */ + char *widgRec, /* Widget structure record */ + int offset) /* Offset of tile in record */ { - double *doublePtr = (double *)(widgRec + offset); + double *doublePtr = (double *) (widgRec + offset); int result; result = TkGetDoublePixels(interp, tkwin, value, doublePtr); if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) { - Tcl_AppendResult(interp, "bad screen distance \"", value, - "\"", (char *) NULL); + Tcl_AppendResult(interp, "bad screen distance \"", value, "\"", NULL); return TCL_ERROR; } return result; @@ -494,18 +494,17 @@ TkPixelParseProc(clientData, interp, tkwin, value, widgRec, offset) */ char * -TkPixelPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) - ClientData clientData; /* not used */ - Tk_Window tkwin; /* not used */ - char *widgRec; /* Widget structure record */ - int offset; /* Offset of tile in record */ - Tcl_FreeProc **freeProcPtr; /* not used */ +TkPixelPrintProc( + ClientData clientData, /* not used */ + Tk_Window tkwin, /* not used */ + char *widgRec, /* Widget structure record */ + int offset, /* Offset of tile in record */ + Tcl_FreeProc **freeProcPtr) /* not used */ { - double *doublePtr = (double *)(widgRec + offset); - char *p; + double *doublePtr = (double *) (widgRec + offset); + char *p = (char *) ckalloc(24); - p = (char *) ckalloc(24); - Tcl_PrintDouble((Tcl_Interp *) NULL, *doublePtr, p); + Tcl_PrintDouble(NULL, *doublePtr, p); *freeProcPtr = TCL_DYNAMIC; return p; } @@ -515,31 +514,31 @@ TkPixelPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr) * * TkDrawInsetFocusHighlight -- * - * This procedure draws a rectangular ring around the outside of - * a widget to indicate that it has received the input focus. It - * takes an additional padding argument that specifies how much - * padding is present outside th widget. + * This function draws a rectangular ring around the outside of a widget + * to indicate that it has received the input focus. It takes an + * additional padding argument that specifies how much padding is present + * outside the widget. * * Results: * None. * * Side effects: - * A rectangle "width" pixels wide is drawn in "drawable", - * corresponding to the outer area of "tkwin". + * A rectangle "width" pixels wide is drawn in "drawable", corresponding + * to the outer area of "tkwin". * *---------------------------------------------------------------------- */ void -TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding) - Tk_Window tkwin; /* Window whose focus highlight ring is - * to be drawn. */ - GC gc; /* Graphics context to use for drawing - * the highlight ring. */ - int width; /* Width of the highlight ring, in pixels. */ - Drawable drawable; /* Where to draw the ring (typically a - * pixmap for double buffering). */ - int padding; /* Width of padding outside of widget. */ +TkDrawInsetFocusHighlight( + Tk_Window tkwin, /* Window whose focus highlight ring is to be + * drawn. */ + GC gc, /* Graphics context to use for drawing the + * highlight ring. */ + int width, /* Width of the highlight ring, in pixels. */ + Drawable drawable, /* Where to draw the ring (typically a pixmap + * for double buffering). */ + int padding) /* Width of padding outside of widget. */ { XRectangle rects[4]; @@ -567,34 +566,34 @@ TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding) * * Tk_DrawFocusHighlight -- * - * This procedure draws a rectangular ring around the outside of - * a widget to indicate that it has received the input focus. + * This function draws a rectangular ring around the outside of a widget + * to indicate that it has received the input focus. * - * This function is now deprecated. Use TkpDrawHighlightBorder instead, - * since this function does not handle drawing the Focus ring properly - * on the Macintosh - you need to know the background GC as well - * as the foreground since the Mac focus ring separated from the widget - * by a 1 pixel border. + * This function is now deprecated. Use TkpDrawHighlightBorder instead, + * since this function does not handle drawing the Focus ring properly on + * the Macintosh - you need to know the background GC as well as the + * foreground since the Mac focus ring separated from the widget by a 1 + * pixel border. * * Results: * None. * * Side effects: - * A rectangle "width" pixels wide is drawn in "drawable", - * corresponding to the outer area of "tkwin". + * A rectangle "width" pixels wide is drawn in "drawable", corresponding + * to the outer area of "tkwin". * *---------------------------------------------------------------------- */ void -Tk_DrawFocusHighlight(tkwin, gc, width, drawable) - Tk_Window tkwin; /* Window whose focus highlight ring is - * to be drawn. */ - GC gc; /* Graphics context to use for drawing - * the highlight ring. */ - int width; /* Width of the highlight ring, in pixels. */ - Drawable drawable; /* Where to draw the ring (typically a - * pixmap for double buffering). */ +Tk_DrawFocusHighlight( + Tk_Window tkwin, /* Window whose focus highlight ring is to be + * drawn. */ + GC gc, /* Graphics context to use for drawing the + * highlight ring. */ + int width, /* Width of the highlight ring, in pixels. */ + Drawable drawable) /* Where to draw the ring (typically a pixmap + * for double buffering). */ { TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, 0); } @@ -604,19 +603,18 @@ Tk_DrawFocusHighlight(tkwin, gc, width, drawable) * * Tk_GetScrollInfo -- * - * This procedure is invoked to parse "xview" and "yview" - * scrolling commands for widgets using the new scrolling - * command syntax ("moveto" or "scroll" options). + * This function is invoked to parse "xview" and "yview" scrolling + * commands for widgets using the new scrolling command syntax ("moveto" + * or "scroll" options). * * Results: * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES, - * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether - * the command was successfully parsed and what form the command - * took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the - * desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS, - * *intPtr is filled in with the number of lines to move (may be - * negative); if TK_SCROLL_ERROR, the interp's result contains an - * error message. + * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether the + * command was successfully parsed and what form the command took. If + * TK_SCROLL_MOVETO, *dblPtr is filled in with the desired position; if + * TK_SCROLL_PAGES or TK_SCROLL_UNITS, *intPtr is filled in with the + * number of lines to move (may be negative); if TK_SCROLL_ERROR, the + * interp's result contains an error message. * * Side effects: * None. @@ -625,25 +623,22 @@ Tk_DrawFocusHighlight(tkwin, gc, width, drawable) */ int -Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - int argc; /* # arguments for command. */ - CONST char **argv; /* Arguments for command. */ - double *dblPtr; /* Filled in with argument "moveto" - * option, if any. */ - int *intPtr; /* Filled in with number of pages - * or lines to scroll, if any. */ +Tk_GetScrollInfo( + Tcl_Interp *interp, /* Used for error reporting. */ + int argc, /* # arguments for command. */ + const char **argv, /* Arguments for command. */ + double *dblPtr, /* Filled in with argument "moveto" option, if + * any. */ + int *intPtr) /* Filled in with number of pages or lines to + * scroll, if any. */ { - int c; - size_t length; + int c = argv[2][0]; + size_t length = strlen(argv[2]); - length = strlen(argv[2]); - c = argv[2][0]; if ((c == 'm') && (strncmp(argv[2], "moveto", length) == 0)) { if (argc != 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " ", argv[1], " moveto fraction\"", - (char *) NULL); + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ", argv[1], " moveto fraction\"", NULL); return TK_SCROLL_ERROR; } if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) { @@ -653,9 +648,8 @@ Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr) } else if ((c == 's') && (strncmp(argv[2], "scroll", length) == 0)) { if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " ", argv[1], " scroll number units|pages\"", - (char *) NULL); + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ", argv[1], " scroll number units|pages\"", NULL); return TK_SCROLL_ERROR; } if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) { @@ -665,17 +659,16 @@ Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr) c = argv[4][0]; if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) { return TK_SCROLL_PAGES; - } else if ((c == 'u') - && (strncmp(argv[4], "units", length) == 0)) { + } else if ((c == 'u') && (strncmp(argv[4], "units", length) == 0)) { return TK_SCROLL_UNITS; - } else { - Tcl_AppendResult(interp, "bad argument \"", argv[4], - "\": must be units or pages", (char *) NULL); - return TK_SCROLL_ERROR; } + + Tcl_AppendResult(interp, "bad argument \"", argv[4], + "\": must be units or pages", NULL); + return TK_SCROLL_ERROR; } Tcl_AppendResult(interp, "unknown option \"", argv[2], - "\": must be moveto or scroll", (char *) NULL); + "\": must be moveto or scroll", NULL); return TK_SCROLL_ERROR; } @@ -684,19 +677,18 @@ Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr) * * Tk_GetScrollInfoObj -- * - * This procedure is invoked to parse "xview" and "yview" - * scrolling commands for widgets using the new scrolling - * command syntax ("moveto" or "scroll" options). + * This function is invoked to parse "xview" and "yview" scrolling + * commands for widgets using the new scrolling command syntax ("moveto" + * or "scroll" options). * * Results: * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES, - * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether - * the command was successfully parsed and what form the command - * took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the - * desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS, - * *intPtr is filled in with the number of lines to move (may be - * negative); if TK_SCROLL_ERROR, the interp's result contains an - * error message. + * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether the + * command was successfully parsed and what form the command took. If + * TK_SCROLL_MOVETO, *dblPtr is filled in with the desired position; if + * TK_SCROLL_PAGES or TK_SCROLL_UNITS, *intPtr is filled in with the + * number of lines to move (may be negative); if TK_SCROLL_ERROR, the + * interp's result contains an error message. * * Side effects: * None. @@ -705,23 +697,23 @@ Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr) */ int -Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr) - Tcl_Interp *interp; /* Used for error reporting. */ - int objc; /* # arguments for command. */ - Tcl_Obj *CONST objv[]; /* Arguments for command. */ - double *dblPtr; /* Filled in with argument "moveto" - * option, if any. */ - int *intPtr; /* Filled in with number of pages - * or lines to scroll, if any. */ +Tk_GetScrollInfoObj( + Tcl_Interp *interp, /* Used for error reporting. */ + int objc, /* # arguments for command. */ + Tcl_Obj *const objv[], /* Arguments for command. */ + double *dblPtr, /* Filled in with argument "moveto" option, if + * any. */ + int *intPtr) /* Filled in with number of pages or lines to + * scroll, if any. */ { - int c; - size_t length; - char *arg2, *arg4; + int length; + const char *arg; + + arg = Tcl_GetStringFromObj(objv[2], &length); - arg2 = Tcl_GetString(objv[2]); - length = strlen(arg2); - c = arg2[0]; - if ((c == 'm') && (strncmp(arg2, "moveto", length) == 0)) { +#define ArgPfxEq(str) ((arg[0]==str[0])&&!strncmp(arg,str,(unsigned)length)) + + if (ArgPfxEq("moveto")) { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "moveto fraction"); return TK_SCROLL_ERROR; @@ -730,8 +722,7 @@ Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr) return TK_SCROLL_ERROR; } return TK_SCROLL_MOVETO; - } else if ((c == 's') - && (strncmp(arg2, "scroll", length) == 0)) { + } else if (ArgPfxEq("scroll")) { if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages"); return TK_SCROLL_ERROR; @@ -739,22 +730,20 @@ Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr) if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) { return TK_SCROLL_ERROR; } - arg4 = Tcl_GetString(objv[4]); - length = (strlen(arg4)); - c = arg4[0]; - if ((c == 'p') && (strncmp(arg4, "pages", length) == 0)) { + + arg = Tcl_GetStringFromObj(objv[4], &length); + if (ArgPfxEq("pages")) { return TK_SCROLL_PAGES; - } else if ((c == 'u') - && (strncmp(arg4, "units", length) == 0)) { + } else if (ArgPfxEq("units")) { return TK_SCROLL_UNITS; - } else { - Tcl_AppendResult(interp, "bad argument \"", arg4, - "\": must be units or pages", (char *) NULL); - return TK_SCROLL_ERROR; } + + Tcl_AppendResult(interp, "bad argument \"", arg, + "\": must be units or pages", NULL); + return TK_SCROLL_ERROR; } - Tcl_AppendResult(interp, "unknown option \"", arg2, - "\": must be moveto or scroll", (char *) NULL); + Tcl_AppendResult(interp, "unknown option \"", arg, + "\": must be moveto or scroll", NULL); return TK_SCROLL_ERROR; } @@ -764,66 +753,80 @@ Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr) * TkComputeAnchor -- * * Determine where to place a rectangle so that it will be properly - * anchored with respect to the given window. Used by widgets - * to align a box of text inside a window. When anchoring with - * respect to one of the sides, the rectangle be placed inside of - * the internal border of the window. + * anchored with respect to the given window. Used by widgets to align a + * box of text inside a window. When anchoring with respect to one of the + * sides, the rectangle be placed inside of the internal border of the + * window. * * Results: - * *xPtr and *yPtr set to the upper-left corner of the rectangle - * anchored in the window. + * *xPtr and *yPtr set to the upper-left corner of the rectangle anchored + * in the window. * * Side effects: * None. * *--------------------------------------------------------------------------- */ + void -TkComputeAnchor(anchor, tkwin, padX, padY, innerWidth, innerHeight, xPtr, yPtr) - Tk_Anchor anchor; /* Desired anchor. */ - Tk_Window tkwin; /* Anchored with respect to this window. */ - int padX, padY; /* Use this extra padding inside window, in +TkComputeAnchor( + Tk_Anchor anchor, /* Desired anchor. */ + Tk_Window tkwin, /* Anchored with respect to this window. */ + int padX, int padY, /* Use this extra padding inside window, in * addition to the internal border. */ - int innerWidth, innerHeight;/* Size of rectangle to anchor in window. */ - int *xPtr, *yPtr; /* Returns upper-left corner of anchored + int innerWidth, int innerHeight, + /* Size of rectangle to anchor in window. */ + int *xPtr, int *yPtr) /* Returns upper-left corner of anchored * rectangle. */ { - switch (anchor) { - case TK_ANCHOR_NW: - case TK_ANCHOR_W: - case TK_ANCHOR_SW: - *xPtr = Tk_InternalBorderLeft(tkwin) + padX; - break; - - case TK_ANCHOR_N: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_S: - *xPtr = (Tk_Width(tkwin) - innerWidth) / 2; - break; - - default: - *xPtr = Tk_Width(tkwin) - (Tk_InternalBorderRight(tkwin) + padX) - - innerWidth; - break; - } + /* + * Handle the horizontal parts. + */ switch (anchor) { - case TK_ANCHOR_NW: - case TK_ANCHOR_N: - case TK_ANCHOR_NE: - *yPtr = Tk_InternalBorderTop(tkwin) + padY; - break; - - case TK_ANCHOR_W: - case TK_ANCHOR_CENTER: - case TK_ANCHOR_E: - *yPtr = (Tk_Height(tkwin) - innerHeight) / 2; - break; + case TK_ANCHOR_NW: + case TK_ANCHOR_W: + case TK_ANCHOR_SW: + *xPtr = Tk_InternalBorderLeft(tkwin) + padX; + break; + + case TK_ANCHOR_N: + case TK_ANCHOR_CENTER: + case TK_ANCHOR_S: + *xPtr = (Tk_Width(tkwin) - innerWidth - Tk_InternalBorderLeft(tkwin) - + Tk_InternalBorderRight(tkwin)) / 2 + + Tk_InternalBorderLeft(tkwin); + break; + + default: + *xPtr = Tk_Width(tkwin) - Tk_InternalBorderRight(tkwin) - padX + - innerWidth; + break; + } + + /* + * Handle the vertical parts. + */ - default: - *yPtr = Tk_Height(tkwin) - Tk_InternalBorderBottom(tkwin) - padY - - innerHeight; - break; + switch (anchor) { + case TK_ANCHOR_NW: + case TK_ANCHOR_N: + case TK_ANCHOR_NE: + *yPtr = Tk_InternalBorderTop(tkwin) + padY; + break; + + case TK_ANCHOR_W: + case TK_ANCHOR_CENTER: + case TK_ANCHOR_E: + *yPtr = (Tk_Height(tkwin) - innerHeight- Tk_InternalBorderTop(tkwin) - + Tk_InternalBorderBottom(tkwin)) / 2 + + Tk_InternalBorderTop(tkwin); + break; + + default: + *yPtr = Tk_Height(tkwin) - Tk_InternalBorderBottom(tkwin) - padY + - innerHeight; + break; } } @@ -835,10 +838,9 @@ TkComputeAnchor(anchor, tkwin, padX, padY, innerWidth, innerHeight, xPtr, yPtr) * Given a lookup table, map a number to a string in the table. * * Results: - * If numKey was equal to the numeric key of one of the elements - * in the table, returns the string key of that element. - * Returns NULL if numKey was not equal to any of the numeric keys - * in the table. + * If numKey was equal to the numeric key of one of the elements in the + * table, returns the string key of that element. Returns NULL if numKey + * was not equal to any of the numeric keys in the table. * * Side effects. * None. @@ -847,13 +849,13 @@ TkComputeAnchor(anchor, tkwin, padX, padY, innerWidth, innerHeight, xPtr, yPtr) */ char * -TkFindStateString(mapPtr, numKey) - CONST TkStateMap *mapPtr; /* The state table. */ - int numKey; /* The key to try to find in the table. */ +TkFindStateString( + const TkStateMap *mapPtr, /* The state table. */ + int numKey) /* The key to try to find in the table. */ { - for ( ; mapPtr->strKey != NULL; mapPtr++) { + for (; mapPtr->strKey!=NULL ; mapPtr++) { if (numKey == mapPtr->numKey) { - return mapPtr->strKey; + return (char *) mapPtr->strKey; } } return NULL; @@ -862,17 +864,17 @@ TkFindStateString(mapPtr, numKey) /* *--------------------------------------------------------------------------- * - * TkFindStateNum -- + * TkFindStateNum, TkFindStateNumObj -- * * Given a lookup table, map a string to a number in the table. * * Results: - * If strKey was equal to the string keys of one of the elements - * in the table, returns the numeric key of that element. - * Returns the numKey associated with the last element (the NULL - * string one) in the table if strKey was not equal to any of the - * string keys in the table. In that case, an error message is - * also left in the interp's result (if interp is not NULL). + * If strKey was equal to the string keys of one of the elements in the + * table, returns the numeric key of that element. Returns the numKey + * associated with the last element (the NULL string one) in the table if + * strKey was not equal to any of the string keys in the table. In that + * case, an error message is also left in the interp's result (if interp + * is not NULL). * * Side effects. * None. @@ -881,48 +883,66 @@ TkFindStateString(mapPtr, numKey) */ int -TkFindStateNum(interp, option, mapPtr, strKey) - Tcl_Interp *interp; /* Interp for error reporting. */ - CONST char *option; /* String to use when constructing error. */ - CONST TkStateMap *mapPtr; /* Lookup table. */ - CONST char *strKey; /* String to try to find in lookup table. */ +TkFindStateNum( + Tcl_Interp *interp, /* Interp for error reporting. */ + const char *option, /* String to use when constructing error. */ + const TkStateMap *mapPtr, /* Lookup table. */ + const char *strKey) /* String to try to find in lookup table. */ { - CONST TkStateMap *mPtr; + const TkStateMap *mPtr; + + /* + * See if the value is in the state map. + */ for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) { if (strcmp(strKey, mPtr->strKey) == 0) { return mPtr->numKey; } } + + /* + * Not there. Generate an error message (if we can) and return the + * default. + */ + if (interp != NULL) { mPtr = mapPtr; Tcl_AppendResult(interp, "bad ", option, " value \"", strKey, - "\": must be ", mPtr->strKey, (char *) NULL); + "\": must be ", mPtr->strKey, NULL); for (mPtr++; mPtr->strKey != NULL; mPtr++) { - Tcl_AppendResult(interp, - ((mPtr[1].strKey != NULL) ? ", " : ", or "), - mPtr->strKey, (char *) NULL); + Tcl_AppendResult(interp, + ((mPtr[1].strKey != NULL) ? ", " : ", or "), + mPtr->strKey, NULL); } } return mPtr->numKey; } int -TkFindStateNumObj(interp, optionPtr, mapPtr, keyPtr) - Tcl_Interp *interp; /* Interp for error reporting. */ - Tcl_Obj *optionPtr; /* String to use when constructing error. */ - CONST TkStateMap *mapPtr; /* Lookup table. */ - Tcl_Obj *keyPtr; /* String key to find in lookup table. */ +TkFindStateNumObj( + Tcl_Interp *interp, /* Interp for error reporting. */ + Tcl_Obj *optionPtr, /* String to use when constructing error. */ + const TkStateMap *mapPtr, /* Lookup table. */ + Tcl_Obj *keyPtr) /* String key to find in lookup table. */ { - CONST TkStateMap *mPtr; - CONST char *key; - CONST Tcl_ObjType *typePtr; + const TkStateMap *mPtr; + const char *key; + const Tcl_ObjType *typePtr; + + /* + * See if the value is in the object cache. + */ if ((keyPtr->typePtr == &tkStateKeyObjType) - && (keyPtr->internalRep.twoPtrValue.ptr1 == (VOID *) mapPtr)) { - return (int) keyPtr->internalRep.twoPtrValue.ptr2; + && (keyPtr->internalRep.twoPtrValue.ptr1 == mapPtr)) { + return PTR2INT(keyPtr->internalRep.twoPtrValue.ptr2); } + /* + * Not there. Look in the state map. + */ + key = Tcl_GetStringFromObj(keyPtr, NULL); for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) { if (strcmp(key, mPtr->strKey) == 0) { @@ -930,168 +950,35 @@ TkFindStateNumObj(interp, optionPtr, mapPtr, keyPtr) if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { (*typePtr->freeIntRepProc)(keyPtr); } - keyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) mapPtr; - keyPtr->internalRep.twoPtrValue.ptr2 = (VOID *) mPtr->numKey; - keyPtr->typePtr = &tkStateKeyObjType; + keyPtr->internalRep.twoPtrValue.ptr1 = (void *) mapPtr; + keyPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(mPtr->numKey); + keyPtr->typePtr = &tkStateKeyObjType; return mPtr->numKey; } } + + /* + * Not there either. Generate an error message (if we can) and return the + * default. + */ + if (interp != NULL) { mPtr = mapPtr; - Tcl_AppendResult(interp, "bad ", - Tcl_GetStringFromObj(optionPtr, NULL), " value \"", key, - "\": must be ", mPtr->strKey, (char *) NULL); + Tcl_AppendResult(interp, "bad ", Tcl_GetString(optionPtr), + " value \"", key, "\": must be ", mPtr->strKey, NULL); for (mPtr++; mPtr->strKey != NULL; mPtr++) { - Tcl_AppendResult(interp, - ((mPtr[1].strKey != NULL) ? ", " : ", or "), - mPtr->strKey, (char *) NULL); + Tcl_AppendResult(interp, + ((mPtr[1].strKey != NULL) ? ", " : ", or "), + mPtr->strKey, NULL); } } return mPtr->numKey; } - -/* - * For each exit handler created with a call to TkCreateExitHandler - * there is a structure of the following type: - */ - -typedef struct ExitHandler { - Tcl_ExitProc *proc; /* Procedure to call when process exits. */ - ClientData clientData; /* One word of information to pass to proc. */ - struct ExitHandler *nextPtr;/* Next in list of all exit handlers for - * this application, or NULL for end of list. */ -} ExitHandler; - -/* - * There is both per-process and per-thread exit handlers. - * The first list is controlled by a mutex. The other is in - * thread local storage. - */ - -static ExitHandler *firstExitPtr = NULL; - /* First in list of all exit handlers for - * application. */ -TCL_DECLARE_MUTEX(exitMutex) - -/* - *--------------------------------------------------------------------------- - * - * TkCreateExitHandler -- - * - * Same as Tcl_CreateExitHandler, but private to Tk. - * - * Results: - * None. - * - * Side effects. - * Sets a handler with Tcl_CreateExitHandler if this is the first call. - * - *--------------------------------------------------------------------------- - */ - -void -TkCreateExitHandler (proc, clientData) - Tcl_ExitProc *proc; /* Procedure to invoke. */ - ClientData clientData; /* Arbitrary value to pass to proc. */ -{ - ExitHandler *exitPtr; - - exitPtr = (ExitHandler *) ckalloc(sizeof(ExitHandler)); - exitPtr->proc = proc; - exitPtr->clientData = clientData; - Tcl_MutexLock(&exitMutex); - if (firstExitPtr == NULL) { - Tcl_CreateExitHandler(TkFinalize, NULL); - } - exitPtr->nextPtr = firstExitPtr; - firstExitPtr = exitPtr; - Tcl_MutexUnlock(&exitMutex); -} - -/* - *--------------------------------------------------------------------------- - * - * TkDeleteExitHandler -- - * - * Same as Tcl_DeleteExitHandler, but private to Tk. - * - * Results: - * None. - * - * Side effects. - * None. - * - *--------------------------------------------------------------------------- - */ - -void -TkDeleteExitHandler (proc, clientData) - Tcl_ExitProc *proc; /* Procedure that was previously registered. */ - ClientData clientData; /* Arbitrary value to pass to proc. */ -{ - ExitHandler *exitPtr, *prevPtr; - - Tcl_MutexLock(&exitMutex); - for (prevPtr = NULL, exitPtr = firstExitPtr; exitPtr != NULL; - prevPtr = exitPtr, exitPtr = exitPtr->nextPtr) { - if ((exitPtr->proc == proc) - && (exitPtr->clientData == clientData)) { - if (prevPtr == NULL) { - firstExitPtr = exitPtr->nextPtr; - } else { - prevPtr->nextPtr = exitPtr->nextPtr; - } - ckfree((char *) exitPtr); - break; - } - } - Tcl_MutexUnlock(&exitMutex); - return; -} - + /* - *--------------------------------------------------------------------------- - * - * TkFinalize -- - * - * Runs our private exit handlers and removes itself from Tcl. This is - * benificial should we want to protect from dangling pointers should - * the Tk shared library be unloaded prior to Tcl which can happen on - * windows should the process be forcefully exiting from an exception - * handler. - * - * Results: - * None. - * - * Side effects. - * None. - * - *--------------------------------------------------------------------------- + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: */ - -void -TkFinalize (clientData) - ClientData clientData; /* Arbitrary value to pass to proc. */ -{ - ExitHandler *exitPtr; - - Tcl_DeleteExitHandler(TkFinalize, NULL); - - Tcl_MutexLock(&exitMutex); - for (exitPtr = firstExitPtr; exitPtr != NULL; exitPtr = firstExitPtr) { - /* - * Be careful to remove the handler from the list before - * invoking its callback. This protects us against - * double-freeing if the callback should call - * Tcl_DeleteExitHandler on itself. - */ - - firstExitPtr = exitPtr->nextPtr; - Tcl_MutexUnlock(&exitMutex); - (*exitPtr->proc)(exitPtr->clientData); - ckfree((char *) exitPtr); - Tcl_MutexLock(&exitMutex); - } - firstExitPtr = NULL; - Tcl_MutexUnlock(&exitMutex); -} diff --git a/generic/tkVisual.c b/generic/tkVisual.c index 41d2060..ec8be11 100644 --- a/generic/tkVisual.c +++ b/generic/tkVisual.c @@ -1,29 +1,28 @@ -/* +/* * tkVisual.c -- * - * This file contains library procedures for allocating and - * freeing visuals and colormaps. This code is based on a - * prototype implementation by Paul Mackerras. + * This file contains library procedures for allocating and freeing + * visuals and colormaps. This code is based on a prototype + * implementation by Paul Mackerras. * * Copyright (c) 1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" -#include "tkPort.h" /* - * The table below maps from symbolic names for visual classes - * to the associated X class symbols. + * The table below maps from symbolic names for visual classes to the + * associated X class symbols. */ typedef struct VisualDictionary { char *name; /* Textual name of class. */ - int minLength; /* Minimum # characters that must be - * specified for an unambiguous match. */ + int minLength; /* Minimum # characters that must be specified + * for an unambiguous match. */ int class; /* X symbol for class. */ } VisualDictionary; static VisualDictionary visualNames[] = { @@ -46,17 +45,16 @@ static VisualDictionary visualNames[] = { struct TkColormap { Colormap colormap; /* X's identifier for the colormap. */ - Visual *visual; /* Visual for which colormap was - * allocated. */ + Visual *visual; /* Visual for which colormap was allocated. */ int refCount; /* How many uses of the colormap are still - * outstanding (calls to Tk_GetColormap - * minus calls to Tk_FreeColormap). */ - int shareable; /* 0 means this colormap was allocated by - * a call to Tk_GetColormap with "new", - * implying that the window wants it all - * for itself. 1 means that the colormap - * was allocated as a default for a particular - * visual, so it can be shared. */ + * outstanding (calls to Tk_GetColormap minus + * calls to Tk_FreeColormap). */ + int shareable; /* 0 means this colormap was allocated by a + * call to Tk_GetColormap with "new", implying + * that the window wants it all for itself. 1 + * means that the colormap was allocated as a + * default for a particular visual, so it can + * be shared. */ struct TkColormap *nextPtr; /* Next in list of colormaps for this display, * or NULL for end of list. */ }; @@ -66,17 +64,17 @@ struct TkColormap { * * Tk_GetVisual -- * - * Given a string identifying a particular kind of visual, this - * procedure returns a visual and depth that matches the specification. + * Given a string identifying a particular kind of visual, this procedure + * returns a visual and depth that matches the specification. * * Results: - * The return value is normally a pointer to a visual. If an - * error occurred in looking up the visual, NULL is returned and - * an error message is left in the interp's result. The depth of the - * visual is returned to *depthPtr under normal returns. If - * colormapPtr is non-NULL, then this procedure also finds a - * suitable colormap for use with the visual in tkwin, and it - * returns that colormap in *colormapPtr unless an error occurs. + * The return value is normally a pointer to a visual. If an error + * occurred in looking up the visual, NULL is returned and an error + * message is left in the interp's result. The depth of the visual is + * returned to *depthPtr under normal returns. If colormapPtr is + * non-NULL, then this procedure also finds a suitable colormap for use + * with the visual in tkwin, and it returns that colormap in *colormapPtr + * unless an error occurs. * * Side effects: * A new colormap may be allocated. @@ -85,42 +83,40 @@ struct TkColormap { */ Visual * -Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) - Tcl_Interp *interp; /* Interpreter to use for error - * reporting. */ - Tk_Window tkwin; /* Window in which visual will be - * used. */ - CONST char *string; /* String describing visual. See - * manual entry for details. */ - int *depthPtr; /* The depth of the returned visual - * is stored here. */ - Colormap *colormapPtr; /* If non-NULL, then a suitable - * colormap for visual is placed here. - * This colormap must eventually be - * freed by calling Tk_FreeColormap. */ +Tk_GetVisual( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which visual will be used. */ + CONST char *string, /* String describing visual. See manual entry + * for details. */ + int *depthPtr, /* The depth of the returned visual is stored + * here. */ + Colormap *colormapPtr) /* If non-NULL, then a suitable colormap for + * visual is placed here. This colormap must + * eventually be freed by calling + * Tk_FreeColormap. */ { Tk_Window tkwin2; XVisualInfo template, *visInfoList, *bestPtr; long mask; Visual *visual; - int length, c, numVisuals, prio, bestPrio, i; + ptrdiff_t length; + int c, numVisuals, prio, bestPrio, i; CONST char *p; VisualDictionary *dictPtr; TkColormap *cmapPtr; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; /* - * Parse string and set up a template for use in searching for - * an appropriate visual. + * Parse string and set up a template for use in searching for an + * appropriate visual. */ c = string[0]; if (c == '.') { /* - * The string must be a window name. If the window is on the - * same screen as tkwin, then just use its visual. Otherwise - * use the information about the visual as a template for the - * search. + * The string must be a window name. If the window is on the same + * screen as tkwin, then just use its visual. Otherwise use the + * information about the visual as a template for the search. */ tkwin2 = Tk_NameToWindow(interp, string, tkwin); @@ -132,8 +128,8 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) *depthPtr = Tk_Depth(tkwin2); if (colormapPtr != NULL) { /* - * Use the colormap from the other window too (but be sure - * to increment its reference count if it's one of the ones + * Use the colormap from the other window too (but be sure to + * increment its reference count if it's one of the ones * allocated here). */ @@ -173,21 +169,21 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) int visualId; /* - * This is a visual ID. - */ + * This is a visual ID. + */ if (Tcl_GetInt(interp, string, &visualId) == TCL_ERROR) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad X identifier for visual: ", - string, "\"", (char *) NULL); + Tcl_AppendResult(interp, "bad X identifier for visual: \"", + string, "\"", NULL); return NULL; } template.visualid = visualId; mask = VisualIDMask; } else { /* - * Parse the string into a class name (or "best") optionally - * followed by whitespace and a depth. + * Parse the string into a class name (or "best") optionally followed + * by whitespace and a depth. */ for (p = string; *p != 0; p++) { @@ -207,11 +203,11 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) } if (template.class == -1) { Tcl_AppendResult(interp, "unknown or ambiguous visual name \"", - string, "\": class must be ", (char *) NULL); + string, "\": class must be ", NULL); for (dictPtr = visualNames; dictPtr->name != NULL; dictPtr++) { - Tcl_AppendResult(interp, dictPtr->name, ", ", (char *) NULL); + Tcl_AppendResult(interp, dictPtr->name, ", ", NULL); } - Tcl_AppendResult(interp, "or default", (char *) NULL); + Tcl_AppendResult(interp, "or default", NULL); return NULL; } while (isspace(UCHAR(*p))) { @@ -232,8 +228,8 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) } /* - * Find all visuals that match the template we've just created, - * and return an error if there are none that match. + * Find all visuals that match the template we've just created, and return + * an error if there are none that match. */ template.screen = Tk_ScreenNumber(tkwin); @@ -247,31 +243,37 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) } /* - * Search through the visuals that were returned to find the best - * one. The choice is based on the following criteria, in decreasing - * order of importance: + * Search through the visuals that were returned to find the best one. + * The choice is based on the following criteria, in decreasing order of + * importance: * - * 1. Depth: choose a visual with exactly the desired depth, - * else one with more bits than requested but as few bits - * as possible, else one with fewer bits but as many as - * possible. - * 2. Class: some visual classes are more desirable than others; - * pick the visual with the most desirable class. - * 3. Default: the default visual for the screen gets preference - * over other visuals, all else being equal. + * 1. Depth: choose a visual with exactly the desired depth, else one with + * more bits than requested but as few bits as possible, else one with + * fewer bits but as many as possible. + * 2. Class: some visual classes are more desirable than others; pick the + * visual with the most desirable class. + * 3. Default: the default visual for the screen gets preference over + * other visuals, all else being equal. */ bestPrio = 0; bestPtr = NULL; for (i = 0; i < numVisuals; i++) { switch (visInfoList[i].class) { - case DirectColor: prio = 5; break; - case GrayScale: prio = 1; break; - case PseudoColor: prio = 7; break; - case StaticColor: prio = 3; break; - case StaticGray: prio = 1; break; - case TrueColor: prio = 5; break; - default: prio = 0; break; + case DirectColor: + prio = 5; break; + case GrayScale: + prio = 1; break; + case PseudoColor: + prio = 7; break; + case StaticColor: + prio = 3; break; + case StaticGray: + prio = 1; break; + case TrueColor: + prio = 5; break; + default: + prio = 0; break; } if (visInfoList[i].visual == DefaultVisualOfScreen(Tk_Screen(tkwin))) { @@ -295,7 +297,7 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) } continue; - newBest: + newBest: bestPtr = &visInfoList[i]; bestPrio = prio; } @@ -304,11 +306,10 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) XFree((char *) visInfoList); /* - * If we need to find a colormap for this visual, do it now. - * If the visual is the default visual for the screen, then - * use the default colormap. Otherwise search for an existing - * colormap that's shareable. If all else fails, create a new - * colormap. + * If we need to find a colormap for this visual, do it now. If the visual + * is the default visual for the screen, then use the default colormap. + * Otherwise search for an existing colormap that's shareable. If all else + * fails, create a new colormap. */ if (colormapPtr != NULL) { @@ -336,7 +337,7 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) } } - done: + done: return visual; } @@ -345,31 +346,28 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr) * * Tk_GetColormap -- * - * Given a string identifying a colormap, this procedure finds - * an appropriate colormap. + * Given a string identifying a colormap, this procedure finds an + * appropriate colormap. * * Results: * The return value is normally the X resource identifier for the - * colormap. If an error occurs, None is returned and an error - * message is placed in the interp's result. + * colormap. If an error occurs, None is returned and an error message is + * placed in the interp's result. * * Side effects: - * A reference count is incremented for the colormap, so - * Tk_FreeColormap must eventually be called exactly once for - * each call to Tk_GetColormap. + * A reference count is incremented for the colormap, so Tk_FreeColormap + * must eventually be called exactly once for each call to + * Tk_GetColormap. * *---------------------------------------------------------------------- */ Colormap -Tk_GetColormap(interp, tkwin, string) - Tcl_Interp *interp; /* Interpreter to use for error - * reporting. */ - Tk_Window tkwin; /* Window where colormap will be - * used. */ - CONST char *string; /* String that identifies colormap: - * either "new" or the name of - * another window. */ +Tk_GetColormap( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window where colormap will be used. */ + CONST char *string) /* String that identifies colormap: either + * "new" or the name of another window. */ { Colormap colormap; TkColormap *cmapPtr; @@ -394,9 +392,9 @@ Tk_GetColormap(interp, tkwin, string) } /* - * Use a colormap from an existing window. It must have the same - * visual as tkwin (which means, among other things, that the - * other window must be on the same screen). + * Use a colormap from an existing window. It must have the same visual as + * tkwin (which means, among other things, that the other window must be + * on the same screen). */ other = Tk_NameToWindow(interp, string, tkwin); @@ -405,12 +403,12 @@ Tk_GetColormap(interp, tkwin, string) } if (Tk_Screen(other) != Tk_Screen(tkwin)) { Tcl_AppendResult(interp, "can't use colormap for ", string, - ": not on same screen", (char *) NULL); + ": not on same screen", NULL); return None; } if (Tk_Visual(other) != Tk_Visual(tkwin)) { Tcl_AppendResult(interp, "can't use colormap for ", string, - ": incompatible visuals", (char *) NULL); + ": incompatible visuals", NULL); return None; } colormap = Tk_Colormap(other); @@ -434,41 +432,40 @@ Tk_GetColormap(interp, tkwin, string) * * Tk_FreeColormap -- * - * This procedure is called to release a colormap that was - * previously allocated by Tk_GetColormap. + * This procedure is called to release a colormap that was previously + * allocated by Tk_GetColormap. * * Results: * None. * * Side effects: - * The colormap's reference count is decremented. If this was the - * last reference to the colormap, then the colormap is freed. + * The colormap's reference count is decremented. If this was the last + * reference to the colormap, then the colormap is freed. * *---------------------------------------------------------------------- */ void -Tk_FreeColormap(display, colormap) - Display *display; /* Display for which colormap was - * allocated. */ - Colormap colormap; /* Colormap that is no longer needed. - * Must have been returned by previous - * call to Tk_GetColormap, or - * preserved by a previous call to - * Tk_PreserveColormap. */ +Tk_FreeColormap( + Display *display, /* Display for which colormap was + * allocated. */ + Colormap colormap) /* Colormap that is no longer needed. Must + * have been returned by previous call to + * Tk_GetColormap, or preserved by a previous + * call to Tk_PreserveColormap. */ { TkDisplay *dispPtr; TkColormap *cmapPtr, *prevPtr; /* - * Find Tk's information about the display, then see if this - * colormap is a non-default one (if it's a default one, there - * won't be an entry for it in the display's list). + * Find Tk's information about the display, then see if this colormap is a + * non-default one (if it's a default one, there won't be an entry for it + * in the display's list). */ dispPtr = TkGetDisplay(display); if (dispPtr == NULL) { - panic("unknown display passed to Tk_FreeColormap"); + Tcl_Panic("unknown display passed to Tk_FreeColormap"); } for (prevPtr = NULL, cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; prevPtr = cmapPtr, cmapPtr = cmapPtr->nextPtr) { @@ -485,7 +482,7 @@ Tk_FreeColormap(display, colormap) } return; } - } + } } /* @@ -493,41 +490,40 @@ Tk_FreeColormap(display, colormap) * * Tk_PreserveColormap -- * - * This procedure is called to indicate to Tk that the specified - * colormap is being referenced from another location and should - * not be freed until all extra references are eliminated. The - * colormap must have been returned by Tk_GetColormap. + * This procedure is called to indicate to Tk that the specified colormap + * is being referenced from another location and should not be freed + * until all extra references are eliminated. The colormap must have been + * returned by Tk_GetColormap. * * Results: * None. * * Side effects: - * The colormap's reference count is incremented, so - * Tk_FreeColormap must eventually be called exactly once for - * each call to Tk_PreserveColormap. + * The colormap's reference count is incremented, so Tk_FreeColormap must + * eventually be called exactly once for each call to + * Tk_PreserveColormap. * *---------------------------------------------------------------------- */ void -Tk_PreserveColormap(display, colormap) - Display *display; /* Display for which colormap was - * allocated. */ - Colormap colormap; /* Colormap that should be - * preserved. */ +Tk_PreserveColormap( + Display *display, /* Display for which colormap was + * allocated. */ + Colormap colormap) /* Colormap that should be preserved. */ { TkDisplay *dispPtr; TkColormap *cmapPtr; /* - * Find Tk's information about the display, then see if this - * colormap is a non-default one (if it's a default one, there - * won't be an entry for it in the display's list). + * Find Tk's information about the display, then see if this colormap is a + * non-default one (if it's a default one, there won't be an entry for it + * in the display's list). */ dispPtr = TkGetDisplay(display); if (dispPtr == NULL) { - panic("unknown display passed to Tk_PreserveColormap"); + Tcl_Panic("unknown display passed to Tk_PreserveColormap"); } for (cmapPtr = dispPtr->cmapPtr; cmapPtr != NULL; cmapPtr = cmapPtr->nextPtr) { @@ -535,5 +531,13 @@ Tk_PreserveColormap(display, colormap) cmapPtr->refCount += 1; return; } - } + } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 422b27e..1ffdd56 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -1,30 +1,26 @@ -/* +/* * tkWindow.c -- * - * This file provides basic window-manipulation procedures, - * which are equivalent to procedures in Xlib (and even - * invoke them) but also maintain the local Tk_Window - * structure. + * This file provides basic window-manipulation functions, which are + * equivalent to functions in Xlib (and even invoke them) but also + * maintain the local Tk_Window structure. * * Copyright (c) 1989-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include "tkPort.h" #include "tkInt.h" -#if !( defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)) +#if !( defined(__WIN32__) || defined(MAC_OSX_TK)) #include "tkUnixInt.h" #endif -#include "tclInt.h" /* for Tcl_CreateNamespace() */ - -/* - * Type used to keep track of Window objects that were - * only partically deallocated by Tk_DestroyWindow. +/* + * Type used to keep track of Window objects that were only partially + * deallocated by Tk_DestroyWindow. */ #define HD_CLEANUP 1 @@ -39,34 +35,32 @@ typedef struct TkHalfdeadWindow { struct TkHalfdeadWindow *nextPtr; } TkHalfdeadWindow; - typedef struct ThreadSpecificData { - int numMainWindows; /* Count of numver of main windows currently - * open in this thread. */ + int numMainWindows; /* Count of numver of main windows currently + * open in this thread. */ TkMainInfo *mainWindowList; - /* First in list of all main windows managed - * by this thread. */ + /* First in list of all main windows managed + * by this thread. */ TkHalfdeadWindow *halfdeadWindowList; - /* First in list of partially deallocated - * windows. */ - TkDisplay *displayList; - /* List of all displays currently in use by - * the current thread. */ - int initialized; /* 0 means the structures above need - * initializing. */ + /* First in list of partially deallocated + * windows. */ + TkDisplay *displayList; /* List of all displays currently in use by + * the current thread. */ + int initialized; /* 0 means the structures above need + * initializing. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -/* - * The Mutex below is used to lock access to the Tk_Uid structs above. +/* + * 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. + * 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. */ static XWindowChanges defChanges = { @@ -95,21 +89,20 @@ static XSetWindowAttributes defAtts= { }; /* - * The following structure defines all of the commands supported by - * Tk, and the C procedures that execute them. + * The following structure defines all of the commands supported by Tk, and + * the C functions that execute them. */ typedef struct { char *name; /* Name of command. */ - Tcl_CmdProc *cmdProc; /* Command's string-based procedure. */ - Tcl_ObjCmdProc *objProc; /* Command's object-based procedure. */ - int isSafe; /* If !0, this command will be exposed in - * a safe interpreter. Otherwise it will be - * hidden in a safe interpreter. */ - int passMainWindow; /* 0 means provide NULL clientData to - * command procedure; 1 means pass main - * window as clientData to command - * procedure. */ + Tcl_CmdProc *cmdProc; /* Command's string-based function. */ + Tcl_ObjCmdProc *objProc; /* Command's object-based function. */ + int isSafe; /* If !0, this command will be exposed in a + * safe interpreter. Otherwise it will be + * hidden in a safe interpreter. */ + int passMainWindow; /* 0 means provide NULL clientData to command + * function; 1 means pass main window as + * clientData to command function. */ } TkCmd; static TkCmd commands[] = { @@ -136,55 +129,81 @@ static TkCmd commands[] = { {"selection", NULL, Tk_SelectionObjCmd, 0, 1}, {"tk", NULL, Tk_TkObjCmd, 1, 1}, {"tkwait", NULL, Tk_TkwaitObjCmd, 1, 1}, -#if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK) - {"tk_chooseColor", NULL, Tk_ChooseColorObjCmd, 0, 1}, - {"tk_chooseDirectory", NULL, Tk_ChooseDirectoryObjCmd, 0, 1}, - {"tk_getOpenFile", NULL, Tk_GetOpenFileObjCmd, 0, 1}, - {"tk_getSaveFile", NULL, Tk_GetSaveFileObjCmd, 0, 1}, -#endif -#if defined(__WIN32__) || defined(MAC_OSX_TK) - {"tk_messageBox", NULL, Tk_MessageBoxObjCmd, 0, 1}, -#endif {"update", NULL, Tk_UpdateObjCmd, 1, 1}, {"winfo", NULL, Tk_WinfoObjCmd, 1, 1}, {"wm", NULL, Tk_WmObjCmd, 0, 1}, /* - * Widget class commands. + * Default widget class commands. */ {"button", NULL, Tk_ButtonObjCmd, 1, 0}, {"canvas", NULL, Tk_CanvasObjCmd, 1, 1}, {"checkbutton", NULL, Tk_CheckbuttonObjCmd, 1, 0}, - {"entry", NULL, Tk_EntryObjCmd, 1, 0}, + {"entry", NULL, Tk_EntryObjCmd, 1, 0}, {"frame", NULL, Tk_FrameObjCmd, 1, 0}, {"label", NULL, Tk_LabelObjCmd, 1, 0}, {"labelframe", NULL, Tk_LabelframeObjCmd, 1, 0}, {"listbox", NULL, Tk_ListboxObjCmd, 1, 0}, - {"menubutton", NULL, Tk_MenubuttonObjCmd, 1, 0}, + {"menubutton", NULL, Tk_MenubuttonObjCmd, 1, 0}, {"message", NULL, Tk_MessageObjCmd, 1, 0}, {"panedwindow", NULL, Tk_PanedWindowObjCmd, 1, 0}, {"radiobutton", NULL, Tk_RadiobuttonObjCmd, 1, 0}, - {"scale", NULL, Tk_ScaleObjCmd, 1, 0}, + {"scale", NULL, Tk_ScaleObjCmd, 1, 0}, {"scrollbar", Tk_ScrollbarCmd, NULL, 1, 1}, - {"spinbox", NULL, Tk_SpinboxObjCmd, 1, 0}, - {"text", Tk_TextCmd, NULL, 1, 1}, + {"spinbox", NULL, Tk_SpinboxObjCmd, 1, 0}, + {"text", NULL, Tk_TextObjCmd, 1, 1}, {"toplevel", NULL, Tk_ToplevelObjCmd, 0, 0}, /* + * Classic widget class commands. + */ + + {"::tk::button", NULL, Tk_ButtonObjCmd, 1, 0}, + {"::tk::canvas", NULL, Tk_CanvasObjCmd, 1, 1}, + {"::tk::checkbutton",NULL, Tk_CheckbuttonObjCmd, 1, 0}, + {"::tk::entry", NULL, Tk_EntryObjCmd, 1, 0}, + {"::tk::frame", NULL, Tk_FrameObjCmd, 1, 0}, + {"::tk::label", NULL, Tk_LabelObjCmd, 1, 0}, + {"::tk::labelframe",NULL, Tk_LabelframeObjCmd, 1, 0}, + {"::tk::listbox", NULL, Tk_ListboxObjCmd, 1, 0}, + {"::tk::menubutton",NULL, Tk_MenubuttonObjCmd, 1, 0}, + {"::tk::message", NULL, Tk_MessageObjCmd, 1, 0}, + {"::tk::panedwindow",NULL, Tk_PanedWindowObjCmd, 1, 0}, + {"::tk::radiobutton",NULL, Tk_RadiobuttonObjCmd, 1, 0}, + {"::tk::scale", NULL, Tk_ScaleObjCmd, 1, 0}, + {"::tk::scrollbar", Tk_ScrollbarCmd, NULL, 1, 1}, + {"::tk::spinbox", NULL, Tk_SpinboxObjCmd, 1, 0}, + {"::tk::text", NULL, Tk_TextObjCmd, 1, 1}, + {"::tk::toplevel", NULL, Tk_ToplevelObjCmd, 0, 0}, + + /* + * Standard dialog support. Note that the Unix/X11 platform implements + * these commands differently (via the script library). + */ + +#if defined(__WIN32__) || defined(MAC_OSX_TK) + {"tk_chooseColor", NULL, Tk_ChooseColorObjCmd, 0, 1}, + {"tk_chooseDirectory", NULL, Tk_ChooseDirectoryObjCmd,0,1}, + {"tk_getOpenFile", NULL, Tk_GetOpenFileObjCmd, 0, 1}, + {"tk_getSaveFile", NULL, Tk_GetSaveFileObjCmd, 0, 1}, + {"tk_messageBox", NULL, Tk_MessageBoxObjCmd, 0, 1}, +#endif + + /* * Misc. */ -#if defined(MAC_TCL) || defined(MAC_OSX_TK) +#if defined(MAC_OSX_TK) {"::tk::unsupported::MacWindowStyle", - NULL, TkUnsupported1ObjCmd, 1, 1}, + NULL, TkUnsupported1ObjCmd, 1, 1}, #endif - {(char *) NULL, (int (*) _ANSI_ARGS_((ClientData, Tcl_Interp *, int, CONST char **))) NULL, NULL, 0} + {NULL, NULL, NULL, 0, 0} }; /* - * The variables and table below are used to parse arguments from - * the "argv" variable in Tk_Init. + * The variables and table below are used to parse arguments from the "argv" + * variable in Tk_Init. */ static int synchronize = 0; @@ -197,62 +216,62 @@ static char *visual = NULL; static int rest = 0; static Tk_ArgvInfo argTable[] = { - {"-colormap", TK_ARGV_STRING, (char *) NULL, (char *) &colormap, + {"-colormap", TK_ARGV_STRING, NULL, (char *) &colormap, "Colormap for main window"}, - {"-display", TK_ARGV_STRING, (char *) NULL, (char *) &display, + {"-display", TK_ARGV_STRING, NULL, (char *) &display, "Display to use"}, - {"-geometry", TK_ARGV_STRING, (char *) NULL, (char *) &geometry, + {"-geometry", TK_ARGV_STRING, NULL, (char *) &geometry, "Initial geometry for window"}, - {"-name", TK_ARGV_STRING, (char *) NULL, (char *) &name, + {"-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, (char *) NULL, (char *) &visual, + {"-visual", TK_ARGV_STRING, NULL, (char *) &visual, "Visual for main window"}, - {"-use", TK_ARGV_STRING, (char *) NULL, (char *) &use, + {"-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"}, - {(char *) NULL, TK_ARGV_END, (char *) NULL, (char *) NULL, - (char *) NULL} + {NULL, TK_ARGV_END, NULL, NULL, NULL} }; /* - * Forward declarations to procedures defined later in this file: + * Forward declarations to functions defined later in this file: */ -static Tk_Window CreateTopLevelWindow _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window parent, CONST char *name, - CONST char *screenName, unsigned int flags)); -static void DeleteWindowsExitProc _ANSI_ARGS_(( - ClientData clientData)); -static TkDisplay * GetScreen _ANSI_ARGS_((Tcl_Interp *interp, - CONST char *screenName, int *screenPtr)); -static int Initialize _ANSI_ARGS_((Tcl_Interp *interp)); -static int NameWindow _ANSI_ARGS_((Tcl_Interp *interp, - TkWindow *winPtr, TkWindow *parentPtr, - CONST char *name)); -static void UnlinkWindow _ANSI_ARGS_((TkWindow *winPtr)); +static Tk_Window CreateTopLevelWindow(Tcl_Interp *interp, + Tk_Window parent, CONST char *name, + CONST char *screenName, unsigned int flags); +static void DeleteWindowsExitProc(ClientData clientData); +static TkDisplay * GetScreen(Tcl_Interp *interp, CONST char *screenName, + int *screenPtr); +static int Initialize(Tcl_Interp *interp); +static int NameWindow(Tcl_Interp *interp, TkWindow *winPtr, + TkWindow *parentPtr, CONST char *name); +static void UnlinkWindow(TkWindow *winPtr); /* *---------------------------------------------------------------------- * * TkCloseDisplay -- - * Closing the display can lead to order of deletion problems. - * We defer it until exit handling for Mac/Win, but since Unix can - * use many displays, try and clean it up as best as possible. + * + * Closing the display can lead to order of deletion problems. We defer + * it until exit handling for Mac/Win, but since Unix can use many + * displays, try and clean it up as best as possible. * * Results: * None. * * Side effects: - * Resources associated with the display will be free. - * The display may not be referenced at all after this. + * Resources associated with the display will be free. The display may + * not be referenced at all after this. + * *---------------------------------------------------------------------- */ static void -TkCloseDisplay(TkDisplay *dispPtr) +TkCloseDisplay( + TkDisplay *dispPtr) { TkClipCleanup(dispPtr); @@ -269,8 +288,8 @@ TkCloseDisplay(TkDisplay *dispPtr) if (dispPtr->errorPtr != NULL) { TkErrorHandler *errorPtr; for (errorPtr = dispPtr->errorPtr; - errorPtr != NULL; - errorPtr = dispPtr->errorPtr) { + errorPtr != NULL; + errorPtr = dispPtr->errorPtr) { dispPtr->errorPtr = errorPtr->nextPtr; ckfree((char *) errorPtr); } @@ -281,8 +300,8 @@ TkCloseDisplay(TkDisplay *dispPtr) TkpCloseDisplay(dispPtr); /* - * Delete winTable after TkpCloseDisplay since special windows - * may need call Tk_DestroyWindow and it checks the winTable. + * Delete winTable after TkpCloseDisplay since special windows may need + * call Tk_DestroyWindow and it checks the winTable. */ Tcl_DeleteHashTable(&dispPtr->winTable); @@ -299,44 +318,42 @@ TkCloseDisplay(TkDisplay *dispPtr) * * CreateTopLevelWindow -- * - * Make a new window that will be at top-level (its parent will - * be the root window of a screen). + * Make a new window that will be at top-level (its parent will be the + * root window of a screen). * * Results: - * The return value is a token for the new window, or NULL if - * an error prevented the new window from being created. If - * NULL is returned, an error message will be left in - * the interp's result. + * The return value is a token for the new window, or NULL if an error + * prevented the new window from being created. If NULL is returned, an + * error message will be left in the interp's result. * * Side effects: - * A new window structure is allocated locally. An X - * window is NOT initially created, but will be created - * the first time the window is mapped. + * A new window structure is allocated locally. An X window is NOT + * initially created, but will be created the first time the window is + * mapped. * *---------------------------------------------------------------------- */ static Tk_Window -CreateTopLevelWindow(interp, parent, name, screenName, flags) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - Tk_Window parent; /* Token for logical parent of new window - * (used for naming, options, etc.). May - * be NULL. */ - CONST char *name; /* Name for new window; if parent is - * non-NULL, must be unique among parent's - * children. */ - CONST char *screenName; /* Name of screen on which to create - * window. NULL means use DISPLAY environment - * variable to determine. Empty string means - * use parent's screen, or DISPLAY if no +CreateTopLevelWindow( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window parent, /* Token for logical parent of new window + * (used for naming, options, etc.). May be + * NULL. */ + CONST char *name, /* Name for new window; if parent is non-NULL, + * must be unique among parent's children. */ + CONST char *screenName, /* Name of screen on which to create window. + * NULL means use DISPLAY environment variable + * to determine. Empty string means use + * parent's screen, or DISPLAY if no * parent. */ - unsigned int flags; /* Additional flags to set on the window. */ + unsigned int flags) /* Additional flags to set on the window. */ { register TkWindow *winPtr; register TkDisplay *dispPtr; int screenId; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!tsdPtr->initialized) { tsdPtr->initialized = 1; @@ -354,16 +371,6 @@ CreateTopLevelWindow(interp, parent, name, screenName, flags) Tk_CreatePhotoImageFormat(&tkImgFmtGIF); Tk_CreatePhotoImageFormat(&tkImgFmtPPM); - - /* - * Create exit handler to delete all windows when the application - * exits. This must be a thread exit handler, but there may be - * ordering issues with other exit handlers - * (i.e. OptionThreadExitProc). - */ - - Tcl_CreateThreadExitHandler(DeleteWindowsExitProc, - (ClientData) tsdPtr); } if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) { @@ -381,28 +388,29 @@ CreateTopLevelWindow(interp, parent, name, screenName, flags) /* * Set the flags specified in the call. */ + winPtr->flags |= flags; - + /* - * Force the window to use a border pixel instead of border pixmap. - * This is needed for the case where the window doesn't use the - * default visual. In this case, the default border is a pixmap - * inherited from the root window, which won't work because it will - * have the wrong visual. + * Force the window to use a border pixel instead of border pixmap. This + * is needed for the case where the window doesn't use the default visual. + * In this case, the default border is a pixmap inherited from the root + * window, which won't work because it will have the wrong visual. */ winPtr->dirtyAtts |= CWBorderPixel; /* - * (Need to set the TK_TOP_HIERARCHY flag immediately here; otherwise - * Tk_DestroyWindow will core dump if it is called before the flag - * has been set.) + * (Need to set the TK_TOP_HIERARCHY flag immediately here; otherwise + * Tk_DestroyWindow will core dump if it is called before the flag has + * been set.) */ - winPtr->flags |= TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED; + winPtr->flags |= + TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED; if (parent != NULL) { - if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) { + if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) { Tk_DestroyWindow((Tk_Window) winPtr); return (Tk_Window) NULL; } @@ -417,44 +425,40 @@ CreateTopLevelWindow(interp, parent, name, screenName, flags) * * GetScreen -- * - * Given a string name for a display-plus-screen, find the - * TkDisplay structure for the display and return the screen - * number too. + * Given a string name for a display-plus-screen, find the TkDisplay + * structure for the display and return the screen number too. * * Results: - * The return value is a pointer to information about the display, - * or NULL if the display couldn't be opened. In this case, an - * error message is left in the interp's result. The location at - * *screenPtr is overwritten with the screen number parsed from - * screenName. + * The return value is a pointer to information about the display, or + * NULL if the display couldn't be opened. In this case, an error message + * is left in the interp's result. The location at *screenPtr is + * overwritten with the screen number parsed from screenName. * * Side effects: - * A new connection is opened to the display if there is no - * connection already. A new TkDisplay data structure is also - * setup, if necessary. + * A new connection is opened to the display if there is no connection + * already. A new TkDisplay data structure is also setup, if necessary. * *---------------------------------------------------------------------- */ static TkDisplay * -GetScreen(interp, screenName, screenPtr) - Tcl_Interp *interp; /* Place to leave error message. */ - CONST char *screenName; /* Name for screen. NULL or empty means - * use DISPLAY envariable. */ - int *screenPtr; /* Where to store screen number. */ +GetScreen( + Tcl_Interp *interp, /* Place to leave error message. */ + CONST char *screenName, /* Name for screen. NULL or empty means use + * DISPLAY envariable. */ + int *screenPtr) /* Where to store screen number. */ { register TkDisplay *dispPtr; CONST char *p; int screenId; size_t length; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* - * Separate the screen number from the rest of the display - * name. ScreenName is assumed to have the syntax - * <display>.<screen> with the dot and the screen being - * optional. + * Separate the screen number from the rest of the display name. + * ScreenName is assumed to have the syntax <display>.<screen> with the + * dot and the screen being optional. */ screenName = TkGetDefaultScreenName(interp, screenName); @@ -462,7 +466,7 @@ GetScreen(interp, screenName, screenPtr) Tcl_SetResult(interp, "no display name and no $DISPLAY environment variable", TCL_STATIC); - return (TkDisplay *) NULL; + return NULL; } length = strlen(screenName); screenId = 0; @@ -472,26 +476,27 @@ GetScreen(interp, screenName, screenPtr) } if ((*p == '.') && (p[1] != '\0')) { length = p - screenName; - screenId = strtoul(p+1, (char **) NULL, 10); + screenId = strtoul(p+1, NULL, 10); } /* - * See if we already have a connection to this display. If not, - * then open a new connection. + * See if we already have a connection to this display. If not, then open + * a new connection. */ for (dispPtr = tsdPtr->displayList; ; dispPtr = dispPtr->nextPtr) { if (dispPtr == NULL) { /* - * The private function zeros out dispPtr when it is created, - * so we only need to initialize the non-zero items. + * The private function zeros out dispPtr when it is created, so + * we only need to initialize the non-zero items. */ + dispPtr = TkpOpenDisplay(screenName); if (dispPtr == NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't connect to display \"", - screenName, "\"", (char *) NULL); - return (TkDisplay *) NULL; + screenName, "\"", NULL); + return NULL; } dispPtr->nextPtr = tsdPtr->displayList; /* TkGetDisplayList(); */ tsdPtr->displayList = dispPtr; @@ -501,10 +506,12 @@ GetScreen(interp, screenName, screenPtr) dispPtr->cursorFont = None; dispPtr->warpWindow = None; dispPtr->multipleAtom = None; + /* * By default we do want to collapse motion events in * Tk_QueueWindowEvent. */ + dispPtr->flags |= TK_DISPLAY_COLLAPSE_MOTION_EVENTS; Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS); @@ -523,10 +530,10 @@ GetScreen(interp, screenName, screenPtr) } if (screenId >= ScreenCount(dispPtr->display)) { char buf[32 + TCL_INTEGER_SPACE]; - + sprintf(buf, "bad screen number \"%d\"", screenId); Tcl_SetResult(interp, buf, TCL_VOLATILE); - return (TkDisplay *) NULL; + return NULL; } *screenPtr = screenId; return dispPtr; @@ -537,26 +544,26 @@ GetScreen(interp, screenName, screenPtr) * * TkGetDisplay -- * - * Given an X display, TkGetDisplay returns the TkDisplay - * structure for the display. + * Given an X display, TkGetDisplay returns the TkDisplay structure for + * the display. * * Results: - * The return value is a pointer to information about the display, - * or NULL if the display did not have a TkDisplay structure. + * The return value is a pointer to information about the display, or + * NULL if the display did not have a TkDisplay structure. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ TkDisplay * -TkGetDisplay(display) - Display *display; /* X's display pointer */ +TkGetDisplay( + Display *display) /* X's display pointer */ { TkDisplay *dispPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (dispPtr = tsdPtr->displayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) { @@ -572,24 +579,25 @@ TkGetDisplay(display) * * TkGetDisplayList -- * - * This procedure returns a pointer to the thread-local - * list of TkDisplays corresponding to the open displays. + * This function returns a pointer to the thread-local list of TkDisplays + * corresponding to the open displays. * * Results: - * The return value is a pointer to the first TkDisplay - * structure in thread-local-storage. + * The return value is a pointer to the first TkDisplay structure in + * thread-local-storage. * * Side effects: - * None. + * None. * *-------------------------------------------------------------- */ + TkDisplay * -TkGetDisplayList() +TkGetDisplayList(void) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + return tsdPtr->displayList; } @@ -598,25 +606,25 @@ TkGetDisplayList() * * TkGetMainInfoList -- * - * This procedure returns a pointer to the list of structures - * containing information about all main windows for the - * current thread. + * This function returns a pointer to the list of structures containing + * information about all main windows for the current thread. * * Results: - * The return value is a pointer to the first TkMainInfo - * structure in thread local storage. + * The return value is a pointer to the first TkMainInfo structure in + * thread local storage. * * Side effects: - * None. + * None. * *-------------------------------------------------------------- */ + TkMainInfo * -TkGetMainInfoList() +TkGetMainInfoList(void) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + return tsdPtr->mainWindowList; } /* @@ -624,7 +632,7 @@ TkGetMainInfoList() * * TkAllocWindow -- * - * This procedure creates and initializes a TkWindow structure. + * This function creates and initializes a TkWindow structure. * * Results: * The return value is a pointer to the new window. @@ -637,13 +645,12 @@ TkGetMainInfoList() */ TkWindow * -TkAllocWindow(dispPtr, screenNum, parentPtr) - TkDisplay *dispPtr; /* Display associated with new window. */ - int screenNum; /* Index of screen for new window. */ - TkWindow *parentPtr; /* Parent from which this window should - * inherit visual information. NULL means - * use screen defaults instead of - * inheriting. */ +TkAllocWindow( + TkDisplay *dispPtr, /* Display associated with new window. */ + int screenNum, /* Index of screen for new window. */ + TkWindow *parentPtr) /* Parent from which this window should + * inherit visual information. NULL means use + * screen defaults instead of inheriting. */ { register TkWindow *winPtr; @@ -709,41 +716,41 @@ TkAllocWindow(dispPtr, screenNum, parentPtr) * * NameWindow -- * - * This procedure is invoked to give a window a name and insert - * the window into the hierarchy associated with a particular - * application. + * This function is invoked to give a window a name and insert the window + * into the hierarchy associated with a particular application. * * Results: * A standard Tcl return value. * * Side effects: - * See above. + * See above. * *---------------------------------------------------------------------- */ static int -NameWindow(interp, winPtr, parentPtr, name) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - register TkWindow *winPtr; /* Window that is to be named and inserted. */ - TkWindow *parentPtr; /* Pointer to logical parent for winPtr - * (used for naming, options, etc.). */ - CONST char *name; /* Name for winPtr; must be unique among +NameWindow( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + register TkWindow *winPtr, /* Window that is to be named and inserted. */ + TkWindow *parentPtr, /* Pointer to logical parent for winPtr (used + * for naming, options, etc.). */ + CONST char *name) /* Name for winPtr; must be unique among * parentPtr's children. */ { #define FIXED_SIZE 200 char staticSpace[FIXED_SIZE]; char *pathName; - int new; + int isNew; Tcl_HashEntry *hPtr; - int length1, length2; + size_t length1, length2; /* * Setup all the stuff except name right away, then do the name stuff - * last. This is so that if the name stuff fails, everything else - * will be properly initialized (needed to destroy the window cleanly - * after the naming failure). + * last. This is so that if the name stuff fails, everything else will be + * properly initialized (needed to destroy the window cleanly after the + * naming failure). */ + winPtr->parentPtr = parentPtr; winPtr->nextPtr = NULL; if (parentPtr->childList == NULL) { @@ -759,6 +766,7 @@ NameWindow(interp, winPtr, parentPtr, name) * If this is an anonymous window (ie, it has no name), just return OK * now. */ + if (winPtr->flags & TK_ANONYMOUS_WINDOW) { return TCL_OK; } @@ -770,22 +778,21 @@ NameWindow(interp, winPtr, parentPtr, name) winPtr->nameUid = Tk_GetUid(name); /* - * Don't permit names that start with an upper-case letter: this - * will just cause confusion with class names in the option database. + * Don't permit names that start with an upper-case letter: this will just + * cause confusion with class names in the option database. */ if (isupper(UCHAR(name[0]))) { Tcl_AppendResult(interp, "window name starts with an upper-case letter: \"", - name, "\"", (char *) NULL); + name, "\"", NULL); return TCL_ERROR; } /* - * To permit names of arbitrary length, must be prepared to malloc - * a buffer to hold the new path name. To run fast in the common - * case where names are short, use a fixed-size buffer on the - * stack. + * To permit names of arbitrary length, must be prepared to malloc a + * buffer to hold the new path name. To run fast in the common case where + * names are short, use a fixed-size buffer on the stack. */ length1 = strlen(parentPtr->pathName); @@ -803,13 +810,14 @@ NameWindow(interp, winPtr, parentPtr, name) pathName[length1] = '.'; strcpy(pathName+length1+1, name); } - hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new); + hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, + &isNew); if (pathName != staticSpace) { ckfree(pathName); } - if (!new) { + if (!isNew) { Tcl_AppendResult(interp, "window name \"", name, - "\" already exists in parent", (char *) NULL); + "\" already exists in parent", NULL); return TCL_ERROR; } Tcl_SetHashValue(hPtr, winPtr); @@ -822,53 +830,50 @@ NameWindow(interp, winPtr, parentPtr, name) * * TkCreateMainWindow -- * - * Make a new main window. A main window is a special kind of - * top-level window used as the outermost window in an - * application. + * Make a new main window. A main window is a special kind of top-level + * window used as the outermost window in an application. * * Results: - * The return value is a token for the new window, or NULL if - * an error prevented the new window from being created. If - * NULL is returned, an error message will be left in - * the interp's result. + * The return value is a token for the new window, or NULL if an error + * prevented the new window from being created. If NULL is returned, an + * error message will be left in the interp's result. * * Side effects: - * A new window structure is allocated locally; "interp" is - * associated with the window and registered for "send" commands - * under "baseName". BaseName may be extended with an instance - * number in the form "#2" if necessary to make it globally - * unique. Tk-related commands are bound into interp. + * A new window structure is allocated locally; "interp" is associated + * with the window and registered for "send" commands under "baseName". + * BaseName may be extended with an instance number in the form "#2" if + * necessary to make it globally unique. Tk-related commands are bound + * into interp. * *---------------------------------------------------------------------- */ Tk_Window -TkCreateMainWindow(interp, screenName, baseName) - Tcl_Interp *interp; /* Interpreter to use for error reporting. */ - CONST char *screenName; /* Name of screen on which to create - * window. Empty or NULL string means - * use DISPLAY environment variable. */ - char *baseName; /* Base name for application; usually of the +TkCreateMainWindow( + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + CONST char *screenName, /* Name of screen on which to create window. + * Empty or NULL string means use DISPLAY + * environment variable. */ + char *baseName) /* Base name for application; usually of the * form "prog instance". */ { Tk_Window tkwin; - int dummy; - int isSafe; + int dummy, isSafe; Tcl_HashEntry *hPtr; register TkMainInfo *mainPtr; register TkWindow *winPtr; register TkCmd *cmdPtr; ClientData clientData; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + /* - * Panic if someone updated the TkWindow structure without - * also updating the Tk_FakeWin structure (or vice versa). + * Panic if someone updated the TkWindow structure without also updating + * the Tk_FakeWin structure (or vice versa). */ if (sizeof(TkWindow) != sizeof(Tk_FakeWin)) { - panic("TkWindow and Tk_FakeWin are not the same size"); + Tcl_Panic("TkWindow and Tk_FakeWin are not the same size"); } /* @@ -880,10 +885,10 @@ TkCreateMainWindow(interp, screenName, baseName) if (tkwin == NULL) { return NULL; } - + /* - * Create the TkMainInfo structure for this application, and set - * up name-related information for the new window. + * Create the TkMainInfo structure for this application, and set up + * name-related information for the new window. */ winPtr = (TkWindow *) tkwin; @@ -911,8 +916,8 @@ TkCreateMainWindow(interp, screenName, baseName) Tcl_ResetResult(interp); } if (Tcl_LinkVar(interp, "::tk::AlwaysShowSelection", - (char *) &mainPtr->alwaysShowSelection, - TCL_LINK_BOOLEAN) != TCL_OK) { + (char *) &mainPtr->alwaysShowSelection, + TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } mainPtr->nextPtr = tsdPtr->mainWindowList; @@ -923,8 +928,8 @@ TkCreateMainWindow(interp, screenName, baseName) winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr); /* - * We have just created another Tk application; increment the refcount - * on the display pointer. + * We have just created another Tk application; increment the refcount on + * the display pointer. */ winPtr->dispPtr->refCount++; @@ -942,7 +947,7 @@ TkCreateMainWindow(interp, screenName, baseName) isSafe = Tcl_IsSafe(interp); for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { if ((cmdPtr->cmdProc == NULL) && (cmdPtr->objProc == NULL)) { - panic("TkCreateMainWindow: builtin command with NULL string and object procs"); + Tcl_Panic("TkCreateMainWindow: builtin command with NULL string and object procs"); } if (cmdPtr->passMainWindow) { clientData = (ClientData) tkwin; @@ -956,11 +961,11 @@ TkCreateMainWindow(interp, screenName, baseName) Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc, clientData, NULL); } - if (isSafe) { - if (!(cmdPtr->isSafe)) { - Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name); - } - } + if (isSafe) { + if (!(cmdPtr->isSafe)) { + Tcl_HideCommand(interp, cmdPtr->name, cmdPtr->name); + } + } } TkCreateMenuCmd(interp); @@ -981,36 +986,35 @@ TkCreateMainWindow(interp, screenName, baseName) * * Tk_CreateWindow -- * - * Create a new internal or top-level window as a child of an - * existing window. + * Create a new internal or top-level window as a child of an existing + * window. * * Results: - * The return value is a token for the new window. This - * is not the same as X's token for the window. If an error - * occurred in creating the window (e.g. no such display or - * screen), then an error message is left in the interp's result and - * NULL is returned. + * The return value is a token for the new window. This is not the same + * as X's token for the window. If an error occurred in creating the + * window (e.g. no such display or screen), then an error message is left + * in the interp's result and NULL is returned. * * Side effects: - * A new window structure is allocated locally. An X - * window is not initially created, but will be created - * the first time the window is mapped. + * A new window structure is allocated locally. An X window is not + * initially created, but will be created the first time the window is + * mapped. * *-------------------------------------------------------------- */ Tk_Window -Tk_CreateWindow(interp, parent, name, screenName) - Tcl_Interp *interp; /* Interpreter to use for error reporting. +Tk_CreateWindow( + Tcl_Interp *interp, /* Interpreter to use for error reporting. * the interp's result is assumed to be * initialized by the caller. */ - Tk_Window parent; /* Token for parent of new window. */ - CONST char *name; /* Name for new window. Must be unique - * among parent's children. */ - CONST char *screenName; /* If NULL, new window will be internal on - * same screen as its parent. If non-NULL, - * gives name of screen on which to create - * new window; window will be a top-level + Tk_Window parent, /* Token for parent of new window. */ + CONST char *name, /* Name for new window. Must be unique among + * parent's children. */ + CONST char *screenName) /* If NULL, new window will be internal on + * same screen as its parent. If non-NULL, + * gives name of screen on which to create new + * window; window will be a top-level * window. */ { TkWindow *parentPtr = (TkWindow *) parent; @@ -1018,29 +1022,26 @@ Tk_CreateWindow(interp, parent, name, screenName) if ((parentPtr != NULL) && (parentPtr->flags & TK_ALREADY_DEAD)) { Tcl_AppendResult(interp, - "can't create window: parent has been destroyed", - (char *) NULL); + "can't create window: parent has been destroyed", NULL); return NULL; } else if ((parentPtr != NULL) && (parentPtr->flags & TK_CONTAINER)) { Tcl_AppendResult(interp, - "can't create window: its parent has -container = yes", - (char *) NULL); + "can't create window: its parent has -container = yes", NULL); return NULL; } + if (screenName == NULL) { winPtr = TkAllocWindow(parentPtr->dispPtr, parentPtr->screenNum, parentPtr); if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) { Tk_DestroyWindow((Tk_Window) winPtr); return NULL; - } else { - return (Tk_Window) winPtr; } - } else { - return CreateTopLevelWindow(interp, parent, name, screenName, - /* flags */ 0); + return (Tk_Window) winPtr; } + return CreateTopLevelWindow(interp, parent, name, screenName, + /* flags */ 0); } /* @@ -1048,35 +1049,34 @@ Tk_CreateWindow(interp, parent, name, screenName) * * Tk_CreateAnonymousWindow -- * - * Create a new internal or top-level window as a child of an - * existing window; this window will be anonymous (unnamed), so - * it will not be visible at the Tcl level. + * Create a new internal or top-level window as a child of an existing + * window; this window will be anonymous (unnamed), so it will not be + * visible at the Tcl level. * * Results: - * The return value is a token for the new window. This - * is not the same as X's token for the window. If an error - * occurred in creating the window (e.g. no such display or - * screen), then an error message is left in the interp's result and - * NULL is returned. + * The return value is a token for the new window. This is not the same + * as X's token for the window. If an error occurred in creating the + * window (e.g. no such display or screen), then an error message is left + * in the interp's result and NULL is returned. * * Side effects: - * A new window structure is allocated locally. An X - * window is not initially created, but will be created - * the first time the window is mapped. + * A new window structure is allocated locally. An X window is not + * initially created, but will be created the first time the window is + * mapped. * *-------------------------------------------------------------- */ Tk_Window -Tk_CreateAnonymousWindow(interp, parent, screenName) - Tcl_Interp *interp; /* Interpreter to use for error reporting. +Tk_CreateAnonymousWindow( + Tcl_Interp *interp, /* Interpreter to use for error reporting. * the interp's result is assumed to be * initialized by the caller. */ - Tk_Window parent; /* Token for parent of new window. */ - CONST char *screenName; /* If NULL, new window will be internal on - * same screen as its parent. If non-NULL, - * gives name of screen on which to create - * new window; window will be a top-level + Tk_Window parent, /* Token for parent of new window. */ + CONST char *screenName) /* If NULL, new window will be internal on + * same screen as its parent. If non-NULL, + * gives name of screen on which to create new + * window; window will be a top-level * window. */ { TkWindow *parentPtr = (TkWindow *) parent; @@ -1084,14 +1084,12 @@ Tk_CreateAnonymousWindow(interp, parent, screenName) if ((parentPtr != NULL) && (parentPtr->flags & TK_ALREADY_DEAD)) { Tcl_AppendResult(interp, - "can't create window: parent has been destroyed", - (char *) NULL); + "can't create window: parent has been destroyed", NULL); return NULL; } else if ((parentPtr != NULL) && (parentPtr->flags & TK_CONTAINER)) { Tcl_AppendResult(interp, - "can't create window: its parent has -container = yes", - (char *) NULL); + "can't create window: its parent has -container = yes", NULL); return NULL; } if (screenName == NULL) { @@ -1103,15 +1101,14 @@ Tk_CreateAnonymousWindow(interp, parent, screenName) */ winPtr->flags |= TK_ANONYMOUS_WINDOW; - if (NameWindow(interp, winPtr, parentPtr, (char *)NULL) != TCL_OK) { + if (NameWindow(interp, winPtr, parentPtr, NULL) != TCL_OK) { Tk_DestroyWindow((Tk_Window) winPtr); return NULL; } return (Tk_Window) winPtr; - } else { - return CreateTopLevelWindow(interp, parent, (char *)NULL, screenName, - TK_ANONYMOUS_WINDOW); } + return CreateTopLevelWindow(interp, parent, NULL, screenName, + TK_ANONYMOUS_WINDOW); } /* @@ -1119,41 +1116,38 @@ Tk_CreateAnonymousWindow(interp, parent, screenName) * * Tk_CreateWindowFromPath -- * - * This procedure is similar to Tk_CreateWindow except that - * it uses a path name to create the window, rather than a - * parent and a child name. + * This function is similar to Tk_CreateWindow except that it uses a path + * name to create the window, rather than a parent and a child name. * * Results: - * The return value is a token for the new window. This - * is not the same as X's token for the window. If an error - * occurred in creating the window (e.g. no such display or - * screen), then an error message is left in the interp's result and - * NULL is returned. + * The return value is a token for the new window. This is not the same + * as X's token for the window. If an error occurred in creating the + * window (e.g. no such display or screen), then an error message is left + * in the interp's result and NULL is returned. * * Side effects: - * A new window structure is allocated locally. An X - * window is not initially created, but will be created - * the first time the window is mapped. + * A new window structure is allocated locally. An X window is not + * initially created, but will be created the first time the window is + * mapped. * *---------------------------------------------------------------------- */ Tk_Window -Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName) - Tcl_Interp *interp; /* Interpreter to use for error reporting. +Tk_CreateWindowFromPath( + Tcl_Interp *interp, /* Interpreter to use for error reporting. * the interp's result is assumed to be * initialized by the caller. */ - Tk_Window tkwin; /* Token for any window in application - * that is to contain new window. */ - CONST char *pathName; /* Path name for new window within the - * application of tkwin. The parent of - * this window must already exist, but - * the window itself must not exist. */ - CONST char *screenName; /* If NULL, new window will be on same - * screen as its parent. If non-NULL, - * gives name of screen on which to create - * new window; window will be a top-level - * window. */ + Tk_Window tkwin, /* Token for any window in application that is + * to contain new window. */ + CONST char *pathName, /* Path name for new window within the + * application of tkwin. The parent of this + * window must already exist, but the window + * itself must not exist. */ + CONST char *screenName) /* If NULL, new window will be on same screen + * as its parent. If non-NULL, gives name of + * screen on which to create new window; + * window will be a top-level window. */ { #define FIXED_SPACE 5 char fixedSpace[FIXED_SPACE+1]; @@ -1162,18 +1156,17 @@ Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName) int numChars; /* - * Strip the parent's name out of pathName (it's everything up - * to the last dot). There are two tricky parts: (a) must - * copy the parent's name somewhere else to avoid modifying - * the pathName string (for large names, space for the copy - * will have to be malloc'ed); (b) must special-case the - * situation where the parent is ".". + * Strip the parent's name out of pathName (it's everything up to the last + * dot). There are two tricky parts: (a) must copy the parent's name + * somewhere else to avoid modifying the pathName string (for large names, + * space for the copy will have to be malloc'ed); (b) must special-case + * the situation where the parent is ".". */ p = strrchr(pathName, '.'); if (p == NULL) { Tcl_AppendResult(interp, "bad window path name \"", pathName, - "\"", (char *) NULL); + "\"", NULL); return NULL; } numChars = (int) (p-pathName); @@ -1196,19 +1189,19 @@ Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName) parent = Tk_NameToWindow(interp, p, tkwin); if (p != fixedSpace) { - ckfree(p); + ckfree(p); } if (parent == NULL) { return NULL; } if (((TkWindow *) parent)->flags & TK_ALREADY_DEAD) { - Tcl_AppendResult(interp, - "can't create window: parent has been destroyed", (char *) NULL); + Tcl_AppendResult(interp, + "can't create window: parent has been destroyed", NULL); return NULL; - } else if (((TkWindow *) parent)->flags & TK_CONTAINER) { - Tcl_AppendResult(interp, - "can't create window: its parent has -container = yes", - (char *) NULL); + } + if (((TkWindow *) parent)->flags & TK_CONTAINER) { + Tcl_AppendResult(interp, + "can't create window: its parent has -container = yes", NULL); return NULL; } @@ -1226,13 +1219,12 @@ Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName) != TCL_OK) { Tk_DestroyWindow((Tk_Window) winPtr); return NULL; - } else { - return (Tk_Window) winPtr; } - } else { - return CreateTopLevelWindow(interp, parent, pathName+numChars+1, - screenName, /* flags */ 0); + return (Tk_Window) winPtr; } + + return CreateTopLevelWindow(interp, parent, pathName+numChars+1, + screenName, /* flags */ 0); } /* @@ -1240,36 +1232,36 @@ Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName) * * Tk_DestroyWindow -- * - * Destroy an existing window. After this call, the caller - * should never again use the token. Note that this function - * can be reentered to destroy a window that was only - * partially destroyed before a call to exit. + * Destroy an existing window. After this call, the caller should never + * again use the token. Note that this function can be reentered to + * destroy a window that was only partially destroyed before a call to + * exit. * * Results: * None. * * Side effects: - * The window is deleted, along with all of its children. - * Relevant callback procedures are invoked. + * The window is deleted, along with all of its children. Relevant + * callback functions are invoked. * *-------------------------------------------------------------- */ void -Tk_DestroyWindow(tkwin) - Tk_Window tkwin; /* Window to destroy. */ +Tk_DestroyWindow( + Tk_Window tkwin) /* Window to destroy. */ { TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; XEvent event; TkHalfdeadWindow *halfdeadPtr, *prev_halfdeadPtr; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->flags & TK_ALREADY_DEAD) { /* - * A destroy event binding caused the window to be destroyed - * again. Ignore the request. + * A destroy event binding caused the window to be destroyed again. + * Ignore the request. */ return; @@ -1277,9 +1269,8 @@ Tk_DestroyWindow(tkwin) winPtr->flags |= TK_ALREADY_DEAD; /* - * Unless we are cleaning up a half dead - * window from DeleteWindowsExitProc, - * add this window to the half dead list. + * Unless we are cleaning up a half dead window from + * DeleteWindowsExitProc, add this window to the half dead list. */ if (tsdPtr->halfdeadWindowList && @@ -1295,12 +1286,12 @@ Tk_DestroyWindow(tkwin) } /* - * Some cleanup needs to be done immediately, rather than later, - * because it needs information that will be destoyed before we - * get to the main cleanup point. For example, TkFocusDeadWindow - * needs to access the parentPtr field from a window, but if - * a Destroy event handler deletes the window's parent this - * field will be NULL before the main cleanup point is reached. + * Some cleanup needs to be done immediately, rather than later, because + * it needs information that will be destoyed before we get to the main + * cleanup point. For example, TkFocusDeadWindow needs to access the + * parentPtr field from a window, but if a Destroy event handler deletes + * the window's parent this field will be NULL before the main cleanup + * point is reached. */ if (!(halfdeadPtr->flags & HD_FOCUS)) { @@ -1309,23 +1300,23 @@ Tk_DestroyWindow(tkwin) } /* - * If this is a main window, remove it from the list of main - * windows. This needs to be done now (rather than later with - * all the other main window cleanup) to handle situations where - * a destroy binding for a window calls "exit". In this case - * the child window cleanup isn't complete when exit is called. - * This situation is dealt with using the half dead window - * list. Windows that are half dead gets cleaned up during exit. + * If this is a main window, remove it from the list of main windows. + * This needs to be done now (rather than later with all the other main + * window cleanup) to handle situations where a destroy binding for a + * window calls "exit". In this case the child window cleanup isn't + * complete when exit is called. This situation is dealt with using the + * half dead window list. Windows that are half dead gets cleaned up + * during exit. * - * Also decrement the display refcount so that if this is the - * last Tk application in this process on this display, the display - * can be closed and its data structures deleted. + * Also decrement the display refcount so that if this is the last Tk + * application in this process on this display, the display can be closed + * and its data structures deleted. */ if (!(halfdeadPtr->flags & HD_MAIN_WIN) && winPtr->mainPtr != NULL && winPtr->mainPtr->winPtr == winPtr) { halfdeadPtr->flags |= HD_MAIN_WIN; - dispPtr->refCount--; + dispPtr->refCount--; if (tsdPtr->mainWindowList == winPtr->mainPtr) { tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr; } else { @@ -1342,10 +1333,9 @@ Tk_DestroyWindow(tkwin) } /* - * Recursively destroy children. Note that this child - * window block may need to be run multiple times - * in the case where a child window has a Destroy - * binding that calls exit. + * Recursively destroy children. Note that this child window block may + * need to be run multiple times in the case where a child window has a + * Destroy binding that calls exit. */ if (!(halfdeadPtr->flags & HD_DESTROY_COUNT)) { @@ -1360,10 +1350,10 @@ Tk_DestroyWindow(tkwin) Tk_DestroyWindow((Tk_Window) childPtr); if (winPtr->childList == childPtr) { /* - * The child didn't remove itself from the child list, so - * let's remove it here. This can happen in some strange - * conditions, such as when a Destroy event handler for a - * window destroys the window's parent. + * The child didn't remove itself from the child list, so let's + * remove it here. This can happen in some strange conditions, + * such as when a Destroy event handler for a window destroys the + * window's parent. */ winPtr->childList = childPtr->nextPtr; @@ -1373,14 +1363,13 @@ Tk_DestroyWindow(tkwin) if ((winPtr->flags & (TK_CONTAINER|TK_BOTH_HALVES)) == (TK_CONTAINER|TK_BOTH_HALVES)) { /* - * This is the container for an embedded application, and - * the embedded application is also in this process. Delete - * the embedded window in-line here, for the same reasons we - * delete children in-line (otherwise, for example, the Tk - * window may appear to exist even though its X window is - * gone; this could cause errors). Special note: it's possible - * that the embedded window has already been deleted, in which - * case TkpGetOtherWindow will return NULL. + * This is the container for an embedded application, and the embedded + * application is also in this process. Delete the embedded window + * in-line here, for the same reasons we delete children in-line + * (otherwise, for example, the Tk window may appear to exist even + * though its X window is gone; this could cause errors). Special + * note: it's possible that the embedded window has already been + * deleted, in which case TkpGetOtherWindow will return NULL. */ TkWindow *childPtr; @@ -1392,11 +1381,10 @@ Tk_DestroyWindow(tkwin) } /* - * Generate a DestroyNotify event. In order for the DestroyNotify - * event to be processed correctly, need to make sure the window - * exists. This is a bit of a kludge, and may be unnecessarily - * expensive, but without it no event handlers will get called for - * windows that don't exist yet. + * Generate a DestroyNotify event. In order for the DestroyNotify event to + * be processed correctly, need to make sure the window exists. This is a + * bit of a kludge, and may be unnecessarily expensive, but without it no + * event handlers will get called for windows that don't exist yet. * * Note: if the window's pathName is NULL and the window is not an * anonymous window, it means that the window was not successfully @@ -1422,28 +1410,28 @@ Tk_DestroyWindow(tkwin) } /* - * No additional bindings that could call exit - * should be invoked from this point on, - * so it is safe to remove this window - * from the half dead list. + * No additional bindings that could call exit should be invoked from this + * point on, so it is safe to remove this window from the half dead list. */ for (prev_halfdeadPtr = NULL, halfdeadPtr = tsdPtr->halfdeadWindowList; halfdeadPtr != NULL; ) { if (halfdeadPtr->winPtr == winPtr) { - if (prev_halfdeadPtr == NULL) - tsdPtr->halfdeadWindowList = halfdeadPtr->nextPtr; - else - prev_halfdeadPtr->nextPtr = halfdeadPtr->nextPtr; + if (prev_halfdeadPtr == NULL) { + tsdPtr->halfdeadWindowList = halfdeadPtr->nextPtr; + } else { + prev_halfdeadPtr->nextPtr = halfdeadPtr->nextPtr; + } ckfree((char *) halfdeadPtr); break; } prev_halfdeadPtr = halfdeadPtr; halfdeadPtr = halfdeadPtr->nextPtr; } - if (halfdeadPtr == NULL) - panic("window not found on half dead list"); + if (halfdeadPtr == NULL) { + Tcl_Panic("window not found on half dead list"); + } /* * Cleanup the data structures associated with this window. @@ -1455,17 +1443,16 @@ Tk_DestroyWindow(tkwin) TkWmRemoveFromColormapWindows(winPtr); } if (winPtr->window != None) { -#if defined(MAC_TCL) || defined(MAC_OSX_TK) || defined(__WIN32__) +#if defined(MAC_OSX_TK) || defined(__WIN32__) XDestroyWindow(winPtr->display, winPtr->window); #else if ((winPtr->flags & TK_TOP_HIERARCHY) || !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) { /* - * The parent has already been destroyed and this isn't - * a top-level window, so this window will be destroyed - * implicitly when the parent's X window is destroyed; - * it's much faster not to do an explicit destroy of this - * X window. + * The parent has already been destroyed and this isn't a + * top-level window, so this window will be destroyed implicitly + * when the parent's X window is destroyed; it's much faster not + * to do an explicit destroy of this X window. */ dispPtr->lastDestroyRequest = NextRequest(winPtr->display); @@ -1499,17 +1486,20 @@ Tk_DestroyWindow(tkwin) (ClientData) winPtr->pathName); Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, winPtr->pathName)); - /* - * The memory pointed to by pathName has been deallocated. - * Keep users from accessing it after the window has been - * destroyed by setting it to NULL. - */ - winPtr->pathName = NULL; /* - * Invalidate all objects referring to windows - * with the same main window + * The memory pointed to by pathName has been deallocated. Keep + * users from accessing it after the window has been destroyed by + * setting it to NULL. + */ + + winPtr->pathName = NULL; + + /* + * Invalidate all objects referring to windows with the same main + * window. */ + winPtr->mainPtr->deletionEpoch++; } winPtr->mainPtr->refCount--; @@ -1517,30 +1507,29 @@ Tk_DestroyWindow(tkwin) register TkCmd *cmdPtr; /* - * We just deleted the last window in the application. Delete - * the TkMainInfo structure too and replace all of Tk's commands - * with dummy commands that return errors. Also delete the - * "send" command to unregister the interpreter. + * We just deleted the last window in the application. Delete the + * TkMainInfo structure too and replace all of Tk's commands with + * dummy commands that return errors. Also delete the "send" + * command to unregister the interpreter. * - * NOTE: Only replace the commands it if the interpreter is - * not being deleted. If it *is*, the interpreter cleanup will - * do all the needed work. + * NOTE: Only replace the commands it if the interpreter is not + * being deleted. If it *is*, the interpreter cleanup will do all + * the needed work. */ - if ((winPtr->mainPtr->interp != NULL) && - (!Tcl_InterpDeleted(winPtr->mainPtr->interp))) { - for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { - Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name, - TkDeadAppCmd, (ClientData) NULL, - (void (*) _ANSI_ARGS_((ClientData))) NULL); - } - Tcl_CreateCommand(winPtr->mainPtr->interp, "send", - TkDeadAppCmd, (ClientData) NULL, - (void (*) _ANSI_ARGS_((ClientData))) NULL); - Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif"); - Tcl_UnlinkVar(winPtr->mainPtr->interp, "::tk::AlwaysShowSelection"); - } - + if ((winPtr->mainPtr->interp != NULL) && + (!Tcl_InterpDeleted(winPtr->mainPtr->interp))) { + for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { + Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name, + TkDeadAppCmd, NULL, NULL); + } + Tcl_CreateCommand(winPtr->mainPtr->interp, "send", + TkDeadAppCmd, NULL, NULL); + Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif"); + Tcl_UnlinkVar(winPtr->mainPtr->interp, + "::tk::AlwaysShowSelection"); + } + Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable); TkBindFree(winPtr->mainPtr); TkDeleteAllImages(winPtr->mainPtr); @@ -1548,72 +1537,71 @@ Tk_DestroyWindow(tkwin) TkFocusFree(winPtr->mainPtr); TkStylePkgFree(winPtr->mainPtr); - /* - * When embedding Tk into other applications, make sure - * that all destroy events reach the server. Otherwise - * the embedding application may also attempt to destroy - * the windows, resulting in an X error - */ + /* + * When embedding Tk into other applications, make sure that all + * destroy events reach the server. Otherwise the embedding + * application may also attempt to destroy the windows, resulting + * in an X error + */ - if (winPtr->flags & TK_EMBEDDED) { - XSync(winPtr->display, False); - } + if (winPtr->flags & TK_EMBEDDED) { + XSync(winPtr->display, False); + } ckfree((char *) winPtr->mainPtr); - /* - * If no other applications are using the display, close the - * display now and relinquish its data structures. - */ - -#if !defined(WIN32) && !defined(MAC_TCL) && defined(NOT_YET) - if (dispPtr->refCount <= 0) { - /* - * I have disabled this code because on Windows there are - * still order dependencies in close-down. All displays - * and resources will get closed down properly anyway at - * exit, through the exit handler. -- jyl - */ + /* + * If no other applications are using the display, close the + * display now and relinquish its data structures. + */ + +#if !defined(WIN32) && defined(NOT_YET) + if (dispPtr->refCount <= 0) { /* + * I have disabled this code because on Windows there are + * still order dependencies in close-down. All displays and + * resources will get closed down properly anyway at exit, + * through the exit handler. -- jyl + * * Ideally this should be enabled, as unix Tk can use multiple - * displays. However, there are order issues still, as well - * as the handling of queued events and such that must be - * addressed before this can be enabled. The current cleanup + * displays. However, there are order issues still, as well as + * the handling of queued events and such that must be + * addressed before this can be enabled. The current cleanup * works except for send event issues. -- hobbs 04/2002 */ - - TkDisplay *theDispPtr, *backDispPtr; - - /* - * Splice this display out of the list of displays. - */ - - for (theDispPtr = tsdPtr->displayList, backDispPtr = NULL; - (theDispPtr != winPtr->dispPtr) && - (theDispPtr != NULL); - theDispPtr = theDispPtr->nextPtr) { - backDispPtr = theDispPtr; - } - if (theDispPtr == NULL) { - panic("could not find display to close!"); - } - if (backDispPtr == NULL) { - tsdPtr->displayList = theDispPtr->nextPtr; - } else { - backDispPtr->nextPtr = theDispPtr->nextPtr; - } - - /* + + TkDisplay *theDispPtr, *backDispPtr; + + /* + * Splice this display out of the list of displays. + */ + + for (theDispPtr = tsdPtr->displayList, backDispPtr = NULL; + (theDispPtr!=winPtr->dispPtr) && (theDispPtr!=NULL); + theDispPtr = theDispPtr->nextPtr) { + backDispPtr = theDispPtr; + } + if (theDispPtr == NULL) { + Tcl_Panic("could not find display to close!"); + } + if (backDispPtr == NULL) { + tsdPtr->displayList = theDispPtr->nextPtr; + } else { + backDispPtr->nextPtr = theDispPtr->nextPtr; + } + + /* * Calling XSync creates X server traffic, but addresses a * focus issue on close (but not the send issue). -- hobbs - XSync(dispPtr->display, True); + * + * XSync(dispPtr->display, True); */ - /* - * Found and spliced it out, now actually do the cleanup. - */ + /* + * Found and spliced it out, now actually do the cleanup. + */ TkCloseDisplay(dispPtr); - } + } #endif } } @@ -1625,22 +1613,21 @@ Tk_DestroyWindow(tkwin) * * Tk_MapWindow -- * - * Map a window within its parent. This may require the - * window and/or its parents to actually be created. + * Map a window within its parent. This may require the window and/or its + * parents to actually be created. * * Results: * None. * * Side effects: - * The given window will be mapped. Windows may also - * be created. + * The given window will be mapped. Windows may also be created. * *-------------------------------------------------------------- */ void -Tk_MapWindow(tkwin) - Tk_Window tkwin; /* Token for window to map. */ +Tk_MapWindow( + Tk_Window tkwin) /* Token for window to map. */ { TkWindow *winPtr = (TkWindow *) tkwin; XEvent event; @@ -1660,8 +1647,8 @@ Tk_MapWindow(tkwin) } if (winPtr->flags & TK_WIN_MANAGED) { /* - * Lots of special processing has to be done for top-level - * windows. Let tkWm.c handle everything itself. + * Lots of special processing has to be done for top-level windows. + * Let tkWm.c handle everything itself. */ TkWmMapWindow(winPtr); @@ -1684,32 +1671,31 @@ Tk_MapWindow(tkwin) * * Tk_MakeWindowExist -- * - * Ensure that a particular window actually exists. This - * procedure shouldn't normally need to be invoked from - * outside the Tk package, but may be needed if someone - * wants to manipulate a window before mapping it. + * Ensure that a particular window actually exists. This function should + * not normally need to be invoked from outside the Tk package, but may + * be needed if someone wants to manipulate a window before mapping it. * * Results: * None. * * Side effects: - * When the procedure returns, the X window associated with - * tkwin is guaranteed to exist. This may require the - * window's ancestors to be created also. + * When the function returns, the X window associated with tkwin is + * guaranteed to exist. This may require the window's ancestors to be + * created also. * *-------------------------------------------------------------- */ void -Tk_MakeWindowExist(tkwin) - Tk_Window tkwin; /* Token for window. */ +Tk_MakeWindowExist( + Tk_Window tkwin) /* Token for window. */ { register TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *winPtr2; Window parent; Tcl_HashEntry *hPtr; Tk_ClassCreateProc *createProc; - int new; + int isNew; if (winPtr->window != None) { return; @@ -1725,28 +1711,28 @@ Tk_MakeWindowExist(tkwin) } createProc = Tk_GetClassProc(winPtr->classProcsPtr, createProc); - if (createProc != NULL) { + if (createProc != NULL && parent != None) { winPtr->window = (*createProc)(tkwin, parent, winPtr->instanceData); } else { winPtr->window = TkpMakeWindow(winPtr, parent); } hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable, - (char *) winPtr->window, &new); + (char *) winPtr->window, &isNew); Tcl_SetHashValue(hPtr, winPtr); winPtr->dirtyAtts = 0; winPtr->dirtyChanges = 0; if (!(winPtr->flags & TK_TOP_HIERARCHY)) { /* - * If any siblings higher up in the stacking order have already - * been created then move this window to its rightful position - * in the stacking order. + * If any siblings higher up in the stacking order have already been + * created then move this window to its rightful position in the + * stacking order. * - * NOTE: this code ignores any changes anyone might have made - * to the sibling and stack_mode field of the window's attributes, - * so it really isn't safe for these to be manipulated except - * by calling Tk_RestackWindow. + * NOTE: this code ignores any changes anyone might have made to the + * sibling and stack_mode field of the window's attributes, so it + * really isn't safe for these to be manipulated except by calling + * Tk_RestackWindow. */ for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL; @@ -1763,8 +1749,8 @@ Tk_MakeWindowExist(tkwin) } /* - * If this window has a different colormap than its parent, add - * the window to the WM_COLORMAP_WINDOWS property for its top-level. + * If this window has a different colormap than its parent, add the + * window to the WM_COLORMAP_WINDOWS property for its top-level. */ if ((winPtr->parentPtr != NULL) && @@ -1776,9 +1762,9 @@ Tk_MakeWindowExist(tkwin) /* * Issue a ConfigureNotify event if there were deferred configuration - * changes (but skip it if the window is being deleted; the - * ConfigureNotify event could cause problems if we're being called - * from Tk_DestroyWindow under some conditions). + * changes (but skip it if the window is being deleted; the + * ConfigureNotify event could cause problems if we're being called from + * Tk_DestroyWindow under some conditions). */ if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY) @@ -1793,12 +1779,11 @@ Tk_MakeWindowExist(tkwin) * * Tk_UnmapWindow, etc. -- * - * There are several procedures under here, each of which - * mirrors an existing X procedure. In addition to performing - * the functions of the corresponding procedure, each - * procedure also updates the local window structure and - * synthesizes an X event (if the window's structure is being - * managed internally). + * There are several functions under here, each of which mirrors an + * existing X function. In addition to performing the functions of the + * corresponding function, each function also updates the local window + * structure and synthesizes an X event (if the window's structure is + * being managed internally). * * Results: * See the manual entries. @@ -1810,8 +1795,8 @@ Tk_MakeWindowExist(tkwin) */ void -Tk_UnmapWindow(tkwin) - Tk_Window tkwin; /* Token for window to unmap. */ +Tk_UnmapWindow( + Tk_Window tkwin) /* Token for window to unmap. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -1820,8 +1805,8 @@ Tk_UnmapWindow(tkwin) } if (winPtr->flags & TK_WIN_MANAGED) { /* - * Special processing has to be done for top-level windows. Let - * tkWm.c handle everything itself. + * Special processing has to be done for top-level windows. Let tkWm.c + * handle everything itself. */ TkWmUnmapWindow(winPtr); @@ -1844,11 +1829,11 @@ Tk_UnmapWindow(tkwin) } void -Tk_ConfigureWindow(tkwin, valueMask, valuePtr) - Tk_Window tkwin; /* Window to re-configure. */ - unsigned int valueMask; /* Mask indicating which parts of - * *valuePtr are to be used. */ - XWindowChanges *valuePtr; /* New values. */ +Tk_ConfigureWindow( + Tk_Window tkwin, /* Window to re-configure. */ + unsigned int valueMask, /* Mask indicating which parts of *valuePtr + * are to be used. */ + XWindowChanges *valuePtr) /* New values. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -1868,13 +1853,13 @@ Tk_ConfigureWindow(tkwin, valueMask, valuePtr) winPtr->changes.border_width = valuePtr->border_width; } if (valueMask & (CWSibling|CWStackMode)) { - panic("Can't set sibling or stack mode from Tk_ConfigureWindow."); + Tcl_Panic("Can't set sibling or stack mode from Tk_ConfigureWindow."); } if (winPtr->window != None) { XConfigureWindow(winPtr->display, winPtr->window, valueMask, valuePtr); - TkDoConfigureNotify(winPtr); + TkDoConfigureNotify(winPtr); } else { winPtr->dirtyChanges |= valueMask; winPtr->flags |= TK_NEED_CONFIG_NOTIFY; @@ -1882,10 +1867,9 @@ Tk_ConfigureWindow(tkwin, valueMask, valuePtr) } void -Tk_MoveWindow(tkwin, x, y) - Tk_Window tkwin; /* Window to move. */ - int x, y; /* New location for window (within - * parent). */ +Tk_MoveWindow( + Tk_Window tkwin, /* Window to move. */ + int x, int y) /* New location for window (within parent). */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -1893,7 +1877,7 @@ Tk_MoveWindow(tkwin, x, y) winPtr->changes.y = y; if (winPtr->window != None) { XMoveWindow(winPtr->display, winPtr->window, x, y); - TkDoConfigureNotify(winPtr); + TkDoConfigureNotify(winPtr); } else { winPtr->dirtyChanges |= CWX|CWY; winPtr->flags |= TK_NEED_CONFIG_NOTIFY; @@ -1901,9 +1885,9 @@ Tk_MoveWindow(tkwin, x, y) } void -Tk_ResizeWindow(tkwin, width, height) - Tk_Window tkwin; /* Window to resize. */ - int width, height; /* New dimensions for window. */ +Tk_ResizeWindow( + Tk_Window tkwin, /* Window to resize. */ + int width, int height) /* New dimensions for window. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -1912,7 +1896,7 @@ Tk_ResizeWindow(tkwin, width, height) if (winPtr->window != None) { XResizeWindow(winPtr->display, winPtr->window, (unsigned) width, (unsigned) height); - TkDoConfigureNotify(winPtr); + TkDoConfigureNotify(winPtr); } else { winPtr->dirtyChanges |= CWWidth|CWHeight; winPtr->flags |= TK_NEED_CONFIG_NOTIFY; @@ -1920,11 +1904,10 @@ Tk_ResizeWindow(tkwin, width, height) } void -Tk_MoveResizeWindow(tkwin, x, y, width, height) - Tk_Window tkwin; /* Window to move and resize. */ - int x, y; /* New location for window (within - * parent). */ - int width, height; /* New dimensions for window. */ +Tk_MoveResizeWindow( + Tk_Window tkwin, /* Window to move and resize. */ + int x, int y, /* New location for window (within parent). */ + int width, int height) /* New dimensions for window. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -1935,7 +1918,7 @@ Tk_MoveResizeWindow(tkwin, x, y, width, height) if (winPtr->window != None) { XMoveResizeWindow(winPtr->display, winPtr->window, x, y, (unsigned) width, (unsigned) height); - TkDoConfigureNotify(winPtr); + TkDoConfigureNotify(winPtr); } else { winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight; winPtr->flags |= TK_NEED_CONFIG_NOTIFY; @@ -1943,9 +1926,9 @@ Tk_MoveResizeWindow(tkwin, x, y, width, height) } void -Tk_SetWindowBorderWidth(tkwin, width) - Tk_Window tkwin; /* Window to modify. */ - int width; /* New border width for window. */ +Tk_SetWindowBorderWidth( + Tk_Window tkwin, /* Window to modify. */ + int width) /* New border width for window. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -1953,7 +1936,7 @@ Tk_SetWindowBorderWidth(tkwin, width) if (winPtr->window != None) { XSetWindowBorderWidth(winPtr->display, winPtr->window, (unsigned) width); - TkDoConfigureNotify(winPtr); + TkDoConfigureNotify(winPtr); } else { winPtr->dirtyChanges |= CWBorderWidth; winPtr->flags |= TK_NEED_CONFIG_NOTIFY; @@ -1961,12 +1944,11 @@ Tk_SetWindowBorderWidth(tkwin, width) } void -Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr) - Tk_Window tkwin; /* Window to manipulate. */ - unsigned long valueMask; /* OR'ed combination of bits, - * indicating which fields of - * *attsPtr are to be used. */ - register XSetWindowAttributes *attsPtr; +Tk_ChangeWindowAttributes( + Tk_Window tkwin, /* Window to manipulate. */ + unsigned long valueMask, /* OR'ed combination of bits, indicating which + * fields of *attsPtr are to be used. */ + register XSetWindowAttributes *attsPtr) /* New values for some attributes. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2027,10 +2009,10 @@ Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr) } void -Tk_SetWindowBackground(tkwin, pixel) - Tk_Window tkwin; /* Window to manipulate. */ - unsigned long pixel; /* Pixel value to use for - * window's background. */ +Tk_SetWindowBackground( + Tk_Window tkwin, /* Window to manipulate. */ + unsigned long pixel) /* Pixel value to use for window's + * background. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2045,10 +2027,9 @@ Tk_SetWindowBackground(tkwin, pixel) } void -Tk_SetWindowBackgroundPixmap(tkwin, pixmap) - Tk_Window tkwin; /* Window to manipulate. */ - Pixmap pixmap; /* Pixmap to use for window's - * background. */ +Tk_SetWindowBackgroundPixmap( + Tk_Window tkwin, /* Window to manipulate. */ + Pixmap pixmap) /* Pixmap to use for window's background. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2064,10 +2045,9 @@ Tk_SetWindowBackgroundPixmap(tkwin, pixmap) } void -Tk_SetWindowBorder(tkwin, pixel) - Tk_Window tkwin; /* Window to manipulate. */ - unsigned long pixel; /* Pixel value to use for - * window's border. */ +Tk_SetWindowBorder( + Tk_Window tkwin, /* Window to manipulate. */ + unsigned long pixel) /* Pixel value to use for window's border. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2082,10 +2062,9 @@ Tk_SetWindowBorder(tkwin, pixel) } void -Tk_SetWindowBorderPixmap(tkwin, pixmap) - Tk_Window tkwin; /* Window to manipulate. */ - Pixmap pixmap; /* Pixmap to use for window's - * border. */ +Tk_SetWindowBorderPixmap( + Tk_Window tkwin, /* Window to manipulate. */ + Pixmap pixmap) /* Pixmap to use for window's border. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2101,18 +2080,18 @@ Tk_SetWindowBorderPixmap(tkwin, pixmap) } void -Tk_DefineCursor(tkwin, cursor) - Tk_Window tkwin; /* Window to manipulate. */ - Tk_Cursor cursor; /* Cursor to use for window (may be None). */ +Tk_DefineCursor( + Tk_Window tkwin, /* Window to manipulate. */ + Tk_Cursor cursor) /* Cursor to use for window (may be None). */ { register TkWindow *winPtr = (TkWindow *) tkwin; -#if defined(MAC_TCL) || defined(MAC_OSX_TK) +#if defined(MAC_OSX_TK) winPtr->atts.cursor = (XCursor) cursor; #else winPtr->atts.cursor = (Cursor) cursor; #endif - + if (winPtr->window != None) { XDefineCursor(winPtr->display, winPtr->window, winPtr->atts.cursor); } else { @@ -2121,16 +2100,16 @@ Tk_DefineCursor(tkwin, cursor) } void -Tk_UndefineCursor(tkwin) - Tk_Window tkwin; /* Window to manipulate. */ +Tk_UndefineCursor( + Tk_Window tkwin) /* Window to manipulate. */ { Tk_DefineCursor(tkwin, None); } void -Tk_SetWindowColormap(tkwin, colormap) - Tk_Window tkwin; /* Window to manipulate. */ - Colormap colormap; /* Colormap to use for window. */ +Tk_SetWindowColormap( + Tk_Window tkwin, /* Window to manipulate. */ + Colormap colormap) /* Colormap to use for window. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2152,14 +2131,14 @@ Tk_SetWindowColormap(tkwin, colormap) * * Tk_SetWindowVisual -- * - * This procedure is called to specify a visual to be used - * for a Tk window when it is created. This procedure, if - * called at all, must be called before the X window is created - * (i.e. before Tk_MakeWindowExist is called). + * This function is called to specify a visual to be used for a Tk window + * when it is created. This function, if called at all, must be called + * before the X window is created (i.e. before Tk_MakeWindowExist is + * called). * * Results: - * The return value is 1 if successful, or 0 if the X window has - * been already created. + * The return value is 1 if successful, or 0 if the X window has been + * already created. * * Side effects: * The information given is stored for when the window is created. @@ -2168,15 +2147,15 @@ Tk_SetWindowColormap(tkwin, colormap) */ int -Tk_SetWindowVisual(tkwin, visual, depth, colormap) - Tk_Window tkwin; /* Window to manipulate. */ - Visual *visual; /* New visual for window. */ - int depth; /* New depth for window. */ - Colormap colormap; /* An appropriate colormap for the visual. */ +Tk_SetWindowVisual( + Tk_Window tkwin, /* Window to manipulate. */ + Visual *visual, /* New visual for window. */ + int depth, /* New depth for window. */ + Colormap colormap) /* An appropriate colormap for the visual. */ { register TkWindow *winPtr = (TkWindow *) tkwin; - if( winPtr->window != None ){ + if (winPtr->window != None) { /* Too late! */ return 0; } @@ -2203,8 +2182,8 @@ Tk_SetWindowVisual(tkwin, visual, depth, colormap) * * TkDoConfigureNotify -- * - * Generate a ConfigureNotify event describing the current - * configuration of a window. + * Generate a ConfigureNotify event describing the current configuration + * of a window. * * Results: * None. @@ -2216,9 +2195,9 @@ Tk_SetWindowVisual(tkwin, visual, depth, colormap) */ void -TkDoConfigureNotify(winPtr) - register TkWindow *winPtr; /* Window whose configuration - * was just changed. */ +TkDoConfigureNotify( + register TkWindow *winPtr) /* Window whose configuration was just + * changed. */ { XEvent event; @@ -2247,22 +2226,21 @@ TkDoConfigureNotify(winPtr) * * Tk_SetClass -- * - * This procedure is used to give a window a class. + * This function is used to give a window a class. * * Results: * None. * * Side effects: - * A new class is stored for tkwin, replacing any existing - * class for it. + * A new class is stored for tkwin, replacing any existing class for it. * *---------------------------------------------------------------------- */ void -Tk_SetClass(tkwin, className) - Tk_Window tkwin; /* Token for window to assign class. */ - CONST char *className; /* New class for tkwin. */ +Tk_SetClass( + Tk_Window tkwin, /* Token for window to assign class. */ + CONST char *className) /* New class for tkwin. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2278,24 +2256,24 @@ Tk_SetClass(tkwin, className) * * Tk_SetClassProcs -- * - * This procedure is used to set the class procedures and - * instance data for a window. + * This function is used to set the class functions and instance data for + * a window. * * Results: * None. * * Side effects: - * A new set of class procedures and instance data is stored - * for tkwin, replacing any existing values. + * A new set of class functions and instance data is stored for tkwin, + * replacing any existing values. * *---------------------------------------------------------------------- */ void -Tk_SetClassProcs(tkwin, procs, instanceData) - Tk_Window tkwin; /* Token for window to modify. */ - Tk_ClassProcs *procs; /* Class procs structure. */ - ClientData instanceData; /* Data to be passed to class procedures. */ +Tk_SetClassProcs( + Tk_Window tkwin, /* Token for window to modify. */ + Tk_ClassProcs *procs, /* Class procs structure. */ + ClientData instanceData) /* Data to be passed to class functions. */ { register TkWindow *winPtr = (TkWindow *) tkwin; @@ -2308,14 +2286,14 @@ Tk_SetClassProcs(tkwin, procs, instanceData) * * Tk_NameToWindow -- * - * Given a string name for a window, this procedure - * returns the token for the window, if there exists a - * window corresponding to the given name. + * Given a string name for a window, this function returns the token for + * the window, if there exists a window corresponding to the given name. * * Results: - * The return result is either a token for the window corresponding - * to "name", or else NULL to indicate that there is no such - * window. In this case, an error message is left in the interp's result. + * The return result is either a token for the window corresponding to + * "name", or else NULL to indicate that there is no such window. In this + * case, an error message is left in the interp's result, unless interp + * is NULL. * * Side effects: * None. @@ -2324,28 +2302,33 @@ Tk_SetClassProcs(tkwin, procs, instanceData) */ Tk_Window -Tk_NameToWindow(interp, pathName, tkwin) - Tcl_Interp *interp; /* Where to report errors. */ - CONST char *pathName; /* Path name of window. */ - Tk_Window tkwin; /* Token for window: name is assumed to - * belong to the same main window as tkwin. */ +Tk_NameToWindow( + Tcl_Interp *interp, /* Where to report errors. */ + CONST char *pathName, /* Path name of window. */ + Tk_Window tkwin) /* Token for window: name is assumed to belong + * to the same main window as tkwin. */ { Tcl_HashEntry *hPtr; if (tkwin == NULL) { /* * Either we're not really in Tk, or the main window was destroyed and - * we're on our way out of the application + * we're on our way out of the application. */ - Tcl_AppendResult(interp, "NULL main window", (char *)NULL); + + if (interp != NULL) { + Tcl_AppendResult(interp, "NULL main window", NULL); + } return NULL; } - + hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable, pathName); if (hPtr == NULL) { - Tcl_AppendResult(interp, "bad window path name \"", - pathName, "\"", (char *) NULL); + if (interp != NULL) { + Tcl_AppendResult(interp, "bad window path name \"", + pathName, "\"", NULL); + } return NULL; } return (Tk_Window) Tcl_GetHashValue(hPtr); @@ -2356,14 +2339,13 @@ Tk_NameToWindow(interp, pathName, tkwin) * * Tk_IdToWindow -- * - * Given an X display and window ID, this procedure returns the - * Tk token for the window, if there exists a Tk window corresponding - * to the given ID. + * Given an X display and window ID, this function returns the Tk token + * for the window, if there exists a Tk window corresponding to the given + * ID. * * Results: - * The return result is either a token for the window corresponding - * to the given X id, or else NULL to indicate that there is no such - * window. + * The return result is either a token for the window corresponding to + * the given X id, or else NULL to indicate that there is no such window. * * Side effects: * None. @@ -2372,9 +2354,9 @@ Tk_NameToWindow(interp, pathName, tkwin) */ Tk_Window -Tk_IdToWindow(display, window) - Display *display; /* X display containing the window. */ - Window window; /* X window window id. */ +Tk_IdToWindow( + Display *display, /* X display containing the window. */ + Window window) /* X window window id. */ { TkDisplay *dispPtr; Tcl_HashEntry *hPtr; @@ -2403,8 +2385,8 @@ Tk_IdToWindow(display, window) * Return the textual name of a window's display. * * Results: - * The return value is the string name of the display associated - * with tkwin. + * The return value is the string name of the display associated with + * tkwin. * * Side effects: * None. @@ -2413,8 +2395,8 @@ Tk_IdToWindow(display, window) */ CONST char * -Tk_DisplayName(tkwin) - Tk_Window tkwin; /* Window whose display name is desired. */ +Tk_DisplayName( + Tk_Window tkwin) /* Window whose display name is desired. */ { return ((TkWindow *) tkwin)->dispPtr->name; } @@ -2422,10 +2404,35 @@ Tk_DisplayName(tkwin) /* *---------------------------------------------------------------------- * + * Tk_Interp -- + * + * Get the Tcl interpreter from a Tk window. + * + * Results: + * A pointer to the interpreter or NULL. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tcl_Interp * +Tk_Interp( + Tk_Window tkwin) +{ + if (tkwin != NULL && ((TkWindow *)tkwin)->mainPtr != NULL) { + return ((TkWindow *)tkwin)->mainPtr->interp; + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * * UnlinkWindow -- * - * This procedure removes a window from the childList of its - * parent. + * This function removes a window from the childList of its parent. * * Results: * None. @@ -2437,8 +2444,8 @@ Tk_DisplayName(tkwin) */ static void -UnlinkWindow(winPtr) - TkWindow *winPtr; /* Child window to be unlinked. */ +UnlinkWindow( + TkWindow *winPtr) /* Child window to be unlinked. */ { TkWindow *prevPtr; @@ -2455,7 +2462,7 @@ UnlinkWindow(winPtr) while (prevPtr->nextPtr != winPtr) { prevPtr = prevPtr->nextPtr; if (prevPtr == NULL) { - panic("UnlinkWindow couldn't find child in parent"); + Tcl_Panic("UnlinkWindow couldn't find child in parent"); } } prevPtr->nextPtr = winPtr->nextPtr; @@ -2473,9 +2480,8 @@ UnlinkWindow(winPtr) * Change a window's position in the stacking order. * * Results: - * TCL_OK is normally returned. If other is not a descendant - * of tkwin's parent then TCL_ERROR is returned and tkwin is - * not repositioned. + * TCL_OK is normally returned. If other is not a descendant of tkwin's + * parent then TCL_ERROR is returned and tkwin is not repositioned. * * Side effects: * Tkwin is repositioned in the stacking order. @@ -2484,23 +2490,23 @@ UnlinkWindow(winPtr) */ int -Tk_RestackWindow(tkwin, aboveBelow, other) - Tk_Window tkwin; /* Token for window whose position in - * the stacking order is to change. */ - int aboveBelow; /* Indicates new position of tkwin relative - * to other; must be Above or Below. */ - Tk_Window other; /* Tkwin will be moved to a position that - * puts it just above or below this window. - * If NULL then tkwin goes above or below - * all windows in the same parent. */ +Tk_RestackWindow( + Tk_Window tkwin, /* Token for window whose position in the + * stacking order is to change. */ + int aboveBelow, /* Indicates new position of tkwin relative to + * other; must be Above or Below. */ + Tk_Window other) /* Tkwin will be moved to a position that puts + * it just above or below this window. If NULL + * then tkwin goes above or below all windows + * in the same parent. */ { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *otherPtr = (TkWindow *) other; /* - * Special case: if winPtr is a top-level window then just find - * the top-level ancestor of otherPtr and restack winPtr above - * otherPtr without changing any of Tk's childLists. + * Special case: if winPtr is a top-level window then just find the + * top-level ancestor of otherPtr and restack winPtr above otherPtr + * without changing any of Tk's childLists. */ if (winPtr->flags & TK_WIN_MANAGED) { @@ -2517,7 +2523,7 @@ Tk_RestackWindow(tkwin, aboveBelow, other) if (winPtr->parentPtr == NULL) { /* - * Window is going to be deleted shortly; don't do anything. + * Window is going to be deleted shortly; don't do anything. */ return TCL_OK; @@ -2567,10 +2573,9 @@ Tk_RestackWindow(tkwin, aboveBelow, other) } /* - * Notify the X server of the change. If winPtr hasn't yet been - * created then there's no need to tell the X server now, since - * the stacking order will be handled properly when the window - * is finally created. + * Notify the X server of the change. If winPtr hasn't yet been created + * then there's no need to tell the X server now, since the stacking order + * will be handled properly when the window is finally created. */ if (winPtr->window != None) { @@ -2602,9 +2607,9 @@ Tk_RestackWindow(tkwin, aboveBelow, other) * Returns the main window for an application. * * Results: - * If interp has a Tk application associated with it, the main - * window for the application is returned. Otherwise NULL is - * returned and an error message is left in the interp's result. + * If interp has a Tk application associated with it, the main window for + * the application is returned. Otherwise NULL is returned and an error + * message is left in the interp's result. * * Side effects: * None. @@ -2613,10 +2618,9 @@ Tk_RestackWindow(tkwin, aboveBelow, other) */ Tk_Window -Tk_MainWindow(interp) - Tcl_Interp *interp; /* Interpreter that embodies the - * application. Used for error - * reporting also. */ +Tk_MainWindow( + Tcl_Interp *interp) /* Interpreter that embodies the application. + * Used for error reporting also. */ { TkMainInfo *mainPtr; ThreadSpecificData *tsdPtr; @@ -2629,7 +2633,7 @@ Tk_MainWindow(interp) return NULL; } #endif - tsdPtr = (ThreadSpecificData *) + tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL; @@ -2647,14 +2651,14 @@ Tk_MainWindow(interp) * * Tk_StrictMotif -- * - * Indicates whether strict Motif compliance has been specified - * for the given window. + * Indicates whether strict Motif compliance has been specified for the + * given window. * * Results: - * The return value is 1 if strict Motif compliance has been - * requested for tkwin's application by setting the tk_strictMotif - * variable in its interpreter to a true value. 0 is returned - * if tk_strictMotif has a false value. + * The return value is 1 if strict Motif compliance has been requested + * for tkwin's application by setting the tk_strictMotif variable in its + * interpreter to a true value. 0 is returned if tk_strictMotif has a + * false value. * * Side effects: * None. @@ -2663,9 +2667,9 @@ Tk_MainWindow(interp) */ int -Tk_StrictMotif(tkwin) - Tk_Window tkwin; /* Window whose application is - * to be checked. */ +Tk_StrictMotif( + Tk_Window tkwin) /* Window whose application is to be + * checked. */ { return ((TkWindow *) tkwin)->mainPtr->strictMotif; } @@ -2675,8 +2679,8 @@ Tk_StrictMotif(tkwin) * * Tk_GetNumMainWindows -- * - * This procedure returns the number of main windows currently - * open in this process. + * This function returns the number of main windows currently open in + * this process. * * Results: * The number of main windows open in this process. @@ -2688,7 +2692,7 @@ Tk_StrictMotif(tkwin) */ int -Tk_GetNumMainWindows() +Tk_GetNumMainWindows(void) { ThreadSpecificData *tsdPtr; @@ -2698,8 +2702,8 @@ Tk_GetNumMainWindows() } #endif - tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); return tsdPtr->numMainWindows; } @@ -2725,9 +2729,9 @@ Tk_GetNumMainWindows() */ int -TkpAlwaysShowSelection(tkwin) - Tk_Window tkwin; /* Window whose application is - * to be checked. */ +TkpAlwaysShowSelection( + Tk_Window tkwin) /* Window whose application is to be + * checked. */ { return ((TkWindow *) tkwin)->mainPtr->alwaysShowSelection; } @@ -2737,11 +2741,10 @@ TkpAlwaysShowSelection(tkwin) * * DeleteWindowsExitProc -- * - * This procedure is invoked as an exit handler. It deletes all - * of the main windows in the current thread. We really should - * be using a thread local exit handler to delete windows and a - * process exit handler to close the display but Tcl does - * not provide support for this usage. + * This function is invoked as an exit handler. It deletes all of the + * main windows in the current thread. We really should be using a thread + * local exit handler to delete windows and a process exit handler to + * close the display but Tcl does not provide support for this usage. * * Results: * None. @@ -2753,67 +2756,67 @@ TkpAlwaysShowSelection(tkwin) */ static void -DeleteWindowsExitProc(clientData) - ClientData clientData; /* tsdPtr when handler was created. */ +DeleteWindowsExitProc( + ClientData clientData) /* tsdPtr when handler was created. */ { TkDisplay *dispPtr, *nextPtr; Tcl_Interp *interp; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; + if (tsdPtr == NULL) { + return; + } + /* - * Finish destroying any windows that are in a - * half-dead state. We must protect the interpreter - * while destroying the window, because of <Destroy> - * bindings which could destroy the interpreter - * while the window is being deleted. This would - * leave frames on the call stack pointing at + * Finish destroying any windows that are in a half-dead state. We must + * protect the interpreter while destroying the window, because of + * <Destroy> bindings which could destroy the interpreter while the window + * is being deleted. This would leave frames on the call stack pointing at * deleted memory, causing core dumps. */ while (tsdPtr->halfdeadWindowList != NULL) { - interp = tsdPtr->halfdeadWindowList->winPtr->mainPtr->interp; - Tcl_Preserve((ClientData) interp); - tsdPtr->halfdeadWindowList->flags |= HD_CLEANUP; - tsdPtr->halfdeadWindowList->winPtr->flags &= ~TK_ALREADY_DEAD; - Tk_DestroyWindow((Tk_Window) tsdPtr->halfdeadWindowList->winPtr); - Tcl_Release((ClientData) interp); + interp = tsdPtr->halfdeadWindowList->winPtr->mainPtr->interp; + Tcl_Preserve((ClientData) interp); + tsdPtr->halfdeadWindowList->flags |= HD_CLEANUP; + tsdPtr->halfdeadWindowList->winPtr->flags &= ~TK_ALREADY_DEAD; + Tk_DestroyWindow((Tk_Window) tsdPtr->halfdeadWindowList->winPtr); + Tcl_Release((ClientData) interp); } /* * Destroy any remaining main windows. */ - while (tsdPtr->mainWindowList != NULL) { - interp = tsdPtr->mainWindowList->interp; - Tcl_Preserve((ClientData) interp); - Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr); - Tcl_Release((ClientData) interp); + while (tsdPtr->mainWindowList != NULL) { + interp = tsdPtr->mainWindowList->interp; + Tcl_Preserve((ClientData) interp); + Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr); + Tcl_Release((ClientData) interp); } /* - * 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 old ones. + * 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 + * old ones. */ - for (dispPtr = tsdPtr->displayList; - dispPtr != NULL; - dispPtr = tsdPtr->displayList) { - /* - * Now iterate over the current list of open displays, and first - * set the global pointer to NULL so we will be able to notice if - * any new displays got created during deletion of the current set. - * We must also do this to ensure that Tk_IdToWindow does not find - * the old display as it is being destroyed, when it wants to see - * if it needs to dispatch a message. - */ - - for (tsdPtr->displayList = NULL; dispPtr != NULL; - dispPtr = nextPtr) { - nextPtr = dispPtr->nextPtr; - TkCloseDisplay(dispPtr); - } + for (dispPtr = tsdPtr->displayList; dispPtr != NULL; + dispPtr = tsdPtr->displayList) { + /* + * Now iterate over the current list of open displays, and first set + * the global pointer to NULL so we will be able to notice if any new + * displays got created during deletion of the current set. We must + * also do this to ensure that Tk_IdToWindow does not find the old + * display as it is being destroyed, when it wants to see if it needs + * to dispatch a message. + */ + + for (tsdPtr->displayList = NULL; dispPtr != NULL; dispPtr = nextPtr) { + nextPtr = dispPtr->nextPtr; + TkCloseDisplay(dispPtr); + } } tsdPtr->numMainWindows = 0; @@ -2826,18 +2829,17 @@ DeleteWindowsExitProc(clientData) * * Tk_Init -- * - * This procedure is invoked to add Tk to an interpreter. It - * incorporates all of Tk's commands into the interpreter and - * creates the main window for a new Tk application. If the - * interpreter contains a variable "argv", this procedure - * extracts several arguments from that variable, uses them - * to configure the main window, and modifies argv to exclude - * the arguments (see the "wish" documentation for a list of - * the arguments that are extracted). + * This function is invoked to add Tk to an interpreter. It incorporates + * all of Tk's commands into the interpreter and creates the main window + * for a new Tk application. If the interpreter contains a variable + * "argv", this function extracts several arguments from that variable, + * uses them to configure the main window, and modifies argv to exclude + * the arguments (see the "wish" documentation for a list of the + * arguments that are extracted). * * Results: - * Returns a standard Tcl completion code and sets the interp's result - * if there is an error. + * Returns a standard Tcl completion code and sets the interp's result if + * there is an error. * * Side effects: * Depends on various initialization scripts that get invoked. @@ -2846,8 +2848,8 @@ DeleteWindowsExitProc(clientData) */ int -Tk_Init(interp) - Tcl_Interp *interp; /* Interpreter to initialize. */ +Tk_Init( + Tcl_Interp *interp) /* Interpreter to initialize. */ { return Initialize(interp); } @@ -2857,12 +2859,12 @@ Tk_Init(interp) * * Tk_SafeInit -- * - * This procedure is invoked to add Tk to a safe interpreter. It - * invokes the internal procedure that does the real work. + * This function is invoked to add Tk to a safe interpreter. It invokes + * the internal function that does the real work. * * Results: - * Returns a standard Tcl completion code and sets the interp's result - * if there is an error. + * Returns a standard Tcl completion code and sets the interp's result if + * there is an error. * * Side effects: * Depends on various initialization scripts that are invoked. @@ -2871,50 +2873,50 @@ Tk_Init(interp) */ int -Tk_SafeInit(interp) - Tcl_Interp *interp; /* Interpreter to initialize. */ +Tk_SafeInit( + Tcl_Interp *interp) /* Interpreter to initialize. */ { /* - * Initialize the interpreter with Tk, safely. This removes - * all the Tk commands that are unsafe. + * Initialize the interpreter with Tk, safely. This removes all the Tk + * commands that are unsafe. * * Rationale: * - * - Toplevel and menu are unsafe because they can be used to cover - * the entire screen and to steal input from the user. + * - Toplevel and menu are unsafe because they can be used to cover the + * entire screen and to steal input from the user. * - Continuous ringing of the bell is a nuisance. - * - Cannot allow access to the clipboard because a malicious script - * can replace the contents with the string "rm -r *" and lead to - * surprises when the contents of the clipboard are pasted. Similarly, - * the selection command is blocked. - * - Cannot allow send because it can be used to cause unsafe - * interpreters to execute commands. The tk command recreates the - * send command, so that too must be hidden. - * - Focus can be used to grab the focus away from another window, - * in effect stealing user input. Cannot allow that. - * NOTE: We currently do *not* hide focus as it would make it - * impossible to provide keyboard input to Tk in a safe interpreter. - * - Grab can be used to block the user from using any other apps - * on the screen. + * - Cannot allow access to the clipboard because a malicious script can + * replace the contents with the string "rm -r *" and lead to surprises + * when the contents of the clipboard are pasted. Similarly, the + * selection command is blocked. + * - Cannot allow send because it can be used to cause unsafe interpreters + * to execute commands. The tk command recreates the send command, so + * that too must be hidden. + * - Focus can be used to grab the focus away from another window, in + * effect stealing user input. Cannot allow that. + * NOTE: We currently do *not* hide focus as it would make it impossible + * to provide keyboard input to Tk in a safe interpreter. + * - Grab can be used to block the user from using any other apps on the + * screen. * - Tkwait can block the containing process forever. Use bindings, * fileevents and split the protocol into before-the-wait and * after-the-wait parts. More work but necessary. - * - Wm is unsafe because (if toplevels are allowed, in the future) - * it can be used to remove decorations, move windows around, cover - * the entire screen etc etc. + * - Wm is unsafe because (if toplevels are allowed, in the future) it can + * be used to remove decorations, move windows around, cover the entire + * screen etc etc. * * Current risks: * * - No CPU time limit, no memory allocation limits, no color limits. + * CPU time limits can be imposed by an unsafe master interpreter. * - * The actual code called is the same as Tk_Init but Tcl_IsSafe() - * is checked at several places to differentiate the two initialisations. + * The actual code called is the same as Tk_Init but Tcl_IsSafe() is + * checked at several places to differentiate the two initialisations. */ return Initialize(interp); } - extern TkStubs tkStubs; /* @@ -2922,6 +2924,7 @@ extern TkStubs tkStubs; * * Initialize -- * + * ???TODO??? * * Results: * A standard Tcl result. Also leaves an error message in the interp's @@ -2934,33 +2937,34 @@ extern TkStubs tkStubs; */ static int -Initialize(interp) - Tcl_Interp *interp; /* Interpreter to initialize. */ +Initialize( + Tcl_Interp *interp) /* Interpreter to initialize. */ { char *p; int argc, code; - CONST char **argv; + CONST char **argv; char *args[20]; CONST char *argString = NULL; Tcl_DString class; ThreadSpecificData *tsdPtr; - + /* - * Ensure that we are getting the matching version of Tcl. This is - * really only an issue when Tk is loaded dynamically. + * Ensure that we are getting the matching version of Tcl. This is really + * only an issue when Tk is loaded dynamically. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) { - return TCL_ERROR; + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { + return TCL_ERROR; } /* * Ensure that our obj-types are registered with the Tcl runtime. */ + TkRegisterObjTypes(); - tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Start by initializing all the static variables to default acceptable @@ -2982,27 +2986,30 @@ Initialize(interp) /* * We start by resetting the result because it might not be clean */ + Tcl_ResetResult(interp); if (Tcl_IsSafe(interp)) { /* - * Get the clearance to start Tk and the "argv" parameters - * from the master. + * Get the clearance to start Tk and the "argv" parameters from the + * 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 while walking, but there - * is no API to get the name of an interp either. + * 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 + * while walking, but there is no API to get the name of an interp + * either. */ + Tcl_Interp *master = interp; while (1) { master = Tcl_GetMaster(master); if (master == NULL) { - Tcl_AppendResult(interp, "NULL master", (char *) NULL); + Tcl_AppendResult(interp, "NULL master", NULL); code = TCL_ERROR; goto done; } @@ -3011,59 +3018,65 @@ Initialize(interp) break; } } + /* * Construct the name (rewalk...) */ - if ((code = Tcl_GetInterpPath(master, interp)) != TCL_OK) { - Tcl_AppendResult(interp, "error in Tcl_GetInterpPath", - (char *) NULL); + + code = Tcl_GetInterpPath(master, interp); + if (code != TCL_OK) { + Tcl_AppendResult(interp, "error in Tcl_GetInterpPath", NULL); goto done; } + /* * Build the string to eval. */ + Tcl_DStringInit(&ds); Tcl_DStringAppendElement(&ds, "::safe::TkInit"); Tcl_DStringAppendElement(&ds, Tcl_GetStringResult(master)); /* - * Step 2 : Eval in the master. The argument is the *reversed* - * interp path of the slave. + * Step 2 : Eval in the master. The argument is the *reversed* interp + * path of the slave. */ - if ((code = Tcl_Eval(master, Tcl_DStringValue(&ds))) != TCL_OK) { + code = Tcl_Eval(master, Tcl_DStringValue(&ds)); + 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). + * 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_AppendResult(interp, - "not allowed to start Tk by master's safe::TkInit", - (char *) NULL); + Tcl_AppendResult(interp, + "not allowed to start Tk by master's safe::TkInit", NULL); goto done; } Tcl_DStringFree(&ds); - /* - * Use the master's result as argv. - * Note: We don't use the Obj interfaces to avoid dealing with - * cross interp refcounting and changing the code below. + + /* + * Use the master's result as argv. Note: We don't use the Obj + * interfaces to avoid dealing with cross interp refcounting and + * changing the code below. */ argString = Tcl_GetStringResult(master); } else { /* - * If there is an "argv" variable, get its value, extract out - * relevant arguments from it, and rewrite the variable without - * the arguments that we used. + * If there is an "argv" variable, get its value, extract out relevant + * arguments from it, and rewrite the variable without the arguments + * that we used. */ - argString = Tcl_GetVar2(interp, "argv", (char *) NULL, TCL_GLOBAL_ONLY); + argString = Tcl_GetVar2(interp, "argv", NULL, TCL_GLOBAL_ONLY); } if (argString != NULL) { char buffer[TCL_INTEGER_SPACE]; if (Tcl_SplitList(interp, argString, &argc, &argv) != TCL_OK) { - argError: + argError: Tcl_AddErrorInfo(interp, "\n (processing arguments in argv variable)"); code = TCL_ERROR; @@ -3075,9 +3088,9 @@ Initialize(interp) goto argError; } p = Tcl_Merge(argc, argv); - Tcl_SetVar2(interp, "argv", (char *) NULL, p, TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "argv", NULL, p, TCL_GLOBAL_ONLY); sprintf(buffer, "%d", argc); - Tcl_SetVar2(interp, "argc", (char *) NULL, buffer, TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "argc", NULL, buffer, TCL_GLOBAL_ONLY); ckfree(p); } @@ -3088,6 +3101,7 @@ Initialize(interp) Tcl_DStringInit(&class); if (name == NULL) { int offset; + TkpGetAppName(interp, &class); offset = Tcl_DStringLength(&class)+1; Tcl_DStringSetLength(&class, offset); @@ -3103,8 +3117,8 @@ Initialize(interp) } /* - * Create an argument list for creating the top-level window, - * using the information parsed from argv, if any. + * Create an argument list for creating the top-level window, using the + * information parsed from argv, if any. */ args[0] = "toplevel"; @@ -3118,9 +3132,9 @@ Initialize(interp) argc += 2; /* - * If this is the first application for this process, save - * the display name in the DISPLAY environment variable so - * that it will be available to subprocesses created by us. + * If this is the first application for this process, save the display + * name in the DISPLAY environment variable so that it will be + * available to subprocesses created by us. */ if (tsdPtr->numMainWindows == 0) { @@ -3131,19 +3145,19 @@ Initialize(interp) args[argc] = "-colormap"; args[argc+1] = colormap; argc += 2; - colormap = NULL; + colormap = NULL; } if (use != NULL) { args[argc] = "-use"; args[argc+1] = use; argc += 2; - use = NULL; + use = NULL; } if (visual != NULL) { args[argc] = "-visual"; args[argc+1] = visual; argc += 2; - visual = NULL; + visual = NULL; } args[argc] = NULL; code = TkCreateFrame((ClientData) NULL, interp, argc, args, 1, name); @@ -3158,20 +3172,20 @@ Initialize(interp) } /* - * Set the geometry of the main window, if requested. Put the - * requested geometry into the "geometry" variable. + * Set the geometry of the main window, if requested. Put the requested + * geometry into the "geometry" variable. */ if (geometry != NULL) { Tcl_SetVar(interp, "geometry", geometry, TCL_GLOBAL_ONLY); - code = Tcl_VarEval(interp, "wm geometry . ", geometry, (char *) NULL); + code = Tcl_VarEval(interp, "wm geometry . ", geometry, NULL); if (code != TCL_OK) { goto done; } - geometry = NULL; + geometry = NULL; } - if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) { + if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) { code = TCL_ERROR; goto done; } @@ -3180,21 +3194,21 @@ Initialize(interp) * Provide Tk and its stub table. */ - code = Tcl_PkgProvideEx(interp, "Tk", TK_VERSION, (ClientData) &tkStubs); + code = Tcl_PkgProvideEx(interp, "Tk", TK_PATCH_LEVEL, + (ClientData) &tkStubs); if (code != TCL_OK) { goto done; - } else { - /* - * If we were able to provide ourselves as a package, then set - * the main loop procedure in Tcl to our main loop proc. This - * will cause tclsh to be event-aware when Tk is dynamically - * loaded. This will have no effect in wish, which already is - * prepared to run the event loop. - */ - - Tcl_SetMainLoop(Tk_MainLoop); } + /* + * If we were able to provide ourselves as a package, then set the main + * loop function in Tcl to our main loop proc. This will cause tclsh to be + * event-aware when Tk is dynamically loaded. This will have no effect in + * wish, which already is prepared to run the event loop. + */ + + Tcl_SetMainLoop(Tk_MainLoop); + #ifdef Tk_InitStubs #undef Tk_InitStubs #endif @@ -3202,21 +3216,116 @@ Initialize(interp) Tk_InitStubs(interp, TK_VERSION, 1); /* - * Invoke platform-specific initialization. - * Unlock mutex before entering TkpInit, as that may run through the - * Tk_Init routine again for the console window interpreter. + * Initialized the themed widget set + */ + + code = Ttk_Init(interp); + if (code != TCL_OK) { + goto done; + } + + /* + * Invoke platform-specific initialization. Unlock mutex before entering + * TkpInit, as that may run through the Tk_Init routine again for the + * console window interpreter. */ Tcl_MutexUnlock(&windowMutex); if (argv != NULL) { ckfree((char *) argv); } - return TkpInit(interp); + code = TkpInit(interp); + if (code == TCL_OK) { - done: + /* + * In order to find tk.tcl during initialization, we evaluate the + * following script. It calls on the Tcl command [tcl_findLibrary] + * to perform the search. See the docs for that command for details + * on where it looks. + * + * Note that this entire search mechanism can be bypassed by defining + * an alternate [tkInit] command before calling Tk_Init(). + */ + + code = Tcl_Eval(interp, +"if {[namespace which -command tkInit] eq \"\"} {\n\ + proc tkInit {} {\n\ + global tk_library tk_version tk_patchLevel\n\ + rename tkInit {}\n\ + tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\ + }\n\ +}\n\ +tkInit"); + } + if (code == TCL_OK) { + /* + * Create exit handlers to delete all windows when the application or + * thread exits. The handler need to be invoked before other platform + * specific cleanups take place to avoid panics in finalization. + */ + + TkCreateThreadExitHandler(DeleteWindowsExitProc, (ClientData) tsdPtr); + } + return code; + + done: Tcl_MutexUnlock(&windowMutex); if (argv != NULL) { ckfree((char *) argv); } return code; } + +/* + *---------------------------------------------------------------------- + * + * Tk_PkgInitStubsCheck -- + * + * This is a replacement routine for Tk_InitStubs() that is called + * from code where -DUSE_TK_STUBS has not been enabled. + * + * Results: + * Returns the version of a conforming Tk stubs table, or NULL, if + * the table version doesn't satisfy the requested requirements, + * according to historical practice. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +CONST char * +Tk_PkgInitStubsCheck( + Tcl_Interp *interp, + CONST char * version, + int exact) +{ + CONST char *actualVersion = Tcl_PkgRequire(interp, "Tk", version, 0); + + if (exact && actualVersion) { + CONST char *p = version; + int count = 0; + + while (*p) { + count += !isdigit(UCHAR(*p++)); + } + if (count == 1) { + if (0 != strncmp(version, actualVersion, strlen(version))) { + /* Construct error message */ + Tcl_PkgPresent(interp, "Tk", version, 1); + return NULL; + } + } else { + return Tcl_PkgPresent(interp, "Tk", version, 1); + } + } + return actualVersion; +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ diff --git a/generic/ttk/ttk.decls b/generic/ttk/ttk.decls new file mode 100644 index 0000000..8b2b50b --- /dev/null +++ b/generic/ttk/ttk.decls @@ -0,0 +1,150 @@ +library ttk +interface ttk +epoch 0 +scspec TTKAPI + +declare 0 current { + Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name); +} +declare 1 current { + Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp); +} +declare 2 current { + Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp); +} +declare 3 current { + Ttk_Theme Ttk_CreateTheme( + Tcl_Interp *interp, const char *name, Ttk_Theme parent); +} +declare 4 current { + void Ttk_RegisterCleanup( + Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc); +} + +declare 5 current { + int Ttk_RegisterElementSpec( + Ttk_Theme theme, + const char *elementName, + Ttk_ElementSpec *elementSpec, + void *clientData); +} + +declare 6 current { + Ttk_ElementClass *Ttk_RegisterElement( + Tcl_Interp *interp, + Ttk_Theme theme, + const char *elementName, + Ttk_ElementSpec *elementSpec, + void *clientData); +} + +declare 7 current { + int Ttk_RegisterElementFactory( + Tcl_Interp *interp, + const char *name, + Ttk_ElementFactory factoryProc, + void *clientData); +} + +declare 8 current { + void Ttk_RegisterLayout( + Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec); +} + +# +# State maps. +# +declare 10 current { + int Ttk_GetStateSpecFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn); +} +declare 11 current { + Tcl_Obj *Ttk_NewStateSpecObj( + unsigned int onbits, unsigned int offbits); +} +declare 12 current { + Ttk_StateMap Ttk_GetStateMapFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr); +} +declare 13 current { + Tcl_Obj *Ttk_StateMapLookup( + Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state); +} +declare 14 current { + int Ttk_StateTableLookup( + Ttk_StateTable map[], Ttk_State state); +} + + +# +# Low-level geometry utilities. +# +declare 20 current { + int Ttk_GetPaddingFromObj( + Tcl_Interp *interp, + Tk_Window tkwin, + Tcl_Obj *objPtr, + Ttk_Padding *pad_rtn); +} +declare 21 current { + int Ttk_GetBorderFromObj( + Tcl_Interp *interp, + Tcl_Obj *objPtr, + Ttk_Padding *pad_rtn); +} +declare 22 current { + int Ttk_GetStickyFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn); +} +declare 23 current { + Ttk_Padding Ttk_MakePadding( + short l, short t, short r, short b); +} +declare 24 current { + Ttk_Padding Ttk_UniformPadding( + short borderWidth); +} +declare 25 current { + Ttk_Padding Ttk_AddPadding(Ttk_Padding pad1, Ttk_Padding pad2); +} +declare 26 current { + Ttk_Padding Ttk_RelievePadding( + Ttk_Padding padding, int relief, int n); +} +declare 27 current { + Ttk_Box Ttk_MakeBox(int x, int y, int width, int height); +} +declare 28 current { + int Ttk_BoxContains(Ttk_Box box, int x, int y); +} +declare 29 current { + Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, Ttk_Side side); +} +declare 30 current { + Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, Ttk_Sticky sticky); +} +declare 31 current { + Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, Tk_Anchor anchor); +} +declare 32 current { + Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p); +} +declare 33 current { + Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p); +} +declare 34 current { + Ttk_Box Ttk_PlaceBox( + Ttk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky); +} +declare 35 current { + Tcl_Obj *Ttk_NewBoxObj(Ttk_Box box); +} + +# +# Utilities. +# +declare 40 current { + int Ttk_GetOrientFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient); +} + + diff --git a/generic/ttk/ttkBlink.c b/generic/ttk/ttkBlink.c new file mode 100644 index 0000000..7e46fac --- /dev/null +++ b/generic/ttk/ttkBlink.c @@ -0,0 +1,166 @@ +/* + * Copyright 2004, Joe English. + * + * Usage: + * TtkBlinkCursor(corePtr), usually called in a widget's Init hook, + * arranges to periodically toggle the corePtr->flags CURSOR_ON bit + * on and off (and schedule a redisplay) whenever the widget has focus. + * + * Note: Widgets may have additional logic to decide whether + * to display the cursor or not (e.g., readonly or disabled states); + * TtkBlinkCursor() does not account for this. + * + * TODO: + * Add script-level access to configure application-wide blink rate. + */ + +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +#define DEF_CURSOR_ON_TIME 600 /* milliseconds */ +#define DEF_CURSOR_OFF_TIME 300 /* milliseconds */ + +/* Interp-specific data for tracking cursors: + */ +typedef struct +{ + WidgetCore *owner; /* Widget that currently has cursor */ + Tcl_TimerToken timer; /* Blink timer */ + int onTime; /* #milliseconds to blink cursor on */ + int offTime; /* #milliseconds to blink cursor off */ +} CursorManager; + +/* CursorManagerDeleteProc -- + * InterpDeleteProc for cursor manager. + */ +static void CursorManagerDeleteProc(ClientData clientData, Tcl_Interp *interp) +{ + CursorManager *cm = (CursorManager*)clientData; + if (cm->timer) { + Tcl_DeleteTimerHandler(cm->timer); + } + ckfree(clientData); +} + +/* GetCursorManager -- + * Look up and create if necessary the interp's cursor manager. + */ +static CursorManager *GetCursorManager(Tcl_Interp *interp) +{ + static const char *cm_key = "ttk::CursorManager"; + CursorManager *cm = (CursorManager *) Tcl_GetAssocData(interp, cm_key,0); + + if (!cm) { + cm = (CursorManager*)ckalloc(sizeof(*cm)); + cm->timer = 0; + cm->owner = 0; + cm->onTime = DEF_CURSOR_ON_TIME; + cm->offTime = DEF_CURSOR_OFF_TIME; + Tcl_SetAssocData(interp,cm_key,CursorManagerDeleteProc,(ClientData)cm); + } + return cm; +} + +/* CursorBlinkProc -- + * Timer handler to blink the insert cursor on and off. + */ +static void +CursorBlinkProc(ClientData clientData) +{ + CursorManager *cm = (CursorManager*)clientData; + int blinkTime; + + if (cm->owner->flags & CURSOR_ON) { + cm->owner->flags &= ~CURSOR_ON; + blinkTime = cm->offTime; + } else { + cm->owner->flags |= CURSOR_ON; + blinkTime = cm->onTime; + } + cm->timer = Tcl_CreateTimerHandler(blinkTime, CursorBlinkProc, clientData); + TtkRedisplayWidget(cm->owner); +} + +/* LoseCursor -- + * Turn cursor off, disable blink timer. + */ +static void LoseCursor(CursorManager *cm, WidgetCore *corePtr) +{ + if (corePtr->flags & CURSOR_ON) { + corePtr->flags &= ~CURSOR_ON; + TtkRedisplayWidget(corePtr); + } + if (cm->owner == corePtr) { + cm->owner = NULL; + } + if (cm->timer) { + Tcl_DeleteTimerHandler(cm->timer); + cm->timer = 0; + } +} + +/* ClaimCursor -- + * Claim ownership of the insert cursor and blink on. + */ +static void ClaimCursor(CursorManager *cm, WidgetCore *corePtr) +{ + if (cm->owner == corePtr) + return; + if (cm->owner) + LoseCursor(cm, cm->owner); + + corePtr->flags |= CURSOR_ON; + TtkRedisplayWidget(corePtr); + + cm->owner = corePtr; + cm->timer = Tcl_CreateTimerHandler(cm->onTime, CursorBlinkProc, cm); +} + +/* + * CursorEventProc -- + * Event handler for FocusIn and FocusOut events; + * claim/lose ownership of the insert cursor when the widget + * acquires/loses keyboard focus. + */ + +#define CursorEventMask (FocusChangeMask|StructureNotifyMask) +#define RealFocusEvent(d) \ + (d == NotifyInferior || d == NotifyAncestor || d == NotifyNonlinear) + +static void +CursorEventProc(ClientData clientData, XEvent *eventPtr) +{ + WidgetCore *corePtr = (WidgetCore *)clientData; + CursorManager *cm = GetCursorManager(corePtr->interp); + + switch (eventPtr->type) { + case DestroyNotify: + if (cm->owner == corePtr) + LoseCursor(cm, corePtr); + Tk_DeleteEventHandler( + corePtr->tkwin, CursorEventMask, CursorEventProc, clientData); + break; + case FocusIn: + if (RealFocusEvent(eventPtr->xfocus.detail)) + ClaimCursor(cm, corePtr); + break; + case FocusOut: + if (RealFocusEvent(eventPtr->xfocus.detail)) + LoseCursor(cm, corePtr); + break; + } +} + +/* + * TtkBlinkCursor (main routine) -- + * Arrange to blink the cursor on and off whenever the + * widget has focus. + */ +void TtkBlinkCursor(WidgetCore *corePtr) +{ + Tk_CreateEventHandler( + corePtr->tkwin, CursorEventMask, CursorEventProc, corePtr); +} + +/*EOF*/ diff --git a/generic/ttk/ttkButton.c b/generic/ttk/ttkButton.c new file mode 100644 index 0000000..2954184 --- /dev/null +++ b/generic/ttk/ttkButton.c @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2003, Joe English + * + * label, button, checkbutton, radiobutton, and menubutton widgets. + */ + +#include <string.h> +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +/* Bit fields for OptionSpec mask field: + */ +#define STATE_CHANGED (0x100) /* -state option changed */ +#define DEFAULTSTATE_CHANGED (0x200) /* -default option changed */ + +/*------------------------------------------------------------------------ + * +++ Base resources for labels, buttons, checkbuttons, etc: + */ +typedef struct +{ + /* + * Text element resources: + */ + Tcl_Obj *textObj; + Tcl_Obj *textVariableObj; + Tcl_Obj *underlineObj; + Tcl_Obj *widthObj; + + Ttk_TraceHandle *textVariableTrace; + Ttk_ImageSpec *imageSpec; + + /* + * Image element resources: + */ + Tcl_Obj *imageObj; + + /* + * Compound label/image resources: + */ + Tcl_Obj *compoundObj; + Tcl_Obj *paddingObj; + + /* + * Compatibility/legacy options: + */ + Tcl_Obj *stateObj; + +} BasePart; + +typedef struct +{ + WidgetCore core; + BasePart base; +} Base; + +static Tk_OptionSpec BaseOptionSpecs[] = +{ + {TK_OPTION_STRING, "-text", "text", "Text", "", + Tk_Offset(Base,base.textObj), -1, + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", "", + Tk_Offset(Base,base.textVariableObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-underline", "underline", "Underline", + "-1", Tk_Offset(Base,base.underlineObj), -1, + 0,0,0 }, + /* SB: OPTION_INT, see <<NOTE-NULLOPTIONS>> */ + {TK_OPTION_STRING, "-width", "width", "Width", + NULL, Tk_Offset(Base,base.widthObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + + /* + * Image options + */ + {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/, + Tk_Offset(Base,base.imageObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + + /* + * Compound base/image options + */ + {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", + "none", Tk_Offset(Base,base.compoundObj), -1, + 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-padding", "padding", "Pad", + NULL, Tk_Offset(Base,base.paddingObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED}, + + /* + * Compatibility/legacy options + */ + {TK_OPTION_STRING, "-state", "state", "State", + "normal", Tk_Offset(Base,base.stateObj), -1, + 0,0,STATE_CHANGED }, + + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/* + * Variable trace procedure for -textvariable option: + */ +static void TextVariableChanged(void *clientData, const char *value) +{ + Base *basePtr = clientData; + Tcl_Obj *newText; + + if (WidgetDestroyed(&basePtr->core)) { + return; + } + + newText = value ? Tcl_NewStringObj(value, -1) : Tcl_NewStringObj("", 0); + + Tcl_IncrRefCount(newText); + Tcl_DecrRefCount(basePtr->base.textObj); + basePtr->base.textObj = newText; + + TtkResizeWidget(&basePtr->core); +} + +static void +BaseInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Base *basePtr = recordPtr; + basePtr->base.textVariableTrace = 0; + basePtr->base.imageSpec = NULL; +} + +static void +BaseCleanup(void *recordPtr) +{ + Base *basePtr = recordPtr; + if (basePtr->base.textVariableTrace) + Ttk_UntraceVariable(basePtr->base.textVariableTrace); + if (basePtr->base.imageSpec) + TtkFreeImageSpec(basePtr->base.imageSpec); +} + +static int BaseConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Base *basePtr = recordPtr; + Tcl_Obj *textVarName = basePtr->base.textVariableObj; + Ttk_TraceHandle *vt = 0; + Ttk_ImageSpec *imageSpec = NULL; + + if (textVarName != NULL && *Tcl_GetString(textVarName) != '\0') { + vt = Ttk_TraceVariable(interp,textVarName,TextVariableChanged,basePtr); + if (!vt) return TCL_ERROR; + } + + if (basePtr->base.imageObj) { + imageSpec = TtkGetImageSpec( + interp, basePtr->core.tkwin, basePtr->base.imageObj); + if (!imageSpec) { + goto error; + } + } + + if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) { +error: + if (imageSpec) TtkFreeImageSpec(imageSpec); + if (vt) Ttk_UntraceVariable(vt); + return TCL_ERROR; + } + + if (basePtr->base.textVariableTrace) { + Ttk_UntraceVariable(basePtr->base.textVariableTrace); + } + basePtr->base.textVariableTrace = vt; + + if (basePtr->base.imageSpec) { + TtkFreeImageSpec(basePtr->base.imageSpec); + } + basePtr->base.imageSpec = imageSpec; + + if (mask & STATE_CHANGED) { + TtkCheckStateOption(&basePtr->core, basePtr->base.stateObj); + } + + return TCL_OK; +} + +static int +BasePostConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Base *basePtr = recordPtr; + int status = TCL_OK; + + if (basePtr->base.textVariableTrace) { + status = Ttk_FireTrace(basePtr->base.textVariableTrace); + } + + return status; +} + +/*------------------------------------------------------------------------ + * +++ Label widget. + * Just a base widget that adds a few appearance-related options + */ + +typedef struct +{ + Tcl_Obj *backgroundObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *fontObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *anchorObj; + Tcl_Obj *justifyObj; + Tcl_Obj *wrapLengthObj; +} LabelPart; + +typedef struct +{ + WidgetCore core; + BasePart base; + LabelPart label; +} Label; + +static Tk_OptionSpec LabelOptionSpecs[] = +{ + {TK_OPTION_BORDER, "-background", "frameColor", "FrameColor", + NULL, Tk_Offset(Label,label.backgroundObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", + NULL, Tk_Offset(Label,label.foregroundObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_FONT, "-font", "font", "Font", + NULL, Tk_Offset(Label,label.fontObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", + NULL, Tk_Offset(Label,label.borderWidthObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", + NULL, Tk_Offset(Label,label.reliefObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", + NULL, Tk_Offset(Label,label.anchorObj), -1, + TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + NULL, Tk_Offset(Label, label.justifyObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", + NULL, Tk_Offset(Label, label.wrapLengthObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED /*SB: SIZE_CHANGED*/ }, + + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) +}; + +static const Ttk_Ensemble LabelCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec LabelWidgetSpec = +{ + "TLabel", /* className */ + sizeof(Label), /* recordSize */ + LabelOptionSpecs, /* optionSpecs */ + LabelCommands, /* subcommands */ + BaseInitialize, /* initializeProc */ + BaseCleanup, /* cleanupProc */ + BaseConfigure, /* configureProc */ + BasePostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(LabelLayout) + TTK_GROUP("Label.border", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("Label.padding", TTK_FILL_BOTH|TTK_BORDER, + TTK_NODE("Label.label", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Button widget. + * Adds a new subcommand "invoke", and options "-command" and "-default" + */ + +typedef struct +{ + Tcl_Obj *commandObj; + Tcl_Obj *defaultStateObj; +} ButtonPart; + +typedef struct +{ + WidgetCore core; + BasePart base; + ButtonPart button; +} Button; + +/* + * Option specifications: + */ +static Tk_OptionSpec ButtonOptionSpecs[] = +{ + {TK_OPTION_STRING, "-command", "command", "Command", + "", Tk_Offset(Button, button.commandObj), -1, 0,0,0}, + {TK_OPTION_STRING_TABLE, "-default", "default", "Default", + "normal", Tk_Offset(Button, button.defaultStateObj), -1, + 0, (ClientData) ttkDefaultStrings, DEFAULTSTATE_CHANGED}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) +}; + +static int ButtonConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Button *buttonPtr = recordPtr; + + if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) { + return TCL_ERROR; + } + + /* Handle "-default" option: + */ + if (mask & DEFAULTSTATE_CHANGED) { + int defaultState = TTK_BUTTON_DEFAULT_DISABLED; + Ttk_GetButtonDefaultStateFromObj( + NULL, buttonPtr->button.defaultStateObj, &defaultState); + if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) { + TtkWidgetChangeState(&buttonPtr->core, TTK_STATE_ALTERNATE, 0); + } else { + TtkWidgetChangeState(&buttonPtr->core, 0, TTK_STATE_ALTERNATE); + } + } + return TCL_OK; +} + +/* $button invoke -- + * Evaluate the button's -command. + */ +static int +ButtonInvokeCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Button *buttonPtr = recordPtr; + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "invoke"); + return TCL_ERROR; + } + if (buttonPtr->core.state & TTK_STATE_DISABLED) { + return TCL_OK; + } + return Tcl_EvalObjEx(interp, buttonPtr->button.commandObj, TCL_EVAL_GLOBAL); +} + +static const Ttk_Ensemble ButtonCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "invoke", ButtonInvokeCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec ButtonWidgetSpec = +{ + "TButton", /* className */ + sizeof(Button), /* recordSize */ + ButtonOptionSpecs, /* optionSpecs */ + ButtonCommands, /* subcommands */ + BaseInitialize, /* initializeProc */ + BaseCleanup, /* cleanupProc */ + ButtonConfigure, /* configureProc */ + BasePostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(ButtonLayout) + TTK_GROUP("Button.border", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("Button.focus", TTK_FILL_BOTH, + TTK_GROUP("Button.padding", TTK_FILL_BOTH, + TTK_NODE("Button.label", TTK_FILL_BOTH)))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Checkbutton widget. + */ +typedef struct +{ + Tcl_Obj *variableObj; + Tcl_Obj *onValueObj; + Tcl_Obj *offValueObj; + Tcl_Obj *commandObj; + + Ttk_TraceHandle *variableTrace; + +} CheckbuttonPart; + +typedef struct +{ + WidgetCore core; + BasePart base; + CheckbuttonPart checkbutton; +} Checkbutton; + +/* + * Option specifications: + */ +static Tk_OptionSpec CheckbuttonOptionSpecs[] = +{ + {TK_OPTION_STRING, "-variable", "variable", "Variable", + "", Tk_Offset(Checkbutton, checkbutton.variableObj), -1, + TK_OPTION_DONT_SET_DEFAULT,0,0}, + {TK_OPTION_STRING, "-onvalue", "onValue", "OnValue", + "1", Tk_Offset(Checkbutton, checkbutton.onValueObj), -1, + 0,0,0}, + {TK_OPTION_STRING, "-offvalue", "offValue", "OffValue", + "0", Tk_Offset(Checkbutton, checkbutton.offValueObj), -1, + 0,0,0}, + {TK_OPTION_STRING, "-command", "command", "Command", + "", Tk_Offset(Checkbutton, checkbutton.commandObj), -1, + 0,0,0}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) +}; + +/* + * Variable trace procedure for checkbutton -variable option + */ +static void CheckbuttonVariableChanged(void *clientData, const char *value) +{ + Checkbutton *checkPtr = clientData; + + if (WidgetDestroyed(&checkPtr->core)) { + return; + } + + if (!value) { + TtkWidgetChangeState(&checkPtr->core, TTK_STATE_ALTERNATE, 0); + return; + } + /* else */ + TtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_ALTERNATE); + if (!strcmp(value, Tcl_GetString(checkPtr->checkbutton.onValueObj))) { + TtkWidgetChangeState(&checkPtr->core, TTK_STATE_SELECTED, 0); + } else { + TtkWidgetChangeState(&checkPtr->core, 0, TTK_STATE_SELECTED); + } +} + +static void +CheckbuttonInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Checkbutton *checkPtr = recordPtr; + Tcl_Obj *variableObj; + + /* default -variable is the widget name: + */ + variableObj = Tcl_NewStringObj(Tk_PathName(checkPtr->core.tkwin), -1); + Tcl_IncrRefCount(variableObj); + checkPtr->checkbutton.variableObj = variableObj; + BaseInitialize(interp, recordPtr); +} + +static void +CheckbuttonCleanup(void *recordPtr) +{ + Checkbutton *checkPtr = recordPtr; + Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace); + checkPtr->checkbutton.variableTrace = 0; + BaseCleanup(recordPtr); +} + +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; + } + + if (BaseConfigure(interp, recordPtr, mask) != TCL_OK){ + Ttk_UntraceVariable(vt); + return TCL_ERROR; + } + + Ttk_UntraceVariable(checkPtr->checkbutton.variableTrace); + checkPtr->checkbutton.variableTrace = vt; + + return TCL_OK; +} + +static int +CheckbuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Checkbutton *checkPtr = recordPtr; + int status = TCL_OK; + + if (checkPtr->checkbutton.variableTrace) + status = Ttk_FireTrace(checkPtr->checkbutton.variableTrace); + if (status == TCL_OK && !WidgetDestroyed(&checkPtr->core)) + status = BasePostConfigure(interp, recordPtr, mask); + return status; +} + +/* + * Checkbutton 'invoke' subcommand: + * Toggles the checkbutton state. + */ +static int +CheckbuttonInvokeCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Checkbutton *checkPtr = recordPtr; + WidgetCore *corePtr = &checkPtr->core; + Tcl_Obj *newValue; + + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "invoke"); + return TCL_ERROR; + } + if (corePtr->state & TTK_STATE_DISABLED) + return TCL_OK; + + /* + * Toggle the selected state. + */ + if (corePtr->state & TTK_STATE_SELECTED) + newValue = checkPtr->checkbutton.offValueObj; + else + newValue = checkPtr->checkbutton.onValueObj; + + if (Tcl_ObjSetVar2(interp, + checkPtr->checkbutton.variableObj, NULL, newValue, + TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) + == NULL) + return TCL_ERROR; + + if (WidgetDestroyed(corePtr)) + return TCL_ERROR; + + return Tcl_EvalObjEx(interp, + checkPtr->checkbutton.commandObj, TCL_EVAL_GLOBAL); +} + +static const Ttk_Ensemble CheckbuttonCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "invoke", CheckbuttonInvokeCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + /* MISSING: select, deselect, toggle */ + { 0,0,0 } +}; + +static WidgetSpec CheckbuttonWidgetSpec = +{ + "TCheckbutton", /* className */ + sizeof(Checkbutton), /* recordSize */ + CheckbuttonOptionSpecs, /* optionSpecs */ + CheckbuttonCommands, /* subcommands */ + CheckbuttonInitialize, /* initializeProc */ + CheckbuttonCleanup, /* cleanupProc */ + CheckbuttonConfigure, /* configureProc */ + CheckbuttonPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(CheckbuttonLayout) + TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, + TTK_NODE("Checkbutton.indicator", TTK_PACK_LEFT) + TTK_GROUP("Checkbutton.focus", TTK_PACK_LEFT | TTK_STICK_W, + TTK_NODE("Checkbutton.label", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Radiobutton widget. + */ + +typedef struct +{ + Tcl_Obj *variableObj; + Tcl_Obj *valueObj; + Tcl_Obj *commandObj; + + Ttk_TraceHandle *variableTrace; + +} RadiobuttonPart; + +typedef struct +{ + WidgetCore core; + BasePart base; + RadiobuttonPart radiobutton; +} Radiobutton; + +/* + * Option specifications: + */ +static Tk_OptionSpec RadiobuttonOptionSpecs[] = +{ + {TK_OPTION_STRING, "-variable", "variable", "Variable", + "::selectedButton", Tk_Offset(Radiobutton, radiobutton.variableObj),-1, + 0,0,0}, + {TK_OPTION_STRING, "-value", "Value", "Value", + "1", Tk_Offset(Radiobutton, radiobutton.valueObj), -1, + 0,0,0}, + {TK_OPTION_STRING, "-command", "command", "Command", + "", Tk_Offset(Radiobutton, radiobutton.commandObj), -1, + 0,0,0}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) +}; + +/* + * Variable trace procedure for radiobuttons. + */ +static void +RadiobuttonVariableChanged(void *clientData, const char *value) +{ + Radiobutton *radioPtr = clientData; + + if (WidgetDestroyed(&radioPtr->core)) { + return; + } + + if (!value) { + TtkWidgetChangeState(&radioPtr->core, TTK_STATE_ALTERNATE, 0); + return; + } + /* else */ + TtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_ALTERNATE); + if (!strcmp(value, Tcl_GetString(radioPtr->radiobutton.valueObj))) { + TtkWidgetChangeState(&radioPtr->core, TTK_STATE_SELECTED, 0); + } else { + TtkWidgetChangeState(&radioPtr->core, 0, TTK_STATE_SELECTED); + } +} + +static void +RadiobuttonCleanup(void *recordPtr) +{ + Radiobutton *radioPtr = recordPtr; + Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace); + radioPtr->radiobutton.variableTrace = 0; + BaseCleanup(recordPtr); +} + +static int +RadiobuttonConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Radiobutton *radioPtr = recordPtr; + Ttk_TraceHandle *vt = Ttk_TraceVariable( + interp, radioPtr->radiobutton.variableObj, + RadiobuttonVariableChanged, radioPtr); + + if (!vt) { + return TCL_ERROR; + } + + if (BaseConfigure(interp, recordPtr, mask) != TCL_OK) { + Ttk_UntraceVariable(vt); + return TCL_ERROR; + } + + Ttk_UntraceVariable(radioPtr->radiobutton.variableTrace); + radioPtr->radiobutton.variableTrace = vt; + + return TCL_OK; +} + +static int +RadiobuttonPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Radiobutton *radioPtr = recordPtr; + int status = TCL_OK; + + if (radioPtr->radiobutton.variableTrace) + status = Ttk_FireTrace(radioPtr->radiobutton.variableTrace); + if (status == TCL_OK && !WidgetDestroyed(&radioPtr->core)) + status = BasePostConfigure(interp, recordPtr, mask); + return status; +} + +/* + * Radiobutton 'invoke' subcommand: + * Sets the radiobutton -variable to the -value, evaluates the -command. + */ +static int +RadiobuttonInvokeCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Radiobutton *radioPtr = recordPtr; + WidgetCore *corePtr = &radioPtr->core; + + if (objc > 2) { + Tcl_WrongNumArgs(interp, 1, objv, "invoke"); + return TCL_ERROR; + } + if (corePtr->state & TTK_STATE_DISABLED) + return TCL_OK; + + if (Tcl_ObjSetVar2(interp, + radioPtr->radiobutton.variableObj, NULL, + radioPtr->radiobutton.valueObj, + TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) + == NULL) + return TCL_ERROR; + + if (WidgetDestroyed(corePtr)) + return TCL_ERROR; + + return Tcl_EvalObjEx(interp, + radioPtr->radiobutton.commandObj, TCL_EVAL_GLOBAL); +} + +static const Ttk_Ensemble RadiobuttonCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "invoke", RadiobuttonInvokeCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + /* MISSING: select, deselect */ + { 0,0,0 } +}; + +static WidgetSpec RadiobuttonWidgetSpec = +{ + "TRadiobutton", /* className */ + sizeof(Radiobutton), /* recordSize */ + RadiobuttonOptionSpecs, /* optionSpecs */ + RadiobuttonCommands, /* subcommands */ + BaseInitialize, /* initializeProc */ + RadiobuttonCleanup, /* cleanupProc */ + RadiobuttonConfigure, /* configureProc */ + RadiobuttonPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(RadiobuttonLayout) + TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, + TTK_NODE("Radiobutton.indicator", TTK_PACK_LEFT) + TTK_GROUP("Radiobutton.focus", TTK_PACK_LEFT, + TTK_NODE("Radiobutton.label", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Menubutton widget. + */ + +typedef struct +{ + Tcl_Obj *menuObj; + Tcl_Obj *directionObj; +} MenubuttonPart; + +typedef struct +{ + WidgetCore core; + BasePart base; + MenubuttonPart menubutton; +} Menubutton; + +/* + * Option specifications: + */ +static const char *const directionStrings[] = { + "above", "below", "left", "right", "flush", NULL +}; +static Tk_OptionSpec MenubuttonOptionSpecs[] = +{ + {TK_OPTION_STRING, "-menu", "menu", "Menu", + "", Tk_Offset(Menubutton, menubutton.menuObj), -1, 0,0,0}, + {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction", + "below", Tk_Offset(Menubutton, menubutton.directionObj), -1, + 0,(ClientData)directionStrings,GEOMETRY_CHANGED}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) +}; + +static const Ttk_Ensemble MenubuttonCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec MenubuttonWidgetSpec = +{ + "TMenubutton", /* className */ + sizeof(Menubutton), /* recordSize */ + MenubuttonOptionSpecs, /* optionSpecs */ + MenubuttonCommands, /* subcommands */ + BaseInitialize, /* initializeProc */ + BaseCleanup, /* cleanupProc */ + BaseConfigure, /* configureProc */ + BasePostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(MenubuttonLayout) + TTK_GROUP("Menubutton.border", TTK_FILL_BOTH, + TTK_GROUP("Menubutton.focus", TTK_FILL_BOTH, + TTK_NODE("Menubutton.indicator", TTK_PACK_RIGHT) + TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X, + TTK_NODE("Menubutton.label", TTK_PACK_LEFT)))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Initialization. + */ + +MODULE_SCOPE +void TtkButton_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(theme, "TLabel", LabelLayout); + Ttk_RegisterLayout(theme, "TButton", ButtonLayout); + Ttk_RegisterLayout(theme, "TCheckbutton", CheckbuttonLayout); + Ttk_RegisterLayout(theme, "TRadiobutton", RadiobuttonLayout); + Ttk_RegisterLayout(theme, "TMenubutton", MenubuttonLayout); + + RegisterWidget(interp, "ttk::label", &LabelWidgetSpec); + RegisterWidget(interp, "ttk::button", &ButtonWidgetSpec); + RegisterWidget(interp, "ttk::checkbutton", &CheckbuttonWidgetSpec); + RegisterWidget(interp, "ttk::radiobutton", &RadiobuttonWidgetSpec); + RegisterWidget(interp, "ttk::menubutton", &MenubuttonWidgetSpec); +} diff --git a/generic/ttk/ttkCache.c b/generic/ttk/ttkCache.c new file mode 100644 index 0000000..e3aeaba --- /dev/null +++ b/generic/ttk/ttkCache.c @@ -0,0 +1,350 @@ +/* + * Theme engine resource cache. + * + * Copyright (c) 2004, Joe English + * + * The problem: + * + * Tk maintains reference counts for fonts, colors, and images, + * and deallocates them when the reference count goes to zero. + * With the theme engine, resources are allocated right before + * drawing an element and released immediately after. + * This causes a severe performance penalty, and on PseudoColor + * visuals it causes colormap cycling as colormap entries are + * released and reused. + * + * Solution: Acquire fonts, colors, and objects from a + * resource cache instead of directly from Tk; the cache + * holds a semipermanent reference to the resource to keep + * it from being deallocated. + * + * The plumbing and control flow here is quite contorted; + * it would be better to address this problem in the core instead. + * + * @@@ BUGS/TODO: Need distinct caches for each combination + * of display, visual, and colormap. + * + * @@@ Colormap flashing on PseudoColor visuals is still possible, + * but this will be a transient effect. + */ + +#include <stdio.h> /* for sprintf */ +#include <tk.h> +#include "ttkTheme.h" + +struct Ttk_ResourceCache_ { + Tcl_Interp *interp; /* Interpreter for error reporting */ + Tk_Window tkwin; /* Cache window. */ + Tcl_HashTable fontTable; /* Entries: Tcl_Obj* holding FontObjs */ + Tcl_HashTable colorTable; /* Entries: Tcl_Obj* holding ColorObjs */ + Tcl_HashTable borderTable; /* Entries: Tcl_Obj* holding BorderObjs */ + Tcl_HashTable imageTable; /* Entries: Tk_Images */ + + Tcl_HashTable namedColors; /* Entries: RGB values as Tcl_StringObjs */ +}; + +/* + * Ttk_CreateResourceCache -- + * Initialize a new resource cache. + */ +Ttk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *interp) +{ + Ttk_ResourceCache cache = (Ttk_ResourceCache)ckalloc(sizeof(*cache)); + + cache->tkwin = NULL; /* initialized later */ + cache->interp = interp; + Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&cache->namedColors, TCL_STRING_KEYS); + + return cache; +} + +/* + * Ttk_ClearCache -- + * Release references to all cached resources. + */ +static void Ttk_ClearCache(Ttk_ResourceCache cache) +{ + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + + /* + * Free fonts: + */ + entryPtr = Tcl_FirstHashEntry(&cache->fontTable, &search); + while (entryPtr != NULL) { + Tcl_Obj *fontObj = Tcl_GetHashValue(entryPtr); + if (fontObj) { + Tk_FreeFontFromObj(cache->tkwin, fontObj); + Tcl_DecrRefCount(fontObj); + } + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&cache->fontTable); + Tcl_InitHashTable(&cache->fontTable, TCL_STRING_KEYS); + + /* + * Free colors: + */ + entryPtr = Tcl_FirstHashEntry(&cache->colorTable, &search); + while (entryPtr != NULL) { + Tcl_Obj *colorObj = Tcl_GetHashValue(entryPtr); + if (colorObj) { + Tk_FreeColorFromObj(cache->tkwin, colorObj); + Tcl_DecrRefCount(colorObj); + } + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&cache->colorTable); + Tcl_InitHashTable(&cache->colorTable, TCL_STRING_KEYS); + + /* + * Free borders: + */ + entryPtr = Tcl_FirstHashEntry(&cache->borderTable, &search); + while (entryPtr != NULL) { + Tcl_Obj *borderObj = Tcl_GetHashValue(entryPtr); + if (borderObj) { + Tk_Free3DBorderFromObj(cache->tkwin, borderObj); + Tcl_DecrRefCount(borderObj); + } + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&cache->borderTable); + Tcl_InitHashTable(&cache->borderTable, TCL_STRING_KEYS); + + /* + * Free images: + */ + entryPtr = Tcl_FirstHashEntry(&cache->imageTable, &search); + while (entryPtr != NULL) { + Tk_Image image = Tcl_GetHashValue(entryPtr); + if (image) { + Tk_FreeImage(image); + } + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&cache->imageTable); + Tcl_InitHashTable(&cache->imageTable, TCL_STRING_KEYS); + + return; +} + +/* + * Ttk_FreeResourceCache -- + * Release references to all cached resources, delete the cache. + */ + +void Ttk_FreeResourceCache(Ttk_ResourceCache cache) +{ + Tcl_HashEntry *entryPtr; + Tcl_HashSearch search; + + Ttk_ClearCache(cache); + + Tcl_DeleteHashTable(&cache->colorTable); + Tcl_DeleteHashTable(&cache->fontTable); + Tcl_DeleteHashTable(&cache->imageTable); + + /* + * Free named colors: + */ + entryPtr = Tcl_FirstHashEntry(&cache->namedColors, &search); + while (entryPtr != NULL) { + Tcl_Obj *colorNameObj = Tcl_GetHashValue(entryPtr); + Tcl_DecrRefCount(colorNameObj); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&cache->namedColors); + + ckfree((ClientData)cache); +} + +/* + * CacheWinEventHandler -- + * Detect when the cache window is destroyed, clear cache. + */ +static void CacheWinEventHandler(ClientData clientData, XEvent *eventPtr) +{ + Ttk_ResourceCache cache = clientData; + + if (eventPtr->type != DestroyNotify) { + return; + } + Tk_DeleteEventHandler(cache->tkwin, StructureNotifyMask, + CacheWinEventHandler, clientData); + Ttk_ClearCache(cache); + cache->tkwin = NULL; +} + +/* + * InitCacheWindow -- + * Specify the cache window if not already set. + * @@@ SHOULD: use separate caches for each combination + * @@@ of display, visual, and colormap. + */ +static void InitCacheWindow(Ttk_ResourceCache cache, Tk_Window tkwin) +{ + if (cache->tkwin == NULL) { + cache->tkwin = tkwin; + Tk_CreateEventHandler(tkwin, StructureNotifyMask, + CacheWinEventHandler, cache); + } +} + +/* + * Ttk_RegisterNamedColor -- + * Specify an RGB triplet as a named color. + * Overrides any previous named color specification. + */ +void Ttk_RegisterNamedColor( + Ttk_ResourceCache cache, + const char *colorName, + XColor *colorPtr) +{ + int newEntry; + Tcl_HashEntry *entryPtr; + char nameBuf[14]; + Tcl_Obj *colorNameObj; + + sprintf(nameBuf, "#%04X%04X%04X", + colorPtr->red, colorPtr->green, colorPtr->blue); + colorNameObj = Tcl_NewStringObj(nameBuf, -1); + Tcl_IncrRefCount(colorNameObj); + + entryPtr = Tcl_CreateHashEntry(&cache->namedColors, colorName, &newEntry); + if (!newEntry) { + Tcl_Obj *oldColor = Tcl_GetHashValue(entryPtr); + Tcl_DecrRefCount(oldColor); + } + + Tcl_SetHashValue(entryPtr, colorNameObj); +} + +/* + * CheckNamedColor(objPtr) -- + * If objPtr is a registered color name, return a Tcl_Obj * + * containing the registered color value specification. + * Otherwise, return the input argument. + */ +static Tcl_Obj *CheckNamedColor(Ttk_ResourceCache cache, Tcl_Obj *objPtr) +{ + Tcl_HashEntry *entryPtr = + Tcl_FindHashEntry(&cache->namedColors, Tcl_GetString(objPtr)); + if (entryPtr) { /* Use named color instead */ + objPtr = Tcl_GetHashValue(entryPtr); + } + return objPtr; +} + +/* + * Template for allocation routines: + */ +typedef void *(*Allocator)(Tcl_Interp *, Tk_Window, Tcl_Obj *); + +static Tcl_Obj *Ttk_Use( + Tcl_Interp *interp, + Tcl_HashTable *table, + Allocator allocate, + Tk_Window tkwin, + Tcl_Obj *objPtr) +{ + int newEntry; + Tcl_HashEntry *entryPtr = + Tcl_CreateHashEntry(table,Tcl_GetString(objPtr),&newEntry); + Tcl_Obj *cacheObj; + + if (!newEntry) { + return Tcl_GetHashValue(entryPtr); + } + + cacheObj = Tcl_DuplicateObj(objPtr); + Tcl_IncrRefCount(cacheObj); + + if (allocate(interp, tkwin, cacheObj)) { + Tcl_SetHashValue(entryPtr, cacheObj); + return cacheObj; + } else { + Tcl_DecrRefCount(cacheObj); + Tcl_SetHashValue(entryPtr, NULL); + Tcl_BackgroundError(interp); + return NULL; + } +} + +/* + * Ttk_UseFont -- + * Acquire a font from the cache. + */ +Tcl_Obj *Ttk_UseFont(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr) +{ + InitCacheWindow(cache, tkwin); + return Ttk_Use(cache->interp, + &cache->fontTable,(Allocator)Tk_AllocFontFromObj, tkwin, objPtr); +} + +/* + * Ttk_UseColor -- + * Acquire a color from the cache. + */ +Tcl_Obj *Ttk_UseColor(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr) +{ + objPtr = CheckNamedColor(cache, objPtr); + InitCacheWindow(cache, tkwin); + return Ttk_Use(cache->interp, + &cache->colorTable,(Allocator)Tk_AllocColorFromObj, tkwin, objPtr); +} + +/* + * Ttk_UseBorder -- + * Acquire a Tk_3DBorder from the cache. + */ +Tcl_Obj *Ttk_UseBorder( + Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr) +{ + objPtr = CheckNamedColor(cache, objPtr); + InitCacheWindow(cache, tkwin); + return Ttk_Use(cache->interp, + &cache->borderTable,(Allocator)Tk_Alloc3DBorderFromObj, tkwin, objPtr); +} + +/* NullImageChanged -- + * Tk_ImageChangedProc for Ttk_UseImage + */ + +static void NullImageChanged(ClientData clientData, + int x, int y, int width, int height, int imageWidth, int imageHeight) +{ /* No-op */ } + +/* + * Ttk_UseImage -- + * Acquire a Tk_Image from the cache. + */ +Tk_Image Ttk_UseImage(Ttk_ResourceCache cache, Tk_Window tkwin, Tcl_Obj *objPtr) +{ + const char *imageName = Tcl_GetString(objPtr); + int newEntry; + Tcl_HashEntry *entryPtr = + Tcl_CreateHashEntry(&cache->imageTable,imageName,&newEntry); + Tk_Image image; + + InitCacheWindow(cache, tkwin); + + if (!newEntry) { + return Tcl_GetHashValue(entryPtr); + } + + image = Tk_GetImage(cache->interp, tkwin, imageName, NullImageChanged,0); + Tcl_SetHashValue(entryPtr, image); + + if (!image) { + Tcl_BackgroundError(cache->interp); + } + + return image; +} + +/*EOF*/ diff --git a/generic/ttk/ttkClamTheme.c b/generic/ttk/ttkClamTheme.c new file mode 100644 index 0000000..572f630 --- /dev/null +++ b/generic/ttk/ttkClamTheme.c @@ -0,0 +1,971 @@ +/* + * Copyright (C) 2004 Joe English + * + * "clam" theme; inspired by the XFCE family of Gnome themes. + */ + +#include <tk.h> +#include "ttkTheme.h" + +/* + * Under windows, the Tk-provided XDrawLine and XDrawArc have an + * off-by-one error in the end point. This is especially apparent with this + * theme. Defining this macro as true handles this case. + */ +#if defined(WIN32) && !defined(WIN32_XDRAWLINE_HACK) +# define WIN32_XDRAWLINE_HACK 1 +#else +# define WIN32_XDRAWLINE_HACK 0 +#endif + +#define STR(x) StR(x) +#define StR(x) #x + +#define SCROLLBAR_THICKNESS 14 + +#define FRAME_COLOR "#dcdad5" +#define LIGHT_COLOR "#ffffff" +#define DARK_COLOR "#cfcdc8" +#define DARKER_COLOR "#bab5ab" +#define DARKEST_COLOR "#9e9a91" + +/*------------------------------------------------------------------------ + * +++ Utilities. + */ + +static GC Ttk_GCForColor(Tk_Window tkwin, Tcl_Obj* colorObj, Drawable d) +{ + GC gc = Tk_GCForColor(Tk_GetColorFromObj(tkwin, colorObj), d); + +#ifdef MAC_OSX_TK + /* + * Workaround for Tk bug under Aqua where the default line width is 0. + */ + Display *display = Tk_Display(tkwin); + unsigned long mask = 0ul; + XGCValues gcValues; + + gcValues.line_width = 1; + mask = GCLineWidth; + + XChangeGC(display, gc, mask, &gcValues); +#endif + + return gc; +} + +static void DrawSmoothBorder( + Tk_Window tkwin, Drawable d, Ttk_Box b, + Tcl_Obj *outerColorObj, Tcl_Obj *upperColorObj, Tcl_Obj *lowerColorObj) +{ + Display *display = Tk_Display(tkwin); + int x1 = b.x, x2 = b.x + b.width - 1; + int y1 = b.y, y2 = b.y + b.height - 1; + const int w = WIN32_XDRAWLINE_HACK; + GC gc; + + if ( outerColorObj + && (gc=Ttk_GCForColor(tkwin,outerColorObj,d))) + { + XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); /* N */ + XDrawLine(display,d,gc, x1+1,y2, x2-1+w,y2); /* S */ + XDrawLine(display,d,gc, x1,y1+1, x1,y2-1+w); /* E */ + XDrawLine(display,d,gc, x2,y1+1, x2,y2-1+w); /* W */ + } + + if ( upperColorObj + && (gc=Ttk_GCForColor(tkwin,upperColorObj,d))) + { + XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); /* N */ + XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1); /* E */ + } + + if ( lowerColorObj + && (gc=Ttk_GCForColor(tkwin,lowerColorObj,d))) + { + XDrawLine(display,d,gc, x2-1,y2-1, x1+1-w,y2-1); /* S */ + XDrawLine(display,d,gc, x2-1,y2-1, x2-1,y1+1-w); /* W */ + } +} + +static GC BackgroundGC(Tk_Window tkwin, Tcl_Obj *backgroundObj) +{ + Tk_3DBorder bd = Tk_Get3DBorderFromObj(tkwin, backgroundObj); + return Tk_3DBorderGC(tkwin, bd, TK_3D_FLAT_GC); +} + +/*------------------------------------------------------------------------ + * +++ Border element. + */ + +typedef struct { + Tcl_Obj *borderColorObj; + Tcl_Obj *lightColorObj; + Tcl_Obj *darkColorObj; + Tcl_Obj *reliefObj; + Tcl_Obj *borderWidthObj; /* See <<NOTE-BORDERWIDTH>> */ +} BorderElement; + +static Ttk_ElementOptionSpec BorderElementOptions[] = { + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR }, + { "-lightcolor", TK_OPTION_COLOR, + Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR }, + { "-darkcolor", TK_OPTION_COLOR, + Tk_Offset(BorderElement,darkColorObj), DARK_COLOR }, + { "-relief", TK_OPTION_RELIEF, + Tk_Offset(BorderElement,reliefObj), "flat" }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(BorderElement,borderWidthObj), "2" }, + { NULL, 0, 0, NULL } +}; + +/* + * <<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, + * the excess is used as padding. + */ + +static void BorderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + BorderElement *border = (BorderElement*)elementRecord; + int borderWidth = 2; + Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth); + if (borderWidth == 1) ++borderWidth; + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void BorderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + BorderElement *border = elementRecord; + int relief = TK_RELIEF_FLAT; + int borderWidth = 2; + Tcl_Obj *outer = 0, *upper = 0, *lower = 0; + + Tk_GetReliefFromObj(NULL, border->reliefObj, &relief); + Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth); + + if (borderWidth == 0) return; + + switch (relief) { + case TK_RELIEF_GROOVE : + case TK_RELIEF_RIDGE : + case TK_RELIEF_RAISED : + outer = border->borderColorObj; + upper = border->lightColorObj; + lower = border->darkColorObj; + break; + case TK_RELIEF_SUNKEN : + outer = border->borderColorObj; + upper = border->darkColorObj; + lower = border->lightColorObj; + break; + case TK_RELIEF_FLAT : + outer = upper = lower = 0; + break; + case TK_RELIEF_SOLID : + outer = upper = lower = border->borderColorObj; + break; + } + + DrawSmoothBorder(tkwin, d, b, outer, upper, lower); +} + +static Ttk_ElementSpec BorderElementSpec = { + TK_STYLE_VERSION_2, + sizeof(BorderElement), + BorderElementOptions, + BorderElementSize, + BorderElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Field element. + */ + +typedef struct { + Tcl_Obj *borderColorObj; + Tcl_Obj *lightColorObj; + Tcl_Obj *darkColorObj; + Tcl_Obj *backgroundObj; +} FieldElement; + +static Ttk_ElementOptionSpec FieldElementOptions[] = { + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR }, + { "-lightcolor", TK_OPTION_COLOR, + Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR }, + { "-darkcolor", TK_OPTION_COLOR, + Tk_Offset(FieldElement,darkColorObj), DARK_COLOR }, + { "-fieldbackground", TK_OPTION_BORDER, + Tk_Offset(FieldElement,backgroundObj), "white" }, + { NULL, 0, 0, NULL } +}; + +static void FieldElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + *paddingPtr = Ttk_UniformPadding(2); +} + +static void FieldElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + FieldElement *field = elementRecord; + Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj); + Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2)); + Tcl_Obj *outer = field->borderColorObj, + *inner = field->lightColorObj; + + DrawSmoothBorder(tkwin, d, b, outer, inner, inner); + Tk_Fill3DRectangle( + tkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN); +} + +static Ttk_ElementSpec FieldElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + FieldElementSize, + FieldElementDraw +}; + +/* + * Modified field element for comboboxes: + * Right edge is expanded to overlap the dropdown button. + */ +static void ComboboxFieldElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + FieldElement *field = elementRecord; + GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d); + + ++b.width; + FieldElementDraw(clientData, elementRecord, tkwin, d, b, state); + + XDrawLine(Tk_Display(tkwin), d, gc, + b.x + b.width - 1, b.y, + b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK); +} + +static Ttk_ElementSpec ComboboxFieldElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + FieldElementSize, + ComboboxFieldElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Indicator elements for check and radio buttons. + */ + +typedef struct { + Tcl_Obj *sizeObj; + Tcl_Obj *marginObj; + Tcl_Obj *backgroundObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *upperColorObj; + Tcl_Obj *lowerColorObj; +} IndicatorElement; + +static Ttk_ElementOptionSpec IndicatorElementOptions[] = { + { "-indicatorsize", TK_OPTION_PIXELS, + Tk_Offset(IndicatorElement,sizeObj), "10" }, + { "-indicatormargin", TK_OPTION_STRING, + Tk_Offset(IndicatorElement,marginObj), "1" }, + { "-indicatorbackground", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,backgroundObj), "white" }, + { "-indicatorforeground", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,foregroundObj), "black" }, + { "-upperbordercolor", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR }, + { "-lowerbordercolor", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR }, + { NULL, 0, 0, NULL } +}; + +static void IndicatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + IndicatorElement *indicator = elementRecord; + Ttk_Padding margins; + int size = 10; + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins); + Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size); + *widthPtr = size + Ttk_PaddingWidth(margins); + *heightPtr = size + Ttk_PaddingHeight(margins); +} + +static void RadioIndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + IndicatorElement *indicator = elementRecord; + GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d); + GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d); + GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d); + GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d); + Ttk_Padding padding; + + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding); + b = Ttk_PadBox(b, padding); + + XFillArc(Tk_Display(tkwin),d,gcb, b.x,b.y,b.width,b.height, 0,360*64); + XDrawArc(Tk_Display(tkwin),d,gcl, b.x,b.y,b.width,b.height, 225*64,180*64); + XDrawArc(Tk_Display(tkwin),d,gcu, b.x,b.y,b.width,b.height, 45*64,180*64); + + if (state & TTK_STATE_SELECTED) { + b = Ttk_PadBox(b,Ttk_UniformPadding(3)); + XFillArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64); + XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64); +#if WIN32_XDRAWLINE_HACK + XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 300*64,360*64); +#endif + } +} + +static void CheckIndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + Display *display = Tk_Display(tkwin); + IndicatorElement *indicator = elementRecord; + GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d); + GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d); + GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d); + GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d); + Ttk_Padding padding; + const int w = WIN32_XDRAWLINE_HACK; + + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding); + b = Ttk_PadBox(b, padding); + + XFillRectangle(display,d,gcb, b.x,b.y,b.width,b.height); + XDrawLine(display,d,gcl,b.x,b.y+b.height,b.x+b.width+w,b.y+b.height);/*S*/ + XDrawLine(display,d,gcl,b.x+b.width,b.y,b.x+b.width,b.y+b.height+w); /*E*/ + XDrawLine(display,d,gcu,b.x,b.y, b.x,b.y+b.height+w); /*W*/ + XDrawLine(display,d,gcu,b.x,b.y, b.x+b.width+w,b.y); /*N*/ + + if (state & TTK_STATE_SELECTED) { + int p,q,r,s; + + b = Ttk_PadBox(b,Ttk_UniformPadding(2)); + p = b.x, q = b.y, r = b.x+b.width, s = b.y+b.height; + + r+=w, s+=w; + XDrawLine(display, d, gcf, p, q, r, s); + XDrawLine(display, d, gcf, p+1, q, r, s-1); + XDrawLine(display, d, gcf, p, q+1, r-1, s); + + s-=w, q-=w; + XDrawLine(display, d, gcf, p, s, r, q); + XDrawLine(display, d, gcf, p+1, s, r, q+1); + XDrawLine(display, d, gcf, p, s-1, r-1, q); + } +} + +static Ttk_ElementSpec RadioIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(IndicatorElement), + IndicatorElementOptions, + IndicatorElementSize, + RadioIndicatorElementDraw +}; + +static Ttk_ElementSpec CheckIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(IndicatorElement), + IndicatorElementOptions, + IndicatorElementSize, + CheckIndicatorElementDraw +}; + +#define MENUBUTTON_ARROW_SIZE 5 + +typedef struct { + Tcl_Obj *sizeObj; + Tcl_Obj *colorObj; + Tcl_Obj *paddingObj; +} MenuIndicatorElement; + +static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = +{ + { "-arrowsize", TK_OPTION_PIXELS, + Tk_Offset(MenuIndicatorElement,sizeObj), + STR(MENUBUTTON_ARROW_SIZE)}, + { "-arrowcolor",TK_OPTION_COLOR, + Tk_Offset(MenuIndicatorElement,colorObj), + "black" }, + { "-arrowpadding",TK_OPTION_STRING, + Tk_Offset(MenuIndicatorElement,paddingObj), + "3" }, + { NULL, 0, 0, NULL } +}; + +static void MenuIndicatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + MenuIndicatorElement *indicator = elementRecord; + Ttk_Padding margins; + int size = MENUBUTTON_ARROW_SIZE; + Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size); + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins); + TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr); + *widthPtr += Ttk_PaddingWidth(margins); + *heightPtr += Ttk_PaddingHeight(margins); +} + +static void MenuIndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + MenuIndicatorElement *indicator = elementRecord; + XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); + GC gc = Tk_GCForColor(arrowColor, d); + int size = MENUBUTTON_ARROW_SIZE; + int width, height; + + Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size); + + TtkArrowSize(size, ARROW_DOWN, &width, &height); + b = Ttk_StickBox(b, width, height, 0); + TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN); +} + +static Ttk_ElementSpec MenuIndicatorElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(MenuIndicatorElement), + MenuIndicatorElementOptions, + MenuIndicatorElementSize, + MenuIndicatorElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Grips. + * + * TODO: factor this with ThumbElementDraw + */ + +static Ttk_Orient GripClientData[] = { + TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL +}; + +typedef struct { + Tcl_Obj *lightColorObj; + Tcl_Obj *borderColorObj; + Tcl_Obj *gripCountObj; +} GripElement; + +static Ttk_ElementOptionSpec GripElementOptions[] = { + { "-lightcolor", TK_OPTION_COLOR, + Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR }, + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR }, + { "-gripcount", TK_OPTION_INT, + Tk_Offset(GripElement,gripCountObj), "5" }, + { NULL, 0, 0, NULL } +}; + +static void GripElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL; + GripElement *grip = elementRecord; + int gripCount = 0; + + Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount); + if (horizontal) { + *widthPtr = 2*gripCount; + } else { + *heightPtr = 2*gripCount; + } +} + +static void GripElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + const int w = WIN32_XDRAWLINE_HACK; + int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL; + GripElement *grip = elementRecord; + GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d); + GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d); + int gripPad = 1, gripCount = 0; + int i; + + Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount); + + if (horizontal) { + int x = b.x + b.width / 2 - gripCount; + int y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w; + for (i=0; i<gripCount; ++i) { + XDrawLine(Tk_Display(tkwin), d, darkGC, x,y1, x,y2); ++x; + XDrawLine(Tk_Display(tkwin), d, lightGC, x,y1, x,y2); ++x; + } + } else { + int y = b.y + b.height / 2 - gripCount; + int x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w; + for (i=0; i<gripCount; ++i) { + XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y, x2,y); ++y; + XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y, x2,y); ++y; + } + } +} + +static Ttk_ElementSpec GripElementSpec = { + TK_STYLE_VERSION_2, + sizeof(GripElement), + GripElementOptions, + GripElementSize, + GripElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Scrollbar elements: trough, arrows, thumb. + * + * Notice that the trough element has 0 internal padding; + * that way the thumb and arrow borders overlap the trough. + */ + +typedef struct { /* Common element record for scrollbar elements */ + Tcl_Obj *orientObj; + Tcl_Obj *backgroundObj; + Tcl_Obj *borderColorObj; + Tcl_Obj *troughColorObj; + Tcl_Obj *lightColorObj; + Tcl_Obj *darkColorObj; + Tcl_Obj *arrowColorObj; + Tcl_Obj *arrowSizeObj; + Tcl_Obj *gripCountObj; + Tcl_Obj *sliderlengthObj; +} ScrollbarElement; + +static Ttk_ElementOptionSpec ScrollbarElementOptions[] = { + { "-orient", TK_OPTION_ANY, + Tk_Offset(ScrollbarElement, orientObj), "horizontal" }, + { "-background", TK_OPTION_BORDER, + Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR }, + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR }, + { "-troughcolor", TK_OPTION_COLOR, + Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR }, + { "-lightcolor", TK_OPTION_COLOR, + Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR }, + { "-darkcolor", TK_OPTION_COLOR, + Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR }, + { "-arrowcolor", TK_OPTION_COLOR, + Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" }, + { "-arrowsize", TK_OPTION_PIXELS, + Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) }, + { "-gripcount", TK_OPTION_INT, + Tk_Offset(ScrollbarElement,gripCountObj), "5" }, + { "-sliderlength", TK_OPTION_INT, + Tk_Offset(ScrollbarElement,sliderlengthObj), "30" }, + { NULL, 0, 0, NULL } +}; + +static void TroughElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + ScrollbarElement *sb = elementRecord; + GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d); + GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d); + XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, b.width-1, b.height-1); + XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, b.width-1, b.height-1); +} + +static Ttk_ElementSpec TroughElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + TtkNullElementSize, + TroughElementDraw +}; + +static void ThumbElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ScrollbarElement *sb = elementRecord; + int size = SCROLLBAR_THICKNESS; + Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size); + *widthPtr = *heightPtr = size; +} + +static void ThumbElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + ScrollbarElement *sb = elementRecord; + int gripCount = 0, orient = TTK_ORIENT_HORIZONTAL; + GC lightGC, darkGC; + int x1, y1, x2, y2, dx, dy, i; + const int w = WIN32_XDRAWLINE_HACK; + + DrawSmoothBorder(tkwin, d, b, + sb->borderColorObj, sb->lightColorObj, sb->darkColorObj); + XFillRectangle( + Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj), + b.x+2, b.y+2, b.width-4, b.height-4); + + /* + * Draw grip: + */ + Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient); + Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount); + lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d); + darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d); + + if (orient == TTK_ORIENT_HORIZONTAL) { + dx = 1; dy = 0; + x1 = x2 = b.x + b.width / 2 - gripCount; + y1 = b.y + 2; + y2 = b.y + b.height - 3 + w; + } else { + dx = 0; dy = 1; + y1 = y2 = b.y + b.height / 2 - gripCount; + x1 = b.x + 2; + x2 = b.x + b.width - 3 + w; + } + + for (i=0; i<gripCount; ++i) { + XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); + x1 += dx; x2 += dx; y1 += dy; y2 += dy; + XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2); + x1 += dx; x2 += dx; y1 += dy; y2 += dy; + } +} + +static Ttk_ElementSpec ThumbElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + ThumbElementSize, + ThumbElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Slider element. + */ +static void SliderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ScrollbarElement *sb = elementRecord; + int length, thickness, orient; + + length = thickness = SCROLLBAR_THICKNESS; + Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient); + Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &thickness); + Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length); + if (orient == TTK_ORIENT_VERTICAL) { + *heightPtr = length; + *widthPtr = thickness; + } else { + *heightPtr = thickness; + *widthPtr = length; + } + +} + +static Ttk_ElementSpec SliderElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + SliderElementSize, + ThumbElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Progress bar element + */ +static void PbarElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SliderElementSize(clientData, elementRecord, tkwin, + widthPtr, heightPtr, paddingPtr); + *paddingPtr = Ttk_UniformPadding(2); + *widthPtr += 4; + *heightPtr += 4; +} + +static void PbarElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + ScrollbarElement *sb = elementRecord; + + b = Ttk_PadBox(b, Ttk_UniformPadding(2)); + if (b.width > 4 && b.height > 4) { + DrawSmoothBorder(tkwin, d, b, + sb->borderColorObj, sb->lightColorObj, sb->darkColorObj); + XFillRectangle(Tk_Display(tkwin), d, + BackgroundGC(tkwin, sb->backgroundObj), + b.x+2, b.y+2, b.width-4, b.height-4); + } +} + +static Ttk_ElementSpec PbarElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + PbarElementSize, + PbarElementDraw +}; + + +/*------------------------------------------------------------------------ + * +++ Scrollbar arrows. + */ +static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT }; + +static void ArrowElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ScrollbarElement *sb = elementRecord; + int size = SCROLLBAR_THICKNESS; + Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size); + *widthPtr = *heightPtr = size; +} + +static void ArrowElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned state) +{ + ArrowDirection dir = *(ArrowDirection*)clientData; + ScrollbarElement *sb = elementRecord; + GC gc = Ttk_GCForColor(tkwin,sb->arrowColorObj, d); + int h, cx, cy; + + DrawSmoothBorder(tkwin, d, b, + sb->borderColorObj, sb->lightColorObj, sb->darkColorObj); + + XFillRectangle( + Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj), + b.x+2, b.y+2, b.width-4, b.height-4); + + b = Ttk_PadBox(b, Ttk_UniformPadding(3)); + h = b.width < b.height ? b.width : b.height; + TtkArrowSize(h/2, dir, &cx, &cy); + b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER); + + TtkFillArrow(Tk_Display(tkwin), d, gc, b, dir); +} + +static Ttk_ElementSpec ArrowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ScrollbarElement), + ScrollbarElementOptions, + ArrowElementSize, + ArrowElementDraw +}; + + +/*------------------------------------------------------------------------ + * +++ Notebook elements. + * + * Note: Tabs, except for the rightmost, overlap the neighbor to + * their right by one pixel. + */ + +typedef struct { + Tcl_Obj *backgroundObj; + Tcl_Obj *borderColorObj; + Tcl_Obj *lightColorObj; + Tcl_Obj *darkColorObj; +} NotebookElement; + +static Ttk_ElementOptionSpec NotebookElementOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR }, + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR }, + { "-lightcolor", TK_OPTION_COLOR, + Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR }, + { "-darkcolor", TK_OPTION_COLOR, + Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR }, + { NULL, 0, 0, NULL } +}; + +static void TabElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + int borderWidth = 2; + paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth; + paddingPtr->bottom = 0; +} + +static void TabElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + NotebookElement *tab = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj); + Display *display = Tk_Display(tkwin); + int borderWidth = 2, dh = 0; + int x1,y1,x2,y2; + GC gc; + const int w = WIN32_XDRAWLINE_HACK; + + if (state & TTK_STATE_SELECTED) { + dh = borderWidth; + } + + if (state & TTK_STATE_USER2) { /* Rightmost tab */ + --b.width; + } + + Tk_Fill3DRectangle(tkwin, d, border, + b.x+2, b.y+2, b.width-1, b.height-2+dh, borderWidth, TK_RELIEF_FLAT); + + x1 = b.x, x2 = b.x + b.width; + y1 = b.y, y2 = b.y + b.height; + + + gc=Ttk_GCForColor(tkwin,tab->borderColorObj,d); + XDrawLine(display,d,gc, x1,y1+1, x1,y2+w); + XDrawLine(display,d,gc, x2,y1+1, x2,y2+w); + XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); + + gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d); + XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w); + XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); +} + +static Ttk_ElementSpec TabElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NotebookElement), + NotebookElementOptions, + TabElementSize, + TabElementDraw +}; + +static void ClientElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + int borderWidth = 2; + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void ClientElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + NotebookElement *ce = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj); + int borderWidth = 2; + + Tk_Fill3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT); + DrawSmoothBorder(tkwin, d, b, + ce->borderColorObj, ce->lightColorObj, ce->darkColorObj); +} + +static Ttk_ElementSpec ClientElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NotebookElement), + NotebookElementOptions, + ClientElementSize, + ClientElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Modified widget layouts. + */ + +TTK_BEGIN_LAYOUT_TABLE(LayoutTable) + +TTK_LAYOUT("TCombobox", + TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y) + TTK_GROUP("Combobox.field", TTK_PACK_LEFT|TTK_FILL_BOTH|TTK_EXPAND, + TTK_GROUP("Combobox.padding", TTK_FILL_BOTH, + TTK_NODE("Combobox.textarea", TTK_FILL_BOTH)))) + +TTK_LAYOUT("Horizontal.Sash", + TTK_GROUP("Sash.hsash", TTK_FILL_BOTH, + TTK_NODE("Sash.hgrip", TTK_FILL_BOTH))) + +TTK_LAYOUT("Vertical.Sash", + TTK_GROUP("Sash.vsash", TTK_FILL_BOTH, + TTK_NODE("Sash.vgrip", TTK_FILL_BOTH))) + +TTK_END_LAYOUT_TABLE + +/*------------------------------------------------------------------------ + * +++ Initialization. + */ + +MODULE_SCOPE int +TtkClamTheme_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_CreateTheme(interp, "clam", 0); + + if (!theme) { + return TCL_ERROR; + } + + Ttk_RegisterElement(interp, + theme, "border", &BorderElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "field", &FieldElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "Combobox.field", &ComboboxFieldElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "trough", &TroughElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "thumb", &ThumbElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "uparrow", &ArrowElementSpec, &ArrowElements[0]); + Ttk_RegisterElement(interp, + theme, "downarrow", &ArrowElementSpec, &ArrowElements[1]); + Ttk_RegisterElement(interp, + theme, "leftarrow", &ArrowElementSpec, &ArrowElements[2]); + Ttk_RegisterElement(interp, + theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]); + + Ttk_RegisterElement(interp, + theme, "Radiobutton.indicator", &RadioIndicatorElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "Checkbutton.indicator", &CheckIndicatorElementSpec, NULL); + Ttk_RegisterElement(interp, + theme, "Menubutton.indicator", &MenuIndicatorElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "hgrip", + &GripElementSpec, &GripClientData[0]); + Ttk_RegisterElement(interp, theme, "vgrip", + &GripElementSpec, &GripClientData[1]); + + Ttk_RegisterLayouts(theme, LayoutTable); + + Tcl_PkgProvide(interp, "ttk::theme::clam", TTK_VERSION); + + return TCL_OK; +} diff --git a/generic/ttk/ttkClassicTheme.c b/generic/ttk/ttkClassicTheme.c new file mode 100644 index 0000000..2fbcd76 --- /dev/null +++ b/generic/ttk/ttkClassicTheme.c @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2004, Joe English + * + * "classic" theme; implements the classic Motif-like Tk look. + * + */ + +#include <tk.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "ttkTheme.h" + +#define DEFAULT_BORDERWIDTH "2" +#define DEFAULT_ARROW_SIZE "15" + +/*---------------------------------------------------------------------- + * +++ Highlight element implementation. + * Draw a solid highlight border to indicate focus. + */ + +typedef struct { + Tcl_Obj *highlightColorObj; + Tcl_Obj *highlightThicknessObj; +} HighlightElement; + +static Ttk_ElementOptionSpec HighlightElementOptions[] = { + { "-highlightcolor",TK_OPTION_COLOR, + Tk_Offset(HighlightElement,highlightColorObj), DEFAULT_BACKGROUND }, + { "-highlightthickness",TK_OPTION_PIXELS, + Tk_Offset(HighlightElement,highlightThicknessObj), "0" }, + { NULL, 0, 0, NULL } +}; + +static void HighlightElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + HighlightElement *hl = elementRecord; + int highlightThickness = 0; + + Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness); + *paddingPtr = Ttk_UniformPadding((short)highlightThickness); +} + +static void HighlightElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + HighlightElement *hl = elementRecord; + int highlightThickness = 0; + XColor *highlightColor = Tk_GetColorFromObj(tkwin, hl->highlightColorObj); + + Tcl_GetIntFromObj(NULL,hl->highlightThicknessObj,&highlightThickness); + if (highlightColor && highlightThickness > 0) { + GC gc = Tk_GCForColor(highlightColor, d); + Tk_DrawFocusHighlight(tkwin, gc, highlightThickness, d); + } +} + +static Ttk_ElementSpec HighlightElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(HighlightElement), + HighlightElementOptions, + HighlightElementSize, + HighlightElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Button Border element: + * + * The Motif-style button border on X11 consists of (from outside-in): + * + * + focus indicator (controlled by -highlightcolor and -highlightthickness), + * + default ring (if -default active; blank if -default normal) + * + shaded border (controlled by -background, -borderwidth, and -relief) + */ + +typedef struct { + Tcl_Obj *borderObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *defaultStateObj; +} ButtonBorderElement; + +static Ttk_ElementOptionSpec ButtonBorderElementOptions[] = +{ + { "-background", TK_OPTION_BORDER, + Tk_Offset(ButtonBorderElement,borderObj), DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(ButtonBorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { "-relief", TK_OPTION_RELIEF, + Tk_Offset(ButtonBorderElement,reliefObj), "flat" }, + { "-default", TK_OPTION_ANY, + Tk_Offset(ButtonBorderElement,defaultStateObj), "disabled" }, + { NULL, 0, 0, NULL } +}; + +static void ButtonBorderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ButtonBorderElement *bd = elementRecord; + int defaultState = TTK_BUTTON_DEFAULT_DISABLED; + int borderWidth = 0; + + Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth); + Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); + + if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { + borderWidth += 5; + } + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +/* + * (@@@ Note: ButtonBorderElement still still still buggy: + * padding for default ring is drawn in the wrong color + * when the button is active.) + */ +static void ButtonBorderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + ButtonBorderElement *bd = elementRecord; + Tk_3DBorder border = NULL; + int borderWidth = 1, relief = TK_RELIEF_FLAT; + int defaultState = TTK_BUTTON_DEFAULT_DISABLED; + int inset = 0; + + /* + * Get option values. + */ + border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj); + Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); + Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); + + /* + * Default ring: + */ + switch (defaultState) + { + case TTK_BUTTON_DEFAULT_DISABLED : + break; + case TTK_BUTTON_DEFAULT_NORMAL : + inset += 5; + break; + case TTK_BUTTON_DEFAULT_ACTIVE : + Tk_Draw3DRectangle(tkwin, d, border, + b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset, + 2, TK_RELIEF_FLAT); + inset += 2; + Tk_Draw3DRectangle(tkwin, d, border, + b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset, + 1, TK_RELIEF_SUNKEN); + ++inset; + Tk_Draw3DRectangle(tkwin, d, border, + b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset, + 2, TK_RELIEF_FLAT); + inset += 2; + break; + } + + /* + * 3-D border: + */ + if (border && borderWidth > 0) { + Tk_Draw3DRectangle(tkwin, d, border, + b.x+inset, b.y+inset, b.width - 2*inset, b.height - 2*inset, + borderWidth,relief); + } +} + +static Ttk_ElementSpec ButtonBorderElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(ButtonBorderElement), + ButtonBorderElementOptions, + ButtonBorderElementSize, + ButtonBorderElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Arrow element(s). + * + * Draws a 3-D shaded triangle. + * clientData is an enum ArrowDirection pointer. + */ + +static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT }; +typedef struct +{ + Tcl_Obj *sizeObj; + Tcl_Obj *borderObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; +} ArrowElement; + +static Ttk_ElementOptionSpec ArrowElementOptions[] = +{ + { "-arrowsize", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,sizeObj), + DEFAULT_ARROW_SIZE }, + { "-background", TK_OPTION_BORDER, Tk_Offset(ArrowElement,borderObj), + DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(ArrowElement,borderWidthObj), + DEFAULT_BORDERWIDTH }, + { "-relief", TK_OPTION_RELIEF, Tk_Offset(ArrowElement,reliefObj),"raised" }, + { NULL, 0, 0, NULL } +}; + +static void ArrowElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ArrowElement *arrow = elementRecord; + int size = 12; + + Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size); + *widthPtr = *heightPtr = size; +} + +static void ArrowElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + int direction = *(int *)clientData; + ArrowElement *arrow = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj); + int borderWidth = 2; + int relief = TK_RELIEF_RAISED; + int size = b.width < b.height ? b.width : b.height; + XPoint points[3]; + + Tk_GetPixelsFromObj(NULL, tkwin, arrow->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief); + + + /* + * @@@ There are off-by-one pixel errors in the way these are drawn; + * @@@ need to take a look at Tk_Fill3DPolygon and X11 to find the + * @@@ exact rules. + */ + switch (direction) + { + case ARROW_UP: + points[2].x = b.x; points[2].y = b.y + size; + points[1].x = b.x + size/2; points[1].y = b.y; + points[0].x = b.x + size; points[0].y = b.y + size; + break; + case ARROW_DOWN: + points[0].x = b.x; points[0].y = b.y; + points[1].x = b.x + size/2; points[1].y = b.y + size; + points[2].x = b.x + size; points[2].y = b.y; + break; + case ARROW_LEFT: + points[0].x = b.x; points[0].y = b.y + size / 2; + points[1].x = b.x + size; points[1].y = b.y + size; + points[2].x = b.x + size; points[2].y = b.y; + break; + case ARROW_RIGHT: + points[0].x = b.x + size; points[0].y = b.y + size / 2; + points[1].x = b.x; points[1].y = b.y; + points[2].x = b.x; points[2].y = b.y + size; + break; + } + + Tk_Fill3DPolygon(tkwin, d, border, points, 3, borderWidth, relief); +} + +static Ttk_ElementSpec ArrowElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(ArrowElement), + ArrowElementOptions, + ArrowElementSize, + ArrowElementDraw +}; + + +/*------------------------------------------------------------------------ + * +++ Sash element (for ttk::panedwindow) + * + * 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 + * -sashrelief raised, but that looks wrong to me. + */ + +static Ttk_Orient SashClientData[] = { + TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL +}; + +typedef struct { + Tcl_Obj *borderObj; /* background color */ + Tcl_Obj *sashReliefObj; /* sash relief */ + Tcl_Obj *sashThicknessObj; /* overall thickness of sash */ + Tcl_Obj *sashPadObj; /* padding on either side of handle */ + Tcl_Obj *handleSizeObj; /* handle width and height */ + Tcl_Obj *handlePadObj; /* handle's distance from edge */ +} SashElement; + +static Ttk_ElementOptionSpec SashOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(SashElement,borderObj), DEFAULT_BACKGROUND }, + { "-sashrelief", TK_OPTION_RELIEF, + Tk_Offset(SashElement,sashReliefObj), "sunken" }, + { "-sashthickness", TK_OPTION_PIXELS, + Tk_Offset(SashElement,sashThicknessObj), "6" }, + { "-sashpad", TK_OPTION_PIXELS, + Tk_Offset(SashElement,sashPadObj), "2" }, + { "-handlesize", TK_OPTION_PIXELS, + Tk_Offset(SashElement,handleSizeObj), "8" }, + { "-handlepad", TK_OPTION_PIXELS, + Tk_Offset(SashElement,handlePadObj), "8" }, + { NULL, 0, 0, NULL } +}; + +static void SashElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SashElement *sash = elementRecord; + int sashPad = 2, sashThickness = 6, handleSize = 8; + int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL; + + Tk_GetPixelsFromObj(NULL, tkwin, sash->sashThicknessObj, &sashThickness); + Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize); + Tk_GetPixelsFromObj(NULL, tkwin, sash->sashPadObj, &sashPad); + + if (sashThickness < handleSize + 2*sashPad) + sashThickness = handleSize + 2*sashPad; + + if (horizontal) + *heightPtr = sashThickness; + else + *widthPtr = sashThickness; +} + +static void SashElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + SashElement *sash = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, sash->borderObj); + GC gc1,gc2; + int relief = TK_RELIEF_RAISED; + int handleSize = 8, handlePad = 8; + int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL; + Ttk_Box hb; + + Tk_GetPixelsFromObj(NULL, tkwin, sash->handleSizeObj, &handleSize); + Tk_GetPixelsFromObj(NULL, tkwin, sash->handlePadObj, &handlePad); + Tk_GetReliefFromObj(NULL, sash->sashReliefObj, &relief); + + switch (relief) { + case TK_RELIEF_RAISED: case TK_RELIEF_RIDGE: + gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); + break; + case TK_RELIEF_SUNKEN: case TK_RELIEF_GROOVE: + gc1 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); + gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + break; + case TK_RELIEF_SOLID: + gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); + break; + case TK_RELIEF_FLAT: + default: + gc1 = gc2 = Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC); + break; + } + + /* Draw sash line: + */ + if (horizontal) { + int y = b.y + b.height/2 - 1; + XDrawLine(Tk_Display(tkwin), d, gc1, b.x, y, b.x+b.width, y); ++y; + XDrawLine(Tk_Display(tkwin), d, gc2, b.x, y, b.x+b.width, y); + } else { + int x = b.x + b.width/2 - 1; + XDrawLine(Tk_Display(tkwin), d, gc1, x, b.y, x, b.y+b.height); ++x; + XDrawLine(Tk_Display(tkwin), d, gc2, x, b.y, x, b.y+b.height); + } + + /* Draw handle: + */ + if (handleSize >= 0) { + if (horizontal) { + hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_W); + hb.x += handlePad; + } else { + hb = Ttk_StickBox(b, handleSize, handleSize, TTK_STICK_N); + hb.y += handlePad; + } + Tk_Fill3DRectangle(tkwin, d, border, + hb.x, hb.y, hb.width, hb.height, 1, TK_RELIEF_RAISED); + } +} + +static Ttk_ElementSpec SashElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SashElement), + SashOptions, + SashElementSize, + SashElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Widget layouts. + */ + +TTK_BEGIN_LAYOUT_TABLE(LayoutTable) + +TTK_LAYOUT("TButton", + TTK_GROUP("Button.highlight", TTK_FILL_BOTH, + TTK_GROUP("Button.border", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("Button.padding", TTK_FILL_BOTH, + TTK_NODE("Button.label", TTK_FILL_BOTH))))) + +TTK_LAYOUT("TCheckbutton", + TTK_GROUP("Checkbutton.highlight", TTK_FILL_BOTH, + TTK_GROUP("Checkbutton.border", TTK_FILL_BOTH, + TTK_GROUP("Checkbutton.padding", TTK_FILL_BOTH, + TTK_NODE("Checkbutton.indicator", TTK_PACK_LEFT) + TTK_NODE("Checkbutton.label", TTK_PACK_LEFT|TTK_FILL_BOTH))))) + +TTK_LAYOUT("TRadiobutton", + TTK_GROUP("Radiobutton.highlight", TTK_FILL_BOTH, + TTK_GROUP("Radiobutton.border", TTK_FILL_BOTH, + TTK_GROUP("Radiobutton.padding", TTK_FILL_BOTH, + TTK_NODE("Radiobutton.indicator", TTK_PACK_LEFT) + TTK_NODE("Radiobutton.label", TTK_PACK_LEFT|TTK_FILL_BOTH))))) + +TTK_LAYOUT("TMenubutton", + TTK_GROUP("Menubutton.highlight", TTK_FILL_BOTH, + TTK_GROUP("Menubutton.border", TTK_FILL_BOTH, + TTK_NODE("Menubutton.indicator", TTK_PACK_RIGHT) + TTK_GROUP("Menubutton.padding", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_X, + TTK_NODE("Menubutton.label", 0))))) + +/* "classic" entry, includes highlight border */ +TTK_LAYOUT("TEntry", + TTK_GROUP("Entry.highlight", TTK_FILL_BOTH, + TTK_GROUP("Entry.field", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("Entry.padding", TTK_FILL_BOTH, + TTK_NODE("Entry.textarea", TTK_FILL_BOTH))))) + +/* Notebook tabs -- omit focus ring */ +TTK_LAYOUT("Tab", + TTK_GROUP("Notebook.tab", TTK_FILL_BOTH, + TTK_GROUP("Notebook.padding", TTK_FILL_BOTH, + TTK_NODE("Notebook.label", TTK_FILL_BOTH)))) + +TTK_END_LAYOUT_TABLE + +/* POSSIBLY: include Scale layouts w/focus border + */ + +/*------------------------------------------------------------------------ + * TtkClassicTheme_Init -- + * Install classic theme. + */ + +MODULE_SCOPE int TtkClassicTheme_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_CreateTheme(interp, "classic", NULL); + + if (!theme) { + return TCL_ERROR; + } + + /* + * Register elements: + */ + Ttk_RegisterElement(interp, theme, "highlight", + &HighlightElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "Button.border", + &ButtonBorderElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "uparrow", + &ArrowElementSpec, &ArrowElements[0]); + Ttk_RegisterElement(interp, theme, "downarrow", + &ArrowElementSpec, &ArrowElements[1]); + Ttk_RegisterElement(interp, theme, "leftarrow", + &ArrowElementSpec, &ArrowElements[2]); + Ttk_RegisterElement(interp, theme, "rightarrow", + &ArrowElementSpec, &ArrowElements[3]); + Ttk_RegisterElement(interp, theme, "arrow", + &ArrowElementSpec, &ArrowElements[0]); + + Ttk_RegisterElement(interp, theme, "hsash", + &SashElementSpec, &SashClientData[0]); + Ttk_RegisterElement(interp, theme, "vsash", + &SashElementSpec, &SashClientData[1]); + + /* + * Register layouts: + */ + Ttk_RegisterLayouts(theme, LayoutTable); + + Tcl_PkgProvide(interp, "ttk::theme::classic", TTK_VERSION); + + return TCL_OK; +} + +/*EOF*/ diff --git a/generic/ttk/ttkDecls.h b/generic/ttk/ttkDecls.h new file mode 100644 index 0000000..ee679b7 --- /dev/null +++ b/generic/ttk/ttkDecls.h @@ -0,0 +1,272 @@ +/* + * This file is (mostly) automatically generated from ttk.decls. + */ + +#ifndef _TTKDECLS +#define _TTKDECLS + +#if defined(USE_TTK_STUBS) + +extern const char *TtkInitializeStubs( + Tcl_Interp *, const char *version, int epoch, int revision); +#define Ttk_InitStubs(interp) TtkInitializeStubs( \ + interp, TTK_VERSION, TTK_STUBS_EPOCH, TTK_STUBS_REVISION) +#else + +#define Ttk_InitStubs(interp) Tcl_PkgRequire(interp, "Ttk", TTK_VERSION, 0) + +#endif + + +/* !BEGIN!: Do not edit below this line. */ + +#define TTK_STUBS_EPOCH 0 +#define TTK_STUBS_REVISION 31 + +/* + * Exported function declarations: + */ + +/* 0 */ +TTKAPI Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, CONST char *name); +/* 1 */ +TTKAPI Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp); +/* 2 */ +TTKAPI Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp); +/* 3 */ +TTKAPI Ttk_Theme Ttk_CreateTheme(Tcl_Interp *interp, CONST char *name, + Ttk_Theme parent); +/* 4 */ +TTKAPI void Ttk_RegisterCleanup(Tcl_Interp *interp, + VOID *deleteData, + Ttk_CleanupProc *cleanupProc); +/* 5 */ +TTKAPI int Ttk_RegisterElementSpec(Ttk_Theme theme, + CONST char *elementName, + Ttk_ElementSpec *elementSpec, + VOID *clientData); +/* 6 */ +TTKAPI Ttk_ElementClass * Ttk_RegisterElement(Tcl_Interp *interp, + Ttk_Theme theme, CONST char *elementName, + Ttk_ElementSpec *elementSpec, + VOID *clientData); +/* 7 */ +TTKAPI int Ttk_RegisterElementFactory(Tcl_Interp *interp, + CONST char *name, + Ttk_ElementFactory factoryProc, + VOID *clientData); +/* 8 */ +TTKAPI void Ttk_RegisterLayout(Ttk_Theme theme, + CONST char *className, + Ttk_LayoutSpec layoutSpec); +/* Slot 9 is reserved */ +/* 10 */ +TTKAPI int Ttk_GetStateSpecFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn); +/* 11 */ +TTKAPI Tcl_Obj * Ttk_NewStateSpecObj(unsigned int onbits, + unsigned int offbits); +/* 12 */ +TTKAPI Ttk_StateMap Ttk_GetStateMapFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr); +/* 13 */ +TTKAPI Tcl_Obj * Ttk_StateMapLookup(Tcl_Interp *interp, + Ttk_StateMap map, Ttk_State state); +/* 14 */ +TTKAPI int Ttk_StateTableLookup(Ttk_StateTable map[], + Ttk_State state); +/* Slot 15 is reserved */ +/* Slot 16 is reserved */ +/* Slot 17 is reserved */ +/* Slot 18 is reserved */ +/* Slot 19 is reserved */ +/* 20 */ +TTKAPI int Ttk_GetPaddingFromObj(Tcl_Interp *interp, + Tk_Window tkwin, Tcl_Obj *objPtr, + Ttk_Padding *pad_rtn); +/* 21 */ +TTKAPI int Ttk_GetBorderFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); +/* 22 */ +TTKAPI int Ttk_GetStickyFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn); +/* 23 */ +TTKAPI Ttk_Padding Ttk_MakePadding(short l, short t, short r, short b); +/* 24 */ +TTKAPI Ttk_Padding Ttk_UniformPadding(short borderWidth); +/* 25 */ +TTKAPI Ttk_Padding Ttk_AddPadding(Ttk_Padding pad1, Ttk_Padding pad2); +/* 26 */ +TTKAPI Ttk_Padding Ttk_RelievePadding(Ttk_Padding padding, int relief, + int n); +/* 27 */ +TTKAPI Ttk_Box Ttk_MakeBox(int x, int y, int width, int height); +/* 28 */ +TTKAPI int Ttk_BoxContains(Ttk_Box box, int x, int y); +/* 29 */ +TTKAPI Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, + Ttk_Side side); +/* 30 */ +TTKAPI Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, + Ttk_Sticky sticky); +/* 31 */ +TTKAPI Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, + Tk_Anchor anchor); +/* 32 */ +TTKAPI Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p); +/* 33 */ +TTKAPI Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p); +/* 34 */ +TTKAPI Ttk_Box Ttk_PlaceBox(Ttk_Box *cavity, int w, int h, + Ttk_Side side, Ttk_Sticky sticky); +/* 35 */ +TTKAPI Tcl_Obj * Ttk_NewBoxObj(Ttk_Box box); +/* Slot 36 is reserved */ +/* Slot 37 is reserved */ +/* Slot 38 is reserved */ +/* Slot 39 is reserved */ +/* 40 */ +TTKAPI int Ttk_GetOrientFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, int *orient); + +typedef struct TtkStubs { + int magic; + int epoch; + int revision; + const struct TtkStubHooks *hooks; + + Ttk_Theme (*ttk_GetTheme) (Tcl_Interp *interp, CONST char *name); /* 0 */ + Ttk_Theme (*ttk_GetDefaultTheme) (Tcl_Interp *interp); /* 1 */ + Ttk_Theme (*ttk_GetCurrentTheme) (Tcl_Interp *interp); /* 2 */ + Ttk_Theme (*ttk_CreateTheme) (Tcl_Interp *interp, CONST char *name, Ttk_Theme parent); /* 3 */ + void (*ttk_RegisterCleanup) (Tcl_Interp *interp, VOID *deleteData, Ttk_CleanupProc *cleanupProc); /* 4 */ + int (*ttk_RegisterElementSpec) (Ttk_Theme theme, CONST char *elementName, Ttk_ElementSpec *elementSpec, VOID *clientData); /* 5 */ + Ttk_ElementClass * (*ttk_RegisterElement) (Tcl_Interp *interp, Ttk_Theme theme, CONST char *elementName, Ttk_ElementSpec *elementSpec, VOID *clientData); /* 6 */ + int (*ttk_RegisterElementFactory) (Tcl_Interp *interp, CONST char *name, Ttk_ElementFactory factoryProc, VOID *clientData); /* 7 */ + void (*ttk_RegisterLayout) (Ttk_Theme theme, CONST char *className, Ttk_LayoutSpec layoutSpec); /* 8 */ + void (*reserved9)(void); + int (*ttk_GetStateSpecFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_StateSpec *spec_rtn); /* 10 */ + Tcl_Obj * (*ttk_NewStateSpecObj) (unsigned int onbits, unsigned int offbits); /* 11 */ + Ttk_StateMap (*ttk_GetStateMapFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 12 */ + Tcl_Obj * (*ttk_StateMapLookup) (Tcl_Interp *interp, Ttk_StateMap map, Ttk_State state); /* 13 */ + int (*ttk_StateTableLookup) (Ttk_StateTable map[], Ttk_State state); /* 14 */ + void (*reserved15)(void); + void (*reserved16)(void); + void (*reserved17)(void); + void (*reserved18)(void); + void (*reserved19)(void); + int (*ttk_GetPaddingFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 20 */ + int (*ttk_GetBorderFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad_rtn); /* 21 */ + int (*ttk_GetStickyFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *sticky_rtn); /* 22 */ + Ttk_Padding (*ttk_MakePadding) (short l, short t, short r, short b); /* 23 */ + Ttk_Padding (*ttk_UniformPadding) (short borderWidth); /* 24 */ + Ttk_Padding (*ttk_AddPadding) (Ttk_Padding pad1, Ttk_Padding pad2); /* 25 */ + Ttk_Padding (*ttk_RelievePadding) (Ttk_Padding padding, int relief, int n); /* 26 */ + Ttk_Box (*ttk_MakeBox) (int x, int y, int width, int height); /* 27 */ + int (*ttk_BoxContains) (Ttk_Box box, int x, int y); /* 28 */ + Ttk_Box (*ttk_PackBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side); /* 29 */ + Ttk_Box (*ttk_StickBox) (Ttk_Box parcel, int w, int h, Ttk_Sticky sticky); /* 30 */ + Ttk_Box (*ttk_AnchorBox) (Ttk_Box parcel, int w, int h, Tk_Anchor anchor); /* 31 */ + Ttk_Box (*ttk_PadBox) (Ttk_Box b, Ttk_Padding p); /* 32 */ + Ttk_Box (*ttk_ExpandBox) (Ttk_Box b, Ttk_Padding p); /* 33 */ + Ttk_Box (*ttk_PlaceBox) (Ttk_Box *cavity, int w, int h, Ttk_Side side, Ttk_Sticky sticky); /* 34 */ + Tcl_Obj * (*ttk_NewBoxObj) (Ttk_Box box); /* 35 */ + void (*reserved36)(void); + void (*reserved37)(void); + void (*reserved38)(void); + void (*reserved39)(void); + int (*ttk_GetOrientFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int *orient); /* 40 */ +} TtkStubs; + +#ifdef __cplusplus +extern "C" { +#endif +extern const TtkStubs *ttkStubsPtr; +#ifdef __cplusplus +} +#endif + +#if defined(USE_TTK_STUBS) + +/* + * Inline function declarations: + */ + +#define Ttk_GetTheme \ + (ttkStubsPtr->ttk_GetTheme) /* 0 */ +#define Ttk_GetDefaultTheme \ + (ttkStubsPtr->ttk_GetDefaultTheme) /* 1 */ +#define Ttk_GetCurrentTheme \ + (ttkStubsPtr->ttk_GetCurrentTheme) /* 2 */ +#define Ttk_CreateTheme \ + (ttkStubsPtr->ttk_CreateTheme) /* 3 */ +#define Ttk_RegisterCleanup \ + (ttkStubsPtr->ttk_RegisterCleanup) /* 4 */ +#define Ttk_RegisterElementSpec \ + (ttkStubsPtr->ttk_RegisterElementSpec) /* 5 */ +#define Ttk_RegisterElement \ + (ttkStubsPtr->ttk_RegisterElement) /* 6 */ +#define Ttk_RegisterElementFactory \ + (ttkStubsPtr->ttk_RegisterElementFactory) /* 7 */ +#define Ttk_RegisterLayout \ + (ttkStubsPtr->ttk_RegisterLayout) /* 8 */ +/* Slot 9 is reserved */ +#define Ttk_GetStateSpecFromObj \ + (ttkStubsPtr->ttk_GetStateSpecFromObj) /* 10 */ +#define Ttk_NewStateSpecObj \ + (ttkStubsPtr->ttk_NewStateSpecObj) /* 11 */ +#define Ttk_GetStateMapFromObj \ + (ttkStubsPtr->ttk_GetStateMapFromObj) /* 12 */ +#define Ttk_StateMapLookup \ + (ttkStubsPtr->ttk_StateMapLookup) /* 13 */ +#define Ttk_StateTableLookup \ + (ttkStubsPtr->ttk_StateTableLookup) /* 14 */ +/* Slot 15 is reserved */ +/* Slot 16 is reserved */ +/* Slot 17 is reserved */ +/* Slot 18 is reserved */ +/* Slot 19 is reserved */ +#define Ttk_GetPaddingFromObj \ + (ttkStubsPtr->ttk_GetPaddingFromObj) /* 20 */ +#define Ttk_GetBorderFromObj \ + (ttkStubsPtr->ttk_GetBorderFromObj) /* 21 */ +#define Ttk_GetStickyFromObj \ + (ttkStubsPtr->ttk_GetStickyFromObj) /* 22 */ +#define Ttk_MakePadding \ + (ttkStubsPtr->ttk_MakePadding) /* 23 */ +#define Ttk_UniformPadding \ + (ttkStubsPtr->ttk_UniformPadding) /* 24 */ +#define Ttk_AddPadding \ + (ttkStubsPtr->ttk_AddPadding) /* 25 */ +#define Ttk_RelievePadding \ + (ttkStubsPtr->ttk_RelievePadding) /* 26 */ +#define Ttk_MakeBox \ + (ttkStubsPtr->ttk_MakeBox) /* 27 */ +#define Ttk_BoxContains \ + (ttkStubsPtr->ttk_BoxContains) /* 28 */ +#define Ttk_PackBox \ + (ttkStubsPtr->ttk_PackBox) /* 29 */ +#define Ttk_StickBox \ + (ttkStubsPtr->ttk_StickBox) /* 30 */ +#define Ttk_AnchorBox \ + (ttkStubsPtr->ttk_AnchorBox) /* 31 */ +#define Ttk_PadBox \ + (ttkStubsPtr->ttk_PadBox) /* 32 */ +#define Ttk_ExpandBox \ + (ttkStubsPtr->ttk_ExpandBox) /* 33 */ +#define Ttk_PlaceBox \ + (ttkStubsPtr->ttk_PlaceBox) /* 34 */ +#define Ttk_NewBoxObj \ + (ttkStubsPtr->ttk_NewBoxObj) /* 35 */ +/* Slot 36 is reserved */ +/* Slot 37 is reserved */ +/* Slot 38 is reserved */ +/* Slot 39 is reserved */ +#define Ttk_GetOrientFromObj \ + (ttkStubsPtr->ttk_GetOrientFromObj) /* 40 */ + +#endif /* defined(USE_TTK_STUBS) */ + +/* !END!: Do not edit above this line. */ + +#endif /* _TTKDECLS */ diff --git a/generic/ttk/ttkDefaultTheme.c b/generic/ttk/ttkDefaultTheme.c new file mode 100644 index 0000000..d2deee8 --- /dev/null +++ b/generic/ttk/ttkDefaultTheme.c @@ -0,0 +1,1130 @@ +/* + * Copyright (c) 2003, Joe English + * + * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme + */ + +#include <math.h> +#include <string.h> + +#include <tkInt.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "ttkTheme.h" + +#if defined(WIN32) +static const int WIN32_XDRAWLINE_HACK = 1; +#else +static const int WIN32_XDRAWLINE_HACK = 0; +#endif + +#define BORDERWIDTH 2 +#define SCROLLBAR_WIDTH 14 +#define MIN_THUMB_SIZE 8 + +/* + *---------------------------------------------------------------------- + * + * Helper routines for border drawing: + * + * NOTE: MSUE specifies a slightly different arrangement + * for button borders than for other elements; "shadowColors" + * is for button borders. + * + * Please excuse the gross misspelling "LITE" for "LIGHT", + * but it makes things line up nicer. + */ + +enum BorderColor { FLAT = 1, LITE = 2, DARK = 3, BRDR = 4 }; + +/* top-left outer, top-left inner, bottom-right inner, bottom-right outer */ +static int const shadowColors[6][4] = { + { FLAT, FLAT, FLAT, FLAT }, /* TK_RELIEF_FLAT = 0*/ + { DARK, LITE, DARK, LITE }, /* TK_RELIEF_GROOVE = 1*/ + { LITE, FLAT, DARK, BRDR }, /* TK_RELIEF_RAISED = 2*/ + { LITE, DARK, LITE, DARK }, /* TK_RELIEF_RIDGE = 3*/ + { BRDR, BRDR, BRDR, BRDR }, /* TK_RELIEF_SOLID = 4*/ + { BRDR, DARK, FLAT, LITE } /* TK_RELIEF_SUNKEN = 5*/ +}; + +/* top-left, bottom-right */ +static int const thinShadowColors[6][4] = { + { FLAT, FLAT }, /* TK_RELIEF_FLAT = 0*/ + { DARK, LITE }, /* TK_RELIEF_GROOVE = 1*/ + { LITE, DARK }, /* TK_RELIEF_RAISED = 2*/ + { LITE, DARK }, /* TK_RELIEF_RIDGE = 3*/ + { BRDR, BRDR }, /* TK_RELIEF_SOLID = 4*/ + { DARK, LITE } /* TK_RELIEF_SUNKEN = 5*/ +}; + +static void DrawCorner( + Tk_Window tkwin, + Drawable d, + Tk_3DBorder border, /* get most GCs from here... */ + GC borderGC, /* "window border" color GC */ + int x,int y, int width,int height, /* where to draw */ + int corner, /* 0 => top left; 1 => bottom right */ + enum BorderColor color) +{ + XPoint points[3]; + GC gc; + + --width; --height; + points[0].x = x; points[0].y = y+height; + points[1].x = x+width*corner; points[1].y = y+height*corner; + points[2].x = x+width; points[2].y = y; + + if (color == BRDR) + gc = borderGC; + else + gc = Tk_3DBorderGC(tkwin, border, (int)color); + + XDrawLines(Tk_Display(tkwin), d, gc, points, 3, CoordModeOrigin); +} + +static void DrawBorder( + Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor, + Ttk_Box b, int borderWidth, int relief) +{ + GC borderGC = Tk_GCForColor(borderColor, d); + + switch (borderWidth) { + case 2: /* "thick" border */ + DrawCorner(tkwin, d, border, borderGC, + b.x, b.y, b.width, b.height, 0,shadowColors[relief][0]); + DrawCorner(tkwin, d, border, borderGC, + b.x+1, b.y+1, b.width-2, b.height-2, 0,shadowColors[relief][1]); + DrawCorner(tkwin, d, border, borderGC, + b.x+1, b.y+1, b.width-2, b.height-2, 1,shadowColors[relief][2]); + DrawCorner(tkwin, d, border, borderGC, + b.x, b.y, b.width, b.height, 1,shadowColors[relief][3]); + break; + case 1: /* "thin" border */ + DrawCorner(tkwin, d, border, borderGC, + b.x, b.y, b.width, b.height, 0, thinShadowColors[relief][0]); + DrawCorner(tkwin, d, border, borderGC, + b.x, b.y, b.width, b.height, 1, thinShadowColors[relief][1]); + break; + case 0: /* no border -- do nothing */ + break; + default: /* Fall back to Motif-style borders: */ + Tk_Draw3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, borderWidth,relief); + break; + } +} + +/* Alternate shadow colors for entry fields: + * NOTE: FLAT color is normally white, and the LITE color is a darker shade. + */ +static int fieldShadowColors[4] = { DARK, BRDR, LITE, FLAT }; + +static void DrawFieldBorder( + Tk_Window tkwin, Drawable d, Tk_3DBorder border, XColor *borderColor, + Ttk_Box b) +{ + GC borderGC = Tk_GCForColor(borderColor, d); + DrawCorner(tkwin, d, border, borderGC, + b.x, b.y, b.width, b.height, 0,fieldShadowColors[0]); + DrawCorner(tkwin, d, border, borderGC, + b.x+1, b.y+1, b.width-2, b.height-2, 0,fieldShadowColors[1]); + DrawCorner(tkwin, d, border, borderGC, + b.x+1, b.y+1, b.width-2, b.height-2, 1,fieldShadowColors[2]); + DrawCorner(tkwin, d, border, borderGC, + b.x, b.y, b.width, b.height, 1,fieldShadowColors[3]); + return; +} + +/* + * ArrowPoints -- + * Compute points of arrow polygon. + */ +static void ArrowPoints(Ttk_Box b, ArrowDirection dir, XPoint points[4]) +{ + int cx, cy, h; + + switch (dir) { + case ARROW_UP: + h = (b.width - 1)/2; + cx = b.x + h; + cy = b.y; + if (b.height <= h) h = b.height - 1; + points[0].x = cx; points[0].y = cy; + points[1].x = cx - h; points[1].y = cy + h; + points[2].x = cx + h; points[2].y = cy + h; + break; + case ARROW_DOWN: + h = (b.width - 1)/2; + cx = b.x + h; + cy = b.y + b.height - 1; + if (b.height <= h) h = b.height - 1; + points[0].x = cx; points[0].y = cy; + points[1].x = cx - h; points[1].y = cy - h; + points[2].x = cx + h; points[2].y = cy - h; + break; + case ARROW_LEFT: + h = (b.height - 1)/2; + cx = b.x; + cy = b.y + h; + if (b.width <= h) h = b.width - 1; + points[0].x = cx; points[0].y = cy; + points[1].x = cx + h; points[1].y = cy - h; + points[2].x = cx + h; points[2].y = cy + h; + break; + case ARROW_RIGHT: + h = (b.height - 1)/2; + cx = b.x + b.width - 1; + cy = b.y + h; + if (b.width <= h) h = b.width - 1; + points[0].x = cx; points[0].y = cy; + points[1].x = cx - h; points[1].y = cy - h; + points[2].x = cx - h; points[2].y = cy + h; + break; + } + + points[3].x = points[0].x; + points[3].y = points[0].y; +} + +/*public*/ +void TtkArrowSize(int h, ArrowDirection dir, int *widthPtr, int *heightPtr) +{ + switch (dir) { + case ARROW_UP: + case ARROW_DOWN: *widthPtr = 2*h+1; *heightPtr = h+1; break; + case ARROW_LEFT: + case ARROW_RIGHT: *widthPtr = h+1; *heightPtr = 2*h+1; + } +} + +/* + * TtkDrawArrow, TtkFillArrow -- + * Draw an arrow in the indicated direction inside the specified box. + */ +/*public*/ +void TtkFillArrow( + Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir) +{ + XPoint points[4]; + ArrowPoints(b, dir, points); + XFillPolygon(display, d, gc, points, 3, Convex, CoordModeOrigin); + XDrawLines(display, d, gc, points, 4, CoordModeOrigin); +} + +/*public*/ +void TtkDrawArrow( + Display *display, Drawable d, GC gc, Ttk_Box b, ArrowDirection dir) +{ + XPoint points[4]; + ArrowPoints(b, dir, points); + XDrawLines(display, d, gc, points, 4, CoordModeOrigin); +} + +/* + *---------------------------------------------------------------------- + * +++ Border element implementation. + * + * This border consists of (from outside-in): + * + * + a 1-pixel thick default indicator (defaultable widgets only) + * + 1- or 2- pixel shaded border (controlled by -background and -relief) + * + 1 pixel padding (???) + */ + +typedef struct { + Tcl_Obj *borderObj; + Tcl_Obj *borderColorObj; /* Extra border color */ + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *defaultStateObj; /* for buttons */ +} BorderElement; + +static Ttk_ElementOptionSpec BorderElementOptions[] = { + { "-background", TK_OPTION_BORDER, Tk_Offset(BorderElement,borderObj), + DEFAULT_BACKGROUND }, + { "-bordercolor",TK_OPTION_COLOR, + Tk_Offset(BorderElement,borderColorObj), "black" }, + { "-default", TK_OPTION_ANY, Tk_Offset(BorderElement,defaultStateObj), + "disabled" }, + { "-borderwidth",TK_OPTION_PIXELS,Tk_Offset(BorderElement,borderWidthObj), + STRINGIFY(BORDERWIDTH) }, + { "-relief", TK_OPTION_RELIEF, Tk_Offset(BorderElement,reliefObj), + "flat" }, + { NULL, 0, 0, NULL } +}; + +static void BorderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + BorderElement *bd = elementRecord; + int borderWidth = 0; + int defaultState = TTK_BUTTON_DEFAULT_DISABLED; + + Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth); + Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); + + if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { + ++borderWidth; + } + + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void BorderElementDraw( + void *clientData, void *elementRecord, + Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) +{ + BorderElement *bd = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj); + XColor *borderColor = Tk_GetColorFromObj(tkwin, bd->borderColorObj); + int borderWidth = 2; + int relief = TK_RELIEF_FLAT; + int defaultState = TTK_BUTTON_DEFAULT_DISABLED; + + /* + * Get option values. + */ + Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); + Ttk_GetButtonDefaultStateFromObj(NULL, bd->defaultStateObj, &defaultState); + + if (defaultState == TTK_BUTTON_DEFAULT_ACTIVE) { + GC gc = Tk_GCForColor(borderColor, d); + XDrawRectangle(Tk_Display(tkwin), d, gc, + b.x, b.y, b.width-1, b.height-1); + } + if (defaultState != TTK_BUTTON_DEFAULT_DISABLED) { + /* Space for default ring: */ + b = Ttk_PadBox(b, Ttk_UniformPadding(1)); + } + + DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief); +} + +static Ttk_ElementSpec BorderElementSpec = { + TK_STYLE_VERSION_2, + sizeof(BorderElement), + BorderElementOptions, + BorderElementSize, + BorderElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Field element: + * Used for editable fields. + */ +typedef struct { + Tcl_Obj *borderObj; + Tcl_Obj *borderColorObj; /* Extra border color */ +} FieldElement; + +static Ttk_ElementOptionSpec FieldElementOptions[] = { + { "-fieldbackground", TK_OPTION_BORDER, Tk_Offset(FieldElement,borderObj), + "white" }, + { "-bordercolor",TK_OPTION_COLOR, Tk_Offset(FieldElement,borderColorObj), + "black" }, + { NULL, 0, 0, NULL } +}; + +static void FieldElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + *paddingPtr = Ttk_UniformPadding(2); +} + +static void FieldElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FieldElement *field = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj); + XColor *borderColor = Tk_GetColorFromObj(tkwin, field->borderColorObj); + + Tk_Fill3DRectangle( + tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_SUNKEN); + DrawFieldBorder(tkwin, d, border, borderColor, b); +} + +static Ttk_ElementSpec FieldElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + FieldElementSize, + FieldElementDraw +}; + +/*------------------------------------------------------------------------ + * Indicators -- + * + * Code derived (probably incorrectly) from TIP 109 implementation, + * unix/tkUnixButton.c r 1.15. + */ + +/* + * Indicator bitmap descriptor: + */ +typedef struct { + int width; /* Width of each image */ + int height; /* Height of each image */ + int nimages; /* #images / row */ + const char *const *pixels; /* array[height] of char[width*nimage] */ + Ttk_StateTable *map;/* used to look up image index by state */ +} IndicatorSpec; + +#if 0 +/*XPM*/ +static const char *const button_images[] = { + /* width height ncolors chars_per_pixel */ + "52 13 8 1", + /* colors */ + "A c #808000000000 s shadow", + "B c #000080800000 s highlight", + "C c #808080800000 s 3dlight", + "D c #000000008080 s window", + "E c #808000008080 s 3ddark", + "F c #000080808080 s frame", + "G c #000000000000 s foreground", + "H c #000080800000 s disabledfg", +}; +#endif + +static Ttk_StateTable checkbutton_states[] = { + { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED }, + { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED }, + { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED }, + { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 }, + { 0, 0, 0 } +}; + +static const char *const checkbutton_pixels[] = { + "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB", + "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB", + "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", + "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB", + "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB", + "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB", + "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB", + "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB", + "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB", + "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB", + "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", + "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB", + "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", +}; + +static IndicatorSpec checkbutton_spec = { + 13, 13, 4, /* width, height, nimages */ + checkbutton_pixels, + checkbutton_states +}; + +static Ttk_StateTable radiobutton_states[] = { + { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED }, + { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED }, + { 2, TTK_STATE_DISABLED, TTK_STATE_SELECTED }, + { 3, TTK_STATE_SELECTED|TTK_STATE_DISABLED, 0 }, + { 0, 0, 0 } +}; + +static const char *const radiobutton_pixels[] = { + "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF", + "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF", + "FAEEDDDDEEBFFFAEEDDDDEEBFFFAEEFFFFEEBFFFAEEFFFFEEBFF", + "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", + "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", + "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", + "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", + "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", + "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", + "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF", + "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF", + "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", +}; + +static IndicatorSpec radiobutton_spec = { + 13, 13, 4, /* width, height, nimages */ + radiobutton_pixels, + radiobutton_states +}; + +typedef struct { + Tcl_Obj *backgroundObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *colorObj; + Tcl_Obj *lightColorObj; + Tcl_Obj *shadeColorObj; + Tcl_Obj *borderColorObj; + Tcl_Obj *marginObj; +} IndicatorElement; + +static Ttk_ElementOptionSpec IndicatorElementOptions[] = { + { "-background", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, + { "-foreground", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,foregroundObj), DEFAULT_FOREGROUND }, + { "-indicatorcolor", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,colorObj), "#FFFFFF" }, + { "-lightcolor", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,lightColorObj), "#DDDDDD" }, + { "-shadecolor", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,shadeColorObj), "#888888" }, + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(IndicatorElement,borderColorObj), "black" }, + { "-indicatormargin", TK_OPTION_STRING, + Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" }, + { NULL, 0, 0, NULL } +}; + +static void IndicatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + IndicatorSpec *spec = clientData; + IndicatorElement *indicator = elementRecord; + Ttk_Padding margins; + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins); + *widthPtr = spec->width + Ttk_PaddingWidth(margins); + *heightPtr = spec->height + Ttk_PaddingHeight(margins); +} + +static void IndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + IndicatorSpec *spec = clientData; + IndicatorElement *indicator = elementRecord; + Display *display = Tk_Display(tkwin); + Ttk_Padding padding; + XColor *fgColor, *frameColor, *shadeColor, *indicatorColor, *borderColor; + + int index, ix, iy; + XGCValues gcValues; + GC copyGC; + unsigned long imgColors[8]; + XImage *img; + + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding); + b = Ttk_PadBox(b, padding); + + if ( b.x < 0 + || b.y < 0 + || Tk_Width(tkwin) < b.x + spec->width + || Tk_Height(tkwin) < b.y + spec->height) + { + /* Oops! not enough room to display the image. + * Don't draw anything. + */ + return; + } + + /* + * Fill in imgColors palette: + * + * (SHOULD: take light and shade colors from the border object, + * but Tk doesn't provide easy access to these in the public API.) + */ + fgColor = Tk_GetColorFromObj(tkwin, indicator->foregroundObj); + frameColor = Tk_GetColorFromObj(tkwin, indicator->backgroundObj); + shadeColor = Tk_GetColorFromObj(tkwin, indicator->shadeColorObj); + indicatorColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); + borderColor = Tk_GetColorFromObj(tkwin, indicator->borderColorObj); + + imgColors[0 /*A*/] = shadeColor->pixel; + imgColors[1 /*B*/] = indicatorColor->pixel; + imgColors[2 /*C*/] = frameColor->pixel; + imgColors[3 /*D*/] = indicatorColor->pixel; + imgColors[4 /*E*/] = borderColor->pixel; + imgColors[5 /*F*/] = frameColor->pixel; + imgColors[6 /*G*/] = fgColor->pixel; + imgColors[7 /*H*/] = fgColor->pixel; + + /* + * Create a scratch buffer to store the image: + */ + img = XGetImage(display,d, 0, 0, + (unsigned int)spec->width, (unsigned int)spec->height, + AllPlanes, ZPixmap); + if (img == NULL) + return; + + /* + * Create the image, painting it into an XImage one pixel at a time. + */ + index = Ttk_StateTableLookup(spec->map, state); + for (iy=0 ; iy<spec->height ; iy++) { + for (ix=0 ; ix<spec->width ; ix++) { + XPutPixel(img, ix, iy, + imgColors[spec->pixels[iy][index*spec->width+ix] - 'A'] ); + } + } + + /* + * Copy onto our target drawable surface. + */ + memset(&gcValues, 0, sizeof(gcValues)); + copyGC = Tk_GetGC(tkwin, 0, &gcValues); + + TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y, + spec->width, spec->height); + + /* + * Tidy up. + */ + Tk_FreeGC(display, copyGC); + XDestroyImage(img); +} + +static Ttk_ElementSpec IndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(IndicatorElement), + IndicatorElementOptions, + IndicatorElementSize, + IndicatorElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Arrow element(s). + * + * Draws a solid triangle, inside a box. + * clientData is an enum ArrowDirection pointer. + */ + +static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT }; +typedef struct { + Tcl_Obj *sizeObj; + Tcl_Obj *borderObj; + Tcl_Obj *borderColorObj; /* Extra color for borders */ + Tcl_Obj *reliefObj; + Tcl_Obj *colorObj; /* Arrow color */ +} ArrowElement; + +static Ttk_ElementOptionSpec ArrowElementOptions[] = { + { "-arrowsize", TK_OPTION_PIXELS, + Tk_Offset(ArrowElement,sizeObj), STRINGIFY(SCROLLBAR_WIDTH) }, + { "-background", TK_OPTION_BORDER, + Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND }, + { "-bordercolor", TK_OPTION_COLOR, + Tk_Offset(ArrowElement,borderColorObj), "black" }, + { "-relief", TK_OPTION_RELIEF, + Tk_Offset(ArrowElement,reliefObj),"raised"}, + { "-arrowcolor", TK_OPTION_COLOR, + Tk_Offset(ArrowElement,colorObj),"black"}, + { NULL, 0, 0, NULL } +}; + +/* + * Note asymmetric padding: + * top/left padding is 1 less than bottom/right, + * since in this theme 2-pixel borders are asymmetric. + */ +static Ttk_Padding ArrowPadding = { 3,3,4,4 }; + +static void ArrowElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ArrowElement *arrow = elementRecord; + int direction = *(int *)clientData; + int width = SCROLLBAR_WIDTH; + + Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width); + width -= Ttk_PaddingWidth(ArrowPadding); + TtkArrowSize(width/2, direction, widthPtr, heightPtr); + *widthPtr += Ttk_PaddingWidth(ArrowPadding); + *heightPtr += Ttk_PaddingHeight(ArrowPadding); +} + +static void ArrowElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + int direction = *(int *)clientData; + ArrowElement *arrow = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj); + XColor *borderColor = Tk_GetColorFromObj(tkwin, arrow->borderColorObj); + XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj); + int relief = TK_RELIEF_RAISED; + int borderWidth = 2; + + Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief); + + Tk_Fill3DRectangle( + tkwin, d, border, b.x, b.y, b.width, b.height, 0, TK_RELIEF_FLAT); + DrawBorder(tkwin,d,border,borderColor,b,borderWidth,relief); + + TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d), + Ttk_PadBox(b, ArrowPadding), direction); +} + +static Ttk_ElementSpec ArrowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ArrowElement), + ArrowElementOptions, + ArrowElementSize, + ArrowElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Menubutton indicator: + * Draw an arrow in the direction where the menu will be posted. + */ + +#define MENUBUTTON_ARROW_SIZE 5 + +typedef struct { + Tcl_Obj *directionObj; + Tcl_Obj *sizeObj; + Tcl_Obj *colorObj; +} MenubuttonArrowElement; + +static const char *directionStrings[] = { /* See also: button.c */ + "above", "below", "left", "right", "flush", NULL +}; +enum { POST_ABOVE, POST_BELOW, POST_LEFT, POST_RIGHT, POST_FLUSH }; + +static Ttk_ElementOptionSpec MenubuttonArrowElementOptions[] = { + { "-direction", TK_OPTION_STRING, + Tk_Offset(MenubuttonArrowElement,directionObj), "below" }, + { "-arrowsize", TK_OPTION_PIXELS, + Tk_Offset(MenubuttonArrowElement,sizeObj), STRINGIFY(MENUBUTTON_ARROW_SIZE)}, + { "-arrowcolor",TK_OPTION_COLOR, + Tk_Offset(MenubuttonArrowElement,colorObj), "black"}, + { NULL, 0, 0, NULL } +}; + +static Ttk_Padding MenubuttonArrowPadding = { 3, 0, 3, 0 }; + +static void MenubuttonArrowElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + MenubuttonArrowElement *arrow = elementRecord; + int size = MENUBUTTON_ARROW_SIZE; + Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size); + *widthPtr = *heightPtr = 2 * size + 1; + *widthPtr += Ttk_PaddingWidth(MenubuttonArrowPadding); + *heightPtr += Ttk_PaddingHeight(MenubuttonArrowPadding); +} + +static void MenubuttonArrowElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + MenubuttonArrowElement *arrow = elementRecord; + XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj); + GC gc = Tk_GCForColor(arrowColor, d); + int size = MENUBUTTON_ARROW_SIZE; + int postDirection = POST_BELOW; + ArrowDirection arrowDirection = ARROW_DOWN; + int width = 0, height = 0; + + Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &size); + Tcl_GetIndexFromObj(NULL, arrow->directionObj, directionStrings, + ""/*message*/, 0/*flags*/, &postDirection); + + /* ... this might not be such a great idea ... */ + switch (postDirection) { + case POST_ABOVE: arrowDirection = ARROW_UP; break; + case POST_BELOW: arrowDirection = ARROW_DOWN; break; + case POST_LEFT: arrowDirection = ARROW_LEFT; break; + case POST_RIGHT: arrowDirection = ARROW_RIGHT; break; + case POST_FLUSH: arrowDirection = ARROW_DOWN; break; + } + + TtkArrowSize(size, arrowDirection, &width, &height); + b = Ttk_PadBox(b, MenubuttonArrowPadding); + b = Ttk_AnchorBox(b, width, height, TK_ANCHOR_CENTER); + TtkFillArrow(Tk_Display(tkwin), d, gc, b, arrowDirection); +} + +static Ttk_ElementSpec MenubuttonArrowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(MenubuttonArrowElement), + MenubuttonArrowElementOptions, + MenubuttonArrowElementSize, + MenubuttonArrowElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Trough element + * + * Used in scrollbars and the scale. + * + * The -groovewidth option can be used to set the size of the short axis + * for the drawn area. This will not affect the geometry, but can be used + * to draw a thin centered trough inside the packet alloted. This is used + * to show a win32-style scale widget. Use -1 or a large number to use the + * full area (default). + * + */ + +typedef struct { + Tcl_Obj *colorObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *grooveWidthObj; + Tcl_Obj *orientObj; +} TroughElement; + +static Ttk_ElementOptionSpec TroughElementOptions[] = { + { "-orient", TK_OPTION_ANY, + Tk_Offset(TroughElement, orientObj), "horizontal" }, + { "-troughborderwidth", TK_OPTION_PIXELS, + Tk_Offset(TroughElement,borderWidthObj), "1" }, + { "-troughcolor", TK_OPTION_BORDER, + Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND }, + { "-troughrelief",TK_OPTION_RELIEF, + Tk_Offset(TroughElement,reliefObj), "sunken" }, + { "-groovewidth", TK_OPTION_PIXELS, + Tk_Offset(TroughElement,grooveWidthObj), "-1" }, + { NULL, 0, 0, NULL } +}; + +static void TroughElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TroughElement *troughPtr = elementRecord; + int borderWidth = 2, grooveWidth = 0; + + Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth); + Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &grooveWidth); + + if (grooveWidth <= 0) { + *paddingPtr = Ttk_UniformPadding((short)borderWidth); + } +} + +static void TroughElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + TroughElement *troughPtr = elementRecord; + Tk_3DBorder border = NULL; + int borderWidth = 2, relief = TK_RELIEF_SUNKEN, groove = -1, orient; + + border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj); + Ttk_GetOrientFromObj(NULL, troughPtr->orientObj, &orient); + Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief); + Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth); + Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->grooveWidthObj, &groove); + + if (groove != -1 && groove < b.height && groove < b.width) { + if (orient == TTK_ORIENT_HORIZONTAL) { + b.y = b.y + b.height/2 - groove/2; + b.height = groove; + } else { + b.x = b.x + b.width/2 - groove/2; + b.width = groove; + } + } + + Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height, + borderWidth, relief); +} + +static Ttk_ElementSpec TroughElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TroughElement), + TroughElementOptions, + TroughElementSize, + TroughElementDraw +}; + +/* + *---------------------------------------------------------------------- + * +++ Thumb element. + */ + +typedef struct { + Tcl_Obj *sizeObj; + Tcl_Obj *firstObj; + Tcl_Obj *lastObj; + Tcl_Obj *borderObj; + Tcl_Obj *borderColorObj; + Tcl_Obj *reliefObj; + Tcl_Obj *orientObj; +} ThumbElement; + +static Ttk_ElementOptionSpec ThumbElementOptions[] = { + { "-width", TK_OPTION_PIXELS, Tk_Offset(ThumbElement,sizeObj), + STRINGIFY(SCROLLBAR_WIDTH) }, + { "-background", TK_OPTION_BORDER, Tk_Offset(ThumbElement,borderObj), + DEFAULT_BACKGROUND }, + { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj), + "black" }, + { "-relief", TK_OPTION_RELIEF,Tk_Offset(ThumbElement,reliefObj),"raised" }, + { "-orient", TK_OPTION_ANY,Tk_Offset(ThumbElement,orientObj),"horizontal"}, + { NULL, 0, 0, NULL } +}; + +static void ThumbElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ThumbElement *thumb = elementRecord; + int orient, size; + Tk_GetPixelsFromObj(NULL, tkwin, thumb->sizeObj, &size); + Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient); + + if (orient == TTK_ORIENT_VERTICAL) { + *widthPtr = size; + *heightPtr = MIN_THUMB_SIZE; + } else { + *widthPtr = MIN_THUMB_SIZE; + *heightPtr = size; + } +} + +static void ThumbElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + ThumbElement *thumb = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj); + XColor *borderColor = Tk_GetColorFromObj(tkwin, thumb->borderColorObj); + int relief = TK_RELIEF_RAISED; + int borderWidth = 2; + + /* + * Don't draw the thumb if we are disabled. + * This makes it behave like Windows ... if that's what we want. + if (state & TTK_STATE_DISABLED) + return; + */ + + Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief); + + Tk_Fill3DRectangle( + tkwin, d, border, b.x,b.y,b.width,b.height, 0, TK_RELIEF_FLAT); + DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief); +} + +static Ttk_ElementSpec ThumbElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ThumbElement), + ThumbElementOptions, + ThumbElementSize, + ThumbElementDraw +}; + +/* + *---------------------------------------------------------------------- + * +++ Slider element. + * + * This is the moving part of the scale widget. + * + * The slider element is the thumb in the scale widget. This is drawn + * as an arrow-type element that can point up, down, left or right. + * + */ + +typedef struct { + Tcl_Obj *lengthObj; /* Long axis dimension */ + Tcl_Obj *thicknessObj; /* Short axis dimension */ + Tcl_Obj *reliefObj; /* Relief for this object */ + Tcl_Obj *borderObj; /* Border / background color */ + Tcl_Obj *borderColorObj; /* Additional border color */ + Tcl_Obj *borderWidthObj; + Tcl_Obj *orientObj; /* Orientation of overall slider */ +} SliderElement; + +static Ttk_ElementOptionSpec SliderElementOptions[] = { + { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj), + "15" }, + { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj), + "15" }, + { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj), + "raised" }, + { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj), + STRINGIFY(BORDERWIDTH) }, + { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj), + DEFAULT_BACKGROUND }, + { "-bordercolor", TK_OPTION_COLOR, Tk_Offset(ThumbElement,borderColorObj), + "black" }, + { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj), + "horizontal" }, + { NULL, 0, 0, NULL } +}; + +static void SliderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SliderElement *slider = elementRecord; + int orient, length, thickness, borderWidth; + + Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient); + Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth); + Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length); + Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness); + + switch (orient) { + case TTK_ORIENT_VERTICAL: + *widthPtr = thickness + (borderWidth *2); + *heightPtr = *widthPtr/2; + break; + + case TTK_ORIENT_HORIZONTAL: + *heightPtr = thickness + (borderWidth *2); + *widthPtr = *heightPtr/2; + break; + } +} + +static void SliderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + SliderElement *slider = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj); + XColor *borderColor = Tk_GetColorFromObj(tkwin, slider->borderColorObj); + int relief = TK_RELIEF_RAISED, borderWidth = 2; + + Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief); + + Tk_Fill3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, + borderWidth, TK_RELIEF_FLAT); + DrawBorder(tkwin, d, border, borderColor, b, borderWidth, relief); +} + +static Ttk_ElementSpec SliderElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SliderElement), + SliderElementOptions, + SliderElementSize, + SliderElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Tree indicator element. + */ + +#define TTK_STATE_OPEN TTK_STATE_USER1 /* XREF: treeview.c */ +#define TTK_STATE_LEAF TTK_STATE_USER2 + +typedef struct { + Tcl_Obj *colorObj; + Tcl_Obj *marginObj; + Tcl_Obj *diameterObj; +} TreeitemIndicator; + +static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = { + { "-foreground", TK_OPTION_COLOR, + Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND }, + { "-diameter", TK_OPTION_PIXELS, + Tk_Offset(TreeitemIndicator,diameterObj), "9" }, + { "-indicatormargins", TK_OPTION_STRING, + Tk_Offset(TreeitemIndicator,marginObj), "2 2 4 2" }, + { NULL, 0, 0, NULL } +}; + +static void TreeitemIndicatorSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TreeitemIndicator *indicator = elementRecord; + int diameter = 0; + Ttk_Padding margins; + + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins); + Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter); + *widthPtr = diameter + Ttk_PaddingWidth(margins); + *heightPtr = diameter + Ttk_PaddingHeight(margins); +} + +static void TreeitemIndicatorDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + TreeitemIndicator *indicator = elementRecord; + XColor *color = Tk_GetColorFromObj(tkwin, indicator->colorObj); + GC gc = Tk_GCForColor(color, d); + Ttk_Padding padding = Ttk_UniformPadding(0); + int w = WIN32_XDRAWLINE_HACK; + int cx, cy; + + if (state & TTK_STATE_LEAF) { + /* don't draw anything ... */ + return; + } + + Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding); + b = Ttk_PadBox(b, padding); + + XDrawRectangle(Tk_Display(tkwin), d, gc, + b.x, b.y, b.width - 1, b.height - 1); + + cx = b.x + (b.width - 1) / 2; + cy = b.y + (b.height - 1) / 2; + XDrawLine(Tk_Display(tkwin), d, gc, b.x+2, cy, b.x+b.width-3+w, cy); + + if (!(state & TTK_STATE_OPEN)) { + /* turn '-' into a '+' */ + XDrawLine(Tk_Display(tkwin), d, gc, cx, b.y+2, cx, b.y+b.height-3+w); + } +} + +static Ttk_ElementSpec TreeitemIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TreeitemIndicator), + TreeitemIndicatorOptions, + TreeitemIndicatorSize, + TreeitemIndicatorDraw +}; + +/*------------------------------------------------------------------------ + * TtkAltTheme_Init -- + * Install alternate theme. + */ +MODULE_SCOPE int TtkAltTheme_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_CreateTheme(interp, "alt", NULL); + + if (!theme) { + return TCL_ERROR; + } + + Ttk_RegisterElement(interp, theme, "border", &BorderElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "Checkbutton.indicator", + &IndicatorElementSpec, &checkbutton_spec); + Ttk_RegisterElement(interp, theme, "Radiobutton.indicator", + &IndicatorElementSpec, &radiobutton_spec); + Ttk_RegisterElement(interp, theme, "Menubutton.indicator", + &MenubuttonArrowElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "uparrow", + &ArrowElementSpec, &ArrowElements[0]); + Ttk_RegisterElement(interp, theme, "downarrow", + &ArrowElementSpec, &ArrowElements[1]); + Ttk_RegisterElement(interp, theme, "leftarrow", + &ArrowElementSpec, &ArrowElements[2]); + Ttk_RegisterElement(interp, theme, "rightarrow", + &ArrowElementSpec, &ArrowElements[3]); + Ttk_RegisterElement(interp, theme, "arrow", + &ArrowElementSpec, &ArrowElements[0]); + + Ttk_RegisterElement(interp, theme, "arrow", + &ArrowElementSpec, &ArrowElements[0]); + + Ttk_RegisterElement(interp, theme, "Treeitem.indicator", + &TreeitemIndicatorElementSpec, 0); + + Tcl_PkgProvide(interp, "ttk::theme::alt", TTK_VERSION); + + return TCL_OK; +} + +/*EOF*/ diff --git a/generic/ttk/ttkElements.c b/generic/ttk/ttkElements.c new file mode 100644 index 0000000..22af1d6 --- /dev/null +++ b/generic/ttk/ttkElements.c @@ -0,0 +1,1281 @@ +/* + * Copyright (c) 2003, Joe English + * + * Default implementation for themed elements. + * + */ + +#include <tcl.h> +#include <tk.h> +#include <string.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +#define DEFAULT_BORDERWIDTH "2" +#define DEFAULT_ARROW_SIZE "15" +#define MIN_THUMB_SIZE 10 + +/*---------------------------------------------------------------------- + * +++ Null element. Does nothing; used as a stub. + * Null element methods, option table and element spec are public, + * and may be used in other engines. + */ + +/* public */ Ttk_ElementOptionSpec TtkNullElementOptions[] = { { NULL, 0, 0, NULL } }; + +/* public */ void +TtkNullElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ +} + +/* public */ void +TtkNullElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ +} + +/* public */ Ttk_ElementSpec ttkNullElementSpec = { + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + TtkNullElementSize, + TtkNullElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Background and fill elements. + * + * The fill element fills its parcel with the background color. + * The background element ignores the parcel, and fills the entire window. + * + * Ttk_GetLayout() automatically includes a background element. + */ + +typedef struct { + Tcl_Obj *backgroundObj; +} BackgroundElement; + +static Ttk_ElementOptionSpec BackgroundElementOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(BackgroundElement,backgroundObj), DEFAULT_BACKGROUND }, + { NULL, 0, 0, NULL } +}; + +static void FillElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + BackgroundElement *bg = elementRecord; + Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin,bg->backgroundObj); + + XFillRectangle(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), + b.x, b.y, b.width, b.height); +} + +static void BackgroundElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FillElementDraw( + clientData, elementRecord, tkwin, + d, Ttk_WinBox(tkwin), state); +} + +static Ttk_ElementSpec FillElementSpec = { + TK_STYLE_VERSION_2, + sizeof(BackgroundElement), + BackgroundElementOptions, + TtkNullElementSize, + FillElementDraw +}; + +static Ttk_ElementSpec BackgroundElementSpec = { + TK_STYLE_VERSION_2, + sizeof(BackgroundElement), + BackgroundElementOptions, + TtkNullElementSize, + BackgroundElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Border element. + */ + +typedef struct { + Tcl_Obj *borderObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; +} BorderElement; + +static Ttk_ElementOptionSpec BorderElementOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(BorderElement,borderObj), DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(BorderElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { "-relief", TK_OPTION_RELIEF, + Tk_Offset(BorderElement,reliefObj), "flat" }, + { NULL, 0, 0, NULL } +}; + +static void BorderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + BorderElement *bd = elementRecord; + int borderWidth = 0; + Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth); + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void BorderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + BorderElement *bd = elementRecord; + Tk_3DBorder border = NULL; + int borderWidth = 1, relief = TK_RELIEF_FLAT; + + border = Tk_Get3DBorderFromObj(tkwin, bd->borderObj); + Tcl_GetIntFromObj(NULL, bd->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, bd->reliefObj, &relief); + + if (border && borderWidth > 0 && relief != TK_RELIEF_FLAT) { + Tk_Draw3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, borderWidth,relief); + } +} + +static Ttk_ElementSpec BorderElementSpec = { + TK_STYLE_VERSION_2, + sizeof(BorderElement), + BorderElementOptions, + BorderElementSize, + BorderElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Field element. + * Used for editable fields. + */ +typedef struct { + Tcl_Obj *borderObj; + Tcl_Obj *borderWidthObj; +} FieldElement; + +static Ttk_ElementOptionSpec FieldElementOptions[] = { + { "-fieldbackground", TK_OPTION_BORDER, + Tk_Offset(FieldElement,borderObj), "white" }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(FieldElement,borderWidthObj), "2" }, + { NULL, 0, 0, NULL } +}; + +static void FieldElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + FieldElement *field = elementRecord; + int borderWidth = 2; + Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth); + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void FieldElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FieldElement *field = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, field->borderObj); + int borderWidth = 2; + + Tk_GetPixelsFromObj(NULL, tkwin, field->borderWidthObj, &borderWidth); + Tk_Fill3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, borderWidth, TK_RELIEF_SUNKEN); +} + +static Ttk_ElementSpec FieldElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FieldElement), + FieldElementOptions, + FieldElementSize, + FieldElementDraw +}; + +/* + *---------------------------------------------------------------------- + * +++ Padding element. + * + * This element has no visual representation, only geometry. + * It adds a (possibly non-uniform) internal border. + * In addition, if "-shiftrelief" is specified, + * adds additional pixels to shift child elements "in" or "out" + * depending on the -relief. + */ + +typedef struct { + Tcl_Obj *paddingObj; + Tcl_Obj *reliefObj; + Tcl_Obj *shiftreliefObj; +} PaddingElement; + +static Ttk_ElementOptionSpec PaddingElementOptions[] = { + { "-padding", TK_OPTION_STRING, + Tk_Offset(PaddingElement,paddingObj), "0" }, + { "-relief", TK_OPTION_RELIEF, + Tk_Offset(PaddingElement,reliefObj), "flat" }, + { "-shiftrelief", TK_OPTION_INT, + Tk_Offset(PaddingElement,shiftreliefObj), "0" }, + { NULL, 0, 0, NULL } +}; + +static void PaddingElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + PaddingElement *padding = elementRecord; + int shiftRelief = 0; + int relief = TK_RELIEF_FLAT; + Ttk_Padding pad; + + Tk_GetReliefFromObj(NULL, padding->reliefObj, &relief); + Tcl_GetIntFromObj(NULL, padding->shiftreliefObj, &shiftRelief); + Ttk_GetPaddingFromObj(NULL,tkwin,padding->paddingObj,&pad); + *paddingPtr = Ttk_RelievePadding(pad, relief, shiftRelief); +} + +static Ttk_ElementSpec PaddingElementSpec = { + TK_STYLE_VERSION_2, + sizeof(PaddingElement), + PaddingElementOptions, + PaddingElementSize, + TtkNullElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Focus ring element. + * Draws a dashed focus ring, if the widget has keyboard focus. + */ +typedef struct { + Tcl_Obj *focusColorObj; + Tcl_Obj *focusThicknessObj; +} FocusElement; + +/* + * DrawFocusRing -- + * Draw a dotted rectangle to indicate focus. + */ +static void DrawFocusRing( + Tk_Window tkwin, Drawable d, Tcl_Obj *colorObj, Ttk_Box b) +{ + XColor *color = Tk_GetColorFromObj(tkwin, colorObj); + unsigned long mask = 0UL; + XGCValues gcvalues; + GC gc; + + gcvalues.foreground = color->pixel; + gcvalues.line_style = LineOnOffDash; + gcvalues.line_width = 1; + gcvalues.dashes = 1; + gcvalues.dash_offset = 1; + mask = GCForeground | GCLineStyle | GCDashList | GCDashOffset | GCLineWidth; + + gc = Tk_GetGC(tkwin, mask, &gcvalues); + XDrawRectangle(Tk_Display(tkwin), d, gc, b.x, b.y, b.width-1, b.height-1); + Tk_FreeGC(Tk_Display(tkwin), gc); +} + +static Ttk_ElementOptionSpec FocusElementOptions[] = { + { "-focuscolor",TK_OPTION_COLOR, + Tk_Offset(FocusElement,focusColorObj), "black" }, + { "-focusthickness",TK_OPTION_PIXELS, + Tk_Offset(FocusElement,focusThicknessObj), "1" }, + { NULL, 0, 0, NULL } +}; + +static void FocusElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + FocusElement *focus = elementRecord; + int focusThickness = 0; + + Tcl_GetIntFromObj(NULL, focus->focusThicknessObj, &focusThickness); + *paddingPtr = Ttk_UniformPadding((short)focusThickness); +} + +static void FocusElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + FocusElement *focus = elementRecord; + int focusThickness = 0; + + if (state & TTK_STATE_FOCUS) { + Tcl_GetIntFromObj(NULL,focus->focusThicknessObj,&focusThickness); + DrawFocusRing(tkwin, d, focus->focusColorObj, b); + } +} + +static Ttk_ElementSpec FocusElementSpec = { + TK_STYLE_VERSION_2, + sizeof(FocusElement), + FocusElementOptions, + FocusElementSize, + FocusElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Separator element. + * Just draws a horizontal or vertical bar. + * Three elements are defined: horizontal, vertical, and general; + * the general separator checks the "-orient" option. + */ + +typedef struct { + Tcl_Obj *orientObj; + Tcl_Obj *borderObj; +} SeparatorElement; + +static Ttk_ElementOptionSpec SeparatorElementOptions[] = { + { "-orient", TK_OPTION_ANY, + Tk_Offset(SeparatorElement, orientObj), "horizontal" }, + { "-background", TK_OPTION_BORDER, + Tk_Offset(SeparatorElement,borderObj), DEFAULT_BACKGROUND }, + { NULL, 0, 0, NULL } +}; + +static void SeparatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + *widthPtr = *heightPtr = 2; +} + +static void HorizontalSeparatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + SeparatorElement *separator = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj); + GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); + + XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x + b.width, b.y); + XDrawLine(Tk_Display(tkwin), d, lightGC, b.x, b.y+1, b.x + b.width, b.y+1); +} + +static void VerticalSeparatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + SeparatorElement *separator = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, separator->borderObj); + GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); + + XDrawLine(Tk_Display(tkwin), d, darkGC, b.x, b.y, b.x, b.y + b.height); + XDrawLine(Tk_Display(tkwin), d, lightGC, b.x+1, b.y, b.x+1, b.y+b.height); +} + +static void GeneralSeparatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + SeparatorElement *separator = elementRecord; + int orient; + Ttk_GetOrientFromObj(NULL, separator->orientObj, &orient); + switch (orient) { + case TTK_ORIENT_HORIZONTAL: + HorizontalSeparatorElementDraw( + clientData, elementRecord, tkwin, d, b, state); + break; + case TTK_ORIENT_VERTICAL: + VerticalSeparatorElementDraw( + clientData, elementRecord, tkwin, d, b, state); + break; + } +} + +static Ttk_ElementSpec HorizontalSeparatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SeparatorElement), + SeparatorElementOptions, + SeparatorElementSize, + HorizontalSeparatorElementDraw +}; + +static Ttk_ElementSpec VerticalSeparatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SeparatorElement), + SeparatorElementOptions, + SeparatorElementSize, + HorizontalSeparatorElementDraw +}; + +static Ttk_ElementSpec SeparatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SeparatorElement), + SeparatorElementOptions, + SeparatorElementSize, + GeneralSeparatorElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Sizegrip: lower-right corner grip handle for resizing window. + */ + +typedef struct { + Tcl_Obj *backgroundObj; +} SizegripElement; + +static Ttk_ElementOptionSpec SizegripOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(SizegripElement,backgroundObj), DEFAULT_BACKGROUND }, + {0,0,0,0} +}; + +static void SizegripSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + int gripCount = 3, gripSpace = 2, gripThickness = 3; + *widthPtr = *heightPtr = gripCount * (gripSpace + gripThickness); +} + +static void SizegripDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + SizegripElement *grip = elementRecord; + int gripCount = 3, gripSpace = 2; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, grip->backgroundObj); + GC lightGC = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC); + GC darkGC = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC); + int x1 = b.x + b.width-1, y1 = b.y + b.height-1, x2 = x1, y2 = y1; + + while (gripCount--) { + x1 -= gripSpace; y2 -= gripSpace; + XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); --x1; --y2; + XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2); --x1; --y2; + XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2); --x1; --y2; + } +} + +static Ttk_ElementSpec SizegripElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SizegripElement), + SizegripOptions, + SizegripSize, + SizegripDraw +}; + +/*---------------------------------------------------------------------- + * +++ Indicator element. + * + * Draws the on/off indicator for checkbuttons and radiobuttons. + * + * Draws a 3-D square (or diamond), raised if off, sunken if on. + * + * This is actually a regression from Tk 8.5 back to the ugly old Motif + * style; use "altTheme" for the newer, nicer version. + */ + +typedef struct { + Tcl_Obj *backgroundObj; + Tcl_Obj *reliefObj; + Tcl_Obj *colorObj; + Tcl_Obj *diameterObj; + Tcl_Obj *marginObj; + Tcl_Obj *borderWidthObj; +} IndicatorElement; + +static Ttk_ElementOptionSpec IndicatorElementOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(IndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, + { "-indicatorcolor", TK_OPTION_BORDER, + Tk_Offset(IndicatorElement,colorObj), DEFAULT_BACKGROUND }, + { "-indicatorrelief", TK_OPTION_RELIEF, + Tk_Offset(IndicatorElement,reliefObj), "raised" }, + { "-indicatordiameter", TK_OPTION_PIXELS, + Tk_Offset(IndicatorElement,diameterObj), "12" }, + { "-indicatormargin", TK_OPTION_STRING, + Tk_Offset(IndicatorElement,marginObj), "0 2 4 2" }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(IndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { NULL, 0, 0, NULL } +}; + +/* + * Checkbutton indicators (default): 3-D square. + */ +static void SquareIndicatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + IndicatorElement *indicator = elementRecord; + Ttk_Padding margins; + int diameter = 0; + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins); + Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter); + *widthPtr = diameter + Ttk_PaddingWidth(margins); + *heightPtr = diameter + Ttk_PaddingHeight(margins); +} + +static void SquareIndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + IndicatorElement *indicator = elementRecord; + Tk_3DBorder border = 0, interior = 0; + int relief = TK_RELIEF_RAISED; + Ttk_Padding padding; + int borderWidth = 2; + int diameter; + + interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj); + border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj); + Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth); + Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief); + Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding); + + b = Ttk_PadBox(b, padding); + + diameter = b.width < b.height ? b.width : b.height; + Tk_Fill3DRectangle(tkwin, d, interior, b.x, b.y, + diameter, diameter,borderWidth, TK_RELIEF_FLAT); + Tk_Draw3DRectangle(tkwin, d, border, b.x, b.y, + diameter, diameter, borderWidth, relief); +} + +/* + * Radiobutton indicators: 3-D diamond. + */ +static void DiamondIndicatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + IndicatorElement *indicator = elementRecord; + Ttk_Padding margins; + int diameter = 0; + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins); + Tk_GetPixelsFromObj(NULL, tkwin, indicator->diameterObj, &diameter); + *widthPtr = diameter + 3 + Ttk_PaddingWidth(margins); + *heightPtr = diameter + 3 + Ttk_PaddingHeight(margins); +} + +static void DiamondIndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + IndicatorElement *indicator = elementRecord; + Tk_3DBorder border = 0, interior = 0; + int borderWidth = 2; + int relief = TK_RELIEF_RAISED; + int diameter, radius; + XPoint points[4]; + Ttk_Padding padding; + + interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj); + border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj); + Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth); + Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief); + Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding); + + b = Ttk_PadBox(b, padding); + + diameter = b.width < b.height ? b.width : b.height; + radius = diameter / 2; + + points[0].x = b.x; + points[0].y = b.y + radius; + points[1].x = b.x + radius; + points[1].y = b.y + 2*radius; + points[2].x = b.x + 2*radius; + points[2].y = b.y + radius; + points[3].x = b.x + radius; + points[3].y = b.y; + + Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT); + Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief); +} + +static Ttk_ElementSpec CheckbuttonIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(IndicatorElement), + IndicatorElementOptions, + SquareIndicatorElementSize, + SquareIndicatorElementDraw +}; + +static Ttk_ElementSpec RadiobuttonIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(IndicatorElement), + IndicatorElementOptions, + DiamondIndicatorElementSize, + DiamondIndicatorElementDraw +}; + +/* + *---------------------------------------------------------------------- + * +++ Menubutton indicators. + * + * These aren't functional like radio/check indicators, + * they're just affordability indicators. + * + * Standard Tk sets the indicator size to 4.0 mm by 1.7 mm. + * I have no idea where these numbers came from. + */ + +typedef struct { + Tcl_Obj *backgroundObj; + Tcl_Obj *widthObj; + Tcl_Obj *heightObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *marginObj; +} MenuIndicatorElement; + +static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(MenuIndicatorElement,backgroundObj), DEFAULT_BACKGROUND }, + { "-indicatorwidth", TK_OPTION_PIXELS, + Tk_Offset(MenuIndicatorElement,widthObj), "4.0m" }, + { "-indicatorheight", TK_OPTION_PIXELS, + Tk_Offset(MenuIndicatorElement,heightObj), "1.7m" }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(MenuIndicatorElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { "-indicatorrelief", TK_OPTION_RELIEF, + Tk_Offset(MenuIndicatorElement,reliefObj),"raised" }, + { "-indicatormargin", TK_OPTION_STRING, + Tk_Offset(MenuIndicatorElement,marginObj), "5 0" }, + { NULL, 0, 0, NULL } +}; + +static void MenuIndicatorElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + MenuIndicatorElement *mi = elementRecord; + Ttk_Padding margins; + Tk_GetPixelsFromObj(NULL, tkwin, mi->widthObj, widthPtr); + Tk_GetPixelsFromObj(NULL, tkwin, mi->heightObj, heightPtr); + Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj, &margins); + *widthPtr += Ttk_PaddingWidth(margins); + *heightPtr += Ttk_PaddingHeight(margins); +} + +static void MenuIndicatorElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + MenuIndicatorElement *mi = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, mi->backgroundObj); + Ttk_Padding margins; + int borderWidth = 2; + + Ttk_GetPaddingFromObj(NULL,tkwin,mi->marginObj,&margins); + b = Ttk_PadBox(b, margins); + Tk_GetPixelsFromObj(NULL, tkwin, mi->borderWidthObj, &borderWidth); + Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height, + borderWidth, TK_RELIEF_RAISED); +} + +static Ttk_ElementSpec MenuIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(MenuIndicatorElement), + MenuIndicatorElementOptions, + MenuIndicatorElementSize, + MenuIndicatorElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Arrow elements. + * + * Draws a solid triangle inside a box. + * clientData is an enum ArrowDirection pointer. + */ + +static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT }; +typedef struct { + Tcl_Obj *borderObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *sizeObj; + Tcl_Obj *colorObj; +} ArrowElement; + +static Ttk_ElementOptionSpec ArrowElementOptions[] = { + { "-background", TK_OPTION_BORDER, + Tk_Offset(ArrowElement,borderObj), DEFAULT_BACKGROUND }, + { "-relief",TK_OPTION_RELIEF, + Tk_Offset(ArrowElement,reliefObj),"raised"}, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(ArrowElement,borderWidthObj), "1" }, + { "-arrowcolor",TK_OPTION_COLOR, + Tk_Offset(ArrowElement,colorObj),"black"}, + { "-arrowsize", TK_OPTION_PIXELS, + Tk_Offset(ArrowElement,sizeObj), "14" }, + { NULL, 0, 0, NULL } +}; + +static Ttk_Padding ArrowMargins = { 3,3,3,3 }; + +static void ArrowElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ArrowElement *arrow = elementRecord; + int direction = *(int *)clientData; + int width = 14; + + Tk_GetPixelsFromObj(NULL, tkwin, arrow->sizeObj, &width); + width -= Ttk_PaddingWidth(ArrowMargins); + TtkArrowSize(width/2, direction, widthPtr, heightPtr); + *widthPtr += Ttk_PaddingWidth(ArrowMargins); + *heightPtr += Ttk_PaddingWidth(ArrowMargins); +} + +static void ArrowElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + int direction = *(int *)clientData; + ArrowElement *arrow = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, arrow->borderObj); + XColor *arrowColor = Tk_GetColorFromObj(tkwin, arrow->colorObj); + int relief = TK_RELIEF_RAISED; + int borderWidth = 1; + + Tk_GetReliefFromObj(NULL, arrow->reliefObj, &relief); + + Tk_Fill3DRectangle( + tkwin, d, border, b.x, b.y, b.width, b.height, borderWidth, relief); + + TtkFillArrow(Tk_Display(tkwin), d, Tk_GCForColor(arrowColor, d), + Ttk_PadBox(b, ArrowMargins), direction); +} + +static Ttk_ElementSpec ArrowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ArrowElement), + ArrowElementOptions, + ArrowElementSize, + ArrowElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Trough element. + * + * Used in scrollbars and scales in place of "border". + */ + +typedef struct { + Tcl_Obj *colorObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; +} TroughElement; + +static Ttk_ElementOptionSpec TroughElementOptions[] = { + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(TroughElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { "-troughcolor", TK_OPTION_BORDER, + Tk_Offset(TroughElement,colorObj), DEFAULT_BACKGROUND }, + { "-troughrelief",TK_OPTION_RELIEF, + Tk_Offset(TroughElement,reliefObj), "sunken" }, + { NULL, 0, 0, NULL } +}; + +static void TroughElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TroughElement *troughPtr = elementRecord; + int borderWidth = 2; + + Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth); + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static void TroughElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + TroughElement *troughPtr = elementRecord; + Tk_3DBorder border = NULL; + int borderWidth = 2, relief = TK_RELIEF_SUNKEN; + + border = Tk_Get3DBorderFromObj(tkwin, troughPtr->colorObj); + Tk_GetReliefFromObj(NULL, troughPtr->reliefObj, &relief); + Tk_GetPixelsFromObj(NULL, tkwin, troughPtr->borderWidthObj, &borderWidth); + + Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height, + borderWidth, relief); +} + +static Ttk_ElementSpec TroughElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TroughElement), + TroughElementOptions, + TroughElementSize, + TroughElementDraw +}; + +/* + *---------------------------------------------------------------------- + * +++ Thumb element. + * + * Used in scrollbars. + */ + +typedef struct { + Tcl_Obj *orientObj; + Tcl_Obj *thicknessObj; + Tcl_Obj *reliefObj; + Tcl_Obj *borderObj; + Tcl_Obj *borderWidthObj; +} ThumbElement; + +static Ttk_ElementOptionSpec ThumbElementOptions[] = { + { "-orient", TK_OPTION_ANY, + Tk_Offset(ThumbElement, orientObj), "horizontal" }, + { "-width", TK_OPTION_PIXELS, + Tk_Offset(ThumbElement,thicknessObj), DEFAULT_ARROW_SIZE }, + { "-relief", TK_OPTION_RELIEF, + Tk_Offset(ThumbElement,reliefObj), "raised" }, + { "-background", TK_OPTION_BORDER, + Tk_Offset(ThumbElement,borderObj), DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(ThumbElement,borderWidthObj), DEFAULT_BORDERWIDTH }, + { NULL, 0, 0, NULL } +}; + +static void ThumbElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ThumbElement *thumb = elementRecord; + int orient, thickness; + + Tk_GetPixelsFromObj(NULL, tkwin, thumb->thicknessObj, &thickness); + Ttk_GetOrientFromObj(NULL, thumb->orientObj, &orient); + + if (orient == TTK_ORIENT_VERTICAL) { + *widthPtr = thickness; + *heightPtr = MIN_THUMB_SIZE; + } else { + *widthPtr = MIN_THUMB_SIZE; + *heightPtr = thickness; + } +} + +static void ThumbElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + ThumbElement *thumb = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, thumb->borderObj); + int borderWidth = 2, relief = TK_RELIEF_RAISED; + + Tk_GetPixelsFromObj(NULL, tkwin, thumb->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, thumb->reliefObj, &relief); + Tk_Fill3DRectangle(tkwin, d, border, b.x, b.y, b.width, b.height, + borderWidth, relief); +} + +static Ttk_ElementSpec ThumbElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ThumbElement), + ThumbElementOptions, + ThumbElementSize, + ThumbElementDraw +}; + +/* + *---------------------------------------------------------------------- + * +++ Slider element. + * + * This is the moving part of the scale widget. Drawn as a raised box. + */ + +typedef struct { + Tcl_Obj *orientObj; /* orientation of overall slider */ + Tcl_Obj *lengthObj; /* slider length */ + Tcl_Obj *thicknessObj; /* slider thickness */ + Tcl_Obj *reliefObj; /* the relief for this object */ + Tcl_Obj *borderObj; /* the background color */ + Tcl_Obj *borderWidthObj; /* the size of the border */ +} SliderElement; + +static Ttk_ElementOptionSpec SliderElementOptions[] = { + { "-sliderlength", TK_OPTION_PIXELS, Tk_Offset(SliderElement,lengthObj), + "30" }, + { "-sliderthickness",TK_OPTION_PIXELS,Tk_Offset(SliderElement,thicknessObj), + "15" }, + { "-sliderrelief", TK_OPTION_RELIEF, Tk_Offset(SliderElement,reliefObj), + "raised" }, + { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SliderElement,borderWidthObj), + DEFAULT_BORDERWIDTH }, + { "-background", TK_OPTION_BORDER, Tk_Offset(SliderElement,borderObj), + DEFAULT_BACKGROUND }, + { "-orient", TK_OPTION_ANY, Tk_Offset(SliderElement,orientObj), + "horizontal" }, + { NULL, 0, 0, NULL } +}; + +static void SliderElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SliderElement *slider = elementRecord; + int orient, length, thickness; + + Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient); + Tk_GetPixelsFromObj(NULL, tkwin, slider->lengthObj, &length); + Tk_GetPixelsFromObj(NULL, tkwin, slider->thicknessObj, &thickness); + + switch (orient) { + case TTK_ORIENT_VERTICAL: + *widthPtr = thickness; + *heightPtr = length; + break; + + case TTK_ORIENT_HORIZONTAL: + *widthPtr = length; + *heightPtr = thickness; + break; + } +} + +static void SliderElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + SliderElement *slider = elementRecord; + Tk_3DBorder border = NULL; + int relief = TK_RELIEF_RAISED, borderWidth = 2, orient; + + border = Tk_Get3DBorderFromObj(tkwin, slider->borderObj); + Ttk_GetOrientFromObj(NULL, slider->orientObj, &orient); + Tk_GetPixelsFromObj(NULL, tkwin, slider->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, slider->reliefObj, &relief); + + Tk_Fill3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, + borderWidth, relief); + + if (relief != TK_RELIEF_FLAT) { + if (orient == TTK_ORIENT_HORIZONTAL) { + if (b.width > 4) { + b.x += b.width/2; + XDrawLine(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC), + b.x-1, b.y+borderWidth, b.x-1, b.y+b.height-borderWidth); + XDrawLine(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC), + b.x, b.y+borderWidth, b.x, b.y+b.height-borderWidth); + } + } else { + if (b.height > 4) { + b.y += b.height/2; + XDrawLine(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC), + b.x+borderWidth, b.y-1, b.x+b.width-borderWidth, b.y-1); + XDrawLine(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC), + b.x+borderWidth, b.y, b.x+b.width-borderWidth, b.y); + } + } + } +} + +static Ttk_ElementSpec SliderElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SliderElement), + SliderElementOptions, + SliderElementSize, + SliderElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Progress bar element: + * Draws the moving part of the progress bar. + * + * -thickness specifies the size along the short axis of the bar. + * -length specifies the default size along the long axis; + * the bar will be this long in indeterminate mode. + */ + +#define DEFAULT_PBAR_THICKNESS "15" +#define DEFAULT_PBAR_LENGTH "30" + +typedef struct { + Tcl_Obj *orientObj; /* widget orientation */ + Tcl_Obj *thicknessObj; /* the height/width of the bar */ + Tcl_Obj *lengthObj; /* default width/height of the bar */ + Tcl_Obj *reliefObj; /* border relief for this object */ + Tcl_Obj *borderObj; /* background color */ + Tcl_Obj *borderWidthObj; /* thickness of the border */ +} PbarElement; + +static Ttk_ElementOptionSpec PbarElementOptions[] = { + { "-orient", TK_OPTION_ANY, Tk_Offset(PbarElement,orientObj), + "horizontal" }, + { "-thickness", TK_OPTION_PIXELS, Tk_Offset(PbarElement,thicknessObj), + DEFAULT_PBAR_THICKNESS }, + { "-barsize", TK_OPTION_PIXELS, Tk_Offset(PbarElement,lengthObj), + DEFAULT_PBAR_LENGTH }, + { "-pbarrelief", TK_OPTION_RELIEF, Tk_Offset(PbarElement,reliefObj), + "raised" }, + { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(PbarElement,borderWidthObj), + DEFAULT_BORDERWIDTH }, + { "-background", TK_OPTION_BORDER, Tk_Offset(PbarElement,borderObj), + DEFAULT_BACKGROUND }, + { NULL, 0, 0, NULL } +}; + +static void PbarElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + PbarElement *pbar = elementRecord; + int orient, thickness = 15, length = 30, borderWidth = 2; + + Ttk_GetOrientFromObj(NULL, pbar->orientObj, &orient); + Tk_GetPixelsFromObj(NULL, tkwin, pbar->thicknessObj, &thickness); + Tk_GetPixelsFromObj(NULL, tkwin, pbar->lengthObj, &length); + Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth); + + switch (orient) { + case TTK_ORIENT_HORIZONTAL: + *widthPtr = length + 2 * borderWidth; + *heightPtr = thickness + 2 * borderWidth; + break; + case TTK_ORIENT_VERTICAL: + *widthPtr = thickness + 2 * borderWidth; + *heightPtr = length + 2 * borderWidth; + break; + } +} + +static void PbarElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + PbarElement *pbar = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, pbar->borderObj); + int relief = TK_RELIEF_RAISED, borderWidth = 2; + + Tk_GetPixelsFromObj(NULL, tkwin, pbar->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, pbar->reliefObj, &relief); + + Tk_Fill3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, + borderWidth, relief); +} + +static Ttk_ElementSpec PbarElementSpec = { + TK_STYLE_VERSION_2, + sizeof(PbarElement), + PbarElementOptions, + PbarElementSize, + PbarElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Notebook tabs and client area. + */ + +typedef struct { + Tcl_Obj *borderWidthObj; + Tcl_Obj *backgroundObj; +} TabElement; + +static Ttk_ElementOptionSpec TabElementOptions[] = { + { "-borderwidth", TK_OPTION_PIXELS, + Tk_Offset(TabElement,borderWidthObj),"1" }, + { "-background", TK_OPTION_BORDER, + Tk_Offset(TabElement,backgroundObj), DEFAULT_BACKGROUND }, + {0,0,0,0} +}; + +static void TabElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TabElement *tab = elementRecord; + int borderWidth = 1; + Tk_GetPixelsFromObj(0, tkwin, tab->borderWidthObj, &borderWidth); + paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth; + paddingPtr->bottom = 0; +} + +static void TabElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + TabElement *tab = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj); + int borderWidth = 1; + int cut = 2; + XPoint pts[6]; + int n = 0; + + Tcl_GetIntFromObj(NULL, tab->borderWidthObj, &borderWidth); + + if (state & TTK_STATE_SELECTED) { + /* + * Draw slightly outside of the allocated parcel, + * to overwrite the client area border. + */ + b.height += borderWidth; + } + + pts[n].x = b.x; pts[n].y = b.y + b.height - 1; ++n; + pts[n].x = b.x; pts[n].y = b.y + cut; ++n; + pts[n].x = b.x + cut; pts[n].y = b.y; ++n; + pts[n].x = b.x + b.width-1-cut; pts[n].y = b.y; ++n; + pts[n].x = b.x + b.width-1; pts[n].y = b.y + cut; ++n; + pts[n].x = b.x + b.width-1; pts[n].y = b.y + b.height; ++n; + + XFillPolygon(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_FLAT_GC), + pts, 6, Convex, CoordModeOrigin); + +#ifndef WIN32 + /* + * Account for whether XDrawLines draws endpoints by platform + */ + --pts[5].y; +#endif + + while (borderWidth--) { + XDrawLines(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC), + pts, 4, CoordModeOrigin); + XDrawLines(Tk_Display(tkwin), d, + Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC), + pts+3, 3, CoordModeOrigin); + ++pts[0].x; ++pts[1].x; ++pts[2].x; --pts[4].x; --pts[5].x; + ++pts[2].y; ++pts[3].y; + } + +} + +static Ttk_ElementSpec TabElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TabElement), + TabElementOptions, + TabElementSize, + TabElementDraw +}; + +/* + * Client area element: + * Uses same resources as tab element. + */ +typedef TabElement ClientElement; +#define ClientElementOptions TabElementOptions + +static void ClientElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + ClientElement *ce = elementRecord; + Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj); + int borderWidth = 1; + + Tcl_GetIntFromObj(NULL, ce->borderWidthObj, &borderWidth); + + Tk_Fill3DRectangle(tkwin, d, border, + b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_RAISED); +} + +static void ClientElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ClientElement *ce = elementRecord; + int borderWidth = 1; + Tk_GetPixelsFromObj(0, tkwin, ce->borderWidthObj, &borderWidth); + *paddingPtr = Ttk_UniformPadding((short)borderWidth); +} + +static Ttk_ElementSpec ClientElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ClientElement), + ClientElementOptions, + ClientElementSize, + ClientElementDraw +}; + +/*---------------------------------------------------------------------- + * TtkElements_Init -- + * Register default element implementations. + */ + +MODULE_SCOPE +void TtkElements_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + /* + * Elements: + */ + Ttk_RegisterElement(interp, theme, "background", + &BackgroundElementSpec,NULL); + + Ttk_RegisterElement(interp, theme, "fill", &FillElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "border", &BorderElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "field", &FieldElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "focus", &FocusElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "padding", &PaddingElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "Checkbutton.indicator", + &CheckbuttonIndicatorElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "Radiobutton.indicator", + &RadiobuttonIndicatorElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "Menubutton.indicator", + &MenuIndicatorElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "indicator", &ttkNullElementSpec,NULL); + + Ttk_RegisterElement(interp, theme, "uparrow", + &ArrowElementSpec, &ArrowElements[0]); + Ttk_RegisterElement(interp, theme, "downarrow", + &ArrowElementSpec, &ArrowElements[1]); + Ttk_RegisterElement(interp, theme, "leftarrow", + &ArrowElementSpec, &ArrowElements[2]); + Ttk_RegisterElement(interp, theme, "rightarrow", + &ArrowElementSpec, &ArrowElements[3]); + Ttk_RegisterElement(interp, theme, "arrow", + &ArrowElementSpec, &ArrowElements[0]); + + Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "separator", + &SeparatorElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "hseparator", + &HorizontalSeparatorElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "vseparator", + &VerticalSeparatorElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "sizegrip", &SizegripElementSpec, NULL); + + Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL); + + /* + * Register "default" as a user-loadable theme (for now): + */ + Tcl_PkgProvide(interp, "ttk::theme::default", TTK_VERSION); +} + +/*EOF*/ diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c new file mode 100644 index 0000000..c4b1b6a --- /dev/null +++ b/generic/ttk/ttkEntry.c @@ -0,0 +1,2014 @@ +/* + * DERIVED FROM: tk/generic/tkEntry.c r1.35. + * + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright (c) 2000 Ajuba Solutions. + * Copyright (c) 2002 ActiveState Corporation. + * Copyright (c) 2004 Joe English + */ + +#include <string.h> +#include <stdio.h> +#include <tk.h> +#include <X11/Xatom.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" + +/* + * Extra bits for core.flags: + */ +#define GOT_SELECTION (WIDGET_USER_FLAG<<1) +#define SYNCING_VARIABLE (WIDGET_USER_FLAG<<2) +#define VALIDATING (WIDGET_USER_FLAG<<3) +#define VALIDATION_SET_VALUE (WIDGET_USER_FLAG<<4) + +/* + * Definitions for -validate option values: + */ +typedef enum validateMode { + VMODE_ALL, VMODE_KEY, VMODE_FOCUS, VMODE_FOCUSIN, VMODE_FOCUSOUT, VMODE_NONE +} VMODE; + +static const char *const validateStrings[] = { + "all", "key", "focus", "focusin", "focusout", "none", NULL +}; + +/* + * Validation reasons: + */ +typedef enum validateReason { + VALIDATE_INSERT, VALIDATE_DELETE, + VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT, + VALIDATE_FORCED +} VREASON; + +static const char *const validateReasonStrings[] = { + "key", "key", "focusin", "focusout", "forced", NULL +}; + +/*------------------------------------------------------------------------ + * +++ Entry widget record. + * + * Dependencies: + * + * textVariableTrace : textVariableObj + * + * numBytes,numChars : string + * displayString : numChars, showChar + * layoutHeight, + * layoutWidth, + * textLayout : fontObj, displayString + * layoutX, layoutY : textLayout, justify, xscroll.first + * + * Invariants: + * + * 0 <= insertPos <= numChars + * 0 <= selectFirst < selectLast <= numChars || selectFirst == selectLast == -1 + * displayString points to string if showChar == NULL, + * or to malloc'ed storage if showChar != NULL. + */ + +/* Style parameters: + */ +typedef struct { + Tcl_Obj *foregroundObj; /* Foreground color for normal text */ + Tcl_Obj *backgroundObj; /* Entry widget background color */ + Tcl_Obj *selBorderObj; /* Border and background for selection */ + Tcl_Obj *selBorderWidthObj; /* Width of selection border */ + Tcl_Obj *selForegroundObj; /* Foreground color for selected text */ + Tcl_Obj *insertColorObj; /* Color of insertion cursor */ + Tcl_Obj *insertWidthObj; /* Insert cursor width */ +} EntryStyleData; + +typedef struct { + /* + * Internal state: + */ + char *string; /* Storage for string (malloced) */ + int numBytes; /* Length of string in bytes. */ + int numChars; /* Length of string in characters. */ + + int insertPos; /* Insert index */ + int selectFirst; /* Index of start of selection, or -1 */ + int selectLast; /* Index of end of selection, or -1 */ + + Scrollable xscroll; /* Current scroll position */ + ScrollHandle xscrollHandle; + + /* + * Options managed by Tk_SetOptions: + */ + Tcl_Obj *textVariableObj; /* Name of linked variable */ + int exportSelection; /* Tie internal selection to X selection? */ + + VMODE validate; /* Validation mode */ + char *validateCmd; /* Validation script template */ + char *invalidCmd; /* Invalid callback script template */ + + char *showChar; /* Used to derive displayString */ + + Tcl_Obj *fontObj; /* Text font to use */ + Tcl_Obj *widthObj; /* Desired width of window (in avgchars) */ + Tk_Justify justify; /* Text justification */ + + EntryStyleData styleData; /* Display style data (widget options) */ + EntryStyleData styleDefaults;/* Style defaults (fallback values) */ + + Tcl_Obj *stateObj; /* Compatibility option -- see CheckStateObj */ + + /* + * Derived resources: + */ + Ttk_TraceHandle *textVariableTrace; + + char *displayString; /* String to use when displaying */ + Tk_TextLayout textLayout; /* Cached text layout information. */ + int layoutWidth; /* textLayout width */ + int layoutHeight; /* textLayout height */ + + int layoutX, layoutY; /* Origin for text layout. */ + +} EntryPart; + +typedef struct { + WidgetCore core; + EntryPart entry; +} Entry; + +/* + * Extra mask bits for Tk_SetOptions() + */ +#define STATE_CHANGED (0x100) /* -state option changed */ +#define TEXTVAR_CHANGED (0x200) /* -textvariable option changed */ +#define SCROLLCMD_CHANGED (0x400) /* -xscrollcommand option changed */ + +/* + * Default option values: + */ +#define DEF_SELECT_BG "#000000" +#define DEF_SELECT_FG "#ffffff" +#define DEF_INSERT_BG "black" +#define DEF_ENTRY_WIDTH "20" +#define DEF_ENTRY_FONT "TkTextFont" +#define DEF_LIST_HEIGHT "10" + +static Tk_OptionSpec EntryOptionSpecs[] = { + {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection", + "ExportSelection", "1", -1, Tk_Offset(Entry, entry.exportSelection), + 0,0,0 }, + {TK_OPTION_FONT, "-font", "font", "Font", + DEF_ENTRY_FONT, Tk_Offset(Entry, entry.fontObj),-1, + 0,0,GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand", + NULL, -1, Tk_Offset(Entry, entry.invalidCmd), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", + "left", -1, Tk_Offset(Entry, entry.justify), + 0, 0, GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-show", "show", "Show", + NULL, -1, Tk_Offset(Entry, entry.showChar), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_STRING, "-state", "state", "State", + "normal", Tk_Offset(Entry, entry.stateObj), -1, + 0,0,STATE_CHANGED}, + {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", + NULL, Tk_Offset(Entry, entry.textVariableObj), -1, + TK_OPTION_NULL_OK,0,TEXTVAR_CHANGED}, + {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate", + "none", -1, Tk_Offset(Entry, entry.validate), + 0, (ClientData) validateStrings, 0}, + {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand", + NULL, -1, Tk_Offset(Entry, entry.validateCmd), + TK_OPTION_NULL_OK, 0, 0}, + {TK_OPTION_INT, "-width", "width", "Width", + DEF_ENTRY_WIDTH, Tk_Offset(Entry, entry.widthObj), -1, + 0,0,GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", + NULL, -1, Tk_Offset(Entry, entry.xscroll.scrollCmd), + TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, + + /* EntryStyleData options: + */ + {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_NULL_OK,0,0}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/*------------------------------------------------------------------------ + * +++ EntryStyleData management. + * This is still more awkward than it should be; + * it should be able to use the Element API instead. + */ + +/* EntryInitStyleDefaults -- + * Initialize EntryStyleData record to fallback values. + */ +static void EntryInitStyleDefaults(EntryStyleData *es) +{ +#define INIT(member, value) \ + es->member = Tcl_NewStringObj(value, -1); \ + Tcl_IncrRefCount(es->member); + INIT(foregroundObj, DEFAULT_FOREGROUND) + INIT(selBorderObj, DEF_SELECT_BG) + INIT(selForegroundObj, DEF_SELECT_FG) + INIT(insertColorObj, DEFAULT_FOREGROUND) + INIT(selBorderWidthObj, "0") + INIT(insertWidthObj, "1") +#undef INIT +} + +static void EntryFreeStyleDefaults(EntryStyleData *es) +{ + Tcl_DecrRefCount(es->foregroundObj); + Tcl_DecrRefCount(es->selBorderObj); + Tcl_DecrRefCount(es->selForegroundObj); + Tcl_DecrRefCount(es->insertColorObj); + Tcl_DecrRefCount(es->selBorderWidthObj); + Tcl_DecrRefCount(es->insertWidthObj); +} + +/* + * EntryInitStyleData -- + * Look up style-specific data for an entry widget. + */ +static void EntryInitStyleData(Entry *entryPtr, EntryStyleData *es) +{ + Ttk_State state = entryPtr->core.state; + Ttk_ResourceCache cache = Ttk_GetResourceCache(entryPtr->core.interp); + Tk_Window tkwin = entryPtr->core.tkwin; + Tcl_Obj *tmp; + + /* Initialize to fallback values: + */ + *es = entryPtr->entry.styleDefaults; + +# define INIT(member, name) \ + if ((tmp=Ttk_QueryOption(entryPtr->core.layout,name,state))) \ + es->member=tmp; + INIT(foregroundObj, "-foreground"); + INIT(selBorderObj, "-selectbackground") + INIT(selBorderWidthObj, "-selectborderwidth") + INIT(selForegroundObj, "-selectforeground") + INIT(insertColorObj, "-insertcolor") + INIT(insertWidthObj, "-insertwidth") +#undef INIT + + /* Reacquire color & border resources from resource cache. + */ + es->foregroundObj = Ttk_UseColor(cache, tkwin, es->foregroundObj); + es->selForegroundObj = Ttk_UseColor(cache, tkwin, es->selForegroundObj); + es->insertColorObj = Ttk_UseColor(cache, tkwin, es->insertColorObj); + es->selBorderObj = Ttk_UseBorder(cache, tkwin, es->selBorderObj); +} + +/*------------------------------------------------------------------------ + * +++ Resource management. + */ + +/* EntryDisplayString -- + * Return a malloc'ed string consisting of 'numChars' copies + * of (the first character in the string) 'showChar'. + * Used to compute the displayString if -show is non-NULL. + */ +static char *EntryDisplayString(const char *showChar, int numChars) +{ + char *displayString, *p; + int size; + Tcl_UniChar ch; + char buf[TCL_UTF_MAX]; + + Tcl_UtfToUniChar(showChar, &ch); + size = Tcl_UniCharToUtf(ch, buf); + p = displayString = ckalloc(numChars * size + 1); + + while (numChars--) { + p += Tcl_UniCharToUtf(ch, p); + } + *p = '\0'; + + return displayString; +} + +/* EntryUpdateTextLayout -- + * Recompute textLayout, layoutWidth, and layoutHeight + * from displayString and fontObj. + */ +static void EntryUpdateTextLayout(Entry *entryPtr) +{ + Tk_FreeTextLayout(entryPtr->entry.textLayout); + 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); +} + +/* EntryEditable -- + * Returns 1 if the entry widget accepts user changes, 0 otherwise + */ +static int +EntryEditable(Entry *entryPtr) +{ + return !(entryPtr->core.state & (TTK_STATE_DISABLED|TTK_STATE_READONLY)); +} + +/*------------------------------------------------------------------------ + * +++ Selection management. + */ + +/* EntryFetchSelection -- + * Selection handler for entry widgets. + */ +static int +EntryFetchSelection( + ClientData clientData, int offset, char *buffer, int maxBytes) +{ + Entry *entryPtr = (Entry *) clientData; + size_t byteCount; + const char *string; + const char *selStart, *selEnd; + + if (entryPtr->entry.selectFirst < 0 || !entryPtr->entry.exportSelection) { + return -1; + } + string = entryPtr->entry.displayString; + + selStart = Tcl_UtfAtIndex(string, entryPtr->entry.selectFirst); + selEnd = Tcl_UtfAtIndex(selStart, + entryPtr->entry.selectLast - entryPtr->entry.selectFirst); + byteCount = selEnd - selStart - offset; + if (byteCount > (size_t)maxBytes) { + /* @@@POSSIBLE BUG: Can transfer partial UTF-8 sequences. Is this OK? */ + byteCount = maxBytes; + } + if (byteCount <= 0) { + return 0; + } + memcpy(buffer, selStart + offset, byteCount); + buffer[byteCount] = '\0'; + return byteCount; +} + +/* EntryLostSelection -- + * Tk_LostSelProc for Entry widgets; called when an entry + * loses ownership of the selection. + */ +static void EntryLostSelection(ClientData clientData) +{ + Entry *entryPtr = (Entry *) clientData; + entryPtr->core.flags &= ~GOT_SELECTION; + entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1; + TtkRedisplayWidget(&entryPtr->core); +} + +/* EntryOwnSelection -- + * Assert ownership of the PRIMARY selection, + * if -exportselection set and selection is present. + */ +static void EntryOwnSelection(Entry *entryPtr) +{ + if (entryPtr->entry.exportSelection + && !(entryPtr->core.flags & GOT_SELECTION)) { + Tk_OwnSelection(entryPtr->core.tkwin, XA_PRIMARY, EntryLostSelection, + (ClientData) entryPtr); + entryPtr->core.flags |= GOT_SELECTION; + } +} + +/*------------------------------------------------------------------------ + * +++ Validation. + */ + +/* ExpandPercents -- + * Expand an entry validation script template (-validatecommand + * or -invalidcommand). + */ +static void +ExpandPercents( + Entry *entryPtr, /* Entry that needs validation. */ + const char *template, /* Script template */ + const char *new, /* Potential new value of entry string */ + int index, /* index of insert/delete */ + int count, /* #changed characters */ + VREASON reason, /* Reason for change */ + Tcl_DString *dsPtr) /* Result of %-substitutions */ +{ + int spaceNeeded, cvtFlags; + int number, length; + const char *string; + int stringLength; + Tcl_UniChar ch; + char numStorage[2*TCL_INTEGER_SPACE]; + + while (*template) { + /* Find everything up to the next % character and append it + * to the result string. + */ + string = Tcl_UtfFindFirst(template, '%'); + if (string == NULL) { + /* No more %-sequences to expand. + * Copy the rest of the template. + */ + Tcl_DStringAppend(dsPtr, template, -1); + return; + } + if (string != template) { + Tcl_DStringAppend(dsPtr, template, string - template); + template = string; + } + + /* There's a percent sequence here. Process it. + */ + ++template; /* skip over % */ + if (*template != '\0') { + template += Tcl_UtfToUniChar(template, &ch); + } else { + ch = '%'; + } + + stringLength = -1; + switch (ch) { + case 'd': /* Type of call that caused validation */ + if (reason == VALIDATE_INSERT) { + number = 1; + } else if (reason == VALIDATE_DELETE) { + number = 0; + } else { + number = -1; + } + sprintf(numStorage, "%d", number); + string = numStorage; + break; + case 'i': /* index of insert/delete */ + sprintf(numStorage, "%d", index); + string = numStorage; + break; + case 'P': /* 'Peeked' new value of the string */ + string = new; + break; + case 's': /* Current string value */ + string = entryPtr->entry.string; + break; + case 'S': /* string to be inserted/deleted, if any */ + if (reason == VALIDATE_INSERT) { + string = Tcl_UtfAtIndex(new, index); + stringLength = Tcl_UtfAtIndex(string, count) - string; + } else if (reason == VALIDATE_DELETE) { + string = Tcl_UtfAtIndex(entryPtr->entry.string, index); + stringLength = Tcl_UtfAtIndex(string, count) - string; + } else { + string = ""; + stringLength = 0; + } + break; + case 'v': /* type of validation currently set */ + string = validateStrings[entryPtr->entry.validate]; + break; + case 'V': /* type of validation in effect */ + string = validateReasonStrings[reason]; + break; + case 'W': /* widget name */ + string = Tk_PathName(entryPtr->core.tkwin); + break; + default: + length = Tcl_UniCharToUtf(ch, numStorage); + numStorage[length] = '\0'; + string = numStorage; + break; + } + + spaceNeeded = Tcl_ScanCountedElement(string, stringLength, &cvtFlags); + length = Tcl_DStringLength(dsPtr); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + spaceNeeded = Tcl_ConvertCountedElement(string, stringLength, + Tcl_DStringValue(dsPtr) + length, + cvtFlags | TCL_DONT_USE_BRACES); + Tcl_DStringSetLength(dsPtr, length + spaceNeeded); + } +} + +/* RunValidationScript -- + * Build and evaluate an entry validation script. + * If the script raises an error, disable validation + * by setting '-validate none' + */ +static int RunValidationScript( + Tcl_Interp *interp, /* Interpreter to use */ + Entry *entryPtr, /* Entry being validated */ + const char *template, /* Script template */ + const char *optionName, /* "-validatecommand", "-invalidcommand" */ + const char *new, /* Potential new value of entry string */ + int index, /* index of insert/delete */ + int count, /* #changed characters */ + VREASON reason) /* Reason for change */ +{ + Tcl_DString script; + int code; + + Tcl_DStringInit(&script); + ExpandPercents(entryPtr, template, new, index, count, reason, &script); + code = Tcl_EvalEx(interp, + Tcl_DStringValue(&script), Tcl_DStringLength(&script), + TCL_EVAL_GLOBAL); + Tcl_DStringFree(&script); + if (WidgetDestroyed(&entryPtr->core)) + return TCL_ERROR; + + if (code != TCL_OK && code != TCL_RETURN) { + Tcl_AddErrorInfo(interp, "\n\t(in "); + Tcl_AddErrorInfo(interp, optionName); + Tcl_AddErrorInfo(interp, " validation command executed by "); + Tcl_AddErrorInfo(interp, Tk_PathName(entryPtr->core.tkwin)); + Tcl_AddErrorInfo(interp, ")"); + entryPtr->entry.validate = VMODE_NONE; + return TCL_ERROR; + } + return TCL_OK; +} + +/* EntryNeedsValidation -- + * Determine whether the specified VREASON should trigger validation + * in the current VMODE. + */ +static int EntryNeedsValidation(VMODE vmode, VREASON reason) +{ + return (reason == VALIDATE_FORCED) + || (vmode == VMODE_ALL) + || (reason == VALIDATE_FOCUSIN + && (vmode == VMODE_FOCUSIN || vmode == VMODE_FOCUS)) + || (reason == VALIDATE_FOCUSOUT + && (vmode == VMODE_FOCUSOUT || vmode == VMODE_FOCUS)) + || (reason == VALIDATE_INSERT && vmode == VMODE_KEY) + || (reason == VALIDATE_DELETE && vmode == VMODE_KEY) + ; +} + +/* EntryValidateChange -- + * Validate a proposed change to the entry widget's value if required. + * Call the -invalidcommand if validation fails. + * + * Returns: + * TCL_OK if the change is accepted + * TCL_BREAK if the change is rejected + * TCL_ERROR if any errors occured + * + * The change will be rejected if -validatecommand returns 0, + * or if -validatecommand or -invalidcommand modifies the value. + */ +static int +EntryValidateChange( + Entry *entryPtr, /* Entry that needs validation. */ + const char *newValue, /* Potential new value of entry string */ + int index, /* index of insert/delete, -1 otherwise */ + int count, /* #changed characters */ + VREASON reason) /* Reason for change */ +{ + Tcl_Interp *interp = entryPtr->core.interp; + VMODE vmode = entryPtr->entry.validate; + int code, change_ok; + + if ( (entryPtr->entry.validateCmd == NULL) + || (entryPtr->core.flags & VALIDATING) + || !EntryNeedsValidation(vmode, reason) ) + { + return TCL_OK; + } + + entryPtr->core.flags |= VALIDATING; + + /* Run -validatecommand and check return value: + */ + code = RunValidationScript(interp, entryPtr, + entryPtr->entry.validateCmd, "-validatecommand", + newValue, index, count, reason); + if (code != TCL_OK) { + goto done; + } + + code = Tcl_GetBooleanFromObj(interp,Tcl_GetObjResult(interp), &change_ok); + if (code != TCL_OK) { + entryPtr->entry.validate = VMODE_NONE; /* Disable validation */ + Tcl_AddErrorInfo(interp, + "\n(validation command did not return valid boolean)"); + goto done; + } + + /* Run the -invalidcommand if validation failed: + */ + if (!change_ok && entryPtr->entry.invalidCmd != NULL) { + code = RunValidationScript(interp, entryPtr, + entryPtr->entry.invalidCmd, "-invalidcommand", + newValue, index, count, reason); + if (code != TCL_OK) { + goto done; + } + } + + /* Reject the pending change if validation failed + * or if a validation script changed the value. + */ + if (!change_ok || (entryPtr->core.flags & VALIDATION_SET_VALUE)) { + code = TCL_BREAK; + } + +done: + entryPtr->core.flags &= ~(VALIDATING|VALIDATION_SET_VALUE); + return code; +} + +/* EntryRevalidate -- + * Revalidate the current value of an entry widget, + * update the TTK_STATE_INVALID bit. + * + * Returns: + * TCL_OK if valid, TCL_BREAK if invalid, TCL_ERROR on error. + */ +static int EntryRevalidate(Tcl_Interp *interp, Entry *entryPtr, VREASON reason) +{ + int code = EntryValidateChange( + entryPtr, entryPtr->entry.string, -1,0, reason); + + if (code == TCL_BREAK) { + TtkWidgetChangeState(&entryPtr->core, TTK_STATE_INVALID, 0); + } else if (code == TCL_OK) { + TtkWidgetChangeState(&entryPtr->core, 0, TTK_STATE_INVALID); + } + + return code; +} + +/* EntryRevalidateBG -- + * Revalidate in the background (called from event handler). + */ +static void EntryRevalidateBG(Entry *entryPtr, VREASON reason) +{ + Tcl_Interp *interp = entryPtr->core.interp; + if (EntryRevalidate(interp, entryPtr, reason) == TCL_ERROR) { + Tcl_BackgroundError(interp); + } +} + +/*------------------------------------------------------------------------ + * +++ Entry widget modification. + */ + +/* AdjustIndex -- + * Adjust index to account for insertion (nChars > 0) + * or deletion (nChars < 0) at specified index. + */ +static int AdjustIndex(int i0, int index, int nChars) +{ + if (i0 >= index) { + i0 += nChars; + if (i0 < index) { /* index was inside deleted range */ + i0 = index; + } + } + return i0; +} + +/* AdjustIndices -- + * Adjust all internal entry indexes to account for change. + * Note that insertPos, and selectFirst have "right gravity", + * while leftIndex (=xscroll.first) and selectLast have "left gravity". + */ +static void AdjustIndices(Entry *entryPtr, int index, int nChars) +{ + EntryPart *e = &entryPtr->entry; + int g = nChars > 0; /* left gravity adjustment */ + + e->insertPos = AdjustIndex(e->insertPos, index, nChars); + e->selectFirst = AdjustIndex(e->selectFirst, index, nChars); + e->selectLast = AdjustIndex(e->selectLast, index+g, nChars); + e->xscroll.first= AdjustIndex(e->xscroll.first, index+g, nChars); + + if (e->selectLast <= e->selectFirst) + e->selectFirst = e->selectLast = -1; +} + +/* EntryStoreValue -- + * Replace the contents of a text entry with a given value, + * recompute dependent resources, and schedule a redisplay. + * + * See also: EntrySetValue(). + */ +static void +EntryStoreValue(Entry *entryPtr, const char *value) +{ + size_t numBytes = strlen(value); + int numChars = Tcl_NumUtfChars(value, numBytes); + + if (entryPtr->core.flags & VALIDATING) + entryPtr->core.flags |= VALIDATION_SET_VALUE; + + /* Make sure all indices remain in bounds: + */ + if (numChars < entryPtr->entry.numChars) + AdjustIndices(entryPtr, numChars, numChars - entryPtr->entry.numChars); + + /* Free old value: + */ + if (entryPtr->entry.displayString != entryPtr->entry.string) + ckfree(entryPtr->entry.displayString); + ckfree(entryPtr->entry.string); + + /* Store new value: + */ + entryPtr->entry.string = ckalloc(numBytes + 1); + strcpy(entryPtr->entry.string, value); + entryPtr->entry.numBytes = numBytes; + entryPtr->entry.numChars = numChars; + + entryPtr->entry.displayString + = entryPtr->entry.showChar + ? EntryDisplayString(entryPtr->entry.showChar, numChars) + : entryPtr->entry.string + ; + + /* Update layout, schedule redisplay: + */ + EntryUpdateTextLayout(entryPtr); + TtkRedisplayWidget(&entryPtr->core); +} + +/* EntrySetValue -- + * Stores a new value in the entry widget and updates the + * linked -textvariable, if any. The write trace on the + * text variable is temporarily disabled; however, other + * write traces may change the value of the variable. + * If so, the widget is updated again with the new value. + * + * Returns: + * TCL_OK if successful, TCL_ERROR otherwise. + */ +static int EntrySetValue(Entry *entryPtr, const char *value) +{ + EntryStoreValue(entryPtr, value); + + if (entryPtr->entry.textVariableObj) { + const char *textVarName = + Tcl_GetString(entryPtr->entry.textVariableObj); + if (textVarName && *textVarName) { + entryPtr->core.flags |= SYNCING_VARIABLE; + value = Tcl_SetVar(entryPtr->core.interp, textVarName, + value, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + entryPtr->core.flags &= ~SYNCING_VARIABLE; + if (!value || WidgetDestroyed(&entryPtr->core)) { + return TCL_ERROR; + } else if (strcmp(value, entryPtr->entry.string) != 0) { + /* Some write trace has changed the variable value. + */ + EntryStoreValue(entryPtr, value); + } + } + } + + return TCL_OK; +} + +/* EntryTextVariableTrace -- + * Variable trace procedure for entry -textvariable + */ +static void EntryTextVariableTrace(void *recordPtr, const char *value) +{ + Entry *entryPtr = recordPtr; + + if (WidgetDestroyed(&entryPtr->core)) { + return; + } + + if (entryPtr->core.flags & SYNCING_VARIABLE) { + /* Trace was fired due to Tcl_SetVar call in EntrySetValue. + * Don't do anything. + */ + return; + } + + EntryStoreValue(entryPtr, value ? value : ""); +} + +/*------------------------------------------------------------------------ + * +++ Insertion and deletion. + */ + +/* InsertChars -- + * Add new characters to an entry widget. + */ +static int +InsertChars( + Entry *entryPtr, /* Entry that is to get the new elements. */ + int index, /* Insert before this index */ + const char *value) /* New characters to add */ +{ + char *string = entryPtr->entry.string; + size_t byteIndex = Tcl_UtfAtIndex(string, index) - string; + size_t byteCount = strlen(value); + int charsAdded = Tcl_NumUtfChars(value, byteCount); + size_t newByteCount = entryPtr->entry.numBytes + byteCount + 1; + char *new; + int code; + + if (byteCount == 0) { + return TCL_OK; + } + + new = ckalloc(newByteCount); + memcpy(new, string, byteIndex); + strcpy(new + byteIndex, value); + strcpy(new + byteIndex + byteCount, string + byteIndex); + + code = EntryValidateChange( + entryPtr, new, index, charsAdded, VALIDATE_INSERT); + + if (code == TCL_OK) { + AdjustIndices(entryPtr, index, charsAdded); + code = EntrySetValue(entryPtr, new); + } else if (code == TCL_BREAK) { + code = TCL_OK; + } + + ckfree(new); + return code; +} + +/* DeleteChars -- + * Remove one or more characters from an entry widget. + */ +static int +DeleteChars( + Entry *entryPtr, /* Entry widget to modify. */ + int index, /* Index of first character to delete. */ + int count) /* How many characters to delete. */ +{ + char *string = entryPtr->entry.string; + size_t byteIndex, byteCount, newByteCount; + char *new; + int code; + + if (index < 0) { + index = 0; + } + if (count > entryPtr->entry.numChars - index) { + count = entryPtr->entry.numChars - index; + } + if (count <= 0) { + return TCL_OK; + } + + byteIndex = Tcl_UtfAtIndex(string, index) - string; + byteCount = Tcl_UtfAtIndex(string+byteIndex, count) - (string+byteIndex); + + newByteCount = entryPtr->entry.numBytes + 1 - byteCount; + new = ckalloc(newByteCount); + memcpy(new, string, byteIndex); + strcpy(new + byteIndex, string + byteIndex + byteCount); + + code = EntryValidateChange( + entryPtr, new, index, count, VALIDATE_DELETE); + + if (code == TCL_OK) { + AdjustIndices(entryPtr, index, -count); + code = EntrySetValue(entryPtr, new); + } else if (code == TCL_BREAK) { + code = TCL_OK; + } + ckfree(new); + + return code; +} + +/*------------------------------------------------------------------------ + * +++ Event handler. + */ + +/* EntryEventProc -- + * Extra event handling for entry widgets: + * Triggers validation on FocusIn and FocusOut events. + */ +#define EntryEventMask (FocusChangeMask) +static void +EntryEventProc(ClientData clientData, XEvent *eventPtr) +{ + Entry *entryPtr = (Entry *) clientData; + + Tcl_Preserve(clientData); + switch (eventPtr->type) { + case DestroyNotify: + Tk_DeleteEventHandler(entryPtr->core.tkwin, + EntryEventMask, EntryEventProc, clientData); + break; + case FocusIn: + EntryRevalidateBG(entryPtr, VALIDATE_FOCUSIN); + break; + case FocusOut: + EntryRevalidateBG(entryPtr, VALIDATE_FOCUSOUT); + break; + } + Tcl_Release(clientData); +} + +/*------------------------------------------------------------------------ + * +++ Initialization and cleanup. + */ + +static void +EntryInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Entry *entryPtr = recordPtr; + + Tk_CreateEventHandler( + entryPtr->core.tkwin, EntryEventMask, EntryEventProc, entryPtr); + Tk_CreateSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING, + EntryFetchSelection, (ClientData) entryPtr, XA_STRING); + TtkBlinkCursor(&entryPtr->core); + + entryPtr->entry.string = ckalloc(1); + *entryPtr->entry.string = '\0'; + entryPtr->entry.displayString = entryPtr->entry.string; + entryPtr->entry.textVariableTrace = 0; + entryPtr->entry.numBytes = entryPtr->entry.numChars = 0; + + EntryInitStyleDefaults(&entryPtr->entry.styleDefaults); + + entryPtr->entry.xscrollHandle = + TtkCreateScrollHandle(&entryPtr->core, &entryPtr->entry.xscroll); + + entryPtr->entry.insertPos = 0; + entryPtr->entry.selectFirst = -1; + entryPtr->entry.selectLast = -1; +} + +static void +EntryCleanup(void *recordPtr) +{ + Entry *entryPtr = recordPtr; + + if (entryPtr->entry.textVariableTrace) + Ttk_UntraceVariable(entryPtr->entry.textVariableTrace); + + TtkFreeScrollHandle(entryPtr->entry.xscrollHandle); + + EntryFreeStyleDefaults(&entryPtr->entry.styleDefaults); + + Tk_DeleteSelHandler(entryPtr->core.tkwin, XA_PRIMARY, XA_STRING); + + Tk_FreeTextLayout(entryPtr->entry.textLayout); + if (entryPtr->entry.displayString != entryPtr->entry.string) + ckfree(entryPtr->entry.displayString); + ckfree(entryPtr->entry.string); +} + +/* EntryConfigure -- + * Configure hook for Entry widgets. + */ +static int EntryConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Entry *entryPtr = recordPtr; + Tcl_Obj *textVarName = entryPtr->entry.textVariableObj; + Ttk_TraceHandle *vt = 0; + + if (mask & TEXTVAR_CHANGED) { + if (textVarName && *Tcl_GetString(textVarName)) { + vt = Ttk_TraceVariable(interp, + textVarName,EntryTextVariableTrace,entryPtr); + if (!vt) return TCL_ERROR; + } + } + + if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) { + if (vt) Ttk_UntraceVariable(vt); + return TCL_ERROR; + } + + /* Update derived resources: + */ + if (mask & TEXTVAR_CHANGED) { + if (entryPtr->entry.textVariableTrace) + Ttk_UntraceVariable(entryPtr->entry.textVariableTrace); + entryPtr->entry.textVariableTrace = vt; + } + + /* Claim the selection, in case we've suddenly started exporting it. + */ + if (entryPtr->entry.exportSelection && entryPtr->entry.selectFirst != -1) { + EntryOwnSelection(entryPtr); + } + + /* Handle -state compatibility option: + */ + if (mask & STATE_CHANGED) { + TtkCheckStateOption(&entryPtr->core, entryPtr->entry.stateObj); + } + + /* Force scrollbar update if needed: + */ + if (mask & SCROLLCMD_CHANGED) { + TtkScrollbarUpdateRequired(entryPtr->entry.xscrollHandle); + } + + /* Recompute the displayString, in case showChar changed: + */ + if (entryPtr->entry.displayString != entryPtr->entry.string) + ckfree(entryPtr->entry.displayString); + + entryPtr->entry.displayString + = entryPtr->entry.showChar + ? EntryDisplayString(entryPtr->entry.showChar, entryPtr->entry.numChars) + : entryPtr->entry.string + ; + + /* Update textLayout: + */ + EntryUpdateTextLayout(entryPtr); + return TCL_OK; +} + +/* EntryPostConfigure -- + * Post-configuration hook for entry widgets. + */ +static int EntryPostConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Entry *entryPtr = recordPtr; + int status = TCL_OK; + + if ((mask & TEXTVAR_CHANGED) && entryPtr->entry.textVariableTrace != NULL) { + status = Ttk_FireTrace(entryPtr->entry.textVariableTrace); + } + + return status; +} + +/*------------------------------------------------------------------------ + * +++ Layout and display. + */ + +/* EntryCharPosition -- + * Return the X coordinate of the specified character index. + * Precondition: textLayout and layoutX up-to-date. + */ +static int +EntryCharPosition(Entry *entryPtr, int index) +{ + int xPos; + Tk_CharBbox(entryPtr->entry.textLayout, index, &xPos, NULL, NULL, NULL); + return xPos + entryPtr->entry.layoutX; +} + +/* EntryDoLayout -- + * Layout hook for entry widgets. + * + * Determine position of textLayout based on xscroll.first, justify, + * and display area. + * + * Recalculates layoutX, layoutY, and rightIndex, + * and updates xscroll accordingly. + * May adjust xscroll.first to ensure the maximum #characters are onscreen. + */ +static void +EntryDoLayout(void *recordPtr) +{ + Entry *entryPtr = recordPtr; + WidgetCore *corePtr = &entryPtr->core; + Tk_TextLayout textLayout = entryPtr->entry.textLayout; + int leftIndex = entryPtr->entry.xscroll.first; + int rightIndex; + Ttk_Box textarea; + + Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin)); + textarea = Ttk_ClientRegion(corePtr->layout, "textarea"); + + /* Center the text vertically within the available parcel: + */ + entryPtr->entry.layoutY = textarea.y + + (textarea.height - entryPtr->entry.layoutHeight)/2; + + /* Recompute where the leftmost character on the display will + * be drawn (layoutX) and adjust leftIndex if necessary. + */ + if (entryPtr->entry.layoutWidth <= textarea.width) { + /* Everything fits. Set leftIndex to zero (no need to scroll), + * and compute layoutX based on -justify. + */ + int extraSpace = textarea.width - entryPtr->entry.layoutWidth; + leftIndex = 0; + rightIndex = entryPtr->entry.numChars; + entryPtr->entry.layoutX = textarea.x; + if (entryPtr->entry.justify == TK_JUSTIFY_RIGHT) { + entryPtr->entry.layoutX += extraSpace; + } else if (entryPtr->entry.justify == TK_JUSTIFY_CENTER) { + entryPtr->entry.layoutX += extraSpace / 2; + } + } else { + /* The whole string doesn't fit in the window. + * Limit leftIndex to leave at most one character's worth + * of empty space on the right. + */ + int overflow = entryPtr->entry.layoutWidth - textarea.width; + int maxLeftIndex = 1 + Tk_PointToChar(textLayout, overflow, 0); + int leftX; + + if (leftIndex > maxLeftIndex) { + leftIndex = maxLeftIndex; + } + + /* Compute layoutX and rightIndex. + * rightIndex is set to one past the last fully-visible character. + */ + Tk_CharBbox(textLayout, leftIndex, &leftX, NULL, NULL, NULL); + rightIndex = Tk_PointToChar(textLayout, leftX + textarea.width, 0); + entryPtr->entry.layoutX = textarea.x - leftX; + } + + TtkScrolled(entryPtr->entry.xscrollHandle, + leftIndex, rightIndex, entryPtr->entry.numChars); +} + +/* EntryGetGC -- Helper routine. + * Get a GC using the specified foreground color and the entry's font. + * Result must be freed with Tk_FreeGC(). + */ +static GC EntryGetGC(Entry *entryPtr, Tcl_Obj *colorObj) +{ + Tk_Window tkwin = entryPtr->core.tkwin; + Tk_Font font = Tk_GetFontFromObj(tkwin, entryPtr->entry.fontObj); + XColor *colorPtr; + unsigned long mask = 0ul; + XGCValues gcValues; + + gcValues.line_width = 1; mask |= GCLineWidth; + gcValues.font = Tk_FontId(font); mask |= GCFont; + if (colorObj != 0 && (colorPtr=Tk_GetColorFromObj(tkwin,colorObj)) != 0) { + gcValues.foreground = colorPtr->pixel; + mask |= GCForeground; + } + return Tk_GetGC(entryPtr->core.tkwin, mask, &gcValues); +} + +/* EntryDisplay -- + * Redraws the contents of an entry window. + */ +static void EntryDisplay(void *clientData, Drawable d) +{ + Entry *entryPtr = clientData; + Tk_Window tkwin = entryPtr->core.tkwin; + int leftIndex = entryPtr->entry.xscroll.first, + rightIndex = entryPtr->entry.xscroll.last, + selFirst = entryPtr->entry.selectFirst, + selLast = entryPtr->entry.selectLast; + EntryStyleData es; + GC gc; + int showSelection, showCursor; + + EntryInitStyleData(entryPtr, &es); + + showCursor = + (entryPtr->core.flags & CURSOR_ON) != 0 + && EntryEditable(entryPtr) + && entryPtr->entry.insertPos >= leftIndex + && entryPtr->entry.insertPos <= rightIndex + ; + showSelection = + (entryPtr->core.state & TTK_STATE_DISABLED) == 0 + && selFirst > -1 + && selLast > leftIndex + && selFirst <= rightIndex + ; + + /* Adjust selection range to keep in display bounds. + */ + if (showSelection) { + if (selFirst < leftIndex) + selFirst = leftIndex; + if (selLast > rightIndex) + selLast = rightIndex; + } + + /* Draw widget background & border + */ + Ttk_DrawLayout(entryPtr->core.layout, entryPtr->core.state, d); + + /* Draw selection background + */ + if (showSelection && es.selBorderObj) { + Tk_3DBorder selBorder = Tk_Get3DBorderFromObj(tkwin, es.selBorderObj); + int selStartX = EntryCharPosition(entryPtr, selFirst); + int selEndX = EntryCharPosition(entryPtr, selLast); + int borderWidth = 1; + + Tcl_GetIntFromObj(NULL, es.selBorderWidthObj, &borderWidth); + + if (selBorder) { + Tk_Fill3DRectangle(tkwin, d, selBorder, + selStartX - borderWidth, entryPtr->entry.layoutY - borderWidth, + selEndX - selStartX + 2*borderWidth, + entryPtr->entry.layoutHeight + 2*borderWidth, + borderWidth, TK_RELIEF_RAISED); + } + } + + /* Draw cursor: + */ + if (showCursor) { + int cursorX = EntryCharPosition(entryPtr, entryPtr->entry.insertPos), + cursorY = entryPtr->entry.layoutY, + cursorHeight = entryPtr->entry.layoutHeight, + cursorWidth = 1; + + Tcl_GetIntFromObj(NULL,es.insertWidthObj,&cursorWidth); + if (cursorWidth <= 0) { + cursorWidth = 1; + } + + /* @@@ should: maybe: SetCaretPos even when blinked off */ + Tk_SetCaretPos(tkwin, cursorX, cursorY, cursorHeight); + + gc = EntryGetGC(entryPtr, es.insertColorObj); + XFillRectangle(Tk_Display(tkwin), d, gc, + cursorX-cursorWidth/2, cursorY, cursorWidth, cursorHeight); + Tk_FreeGC(Tk_Display(tkwin), gc); + } + + /* Draw the text: + */ + gc = EntryGetGC(entryPtr, es.foregroundObj); + Tk_DrawTextLayout( + Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, + entryPtr->entry.layoutX, entryPtr->entry.layoutY, + leftIndex, rightIndex); + Tk_FreeGC(Tk_Display(tkwin), gc); + + /* Overwrite the selected portion (if any) in the -selectforeground color: + */ + if (showSelection) { + gc = EntryGetGC(entryPtr, es.selForegroundObj); + Tk_DrawTextLayout( + Tk_Display(tkwin), d, gc, entryPtr->entry.textLayout, + entryPtr->entry.layoutX, entryPtr->entry.layoutY, + selFirst, selLast); + Tk_FreeGC(Tk_Display(tkwin), gc); + } +} + +/*------------------------------------------------------------------------ + * +++ Widget commands. + */ + +/* EntryIndex -- + * Parse an index into an entry and return either its value + * or an error. + * + * Results: + * A standard Tcl result. If all went well, then *indexPtr is + * filled in with the character index (into entryPtr) corresponding to + * string. The index value is guaranteed to lie between 0 and + * the number of characters in the string, inclusive. If an + * error occurs then an error message is left in the interp's result. + */ +static int +EntryIndex( + Tcl_Interp *interp, /* For error messages. */ + Entry *entryPtr, /* Entry widget to query */ + Tcl_Obj *indexObj, /* Symbolic index name */ + int *indexPtr) /* Return value */ +{ +# define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */ + int length; + const char *string = Tcl_GetStringFromObj(indexObj, &length); + + if (strncmp(string, "end", length) == 0) { + *indexPtr = entryPtr->entry.numChars; + } else if (strncmp(string, "insert", length) == 0) { + *indexPtr = entryPtr->entry.insertPos; + } else if (strncmp(string, "left", length) == 0) { /* for debugging */ + *indexPtr = entryPtr->entry.xscroll.first; + } else if (strncmp(string, "right", length) == 0) { /* for debugging */ + *indexPtr = entryPtr->entry.xscroll.last; + } else if (strncmp(string, "sel.", 4) == 0) { + if (entryPtr->entry.selectFirst < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "selection isn't in widget ", + Tk_PathName(entryPtr->core.tkwin), NULL); + return TCL_ERROR; + } + if (strncmp(string, "sel.first", length) == 0) { + *indexPtr = entryPtr->entry.selectFirst; + } else if (strncmp(string, "sel.last", length) == 0) { + *indexPtr = entryPtr->entry.selectLast; + } else { + goto badIndex; + } + } else if (string[0] == '@') { + int roundUp = 0; + int maxWidth = EntryWidth(entryPtr); + int x; + + if (Tcl_GetInt(interp, string + 1, &x) != TCL_OK) { + goto badIndex; + } + if (x > maxWidth) { + x = maxWidth; + roundUp = 1; + } + *indexPtr = Tk_PointToChar(entryPtr->entry.textLayout, + x - entryPtr->entry.layoutX, 0); + + if (*indexPtr < entryPtr->entry.xscroll.first) { + *indexPtr = entryPtr->entry.xscroll.first; + } + + /* + * Special trick: if the x-position was off-screen to the right, + * round the index up to refer to the character just after the + * last visible one on the screen. This is needed to enable the + * last character to be selected, for example. + */ + + if (roundUp && (*indexPtr < entryPtr->entry.numChars)) { + *indexPtr += 1; + } + } else { + if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) { + goto badIndex; + } + if (*indexPtr < 0) { + *indexPtr = 0; + } else if (*indexPtr > entryPtr->entry.numChars) { + *indexPtr = entryPtr->entry.numChars; + } + } + return TCL_OK; + +badIndex: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "bad entry index \"", string, "\"", NULL); + return TCL_ERROR; +} + +/* $entry bbox $index -- + * Return the bounding box of the character at the specified index. + */ +static int +EntryBBoxCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + Ttk_Box b; + int index; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "index"); + return TCL_ERROR; + } + if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) { + return TCL_ERROR; + } + if ((index == entryPtr->entry.numChars) && (index > 0)) { + index--; + } + Tk_CharBbox(entryPtr->entry.textLayout, index, + &b.x, &b.y, &b.width, &b.height); + b.x += entryPtr->entry.layoutX; + b.y += entryPtr->entry.layoutY; + Tcl_SetObjResult(interp, Ttk_NewBoxObj(b)); + return TCL_OK; +} + +/* $entry delete $from ?$to? -- + * Delete the characters in the range [$from,$to). + * $to defaults to $from+1 if not specified. + */ +static int +EntryDeleteCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + int first, last; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?"); + return TCL_ERROR; + } + if (EntryIndex(interp, entryPtr, objv[2], &first) != TCL_OK) { + return TCL_ERROR; + } + if (objc == 3) { + last = first + 1; + } else if (EntryIndex(interp, entryPtr, objv[3], &last) != TCL_OK) { + return TCL_ERROR; + } + + if (last >= first && EntryEditable(entryPtr)) { + return DeleteChars(entryPtr, first, last - first); + } + return TCL_OK; +} + +/* $entry get -- + * Return the current value of the entry widget. + */ +static int +EntryGetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + Tcl_SetResult(interp, entryPtr->entry.string, TCL_VOLATILE); + return TCL_OK; +} + +/* $entry icursor $index -- + * Set the insert cursor position. + */ +static int +EntryICursorCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "pos"); + return TCL_ERROR; + } + if (EntryIndex(interp, entryPtr, objv[2], + &entryPtr->entry.insertPos) != TCL_OK) { + return TCL_ERROR; + } + TtkRedisplayWidget(&entryPtr->core); + return TCL_OK; +} + +/* $entry index $index -- + * Return numeric value (0..numChars) of the specified index. + */ +static int +EntryIndexCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + int index; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "string"); + return TCL_ERROR; + } + if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + return TCL_OK; +} + +/* $entry insert $index $text -- + * Insert $text after position $index. + * Silent no-op if the entry is disabled or read-only. + */ +static int +EntryInsertCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + int index; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "index text"); + return TCL_ERROR; + } + if (EntryIndex(interp, entryPtr, objv[2], &index) != TCL_OK) { + return TCL_ERROR; + } + if (EntryEditable(entryPtr)) { + return InsertChars(entryPtr, index, Tcl_GetString(objv[3])); + } + return TCL_OK; +} + +/* $entry selection clear -- + * Clear selection. + */ +static int EntrySelectionClearCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1; + TtkRedisplayWidget(&entryPtr->core); + return TCL_OK; +} + +/* $entry selection present -- + * Returns 1 if any characters are selected, 0 otherwise. + */ +static int EntrySelectionPresentCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(entryPtr->entry.selectFirst >= 0)); + return TCL_OK; +} + +/* $entry selection range $start $end -- + * Explicitly set the selection range. + */ +static int EntrySelectionRangeCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + int start, end; + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "start end"); + return TCL_ERROR; + } + if ( EntryIndex(interp, entryPtr, objv[3], &start) != TCL_OK + || EntryIndex(interp, entryPtr, objv[4], &end) != TCL_OK) { + return TCL_ERROR; + } + if (entryPtr->core.state & TTK_STATE_DISABLED) { + return TCL_OK; + } + + if (start >= end) { + entryPtr->entry.selectFirst = entryPtr->entry.selectLast = -1; + } else { + entryPtr->entry.selectFirst = start; + entryPtr->entry.selectLast = end; + EntryOwnSelection(entryPtr); + } + TtkRedisplayWidget(&entryPtr->core); + return TCL_OK; +} + +static const Ttk_Ensemble EntrySelectionCommands[] = { + { "clear", EntrySelectionClearCommand,0 }, + { "present", EntrySelectionPresentCommand,0 }, + { "range", EntrySelectionRangeCommand,0 }, + { 0,0,0 } +}; + +/* $entry set $value + * Sets the value of an entry widget. + */ +static int EntrySetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "value"); + return TCL_ERROR; + } + EntrySetValue(entryPtr, Tcl_GetString(objv[2])); + return TCL_OK; +} + +/* $entry validate -- + * Trigger forced validation. Returns 1/0 if validation succeeds/fails + * or error status from -validatecommand / -invalidcommand. + */ +static int EntryValidateCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + int code; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, NULL); + return TCL_ERROR; + } + + code = EntryRevalidate(interp, entryPtr, VALIDATE_FORCED); + + if (code == TCL_ERROR) + return code; + + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(code == TCL_OK)); + return TCL_OK; +} + +/* $entry xview -- horizontal scrolling interface + */ +static int EntryXViewCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Entry *entryPtr = recordPtr; + return TtkScrollviewCommand(interp, objc, objv, entryPtr->entry.xscrollHandle); +} + +static const Ttk_Ensemble EntryCommands[] = { + { "bbox", EntryBBoxCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "delete", EntryDeleteCommand,0 }, + { "get", EntryGetCommand,0 }, + { "icursor", EntryICursorCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "index", EntryIndexCommand,0 }, + { "insert", EntryInsertCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "selection", 0,EntrySelectionCommands }, + { "state", TtkWidgetStateCommand,0 }, + { "validate", EntryValidateCommand,0 }, + { "xview", EntryXViewCommand,0 }, + { 0,0,0 } +}; + +/*------------------------------------------------------------------------ + * +++ Entry widget definition. + */ + +static WidgetSpec EntryWidgetSpec = { + "TEntry", /* className */ + sizeof(Entry), /* recordSize */ + EntryOptionSpecs, /* optionSpecs */ + EntryCommands, /* subcommands */ + EntryInitialize, /* initializeProc */ + EntryCleanup, /* cleanupProc */ + EntryConfigure, /* configureProc */ + EntryPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + EntryDoLayout, /* layoutProc */ + EntryDisplay /* displayProc */ +}; + +/*------------------------------------------------------------------------ + * +++ Combobox widget record. + */ + +typedef struct { + Tcl_Obj *postCommandObj; + Tcl_Obj *valuesObj; + Tcl_Obj *heightObj; + int currentIndex; +} ComboboxPart; + +typedef struct { + WidgetCore core; + EntryPart entry; + ComboboxPart combobox; +} Combobox; + +static Tk_OptionSpec ComboboxOptionSpecs[] = { + {TK_OPTION_STRING, "-height", "height", "Height", + DEF_LIST_HEIGHT, Tk_Offset(Combobox, combobox.heightObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-postcommand", "postCommand", "PostCommand", + "", Tk_Offset(Combobox, combobox.postCommandObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-values", "values", "Values", + "", Tk_Offset(Combobox, combobox.valuesObj), -1, + 0,0,0 }, + WIDGET_INHERIT_OPTIONS(EntryOptionSpecs) +}; + +/* ComboboxInitialize -- + * Initialization hook for combobox widgets. + */ +static void +ComboboxInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Combobox *cb = recordPtr; + + cb->combobox.currentIndex = -1; + TtkTrackElementState(&cb->core); + EntryInitialize(interp, recordPtr); +} + +/* ComboboxConfigure -- + * Configuration hook for combobox widgets. + */ +static int +ComboboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Combobox *cbPtr = recordPtr; + int unused; + + /* Make sure -values is a valid list: + */ + if (Tcl_ListObjLength(interp,cbPtr->combobox.valuesObj,&unused) != TCL_OK) + return TCL_ERROR; + + return EntryConfigure(interp, recordPtr, mask); +} + +/* $cb current ?newIndex? -- get or set current index. + * Setting the current index updates the combobox value, + * but the value and -values may be changed independently + * of the index. Instead of trying to keep currentIndex + * in sync at all times, [$cb current] double-checks + */ +static int ComboboxCurrentCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Combobox *cbPtr = recordPtr; + int currentIndex = cbPtr->combobox.currentIndex; + const char *currentValue = cbPtr->entry.string; + int nValues; + Tcl_Obj **values; + + Tcl_ListObjGetElements(interp,cbPtr->combobox.valuesObj,&nValues,&values); + + if (objc == 2) { + /* Check if currentIndex still valid: + */ + if ( currentIndex < 0 + || currentIndex >= nValues + || strcmp(currentValue,Tcl_GetString(values[currentIndex])) + ) + { + /* Not valid. Check current value against each element in -values: + */ + for (currentIndex = 0; currentIndex < nValues; ++currentIndex) { + if (!strcmp(currentValue,Tcl_GetString(values[currentIndex]))) { + break; + } + } + if (currentIndex >= nValues) { + /* Not found */ + currentIndex = -1; + } + } + cbPtr->combobox.currentIndex = currentIndex; + Tcl_SetObjResult(interp, Tcl_NewIntObj(currentIndex)); + return TCL_OK; + } else if (objc == 3) { + if (Tcl_GetIntFromObj(interp, objv[2], ¤tIndex) != TCL_OK) { + return TCL_ERROR; + } + if (currentIndex < 0 || currentIndex >= nValues) { + Tcl_AppendResult(interp, + "Index ", Tcl_GetString(objv[2]), " out of range", + NULL); + return TCL_ERROR; + } + + cbPtr->combobox.currentIndex = currentIndex; + + return EntrySetValue(recordPtr, Tcl_GetString(values[currentIndex])); + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?newIndex?"); + return TCL_ERROR; + } + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Combobox widget definition. + */ +static const Ttk_Ensemble ComboboxCommands[] = { + { "bbox", EntryBBoxCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "current", ComboboxCurrentCommand,0 }, + { "delete", EntryDeleteCommand,0 }, + { "get", EntryGetCommand,0 }, + { "icursor", EntryICursorCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "index", EntryIndexCommand,0 }, + { "insert", EntryInsertCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "selection", 0,EntrySelectionCommands }, + { "state", TtkWidgetStateCommand,0 }, + { "set", EntrySetCommand,0 }, + { "validate", EntryValidateCommand,0 }, + { "xview", EntryXViewCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec ComboboxWidgetSpec = { + "TCombobox", /* className */ + sizeof(Combobox), /* recordSize */ + ComboboxOptionSpecs, /* optionSpecs */ + ComboboxCommands, /* subcommands */ + ComboboxInitialize, /* initializeProc */ + EntryCleanup, /* cleanupProc */ + ComboboxConfigure, /* configureProc */ + EntryPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + EntryDoLayout, /* layoutProc */ + EntryDisplay /* displayProc */ +}; + +/*------------------------------------------------------------------------ + * +++ Spinbox widget. + */ + +typedef struct { + Tcl_Obj *valuesObj; + + Tcl_Obj *fromObj; + Tcl_Obj *toObj; + Tcl_Obj *incrementObj; + Tcl_Obj *formatObj; + + Tcl_Obj *wrapObj; + Tcl_Obj *commandObj; +} SpinboxPart; + +typedef struct { + WidgetCore core; + EntryPart entry; + SpinboxPart spinbox; +} Spinbox; + +static Tk_OptionSpec SpinboxOptionSpecs[] = { + {TK_OPTION_STRING, "-values", "values", "Values", + "", Tk_Offset(Spinbox, spinbox.valuesObj), -1, + 0,0,0 }, + + {TK_OPTION_DOUBLE, "-from", "from", "From", + "0", Tk_Offset(Spinbox,spinbox.fromObj), -1, + 0,0,0 }, + {TK_OPTION_DOUBLE, "-to", "to", "To", + "0", Tk_Offset(Spinbox,spinbox.toObj), -1, + 0,0,0 }, + {TK_OPTION_DOUBLE, "-increment", "increment", "Increment", + "1", Tk_Offset(Spinbox,spinbox.incrementObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-format", "format", "Format", + "", Tk_Offset(Spinbox, spinbox.formatObj), -1, + 0,0,0 }, + + {TK_OPTION_STRING, "-command", "command", "Command", + "", Tk_Offset(Spinbox, spinbox.commandObj), -1, + 0,0,0 }, + {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap", + "0", Tk_Offset(Spinbox,spinbox.wrapObj), -1, + 0,0,0 }, + + WIDGET_INHERIT_OPTIONS(EntryOptionSpecs) +}; + +/* SpinboxInitialize -- + * Initialization hook for spinbox widgets. + */ +static void +SpinboxInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Spinbox *sb = recordPtr; + TtkTrackElementState(&sb->core); + EntryInitialize(interp, recordPtr); +} + +/* SpinboxConfigure -- + * Configuration hook for spinbox widgets. + */ +static int +SpinboxConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Spinbox *sb = recordPtr; + int unused; + + /* Make sure -values is a valid list: + */ + if (Tcl_ListObjLength(interp,sb->spinbox.valuesObj,&unused) != TCL_OK) + return TCL_ERROR; + + return EntryConfigure(interp, recordPtr, mask); +} + +static const Ttk_Ensemble SpinboxCommands[] = { + { "bbox", EntryBBoxCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "delete", EntryDeleteCommand,0 }, + { "get", EntryGetCommand,0 }, + { "icursor", EntryICursorCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "index", EntryIndexCommand,0 }, + { "insert", EntryInsertCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "selection", 0,EntrySelectionCommands }, + { "state", TtkWidgetStateCommand,0 }, + { "set", EntrySetCommand,0 }, + { "validate", EntryValidateCommand,0 }, + { "xview", EntryXViewCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec SpinboxWidgetSpec = { + "TSpinbox", /* className */ + sizeof(Spinbox), /* recordSize */ + SpinboxOptionSpecs, /* optionSpecs */ + SpinboxCommands, /* subcommands */ + SpinboxInitialize, /* initializeProc */ + EntryCleanup, /* cleanupProc */ + SpinboxConfigure, /* configureProc */ + EntryPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + EntryDoLayout, /* layoutProc */ + EntryDisplay /* displayProc */ +}; + +/*------------------------------------------------------------------------ + * +++ Textarea element. + * + * Text display area for Entry widgets. + * Just computes requested size; display is handled by the widget itself. + */ + +typedef struct { + Tcl_Obj *fontObj; + Tcl_Obj *widthObj; +} TextareaElement; + +static Ttk_ElementOptionSpec TextareaElementOptions[] = { + { "-font", TK_OPTION_FONT, + Tk_Offset(TextareaElement,fontObj), DEF_ENTRY_FONT }, + { "-width", TK_OPTION_INT, + Tk_Offset(TextareaElement,widthObj), "20" }, + { NULL, 0, 0, NULL } +}; + +static void TextareaElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TextareaElement *textarea = elementRecord; + Tk_Font font = Tk_GetFontFromObj(tkwin, textarea->fontObj); + int avgWidth = Tk_TextWidth(font, "0", 1); + Tk_FontMetrics fm; + int prefWidth = 1; + + Tk_GetFontMetrics(font, &fm); + Tcl_GetIntFromObj(NULL, textarea->widthObj, &prefWidth); + if (prefWidth <= 0) + prefWidth = 1; + + *heightPtr = fm.linespace; + *widthPtr = prefWidth * avgWidth; +} + +static Ttk_ElementSpec TextareaElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TextareaElement), + TextareaElementOptions, + TextareaElementSize, + TtkNullElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Widget layouts. + */ + +TTK_BEGIN_LAYOUT(EntryLayout) + TTK_GROUP("Entry.field", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("Entry.padding", TTK_FILL_BOTH, + TTK_NODE("Entry.textarea", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(ComboboxLayout) + TTK_GROUP("Combobox.field", TTK_FILL_BOTH, + TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y) + TTK_GROUP("Combobox.padding", TTK_FILL_BOTH|TTK_PACK_LEFT|TTK_EXPAND, + TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(SpinboxLayout) + TTK_GROUP("Spinbox.field", TTK_PACK_TOP|TTK_FILL_X, + TTK_GROUP("null", TTK_PACK_RIGHT, + TTK_NODE("Spinbox.uparrow", TTK_PACK_TOP|TTK_STICK_E) + TTK_NODE("Spinbox.downarrow", TTK_PACK_BOTTOM|TTK_STICK_E)) + TTK_GROUP("Spinbox.padding", TTK_FILL_BOTH, + TTK_NODE("Spinbox.textarea", TTK_FILL_BOTH))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Initialization. + */ +MODULE_SCOPE +void TtkEntry_Init(Tcl_Interp *interp) +{ + Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterElement(interp, themePtr, "textarea", &TextareaElementSpec, 0); + + Ttk_RegisterLayout(themePtr, "TEntry", EntryLayout); + Ttk_RegisterLayout(themePtr, "TCombobox", ComboboxLayout); + Ttk_RegisterLayout(themePtr, "TSpinbox", SpinboxLayout); + + RegisterWidget(interp, "ttk::entry", &EntryWidgetSpec); + RegisterWidget(interp, "ttk::combobox", &ComboboxWidgetSpec); + RegisterWidget(interp, "ttk::spinbox", &SpinboxWidgetSpec); +} + +/*EOF*/ diff --git a/generic/ttk/ttkFrame.c b/generic/ttk/ttkFrame.c new file mode 100644 index 0000000..7860024 --- /dev/null +++ b/generic/ttk/ttkFrame.c @@ -0,0 +1,654 @@ +/* + * Copyright (c) 2004, Joe English + * + * ttk::frame and ttk::labelframe widgets. + */ + +#include <tk.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" +#include "ttkManager.h" + +/* ====================================================================== + * +++ Frame widget: + */ + +typedef struct { + Tcl_Obj *borderWidthObj; + Tcl_Obj *paddingObj; + Tcl_Obj *reliefObj; + Tcl_Obj *widthObj; + Tcl_Obj *heightObj; +} FramePart; + +typedef struct { + WidgetCore core; + FramePart frame; +} Frame; + +static Tk_OptionSpec FrameOptionSpecs[] = { + {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", NULL, + Tk_Offset(Frame,frame.borderWidthObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-padding", "padding", "Pad", NULL, + Tk_Offset(Frame,frame.paddingObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_RELIEF, "-relief", "relief", "Relief", NULL, + Tk_Offset(Frame,frame.reliefObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_PIXELS, "-width", "width", "Width", "0", + Tk_Offset(Frame,frame.widthObj), -1, + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_PIXELS, "-height", "height", "Height", "0", + Tk_Offset(Frame,frame.heightObj), -1, + 0,0,GEOMETRY_CHANGED }, + + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +static const Ttk_Ensemble FrameCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { 0,0,0 } +}; + +/* + * FrameMargins -- + * Compute internal margins for a frame widget. + * This includes the -borderWidth, plus any additional -padding. + */ +static Ttk_Padding FrameMargins(Frame *framePtr) +{ + Ttk_Padding margins = Ttk_UniformPadding(0); + + /* Check -padding: + */ + if (framePtr->frame.paddingObj) { + Ttk_GetPaddingFromObj(NULL, + framePtr->core.tkwin, framePtr->frame.paddingObj, &margins); + } + + /* Add padding for border: + */ + if (framePtr->frame.borderWidthObj) { + int border = 0; + Tk_GetPixelsFromObj(NULL, + framePtr->core.tkwin, framePtr->frame.borderWidthObj, &border); + margins = Ttk_AddPadding(margins, Ttk_UniformPadding((short)border)); + } + + return margins; +} + +/* FrameSize procedure -- + * The frame doesn't request a size of its own by default, + * but it does have an internal border. See also <<NOTE-SIZE>> + */ +static int FrameSize(void *recordPtr, int *widthPtr, int *heightPtr) +{ + Frame *framePtr = recordPtr; + Ttk_SetMargins(framePtr->core.tkwin, FrameMargins(framePtr)); + return 0; +} + +/* + * FrameConfigure -- configure hook. + * <<NOTE-SIZE>> Usually the size of a frame is controlled by + * a geometry manager (pack, grid); the -width and -height + * options are only effective if geometry propagation is turned + * off or if the [place] GM is used for child widgets. + * + * To avoid geometry blinking, we issue a geometry request + * in the Configure hook instead of the Size hook, and only + * if -width and/or -height is nonzero and one of them + * or the other size-related options (-borderwidth, -padding) + * has been changed. + */ + +static int FrameConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Frame *framePtr = recordPtr; + int width, height; + + /* + * Make sure -padding resource, if present, is correct: + */ + if (framePtr->frame.paddingObj) { + Ttk_Padding unused; + if (Ttk_GetPaddingFromObj(interp, + framePtr->core.tkwin, + framePtr->frame.paddingObj, + &unused) != TCL_OK) { + return TCL_ERROR; + } + } + + /* See <<NOTE-SIZE>> + */ + if ( TCL_OK != Tk_GetPixelsFromObj( + interp,framePtr->core.tkwin,framePtr->frame.widthObj,&width) + || TCL_OK != Tk_GetPixelsFromObj( + interp,framePtr->core.tkwin,framePtr->frame.heightObj,&height) + ) + { + return TCL_ERROR; + } + + if ((width > 0 || height > 0) && (mask & GEOMETRY_CHANGED)) { + Tk_GeometryRequest(framePtr->core.tkwin, width, height); + } + + return TtkCoreConfigure(interp, recordPtr, mask); +} + +static WidgetSpec FrameWidgetSpec = { + "TFrame", /* className */ + sizeof(Frame), /* recordSize */ + FrameOptionSpecs, /* optionSpecs */ + FrameCommands, /* subcommands */ + TtkNullInitialize, /* initializeProc */ + TtkNullCleanup, /* cleanupProc */ + FrameConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + FrameSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(FrameLayout) + TTK_NODE("Frame.border", TTK_FILL_BOTH) +TTK_END_LAYOUT + +/* ====================================================================== + * +++ Labelframe widget: + */ + +#define DEFAULT_LABELINSET 8 +#define DEFAULT_BORDERWIDTH 2 + +int TtkGetLabelAnchorFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_PositionSpec *anchorPtr) +{ + const char *string = Tcl_GetString(objPtr); + char c = *string++; + Ttk_PositionSpec flags = 0; + + /* First character determines side: + */ + switch (c) { + case 'w' : flags = TTK_PACK_LEFT; break; + case 'e' : flags = TTK_PACK_RIGHT; break; + case 'n' : flags = TTK_PACK_TOP; break; + case 's' : flags = TTK_PACK_BOTTOM; break; + default : goto error; + } + + /* Remaining characters are as per -sticky: + */ + while ((c = *string++) != '\0') { + switch (c) { + case 'w' : flags |= TTK_STICK_W; break; + case 'e' : flags |= TTK_STICK_E; break; + case 'n' : flags |= TTK_STICK_N; break; + case 's' : flags |= TTK_STICK_S; break; + default : goto error; + } + } + + *anchorPtr = flags; + return TCL_OK; + +error: + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Bad label anchor specification ", Tcl_GetString(objPtr), + NULL); + } + return TCL_ERROR; +} + +/* LabelAnchorSide -- + * Returns the side corresponding to a LabelAnchor value. + */ +static Ttk_Side LabelAnchorSide(Ttk_PositionSpec flags) +{ + if (flags & TTK_PACK_LEFT) return TTK_SIDE_LEFT; + else if (flags & TTK_PACK_RIGHT) return TTK_SIDE_RIGHT; + else if (flags & TTK_PACK_TOP) return TTK_SIDE_TOP; + else if (flags & TTK_PACK_BOTTOM) return TTK_SIDE_BOTTOM; + /*NOTREACHED*/ + return TTK_SIDE_TOP; +} + +/* + * Labelframe widget record: + */ +typedef struct { + Tcl_Obj *labelAnchorObj; + Tcl_Obj *textObj; + Tcl_Obj *underlineObj; + Tk_Window labelWidget; + + Ttk_Manager *mgr; + Ttk_Layout labelLayout; /* Sublayout for label */ + Ttk_Box labelParcel; /* Set in layoutProc */ +} LabelframePart; + +typedef struct { + WidgetCore core; + FramePart frame; + LabelframePart label; +} Labelframe; + +#define LABELWIDGET_CHANGED 0x100 + +static Tk_OptionSpec LabelframeOptionSpecs[] = { + {TK_OPTION_STRING, "-labelanchor", "labelAnchor", "LabelAnchor", + "nw", Tk_Offset(Labelframe, label.labelAnchorObj),-1, + 0,0,GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-text", "text", "Text", "", + Tk_Offset(Labelframe,label.textObj), -1, + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-underline", "underline", "Underline", + "-1", Tk_Offset(Labelframe,label.underlineObj), -1, + 0,0,0 }, + {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL, + -1, Tk_Offset(Labelframe,label.labelWidget), + TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED }, + + WIDGET_INHERIT_OPTIONS(FrameOptionSpecs) +}; + +/* + * Labelframe style parameters: + */ +typedef struct { + int borderWidth; /* border width */ + Ttk_Padding padding; /* internal padding */ + Ttk_PositionSpec labelAnchor; /* corner/side to place label */ + Ttk_Padding labelMargins; /* extra space around label */ + int labelOutside; /* true=>place label outside border */ +} LabelframeStyle; + +static void LabelframeStyleOptions(Labelframe *lf, LabelframeStyle *style) +{ + Ttk_Layout layout = lf->core.layout; + Tcl_Obj *objPtr; + + style->borderWidth = DEFAULT_BORDERWIDTH; + style->padding = Ttk_UniformPadding(0); + style->labelAnchor = TTK_PACK_TOP | TTK_STICK_W; + style->labelOutside = 0; + + if ((objPtr = Ttk_QueryOption(layout, "-borderwidth", 0)) != NULL) { + Tk_GetPixelsFromObj(NULL, lf->core.tkwin, objPtr, &style->borderWidth); + } + if ((objPtr = Ttk_QueryOption(layout, "-padding", 0)) != NULL) { + Ttk_GetPaddingFromObj(NULL, lf->core.tkwin, objPtr, &style->padding); + } + if ((objPtr = Ttk_QueryOption(layout,"-labelanchor", 0)) != NULL) { + TtkGetLabelAnchorFromObj(NULL, objPtr, &style->labelAnchor); + } + if ((objPtr = Ttk_QueryOption(layout,"-labelmargins", 0)) != NULL) { + Ttk_GetBorderFromObj(NULL, objPtr, &style->labelMargins); + } else { + if (style->labelAnchor & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) { + style->labelMargins = + Ttk_MakePadding(DEFAULT_LABELINSET,0,DEFAULT_LABELINSET,0); + } else { + style->labelMargins = + Ttk_MakePadding(0,DEFAULT_LABELINSET,0,DEFAULT_LABELINSET); + } + } + if ((objPtr = Ttk_QueryOption(layout,"-labeloutside", 0)) != NULL) { + Tcl_GetBooleanFromObj(NULL, objPtr, &style->labelOutside); + } + + return; +} + +/* LabelframeLabelSize -- + * Extract the requested width and height of the labelframe's label: + * taken from the label widget if specified, otherwise the text label. + */ +static void +LabelframeLabelSize(Labelframe *lframePtr, int *widthPtr, int *heightPtr) +{ + Tk_Window labelWidget = lframePtr->label.labelWidget; + Ttk_Layout labelLayout = lframePtr->label.labelLayout; + + if (labelWidget) { + *widthPtr = Tk_ReqWidth(labelWidget); + *heightPtr = Tk_ReqHeight(labelWidget); + } else if (labelLayout) { + Ttk_LayoutSize(labelLayout, 0, widthPtr, heightPtr); + } else { + *widthPtr = *heightPtr = 0; + } +} + +/* + * LabelframeSize -- + * Like the frame, this doesn't request a size of its own + * but it does have internal padding and a minimum size. + */ +static int LabelframeSize(void *recordPtr, int *widthPtr, int *heightPtr) +{ + Labelframe *lframePtr = recordPtr; + WidgetCore *corePtr = &lframePtr->core; + Ttk_Padding margins; + LabelframeStyle style; + int labelWidth, labelHeight; + + LabelframeStyleOptions(lframePtr, &style); + + /* Compute base margins (See also: FrameMargins) + */ + margins = Ttk_AddPadding( + style.padding, Ttk_UniformPadding((short)style.borderWidth)); + + /* Adjust margins based on label size and position: + */ + LabelframeLabelSize(lframePtr, &labelWidth, &labelHeight); + labelWidth += Ttk_PaddingWidth(style.labelMargins); + labelHeight += Ttk_PaddingHeight(style.labelMargins); + + switch (LabelAnchorSide(style.labelAnchor)) { + case TTK_SIDE_LEFT: margins.left += labelWidth; break; + case TTK_SIDE_RIGHT: margins.right += labelWidth; break; + case TTK_SIDE_TOP: margins.top += labelHeight; break; + case TTK_SIDE_BOTTOM: margins.bottom += labelHeight; break; + } + + Ttk_SetMargins(corePtr->tkwin,margins); + + /* Request minimum size based on border width and label size: + */ + Tk_SetMinimumRequestSize(corePtr->tkwin, + labelWidth + 2*style.borderWidth, + labelHeight + 2*style.borderWidth); + + return 0; +} + +/* + * LabelframeGetLayout -- + * Getlayout widget hook. + */ + +static Ttk_Layout LabelframeGetLayout( + Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) +{ + Labelframe *lf = recordPtr; + Ttk_Layout frameLayout = TtkWidgetGetLayout(interp, theme, recordPtr); + Ttk_Layout labelLayout; + + if (!frameLayout) { + return NULL; + } + + labelLayout = Ttk_CreateSublayout( + interp, theme, frameLayout, ".Label", lf->core.optionTable); + + if (labelLayout) { + if (lf->label.labelLayout) { + Ttk_FreeLayout(lf->label.labelLayout); + } + Ttk_RebindSublayout(labelLayout, recordPtr); + lf->label.labelLayout = labelLayout; + } + + return frameLayout; +} + +/* + * LabelframeDoLayout -- + * Labelframe layout hook. + * + * Side effects: Computes labelParcel. + */ + +static void LabelframeDoLayout(void *recordPtr) +{ + Labelframe *lframePtr = recordPtr; + WidgetCore *corePtr = &lframePtr->core; + int lw, lh; /* Label width and height */ + LabelframeStyle style; + Ttk_Box borderParcel = Ttk_WinBox(lframePtr->core.tkwin); + Ttk_Box labelParcel; + + /* + * Compute label parcel: + */ + LabelframeStyleOptions(lframePtr, &style); + LabelframeLabelSize(lframePtr, &lw, &lh); + lw += Ttk_PaddingWidth(style.labelMargins); + lh += Ttk_PaddingHeight(style.labelMargins); + + labelParcel = Ttk_PadBox( + Ttk_PositionBox(&borderParcel, lw, lh, style.labelAnchor), + style.labelMargins); + + if (!style.labelOutside) { + /* Move border edge so it's over label: + */ + switch (LabelAnchorSide(style.labelAnchor)) { + case TTK_SIDE_LEFT: borderParcel.x -= lw / 2; + case TTK_SIDE_RIGHT: borderParcel.width += lw/2; break; + case TTK_SIDE_TOP: borderParcel.y -= lh / 2; + case TTK_SIDE_BOTTOM: borderParcel.height += lh / 2; break; + } + } + + /* + * Place border and label: + */ + Ttk_PlaceLayout(corePtr->layout, corePtr->state, borderParcel); + if (lframePtr->label.labelLayout) { + Ttk_PlaceLayout( + lframePtr->label.labelLayout, corePtr->state, labelParcel); + } + /* labelWidget placed in LabelframePlaceSlaves GM hook */ + lframePtr->label.labelParcel = labelParcel; +} + +static void LabelframeDisplay(void *recordPtr, Drawable d) +{ + Labelframe *lframePtr = recordPtr; + Ttk_DrawLayout(lframePtr->core.layout, lframePtr->core.state, d); + if (lframePtr->label.labelLayout) { + Ttk_DrawLayout(lframePtr->label.labelLayout, lframePtr->core.state, d); + } +} + +/* +++ Labelframe geometry manager hooks. + */ + +/* LabelframePlaceSlaves -- + * Sets the position and size of the labelwidget. + */ +static void LabelframePlaceSlaves(void *recordPtr) +{ + Labelframe *lframe = recordPtr; + + if (Ttk_NumberSlaves(lframe->label.mgr) == 1) { + Ttk_Box b; + LabelframeDoLayout(recordPtr); + b = lframe->label.labelParcel; + /* ASSERT: slave #0 is lframe->label.labelWidget */ + Ttk_PlaceSlave(lframe->label.mgr, 0, b.x,b.y,b.width,b.height); + } +} + +static int LabelRequest(void *managerData, int index, int width, int height) +{ + return 1; +} + +/* LabelRemoved -- + * Unset the -labelwidget option. + * + * <<NOTE-LABELREMOVED>>: + * This routine is also called when the widget voluntarily forgets + * the slave in LabelframeConfigure. + */ +static void LabelRemoved(void *managerData, int slaveIndex) +{ + Labelframe *lframe = managerData; + lframe->label.labelWidget = 0; +} + +static Ttk_ManagerSpec LabelframeManagerSpec = { + { "labelframe", Ttk_GeometryRequestProc, Ttk_LostSlaveProc }, + LabelframeSize, + LabelframePlaceSlaves, + LabelRequest, + LabelRemoved +}; + +/* LabelframeInitialize -- + * Initialization hook. + */ +static void LabelframeInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Labelframe *lframe = recordPtr; + + lframe->label.mgr = Ttk_CreateManager( + &LabelframeManagerSpec, lframe, lframe->core.tkwin); + lframe->label.labelWidget = 0; + lframe->label.labelLayout = 0; + lframe->label.labelParcel = Ttk_MakeBox(-1,-1,-1,-1); +} + +/* LabelframeCleanup -- + * Cleanup hook. + */ +static void LabelframeCleanup(void *recordPtr) +{ + Labelframe *lframe = recordPtr; + Ttk_DeleteManager(lframe->label.mgr); + if (lframe->label.labelLayout) { + Ttk_FreeLayout(lframe->label.labelLayout); + } +} + +/* RaiseLabelWidget -- + * Raise the -labelwidget to ensure that the labelframe doesn't + * obscure it (if it's not a direct child), or bring it to + * the top of the stacking order (if it is). + */ +static void RaiseLabelWidget(Labelframe *lframe) +{ + Tk_Window parent = Tk_Parent(lframe->label.labelWidget); + Tk_Window sibling = NULL; + Tk_Window w = lframe->core.tkwin; + + while (w && w != parent) { + sibling = w; + w = Tk_Parent(w); + } + + Tk_RestackWindow(lframe->label.labelWidget, Above, sibling); +} + +/* LabelframeConfigure -- + * Configuration hook. + */ +static int LabelframeConfigure(Tcl_Interp *interp,void *recordPtr,int mask) +{ + Labelframe *lframePtr = recordPtr; + Tk_Window labelWidget = lframePtr->label.labelWidget; + Ttk_PositionSpec unused; + + /* Validate options: + */ + if (mask & LABELWIDGET_CHANGED && labelWidget != NULL) { + if (!Ttk_Maintainable(interp, labelWidget, lframePtr->core.tkwin)) { + return TCL_ERROR; + } + } + + if (TtkGetLabelAnchorFromObj( + interp, lframePtr->label.labelAnchorObj, &unused) != TCL_OK) + { + return TCL_ERROR; + } + + /* Base class configuration: + */ + if (FrameConfigure(interp, recordPtr, mask) != TCL_OK) { + return TCL_ERROR; + } + + /* Update -labelwidget changes, if any: + */ + if (mask & LABELWIDGET_CHANGED) { + if (Ttk_NumberSlaves(lframePtr->label.mgr) == 1) { + Ttk_ForgetSlave(lframePtr->label.mgr, 0); + /* Restore labelWidget field (see <<NOTE-LABELREMOVED>>) + */ + lframePtr->label.labelWidget = labelWidget; + } + + if (labelWidget) { + Ttk_InsertSlave(lframePtr->label.mgr, 0, labelWidget, NULL); + RaiseLabelWidget(lframePtr); + } + } + + if (mask & GEOMETRY_CHANGED) { + Ttk_ManagerSizeChanged(lframePtr->label.mgr); + Ttk_ManagerLayoutChanged(lframePtr->label.mgr); + } + + return TCL_OK; +} + +static WidgetSpec LabelframeWidgetSpec = { + "TLabelframe", /* className */ + sizeof(Labelframe), /* recordSize */ + LabelframeOptionSpecs, /* optionSpecs */ + FrameCommands, /* subcommands */ + LabelframeInitialize, /* initializeProc */ + LabelframeCleanup, /* cleanupProc */ + LabelframeConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + LabelframeGetLayout, /* getLayoutProc */ + LabelframeSize, /* sizeProc */ + LabelframeDoLayout, /* layoutProc */ + LabelframeDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(LabelframeLayout) + TTK_NODE("Labelframe.border", TTK_FILL_BOTH) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(LabelSublayout) + TTK_GROUP("Label.fill", TTK_FILL_BOTH, + TTK_NODE("Label.text", TTK_FILL_BOTH)) +TTK_END_LAYOUT + +/* ====================================================================== + * +++ Initialization. + */ + +MODULE_SCOPE +void TtkFrame_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(theme, "TFrame", FrameLayout); + Ttk_RegisterLayout(theme, "TLabelframe", LabelframeLayout); + Ttk_RegisterLayout(theme, "Label", LabelSublayout); + + RegisterWidget(interp, "ttk::frame", &FrameWidgetSpec); + RegisterWidget(interp, "ttk::labelframe", &LabelframeWidgetSpec); +} + diff --git a/generic/ttk/ttkGenStubs.tcl b/generic/ttk/ttkGenStubs.tcl new file mode 100644 index 0000000..fb9c018 --- /dev/null +++ b/generic/ttk/ttkGenStubs.tcl @@ -0,0 +1,920 @@ +# ttkGenStubs.tcl -- +# +# This script generates a set of stub files for a given +# interface. +# +# +# Copyright (c) 1998-1999 by Scriptics Corporation. +# 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.20 +# +# CHANGES: +# + Remove xxx_TCL_DECLARED #ifdeffery +# + Use application-defined storage class specifier instead of "EXTERN" +# + Add "epoch" and "revision" fields to stubs table record +# + Remove dead code related to USE_*_STUB_PROCS (emitStubs, makeStub) +# + Second argument to "declare" is used as a status guard +# instead of a platform guard. +# + Use void (*reserved$i)(void) = 0 instead of void *reserved$i = NULL +# for unused stub entries, in case pointer-to-function and +# pointer-to-object are different sizes. +# + Allow trailing semicolon in function declarations +# + stubs table is const-qualified +# + +package require Tcl 8 + +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 0 + 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. +# +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 const $decl CONST decl + 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::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] + + 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 text} { + switch $plat { + win { + return "#ifdef __WIN32__\n${text}#endif /* __WIN32__ */\n" + } + unix { + return "#if !defined(__WIN32__) /* UNIX */\n${text}#endif /* UNIX */\n" + } + macosx { + return "#ifdef MAC_OSX_TCL\n${text}#endif /* MAC_OSX_TCL */\n" + } + aqua { + return "#ifdef MAC_OSX_TK\n${text}#endif /* MAC_OSX_TK */\n" + } + x11 { + return "#if !(defined(__WIN32__) || defined(MAC_OSX_TK)) /* X11 */\n${text}#endif /* X11 */\n" + } + } + return $text +} + +# genStubs::emitSlots -- +# +# Generate the stub table slots for the given interface. +# +# 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 == ""} { + 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 == "void"} { + return $arg + } else { + return + } + } + set result [list [string trim $type] $name] + if {$array != ""} { + 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" + if {$rtype != "void"} { + regsub -all void $rtype VOID rtype + } + 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 == ""} { + append line $fname + append text $line + append text ";\n" + return $text + } + append line $fname + + regsub -all void $args VOID args + 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 == ""} { + 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 {$rtype != "void"} { + regsub -all void $rtype VOID rtype + } + if {$args == ""} { + append text $rtype " *" $lfname "; /* $index */\n" + return $text + } + append text $rtype " (*" $lfname ") " + + regsub -all void $args VOID args + 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] == ""} { + 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] + + set CAPName [string toupper $name] + append text "\n" + append text "#define ${CAPName}_STUBS_EPOCH $epoch\n" + append text "#define ${CAPName}_STUBS_REVISION $revision\n" + + emitDeclarations $name text + + if {[info exists hooks($name)]} { + append text "\ntypedef struct ${capName}StubHooks {\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" + append text " int epoch;\n" + append text " int revision;\n" + append text " const struct ${capName}StubHooks *hooks;\n\n" + + emitSlots $name text + + append text "} ${capName}Stubs;\n\n" + + append text "#ifdef __cplusplus\nextern \"C\" {\n#endif\n" + append text "extern const ${capName}Stubs *${name}StubsPtr;\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 + variable revision + + upvar $textVar text + set root 1 + + set capName [string toupper [string index $name 0]] + append capName [string range $name 1 end] + set CAPName [string toupper $name] + + 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 {0<=[lsearch -exact $hooks($intf) $name]} { + set root 0 + break; + } + } + } + + if {$root} { + append text "\nconst ${capName}Stubs ${name}Stubs = \{\n" + } else { + append text "\nstatic const ${capName}Stubs ${name}Stubs = \{\n" + } + append text " TCL_STUB_MAGIC,\n" + 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 new file mode 100644 index 0000000..c3b55e9 --- /dev/null +++ b/generic/ttk/ttkImage.c @@ -0,0 +1,415 @@ +/* + * Image specifications and image element factory. + * + * Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net> + * Copyright (C) 2004 Joe English + * + * An imageSpec is a multi-element list; the first element + * is the name of the default image to use, the remainder of the + * list is a sequence of statespec/imagename options as per + * [style map]. + */ + +#include <string.h> +#include <tk.h> +#include "ttkTheme.h" + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +/*------------------------------------------------------------------------ + * +++ ImageSpec management. + */ + +struct TtkImageSpec { + Tk_Image baseImage; /* Base image to use */ + int mapCount; /* #state-specific overrides */ + Ttk_StateSpec *states; /* array[mapCount] of states ... */ + Tk_Image *images; /* ... per-state images to use */ +}; + +/* NullImageChanged -- + * Do-nothing Tk_ImageChangedProc. + */ +static void NullImageChanged(ClientData clientData, + int x, int y, int width, int height, int imageWidth, int imageHeight) +{ /* No-op */ } + +/* 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) +{ + Ttk_ImageSpec *imageSpec = 0; + int i = 0, n = 0, objc; + Tcl_Obj **objv; + + imageSpec = (Ttk_ImageSpec *)ckalloc(sizeof(*imageSpec)); + imageSpec->baseImage = 0; + imageSpec->mapCount = 0; + imageSpec->states = 0; + imageSpec->images = 0; + + if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { + goto error; + } + + if ((objc % 2) != 1) { + if (interp) { + Tcl_SetResult(interp, + "image specification must contain an odd number of elements", + TCL_STATIC); + } + goto error; + } + + n = (objc - 1) / 2; + imageSpec->states = (Ttk_StateSpec*)ckalloc(n * sizeof(Ttk_StateSpec)); + imageSpec->images = (Tk_Image*)ckalloc(n * sizeof(Tk_Image *)); + + /* Get base image: + */ + imageSpec->baseImage = Tk_GetImage( + interp, tkwin, Tcl_GetString(objv[0]), NullImageChanged, NULL); + if (!imageSpec->baseImage) { + goto error; + } + + /* Extract state and image specifications: + */ + for (i = 0; i < n; ++i) { + Tcl_Obj *stateSpec = objv[2*i + 1]; + const char *imageName = Tcl_GetString(objv[2*i + 2]); + Ttk_StateSpec state; + + if (Ttk_GetStateSpecFromObj(interp, stateSpec, &state) != TCL_OK) { + goto error; + } + imageSpec->states[i] = state; + + imageSpec->images[i] = Tk_GetImage( + interp, tkwin, imageName, NullImageChanged, NULL); + if (imageSpec->images[i] == NULL) { + goto error; + } + imageSpec->mapCount = i+1; + } + + return imageSpec; + +error: + TtkFreeImageSpec(imageSpec); + return NULL; +} + +/* TtkFreeImageSpec -- + * Dispose of an image specification. + */ +void TtkFreeImageSpec(Ttk_ImageSpec *imageSpec) +{ + int i; + + for (i=0; i < imageSpec->mapCount; ++i) { + Tk_FreeImage(imageSpec->images[i]); + } + + if (imageSpec->baseImage) { Tk_FreeImage(imageSpec->baseImage); } + if (imageSpec->states) { ckfree((ClientData)imageSpec->states); } + if (imageSpec->images) { ckfree((ClientData)imageSpec->images); } + + ckfree((ClientData)imageSpec); +} + +/* TtkSelectImage -- + * Return a state-specific image from an ImageSpec + */ +Tk_Image TtkSelectImage(Ttk_ImageSpec *imageSpec, Ttk_State state) +{ + int i; + for (i = 0; i < imageSpec->mapCount; ++i) { + if (Ttk_StateMatches(state, imageSpec->states+i)) { + return imageSpec->images[i]; + } + } + return imageSpec->baseImage; +} + +/*------------------------------------------------------------------------ + * +++ Drawing utilities. + */ + +/* LPadding, CPadding, RPadding -- + * Split a box+padding pair into left, center, and right boxes. + */ +static Ttk_Box LPadding(Ttk_Box b, Ttk_Padding p) + { return Ttk_MakeBox(b.x, b.y, p.left, b.height); } + +static Ttk_Box CPadding(Ttk_Box b, Ttk_Padding p) + { return Ttk_MakeBox(b.x+p.left, b.y, b.width-p.left-p.right, b.height); } + +static Ttk_Box RPadding(Ttk_Box b, Ttk_Padding p) + { return Ttk_MakeBox(b.x+b.width-p.right, b.y, p.right, b.height); } + +/* TPadding, MPadding, BPadding -- + * Split a box+padding pair into top, middle, and bottom parts. + */ +static Ttk_Box TPadding(Ttk_Box b, Ttk_Padding p) + { return Ttk_MakeBox(b.x, b.y, b.width, p.top); } + +static Ttk_Box MPadding(Ttk_Box b, Ttk_Padding p) + { return Ttk_MakeBox(b.x, b.y+p.top, b.width, b.height-p.top-p.bottom); } + +static Ttk_Box BPadding(Ttk_Box b, Ttk_Padding p) + { return Ttk_MakeBox(b.x, b.y+b.height-p.bottom, b.width, p.bottom); } + +/* Ttk_Fill -- + * Fill the destination area of the drawable by replicating + * the source area of the image. + */ +static void Ttk_Fill( + Tk_Window tkwin, Drawable d, Tk_Image image, Ttk_Box src, Ttk_Box dst) +{ + int dr = dst.x + dst.width; + int db = dst.y + dst.height; + int x,y; + + if (!(src.width && src.height && dst.width && dst.height)) + return; + + for (x = dst.x; x < dr; x += src.width) { + int cw = MIN(src.width, dr - x); + for (y = dst.y; y <= db; y += src.height) { + int ch = MIN(src.height, db - y); + Tk_RedrawImage(image, src.x, src.y, cw, ch, d, x, y); + } + } +} + +/* Ttk_Stripe -- + * Fill a horizontal stripe of the destination drawable. + */ +static void Ttk_Stripe( + Tk_Window tkwin, Drawable d, Tk_Image image, + Ttk_Box src, Ttk_Box dst, Ttk_Padding p) +{ + Ttk_Fill(tkwin, d, image, LPadding(src,p), LPadding(dst,p)); + Ttk_Fill(tkwin, d, image, CPadding(src,p), CPadding(dst,p)); + Ttk_Fill(tkwin, d, image, RPadding(src,p), RPadding(dst,p)); +} + +/* Ttk_Tile -- + * Fill successive horizontal stripes of the destination drawable. + */ +static void Ttk_Tile( + Tk_Window tkwin, Drawable d, Tk_Image image, + Ttk_Box src, Ttk_Box dst, Ttk_Padding p) +{ + Ttk_Stripe(tkwin, d, image, TPadding(src,p), TPadding(dst,p), p); + Ttk_Stripe(tkwin, d, image, MPadding(src,p), MPadding(dst,p), p); + Ttk_Stripe(tkwin, d, image, BPadding(src,p), BPadding(dst,p), p); +} + +/*------------------------------------------------------------------------ + * +++ Image element definition. + */ + +typedef struct { /* ClientData for image elements */ + Ttk_ImageSpec *imageSpec; /* Image(s) to use */ + int minWidth; /* Minimum width; overrides image width */ + int minHeight; /* Minimum width; overrides image width */ + Ttk_Sticky sticky; /* -stickiness specification */ + Ttk_Padding border; /* Fixed border region */ + Ttk_Padding padding; /* Internal padding */ + +#if TILE_07_COMPAT + Ttk_ResourceCache cache; /* Resource cache for images */ + Ttk_StateMap imageMap; /* State-based lookup table for images */ +#endif +} ImageData; + +static void FreeImageData(void *clientData) +{ + ImageData *imageData = clientData; + if (imageData->imageSpec) { TtkFreeImageSpec(imageData->imageSpec); } +#if TILE_07_COMPAT + if (imageData->imageMap) { Tcl_DecrRefCount(imageData->imageMap); } +#endif + ckfree(clientData); +} + +static void ImageElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ImageData *imageData = clientData; + Tk_Image image = imageData->imageSpec->baseImage; + + if (image) { + Tk_SizeOfImage(image, widthPtr, heightPtr); + } + if (imageData->minWidth >= 0) { + *widthPtr = imageData->minWidth; + } + if (imageData->minHeight >= 0) { + *heightPtr = imageData->minHeight; + } + + *paddingPtr = imageData->padding; +} + +static void ImageElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + ImageData *imageData = clientData; + Tk_Image image = 0; + int imgWidth, imgHeight; + Ttk_Box src, dst; + +#if TILE_07_COMPAT + if (imageData->imageMap) { + Tcl_Obj *imageObj = Ttk_StateMapLookup(NULL,imageData->imageMap,state); + if (imageObj) { + image = Ttk_UseImage(imageData->cache, tkwin, imageObj); + } + } + if (!image) { + image = TtkSelectImage(imageData->imageSpec, state); + } +#else + image = TtkSelectImage(imageData->imageSpec, state); +#endif + + if (!image) { + return; + } + + Tk_SizeOfImage(image, &imgWidth, &imgHeight); + src = Ttk_MakeBox(0, 0, imgWidth, imgHeight); + dst = Ttk_StickBox(b, imgWidth, imgHeight, imageData->sticky); + + Ttk_Tile(tkwin, d, image, src, dst, imageData->border); +} + +static Ttk_ElementSpec ImageElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(NullElement), + TtkNullElementOptions, + ImageElementSize, + ImageElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Image element factory. + */ +static int +Ttk_CreateImageElement( + Tcl_Interp *interp, + void *clientData, + Ttk_Theme theme, + const char *elementName, + int objc, Tcl_Obj *const objv[]) +{ + const char *optionStrings[] = + { "-border","-height","-padding","-sticky","-width",NULL }; + enum { O_BORDER, O_HEIGHT, O_PADDING, O_STICKY, O_WIDTH }; + + Ttk_ImageSpec *imageSpec = 0; + ImageData *imageData = 0; + int padding_specified = 0; + int i; + + if (objc <= 0) { + Tcl_AppendResult(interp, "Must supply a base image", NULL); + return TCL_ERROR; + } + + imageSpec = TtkGetImageSpec(interp, Tk_MainWindow(interp), objv[0]); + if (!imageSpec) { + return TCL_ERROR; + } + + imageData = (ImageData*)ckalloc(sizeof(*imageData)); + imageData->imageSpec = imageSpec; + imageData->minWidth = imageData->minHeight = -1; + imageData->sticky = TTK_FILL_BOTH; + imageData->border = imageData->padding = Ttk_UniformPadding(0); +#if TILE_07_COMPAT + imageData->cache = Ttk_GetResourceCache(interp); + imageData->imageMap = 0; +#endif + + for (i = 1; i < objc; i += 2) { + int option; + + if (i == objc - 1) { + Tcl_AppendResult(interp, + "Value for ", Tcl_GetString(objv[i]), " missing", + NULL); + goto error; + } + +#if TILE_07_COMPAT + if (!strcmp("-map", Tcl_GetString(objv[i]))) { + imageData->imageMap = objv[i+1]; + Tcl_IncrRefCount(imageData->imageMap); + continue; + } +#endif + + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, + "option", 0, &option) != TCL_OK) { goto error; } + + switch (option) { + case O_BORDER: + if (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->border) + != TCL_OK) { goto error; } + if (!padding_specified) { + imageData->padding = imageData->border; + } + break; + case O_PADDING: + if (Ttk_GetBorderFromObj(interp, objv[i+1], &imageData->padding) + != TCL_OK) { goto error; } + padding_specified = 1; + break; + case O_WIDTH: + if (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minWidth) + != TCL_OK) { goto error; } + break; + case O_HEIGHT: + if (Tcl_GetIntFromObj(interp, objv[i+1], &imageData->minHeight) + != TCL_OK) { goto error; } + break; + case O_STICKY: + if (Ttk_GetStickyFromObj(interp, objv[i+1], &imageData->sticky) + != TCL_OK) { goto error; } + } + } + + if (!Ttk_RegisterElement(interp, theme, elementName, &ImageElementSpec, + imageData)) + { + goto error; + } + + Ttk_RegisterCleanup(interp, imageData, FreeImageData); + Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1)); + return TCL_OK; + +error: + FreeImageData(imageData); + return TCL_ERROR; +} + +MODULE_SCOPE +void TtkImage_Init(Tcl_Interp *interp) +{ + Ttk_RegisterElementFactory(interp, "image", Ttk_CreateImageElement, NULL); +} + +/*EOF*/ diff --git a/generic/ttk/ttkInit.c b/generic/ttk/ttkInit.c new file mode 100644 index 0000000..78676c6 --- /dev/null +++ b/generic/ttk/ttkInit.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2003, Joe English + * + * Ttk package: initialization routine and miscellaneous utilities. + */ + +#include <string.h> +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +/* + * Legal values for the button -default option. + * See also: enum Ttk_ButtonDefaultState. + */ +const char *ttkDefaultStrings[] = { + "normal", "active", "disabled", NULL +}; + +int Ttk_GetButtonDefaultStateFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr) +{ + *statePtr = TTK_BUTTON_DEFAULT_DISABLED; + return Tcl_GetIndexFromObj(interp, objPtr, + ttkDefaultStrings, "default state", 0, statePtr); +} + +/* + * Legal values for the -compound option. + * See also: enum Ttk_Compound. + */ +const char *ttkCompoundStrings[] = { + "none", "text", "image", "center", + "top", "bottom", "left", "right", NULL +}; + +int Ttk_GetCompoundFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, int *statePtr) +{ + *statePtr = TTK_COMPOUND_NONE; + return Tcl_GetIndexFromObj(interp, objPtr, + ttkCompoundStrings, "compound layout", 0, statePtr); +} + +/* + * Legal values for the -orient option. + * See also: enum Ttk_Orient. + */ +const char *ttkOrientStrings[] = { + "horizontal", "vertical", NULL +}; + +int Ttk_GetOrientFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, int *resultPtr) +{ + *resultPtr = TTK_ORIENT_HORIZONTAL; + return Tcl_GetIndexFromObj(interp, objPtr, + ttkOrientStrings, "orientation", 0, resultPtr); +} + +/* + * Recognized values for the -state compatibility option. + * Other options are accepted and interpreted as synonyms for "normal". + */ +static const char *ttkStateStrings[] = { + "normal", "readonly", "disabled", "active", NULL +}; +enum { + TTK_COMPAT_STATE_NORMAL, + TTK_COMPAT_STATE_READONLY, + TTK_COMPAT_STATE_DISABLED, + TTK_COMPAT_STATE_ACTIVE +}; + +/* TtkCheckStateOption -- + * Handle -state compatibility option. + * + * NOTE: setting -state disabled / -state enabled affects the + * widget state, but the internal widget state does *not* affect + * the value of the -state option. + * This option is present for compatibility only. + */ +void TtkCheckStateOption(WidgetCore *corePtr, Tcl_Obj *objPtr) +{ + int stateOption = TTK_COMPAT_STATE_NORMAL; + unsigned all = TTK_STATE_DISABLED|TTK_STATE_READONLY|TTK_STATE_ACTIVE; +# define SETFLAGS(f) TtkWidgetChangeState(corePtr, f, all^f) + + (void)Tcl_GetIndexFromObj(NULL,objPtr,ttkStateStrings,"",0,&stateOption); + switch (stateOption) { + case TTK_COMPAT_STATE_NORMAL: + default: + SETFLAGS(0); + break; + case TTK_COMPAT_STATE_READONLY: + SETFLAGS(TTK_STATE_READONLY); + break; + case TTK_COMPAT_STATE_DISABLED: + SETFLAGS(TTK_STATE_DISABLED); + break; + case TTK_COMPAT_STATE_ACTIVE: + SETFLAGS(TTK_STATE_ACTIVE); + break; + } +# undef SETFLAGS +} + +/* TtkSendVirtualEvent -- + * Send a virtual event notification to the specified target window. + * Equivalent to "event generate $tgtWindow <<$eventName>>" + * + * Note that we use Tk_QueueWindowEvent, not Tk_HandleEvent, + * so this routine does not reenter the interpreter. + */ +void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName) +{ + union {XEvent general; XVirtualEvent virtual;} event; + + memset(&event, 0, sizeof(event)); + event.general.xany.type = VirtualEvent; + event.general.xany.serial = NextRequest(Tk_Display(tgtWin)); + event.general.xany.send_event = False; + event.general.xany.window = Tk_WindowId(tgtWin); + event.general.xany.display = Tk_Display(tgtWin); + event.virtual.name = Tk_GetUid(eventName); + + Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL); +} + +/* TtkEnumerateOptions, TtkGetOptionValue -- + * Common factors for data accessor commands. + */ +int TtkEnumerateOptions( + Tcl_Interp *interp, void *recordPtr, const Tk_OptionSpec *specPtr, + Tk_OptionTable optionTable, Tk_Window tkwin) +{ + Tcl_Obj *result = Tcl_NewListObj(0,0); + while (specPtr->type != TK_OPTION_END) + { + Tcl_Obj *optionName = Tcl_NewStringObj(specPtr->optionName, -1); + Tcl_Obj *optionValue = + Tk_GetOptionValue(interp,recordPtr,optionTable,optionName,tkwin); + if (optionValue) { + Tcl_ListObjAppendElement(interp, result, optionName); + Tcl_ListObjAppendElement(interp, result, optionValue); + } + ++specPtr; + + if (specPtr->type == TK_OPTION_END && specPtr->clientData != NULL) { + /* Chain to next option spec array: */ + specPtr = specPtr->clientData; + } + } + Tcl_SetObjResult(interp, result); + return TCL_OK; +} + +int TtkGetOptionValue( + Tcl_Interp *interp, void *recordPtr, Tcl_Obj *optionName, + Tk_OptionTable optionTable, Tk_Window tkwin) +{ + Tcl_Obj *result = + Tk_GetOptionValue(interp,recordPtr,optionTable,optionName,tkwin); + if (result) { + Tcl_SetObjResult(interp, result); + return TCL_OK; + } + return TCL_ERROR; +} + + +/*------------------------------------------------------------------------ + * Core Option specifications: + * type name dbName dbClass default objOffset intOffset flags clientData mask + */ + +/* public */ +Tk_OptionSpec ttkCoreOptionSpecs[] = +{ + {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", NULL, + Tk_Offset(WidgetCore, cursorObj), -1, TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_STRING, "-style", "style", "Style", "", + Tk_Offset(WidgetCore,styleObj), -1, 0,0,STYLE_CHANGED}, + {TK_OPTION_STRING, "-class", "", "", NULL, + Tk_Offset(WidgetCore,classObj), -1, 0,0,READONLY_OPTION}, + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0} +}; + +/*------------------------------------------------------------------------ + * +++ Initialization: elements and element factories. + */ + +extern void TtkElements_Init(Tcl_Interp *); +extern void TtkLabel_Init(Tcl_Interp *); +extern void TtkImage_Init(Tcl_Interp *); + +static void RegisterElements(Tcl_Interp *interp) +{ + TtkElements_Init(interp); + TtkLabel_Init(interp); + TtkImage_Init(interp); +} + +/*------------------------------------------------------------------------ + * +++ Initialization: Widget definitions. + */ + +extern void TtkButton_Init(Tcl_Interp *); +extern void TtkEntry_Init(Tcl_Interp *); +extern void TtkFrame_Init(Tcl_Interp *); +extern void TtkNotebook_Init(Tcl_Interp *); +extern void TtkPanedwindow_Init(Tcl_Interp *); +extern void TtkProgressbar_Init(Tcl_Interp *); +extern void TtkScale_Init(Tcl_Interp *); +extern void TtkScrollbar_Init(Tcl_Interp *); +extern void TtkSeparator_Init(Tcl_Interp *); +extern void TtkTreeview_Init(Tcl_Interp *); + +#ifdef TTK_SQUARE_WIDGET +extern int TtkSquareWidget_Init(Tcl_Interp *); +#endif + +static void RegisterWidgets(Tcl_Interp *interp) +{ + TtkButton_Init(interp); + TtkEntry_Init(interp); + TtkFrame_Init(interp); + TtkNotebook_Init(interp); + TtkPanedwindow_Init(interp); + TtkProgressbar_Init(interp); + TtkScale_Init(interp); + TtkScrollbar_Init(interp); + TtkSeparator_Init(interp); + TtkTreeview_Init(interp); +#ifdef TTK_SQUARE_WIDGET + TtkSquareWidget_Init(interp); +#endif +} + +/*------------------------------------------------------------------------ + * +++ Initialization: Built-in themes. + */ + +extern int TtkAltTheme_Init(Tcl_Interp *); +extern int TtkClassicTheme_Init(Tcl_Interp *); +extern int TtkClamTheme_Init(Tcl_Interp *); + +static void RegisterThemes(Tcl_Interp *interp) +{ + + TtkAltTheme_Init(interp); + TtkClassicTheme_Init(interp); + TtkClamTheme_Init(interp); +} + +/* + * Ttk initialization. + */ + +extern const TtkStubs ttkStubs; + +MODULE_SCOPE int +Ttk_Init(Tcl_Interp *interp) +{ + /* + * This will be run for both safe and regular interp init. + * Use Tcl_IsSafe if necessary to not initialize unsafe bits. + */ + Ttk_StylePkgInit(interp); + + RegisterElements(interp); + RegisterWidgets(interp); + RegisterThemes(interp); + + Ttk_PlatformInit(interp); + + Tcl_PkgProvideEx(interp, "Ttk", TTK_PATCH_LEVEL, (ClientData)&ttkStubs); + + return TCL_OK; +} + +/*EOF*/ diff --git a/generic/ttk/ttkLabel.c b/generic/ttk/ttkLabel.c new file mode 100644 index 0000000..0f773e7 --- /dev/null +++ b/generic/ttk/ttkLabel.c @@ -0,0 +1,670 @@ +/* + * text, image, and label elements. + * + * The label element combines text and image elements, + * with layout determined by the "-compound" option. + * + */ + +#include <tcl.h> +#include <tk.h> +#include "ttkTheme.h" + +/*---------------------------------------------------------------------- + * +++ Text element. + * + * This element displays a textual label in the foreground color. + * + * Optionally underlines the mnemonic character if the -underline resource + * is present and >= 0. + */ + +typedef struct { + /* + * Element options: + */ + Tcl_Obj *textObj; + Tcl_Obj *fontObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *underlineObj; + Tcl_Obj *widthObj; + Tcl_Obj *anchorObj; + Tcl_Obj *justifyObj; + Tcl_Obj *wrapLengthObj; + Tcl_Obj *embossedObj; + + /* + * Computed resources: + */ + Tk_Font tkfont; + Tk_TextLayout textLayout; + int width; + int height; + int embossed; + +} TextElement; + +/* Text element options table. + * NB: Keep in sync with label element option table. + */ +static Ttk_ElementOptionSpec TextElementOptions[] = { + { "-text", TK_OPTION_STRING, + Tk_Offset(TextElement,textObj), "" }, + { "-font", TK_OPTION_FONT, + Tk_Offset(TextElement,fontObj), DEFAULT_FONT }, + { "-foreground", TK_OPTION_COLOR, + Tk_Offset(TextElement,foregroundObj), "black" }, + { "-underline", TK_OPTION_INT, + Tk_Offset(TextElement,underlineObj), "-1"}, + { "-width", TK_OPTION_INT, + Tk_Offset(TextElement,widthObj), "-1"}, + { "-anchor", TK_OPTION_ANCHOR, + Tk_Offset(TextElement,anchorObj), "w"}, + { "-justify", TK_OPTION_JUSTIFY, + Tk_Offset(TextElement,justifyObj), "left" }, + { "-wraplength", TK_OPTION_PIXELS, + Tk_Offset(TextElement,wrapLengthObj), "0" }, + { "-embossed", TK_OPTION_INT, + Tk_Offset(TextElement,embossedObj), "0"}, + { NULL, 0, 0, NULL } +}; + +static int TextSetup(TextElement *text, Tk_Window tkwin) +{ + const char *string = Tcl_GetString(text->textObj); + Tk_Justify justify = TK_JUSTIFY_LEFT; + int wrapLength = 0; + + text->tkfont = Tk_GetFontFromObj(tkwin, text->fontObj); + Tk_GetJustifyFromObj(NULL, text->justifyObj, &justify); + Tk_GetPixelsFromObj(NULL, tkwin, text->wrapLengthObj, &wrapLength); + Tcl_GetBooleanFromObj(NULL, text->embossedObj, &text->embossed); + + text->textLayout = Tk_ComputeTextLayout( + text->tkfont, string, -1/*numChars*/, wrapLength, justify, + 0/*flags*/, &text->width, &text->height); + + return 1; +} + +/* + * TextReqWidth -- compute the requested width of a text element. + * + * If -width is positive, use that as the width + * If -width is negative, use that as the minimum width + * If not specified or empty, use the natural size of the text + */ + +static int TextReqWidth(TextElement *text) +{ + int reqWidth; + + if ( text->widthObj + && Tcl_GetIntFromObj(NULL, text->widthObj, &reqWidth) == TCL_OK) + { + int avgWidth = Tk_TextWidth(text->tkfont, "0", 1); + if (reqWidth <= 0) { + int specWidth = avgWidth * -reqWidth; + if (specWidth > text->width) + return specWidth; + } else { + return avgWidth * reqWidth; + } + } + return text->width; +} + +static void TextCleanup(TextElement *text) +{ + Tk_FreeTextLayout(text->textLayout); +} + +/* + * TextDraw -- + * Draw a text element. + * Called by TextElementDraw() and LabelElementDraw(). + */ +static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) +{ + XColor *color = Tk_GetColorFromObj(tkwin, text->foregroundObj); + int underline = -1; + int lastChar = -1; + XGCValues gcValues; + GC gc1, gc2; + Tk_Anchor anchor = TK_ANCHOR_CENTER; + + gcValues.font = Tk_FontId(text->tkfont); + gcValues.foreground = color->pixel; + gc1 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); + gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin)); + gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); + + /* + * Place text according to -anchor: + */ + Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor); + b = Ttk_AnchorBox(b, text->width, text->height, anchor); + + /* + * Clip text if it's too wide: + * @@@ BUG: This will overclip multi-line text. + */ + if (b.width < text->width) { + lastChar = Tk_PointToChar(text->textLayout, b.width, 1) + 1; + } + + if (text->embossed) { + Tk_DrawTextLayout(Tk_Display(tkwin), d, gc2, + text->textLayout, b.x+1, b.y+1, 0/*firstChar*/, lastChar); + } + Tk_DrawTextLayout(Tk_Display(tkwin), d, gc1, + text->textLayout, b.x, b.y, 0/*firstChar*/, lastChar); + + Tcl_GetIntFromObj(NULL, text->underlineObj, &underline); + if (underline >= 0 && (lastChar == -1 || underline <= lastChar)) { + if (text->embossed) { + Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc2, + text->textLayout, b.x+1, b.y+1, underline); + } + Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc1, + text->textLayout, b.x, b.y, underline); + } + + Tk_FreeGC(Tk_Display(tkwin), gc1); + Tk_FreeGC(Tk_Display(tkwin), gc2); +} + +static void TextElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TextElement *text = elementRecord; + + if (!TextSetup(text, tkwin)) + return; + + *heightPtr = text->height; + *widthPtr = TextReqWidth(text); + + TextCleanup(text); + + return; +} + +static void TextElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + TextElement *text = elementRecord; + if (TextSetup(text, tkwin)) { + TextDraw(text, tkwin, d, b); + TextCleanup(text); + } +} + +static Ttk_ElementSpec TextElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TextElement), + TextElementOptions, + TextElementSize, + TextElementDraw +}; + +/*---------------------------------------------------------------------- + * +++ Image element. + * Draws an image. + */ + +typedef struct { + Tcl_Obj *imageObj; + Tcl_Obj *stippleObj; /* For TTK_STATE_DISABLED */ + Tcl_Obj *backgroundObj; /* " " */ + + Ttk_ImageSpec *imageSpec; + Tk_Image tkimg; + int width; + int height; +} ImageElement; + +/* ===> NB: Keep in sync with label element option table. <=== + */ +static Ttk_ElementOptionSpec ImageElementOptions[] = { + { "-image", TK_OPTION_STRING, + Tk_Offset(ImageElement,imageObj), "" }, + { "-stipple", TK_OPTION_STRING, /* Really: TK_OPTION_BITMAP */ + Tk_Offset(ImageElement,stippleObj), "gray50" }, + { "-background", TK_OPTION_COLOR, + Tk_Offset(ImageElement,backgroundObj), DEFAULT_BACKGROUND }, + { NULL, 0, 0, NULL } +}; + +/* + * ImageSetup() -- + * Look up the Tk_Image from the image element's imageObj resource. + * Caller must release the image with ImageCleanup(). + * + * Returns: + * 1 if successful, 0 if there was an error (unreported) + * or the image resource was not specified. + */ + +static int ImageSetup( + ImageElement *image, Tk_Window tkwin, Ttk_State state) +{ + + if (!image->imageObj) { + return 0; + } + image->imageSpec = TtkGetImageSpec(NULL, tkwin, image->imageObj); + if (!image->imageSpec) { + return 0; + } + image->tkimg = TtkSelectImage(image->imageSpec, state); + if (!image->tkimg) { + TtkFreeImageSpec(image->imageSpec); + return 0; + } + Tk_SizeOfImage(image->tkimg, &image->width, &image->height); + + return 1; +} + +static void ImageCleanup(ImageElement *image) +{ + TtkFreeImageSpec(image->imageSpec); +} + +/* + * StippleOver -- + * Draw a stipple over the image area, to make it look "grayed-out" + * when TTK_STATE_DISABLED is set. + */ +static void StippleOver( + ImageElement *image, Tk_Window tkwin, Drawable d, int x, int y) +{ + Pixmap stipple = Tk_AllocBitmapFromObj(NULL, tkwin, image->stippleObj); + XColor *color = Tk_GetColorFromObj(tkwin, image->backgroundObj); + + if (stipple != None) { + unsigned long mask = GCFillStyle | GCStipple | GCForeground; + XGCValues gcvalues; + GC gc; + gcvalues.foreground = color->pixel; + gcvalues.fill_style = FillStippled; + gcvalues.stipple = stipple; + gc = Tk_GetGC(tkwin, mask, &gcvalues); + XFillRectangle(Tk_Display(tkwin),d,gc,x,y,image->width,image->height); + Tk_FreeGC(Tk_Display(tkwin), gc); + Tk_FreeBitmapFromObj(tkwin, image->stippleObj); + } +} + +static void ImageDraw( + ImageElement *image, Tk_Window tkwin,Drawable d,Ttk_Box b,Ttk_State state) +{ + int width = image->width, height = image->height; + + /* Clip width and height to remain within window bounds: + */ + if (b.x + width > Tk_Width(tkwin)) { + width = Tk_Width(tkwin) - b.x; + } + if (b.y + height > Tk_Height(tkwin)) { + height = Tk_Height(tkwin) - b.y; + } + + if (height <= 0 || width <= 0) { + /* Completely clipped - bail out. + */ + return; + } + + Tk_RedrawImage(image->tkimg, 0,0, width, height, d, b.x, b.y); + + /* If we're disabled there's no state-specific 'disabled' image, + * stipple the image. + * @@@ Possibly: Don't do disabled-stippling at all; + * @@@ it's ugly and out of fashion. + */ + if (state & TTK_STATE_DISABLED) { + if (TtkSelectImage(image->imageSpec, 0ul) == image->tkimg) { + StippleOver(image, tkwin, d, b.x,b.y); + } + } +} + +static void ImageElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + ImageElement *image = elementRecord; + + if (ImageSetup(image, tkwin, 0)) { + *widthPtr = image->width; + *heightPtr = image->height; + ImageCleanup(image); + } +} + +static void ImageElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + ImageElement *image = elementRecord; + + if (ImageSetup(image, tkwin, state)) { + ImageDraw(image, tkwin, d, b, state); + ImageCleanup(image); + } +} + +static Ttk_ElementSpec ImageElementSpec = { + TK_STYLE_VERSION_2, + sizeof(ImageElement), + ImageElementOptions, + ImageElementSize, + ImageElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Label element. + * + * Displays an image and/or text, as determined by the -compound option. + * + * Differences from Tk 8.4 compound elements: + * + * This adds two new values for the -compound option, "text" + * and "image". (This is useful for configuring toolbars to + * display icons, text and icons, or text only, as found in + * many browsers.) + * + * "-compound none" is supported, but I'd like to get rid of it; + * it makes the logic more complex, and the only benefit is + * backwards compatibility with Tk < 8.3.0 scripts. + * + * This adds a new resource, -space, for determining how much + * space to leave between the text and image; Tk 8.4 reuses the + * -padx or -pady option for this purpose. + * + * -width always specifies the length in characters of the text part; + * in Tk 8.4 it's either characters or pixels, depending on the + * value of -compound. + * + * Negative values of -width are interpreted as a minimum width + * on all platforms, not just on Windows. + * + * Tk 8.4 ignores -padx and -pady if -compound is set to "none". + * Here, padding is handled by a different element. + */ + +typedef struct { + /* + * Element options: + */ + Tcl_Obj *compoundObj; + Tcl_Obj *spaceObj; + TextElement text; + ImageElement image; + + /* + * Computed values (see LabelSetup) + */ + Ttk_Compound compound; + int space; + int totalWidth, totalHeight; +} LabelElement; + +static Ttk_ElementOptionSpec LabelElementOptions[] = { + { "-compound", TK_OPTION_ANY, + Tk_Offset(LabelElement,compoundObj), "none" }, + { "-space", TK_OPTION_PIXELS, + Tk_Offset(LabelElement,spaceObj), "4" }, + + /* Text element part: + * NB: Keep in sync with TextElementOptions. + */ + { "-text", TK_OPTION_STRING, + Tk_Offset(LabelElement,text.textObj), "" }, + { "-font", TK_OPTION_FONT, + Tk_Offset(LabelElement,text.fontObj), DEFAULT_FONT }, + { "-foreground", TK_OPTION_COLOR, + Tk_Offset(LabelElement,text.foregroundObj), "black" }, + { "-underline", TK_OPTION_INT, + Tk_Offset(LabelElement,text.underlineObj), "-1"}, + { "-width", TK_OPTION_INT, + Tk_Offset(LabelElement,text.widthObj), ""}, + { "-anchor", TK_OPTION_ANCHOR, + Tk_Offset(LabelElement,text.anchorObj), "w"}, + { "-justify", TK_OPTION_JUSTIFY, + Tk_Offset(LabelElement,text.justifyObj), "left" }, + { "-wraplength", TK_OPTION_PIXELS, + Tk_Offset(LabelElement,text.wrapLengthObj), "0" }, + { "-embossed", TK_OPTION_INT, + Tk_Offset(LabelElement,text.embossedObj), "0"}, + + /* Image element part: + * NB: Keep in sync with ImageElementOptions. + */ + { "-image", TK_OPTION_STRING, + Tk_Offset(LabelElement,image.imageObj), "" }, + { "-stipple", TK_OPTION_STRING, /* Really: TK_OPTION_BITMAP */ + Tk_Offset(LabelElement,image.stippleObj), "gray50" }, + { "-background", TK_OPTION_COLOR, + Tk_Offset(LabelElement,image.backgroundObj), DEFAULT_BACKGROUND }, + { NULL, 0, 0, NULL } +}; + +/* + * LabelSetup -- + * Fills in computed fields of the label element. + * + * Calculate the text, image, and total width and height. + */ + +#define MAX(a,b) ((a) > (b) ? a : b); +static void LabelSetup( + LabelElement *c, Tk_Window tkwin, Ttk_State state) +{ + Ttk_Compound *compoundPtr = &c->compound; + + Tk_GetPixelsFromObj(NULL,tkwin,c->spaceObj,&c->space); + Ttk_GetCompoundFromObj(NULL,c->compoundObj,(int*)compoundPtr); + + /* + * Deal with TTK_COMPOUND_NONE. + */ + if (c->compound == TTK_COMPOUND_NONE) { + if (ImageSetup(&c->image, tkwin, state)) { + c->compound = TTK_COMPOUND_IMAGE; + } else { + c->compound = TTK_COMPOUND_TEXT; + } + } else if (c->compound != TTK_COMPOUND_TEXT) { + if (!ImageSetup(&c->image, tkwin, state)) { + c->compound = TTK_COMPOUND_TEXT; + } + } + if (c->compound != TTK_COMPOUND_IMAGE) + TextSetup(&c->text, tkwin); + + /* + * ASSERT: + * if c->compound != IMAGE, then TextSetup() has been called + * if c->compound != TEXT, then ImageSetup() has returned successfully + * c->compound != COMPOUND_NONE. + */ + + switch (c->compound) + { + case TTK_COMPOUND_NONE: + /* Can't happen */ + break; + case TTK_COMPOUND_TEXT: + c->totalWidth = c->text.width; + c->totalHeight = c->text.height; + break; + case TTK_COMPOUND_IMAGE: + c->totalWidth = c->image.width; + c->totalHeight = c->image.height; + break; + case TTK_COMPOUND_CENTER: + c->totalWidth = MAX(c->image.width, c->text.width); + c->totalHeight = MAX(c->image.height, c->text.height); + break; + case TTK_COMPOUND_TOP: + case TTK_COMPOUND_BOTTOM: + c->totalWidth = MAX(c->image.width, c->text.width); + c->totalHeight = c->image.height + c->text.height + c->space; + break; + + case TTK_COMPOUND_LEFT: + case TTK_COMPOUND_RIGHT: + c->totalWidth = c->image.width + c->text.width + c->space; + c->totalHeight = MAX(c->image.height, c->text.height); + break; + } +} + +static void LabelCleanup(LabelElement *c) +{ + if (c->compound != TTK_COMPOUND_TEXT) + ImageCleanup(&c->image); + if (c->compound != TTK_COMPOUND_IMAGE) + TextCleanup(&c->text); +} + +static void LabelElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + LabelElement *label = elementRecord; + int textReqWidth = 0; + + LabelSetup(label, tkwin, 0); + + *heightPtr = label->totalHeight; + + /* Requested width based on -width option, not actual text width: + */ + if (label->compound != TTK_COMPOUND_IMAGE) + textReqWidth = TextReqWidth(&label->text); + + switch (label->compound) + { + case TTK_COMPOUND_TEXT: + *widthPtr = textReqWidth; + break; + case TTK_COMPOUND_IMAGE: + *widthPtr = label->image.width; + break; + case TTK_COMPOUND_TOP: + case TTK_COMPOUND_BOTTOM: + case TTK_COMPOUND_CENTER: + *widthPtr = MAX(label->image.width, textReqWidth); + break; + case TTK_COMPOUND_LEFT: + case TTK_COMPOUND_RIGHT: + *widthPtr = label->image.width + textReqWidth + label->space; + break; + case TTK_COMPOUND_NONE: + break; /* Can't happen */ + } + + LabelCleanup(label); +} + +/* + * DrawCompound -- + * Helper routine for LabelElementDraw; + * Handles layout for -compound {left,right,top,bottom} + */ +static void DrawCompound( + LabelElement *l, Ttk_Box b, Tk_Window tkwin, Drawable d, Ttk_State state, + int imageSide, int textSide) +{ + Ttk_Box imageBox = + Ttk_PlaceBox(&b, l->image.width, l->image.height, imageSide, 0); + Ttk_Box textBox = + Ttk_PlaceBox(&b, l->text.width, l->text.height, textSide, 0); + ImageDraw(&l->image,tkwin,d,imageBox,state); + TextDraw(&l->text,tkwin,d,textBox); +} + +static void LabelElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + LabelElement *l = elementRecord; + Tk_Anchor anchor = TK_ANCHOR_CENTER; + + LabelSetup(l, tkwin, state); + + /* + * Adjust overall parcel based on -anchor: + */ + Tk_GetAnchorFromObj(NULL, l->text.anchorObj, &anchor); + b = Ttk_AnchorBox(b, l->totalWidth, l->totalHeight, anchor); + + /* + * Draw text and/or image parts based on -compound: + */ + switch (l->compound) + { + case TTK_COMPOUND_NONE: + /* Can't happen */ + break; + case TTK_COMPOUND_TEXT: + TextDraw(&l->text,tkwin,d,b); + break; + case TTK_COMPOUND_IMAGE: + ImageDraw(&l->image,tkwin,d,b,state); + break; + case TTK_COMPOUND_CENTER: + { + Ttk_Box pb = Ttk_AnchorBox( + b, l->image.width, l->image.height, TK_ANCHOR_CENTER); + ImageDraw(&l->image, tkwin, d, pb, state); + pb = Ttk_AnchorBox( + b, l->text.width, l->text.height, TK_ANCHOR_CENTER); + TextDraw(&l->text, tkwin, d, pb); + break; + } + case TTK_COMPOUND_TOP: + DrawCompound(l, b, tkwin, d, state, TTK_SIDE_TOP, TTK_SIDE_BOTTOM); + break; + case TTK_COMPOUND_BOTTOM: + DrawCompound(l, b, tkwin, d, state, TTK_SIDE_BOTTOM, TTK_SIDE_TOP); + break; + case TTK_COMPOUND_LEFT: + DrawCompound(l, b, tkwin, d, state, TTK_SIDE_LEFT, TTK_SIDE_RIGHT); + break; + case TTK_COMPOUND_RIGHT: + DrawCompound(l, b, tkwin, d, state, TTK_SIDE_RIGHT, TTK_SIDE_LEFT); + break; + } + + LabelCleanup(l); +} + +static Ttk_ElementSpec LabelElementSpec = { + TK_STYLE_VERSION_2, + sizeof(LabelElement), + LabelElementOptions, + LabelElementSize, + LabelElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Initialization. + */ + +MODULE_SCOPE +void TtkLabel_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterElement(interp, theme, "text", &TextElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "image", &ImageElementSpec, NULL); + Ttk_RegisterElement(interp, theme, "label", &LabelElementSpec, NULL); +} + diff --git a/generic/ttk/ttkLayout.c b/generic/ttk/ttkLayout.c new file mode 100644 index 0000000..58c99eb --- /dev/null +++ b/generic/ttk/ttkLayout.c @@ -0,0 +1,1252 @@ +/* + * ttkLayout.c -- + * + * Generic layout processing. + * + * Copyright (c) 2003 Joe English. Freely redistributable. + */ + +#include <string.h> +#include <tk.h> +#include "ttkThemeInt.h" + +#define MAX(a,b) (a > b ? a : b) +#define MIN(a,b) (a < b ? a : b) + +/*------------------------------------------------------------------------ + * +++ Ttk_Box and Ttk_Padding utilities: + */ + +Ttk_Box +Ttk_MakeBox(int x, int y, int width, int height) +{ + Ttk_Box b; + b.x = x; b.y = y; b.width = width; b.height = height; + return b; +} + +int +Ttk_BoxContains(Ttk_Box box, int x, int y) +{ + return box.x <= x && x < box.x + box.width + && box.y <= y && y < box.y + box.height; +} + +Tcl_Obj * +Ttk_NewBoxObj(Ttk_Box box) +{ + Tcl_Obj *result[4]; + + result[0] = Tcl_NewIntObj(box.x); + result[1] = Tcl_NewIntObj(box.y); + result[2] = Tcl_NewIntObj(box.width); + result[3] = Tcl_NewIntObj(box.height); + + return Tcl_NewListObj(4, result); +} + +/* + * packTop, packBottom, packLeft, packRight -- + * Carve out a parcel of the specified height (resp width) + * from the specified cavity. + * + * Returns: + * The new parcel. + * + * Side effects: + * Adjust the cavity. + */ + +static Ttk_Box packTop(Ttk_Box *cavity, int height) +{ + Ttk_Box parcel; + height = MIN(height, cavity->height); + parcel = Ttk_MakeBox(cavity->x, cavity->y, cavity->width, height); + cavity->y += height; + cavity->height -= height; + return parcel; +} + +static Ttk_Box packBottom(Ttk_Box *cavity, int height) +{ + height = MIN(height, cavity->height); + cavity->height -= height; + return Ttk_MakeBox( + cavity->x, cavity->y + cavity->height, + cavity->width, height); +} + +static Ttk_Box packLeft(Ttk_Box *cavity, int width) +{ + Ttk_Box parcel; + width = MIN(width, cavity->width); + parcel = Ttk_MakeBox(cavity->x, cavity->y, width,cavity->height); + cavity->x += width; + cavity->width -= width; + return parcel; +} + +static Ttk_Box packRight(Ttk_Box *cavity, int width) +{ + width = MIN(width, cavity->width); + cavity->width -= width; + return Ttk_MakeBox(cavity->x + cavity->width, + cavity->y, width, cavity->height); +} + +/* + * Ttk_PackBox -- + * Carve out a parcel of the specified size on the specified side + * in the specified cavity. + * + * Returns: + * The new parcel. + * + * Side effects: + * Adjust the cavity. + */ + +Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int width, int height, Ttk_Side side) +{ + switch (side) { + default: + case TTK_SIDE_TOP: return packTop(cavity, height); + case TTK_SIDE_BOTTOM: return packBottom(cavity, height); + case TTK_SIDE_LEFT: return packLeft(cavity, width); + case TTK_SIDE_RIGHT: return packRight(cavity, width); + } +} + +/* + * Ttk_PadBox -- + * Shrink a box by the specified padding amount. + */ +Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p) +{ + b.x += p.left; + b.y += p.top; + b.width -= (p.left + p.right); + b.height -= (p.top + p.bottom); + if (b.width <= 0) b.width = 1; + if (b.height <= 0) b.height = 1; + return b; +} + +/* + * Ttk_ExpandBox -- + * Grow a box by the specified padding amount. + */ +Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p) +{ + b.x -= p.left; + b.y -= p.top; + b.width += (p.left + p.right); + b.height += (p.top + p.bottom); + return b; +} + +/* + * Ttk_StickBox -- + * Place a box of size w * h in the specified parcel, + * according to the specified sticky bits. + */ +Ttk_Box Ttk_StickBox(Ttk_Box parcel, int width, int height, unsigned sticky) +{ + int dx, dy; + + if (width > parcel.width) width = parcel.width; + if (height > parcel.height) height = parcel.height; + + dx = parcel.width - width; + dy = parcel.height - height; + + /* + * X coordinate adjustment: + */ + switch (sticky & (TTK_STICK_W | TTK_STICK_E)) + { + case TTK_STICK_W | TTK_STICK_E: + /* no-op -- use entire parcel width */ + break; + case TTK_STICK_W: + parcel.width = width; + break; + case TTK_STICK_E: + parcel.x += dx; + parcel.width = width; + break; + default : + parcel.x += dx / 2; + parcel.width = width; + break; + } + + /* + * Y coordinate adjustment: + */ + switch (sticky & (TTK_STICK_N | TTK_STICK_S)) + { + case TTK_STICK_N | TTK_STICK_S: + /* use entire parcel height */ + break; + case TTK_STICK_N: + parcel.height = height; + break; + case TTK_STICK_S: + parcel.y += dy; + parcel.height = height; + break; + default : + parcel.y += dy / 2; + parcel.height = height; + break; + } + + return parcel; +} + +/* + * AnchorToSticky -- + * Convert a Tk_Anchor enum to a TTK_STICKY bitmask. + */ +static Ttk_Sticky AnchorToSticky(Tk_Anchor anchor) +{ + switch (anchor) + { + case TK_ANCHOR_N: return TTK_STICK_N; + case TK_ANCHOR_NE: return TTK_STICK_N | TTK_STICK_E; + case TK_ANCHOR_E: return TTK_STICK_E; + case TK_ANCHOR_SE: return TTK_STICK_S | TTK_STICK_E; + case TK_ANCHOR_S: return TTK_STICK_S; + case TK_ANCHOR_SW: return TTK_STICK_S | TTK_STICK_W; + case TK_ANCHOR_W: return TTK_STICK_W; + case TK_ANCHOR_NW: return TTK_STICK_N | TTK_STICK_W; + default: + case TK_ANCHOR_CENTER: return 0; + } +} + +/* + * Ttk_AnchorBox -- + * Place a box of size w * h in the specified parcel, + * according to the specified anchor. + */ +Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int width, int height, Tk_Anchor anchor) +{ + return Ttk_StickBox(parcel, width, height, AnchorToSticky(anchor)); +} + +/* + * Ttk_PlaceBox -- + * Combine Ttk_PackBox() and Ttk_StickBox(). + */ +Ttk_Box Ttk_PlaceBox( + Ttk_Box *cavity, int width, int height, Ttk_Side side, unsigned sticky) +{ + return Ttk_StickBox( + Ttk_PackBox(cavity, width, height, side), width, height, sticky); +} + +/* + * Ttk_PositionBox -- + * Pack and stick a box according to PositionSpec flags. + */ +MODULE_SCOPE Ttk_Box +Ttk_PositionBox(Ttk_Box *cavity, int width, int height, Ttk_PositionSpec flags) +{ + Ttk_Box parcel; + + if (flags & TTK_EXPAND) parcel = *cavity; + else if (flags & TTK_PACK_TOP) parcel = packTop(cavity, height); + else if (flags & TTK_PACK_LEFT) parcel = packLeft(cavity, width); + else if (flags & TTK_PACK_BOTTOM) parcel = packBottom(cavity, height); + else if (flags & TTK_PACK_RIGHT) parcel = packRight(cavity, width); + else parcel = *cavity; + + return Ttk_StickBox(parcel, width, height, flags); +} + +/* + * TTKInitPadding -- + * Common factor of Ttk_GetPaddingFromObj and Ttk_GetBorderFromObj. + * Initializes Ttk_Padding record, supplying default values + * for missing entries. + */ +static void TTKInitPadding(int padc, int pixels[4], Ttk_Padding *pad) +{ + switch (padc) + { + case 0: pixels[0] = 0; /*FALLTHRU*/ + case 1: pixels[1] = pixels[0]; /*FALLTHRU*/ + case 2: pixels[2] = pixels[0]; /*FALLTHRU*/ + case 3: pixels[3] = pixels[1]; /*FALLTHRU*/ + } + + pad->left = (short)pixels[0]; + pad->top = (short)pixels[1]; + pad->right = (short)pixels[2]; + pad->bottom = (short)pixels[3]; +} + +/* + * Ttk_GetPaddingFromObj -- + * + * Extract a padding specification from a Tcl_Obj * scaled + * to work with a particular Tk_Window. + * + * The string representation of a Ttk_Padding is a list + * of one to four Tk_Pixel specifications, corresponding + * to the left, top, right, and bottom padding. + * + * If the 'bottom' (fourth) element is missing, it defaults to 'top'. + * If the 'right' (third) element is missing, it defaults to 'left'. + * If the 'top' (second) element is missing, it defaults to 'left'. + * + * The internal representation is a Tcl_ListObj containing + * one to four Tk_PixelObj objects. + * + * Returns: + * TCL_OK or TCL_ERROR. In the latter case an error message is + * left in 'interp' and '*paddingPtr' is set to all-zeros. + * Otherwise, *paddingPtr is filled in with the padding specification. + * + */ +int Ttk_GetPaddingFromObj( + Tcl_Interp *interp, + Tk_Window tkwin, + Tcl_Obj *objPtr, + Ttk_Padding *pad) +{ + Tcl_Obj **padv; + int i, padc, pixels[4]; + + if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) { + goto error; + } + + if (padc > 4) { + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Wrong #elements in padding spec", NULL); + } + goto error; + } + + for (i=0; i < padc; ++i) { + if (Tk_GetPixelsFromObj(interp, tkwin, padv[i], &pixels[i]) != TCL_OK) { + goto error; + } + } + + TTKInitPadding(padc, pixels, pad); + return TCL_OK; + +error: + pad->left = pad->top = pad->right = pad->bottom = 0; + return TCL_ERROR; +} + +/* Ttk_GetBorderFromObj -- + * Same as Ttk_GetPaddingFromObj, except padding is a list of integers + * instead of Tk_Pixel specifications. Does not require a Tk_Window + * parameter. + * + */ +int Ttk_GetBorderFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Padding *pad) +{ + Tcl_Obj **padv; + int i, padc, pixels[4]; + + if (TCL_OK != Tcl_ListObjGetElements(interp, objPtr, &padc, &padv)) { + goto error; + } + + if (padc > 4) { + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Wrong #elements in border spec", NULL); + } + goto error; + } + + for (i=0; i < padc; ++i) { + if (Tcl_GetIntFromObj(interp, padv[i], &pixels[i]) != TCL_OK) { + goto error; + } + } + + TTKInitPadding(padc, pixels, pad); + return TCL_OK; + +error: + pad->left = pad->top = pad->right = pad->bottom = 0; + return TCL_ERROR; +} + +/* + * Ttk_MakePadding -- + * Return an initialized Ttk_Padding structure. + */ +Ttk_Padding Ttk_MakePadding(short left, short top, short right, short bottom) +{ + Ttk_Padding pad; + pad.left = left; + pad.top = top; + pad.right = right; + pad.bottom = bottom; + return pad; +} + +/* + * Ttk_UniformPadding -- + * Returns a uniform Ttk_Padding structure, with the same + * border width on all sides. + */ +Ttk_Padding Ttk_UniformPadding(short borderWidth) +{ + Ttk_Padding pad; + pad.left = pad.top = pad.right = pad.bottom = borderWidth; + return pad; +} + +/* + * Ttk_AddPadding -- + * Combine two padding records. + */ +Ttk_Padding Ttk_AddPadding(Ttk_Padding p1, Ttk_Padding p2) +{ + p1.left += p2.left; + p1.top += p2.top; + p1.right += p2.right; + p1.bottom += p2.bottom; + return p1; +} + +/* Ttk_RelievePadding -- + * Add an extra n pixels of padding according to specified relief. + * This may be used in element geometry procedures to simulate + * a "pressed-in" look for pushbuttons. + */ +Ttk_Padding Ttk_RelievePadding(Ttk_Padding padding, int relief, int n) +{ + switch (relief) + { + case TK_RELIEF_RAISED: + padding.right += n; + padding.bottom += n; + break; + case TK_RELIEF_SUNKEN: /* shift */ + padding.left += n; + padding.top += n; + break; + default: + { + int h1 = n/2, h2 = h1 + n % 2; + padding.left += h1; + padding.top += h1; + padding.right += h2; + padding.bottom += h2; + break; + } + } + return padding; +} + +/* + * Ttk_GetStickyFromObj -- + * Returns a stickiness specification from the specified Tcl_Obj*, + * consisting of any combination of n, s, e, and w. + * + * Returns: TCL_OK if objPtr holds a valid stickiness specification, + * otherwise TCL_ERROR. interp is used for error reporting if non-NULL. + * + */ +int Ttk_GetStickyFromObj( + Tcl_Interp *interp, Tcl_Obj *objPtr, Ttk_Sticky *result) +{ + const char *string = Tcl_GetString(objPtr); + Ttk_Sticky sticky = 0; + char c; + + while ((c = *string++) != '\0') { + switch (c) { + case 'w': case 'W': sticky |= TTK_STICK_W; break; + case 'e': case 'E': sticky |= TTK_STICK_E; break; + case 'n': case 'N': sticky |= TTK_STICK_N; break; + case 's': case 'S': sticky |= TTK_STICK_S; break; + default: + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Bad -sticky specification ", + Tcl_GetString(objPtr), + NULL); + } + return TCL_ERROR; + } + } + + *result = sticky; + return TCL_OK; +} + +/* Ttk_NewStickyObj -- + * Construct a new Tcl_Obj * containing a stickiness specification. + */ +Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky sticky) +{ + char buf[5]; + char *p = buf; + + if (sticky & TTK_STICK_N) *p++ = 'n'; + if (sticky & TTK_STICK_S) *p++ = 's'; + if (sticky & TTK_STICK_W) *p++ = 'w'; + if (sticky & TTK_STICK_E) *p++ = 'e'; + + *p = '\0'; + return Tcl_NewStringObj(buf, p - buf); +} + +/*------------------------------------------------------------------------ + * +++ Layout nodes. + */ + +typedef struct Ttk_LayoutNode_ Ttk_LayoutNode; +struct Ttk_LayoutNode_ +{ + unsigned flags; /* Packing and sticky flags */ + Ttk_ElementClass *eclass; /* Class record */ + Ttk_State state; /* Current state */ + Ttk_Box parcel; /* allocated parcel */ + Ttk_LayoutNode *next, *child; +}; + +static Ttk_LayoutNode *Ttk_NewLayoutNode( + unsigned flags, Ttk_ElementClass *elementClass) +{ + Ttk_LayoutNode *node = (Ttk_LayoutNode*)ckalloc(sizeof(*node)); + + node->flags = flags; + node->eclass = elementClass; + node->state = 0u; + node->next = node->child = 0; + node->parcel = Ttk_MakeBox(0,0,0,0); + + return node; +} + +static void Ttk_FreeLayoutNode(Ttk_LayoutNode *node) +{ + while (node) { + Ttk_LayoutNode *next = node->next; + Ttk_FreeLayoutNode(node->child); + ckfree((ClientData)node); + node = next; + } +} + +/*------------------------------------------------------------------------ + * +++ Layout templates. + */ + +struct Ttk_TemplateNode_ { + char *name; + unsigned flags; + struct Ttk_TemplateNode_ *next, *child; +}; + +static Ttk_TemplateNode *Ttk_NewTemplateNode(const char *name, unsigned flags) +{ + Ttk_TemplateNode *op = (Ttk_TemplateNode*)ckalloc(sizeof(*op)); + op->name = ckalloc(strlen(name) + 1); strcpy(op->name, name); + op->flags = flags; + op->next = op->child = 0; + return op; +} + +void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate op) +{ + while (op) { + Ttk_LayoutTemplate next = op->next; + Ttk_FreeLayoutTemplate(op->child); + ckfree(op->name); + ckfree((ClientData)op); + op = next; + } +} + +/* InstantiateLayout -- + * Create a layout tree from a template. + */ +static Ttk_LayoutNode * +Ttk_InstantiateLayout(Ttk_Theme theme, Ttk_TemplateNode *op) +{ + Ttk_ElementClass *elementClass = Ttk_GetElement(theme, op->name); + Ttk_LayoutNode *node = Ttk_NewLayoutNode(op->flags, elementClass); + + if (op->next) { + node->next = Ttk_InstantiateLayout(theme,op->next); + } + if (op->child) { + node->child = Ttk_InstantiateLayout(theme,op->child); + } + + return node; +} + +/* + * Ttk_ParseLayoutTemplate -- + * Convert a Tcl list into a layout template. + * + * Syntax: + * layoutSpec ::= { elementName ?-option value ...? }+ + */ + +/* NB: This must match bit definitions TTK_PACK_LEFT etc. */ +static const char *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[] = { + "-side", "-sticky", "-expand", "-border", "-unit", "-children", 0 }; + + int i = 0, objc; + Tcl_Obj **objv; + Ttk_TemplateNode *head = 0, *tail = 0; + + if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) + return 0; + + while (i < objc) { + const char *elementName = Tcl_GetString(objv[i]); + unsigned flags = 0x0, sticky = TTK_FILL_BOTH; + Tcl_Obj *childSpec = 0; + + /* + * Parse options: + */ + ++i; + while (i < objc) { + const char *optName = Tcl_GetString(objv[i]); + int option, value; + + if (optName[0] != '-') + break; + + if (Tcl_GetIndexFromObj( + interp, objv[i], optStrings, "option", 0, &option) + != TCL_OK) + { + goto error; + } + + if (++i >= objc) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Missing value for option ",Tcl_GetString(objv[i-1]), + NULL); + goto error; + } + + switch (option) { + case OP_SIDE: /* <<NOTE-PACKSIDE>> */ + if (Tcl_GetIndexFromObj(interp, objv[i], packSideStrings, + "side", 0, &value) != TCL_OK) + { + goto error; + } + flags |= (TTK_PACK_LEFT << value); + + break; + case OP_STICKY: + if (Ttk_GetStickyFromObj(interp,objv[i],&sticky) != TCL_OK) + goto error; + break; + case OP_EXPAND: + if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK) + goto error; + if (value) + flags |= TTK_EXPAND; + break; + case OP_BORDER: + if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK) + goto error; + if (value) + flags |= TTK_BORDER; + break; + case OP_UNIT: + if (Tcl_GetBooleanFromObj(interp,objv[i],&value) != TCL_OK) + goto error; + if (value) + flags |= TTK_UNIT; + break; + case OP_CHILDREN: + childSpec = objv[i]; + break; + } + ++i; + } + + /* + * Build new node: + */ + if (tail) { + tail->next = Ttk_NewTemplateNode(elementName, flags | sticky); + tail = tail->next; + } else { + head = tail = Ttk_NewTemplateNode(elementName, flags | sticky); + } + if (childSpec) { + tail->child = Ttk_ParseLayoutTemplate(interp, childSpec); + if (!tail->child) { + goto error; + } + } + } + + return head; + +error: + Ttk_FreeLayoutTemplate(head); + return 0; +} + +/* Ttk_BuildLayoutTemplate -- + * Build a layout template tree from a statically defined + * Ttk_LayoutSpec array. + */ +Ttk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec spec) +{ + Ttk_TemplateNode *first = 0, *last = 0; + + for ( ; !(spec->opcode & _TTK_LAYOUT_END) ; ++spec) { + if (spec->elementName) { + Ttk_TemplateNode *node = + Ttk_NewTemplateNode(spec->elementName, spec->opcode); + + if (last) { + last->next = node; + } else { + first = node; + } + last = node; + } + + if (spec->opcode & _TTK_CHILDREN && last) { + int depth = 1; + last->child = Ttk_BuildLayoutTemplate(spec+1); + + /* Skip to end of group: + */ + while (depth) { + ++spec; + if (spec->opcode & _TTK_CHILDREN) { + ++depth; + } + if (spec->opcode & _TTK_LAYOUT_END) { + --depth; + } + } + } + + } /* for */ + + return first; +} + +void Ttk_RegisterLayouts(Ttk_Theme theme, Ttk_LayoutSpec spec) +{ + while (!(spec->opcode & _TTK_LAYOUT_END)) { + Ttk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(spec+1); + Ttk_RegisterLayoutTemplate(theme, spec->elementName, layoutTemplate); + do { + ++spec; + } while (!(spec->opcode & _TTK_LAYOUT)); + } +} + +Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_TemplateNode *node) +{ + Tcl_Obj *result = Tcl_NewListObj(0,0); + +# define APPENDOBJ(obj) Tcl_ListObjAppendElement(NULL, result, obj) +# define APPENDSTR(str) APPENDOBJ(Tcl_NewStringObj(str,-1)) + + while (node) { + unsigned flags = node->flags; + + APPENDSTR(node->name); + + /* Back-compute -side. <<NOTE-PACKSIDE>> + * @@@ NOTES: Ick. + */ + if (flags & TTK_EXPAND) { + APPENDSTR("-expand"); + APPENDSTR("1"); + } else { + if (flags & _TTK_MASK_PACK) { + int side = 0; + unsigned sideFlags = flags & _TTK_MASK_PACK; + + while ((sideFlags & TTK_PACK_LEFT) == 0) { + ++side; + sideFlags >>= 1; + } + APPENDSTR("-side"); + APPENDSTR(packSideStrings[side]); + } + } + + /* In Ttk_ParseLayoutTemplate, default -sticky is "nsew", + * so always include this even if no sticky bits are set. + */ + APPENDSTR("-sticky"); + APPENDOBJ(Ttk_NewStickyObj(flags & _TTK_MASK_STICK)); + + /* @@@ Check again: are these necessary? */ + if (flags & TTK_BORDER) { APPENDSTR("-border"); APPENDSTR("1"); } + if (flags & TTK_UNIT) { APPENDSTR("-unit"); APPENDSTR("1"); } + + if (node->child) { + APPENDSTR("-children"); + APPENDOBJ(Ttk_UnparseLayoutTemplate(node->child)); + } + node = node->next; + } + +# undef APPENDOBJ +# undef APPENDSTR + + return result; +} + +/*------------------------------------------------------------------------ + * +++ Layouts. + */ +struct Ttk_Layout_ +{ + Ttk_Style style; + void *recordPtr; + Tk_OptionTable optionTable; + Tk_Window tkwin; + Ttk_LayoutNode *root; +}; + +static Ttk_Layout TTKNewLayout( + Ttk_Style style, + void *recordPtr,Tk_OptionTable optionTable, Tk_Window tkwin, + Ttk_LayoutNode *root) +{ + Ttk_Layout layout = (Ttk_Layout)ckalloc(sizeof(*layout)); + layout->style = style; + layout->recordPtr = recordPtr; + layout->optionTable = optionTable; + layout->tkwin = tkwin; + layout->root = root; + return layout; +} + +void Ttk_FreeLayout(Ttk_Layout layout) +{ + Ttk_FreeLayoutNode(layout->root); + ckfree((ClientData)layout); +} + +/* + * Ttk_CreateLayout -- + * Create a layout from the specified theme and style name. + * Returns: New layout, 0 on error. + * Leaves an error message in interp's result if there is an error. + */ +Ttk_Layout Ttk_CreateLayout( + Tcl_Interp *interp, /* where to leave error messages */ + Ttk_Theme themePtr, + const char *styleName, + void *recordPtr, + Tk_OptionTable optionTable, + Tk_Window tkwin) +{ + Ttk_Style style = Ttk_GetStyle(themePtr, styleName); + Ttk_LayoutTemplate layoutTemplate = + Ttk_FindLayoutTemplate(themePtr,styleName); + Ttk_ElementClass *bgelement = Ttk_GetElement(themePtr, "background"); + Ttk_LayoutNode *bgnode; + + if (!layoutTemplate) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Layout ", styleName, " not found", NULL); + return 0; + } + + bgnode = Ttk_NewLayoutNode(TTK_FILL_BOTH, bgelement); + bgnode->next = Ttk_InstantiateLayout(themePtr, layoutTemplate); + + return TTKNewLayout(style, recordPtr, optionTable, tkwin, bgnode); +} + +/* Ttk_CreateSublayout -- + * Creates a new sublayout. + * + * Sublayouts are used to draw subparts of a compound widget. + * They use the same Tk_Window, but a different option table + * and data record. + */ +Ttk_Layout +Ttk_CreateSublayout( + Tcl_Interp *interp, + Ttk_Theme themePtr, + Ttk_Layout parentLayout, + const char *baseName, + Tk_OptionTable optionTable) +{ + Tcl_DString buf; + const char *styleName; + Ttk_Style style; + Ttk_LayoutTemplate layoutTemplate; + + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, Ttk_StyleName(parentLayout->style), -1); + Tcl_DStringAppend(&buf, baseName, -1); + styleName = Tcl_DStringValue(&buf); + + style = Ttk_GetStyle(themePtr, styleName); + layoutTemplate = Ttk_FindLayoutTemplate(themePtr, styleName); + + if (!layoutTemplate) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Layout ", styleName, " not found", NULL); + return 0; + } + + Tcl_DStringFree(&buf); + + return TTKNewLayout( + style, 0, optionTable, parentLayout->tkwin, + Ttk_InstantiateLayout(themePtr, layoutTemplate)); +} + +/* Ttk_RebindSublayout -- + * Bind sublayout to new data source. + */ +void Ttk_RebindSublayout(Ttk_Layout layout, void *recordPtr) +{ + layout->recordPtr = recordPtr; +} + +/* + * Ttk_QueryOption -- + * Look up an option from a layout's associated option. + */ +Tcl_Obj *Ttk_QueryOption( + Ttk_Layout layout, const char *optionName, Ttk_State state) +{ + return Ttk_QueryStyle( + layout->style,layout->recordPtr,layout->optionTable,optionName,state); +} + +/* + * Ttk_LayoutStyle -- + * Extract Ttk_Style from Ttk_Layout. + */ +Ttk_Style Ttk_LayoutStyle(Ttk_Layout layout) +{ + return layout->style; +} + +/*------------------------------------------------------------------------ + * +++ Size computation. + */ +static void Ttk_NodeListSize( + Ttk_Layout layout, Ttk_LayoutNode *node, + Ttk_State state, int *widthPtr, int *heightPtr); /* Forward */ + +static void Ttk_NodeSize( + Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + int elementWidth, elementHeight, subWidth, subHeight; + Ttk_Padding elementPadding; + + Ttk_ElementSize(node->eclass, + layout->style, layout->recordPtr,layout->optionTable, layout->tkwin, + state|node->state, + &elementWidth, &elementHeight, &elementPadding); + + Ttk_NodeListSize(layout,node->child,state,&subWidth,&subHeight); + subWidth += Ttk_PaddingWidth(elementPadding); + subHeight += Ttk_PaddingHeight(elementPadding); + + *widthPtr = MAX(elementWidth, subWidth); + *heightPtr = MAX(elementHeight, subHeight); + *paddingPtr = elementPadding; +} + +static void Ttk_NodeListSize( + Ttk_Layout layout, Ttk_LayoutNode *node, + Ttk_State state, int *widthPtr, int *heightPtr) +{ + if (!node) { + *widthPtr = *heightPtr = 0; + } else { + int width, height, restWidth, restHeight; + Ttk_Padding unused; + + Ttk_NodeSize(layout, node, state, &width, &height, &unused); + Ttk_NodeListSize(layout, node->next, state, &restWidth, &restHeight); + + if (node->flags & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) { + *widthPtr = width + restWidth; + } else { + *widthPtr = MAX(width, restWidth); + } + + if (node->flags & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) { + *heightPtr = height + restHeight; + } else { + *heightPtr = MAX(height, restHeight); + } + } +} + +/* + * Ttk_LayoutNodeInternalPadding -- + * Returns the internal padding of a layout node. + */ +Ttk_Padding Ttk_LayoutNodeInternalPadding( + Ttk_Layout layout, Ttk_LayoutNode *node) +{ + int unused; + Ttk_Padding padding; + Ttk_ElementSize(node->eclass, + layout->style, layout->recordPtr, layout->optionTable, layout->tkwin, + 0/*state*/, &unused, &unused, &padding); + return padding; +} + +/* + * Ttk_LayoutNodeInternalParcel -- + * Returns the inner area of a specified layout node, + * based on current parcel and element's internal padding. + */ +Ttk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout layout, Ttk_LayoutNode *node) +{ + Ttk_Padding padding = Ttk_LayoutNodeInternalPadding(layout, node); + return Ttk_PadBox(node->parcel, padding); +} + +/* Ttk_LayoutSize -- + * Compute requested size of a layout. + */ +void Ttk_LayoutSize( + Ttk_Layout layout, Ttk_State state, int *widthPtr, int *heightPtr) +{ + Ttk_NodeListSize(layout, layout->root, state, widthPtr, heightPtr); +} + +void Ttk_LayoutNodeReqSize( /* @@@ Rename this */ + Ttk_Layout layout, Ttk_LayoutNode *node, int *widthPtr, int *heightPtr) +{ + Ttk_Padding unused; + Ttk_NodeSize(layout, node, 0/*state*/, widthPtr, heightPtr, &unused); +} + +/*------------------------------------------------------------------------ + * +++ Layout placement. + */ + +/* Ttk_PlaceNodeList -- + * Compute parcel for each node in a layout tree + * according to position specification and overall size. + */ +static void Ttk_PlaceNodeList( + Ttk_Layout layout, Ttk_LayoutNode *node, Ttk_State state, Ttk_Box cavity) +{ + for (; node; node = node->next) + { + int width, height; + Ttk_Padding padding; + + /* Compute node size: (@@@ cache this instead?) + */ + Ttk_NodeSize(layout, node, state, &width, &height, &padding); + + /* Compute parcel: + */ + node->parcel = Ttk_PositionBox(&cavity, width, height, node->flags); + + /* Place child nodes: + */ + if (node->child) { + Ttk_Box childBox = Ttk_PadBox(node->parcel, padding); + Ttk_PlaceNodeList(layout,node->child, state, childBox); + } + } +} + +void Ttk_PlaceLayout(Ttk_Layout layout, Ttk_State state, Ttk_Box b) +{ + Ttk_PlaceNodeList(layout, layout->root, state, b); +} + +/*------------------------------------------------------------------------ + * +++ Layout drawing. + */ + +/* + * Ttk_DrawLayout -- + * Draw a layout tree. + */ +static void Ttk_DrawNodeList( + Ttk_Layout layout, Ttk_State state, Ttk_LayoutNode *node, Drawable d) +{ + for (; node; node = node->next) + { + int border = node->flags & TTK_BORDER; + int substate = state; + + if (node->flags & TTK_UNIT) + substate |= node->state; + + if (node->child && border) + Ttk_DrawNodeList(layout, substate, node->child, d); + + Ttk_DrawElement( + node->eclass, + layout->style,layout->recordPtr,layout->optionTable,layout->tkwin, + d, node->parcel, state | node->state); + + if (node->child && !border) + Ttk_DrawNodeList(layout, substate, node->child, d); + } +} + +void Ttk_DrawLayout(Ttk_Layout layout, Ttk_State state, Drawable d) +{ + Ttk_DrawNodeList(layout, state, layout->root, d); +} + +/*------------------------------------------------------------------------ + * +++ Inquiry and modification. + */ + +/* + * Ttk_IdentifyElement -- + * Find the element at the specified x,y coordinate. + */ +static Ttk_Element IdentifyNode(Ttk_Element node, int x, int y) +{ + Ttk_Element closest = NULL; + + for (; node; node = node->next) { + if (Ttk_BoxContains(node->parcel, x, y)) { + closest = node; + if (node->child && !(node->flags & TTK_UNIT)) { + Ttk_Element childNode = IdentifyNode(node->child, x,y); + if (childNode) { + closest = childNode; + } + } + } + } + return closest; +} + +Ttk_Element Ttk_IdentifyElement(Ttk_Layout layout, int x, int y) +{ + return IdentifyNode(layout->root, x, y); +} + +/* + * tail -- + * Return the last component of an element name, e.g., + * "Scrollbar.thumb" => "thumb" + */ +static const char *tail(const char *elementName) +{ + const char *dot; + while ((dot=strchr(elementName,'.')) != NULL) + elementName = dot + 1; + return elementName; +} + +/* + * Ttk_FindElement -- + * Look up an element by name + */ +static Ttk_Element +FindNode(Ttk_Element node, const char *nodeName) +{ + for (; node ; node = node->next) { + if (!strcmp(tail(Ttk_ElementName(node)), nodeName)) + return node; + + if (node->child) { + Ttk_Element childNode = FindNode(node->child, nodeName); + if (childNode) + return childNode; + } + } + return 0; +} + +Ttk_Element Ttk_FindElement(Ttk_Layout layout, const char *nodeName) +{ + return FindNode(layout->root, nodeName); +} + +/* + * Ttk_ClientRegion -- + * Find the internal parcel of a named element within a given layout. + * If the element is not present, use the entire window. + */ +Ttk_Box Ttk_ClientRegion(Ttk_Layout layout, const char *elementName) +{ + Ttk_Element element = Ttk_FindElement(layout, elementName); + return element + ? Ttk_LayoutNodeInternalParcel(layout, element) + : Ttk_WinBox(layout->tkwin) + ; +} + +/* + * Ttk_ElementName -- + * Return the name (class name) of the element. + */ +const char *Ttk_ElementName(Ttk_Element node) +{ + return Ttk_ElementClassName(node->eclass); +} + +/* + * Ttk_ElementParcel -- + * Return the element's current parcel. + */ +Ttk_Box Ttk_ElementParcel(Ttk_Element node) +{ + return node->parcel; +} + +/* + * Ttk_PlaceElement -- + * Explicitly specify an element's parcel. + */ +void Ttk_PlaceElement(Ttk_Layout layout, Ttk_Element node, Ttk_Box b) +{ + node->parcel = b; + if (node->child) { + Ttk_PlaceNodeList(layout, node->child, 0, + Ttk_PadBox(b, Ttk_LayoutNodeInternalPadding(layout, node))); + } +} + +/* + * Ttk_ChangeElementState -- + */ +void Ttk_ChangeElementState(Ttk_LayoutNode *node,unsigned set,unsigned clr) +{ + node->state = (node->state | set) & ~clr; +} + +/*EOF*/ diff --git a/generic/ttk/ttkManager.c b/generic/ttk/ttkManager.c new file mode 100644 index 0000000..ba9e5c0 --- /dev/null +++ b/generic/ttk/ttkManager.c @@ -0,0 +1,552 @@ +/* + * Copyright 2005, Joe English. Freely redistributable. + * + * Support routines for geometry managers. + */ + +#include <string.h> +#include <tk.h> +#include "ttkManager.h" + +/*------------------------------------------------------------------------ + * +++ The Geometry Propagation Dance. + * + * When a slave window requests a new size or some other parameter changes, + * the manager recomputes the required size for the master window and calls + * Tk_GeometryRequest(). This is scheduled as an idle handler so multiple + * updates can be processed as a single batch. + * + * If all goes well, the master's manager will process the request + * (and so on up the chain to the toplevel window), and the master + * window will eventually receive a <Configure> event. At this point + * it recomputes the size and position of all slaves and places them. + * + * If all does not go well, however, the master's request may be ignored + * (typically because the top-level window has a fixed, user-specified size). + * Tk doesn't provide any notification when this happens; to account for this, + * we also schedule an idle handler to call the layout procedure + * after making a geometry request. + * + * +++ Slave removal <<NOTE-LOSTSLAVE>>. + * + * There are three conditions under which a slave is removed: + * + * (1) Another GM claims control + * (2) Manager voluntarily relinquishes control + * (3) Slave is destroyed + * + * In case (1), Tk calls the manager's lostSlaveProc. + * Case (2) is performed by calling Tk_ManageGeometry(slave,NULL,0); + * in this case Tk does _not_ call the LostSlaveProc (documented behavior). + * Tk doesn't handle case (3) either; to account for that we + * register an event handler on the slave widget to track <Destroy> events. + */ + +/* ++ Data structures. + */ +typedef struct +{ + Tk_Window slaveWindow; + Ttk_Manager *manager; + void *slaveData; + unsigned flags; +} Ttk_Slave; + +/* slave->flags bits: + */ +#define SLAVE_MAPPED 0x1 /* slave to be mapped when master is */ + +struct TtkManager_ +{ + Ttk_ManagerSpec *managerSpec; + void *managerData; + Tk_Window masterWindow; + unsigned flags; + int nSlaves; + Ttk_Slave **slaves; +}; + +/* manager->flags bits: + */ +#define MGR_UPDATE_PENDING 0x1 +#define MGR_RESIZE_REQUIRED 0x2 +#define MGR_RELAYOUT_REQUIRED 0x4 + +static void ManagerIdleProc(void *); /* forward */ + +/* ++ ScheduleUpdate -- + * Schedule a call to recompute the size and/or layout, + * depending on flags. + */ +static void ScheduleUpdate(Ttk_Manager *mgr, unsigned flags) +{ + if (!(mgr->flags & MGR_UPDATE_PENDING)) { + Tcl_DoWhenIdle(ManagerIdleProc, mgr); + mgr->flags |= MGR_UPDATE_PENDING; + } + mgr->flags |= flags; +} + +/* ++ RecomputeSize -- + * Recomputes the required size of the master window, + * makes geometry request. + */ +static void RecomputeSize(Ttk_Manager *mgr) +{ + int width = 1, height = 1; + + if (mgr->managerSpec->RequestedSize(mgr->managerData, &width, &height)) { + Tk_GeometryRequest(mgr->masterWindow, width, height); + ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED); + } + mgr->flags &= ~MGR_RESIZE_REQUIRED; +} + +/* ++ RecomputeLayout -- + * Recompute geometry of all slaves. + */ +static void RecomputeLayout(Ttk_Manager *mgr) +{ + mgr->managerSpec->PlaceSlaves(mgr->managerData); + mgr->flags &= ~MGR_RELAYOUT_REQUIRED; +} + +/* ++ ManagerIdleProc -- + * DoWhenIdle procedure for deferred updates. + */ +static void ManagerIdleProc(ClientData clientData) +{ + Ttk_Manager *mgr = clientData; + mgr->flags &= ~MGR_UPDATE_PENDING; + + if (mgr->flags & MGR_RESIZE_REQUIRED) { + RecomputeSize(mgr); + } + if (mgr->flags & MGR_RELAYOUT_REQUIRED) { + if (mgr->flags & MGR_UPDATE_PENDING) { + /* RecomputeSize has scheduled another update; relayout later */ + return; + } + RecomputeLayout(mgr); + } +} + +/*------------------------------------------------------------------------ + * +++ Event handlers. + */ + +/* ++ ManagerEventHandler -- + * Recompute slave layout when master widget is resized. + * Keep the slave's map state in sync with the master's. + */ +static const int ManagerEventMask = StructureNotifyMask; +static void ManagerEventHandler(ClientData clientData, XEvent *eventPtr) +{ + Ttk_Manager *mgr = clientData; + int i; + + switch (eventPtr->type) + { + case ConfigureNotify: + RecomputeLayout(mgr); + break; + case MapNotify: + for (i = 0; i < mgr->nSlaves; ++i) { + Ttk_Slave *slave = mgr->slaves[i]; + if (slave->flags & SLAVE_MAPPED) { + Tk_MapWindow(slave->slaveWindow); + } + } + break; + case UnmapNotify: + for (i = 0; i < mgr->nSlaves; ++i) { + Ttk_Slave *slave = mgr->slaves[i]; + Tk_UnmapWindow(slave->slaveWindow); + } + break; + } +} + +/* ++ SlaveEventHandler -- + * Notifies manager when a slave is destroyed + * (see <<NOTE-LOSTSLAVE>>). + */ +static const unsigned SlaveEventMask = StructureNotifyMask; +static void SlaveEventHandler(ClientData clientData, XEvent *eventPtr) +{ + Ttk_Slave *slave = clientData; + if (eventPtr->type == DestroyNotify) { + slave->manager->managerSpec->tkGeomMgr.lostSlaveProc( + slave->manager, slave->slaveWindow); + } +} + +/*------------------------------------------------------------------------ + * +++ Slave initialization and cleanup. + */ + +static Ttk_Slave *NewSlave( + Ttk_Manager *mgr, Tk_Window slaveWindow, void *slaveData) +{ + Ttk_Slave *slave = (Ttk_Slave*)ckalloc(sizeof(*slave)); + + slave->slaveWindow = slaveWindow; + slave->manager = mgr; + slave->flags = 0; + slave->slaveData = slaveData; + + return slave; +} + +static void DeleteSlave(Ttk_Slave *slave) +{ + ckfree((ClientData)slave); +} + +/*------------------------------------------------------------------------ + * +++ Manager initialization and cleanup. + */ + +Ttk_Manager *Ttk_CreateManager( + Ttk_ManagerSpec *managerSpec, void *managerData, Tk_Window masterWindow) +{ + Ttk_Manager *mgr = (Ttk_Manager*)ckalloc(sizeof(*mgr)); + + mgr->managerSpec = managerSpec; + mgr->managerData = managerData; + mgr->masterWindow = masterWindow; + mgr->nSlaves = 0; + mgr->slaves = NULL; + mgr->flags = 0; + + Tk_CreateEventHandler( + mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr); + + return mgr; +} + +void Ttk_DeleteManager(Ttk_Manager *mgr) +{ + Tk_DeleteEventHandler( + mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr); + + while (mgr->nSlaves > 0) { + Ttk_ForgetSlave(mgr, mgr->nSlaves - 1); + } + if (mgr->slaves) { + ckfree((ClientData)mgr->slaves); + } + + Tk_CancelIdleCall(ManagerIdleProc, mgr); + + ckfree((ClientData)mgr); +} + +/*------------------------------------------------------------------------ + * +++ Slave management. + */ + +/* ++ InsertSlave -- + * Adds slave to the list of managed windows. + */ +static void InsertSlave(Ttk_Manager *mgr, Ttk_Slave *slave, int index) +{ + int endIndex = mgr->nSlaves++; + mgr->slaves = (Ttk_Slave**)ckrealloc( + (ClientData)mgr->slaves, mgr->nSlaves * sizeof(Ttk_Slave *)); + + while (endIndex > index) { + mgr->slaves[endIndex] = mgr->slaves[endIndex - 1]; + --endIndex; + } + + mgr->slaves[index] = slave; + + Tk_ManageGeometry(slave->slaveWindow, + &mgr->managerSpec->tkGeomMgr, (ClientData)mgr); + + Tk_CreateEventHandler(slave->slaveWindow, + SlaveEventMask, SlaveEventHandler, (ClientData)slave); + + ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); +} + +/* RemoveSlave -- + * Unmanage and delete the slave. + * + * NOTES/ASSUMPTIONS: + * + * [1] It's safe to call Tk_UnmapWindow / Tk_UnmaintainGeometry even if this + * routine is called from the slave's DestroyNotify event handler. + */ +static void RemoveSlave(Ttk_Manager *mgr, int index) +{ + Ttk_Slave *slave = mgr->slaves[index]; + int i; + + /* Notify manager: + */ + mgr->managerSpec->SlaveRemoved(mgr->managerData, index); + + /* Remove from array: + */ + --mgr->nSlaves; + for (i = index ; i < mgr->nSlaves; ++i) { + mgr->slaves[i] = mgr->slaves[i+1]; + } + + /* Clean up: + */ + Tk_DeleteEventHandler( + slave->slaveWindow, SlaveEventMask, SlaveEventHandler, slave); + + /* Note [1] */ + Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow); + Tk_UnmapWindow(slave->slaveWindow); + + DeleteSlave(slave); + + ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); +} + +/*------------------------------------------------------------------------ + * +++ Tk_GeomMgr hooks. + */ + +void Ttk_GeometryRequestProc(ClientData clientData, Tk_Window slaveWindow) +{ + Ttk_Manager *mgr = clientData; + int slaveIndex = Ttk_SlaveIndex(mgr, slaveWindow); + int reqWidth = Tk_ReqWidth(slaveWindow); + int reqHeight= Tk_ReqHeight(slaveWindow); + + if (mgr->managerSpec->SlaveRequest( + mgr->managerData, slaveIndex, reqWidth, reqHeight)) + { + ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); + } +} + +void Ttk_LostSlaveProc(ClientData clientData, Tk_Window slaveWindow) +{ + Ttk_Manager *mgr = clientData; + int index = Ttk_SlaveIndex(mgr, slaveWindow); + + /* ASSERT: index >= 0 */ + RemoveSlave(mgr, index); +} + +/*------------------------------------------------------------------------ + * +++ Public API. + */ + +/* ++ Ttk_InsertSlave -- + * Add a new slave window at the specified index. + */ +void Ttk_InsertSlave( + Ttk_Manager *mgr, int index, Tk_Window tkwin, void *slaveData) +{ + Ttk_Slave *slave = NewSlave(mgr, tkwin, slaveData); + InsertSlave(mgr, slave, index); +} + +/* ++ Ttk_ForgetSlave -- + * Unmanage the specified slave. + */ +void Ttk_ForgetSlave(Ttk_Manager *mgr, int slaveIndex) +{ + Tk_Window slaveWindow = mgr->slaves[slaveIndex]->slaveWindow; + RemoveSlave(mgr, slaveIndex); + Tk_ManageGeometry(slaveWindow, NULL, 0); +} + +/* ++ Ttk_PlaceSlave -- + * Set the position and size of the specified slave window. + * + * NOTES: + * Contrary to documentation, Tk_MaintainGeometry doesn't always + * map the slave. + */ +void Ttk_PlaceSlave( + Ttk_Manager *mgr, int slaveIndex, int x, int y, int width, int height) +{ + Ttk_Slave *slave = mgr->slaves[slaveIndex]; + Tk_MaintainGeometry(slave->slaveWindow,mgr->masterWindow,x,y,width,height); + slave->flags |= SLAVE_MAPPED; + if (Tk_IsMapped(mgr->masterWindow)) { + Tk_MapWindow(slave->slaveWindow); + } +} + +/* ++ Ttk_UnmapSlave -- + * Unmap the specified slave, but leave it managed. + */ +void Ttk_UnmapSlave(Ttk_Manager *mgr, int slaveIndex) +{ + Ttk_Slave *slave = mgr->slaves[slaveIndex]; + Tk_UnmaintainGeometry(slave->slaveWindow, mgr->masterWindow); + slave->flags &= ~SLAVE_MAPPED; + /* Contrary to documentation, Tk_UnmaintainGeometry doesn't always + * unmap the slave: + */ + Tk_UnmapWindow(slave->slaveWindow); +} + +/* LayoutChanged, SizeChanged -- + * Schedule a relayout, resp. resize request. + */ +void Ttk_ManagerLayoutChanged(Ttk_Manager *mgr) +{ + ScheduleUpdate(mgr, MGR_RELAYOUT_REQUIRED); +} + +void Ttk_ManagerSizeChanged(Ttk_Manager *mgr) +{ + ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); +} + +/* +++ Accessors. + */ +int Ttk_NumberSlaves(Ttk_Manager *mgr) +{ + return mgr->nSlaves; +} +void *Ttk_SlaveData(Ttk_Manager *mgr, int slaveIndex) +{ + return mgr->slaves[slaveIndex]->slaveData; +} +Tk_Window Ttk_SlaveWindow(Ttk_Manager *mgr, int slaveIndex) +{ + return mgr->slaves[slaveIndex]->slaveWindow; +} + +/*------------------------------------------------------------------------ + * +++ Utility routines. + */ + +/* ++ Ttk_SlaveIndex -- + * Returns the index of specified slave window, -1 if not found. + */ +int Ttk_SlaveIndex(Ttk_Manager *mgr, Tk_Window slaveWindow) +{ + int index; + for (index = 0; index < mgr->nSlaves; ++index) + if (mgr->slaves[index]->slaveWindow == slaveWindow) + return index; + return -1; +} + +/* ++ Ttk_GetSlaveIndexFromObj(interp, mgr, objPtr, indexPtr) -- + * Return the index of the slave specified by objPtr. + * Slaves may be specified as an integer index or + * as the name of the managed window. + * + * Returns: + * Standard Tcl completion code. Leaves an error message in case of error. + */ + +int Ttk_GetSlaveIndexFromObj( + Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, int *indexPtr) +{ + const char *string = Tcl_GetString(objPtr); + int slaveIndex = 0; + Tk_Window tkwin; + + /* Try interpreting as an integer first: + */ + if (Tcl_GetIntFromObj(NULL, objPtr, &slaveIndex) == TCL_OK) { + if (slaveIndex < 0 || slaveIndex >= mgr->nSlaves) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Slave index ", Tcl_GetString(objPtr), " out of bounds", + NULL); + return TCL_ERROR; + } + *indexPtr = slaveIndex; + return TCL_OK; + } + + /* Try interpreting as a slave window name; + */ + if ( (*string == '.') + && (tkwin = Tk_NameToWindow(interp, string, mgr->masterWindow))) + { + slaveIndex = Ttk_SlaveIndex(mgr, tkwin); + if (slaveIndex < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + string, " is not managed by ", Tk_PathName(mgr->masterWindow), + NULL); + return TCL_ERROR; + } + *indexPtr = slaveIndex; + return TCL_OK; + } + + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Invalid slave specification ", string, NULL); + return TCL_ERROR; +} + +/* ++ Ttk_ReorderSlave(mgr, fromIndex, toIndex) -- + * Change slave order. + */ +void Ttk_ReorderSlave(Ttk_Manager *mgr, int fromIndex, int toIndex) +{ + Ttk_Slave *moved = mgr->slaves[fromIndex]; + + /* Shuffle down: */ + while (fromIndex > toIndex) { + mgr->slaves[fromIndex] = mgr->slaves[fromIndex - 1]; + --fromIndex; + } + /* Or, shuffle up: */ + while (fromIndex < toIndex) { + mgr->slaves[fromIndex] = mgr->slaves[fromIndex + 1]; + ++fromIndex; + } + /* ASSERT: fromIndex == toIndex */ + mgr->slaves[fromIndex] = moved; + + /* Schedule a relayout. In general, rearranging slaves + * may also change the size: + */ + ScheduleUpdate(mgr, MGR_RESIZE_REQUIRED); +} + +/* ++ Ttk_Maintainable(interp, slave, master) -- + * Utility routine. Verifies that 'master' may be used to maintain + * the geometry of 'slave' via Tk_MaintainGeometry: + * + * + 'master' is either 'slave's parent -OR- + * + 'master is a descendant of 'slave's parent. + * + 'slave' is not a toplevel window + * + 'slave' belongs to the same toplevel as 'master' + * + * Returns: 1 if OK; otherwise 0, leaving an error message in 'interp'. + */ +int Ttk_Maintainable(Tcl_Interp *interp, Tk_Window slave, Tk_Window master) +{ + Tk_Window ancestor = master, parent = Tk_Parent(slave); + + if (Tk_IsTopLevel(slave) || slave == master) { + goto badWindow; + } + + while (ancestor != parent) { + if (Tk_IsTopLevel(ancestor)) { + goto badWindow; + } + ancestor = Tk_Parent(ancestor); + } + + return 1; + +badWindow: + Tcl_AppendResult(interp, + "can't add ", Tk_PathName(slave), + " as slave of ", Tk_PathName(master), + NULL); + return 0; +} + diff --git a/generic/ttk/ttkManager.h b/generic/ttk/ttkManager.h new file mode 100644 index 0000000..d22ff98 --- /dev/null +++ b/generic/ttk/ttkManager.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2005, Joe English. Freely redistributable. + * + * Geometry manager utilities. + */ + +#ifndef _TTKMANAGER +#define _TTKMANAGER + +#include "ttkTheme.h" + +typedef struct TtkManager_ Ttk_Manager; + +/* + * Geometry manager specification record: + * + * RequestedSize computes the requested size of the master window. + * + * PlaceSlaves sets the position and size of all managed slaves + * by calling Ttk_PlaceSlave(). + * + * SlaveRemoved() is called immediately before a slave is removed. + * NB: the associated slave window may have been destroyed when this + * routine is called. + * + * SlaveRequest() is called when a slave requests a size change. + * It should return 1 if the request should propagate, 0 otherwise. + */ +typedef struct { /* Manager hooks */ + Tk_GeomMgr tkGeomMgr; /* "real" Tk Geometry Manager */ + + int (*RequestedSize)(void *managerData, int *widthPtr, int *heightPtr); + void (*PlaceSlaves)(void *managerData); + int (*SlaveRequest)(void *managerData, int slaveIndex, int w, int h); + void (*SlaveRemoved)(void *managerData, int slaveIndex); +} Ttk_ManagerSpec; + +/* + * Default implementations for Tk_GeomMgr hooks: + */ +MODULE_SCOPE void Ttk_GeometryRequestProc(ClientData, Tk_Window slave); +MODULE_SCOPE void Ttk_LostSlaveProc(ClientData, Tk_Window slave); + +/* + * Public API: + */ +MODULE_SCOPE Ttk_Manager *Ttk_CreateManager( + Ttk_ManagerSpec *, void *managerData, Tk_Window masterWindow); +MODULE_SCOPE void Ttk_DeleteManager(Ttk_Manager *); + +MODULE_SCOPE void Ttk_InsertSlave( + Ttk_Manager *, int position, Tk_Window, void *slaveData); + +MODULE_SCOPE void Ttk_ForgetSlave(Ttk_Manager *, int slaveIndex); + +MODULE_SCOPE void Ttk_ReorderSlave(Ttk_Manager *, int fromIndex, int toIndex); + /* Rearrange slave positions */ + +MODULE_SCOPE void Ttk_PlaceSlave( + Ttk_Manager *, int slaveIndex, int x, int y, int width, int height); + /* Position and map the slave */ + +MODULE_SCOPE void Ttk_UnmapSlave(Ttk_Manager *, int slaveIndex); + /* Unmap the slave */ + +MODULE_SCOPE void Ttk_ManagerSizeChanged(Ttk_Manager *); +MODULE_SCOPE void Ttk_ManagerLayoutChanged(Ttk_Manager *); + /* Notify manager that size (resp. layout) needs to be recomputed */ + +/* Utilities: + */ +MODULE_SCOPE int Ttk_SlaveIndex(Ttk_Manager *, Tk_Window); + /* Returns: index in slave array of specified window, -1 if not found */ + +MODULE_SCOPE int Ttk_GetSlaveIndexFromObj( + Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, int *indexPtr); + +/* Accessor functions: + */ +MODULE_SCOPE int Ttk_NumberSlaves(Ttk_Manager *); + /* Returns: number of managed slaves */ + +MODULE_SCOPE void *Ttk_SlaveData(Ttk_Manager *, int slaveIndex); + /* Returns: client data associated with slave */ + +MODULE_SCOPE Tk_Window Ttk_SlaveWindow(Ttk_Manager *, int slaveIndex); + /* Returns: slave window */ + +MODULE_SCOPE int Ttk_Maintainable(Tcl_Interp *, Tk_Window slave, Tk_Window master); + /* Returns: 1 if master can manage slave; 0 otherwise leaving error msg */ + +#endif /* _TTKMANAGER */ diff --git a/generic/ttk/ttkNotebook.c b/generic/ttk/ttkNotebook.c new file mode 100644 index 0000000..551f4a6 --- /dev/null +++ b/generic/ttk/ttkNotebook.c @@ -0,0 +1,1413 @@ +/* + * Copyright (c) 2004, Joe English + */ + +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <tk.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" +#include "ttkManager.h" + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +/*------------------------------------------------------------------------ + * +++ Tab resources. + */ + +#define DEFAULT_MIN_TAB_WIDTH 24 + +static const char *const TabStateStrings[] = { "normal", "disabled", "hidden", 0 }; +typedef enum { + TAB_STATE_NORMAL, TAB_STATE_DISABLED, TAB_STATE_HIDDEN +} TAB_STATE; + +typedef struct +{ + /* Internal data: + */ + int width, height; /* Requested size of tab */ + Ttk_Box parcel; /* Tab position */ + + /* Tab options: + */ + TAB_STATE state; + + /* Child window options: + */ + Tcl_Obj *paddingObj; /* Padding inside pane */ + Ttk_Padding padding; + Tcl_Obj *stickyObj; + Ttk_Sticky sticky; + + /* Label options: + */ + Tcl_Obj *textObj; + Tcl_Obj *imageObj; + Tcl_Obj *compoundObj; + Tcl_Obj *underlineObj; + +} Tab; + +/* Two different option tables are used for tabs: + * TabOptionSpecs is used to draw the tab, and only includes resources + * relevant to the tab. + * + * PaneOptionSpecs includes additional options for child window placement + * and is used to configure the slave. + */ +static Tk_OptionSpec TabOptionSpecs[] = +{ + {TK_OPTION_STRING_TABLE, "-state", "", "", + "normal", -1,Tk_Offset(Tab,state), + 0,(ClientData)TabStateStrings,0 }, + {TK_OPTION_STRING, "-text", "text", "Text", "", + Tk_Offset(Tab,textObj), -1, 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/, + Tk_Offset(Tab,imageObj), -1, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", + "none", Tk_Offset(Tab,compoundObj), -1, + 0,(ClientData)ttkCompoundStrings,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-underline", "underline", "Underline", "-1", + Tk_Offset(Tab,underlineObj), -1, 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 } +}; + +static Tk_OptionSpec PaneOptionSpecs[] = +{ + {TK_OPTION_STRING, "-padding", "padding", "Padding", "0", + Tk_Offset(Tab,paddingObj), -1, 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-sticky", "sticky", "Sticky", "nsew", + Tk_Offset(Tab,stickyObj), -1, 0,0,GEOMETRY_CHANGED }, + + WIDGET_INHERIT_OPTIONS(TabOptionSpecs) +}; + +/*------------------------------------------------------------------------ + * +++ Notebook resources. + */ +typedef struct +{ + Tcl_Obj *widthObj; /* Default width */ + Tcl_Obj *heightObj; /* Default height */ + Tcl_Obj *paddingObj; /* Padding around notebook */ + + Ttk_Manager *mgr; /* Geometry manager */ + Tk_OptionTable tabOptionTable; /* Tab options */ + Tk_OptionTable paneOptionTable; /* Tab+pane options */ + int currentIndex; /* index of currently selected tab */ + int activeIndex; /* index of currently active tab */ + Ttk_Layout tabLayout; /* Sublayout for tabs */ + + Ttk_Box clientArea; /* Where to pack slave widgets */ +} NotebookPart; + +typedef struct +{ + WidgetCore core; + NotebookPart notebook; +} Notebook; + +static Tk_OptionSpec NotebookOptionSpecs[] = +{ + {TK_OPTION_INT, "-width", "width", "Width", "0", + Tk_Offset(Notebook,notebook.widthObj),-1, + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-height", "height", "Height", "0", + Tk_Offset(Notebook,notebook.heightObj),-1, + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-padding", "padding", "Padding", NULL, + Tk_Offset(Notebook,notebook.paddingObj),-1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/* Notebook style options: + */ +typedef struct +{ + Ttk_PositionSpec tabPosition; /* Where to place tabs */ + Ttk_Padding tabMargins; /* Margins around tab row */ + Ttk_PositionSpec tabPlacement; /* How to pack tabs within tab row */ + Ttk_Orient tabOrient; /* ... */ + int minTabWidth; /* Minimum tab width */ + Ttk_Padding padding; /* External padding */ +} NotebookStyle; + +static void NotebookStyleOptions(Notebook *nb, NotebookStyle *nbstyle) +{ + Tcl_Obj *objPtr; + + nbstyle->tabPosition = TTK_PACK_TOP | TTK_STICK_W; + if ((objPtr = Ttk_QueryOption(nb->core.layout, "-tabposition", 0)) != 0) { + TtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPosition); + } + + /* Guess default tabPlacement as function of tabPosition: + */ + if (nbstyle->tabPosition & TTK_PACK_LEFT) { + nbstyle->tabPlacement = TTK_PACK_TOP | TTK_STICK_E; + } else if (nbstyle->tabPosition & TTK_PACK_RIGHT) { + nbstyle->tabPlacement = TTK_PACK_TOP | TTK_STICK_W; + } else if (nbstyle->tabPosition & TTK_PACK_BOTTOM) { + nbstyle->tabPlacement = TTK_PACK_LEFT | TTK_STICK_N; + } else { /* Assume TTK_PACK_TOP */ + nbstyle->tabPlacement = TTK_PACK_LEFT | TTK_STICK_S; + } + if ((objPtr = Ttk_QueryOption(nb->core.layout, "-tabplacement", 0)) != 0) { + TtkGetLabelAnchorFromObj(NULL, objPtr, &nbstyle->tabPlacement); + } + + /* Compute tabOrient as function of tabPlacement: + */ + if (nbstyle->tabPlacement & (TTK_PACK_LEFT|TTK_PACK_RIGHT)) { + nbstyle->tabOrient = TTK_ORIENT_HORIZONTAL; + } else { + nbstyle->tabOrient = TTK_ORIENT_VERTICAL; + } + + nbstyle->tabMargins = Ttk_UniformPadding(0); + if ((objPtr = Ttk_QueryOption(nb->core.layout, "-tabmargins", 0)) != 0) { + Ttk_GetBorderFromObj(NULL, objPtr, &nbstyle->tabMargins); + } + + nbstyle->padding = Ttk_UniformPadding(0); + if ((objPtr = Ttk_QueryOption(nb->core.layout, "-padding", 0)) != 0) { + Ttk_GetPaddingFromObj(NULL,nb->core.tkwin,objPtr,&nbstyle->padding); + } + + nbstyle->minTabWidth = DEFAULT_MIN_TAB_WIDTH; + if ((objPtr = Ttk_QueryOption(nb->core.layout, "-mintabwidth", 0)) != 0) { + Tcl_GetIntFromObj(NULL, objPtr, &nbstyle->minTabWidth); + } +} + +/*------------------------------------------------------------------------ + * +++ Tab management. + */ + +static Tab *CreateTab(Tcl_Interp *interp, Notebook *nb, Tk_Window slaveWindow) +{ + Tk_OptionTable optionTable = nb->notebook.paneOptionTable; + void *record = ckalloc(sizeof(Tab)); + memset(record, 0, sizeof(Tab)); + + if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) { + ckfree(record); + return NULL; + } + + return record; +} + +static void DestroyTab(Notebook *nb, Tab *tab) +{ + void *record = tab; + Tk_FreeConfigOptions(record, nb->notebook.paneOptionTable, nb->core.tkwin); + ckfree(record); +} + +static int ConfigureTab( + Tcl_Interp *interp, Notebook *nb, Tab *tab, Tk_Window slaveWindow, + int objc, Tcl_Obj *const objv[]) +{ + Ttk_Sticky sticky = tab->sticky; + Ttk_Padding padding = tab->padding; + Tk_SavedOptions savedOptions; + int mask = 0; + + if (Tk_SetOptions(interp, (ClientData)tab, nb->notebook.paneOptionTable, + objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK) + { + return TCL_ERROR; + } + + /* Check options: + * @@@ TODO: validate -image option. + */ + if (Ttk_GetStickyFromObj(interp, tab->stickyObj, &sticky) != TCL_OK) + { + goto error; + } + if (Ttk_GetPaddingFromObj(interp, slaveWindow, tab->paddingObj, &padding) + != TCL_OK) + { + goto error; + } + + tab->sticky = sticky; + tab->padding = padding; + + Tk_FreeSavedOptions(&savedOptions); + Ttk_ManagerSizeChanged(nb->notebook.mgr); + TtkRedisplayWidget(&nb->core); + + return TCL_OK; +error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; +} + +/* + * IdentifyTab -- + * Return the index of the tab at point x,y, + * or -1 if no tab at that point. + */ +static int IdentifyTab(Notebook *nb, int x, int y) +{ + int index; + for (index = 0; index < Ttk_NumberSlaves(nb->notebook.mgr); ++index) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr,index); + if ( tab->state != TAB_STATE_HIDDEN + && Ttk_BoxContains(tab->parcel, x,y)) + { + return index; + } + } + return -1; +} + +/* + * ActivateTab -- + * Set the active tab index, redisplay if necessary. + */ +static void ActivateTab(Notebook *nb, int index) +{ + if (index != nb->notebook.activeIndex) { + nb->notebook.activeIndex = index; + TtkRedisplayWidget(&nb->core); + } +} + +/* + * 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. + */ +static Ttk_State TabState(Notebook *nb, int index) +{ + Ttk_State state = nb->core.state; + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index); + + if (index == nb->notebook.currentIndex) { + state |= TTK_STATE_SELECTED; + } else { + state &= ~TTK_STATE_FOCUS; + } + + if (index == nb->notebook.activeIndex) { + state |= TTK_STATE_ACTIVE; + } + if (index == 0) { + state |= TTK_STATE_USER1; + } + if (index == Ttk_NumberSlaves(nb->notebook.mgr) - 1) { + state |= TTK_STATE_USER2; + } + if (tab->state == TAB_STATE_DISABLED) { + state |= TTK_STATE_DISABLED; + } + + return state; +} + +/*------------------------------------------------------------------------ + * +++ Geometry management - size computation. + */ + +/* TabrowSize -- + * Compute max height and total width of all tabs (horizontal layouts) + * or total height and max width (vertical layouts). + * + * Side effects: + * Sets width and height fields for all tabs. + * + * Notes: + * Hidden tabs are included in the perpendicular computation + * (max height/width) but not parallel (total width/height). + */ +static void TabrowSize( + Notebook *nb, Ttk_Orient orient, int *widthPtr, int *heightPtr) +{ + Ttk_Layout tabLayout = nb->notebook.tabLayout; + int tabrowWidth = 0, tabrowHeight = 0; + int i; + + for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + Ttk_State tabState = TabState(nb,i); + + Ttk_RebindSublayout(tabLayout, tab); + Ttk_LayoutSize(tabLayout,tabState,&tab->width,&tab->height); + + if (orient == TTK_ORIENT_HORIZONTAL) { + tabrowHeight = MAX(tabrowHeight, tab->height); + if (tab->state != TAB_STATE_HIDDEN) { tabrowWidth += tab->width; } + } else { + tabrowWidth = MAX(tabrowWidth, tab->width); + if (tab->state != TAB_STATE_HIDDEN) { tabrowHeight += tab->height; } + } + } + + *widthPtr = tabrowWidth; + *heightPtr = tabrowHeight; +} + +/* NotebookSize -- GM and widget size hook. + * + * Total height is tab height + client area height + pane internal padding + * Total width is max(client width, tab width) + pane internal padding + * Client area size determined by max size of slaves, + * overridden by -width and/or -height if nonzero. + */ + +static int NotebookSize(void *clientData, int *widthPtr, int *heightPtr) +{ + Notebook *nb = clientData; + NotebookStyle nbstyle; + Ttk_Padding padding; + Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, "client"); + int clientWidth = 0, clientHeight = 0, + reqWidth = 0, reqHeight = 0, + tabrowWidth = 0, tabrowHeight = 0; + int i; + + NotebookStyleOptions(nb, &nbstyle); + + /* Compute max requested size of all slaves: + */ + for (i = 0; i < Ttk_NumberSlaves(nb->notebook.mgr); ++i) { + Tk_Window slaveWindow = Ttk_SlaveWindow(nb->notebook.mgr, i); + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + int slaveWidth + = Tk_ReqWidth(slaveWindow) + Ttk_PaddingWidth(tab->padding); + int slaveHeight + = Tk_ReqHeight(slaveWindow) + Ttk_PaddingHeight(tab->padding); + + clientWidth = MAX(clientWidth, slaveWidth); + clientHeight = MAX(clientHeight, slaveHeight); + } + + /* Client width/height overridable by widget options: + */ + Tcl_GetIntFromObj(NULL, nb->notebook.widthObj,&reqWidth); + Tcl_GetIntFromObj(NULL, nb->notebook.heightObj,&reqHeight); + if (reqWidth > 0) + clientWidth = reqWidth; + if (reqHeight > 0) + clientHeight = reqHeight; + + /* Tab row: + */ + TabrowSize(nb, nbstyle.tabOrient, &tabrowWidth, &tabrowHeight); + tabrowHeight += Ttk_PaddingHeight(nbstyle.tabMargins); + tabrowWidth += Ttk_PaddingWidth(nbstyle.tabMargins); + + /* Account for exterior and interior padding: + */ + padding = nbstyle.padding; + if (clientNode) { + Ttk_Padding ipad = + Ttk_LayoutNodeInternalPadding(nb->core.layout, clientNode); + padding = Ttk_AddPadding(padding, ipad); + } + + if (nbstyle.tabPosition & (TTK_PACK_TOP|TTK_PACK_BOTTOM)) { + *widthPtr = MAX(tabrowWidth, clientWidth) + Ttk_PaddingWidth(padding); + *heightPtr = tabrowHeight + clientHeight + Ttk_PaddingHeight(padding); + } else { + *widthPtr = tabrowWidth + clientWidth + Ttk_PaddingWidth(padding); + *heightPtr = MAX(tabrowHeight,clientHeight) + Ttk_PaddingHeight(padding); + } + + return 1; +} + +/*------------------------------------------------------------------------ + * +++ Geometry management - layout. + */ + +/* SqueezeTabs -- + * Squeeze or stretch tabs to fit within the tab area parcel. + * + * 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. + * + * @@@ <<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) +{ + int nTabs = Ttk_NumberSlaves(nb->notebook.mgr); + + if (nTabs > 0) { + int difference = available - needed, + delta = difference / nTabs, + remainder = difference % nTabs, + 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; + } + } + } +} + +/* PlaceTabs -- + * Compute all tab parcels. + */ +static void PlaceTabs( + Notebook *nb, Ttk_Box tabrowBox, Ttk_PositionSpec tabPlacement) +{ + Ttk_Layout tabLayout = nb->notebook.tabLayout; + int nTabs = Ttk_NumberSlaves(nb->notebook.mgr); + int i; + + for (i = 0; i < nTabs; ++i) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, i); + Ttk_State tabState = TabState(nb, i); + + if (tab->state != TAB_STATE_HIDDEN) { + Ttk_Padding expand = Ttk_UniformPadding(0); + Tcl_Obj *expandObj = Ttk_QueryOption(tabLayout,"-expand",tabState); + + if (expandObj) { + Ttk_GetBorderFromObj(NULL, expandObj, &expand); + } + + tab->parcel = + Ttk_ExpandBox( + Ttk_PositionBox(&tabrowBox, + tab->width, tab->height, tabPlacement), + expand); + } + } +} + +/* NotebookDoLayout -- + * Computes notebook layout and places tabs. + * + * Side effects: + * Sets clientArea, used to place slave panes. + */ +static void NotebookDoLayout(void *recordPtr) +{ + Notebook *nb = recordPtr; + Tk_Window nbwin = nb->core.tkwin; + Ttk_Box cavity = Ttk_WinBox(nbwin); + int tabrowWidth = 0, tabrowHeight = 0; + Ttk_Element clientNode = Ttk_FindElement(nb->core.layout, "client"); + Ttk_Box tabrowBox; + NotebookStyle nbstyle; + + NotebookStyleOptions(nb, &nbstyle); + + /* Notebook internal padding: + */ + cavity = Ttk_PadBox(cavity, nbstyle.padding); + + /* Layout for notebook background (base layout): + */ + Ttk_PlaceLayout(nb->core.layout, nb->core.state, Ttk_WinBox(nbwin)); + + /* Place tabs: + */ + TabrowSize(nb, nbstyle.tabOrient, &tabrowWidth, &tabrowHeight); + tabrowBox = Ttk_PadBox( + Ttk_PositionBox(&cavity, + tabrowWidth + Ttk_PaddingWidth(nbstyle.tabMargins), + tabrowHeight + Ttk_PaddingHeight(nbstyle.tabMargins), + nbstyle.tabPosition), + nbstyle.tabMargins); + + SqueezeTabs(nb, tabrowWidth, tabrowBox.width, nbstyle.minTabWidth); + PlaceTabs(nb, tabrowBox, nbstyle.tabPlacement); + + /* Layout for client area frame: + */ + if (clientNode) { + Ttk_PlaceElement(nb->core.layout, clientNode, cavity); + cavity = Ttk_LayoutNodeInternalParcel(nb->core.layout, clientNode); + } + + if (cavity.height <= 0) cavity.height = 1; + if (cavity.width <= 0) cavity.width = 1; + + nb->notebook.clientArea = cavity; +} + +/* + * NotebookPlaceSlave -- + * Set the position and size of a child widget + * based on the current client area and slave options: + */ +static void NotebookPlaceSlave(Notebook *nb, int slaveIndex) +{ + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, slaveIndex); + Tk_Window slaveWindow = Ttk_SlaveWindow(nb->notebook.mgr, slaveIndex); + Ttk_Box slaveBox = + Ttk_StickBox(Ttk_PadBox(nb->notebook.clientArea, tab->padding), + Tk_ReqWidth(slaveWindow), Tk_ReqHeight(slaveWindow),tab->sticky); + + Ttk_PlaceSlave(nb->notebook.mgr, slaveIndex, + slaveBox.x, slaveBox.y, slaveBox.width, slaveBox.height); +} + +/* NotebookPlaceSlaves -- + * Geometry manager hook. + */ +static void NotebookPlaceSlaves(void *recordPtr) +{ + Notebook *nb = recordPtr; + int currentIndex = nb->notebook.currentIndex; + if (currentIndex >= 0) { + NotebookDoLayout(nb); + NotebookPlaceSlave(nb, currentIndex); + } +} + +/* + * SelectTab(nb, index) -- + * Change the currently-selected tab. + */ +static void SelectTab(Notebook *nb, int index) +{ + Tab *tab = Ttk_SlaveData(nb->notebook.mgr,index); + int currentIndex = nb->notebook.currentIndex; + + if (index == currentIndex) { + return; + } + + if (TabState(nb, index) & TTK_STATE_DISABLED) { + return; + } + + /* Unhide the tab if it is currently hidden and being selected. + */ + if (tab->state == TAB_STATE_HIDDEN) { + tab->state = TAB_STATE_NORMAL; + } + + if (currentIndex >= 0) { + Ttk_UnmapSlave(nb->notebook.mgr, currentIndex); + } + + NotebookPlaceSlave(nb, index); + + nb->notebook.currentIndex = index; + TtkRedisplayWidget(&nb->core); + + TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged"); +} + +/* NextTab -- + * Returns the index of the next tab after the specified tab + * in the normal state (e.g., not hidden or disabled), + * or -1 if all tabs are disabled or hidden. + */ +static int NextTab(Notebook *nb, int index) +{ + int nTabs = Ttk_NumberSlaves(nb->notebook.mgr); + int nextIndex; + + /* Scan forward for following usable tab: + */ + for (nextIndex = index + 1; nextIndex < nTabs; ++nextIndex) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, nextIndex); + if (tab->state == TAB_STATE_NORMAL) { + return nextIndex; + } + } + + /* Not found -- scan backwards. + */ + for (nextIndex = index - 1; nextIndex >= 0; --nextIndex) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, nextIndex); + if (tab->state == TAB_STATE_NORMAL) { + return nextIndex; + } + } + + /* Still nothing. Give up. + */ + return -1; +} + +/* SelectNearestTab -- + * Handles the case where the current tab is forgotten, hidden, + * or destroyed. + * + * Unmap the current tab and schedule the next available one + * to be mapped at the next GM update. + */ +static void SelectNearestTab(Notebook *nb) +{ + int currentIndex = nb->notebook.currentIndex; + int nextIndex = NextTab(nb, currentIndex); + + if (currentIndex >= 0) { + Ttk_UnmapSlave(nb->notebook.mgr, currentIndex); + } + if (currentIndex != nextIndex) { + TtkSendVirtualEvent(nb->core.tkwin, "NotebookTabChanged"); + } + + nb->notebook.currentIndex = nextIndex; + Ttk_ManagerLayoutChanged(nb->notebook.mgr); + TtkRedisplayWidget(&nb->core); +} + +/* TabRemoved -- GM SlaveRemoved hook. + * Select the next tab if the current one is being removed. + * Adjust currentIndex to account for removed slave. + */ +static void TabRemoved(void *managerData, int index) +{ + Notebook *nb = managerData; + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index); + + if (index == nb->notebook.currentIndex) { + SelectNearestTab(nb); + } + + if (index < nb->notebook.currentIndex) { + --nb->notebook.currentIndex; + } + + DestroyTab(nb, tab); + + TtkRedisplayWidget(&nb->core); +} + +static int TabRequest(void *managerData, int index, int width, int height) +{ + return 1; +} + +/* AddTab -- + * Add new tab at specified index. + */ +static int AddTab( + Tcl_Interp *interp, Notebook *nb, + int destIndex, Tk_Window slaveWindow, + int objc, Tcl_Obj *const objv[]) +{ + Tab *tab; + if (!Ttk_Maintainable(interp, slaveWindow, nb->core.tkwin)) { + return TCL_ERROR; + } +#if 0 /* can't happen */ + if (Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow) >= 0) { + Tcl_AppendResult(interp, + Tk_PathName(slaveWindow), " already added", + NULL); + return TCL_ERROR; + } +#endif + + /* Create and insert tab. + */ + tab = CreateTab(interp, nb, slaveWindow); + if (!tab) { + return TCL_ERROR; + } + if (ConfigureTab(interp, nb, tab, slaveWindow, objc, objv) != TCL_OK) { + DestroyTab(nb, tab); + return TCL_ERROR; + } + + Ttk_InsertSlave(nb->notebook.mgr, destIndex, slaveWindow, tab); + + /* Adjust indices and/or autoselect first tab: + */ + if (nb->notebook.currentIndex < 0) { + SelectTab(nb, destIndex); + } else if (nb->notebook.currentIndex >= destIndex) { + ++nb->notebook.currentIndex; + } + + return TCL_OK; +} + +static Ttk_ManagerSpec NotebookManagerSpec = { + { "notebook", Ttk_GeometryRequestProc, Ttk_LostSlaveProc }, + NotebookSize, + NotebookPlaceSlaves, + TabRequest, + TabRemoved +}; + +/*------------------------------------------------------------------------ + * +++ Event handlers. + */ + +/* NotebookEventHandler -- + * Tracks the active tab. + */ +static const int NotebookEventMask + = StructureNotifyMask + | PointerMotionMask + | LeaveWindowMask + ; +static void NotebookEventHandler(ClientData clientData, XEvent *eventPtr) +{ + Notebook *nb = clientData; + + if (eventPtr->type == DestroyNotify) { /* Remove self */ + Tk_DeleteEventHandler(nb->core.tkwin, + NotebookEventMask, NotebookEventHandler, clientData); + } else if (eventPtr->type == MotionNotify) { + int index = IdentifyTab(nb, eventPtr->xmotion.x, eventPtr->xmotion.y); + ActivateTab(nb, index); + } else if (eventPtr->type == LeaveNotify) { + ActivateTab(nb, -1); + } +} + +/*------------------------------------------------------------------------ + * +++ Utilities. + */ + +/* FindTabIndex -- + * Find the index of the specified tab. + * Tab identifiers are one of: + * + * + positional specifications @x,y, + * + "current", + * + numeric indices [0..nTabs], + * + slave window names + * + * Stores index of specified tab in *index_rtn, -1 if not found. + * + * Returns TCL_ERROR and leaves an error message in interp->result + * if the tab identifier was incorrect. + * + * See also: GetTabIndex. + */ +static int FindTabIndex( + Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, int *index_rtn) +{ + const char *string = Tcl_GetString(objPtr); + int x, y; + + *index_rtn = -1; + + /* Check for @x,y ... + */ + if (string[0] == '@' && sscanf(string, "@%d,%d",&x,&y) == 2) { + *index_rtn = IdentifyTab(nb, x, y); + return TCL_OK; + } + + /* ... or "current" ... + */ + if (!strcmp(string, "current")) { + *index_rtn = nb->notebook.currentIndex; + return TCL_OK; + } + + /* ... or integer index or slave window name: + */ + if (Ttk_GetSlaveIndexFromObj( + interp, nb->notebook.mgr, objPtr, index_rtn) == TCL_OK) + { + return TCL_OK; + } + + /* Nothing matched; Ttk_GetSlaveIndexFromObj will have left error message. + */ + return TCL_ERROR; +} + +/* GetTabIndex -- + * Get the index of an existing tab. + * Tab identifiers are as per FindTabIndex. + * Returns TCL_ERROR if the tab does not exist. + */ +static int GetTabIndex( + Tcl_Interp *interp, Notebook *nb, Tcl_Obj *objPtr, int *index_rtn) +{ + int status = FindTabIndex(interp, nb, objPtr, index_rtn); + + if (status == TCL_OK && *index_rtn < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "tab '", Tcl_GetString(objPtr), "' not found", + NULL); + status = TCL_ERROR; + } + return status; +} + +/*------------------------------------------------------------------------ + * +++ Widget command routines. + */ + +/* $nb add window ?options ... ? + */ +static int NotebookAddCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + int index = Ttk_NumberSlaves(nb->notebook.mgr); + Tk_Window slaveWindow; + int slaveIndex; + Tab *tab; + + if (objc <= 2 || objc % 2 != 1) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value ...?"); + return TCL_ERROR; + } + + slaveWindow = Tk_NameToWindow(interp,Tcl_GetString(objv[2]),nb->core.tkwin); + if (!slaveWindow) { + return TCL_ERROR; + } + slaveIndex = Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow); + + if (slaveIndex < 0) { /* New tab */ + return AddTab(interp, nb, index, slaveWindow, objc-3,objv+3); + } + + tab = Ttk_SlaveData(nb->notebook.mgr, slaveIndex); + if (tab->state == TAB_STATE_HIDDEN) { + tab->state = TAB_STATE_NORMAL; + } + if (ConfigureTab(interp, nb, tab, slaveWindow, objc-4,objv+4) != TCL_OK) { + return TCL_ERROR; + } + + TtkRedisplayWidget(&nb->core); + + return TCL_OK; +} + +/* $nb insert $index $tab ?-option value ...? + * Insert new tab, or move existing one. + */ +static int NotebookInsertCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + int current = nb->notebook.currentIndex; + int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr); + int srcIndex, destIndex; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?"); + return TCL_ERROR; + } + + if (!strcmp(Tcl_GetString(objv[2]), "end")) { + destIndex = Ttk_NumberSlaves(nb->notebook.mgr); + } else if (TCL_OK != Ttk_GetSlaveIndexFromObj( + interp, nb->notebook.mgr, objv[2], &destIndex)) { + return TCL_ERROR; + } + + if (Tcl_GetString(objv[3])[0] == '.') { + /* Window name -- could be new or existing slave. + */ + Tk_Window slaveWindow = + Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin); + + if (!slaveWindow) { + return TCL_ERROR; + } + + srcIndex = Ttk_SlaveIndex(nb->notebook.mgr, slaveWindow); + if (srcIndex < 0) { /* New slave */ + return AddTab(interp, nb, destIndex, slaveWindow, objc-4,objv+4); + } + } else if (Ttk_GetSlaveIndexFromObj( + interp, nb->notebook.mgr, objv[3], &srcIndex) != TCL_OK) + { + return TCL_ERROR; + } + + /* Move existing slave: + */ + if (ConfigureTab(interp, nb, + Ttk_SlaveData(nb->notebook.mgr,srcIndex), + Ttk_SlaveWindow(nb->notebook.mgr,srcIndex), + objc-4,objv+4) != TCL_OK) + { + return TCL_ERROR; + } + + if (destIndex >= nSlaves) { + destIndex = nSlaves - 1; + } + Ttk_ReorderSlave(nb->notebook.mgr, srcIndex, destIndex); + + /* Adjust internal indexes: + */ + nb->notebook.activeIndex = -1; + if (current == srcIndex) { + nb->notebook.currentIndex = destIndex; + } else if (destIndex <= current && current < srcIndex) { + ++nb->notebook.currentIndex; + } else if (srcIndex < current && current <= destIndex) { + --nb->notebook.currentIndex; + } + + TtkRedisplayWidget(&nb->core); + + return TCL_OK; +} + +/* $nb forget $tab -- + * Removes the specified tab. + */ +static int NotebookForgetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + int index; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "tab"); + return TCL_ERROR; + } + + if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) { + return TCL_ERROR; + } + + Ttk_ForgetSlave(nb->notebook.mgr, index); + TtkRedisplayWidget(&nb->core); + + return TCL_OK; +} + +/* $nb hide $tab -- + * Hides the specified tab. + */ +static int NotebookHideCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + int index; + Tab *tab; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "tab"); + return TCL_ERROR; + } + + if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) { + return TCL_ERROR; + } + + tab = Ttk_SlaveData(nb->notebook.mgr, index); + tab->state = TAB_STATE_HIDDEN; + if (index == nb->notebook.currentIndex) { + SelectNearestTab(nb); + } + + TtkRedisplayWidget(&nb->core); + + return TCL_OK; +} + +/* $nb identify $x $y -- + * Returns name of tab element at $x,$y; empty string if none. + */ +static int NotebookIdentifyCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + static const char *whatTable[] = { "element", "tab", NULL }; + enum { IDENTIFY_ELEMENT, IDENTIFY_TAB }; + int what = IDENTIFY_ELEMENT; + Notebook *nb = recordPtr; + Ttk_Element element = NULL; + int x, y, tabIndex; + + if (objc < 4 || objc > 5) { + Tcl_WrongNumArgs(interp, 2,objv, "?what? x y"); + return TCL_ERROR; + } + + if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK + || (objc == 5 && + Tcl_GetIndexFromObj(interp, objv[2], whatTable, "option", 0, &what) + != TCL_OK) + ) { + return TCL_ERROR; + } + + tabIndex = IdentifyTab(nb, x, y); + if (tabIndex >= 0) { + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, tabIndex); + Ttk_State state = TabState(nb, tabIndex); + Ttk_Layout tabLayout = nb->notebook.tabLayout; + + Ttk_RebindSublayout(tabLayout, tab); + Ttk_PlaceLayout(tabLayout, state, tab->parcel); + + element = Ttk_IdentifyElement(tabLayout, x, y); + } + + switch (what) { + case IDENTIFY_ELEMENT: + if (element) { + const char *elementName = Ttk_ElementName(element); + Tcl_SetObjResult(interp,Tcl_NewStringObj(elementName,-1)); + } + break; + case IDENTIFY_TAB: + if (tabIndex >= 0) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(tabIndex)); + } + break; + } + return TCL_OK; +} + +/* $nb index $item -- + * Returns the integer index of the tab specified by $item, + * the empty string if $item does not identify a tab. + * See above for valid item formats. + */ +static int NotebookIndexCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + int index, status; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "tab"); + return TCL_ERROR; + } + + /* + * Special-case for "end": + */ + if (!strcmp("end", Tcl_GetString(objv[2]))) { + int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr); + Tcl_SetObjResult(interp, Tcl_NewIntObj(nSlaves)); + return TCL_OK; + } + + status = FindTabIndex(interp, nb, objv[2], &index); + if (status == TCL_OK && index >= 0) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + } + + return status; +} + +/* $nb select ?$item? -- + * Select the specified tab, or return the widget path of + * the currently-selected pane. + */ +static int NotebookSelectCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + + if (objc == 2) { + if (nb->notebook.currentIndex >= 0) { + Tk_Window pane = Ttk_SlaveWindow( + nb->notebook.mgr, nb->notebook.currentIndex); + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(pane), -1)); + } + return TCL_OK; + } else if (objc == 3) { + int index, status = GetTabIndex(interp, nb, objv[2], &index); + if (status == TCL_OK) { + SelectTab(nb, index); + } + return status; + } /*else*/ + Tcl_WrongNumArgs(interp, 2, objv, "?tab?"); + return TCL_ERROR; +} + +/* $nb tabs -- + * Return list of tabs. + */ +static int NotebookTabsCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + Ttk_Manager *mgr = nb->notebook.mgr; + Tcl_Obj *result; + int i; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + result = Tcl_NewListObj(0, NULL); + for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) { + const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i)); + Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(pathName,-1)); + } + Tcl_SetObjResult(interp, result); + + return TCL_OK; +} + +/* $nb tab $tab ?-option ?value -option value...?? + */ +static int NotebookTabCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Notebook *nb = recordPtr; + Ttk_Manager *mgr = nb->notebook.mgr; + int index; + Tk_Window slaveWindow; + Tab *tab; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "tab ?-option ?value??..."); + return TCL_ERROR; + } + + if (GetTabIndex(interp, nb, objv[2], &index) != TCL_OK) { + return TCL_ERROR; + } + + tab = Ttk_SlaveData(mgr, index); + slaveWindow = Ttk_SlaveWindow(mgr, index); + + if (objc == 3) { + return TtkEnumerateOptions(interp, tab, + PaneOptionSpecs, nb->notebook.paneOptionTable, slaveWindow); + } else if (objc == 4) { + return TtkGetOptionValue(interp, tab, objv[3], + nb->notebook.paneOptionTable, slaveWindow); + } /* else */ + + if (ConfigureTab(interp, nb, tab, slaveWindow, objc-3,objv+3) != TCL_OK) { + return TCL_ERROR; + } + + /* If the current tab has become disabled or hidden, + * select the next nondisabled, unhidden one: + */ + if (index == nb->notebook.currentIndex && tab->state != TAB_STATE_NORMAL) { + SelectNearestTab(nb); + } + + return TCL_OK; +} + +/* Subcommand table: + */ +static const Ttk_Ensemble NotebookCommands[] = { + { "add", NotebookAddCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "forget", NotebookForgetCommand,0 }, + { "hide", NotebookHideCommand,0 }, + { "identify", NotebookIdentifyCommand,0 }, + { "index", NotebookIndexCommand,0 }, + { "insert", NotebookInsertCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "select", NotebookSelectCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "tab", NotebookTabCommand,0 }, + { "tabs", NotebookTabsCommand,0 }, + { 0,0,0 } +}; + +/*------------------------------------------------------------------------ + * +++ Widget class hooks. + */ + +static void NotebookInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Notebook *nb = recordPtr; + + nb->notebook.mgr = Ttk_CreateManager( + &NotebookManagerSpec, recordPtr, nb->core.tkwin); + + nb->notebook.tabOptionTable = Tk_CreateOptionTable(interp,TabOptionSpecs); + nb->notebook.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs); + + nb->notebook.currentIndex = -1; + nb->notebook.activeIndex = -1; + nb->notebook.tabLayout = 0; + + nb->notebook.clientArea = Ttk_MakeBox(0,0,1,1); + + Tk_CreateEventHandler( + nb->core.tkwin, NotebookEventMask, NotebookEventHandler, recordPtr); +} + +static void NotebookCleanup(void *recordPtr) +{ + Notebook *nb = recordPtr; + + Ttk_DeleteManager(nb->notebook.mgr); + if (nb->notebook.tabLayout) + Ttk_FreeLayout(nb->notebook.tabLayout); +} + +static int NotebookConfigure(Tcl_Interp *interp, void *clientData, int mask) +{ + Notebook *nb = clientData; + + /* + * Error-checks: + */ + if (nb->notebook.paddingObj) { + /* Check for valid -padding: */ + Ttk_Padding unused; + if (Ttk_GetPaddingFromObj( + interp, nb->core.tkwin, nb->notebook.paddingObj, &unused) + != TCL_OK) { + return TCL_ERROR; + } + } + + return TtkCoreConfigure(interp, clientData, mask); +} + +/* NotebookGetLayout -- + * GetLayout widget hook. + */ +static Ttk_Layout NotebookGetLayout( + Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) +{ + Notebook *nb = recordPtr; + Ttk_Layout notebookLayout = TtkWidgetGetLayout(interp, theme, recordPtr); + Ttk_Layout tabLayout; + + if (!notebookLayout) { + return NULL; + } + + tabLayout = Ttk_CreateSublayout( + interp, theme, notebookLayout, ".Tab", nb->notebook.tabOptionTable); + + if (tabLayout) { + if (nb->notebook.tabLayout) { + Ttk_FreeLayout(nb->notebook.tabLayout); + } + nb->notebook.tabLayout = tabLayout; + } + + return notebookLayout; +} + +/*------------------------------------------------------------------------ + * +++ Display routines. + */ + +static void DisplayTab(Notebook *nb, int index, Drawable d) +{ + Ttk_Layout tabLayout = nb->notebook.tabLayout; + Tab *tab = Ttk_SlaveData(nb->notebook.mgr, index); + Ttk_State state = TabState(nb, index); + + if (tab->state != TAB_STATE_HIDDEN) { + Ttk_RebindSublayout(tabLayout, tab); + Ttk_PlaceLayout(tabLayout, state, tab->parcel); + Ttk_DrawLayout(tabLayout, state, d); + } +} + +static void NotebookDisplay(void *clientData, Drawable d) +{ + Notebook *nb = clientData; + int nSlaves = Ttk_NumberSlaves(nb->notebook.mgr); + int index; + + /* Draw notebook background (base layout): + */ + Ttk_DrawLayout(nb->core.layout, nb->core.state, d); + + /* Draw tabs from left to right, but draw the current tab last + * so it will overwrite its neighbors. + */ + for (index = 0; index < nSlaves; ++index) { + if (index != nb->notebook.currentIndex) { + DisplayTab(nb, index, d); + } + } + if (nb->notebook.currentIndex >= 0) { + DisplayTab(nb, nb->notebook.currentIndex, d); + } +} + +/*------------------------------------------------------------------------ + * +++ Widget specification and layout definitions. + */ + +static WidgetSpec NotebookWidgetSpec = +{ + "TNotebook", /* className */ + sizeof(Notebook), /* recordSize */ + NotebookOptionSpecs, /* optionSpecs */ + NotebookCommands, /* subcommands */ + NotebookInitialize, /* initializeProc */ + NotebookCleanup, /* cleanupProc */ + NotebookConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + NotebookGetLayout, /* getLayoutProc */ + NotebookSize, /* geometryProc */ + NotebookDoLayout, /* layoutProc */ + NotebookDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(NotebookLayout) + TTK_NODE("Notebook.client", TTK_FILL_BOTH) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(TabLayout) + TTK_GROUP("Notebook.tab", TTK_FILL_BOTH, + TTK_GROUP("Notebook.padding", TTK_PACK_TOP|TTK_FILL_BOTH, + TTK_GROUP("Notebook.focus", TTK_PACK_TOP|TTK_FILL_BOTH, + TTK_NODE("Notebook.label", TTK_PACK_TOP)))) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Initialization. + */ + +MODULE_SCOPE +void TtkNotebook_Init(Tcl_Interp *interp) +{ + Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(themePtr, "Tab", TabLayout); + Ttk_RegisterLayout(themePtr, "TNotebook", NotebookLayout); + + RegisterWidget(interp, "ttk::notebook", &NotebookWidgetSpec); +} + +/*EOF*/ diff --git a/generic/ttk/ttkPanedwindow.c b/generic/ttk/ttkPanedwindow.c new file mode 100644 index 0000000..065774e --- /dev/null +++ b/generic/ttk/ttkPanedwindow.c @@ -0,0 +1,975 @@ +/* + * Copyright (c) 2005, Joe English. Freely redistributable. + * + * ttk::panedwindow widget implementation. + * + * TODO: track active/pressed sash. + */ + +#include <string.h> +#include <tk.h> +#include "ttkManager.h" +#include "ttkTheme.h" +#include "ttkWidget.h" + +/*------------------------------------------------------------------------ + * +++ Layout algorithm. + * + * (pos=x/y, size=width/height, depending on -orient=horizontal/vertical) + * + * Each pane carries two pieces of state: the request size and the + * position of the following sash. (The final pane has no sash, + * its sash position is used as a sentinel value). + * + * Pane geometry is determined by the sash positions. + * When resizing, sash positions are computed from the request sizes, + * the available space, and pane weights (see PlaceSashes()). + * This ensures continuous resize behavior (that is: changing + * the size by X pixels then changing the size by Y pixels + * gives the same result as changing the size by X+Y pixels + * in one step). + * + * The request size is initially set to the slave window's requested size. + * When the user drags a sash, each pane's request size is set to its + * actual size. This ensures that panes "stay put" on the next resize. + * + * If reqSize == 0, use 0 for the weight as well. This ensures that + * "collapsed" panes stay collapsed during a resize, regardless of + * their nominal -weight. + * + * +++ Invariants. + * + * #sash = #pane - 1 + * pos(pane[0]) = 0 + * pos(sash[i]) = pos(pane[i]) + size(pane[i]), 0 <= i <= #sash + * pos(pane[i+1]) = pos(sash[i]) + size(sash[i]), 0 <= i < #sash + * pos(sash[#sash]) = size(pw) // sentinel value, constraint + * + * size(pw) = sum(size(pane(0..#pane))) + sum(size(sash(0..#sash))) + * size(pane[i]) >= 0, for 0 <= i < #pane + * size(sash[i]) >= 0, for 0 <= i < #sash + * ==> pos(pane[i]) <= pos(sash[i]) <= pos(pane[i+1]), for 0 <= i < #sash + * + * Assumption: all sashes are the same size. + */ + +/*------------------------------------------------------------------------ + * +++ Widget record. + */ + +typedef struct { + Tcl_Obj *orientObj; + int orient; + int width; + int height; + Ttk_Manager *mgr; + Tk_OptionTable paneOptionTable; + Ttk_Layout sashLayout; + int sashThickness; +} PanedPart; + +typedef struct { + WidgetCore core; + PanedPart paned; +} Paned; + +/* @@@ NOTE: -orient is readonly 'cause dynamic oriention changes NYI + */ +static Tk_OptionSpec PanedOptionSpecs[] = { + {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical", + Tk_Offset(Paned,paned.orientObj), Tk_Offset(Paned,paned.orient), + 0,(ClientData)ttkOrientStrings,READONLY_OPTION|STYLE_CHANGED }, + {TK_OPTION_INT, "-width", "width", "Width", "0", + -1,Tk_Offset(Paned,paned.width), + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-height", "height", "Height", "0", + -1,Tk_Offset(Paned,paned.height), + 0,0,GEOMETRY_CHANGED }, + + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/*------------------------------------------------------------------------ + * +++ Slave pane record. + */ +typedef struct { + int reqSize; /* Pane request size */ + int sashPos; /* Folowing sash position */ + int weight; /* Pane -weight, for resizing */ +} Pane; + +static Tk_OptionSpec PaneOptionSpecs[] = { + {TK_OPTION_INT, "-weight", "weight", "Weight", "0", + -1,Tk_Offset(Pane,weight), 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} +}; + +/* CreatePane -- + * Create a new pane record. + */ +static Pane *CreatePane(Tcl_Interp *interp, Paned *pw, Tk_Window slaveWindow) +{ + Tk_OptionTable optionTable = pw->paned.paneOptionTable; + void *record = ckalloc(sizeof(Pane)); + Pane *pane = record; + + memset(record, 0, sizeof(Pane)); + if (Tk_InitOptions(interp, record, optionTable, slaveWindow) != TCL_OK) { + ckfree(record); + return NULL; + } + + pane->reqSize + = pw->paned.orient == TTK_ORIENT_HORIZONTAL + ? Tk_ReqWidth(slaveWindow) : Tk_ReqHeight(slaveWindow); + + return pane; +} + +/* DestroyPane -- + * Free pane record. + */ +static void DestroyPane(Paned *pw, Pane *pane) +{ + void *record = pane; + Tk_FreeConfigOptions(record, pw->paned.paneOptionTable, pw->core.tkwin); + ckfree(record); +} + +/* ConfigurePane -- + * Set pane options. + */ +static int ConfigurePane( + Tcl_Interp *interp, Paned *pw, Pane *pane, Tk_Window slaveWindow, + int objc, Tcl_Obj *const objv[]) +{ + Ttk_Manager *mgr = pw->paned.mgr; + Tk_SavedOptions savedOptions; + int mask = 0; + + if (Tk_SetOptions(interp, (void*)pane, pw->paned.paneOptionTable, + objc, objv, slaveWindow, &savedOptions, &mask) != TCL_OK) + { + return TCL_ERROR; + } + + /* Sanity-check: + */ + if (pane->weight < 0) { + Tcl_AppendResult(interp, "-weight must be nonnegative", NULL); + goto error; + } + + /* Done. + */ + Tk_FreeSavedOptions(&savedOptions); + Ttk_ManagerSizeChanged(mgr); + return TCL_OK; + +error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; +} + + +/*------------------------------------------------------------------------ + * +++ Sash adjustment. + */ + +/* ShoveUp -- + * Place sash i at specified position, recursively shoving + * previous sashes upwards as needed, until hitting the top + * of the window. If that happens, shove back down. + * + * Returns: final position of sash i. + */ + +static int ShoveUp(Paned *pw, int i, int pos) +{ + Pane *pane = Ttk_SlaveData(pw->paned.mgr, i); + int sashThickness = pw->paned.sashThickness; + + if (i == 0) { + if (pos < 0) + pos = 0; + } else { + Pane *prevPane = Ttk_SlaveData(pw->paned.mgr, i-1); + if (pos < prevPane->sashPos + sashThickness) + pos = ShoveUp(pw, i-1, pos - sashThickness) + sashThickness; + } + return pane->sashPos = pos; +} + +/* ShoveDown -- + * Same as ShoveUp, but going in the opposite direction + * and stopping at the sentinel sash. + */ +static int ShoveDown(Paned *pw, int i, int pos) +{ + Pane *pane = Ttk_SlaveData(pw->paned.mgr,i); + int sashThickness = pw->paned.sashThickness; + + if (i == Ttk_NumberSlaves(pw->paned.mgr) - 1) { + pos = pane->sashPos; /* Sentinel value == master window size */ + } else { + Pane *nextPane = Ttk_SlaveData(pw->paned.mgr,i+1); + if (pos + sashThickness > nextPane->sashPos) + pos = ShoveDown(pw, i+1, pos + sashThickness) - sashThickness; + } + return pane->sashPos = pos; +} + +/* PanedSize -- + * Compute the requested size of the paned widget + * from the individual pane request sizes. + * + * Used as the WidgetSpec sizeProc and the ManagerSpec sizeProc. + */ +static int PanedSize(void *recordPtr, int *widthPtr, int *heightPtr) +{ + Paned *pw = recordPtr; + int nPanes = Ttk_NumberSlaves(pw->paned.mgr); + int nSashes = nPanes - 1; + int sashThickness = pw->paned.sashThickness; + int width = 0, height = 0; + int index; + + if (pw->paned.orient == TTK_ORIENT_HORIZONTAL) { + for (index = 0; index < nPanes; ++index) { + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index); + + if (height < Tk_ReqHeight(slaveWindow)) + height = Tk_ReqHeight(slaveWindow); + width += pane->reqSize; + } + width += nSashes * sashThickness; + } else { + for (index = 0; index < nPanes; ++index) { + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index); + + if (width < Tk_ReqWidth(slaveWindow)) + width = Tk_ReqWidth(slaveWindow); + height += pane->reqSize; + } + height += nSashes * sashThickness; + } + + *widthPtr = pw->paned.width > 0 ? pw->paned.width : width; + *heightPtr = pw->paned.height > 0 ? pw->paned.height : height; + return 1; +} + +/* AdjustPanes -- + * Set pane request sizes from sash positions. + * + * NOTE: + * AdjustPanes followed by PlaceSashes (called during relayout) + * will leave the sashes in the same place, as long as available size + * remains contant. + */ +static void AdjustPanes(Paned *pw) +{ + int sashThickness = pw->paned.sashThickness; + int pos = 0; + int index; + + for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) { + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + int size = pane->sashPos - pos; + pane->reqSize = size >= 0 ? size : 0; + pos = pane->sashPos + sashThickness; + } +} + +/* PlaceSashes -- + * Set sash positions from pane request sizes and available space. + * The sentinel sash position is set to the available space. + * + * Allocate pane->reqSize pixels to each pane, and distribute + * the difference = available size - requested size according + * to pane->weight. + * + * If there's still some left over, squeeze panes from the bottom up + * (This can happen if all weights are zero, or if one or more panes + * are too small to absorb the required shrinkage). + * + * Notes: + * This doesn't distribute the remainder pixels as evenly as it could + * when more than one pane has weight > 1. + */ +static void PlaceSashes(Paned *pw, int width, int height) +{ + Ttk_Manager *mgr = pw->paned.mgr; + int nPanes = Ttk_NumberSlaves(mgr); + int sashThickness = pw->paned.sashThickness; + int available = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? width : height; + int reqSize = 0, totalWeight = 0; + int difference, delta, remainder, pos, i; + + if (nPanes == 0) + return; + + /* Compute total required size and total available weight: + */ + for (i = 0; i < nPanes; ++i) { + Pane *pane = Ttk_SlaveData(mgr, i); + reqSize += pane->reqSize; + totalWeight += pane->weight * (pane->reqSize != 0); + } + + /* Compute difference to be redistributed: + */ + difference = available - reqSize - sashThickness*(nPanes-1); + if (totalWeight != 0) { + delta = difference / totalWeight; + remainder = difference % totalWeight; + if (remainder < 0) { + --delta; + remainder += totalWeight; + } + } else { + delta = remainder = 0; + } + /* ASSERT: 0 <= remainder < totalWeight */ + + /* Place sashes: + */ + pos = 0; + for (i = 0; i < nPanes; ++i) { + Pane *pane = Ttk_SlaveData(mgr, i); + int weight = pane->weight * (pane->reqSize != 0); + int size = pane->reqSize + delta * weight; + + if (weight > remainder) + weight = remainder; + remainder -= weight; + size += weight; + + if (size < 0) + size = 0; + + pane->sashPos = (pos += size); + pos += sashThickness; + } + + /* Handle emergency shrink/emergency stretch: + * Set sentinel sash position to end of widget, + * shove preceding sashes up. + */ + ShoveUp(pw, nPanes - 1, available); +} + +/* PlacePanes -- + * Places slave panes based on sash positions. + */ +static void PlacePanes(Paned *pw) +{ + int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL; + int width = Tk_Width(pw->core.tkwin), height = Tk_Height(pw->core.tkwin); + int sashThickness = pw->paned.sashThickness; + int pos = 0; + int index; + + for (index = 0; index < Ttk_NumberSlaves(pw->paned.mgr); ++index) { + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + int size = pane->sashPos - pos; + + if (size > 0) { + if (horizontal) { + Ttk_PlaceSlave(pw->paned.mgr, index, pos, 0, size, height); + } else { + Ttk_PlaceSlave(pw->paned.mgr, index, 0, pos, width, size); + } + } else { + Ttk_UnmapSlave(pw->paned.mgr, index); + } + + pos = pane->sashPos + sashThickness; + } +} + +/*------------------------------------------------------------------------ + * +++ Manager specification. + */ + +static void PanedPlaceSlaves(void *managerData) +{ + Paned *pw = managerData; + PlaceSashes(pw, Tk_Width(pw->core.tkwin), Tk_Height(pw->core.tkwin)); + PlacePanes(pw); +} + +static void PaneRemoved(void *managerData, int index) +{ + Paned *pw = managerData; + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + DestroyPane(pw, pane); +} + +static int AddPane( + Tcl_Interp *interp, Paned *pw, + int destIndex, Tk_Window slaveWindow, + int objc, Tcl_Obj *const objv[]) +{ + Pane *pane; + if (!Ttk_Maintainable(interp, slaveWindow, pw->core.tkwin)) { + return TCL_ERROR; + } + if (Ttk_SlaveIndex(pw->paned.mgr, slaveWindow) >= 0) { + Tcl_AppendResult(interp, + Tk_PathName(slaveWindow), " already added", + NULL); + return TCL_ERROR; + } + + pane = CreatePane(interp, pw, slaveWindow); + if (!pane) { + return TCL_ERROR; + } + if (ConfigurePane(interp, pw, pane, slaveWindow, objc, objv) != TCL_OK) { + DestroyPane(pw, pane); + return TCL_ERROR; + } + + Ttk_InsertSlave(pw->paned.mgr, destIndex, slaveWindow, pane); + return TCL_OK; +} + +/* PaneRequest -- + * Only update pane request size if slave is currently unmapped. + * Geometry requests from mapped slaves are not directly honored + * in order to avoid unexpected pane resizes (esp. while the + * user is dragging a sash [#1325286]). + */ +static int PaneRequest(void *managerData, int index, int width, int height) +{ + Paned *pw = managerData; + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + Tk_Window slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, index); + int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL; + + if (!Tk_IsMapped(slaveWindow)) { + pane->reqSize = horizontal ? width : height; + } + return 1; +} + +static Ttk_ManagerSpec PanedManagerSpec = { + { "panedwindow", Ttk_GeometryRequestProc, Ttk_LostSlaveProc }, + PanedSize, + PanedPlaceSlaves, + PaneRequest, + PaneRemoved +}; + +/*------------------------------------------------------------------------ + * +++ Event handler. + * + * <<NOTE-PW-LEAVE-NOTIFYINFERIOR>> + * Tk does not execute binding scripts for <Leave> events when + * the pointer crosses from a parent to a child. This widget + * needs to know when that happens, though, so it can reset + * the cursor. + * + * This event handler generates an <<EnteredChild>> virtual event + * on LeaveNotify/NotifyInferior. + */ + +static const unsigned PanedEventMask = LeaveWindowMask; +static void PanedEventProc(ClientData clientData, XEvent *eventPtr) +{ + WidgetCore *corePtr = clientData; + if ( eventPtr->type == LeaveNotify + && eventPtr->xcrossing.detail == NotifyInferior) + { + TtkSendVirtualEvent(corePtr->tkwin, "EnteredChild"); + } +} + +/*------------------------------------------------------------------------ + * +++ Initialization and cleanup hooks. + */ + +static void PanedInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Paned *pw = recordPtr; + + Tk_CreateEventHandler(pw->core.tkwin, + PanedEventMask, PanedEventProc, recordPtr); + pw->paned.mgr = Ttk_CreateManager(&PanedManagerSpec, pw, pw->core.tkwin); + pw->paned.paneOptionTable = Tk_CreateOptionTable(interp,PaneOptionSpecs); + pw->paned.sashLayout = 0; + pw->paned.sashThickness = 1; +} + +static void PanedCleanup(void *recordPtr) +{ + Paned *pw = recordPtr; + + if (pw->paned.sashLayout) + Ttk_FreeLayout(pw->paned.sashLayout); + Tk_DeleteEventHandler(pw->core.tkwin, + PanedEventMask, PanedEventProc, recordPtr); + Ttk_DeleteManager(pw->paned.mgr); +} + +/* Post-configuration hook. + */ +static int PanedPostConfigure(Tcl_Interp *interp, void *clientData, int mask) +{ + Paned *pw = clientData; + + if (mask & GEOMETRY_CHANGED) { + /* User has changed -width or -height. + * Recalculate sash positions based on requested size. + */ + Tk_Window tkwin = pw->core.tkwin; + PlaceSashes(pw, + pw->paned.width > 0 ? pw->paned.width : Tk_Width(tkwin), + pw->paned.height > 0 ? pw->paned.height : Tk_Height(tkwin)); + } + + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Layout management hooks. + */ +static Ttk_Layout PanedGetLayout( + Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr) +{ + Paned *pw = recordPtr; + Ttk_Layout panedLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr); + + if (panedLayout) { + int horizontal = pw->paned.orient == TTK_ORIENT_HORIZONTAL; + const char *layoutName = + horizontal ? ".Vertical.Sash" : ".Horizontal.Sash"; + Ttk_Layout sashLayout = Ttk_CreateSublayout( + interp, themePtr, panedLayout, layoutName, pw->core.optionTable); + + if (sashLayout) { + int sashWidth, sashHeight; + + Ttk_LayoutSize(sashLayout, 0, &sashWidth, &sashHeight); + pw->paned.sashThickness = horizontal ? sashWidth : sashHeight; + + if (pw->paned.sashLayout) + Ttk_FreeLayout(pw->paned.sashLayout); + pw->paned.sashLayout = sashLayout; + } else { + Ttk_FreeLayout(panedLayout); + return 0; + } + } + + return panedLayout; +} + +/*------------------------------------------------------------------------ + * +++ Drawing routines. + */ + +/* SashLayout -- + * Place the sash sublayout after the specified pane, + * in preparation for drawing. + */ +static Ttk_Layout SashLayout(Paned *pw, int index) +{ + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + int thickness = pw->paned.sashThickness, + height = Tk_Height(pw->core.tkwin), + width = Tk_Width(pw->core.tkwin), + sashPos = pane->sashPos; + + Ttk_PlaceLayout( + pw->paned.sashLayout, pw->core.state, + pw->paned.orient == TTK_ORIENT_HORIZONTAL + ? Ttk_MakeBox(sashPos, 0, thickness, height) + : Ttk_MakeBox(0, sashPos, width, thickness)); + + return pw->paned.sashLayout; +} + +static void DrawSash(Paned *pw, int index, Drawable d) +{ + Ttk_DrawLayout(SashLayout(pw, index), pw->core.state, d); +} + +static void PanedDisplay(void *recordPtr, Drawable d) +{ + Paned *pw = recordPtr; + int i, nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1; + + TtkWidgetDisplay(recordPtr, d); + for (i = 0; i < nSashes; ++i) { + DrawSash(pw, i, d); + } +} + +/*------------------------------------------------------------------------ + * +++ Widget commands. + */ + +/* $pw add window [ options ... ] + */ +static int PanedAddCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Paned *pw = recordPtr; + Tk_Window slaveWindow; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + + slaveWindow = Tk_NameToWindow( + interp, Tcl_GetString(objv[2]), pw->core.tkwin); + + if (!slaveWindow) { + return TCL_ERROR; + } + + return AddPane(interp, pw, Ttk_NumberSlaves(pw->paned.mgr), slaveWindow, + objc - 3, objv + 3); +} + +/* $pw insert $index $slave ?-option value ...? + * Insert new slave, or move existing one. + */ +static int PanedInsertCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Paned *pw = recordPtr; + int nSlaves = Ttk_NumberSlaves(pw->paned.mgr); + int srcIndex, destIndex; + Tk_Window slaveWindow; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2,objv, "index slave ?-option value ...?"); + return TCL_ERROR; + } + + slaveWindow = Tk_NameToWindow( + interp, Tcl_GetString(objv[3]), pw->core.tkwin); + if (!slaveWindow) { + return TCL_ERROR; + } + + if (!strcmp(Tcl_GetString(objv[2]), "end")) { + destIndex = Ttk_NumberSlaves(pw->paned.mgr); + } else if (TCL_OK != Ttk_GetSlaveIndexFromObj( + interp,pw->paned.mgr,objv[2],&destIndex)) + { + return TCL_ERROR; + } + + srcIndex = Ttk_SlaveIndex(pw->paned.mgr, slaveWindow); + if (srcIndex < 0) { /* New slave: */ + return AddPane(interp, pw, destIndex, slaveWindow, objc-4, objv+4); + } /* else -- move existing slave: */ + + if (destIndex >= nSlaves) + destIndex = nSlaves - 1; + Ttk_ReorderSlave(pw->paned.mgr, srcIndex, destIndex); + + return objc == 4 ? TCL_OK : + ConfigurePane(interp, pw, + Ttk_SlaveData(pw->paned.mgr, destIndex), + Ttk_SlaveWindow(pw->paned.mgr, destIndex), + objc-4,objv+4); +} + +/* $pw forget $pane + */ +static int PanedForgetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Paned *pw = recordPtr; + int paneIndex; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2,objv, "pane"); + return TCL_ERROR; + } + + if (TCL_OK != Ttk_GetSlaveIndexFromObj( + interp, pw->paned.mgr, objv[2], &paneIndex)) + { + return TCL_ERROR; + } + Ttk_ForgetSlave(pw->paned.mgr, paneIndex); + + return TCL_OK; +} + +/* $pw identify ?what? $x $y -- + * Return index of sash at $x,$y + */ +static int PanedIdentifyCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + const char *whatTable[] = { "element", "sash", NULL }; + enum { IDENTIFY_ELEMENT, IDENTIFY_SASH }; + int what = IDENTIFY_SASH; + Paned *pw = recordPtr; + int sashThickness = pw->paned.sashThickness; + int nSashes = Ttk_NumberSlaves(pw->paned.mgr) - 1; + int x, y, pos; + int index; + + if (objc < 4 || objc > 5) { + Tcl_WrongNumArgs(interp, 2,objv, "?what? x y"); + return TCL_ERROR; + } + + if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK + || (objc == 5 && + Tcl_GetIndexFromObj(interp, objv[2], whatTable, "option", 0, &what) + != TCL_OK) + ) { + return TCL_ERROR; + } + + pos = pw->paned.orient == TTK_ORIENT_HORIZONTAL ? x : y; + for (index = 0; index < nSashes; ++index) { + Pane *pane = Ttk_SlaveData(pw->paned.mgr, index); + if (pane->sashPos <= pos && pos <= pane->sashPos + sashThickness) { + /* Found it. */ + switch (what) { + case IDENTIFY_SASH: + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + return TCL_OK; + case IDENTIFY_ELEMENT: + { + Ttk_Element element = + Ttk_IdentifyElement(SashLayout(pw, index), x, y); + if (element) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj(Ttk_ElementName(element), -1)); + } + return TCL_OK; + } + } + } + } + + return TCL_OK; /* nothing found - return empty string */ +} + +/* $pw pane $pane ?-option ?value -option value ...?? + * Query/modify pane options. + */ +static int PanedPaneCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Paned *pw = recordPtr; + int paneIndex; + Tk_Window slaveWindow; + Pane *pane; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value ...?"); + return TCL_ERROR; + } + + if (TCL_OK != Ttk_GetSlaveIndexFromObj( + interp,pw->paned.mgr,objv[2],&paneIndex)) + { + return TCL_ERROR; + } + + pane = Ttk_SlaveData(pw->paned.mgr, paneIndex); + slaveWindow = Ttk_SlaveWindow(pw->paned.mgr, paneIndex); + + switch (objc) { + case 3: + return TtkEnumerateOptions(interp, pane, PaneOptionSpecs, + pw->paned.paneOptionTable, slaveWindow); + case 4: + return TtkGetOptionValue(interp, pane, objv[3], + pw->paned.paneOptionTable, slaveWindow); + default: + return ConfigurePane(interp, pw, pane, slaveWindow, objc-3,objv+3); + } +} + +/* $pw panes -- + * Return list of managed panes. + */ +static int PanedPanesCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Paned *pw = recordPtr; + Ttk_Manager *mgr = pw->paned.mgr; + Tcl_Obj *panes; + int i; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + panes = Tcl_NewListObj(0, NULL); + for (i = 0; i < Ttk_NumberSlaves(mgr); ++i) { + const char *pathName = Tk_PathName(Ttk_SlaveWindow(mgr,i)); + Tcl_ListObjAppendElement(interp, panes, Tcl_NewStringObj(pathName,-1)); + } + Tcl_SetObjResult(interp, panes); + + return TCL_OK; +} + + +/* $pw sashpos $index ?$newpos? + * Query or modify sash position. + */ +static int PanedSashposCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Paned *pw = recordPtr; + int sashIndex, position = -1; + Pane *pane; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 2,objv, "index ?newpos?"); + return TCL_ERROR; + } + if (Tcl_GetIntFromObj(interp, objv[2], &sashIndex) != TCL_OK) { + return TCL_ERROR; + } + if (sashIndex < 0 || sashIndex >= Ttk_NumberSlaves(pw->paned.mgr) - 1) { + Tcl_AppendResult(interp, + "sash index ", Tcl_GetString(objv[2]), " out of range", + NULL); + return TCL_ERROR; + } + + pane = Ttk_SlaveData(pw->paned.mgr, sashIndex); + + if (objc == 3) { + Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos)); + return TCL_OK; + } + /* else -- set new sash position */ + + if (Tcl_GetIntFromObj(interp, objv[3], &position) != TCL_OK) { + return TCL_ERROR; + } + + if (position < pane->sashPos) { + ShoveUp(pw, sashIndex, position); + } else { + ShoveDown(pw, sashIndex, position); + } + + AdjustPanes(pw); + Ttk_ManagerLayoutChanged(pw->paned.mgr); + + Tcl_SetObjResult(interp, Tcl_NewIntObj(pane->sashPos)); + return TCL_OK; +} + +static const Ttk_Ensemble PanedCommands[] = { + { "add", PanedAddCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "forget", PanedForgetCommand,0 }, + { "identify", PanedIdentifyCommand,0 }, + { "insert", PanedInsertCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "pane", PanedPaneCommand,0 }, + { "panes", PanedPanesCommand,0 }, + { "sashpos", PanedSashposCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { 0,0,0 } +}; + +/*------------------------------------------------------------------------ + * +++ Widget specification. + */ + +static WidgetSpec PanedWidgetSpec = +{ + "TPanedwindow", /* className */ + sizeof(Paned), /* recordSize */ + PanedOptionSpecs, /* optionSpecs */ + PanedCommands, /* subcommands */ + PanedInitialize, /* initializeProc */ + PanedCleanup, /* cleanupProc */ + TtkCoreConfigure, /* configureProc */ + PanedPostConfigure, /* postConfigureProc */ + PanedGetLayout, /* getLayoutProc */ + PanedSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + PanedDisplay /* displayProc */ +}; + +/*------------------------------------------------------------------------ + * +++ Elements and layouts. + */ + +static const int DEFAULT_SASH_THICKNESS = 5; + +typedef struct { + Tcl_Obj *thicknessObj; +} SashElement; + +static Ttk_ElementOptionSpec SashElementOptions[] = { + { "-sashthickness", TK_OPTION_INT, + Tk_Offset(SashElement,thicknessObj), "5" }, + { NULL, 0, 0, NULL } +}; + +static void SashElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SashElement *sash = elementRecord; + int thickness = DEFAULT_SASH_THICKNESS; + Tcl_GetIntFromObj(NULL, sash->thicknessObj, &thickness); + *widthPtr = *heightPtr = thickness; +} + +static Ttk_ElementSpec SashElementSpec = { + TK_STYLE_VERSION_2, + sizeof(SashElement), + SashElementOptions, + SashElementSize, + TtkNullElementDraw +}; + +TTK_BEGIN_LAYOUT(PanedLayout) + TTK_NODE("Panedwindow.background", 0)/* @@@ BUG: empty layouts don't work */ +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(HorizontalSashLayout) + TTK_NODE("Sash.hsash", TTK_FILL_X) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(VerticalSashLayout) + TTK_NODE("Sash.vsash", TTK_FILL_Y) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Registration routine. + */ +MODULE_SCOPE +void TtkPanedwindow_Init(Tcl_Interp *interp) +{ + Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp); + RegisterWidget(interp, "ttk::panedwindow", &PanedWidgetSpec); + + Ttk_RegisterElement(interp, themePtr, "hsash", &SashElementSpec, 0); + Ttk_RegisterElement(interp, themePtr, "vsash", &SashElementSpec, 0); + + Ttk_RegisterLayout(themePtr, "TPanedwindow", PanedLayout); + Ttk_RegisterLayout(themePtr, "Horizontal.Sash", HorizontalSashLayout); + Ttk_RegisterLayout(themePtr, "Vertical.Sash", VerticalSashLayout); +} + diff --git a/generic/ttk/ttkProgress.c b/generic/ttk/ttkProgress.c new file mode 100644 index 0000000..4dc50a2 --- /dev/null +++ b/generic/ttk/ttkProgress.c @@ -0,0 +1,545 @@ +/* + * Copyright (c) Joe English, Pat Thoyts, Michael Kirkham + * + * ttk::progressbar widget. + */ + +#include <math.h> +#include <tk.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" + +/*------------------------------------------------------------------------ + * +++ Widget record: + */ + +#define DEF_PROGRESSBAR_LENGTH "100" +enum { + TTK_PROGRESSBAR_DETERMINATE, TTK_PROGRESSBAR_INDETERMINATE +}; +static const char *const ProgressbarModeStrings[] = { + "determinate", "indeterminate", NULL +}; + +typedef struct { + Tcl_Obj *orientObj; + Tcl_Obj *lengthObj; + Tcl_Obj *modeObj; + Tcl_Obj *variableObj; + Tcl_Obj *maximumObj; + Tcl_Obj *valueObj; + Tcl_Obj *phaseObj; + + int mode; + Ttk_TraceHandle *variableTrace; /* Trace handle for -variable option */ + int period; /* Animation period */ + int maxPhase; /* Max animation phase */ + Tcl_TimerToken timer; /* Animation timer */ + +} ProgressbarPart; + +typedef struct { + WidgetCore core; + ProgressbarPart progress; +} Progressbar; + +static Tk_OptionSpec ProgressbarOptionSpecs[] = +{ + {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", + "horizontal", Tk_Offset(Progressbar,progress.orientObj), -1, + 0, (ClientData)ttkOrientStrings, STYLE_CHANGED }, + {TK_OPTION_PIXELS, "-length", "length", "Length", + DEF_PROGRESSBAR_LENGTH, Tk_Offset(Progressbar,progress.lengthObj), -1, + 0, 0, GEOMETRY_CHANGED }, + {TK_OPTION_STRING_TABLE, "-mode", "mode", "ProgressMode", "determinate", + Tk_Offset(Progressbar,progress.modeObj), + Tk_Offset(Progressbar,progress.mode), + 0, (ClientData)ProgressbarModeStrings, 0 }, + {TK_OPTION_DOUBLE, "-maximum", "maximum", "Maximum", + "100", Tk_Offset(Progressbar,progress.maximumObj), -1, + 0, 0, 0 }, + {TK_OPTION_STRING, "-variable", "variable", "Variable", + NULL, Tk_Offset(Progressbar,progress.variableObj), -1, + TK_OPTION_NULL_OK, 0, 0 }, + {TK_OPTION_DOUBLE, "-value", "value", "Value", + "0.0", Tk_Offset(Progressbar,progress.valueObj), -1, + 0, 0, 0 }, + {TK_OPTION_INT, "-phase", "phase", "Phase", + "0", Tk_Offset(Progressbar,progress.phaseObj), -1, + 0, 0, 0 }, + + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/*------------------------------------------------------------------------ + * +++ Animation procedures: + */ + +/* AnimationEnabled -- + * Returns 1 if animation should be active, 0 otherwise. + */ +static int AnimationEnabled(Progressbar *pb) +{ + double maximum = 100, value = 0; + + Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum); + Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value); + + return pb->progress.period > 0 + && value > 0.0 + && ( value < maximum + || pb->progress.mode == TTK_PROGRESSBAR_INDETERMINATE); +} + +/* AnimateProgressProc -- + * Timer callback for progress bar animation. + * Increments the -phase option, redisplays the widget, + * and reschedules itself if animation still enabled. + */ +static void AnimateProgressProc(ClientData clientData) +{ + Progressbar *pb = clientData; + + pb->progress.timer = 0; + + if (AnimationEnabled(pb)) { + int phase = 0; + Tcl_GetIntFromObj(NULL, pb->progress.phaseObj, &phase); + + /* + * Update -phase: + */ + ++phase; + if (pb->progress.maxPhase) + phase %= pb->progress.maxPhase; + Tcl_DecrRefCount(pb->progress.phaseObj); + pb->progress.phaseObj = Tcl_NewIntObj(phase); + Tcl_IncrRefCount(pb->progress.phaseObj); + + /* + * Reschedule: + */ + pb->progress.timer = Tcl_CreateTimerHandler( + pb->progress.period, AnimateProgressProc, clientData); + + TtkRedisplayWidget(&pb->core); + } +} + +/* CheckAnimation -- + * If animation is enabled and not scheduled, schedule it. + * If animation is disabled but scheduled, cancel it. + */ +static void CheckAnimation(Progressbar *pb) +{ + if (AnimationEnabled(pb)) { + if (pb->progress.timer == 0) { + pb->progress.timer = Tcl_CreateTimerHandler( + pb->progress.period, AnimateProgressProc, (ClientData)pb); + } + } else { + if (pb->progress.timer != 0) { + Tcl_DeleteTimerHandler(pb->progress.timer); + pb->progress.timer = 0; + } + } +} + +/*------------------------------------------------------------------------ + * +++ Trace hook for progressbar -variable option: + */ + +static void VariableChanged(void *recordPtr, const char *value) +{ + Progressbar *pb = recordPtr; + Tcl_Obj *newValue; + double scratch; + + if (WidgetDestroyed(&pb->core)) { + return; + } + + if (!value) { + /* Linked variable is unset -- disable widget */ + TtkWidgetChangeState(&pb->core, TTK_STATE_DISABLED, 0); + return; + } + TtkWidgetChangeState(&pb->core, 0, TTK_STATE_DISABLED); + + newValue = Tcl_NewStringObj(value, -1); + Tcl_IncrRefCount(newValue); + if (Tcl_GetDoubleFromObj(NULL, newValue, &scratch) != TCL_OK) { + TtkWidgetChangeState(&pb->core, TTK_STATE_INVALID, 0); + return; + } + TtkWidgetChangeState(&pb->core, 0, TTK_STATE_INVALID); + Tcl_DecrRefCount(pb->progress.valueObj); + pb->progress.valueObj = newValue; + + CheckAnimation(pb); + TtkRedisplayWidget(&pb->core); +} + +/*------------------------------------------------------------------------ + * +++ Widget class methods: + */ + +static void ProgressbarInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Progressbar *pb = recordPtr; + pb->progress.variableTrace = 0; + pb->progress.timer = 0; +} + +static void ProgressbarCleanup(void *recordPtr) +{ + Progressbar *pb = recordPtr; + if (pb->progress.variableTrace) + Ttk_UntraceVariable(pb->progress.variableTrace); + if (pb->progress.timer) + Tcl_DeleteTimerHandler(pb->progress.timer); +} + +/* + * Configure hook: + * + * @@@ TODO: deal with [$pb configure -value ... -variable ...] + */ +static int ProgressbarConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Progressbar *pb = recordPtr; + Tcl_Obj *varName = pb->progress.variableObj; + Ttk_TraceHandle *vt = 0; + + if (varName != NULL && *Tcl_GetString(varName) != '\0') { + vt = Ttk_TraceVariable(interp, varName, VariableChanged, recordPtr); + if (!vt) return TCL_ERROR; + } + + if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) { + if (vt) Ttk_UntraceVariable(vt); + return TCL_ERROR; + } + + if (pb->progress.variableTrace) { + Ttk_UntraceVariable(pb->progress.variableTrace); + } + pb->progress.variableTrace = vt; + + return TCL_OK; +} + +/* + * Post-configuration hook: + */ +static int ProgressbarPostConfigure( + Tcl_Interp *interp, void *recordPtr, int mask) +{ + Progressbar *pb = recordPtr; + int status = TCL_OK; + + if (pb->progress.variableTrace) { + status = Ttk_FireTrace(pb->progress.variableTrace); + if (WidgetDestroyed(&pb->core)) { + return TCL_ERROR; + } + if (status != TCL_OK) { + /* Unset -variable: */ + Ttk_UntraceVariable(pb->progress.variableTrace); + Tcl_DecrRefCount(pb->progress.variableObj); + pb->progress.variableTrace = 0; + pb->progress.variableObj = NULL; + return TCL_ERROR; + } + } + + CheckAnimation(pb); + + return status; +} + +/* + * Size hook: + * Compute base layout size, overrid + */ +static int ProgressbarSize(void *recordPtr, int *widthPtr, int *heightPtr) +{ + Progressbar *pb = recordPtr; + int length = 100, orient = TTK_ORIENT_HORIZONTAL; + + TtkWidgetSize(recordPtr, widthPtr, heightPtr); + + /* Override requested width (height) based on -length and -orient + */ + Tk_GetPixelsFromObj(NULL, pb->core.tkwin, pb->progress.lengthObj, &length); + Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient); + + if (orient == TTK_ORIENT_HORIZONTAL) { + *widthPtr = length; + } else { + *heightPtr = length; + } + + return 1; +} + +/* + * Layout hook: + * Adjust size and position of pbar element, if present. + */ + +static void ProgressbarDeterminateLayout( + Progressbar *pb, + Ttk_Element pbar, + Ttk_Box parcel, + double fraction, + Ttk_Orient orient) +{ + if (fraction < 0.0) fraction = 0.0; + if (fraction > 1.0) fraction = 1.0; + + if (orient == TTK_ORIENT_HORIZONTAL) { + parcel.width = (int)(parcel.width * fraction); + } else { + int newHeight = (int)(parcel.height * fraction); + parcel.y += (parcel.height - newHeight); + parcel.height = newHeight; + } + Ttk_PlaceElement(pb->core.layout, pbar, parcel); +} + +static void ProgressbarIndeterminateLayout( + Progressbar *pb, + Ttk_Element pbar, + Ttk_Box parcel, + double fraction, + Ttk_Orient orient) +{ + Ttk_Box pbarBox = Ttk_ElementParcel(pbar); + + fraction = fmod(fabs(fraction), 2.0); + if (fraction > 1.0) { + fraction = 2.0 - fraction; + } + + if (orient == TTK_ORIENT_HORIZONTAL) { + pbarBox.x = parcel.x + (int)(fraction * (parcel.width-pbarBox.width)); + } else { + pbarBox.y = parcel.y + (int)(fraction * (parcel.height-pbarBox.height)); + } + Ttk_PlaceElement(pb->core.layout, pbar, pbarBox); +} + +static void ProgressbarDoLayout(void *recordPtr) +{ + Progressbar *pb = recordPtr; + WidgetCore *corePtr = &pb->core; + Ttk_Element pbar = Ttk_FindElement(corePtr->layout, "pbar"); + double value = 0.0, maximum = 100.0; + int orient = TTK_ORIENT_HORIZONTAL; + + Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin)); + + /* Adjust the bar size: + */ + + Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value); + Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum); + Ttk_GetOrientFromObj(NULL, pb->progress.orientObj, &orient); + + if (pbar) { + double fraction = value / maximum; + Ttk_Box parcel = Ttk_ClientRegion(corePtr->layout, "trough"); + + if (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) { + ProgressbarDeterminateLayout( + pb, pbar, parcel, fraction, orient); + } else { + ProgressbarIndeterminateLayout( + pb, pbar, parcel, fraction, orient); + } + } +} + +static Ttk_Layout ProgressbarGetLayout( + Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) +{ + Progressbar *pb = recordPtr; + Ttk_Layout layout = TtkWidgetGetOrientedLayout( + interp, theme, recordPtr, pb->progress.orientObj); + + /* + * Check if the style supports animation: + */ + pb->progress.period = 0; + pb->progress.maxPhase = 0; + if (layout) { + Tcl_Obj *periodObj = Ttk_QueryOption(layout,"-period", 0); + Tcl_Obj *maxPhaseObj = Ttk_QueryOption(layout,"-maxphase", 0); + if (periodObj) + Tcl_GetIntFromObj(NULL, periodObj, &pb->progress.period); + if (maxPhaseObj) + Tcl_GetIntFromObj(NULL, maxPhaseObj, &pb->progress.maxPhase); + } + + return layout; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands: + */ + +/* $sb step ?amount? + */ +static int ProgressbarStepCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Progressbar *pb = recordPtr; + double value = 0.0, stepAmount = 1.0; + Tcl_Obj *newValueObj; + + if (objc == 3) { + if (Tcl_GetDoubleFromObj(interp, objv[2], &stepAmount) != TCL_OK) { + return TCL_ERROR; + } + } else if (objc != 2) { + Tcl_WrongNumArgs(interp, 2,objv, "?stepAmount?"); + return TCL_ERROR; + } + + (void)Tcl_GetDoubleFromObj(NULL, pb->progress.valueObj, &value); + value += stepAmount; + + /* In determinate mode, wrap around if value exceeds maximum: + */ + if (pb->progress.mode == TTK_PROGRESSBAR_DETERMINATE) { + double maximum = 100.0; + (void)Tcl_GetDoubleFromObj(NULL, pb->progress.maximumObj, &maximum); + value = fmod(value, maximum); + } + + newValueObj = Tcl_NewDoubleObj(value); + + TtkRedisplayWidget(&pb->core); + + /* 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; + } + + /* Otherwise, change the -value directly: + */ + Tcl_IncrRefCount(newValueObj); + Tcl_DecrRefCount(pb->progress.valueObj); + pb->progress.valueObj = newValueObj; + CheckAnimation(pb); + + return TCL_OK; +} + +/* $sb start|stop ?args? -- + * Change [$sb $cmd ...] to [ttk::progressbar::$cmd ...] + * and pass to interpreter. + */ +static int ProgressbarStartStopCommand( + Tcl_Interp *interp, const char *cmdName, int objc, Tcl_Obj *const objv[]) +{ + Tcl_Obj *cmd = Tcl_NewListObj(objc, objv); + Tcl_Obj *prefix[2]; + int status; + + /* ASSERT: objc >= 2 */ + + prefix[0] = Tcl_NewStringObj(cmdName, -1); + prefix[1] = objv[0]; + Tcl_ListObjReplace(interp, cmd, 0,2, 2,prefix); + + Tcl_IncrRefCount(cmd); + status = Tcl_EvalObjEx(interp, cmd, 0); + Tcl_DecrRefCount(cmd); + + return status; +} + +static int ProgressbarStartCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + return ProgressbarStartStopCommand( + interp, "::ttk::progressbar::start", objc, objv); +} + +static int ProgressbarStopCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + return ProgressbarStartStopCommand( + interp, "::ttk::progressbar::stop", objc, objv); +} + +static const Ttk_Ensemble ProgressbarCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "start", ProgressbarStartCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "step", ProgressbarStepCommand,0 }, + { "stop", ProgressbarStopCommand,0 }, + { 0,0,0 } +}; + +/* + * Widget specification: + */ +static WidgetSpec ProgressbarWidgetSpec = +{ + "TProgressbar", /* className */ + sizeof(Progressbar), /* recordSize */ + ProgressbarOptionSpecs, /* optionSpecs */ + ProgressbarCommands, /* subcommands */ + ProgressbarInitialize, /* initializeProc */ + ProgressbarCleanup, /* cleanupProc */ + ProgressbarConfigure, /* configureProc */ + ProgressbarPostConfigure, /* postConfigureProc */ + ProgressbarGetLayout, /* getLayoutProc */ + ProgressbarSize, /* sizeProc */ + ProgressbarDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +/* + * Layouts: + */ +TTK_BEGIN_LAYOUT(VerticalProgressbarLayout) + TTK_GROUP("Vertical.Progressbar.trough", TTK_FILL_BOTH, + TTK_NODE("Vertical.Progressbar.pbar", TTK_PACK_BOTTOM|TTK_FILL_X)) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(HorizontalProgressbarLayout) + TTK_GROUP("Horizontal.Progressbar.trough", TTK_FILL_BOTH, + TTK_NODE("Horizontal.Progressbar.pbar", TTK_PACK_LEFT|TTK_FILL_Y)) +TTK_END_LAYOUT + +/* + * Initialization: + */ + +MODULE_SCOPE +void TtkProgressbar_Init(Tcl_Interp *interp) +{ + Ttk_Theme themePtr = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(themePtr, + "Vertical.TProgressbar", VerticalProgressbarLayout); + Ttk_RegisterLayout(themePtr, + "Horizontal.TProgressbar", HorizontalProgressbarLayout); + + RegisterWidget(interp, "ttk::progressbar", &ProgressbarWidgetSpec); +} + +/*EOF*/ diff --git a/generic/ttk/ttkScale.c b/generic/ttk/ttkScale.c new file mode 100644 index 0000000..69753d1 --- /dev/null +++ b/generic/ttk/ttkScale.c @@ -0,0 +1,515 @@ +/* + * Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net> + * + * ttk::scale widget. + */ + +#include <tk.h> +#include <string.h> +#include <stdio.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +#define DEF_SCALE_LENGTH "100" + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +/* + * Scale widget record + */ +typedef struct +{ + /* slider element options */ + Tcl_Obj *fromObj; /* minimum value */ + Tcl_Obj *toObj; /* maximum value */ + Tcl_Obj *valueObj; /* current value */ + Tcl_Obj *lengthObj; /* length of the long axis of the scale */ + Tcl_Obj *orientObj; /* widget orientation */ + int orient; + + /* widget options */ + Tcl_Obj *commandObj; + Tcl_Obj *variableObj; + + /* internal state */ + Ttk_TraceHandle *variableTrace; + +} ScalePart; + +typedef struct +{ + WidgetCore core; + ScalePart scale; +} Scale; + +static Tk_OptionSpec ScaleOptionSpecs[] = +{ + {TK_OPTION_STRING, "-command", "command", "Command", "", + Tk_Offset(Scale,scale.commandObj), -1, + TK_OPTION_NULL_OK,0,0}, + {TK_OPTION_STRING, "-variable", "variable", "Variable", "", + 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, + (ClientData)ttkOrientStrings, STYLE_CHANGED }, + + {TK_OPTION_DOUBLE, "-from", "from", "From", "0", + Tk_Offset(Scale,scale.fromObj), -1, 0, 0, 0}, + {TK_OPTION_DOUBLE, "-to", "to", "To", "1.0", + Tk_Offset(Scale,scale.toObj), -1, 0, 0, 0}, + {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, + GEOMETRY_CHANGED}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +static XPoint ValueToPoint(Scale *scalePtr, double value); +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, + * sets the 'invalid' state. + */ +static void ScaleVariableChanged(void *recordPtr, const char *value) +{ + Scale *scale = recordPtr; + double v; + + if (value == NULL || Tcl_GetDouble(0, value, &v) != TCL_OK) { + TtkWidgetChangeState(&scale->core, TTK_STATE_INVALID, 0); + } else { + Tcl_Obj *valueObj = Tcl_NewDoubleObj(v); + Tcl_IncrRefCount(valueObj); + Tcl_DecrRefCount(scale->scale.valueObj); + scale->scale.valueObj = valueObj; + TtkWidgetChangeState(&scale->core, 0, TTK_STATE_INVALID); + } + TtkRedisplayWidget(&scale->core); +} + +/* ScaleInitialize -- + * Scale widget initialization hook. + */ +static void ScaleInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Scale *scalePtr = recordPtr; + TtkTrackElementState(&scalePtr->core); +} + +static void ScaleCleanup(void *recordPtr) +{ + Scale *scale = recordPtr; + + if (scale->scale.variableTrace) { + Ttk_UntraceVariable(scale->scale.variableTrace); + scale->scale.variableTrace = 0; + } +} + +/* ScaleConfigure -- + * Configuration hook. + */ +static int ScaleConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Scale *scale = recordPtr; + Tcl_Obj *varName = scale->scale.variableObj; + Ttk_TraceHandle *vt = 0; + + if (varName != NULL && *Tcl_GetString(varName) != '\0') { + vt = Ttk_TraceVariable(interp,varName, ScaleVariableChanged,recordPtr); + if (!vt) return TCL_ERROR; + } + + if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) { + if (vt) Ttk_UntraceVariable(vt); + return TCL_ERROR; + } + + if (scale->scale.variableTrace) { + Ttk_UntraceVariable(scale->scale.variableTrace); + } + scale->scale.variableTrace = vt; + + return TCL_OK; +} + +/* ScalePostConfigure -- + * Post-configuration hook. + */ +static int ScalePostConfigure( + Tcl_Interp *interp, void *recordPtr, int mask) +{ + Scale *scale = recordPtr; + int status = TCL_OK; + + if (scale->scale.variableTrace) { + status = Ttk_FireTrace(scale->scale.variableTrace); + if (WidgetDestroyed(&scale->core)) { + return TCL_ERROR; + } + if (status != TCL_OK) { + /* Unset -variable: */ + Ttk_UntraceVariable(scale->scale.variableTrace); + Tcl_DecrRefCount(scale->scale.variableObj); + scale->scale.variableTrace = 0; + scale->scale.variableObj = NULL; + status = TCL_ERROR; + } + } + + return status; +} + +/* ScaleGetLayout -- + * getLayout hook. + */ +static Ttk_Layout +ScaleGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) +{ + Scale *scalePtr = recordPtr; + return TtkWidgetGetOrientedLayout( + interp, theme, recordPtr, scalePtr->scale.orientObj); +} + +/* + * TroughBox -- + * Returns the inner area of the trough element. + */ +static Ttk_Box TroughBox(Scale *scalePtr) +{ + return Ttk_ClientRegion(scalePtr->core.layout, "trough"); +} + +/* + * TroughRange -- + * Return the value area of the trough element, adjusted + * for slider size. + */ +static Ttk_Box TroughRange(Scale *scalePtr) +{ + Ttk_Box troughBox = TroughBox(scalePtr); + Ttk_Element slider = Ttk_FindElement(scalePtr->core.layout,"slider"); + + /* + * If this is a scale widget, adjust range for slider: + */ + if (slider) { + Ttk_Box sliderBox = Ttk_ElementParcel(slider); + if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) { + troughBox.x += sliderBox.width / 2; + troughBox.width -= sliderBox.width; + } else { + troughBox.y += sliderBox.height / 2; + troughBox.height -= sliderBox.height; + } + } + + return troughBox; +} + +/* + * ScaleFraction -- + */ +static double ScaleFraction(Scale *scalePtr, double value) +{ + double from = 0, to = 1, fraction; + + Tcl_GetDoubleFromObj(NULL, scalePtr->scale.fromObj, &from); + Tcl_GetDoubleFromObj(NULL, scalePtr->scale.toObj, &to); + + if (from == to) { + return 1.0; + } + + fraction = (value - from) / (to - from); + + return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction; +} + +/* $scale get ?x y? -- + * Returns the current value of the scale widget, or if $x and + * $y are specified, the value represented by point @x,y. + */ +static int +ScaleGetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scale *scalePtr = recordPtr; + int x, y, r = TCL_OK; + double value = 0; + + if ((objc != 2) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?"); + return TCL_ERROR; + } + if (objc == 2) { + Tcl_SetObjResult(interp, scalePtr->scale.valueObj); + } else { + r = Tcl_GetIntFromObj(interp, objv[2], &x); + if (r == TCL_OK) + r = Tcl_GetIntFromObj(interp, objv[3], &y); + if (r == TCL_OK) { + value = PointToValue(scalePtr, x, y); + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value)); + } + } + return r; +} + +/* $scale set $newValue + */ +static int +ScaleSetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scale *scalePtr = recordPtr; + double from = 0.0, to = 1.0, value; + int result = TCL_OK; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 1, objv, "set value"); + return TCL_ERROR; + } + + if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) { + return TCL_ERROR; + } + + if (scalePtr->core.state & TTK_STATE_DISABLED) { + return TCL_OK; + } + + /* ASSERT: fromObj and toObj are valid doubles. + */ + Tcl_GetDoubleFromObj(interp, scalePtr->scale.fromObj, &from); + Tcl_GetDoubleFromObj(interp, scalePtr->scale.toObj, &to); + + /* Limit new value to between 'from' and 'to': + */ + if (from < to) { + value = value < from ? from : value > to ? to : value; + } else { + value = value < to ? to : value > from ? from : value; + } + + /* + * Set value: + */ + Tcl_DecrRefCount(scalePtr->scale.valueObj); + scalePtr->scale.valueObj = Tcl_NewDoubleObj(value); + Tcl_IncrRefCount(scalePtr->scale.valueObj); + TtkRedisplayWidget(&scalePtr->core); + + /* + * Set attached variable, if any: + */ + if (scalePtr->scale.variableObj != NULL) { + Tcl_ObjSetVar2(interp, scalePtr->scale.variableObj, NULL, + scalePtr->scale.valueObj, TCL_GLOBAL_ONLY); + } + if (WidgetDestroyed(&scalePtr->core)) { + return TCL_ERROR; + } + + /* + * Invoke -command, if any: + */ + if (scalePtr->scale.commandObj != NULL) { + Tcl_Obj *cmdObj = Tcl_DuplicateObj(scalePtr->scale.commandObj); + Tcl_IncrRefCount(cmdObj); + Tcl_AppendToObj(cmdObj, " ", 1); + Tcl_AppendObjToObj(cmdObj, scalePtr->scale.valueObj); + result = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL); + Tcl_DecrRefCount(cmdObj); + } + + return result; +} + +static int +ScaleCoordsCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scale *scalePtr = recordPtr; + double value; + int r = TCL_OK; + + if (objc < 2 || objc > 3) { + Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?"); + return TCL_ERROR; + } + + if (objc == 3) { + r = Tcl_GetDoubleFromObj(interp, objv[2], &value); + } else { + r = Tcl_GetDoubleFromObj(interp, scalePtr->scale.valueObj, &value); + } + + if (r == TCL_OK) { + Tcl_Obj *point[2]; + XPoint pt = ValueToPoint(scalePtr, value); + point[0] = Tcl_NewIntObj(pt.x); + point[1] = Tcl_NewIntObj(pt.y); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, point)); + } + return r; +} + +static void ScaleDoLayout(void *clientData) +{ + WidgetCore *corePtr = clientData; + Ttk_Element slider = Ttk_FindElement(corePtr->layout, "slider"); + + Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin)); + + /* Adjust the slider position: + */ + if (slider) { + Scale *scalePtr = clientData; + Ttk_Box troughBox = TroughBox(scalePtr); + Ttk_Box sliderBox = Ttk_ElementParcel(slider); + double value = 0.0; + double fraction; + int range; + + Tcl_GetDoubleFromObj(NULL, scalePtr->scale.valueObj, &value); + fraction = ScaleFraction(scalePtr, value); + + if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) { + range = troughBox.width - sliderBox.width; + sliderBox.x += (int)(fraction * range); + } else { + range = troughBox.height - sliderBox.height; + sliderBox.y += (int)(fraction * range); + } + Ttk_PlaceElement(corePtr->layout, slider, sliderBox); + } +} + +/* + * ScaleSize -- + * Compute requested size of scale. + */ +static int ScaleSize(void *clientData, int *widthPtr, int *heightPtr) +{ + WidgetCore *corePtr = clientData; + Scale *scalePtr = clientData; + int length; + + Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr); + + /* Assert the -length configuration option */ + Tk_GetPixelsFromObj(NULL, corePtr->tkwin, + scalePtr->scale.lengthObj, &length); + if (scalePtr->scale.orient == TTK_ORIENT_VERTICAL) { + *heightPtr = MAX(*heightPtr, length); + } else { + *widthPtr = MAX(*widthPtr, length); + } + + return 1; +} + +static double +PointToValue(Scale *scalePtr, int x, int y) +{ + Ttk_Box troughBox = TroughRange(scalePtr); + double from = 0, to = 1, fraction; + + Tcl_GetDoubleFromObj(NULL, scalePtr->scale.fromObj, &from); + Tcl_GetDoubleFromObj(NULL, scalePtr->scale.toObj, &to); + + if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) { + fraction = (double)(x - troughBox.x) / (double)troughBox.width; + } else { + fraction = (double)(y - troughBox.y) / (double)troughBox.height; + } + + fraction = fraction < 0 ? 0 : fraction > 1 ? 1 : fraction; + + return from + fraction * (to-from); +} + +/* + * Return the center point in the widget corresponding to the given + * value. This point can be used to center the slider. + */ + +static XPoint +ValueToPoint(Scale *scalePtr, double value) +{ + Ttk_Box troughBox = TroughRange(scalePtr); + double fraction = ScaleFraction(scalePtr, value); + XPoint pt = {0, 0}; + + if (scalePtr->scale.orient == TTK_ORIENT_HORIZONTAL) { + pt.x = troughBox.x + (int)(fraction * troughBox.width); + pt.y = troughBox.y + troughBox.height / 2; + } else { + pt.x = troughBox.x + troughBox.width / 2; + pt.y = troughBox.y + (int)(fraction * troughBox.height); + } + return pt; +} + +static const Ttk_Ensemble ScaleCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "set", ScaleSetCommand,0 }, + { "get", ScaleGetCommand,0 }, + { "coords", ScaleCoordsCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec ScaleWidgetSpec = +{ + "TScale", /* Class name */ + sizeof(Scale), /* record size */ + ScaleOptionSpecs, /* option specs */ + ScaleCommands, /* widget commands */ + ScaleInitialize, /* initialization proc */ + ScaleCleanup, /* cleanup proc */ + ScaleConfigure, /* configure proc */ + ScalePostConfigure, /* postConfigure */ + ScaleGetLayout, /* getLayoutProc */ + ScaleSize, /* sizeProc */ + ScaleDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(VerticalScaleLayout) + TTK_GROUP("Vertical.Scale.trough", TTK_FILL_BOTH, + TTK_NODE("Vertical.Scale.slider", TTK_PACK_TOP) ) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(HorizontalScaleLayout) + TTK_GROUP("Horizontal.Scale.trough", TTK_FILL_BOTH, + TTK_NODE("Horizontal.Scale.slider", TTK_PACK_LEFT) ) +TTK_END_LAYOUT + +/* + * Initialization. + */ +MODULE_SCOPE +void TtkScale_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(theme, "Vertical.TScale", VerticalScaleLayout); + Ttk_RegisterLayout(theme, "Horizontal.TScale", HorizontalScaleLayout); + + RegisterWidget(interp, "ttk::scale", &ScaleWidgetSpec); +} + diff --git a/generic/ttk/ttkScroll.c b/generic/ttk/ttkScroll.c new file mode 100644 index 0000000..defe05a --- /dev/null +++ b/generic/ttk/ttkScroll.c @@ -0,0 +1,252 @@ +/* + * Copyright 2004, Joe English + * + * Support routines for scrollable widgets. + * + * (This is sort of half-baked; needs some work) + * + * Scrollable interface: + * + * + 'first' is controlled by [xy]view widget command + * and other scrolling commands like 'see'; + * + 'total' depends on widget contents; + * + 'last' depends on first, total, and widget size. + * + * Choreography (typical usage): + * + * 1. User adjusts scrollbar, scrollbar widget calls its -command + * 2. Scrollbar -command invokes the scrollee [xy]view widget method + * 3. TtkScrollviewCommand calls TtkScrollTo(), which updates + * 'first' and schedules a redisplay. + * 4. Once the scrollee knows 'total' and 'last' (typically in + * the LayoutProc), call TtkScrolled(h,first,last,total) to + * synchronize the scrollbar. + * 5. The scrollee -[xy]scrollcommand is called (in an idle callback) + * 6. Which calls the scrollbar 'set' method and redisplays the scrollbar. + * + * If the scrollee has internal scrolling (e.g., a 'see' method), + * it should TtkScrollTo() directly (step 2). + * + * If the widget value changes, it should call TtkScrolled() (step 4). + * (This usually happens automatically when the widget is redisplayed). + * + * If the scrollee's -[xy]scrollcommand changes, it should call + * TtkScrollbarUpdateRequired, which will invoke step (5) (@@@ Fix this) + */ + +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +/* Private data: + */ +#define SCROLL_UPDATE_PENDING (0x1) +#define SCROLL_UPDATE_REQUIRED (0x2) + +struct ScrollHandleRec +{ + unsigned flags; + WidgetCore *corePtr; + Scrollable *scrollPtr; +}; + +/* TtkCreateScrollHandle -- + * Initialize scroll handle. + */ +ScrollHandle TtkCreateScrollHandle(WidgetCore *corePtr, Scrollable *scrollPtr) +{ + ScrollHandle h = (ScrollHandle)ckalloc(sizeof(*h)); + + h->flags = 0; + h->corePtr = corePtr; + h->scrollPtr = scrollPtr; + + scrollPtr->first = 0; + scrollPtr->last = 1; + scrollPtr->total = 1; + return h; +} + +/* UpdateScrollbar -- + * Call the -scrollcommand callback to sync the scrollbar. + * Returns: Whatever the -scrollcommand does. + */ +static int UpdateScrollbar(Tcl_Interp *interp, ScrollHandle h) +{ + Scrollable *s = h->scrollPtr; + WidgetCore *corePtr = h->corePtr; + char arg1[TCL_DOUBLE_SPACE + 2]; + char arg2[TCL_DOUBLE_SPACE + 2]; + int code; + + h->flags &= ~SCROLL_UPDATE_REQUIRED; + + if (s->scrollCmd == NULL) { + return TCL_OK; + } + + arg1[0] = arg2[0] = ' '; + Tcl_PrintDouble(interp, (double)s->first / s->total, arg1+1); + Tcl_PrintDouble(interp, (double)s->last / s->total, arg2+1); + + Tcl_Preserve(corePtr); + code = Tcl_VarEval(interp, s->scrollCmd, arg1, arg2, NULL); + if (WidgetDestroyed(corePtr)) { + Tcl_Release(corePtr); + return TCL_ERROR; + } + Tcl_Release(corePtr); + + if (code != TCL_OK && !Tcl_InterpDeleted(interp)) { + /* Disable the -scrollcommand, add to stack trace: + */ + ckfree(s->scrollCmd); + s->scrollCmd = 0; + + Tcl_AddErrorInfo(interp, /* @@@ "horizontal" / "vertical" */ + "\n (scrolling command executed by "); + Tcl_AddErrorInfo(interp, Tk_PathName(h->corePtr->tkwin)); + Tcl_AddErrorInfo(interp, ")"); + } + return code; +} + +/* UpdateScrollbarBG -- + * Idle handler to update the scrollbar. + */ +static void UpdateScrollbarBG(ClientData clientData) +{ + ScrollHandle h = (ScrollHandle)clientData; + Tcl_Interp *interp = h->corePtr->interp; + int code; + + h->flags &= ~SCROLL_UPDATE_PENDING; + Tcl_Preserve((ClientData) interp); + code = UpdateScrollbar(interp, h); + if (code == TCL_ERROR && !Tcl_InterpDeleted(interp)) { + Tcl_BackgroundError(interp); + } + Tcl_Release((ClientData) interp); +} + +/* TtkScrolled -- + * Update scroll info, schedule scrollbar update. + */ +void TtkScrolled(ScrollHandle h, int first, int last, int total) +{ + Scrollable *s = h->scrollPtr; + + /* Sanity-check inputs: + */ + if (total <= 0) { + first = 0; + last = 1; + total = 1; + } + + if (last > total) { + first -= (last - total); + if (first < 0) first = 0; + last = total; + } + + if (s->first != first || s->last != last || s->total != total + || (h->flags & SCROLL_UPDATE_REQUIRED)) + { + s->first = first; + s->last = last; + s->total = total; + + if (!(h->flags & SCROLL_UPDATE_PENDING)) { + Tcl_DoWhenIdle(UpdateScrollbarBG, (ClientData)h); + h->flags |= SCROLL_UPDATE_PENDING; + } + } +} + +/* TtkScrollbarUpdateRequired -- + * Force a scrollbar update at the next call to TtkScrolled(), + * even if scroll parameters haven't changed (e.g., if + * -yscrollcommand has changed). + */ + +void TtkScrollbarUpdateRequired(ScrollHandle h) +{ + h->flags |= SCROLL_UPDATE_REQUIRED; +} + +/* TtkScrollviewCommand -- + * Widget [xy]view command implementation. + * + * $w [xy]view -- return current view region + * $w [xy]view $index -- set topmost item + * $w [xy]view moveto $fraction + * $w [xy]view scroll $number $what -- scrollbar interface + */ +int TtkScrollviewCommand( + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle h) +{ + Scrollable *s = h->scrollPtr; + int newFirst = s->first; + + if (objc == 2) { + Tcl_Obj *result[2]; + result[0] = Tcl_NewDoubleObj((double)s->first / s->total); + result[1] = Tcl_NewDoubleObj((double)s->last / s->total); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); + return TCL_OK; + } else if (objc == 3) { + if (Tcl_GetIntFromObj(interp, objv[2], &newFirst) != TCL_OK) { + return TCL_ERROR; + } + } else { + double fraction; + int count; + + switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count)) { + case TK_SCROLL_ERROR: + return TCL_ERROR; + case TK_SCROLL_MOVETO: + newFirst = (int) ((fraction * s->total) + 0.5); + break; + case TK_SCROLL_UNITS: + newFirst = s->first + count; + break; + case TK_SCROLL_PAGES: { + int perPage = s->last - s->first; /* @@@ */ + newFirst = s->first + count * perPage; + break; + } + } + } + + TtkScrollTo(h, newFirst); + + return TCL_OK; +} + +void TtkScrollTo(ScrollHandle h, int newFirst) +{ + Scrollable *s = h->scrollPtr; + + if (newFirst >= s->total) + newFirst = s->total - 1; + if (newFirst > s->first && s->last >= s->total) /* don't scroll past end */ + newFirst = s->first; + if (newFirst < 0) + newFirst = 0; + + if (newFirst != s->first) { + s->first = newFirst; + TtkRedisplayWidget(h->corePtr); + } +} + +void TtkFreeScrollHandle(ScrollHandle h) +{ + if (h->flags & SCROLL_UPDATE_PENDING) { + Tcl_CancelIdleCall(UpdateScrollbarBG, (ClientData)h); + } + ckfree((ClientData)h); +} + diff --git a/generic/ttk/ttkScrollbar.c b/generic/ttk/ttkScrollbar.c new file mode 100644 index 0000000..5b0c212 --- /dev/null +++ b/generic/ttk/ttkScrollbar.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2003, Joe English + * + * ttk::scrollbar widget. + */ + +#include <tk.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" + +/*------------------------------------------------------------------------ + * +++ Scrollbar widget record. + */ +typedef struct +{ + Tcl_Obj *commandObj; + + int orient; + Tcl_Obj *orientObj; + + double first; /* top fraction */ + double last; /* bottom fraction */ + + Ttk_Box troughBox; /* trough parcel */ + int minSize; /* minimum size of thumb */ +} ScrollbarPart; + +typedef struct +{ + WidgetCore core; + ScrollbarPart scrollbar; +} Scrollbar; + +static Tk_OptionSpec ScrollbarOptionSpecs[] = +{ + {TK_OPTION_STRING, "-command", "command", "Command", "", + Tk_Offset(Scrollbar,scrollbar.commandObj), -1, 0,0,0}, + + {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "vertical", + Tk_Offset(Scrollbar,scrollbar.orientObj), + Tk_Offset(Scrollbar,scrollbar.orient), + 0,(ClientData)ttkOrientStrings,STYLE_CHANGED }, + + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/*------------------------------------------------------------------------ + * +++ Widget hooks. + */ + +static void +ScrollbarInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Scrollbar *sb = recordPtr; + sb->scrollbar.first = 0.0; + sb->scrollbar.last = 1.0; + + TtkTrackElementState(&sb->core); +} + +static Ttk_Layout ScrollbarGetLayout( + Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) +{ + Scrollbar *sb = recordPtr; + return TtkWidgetGetOrientedLayout( + interp, theme, recordPtr, sb->scrollbar.orientObj); +} + +/* + * ScrollbarDoLayout -- + * Layout hook. Adjusts the position of the scrollbar thumb. + * + * Side effects: + * Sets sb->troughBox and sb->minSize. + */ +static void ScrollbarDoLayout(void *recordPtr) +{ + Scrollbar *sb = recordPtr; + WidgetCore *corePtr = &sb->core; + Ttk_Element thumb; + Ttk_Box thumbBox; + int thumbWidth, thumbHeight; + double first, last, size; + int minSize; + + /* + * Use generic layout manager to compute initial layout: + */ + Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin)); + + /* + * Locate thumb element, extract parcel and requested minimum size: + */ + thumb = Ttk_FindElement(corePtr->layout, "thumb"); + if (!thumb) /* Something has gone wrong -- bail */ + return; + + sb->scrollbar.troughBox = thumbBox = Ttk_ElementParcel(thumb); + Ttk_LayoutNodeReqSize( + corePtr->layout, thumb, &thumbWidth,&thumbHeight); + + /* + * Adjust thumb element parcel: + */ + first = sb->scrollbar.first; + last = sb->scrollbar.last; + + if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) { + minSize = thumbHeight; + size = thumbBox.height - minSize; + thumbBox.y += (int)(size * first); + thumbBox.height = (int)(size * last) + minSize - (int)(size * first); + } else { + minSize = thumbWidth; + size = thumbBox.width - minSize; + thumbBox.x += (int)(size * first); + thumbBox.width = (int)(size * last) + minSize - (int)(size * first); + } + sb->scrollbar.minSize = minSize; + Ttk_PlaceElement(corePtr->layout, thumb, thumbBox); +} + +/*------------------------------------------------------------------------ + * +++ Widget commands. + */ + +/* $sb set $first $last -- + * Set the position of the scrollbar. + */ +static int +ScrollbarSetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scrollbar *scrollbar = recordPtr; + Tcl_Obj *firstObj, *lastObj; + double first, last; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "first last"); + return TCL_ERROR; + } + + firstObj = objv[2]; + lastObj = objv[3]; + if (Tcl_GetDoubleFromObj(interp, firstObj, &first) != TCL_OK + || Tcl_GetDoubleFromObj(interp, lastObj, &last) != TCL_OK) + return TCL_ERROR; + + /* Range-checks: + */ + if (first < 0.0) { + first = 0.0; + } else if (first > 1.0) { + first = 1.0; + } + + if (last < first) { + last = first; + } else if (last > 1.0) { + last = 1.0; + } + + /* ASSERT: 0.0 <= first <= last <= 1.0 */ + + scrollbar->scrollbar.first = first; + scrollbar->scrollbar.last = last; + if (first <= 0.0 && last >= 1.0) { + scrollbar->core.state |= TTK_STATE_DISABLED; + } else { + scrollbar->core.state &= ~TTK_STATE_DISABLED; + } + + TtkRedisplayWidget(&scrollbar->core); + + return TCL_OK; +} + +/* $sb get -- + * Returns the last thing passed to 'set'. + */ +static int +ScrollbarGetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scrollbar *scrollbar = recordPtr; + Tcl_Obj *result[2]; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + result[0] = Tcl_NewDoubleObj(scrollbar->scrollbar.first); + result[1] = Tcl_NewDoubleObj(scrollbar->scrollbar.last); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); + + return TCL_OK; +} + +/* $sb delta $dx $dy -- + * Returns the percentage change corresponding to a mouse movement + * of $dx, $dy. + */ +static int +ScrollbarDeltaCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scrollbar *sb = recordPtr; + double dx, dy; + double delta = 0.0; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "dx dy"); + return TCL_ERROR; + } + + if (Tcl_GetDoubleFromObj(interp, objv[2], &dx) != TCL_OK + || Tcl_GetDoubleFromObj(interp, objv[3], &dy) != TCL_OK) + { + return TCL_ERROR; + } + + delta = 0.0; + if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) { + int size = sb->scrollbar.troughBox.height - sb->scrollbar.minSize; + if (size > 0) { + delta = (double)dy / (double)size; + } + } else { + int size = sb->scrollbar.troughBox.width - sb->scrollbar.minSize; + if (size > 0) { + delta = (double)dx / (double)size; + } + } + + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(delta)); + return TCL_OK; +} + +/* $sb fraction $x $y -- + * Returns a real number between 0 and 1 indicating where the + * point given by x and y lies in the trough area of the scrollbar. + */ +static int +ScrollbarFractionCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Scrollbar *sb = recordPtr; + Ttk_Box b = sb->scrollbar.troughBox; + int minSize = sb->scrollbar.minSize; + double x, y; + double fraction = 0.0; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "x y"); + return TCL_ERROR; + } + + if (Tcl_GetDoubleFromObj(interp, objv[2], &x) != TCL_OK + || Tcl_GetDoubleFromObj(interp, objv[3], &y) != TCL_OK) + { + return TCL_ERROR; + } + + fraction = 0.0; + if (sb->scrollbar.orient == TTK_ORIENT_VERTICAL) { + if (b.height > minSize) { + fraction = (double)(y - b.y) / (double)(b.height - minSize); + } + } else { + if (b.width > minSize) { + fraction = (double)(x - b.x) / (double)(b.width - minSize); + } + } + + Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction)); + return TCL_OK; +} + +static const Ttk_Ensemble ScrollbarCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "delta", ScrollbarDeltaCommand,0 }, + { "fraction", ScrollbarFractionCommand,0 }, + { "get", ScrollbarGetCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "set", ScrollbarSetCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { 0,0,0 } +}; + +/*------------------------------------------------------------------------ + * +++ Widget specification. + */ +static WidgetSpec ScrollbarWidgetSpec = +{ + "TScrollbar", /* className */ + sizeof(Scrollbar), /* recordSize */ + ScrollbarOptionSpecs, /* optionSpecs */ + ScrollbarCommands, /* subcommands */ + ScrollbarInitialize, /* initializeProc */ + TtkNullCleanup, /* cleanupProc */ + TtkCoreConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + ScrollbarGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + ScrollbarDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(VerticalScrollbarLayout) + TTK_GROUP("Vertical.Scrollbar.trough", TTK_FILL_Y, + TTK_NODE("Vertical.Scrollbar.uparrow", TTK_PACK_TOP) + TTK_NODE("Vertical.Scrollbar.downarrow", TTK_PACK_BOTTOM) + TTK_NODE( + "Vertical.Scrollbar.thumb", TTK_PACK_TOP|TTK_EXPAND|TTK_FILL_BOTH)) +TTK_END_LAYOUT + +TTK_BEGIN_LAYOUT(HorizontalScrollbarLayout) + TTK_GROUP("Horizontal.Scrollbar.trough", TTK_FILL_X, + TTK_NODE("Horizontal.Scrollbar.leftarrow", TTK_PACK_LEFT) + TTK_NODE("Horizontal.Scrollbar.rightarrow", TTK_PACK_RIGHT) + TTK_NODE( + "Horizontal.Scrollbar.thumb", TTK_PACK_LEFT|TTK_EXPAND|TTK_FILL_BOTH)) +TTK_END_LAYOUT + +/*------------------------------------------------------------------------ + * +++ Initialization. + */ + +MODULE_SCOPE +void TtkScrollbar_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(theme,"Vertical.TScrollbar",VerticalScrollbarLayout); + Ttk_RegisterLayout(theme,"Horizontal.TScrollbar",HorizontalScrollbarLayout); + + RegisterWidget(interp, "ttk::scrollbar", &ScrollbarWidgetSpec); +} + +/*EOF*/ diff --git a/generic/ttk/ttkSeparator.c b/generic/ttk/ttkSeparator.c new file mode 100644 index 0000000..b52e6f4 --- /dev/null +++ b/generic/ttk/ttkSeparator.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2004, Joe English + * + * ttk::separator and ttk::sizegrip widgets. + */ + +#include <tk.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" + +/* +++ Separator widget record: + */ +typedef struct +{ + Tcl_Obj *orientObj; + int orient; +} SeparatorPart; + +typedef struct +{ + WidgetCore core; + SeparatorPart separator; +} Separator; + +static Tk_OptionSpec SeparatorOptionSpecs[] = { + {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal", + Tk_Offset(Separator,separator.orientObj), + Tk_Offset(Separator,separator.orient), + 0,(ClientData)ttkOrientStrings,STYLE_CHANGED }, + + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/* + * GetLayout hook -- + * Choose layout based on -orient option. + */ +static Ttk_Layout SeparatorGetLayout( + Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr) +{ + Separator *sep = recordPtr; + return TtkWidgetGetOrientedLayout( + interp, theme, recordPtr, sep->separator.orientObj); +} + +/* + * Widget commands: + */ +static const Ttk_Ensemble SeparatorCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { 0,0,0 } +}; + +/* + * Widget specification: + */ +static WidgetSpec SeparatorWidgetSpec = +{ + "TSeparator", /* className */ + sizeof(Separator), /* recordSize */ + SeparatorOptionSpecs, /* optionSpecs */ + SeparatorCommands, /* subcommands */ + TtkNullInitialize, /* initializeProc */ + TtkNullCleanup, /* cleanupProc */ + TtkCoreConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + SeparatorGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(SeparatorLayout) + TTK_NODE("Separator.separator", TTK_FILL_BOTH) +TTK_END_LAYOUT + +/* +++ Sizegrip widget: + * Has no options or methods other than the standard ones. + */ + +static Tk_OptionSpec SizegripOptionSpecs[] = { + WIDGET_TAKEFOCUS_FALSE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +static const Ttk_Ensemble SizegripCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { 0,0,0 } +}; + +static WidgetSpec SizegripWidgetSpec = +{ + "TSizegrip", /* className */ + sizeof(WidgetCore), /* recordSize */ + SizegripOptionSpecs, /* optionSpecs */ + SizegripCommands, /* subcommands */ + TtkNullInitialize, /* initializeProc */ + TtkNullCleanup, /* cleanupProc */ + TtkCoreConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + TtkWidgetDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +TTK_BEGIN_LAYOUT(SizegripLayout) + TTK_NODE("Sizegrip.sizegrip", TTK_PACK_BOTTOM|TTK_STICK_S|TTK_STICK_E) +TTK_END_LAYOUT + +/* +++ Initialization: + */ + +MODULE_SCOPE +void TtkSeparator_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + Ttk_RegisterLayout(theme, "TSeparator", SeparatorLayout); + Ttk_RegisterLayout(theme, "TSizegrip", SizegripLayout); + + RegisterWidget(interp, "ttk::separator", &SeparatorWidgetSpec); + RegisterWidget(interp, "ttk::sizegrip", &SizegripWidgetSpec); +} + +/*EOF*/ diff --git a/generic/ttk/ttkSquare.c b/generic/ttk/ttkSquare.c new file mode 100644 index 0000000..d002f2f --- /dev/null +++ b/generic/ttk/ttkSquare.c @@ -0,0 +1,301 @@ +/* square.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net> + * + * Minimal sample ttk widget. + */ + +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +#if defined(TTK_SQUARE_WIDGET) || 1 + +#ifndef DEFAULT_BORDERWIDTH +#define DEFAULT_BORDERWIDTH "2" +#endif + +/* + * First, we setup the widget record. The Ttk package provides a structure + * that contains standard widget data so it is only necessary to define + * a structure that holds the data required for our widget. We do this by + * defining a widget part and then specifying the widget record as the + * concatenation of the two structures. + */ + +typedef struct +{ + Tcl_Obj *widthObj; + Tcl_Obj *heightObj; + Tcl_Obj *reliefObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *paddingObj; + Tcl_Obj *anchorObj; +} SquarePart; + +typedef struct +{ + WidgetCore core; + SquarePart square; +} Square; + +/* + * Widget options. + * + * This structure is the same as the option specification structure used + * for Tk widgets. For each option we provide the type, name and options + * database name and class name and the position in the structure and + * default values. At the bottom we bring in the standard widget option + * defined for all widgets. + */ + +static Tk_OptionSpec SquareOptionSpecs[] = +{ + {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", + DEFAULT_BORDERWIDTH, Tk_Offset(Square,square.borderWidthObj), -1, + 0,0,GEOMETRY_CHANGED }, + {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_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) +}; + +/* + * Almost all of the widget functionality is handled by the default Ttk + * widget code and the contained element. The one thing that we must handle + * is the -anchor option which positions the square element within the parcel + * of space available for the widget. + * To do this we must find out the layout preferences for the square + * element and adjust its position within our region. + * + * Note that if we do not have a "square" elememt then just the default + * layout will be done. So if someone places a label element into the + * widget layout it will still be handled but the -anchor option will be + * passed onto the label element instead of handled here. + */ + +static void +SquareDoLayout(void *clientData) +{ + WidgetCore *corePtr = (WidgetCore *)clientData; + Ttk_Box winBox; + Ttk_Element squareNode; + + squareNode = Ttk_FindElement(corePtr->layout, "square"); + winBox = Ttk_WinBox(corePtr->tkwin); + Ttk_PlaceLayout(corePtr->layout, corePtr->state, winBox); + + /* + * Adjust the position of the square element within the widget according + * to the -anchor option. + */ + + if (squareNode) { + Square *squarePtr = clientData; + Tk_Anchor anchor = TK_ANCHOR_CENTER; + Ttk_Box b; + + b = Ttk_ElementParcel(squareNode); + if (squarePtr->square.anchorObj != NULL) + Tk_GetAnchorFromObj(NULL, squarePtr->square.anchorObj, &anchor); + b = Ttk_AnchorBox(winBox, b.width, b.height, anchor); + + Ttk_PlaceElement(corePtr->layout, squareNode, b); + } +} + +/* + * Widget commands. A widget is impelemented as an ensemble and the + * subcommands are listed here. Ttk provides default implementations + * that are sufficient for our needs. + */ + +static const Ttk_Ensemble SquareCommands[] = { + { "configure", TtkWidgetConfigureCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { 0,0,0 } +}; + +/* + * The Widget specification structure holds all the implementation + * information about this widget and this is what must be registered + * with Tk in the package initialization code (see bottom). + */ + +static WidgetSpec SquareWidgetSpec = +{ + "TSquare", /* className */ + sizeof(Square), /* recordSize */ + SquareOptionSpecs, /* optionSpecs */ + SquareCommands, /* subcommands */ + TtkNullInitialize, /* initializeProc */ + TtkNullCleanup, /* cleanupProc */ + TtkCoreConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + TtkWidgetGetLayout, /* getLayoutProc */ + TtkWidgetSize, /* sizeProc */ + SquareDoLayout, /* layoutProc */ + TtkWidgetDisplay /* displayProc */ +}; + +/* ---------------------------------------------------------------------- + * Square element + * + * In this section we demonstrate what is required to create a new themed + * element. + */ + +typedef struct +{ + Tcl_Obj *borderObj; + Tcl_Obj *foregroundObj; + Tcl_Obj *borderWidthObj; + Tcl_Obj *reliefObj; + Tcl_Obj *widthObj; + Tcl_Obj *heightObj; +} SquareElement; + +static Ttk_ElementOptionSpec SquareElementOptions[] = +{ + { "-background", TK_OPTION_BORDER, Tk_Offset(SquareElement,borderObj), + DEFAULT_BACKGROUND }, + { "-foreground", TK_OPTION_BORDER, Tk_Offset(SquareElement,foregroundObj), + DEFAULT_BACKGROUND }, + { "-borderwidth", TK_OPTION_PIXELS, Tk_Offset(SquareElement,borderWidthObj), + DEFAULT_BORDERWIDTH }, + { "-relief", TK_OPTION_RELIEF, Tk_Offset(SquareElement,reliefObj), + "raised" }, + { "-width", TK_OPTION_PIXELS, Tk_Offset(SquareElement,widthObj), "20"}, + { "-height", TK_OPTION_PIXELS, Tk_Offset(SquareElement,heightObj), "20"}, + { NULL, 0, 0, NULL } +}; + +/* + * The element geometry function is called when the layout code wishes to + * find out how big this element wants to be. We must return our preferred + * size and padding information + */ + +static void SquareElementSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + SquareElement *square = elementRecord; + int borderWidth = 0; + + Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth); + *paddingPtr = Ttk_UniformPadding((short)borderWidth); + Tk_GetPixelsFromObj(NULL, tkwin, square->widthObj, widthPtr); + Tk_GetPixelsFromObj(NULL, tkwin, square->heightObj, heightPtr); +} + +/* + * Draw the element in the box provided. + */ + +static void SquareElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, unsigned int state) +{ + SquareElement *square = elementRecord; + Tk_3DBorder foreground = NULL; + int borderWidth = 1, relief = TK_RELIEF_FLAT; + + foreground = Tk_Get3DBorderFromObj(tkwin, square->foregroundObj); + Tcl_GetIntFromObj(NULL, square->borderWidthObj, &borderWidth); + Tk_GetReliefFromObj(NULL, square->reliefObj, &relief); + + Tk_Fill3DRectangle(tkwin, d, foreground, + b.x, b.y, b.width, b.height, borderWidth, relief); +} + +static Ttk_ElementSpec SquareElementSpec = +{ + TK_STYLE_VERSION_2, + sizeof(SquareElement), + SquareElementOptions, + SquareElementSize, + SquareElementDraw +}; + +/* ---------------------------------------------------------------------- + * + * Layout section. + * + * Every widget class needs a layout style that specifies which elements + * are part of the widget and how they should be placed. The element layout + * engine is similar to the Tk pack geometry manager. Read the documentation + * for the details. In this example we just need to have the square element + * that has been defined for this widget placed on a background. We will + * also need some padding to keep it away from the edges. + */ + +TTK_BEGIN_LAYOUT(SquareLayout) + TTK_NODE("Square.background", TTK_FILL_BOTH) + TTK_GROUP("Square.padding", TTK_FILL_BOTH, + TTK_NODE("Square.square", 0)) +TTK_END_LAYOUT + +/* ---------------------------------------------------------------------- + * + * Widget initialization. + * + * This file defines a new element and a new widget. We need to register + * the element with the themes that will need it. In this case we will + * register with the default theme that is the root of the theme inheritance + * tree. This means all themes will find this element. + * We then need to register the widget class style. This is the layout + * specification. If a different theme requires an alternative layout, we + * could register that here. For instance, in some themes the scrollbars have + * one uparrow, in other themes there are two uparrow elements. + * Finally we register the widget itself. This step creates a tcl command so + * that we can actually create an instance of this class. The widget is + * linked to a particular style by the widget class name. This is important + * to realise as the programmer may change the classname when creating a + * new instance. If this is done, a new layout will need to be created (which + * can be done at script level). Some widgets may require particular elements + * to be present but we try to avoid this where possible. In this widget's C + * code, no reference is made to any particular elements. The programmer is + * free to specify a new style using completely different elements. + */ + +/* public */ MODULE_SCOPE int +TtkSquareWidget_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + /* register the new elements for this theme engine */ + Ttk_RegisterElement(interp, theme, "square", &SquareElementSpec, NULL); + + /* register the layout for this theme */ + Ttk_RegisterLayout(theme, "TSquare", SquareLayout); + + /* register the widget */ + RegisterWidget(interp, "ttk::square", &SquareWidgetSpec); + + return TCL_OK; +} + +#endif /* TTK_SQUARE_WIDGET */ + diff --git a/generic/ttk/ttkState.c b/generic/ttk/ttkState.c new file mode 100644 index 0000000..a71ae21 --- /dev/null +++ b/generic/ttk/ttkState.c @@ -0,0 +1,273 @@ +/* + * Tk widget state utilities. + * + * Copyright (c) 2003 Joe English. Freely redistributable. + * + */ + +#include <string.h> + +#include <tk.h> +#include "ttkTheme.h" + +/* + * Table of state names. Must be kept in sync with TTK_STATE_* + * #defines in ttkTheme.h. + */ +static const char *const stateNames[] = +{ + "active", /* Mouse cursor is over widget or element */ + "disabled", /* Widget is disabled */ + "focus", /* Widget has keyboard focus */ + "pressed", /* Pressed or "armed" */ + "selected", /* "on", "true", "current", etc. */ + "background", /* Top-level window lost focus (Mac,Win "inactive") */ + "alternate", /* Widget-specific alternate display style */ + "invalid", /* Bad value */ + "readonly", /* Editing/modification disabled */ + "hover", /* Mouse cursor is over widget */ + "reserved1", /* Reserved for future extension */ + "reserved2", /* Reserved for future extension */ + "reserved3", /* Reserved for future extension */ + "user3", /* User-definable state */ + "user2", /* User-definable state */ + "user1", /* User-definable state */ + NULL +}; + +/*------------------------------------------------------------------------ + * +++ StateSpec object type: + * + * The string representation consists of a list of state names, + * each optionally prefixed by an exclamation point (!). + * + * The internal representation uses the upper half of the longValue + * to store the on bits and the lower half to store the off bits. + * If we ever get more than 16 states, this will need to be reconsidered... + */ + +static int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *obj); +/* static void StateSpecFreeIntRep(Tcl_Obj *); */ +#define StateSpecFreeIntRep 0 /* not needed */ +static void StateSpecDupIntRep(Tcl_Obj *, Tcl_Obj *); +static void StateSpecUpdateString(Tcl_Obj *); + +static +struct Tcl_ObjType StateSpecObjType = +{ + "StateSpec", + StateSpecFreeIntRep, + StateSpecDupIntRep, + StateSpecUpdateString, + StateSpecSetFromAny +}; + +static void StateSpecDupIntRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) +{ + copyPtr->internalRep.longValue = srcPtr->internalRep.longValue; + copyPtr->typePtr = &StateSpecObjType; +} + +static int StateSpecSetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) +{ + int status; + int objc; + Tcl_Obj **objv; + int i; + unsigned int onbits = 0, offbits = 0; + + status = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv); + if (status != TCL_OK) + return status; + + for (i = 0; i < objc; ++i) { + const char *stateName = Tcl_GetString(objv[i]); + int on, j; + + if (*stateName == '!') { + ++stateName; + on = 0; + } else { + on = 1; + } + + for (j = 0; stateNames[j] != 0; ++j) { + if (strcmp(stateName, stateNames[j]) == 0) + break; + } + + if (stateNames[j] == 0) { + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Invalid state name ", stateName,NULL); + } + return TCL_ERROR; + } + + if (on) { + onbits |= (1<<j); + } else { + offbits |= (1<<j); + } + } + + /* Invalidate old intrep: + */ + if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) { + objPtr->typePtr->freeIntRepProc(objPtr); + } + + objPtr->typePtr = &StateSpecObjType; + objPtr->internalRep.longValue = (onbits << 16) | offbits; + + return TCL_OK; +} + +static void StateSpecUpdateString(Tcl_Obj *objPtr) +{ + unsigned int onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16; + unsigned int offbits = objPtr->internalRep.longValue & 0x0000FFFF; + unsigned int mask = onbits | offbits; + Tcl_DString result; + int i, len; + + Tcl_DStringInit(&result); + + for (i=0; stateNames[i] != NULL; ++i) { + if (mask & (1<<i)) { + if (offbits & (1<<i)) + Tcl_DStringAppend(&result, "!", 1); + Tcl_DStringAppend(&result, stateNames[i], -1); + Tcl_DStringAppend(&result, " ", 1); + } + } + + len = Tcl_DStringLength(&result); + if (len) { + /* 'len' includes extra trailing ' ' */ + objPtr->bytes = Tcl_Alloc((unsigned)len); + objPtr->length = len-1; + strncpy(objPtr->bytes, Tcl_DStringValue(&result), (size_t)len-1); + objPtr->bytes[len-1] = '\0'; + } else { + /* empty string */ + objPtr->length = 0; + objPtr->bytes = Tcl_Alloc(1); + *objPtr->bytes = '\0'; + } + + Tcl_DStringFree(&result); +} + +Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits, unsigned int offbits) +{ + Tcl_Obj *objPtr = Tcl_NewObj(); + + Tcl_InvalidateStringRep(objPtr); + objPtr->typePtr = &StateSpecObjType; + objPtr->internalRep.longValue = (onbits << 16) | offbits; + + return objPtr; +} + +int Ttk_GetStateSpecFromObj( + Tcl_Interp *interp, + Tcl_Obj *objPtr, + Ttk_StateSpec *spec) +{ + if (objPtr->typePtr != &StateSpecObjType) { + int status = StateSpecSetFromAny(interp, objPtr); + if (status != TCL_OK) + return status; + } + + spec->onbits = (objPtr->internalRep.longValue & 0xFFFF0000) >> 16; + spec->offbits = objPtr->internalRep.longValue & 0x0000FFFF; + return TCL_OK; +} + + +/* + * Tk_StateMapLookup -- + * + * A state map is a paired list of StateSpec / value pairs. + * Returns the value corresponding to the first matching state + * specification, or NULL if not found or an error occurs. + */ +Tcl_Obj *Ttk_StateMapLookup( + Tcl_Interp *interp, /* Where to leave error messages; may be NULL */ + Ttk_StateMap map, /* State map */ + Ttk_State state) /* State to look up */ +{ + Tcl_Obj **specs; + int nSpecs; + int j, status; + + status = Tcl_ListObjGetElements(interp, map, &nSpecs, &specs); + if (status != TCL_OK) + return NULL; + + for (j = 0; j < nSpecs; j += 2) { + Ttk_StateSpec spec; + status = Ttk_GetStateSpecFromObj(interp, specs[j], &spec); + if (status != TCL_OK) + return NULL; + if (Ttk_StateMatches(state, &spec)) + return specs[j+1]; + } + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "No match in state map", NULL); + } + return NULL; +} + +/* Ttk_GetStateMapFromObj -- + * Returns a Ttk_StateMap from a Tcl_Obj*. + * Since a Ttk_StateMap is just a specially-formatted Tcl_Obj, + * this basically just checks for errors. + */ +Ttk_StateMap Ttk_GetStateMapFromObj( + Tcl_Interp *interp, /* Where to leave error messages; may be NULL */ + Tcl_Obj *mapObj) /* State map */ +{ + Tcl_Obj **specs; + int nSpecs; + int j, status; + + status = Tcl_ListObjGetElements(interp, mapObj, &nSpecs, &specs); + if (status != TCL_OK) + return NULL; + + if (nSpecs % 2 != 0) { + if (interp) + Tcl_SetResult(interp, + "State map must have an even number of elements", + TCL_STATIC); + return 0; + } + + for (j = 0; j < nSpecs; j += 2) { + Ttk_StateSpec spec; + if (Ttk_GetStateSpecFromObj(interp, specs[j], &spec) != TCL_OK) + return NULL; + } + + return mapObj; +} + +/* + * Ttk_StateTableLooup -- + * Look up an index from a statically allocated state table. + */ +int Ttk_StateTableLookup(Ttk_StateTable *map, unsigned int state) +{ + while ((state & map->onBits) != map->onBits + || (~state & map->offBits) != map->offBits) + { + ++map; + } + return map->index; +} + +/*EOF*/ diff --git a/generic/ttk/ttkStubInit.c b/generic/ttk/ttkStubInit.c new file mode 100644 index 0000000..87b33dc --- /dev/null +++ b/generic/ttk/ttkStubInit.c @@ -0,0 +1,61 @@ +/* + * This file is (mostly) automatically generated from ttk.decls. + * It is compiled and linked in with the ttk package proper. + */ + +#include "tk.h" +#include "ttkTheme.h" + +MODULE_SCOPE const TtkStubs ttkStubs; + +/* !BEGIN!: Do not edit below this line. */ + +const TtkStubs ttkStubs = { + TCL_STUB_MAGIC, + TTK_STUBS_EPOCH, + TTK_STUBS_REVISION, + 0, + Ttk_GetTheme, /* 0 */ + Ttk_GetDefaultTheme, /* 1 */ + Ttk_GetCurrentTheme, /* 2 */ + Ttk_CreateTheme, /* 3 */ + Ttk_RegisterCleanup, /* 4 */ + Ttk_RegisterElementSpec, /* 5 */ + Ttk_RegisterElement, /* 6 */ + Ttk_RegisterElementFactory, /* 7 */ + Ttk_RegisterLayout, /* 8 */ + 0, /* 9 */ + Ttk_GetStateSpecFromObj, /* 10 */ + Ttk_NewStateSpecObj, /* 11 */ + Ttk_GetStateMapFromObj, /* 12 */ + Ttk_StateMapLookup, /* 13 */ + Ttk_StateTableLookup, /* 14 */ + 0, /* 15 */ + 0, /* 16 */ + 0, /* 17 */ + 0, /* 18 */ + 0, /* 19 */ + Ttk_GetPaddingFromObj, /* 20 */ + Ttk_GetBorderFromObj, /* 21 */ + Ttk_GetStickyFromObj, /* 22 */ + Ttk_MakePadding, /* 23 */ + Ttk_UniformPadding, /* 24 */ + Ttk_AddPadding, /* 25 */ + Ttk_RelievePadding, /* 26 */ + Ttk_MakeBox, /* 27 */ + Ttk_BoxContains, /* 28 */ + Ttk_PackBox, /* 29 */ + Ttk_StickBox, /* 30 */ + Ttk_AnchorBox, /* 31 */ + Ttk_PadBox, /* 32 */ + Ttk_ExpandBox, /* 33 */ + Ttk_PlaceBox, /* 34 */ + Ttk_NewBoxObj, /* 35 */ + 0, /* 36 */ + 0, /* 37 */ + 0, /* 38 */ + 0, /* 39 */ + Ttk_GetOrientFromObj, /* 40 */ +}; + +/* !END!: Do not edit above this line. */ diff --git a/generic/ttk/ttkStubLib.c b/generic/ttk/ttkStubLib.c new file mode 100644 index 0000000..2c07b9d --- /dev/null +++ b/generic/ttk/ttkStubLib.c @@ -0,0 +1,74 @@ +/* + * We need to ensure that we use the tcl stub macros so that this file + * contains no references to any of the tcl stub functions. + */ + +#undef USE_TCL_STUBS +#define USE_TCL_STUBS + +#include "tk.h" + +#define USE_TTK_STUBS 1 +#include "ttkTheme.h" + +MODULE_SCOPE const TtkStubs *ttkStubsPtr; +const TtkStubs *ttkStubsPtr = NULL; + +/* + *---------------------------------------------------------------------- + * + * TtkInitializeStubs -- + * Load the Ttk package, initialize stub table pointer. + * Do not call this function directly, use Ttk_InitStubs() macro instead. + * + * Results: + * The actual version of the package that satisfies the request, or + * NULL to indicate that an error occurred. + * + * Side effects: + * Sets the stub table pointer. + * + */ +MODULE_SCOPE const char * +TtkInitializeStubs( + Tcl_Interp *interp, const char *version, int epoch, int revision) +{ + int exact = 0; + const char *packageName = "Ttk"; + const char *errMsg = NULL; + ClientData pkgClientData = NULL; + const char *actualVersion = Tcl_PkgRequireEx( + interp, packageName, version, exact, &pkgClientData); + const TtkStubs *stubsPtr = pkgClientData; + + if (!actualVersion) { + return NULL; + } + + if (!stubsPtr) { + errMsg = "missing stub table pointer"; + goto error; + } + if (stubsPtr->epoch != epoch) { + errMsg = "epoch number mismatch"; + goto error; + } + if (stubsPtr->revision < revision) { + errMsg = "require later revision"; + goto error; + } + + ttkStubsPtr = stubsPtr; + return actualVersion; + +error: + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Error loading ", packageName, " package", + " (requested version '", version, + "', loaded version '", actualVersion, "'): ", + errMsg, + NULL); + return NULL; +} + diff --git a/generic/ttk/ttkTagSet.c b/generic/ttk/ttkTagSet.c new file mode 100644 index 0000000..9f2a87b --- /dev/null +++ b/generic/ttk/ttkTagSet.c @@ -0,0 +1,306 @@ +/* + * Tag tables. 3/4-baked, work in progress. + * + * Copyright (C) 2005, Joe English. Freely redistributable. + */ + +#include <string.h> /* for memset() */ +#include <tcl.h> +#include <tk.h> + +#include "ttkTheme.h" +#include "ttkWidget.h" + +/*------------------------------------------------------------------------ + * +++ Internal data structures. + */ +struct TtkTag { + int priority; /* 1=>highest */ + const char *tagName; /* Back-pointer to hash table entry */ + void *tagRecord; /* User data */ +}; + +struct TtkTagTable { + Tk_Window tkwin; /* owner window */ + Tk_OptionSpec *optionSpecs; /* ... */ + Tk_OptionTable optionTable; /* ... */ + int recordSize; /* size of tag record */ + int nTags; /* #tags defined so far */ + Tcl_HashTable tags; /* defined tags */ +}; + +/*------------------------------------------------------------------------ + * +++ Tags. + */ +static Ttk_Tag NewTag(Ttk_TagTable tagTable, const char *tagName) +{ + Ttk_Tag tag = (Ttk_Tag)ckalloc(sizeof(*tag)); + tag->tagRecord = ckalloc(tagTable->recordSize); + memset(tag->tagRecord, 0, tagTable->recordSize); + /* Don't need Tk_InitOptions() here, all defaults should be NULL. */ + tag->priority = ++tagTable->nTags; + tag->tagName = tagName; + return tag; +} + +static void DeleteTag(Ttk_TagTable tagTable, Ttk_Tag tag) +{ + Tk_FreeConfigOptions(tag->tagRecord,tagTable->optionTable,tagTable->tkwin); + ckfree(tag->tagRecord); + ckfree((void*)tag); +} + +/*------------------------------------------------------------------------ + * +++ Tag tables. + */ + +Ttk_TagTable Ttk_CreateTagTable( + Tcl_Interp *interp, Tk_Window tkwin, + Tk_OptionSpec optionSpecs[], int recordSize) +{ + Ttk_TagTable tagTable = (Ttk_TagTable)ckalloc(sizeof(*tagTable)); + tagTable->tkwin = tkwin; + tagTable->optionSpecs = optionSpecs; + tagTable->optionTable = Tk_CreateOptionTable(interp, optionSpecs); + tagTable->recordSize = recordSize; + tagTable->nTags = 0; + Tcl_InitHashTable(&tagTable->tags, TCL_STRING_KEYS); + return tagTable; +} + +void Ttk_DeleteTagTable(Ttk_TagTable tagTable) +{ + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + + entryPtr = Tcl_FirstHashEntry(&tagTable->tags, &search); + while (entryPtr != NULL) { + DeleteTag(tagTable, Tcl_GetHashValue(entryPtr)); + entryPtr = Tcl_NextHashEntry(&search); + } + + Tcl_DeleteHashTable(&tagTable->tags); + ckfree((void*)tagTable); +} + +Ttk_Tag Ttk_GetTag(Ttk_TagTable tagTable, const char *tagName) +{ + int isNew = 0; + Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry( + &tagTable->tags, tagName, &isNew); + + if (isNew) { + tagName = Tcl_GetHashKey(&tagTable->tags, entryPtr); + Tcl_SetHashValue(entryPtr, NewTag(tagTable,tagName)); + } + return Tcl_GetHashValue(entryPtr); +} + +Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable tagTable, Tcl_Obj *objPtr) +{ + return Ttk_GetTag(tagTable, Tcl_GetString(objPtr)); +} + +/*------------------------------------------------------------------------ + * +++ Tag sets. + */ + +/* Ttk_GetTagSetFromObj -- + * Extract an array of pointers to Ttk_Tags from a Tcl_Obj. + * objPtr may be NULL, in which case a new empty tag set is returned. + * + * Returns NULL and leaves an error message in interp->result on error. + * + * Non-NULL results must be passed to Ttk_FreeTagSet(). + */ +Ttk_TagSet Ttk_GetTagSetFromObj( + Tcl_Interp *interp, Ttk_TagTable tagTable, Tcl_Obj *objPtr) +{ + Ttk_TagSet tagset = (Ttk_TagSet)(ckalloc(sizeof *tagset)); + Tcl_Obj **objv; + int i, objc; + + if (objPtr == NULL) { + tagset->tags = NULL; + tagset->nTags = 0; + return tagset; + } + + if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { + ckfree((ClientData)tagset); + return NULL; + } + + tagset->tags = (Ttk_Tag*)ckalloc((objc+1) * sizeof(Ttk_Tag)); + for (i=0; i<objc; ++i) { + tagset->tags[i] = Ttk_GetTagFromObj(tagTable, objv[i]); + } + tagset->tags[i] = NULL; + tagset->nTags = objc; + + return tagset; +} + +/* Ttk_NewTagSetObj -- + * Construct a fresh Tcl_Obj * from a tag set. + */ +Tcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet tagset) +{ + Tcl_Obj *result = Tcl_NewListObj(0,0); + int i; + + for (i = 0; i < tagset->nTags; ++i) { + Tcl_ListObjAppendElement( + NULL, result, Tcl_NewStringObj(tagset->tags[i]->tagName, -1)); + } + return result; +} + +void Ttk_FreeTagSet(Ttk_TagSet tagset) +{ + ckfree((ClientData)tagset->tags); + ckfree((ClientData)tagset); +} + +/* Ttk_TagSetContains -- test if tag set contains a tag. + */ +int Ttk_TagSetContains(Ttk_TagSet tagset, Ttk_Tag tag) +{ + int i; + for (i = 0; i < tagset->nTags; ++i) { + if (tagset->tags[i] == tag) { + return 1; + } + } + return 0; +} + +/* Ttk_TagSetAdd -- add a tag to a tag set. + * + * Returns: 0 if tagset already contained tag, + * 1 if tagset was modified. + */ +int Ttk_TagSetAdd(Ttk_TagSet tagset, Ttk_Tag tag) +{ + int i; + for (i = 0; i < tagset->nTags; ++i) { + if (tagset->tags[i] == tag) { + return 0; + } + } + tagset->tags = (void*)ckrealloc((void*)tagset->tags, + (tagset->nTags+1)*sizeof(tagset->tags[0])); + tagset->tags[tagset->nTags++] = tag; + return 1; +} + +/* Ttk_TagSetRemove -- remove a tag from a tag set. + * + * Returns: 0 if tagset did not contain tag, + * 1 if tagset was modified. + */ +int Ttk_TagSetRemove(Ttk_TagSet tagset, Ttk_Tag tag) +{ + int i = 0, j = 0; + while (i < tagset->nTags) { + if ((tagset->tags[j] = tagset->tags[i]) != tag) { + ++j; + } + ++i; + } + tagset->nTags = j; + return j != i; +} + +/*------------------------------------------------------------------------ + * +++ Utilities for widget commands. + */ + +/* Ttk_EnumerateTags -- implements [$w tag names] + */ +int Ttk_EnumerateTags( + Tcl_Interp *interp, Ttk_TagTable tagTable) +{ + return TtkEnumerateHashTable(interp, &tagTable->tags); +} + +/* Ttk_EnumerateTagOptions -- implements [$w tag configure $tag] + */ +int Ttk_EnumerateTagOptions( + Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag) +{ + return TtkEnumerateOptions(interp, tag->tagRecord, + tagTable->optionSpecs, tagTable->optionTable, tagTable->tkwin); +} + +/* Ttk_TagOptionValue -- implements [$w tag configure $tag -option] + */ +Tcl_Obj *Ttk_TagOptionValue( + Tcl_Interp *interp, + Ttk_TagTable tagTable, + Ttk_Tag tag, + Tcl_Obj *optionName) +{ + return Tk_GetOptionValue(interp, + tag->tagRecord, tagTable->optionTable, optionName, tagTable->tkwin); +} + +/* Ttk_ConfigureTag -- implements [$w tag configure $tag -option value...] + */ +int Ttk_ConfigureTag( + Tcl_Interp *interp, + Ttk_TagTable tagTable, + Ttk_Tag tag, + int objc, Tcl_Obj *const objv[]) +{ + return Tk_SetOptions( + interp, tag->tagRecord, tagTable->optionTable, + objc, objv, tagTable->tkwin, NULL/*savedOptions*/, NULL/*mask*/); +} + +/*------------------------------------------------------------------------ + * +++ Tag values. + */ + +#define OBJ_AT(record, offset) (*(Tcl_Obj**)(((char*)record)+offset)) + +void Ttk_TagSetValues(Ttk_TagTable tagTable, Ttk_TagSet tagSet, void *record) +{ + const int LOWEST_PRIORITY = 0x7FFFFFFF; + int i, j; + + memset(record, 0, tagTable->recordSize); + + for (i = 0; tagTable->optionSpecs[i].type != TK_OPTION_END; ++i) { + Tk_OptionSpec *optionSpec = tagTable->optionSpecs + i; + int offset = optionSpec->objOffset; + int prio = LOWEST_PRIORITY; + + for (j = 0; j < tagSet->nTags; ++j) { + Ttk_Tag tag = tagSet->tags[j]; + if (OBJ_AT(tag->tagRecord, offset) != 0 && tag->priority < prio) { + OBJ_AT(record, offset) = OBJ_AT(tag->tagRecord, offset); + prio = tag->priority; + } + } + } +} + +void Ttk_TagSetApplyStyle( + Ttk_TagTable tagTable, Ttk_Style style, Ttk_State state, void *record) +{ + Tk_OptionSpec *optionSpec = tagTable->optionSpecs; + + while (optionSpec->type != TK_OPTION_END) { + int offset = optionSpec->objOffset; + const char *optionName = optionSpec->optionName; + Tcl_Obj *val = Ttk_StyleMap(style, optionName, state); + if (val) { + OBJ_AT(record, offset) = val; + } else if (OBJ_AT(record, offset) == 0) { + OBJ_AT(record, offset) = Ttk_StyleDefault(style, optionName); + } + ++optionSpec; + } +} + diff --git a/generic/ttk/ttkTheme.c b/generic/ttk/ttkTheme.c new file mode 100644 index 0000000..5095487 --- /dev/null +++ b/generic/ttk/ttkTheme.c @@ -0,0 +1,1737 @@ +/* + * ttkTheme.c -- + * + * This file implements the widget styles and themes support. + * + * Copyright (c) 2002 Frederic Bonnet + * Copyright (c) 2003 Joe English + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include <stdlib.h> +#include <string.h> +#include <tk.h> +#include <tkInt.h> +#include "ttkThemeInt.h" + +#define PKG_ASSOC_KEY "Ttk" + +/*------------------------------------------------------------------------ + * +++ Styles. + * + * Invariants: + * If styleName contains a dot, parentStyle->styleName is everything + * after the first dot; otherwise, parentStyle is the theme's root + * style ".". The root style's parentStyle is NULL. + * + */ + +typedef struct Ttk_Style_ +{ + const char *styleName; /* points to hash table key */ + Tcl_HashTable settingsTable; /* KEY: string; VALUE: StateMap */ + Tcl_HashTable defaultsTable; /* KEY: string; VALUE: resource */ + Ttk_LayoutTemplate layoutTemplate; /* Layout template for style, or NULL */ + Ttk_Style parentStyle; /* Previous style in chain */ + Ttk_ResourceCache cache; /* Back-pointer to resource cache */ +} Style; + +static Style *NewStyle() +{ + Style *stylePtr = (Style*)ckalloc(sizeof(Style)); + + stylePtr->styleName = NULL; + stylePtr->parentStyle = NULL; + stylePtr->layoutTemplate = NULL; + stylePtr->cache = NULL; + Tcl_InitHashTable(&stylePtr->settingsTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&stylePtr->defaultsTable, TCL_STRING_KEYS); + + return stylePtr; +} + +static void FreeStyle(Style *stylePtr) +{ + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + + entryPtr = Tcl_FirstHashEntry(&stylePtr->settingsTable, &search); + while (entryPtr != NULL) { + Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr); + Tcl_DecrRefCount(stateMap); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&stylePtr->settingsTable); + + entryPtr = Tcl_FirstHashEntry(&stylePtr->defaultsTable, &search); + while (entryPtr != NULL) { + Tcl_Obj *defaultValue = Tcl_GetHashValue(entryPtr); + Tcl_DecrRefCount(defaultValue); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&stylePtr->defaultsTable); + + Ttk_FreeLayoutTemplate(stylePtr->layoutTemplate); + + ckfree((ClientData)stylePtr); +} + +/* + * Ttk_StyleMap -- + * Look up state-specific option value from specified style. + */ +Tcl_Obj *Ttk_StyleMap(Ttk_Style style, const char *optionName, Ttk_State state) +{ + while (style) { + Tcl_HashEntry *entryPtr = + Tcl_FindHashEntry(&style->settingsTable, optionName); + if (entryPtr) { + Ttk_StateMap stateMap = Tcl_GetHashValue(entryPtr); + return Ttk_StateMapLookup(NULL, stateMap, state); + } + style = style->parentStyle; + } + return 0; +} + +/* + * Ttk_StyleDefault -- + * Look up default resource setting the in the specified style. + */ +Tcl_Obj *Ttk_StyleDefault(Ttk_Style style, const char *optionName) +{ + while (style) { + Tcl_HashEntry *entryPtr = + Tcl_FindHashEntry(&style->defaultsTable, optionName); + if (entryPtr) + return Tcl_GetHashValue(entryPtr); + style= style->parentStyle; + } + return 0; +} + +/*------------------------------------------------------------------------ + * +++ Elements. + */ +typedef const Tk_OptionSpec **OptionMap; + /* array of Tk_OptionSpecs mapping widget options to element options */ + +struct Ttk_ElementClass_ { + const char *name; /* Points to hash table key */ + Ttk_ElementSpec *specPtr; /* Template provided during registration. */ + void *clientData; /* Client data passed in at registration time */ + void *elementRecord; /* Scratch buffer for element record storage */ + int nResources; /* #Element options */ + Tcl_Obj **defaultValues; /* Array of option default values */ + Tcl_HashTable optMapCache; /* Map: Tk_OptionTable * -> OptionMap */ +}; + +/* TTKGetOptionSpec -- + * Look up a Tk_OptionSpec by name from a Tk_OptionTable, + * and verify that it's compatible with the specified Tk_OptionType, + * along with other constraints (see below). + */ +static const Tk_OptionSpec *TTKGetOptionSpec( + const char *optionName, + Tk_OptionTable optionTable, + Tk_OptionType optionType) +{ + const Tk_OptionSpec *optionSpec = TkGetOptionSpec(optionName, optionTable); + + if (!optionSpec) + return 0; + + /* Make sure widget option has a Tcl_Obj* entry: + */ + if (optionSpec->objOffset < 0) { + return 0; + } + + /* Grrr. Ignore accidental mismatches caused by prefix-matching: + */ + if (strcmp(optionSpec->optionName, optionName)) { + return 0; + } + + /* Ensure that the widget option type is compatible with + * the element option type. + * + * TK_OPTION_STRING element options are compatible with anything. + * As a workaround for the workaround for Bug #967209, + * TK_OPTION_STRING widget options are also compatible with anything + * (see <<NOTE-NULLOPTIONS>>). + */ + if ( optionType != TK_OPTION_STRING + && optionSpec->type != TK_OPTION_STRING + && optionType != optionSpec->type) + { + return 0; + } + + return optionSpec; +} + +/* BuildOptionMap -- + * Construct the mapping from element options to widget options. + */ +static OptionMap +BuildOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable) +{ + OptionMap optionMap = (OptionMap)ckalloc( + sizeof(const Tk_OptionSpec) * elementClass->nResources + 1); + int i; + + for (i = 0; i < elementClass->nResources; ++i) { + Ttk_ElementOptionSpec *e = elementClass->specPtr->options+i; + optionMap[i] = TTKGetOptionSpec(e->optionName, optionTable, e->type); + } + + return optionMap; +} + +/* GetOptionMap -- + * Return a cached OptionMap matching the specified optionTable + * for the specified element, creating it if necessary. + */ +static OptionMap +GetOptionMap(Ttk_ElementClass *elementClass, Tk_OptionTable optionTable) +{ + OptionMap optionMap; + int isNew; + Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry( + &elementClass->optMapCache, (void*)optionTable, &isNew); + + if (isNew) { + optionMap = BuildOptionMap(elementClass, optionTable); + Tcl_SetHashValue(entryPtr, optionMap); + } else { + optionMap = Tcl_GetHashValue(entryPtr); + } + + return optionMap; +} + +/* + * NewElementClass -- + * Allocate and initialize an element class record + * from the specified element specification. + */ +static Ttk_ElementClass * +NewElementClass(const char *name, Ttk_ElementSpec *specPtr,void *clientData) +{ + Ttk_ElementClass *elementClass = + (Ttk_ElementClass*)ckalloc(sizeof(Ttk_ElementClass)); + int i; + + elementClass->name = name; + elementClass->specPtr = specPtr; + elementClass->clientData = clientData; + elementClass->elementRecord = ckalloc(specPtr->elementSize); + + /* Count #element resources: + */ + for (i = 0; specPtr->options[i].optionName != 0; ++i) + continue; + elementClass->nResources = i; + + /* Initialize default values: + */ + elementClass->defaultValues = (Tcl_Obj**) + ckalloc(elementClass->nResources * sizeof(Tcl_Obj *) + 1); + for (i=0; i < elementClass->nResources; ++i) { + const char *defaultValue = specPtr->options[i].defaultValue; + if (defaultValue) { + elementClass->defaultValues[i] = Tcl_NewStringObj(defaultValue,-1); + Tcl_IncrRefCount(elementClass->defaultValues[i]); + } else { + elementClass->defaultValues[i] = 0; + } + } + + /* Initialize option map cache: + */ + Tcl_InitHashTable(&elementClass->optMapCache, TCL_ONE_WORD_KEYS); + + return elementClass; +} + +/* + * FreeElementClass -- + * Release resources associated with an element class record. + */ +static void FreeElementClass(Ttk_ElementClass *elementClass) +{ + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + int i; + + /* + * Free default values: + */ + for (i = 0; i < elementClass->nResources; ++i) { + if (elementClass->defaultValues[i]) { + Tcl_DecrRefCount(elementClass->defaultValues[i]); + } + } + ckfree((ClientData)elementClass->defaultValues); + + /* + * Free option map cache: + */ + entryPtr = Tcl_FirstHashEntry(&elementClass->optMapCache, &search); + while (entryPtr != NULL) { + ckfree(Tcl_GetHashValue(entryPtr)); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&elementClass->optMapCache); + + ckfree(elementClass->elementRecord); + ckfree((ClientData)elementClass); +} + +/*------------------------------------------------------------------------ + * +++ Themes. + */ + +static int ThemeEnabled(Ttk_Theme theme, void *clientData) { return 1; } + /* Default ThemeEnabledProc -- always return true */ + +typedef struct Ttk_Theme_ +{ + Ttk_Theme parentPtr; /* Parent theme. */ + Tcl_HashTable elementTable; /* Map element names to class records */ + Tcl_HashTable styleTable; /* Map style names to Styles */ + Ttk_Style rootStyle; /* "." style, root of chain */ + Ttk_ThemeEnabledProc *enabledProc; /* Function called by SetTheme */ + void *enabledData; /* ClientData for enabledProc */ + Ttk_ResourceCache cache; /* Back-pointer to resource cache */ +} Theme; + +static Theme *NewTheme(Ttk_ResourceCache cache, Ttk_Theme parent) +{ + Theme *themePtr = (Theme*)ckalloc(sizeof(Theme)); + Tcl_HashEntry *entryPtr; + int unused; + + themePtr->parentPtr = parent; + themePtr->enabledProc = ThemeEnabled; + themePtr->enabledData = NULL; + themePtr->cache = cache; + Tcl_InitHashTable(&themePtr->elementTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&themePtr->styleTable, TCL_STRING_KEYS); + + /* + * Create root style "." + */ + entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, ".", &unused); + themePtr->rootStyle = NewStyle(); + themePtr->rootStyle->styleName = + Tcl_GetHashKey(&themePtr->styleTable, entryPtr); + themePtr->rootStyle->cache = themePtr->cache; + Tcl_SetHashValue(entryPtr, themePtr->rootStyle); + + return themePtr; +} + +static void FreeTheme(Theme *themePtr) +{ + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + + /* + * Free element table: + */ + entryPtr = Tcl_FirstHashEntry(&themePtr->elementTable, &search); + while (entryPtr != NULL) { + Ttk_ElementClass *elementClass = Tcl_GetHashValue(entryPtr); + FreeElementClass(elementClass); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&themePtr->elementTable); + + /* + * Free style table: + */ + entryPtr = Tcl_FirstHashEntry(&themePtr->styleTable, &search); + while (entryPtr != NULL) { + Style *stylePtr = Tcl_GetHashValue(entryPtr); + FreeStyle(stylePtr); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&themePtr->styleTable); + + /* + * Free theme record: + */ + ckfree((ClientData)themePtr); + + return; +} + +/* + * Element constructors. + */ +typedef struct { + Ttk_ElementFactory factory; + void *clientData; +} FactoryRec; + +/* + * Cleanup records: + */ +typedef struct CleanupStruct { + void *clientData; + Ttk_CleanupProc *cleanupProc; + struct CleanupStruct *next; +} Cleanup; + +/*------------------------------------------------------------------------ + * +++ Master style package data structure. + */ +typedef struct +{ + Tcl_Interp *interp; /* Owner interp */ + Tcl_HashTable themeTable; /* KEY: name; VALUE: Theme pointer */ + Tcl_HashTable factoryTable; /* KEY: name; VALUE: FactoryRec ptr */ + Theme *defaultTheme; /* Default theme; global fallback*/ + Theme *currentTheme; /* Currently-selected theme */ + Cleanup *cleanupList; /* Cleanup records */ + Ttk_ResourceCache cache; /* Resource cache */ + int themeChangePending; /* scheduled ThemeChangedProc call? */ +} StylePackageData; + +static void ThemeChangedProc(ClientData); /* Forward */ + +/* Ttk_StylePkgFree -- + * Cleanup procedure for StylePackageData. + */ +static void Ttk_StylePkgFree(ClientData clientData, Tcl_Interp *interp) +{ + StylePackageData *pkgPtr = clientData; + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr; + Cleanup *cleanup; + + /* + * Cancel any pending ThemeChanged calls: + */ + if (pkgPtr->themeChangePending) { + Tcl_CancelIdleCall(ThemeChangedProc, pkgPtr); + } + + /* + * Free themes. + */ + entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search); + while (entryPtr != NULL) { + Theme *themePtr = Tcl_GetHashValue(entryPtr); + FreeTheme(themePtr); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&pkgPtr->themeTable); + + /* + * Free element constructor table: + */ + entryPtr = Tcl_FirstHashEntry(&pkgPtr->factoryTable, &search); + while (entryPtr != NULL) { + ckfree(Tcl_GetHashValue(entryPtr)); + entryPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&pkgPtr->factoryTable); + + /* + * Release cache: + */ + Ttk_FreeResourceCache(pkgPtr->cache); + + /* + * Call all registered cleanup procedures: + */ + cleanup = pkgPtr->cleanupList; + while (cleanup) { + Cleanup *next = cleanup->next; + cleanup->cleanupProc(cleanup->clientData); + ckfree((ClientData)cleanup); + cleanup = next; + } + + ckfree((ClientData)pkgPtr); +} + +/* + * GetStylePackageData -- + * Look up the package data registered with the interp. + */ + +static StylePackageData *GetStylePackageData(Tcl_Interp *interp) +{ + return Tcl_GetAssocData(interp, PKG_ASSOC_KEY, NULL); +} + +/* + * Ttk_RegisterCleanup -- + * + * Register a function to be called when a theme engine is deleted. + * (This only happens when the main interp is destroyed). The cleanup + * function is called with the current Tcl interpreter and the client + * data provided here. + * + */ +void Ttk_RegisterCleanup( + Tcl_Interp *interp, ClientData clientData, Ttk_CleanupProc *cleanupProc) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + Cleanup *cleanup = (Cleanup*)ckalloc(sizeof(*cleanup)); + + cleanup->clientData = clientData; + cleanup->cleanupProc = cleanupProc; + cleanup->next = pkgPtr->cleanupList; + pkgPtr->cleanupList = cleanup; +} + +/* ThemeChangedProc -- + * Notify all widgets that the theme has been changed. + * Scheduled as an idle callback; clientData is a StylePackageData *. + * + * Sends a <<ThemeChanged>> event to every widget in the hierarchy. + * Widgets respond to this by calling the WorldChanged class proc, + * which in turn recreates the layout. + * + * The Tk C API doesn't doesn't provide an easy way to traverse + * the widget hierarchy, so this is done by evaluating a Tcl script. + */ + +static void ThemeChangedProc(ClientData clientData) +{ + static char ThemeChangedScript[] = "ttk::ThemeChanged"; + StylePackageData *pkgPtr = clientData; + + if (Tcl_GlobalEval(pkgPtr->interp, ThemeChangedScript) != TCL_OK) { + Tcl_BackgroundError(pkgPtr->interp); + } + pkgPtr->themeChangePending = 0; +} + +/* + * ThemeChanged -- + * Schedule a call to ThemeChanged if one is not already pending. + */ +static void ThemeChanged(StylePackageData *pkgPtr) +{ + if (!pkgPtr->themeChangePending) { + Tcl_DoWhenIdle(ThemeChangedProc, pkgPtr); + pkgPtr->themeChangePending = 1; + } +} + +/* + * Ttk_CreateTheme -- + * Create a new theme and register it in the global theme table. + * + * Returns: + * Pointer to new Theme structure; NULL if named theme already exists. + * Leaves an error message in interp's result on error. + */ + +Ttk_Theme +Ttk_CreateTheme( + Tcl_Interp *interp, /* Interpreter in which to create theme */ + const char *name, /* Name of the theme to create. */ + Ttk_Theme parent) /* Parent/fallback theme, NULL for default */ +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + Tcl_HashEntry *entryPtr; + int newEntry; + Theme *themePtr; + + entryPtr = Tcl_CreateHashEntry(&pkgPtr->themeTable, name, &newEntry); + if (!newEntry) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Theme ", name, " already exists", NULL); + return NULL; + } + + /* + * Initialize new theme: + */ + if (!parent) parent = pkgPtr->defaultTheme; + + themePtr = NewTheme(pkgPtr->cache, parent); + Tcl_SetHashValue(entryPtr, themePtr); + + return themePtr; +} + +/* + * Ttk_SetThemeEnabledProc -- + * Sets a procedure that is used to check that this theme is available. + */ + +void Ttk_SetThemeEnabledProc( + Ttk_Theme theme, Ttk_ThemeEnabledProc enabledProc, void *enabledData) +{ + theme->enabledProc = enabledProc; + theme->enabledData = enabledData; +} + +/* + * LookupTheme -- + * Retrieve a registered theme by name. If not found, + * returns NULL and leaves an error message in interp's result. + */ + +static Ttk_Theme LookupTheme( + Tcl_Interp *interp, /* where to leave error messages */ + StylePackageData *pkgPtr, /* style package master record */ + const char *name) /* theme name */ +{ + Tcl_HashEntry *entryPtr; + + entryPtr = Tcl_FindHashEntry(&pkgPtr->themeTable, name); + if (!entryPtr) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "theme \"", name, "\" doesn't exist", NULL); + return NULL; + } + + return Tcl_GetHashValue(entryPtr); +} + +/* + * Ttk_GetTheme -- + * Public interface to LookupTheme. + */ +Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *themeName) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + + return LookupTheme(interp, pkgPtr, themeName); +} + +Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + return pkgPtr->currentTheme; +} + +Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + return pkgPtr->defaultTheme; +} + +/* + * Ttk_UseTheme -- + * Set the current theme, notify all widgets that the theme has changed. + */ +int Ttk_UseTheme(Tcl_Interp *interp, Ttk_Theme theme) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + + /* + * Check if selected theme is enabled: + */ + while (theme && !theme->enabledProc(theme, theme->enabledData)) { + theme = theme->parentPtr; + } + if (!theme) { + /* This shouldn't happen -- default theme should always work */ + Tcl_Panic("No themes available?"); + return TCL_ERROR; + } + + pkgPtr->currentTheme = theme; + ThemeChanged(pkgPtr); + return TCL_OK; +} + +/* + * Ttk_GetResourceCache -- + * Return the resource cache associated with 'interp' + */ +Ttk_ResourceCache +Ttk_GetResourceCache(Tcl_Interp *interp) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + return pkgPtr->cache; +} + +/* + * Register a new layout specification with a style. + * @@@ TODO: Make sure layoutName is not ".", root style must not have a layout + */ +MODULE_SCOPE +void Ttk_RegisterLayoutTemplate( + Ttk_Theme theme, /* Target theme */ + const char *layoutName, /* Name of new layout */ + Ttk_LayoutTemplate layoutTemplate) /* Template */ +{ + Ttk_Style style = Ttk_GetStyle(theme, layoutName); + if (style->layoutTemplate) { + Ttk_FreeLayoutTemplate(style->layoutTemplate); + } + style->layoutTemplate = layoutTemplate; +} + +void Ttk_RegisterLayout( + Ttk_Theme themePtr, /* Target theme */ + const char *layoutName, /* Name of new layout */ + Ttk_LayoutSpec specPtr) /* Static layout information */ +{ + Ttk_LayoutTemplate layoutTemplate = Ttk_BuildLayoutTemplate(specPtr); + Ttk_RegisterLayoutTemplate(themePtr, layoutName, layoutTemplate); +} + +/* + * Ttk_GetStyle -- + * Look up a Style from a Theme, create new style if not found. + */ +Ttk_Style Ttk_GetStyle(Ttk_Theme themePtr, const char *styleName) +{ + Tcl_HashEntry *entryPtr; + int newStyle; + + entryPtr = Tcl_CreateHashEntry(&themePtr->styleTable, styleName, &newStyle); + if (newStyle) { + Ttk_Style stylePtr = NewStyle(); + const char *dot = strchr(styleName, '.'); + + if (dot) { + stylePtr->parentStyle = Ttk_GetStyle(themePtr, dot + 1); + } else { + stylePtr->parentStyle = themePtr->rootStyle; + } + + stylePtr->styleName = Tcl_GetHashKey(&themePtr->styleTable, entryPtr); + stylePtr->cache = stylePtr->parentStyle->cache; + Tcl_SetHashValue(entryPtr, stylePtr); + return stylePtr; + } + return Tcl_GetHashValue(entryPtr); +} + +/* FindLayoutTemplate -- + * Locate a layout template in the layout table, checking + * generic names to specific names first, then looking for + * the full name in the parent theme. + */ +Ttk_LayoutTemplate +Ttk_FindLayoutTemplate(Ttk_Theme themePtr, const char *layoutName) +{ + while (themePtr) { + Ttk_Style stylePtr = Ttk_GetStyle(themePtr, layoutName); + while (stylePtr) { + if (stylePtr->layoutTemplate) { + return stylePtr->layoutTemplate; + } + stylePtr = stylePtr->parentStyle; + } + themePtr = themePtr->parentPtr; + } + return NULL; +} + +const char *Ttk_StyleName(Ttk_Style stylePtr) +{ + return stylePtr->styleName; +} + +/* + * Ttk_GetElement -- + * Look up an element class by name in a given theme. + * If not found, try generic element names in this theme, then + * repeat the lookups in the parent theme. + * If not found, return the null element. + */ +Ttk_ElementClass *Ttk_GetElement(Ttk_Theme themePtr, const char *elementName) +{ + Tcl_HashEntry *entryPtr; + const char *dot = elementName; + + /* + * Check if element has already been registered: + */ + entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, elementName); + if (entryPtr) { + return Tcl_GetHashValue(entryPtr); + } + + /* + * Check generic names: + */ + while (!entryPtr && ((dot = strchr(dot, '.')) != NULL)) { + dot++; + entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, dot); + } + if (entryPtr) { + return Tcl_GetHashValue(entryPtr); + } + + /* + * Check parent theme: + */ + if (themePtr->parentPtr) { + return Ttk_GetElement(themePtr->parentPtr, elementName); + } + + /* + * Not found, and this is the root theme; return null element, "". + * (@@@ SHOULD: signal a background error) + */ + entryPtr = Tcl_FindHashEntry(&themePtr->elementTable, ""); + /* ASSERT: entryPtr != 0 */ + return Tcl_GetHashValue(entryPtr); +} + +const char *Ttk_ElementClassName(Ttk_ElementClass *elementClass) +{ + return elementClass->name; +} + +/* + * Ttk_RegisterElementFactory -- + * Register a new element factory. + */ +int Ttk_RegisterElementFactory( + Tcl_Interp *interp, const char *name, + Ttk_ElementFactory factory, void *clientData) +{ + StylePackageData *pkgPtr = GetStylePackageData(interp); + FactoryRec *recPtr = (FactoryRec*)ckalloc(sizeof(*recPtr)); + Tcl_HashEntry *entryPtr; + int newEntry; + + recPtr->factory = factory; + recPtr->clientData = clientData; + + entryPtr = Tcl_CreateHashEntry(&pkgPtr->factoryTable, name, &newEntry); + if (!newEntry) { + /* Free old factory: */ + ckfree(Tcl_GetHashValue(entryPtr)); + } + Tcl_SetHashValue(entryPtr, recPtr); + + return TCL_OK; +} + +/* Ttk_CloneElement -- element factory procedure. + * (style element create $name) "from" $theme ?$element? + */ +static int Ttk_CloneElement( + Tcl_Interp *interp, void *clientData, + Ttk_Theme theme, const char *elementName, + int objc, Tcl_Obj *const objv[]) +{ + Ttk_Theme fromTheme; + Ttk_ElementClass *fromElement; + + if (objc <= 0 || objc > 2) { + Tcl_WrongNumArgs(interp, 0, objv, "theme ?element?"); + return TCL_ERROR; + } + + fromTheme = Ttk_GetTheme(interp, Tcl_GetString(objv[0])); + if (!fromTheme) { + return TCL_ERROR; + } + + if (objc == 2) { + fromElement = Ttk_GetElement(fromTheme, Tcl_GetString(objv[1])); + } else { + fromElement = Ttk_GetElement(fromTheme, elementName); + } + if (!fromElement) { + return TCL_ERROR; + } + + if (Ttk_RegisterElement(interp, theme, elementName, + fromElement->specPtr, fromElement->clientData) == NULL) + { + return TCL_ERROR; + } + return TCL_OK; +} + +/* Ttk_RegisterElement-- + * Register an element in the given theme. + * Returns: Element handle if successful, NULL otherwise. + * On failure, leaves an error message in interp's result + * if interp is non-NULL. + */ + +Ttk_ElementClass *Ttk_RegisterElement( + Tcl_Interp *interp, /* Where to leave error messages */ + Ttk_Theme theme, /* Style engine providing the implementation. */ + const char *name, /* Name of new element */ + Ttk_ElementSpec *specPtr, /* Static template information */ + void *clientData) /* application-specific data */ +{ + Ttk_ElementClass *elementClass; + Tcl_HashEntry *entryPtr; + int newEntry; + + if (specPtr->version != TK_STYLE_VERSION_2) { + /* Version mismatch */ + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Internal error: Ttk_RegisterElement (", + name, "): invalid version", + NULL); + } + return 0; + } + + entryPtr = Tcl_CreateHashEntry(&theme->elementTable, name, &newEntry); + if (!newEntry) { + if (interp) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Duplicate element ", name, NULL); + } + return 0; + } + + name = Tcl_GetHashKey(&theme->elementTable, entryPtr); + elementClass = NewElementClass(name, specPtr, clientData); + Tcl_SetHashValue(entryPtr, elementClass); + + return elementClass; +} + +/* Ttk_RegisterElementSpec (deprecated) -- + * Register a new element. + */ +int Ttk_RegisterElementSpec(Ttk_Theme theme, + const char *name, Ttk_ElementSpec *specPtr, void *clientData) +{ + return Ttk_RegisterElement(NULL, theme, name, specPtr, clientData) + ? TCL_OK : TCL_ERROR; +} + +/*------------------------------------------------------------------------ + * +++ Element record initialization. + */ + +/* + * AllocateResource -- + * Extra initialization for element options like TK_OPTION_COLOR, etc. + * + * Returns: 1 if OK, 0 on failure. + * + * Note: if resource allocation fails at this point (just prior + * to drawing an element), there's really no good place to + * report the error. Instead we just silently fail. + */ + +static int AllocateResource( + Ttk_ResourceCache cache, + Tk_Window tkwin, + Tcl_Obj **destPtr, + int optionType) +{ + Tcl_Obj *resource = *destPtr; + + switch (optionType) + { + case TK_OPTION_FONT: + return (*destPtr = Ttk_UseFont(cache, tkwin, resource)) != NULL; + case TK_OPTION_COLOR: + return (*destPtr = Ttk_UseColor(cache, tkwin, resource)) != NULL; + case TK_OPTION_BORDER: + return (*destPtr = Ttk_UseBorder(cache, tkwin, resource)) != NULL; + default: + /* no-op; always succeeds */ + return 1; + } +} + +/* + * InitializeElementRecord -- + * + * Fill in the element record based on the element's option table. + * Resources are initialized from: + * the corresponding widget option if present and non-NULL, + * otherwise the dynamic state map if specified, + * otherwise from the corresponding widget resource if present, + * otherwise the default value specified at registration time. + * + * Returns: + * 1 if OK, 0 if an error is detected. + * + * NOTES: + * Tcl_Obj * reference counts are _NOT_ adjusted. + */ + +static +int InitializeElementRecord( + Ttk_ElementClass *eclass, /* Element instance to initialize */ + Ttk_Style style, /* Style table */ + char *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; + OptionMap optionMap = GetOptionMap(eclass,optionTable); + int nResources = eclass->nResources; + Ttk_ResourceCache cache = style->cache; + Ttk_ElementOptionSpec *elementOption = eclass->specPtr->options; + + int i; + for (i=0; i<nResources; ++i, ++elementOption) { + Tcl_Obj **dest = (Tcl_Obj **) + (elementRecord + elementOption->offset); + const char *optionName = elementOption->optionName; + Tcl_Obj *dynamicSetting = Ttk_StyleMap(style, optionName, state); + Tcl_Obj *widgetValue = 0; + Tcl_Obj *elementDefault = eclass->defaultValues[i]; + + if (optionMap[i]) { + widgetValue = *(Tcl_Obj **) + (widgetRecord + optionMap[i]->objOffset); + } + + if (widgetValue) { + *dest = widgetValue; + } else if (dynamicSetting) { + *dest = dynamicSetting; + } else { + Tcl_Obj *styleDefault = Ttk_StyleDefault(style, optionName); + *dest = styleDefault ? styleDefault : elementDefault; + } + + if (!AllocateResource(cache, tkwin, dest, elementOption->type)) { + return 0; + } + } + + return 1; +} + +/*------------------------------------------------------------------------ + * +++ Public API. + */ + +/* + * Ttk_QueryStyle -- + * Look up a style option based on the current state. + */ +Tcl_Obj *Ttk_QueryStyle( + Ttk_Style style, /* Style to query */ + void *recordPtr, /* Widget record */ + Tk_OptionTable optionTable, /* Option table describing widget record */ + const char *optionName, /* Option name */ + Ttk_State state) /* Current state */ +{ + const Tk_OptionSpec *optionSpec; + Tcl_Obj *result; + + /* + * Check widget record: + */ + optionSpec = TTKGetOptionSpec(optionName, optionTable, TK_OPTION_ANY); + if (optionSpec) { + result = *(Tcl_Obj**)(((char*)recordPtr) + optionSpec->objOffset); + if (result) { + return result; + } + } + + /* + * Check dynamic settings: + */ + result = Ttk_StyleMap(style, optionName, state); + if (result) { + return result; + } + + /* + * Use style default: + */ + return Ttk_StyleDefault(style, optionName); +} + +/* + * Ttk_ElementSize -- + * Compute the requested size of the given element. + */ + +void +Ttk_ElementSize( + Ttk_ElementClass *eclass, /* Element to query */ + Ttk_Style style, /* Style settings */ + char *recordPtr, /* The widget record. */ + Tk_OptionTable optionTable, /* Description of widget record */ + Tk_Window tkwin, /* The widget window. */ + Ttk_State state, /* Current widget state */ + int *widthPtr, /* Requested width */ + int *heightPtr, /* Reqested height */ + Ttk_Padding *paddingPtr) /* Requested inner border */ +{ + paddingPtr->left = paddingPtr->right = paddingPtr->top = paddingPtr->bottom + = *widthPtr = *heightPtr = 0; + + if (!InitializeElementRecord( + eclass, style, recordPtr, optionTable, tkwin, state)) + { + return; + } + eclass->specPtr->size( + eclass->clientData, eclass->elementRecord, + tkwin, widthPtr, heightPtr, paddingPtr); +} + +/* + * Ttk_DrawElement -- + * Draw the given widget element in a given drawable area. + */ + +void +Ttk_DrawElement( + Ttk_ElementClass *eclass, /* Element instance */ + Ttk_Style style, /* Style settings */ + char *recordPtr, /* The widget record. */ + Tk_OptionTable optionTable, /* Description of option table */ + Tk_Window tkwin, /* The widget window. */ + Drawable d, /* Where to draw element. */ + Ttk_Box b, /* Element area */ + Ttk_State state) /* Widget or element state flags. */ +{ + if (b.width <= 0 || b.height <= 0) + return; + if (!InitializeElementRecord( + eclass, style, recordPtr, optionTable, tkwin, state)) + { + return; + } + eclass->specPtr->draw( + eclass->clientData, eclass->elementRecord, + tkwin, d, b, state); +} + +/*------------------------------------------------------------------------ + * +++ 'style' command ensemble procedures. + */ + +/* + * TtkEnumerateHashTable -- + * Helper routine. Sets interp's result to the list of all keys + * in the hash table. + * + * Returns: TCL_OK. + * Side effects: Sets interp's result. + */ + +MODULE_SCOPE +int TtkEnumerateHashTable(Tcl_Interp *interp, Tcl_HashTable *ht) +{ + Tcl_HashSearch search; + Tcl_Obj *result = Tcl_NewListObj(0, NULL); + Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search); + + while (entryPtr != NULL) { + Tcl_Obj *nameObj = Tcl_NewStringObj(Tcl_GetHashKey(ht, entryPtr),-1); + Tcl_ListObjAppendElement(interp, result, nameObj); + entryPtr = Tcl_NextHashEntry(&search); + } + + Tcl_SetObjResult(interp, result); + return TCL_OK; +} + +/* HashTableToDict -- + * Helper routine. Converts a TCL_STRING_KEYS Tcl_HashTable + * with Tcl_Obj * entries into a dictionary. + */ +static Tcl_Obj* HashTableToDict(Tcl_HashTable *ht) +{ + Tcl_HashSearch search; + Tcl_Obj *result = Tcl_NewListObj(0, NULL); + Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search); + + while (entryPtr != NULL) { + Tcl_Obj *nameObj = Tcl_NewStringObj(Tcl_GetHashKey(ht, entryPtr),-1); + Tcl_Obj *valueObj = Tcl_GetHashValue(entryPtr); + Tcl_ListObjAppendElement(NULL, result, nameObj); + Tcl_ListObjAppendElement(NULL, result, valueObj); + entryPtr = Tcl_NextHashEntry(&search); + } + + return result; +} + +/* + style map $style ? -resource statemap ... ? + * + * Note that resource names are unconstrained; the Style + * doesn't know what resources individual elements may use. + */ +static int +StyleMapCmd( + ClientData clientData, /* Master StylePackageData pointer */ + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *const objv[]) /* Argument objects */ +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + const char *styleName; + Style *stylePtr; + int i; + + if (objc < 3) { +usage: + Tcl_WrongNumArgs(interp,2,objv,"style ?-option ?value...??"); + return TCL_ERROR; + } + + styleName = Tcl_GetString(objv[2]); + stylePtr = Ttk_GetStyle(theme, styleName); + + /* NOTE: StateMaps are actually Tcl_Obj *s, so HashTableToDict works + * for settingsTable. + */ + if (objc == 3) { /* style map $styleName */ + Tcl_SetObjResult(interp, HashTableToDict(&stylePtr->settingsTable)); + return TCL_OK; + } else if (objc == 4) { /* style map $styleName -option */ + const char *optionName = Tcl_GetString(objv[3]); + Tcl_HashEntry *entryPtr = + Tcl_FindHashEntry(&stylePtr->settingsTable, optionName); + if (entryPtr) { + Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr)); + } + return TCL_OK; + } else if (objc % 2 != 1) { + goto usage; + } + + for (i = 3; i < objc; i += 2) { + const char *optionName = Tcl_GetString(objv[i]); + Tcl_Obj *stateMap = objv[i+1]; + Tcl_HashEntry *entryPtr; + int newEntry; + + /* Make sure 'stateMap' is legal: + * (@@@ SHOULD: check for valid resource values as well, + * but we don't know what types they should be at this level.) + */ + if (!Ttk_GetStateMapFromObj(interp, stateMap)) + return TCL_ERROR; + + entryPtr = Tcl_CreateHashEntry( + &stylePtr->settingsTable,optionName,&newEntry); + + Tcl_IncrRefCount(stateMap); + if (!newEntry) { + Tcl_DecrRefCount((Tcl_Obj*)Tcl_GetHashValue(entryPtr)); + } + Tcl_SetHashValue(entryPtr, stateMap); + } + ThemeChanged(pkgPtr); + return TCL_OK; +} + +/* + style configure $style -option ?value... + */ +static int StyleConfigureCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + const char *styleName; + Style *stylePtr; + int i; + + if (objc < 3) { +usage: + Tcl_WrongNumArgs(interp,2,objv,"style ?-option ?value...??"); + return TCL_ERROR; + } + + styleName = Tcl_GetString(objv[2]); + stylePtr = Ttk_GetStyle(theme, styleName); + + if (objc == 3) { /* style default $styleName */ + Tcl_SetObjResult(interp, HashTableToDict(&stylePtr->defaultsTable)); + return TCL_OK; + } else if (objc == 4) { /* style default $styleName -option */ + const char *optionName = Tcl_GetString(objv[3]); + Tcl_HashEntry *entryPtr = + Tcl_FindHashEntry(&stylePtr->defaultsTable, optionName); + if (entryPtr) { + Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr)); + } + return TCL_OK; + } else if (objc % 2 != 1) { + goto usage; + } + + for (i = 3; i < objc; i += 2) { + const char *optionName = Tcl_GetString(objv[i]); + Tcl_Obj *value = objv[i+1]; + Tcl_HashEntry *entryPtr; + int newEntry; + + entryPtr = Tcl_CreateHashEntry( + &stylePtr->defaultsTable,optionName,&newEntry); + + Tcl_IncrRefCount(value); + if (!newEntry) { + Tcl_DecrRefCount((Tcl_Obj*)Tcl_GetHashValue(entryPtr)); + } + Tcl_SetHashValue(entryPtr, value); + } + + ThemeChanged(pkgPtr); + return TCL_OK; +} + +/* + style lookup $style -option ?statespec? ?defaultValue? + */ +static int StyleLookupCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + Ttk_Style style = NULL; + const char *optionName; + Ttk_State state = 0ul; + Tcl_Obj *result; + + if (objc < 4 || objc > 6) { + Tcl_WrongNumArgs(interp, 2, objv, "style -option ?state? ?default?"); + return TCL_ERROR; + } + + style = Ttk_GetStyle(theme, Tcl_GetString(objv[2])); + if (!style) { + return TCL_ERROR; + } + optionName = Tcl_GetString(objv[3]); + + if (objc >= 5) { + Ttk_StateSpec stateSpec; + /* @@@ SB: Ttk_GetStateFromObj(); 'offbits' spec is ignored */ + if (Ttk_GetStateSpecFromObj(interp, objv[4], &stateSpec) != TCL_OK) { + return TCL_ERROR; + } + state = stateSpec.onbits; + } + + result = Ttk_QueryStyle(style, NULL,NULL, optionName, state); + if (result == NULL && objc >= 6) { /* Use caller-supplied fallback */ + result = objv[5]; + } + + if (result) { + Tcl_SetObjResult(interp, result); + } + + return TCL_OK; +} + +static int StyleThemeCurrentCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr = NULL; + const char *name = NULL; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, ""); + return TCL_ERROR; + } + + entryPtr = Tcl_FirstHashEntry(&pkgPtr->themeTable, &search); + while (entryPtr != NULL) { + Theme *ptr = Tcl_GetHashValue(entryPtr); + if (ptr == pkgPtr->currentTheme) { + name = Tcl_GetHashKey(&pkgPtr->themeTable, entryPtr); + break; + } + entryPtr = Tcl_NextHashEntry(&search); + } + + if (name == NULL) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("error: failed to get theme name", -1)); + return TCL_ERROR; + } + + Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1)); + return TCL_OK; +} + +/* + style theme create name ?-parent $theme? ?-settings { script }? + */ +static int StyleThemeCreateCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + static const char *optStrings[] = + { "-parent", "-settings", NULL }; + enum { OP_PARENT, OP_SETTINGS }; + Ttk_Theme parentTheme = pkgPtr->defaultTheme, newTheme; + Tcl_Obj *settingsScript = NULL; + const char *themeName; + int i; + + if (objc < 4 || objc % 2 != 0) { + Tcl_WrongNumArgs(interp, 3, objv, "name ?-option value ...?"); + return TCL_ERROR; + } + + themeName = Tcl_GetString(objv[3]); + + for (i=4; i < objc; i +=2) { + int option; + if (Tcl_GetIndexFromObj( + interp, objv[i], optStrings, "option", 0, &option) != TCL_OK) + { + return TCL_ERROR; + } + + switch (option) { + case OP_PARENT: + parentTheme = LookupTheme( + interp, pkgPtr, Tcl_GetString(objv[i+1])); + if (!parentTheme) + return TCL_ERROR; + break; + case OP_SETTINGS: + settingsScript = objv[i+1]; + break; + } + } + + newTheme = Ttk_CreateTheme(interp, themeName, parentTheme); + if (!newTheme) { + return TCL_ERROR; + } + + /* + * Evaluate the -settings script, if supplied: + */ + if (settingsScript) { + Ttk_Theme oldTheme = pkgPtr->currentTheme; + int status; + + pkgPtr->currentTheme = newTheme; + status = Tcl_EvalObjEx(interp, settingsScript, 0); + pkgPtr->currentTheme = oldTheme; + return status; + } else { + return TCL_OK; + } +} + +/* + style theme names -- + * Return list of registered themes. + */ +static int StyleThemeNamesCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + return TtkEnumerateHashTable(interp, &pkgPtr->themeTable); +} + +/* + style theme settings $theme $script + * + * Temporarily sets the current theme to $themeName, + * evaluates $script, then restores the old theme. + */ +static int +StyleThemeSettingsCmd( + ClientData clientData, /* Master StylePackageData pointer */ + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *const objv[]) /* Argument objects */ +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme oldTheme = pkgPtr->currentTheme; + Ttk_Theme newTheme; + int status; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "theme script"); + return TCL_ERROR; + } + + newTheme = LookupTheme(interp, pkgPtr, Tcl_GetString(objv[3])); + if (!newTheme) + return TCL_ERROR; + + pkgPtr->currentTheme = newTheme; + status = Tcl_EvalObjEx(interp, objv[4], 0); + pkgPtr->currentTheme = oldTheme; + + return status; +} + +/* + style element create name type ? ...args ? + */ +static int StyleElementCreateCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + const char *elementName, *factoryName; + Tcl_HashEntry *entryPtr; + FactoryRec *recPtr; + + if (objc < 5) { + Tcl_WrongNumArgs(interp, 3, objv, "name type ?-option value ...?"); + return TCL_ERROR; + } + + elementName = Tcl_GetString(objv[3]); + factoryName = Tcl_GetString(objv[4]); + + entryPtr = Tcl_FindHashEntry(&pkgPtr->factoryTable, factoryName); + if (!entryPtr) { + Tcl_AppendResult(interp, "No such element type ", factoryName, NULL); + return TCL_ERROR; + } + + recPtr = Tcl_GetHashValue(entryPtr); + + return recPtr->factory(interp, recPtr->clientData, + theme, elementName, objc - 5, objv + 5); +} + +/* + style element names -- + * Return a list of elements defined in the current theme. + */ +static int StyleElementNamesCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, NULL); + return TCL_ERROR; + } + return TtkEnumerateHashTable(interp, &theme->elementTable); +} + +/* + style element options $element -- + * Return list of element options for specified element + */ +static int StyleElementOptionsCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + const char *elementName; + Ttk_ElementClass *elementClass; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 3, objv, "element"); + return TCL_ERROR; + } + + elementName = Tcl_GetString(objv[3]); + elementClass = Ttk_GetElement(theme, elementName); + if (elementClass) { + Ttk_ElementSpec *specPtr = elementClass->specPtr; + Ttk_ElementOptionSpec *option = specPtr->options; + Tcl_Obj *result = Tcl_NewListObj(0,0); + + while (option->optionName) { + Tcl_ListObjAppendElement( + interp, result, Tcl_NewStringObj(option->optionName,-1)); + ++option; + } + + Tcl_SetObjResult(interp, result); + return TCL_OK; + } + + Tcl_AppendResult(interp, "element ", elementName, " not found", NULL); + return TCL_ERROR; +} + +/* + style layout name ?spec? + */ +static int StyleLayoutCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme = pkgPtr->currentTheme; + const char *layoutName; + Ttk_LayoutTemplate layoutTemplate; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "name ?spec?"); + return TCL_ERROR; + } + + layoutName = Tcl_GetString(objv[2]); + + if (objc == 3) { + layoutTemplate = Ttk_FindLayoutTemplate(theme, layoutName); + if (!layoutTemplate) { + Tcl_AppendResult(interp, "Layout ", layoutName, " not found", NULL); + return TCL_ERROR; + } + Tcl_SetObjResult(interp, Ttk_UnparseLayoutTemplate(layoutTemplate)); + } else { + layoutTemplate = Ttk_ParseLayoutTemplate(interp, objv[3]); + if (!layoutTemplate) { + return TCL_ERROR; + } + Ttk_RegisterLayoutTemplate(theme, layoutName, layoutTemplate); + ThemeChanged(pkgPtr); + } + return TCL_OK; +} + +/* + style theme use $theme -- + * Sets the current theme to $theme + */ +static int +StyleThemeUseCmd( + ClientData clientData, /* Master StylePackageData pointer */ + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *const objv[]) /* Argument objects */ +{ + StylePackageData *pkgPtr = clientData; + Ttk_Theme theme; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 3, objv, "?theme?"); + return TCL_ERROR; + } + + if (objc == 3) { + return StyleThemeCurrentCmd(clientData, interp, objc, objv); + } + + theme = LookupTheme(interp, pkgPtr, Tcl_GetString(objv[3])); + if (!theme) { + return TCL_ERROR; + } + + return Ttk_UseTheme(interp, theme); +} + +/* + * StyleObjCmd -- + * Implementation of the [style] command. + */ + +static const Ttk_Ensemble StyleThemeEnsemble[] = { + { "create", StyleThemeCreateCmd, 0 }, + { "names", StyleThemeNamesCmd, 0 }, + { "settings", StyleThemeSettingsCmd, 0 }, + { "use", StyleThemeUseCmd, 0 }, + { NULL, 0, 0 } +}; + +static const Ttk_Ensemble StyleElementEnsemble[] = { + { "create", StyleElementCreateCmd, 0 }, + { "names", StyleElementNamesCmd, 0 }, + { "options", StyleElementOptionsCmd, 0 }, + { NULL, 0, 0 } +}; + +static const Ttk_Ensemble StyleEnsemble[] = { + { "configure", StyleConfigureCmd, 0 }, + { "map", StyleMapCmd, 0 }, + { "lookup", StyleLookupCmd, 0 }, + { "layout", StyleLayoutCmd, 0 }, + { "theme", 0, StyleThemeEnsemble }, + { "element", 0, StyleElementEnsemble }, + { NULL, 0, 0 } +}; + +static int +StyleObjCmd( + ClientData clientData, /* Master StylePackageData pointer */ + Tcl_Interp *interp, /* Current interpreter */ + int objc, /* Number of arguments */ + Tcl_Obj *const objv[]) /* Argument objects */ +{ + return Ttk_InvokeEnsemble(StyleEnsemble, 1, clientData,interp,objc,objv); +} + +MODULE_SCOPE +int Ttk_InvokeEnsemble( /* Run an ensemble command */ + const Ttk_Ensemble *ensemble, int cmdIndex, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + while (cmdIndex < objc) { + int index; + if (Tcl_GetIndexFromObjStruct(interp, + objv[cmdIndex], ensemble, sizeof(ensemble[0]), + "command", 0, &index) + != TCL_OK) + { + return TCL_ERROR; + } + + if (ensemble[index].command) { + return ensemble[index].command(clientData, interp, objc, objv); + } + ensemble = ensemble[index].ensemble; + ++cmdIndex; + } + Tcl_WrongNumArgs(interp, cmdIndex, objv, "option ?arg ...?"); + return TCL_ERROR; +} + +/* + * Ttk_StylePkgInit -- + * Initializes all the structures that are used by the style + * package on a per-interp basis. + */ + +void Ttk_StylePkgInit(Tcl_Interp *interp) +{ + Tcl_Namespace *nsPtr; + + StylePackageData *pkgPtr = (StylePackageData *) + ckalloc(sizeof(StylePackageData)); + + pkgPtr->interp = interp; + Tcl_InitHashTable(&pkgPtr->themeTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&pkgPtr->factoryTable, TCL_STRING_KEYS); + pkgPtr->cleanupList = NULL; + pkgPtr->cache = Ttk_CreateResourceCache(interp); + pkgPtr->themeChangePending = 0; + + Tcl_SetAssocData(interp, PKG_ASSOC_KEY, Ttk_StylePkgFree, pkgPtr); + + /* + * Create the default system theme: + * + * pkgPtr->defaultTheme must be initialized to 0 before + * calling Ttk_CreateTheme for the first time, since it's used + * as the parent theme. + */ + pkgPtr->defaultTheme = 0; + pkgPtr->defaultTheme = pkgPtr->currentTheme = + Ttk_CreateTheme(interp, "default", NULL); + + /* + * Register null element, used as a last-resort fallback: + */ + Ttk_RegisterElement(interp, pkgPtr->defaultTheme, "", &ttkNullElementSpec, 0); + + /* + * Register commands: + */ + Tcl_CreateObjCommand(interp, "::ttk::style", StyleObjCmd, pkgPtr, 0); + + nsPtr = Tcl_FindNamespace(interp, "::ttk", NULL, TCL_LEAVE_ERR_MSG); + Tcl_Export(interp, nsPtr, "style", 0 /* dontResetList */); + + Ttk_RegisterElementFactory(interp, "from", Ttk_CloneElement, 0); +} + +/*EOF*/ diff --git a/generic/ttk/ttkTheme.h b/generic/ttk/ttkTheme.h new file mode 100644 index 0000000..7bf2a7f --- /dev/null +++ b/generic/ttk/ttkTheme.h @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2003 Joe English. Freely redistributable. + * + * Declarations for Tk theme engine. + */ + +#ifndef _TTKTHEME +#define _TTKTHEME + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MODULE_SCOPE +# ifdef __cplusplus +# define MODULE_SCOPE extern "C" +# else +# define MODULE_SCOPE extern +# endif +#endif + +#define TTKAPI MODULE_SCOPE + +/* Ttk syncs to the Tk version & patchlevel */ +#define TTK_VERSION TK_VERSION +#define TTK_PATCH_LEVEL TK_PATCH_LEVEL + +/*------------------------------------------------------------------------ + * +++ Defaults for element option specifications. + */ +#define DEFAULT_FONT "TkDefaultFont" +#define DEFAULT_BACKGROUND "#d9d9d9" +#define DEFAULT_FOREGROUND "black" + +/*------------------------------------------------------------------------ + * +++ Widget states. + * Keep in sync with stateNames[] in tkstate.c. + */ + +typedef unsigned int Ttk_State; + +#define TTK_STATE_ACTIVE (1<<0) +#define TTK_STATE_DISABLED (1<<1) +#define TTK_STATE_FOCUS (1<<2) +#define TTK_STATE_PRESSED (1<<3) +#define TTK_STATE_SELECTED (1<<4) +#define TTK_STATE_BACKGROUND (1<<5) +#define TTK_STATE_ALTERNATE (1<<6) +#define TTK_STATE_INVALID (1<<7) +#define TTK_STATE_READONLY (1<<8) +#define TTK_STATE_HOVER (1<<9) +#define TTK_STATE_USER6 (1<<10) +#define TTK_STATE_USER5 (1<<11) +#define TTK_STATE_USER4 (1<<12) +#define TTK_STATE_USER3 (1<<13) +#define TTK_STATE_USER2 (1<<14) +#define TTK_STATE_USER1 (1<<15) + +/* Maintenance note: if you get all the way to "USER1", + * see tkstate.c + */ +typedef struct +{ + unsigned int onbits; /* bits to turn on */ + unsigned int offbits; /* bits to turn off */ +} Ttk_StateSpec; + +#define Ttk_StateMatches(state, spec) \ + (((state) & ((spec)->onbits|(spec)->offbits)) == (spec)->onbits) + +#define Ttk_ModifyState(state, spec) \ + (((state) & ~(spec)->offbits) | (spec)->onbits) + +TTKAPI int Ttk_GetStateSpecFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_StateSpec *); +TTKAPI Tcl_Obj *Ttk_NewStateSpecObj(unsigned int onbits,unsigned int offbits); + +/*------------------------------------------------------------------------ + * +++ State maps and state tables. + */ +typedef Tcl_Obj *Ttk_StateMap; + +TTKAPI Ttk_StateMap Ttk_GetStateMapFromObj(Tcl_Interp *, Tcl_Obj *); +TTKAPI Tcl_Obj *Ttk_StateMapLookup(Tcl_Interp*, Ttk_StateMap, Ttk_State); + +/* + * Table for looking up an integer index based on widget state: + */ +typedef struct +{ + int index; /* Value to return if this entry matches */ + unsigned int onBits; /* Bits which must be set */ + unsigned int offBits; /* Bits which must be cleared */ +} Ttk_StateTable; + +TTKAPI int Ttk_StateTableLookup(Ttk_StateTable map[], Ttk_State); + +/*------------------------------------------------------------------------ + * +++ Padding. + * Used to represent internal padding and borders. + */ +typedef struct +{ + short left; + short top; + short right; + short bottom; +} Ttk_Padding; + +TTKAPI int Ttk_GetPaddingFromObj(Tcl_Interp*,Tk_Window,Tcl_Obj*,Ttk_Padding*); +TTKAPI int Ttk_GetBorderFromObj(Tcl_Interp*,Tcl_Obj*,Ttk_Padding*); + +TTKAPI Ttk_Padding Ttk_MakePadding(short l, short t, short r, short b); +TTKAPI Ttk_Padding Ttk_UniformPadding(short borderWidth); +TTKAPI Ttk_Padding Ttk_AddPadding(Ttk_Padding, Ttk_Padding); +TTKAPI Ttk_Padding Ttk_RelievePadding(Ttk_Padding, int relief, int n); + +#define Ttk_PaddingWidth(p) ((p).left + (p).right) +#define Ttk_PaddingHeight(p) ((p).top + (p).bottom) + +#define Ttk_SetMargins(tkwin, pad) \ + Tk_SetInternalBorderEx(tkwin, pad.left, pad.right, pad.top, pad.bottom) + +/*------------------------------------------------------------------------ + * +++ Boxes. + * Used to represent rectangular regions + */ +typedef struct /* Hey, this is an XRectangle! */ +{ + int x; + int y; + int width; + int height; +} Ttk_Box; + +TTKAPI Ttk_Box Ttk_MakeBox(int x, int y, int width, int height); +TTKAPI int Ttk_BoxContains(Ttk_Box, int x, int y); + +#define Ttk_WinBox(tkwin) Ttk_MakeBox(0,0,Tk_Width(tkwin),Tk_Height(tkwin)) + +/*------------------------------------------------------------------------ + * +++ Layout utilities. + */ +typedef enum { + TTK_SIDE_LEFT, TTK_SIDE_TOP, TTK_SIDE_RIGHT, TTK_SIDE_BOTTOM +} Ttk_Side; + +typedef unsigned int Ttk_Sticky; + +/* + * -sticky bits for Ttk_StickBox: + */ +#define TTK_STICK_W (0x1) +#define TTK_STICK_E (0x2) +#define TTK_STICK_N (0x4) +#define TTK_STICK_S (0x8) + +/* + * Aliases and useful combinations: + */ +#define TTK_FILL_X (0x3) /* -sticky ew */ +#define TTK_FILL_Y (0xC) /* -sticky ns */ +#define TTK_FILL_BOTH (0xF) /* -sticky nswe */ + +TTKAPI int Ttk_GetStickyFromObj(Tcl_Interp *, Tcl_Obj *, Ttk_Sticky *); +TTKAPI Tcl_Obj *Ttk_NewStickyObj(Ttk_Sticky); + +/* + * Extra bits for position specifications (combine -side and -sticky) + */ + +typedef unsigned int Ttk_PositionSpec; /* See below */ + +#define TTK_PACK_LEFT (0x10) /* pack at left of current parcel */ +#define TTK_PACK_RIGHT (0x20) /* pack at right of current parcel */ +#define TTK_PACK_TOP (0x40) /* pack at top of current parcel */ +#define TTK_PACK_BOTTOM (0x80) /* pack at bottom of current parcel */ +#define TTK_EXPAND (0x100) /* use entire parcel */ +#define TTK_BORDER (0x200) /* draw this element after children */ +#define TTK_UNIT (0x400) /* treat descendants as a part of element */ + +/* + * Extra bits for layout specifications + */ +#define _TTK_CHILDREN (0x1000)/* for LayoutSpecs -- children follow */ +#define _TTK_LAYOUT_END (0x2000)/* for LayoutSpecs -- end of child list */ +#define _TTK_LAYOUT (0x4000)/* for LayoutSpec tables -- define layout */ + +#define _TTK_MASK_STICK (0x0F) /* See Ttk_UnparseLayout() */ +#define _TTK_MASK_PACK (0xF0) /* See Ttk_UnparseLayout(), packStrings */ + +TTKAPI Ttk_Box Ttk_PackBox(Ttk_Box *cavity, int w, int h, Ttk_Side side); +TTKAPI Ttk_Box Ttk_StickBox(Ttk_Box parcel, int w, int h, Ttk_Sticky sticky); +TTKAPI Ttk_Box Ttk_AnchorBox(Ttk_Box parcel, int w, int h, Tk_Anchor anchor); +TTKAPI Ttk_Box Ttk_PadBox(Ttk_Box b, Ttk_Padding p); +TTKAPI Ttk_Box Ttk_ExpandBox(Ttk_Box b, Ttk_Padding p); +TTKAPI Ttk_Box Ttk_PlaceBox(Ttk_Box *cavity, int w,int h, Ttk_Side,Ttk_Sticky); +TTKAPI Ttk_Box Ttk_PositionBox(Ttk_Box *cavity, int w, int h, Ttk_PositionSpec); + +/*------------------------------------------------------------------------ + * +++ Themes. + */ +MODULE_SCOPE void Ttk_StylePkgInit(Tcl_Interp *); + +typedef struct Ttk_Theme_ *Ttk_Theme; +typedef struct Ttk_ElementClass_ Ttk_ElementClass; +typedef struct Ttk_Layout_ *Ttk_Layout; +typedef struct Ttk_LayoutNode_ *Ttk_Element; +typedef struct Ttk_Style_ *Ttk_Style; + +TTKAPI Ttk_Theme Ttk_GetTheme(Tcl_Interp *interp, const char *name); +TTKAPI Ttk_Theme Ttk_GetDefaultTheme(Tcl_Interp *interp); +TTKAPI Ttk_Theme Ttk_GetCurrentTheme(Tcl_Interp *interp); + +TTKAPI Ttk_Theme Ttk_CreateTheme( + Tcl_Interp *interp, const char *name, Ttk_Theme parent); + +typedef int (Ttk_ThemeEnabledProc)(Ttk_Theme theme, void *clientData); +MODULE_SCOPE void Ttk_SetThemeEnabledProc(Ttk_Theme, Ttk_ThemeEnabledProc, void *); + +MODULE_SCOPE int Ttk_UseTheme(Tcl_Interp *, Ttk_Theme); + +typedef void (Ttk_CleanupProc)(void *clientData); +TTKAPI void Ttk_RegisterCleanup( + Tcl_Interp *interp, void *deleteData, Ttk_CleanupProc *cleanupProc); + +/*------------------------------------------------------------------------ + * +++ Elements. + */ + +enum TTKStyleVersion2 { TK_STYLE_VERSION_2 = 2 }; + +typedef void (Ttk_ElementSizeProc)(void *clientData, void *elementRecord, + Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding*); +typedef void (Ttk_ElementDrawProc)(void *clientData, void *elementRecord, + Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state); + +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 */ + const char *defaultValue; /* Default value to used if resource missing */ +} Ttk_ElementOptionSpec; + +#define TK_OPTION_ANY TK_OPTION_STRING + +typedef struct Ttk_ElementSpec { + enum TTKStyleVersion2 version; /* Version of the style support. */ + size_t elementSize; /* Size of element record */ + Ttk_ElementOptionSpec *options; /* List of options, NULL-terminated */ + Ttk_ElementSizeProc *size; /* Compute min size and padding */ + Ttk_ElementDrawProc *draw; /* Draw the element */ +} Ttk_ElementSpec; + +TTKAPI Ttk_ElementClass *Ttk_RegisterElement( + Tcl_Interp *interp, Ttk_Theme theme, const char *elementName, + Ttk_ElementSpec *, void *clientData); + +typedef int (*Ttk_ElementFactory) + (Tcl_Interp *, void *clientData, + Ttk_Theme, const char *elementName, int objc, Tcl_Obj *const objv[]); + +TTKAPI int Ttk_RegisterElementFactory( + Tcl_Interp *, const char *name, Ttk_ElementFactory, void *clientData); + +/* + * Null element implementation: + * has no geometry or layout; may be used as a stub or placeholder. + */ + +typedef struct { + Tcl_Obj *unused; +} NullElement; + +MODULE_SCOPE void TtkNullElementSize + (void *, void *, Tk_Window, int *, int *, Ttk_Padding *); +MODULE_SCOPE void TtkNullElementDraw + (void *, void *, Tk_Window, Drawable, Ttk_Box, Ttk_State); +MODULE_SCOPE Ttk_ElementOptionSpec TtkNullElementOptions[]; +MODULE_SCOPE Ttk_ElementSpec ttkNullElementSpec; + +/*------------------------------------------------------------------------ + * +++ Layout templates. + */ +typedef struct { + const char * elementName; + unsigned opcode; +} TTKLayoutInstruction, *Ttk_LayoutSpec; + +#define TTK_BEGIN_LAYOUT_TABLE(name) \ + static TTKLayoutInstruction name[] = { +#define TTK_LAYOUT(name, content) \ + { name, _TTK_CHILDREN|_TTK_LAYOUT }, \ + content \ + { 0, _TTK_LAYOUT_END }, +#define TTK_GROUP(name, flags, children) \ + { name, flags | _TTK_CHILDREN }, \ + children \ + { 0, _TTK_LAYOUT_END }, +#define TTK_NODE(name, flags) { name, flags }, +#define TTK_END_LAYOUT_TABLE { 0, _TTK_LAYOUT | _TTK_LAYOUT_END } }; + +#define TTK_BEGIN_LAYOUT(name) static TTKLayoutInstruction name[] = { +#define TTK_END_LAYOUT { 0, _TTK_LAYOUT_END } }; + +TTKAPI void Ttk_RegisterLayout( + Ttk_Theme theme, const char *className, Ttk_LayoutSpec layoutSpec); + +TTKAPI void Ttk_RegisterLayouts( + Ttk_Theme theme, Ttk_LayoutSpec layoutTable); + +/*------------------------------------------------------------------------ + * +++ Layout instances. + */ + +MODULE_SCOPE Ttk_Layout Ttk_CreateLayout( + Tcl_Interp *, Ttk_Theme, const char *name, + void *recordPtr, Tk_OptionTable, Tk_Window tkwin); + +MODULE_SCOPE Ttk_Layout Ttk_CreateSublayout( + Tcl_Interp *, Ttk_Theme, Ttk_Layout, const char *name, Tk_OptionTable); + +MODULE_SCOPE void Ttk_FreeLayout(Ttk_Layout); + +MODULE_SCOPE void Ttk_LayoutSize(Ttk_Layout,Ttk_State,int *widthPtr,int *heightPtr); +MODULE_SCOPE void Ttk_PlaceLayout(Ttk_Layout, Ttk_State, Ttk_Box); +MODULE_SCOPE void Ttk_DrawLayout(Ttk_Layout, Ttk_State, Drawable); + +MODULE_SCOPE void Ttk_RebindSublayout(Ttk_Layout, void *recordPtr); + +MODULE_SCOPE Ttk_Element Ttk_IdentifyElement(Ttk_Layout, int x, int y); +MODULE_SCOPE Ttk_Element Ttk_FindElement(Ttk_Layout, const char *nodeName); + +MODULE_SCOPE const char *Ttk_ElementName(Ttk_Element); +MODULE_SCOPE Ttk_Box Ttk_ElementParcel(Ttk_Element); + +MODULE_SCOPE Ttk_Box Ttk_ClientRegion(Ttk_Layout, const char *elementName); + +MODULE_SCOPE Ttk_Box Ttk_LayoutNodeInternalParcel(Ttk_Layout,Ttk_Element); +MODULE_SCOPE Ttk_Padding Ttk_LayoutNodeInternalPadding(Ttk_Layout,Ttk_Element); +MODULE_SCOPE void Ttk_LayoutNodeReqSize(Ttk_Layout, Ttk_Element, int *w, int *h); + +MODULE_SCOPE void Ttk_PlaceElement(Ttk_Layout, Ttk_Element, Ttk_Box); +MODULE_SCOPE void Ttk_ChangeElementState(Ttk_Element,unsigned set,unsigned clr); + +MODULE_SCOPE Tcl_Obj *Ttk_QueryOption(Ttk_Layout, const char *, Ttk_State); + +TTKAPI Ttk_Style Ttk_LayoutStyle(Ttk_Layout); +TTKAPI Tcl_Obj *Ttk_StyleDefault(Ttk_Style, const char *optionName); +TTKAPI Tcl_Obj *Ttk_StyleMap(Ttk_Style, const char *optionName, Ttk_State); + +/*------------------------------------------------------------------------ + * +++ Resource cache. + * See resource.c for explanation. + */ + +typedef struct Ttk_ResourceCache_ *Ttk_ResourceCache; +MODULE_SCOPE Ttk_ResourceCache Ttk_CreateResourceCache(Tcl_Interp *); +MODULE_SCOPE void Ttk_FreeResourceCache(Ttk_ResourceCache); + +MODULE_SCOPE Ttk_ResourceCache Ttk_GetResourceCache(Tcl_Interp*); +MODULE_SCOPE Tcl_Obj *Ttk_UseFont(Ttk_ResourceCache, Tk_Window, Tcl_Obj *); +MODULE_SCOPE Tcl_Obj *Ttk_UseColor(Ttk_ResourceCache, Tk_Window, Tcl_Obj *); +MODULE_SCOPE Tcl_Obj *Ttk_UseBorder(Ttk_ResourceCache, Tk_Window, Tcl_Obj *); +MODULE_SCOPE Tk_Image Ttk_UseImage(Ttk_ResourceCache, Tk_Window, Tcl_Obj *); + +MODULE_SCOPE void Ttk_RegisterNamedColor(Ttk_ResourceCache, const char *, XColor *); + +/*------------------------------------------------------------------------ + * +++ Image specifications. + */ + +typedef struct TtkImageSpec Ttk_ImageSpec; +TTKAPI Ttk_ImageSpec *TtkGetImageSpec(Tcl_Interp *, Tk_Window, Tcl_Obj *); +TTKAPI void TtkFreeImageSpec(Ttk_ImageSpec *); +TTKAPI Tk_Image TtkSelectImage(Ttk_ImageSpec *, Ttk_State); + +/*------------------------------------------------------------------------ + * +++ Miscellaneous enumerations. + * Other stuff that element implementations need to know about. + */ +typedef enum /* -default option values */ +{ + TTK_BUTTON_DEFAULT_NORMAL, /* widget defaultable */ + TTK_BUTTON_DEFAULT_ACTIVE, /* currently the default widget */ + TTK_BUTTON_DEFAULT_DISABLED /* not defaultable */ +} Ttk_ButtonDefaultState; + +TTKAPI int Ttk_GetButtonDefaultStateFromObj(Tcl_Interp *, Tcl_Obj *, int *); + +typedef enum /* -compound option values */ +{ + TTK_COMPOUND_NONE, /* image if specified, otherwise text */ + TTK_COMPOUND_TEXT, /* text only */ + TTK_COMPOUND_IMAGE, /* image only */ + TTK_COMPOUND_CENTER, /* text overlays image */ + TTK_COMPOUND_TOP, /* image above text */ + TTK_COMPOUND_BOTTOM, /* image below text */ + TTK_COMPOUND_LEFT, /* image to left of text */ + TTK_COMPOUND_RIGHT /* image to right of text */ +} Ttk_Compound; + +TTKAPI int Ttk_GetCompoundFromObj(Tcl_Interp *, Tcl_Obj *, int *); + +typedef enum { /* -orient option values */ + TTK_ORIENT_HORIZONTAL, + TTK_ORIENT_VERTICAL +} Ttk_Orient; + +/*------------------------------------------------------------------------ + * +++ Utilities. + */ + +typedef struct TtkEnsemble { + const char *name; /* subcommand name */ + Tcl_ObjCmdProc *command; /* subcommand implementation, OR: */ + const struct TtkEnsemble *ensemble; /* subcommand ensemble */ +} Ttk_Ensemble; + +MODULE_SCOPE int Ttk_InvokeEnsemble( /* Run an ensemble command */ + const Ttk_Ensemble *commands, int cmdIndex, + void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); + +MODULE_SCOPE int TtkEnumerateHashTable(Tcl_Interp *, Tcl_HashTable *); + +/*------------------------------------------------------------------------ + * +++ Stub table declarations. + */ + +#include "ttkDecls.h" + +/* + * Drawing utilities for theme code: + * (@@@ find a better home for this) + */ +typedef enum { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT } ArrowDirection; +MODULE_SCOPE void TtkArrowSize(int h, ArrowDirection, int *widthPtr, int *heightPtr); +MODULE_SCOPE void TtkDrawArrow(Display *, Drawable, GC, Ttk_Box, ArrowDirection); +MODULE_SCOPE void TtkFillArrow(Display *, Drawable, GC, Ttk_Box, ArrowDirection); + +#ifdef __cplusplus +} +#endif +#endif /* _TTKTHEME */ diff --git a/generic/ttk/ttkThemeInt.h b/generic/ttk/ttkThemeInt.h new file mode 100644 index 0000000..3aaada8 --- /dev/null +++ b/generic/ttk/ttkThemeInt.h @@ -0,0 +1,42 @@ +/* + * Theme engine: private definitions. + * + * Copyright (c) 2004 Joe English. Freely redistributable. + */ + +#ifndef _TTKTHEMEINT +#define _TTKTHEMEINT + +#include "ttkTheme.h" + +typedef struct Ttk_TemplateNode_ Ttk_TemplateNode, *Ttk_LayoutTemplate; + +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, + 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, + Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state); + +MODULE_SCOPE Tcl_Obj *Ttk_QueryStyle( + Ttk_Style, void *, Tk_OptionTable, const char *, Ttk_State state); + +MODULE_SCOPE Ttk_LayoutTemplate Ttk_ParseLayoutTemplate( + Tcl_Interp *, Tcl_Obj *); +MODULE_SCOPE Tcl_Obj *Ttk_UnparseLayoutTemplate(Ttk_LayoutTemplate); +MODULE_SCOPE Ttk_LayoutTemplate Ttk_BuildLayoutTemplate(Ttk_LayoutSpec); +MODULE_SCOPE void Ttk_FreeLayoutTemplate(Ttk_LayoutTemplate); +MODULE_SCOPE void Ttk_RegisterLayoutTemplate( + Ttk_Theme theme, const char *layoutName, Ttk_LayoutTemplate); + +MODULE_SCOPE Ttk_Style Ttk_GetStyle(Ttk_Theme themePtr, const char *styleName); +MODULE_SCOPE Ttk_LayoutTemplate Ttk_FindLayoutTemplate( + Ttk_Theme themePtr, const char *layoutName); + +MODULE_SCOPE const char *Ttk_StyleName(Ttk_Style); + +#endif /* _TTKTHEMEINT */ diff --git a/generic/ttk/ttkTrace.c b/generic/ttk/ttkTrace.c new file mode 100644 index 0000000..8bc8519 --- /dev/null +++ b/generic/ttk/ttkTrace.c @@ -0,0 +1,190 @@ +/* + * Copyright 2003, Joe English + * + * Simplified interface to Tcl_TraceVariable. + * + * PROBLEM: Can't distinguish "variable does not exist" (which is OK) + * from other errors (which are not). + */ + +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +struct TtkTraceHandle_ +{ + Tcl_Interp *interp; /* Containing interpreter */ + Tcl_Obj *varnameObj; /* Name of variable being traced */ + Ttk_TraceProc callback; /* Callback procedure */ + void *clientData; /* Data to pass to callback */ +}; + +/* + * Tcl_VarTraceProc for trace handles. + */ +static char * +VarTraceProc( + ClientData clientData, /* Widget record pointer */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + const char *name1, /* (unused) */ + const char *name2, /* (unused) */ + int flags) /* Information about what happened. */ +{ + Ttk_TraceHandle *tracePtr = clientData; + const char *name, *value; + Tcl_Obj *valuePtr; + + if (flags & TCL_INTERP_DESTROYED) { + return NULL; + } + + name = Tcl_GetString(tracePtr->varnameObj); + + /* + * If the variable is being unset, then re-establish the trace: + */ + if (flags & TCL_TRACE_DESTROYED) { + /* + * If a prior call to Ttk_UntraceVariable() left behind an + * indicator that we wanted this handler to be deleted (see below), + * cleanup the ClientData bits and exit. + */ + if (tracePtr->interp == NULL) { + Tcl_DecrRefCount(tracePtr->varnameObj); + ckfree((ClientData)tracePtr); + return NULL; + } + Tcl_TraceVar(interp, name, + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + VarTraceProc, clientData); + tracePtr->callback(tracePtr->clientData, NULL); + return NULL; + } + + /* + * Call the callback: + */ + valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY); + value = valuePtr ? Tcl_GetString(valuePtr) : NULL; + tracePtr->callback(tracePtr->clientData, value); + + return NULL; +} + +/* Ttk_TraceVariable(interp, varNameObj, callback, clientdata) -- + * Attach a write trace to the specified variable, + * which will pass the variable's value to 'callback' + * whenever the variable is set. + * + * When the variable is unset, passes NULL to the callback + * and reattaches the trace. + */ +Ttk_TraceHandle *Ttk_TraceVariable( + Tcl_Interp *interp, + Tcl_Obj *varnameObj, + Ttk_TraceProc callback, + void *clientData) +{ + Ttk_TraceHandle *h = (Ttk_TraceHandle*)ckalloc(sizeof(*h)); + int status; + + h->interp = interp; + h->varnameObj = Tcl_DuplicateObj(varnameObj); + Tcl_IncrRefCount(h->varnameObj); + h->clientData = clientData; + h->callback = callback; + + status = Tcl_TraceVar(interp, Tcl_GetString(varnameObj), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + VarTraceProc, (ClientData)h); + + if (status != TCL_OK) { + Tcl_DecrRefCount(h->varnameObj); + ckfree((ClientData)h); + return NULL; + } + + return h; +} + +/* + * Ttk_UntraceVariable -- + * Remove previously-registered trace and free the handle. + */ +void Ttk_UntraceVariable(Ttk_TraceHandle *h) +{ + if (h) { + ClientData cd = NULL; + + /* + * Workaround for Tcl Bug 3062331. The trace design problem is + * that when variable unset traces fire, Tcl documents that the + * traced variable has already been unset. It's already gone. + * So from within an unset trace, if you try to call + * Tcl_UntraceVar() on that variable, it will do nothing, because + * the variable by that name can no longer be found. It's gone. + * This means callers of Tcl_UntraceVar() that might be running + * in response to an unset trace have to handle the possibility + * that their Tcl_UntraceVar() call will do nothing. In this case, + * we have to support the possibility that Tcl_UntraceVar() will + * leave the trace in place, so we need to leave the ClientData + * untouched so when that trace does fire it will not crash. + */ + + /* + * Search the traces on the variable to see if the one we are tasked + * with removing is present. + */ + while ((cd = Tcl_VarTraceInfo(h->interp, Tcl_GetString(h->varnameObj), + TCL_GLOBAL_ONLY, VarTraceProc, cd)) != NULL) { + if (cd == (ClientData) h) { + break; + } + } + /* + * If the trace we wish to delete is not visible, Tcl_UntraceVar + * will do nothing, so don't try to call it. Instead set an + * indicator in the Ttk_TraceHandle that we need to cleanup later. + */ + if (cd == NULL) { + h->interp = NULL; + return; + } + Tcl_UntraceVar(h->interp, Tcl_GetString(h->varnameObj), + TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + VarTraceProc, (ClientData)h); + Tcl_DecrRefCount(h->varnameObj); + ckfree((ClientData)h); + } +} + +/* + * Ttk_FireTrace -- + * Executes a trace handle as if the variable has been written. + * + * Note: may reenter the interpreter. + */ +int Ttk_FireTrace(Ttk_TraceHandle *tracePtr) +{ + Tcl_Interp *interp = tracePtr->interp; + void *clientData = tracePtr->clientData; + const char *name = Tcl_GetString(tracePtr->varnameObj); + Ttk_TraceProc callback = tracePtr->callback; + Tcl_Obj *valuePtr; + const char *value; + + /* Read the variable. + * Note that this can reenter the interpreter, and anything can happen -- + * including the current trace handle being freed! + */ + valuePtr = Tcl_GetVar2Ex(interp, name, NULL, TCL_GLOBAL_ONLY); + value = valuePtr ? Tcl_GetString(valuePtr) : NULL; + + /* Call callback. + */ + callback(clientData, value); + + return TCL_OK; +} + +/*EOF*/ diff --git a/generic/ttk/ttkTrack.c b/generic/ttk/ttkTrack.c new file mode 100644 index 0000000..9cf8267 --- /dev/null +++ b/generic/ttk/ttkTrack.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2004, Joe English + * + * TtkTrackElementState() -- helper routine for widgets + * like scrollbars in which individual elements may + * be active or pressed instead of the widget as a whole. + * + * Usage: + * TtkTrackElementState(&recordPtr->core); + * + * Registers an event handler on the widget that tracks pointer + * events and updates the state of the element under the + * mouse cursor. + * + * The "active" element is the one under the mouse cursor, + * and is normally set to the ACTIVE state unless another element + * is currently being pressed. + * + * The active element becomes "pressed" on <ButtonPress> events, + * and remains "active" and "pressed" until the corresponding + * <ButtonRelease> event. + * + * TODO: Handle "chords" properly (e.g., <B1-ButtonPress-2>) + */ + +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +typedef struct { + WidgetCore *corePtr; /* widget to track */ + Ttk_Layout tracking; /* current layout being tracked */ + Ttk_Element activeElement; /* element under the mouse cursor */ + Ttk_Element pressedElement; /* currently pressed element */ +} ElementStateTracker; + +/* + * ActivateElement(es, node) -- + * Make 'node' the active element if non-NULL. + * Deactivates the currently active element if different. + * + * The active element has TTK_STATE_ACTIVE set _unless_ + * another element is 'pressed' + */ +static void ActivateElement(ElementStateTracker *es, Ttk_Element element) +{ + if (es->activeElement == element) { + /* No change */ + return; + } + + if (!es->pressedElement) { + if (es->activeElement) { + /* Deactivate old element */ + Ttk_ChangeElementState(es->activeElement, 0,TTK_STATE_ACTIVE); + } + if (element) { + /* Activate new element */ + Ttk_ChangeElementState(element, TTK_STATE_ACTIVE,0); + } + TtkRedisplayWidget(es->corePtr); + } + + es->activeElement = element; +} + +/* ReleaseElement -- + * Releases the currently pressed element, if any. + */ +static void ReleaseElement(ElementStateTracker *es) +{ + if (!es->pressedElement) + return; + + Ttk_ChangeElementState( + es->pressedElement, 0,TTK_STATE_PRESSED|TTK_STATE_ACTIVE); + es->pressedElement = 0; + + /* Reactivate element under the mouse cursor: + */ + if (es->activeElement) + Ttk_ChangeElementState(es->activeElement, TTK_STATE_ACTIVE,0); + + TtkRedisplayWidget(es->corePtr); +} + +/* PressElement -- + * Presses the specified element. + */ +static void PressElement(ElementStateTracker *es, Ttk_Element element) +{ + if (es->pressedElement) { + ReleaseElement(es); + } + + if (element) { + Ttk_ChangeElementState( + element, TTK_STATE_PRESSED|TTK_STATE_ACTIVE, 0); + } + + es->pressedElement = element; + TtkRedisplayWidget(es->corePtr); +} + +/* ElementStateEventProc -- + * Event handler for tracking element states. + */ + +static const unsigned ElementStateMask = + ButtonPressMask + | ButtonReleaseMask + | PointerMotionMask + | LeaveWindowMask + | EnterWindowMask + | StructureNotifyMask + ; + +static void +ElementStateEventProc(ClientData clientData, XEvent *ev) +{ + ElementStateTracker *es = clientData; + Ttk_Layout layout = es->corePtr->layout; + Ttk_Element element; + + /* Guard against dangling pointers [#2431428] + */ + if (es->tracking != layout) { + es->pressedElement = es->activeElement = 0; + es->tracking = layout; + } + + switch (ev->type) + { + case MotionNotify : + element = Ttk_IdentifyElement( + layout, ev->xmotion.x, ev->xmotion.y); + ActivateElement(es, element); + break; + case LeaveNotify: + ActivateElement(es, 0); + if (ev->xcrossing.mode == NotifyGrab) + PressElement(es, 0); + break; + case EnterNotify: + element = Ttk_IdentifyElement( + layout, ev->xcrossing.x, ev->xcrossing.y); + ActivateElement(es, element); + break; + case ButtonPress: + element = Ttk_IdentifyElement( + layout, ev->xbutton.x, ev->xbutton.y); + if (element) + PressElement(es, element); + break; + case ButtonRelease: + ReleaseElement(es); + break; + case DestroyNotify: + /* Unregister this event handler and free client data. + */ + Tk_DeleteEventHandler(es->corePtr->tkwin, + ElementStateMask, ElementStateEventProc, es); + ckfree(clientData); + break; + } +} + +/* + * TtkTrackElementState -- + * Register an event handler to manage the 'pressed' + * and 'active' states of individual widget elements. + */ + +void TtkTrackElementState(WidgetCore *corePtr) +{ + ElementStateTracker *es = (ElementStateTracker*)ckalloc(sizeof(*es)); + es->corePtr = corePtr; + es->tracking = 0; + es->activeElement = es->pressedElement = 0; + Tk_CreateEventHandler(corePtr->tkwin, + ElementStateMask,ElementStateEventProc,es); +} + diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c new file mode 100644 index 0000000..222b280 --- /dev/null +++ b/generic/ttk/ttkTreeview.c @@ -0,0 +1,3442 @@ +/* + * Copyright (c) 2004, Joe English + * + * ttk::treeview widget implementation. + */ + +#include <string.h> +#include <stdio.h> +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +#define DEF_TREE_ROWS "10" +#define DEF_COLWIDTH "200" +#define DEF_MINWIDTH "20" + +static const int DEFAULT_ROWHEIGHT = 20; +static const int DEFAULT_INDENT = 20; +static const int HALO = 4; /* separator */ + +#define TTK_STATE_OPEN TTK_STATE_USER1 +#define TTK_STATE_LEAF TTK_STATE_USER2 + +#define STATE_CHANGED (0x100) /* item state option changed */ + +/*------------------------------------------------------------------------ + * +++ Tree items. + * + * INVARIANTS: + * item->children ==> item->children->parent == item + * item->next ==> item->next->parent == item->parent + * item->next ==> item->next->prev == item + * item->prev ==> item->prev->next == item + */ + +typedef struct TreeItemRec TreeItem; +struct TreeItemRec { + Tcl_HashEntry *entryPtr; /* Back-pointer to hash table entry */ + TreeItem *parent; /* Parent item */ + TreeItem *children; /* Linked list of child items */ + TreeItem *next; /* Next sibling */ + TreeItem *prev; /* Previous sibling */ + + /* + * Options and instance data: + */ + Ttk_State state; + Tcl_Obj *textObj; + Tcl_Obj *imageObj; + Tcl_Obj *valuesObj; + Tcl_Obj *openObj; + Tcl_Obj *tagsObj; + + /* + * Derived resources: + */ + Ttk_TagSet tagset; + Ttk_ImageSpec *imagespec; +}; + +#define ITEM_OPTION_TAGS_CHANGED 0x100 +#define ITEM_OPTION_IMAGE_CHANGED 0x200 + +static Tk_OptionSpec ItemOptionSpecs[] = { + {TK_OPTION_STRING, "-text", "text", "Text", + "", Tk_Offset(TreeItem,textObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-image", "image", "Image", + NULL, Tk_Offset(TreeItem,imageObj), -1, + TK_OPTION_NULL_OK,0,ITEM_OPTION_IMAGE_CHANGED }, + {TK_OPTION_STRING, "-values", "values", "Values", + NULL, Tk_Offset(TreeItem,valuesObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_BOOLEAN, "-open", "open", "Open", + "0", Tk_Offset(TreeItem,openObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-tags", "tags", "Tags", + NULL, Tk_Offset(TreeItem,tagsObj), -1, + TK_OPTION_NULL_OK,0,ITEM_OPTION_TAGS_CHANGED }, + + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} +}; + +/* + NewItem -- + * Allocate a new, uninitialized, unlinked item + */ +static TreeItem *NewItem(void) +{ + TreeItem *item = (TreeItem*)ckalloc(sizeof(*item)); + + item->entryPtr = 0; + item->parent = item->children = item->next = item->prev = NULL; + + item->state = 0ul; + item->textObj = NULL; + item->imageObj = NULL; + item->valuesObj = NULL; + item->openObj = NULL; + item->tagsObj = NULL; + + item->tagset = NULL; + item->imagespec = NULL; + + return item; +} + +/* + FreeItem -- + * Destroy an item + */ +static void FreeItem(TreeItem *item) +{ + if (item->textObj) { Tcl_DecrRefCount(item->textObj); } + if (item->imageObj) { Tcl_DecrRefCount(item->imageObj); } + if (item->valuesObj) { Tcl_DecrRefCount(item->valuesObj); } + if (item->openObj) { Tcl_DecrRefCount(item->openObj); } + if (item->tagsObj) { Tcl_DecrRefCount(item->tagsObj); } + + if (item->tagset) { Ttk_FreeTagSet(item->tagset); } + if (item->imagespec) { TtkFreeImageSpec(item->imagespec); } + + ckfree((ClientData)item); +} + +static void FreeItemCB(void *clientData) { FreeItem(clientData); } + +/* + DetachItem -- + * Unlink an item from the tree. + */ +static void DetachItem(TreeItem *item) +{ + if (item->parent && item->parent->children == item) + item->parent->children = item->next; + if (item->prev) + item->prev->next = item->next; + if (item->next) + item->next->prev = item->prev; + item->next = item->prev = item->parent = NULL; +} + +/* + InsertItem -- + * Insert an item into the tree after the specified item. + * + * Preconditions: + * + item is currently detached + * + prev != NULL ==> prev->parent == parent. + */ +static void InsertItem(TreeItem *parent, TreeItem *prev, TreeItem *item) +{ + item->parent = parent; + item->prev = prev; + if (prev) { + item->next = prev->next; + prev->next = item; + } else { + item->next = parent->children; + parent->children = item; + } + if (item->next) { + item->next->prev = item; + } +} + +/* + NextPreorder -- + * Return the next item in preorder traversal order. + */ + +static TreeItem *NextPreorder(TreeItem *item) +{ + if (item->children) + return item->children; + while (!item->next) { + item = item->parent; + if (!item) + return 0; + } + return item->next; +} + +/*------------------------------------------------------------------------ + * +++ Display items and tag options. + */ + +typedef struct { + Tcl_Obj *textObj; /* taken from item / data cell */ + Tcl_Obj *imageObj; /* taken from item */ + Tcl_Obj *anchorObj; /* from column <<NOTE-ANCHOR>> */ + Tcl_Obj *backgroundObj; /* remainder from tag */ + Tcl_Obj *foregroundObj; + Tcl_Obj *fontObj; +} DisplayItem; + +static Tk_OptionSpec TagOptionSpecs[] = { + {TK_OPTION_STRING, "-text", "text", "Text", + NULL, Tk_Offset(DisplayItem,textObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_STRING, "-image", "image", "Image", + NULL, Tk_Offset(DisplayItem,imageObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", + NULL, Tk_Offset(DisplayItem,anchorObj), -1, + TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED}, /* <<NOTE-ANCHOR>> */ + {TK_OPTION_COLOR, "-background", "windowColor", "WindowColor", + NULL, Tk_Offset(DisplayItem,backgroundObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_COLOR, "-foreground", "textColor", "TextColor", + NULL, Tk_Offset(DisplayItem,foregroundObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_FONT, "-font", "font", "Font", + NULL, Tk_Offset(DisplayItem,fontObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} +}; + +/*------------------------------------------------------------------------ + * +++ Columns. + * + * There are separate option tables associated with the column record: + * ColumnOptionSpecs is for configuring the column, + * and HeadingOptionSpecs is for drawing headings. + */ +typedef struct { + int width; /* Column width, in pixels */ + int minWidth; /* Minimum column width, in pixels */ + int stretch; /* Should column stretch while resizing? */ + Tcl_Obj *idObj; /* Column identifier, from -columns option */ + + Tcl_Obj *anchorObj; /* -anchor for cell data <<NOTE-ANCHOR>> */ + + /* Column heading data: + */ + Tcl_Obj *headingObj; /* Heading label */ + Tcl_Obj *headingImageObj; /* Heading image */ + Tcl_Obj *headingAnchorObj; /* -anchor for heading label */ + Tcl_Obj *headingCommandObj; /* Command to execute */ + Tcl_Obj *headingStateObj; /* @@@ testing ... */ + Ttk_State headingState; /* ... */ + + /* Temporary storage for cell data + */ + Tcl_Obj *data; +} TreeColumn; + +static void InitColumn(TreeColumn *column) +{ + column->width = 200; + column->minWidth = 20; + column->stretch = 1; + column->idObj = 0; + column->anchorObj = 0; + + column->headingState = 0; + column->headingObj = 0; + column->headingImageObj = 0; + column->headingAnchorObj = 0; + column->headingStateObj = 0; + column->headingCommandObj = 0; + + column->data = 0; +} + +static void FreeColumn(TreeColumn *column) +{ + if (column->idObj) { Tcl_DecrRefCount(column->idObj); } + if (column->anchorObj) { Tcl_DecrRefCount(column->anchorObj); } + + if (column->headingObj) { Tcl_DecrRefCount(column->headingObj); } + if (column->headingImageObj) { Tcl_DecrRefCount(column->headingImageObj); } + if (column->headingAnchorObj) { Tcl_DecrRefCount(column->headingAnchorObj); } + if (column->headingStateObj) { Tcl_DecrRefCount(column->headingStateObj); } + if (column->headingCommandObj) { Tcl_DecrRefCount(column->headingCommandObj); } + + /* Don't touch column->data, it's scratch storage */ +} + +static Tk_OptionSpec ColumnOptionSpecs[] = { + {TK_OPTION_INT, "-width", "width", "Width", + DEF_COLWIDTH, -1, Tk_Offset(TreeColumn,width), + 0,0,GEOMETRY_CHANGED }, + {TK_OPTION_INT, "-minwidth", "minWidth", "MinWidth", + DEF_MINWIDTH, -1, Tk_Offset(TreeColumn,minWidth), + 0,0,0 }, + {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch", + "1", -1, Tk_Offset(TreeColumn,stretch), + 0,0,0 }, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", + "w", Tk_Offset(TreeColumn,anchorObj), -1, /* <<NOTE-ANCHOR>> */ + 0,0,0 }, + {TK_OPTION_STRING, "-id", "id", "ID", + NULL, Tk_Offset(TreeColumn,idObj), -1, + TK_OPTION_NULL_OK,0,READONLY_OPTION }, + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} +}; + +static Tk_OptionSpec HeadingOptionSpecs[] = { + {TK_OPTION_STRING, "-text", "text", "Text", + "", Tk_Offset(TreeColumn,headingObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-image", "image", "Image", + "", Tk_Offset(TreeColumn,headingImageObj), -1, + 0,0,0 }, + {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", + "center", Tk_Offset(TreeColumn,headingAnchorObj), -1, + 0,0,0 }, + {TK_OPTION_STRING, "-command", "", "", + "", Tk_Offset(TreeColumn,headingCommandObj), -1, + TK_OPTION_NULL_OK,0,0 }, + {TK_OPTION_STRING, "state", "", "", + "", Tk_Offset(TreeColumn,headingStateObj), -1, + 0,0,STATE_CHANGED }, + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0,0,0} +}; + +/*------------------------------------------------------------------------ + * +++ -show option: + * TODO: Implement SHOW_BRANCHES. + */ + +#define SHOW_TREE (0x1) /* Show tree column? */ +#define SHOW_HEADINGS (0x2) /* Show heading row? */ + +#define DEFAULT_SHOW "tree headings" + +static const char *showStrings[] = { + "tree", "headings", NULL +}; + +static int GetEnumSetFromObj( + Tcl_Interp *interp, + Tcl_Obj *objPtr, + const char *table[], + unsigned *resultPtr) +{ + unsigned result = 0; + int i, objc; + Tcl_Obj **objv; + + if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) + return TCL_ERROR; + + for (i = 0; i < objc; ++i) { + int index; + if (TCL_OK != Tcl_GetIndexFromObj( + interp, objv[i], table, "value", TCL_EXACT, &index)) + { + return TCL_ERROR; + } + result |= (1 << index); + } + + *resultPtr = result; + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Treeview widget record. + * + * Dependencies: + * columns, columnNames: -columns + * displayColumns: -columns, -displaycolumns + * headingHeight: [layout] + * rowHeight, indent: style + */ +typedef struct { + /* Resources acquired at initialization-time: + */ + Tk_OptionTable itemOptionTable; + Tk_OptionTable columnOptionTable; + Tk_OptionTable headingOptionTable; + Tk_OptionTable tagOptionTable; + Tk_BindingTable bindingTable; + Ttk_TagTable tagTable; + + /* Acquired in GetLayout hook: + */ + Ttk_Layout itemLayout; + Ttk_Layout cellLayout; + Ttk_Layout headingLayout; + Ttk_Layout rowLayout; + + int headingHeight; /* Space for headings */ + int rowHeight; /* Height of each item */ + int indent; /* #pixels horizontal offset for child items */ + + /* Tree data: + */ + Tcl_HashTable items; /* Map: item name -> item */ + int serial; /* Next item # for autogenerated names */ + TreeItem *root; /* Root item */ + + TreeColumn column0; /* Column options for display column #0 */ + TreeColumn *columns; /* Array of column options for data columns */ + + TreeItem *focus; /* Current focus item */ + TreeItem *endPtr; /* See EndPosition() */ + + /* Widget options: + */ + Tcl_Obj *columnsObj; /* List of symbolic column names */ + Tcl_Obj *displayColumnsObj; /* List of columns to display */ + + Tcl_Obj *heightObj; /* height (rows) */ + Tcl_Obj *paddingObj; /* internal padding */ + + Tcl_Obj *showObj; /* -show list */ + Tcl_Obj *selectModeObj; /* -selectmode option */ + + Scrollable xscroll; + ScrollHandle xscrollHandle; + Scrollable yscroll; + ScrollHandle yscrollHandle; + + /* Derived resources: + */ + Tcl_HashTable columnNames; /* Map: column name -> column table entry */ + int nColumns; /* #columns */ + unsigned showFlags; /* bitmask of subparts to display */ + + TreeColumn **displayColumns; /* List of columns for display (incl tree) */ + int nDisplayColumns; /* #display columns */ + Ttk_Box headingArea; /* Display area for column headings */ + Ttk_Box treeArea; /* Display area for tree */ + int slack; /* Slack space (see Resizing section) */ + +} TreePart; + +typedef struct { + WidgetCore core; + TreePart tree; +} Treeview; + +#define USER_MASK 0x0100 +#define COLUMNS_CHANGED (USER_MASK) +#define DCOLUMNS_CHANGED (USER_MASK<<1) +#define SCROLLCMD_CHANGED (USER_MASK<<2) +#define SHOW_CHANGED (USER_MASK<<3) + +static const char *SelectModeStrings[] = { "none", "browse", "extended", NULL }; + +static Tk_OptionSpec TreeviewOptionSpecs[] = { + {TK_OPTION_STRING, "-columns", "columns", "Columns", + "", Tk_Offset(Treeview,tree.columnsObj), -1, + 0,0,COLUMNS_CHANGED | GEOMETRY_CHANGED /*| READONLY_OPTION*/ }, + {TK_OPTION_STRING, "-displaycolumns","displayColumns","DisplayColumns", + "#all", Tk_Offset(Treeview,tree.displayColumnsObj), -1, + 0,0,DCOLUMNS_CHANGED | GEOMETRY_CHANGED }, + {TK_OPTION_STRING, "-show", "show", "Show", + DEFAULT_SHOW, Tk_Offset(Treeview,tree.showObj), -1, + 0,0,SHOW_CHANGED | GEOMETRY_CHANGED }, + + {TK_OPTION_STRING_TABLE, "-selectmode", "selectMode", "SelectMode", + "extended", Tk_Offset(Treeview,tree.selectModeObj), -1, + 0,(ClientData)SelectModeStrings,0 }, + + {TK_OPTION_PIXELS, "-height", "height", "Height", + DEF_TREE_ROWS, Tk_Offset(Treeview,tree.heightObj), -1, + 0,0,GEOMETRY_CHANGED}, + {TK_OPTION_STRING, "-padding", "padding", "Pad", + NULL, Tk_Offset(Treeview,tree.paddingObj), -1, + TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, + + {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", + NULL, -1, Tk_Offset(Treeview, tree.xscroll.scrollCmd), + TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, + {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", + NULL, -1, Tk_Offset(Treeview, tree.yscroll.scrollCmd), + TK_OPTION_NULL_OK, 0, SCROLLCMD_CHANGED}, + + WIDGET_TAKEFOCUS_TRUE, + WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) +}; + +/*------------------------------------------------------------------------ + * +++ Utilities. + */ +typedef void (*HashEntryIterator)(void *hashValue); + +static void foreachHashEntry(Tcl_HashTable *ht, HashEntryIterator func) +{ + Tcl_HashSearch search; + Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(ht, &search); + while (entryPtr != NULL) { + func(Tcl_GetHashValue(entryPtr)); + entryPtr = Tcl_NextHashEntry(&search); + } +} + +/* + unshare(objPtr) -- + * Ensure that a Tcl_Obj * has refcount 1 -- either return objPtr + * itself, or a duplicated copy. + */ +static Tcl_Obj *unshare(Tcl_Obj *objPtr) +{ + if (Tcl_IsShared(objPtr)) { + Tcl_Obj *newObj = Tcl_DuplicateObj(objPtr); + Tcl_DecrRefCount(objPtr); + Tcl_IncrRefCount(newObj); + return newObj; + } + return objPtr; +} + +/* DisplayLayout -- + * Rebind, place, and draw a layout + object combination. + */ +static void DisplayLayout( + Ttk_Layout layout, void *recordPtr, Ttk_State state, Ttk_Box b, Drawable d) +{ + Ttk_RebindSublayout(layout, recordPtr); + Ttk_PlaceLayout(layout, state, b); + Ttk_DrawLayout(layout, state, d); +} + +/* + GetColumn -- + * Look up column by name or number. + * Returns: pointer to column table entry, NULL if not found. + * Leaves an error message in interp->result on error. + */ +static TreeColumn *GetColumn( + Tcl_Interp *interp, Treeview *tv, Tcl_Obj *columnIDObj) +{ + Tcl_HashEntry *entryPtr; + int columnIndex; + + /* Check for named column: + */ + entryPtr = Tcl_FindHashEntry( + &tv->tree.columnNames, Tcl_GetString(columnIDObj)); + if (entryPtr) { + return Tcl_GetHashValue(entryPtr); + } + + /* Check for number: + */ + if (Tcl_GetIntFromObj(NULL, columnIDObj, &columnIndex) == TCL_OK) { + if (columnIndex < 0 || columnIndex >= tv->tree.nColumns) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Column index ", + Tcl_GetString(columnIDObj), + " out of bounds", + NULL); + return NULL; + } + + return tv->tree.columns + columnIndex; + } + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Invalid column index ", Tcl_GetString(columnIDObj), + NULL); + return NULL; +} + +/* + FindColumn -- + * Look up column by name, number, or display index. + */ +static TreeColumn *FindColumn( + Tcl_Interp *interp, Treeview *tv, Tcl_Obj *columnIDObj) +{ + int colno; + + if (sscanf(Tcl_GetString(columnIDObj), "#%d", &colno) == 1) + { /* Display column specification, #n */ + if (colno >= 0 && colno < tv->tree.nDisplayColumns) { + return tv->tree.displayColumns[colno]; + } + /* else */ + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Column ", Tcl_GetString(columnIDObj), " out of range", + NULL); + return NULL; + } + + return GetColumn(interp, tv, columnIDObj); +} + +/* + FindItem -- + * Locates the item with the specified identifier in the tree. + * If there is no such item, leaves an error message in interp. + */ +static TreeItem *FindItem( + Tcl_Interp *interp, Treeview *tv, Tcl_Obj *itemNameObj) +{ + const char *itemName = Tcl_GetString(itemNameObj); + Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&tv->tree.items, itemName); + + if (!entryPtr) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Item ", itemName, " not found", NULL); + return 0; + } + return Tcl_GetHashValue(entryPtr); +} + +/* + GetItemListFromObj -- + * Parse a Tcl_Obj * as a list of items. + * Returns a NULL-terminated array of items; result must + * be ckfree()d. On error, returns NULL and leaves an error + * message in interp. + */ + +static TreeItem **GetItemListFromObj( + Tcl_Interp *interp, Treeview *tv, Tcl_Obj *objPtr) +{ + TreeItem **items; + Tcl_Obj **elements; + int i, nElements; + + if (Tcl_ListObjGetElements(interp,objPtr,&nElements,&elements) != TCL_OK) { + return NULL; + } + + items = (TreeItem**)ckalloc((nElements + 1)*sizeof(TreeItem*)); + for (i = 0; i < nElements; ++i) { + items[i] = FindItem(interp, tv, elements[i]); + if (!items[i]) { + ckfree((ClientData)items); + return NULL; + } + } + items[i] = NULL; + return items; +} + +/* + ItemName -- + * Returns the item's ID. + */ +static const char *ItemName(Treeview *tv, TreeItem *item) +{ + return Tcl_GetHashKey(&tv->tree.items, item->entryPtr); +} + +/* + ItemID -- + * Returns a fresh Tcl_Obj * (refcount 0) holding the + * item identifier of the specified item. + */ +static Tcl_Obj *ItemID(Treeview *tv, TreeItem *item) +{ + return Tcl_NewStringObj(ItemName(tv, item), -1); +} + +/*------------------------------------------------------------------------ + * +++ Column configuration. + */ + +/* + TreeviewFreeColumns -- + * Free column data. + */ +static void TreeviewFreeColumns(Treeview *tv) +{ + int i; + + Tcl_DeleteHashTable(&tv->tree.columnNames); + Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS); + + if (tv->tree.columns) { + for (i = 0; i < tv->tree.nColumns; ++i) + FreeColumn(tv->tree.columns + i); + ckfree((ClientData)tv->tree.columns); + tv->tree.columns = 0; + } +} + +/* + TreeviewInitColumns -- + * Initialize column data when -columns changes. + * Returns: TCL_OK or TCL_ERROR; + */ +static int TreeviewInitColumns(Tcl_Interp *interp, Treeview *tv) +{ + Tcl_Obj **columns; + int i, ncols; + + if (Tcl_ListObjGetElements( + interp, tv->tree.columnsObj, &ncols, &columns) != TCL_OK) + { + return TCL_ERROR; + } + + /* + * Free old values: + */ + TreeviewFreeColumns(tv); + + /* + * Initialize columns array and columnNames hash table: + */ + tv->tree.nColumns = ncols; + tv->tree.columns = + (TreeColumn*)ckalloc(tv->tree.nColumns * sizeof(TreeColumn)); + + for (i = 0; i < ncols; ++i) { + int isNew; + Tcl_Obj *columnName = Tcl_DuplicateObj(columns[i]); + + Tcl_HashEntry *entryPtr = Tcl_CreateHashEntry( + &tv->tree.columnNames, Tcl_GetString(columnName), &isNew); + Tcl_SetHashValue(entryPtr, tv->tree.columns + i); + + InitColumn(tv->tree.columns + i); + Tk_InitOptions( + interp, (ClientData)(tv->tree.columns + i), + tv->tree.columnOptionTable, tv->core.tkwin); + Tk_InitOptions( + interp, (ClientData)(tv->tree.columns + i), + tv->tree.headingOptionTable, tv->core.tkwin); + Tcl_IncrRefCount(columnName); + tv->tree.columns[i].idObj = columnName; + } + + return TCL_OK; +} + +/* + TreeviewInitDisplayColumns -- + * Initializes the 'displayColumns' array. + * + * Note that displayColumns[0] is always the tree column, + * even when SHOW_TREE is not set. + * + * @@@ TODO: disallow duplicated columns + */ +static int TreeviewInitDisplayColumns(Tcl_Interp *interp, Treeview *tv) +{ + Tcl_Obj **dcolumns; + int index, ndcols; + TreeColumn **displayColumns = 0; + + if (Tcl_ListObjGetElements(interp, + tv->tree.displayColumnsObj, &ndcols, &dcolumns) != TCL_OK) { + return TCL_ERROR; + } + + if (!strcmp(Tcl_GetString(tv->tree.displayColumnsObj), "#all")) { + ndcols = tv->tree.nColumns; + displayColumns = (TreeColumn**)ckalloc((ndcols+1)*sizeof(TreeColumn*)); + for (index = 0; index < ndcols; ++index) { + displayColumns[index+1] = tv->tree.columns + index; + } + } else { + displayColumns = (TreeColumn**)ckalloc((ndcols+1)*sizeof(TreeColumn*)); + for (index = 0; index < ndcols; ++index) { + displayColumns[index+1] = GetColumn(interp, tv, dcolumns[index]); + if (!displayColumns[index+1]) { + ckfree((ClientData)displayColumns); + return TCL_ERROR; + } + } + } + displayColumns[0] = &tv->tree.column0; + + if (tv->tree.displayColumns) + ckfree((ClientData)tv->tree.displayColumns); + tv->tree.displayColumns = displayColumns; + tv->tree.nDisplayColumns = ndcols + 1; + + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Resizing. + * slack invariant: TreeWidth(tree) + slack = treeArea.width + */ + +#define FirstColumn(tv) ((tv->tree.showFlags&SHOW_TREE) ? 0 : 1) + +/* + TreeWidth -- + * Compute the requested tree width from the sum of visible column widths. + */ +static int TreeWidth(Treeview *tv) +{ + int i = FirstColumn(tv); + int width = 0; + + while (i < tv->tree.nDisplayColumns) { + width += tv->tree.displayColumns[i++]->width; + } + return width; +} + +/* + RecomputeSlack -- + */ +static void RecomputeSlack(Treeview *tv) +{ + tv->tree.slack = tv->tree.treeArea.width - TreeWidth(tv); +} + +/* + PickupSlack/DepositSlack -- + * When resizing columns, distribute extra space to 'slack' first, + * and only adjust column widths if 'slack' goes to zero. + * That is, don't bother changing column widths if the tree + * is already scrolled or short. + */ +static int PickupSlack(Treeview *tv, int extra) +{ + int newSlack = tv->tree.slack + extra; + + if ( (newSlack < 0 && 0 <= tv->tree.slack) + || (newSlack > 0 && 0 >= tv->tree.slack)) + { + tv->tree.slack = 0; + return newSlack; + } else { + tv->tree.slack = newSlack; + return 0; + } +} + +static void DepositSlack(Treeview *tv, int extra) +{ + tv->tree.slack += extra; +} + +/* + Stretch -- + * Adjust width of column by N pixels, down to minimum width. + * Returns: #pixels actually moved. + */ +static int Stretch(TreeColumn *c, int n) +{ + int newWidth = n + c->width; + if (newWidth < c->minWidth) { + n = c->minWidth - c->width; + c->width = c->minWidth; + } else { + c->width = newWidth; + } + return n; +} + +/* + ShoveLeft -- + * Adjust width of (stretchable) columns to the left by N pixels. + * Returns: leftover slack. + */ +static int ShoveLeft(Treeview *tv, int i, int n) +{ + int first = FirstColumn(tv); + while (n != 0 && i >= first) { + TreeColumn *c = tv->tree.displayColumns[i]; + if (c->stretch) { + n -= Stretch(c, n); + } + --i; + } + return n; +} + +/* + ShoveRight -- + * Adjust width of (stretchable) columns to the right by N pixels. + * Returns: leftover slack. + */ +static int ShoveRight(Treeview *tv, int i, int n) +{ + while (n != 0 && i < tv->tree.nDisplayColumns) { + TreeColumn *c = tv->tree.displayColumns[i]; + if (c->stretch) { + n -= Stretch(c, n); + } + ++i; + } + return n; +} + +/* + DistributeWidth -- + * Distribute n pixels evenly across all stretchable display columns. + * Returns: leftover slack. + * Notes: + * The "((++w % m) < r)" term is there so that the remainder r = n % m + * is distributed round-robin. + */ +static int DistributeWidth(Treeview *tv, int n) +{ + int w = TreeWidth(tv); + int m = 0; + int i, d, r; + + for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) { + if (tv->tree.displayColumns[i]->stretch) { + ++m; + } + } + if (m == 0) { + return n; + } + + d = n / m; + r = n % m; + if (r < 0) { r += m; --d; } + + for (i = FirstColumn(tv); i < tv->tree.nDisplayColumns; ++i) { + TreeColumn *c = tv->tree.displayColumns[i]; + if (c->stretch) { + n -= Stretch(c, d + ((++w % m) < r)); + } + } + return n; +} + +/* + ResizeColumns -- + * Recompute column widths based on available width. + * Pick up slack first; + * Distribute the remainder evenly across stretchable columns; + * If any is still left over due to minwidth constraints, shove left. + */ +static void ResizeColumns(Treeview *tv, int newWidth) +{ + int delta = newWidth - (TreeWidth(tv) + tv->tree.slack); + DepositSlack(tv, + ShoveLeft(tv, tv->tree.nDisplayColumns - 1, + DistributeWidth(tv, PickupSlack(tv, delta)))); +} + +/* + DragColumn -- + * Move the separator to the right of specified column, + * adjusting other column widths as necessary. + */ +static void DragColumn(Treeview *tv, int i, int delta) +{ + TreeColumn *c = tv->tree.displayColumns[i]; + int dl = delta - ShoveLeft(tv, i-1, delta - Stretch(c, delta)); + int dr = ShoveRight(tv, i+1, PickupSlack(tv, -dl)); + DepositSlack(tv, dr); +} + +/*------------------------------------------------------------------------ + * +++ Event handlers. + */ + +static TreeItem *IdentifyItem(Treeview *tv, int y); /*forward*/ + +static const unsigned int TreeviewBindEventMask = + KeyPressMask|KeyReleaseMask + | ButtonPressMask|ButtonReleaseMask + | PointerMotionMask|ButtonMotionMask + | VirtualEventMask + ; + +static void TreeviewBindEventProc(void *clientData, XEvent *event) +{ + Treeview *tv = clientData; + TreeItem *item = NULL; + Ttk_TagSet tagset; + + /* + * Figure out where to deliver the event. + */ + switch (event->type) + { + case KeyPress: + case KeyRelease: + case VirtualEvent: + item = tv->tree.focus; + break; + case ButtonPress: + case ButtonRelease: + item = IdentifyItem(tv, event->xbutton.y); + break; + case MotionNotify: + item = IdentifyItem(tv, event->xmotion.y); + break; + default: + break; + } + + if (!item) { + return; + } + + /* ASSERT: Ttk_GetTagSetFromObj succeeds. + * NB: must use a local copy of the tagset, + * in case a binding script stomps on -tags. + */ + tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, item->tagsObj); + + /* + * Fire binding: + */ + Tcl_Preserve(clientData); + Tk_BindEvent(tv->tree.bindingTable, event, tv->core.tkwin, + tagset->nTags, (void **)tagset->tags); + Tcl_Release(clientData); + + Ttk_FreeTagSet(tagset); +} + +/*------------------------------------------------------------------------ + * +++ Initialization and cleanup. + */ + +static void TreeviewInitialize(Tcl_Interp *interp, void *recordPtr) +{ + Treeview *tv = recordPtr; + int unused; + + tv->tree.itemOptionTable = + Tk_CreateOptionTable(interp, ItemOptionSpecs); + tv->tree.columnOptionTable = + Tk_CreateOptionTable(interp, ColumnOptionSpecs); + tv->tree.headingOptionTable = + Tk_CreateOptionTable(interp, HeadingOptionSpecs); + tv->tree.tagOptionTable = + Tk_CreateOptionTable(interp, TagOptionSpecs); + + tv->tree.tagTable = Ttk_CreateTagTable( + interp, tv->core.tkwin, TagOptionSpecs, sizeof(DisplayItem)); + tv->tree.bindingTable = Tk_CreateBindingTable(interp); + Tk_CreateEventHandler(tv->core.tkwin, + TreeviewBindEventMask, TreeviewBindEventProc, tv); + + tv->tree.itemLayout + = tv->tree.cellLayout + = tv->tree.headingLayout + = tv->tree.rowLayout + = 0; + tv->tree.headingHeight = tv->tree.rowHeight = DEFAULT_ROWHEIGHT; + tv->tree.indent = DEFAULT_INDENT; + + Tcl_InitHashTable(&tv->tree.columnNames, TCL_STRING_KEYS); + tv->tree.nColumns = tv->tree.nDisplayColumns = 0; + tv->tree.columns = NULL; + tv->tree.displayColumns = NULL; + tv->tree.showFlags = ~0; + + InitColumn(&tv->tree.column0); + Tk_InitOptions( + interp, (ClientData)(&tv->tree.column0), + tv->tree.columnOptionTable, tv->core.tkwin); + Tk_InitOptions( + interp, (ClientData)(&tv->tree.column0), + tv->tree.headingOptionTable, tv->core.tkwin); + + Tcl_InitHashTable(&tv->tree.items, TCL_STRING_KEYS); + tv->tree.serial = 0; + + tv->tree.focus = tv->tree.endPtr = 0; + + /* Create root item "": + */ + tv->tree.root = NewItem(); + Tk_InitOptions(interp, (ClientData)tv->tree.root, + tv->tree.itemOptionTable, tv->core.tkwin); + tv->tree.root->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL); + tv->tree.root->entryPtr = Tcl_CreateHashEntry(&tv->tree.items, "", &unused); + Tcl_SetHashValue(tv->tree.root->entryPtr, tv->tree.root); + + /* Scroll handles: + */ + tv->tree.xscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.xscroll); + tv->tree.yscrollHandle = TtkCreateScrollHandle(&tv->core,&tv->tree.yscroll); + + /* Size parameters: + */ + tv->tree.treeArea = tv->tree.headingArea = Ttk_MakeBox(0,0,0,0); + tv->tree.slack = 0; +} + +static void TreeviewCleanup(void *recordPtr) +{ + Treeview *tv = recordPtr; + + Tk_DeleteEventHandler(tv->core.tkwin, + TreeviewBindEventMask, TreeviewBindEventProc, tv); + Tk_DeleteBindingTable(tv->tree.bindingTable); + Ttk_DeleteTagTable(tv->tree.tagTable); + + if (tv->tree.itemLayout) Ttk_FreeLayout(tv->tree.itemLayout); + if (tv->tree.cellLayout) Ttk_FreeLayout(tv->tree.cellLayout); + if (tv->tree.headingLayout) Ttk_FreeLayout(tv->tree.headingLayout); + if (tv->tree.rowLayout) Ttk_FreeLayout(tv->tree.rowLayout); + + TreeviewFreeColumns(tv); + + if (tv->tree.displayColumns) + Tcl_Free((ClientData)tv->tree.displayColumns); + + foreachHashEntry(&tv->tree.items, FreeItemCB); + Tcl_DeleteHashTable(&tv->tree.items); + + TtkFreeScrollHandle(tv->tree.xscrollHandle); + TtkFreeScrollHandle(tv->tree.yscrollHandle); +} + +/* + TreeviewConfigure -- + * Configuration widget hook. + * + * BUG: If user sets -columns and -displaycolumns, but -displaycolumns + * has an error, the widget is left in an inconsistent state. + */ +static int +TreeviewConfigure(Tcl_Interp *interp, void *recordPtr, int mask) +{ + Treeview *tv = recordPtr; + unsigned showFlags = tv->tree.showFlags; + + if (mask & COLUMNS_CHANGED) { + if (TreeviewInitColumns(interp, tv) != TCL_OK) + return TCL_ERROR; + mask |= DCOLUMNS_CHANGED; + } + if (mask & DCOLUMNS_CHANGED) { + if (TreeviewInitDisplayColumns(interp, tv) != TCL_OK) + return TCL_ERROR; + } + if (mask & SCROLLCMD_CHANGED) { + TtkScrollbarUpdateRequired(tv->tree.xscrollHandle); + TtkScrollbarUpdateRequired(tv->tree.yscrollHandle); + } + if ( (mask & SHOW_CHANGED) + && GetEnumSetFromObj( + interp,tv->tree.showObj,showStrings,&showFlags) != TCL_OK) + { + return TCL_ERROR; + } + + if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) { + return TCL_ERROR; + } + + tv->tree.showFlags = showFlags; + + if (mask & (SHOW_CHANGED | DCOLUMNS_CHANGED)) { + RecomputeSlack(tv); + } + return TCL_OK; +} + +/* + ConfigureItem -- + * Set item options. + */ +static int ConfigureItem( + Tcl_Interp *interp, Treeview *tv, TreeItem *item, + int objc, Tcl_Obj *const objv[]) +{ + Tk_SavedOptions savedOptions; + int mask; + Ttk_ImageSpec *newImageSpec = NULL; + Ttk_TagSet newTagSet = NULL; + + if (Tk_SetOptions(interp, (ClientData)item, tv->tree.itemOptionTable, + objc, objv, tv->core.tkwin, &savedOptions, &mask) + != TCL_OK) + { + return TCL_ERROR; + } + + /* Make sure that -values is a valid list: + */ + if (item->valuesObj) { + int unused; + if (Tcl_ListObjLength(interp, item->valuesObj, &unused) != TCL_OK) + goto error; + } + + /* Check -image. + */ + if ((mask & ITEM_OPTION_IMAGE_CHANGED) && item->imageObj) { + newImageSpec = TtkGetImageSpec(interp, tv->core.tkwin, item->imageObj); + if (!newImageSpec) { + goto error; + } + } + + /* Check -tags. + * Side effect: may create new tags. + */ + if (mask & ITEM_OPTION_TAGS_CHANGED) { + newTagSet = Ttk_GetTagSetFromObj( + interp, tv->tree.tagTable, item->tagsObj); + if (!newTagSet) { + goto error; + } + } + + /* Keep TTK_STATE_OPEN flag in sync with item->openObj. + * We use both a state flag and a Tcl_Obj* resource so elements + * can access the value in either way. + */ + if (item->openObj) { + int isOpen; + if (Tcl_GetBooleanFromObj(interp, item->openObj, &isOpen) != TCL_OK) + goto error; + if (isOpen) + item->state |= TTK_STATE_OPEN; + else + item->state &= ~TTK_STATE_OPEN; + } + + /* All OK. + */ + Tk_FreeSavedOptions(&savedOptions); + if (mask & ITEM_OPTION_TAGS_CHANGED) { + if (item->tagset) { Ttk_FreeTagSet(item->tagset); } + item->tagset = newTagSet; + } + if (mask & ITEM_OPTION_IMAGE_CHANGED) { + if (item->imagespec) { TtkFreeImageSpec(item->imagespec); } + item->imagespec = newImageSpec; + } + TtkRedisplayWidget(&tv->core); + return TCL_OK; + +error: + Tk_RestoreSavedOptions(&savedOptions); + if (newTagSet) { Ttk_FreeTagSet(newTagSet); } + if (newImageSpec) { TtkFreeImageSpec(newImageSpec); } + return TCL_ERROR; +} + +/* + ConfigureColumn -- + * Set column options. + */ +static int ConfigureColumn( + Tcl_Interp *interp, Treeview *tv, TreeColumn *column, + int objc, Tcl_Obj *const objv[]) +{ + Tk_SavedOptions savedOptions; + int mask; + + if (Tk_SetOptions(interp, (ClientData)column, + tv->tree.columnOptionTable, objc, objv, tv->core.tkwin, + &savedOptions,&mask) != TCL_OK) + { + return TCL_ERROR; + } + + if (mask & READONLY_OPTION) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "Attempt to change read-only option", NULL); + goto error; + } + + /* Propagate column width changes to overall widget request width, + * but only if the widget is currently unmapped, in order to prevent + * geometry jumping during interactive column resize. + */ + if (mask & GEOMETRY_CHANGED) { + if (!Tk_IsMapped(tv->core.tkwin)) { + TtkResizeWidget(&tv->core); + } + RecomputeSlack(tv); + } + TtkRedisplayWidget(&tv->core); + + /* ASSERT: SLACKINVARIANT */ + + Tk_FreeSavedOptions(&savedOptions); + return TCL_OK; + +error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; +} + +/* + ConfigureHeading -- + * Set heading options. + */ +static int ConfigureHeading( + Tcl_Interp *interp, Treeview *tv, TreeColumn *column, + int objc, Tcl_Obj *const objv[]) +{ + Tk_SavedOptions savedOptions; + int mask; + + if (Tk_SetOptions(interp, (ClientData)column, + tv->tree.headingOptionTable, objc, objv, tv->core.tkwin, + &savedOptions,&mask) != TCL_OK) + { + return TCL_ERROR; + } + + /* @@@ testing ... */ + if ((mask & STATE_CHANGED) && column->headingStateObj) { + Ttk_StateSpec stateSpec; + if (Ttk_GetStateSpecFromObj( + interp, column->headingStateObj, &stateSpec) != TCL_OK) + { + goto error; + } + column->headingState = Ttk_ModifyState(column->headingState,&stateSpec); + Tcl_DecrRefCount(column->headingStateObj); + column->headingStateObj = Ttk_NewStateSpecObj(column->headingState,0); + Tcl_IncrRefCount(column->headingStateObj); + } + + TtkRedisplayWidget(&tv->core); + Tk_FreeSavedOptions(&savedOptions); + return TCL_OK; + +error: + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; +} + +/*------------------------------------------------------------------------ + * +++ Geometry routines. + */ + +/* + CountRows -- + * Returns the number of viewable rows rooted at item + */ +static int CountRows(TreeItem *item) +{ + int rows = 1; + + if (item->state & TTK_STATE_OPEN) { + TreeItem *child = item->children; + while (child) { + rows += CountRows(child); + child = child->next; + } + } + return rows; +} + +/* + IdentifyRow -- + * Recursive search for item at specified y position. + * Main work routine for IdentifyItem() + */ +static TreeItem *IdentifyRow( + Treeview *tv, /* Widget record */ + TreeItem *item, /* Where to start search */ + int *ypos, /* Scan position */ + int y) /* Target y coordinate */ +{ + while (item) { + int next_ypos = *ypos + tv->tree.rowHeight; + if (*ypos <= y && y <= next_ypos) { + return item; + } + *ypos = next_ypos; + if (item->state & TTK_STATE_OPEN) { + TreeItem *subitem = IdentifyRow(tv, item->children, ypos, y); + if (subitem) { + return subitem; + } + } + item = item->next; + } + return 0; +} + +/* + IdentifyItem -- + * Locate the item at the specified y position, if any. + */ +static TreeItem *IdentifyItem(Treeview *tv, int y) +{ + int rowHeight = tv->tree.rowHeight; + int ypos = tv->tree.treeArea.y - rowHeight * tv->tree.yscroll.first; + return IdentifyRow(tv, tv->tree.root->children, &ypos, y); +} + +/* + IdentifyDisplayColumn -- + * Returns the display column number at the specified x position, + * or -1 if x is outside any columns. + */ +static int IdentifyDisplayColumn(Treeview *tv, int x, int *x1) +{ + int colno = FirstColumn(tv); + int xpos = tv->tree.treeArea.x - tv->tree.xscroll.first; + + while (colno < tv->tree.nDisplayColumns) { + TreeColumn *column = tv->tree.displayColumns[colno]; + int next_xpos = xpos + column->width; + if (xpos <= x && x <= next_xpos + HALO) { + *x1 = next_xpos; + return colno; + } + ++colno; + xpos = next_xpos; + } + + return -1; +} + +/* + RowNumber -- + * Calculate which row the specified item appears on; + * returns -1 if the item is not viewable. + * Xref: DrawForest, IdentifyItem. + */ +static int RowNumber(Treeview *tv, TreeItem *item) +{ + TreeItem *p = tv->tree.root->children; + int n = 0; + + while (p) { + if (p == item) + return n; + + ++n; + + /* Find next viewable item in preorder traversal order + */ + if (p->children && (p->state & TTK_STATE_OPEN)) { + p = p->children; + } else { + while (!p->next && p && p->parent) + p = p->parent; + if (p) + p = p->next; + } + } + + return -1; +} + +/* + ItemDepth -- return the depth of a tree item. + * The depth of an item is equal to the number of proper ancestors, + * not counting the root node. + */ +static int ItemDepth(TreeItem *item) +{ + int depth = 0; + while (item->parent) { + ++depth; + item = item->parent; + } + return depth-1; +} + +/* + ItemRow -- + * Returns row number of specified item relative to root, + * -1 if item is not viewable. + */ +static int ItemRow(Treeview *tv, TreeItem *p) +{ + TreeItem *root = tv->tree.root; + int rowNumber = 0; + + for (;;) { + if (p->prev) { + p = p->prev; + rowNumber += CountRows(p); + } else { + p = p->parent; + if (!(p && (p->state & TTK_STATE_OPEN))) { + /* detached or closed ancestor */ + return -1; + } + if (p == root) { + return rowNumber; + } + ++rowNumber; + } + } +} + +/* + BoundingBox -- + * Compute the parcel of the specified column of the specified item, + * (or the entire item if column is NULL) + * Returns: 0 if item or column is not viewable, 1 otherwise. + */ +static int BoundingBox( + Treeview *tv, /* treeview widget */ + TreeItem *item, /* desired item */ + TreeColumn *column, /* desired column */ + Ttk_Box *bbox_rtn) /* bounding box of item */ +{ + int row = ItemRow(tv, item); + Ttk_Box bbox = tv->tree.treeArea; + + if (row < tv->tree.yscroll.first || row > tv->tree.yscroll.last) { + /* not viewable, or off-screen */ + return 0; + } + + bbox.y += (row - tv->tree.yscroll.first) * tv->tree.rowHeight; + bbox.height = tv->tree.rowHeight; + + bbox.x -= tv->tree.xscroll.first; + bbox.width = TreeWidth(tv); + + if (column) { + int xpos = 0, i = FirstColumn(tv); + while (i < tv->tree.nDisplayColumns) { + if (tv->tree.displayColumns[i] == column) { + break; + } + xpos += tv->tree.displayColumns[i]->width; + ++i; + } + if (i == tv->tree.nDisplayColumns) { /* specified column unviewable */ + return 0; + } + bbox.x += xpos; + bbox.width = column->width; + + /* Account for indentation in tree column: + */ + if (column == &tv->tree.column0) { + int indent = tv->tree.indent * ItemDepth(item); + bbox.x += indent; + bbox.width -= indent; + } + } + *bbox_rtn = bbox; + return 1; +} + +/* + IdentifyRegion -- + */ + +typedef enum { + REGION_NOTHING = 0, + REGION_HEADING, + REGION_SEPARATOR, + REGION_TREE, + REGION_CELL +} TreeRegion; + +static const char *regionStrings[] = { + "nothing", "heading", "separator", "tree", "cell", 0 +}; + +static TreeRegion IdentifyRegion(Treeview *tv, int x, int y) +{ + int x1 = 0, colno; + + colno = IdentifyDisplayColumn(tv, x, &x1); + if (Ttk_BoxContains(tv->tree.headingArea, x, y)) { + if (colno < 0) { + return REGION_NOTHING; + } else if (-HALO <= x1 - x && x1 - x <= HALO) { + return REGION_SEPARATOR; + } else { + return REGION_HEADING; + } + } else if (Ttk_BoxContains(tv->tree.treeArea, x, y)) { + TreeItem *item = IdentifyItem(tv, y); + if (item && colno > 0) { + return REGION_CELL; + } else if (item) { + return REGION_TREE; + } + } + return REGION_NOTHING; +} + +/*------------------------------------------------------------------------ + * +++ Display routines. + */ + +/* + GetSublayout -- + * Utility routine; acquires a sublayout for items, cells, etc. + */ +static Ttk_Layout GetSublayout( + Tcl_Interp *interp, + Ttk_Theme themePtr, + Ttk_Layout parentLayout, + const char *layoutName, + Tk_OptionTable optionTable, + Ttk_Layout *layoutPtr) +{ + Ttk_Layout newLayout = Ttk_CreateSublayout( + interp, themePtr, parentLayout, layoutName, optionTable); + + if (newLayout) { + if (*layoutPtr) + Ttk_FreeLayout(*layoutPtr); + *layoutPtr = newLayout; + } + return newLayout; +} + +/* + TreeviewGetLayout -- + * GetLayout() widget hook. + */ +static Ttk_Layout TreeviewGetLayout( + Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr) +{ + Treeview *tv = recordPtr; + Ttk_Layout treeLayout = TtkWidgetGetLayout(interp, themePtr, recordPtr); + Tcl_Obj *objPtr; + int unused; + + if (!( + treeLayout + && GetSublayout(interp, themePtr, treeLayout, ".Item", + tv->tree.tagOptionTable, &tv->tree.itemLayout) + && GetSublayout(interp, themePtr, treeLayout, ".Cell", + tv->tree.tagOptionTable, &tv->tree.cellLayout) + && GetSublayout(interp, themePtr, treeLayout, ".Heading", + tv->tree.headingOptionTable, &tv->tree.headingLayout) + && GetSublayout(interp, themePtr, treeLayout, ".Row", + tv->tree.tagOptionTable, &tv->tree.rowLayout) + )) { + return 0; + } + + /* Compute heading height. + */ + Ttk_RebindSublayout(tv->tree.headingLayout, &tv->tree.column0); + Ttk_LayoutSize(tv->tree.headingLayout, 0, &unused, &tv->tree.headingHeight); + + /* Get item height, indent from style: + * @@@ TODO: sanity-check. + */ + tv->tree.rowHeight = DEFAULT_ROWHEIGHT; + tv->tree.indent = DEFAULT_INDENT; + if ((objPtr = Ttk_QueryOption(treeLayout, "-rowheight", 0))) { + (void)Tcl_GetIntFromObj(NULL, objPtr, &tv->tree.rowHeight); + } + if ((objPtr = Ttk_QueryOption(treeLayout, "-indent", 0))) { + (void)Tcl_GetIntFromObj(NULL, objPtr, &tv->tree.indent); + } + + return treeLayout; +} + +/* + TreeviewDoLayout -- + * DoLayout() widget hook. Computes widget layout. + * + * Side effects: + * Computes headingArea and treeArea. + * Computes subtree height. + * Invokes scroll callbacks. + */ +static void TreeviewDoLayout(void *clientData) +{ + Treeview *tv = clientData; + int visibleRows; + + /* ASSERT: SLACKINVARIANT */ + + Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin)); + tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, "treearea"); + + ResizeColumns(tv, tv->tree.treeArea.width); + /* ASSERT: SLACKINVARIANT */ + + TtkScrolled(tv->tree.xscrollHandle, + tv->tree.xscroll.first, + tv->tree.xscroll.first + tv->tree.treeArea.width, + TreeWidth(tv)); + + if (tv->tree.showFlags & SHOW_HEADINGS) { + tv->tree.headingArea = Ttk_PackBox( + &tv->tree.treeArea, 1, tv->tree.headingHeight, TTK_SIDE_TOP); + } else { + tv->tree.headingArea = Ttk_MakeBox(0,0,0,0); + } + + visibleRows = tv->tree.treeArea.height / tv->tree.rowHeight; + tv->tree.root->state |= TTK_STATE_OPEN; + TtkScrolled(tv->tree.yscrollHandle, + tv->tree.yscroll.first, + tv->tree.yscroll.first + visibleRows, + CountRows(tv->tree.root) - 1); +} + +/* + TreeviewSize -- + * SizeProc() widget hook. Size is determined by + * -height option and column widths. + */ +static int TreeviewSize(void *clientData, int *widthPtr, int *heightPtr) +{ + Treeview *tv = clientData; + int nRows, padHeight, padWidth; + + Ttk_LayoutSize(tv->core.layout, tv->core.state, &padWidth, &padHeight); + Tcl_GetIntFromObj(NULL, tv->tree.heightObj, &nRows); + + *widthPtr = padWidth + TreeWidth(tv); + *heightPtr = padHeight + tv->tree.rowHeight * nRows; + + if (tv->tree.showFlags & SHOW_HEADINGS) { + *heightPtr += tv->tree.headingHeight; + } + + return 1; +} + +/* + ItemState -- + * Returns the state of the specified item, based + * on widget state, item state, and other information. + */ +static Ttk_State ItemState(Treeview *tv, TreeItem *item) +{ + Ttk_State state = tv->core.state | item->state; + if (!item->children) + state |= TTK_STATE_LEAF; + if (item != tv->tree.focus) + state &= ~TTK_STATE_FOCUS; + return state; +} + +/* + DrawHeadings -- + * Draw tree headings. + */ +static void DrawHeadings(Treeview *tv, Drawable d) +{ + const int x0 = tv->tree.headingArea.x - tv->tree.xscroll.first; + const int y0 = tv->tree.headingArea.y; + const int h0 = tv->tree.headingArea.height; + int i = FirstColumn(tv); + int x = 0; + + while (i < tv->tree.nDisplayColumns) { + TreeColumn *column = tv->tree.displayColumns[i]; + Ttk_Box parcel = Ttk_MakeBox(x0+x, y0, column->width, h0); + DisplayLayout(tv->tree.headingLayout, + column, column->headingState, parcel, d); + x += column->width; + ++i; + } +} + +/* + PrepareItem -- + * Fill in a displayItem record. + */ +static void PrepareItem( + Treeview *tv, TreeItem *item, DisplayItem *displayItem) +{ + Ttk_Style style = Ttk_LayoutStyle(tv->core.layout); + Ttk_State state = ItemState(tv, item); + + Ttk_TagSetValues(tv->tree.tagTable, item->tagset, displayItem); + Ttk_TagSetApplyStyle(tv->tree.tagTable, style, state, displayItem); +} + +/* + DrawCells -- + * Draw data cells for specified item. + */ +static void DrawCells( + Treeview *tv, TreeItem *item, DisplayItem *displayItem, + Drawable d, int x, int y) +{ + Ttk_Layout layout = tv->tree.cellLayout; + Ttk_State state = ItemState(tv, item); + Ttk_Padding cellPadding = {4, 0, 4, 0}; + int rowHeight = tv->tree.rowHeight; + int nValues = 0; + Tcl_Obj **values = 0; + int i; + + if (!item->valuesObj) { + return; + } + + Tcl_ListObjGetElements(NULL, item->valuesObj, &nValues, &values); + for (i = 0; i < tv->tree.nColumns; ++i) { + tv->tree.columns[i].data = (i < nValues) ? values[i] : 0; + } + + for (i = 1; i < tv->tree.nDisplayColumns; ++i) { + TreeColumn *column = tv->tree.displayColumns[i]; + Ttk_Box parcel = Ttk_PadBox( + Ttk_MakeBox(x, y, column->width, rowHeight), cellPadding); + + displayItem->textObj = column->data; + displayItem->anchorObj = column->anchorObj; /* <<NOTE-ANCHOR>> */ + + DisplayLayout(layout, displayItem, state, parcel, d); + x += column->width; + } +} + +/* + DrawItem -- + * Draw an item (row background, tree label, and cells). + */ +static void DrawItem( + Treeview *tv, TreeItem *item, Drawable d, int depth, int row) +{ + Ttk_State state = ItemState(tv, item); + DisplayItem displayItem; + int rowHeight = tv->tree.rowHeight; + int x = tv->tree.treeArea.x - tv->tree.xscroll.first; + int y = tv->tree.treeArea.y + rowHeight * (row - tv->tree.yscroll.first); + + if (row % 2) state |= TTK_STATE_ALTERNATE; + + PrepareItem(tv, item, &displayItem); + + /* Draw row background: + */ + { + Ttk_Box rowBox = Ttk_MakeBox(x, y, TreeWidth(tv), rowHeight); + DisplayLayout(tv->tree.rowLayout, &displayItem, state, rowBox, d); + } + + /* Draw tree label: + */ + if (tv->tree.showFlags & SHOW_TREE) { + int indent = depth * tv->tree.indent; + int colwidth = tv->tree.column0.width; + Ttk_Box parcel = Ttk_MakeBox( + x+indent, y, colwidth-indent, rowHeight); + if (item->textObj) { displayItem.textObj = item->textObj; } + if (item->imageObj) { displayItem.imageObj = item->imageObj; } + /* ??? displayItem.anchorObj = 0; <<NOTE-ANCHOR>> */ + DisplayLayout(tv->tree.itemLayout, &displayItem, state, parcel, d); + x += colwidth; + } + + /* Draw data cells: + */ + DrawCells(tv, item, &displayItem, d, x, y); +} + +/* + DrawSubtree -- + * Draw an item and all of its (viewable) descendants. + * + * Returns: + * Row number of the last item drawn. + */ + +static int DrawForest( /* forward */ + Treeview *tv, TreeItem *item, Drawable d, int depth, int row); + +static int DrawSubtree( + Treeview *tv, TreeItem *item, Drawable d, int depth, int row) +{ + if (row >= tv->tree.yscroll.first) { + DrawItem(tv, item, d, depth, row); + } + + if (item->state & TTK_STATE_OPEN) { + return DrawForest(tv, item->children, d, depth + 1, row + 1); + } else { + return row + 1; + } +} + +/* + DrawForest -- + * Draw a sequence of items and their visible descendants. + * + * Returns: + * Row number of the last item drawn. + */ +static int DrawForest( + Treeview *tv, TreeItem *item, Drawable d, int depth, int row) +{ + while (item && row <= tv->tree.yscroll.last) { + row = DrawSubtree(tv, item, d, depth, row); + item = item->next; + } + return row; +} + +/* + TreeviewDisplay -- + * Display() widget hook. Draw the widget contents. + */ +static void TreeviewDisplay(void *clientData, Drawable d) +{ + Treeview *tv = clientData; + + Ttk_DrawLayout(tv->core.layout, tv->core.state, d); + if (tv->tree.showFlags & SHOW_HEADINGS) { + DrawHeadings(tv, d); + } + DrawForest(tv, tv->tree.root->children, d, 0,0); +} + +/*------------------------------------------------------------------------ + * +++ Utilities for widget commands + */ + +/* + InsertPosition -- + * Locate the previous sibling for [$tree insert]. + * + * Returns a pointer to the item just before the specified index, + * or 0 if the item is to be inserted at the beginning. + */ +static TreeItem *InsertPosition(TreeItem *parent, int index) +{ + TreeItem *prev = 0, *next = parent->children; + + while (next != 0 && index > 0) { + --index; + prev = next; + next = prev->next; + } + + return prev; +} + +/* + EndPosition -- + * Locate the last child of the specified node. + * + * To avoid quadratic-time behavior in the common cases + * where the treeview is populated in breadth-first or + * depth-first order using [$tv insert $parent end ...], + * we cache the result from the last call to EndPosition() + * and start the search from there on a cache hit. + * + */ +static TreeItem *EndPosition(Treeview *tv, TreeItem *parent) +{ + TreeItem *endPtr = tv->tree.endPtr; + + while (endPtr && endPtr->parent != parent) { + endPtr = endPtr->parent; + } + if (!endPtr) { + endPtr = parent->children; + } + + if (endPtr) { + while (endPtr->next) { + endPtr = endPtr->next; + } + tv->tree.endPtr = endPtr; + } + + return endPtr; +} + +/* + AncestryCheck -- + * Verify that specified item is not an ancestor of the specified parent; + * returns 1 if OK, 0 and leaves an error message in interp otherwise. + */ +static int AncestryCheck( + Tcl_Interp *interp, Treeview *tv, TreeItem *item, TreeItem *parent) +{ + TreeItem *p = parent; + while (p) { + if (p == item) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "Cannot insert ", ItemName(tv, item), + " as a descendant of ", ItemName(tv, parent), + NULL); + return 0; + } + p = p->parent; + } + return 1; +} + +/* + DeleteItems -- + * Remove an item and all of its descendants from the hash table + * and detach them from the tree; returns a linked list (chained + * along the ->next pointer) of deleted items. + */ +static TreeItem *DeleteItems(TreeItem *item, TreeItem *delq) +{ + if (item->entryPtr) { + DetachItem(item); + while (item->children) { + delq = DeleteItems(item->children, delq); + } + Tcl_DeleteHashEntry(item->entryPtr); + item->entryPtr = 0; + item->next = delq; + delq = item; + } /* else -- item has already been unlinked */ + return delq; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- item inquiry. + */ + +/* + $tv children $item ?newchildren? -- + * Return the list of children associated with $item + */ +static int TreeviewChildrenCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + Tcl_Obj *result; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "item ?newchildren?"); + return TCL_ERROR; + } + item = FindItem(interp, tv, objv[2]); + if (!item) { + return TCL_ERROR; + } + + if (objc == 3) { + result = Tcl_NewListObj(0,0); + for (item = item->children; item; item = item->next) { + Tcl_ListObjAppendElement(interp, result, ItemID(tv, item)); + } + Tcl_SetObjResult(interp, result); + } else { + TreeItem **newChildren = GetItemListFromObj(interp, tv, objv[3]); + TreeItem *child; + int i; + + if (!newChildren) + return TCL_ERROR; + + /* Sanity-check: + */ + for (i=0; newChildren[i]; ++i) { + if (!AncestryCheck(interp, tv, newChildren[i], item)) { + ckfree((ClientData)newChildren); + return TCL_ERROR; + } + } + + /* Detach old children: + */ + child = item->children; + while (child) { + TreeItem *next = child->next; + DetachItem(child); + child = next; + } + + /* Detach new children from their current locations: + */ + for (i=0; newChildren[i]; ++i) { + DetachItem(newChildren[i]); + } + + /* Reinsert new children: + * Note: it is not an error for an item to be listed more than once, + * though it probably should be... + */ + child = 0; + for (i=0; newChildren[i]; ++i) { + if (newChildren[i]->parent) { + /* This is a duplicate element which has already been + * inserted. Ignore it. + */ + continue; + } + InsertItem(item, child, newChildren[i]); + child = newChildren[i]; + } + + ckfree((ClientData)newChildren); + TtkRedisplayWidget(&tv->core); + } + + return TCL_OK; +} + +/* + $tv parent $item -- + * Return the item ID of $item's parent. + */ +static int TreeviewParentCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item"); + return TCL_ERROR; + } + item = FindItem(interp, tv, objv[2]); + if (!item) { + return TCL_ERROR; + } + + if (item->parent) { + Tcl_SetObjResult(interp, ItemID(tv, item->parent)); + } else { + /* This is the root item. @@@ Return an error? */ + Tcl_ResetResult(interp); + } + + return TCL_OK; +} + +/* + $tv next $item + * Return the ID of $item's next sibling. + */ +static int TreeviewNextCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item"); + return TCL_ERROR; + } + item = FindItem(interp, tv, objv[2]); + if (!item) { + return TCL_ERROR; + } + + if (item->next) { + Tcl_SetObjResult(interp, ItemID(tv, item->next)); + } /* else -- leave interp-result empty */ + + return TCL_OK; +} + +/* + $tv prev $item + * Return the ID of $item's previous sibling. + */ +static int TreeviewPrevCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item"); + return TCL_ERROR; + } + item = FindItem(interp, tv, objv[2]); + if (!item) { + return TCL_ERROR; + } + + if (item->prev) { + Tcl_SetObjResult(interp, ItemID(tv, item->prev)); + } /* else -- leave interp-result empty */ + + return TCL_OK; +} + +/* + $tv index $item -- + * Return the index of $item within its parent. + */ +static int TreeviewIndexCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + int index = 0; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item"); + return TCL_ERROR; + } + item = FindItem(interp, tv, objv[2]); + if (!item) { + return TCL_ERROR; + } + + while (item->prev) { + ++index; + item = item->prev; + } + + Tcl_SetObjResult(interp, Tcl_NewIntObj(index)); + return TCL_OK; +} + +/* + $tv exists $itemid -- + * Test if the specified item id is present in the tree. + */ +static int TreeviewExistsCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + Tcl_HashEntry *entryPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "itemid"); + return TCL_ERROR; + } + + entryPtr = Tcl_FindHashEntry(&tv->tree.items, Tcl_GetString(objv[2])); + Tcl_SetObjResult(interp, Tcl_NewBooleanObj(entryPtr != 0)); + return TCL_OK; +} + +/* + $tv bbox $itemid ?$column? -- + * Return bounding box [x y width height] of specified item. + */ +static int TreeviewBBoxCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item = 0; + TreeColumn *column = 0; + Ttk_Box bbox; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "itemid ?column"); + return TCL_ERROR; + } + + item = FindItem(interp, tv, objv[2]); + if (!item) { + return TCL_ERROR; + } + if (objc >=4 && (column = FindColumn(interp,tv,objv[3])) == NULL) { + return TCL_ERROR; + } + + if (BoundingBox(tv, item, column, &bbox)) { + Tcl_SetObjResult(interp, Ttk_NewBoxObj(bbox)); + } + + return TCL_OK; +} + +/* + $tv identify $x $y -- (obsolescent) + * Implements the old, horrible, 2-argument form of [$tv identify]. + * + * Returns: one of + * heading #n + * cell itemid #n + * item itemid element + * row itemid + */ +static int TreeviewHorribleIdentify( + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Treeview *tv) +{ + const char *what = "nothing", *detail = NULL; + TreeItem *item = 0; + Tcl_Obj *result; + int dColumnNumber; + char dcolbuf[16]; + int x, y, x1; + + /* ASSERT: objc == 4 */ + + if ( Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK + ) { + return TCL_ERROR; + } + + dColumnNumber = IdentifyDisplayColumn(tv, x, &x1); + if (dColumnNumber < 0) { + goto done; + } + sprintf(dcolbuf, "#%d", dColumnNumber); + + if (Ttk_BoxContains(tv->tree.headingArea,x,y)) { + if (-HALO <= x1 - x && x1 - x <= HALO) { + what = "separator"; + } else { + what = "heading"; + } + detail = dcolbuf; + } else if (Ttk_BoxContains(tv->tree.treeArea,x,y)) { + item = IdentifyItem(tv, y); + if (item && dColumnNumber > 0) { + what = "cell"; + detail = dcolbuf; + } else if (item) { + Ttk_Layout layout = tv->tree.itemLayout; + Ttk_Box itemBox; + DisplayItem displayItem; + Ttk_Element element; + + BoundingBox(tv, item, NULL, &itemBox); + PrepareItem(tv, item, &displayItem); /*@@@ FIX: -text, etc*/ + Ttk_RebindSublayout(layout, &displayItem); + Ttk_PlaceLayout(layout, ItemState(tv,item), itemBox); + element = Ttk_IdentifyElement(layout, x, y); + + if (element) { + what = "item"; + detail = Ttk_ElementName(element); + } else { + what = "row"; + } + } + } + +done: + result = Tcl_NewListObj(0,0); + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(what, -1)); + if (item) + Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item)); + if (detail) + Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(detail, -1)); + + Tcl_SetObjResult(interp, result); + return TCL_OK; +} + +/* + $tv identify $component $x $y -- + * Identify the component at position x,y. + */ + +static int TreeviewIdentifyCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + static const char *submethodStrings[] = + { "region", "item", "column", "row", "element", NULL }; + enum { I_REGION, I_ITEM, I_COLUMN, I_ROW, I_ELEMENT }; + + Treeview *tv = recordPtr; + int submethod; + int x, y; + + TreeRegion region; + Ttk_Box bbox; + TreeItem *item; + TreeColumn *column = 0; + int colno, x1; + + if (objc == 4) { /* Old form */ + return TreeviewHorribleIdentify(interp, objc, objv, tv); + } else if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "command x y"); + return TCL_ERROR; + } + + if ( Tcl_GetIndexFromObj(interp, objv[2], + submethodStrings, "command", TCL_EXACT, &submethod) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK + ) { + return TCL_ERROR; + } + + region = IdentifyRegion(tv, x, y); + item = IdentifyItem(tv, y); + colno = IdentifyDisplayColumn(tv, x, &x1); + column = (colno >= 0) ? tv->tree.displayColumns[colno] : NULL; + + switch (submethod) + { + case I_REGION : + Tcl_SetObjResult(interp,Tcl_NewStringObj(regionStrings[region],-1)); + break; + + case I_ITEM : + case I_ROW : + if (item) { + Tcl_SetObjResult(interp, ItemID(tv, item)); + } + break; + + case I_COLUMN : + if (colno >= 0) { + char dcolbuf[16]; + sprintf(dcolbuf, "#%d", colno); + Tcl_SetObjResult(interp, Tcl_NewStringObj(dcolbuf, -1)); + } + break; + + case I_ELEMENT : + { + Ttk_Layout layout = 0; + DisplayItem displayItem; + Ttk_Element element; + + switch (region) { + case REGION_NOTHING: + layout = tv->core.layout; + return TCL_OK; /* @@@ NYI */ + case REGION_HEADING: + case REGION_SEPARATOR: + layout = tv->tree.headingLayout; + return TCL_OK; /* @@@ NYI */ + case REGION_TREE: + layout = tv->tree.itemLayout; + break; + case REGION_CELL: + layout = tv->tree.cellLayout; + break; + } + + if (!BoundingBox(tv, item, column, &bbox)) { + return TCL_OK; + } + + PrepareItem(tv, item, &displayItem); /*@@@ FIX: fill in -text,etc */ + Ttk_RebindSublayout(layout, &displayItem); + Ttk_PlaceLayout(layout, ItemState(tv,item), bbox); + element = Ttk_IdentifyElement(layout, x, y); + + if (element) { + const char *elementName = Ttk_ElementName(element); + Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1)); + } + break; + } + } + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- item and column configuration. + */ + +/* + $tv item $item ?options ....? + * Query or configure item options. + */ +static int TreeviewItemCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item ?option ?value??..."); + return TCL_ERROR; + } + if (!(item = FindItem(interp, tv, objv[2]))) { + return TCL_ERROR; + } + + if (objc == 3) { + return TtkEnumerateOptions(interp, item, ItemOptionSpecs, + tv->tree.itemOptionTable, tv->core.tkwin); + } else if (objc == 4) { + return TtkGetOptionValue(interp, item, objv[3], + tv->tree.itemOptionTable, tv->core.tkwin); + } else { + return ConfigureItem(interp, tv, item, objc-3, objv+3); + } +} + +/* + $tv column column ?options ....? + * Column data accessor + */ +static int TreeviewColumnCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeColumn *column; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "column -option value..."); + return TCL_ERROR; + } + if (!(column = FindColumn(interp, tv, objv[2]))) { + return TCL_ERROR; + } + + if (objc == 3) { + return TtkEnumerateOptions(interp, column, ColumnOptionSpecs, + tv->tree.columnOptionTable, tv->core.tkwin); + } else if (objc == 4) { + return TtkGetOptionValue(interp, column, objv[3], + tv->tree.columnOptionTable, tv->core.tkwin); + } else { + return ConfigureColumn(interp, tv, column, objc-3, objv+3); + } +} + +/* + $tv heading column ?options ....? + * Heading data accessor + */ +static int TreeviewHeadingCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + Tk_OptionTable optionTable = tv->tree.headingOptionTable; + Tk_Window tkwin = tv->core.tkwin; + TreeColumn *column; + + if (objc < 3) { + Tcl_WrongNumArgs(interp, 2, objv, "column -option value..."); + return TCL_ERROR; + } + if (!(column = FindColumn(interp, tv, objv[2]))) { + return TCL_ERROR; + } + + if (objc == 3) { + return TtkEnumerateOptions( + interp, column, HeadingOptionSpecs, optionTable, tkwin); + } else if (objc == 4) { + return TtkGetOptionValue( + interp, column, objv[3], optionTable, tkwin); + } else { + return ConfigureHeading(interp, tv, column, objc-3,objv+3); + } +} + +/* + $tv set $item ?$column ?value?? + * Query or configure cell values + */ +static int TreeviewSetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item; + TreeColumn *column; + int columnNumber; + + if (objc < 3 || objc > 5) { + Tcl_WrongNumArgs(interp, 2, objv, "item ?column ?value??"); + return TCL_ERROR; + } + if (!(item = FindItem(interp, tv, objv[2]))) + return TCL_ERROR; + + /* Make sure -values exists: + */ + if (!item->valuesObj) { + item->valuesObj = Tcl_NewListObj(0,0); + Tcl_IncrRefCount(item->valuesObj); + } + + if (objc == 3) { + /* Return dictionary: + */ + Tcl_Obj *result = Tcl_NewListObj(0,0); + Tcl_Obj *value; + for (columnNumber=0; columnNumber<tv->tree.nColumns; ++columnNumber) { + Tcl_ListObjIndex(interp, item->valuesObj, columnNumber, &value); + if (value) { + Tcl_ListObjAppendElement(interp, result, + tv->tree.columns[columnNumber].idObj); + Tcl_ListObjAppendElement(interp, result, value); + } + } + Tcl_SetObjResult(interp, result); + return TCL_OK; + } + + /* else -- get or set column + */ + if (!(column = FindColumn(interp, tv, objv[3]))) + return TCL_ERROR; + + if (column == &tv->tree.column0) { + /* @@@ Maybe set -text here instead? */ + Tcl_AppendResult(interp, "Display column #0 cannot be set", NULL); + return TCL_ERROR; + } + + /* Note: we don't do any error checking in the list operations, + * since item->valuesObj is guaranteed to be a list. + */ + columnNumber = column - tv->tree.columns; + + if (objc == 4) { /* get column */ + Tcl_Obj *result = 0; + Tcl_ListObjIndex(interp, item->valuesObj, columnNumber, &result); + if (!result) { + result = Tcl_NewStringObj("",0); + } + Tcl_SetObjResult(interp, result); + return TCL_OK; + } else { /* set column */ + int length; + + item->valuesObj = unshare(item->valuesObj); + + /* Make sure -values is fully populated: + */ + Tcl_ListObjLength(interp, item->valuesObj, &length); + while (length < tv->tree.nColumns) { + Tcl_Obj *empty = Tcl_NewStringObj("",0); + Tcl_ListObjAppendElement(interp, item->valuesObj, empty); + ++length; + } + + /* Set value: + */ + Tcl_ListObjReplace(interp,item->valuesObj,columnNumber,1,1,objv+4); + TtkRedisplayWidget(&tv->core); + return TCL_OK; + } +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- tree modification. + */ + +/* + $tv insert $parent $index ?-id id? ?-option value ...? + * Insert a new item. + */ +static int TreeviewInsertCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *parent, *sibling, *newItem; + Tcl_HashEntry *entryPtr; + int isNew; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv, "parent index ?-id id? -options..."); + return TCL_ERROR; + } + + /* Get parent node: + */ + if ((parent = FindItem(interp, tv, objv[2])) == NULL) { + return TCL_ERROR; + } + + /* Locate previous sibling based on $index: + */ + if (!strcmp(Tcl_GetString(objv[3]), "end")) { + sibling = EndPosition(tv, parent); + } else { + int index; + if (Tcl_GetIntFromObj(interp, objv[3], &index) != TCL_OK) + return TCL_ERROR; + sibling = InsertPosition(parent, index); + } + + /* Get node name: + * If -id supplied and does not already exist, use that; + * Otherwise autogenerate new one. + */ + objc -= 4; objv += 4; + if (objc >= 2 && !strcmp("-id", Tcl_GetString(objv[0]))) { + const char *itemName = Tcl_GetString(objv[1]); + entryPtr = Tcl_CreateHashEntry(&tv->tree.items, itemName, &isNew); + if (!isNew) { + Tcl_AppendResult(interp, "Item ",itemName," already exists",NULL); + return TCL_ERROR; + } + objc -= 2; objv += 2; + } else { + char idbuf[16]; + do { + ++tv->tree.serial; + sprintf(idbuf, "I%03X", tv->tree.serial); + entryPtr = Tcl_CreateHashEntry(&tv->tree.items, idbuf, &isNew); + } while (!isNew); + } + + /* Create and configure new item: + */ + newItem = NewItem(); + Tk_InitOptions( + interp, (ClientData)newItem, tv->tree.itemOptionTable, tv->core.tkwin); + newItem->tagset = Ttk_GetTagSetFromObj(NULL, tv->tree.tagTable, NULL); + if (ConfigureItem(interp, tv, newItem, objc, objv) != TCL_OK) { + Tcl_DeleteHashEntry(entryPtr); + FreeItem(newItem); + return TCL_ERROR; + } + + /* Store in hash table, link into tree: + */ + Tcl_SetHashValue(entryPtr, newItem); + newItem->entryPtr = entryPtr; + InsertItem(parent, sibling, newItem); + TtkRedisplayWidget(&tv->core); + + Tcl_SetObjResult(interp, ItemID(tv, newItem)); + return TCL_OK; +} + +/* + $tv detach $item -- + * Unlink $item from the tree. + */ +static int TreeviewDetachCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem **items; + int i; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item"); + return TCL_ERROR; + } + if (!(items = GetItemListFromObj(interp, tv, objv[2]))) { + return TCL_ERROR; + } + + /* Sanity-check */ + for (i = 0; items[i]; ++i) { + if (items[i] == tv->tree.root) { + Tcl_AppendResult(interp, "Cannot detach root item", NULL); + ckfree((ClientData)items); + return TCL_ERROR; + } + } + + for (i = 0; items[i]; ++i) { + DetachItem(items[i]); + } + + TtkRedisplayWidget(&tv->core); + ckfree((ClientData)items); + return TCL_OK; +} + +/* + $tv delete $items -- + * Delete each item in $items. + * + * Do this in two passes: + * First detach the item and all its descendants and remove them + * from the hash table. Free the items themselves in a second pass. + * + * It's done this way because an item may appear more than once + * in the list of items to delete (either directly or as a descendant + * of a previously deleted item.) + */ + +static int TreeviewDeleteCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem **items, *delq; + int i; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "items"); + return TCL_ERROR; + } + + if (!(items = GetItemListFromObj(interp, tv, objv[2]))) { + return TCL_ERROR; + } + + /* Sanity-check: + */ + for (i=0; items[i]; ++i) { + if (items[i] == tv->tree.root) { + ckfree((ClientData)items); + Tcl_AppendResult(interp, "Cannot delete root item", NULL); + return TCL_ERROR; + } + } + + /* Remove items from hash table. + */ + delq = 0; + for (i=0; items[i]; ++i) { + delq = DeleteItems(items[i], delq); + } + + /* Free items: + */ + while (delq) { + TreeItem *next = delq->next; + if (tv->tree.focus == delq) + tv->tree.focus = 0; + if (tv->tree.endPtr == delq) + tv->tree.endPtr = 0; + FreeItem(delq); + delq = next; + } + + ckfree((ClientData)items); + TtkRedisplayWidget(&tv->core); + return TCL_OK; +} + +/* + $tv move $item $parent $index + * Move $item to the specified $index in $parent's child list. + */ +static int TreeviewMoveCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item, *parent; + TreeItem *sibling; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "item parent index"); + return TCL_ERROR; + } + if ( (item = FindItem(interp, tv, objv[2])) == 0 + || (parent = FindItem(interp, tv, objv[3])) == 0) + { + return TCL_ERROR; + } + + /* Locate previous sibling based on $index: + */ + if (!strcmp(Tcl_GetString(objv[4]), "end")) { + sibling = EndPosition(tv, parent); + } else { + TreeItem *p; + int index; + + if (Tcl_GetIntFromObj(interp, objv[4], &index) != TCL_OK) { + return TCL_ERROR; + } + + sibling = 0; + for (p = parent->children; p != NULL && index > 0; p = p->next) { + if (p != item) { + --index; + } /* else -- moving node forward, count index+1 nodes */ + sibling = p; + } + } + + /* Check ancestry: + */ + if (!AncestryCheck(interp, tv, item, parent)) { + return TCL_ERROR; + } + + /* Moving an item after itself is a no-op: + */ + if (item == sibling) { + return TCL_OK; + } + + /* Move item: + */ + DetachItem(item); + InsertItem(parent, sibling, item); + + TtkRedisplayWidget(&tv->core); + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- scrolling + */ + +static int TreeviewXViewCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + return TtkScrollviewCommand(interp, objc, objv, tv->tree.xscrollHandle); +} + +static int TreeviewYViewCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + return TtkScrollviewCommand(interp, objc, objv, tv->tree.yscrollHandle); +} + +/* $tree see $item -- + * Ensure that $item is visible. + */ +static int TreeviewSeeCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + TreeItem *item, *parent; + int rowNumber; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "item"); + return TCL_ERROR; + } + if (!(item = FindItem(interp, tv, objv[2]))) { + return TCL_ERROR; + } + + /* Make sure all ancestors are open: + */ + for (parent = item->parent; parent; parent = parent->parent) { + if (!(parent->state & TTK_STATE_OPEN)) { + parent->openObj = unshare(parent->openObj); + Tcl_SetBooleanObj(parent->openObj, 1); + parent->state |= TTK_STATE_OPEN; + TtkRedisplayWidget(&tv->core); + } + } + + /* Make sure item is visible: + * @@@ DOUBLE-CHECK THIS: + */ + rowNumber = RowNumber(tv, item); + if (rowNumber < tv->tree.yscroll.first) { + TtkScrollTo(tv->tree.yscrollHandle, rowNumber); + } else if (rowNumber >= tv->tree.yscroll.last) { + TtkScrollTo(tv->tree.yscrollHandle, + tv->tree.yscroll.first + (1+rowNumber - tv->tree.yscroll.last)); + } + + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- interactive column resize + */ + +/* + $tree drag $column $newX -- + * Set right edge of display column $column to x position $X + */ +static int TreeviewDragCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + int left = tv->tree.treeArea.x - tv->tree.xscroll.first; + int i = FirstColumn(tv); + TreeColumn *column; + int newx; + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "column xposition"); + return TCL_ERROR; + } + + if ( (column = FindColumn(interp, tv, objv[2])) == 0 + || Tcl_GetIntFromObj(interp, objv[3], &newx) != TCL_OK) + { + return TCL_ERROR; + } + + for (;i < tv->tree.nDisplayColumns; ++i) { + TreeColumn *c = tv->tree.displayColumns[i]; + int right = left + c->width; + if (c == column) { + DragColumn(tv, i, newx - right); + /* ASSERT: SLACKINVARIANT */ + TtkRedisplayWidget(&tv->core); + return TCL_OK; + } + left = right; + } + + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, + "column ", Tcl_GetString(objv[2]), " is not displayed", + NULL); + return TCL_ERROR; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- focus and selection + */ + +/* + $tree focus ?item? + */ +static int TreeviewFocusCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + + if (objc == 2) { + if (tv->tree.focus) { + Tcl_SetObjResult(interp, ItemID(tv, tv->tree.focus)); + } + return TCL_OK; + } else if (objc == 3) { + TreeItem *newFocus = FindItem(interp, tv, objv[2]); + if (!newFocus) + return TCL_ERROR; + tv->tree.focus = newFocus; + TtkRedisplayWidget(&tv->core); + return TCL_OK; + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?newFocus?"); + return TCL_ERROR; + } +} + +/* + $tree selection ?add|remove|set|toggle $items? + */ +static int TreeviewSelectionCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + enum { + SELECTION_SET, SELECTION_ADD, SELECTION_REMOVE, SELECTION_TOGGLE + }; + static const char *selopStrings[] = { + "set", "add", "remove", "toggle", NULL + }; + + Treeview *tv = recordPtr; + int selop, i; + TreeItem *item, **items; + + if (objc == 2) { + Tcl_Obj *result = Tcl_NewListObj(0,0); + for (item = tv->tree.root->children; item; item=NextPreorder(item)) { + if (item->state & TTK_STATE_SELECTED) + Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item)); + } + Tcl_SetObjResult(interp, result); + return TCL_OK; + } + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 2, objv, "?add|remove|set|toggle items?"); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObj(interp, objv[2], selopStrings, + "selection operation", 0, &selop) != TCL_OK) + { + return TCL_ERROR; + } + + items = GetItemListFromObj(interp, tv, objv[3]); + if (!items) { + return TCL_ERROR; + } + + switch (selop) + { + case SELECTION_SET: + for (item=tv->tree.root; item; item=NextPreorder(item)) { + item->state &= ~TTK_STATE_SELECTED; + } + /*FALLTHRU*/ + case SELECTION_ADD: + for (i=0; items[i]; ++i) { + items[i]->state |= TTK_STATE_SELECTED; + } + break; + case SELECTION_REMOVE: + for (i=0; items[i]; ++i) { + items[i]->state &= ~TTK_STATE_SELECTED; + } + break; + case SELECTION_TOGGLE: + for (i=0; items[i]; ++i) { + items[i]->state ^= TTK_STATE_SELECTED; + } + break; + } + + ckfree((ClientData)items); + TtkSendVirtualEvent(tv->core.tkwin, "TreeviewSelect"); + TtkRedisplayWidget(&tv->core); + + return TCL_OK; +} + +/*------------------------------------------------------------------------ + * +++ Widget commands -- tags and bindings. + */ + +/* + $tv tag bind $tag ?$sequence ?$script?? + */ +static int TreeviewTagBindCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + Ttk_TagTable tagTable = tv->tree.tagTable; + Tk_BindingTable bindingTable = tv->tree.bindingTable; + Ttk_Tag tag; + + if (objc < 4 || objc > 6) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?sequence? ?script?"); + return TCL_ERROR; + } + + tag = Ttk_GetTagFromObj(tagTable, objv[3]); + if (!tag) { return TCL_ERROR; } + + if (objc == 4) { /* $tv tag bind $tag */ + Tk_GetAllBindings(interp, bindingTable, tag); + } else if (objc == 5) { /* $tv tag bind $tag $sequence */ + /* TODO: distinguish "no such binding" (OK) from "bad pattern" (ERROR) + */ + const char *script = Tk_GetBinding(interp, + bindingTable, tag, Tcl_GetString(objv[4])); + if (script != NULL) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(script,-1)); + } + } else if (objc == 6) { /* $tv tag bind $tag $sequence $script */ + const char *sequence = Tcl_GetString(objv[4]); + const char *script = Tcl_GetString(objv[5]); + + if (!*script) { /* Delete existing binding */ + Tk_DeleteBinding(interp, bindingTable, tag, sequence); + } else { + unsigned long mask = Tk_CreateBinding(interp, + bindingTable, tag, sequence, script, 0); + + /* Test mask to make sure event is supported: + */ + if (mask & (~TreeviewBindEventMask)) { + Tk_DeleteBinding(interp, bindingTable, tag, sequence); + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "unsupported event ", sequence, + "\nonly key, button, motion, and virtual events supported", + NULL); + return TCL_ERROR; + } + } + } + return TCL_OK; +} + +/* + $tv tag configure $tag ?-option ?value -option value...?? + */ +static int TreeviewTagConfigureCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + Ttk_TagTable tagTable = tv->tree.tagTable; + Ttk_Tag tag; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?-option ?value ...??"); + return TCL_ERROR; + } + + tag = Ttk_GetTagFromObj(tagTable, objv[3]); + + if (objc == 4) { + return Ttk_EnumerateTagOptions(interp, tagTable, tag); + } else if (objc == 5) { + Tcl_Obj *result = Ttk_TagOptionValue(interp, tagTable, tag, objv[4]); + if (result) { + Tcl_SetObjResult(interp, result); + return TCL_OK; + } /* else */ + return TCL_ERROR; + } + /* else */ + TtkRedisplayWidget(&tv->core); + return Ttk_ConfigureTag(interp, tagTable, tag, objc - 4, objv + 4); +} + +/* + $tv tag has $tag ?$item? + */ +static int TreeviewTagHasCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + + if (objc == 4) { /* Return list of all items with tag */ + Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]); + TreeItem *item = tv->tree.root; + Tcl_Obj *result = Tcl_NewListObj(0,0); + + while (item) { + if (Ttk_TagSetContains(item->tagset, tag)) { + Tcl_ListObjAppendElement(NULL, result, ItemID(tv, item)); + } + item = NextPreorder(item); + } + + Tcl_SetObjResult(interp, result); + return TCL_OK; + } else if (objc == 5) { /* Test if item has specified tag */ + Ttk_Tag tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]); + TreeItem *item = FindItem(interp, tv, objv[4]); + if (!item) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(Ttk_TagSetContains(item->tagset, tag))); + return TCL_OK; + } else { + Tcl_WrongNumArgs(interp, 3, objv, "tagName ?item?"); + return TCL_ERROR; + } +} + +/* + $tv tag names $tag + */ +static int TreeviewTagNamesCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 3, objv, ""); + return TCL_ERROR; + } + + return Ttk_EnumerateTags(interp, tv->tree.tagTable); +} + +/* + $tv tag add $tag $items + */ +static void AddTag(TreeItem *item, Ttk_Tag tag) +{ + if (Ttk_TagSetAdd(item->tagset, tag)) { + if (item->tagsObj) Tcl_DecrRefCount(item->tagsObj); + item->tagsObj = Ttk_NewTagSetObj(item->tagset); + Tcl_IncrRefCount(item->tagsObj); + } +} + +static int TreeviewTagAddCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + Ttk_Tag tag; + TreeItem **items; + int i; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName items"); + return TCL_ERROR; + } + + tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]); + items = GetItemListFromObj(interp, tv, objv[4]); + + if (!items) { + return TCL_ERROR; + } + + for (i=0; items[i]; ++i) { + AddTag(items[i], tag); + } + + return TCL_OK; +} + +/* + $tv tag remove $tag ?$items? + */ +static void RemoveTag(TreeItem *item, Ttk_Tag tag) +{ + if (Ttk_TagSetRemove(item->tagset, tag)) { + if (item->tagsObj) Tcl_DecrRefCount(item->tagsObj); + item->tagsObj = Ttk_NewTagSetObj(item->tagset); + Tcl_IncrRefCount(item->tagsObj); + } +} + +static int TreeviewTagRemoveCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + Ttk_Tag tag; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 3, objv, "tagName items"); + return TCL_ERROR; + } + + tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]); + + if (objc == 5) { + TreeItem **items = GetItemListFromObj(interp, tv, objv[4]); + int i; + + if (!items) { + return TCL_ERROR; + } + for (i=0; items[i]; ++i) { + RemoveTag(items[i], tag); + } + } else if (objc == 4) { + TreeItem *item = tv->tree.root; + while (item) { + RemoveTag(item, tag); + item=NextPreorder(item); + } + } + return TCL_OK; +} + +static const Ttk_Ensemble TreeviewTagCommands[] = { + { "add", TreeviewTagAddCommand,0 }, + { "bind", TreeviewTagBindCommand,0 }, + { "configure", TreeviewTagConfigureCommand,0 }, + { "has", TreeviewTagHasCommand,0 }, + { "names", TreeviewTagNamesCommand,0 }, + { "remove", TreeviewTagRemoveCommand,0 }, + { 0,0,0 } +}; + +/*------------------------------------------------------------------------ + * +++ Widget commands record. + */ +static const Ttk_Ensemble TreeviewCommands[] = { + { "bbox", TreeviewBBoxCommand,0 }, + { "children", TreeviewChildrenCommand,0 }, + { "cget", TtkWidgetCgetCommand,0 }, + { "column", TreeviewColumnCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "delete", TreeviewDeleteCommand,0 }, + { "detach", TreeviewDetachCommand,0 }, + { "drag", TreeviewDragCommand,0 }, + { "exists", TreeviewExistsCommand,0 }, + { "focus", TreeviewFocusCommand,0 }, + { "heading", TreeviewHeadingCommand,0 }, + { "identify", TreeviewIdentifyCommand,0 }, + { "index", TreeviewIndexCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, + { "insert", TreeviewInsertCommand,0 }, + { "item", TreeviewItemCommand,0 }, + { "move", TreeviewMoveCommand,0 }, + { "next", TreeviewNextCommand,0 }, + { "parent", TreeviewParentCommand,0 }, + { "prev", TreeviewPrevCommand,0 }, + { "see", TreeviewSeeCommand,0 }, + { "selection" , TreeviewSelectionCommand,0 }, + { "set", TreeviewSetCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "tag", 0,TreeviewTagCommands }, + { "xview", TreeviewXViewCommand,0 }, + { "yview", TreeviewYViewCommand,0 }, + { 0,0,0 } +}; + +/*------------------------------------------------------------------------ + * +++ Widget definition. + */ + +static WidgetSpec TreeviewWidgetSpec = { + "Treeview", /* className */ + sizeof(Treeview), /* recordSize */ + TreeviewOptionSpecs, /* optionSpecs */ + TreeviewCommands, /* subcommands */ + TreeviewInitialize, /* initializeProc */ + TreeviewCleanup, /* cleanupProc */ + TreeviewConfigure, /* configureProc */ + TtkNullPostConfigure, /* postConfigureProc */ + TreeviewGetLayout, /* getLayoutProc */ + TreeviewSize, /* sizeProc */ + TreeviewDoLayout, /* layoutProc */ + TreeviewDisplay /* displayProc */ +}; + +/*------------------------------------------------------------------------ + * +++ Layout specifications. + */ + +TTK_BEGIN_LAYOUT_TABLE(LayoutTable) + +TTK_LAYOUT("Treeview", + TTK_GROUP("Treeview.field", TTK_FILL_BOTH|TTK_BORDER, + TTK_GROUP("Treeview.padding", TTK_FILL_BOTH, + TTK_NODE("Treeview.treearea", TTK_FILL_BOTH)))) + +TTK_LAYOUT("Item", + TTK_GROUP("Treeitem.padding", TTK_FILL_BOTH, + TTK_NODE("Treeitem.indicator", TTK_PACK_LEFT) + TTK_NODE("Treeitem.image", TTK_PACK_LEFT) + TTK_GROUP("Treeitem.focus", TTK_PACK_LEFT, + TTK_NODE("Treeitem.text", TTK_PACK_LEFT)))) + +TTK_LAYOUT("Cell", + TTK_GROUP("Treedata.padding", TTK_FILL_BOTH, + TTK_NODE("Treeitem.text", TTK_FILL_BOTH))) + +TTK_LAYOUT("Heading", + TTK_NODE("Treeheading.cell", TTK_FILL_BOTH) + TTK_GROUP("Treeheading.border", TTK_FILL_BOTH, + TTK_GROUP("Treeheading.padding", TTK_FILL_BOTH, + TTK_NODE("Treeheading.image", TTK_PACK_RIGHT) + TTK_NODE("Treeheading.text", TTK_FILL_X)))) + +TTK_LAYOUT("Row", + TTK_NODE("Treeitem.row", TTK_FILL_BOTH)) + +TTK_END_LAYOUT_TABLE + +/*------------------------------------------------------------------------ + * +++ Tree indicator element. + */ + +typedef struct { + Tcl_Obj *colorObj; + Tcl_Obj *sizeObj; + Tcl_Obj *marginsObj; +} TreeitemIndicator; + +static Ttk_ElementOptionSpec TreeitemIndicatorOptions[] = { + { "-foreground", TK_OPTION_COLOR, + Tk_Offset(TreeitemIndicator,colorObj), DEFAULT_FOREGROUND }, + { "-indicatorsize", TK_OPTION_PIXELS, + Tk_Offset(TreeitemIndicator,sizeObj), "12" }, + { "-indicatormargins", TK_OPTION_STRING, + Tk_Offset(TreeitemIndicator,marginsObj), "2 2 4 2" }, + { NULL, 0, 0, NULL } +}; + +static void TreeitemIndicatorSize( + void *clientData, void *elementRecord, Tk_Window tkwin, + int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) +{ + TreeitemIndicator *indicator = elementRecord; + Ttk_Padding margins; + int size = 0; + + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginsObj, &margins); + Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size); + + *widthPtr = size + Ttk_PaddingWidth(margins); + *heightPtr = size + Ttk_PaddingHeight(margins); +} + +static void TreeitemIndicatorDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + TreeitemIndicator *indicator = elementRecord; + ArrowDirection direction = + (state & TTK_STATE_OPEN) ? ARROW_DOWN : ARROW_RIGHT; + Ttk_Padding margins; + XColor *borderColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); + XGCValues gcvalues; GC gc; unsigned mask; + + if (state & TTK_STATE_LEAF) /* don't draw anything */ + return; + + Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginsObj,&margins); + b = Ttk_PadBox(b, margins); + + gcvalues.foreground = borderColor->pixel; + gcvalues.line_width = 1; + mask = GCForeground | GCLineWidth; + gc = Tk_GetGC(tkwin, mask, &gcvalues); + + TtkDrawArrow(Tk_Display(tkwin), d, gc, b, direction); + + Tk_FreeGC(Tk_Display(tkwin), gc); +} + +static Ttk_ElementSpec TreeitemIndicatorElementSpec = { + TK_STYLE_VERSION_2, + sizeof(TreeitemIndicator), + TreeitemIndicatorOptions, + TreeitemIndicatorSize, + TreeitemIndicatorDraw +}; + +/*------------------------------------------------------------------------ + * +++ Row element. + */ + +typedef struct { + Tcl_Obj *backgroundObj; + Tcl_Obj *rowNumberObj; +} RowElement; + +static Ttk_ElementOptionSpec RowElementOptions[] = { + { "-background", TK_OPTION_COLOR, + Tk_Offset(RowElement,backgroundObj), DEFAULT_BACKGROUND }, + { "-rownumber", TK_OPTION_INT, + Tk_Offset(RowElement,rowNumberObj), "0" }, + { NULL, 0, 0, NULL } +}; + +static void RowElementDraw( + void *clientData, void *elementRecord, Tk_Window tkwin, + Drawable d, Ttk_Box b, Ttk_State state) +{ + RowElement *row = elementRecord; + XColor *color = Tk_GetColorFromObj(tkwin, row->backgroundObj); + GC gc = Tk_GCForColor(color, d); + XFillRectangle(Tk_Display(tkwin), d, gc, + b.x, b.y, b.width, b.height); +} + +static Ttk_ElementSpec RowElementSpec = { + TK_STYLE_VERSION_2, + sizeof(RowElement), + RowElementOptions, + TtkNullElementSize, + RowElementDraw +}; + +/*------------------------------------------------------------------------ + * +++ Initialisation. + */ + +MODULE_SCOPE +void TtkTreeview_Init(Tcl_Interp *interp) +{ + Ttk_Theme theme = Ttk_GetDefaultTheme(interp); + + RegisterWidget(interp, "ttk::treeview", &TreeviewWidgetSpec); + + Ttk_RegisterElement(interp, theme, "Treeitem.indicator", + &TreeitemIndicatorElementSpec, 0); + Ttk_RegisterElement(interp, theme, "Treeitem.row", &RowElementSpec, 0); + Ttk_RegisterElement(interp, theme, "Treeheading.cell", &RowElementSpec, 0); + Ttk_RegisterElement(interp, theme, "treearea", &ttkNullElementSpec, 0); + + Ttk_RegisterLayouts(theme, LayoutTable); +} + +/*EOF*/ diff --git a/generic/ttk/ttkWidget.c b/generic/ttk/ttkWidget.c new file mode 100644 index 0000000..d5e0484 --- /dev/null +++ b/generic/ttk/ttkWidget.c @@ -0,0 +1,789 @@ +/* + * Copyright (c) 2003, Joe English + * + * Core widget utilities. + */ + +#include <string.h> +#include <tk.h> +#include "ttkTheme.h" +#include "ttkWidget.h" + +#ifdef MAC_OSX_TK +#define TK_NO_DOUBLE_BUFFERING 1 +#endif + +/*------------------------------------------------------------------------ + * +++ Internal helper routines. + */ + +/* UpdateLayout -- + * Call the widget's get-layout hook to recompute corePtr->layout. + * Returns TCL_OK if successful, returns TCL_ERROR and leaves + * the layout unchanged otherwise. + */ +static int UpdateLayout(Tcl_Interp *interp, WidgetCore *corePtr) +{ + Ttk_Theme themePtr = Ttk_GetCurrentTheme(interp); + Ttk_Layout newLayout = + corePtr->widgetSpec->getLayoutProc(interp, themePtr,corePtr); + + if (newLayout) { + if (corePtr->layout) { + Ttk_FreeLayout(corePtr->layout); + } + corePtr->layout = newLayout; + return TCL_OK; + } + return TCL_ERROR; +} + +/* SizeChanged -- + * Call the widget's sizeProc to compute new requested size + * and pass it to the geometry manager. + */ +static void SizeChanged(WidgetCore *corePtr) +{ + int reqWidth = 1, reqHeight = 1; + + if (corePtr->widgetSpec->sizeProc(corePtr,&reqWidth,&reqHeight)) { + Tk_GeometryRequest(corePtr->tkwin, reqWidth, reqHeight); + } +} + +#ifndef TK_NO_DOUBLE_BUFFERING + +/* BeginDrawing -- + * Returns a Drawable for drawing the widget contents. + * This is normally an off-screen Pixmap, copied to + * the window by EndDrawing(). + */ +static Drawable BeginDrawing(Tk_Window tkwin) +{ + return Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), + Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); +} + +/* EndDrawing -- + * Copy the drawable contents to the screen and release resources. + */ +static void EndDrawing(Tk_Window tkwin, Drawable d) +{ + XGCValues gcValues; + GC gc; + + gcValues.function = GXcopy; + gcValues.graphics_exposures = False; + gc = Tk_GetGC(tkwin, GCFunction|GCGraphicsExposures, &gcValues); + + XCopyArea(Tk_Display(tkwin), d, Tk_WindowId(tkwin), gc, + 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), + 0, 0); + + Tk_FreePixmap(Tk_Display(tkwin), d); + Tk_FreeGC(Tk_Display(tkwin), gc); +} +#else +/* No double-buffering: draw directly into the window. */ +static Drawable BeginDrawing(Tk_Window tkwin) { return Tk_WindowId(tkwin); } +static void EndDrawing(Tk_Window tkwin, Drawable d) { } +#endif + +/* DrawWidget -- + * Redraw a widget. Called as an idle handler. + */ +static void DrawWidget(ClientData recordPtr) +{ + WidgetCore *corePtr = recordPtr; + + corePtr->flags &= ~REDISPLAY_PENDING; + if (Tk_IsMapped(corePtr->tkwin)) { + Drawable d = BeginDrawing(corePtr->tkwin); + corePtr->widgetSpec->layoutProc(recordPtr); + corePtr->widgetSpec->displayProc(recordPtr, d); + EndDrawing(corePtr->tkwin, d); + } +} + +/* TtkRedisplayWidget -- + * Schedule redisplay as an idle handler. + */ +void TtkRedisplayWidget(WidgetCore *corePtr) +{ + if (corePtr->flags & WIDGET_DESTROYED) { + return; + } + + if (!(corePtr->flags & REDISPLAY_PENDING)) { + Tcl_DoWhenIdle(DrawWidget, corePtr); + corePtr->flags |= REDISPLAY_PENDING; + } +} + +/* TtkResizeWidget -- + * Recompute widget size, schedule geometry propagation and redisplay. + */ +void TtkResizeWidget(WidgetCore *corePtr) +{ + if (corePtr->flags & WIDGET_DESTROYED) { + return; + } + + SizeChanged(corePtr); + TtkRedisplayWidget(corePtr); +} + +/* TtkWidgetChangeState -- + * Set / clear the specified bits in the 'state' flag, + */ +void TtkWidgetChangeState(WidgetCore *corePtr, + unsigned int setBits, unsigned int clearBits) +{ + Ttk_State oldState = corePtr->state; + corePtr->state = (oldState & ~clearBits) | setBits; + if (corePtr->state ^ oldState) { + TtkRedisplayWidget(corePtr); + } +} + +/* WidgetInstanceObjCmd -- + * Widget instance command implementation. + */ +static int +WidgetInstanceObjCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = clientData; + const Ttk_Ensemble *commands = corePtr->widgetSpec->commands; + int status; + + Tcl_Preserve(clientData); + status = Ttk_InvokeEnsemble(commands,1, clientData,interp,objc,objv); + Tcl_Release(clientData); + + return status; +} + +/*------------------------------------------------------------------------ + * +++ Widget destruction. + * + * A widget can be destroyed when the application explicitly + * destroys the window or one of its ancestors via [destroy] + * or Tk_DestroyWindow(); when the application deletes the widget + * instance command; when there is an error in the widget constructor; + * or when another application calls XDestroyWindow on the window ID. + * + * The window receives a <DestroyNotify> event in all cases, + * so we do the bulk of the cleanup there. See [#2207435] for + * further notes (esp. re: Tk_FreeConfigOptions). + * + * Widget code that reenters the interp should only do so + * when the widtget is Tcl_Preserve()d, and should check + * the WIDGET_DESTROYED flag bit upon return. + */ + +/* WidgetInstanceObjCmdDeleted -- + * Widget instance command deletion callback. + */ +static void +WidgetInstanceObjCmdDeleted(ClientData clientData) +{ + WidgetCore *corePtr = clientData; + corePtr->widgetCmd = NULL; + if (corePtr->tkwin != NULL) + Tk_DestroyWindow(corePtr->tkwin); +} + +/* FreeWidget -- + * Final cleanup for widget; called via Tcl_EventuallyFree(). + */ +static void +FreeWidget(char *memPtr) +{ + ckfree(memPtr); +} + +/* DestroyWidget -- + * Main widget destructor; called from <DestroyNotify> event handler. + */ +static void +DestroyWidget(WidgetCore *corePtr) +{ + corePtr->flags |= WIDGET_DESTROYED; + + corePtr->widgetSpec->cleanupProc(corePtr); + + Tk_FreeConfigOptions( + (ClientData)corePtr, corePtr->optionTable, corePtr->tkwin); + + if (corePtr->layout) { + Ttk_FreeLayout(corePtr->layout); + } + + if (corePtr->flags & REDISPLAY_PENDING) { + Tcl_CancelIdleCall(DrawWidget, corePtr); + } + + corePtr->tkwin = NULL; + if (corePtr->widgetCmd) { + Tcl_Command cmd = corePtr->widgetCmd; + corePtr->widgetCmd = 0; + /* NB: this can reenter the interpreter via a command traces */ + Tcl_DeleteCommandFromToken(corePtr->interp, cmd); + } + Tcl_EventuallyFree(corePtr, FreeWidget); +} + +/* + * CoreEventProc -- + * Event handler for basic events. + * Processes Expose, Configure, FocusIn/Out, and Destroy events. + * Also handles <<ThemeChanged>> virtual events. + * + * For Expose and Configure, simply schedule the widget for redisplay. + * For Destroy events, handle the cleanup process. + * + * For Focus events, set/clear the focus bit in the state field. + * It turns out this is impossible to do correctly in a binding script, + * because Tk filters out focus events with detail == NotifyInferior. + * + * For Deactivate/Activate pseudo-events, set/clear the background state + * flag. + */ + +static const unsigned CoreEventMask + = ExposureMask + | StructureNotifyMask + | FocusChangeMask + | VirtualEventMask + | ActivateMask + | EnterWindowMask + | LeaveWindowMask + ; + +static void CoreEventProc(ClientData clientData, XEvent *eventPtr) +{ + WidgetCore *corePtr = clientData; + + switch (eventPtr->type) + { + case ConfigureNotify : + TtkRedisplayWidget(corePtr); + break; + case Expose : + if (eventPtr->xexpose.count == 0) { + TtkRedisplayWidget(corePtr); + } + break; + case DestroyNotify : + Tk_DeleteEventHandler( + corePtr->tkwin, CoreEventMask,CoreEventProc,clientData); + DestroyWidget(corePtr); + break; + case FocusIn: + case FocusOut: + /* Don't process "virtual crossing" events */ + if ( eventPtr->xfocus.detail == NotifyInferior + || eventPtr->xfocus.detail == NotifyAncestor + || eventPtr->xfocus.detail == NotifyNonlinear) + { + if (eventPtr->type == FocusIn) + corePtr->state |= TTK_STATE_FOCUS; + else + corePtr->state &= ~TTK_STATE_FOCUS; + TtkRedisplayWidget(corePtr); + } + break; + case ActivateNotify: + corePtr->state &= ~TTK_STATE_BACKGROUND; + TtkRedisplayWidget(corePtr); + break; + case DeactivateNotify: + corePtr->state |= TTK_STATE_BACKGROUND; + TtkRedisplayWidget(corePtr); + break; + case LeaveNotify: + corePtr->state &= ~TTK_STATE_HOVER; + TtkRedisplayWidget(corePtr); + break; + case EnterNotify: + corePtr->state |= TTK_STATE_HOVER; + TtkRedisplayWidget(corePtr); + break; + case VirtualEvent: + if (!strcmp("ThemeChanged", ((XVirtualEvent *)(eventPtr))->name)) { + (void)UpdateLayout(corePtr->interp, corePtr); + SizeChanged(corePtr); + TtkRedisplayWidget(corePtr); + } + default: + /* can't happen... */ + break; + } +} + +/* + * WidgetWorldChanged -- + * Default Tk_ClassWorldChangedProc() for widgets. + * Invoked whenever fonts or other system resources are changed; + * recomputes geometry. + */ +static void WidgetWorldChanged(ClientData clientData) +{ + WidgetCore *corePtr = clientData; + SizeChanged(corePtr); + TtkRedisplayWidget(corePtr); +} + +static Tk_ClassProcs widgetClassProcs = { + sizeof(Tk_ClassProcs), /* size */ + WidgetWorldChanged, /* worldChangedProc */ + NULL, /* createProc */ + NULL /* modalProc */ +}; + +/* + * TtkWidgetConstructorObjCmd -- + * General-purpose widget constructor command implementation. + * ClientData is a WidgetSpec *. + */ +int TtkWidgetConstructorObjCmd( + ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetSpec *widgetSpec = clientData; + const char *className = widgetSpec->className; + Tk_OptionTable optionTable = + Tk_CreateOptionTable(interp, widgetSpec->optionSpecs); + Tk_Window tkwin; + void *recordPtr; + WidgetCore *corePtr; + Tk_SavedOptions savedOptions; + int i; + + if (objc < 2 || objc % 2 == 1) { + Tcl_WrongNumArgs(interp, 1, objv, "pathName ?-option value ...?"); + return TCL_ERROR; + } + + /* Check if a -class option has been specified. + * We have to do this before the InitOptions() call, + * since InitOptions() is affected by the widget class. + */ + for (i = 2; i < objc; i += 2) { + if (!strcmp(Tcl_GetString(objv[i]), "-class")) { + className = Tcl_GetString(objv[i+1]); + break; + } + } + + tkwin = Tk_CreateWindowFromPath( + interp, Tk_MainWindow(interp), Tcl_GetString(objv[1]), NULL); + if (tkwin == NULL) + return TCL_ERROR; + + /* + * Allocate and initialize the widget record. + */ + recordPtr = ckalloc(widgetSpec->recordSize); + memset(recordPtr, 0, widgetSpec->recordSize); + corePtr = recordPtr; + + corePtr->tkwin = tkwin; + corePtr->interp = interp; + corePtr->widgetSpec = widgetSpec; + corePtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin), + WidgetInstanceObjCmd, recordPtr, WidgetInstanceObjCmdDeleted); + corePtr->optionTable = optionTable; + corePtr->layout = NULL; + corePtr->flags = 0; + corePtr->state = 0; + + Tk_SetClass(tkwin, className); + Tk_SetClassProcs(tkwin, &widgetClassProcs, recordPtr); + Tk_SetWindowBackgroundPixmap(tkwin, ParentRelative); + + widgetSpec->initializeProc(interp, recordPtr); + + Tk_CreateEventHandler(tkwin, CoreEventMask, CoreEventProc, recordPtr); + + /* + * Initial configuration. + */ + + Tcl_Preserve(corePtr); + if (Tk_InitOptions(interp, recordPtr, optionTable, tkwin) != TCL_OK) { + goto error; + } + + if (Tk_SetOptions(interp, recordPtr, optionTable, + objc - 2, objv + 2, tkwin, &savedOptions, NULL) != TCL_OK) { + Tk_RestoreSavedOptions(&savedOptions); + goto error; + } else { + Tk_FreeSavedOptions(&savedOptions); + } + if (widgetSpec->configureProc(interp, recordPtr, ~0) != TCL_OK) + goto error; + if (widgetSpec->postConfigureProc(interp, recordPtr, ~0) != TCL_OK) + goto error; + + if (WidgetDestroyed(corePtr)) + goto error; + + Tcl_Release(corePtr); + + SizeChanged(corePtr); + Tk_MakeWindowExist(tkwin); + + Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), -1)); + return TCL_OK; + +error: + if (WidgetDestroyed(corePtr)) { + Tcl_SetResult(interp, "Widget has been destroyed", TCL_STATIC); + } else { + Tk_DestroyWindow(tkwin); + } + Tcl_Release(corePtr); + return TCL_ERROR; +} + +/*------------------------------------------------------------------------ + * +++ Default implementations for widget hook procedures. + */ + +/* TtkWidgetGetLayout -- + * Default getLayoutProc. + * Looks up the layout based on the -style resource (if specified), + * otherwise use the widget class. + */ +Ttk_Layout TtkWidgetGetLayout( + Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr) +{ + WidgetCore *corePtr = recordPtr; + const char *styleName = 0; + + if (corePtr->styleObj) + styleName = Tcl_GetString(corePtr->styleObj); + + if (!styleName || *styleName == '\0') + styleName = corePtr->widgetSpec->className; + + return Ttk_CreateLayout(interp, themePtr, styleName, + recordPtr, corePtr->optionTable, corePtr->tkwin); +} + +/* + * TtkWidgetGetOrientedLayout -- + * Helper routine. Same as TtkWidgetGetLayout, but prefixes + * "Horizontal." or "Vertical." to the style name, depending + * on the value of the 'orient' option. + */ +Ttk_Layout TtkWidgetGetOrientedLayout( + Tcl_Interp *interp, Ttk_Theme themePtr, void *recordPtr, Tcl_Obj *orientObj) +{ + WidgetCore *corePtr = recordPtr; + const char *baseStyleName = 0; + Tcl_DString styleName; + int orient = TTK_ORIENT_HORIZONTAL; + Ttk_Layout layout; + + Tcl_DStringInit(&styleName); + + /* Prefix: + */ + Ttk_GetOrientFromObj(NULL, orientObj, &orient); + if (orient == TTK_ORIENT_HORIZONTAL) + Tcl_DStringAppend(&styleName, "Horizontal.", -1); + else + Tcl_DStringAppend(&styleName, "Vertical.", -1); + + /* Add base style name: + */ + if (corePtr->styleObj) + baseStyleName = Tcl_GetString(corePtr->styleObj); + if (!baseStyleName || *baseStyleName == '\0') + baseStyleName = corePtr->widgetSpec->className; + + Tcl_DStringAppend(&styleName, baseStyleName, -1); + + /* Create layout: + */ + layout= Ttk_CreateLayout(interp, themePtr, Tcl_DStringValue(&styleName), + recordPtr, corePtr->optionTable, corePtr->tkwin); + + Tcl_DStringFree(&styleName); + + return layout; +} + +/* TtkNullInitialize -- + * Default widget initializeProc (no-op) + */ +void TtkNullInitialize(Tcl_Interp *interp, void *recordPtr) +{ +} + +/* TtkNullPostConfigure -- + * Default widget postConfigureProc (no-op) + */ +int TtkNullPostConfigure(Tcl_Interp *interp, void *clientData, int mask) +{ + return TCL_OK; +} + +/* TtkCoreConfigure -- + * Default widget configureProc. + * Handles -style option. + */ +int TtkCoreConfigure(Tcl_Interp *interp, void *clientData, int mask) +{ + WidgetCore *corePtr = clientData; + int status = TCL_OK; + + if (mask & STYLE_CHANGED) { + status = UpdateLayout(interp, corePtr); + } + + return status; +} + +/* TtkNullCleanup -- + * Default widget cleanupProc (no-op) + */ +void TtkNullCleanup(void *recordPtr) +{ + return; +} + +/* TtkWidgetDoLayout -- + * Default widget layoutProc. + */ +void TtkWidgetDoLayout(void *clientData) +{ + WidgetCore *corePtr = clientData; + Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin)); +} + +/* TtkWidgetDisplay -- + * Default widget displayProc. + */ +void TtkWidgetDisplay(void *recordPtr, Drawable d) +{ + WidgetCore *corePtr = recordPtr; + Ttk_DrawLayout(corePtr->layout, corePtr->state, d); +} + +/* TtkWidgetSize -- + * Default widget sizeProc() + */ +int TtkWidgetSize(void *recordPtr, int *widthPtr, int *heightPtr) +{ + WidgetCore *corePtr = recordPtr; + Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr); + return 1; +} + +/*------------------------------------------------------------------------ + * +++ Default implementations for widget subcommands. + */ + +/* $w cget -option + */ +int TtkWidgetCgetCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = recordPtr; + Tcl_Obj *result; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "option"); + return TCL_ERROR; + } + result = Tk_GetOptionValue(interp, recordPtr, + corePtr->optionTable, objv[2], corePtr->tkwin); + if (result == NULL) + return TCL_ERROR; + Tcl_SetObjResult(interp, result); + return TCL_OK; +} + +/* $w configure ?-option ?value ....?? + */ +int TtkWidgetConfigureCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = recordPtr; + Tcl_Obj *result; + + if (objc == 2) { + result = Tk_GetOptionInfo(interp, recordPtr, + corePtr->optionTable, NULL, corePtr->tkwin); + } else if (objc == 3) { + result = Tk_GetOptionInfo(interp, recordPtr, + corePtr->optionTable, objv[2], corePtr->tkwin); + } else { + Tk_SavedOptions savedOptions; + int status; + int mask = 0; + + status = Tk_SetOptions(interp, recordPtr, + corePtr->optionTable, objc - 2, objv + 2, + corePtr->tkwin, &savedOptions, &mask); + if (status != TCL_OK) + return status; + + if (mask & READONLY_OPTION) { + Tcl_SetResult(interp, + "Attempt to change read-only option", TCL_STATIC); + Tk_RestoreSavedOptions(&savedOptions); + return TCL_ERROR; + } + + status = corePtr->widgetSpec->configureProc(interp, recordPtr, mask); + if (status != TCL_OK) { + Tk_RestoreSavedOptions(&savedOptions); + return status; + } + Tk_FreeSavedOptions(&savedOptions); + + status = corePtr->widgetSpec->postConfigureProc(interp,recordPtr,mask); + if (WidgetDestroyed(corePtr)) { + Tcl_SetResult(interp, "Widget has been destroyed", TCL_STATIC); + status = TCL_ERROR; + } + if (status != TCL_OK) { + return status; + } + + if (mask & (STYLE_CHANGED | GEOMETRY_CHANGED)) { + SizeChanged(corePtr); + } + + TtkRedisplayWidget(corePtr); + result = Tcl_NewObj(); + } + + if (result == 0) { + return TCL_ERROR; + } + Tcl_SetObjResult(interp, result); + return TCL_OK; +} + +/* $w state ? $stateSpec ? + * + * If $stateSpec is specified, modify the widget state accordingly, + * return a new stateSpec representing the changed bits. + * + * Otherwise, return a statespec matching all the currently-set bits. + */ + +int TtkWidgetStateCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = recordPtr; + Ttk_StateSpec spec; + int status; + Ttk_State oldState, changed; + + if (objc == 2) { + Tcl_SetObjResult(interp, + Ttk_NewStateSpecObj(corePtr->state, 0ul)); + return TCL_OK; + } + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "state-spec"); + return TCL_ERROR; + } + status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec); + if (status != TCL_OK) + return status; + + oldState = corePtr->state; + corePtr->state = Ttk_ModifyState(corePtr->state, &spec); + changed = corePtr->state ^ oldState; + + TtkRedisplayWidget(corePtr); + + Tcl_SetObjResult(interp, + Ttk_NewStateSpecObj(oldState & changed, ~oldState & changed)); + return status; +} + +/* $w instate $stateSpec ?$script? + * + * Tests if widget state matches $stateSpec. + * If $script is specified, execute script if state matches. + * Otherwise, return true/false + */ + +int TtkWidgetInstateCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = recordPtr; + Ttk_State state = corePtr->state; + Ttk_StateSpec spec; + int status = TCL_OK; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "state-spec ?script?"); + return TCL_ERROR; + } + status = Ttk_GetStateSpecFromObj(interp, objv[2], &spec); + if (status != TCL_OK) + return status; + + if (objc == 3) { + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(Ttk_StateMatches(state,&spec))); + } else if (objc == 4) { + if (Ttk_StateMatches(state,&spec)) { + status = Tcl_EvalObjEx(interp, objv[3], 0); + } + } + return status; +} + +/* $w identify $x $y + * $w identify element $x $y + * Returns: name of element at $x, $y + */ +int TtkWidgetIdentifyCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = recordPtr; + Ttk_Element element; + static const char *whatTable[] = { "element", NULL }; + int x, y, what; + + if (objc < 4 || objc > 5) { + Tcl_WrongNumArgs(interp, 2, objv, "?what? x y"); + return TCL_ERROR; + } + if (objc == 5) { + /* $w identify element $x $y */ + if (Tcl_GetIndexFromObj(interp,objv[2],whatTable,"option",0,&what) + != TCL_OK) + { + return TCL_ERROR; + } + } + + if ( Tcl_GetIntFromObj(interp, objv[objc-2], &x) != TCL_OK + || Tcl_GetIntFromObj(interp, objv[objc-1], &y) != TCL_OK + ) { + return TCL_ERROR; + } + + element = Ttk_IdentifyElement(corePtr->layout, x, y); + if (element) { + const char *elementName = Ttk_ElementName(element); + Tcl_SetObjResult(interp,Tcl_NewStringObj(elementName,-1)); + } + + return TCL_OK; +} + +/*EOF*/ diff --git a/generic/ttk/ttkWidget.h b/generic/ttk/ttkWidget.h new file mode 100644 index 0000000..9e9ab69 --- /dev/null +++ b/generic/ttk/ttkWidget.h @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2003, Joe English + * Helper routines for widget implementations. + */ + +#ifndef _TTKWIDGET +#define _TTKWIDGET + +/* + * State flags for 'flags' field. + */ +#define WIDGET_DESTROYED 0x0001 +#define REDISPLAY_PENDING 0x0002 /* scheduled call to RedisplayWidget */ +#define CURSOR_ON 0x0020 /* See TtkBlinkCursor() */ +#define WIDGET_USER_FLAG 0x0100 /* 0x0100 - 0x8000 for user flags */ + +/* + * Bit fields for OptionSpec 'mask' field: + */ +#define READONLY_OPTION 0x1 +#define STYLE_CHANGED 0x2 +#define GEOMETRY_CHANGED 0x4 + +/* + * Core widget elements + */ +typedef struct WidgetSpec_ WidgetSpec; /* Forward */ + +typedef struct +{ + Tk_Window tkwin; /* Window associated with widget */ + Tcl_Interp *interp; /* Interpreter associated with widget. */ + WidgetSpec *widgetSpec; /* Widget class hooks */ + Tcl_Command widgetCmd; /* Token for widget command. */ + Tk_OptionTable optionTable; /* Option table */ + Ttk_Layout layout; /* Widget layout */ + + /* + * Storage for resources: + */ + Tcl_Obj *takeFocusPtr; /* Storage for -takefocus option */ + Tcl_Obj *cursorObj; /* Storage for -cursor option */ + Tcl_Obj *styleObj; /* Name of currently-applied style */ + Tcl_Obj *classObj; /* Class name (readonly option) */ + + Ttk_State state; /* Current widget state */ + unsigned int flags; /* internal flags, see above */ + +} WidgetCore; + +/* + * Widget specifications: + */ +struct WidgetSpec_ +{ + const char *className; /* Widget class name */ + size_t recordSize; /* #bytes in widget record */ + const Tk_OptionSpec *optionSpecs; /* Option specifications */ + const Ttk_Ensemble *commands; /* Widget instance subcommands */ + + /* + * Hooks: + */ + void (*initializeProc)(Tcl_Interp *, void *recordPtr); + void (*cleanupProc)(void *recordPtr); + int (*configureProc)(Tcl_Interp *, void *recordPtr, int flags); + int (*postConfigureProc)(Tcl_Interp *, void *recordPtr, int flags); + Ttk_Layout (*getLayoutProc)(Tcl_Interp *,Ttk_Theme, void *recordPtr); + int (*sizeProc)(void *recordPtr, int *widthPtr, int *heightPtr); + void (*layoutProc)(void *recordPtr); + void (*displayProc)(void *recordPtr, Drawable d); +}; + +/* + * Common factors for widget implementations: + */ +MODULE_SCOPE void TtkNullInitialize(Tcl_Interp *, void *); +MODULE_SCOPE int TtkNullPostConfigure(Tcl_Interp *, void *, int); +MODULE_SCOPE void TtkNullCleanup(void *recordPtr); +MODULE_SCOPE Ttk_Layout TtkWidgetGetLayout( + Tcl_Interp *, Ttk_Theme, void *recordPtr); +MODULE_SCOPE Ttk_Layout TtkWidgetGetOrientedLayout( + Tcl_Interp *, Ttk_Theme, void *recordPtr, Tcl_Obj *orientObj); +MODULE_SCOPE int TtkWidgetSize(void *recordPtr, int *w, int *h); +MODULE_SCOPE void TtkWidgetDoLayout(void *recordPtr); +MODULE_SCOPE void TtkWidgetDisplay(void *recordPtr, Drawable); + +MODULE_SCOPE int TtkCoreConfigure(Tcl_Interp*, void *, int mask); + +/* Common widget commands: + */ +MODULE_SCOPE int TtkWidgetConfigureCommand( + void *,Tcl_Interp *, int, Tcl_Obj*const[]); +MODULE_SCOPE int TtkWidgetCgetCommand( + void *,Tcl_Interp *, int, Tcl_Obj*const[]); +MODULE_SCOPE int TtkWidgetInstateCommand( + void *,Tcl_Interp *, int, Tcl_Obj*const[]); +MODULE_SCOPE int TtkWidgetStateCommand( + void *,Tcl_Interp *, int, Tcl_Obj*const[]); +MODULE_SCOPE int TtkWidgetIdentifyCommand( + void *,Tcl_Interp *, int, Tcl_Obj*const[]); + +/* Widget constructor: + */ +MODULE_SCOPE int TtkWidgetConstructorObjCmd( + ClientData, Tcl_Interp*, int, Tcl_Obj*const[]); + +#define RegisterWidget(interp, name, specPtr) \ + Tcl_CreateObjCommand(interp, name, \ + TtkWidgetConstructorObjCmd, (ClientData)specPtr,NULL) + +/* WIDGET_TAKEFOCUS_TRUE -- + * WIDGET_TAKEFOCUS_FALSE -- + * Add one or the other of these to each OptionSpecs table + * to indicate whether the widget should take focus + * during keyboard traversal. + */ +#define WIDGET_TAKEFOCUS_TRUE \ + {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \ + "ttk::takefocus", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 } +#define WIDGET_TAKEFOCUS_FALSE \ + {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", \ + "", Tk_Offset(WidgetCore, takeFocusPtr), -1, 0,0,0 } + +/* WIDGET_INHERIT_OPTIONS(baseOptionSpecs) -- + * Add this at the end of an OptionSpecs table to inherit + * the options from 'baseOptionSpecs'. + */ +#define WIDGET_INHERIT_OPTIONS(baseOptionSpecs) \ + {TK_OPTION_END, 0,0,0, NULL, -1,-1, 0, (ClientData)baseOptionSpecs, 0} + +/* All widgets should inherit from ttkCoreOptionSpecs[]. + */ +MODULE_SCOPE Tk_OptionSpec ttkCoreOptionSpecs[]; + +/* + * Useful routines for use inside widget implementations: + */ +/* extern int WidgetDestroyed(WidgetCore *); */ +#define WidgetDestroyed(corePtr) ((corePtr)->flags & WIDGET_DESTROYED) + +MODULE_SCOPE void TtkWidgetChangeState(WidgetCore *, + unsigned int setBits, unsigned int clearBits); + +MODULE_SCOPE void TtkRedisplayWidget(WidgetCore *); +MODULE_SCOPE void TtkResizeWidget(WidgetCore *); + +MODULE_SCOPE void TtkTrackElementState(WidgetCore *); +MODULE_SCOPE void TtkBlinkCursor(WidgetCore *); + +/* + * -state option values (compatibility) + */ +MODULE_SCOPE void TtkCheckStateOption(WidgetCore *, Tcl_Obj *); + +/* + * Variable traces: + */ +typedef void (*Ttk_TraceProc)(void *recordPtr, const char *value); +typedef struct TtkTraceHandle_ Ttk_TraceHandle; + +MODULE_SCOPE Ttk_TraceHandle *Ttk_TraceVariable( + Tcl_Interp*, Tcl_Obj *varnameObj, Ttk_TraceProc callback, void *clientData); +MODULE_SCOPE void Ttk_UntraceVariable(Ttk_TraceHandle *); +MODULE_SCOPE int Ttk_FireTrace(Ttk_TraceHandle *); + +/* + * Virtual events: + */ +MODULE_SCOPE void TtkSendVirtualEvent(Tk_Window tgtWin, const char *eventName); + +/* + * Helper routines for data accessor commands: + */ +MODULE_SCOPE int TtkEnumerateOptions( + Tcl_Interp *, void *, const Tk_OptionSpec *, Tk_OptionTable, Tk_Window); +MODULE_SCOPE int TtkGetOptionValue( + Tcl_Interp *, void *, Tcl_Obj *optName, Tk_OptionTable, Tk_Window); + +/* + * Helper routines for scrolling widgets (see scroll.c). + */ +typedef struct { + int first; /* First visible item */ + int last; /* Last visible item */ + int total; /* Total #items */ + char *scrollCmd; /* Widget option */ +} Scrollable; + +typedef struct ScrollHandleRec *ScrollHandle; + +MODULE_SCOPE ScrollHandle TtkCreateScrollHandle(WidgetCore *, Scrollable *); +MODULE_SCOPE void TtkFreeScrollHandle(ScrollHandle); + +MODULE_SCOPE int TtkScrollviewCommand( + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], ScrollHandle); + +MODULE_SCOPE void TtkScrollTo(ScrollHandle, int newFirst); +MODULE_SCOPE void TtkScrolled(ScrollHandle, int first, int last, int total); +MODULE_SCOPE void TtkScrollbarUpdateRequired(ScrollHandle); + +/* + * Tag sets (work in progress, half-baked) + */ + +typedef struct TtkTag *Ttk_Tag; +typedef struct TtkTagTable *Ttk_TagTable; +typedef struct TtkTagSet { /* TODO: make opaque */ + Ttk_Tag *tags; + int nTags; +} *Ttk_TagSet; + +MODULE_SCOPE Ttk_TagTable Ttk_CreateTagTable( + Tcl_Interp *, Tk_Window tkwin, Tk_OptionSpec[], int recordSize); +MODULE_SCOPE void Ttk_DeleteTagTable(Ttk_TagTable); + +MODULE_SCOPE Ttk_Tag Ttk_GetTag(Ttk_TagTable, const char *tagName); +MODULE_SCOPE Ttk_Tag Ttk_GetTagFromObj(Ttk_TagTable, Tcl_Obj *); + +MODULE_SCOPE Tcl_Obj *Ttk_TagOptionValue( + Tcl_Interp *, Ttk_TagTable, Ttk_Tag, Tcl_Obj *optionName); + +MODULE_SCOPE int Ttk_EnumerateTagOptions( + Tcl_Interp *, Ttk_TagTable, Ttk_Tag); + +MODULE_SCOPE int Ttk_EnumerateTags(Tcl_Interp *, Ttk_TagTable); + +MODULE_SCOPE int Ttk_ConfigureTag( + Tcl_Interp *interp, Ttk_TagTable tagTable, Ttk_Tag tag, + int objc, Tcl_Obj *const objv[]); + +MODULE_SCOPE Ttk_TagSet Ttk_GetTagSetFromObj( + Tcl_Interp *interp, Ttk_TagTable, Tcl_Obj *objPtr); +MODULE_SCOPE Tcl_Obj *Ttk_NewTagSetObj(Ttk_TagSet); + +MODULE_SCOPE void Ttk_FreeTagSet(Ttk_TagSet); + +MODULE_SCOPE int Ttk_TagSetContains(Ttk_TagSet, Ttk_Tag tag); +MODULE_SCOPE int Ttk_TagSetAdd(Ttk_TagSet, Ttk_Tag tag); +MODULE_SCOPE int Ttk_TagSetRemove(Ttk_TagSet, Ttk_Tag tag); + +MODULE_SCOPE void Ttk_TagSetValues(Ttk_TagTable, Ttk_TagSet, void *record); +MODULE_SCOPE void Ttk_TagSetApplyStyle(Ttk_TagTable,Ttk_Style,Ttk_State,void*); + +/* + * String tables for widget resource specifications: + */ + +MODULE_SCOPE const char *ttkOrientStrings[]; +MODULE_SCOPE const char *ttkCompoundStrings[]; +MODULE_SCOPE const char *ttkDefaultStrings[]; + +/* + * ... other option types... + */ +MODULE_SCOPE int TtkGetLabelAnchorFromObj( + Tcl_Interp*, Tcl_Obj*, Ttk_PositionSpec *); + +/* + * Platform-specific initialization. + */ + +#if defined(__WIN32__) +#define Ttk_PlatformInit Ttk_WinPlatformInit +MODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *); +#elif defined(MAC_OSX_TK) +#define Ttk_PlatformInit Ttk_MacOSXPlatformInit +MODULE_SCOPE int Ttk_PlatformInit(Tcl_Interp *); +#else +#define Ttk_PlatformInit(interp) /* TTK_X11PlatformInit() */ +#endif + +#endif /* _TTKWIDGET */ |