summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorstanton <stanton@noemail.net>1998-09-29 00:25:04 (GMT)
committerstanton <stanton@noemail.net>1998-09-29 00:25:04 (GMT)
commitf110d4e2a4b45b23f037e22b18041093a18a028f (patch)
tree99c199f65b7d32755dc8f0ee5cc773bd922a74a6 /generic
parent44fe62a9cda522475be53f14654970aaa3d4a648 (diff)
downloadtk-f110d4e2a4b45b23f037e22b18041093a18a028f.zip
tk-f110d4e2a4b45b23f037e22b18041093a18a028f.tar.gz
tk-f110d4e2a4b45b23f037e22b18041093a18a028f.tar.bz2
initial tk8.1a2 version
FossilOrigin-Name: 644396f2dabc649ad5784768cfe962017d991df1
Diffstat (limited to 'generic')
-rw-r--r--generic/prolog.ps284
-rw-r--r--generic/tk.h477
-rw-r--r--generic/tk3d.c621
-rw-r--r--generic/tk3d.h33
-rw-r--r--generic/tkArgv.c18
-rw-r--r--generic/tkBind.c1183
-rw-r--r--generic/tkBitmap.c612
-rw-r--r--generic/tkButton.c1495
-rw-r--r--generic/tkButton.h243
-rw-r--r--generic/tkCanvArc.c19
-rw-r--r--generic/tkCanvBmap.c22
-rw-r--r--generic/tkCanvImg.c16
-rw-r--r--generic/tkCanvLine.c16
-rw-r--r--generic/tkCanvPoly.c13
-rw-r--r--generic/tkCanvPs.c456
-rw-r--r--generic/tkCanvText.c399
-rw-r--r--generic/tkCanvUtil.c4
-rw-r--r--generic/tkCanvWind.c14
-rw-r--r--generic/tkCanvas.c87
-rw-r--r--generic/tkClipboard.c19
-rw-r--r--generic/tkCmds.c246
-rw-r--r--generic/tkColor.c514
-rw-r--r--generic/tkColor.h29
-rw-r--r--generic/tkConfig.c2411
-rw-r--r--generic/tkConsole.c9
-rw-r--r--generic/tkCursor.c574
-rw-r--r--generic/tkEntry.c564
-rw-r--r--generic/tkFileFilter.c3
-rw-r--r--generic/tkFocus.c147
-rw-r--r--generic/tkFont.c1353
-rw-r--r--generic/tkFont.h76
-rw-r--r--generic/tkFrame.c8
-rw-r--r--generic/tkGet.c99
-rw-r--r--generic/tkGrab.c29
-rw-r--r--generic/tkGrid.c74
-rw-r--r--generic/tkImage.c24
-rw-r--r--generic/tkImgBmap.c19
-rw-r--r--generic/tkImgGIF.c20
-rw-r--r--generic/tkImgPPM.c10
-rw-r--r--generic/tkImgPhoto.c9
-rw-r--r--generic/tkInitScript.h12
-rw-r--r--generic/tkInt.h60
-rw-r--r--generic/tkListbox.c58
-rw-r--r--generic/tkMacWinMenu.c4
-rw-r--r--generic/tkMain.c43
-rw-r--r--generic/tkMenu.c2210
-rw-r--r--generic/tkMenu.h171
-rw-r--r--generic/tkMenuDraw.c233
-rw-r--r--generic/tkMenubutton.c6
-rw-r--r--generic/tkMessage.c8
-rw-r--r--generic/tkObj.c659
-rw-r--r--generic/tkOldConfig.c996
-rw-r--r--generic/tkOption.c29
-rw-r--r--generic/tkPack.c12
-rw-r--r--generic/tkPlace.c8
-rw-r--r--generic/tkRectOval.c23
-rw-r--r--generic/tkScale.c28
-rw-r--r--generic/tkScrollbar.c51
-rw-r--r--generic/tkSelect.c48
-rw-r--r--generic/tkSquare.c390
-rw-r--r--generic/tkTest.c1343
-rw-r--r--generic/tkText.c183
-rw-r--r--generic/tkText.h48
-rw-r--r--generic/tkTextBTree.c59
-rw-r--r--generic/tkTextDisp.c438
-rw-r--r--generic/tkTextImage.c16
-rw-r--r--generic/tkTextIndex.c616
-rw-r--r--generic/tkTextMark.c18
-rw-r--r--generic/tkTextTag.c43
-rw-r--r--generic/tkTextWind.c20
-rw-r--r--generic/tkTrig.c6
-rw-r--r--generic/tkUtil.c77
-rw-r--r--generic/tkVisual.c11
-rw-r--r--generic/tkWindow.c235
74 files changed, 14749 insertions, 5662 deletions
diff --git a/generic/prolog.ps b/generic/prolog.ps
new file mode 100644
index 0000000..378d503
--- /dev/null
+++ b/generic/prolog.ps
@@ -0,0 +1,284 @@
+%%BeginProlog
+50 dict begin
+
+% This is a standard prolog for Postscript generated by Tk's canvas
+% widget.
+% SCCS: @(#) prolog.ps 1.7 96/07/08 17:52:14
+
+% 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.h b/generic/tk.h
index 3e470f0..ac48a9c 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -6,12 +6,12 @@
*
* Copyright (c) 1989-1994 The Regents of the University of California.
* Copyright (c) 1994 The Australian National University.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tk.h 1.211 97/11/20 12:44:45
+ * SCCS: @(#) tk.h 1.217 98/02/18 18:33:32
*/
#ifndef _TK
@@ -25,6 +25,7 @@
* win/makefile.bc
* win/makefile.vc
* library/tk.tcl
+ * README, win/README, unix/README, and mac/README
*
* The release level should be 0 for alpha, 1 for beta, and 2 for
* final/patch. The release serial value is the number that follows the
@@ -38,12 +39,12 @@
*/
#define TK_MAJOR_VERSION 8
-#define TK_MINOR_VERSION 0
-#define TK_RELEASE_LEVEL 2
+#define TK_MINOR_VERSION 1
+#define TK_RELEASE_LEVEL 0
#define TK_RELEASE_SERIAL 2
-#define TK_VERSION "8.0"
-#define TK_PATCH_LEVEL "8.0p2"
+#define TK_VERSION "8.1"
+#define TK_PATCH_LEVEL "8.1a2"
/*
* A special definition used to allow this header file to be included
@@ -97,6 +98,7 @@ typedef struct Tk_ErrorHandler_ *Tk_ErrorHandler;
typedef struct Tk_Font_ *Tk_Font;
typedef struct Tk_Image__ *Tk_Image;
typedef struct Tk_ImageMaster_ *Tk_ImageMaster;
+typedef struct Tk_OptionTable_ *Tk_OptionTable;
typedef struct Tk_TextLayout_ *Tk_TextLayout;
typedef struct Tk_Window_ *Tk_Window;
typedef struct Tk_3DBorder_ *Tk_3DBorder;
@@ -108,54 +110,164 @@ typedef struct Tk_3DBorder_ *Tk_3DBorder;
typedef char *Tk_Uid;
/*
- * Structure used to specify how to handle argv options.
+ * The enum below defines the valid types for Tk configuration options
+ * as implemented by Tk_InitOptions, Tk_SetOptions, etc.
*/
-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. */
-} Tk_ArgvInfo;
+typedef enum {
+ TK_OPTION_BOOLEAN,
+ TK_OPTION_INT,
+ TK_OPTION_DOUBLE,
+ TK_OPTION_STRING,
+ TK_OPTION_STRING_TABLE,
+ TK_OPTION_COLOR,
+ TK_OPTION_FONT,
+ TK_OPTION_BITMAP,
+ TK_OPTION_BORDER,
+ TK_OPTION_RELIEF,
+ TK_OPTION_CURSOR,
+ TK_OPTION_JUSTIFY,
+ TK_OPTION_ANCHOR,
+ TK_OPTION_SYNONYM,
+ TK_OPTION_PIXELS,
+ TK_OPTION_WINDOW,
+ TK_OPTION_END
+} Tk_OptionType;
/*
- * Legal values for the type field of a Tk_ArgvInfo: see the user
- * documentation for details.
+ * 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.
*/
-#define TK_ARGV_CONSTANT 15
-#define TK_ARGV_INT 16
-#define TK_ARGV_STRING 17
-#define TK_ARGV_UID 18
-#define TK_ARGV_REST 19
-#define TK_ARGV_FLOAT 20
-#define TK_ARGV_FUNC 21
-#define TK_ARGV_GENFUNC 22
-#define TK_ARGV_HELP 23
-#define TK_ARGV_CONST_OPTION 24
-#define TK_ARGV_OPTION_VALUE 25
-#define TK_ARGV_OPTION_NAME_VALUE 26
-#define TK_ARGV_END 27
+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
+ * 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. */
+ 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. */
+ 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. */
+ 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
+ * 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. */
+} Tk_OptionSpec;
/*
- * Flag bits for passing to Tk_ParseArgv:
+ * Flag values for Tk_OptionSpec structures. These flags are shared by
+ * Tk_ConfigSpec structures, so be sure to coordinate any changes
+ * carefully.
*/
-#define TK_ARGV_NO_DEFAULTS 0x1
-#define TK_ARGV_NO_LEFTOVERS 0x2
-#define TK_ARGV_NO_ABBREV 0x4
-#define TK_ARGV_DONT_SKIP_FIRST_ARG 0x8
+#define TK_OPTION_NULL_OK 1
+
+/*
+ * Macro to use to fill in "offset" fields of Tk_OptionSpecs.
+ * Computes number of bytes from beginning of structure to a
+ * given field.
+ */
+
+#ifdef offsetof
+#define Tk_Offset(type, field) ((int) offsetof(type, field))
+#else
+#define Tk_Offset(type, field) ((int) ((char *) &((type *) 0)->field))
+#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.
+ */
+
+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. */
+} Tk_SavedOption;
+
+#ifdef TCL_MEM_DEBUG
+# define TK_NUM_SAVED_OPTIONS 2
+#else
+# define TK_NUM_SAVED_OPTIONS 20
+#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. */
+ 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. */
+} 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.
+ * 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.
+ */
+
+#ifndef __NO_OLD_CONFIG
+
typedef int (Tk_OptionParseProc) _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, Tk_Window tkwin, char *value, char *widgRec,
int offset));
@@ -209,40 +321,15 @@ typedef struct Tk_ConfigSpec {
* documentation for details.
*/
-#define TK_CONFIG_BOOLEAN 1
-#define TK_CONFIG_INT 2
-#define TK_CONFIG_DOUBLE 3
-#define TK_CONFIG_STRING 4
-#define TK_CONFIG_UID 5
-#define TK_CONFIG_COLOR 6
-#define TK_CONFIG_FONT 7
-#define TK_CONFIG_BITMAP 8
-#define TK_CONFIG_BORDER 9
-#define TK_CONFIG_RELIEF 10
-#define TK_CONFIG_CURSOR 11
-#define TK_CONFIG_ACTIVE_CURSOR 12
-#define TK_CONFIG_JUSTIFY 13
-#define TK_CONFIG_ANCHOR 14
-#define TK_CONFIG_SYNONYM 15
-#define TK_CONFIG_CAP_STYLE 16
-#define TK_CONFIG_JOIN_STYLE 17
-#define TK_CONFIG_PIXELS 18
-#define TK_CONFIG_MM 19
-#define TK_CONFIG_WINDOW 20
-#define TK_CONFIG_CUSTOM 21
-#define TK_CONFIG_END 22
-
-/*
- * Macro to use to fill in "offset" fields of Tk_ConfigInfos.
- * Computes number of bytes from beginning of structure to a
- * given field.
- */
-
-#ifdef offsetof
-#define Tk_Offset(type, field) ((int) offsetof(type, field))
-#else
-#define Tk_Offset(type, field) ((int) ((char *) &((type *) 0)->field))
-#endif
+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_SYNONYM, TK_CONFIG_CAP_STYLE, TK_CONFIG_JOIN_STYLE,
+ TK_CONFIG_PIXELS, TK_CONFIG_MM, TK_CONFIG_WINDOW, TK_CONFIG_CUSTOM,
+ TK_CONFIG_END
+} Tk_ConfigTypes;
/*
* Possible values for flags argument to Tk_ConfigureWidget:
@@ -251,18 +338,62 @@ typedef struct Tk_ConfigSpec {
#define TK_CONFIG_ARGV_ONLY 1
/*
- * Possible flag values for Tk_ConfigInfo structures. Any bits at
+ * 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
- * tkConfig.c (internal-use-only flags are defined there).
+ * tkOldConfig.c (internal-use-only flags are defined there).
*/
-#define TK_CONFIG_COLOR_ONLY 1
-#define TK_CONFIG_MONO_ONLY 2
-#define TK_CONFIG_NULL_OK 4
+#define TK_CONFIG_NULL_OK 1
+#define TK_CONFIG_COLOR_ONLY 2
+#define TK_CONFIG_MONO_ONLY 4
#define TK_CONFIG_DONT_SET_DEFAULT 8
#define TK_CONFIG_OPTION_SPECIFIED 0x10
#define TK_CONFIG_USER_BIT 0x100
+#endif /* __NO_OLD_CONFIG */
+
+/*
+ * Structure used to specify how to handle argv options.
+ */
+
+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. */
+} Tk_ArgvInfo;
+
+/*
+ * Legal values for the type field of a Tk_ArgvInfo: see the user
+ * documentation for details.
+ */
+
+#define TK_ARGV_CONSTANT 15
+#define TK_ARGV_INT 16
+#define TK_ARGV_STRING 17
+#define TK_ARGV_UID 18
+#define TK_ARGV_REST 19
+#define TK_ARGV_FLOAT 20
+#define TK_ARGV_FUNC 21
+#define TK_ARGV_GENFUNC 22
+#define TK_ARGV_HELP 23
+#define TK_ARGV_CONST_OPTION 24
+#define TK_ARGV_OPTION_VALUE 25
+#define TK_ARGV_OPTION_NAME_VALUE 26
+#define TK_ARGV_END 27
+
+/*
+ * Flag bits for passing to Tk_ParseArgv:
+ */
+
+#define TK_ARGV_NO_DEFAULTS 0x1
+#define TK_ARGV_NO_LEFTOVERS 0x2
+#define TK_ARGV_NO_ABBREV 0x4
+#define TK_ARGV_DONT_SKIP_FIRST_ARG 0x8
/*
* Enumerated type for describing actions to be taken in response
@@ -287,12 +418,12 @@ typedef enum {
* Relief values returned by Tk_GetRelief:
*/
-#define TK_RELIEF_RAISED 1
-#define TK_RELIEF_FLAT 2
-#define TK_RELIEF_SUNKEN 4
-#define TK_RELIEF_GROOVE 8
-#define TK_RELIEF_RIDGE 16
-#define TK_RELIEF_SOLID 32
+#define TK_RELIEF_FLAT 0
+#define TK_RELIEF_GROOVE 1
+#define TK_RELIEF_RAISED 2
+#define TK_RELIEF_RIDGE 3
+#define TK_RELIEF_SOLID 4
+#define TK_RELIEF_SUNKEN 5
/*
* "Which" argument values for Tk_3DBorderGC:
@@ -715,6 +846,8 @@ typedef void Tk_ItemInsertProc _ANSI_ARGS_((Tk_Canvas canvas,
typedef void Tk_ItemDCharsProc _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, int first, int last));
+#ifndef __NO_OLD_CONFIG
+
typedef struct Tk_ItemType {
char *name; /* The name of this type of item, such
* as "line". */
@@ -764,6 +897,8 @@ typedef struct Tk_ItemType {
* a list. */
} 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
@@ -782,16 +917,17 @@ typedef struct Tk_CanvasTextInfo {
Tk_Item *selItemPtr; /* Pointer to selected item. NULL means
* selection isn't in this canvas.
* Writable by items. */
- int selectFirst; /* Index of first selected character.
- * Writable by items. */
- int selectLast; /* Index of last selected character.
- * 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; /* Fixed end of selection (i.e. "select to"
- * operation will use this as one end of the
- * selection). Writable by 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
@@ -1043,6 +1179,16 @@ EXTERN void Tk_3DVerticalBevel _ANSI_ARGS_((Tk_Window tkwin,
int relief));
EXTERN void Tk_AddOption _ANSI_ARGS_((Tk_Window tkwin, char *name,
char *value, int priority));
+EXTERN Pixmap Tk_AllocBitmapFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr));
+EXTERN Tk_3DBorder Tk_Alloc3DBorderFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr));
+EXTERN XColor * Tk_AllocColorFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr));
+EXTERN Tk_Cursor Tk_AllocCursorFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr));
+EXTERN Tk_Font Tk_AllocFontFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr));
EXTERN void Tk_BindEvent _ANSI_ARGS_((Tk_BindingTable bindingTable,
XEvent *eventPtr, Tk_Window tkwin, int numObjects,
ClientData *objectPtr));
@@ -1095,6 +1241,7 @@ EXTERN int Tk_ClipboardAppend _ANSI_ARGS_((Tcl_Interp *interp,
char* buffer));
EXTERN int Tk_ClipboardClear _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin));
+#ifndef __NO_OLD_CONFIG
EXTERN int Tk_ConfigureInfo _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, Tk_ConfigSpec *specs,
char *widgRec, char *argvName, int flags));
@@ -1105,6 +1252,7 @@ EXTERN int Tk_ConfigureWidget _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, Tk_ConfigSpec *specs,
int argc, char **argv, char *widgRec,
int flags));
+#endif
EXTERN void Tk_ConfigureWindow _ANSI_ARGS_((Tk_Window tkwin,
unsigned int valueMask, XWindowChanges *valuePtr));
EXTERN Tk_TextLayout Tk_ComputeTextLayout _ANSI_ARGS_((Tk_Font font,
@@ -1127,7 +1275,11 @@ EXTERN void Tk_CreateGenericHandler _ANSI_ARGS_((
Tk_GenericProc *proc, ClientData clientData));
EXTERN void Tk_CreateImageType _ANSI_ARGS_((
Tk_ImageType *typePtr));
+#ifndef __NO_OLD_CONFIG
EXTERN void Tk_CreateItemType _ANSI_ARGS_((Tk_ItemType *typePtr));
+#endif
+EXTERN Tk_OptionTable Tk_CreateOptionTable _ANSI_ARGS_((Tcl_Interp *interp,
+ CONST Tk_OptionSpec *templatePtr));
EXTERN void Tk_CreatePhotoImageFormat _ANSI_ARGS_((
Tk_PhotoImageFormat *formatPtr));
EXTERN void Tk_CreateSelHandler _ANSI_ARGS_((Tk_Window tkwin,
@@ -1160,6 +1312,8 @@ EXTERN void Tk_DeleteGenericHandler _ANSI_ARGS_((
Tk_GenericProc *proc, ClientData clientData));
EXTERN void Tk_DeleteImage _ANSI_ARGS_((Tcl_Interp *interp,
char *name));
+EXTERN void Tk_DeleteOptionTable _ANSI_ARGS_((
+ Tk_OptionTable optionTable));
EXTERN void Tk_DeleteSelHandler _ANSI_ARGS_((Tk_Window tkwin,
Atom selection, Atom target));
EXTERN void Tk_DestroyWindow _ANSI_ARGS_((Tk_Window tkwin));
@@ -1195,18 +1349,34 @@ EXTERN Tk_PhotoHandle Tk_FindPhoto _ANSI_ARGS_((Tcl_Interp *interp,
char *imageName));
EXTERN Font Tk_FontId _ANSI_ARGS_((Tk_Font font));
EXTERN void Tk_Free3DBorder _ANSI_ARGS_((Tk_3DBorder border));
+EXTERN void Tk_Free3DBorderFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN void Tk_FreeBitmap _ANSI_ARGS_((Display *display,
Pixmap bitmap));
+EXTERN void Tk_FreeBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN void Tk_FreeColor _ANSI_ARGS_((XColor *colorPtr));
+EXTERN void Tk_FreeColorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN void Tk_FreeColormap _ANSI_ARGS_((Display *display,
Colormap colormap));
+EXTERN void Tk_FreeConfigOptions _ANSI_ARGS_((char *recordPtr,
+ Tk_OptionTable optionToken, Tk_Window tkwin));
+EXTERN void Tk_FreeSavedOptions _ANSI_ARGS_((
+ Tk_SavedOptions *savePtr));
EXTERN void Tk_FreeCursor _ANSI_ARGS_((Display *display,
Tk_Cursor cursor));
-EXTERN void Tk_FreeFont _ANSI_ARGS_((Tk_Font));
+EXTERN void Tk_FreeCursorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
+EXTERN void Tk_FreeFont _ANSI_ARGS_((Tk_Font tkfont));
+EXTERN void Tk_FreeFontFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN void Tk_FreeGC _ANSI_ARGS_((Display *display, GC gc));
EXTERN void Tk_FreeImage _ANSI_ARGS_((Tk_Image image));
+#ifndef __NO_OLD_CONFIG
EXTERN void Tk_FreeOptions _ANSI_ARGS_((Tk_ConfigSpec *specs,
char *widgRec, Display *display, int needFlags));
+#endif
EXTERN void Tk_FreePixmap _ANSI_ARGS_((Display *display,
Pixmap pixmap));
EXTERN void Tk_FreeTextLayout _ANSI_ARGS_((
@@ -1217,41 +1387,58 @@ EXTERN GC Tk_GCForColor _ANSI_ARGS_((XColor *colorPtr,
EXTERN void Tk_GeometryRequest _ANSI_ARGS_((Tk_Window tkwin,
int reqWidth, int reqHeight));
EXTERN Tk_3DBorder Tk_Get3DBorder _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_Uid colorName));
+ Tk_Window tkwin, char *colorName));
+EXTERN Tk_3DBorder Tk_Get3DBorderFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN void Tk_GetAllBindings _ANSI_ARGS_((Tcl_Interp *interp,
Tk_BindingTable bindingTable, ClientData object));
EXTERN int Tk_GetAnchor _ANSI_ARGS_((Tcl_Interp *interp,
char *string, Tk_Anchor *anchorPtr));
+EXTERN int Tk_GetAnchorFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tk_Anchor *anchorPtr));
EXTERN char * Tk_GetAtomName _ANSI_ARGS_((Tk_Window tkwin,
Atom atom));
EXTERN char * Tk_GetBinding _ANSI_ARGS_((Tcl_Interp *interp,
Tk_BindingTable bindingTable, ClientData object,
char *eventString));
EXTERN Pixmap Tk_GetBitmap _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_Uid string));
+ Tk_Window tkwin, char *string));
EXTERN Pixmap Tk_GetBitmapFromData _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, char *source,
int width, int height));
+EXTERN Pixmap Tk_GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN int Tk_GetCapStyle _ANSI_ARGS_((Tcl_Interp *interp,
char *string, int *capPtr));
EXTERN XColor * Tk_GetColor _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_Uid name));
+ Tk_Window tkwin, char *name));
EXTERN XColor * Tk_GetColorByValue _ANSI_ARGS_((Tk_Window tkwin,
XColor *colorPtr));
+EXTERN XColor * Tk_GetColorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN Colormap Tk_GetColormap _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, char *string));
EXTERN Tk_Cursor Tk_GetCursor _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_Uid string));
+ Tk_Window tkwin, char *string));
EXTERN Tk_Cursor Tk_GetCursorFromData _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, char *source, char *mask,
int width, int height, int xHot, int yHot,
Tk_Uid fg, Tk_Uid bg));
+EXTERN Tk_Cursor Tk_GetCursorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN Tk_Font Tk_GetFont _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, CONST char *string));
-EXTERN Tk_Font Tk_GetFontFromObj _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tcl_Obj *objPtr));
+EXTERN Tk_Font Tk_GetFontFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
EXTERN void Tk_GetFontMetrics _ANSI_ARGS_((Tk_Font font,
Tk_FontMetrics *fmPtr));
+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_GetOptionValue _ANSI_ARGS_((
+ Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionTable, Tcl_Obj *namePtr,
+ Tk_Window tkwin));
EXTERN GC Tk_GetGC _ANSI_ARGS_((Tk_Window tkwin,
unsigned long valueMask, XGCValues *valuePtr));
EXTERN Tk_Image Tk_GetImage _ANSI_ARGS_((Tcl_Interp *interp,
@@ -1260,20 +1447,31 @@ EXTERN Tk_Image Tk_GetImage _ANSI_ARGS_((Tcl_Interp *interp,
ClientData clientData));
EXTERN ClientData Tk_GetImageMasterData _ANSI_ARGS_ ((Tcl_Interp *interp,
char *name, Tk_ImageType **typePtrPtr));
+#ifndef __NO_OLD_CONFIG
EXTERN Tk_ItemType * Tk_GetItemTypes _ANSI_ARGS_((void));
+#endif
EXTERN int Tk_GetJoinStyle _ANSI_ARGS_((Tcl_Interp *interp,
char *string, int *joinPtr));
EXTERN int Tk_GetJustify _ANSI_ARGS_((Tcl_Interp *interp,
char *string, Tk_Justify *justifyPtr));
+EXTERN int Tk_GetJustifyFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tk_Justify *justifyPtr));
+EXTERN int Tk_GetMMFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ double *doublePtr));
EXTERN int Tk_GetNumMainWindows _ANSI_ARGS_((void));
EXTERN Tk_Uid Tk_GetOption _ANSI_ARGS_((Tk_Window tkwin, char *name,
char *className));
EXTERN int Tk_GetPixels _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, char *string, int *intPtr));
+EXTERN int Tk_GetPixelsFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr));
EXTERN Pixmap Tk_GetPixmap _ANSI_ARGS_((Display *display, Drawable d,
int width, int height, int depth));
EXTERN int Tk_GetRelief _ANSI_ARGS_((Tcl_Interp *interp,
char *name, int *reliefPtr));
+EXTERN int Tk_GetReliefFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr, int *resultPtr));
EXTERN void Tk_GetRootCoords _ANSI_ARGS_ ((Tk_Window tkwin,
int *xPtr, int *yPtr));
EXTERN int Tk_GetScrollInfo _ANSI_ARGS_((Tcl_Interp *interp,
@@ -1301,6 +1499,9 @@ EXTERN void Tk_ImageChanged _ANSI_ARGS_((
int width, int height, int imageWidth,
int imageHeight));
EXTERN int Tk_Init _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int Tk_InitOptions _ANSI_ARGS_((
+ Tcl_Interp *interp, char *recordPtr,
+ Tk_OptionTable optionToken, Tk_Window tkwin));
EXTERN Atom Tk_InternAtom _ANSI_ARGS_((Tk_Window tkwin,
char *name));
EXTERN int Tk_IntersectTextLayout _ANSI_ARGS_((
@@ -1376,6 +1577,8 @@ EXTERN void Tk_QueueWindowEvent _ANSI_ARGS_((XEvent *eventPtr,
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_RestoreSavedOptions _ANSI_ARGS_((
+ Tk_SavedOptions *savePtr));
EXTERN void Tk_ResizeWindow _ANSI_ARGS_((Tk_Window tkwin,
int width, int height));
EXTERN int Tk_RestackWindow _ANSI_ARGS_((Tk_Window tkwin,
@@ -1389,6 +1592,11 @@ EXTERN void Tk_SetBackgroundFromBorder _ANSI_ARGS_((
Tk_Window tkwin, Tk_3DBorder border));
EXTERN void Tk_SetClass _ANSI_ARGS_((Tk_Window tkwin,
char *className));
+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 void Tk_SetGrid _ANSI_ARGS_((Tk_Window tkwin,
int reqWidth, int reqHeight, int gridWidth,
int gridHeight));
@@ -1442,61 +1650,73 @@ EXTERN void Tk_UpdatePointer _ANSI_ARGS_((Tk_Window tkwin,
EXTERN int Tk_AfterCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_BellCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_BellObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_BindCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_BindtagsCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_ButtonCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_ButtonObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_CanvasCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_CheckbuttonCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_CheckbuttonObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_ClipboardCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_ChooseColorCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_ChooseFontCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+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_DestroyCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_EntryCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_EventCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_EventObjCmd _ANSI_ARGS_((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_FrameCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_FocusCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+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_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_GetOpenFileCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_GetSaveFileCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_GrabCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_GridCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_ImageCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_LabelCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_ListboxCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_LowerCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_MenuCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_MenubuttonCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_MessageBoxCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_MessageCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_OptionCmd _ANSI_ARGS_((ClientData clientData,
@@ -1505,8 +1725,9 @@ EXTERN int Tk_PackCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_PlaceCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_RadiobuttonCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_RadiobuttonObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
EXTERN int Tk_RaiseCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_ScaleCmd _ANSI_ARGS_((ClientData clientData,
@@ -1517,6 +1738,9 @@ EXTERN int Tk_SelectionCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_SendCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_SendObjCmd _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, char **argv));
EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData,
@@ -1526,8 +1750,9 @@ EXTERN int Tk_TkwaitCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN int Tk_ToplevelCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_UpdateCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+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_Interp *interp, int objc,
Tcl_Obj *CONST objv[]));
diff --git a/generic/tk3d.c b/generic/tk3d.c
index 53eec8b..36399cc 100644
--- a/generic/tk3d.c
+++ b/generic/tk3d.c
@@ -10,36 +10,162 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tk3d.c 1.60 97/01/13 17:23:10
+ * SCCS: @(#) tk3d.c 1.67 97/12/24 15:50:00
*/
-#include <tk3d.h>
+#include "tk3d.h"
/*
- * Hash table to map from a border's values (color, etc.) to a
- * Border structure for those values.
+ * Hash table to map from a string color name to a TkBorder structure
+ * that can be used to draw borders with that color.
*/
static Tcl_HashTable borderTable;
-typedef struct {
- Tk_Uid colorName; /* Color for border. */
- Colormap colormap; /* Colormap used for allocating border
- * colors. */
- Screen *screen; /* Screen on which border will be drawn. */
-} BorderKey;
static int initialized = 0; /* 0 means static structures haven't
* been initialized yet. */
+/*
+ * The following table defines the string values for reliefs, which are
+ * used by Tk_GetReliefFromObj.
+ */
+
+static char *reliefStrings[] = {"flat", "groove", "raised", "ridge", "solid",
+ "sunken", (char *) NULL};
/*
* Forward declarations for procedures defined in this file:
*/
static void BorderInit _ANSI_ARGS_((void));
+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));
+
+/*
+ * The following structure defines the implementation of the "border" Tcl
+ * object, used for drawing. The border object remembers the hash table entry
+ * associated with a border. The actual allocation and deallocation of the
+ * border should be done by the configuration package when the border option
+ * is set.
+ */
+
+static Tcl_ObjType borderObjType = {
+ "border", /* name */
+ FreeBorderObjProc, /* freeIntRepProc */
+ DupBorderObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocBorderFromObj --
+ *
+ * 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.
+ *
+ * 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 Tk_FreeBorderFromObj 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
+ * background. */
+{
+ TkBorder *borderPtr;
+
+ if (objPtr->typePtr != &borderObjType) {
+ InitBorderObj(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 (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.
+ */
+
+ FreeBorderObjProc(objPtr);
+ borderPtr = NULL;
+ } else if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ borderPtr->resourceRefCount++;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+
+ /*
+ * 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 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 *) Tcl_GetHashValue(borderPtr->hashPtr);
+ FreeBorderObjProc(objPtr);
+ for (borderPtr = firstBorderPtr ; borderPtr != NULL;
+ borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ borderPtr->resourceRefCount++;
+ borderPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+ }
+
+ /*
+ * 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;
+ if (borderPtr != NULL) {
+ borderPtr->objRefCount++;
+ }
+ return (Tk_3DBorder) borderPtr;
+}
/*
*--------------------------------------------------------------
@@ -49,12 +175,11 @@ static void ShiftLine _ANSI_ARGS_((XPoint *p1Ptr, XPoint *p2Ptr,
* 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 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 interp->result.
+ * 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.
*
* Side effects:
* Data structures, graphics contexts, etc. are allocated.
@@ -69,70 +194,72 @@ 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
+ char *colorName; /* String giving name of color
* for window background. */
{
- BorderKey key;
Tcl_HashEntry *hashPtr;
- register TkBorder *borderPtr;
+ TkBorder *borderPtr, *existingBorderPtr;
int new;
XGCValues gcValues;
+ XColor *bgColorPtr;
if (!initialized) {
BorderInit();
}
- /*
- * First, check to see if there's already a border that will work
- * for this request.
- */
-
- key.colorName = colorName;
- key.colormap = Tk_Colormap(tkwin);
- key.screen = Tk_Screen(tkwin);
-
- hashPtr = Tcl_CreateHashEntry(&borderTable, (char *) &key, &new);
+ hashPtr = Tcl_CreateHashEntry(&borderTable, colorName, &new);
if (!new) {
- borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
- borderPtr->refCount++;
+ existingBorderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
+ for (borderPtr = existingBorderPtr; borderPtr != NULL;
+ borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ borderPtr->resourceRefCount++;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
} else {
- XColor *bgColorPtr;
+ existingBorderPtr = NULL;
+ }
- /*
- * No satisfactory border exists yet. Initialize a new one.
- */
-
- bgColorPtr = Tk_GetColor(interp, tkwin, colorName);
- if (bgColorPtr == NULL) {
+ /*
+ * No satisfactory border exists yet. Initialize a new one.
+ */
+
+ bgColorPtr = Tk_GetColor(interp, tkwin, colorName);
+ if (bgColorPtr == NULL) {
+ if (new) {
Tcl_DeleteHashEntry(hashPtr);
- return NULL;
}
-
- borderPtr = TkpGetBorder();
- borderPtr->screen = Tk_Screen(tkwin);
- borderPtr->visual = Tk_Visual(tkwin);
- borderPtr->depth = Tk_Depth(tkwin);
- borderPtr->colormap = key.colormap;
- borderPtr->refCount = 1;
- borderPtr->bgColorPtr = bgColorPtr;
- borderPtr->darkColorPtr = NULL;
- borderPtr->lightColorPtr = NULL;
- borderPtr->shadow = None;
- borderPtr->bgGC = None;
- borderPtr->darkGC = None;
- borderPtr->lightGC = None;
- borderPtr->hashPtr = hashPtr;
- 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.
- */
-
- gcValues.foreground = borderPtr->bgColorPtr->pixel;
- borderPtr->bgGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ return NULL;
}
+
+ borderPtr = TkpGetBorder();
+ borderPtr->screen = Tk_Screen(tkwin);
+ borderPtr->visual = Tk_Visual(tkwin);
+ borderPtr->depth = Tk_Depth(tkwin);
+ borderPtr->colormap = Tk_Colormap(tkwin);
+ borderPtr->resourceRefCount = 1;
+ borderPtr->objRefCount = 0;
+ borderPtr->bgColorPtr = bgColorPtr;
+ borderPtr->darkColorPtr = NULL;
+ borderPtr->lightColorPtr = NULL;
+ borderPtr->shadow = None;
+ borderPtr->bgGC = None;
+ borderPtr->darkGC = None;
+ borderPtr->lightGC = None;
+ borderPtr->hashPtr = hashPtr;
+ borderPtr->nextPtr = existingBorderPtr;
+ 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.
+ */
+
+ gcValues.foreground = borderPtr->bgColorPtr->pixel;
+ borderPtr->bgGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
return (Tk_3DBorder) borderPtr;
}
@@ -208,7 +335,7 @@ Tk_NameOf3DBorder(border)
{
TkBorder *borderPtr = (TkBorder *) border;
- return ((BorderKey *) borderPtr->hashPtr->key.words)->colorName;
+ return borderPtr->hashPtr->key.string;
}
/*
@@ -303,34 +430,51 @@ void
Tk_Free3DBorder(border)
Tk_3DBorder border; /* Token for border to be released. */
{
- register TkBorder *borderPtr = (TkBorder *) border;
+ TkBorder *borderPtr = (TkBorder *) border;
Display *display = DisplayOfScreen(borderPtr->screen);
+ TkBorder *prevPtr;
- borderPtr->refCount--;
- if (borderPtr->refCount == 0) {
- TkpFreeBorder(borderPtr);
- if (borderPtr->bgColorPtr != NULL) {
- Tk_FreeColor(borderPtr->bgColorPtr);
- }
- if (borderPtr->darkColorPtr != NULL) {
- Tk_FreeColor(borderPtr->darkColorPtr);
- }
- if (borderPtr->lightColorPtr != NULL) {
- Tk_FreeColor(borderPtr->lightColorPtr);
- }
- if (borderPtr->shadow != None) {
- Tk_FreeBitmap(display, borderPtr->shadow);
- }
- if (borderPtr->bgGC != None) {
- Tk_FreeGC(display, borderPtr->bgGC);
- }
- if (borderPtr->darkGC != None) {
- Tk_FreeGC(display, borderPtr->darkGC);
+ borderPtr->resourceRefCount--;
+ if (borderPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ prevPtr = (TkBorder *) Tcl_GetHashValue(borderPtr->hashPtr);
+ TkpFreeBorder(borderPtr);
+ if (borderPtr->bgColorPtr != NULL) {
+ Tk_FreeColor(borderPtr->bgColorPtr);
+ }
+ if (borderPtr->darkColorPtr != NULL) {
+ Tk_FreeColor(borderPtr->darkColorPtr);
+ }
+ if (borderPtr->lightColorPtr != NULL) {
+ Tk_FreeColor(borderPtr->lightColorPtr);
+ }
+ if (borderPtr->shadow != None) {
+ Tk_FreeBitmap(display, borderPtr->shadow);
+ }
+ if (borderPtr->bgGC != None) {
+ Tk_FreeGC(display, borderPtr->bgGC);
+ }
+ if (borderPtr->darkGC != None) {
+ Tk_FreeGC(display, borderPtr->darkGC);
+ }
+ if (borderPtr->lightGC != None) {
+ Tk_FreeGC(display, borderPtr->lightGC);
+ }
+ if (prevPtr == borderPtr) {
+ if (borderPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(borderPtr->hashPtr);
+ } else {
+ Tcl_SetHashValue(borderPtr->hashPtr, borderPtr->nextPtr);
}
- if (borderPtr->lightGC != None) {
- Tk_FreeGC(display, borderPtr->lightGC);
+ } else {
+ while (prevPtr->nextPtr != borderPtr) {
+ prevPtr = prevPtr->nextPtr;
}
- Tcl_DeleteHashEntry(borderPtr->hashPtr);
+ prevPtr->nextPtr = borderPtr->nextPtr;
+ }
+ if (borderPtr->objRefCount == 0) {
ckfree((char *) borderPtr);
}
}
@@ -338,6 +482,105 @@ 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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_Free3DBorder(Tk_Get3DBorderFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeBorderObjProc(objPtr)
+ Tcl_Obj *objPtr; /* The object we are releasing. */
+{
+ TkBorder *borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (borderPtr != NULL) {
+ borderPtr->objRefCount--;
+ if ((borderPtr->objRefCount == 0)
+ && (borderPtr->resourceRefCount == 0)) {
+ ckfree((char *) borderPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupBorderObjProc --
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupBorderObjProc(srcObjPtr, dupObjPtr)
+ 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;
+
+ if (borderPtr != NULL) {
+ borderPtr->objRefCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_SetBackgroundFromBorder --
*
* Change the background of a window to one appropriate for a given
@@ -365,6 +608,35 @@ Tk_SetBackgroundFromBorder(tkwin, border)
/*
*----------------------------------------------------------------------
*
+ * Tk_GetReliefFromObj --
+ *
+ * Return an integer value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ return Tcl_GetIndexFromObj(interp, objPtr, reliefStrings, "relief", 0,
+ resultPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_GetRelief --
*
* Parse a relief description and return the corresponding
@@ -407,8 +679,11 @@ Tk_GetRelief(interp, name, reliefPtr)
} else if ((c == 's') && (strncmp(name, "sunken", length) == 0)) {
*reliefPtr = TK_RELIEF_SUNKEN;
} else {
- sprintf(interp->result, "bad relief type \"%.50s\": must be %s",
+ char buf[200];
+
+ sprintf(buf, "bad relief type \"%.50s\": must be %s",
name, "flat, groove, raised, ridge, solid, or sunken");
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -785,7 +1060,7 @@ static void
BorderInit()
{
initialized = 1;
- Tcl_InitHashTable(&borderTable, sizeof(BorderKey)/sizeof(int));
+ Tcl_InitHashTable(&borderTable, TCL_STRING_KEYS);
}
/*
@@ -947,3 +1222,167 @@ Intersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr)
}
return 0;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_3DBorder
+Tk_Get3DBorderFromObj(tkwin, objPtr)
+ Tk_Window tkwin;
+ Tcl_Obj *objPtr; /* The object whose string value selects
+ * a border. */
+{
+ TkBorder *borderPtr = NULL;
+ Tcl_HashEntry *hashPtr;
+
+ if (objPtr->typePtr != &borderObjType) {
+ InitBorderObj(objPtr);
+ }
+
+ borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;
+ if (borderPtr != NULL) {
+ if ((borderPtr->resourceRefCount > 0)
+ && (Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ /*
+ * The object already points to the right border structure.
+ * Just return it.
+ */
+
+ return (Tk_3DBorder) borderPtr;
+ }
+ hashPtr = borderPtr->hashPtr;
+ FreeBorderObjProc(objPtr);
+ } else {
+ hashPtr = Tcl_FindHashEntry(&borderTable, 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 TkBorder structures. See if any of them will work.
+ */
+
+ for (borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
+ (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) borderPtr;
+ borderPtr->objRefCount++;
+ return (Tk_3DBorder) borderPtr;
+ }
+ }
+
+ error:
+ panic("Tk_Get3DBorderFromObj called with non-existent border!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitBorderObj --
+ *
+ * Attempt to generate a border internal form for the Tcl object
+ * "objPtr".
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If no error occurs, a blank internal format for a border value
+ * is intialized. The final form cannot be done without a Tk_Window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitBorderObj(objPtr)
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+ objPtr->typePtr = &borderObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugBorder --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkBorder *borderPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&borderTable, name);
+ if (hashPtr != NULL) {
+ borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
+ if (borderPtr == NULL) {
+ 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_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
diff --git a/generic/tk3d.h b/generic/tk3d.h
index cd9ecd5..4e17eb3 100644
--- a/generic/tk3d.h
+++ b/generic/tk3d.h
@@ -4,12 +4,12 @@
* Declarations of types and functions shared by the 3d border
* module.
*
- * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tk3d.h 1.1 96/11/04 13:52:59
+ * SCCS: @(#) tk3d.h 1.4 97/12/24 15:50:02
*/
#ifndef _TK3D
@@ -18,13 +18,13 @@
#include <tkInt.h>
/*
- * 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.
+ * 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.
*/
-typedef struct {
+typedef struct TkBorder {
Screen *screen; /* Screen on which the border will be used. */
Visual *visual; /* Visual for all windows and pixmaps using
* the border. */
@@ -32,8 +32,18 @@ typedef struct {
* the border will be used. */
Colormap colormap; /* Colormap out of which pixels are
* allocated. */
- int refCount; /* Number of different users of
- * this border. */
+ 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. */
+ int objRefCount; /* The number of Tcl objects that reference
+ * this structure. */
XColor *bgColorPtr; /* Background color (intensity
* between lightColorPtr and
* darkColorPtr). */
@@ -58,6 +68,11 @@ typedef struct {
* 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. */
} TkBorder;
diff --git a/generic/tkArgv.c b/generic/tkArgv.c
index 5842687..66a703c 100644
--- a/generic/tkArgv.c
+++ b/generic/tkArgv.c
@@ -5,12 +5,12 @@
* argv-argc parsing.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkArgv.c 1.21 97/04/25 16:50:27
+ * SCCS: @(#) tkArgv.c 1.22 97/11/07 21:13:03
*/
#include "tkPort.h"
@@ -45,7 +45,7 @@ static void PrintUsage _ANSI_ARGS_((Tcl_Interp *interp,
*
* Results:
* The return value is a standard Tcl return value. If an
- * error occurs then an error message is left in interp->result.
+ * 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
@@ -291,10 +291,14 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags)
srcIndex += 2;
argc -= 2;
break;
- default:
- sprintf(interp->result, "bad argument type %d in Tk_ArgvInfo",
+ 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;
+ }
}
}
@@ -328,7 +332,7 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags)
* Generate a help string describing command-line options.
*
* Results:
- * Interp->result will be modified to hold a help string
+ * 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.
@@ -353,7 +357,7 @@ PrintUsage(interp, argTable, flags)
int width, i, numSpaces;
#define NUM_SPACES 20
static char spaces[] = " ";
- char tmp[30];
+ char tmp[TCL_DOUBLE_SPACE];
/*
* First, compute the width of the widest option key, so that we
diff --git a/generic/tkBind.c b/generic/tkBind.c
index bb37b00..0aa0e9e 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -5,12 +5,12 @@
* with X events or sequences of X events.
*
* Copyright (c) 1989-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkBind.c 1.133 97/07/01 17:59:53
+ * SCCS: @(#) tkBind.c 1.144 98/02/18 17:08:07
*/
#include "tkPort.h"
@@ -571,6 +571,20 @@ static int flagArray[TK_LASTEVENT] = {
};
/*
+ * 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[] = {
+ {-1, "now"},
+ {TCL_QUEUE_HEAD, "head"},
+ {TCL_QUEUE_MARK, "mark"},
+ {TCL_QUEUE_TAIL, "tail"},
+ {-2, NULL}
+};
+
+/*
* 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
@@ -644,7 +658,8 @@ static int GetVirtualEvent _ANSI_ARGS_((Tcl_Interp *interp,
static Tk_Uid GetVirtualEventUid _ANSI_ARGS_((Tcl_Interp *interp,
char *virtString));
static int HandleEventGenerate _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window main, int argc, char **argv));
+ Tk_Window main, int objc,
+ Tcl_Obj *CONST objv[]));
static void InitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr));
static void InitVirtualEventTable _ANSI_ARGS_((
VirtualEventTable *vetPtr));
@@ -652,9 +667,14 @@ static PatSeq * MatchPatterns _ANSI_ARGS_((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,
char **eventStringPtr, Pattern *patPtr,
unsigned long *eventMaskPtr));
+static void SetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin,
+ KeySym keySym, XEvent *eventPtr));
/*
* The following define is used as a short circuit for the callback
@@ -776,6 +796,7 @@ TkBindFree(mainPtr)
bindInfoPtr = (BindInfo *) mainPtr->bindInfo;
DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable);
+ ckfree((char *) bindInfoPtr);
mainPtr->bindInfo = NULL;
}
@@ -890,7 +911,7 @@ Tk_DeleteBindingTable(bindingTable)
* 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 interp->result. If all went well then the return
+ * 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
@@ -995,7 +1016,7 @@ Tk_CreateBinding(interp, bindingTable, object, eventString, command, append)
* 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 interp->result. If all went well then the return
+ * 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
@@ -1079,7 +1100,7 @@ TkCreateBindingProcedure(interp, bindingTable, object, eventString,
*
* Results:
* The result is a standard Tcl return value. If an error
- * occurs then interp->result will contain an error message.
+ * occurs then the interp's result will contain an error message.
*
* Side effects:
* The binding given by object and eventString is removed
@@ -1174,7 +1195,7 @@ Tk_DeleteBinding(interp, bindingTable, object, eventString)
* 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
- * interp->result. The return value is semi-static: it
+ * the interp's result. The return value is semi-static: it
* will persist until the binding is changed or deleted.
*
* Side effects:
@@ -1217,7 +1238,7 @@ Tk_GetBinding(interp, bindingTable, object, eventString)
* associated with a given object.
*
* Results:
- * There is no return value. Interp->result is modified to
+ * 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.
@@ -1381,9 +1402,9 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
{
BindingTable *bindPtr;
TkDisplay *dispPtr;
+ ScreenInfo *screenPtr;
BindInfo *bindInfoPtr;
TkDisplay *oldDispPtr;
- ScreenInfo *screenPtr;
XEvent *ringPtr;
PatSeq *vMatchDetailList, *vMatchNoDetailList;
int flags, oldScreen, i, deferModal;
@@ -1614,12 +1635,12 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
unsigned int oldSize, newSize;
oldSize = sizeof(staticPending)
- - sizeof(staticPending.matchArray)
- + matchSpace * sizeof(PatSeq*);
+ - sizeof(staticPending.matchArray)
+ + matchSpace * sizeof(PatSeq*);
matchSpace *= 2;
newSize = sizeof(staticPending)
- - sizeof(staticPending.matchArray)
- + matchSpace * sizeof(PatSeq*);
+ - sizeof(staticPending.matchArray)
+ + matchSpace * sizeof(PatSeq*);
new = (PendingBinding *) ckalloc(newSize);
memcpy((VOID *) new, (VOID *) pendingPtr, oldSize);
if (pendingPtr != &staticPending) {
@@ -1650,7 +1671,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
*
* There are two tricks here:
* 1. Bindings can be invoked from in the middle of Tcl commands,
- * where interp->result is significant (for example, a widget
+ * 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,
@@ -1681,6 +1702,13 @@ 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.
+ */
+
pendingPtr->nextPtr = bindInfoPtr->pendingList;
pendingPtr->tkwin = tkwin;
pendingPtr->deleted = 0;
@@ -1700,10 +1728,19 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
end = p + Tcl_DStringLength(&scripts);
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.
+ */
+
while (p < end) {
int code;
- screenPtr->bindingDepth++;
+ if (winPtr->mainPtr != NULL) {
+ screenPtr->bindingDepth++;
+ }
Tcl_AllowExceptions(interp);
if (*p == '\0') {
@@ -1729,7 +1766,10 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
p += strlen(p);
}
p++;
- screenPtr->bindingDepth--;
+
+ if (winPtr->mainPtr != NULL) {
+ screenPtr->bindingDepth--;
+ }
if (code != TCL_OK) {
if (code == TCL_CONTINUE) {
/*
@@ -1759,8 +1799,9 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
}
}
- if ((screenPtr->bindingDepth != 0) &&
- ((oldDispPtr != screenPtr->curDispPtr)
+ if ((winPtr->mainPtr != NULL)
+ && (screenPtr->bindingDepth != 0)
+ && ((oldDispPtr != screenPtr->curDispPtr)
|| (oldScreen != screenPtr->curScreenIndex))) {
/*
@@ -1777,14 +1818,21 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
Tcl_DStringFree(&scripts);
if (matchCount > 0) {
- PendingBinding **curPtrPtr;
+ if (winPtr->mainPtr != NULL) {
+ /*
+ * Delete the pending list from the list of pending scripts
+ * for this window.
+ */
+
+ PendingBinding **curPtrPtr;
- for (curPtrPtr = &bindInfoPtr->pendingList; ; ) {
- if (*curPtrPtr == pendingPtr) {
- *curPtrPtr = pendingPtr->nextPtr;
- break;
+ for (curPtrPtr = &bindInfoPtr->pendingList; ; ) {
+ if (*curPtrPtr == pendingPtr) {
+ *curPtrPtr = pendingPtr->nextPtr;
+ break;
+ }
+ curPtrPtr = &(*curPtrPtr)->nextPtr;
}
- curPtrPtr = &(*curPtrPtr)->nextPtr;
}
if (pendingPtr != &staticPending) {
ckfree((char *) pendingPtr);
@@ -2164,7 +2212,8 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr)
bestPtr = matchPtr;
bestSourcePtr = sourcePtr;
- nextSequence: continue;
+ nextSequence:
+ continue;
}
*sourcePtrPtr = bestSourcePtr;
@@ -2208,8 +2257,11 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr)
int number, flags, length;
#define NUM_SIZE 40
char *string;
+ Tcl_DString buf;
char numStorage[NUM_SIZE+1];
+ Tcl_DStringInit(&buf);
+
if (eventPtr->type < TK_LASTEVENT) {
flags = flagArray[eventPtr->type];
} else {
@@ -2358,37 +2410,8 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr)
goto doNumber;
case 'A':
if (flags & KEY) {
- int numChars;
-
- /*
- * If we're using input methods and this is a keypress
- * event, invoke XmbTkFindStateString. Otherwise just use
- * the older XTkFindStateString.
- */
-
-#ifdef TK_USE_INPUT_METHODS
- Status status;
- if ((winPtr->inputContext != NULL)
- && (eventPtr->type == KeyPress)) {
- numChars = XmbLookupString(winPtr->inputContext,
- &eventPtr->xkey, numStorage, NUM_SIZE,
- (KeySym *) NULL, &status);
- if ((status != XLookupChars)
- && (status != XLookupBoth)) {
- numChars = 0;
- }
- } else {
- numChars = XLookupString(&eventPtr->xkey, numStorage,
- NUM_SIZE, (KeySym *) NULL,
- (XComposeStatus *) NULL);
- }
-#else /* TK_USE_INPUT_METHODS */
- numChars = XLookupString(&eventPtr->xkey, numStorage,
- NUM_SIZE, (KeySym *) NULL,
- (XComposeStatus *) NULL);
-#endif /* TK_USE_INPUT_METHODS */
- numStorage[numChars] = '\0';
- string = numStorage;
+ Tcl_DStringFree(&buf);
+ string = TkpGetString(winPtr, eventPtr, &buf);
}
goto doString;
case 'B':
@@ -2482,6 +2505,7 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr)
Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
before += 2;
}
+ Tcl_DStringFree(&buf);
}
/*
@@ -2514,7 +2538,7 @@ ChangeScreen(interp, dispName, screenIndex)
{
Tcl_DString cmd;
int code;
- char screen[30];
+ char screen[TCL_INTEGER_SPACE];
Tcl_DStringInit(&cmd);
Tcl_DStringAppend(&cmd, "tkScreenChanged ", 16);
@@ -2548,87 +2572,98 @@ ChangeScreen(interp, dispName, screenIndex)
*/
int
-Tk_EventCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_EventObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- int i;
- size_t length;
- char *option;
+ int index;
Tk_Window tkwin;
VirtualEventTable *vetPtr;
TkBindInfo bindInfo;
-
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option ?arg1?\"", (char *) NULL);
- return TCL_ERROR;
- }
-
- option = argv[1];
- length = strlen(option);
- if (length == 0) {
- goto badopt;
- }
+ static char *optionStrings[] = {
+ "add", "delete", "generate", "info",
+ NULL
+ };
+ enum options {
+ EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO
+ };
tkwin = (Tk_Window) clientData;
bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo;
vetPtr = &((BindInfo *) bindInfo)->virtualEventTable;
- if (strncmp(option, "add", length) == 0) {
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " add virtual sequence ?sequence ...?\"", (char *) NULL);
- return TCL_ERROR;
- }
- for (i = 3; i < argc; i++) {
- if (CreateVirtualEvent(interp, vetPtr, argv[2], argv[i])
- != TCL_OK) {
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ 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;
}
- } else if (strncmp(option, "delete", length) == 0) {
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " delete virtual ?sequence sequence ...?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 3) {
- return DeleteVirtualEvent(interp, vetPtr, argv[2], NULL);
- }
- for (i = 3; i < argc; i++) {
- if (DeleteVirtualEvent(interp, vetPtr, argv[2], argv[i])
- != TCL_OK) {
+ case EVENT_DELETE: {
+ int i;
+ char *name, *event;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "virtual ?sequence sequence ...?");
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;
}
- } else if (strncmp(option, "generate", length) == 0) {
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " generate window event ?options?\"", (char *) NULL);
- return TCL_ERROR;
+ 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;
}
- return HandleEventGenerate(interp, tkwin, argc - 2, argv + 2);
- } else if (strncmp(option, "info", length) == 0) {
- if (argc == 2) {
- GetAllVirtualEvents(interp, vetPtr);
- return TCL_OK;
- } else if (argc == 3) {
- return GetVirtualEvent(interp, vetPtr, argv[2]);
- } else {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " info ?virtual?\"", (char *) NULL);
- 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?");
+ return TCL_ERROR;
+ }
+ break;
}
- } else {
- badopt:
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": should be add, delete, generate, info", (char *) NULL);
- return TCL_ERROR;
}
return TCL_OK;
}
@@ -2715,8 +2750,8 @@ DeleteVirtualEventTable(vetPtr)
* 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 interp->result. If all went well then the return
- * value is TCL_OK.
+ * 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
@@ -2821,7 +2856,7 @@ CreateVirtualEvent(interp, vetPtr, virtString, eventString)
*
* Results:
* The result is a standard Tcl return value. If an error
- * occurs then interp->result will contain an error message.
+ * 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.
*
@@ -2873,7 +2908,10 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString)
eventPSPtr = FindSequence(interp, &vetPtr->patternTable, NULL,
eventString, 0, 0, &eventMask);
if (eventPSPtr == NULL) {
- return (interp->result[0] != '\0') ? TCL_ERROR : TCL_OK;
+ char *string;
+
+ string = Tcl_GetStringResult(interp);
+ return (string[0] != '\0') ? TCL_ERROR : TCL_OK;
}
}
@@ -2975,12 +3013,12 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString)
* given virtual event.
*
* Results:
- * The return value is TCL_OK and interp->result is filled with the
+ * 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, interp->result is filled with and empty string. If the
+ * 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 interp->result.
+ * returned and an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -3032,7 +3070,7 @@ GetVirtualEvent(interp, vetPtr, virtString)
* event defined.
*
* Results:
- * There is no return value. Interp->result is modified to
+ * 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.
*
@@ -3101,56 +3139,69 @@ GetAllVirtualEvents(interp, vetPtr)
*---------------------------------------------------------------------------
*/
static int
-HandleEventGenerate(interp, main, argc, argv)
- Tcl_Interp *interp; /* Interp for error messages and name lookup. */
- Tk_Window main; /* Main window associated with interp. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+HandleEventGenerate(interp, main, objc, objv)
+ Tcl_Interp *interp; /* Interp for errors return and name lookup. */
+ Tk_Window main; /* Main window associated with interp. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
+ XEvent event;
+ char *name, *p;
+ int count, flags, synch, i, number;
+ Tcl_QueuePosition pos;
Pattern pat;
- Tk_Window tkwin;
- char *p;
+ Tk_Window tkwin, tkwin2;
+ TkWindow *mainPtr;
unsigned long eventMask;
- int count, i, state, flags, synch;
- Tcl_QueuePosition pos;
- XEvent event;
+ static char *fieldStrings[] = {
+ "-when", "-above", "-borderwidth", "-button",
+ "-count", "-detail", "-focus", "-height",
+ "-keycode", "-keysym", "-mode", "-override",
+ "-place", "-root", "-rootx", "-rooty",
+ "-sendevent", "-serial", "-state", "-subwindow",
+ "-time", "-width", "-window", "-x",
+ "-y", NULL
+ };
+ enum field {
+ EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON,
+ EVENT_COUNT, 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,
+ EVENT_TIME, EVENT_WIDTH, EVENT_WINDOW, EVENT_X,
+ EVENT_Y
+ };
+
+ if (NameToWindow(interp, main, objv[0], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
- if (argv[0][0] == '.') {
- tkwin = Tk_NameToWindow(interp, argv[0], main);
- if (tkwin == NULL) {
- return TCL_ERROR;
- }
- } else {
- if (TkpScanWindowId(NULL, argv[0], &i) != TCL_OK) {
- Tcl_AppendResult(interp, "bad window name/identifier \"",
- argv[0], "\"", (char *) NULL);
- return TCL_ERROR;
- }
- tkwin = Tk_IdToWindow(Tk_Display(main), (Window) i);
- if ((tkwin == NULL) || (((TkWindow *) main)->mainPtr
- != ((TkWindow *) tkwin)->mainPtr)) {
- Tcl_AppendResult(interp, "window id \"", argv[0],
- "\" doesn't exist in this application", (char *) NULL);
- return TCL_ERROR;
- }
+ mainPtr = (TkWindow *) main;
+ 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);
+ return TCL_ERROR;
}
- p = argv[1];
+ name = Tcl_GetStringFromObj(objv[1], NULL);
+
+ p = name;
count = ParseEventDescription(interp, &p, &pat, &eventMask);
if (count == 0) {
return TCL_ERROR;
}
if (count != 1) {
- interp->result = "Double or Triple modifier not allowed";
+ Tcl_SetResult(interp, "Double or Triple modifier not allowed",
+ TCL_STATIC);
return TCL_ERROR;
}
if (*p != '\0') {
- interp->result = "only one event specification allowed";
- return TCL_ERROR;
- }
- if (argc & 1) {
- Tcl_AppendResult(interp, "value for \"", argv[argc - 1],
- "\" missing", (char *) NULL);
+ Tcl_SetResult(interp, "only one event specification allowed",
+ TCL_STATIC);
return TCL_ERROR;
}
@@ -3165,34 +3216,7 @@ HandleEventGenerate(interp, main, argc, argv)
if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) {
event.xkey.state = pat.needMods;
if (flags & KEY) {
- /*
- * When mapping from a keysym to a keycode, need information about
- * the modifier state that should be used so that when they call
- * XKeycodeToKeysym taking into account the xkey.state, they will
- * get back the original keysym.
- */
-
- if (pat.detail.keySym == NoSymbol) {
- event.xkey.keycode = 0;
- } else {
- event.xkey.keycode = XKeysymToKeycode(event.xany.display,
- pat.detail.keySym);
- }
- if (event.xkey.keycode != 0) {
- for (state = 0; state < 4; state++) {
- if (XKeycodeToKeysym(event.xany.display,
- event.xkey.keycode, state) == pat.detail.keySym) {
- if (state & 1) {
- event.xkey.state |= ShiftMask;
- }
- if (state & 2) {
- TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- event.xkey.state |= dispPtr->modeModMask;
- }
- break;
- }
- }
- }
+ SetKeycodeAndState(tkwin, pat.detail.keySym, &event);
} else if (flags & BUTTON) {
event.xbutton.button = pat.detail.button;
} else if (flags & VIRTUAL) {
@@ -3210,366 +3234,396 @@ HandleEventGenerate(interp, main, argc, argv)
synch = 1;
pos = TCL_QUEUE_TAIL;
- for (i = 2; i < argc; i += 2) {
- char *field, *value;
- Tk_Window tkwin2;
- int number;
- KeySym keysym;
+ for (i = 2; i < objc; i += 2) {
+ Tcl_Obj *optionPtr, *valuePtr;
+ int index;
- field = argv[i];
- value = argv[i+1];
-
- if (strcmp(field, "-when") == 0) {
- if (strcmp(value, "now") == 0) {
- synch = 1;
- } else if (strcmp(value, "head") == 0) {
- pos = TCL_QUEUE_HEAD;
- synch = 0;
- } else if (strcmp(value, "mark") == 0) {
- pos = TCL_QUEUE_MARK;
- synch = 0;
- } else if (strcmp(value, "tail") == 0) {
- pos = TCL_QUEUE_TAIL;
+ optionPtr = objv[i];
+ valuePtr = objv[i + 1];
+
+ if (Tcl_GetIndexFromObj(interp, optionPtr, fieldStrings, "option",
+ TCL_EXACT, &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ 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.
+ */
+
+ Tcl_AppendResult(interp, "value for \"",
+ Tcl_GetStringFromObj(optionPtr, NULL), "\" missing",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ switch ((enum field) index) {
+ case EVENT_WHEN: {
+ pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr,
+ queuePosition, valuePtr);
+ if ((int) pos < -1) {
+ return TCL_ERROR;
+ }
synch = 0;
- } else {
- Tcl_AppendResult(interp, "bad position \"", value,
- "\": should be now, head, mark, tail", (char *) NULL);
- return TCL_ERROR;
+ if ((int) pos == -1) {
+ synch = 1;
+ }
+ break;
}
- } else if (strcmp(field, "-above") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, main);
- if (tkwin2 == NULL) {
+ case EVENT_ABOVE: {
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
return TCL_ERROR;
}
- number = Tk_WindowId(tkwin2);
- } else if (TkpScanWindowId(interp, value, &number)
- != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & CONFIG) {
- event.xconfigure.above = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-borderwidth") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ if (flags & CONFIG) {
+ event.xconfigure.above = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
}
- if (flags & (CREATE|CONFIG)) {
- event.xcreatewindow.border_width = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-button") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ 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;
}
- if (flags & BUTTON) {
- event.xbutton.button = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-count") == 0) {
- if (Tcl_GetInt(interp, value, &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 & EXPOSE) {
- event.xexpose.count = 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;
}
- } else if (strcmp(field, "-detail") == 0) {
- number = TkFindStateNum(interp, field, notifyDetail, value);
- if (number < 0) {
- 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 & FOCUS) {
- event.xfocus.detail = number;
- } else if (flags & CROSSING) {
- event.xcrossing.detail = number;
- } else {
- goto badopt;
+ case EVENT_KEYCODE: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & KEY) {
+ event.xkey.keycode = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- } else if (strcmp(field, "-focus") == 0) {
- if (Tcl_GetBoolean(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_KEYSYM: {
+ KeySym keysym;
+ char *value;
+
+ value = Tcl_GetStringFromObj(valuePtr, NULL);
+ keysym = TkStringToKeysym(value);
+ if (keysym == NoSymbol) {
+ Tcl_AppendResult(interp, "unknown keysym \"", value, "\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ SetKeycodeAndState(tkwin, keysym, &event);
+ if (event.xkey.keycode == 0) {
+ Tcl_AppendResult(interp, "no keycode for keysym \"", value,
+ "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if ((flags & KEY) == 0) {
+ goto badopt;
+ }
+ break;
}
- if (flags & CROSSING) {
- event.xcrossing.focus = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-height") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ 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;
}
- if (flags & EXPOSE) {
- event.xexpose.height = number;
- } else if (flags & CONFIG) {
- event.xconfigure.height = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-keycode") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ 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;
}
- if (flags & KEY) {
- event.xkey.keycode = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-keysym") == 0) {
- keysym = TkStringToKeysym(value);
- if (keysym == NoSymbol) {
- Tcl_AppendResult(interp, "unknown keysym \"", value,
- "\"", (char *) NULL);
- return TCL_ERROR;
+ 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;
}
- /*
- * When mapping from a keysym to a keycode, need information about
- * the modifier state that should be used so that when they call
- * XKeycodeToKeysym taking into account the xkey.state, they will
- * get back the original keysym.
- */
+ case EVENT_SEND: {
+ CONST char *value;
- number = XKeysymToKeycode(event.xany.display, keysym);
- if (number == 0) {
- Tcl_AppendResult(interp, "no keycode for keysym \"", value,
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
- for (state = 0; state < 4; state++) {
- if (XKeycodeToKeysym(event.xany.display, (unsigned) number,
- state) == keysym) {
- if (state & 1) {
- event.xkey.state |= ShiftMask;
+ 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.
+ */
+
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number)
+ != TCL_OK) {
+ return TCL_ERROR;
}
- if (state & 2) {
- TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- event.xkey.state |= dispPtr->modeModMask;
+ } else {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &number)
+ != TCL_OK) {
+ return TCL_ERROR;
}
- break;
}
- }
- if (flags & KEY) {
- event.xkey.keycode = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-mode") == 0) {
- number = TkFindStateNum(interp, field, notifyMode, value);
- if (number < 0) {
- return TCL_ERROR;
- }
- if (flags & CROSSING) {
- event.xcrossing.mode = number;
- } else if (flags & FOCUS) {
- event.xfocus.mode = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-override") == 0) {
- if (Tcl_GetBoolean(interp, value, &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;
- }
- } else if (strcmp(field, "-place") == 0) {
- number = TkFindStateNum(interp, field, circPlace, value);
- if (number < 0) {
- return TCL_ERROR;
- }
- if (flags & CIRC) {
- event.xcirculate.place = number;
- } else {
- goto badopt;
+ event.xany.send_event = number;
+ break;
}
- } else if (strcmp(field, "-root") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, main);
- if (tkwin2 == NULL) {
+ case EVENT_SERIAL: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
return TCL_ERROR;
}
- number = Tk_WindowId(tkwin2);
- } else if (TkpScanWindowId(interp, value, &number)
- != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.root = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-rootx") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.x_root = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-rooty") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ event.xany.serial = number;
+ break;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.y_root = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-sendevent") == 0) {
- 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_GetInt(interp, value, &number) != TCL_OK) {
+ case EVENT_SUBWINDOW: {
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
return TCL_ERROR;
}
- } else {
- if (Tcl_GetBoolean(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.subwindow = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
}
+ break;
}
- event.xany.send_event = number;
- } else if (strcmp(field, "-serial") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- event.xany.serial = number;
- } else if (strcmp(field, "-state") == 0) {
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
+ case EVENT_TIME: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
return TCL_ERROR;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) {
- event.xkey.state = number;
+ if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.time = (Time) number;
+ } else if (flags & PROP) {
+ event.xproperty.time = (Time) number;
} else {
- event.xcrossing.state = number;
+ goto badopt;
}
- } else if (flags & VISIBILITY) {
- number = TkFindStateNum(interp, field, visNotify, value);
- if (number < 0) {
+ break;
+ }
+ case EVENT_WIDTH: {
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number)
+ != TCL_OK) {
return TCL_ERROR;
}
- event.xvisibility.state = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-subwindow") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, main);
- if (tkwin2 == NULL) {
- return TCL_ERROR;
+ if (flags & EXPOSE) {
+ event.xexpose.width = number;
+ } else if (flags & (CREATE|CONFIG)) {
+ event.xcreatewindow.width = number;
+ } else {
+ goto badopt;
}
- number = Tk_WindowId(tkwin2);
- } else if (TkpScanWindowId(interp, value, &number)
- != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.subwindow = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-time") == 0) {
- if (Tcl_GetInt(interp, value, &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;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-width") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & EXPOSE) {
- event.xexpose.width = number;
- } else if (flags & (CREATE|CONFIG)) {
- event.xcreatewindow.width = number;
- } else {
- goto badopt;
+ break;
}
- } else if (strcmp(field, "-window") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, main);
- if (tkwin2 == NULL) {
+ case EVENT_WINDOW: {
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
return TCL_ERROR;
}
- number = Tk_WindowId(tkwin2);
- } else if (TkpScanWindowId(interp, value, &number)
- != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & (CREATE|DESTROY|UNMAP|MAP|REPARENT|CONFIG
- |GRAVITY|CIRC)) {
- event.xcreatewindow.window = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-x") == 0) {
- int rootX, rootY;
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- Tk_GetRootCoords(tkwin, &rootX, &rootY);
- rootX += number;
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.x = number;
- event.xkey.x_root = rootX;
- } 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;
+ if (flags & (CREATE|DESTROY|UNMAP|MAP|REPARENT|CONFIG
+ |GRAVITY|CIRC)) {
+ event.xcreatewindow.window = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
}
- } else if (strcmp(field, "-y") == 0) {
- int rootX, rootY;
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_X: {
+ int rootX, rootY;
+
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tk_GetRootCoords(tkwin, &rootX, &rootY);
+ rootX += number;
+ if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.x = number;
+ event.xkey.x_root = rootX;
+ } 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;
+ }
+ break;
}
- Tk_GetRootCoords(tkwin, &rootX, &rootY);
- rootY += number;
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.y = number;
- event.xkey.y_root = rootY;
- } 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;
+ case EVENT_Y: {
+ int rootX, rootY;
+
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tk_GetRootCoords(tkwin, &rootX, &rootY);
+ rootY += number;
+ if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.y = number;
+ event.xkey.y_root = rootY;
+ } 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;
+ }
+ break;
}
- } else {
- badopt:
- Tcl_AppendResult(interp, "bad option to ", argv[1],
- " event: \"", field, "\"", (char *) NULL);
- return TCL_ERROR;
}
+ continue;
+
+ badopt:
+ Tcl_AppendResult(interp, name, " event doesn't accept \"",
+ Tcl_GetStringFromObj(optionPtr, NULL), "\" option", NULL);
+ return TCL_ERROR;
}
-
if (synch != 0) {
Tk_HandleEvent(&event);
} else {
@@ -3577,6 +3631,80 @@ HandleEventGenerate(interp, main, argc, argv)
}
Tcl_ResetResult(interp);
return TCL_OK;
+
+}
+static int
+NameToWindow(interp, main, objPtr, tkwinPtr)
+ Tcl_Interp *interp; /* Interp for error return and name lookup. */
+ Tk_Window main; /* 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;
+ int id;
+
+ name = Tcl_GetStringFromObj(objPtr, NULL);
+ if (name[0] == '.') {
+ tkwin = Tk_NameToWindow(interp, name, main);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ *tkwinPtr = tkwin;
+ } else {
+ if (TkpScanWindowId(NULL, name, &id) != TCL_OK) {
+ Tcl_AppendResult(interp, "bad window name/identifier \"",
+ name, "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ *tkwinPtr = Tk_IdToWindow(Tk_Display(main), (Window) id);
+ }
+ return TCL_OK;
+}
+
+ /*
+ * When mapping from a keysym to a keycode, need
+ * information about the modifier state that should be used
+ * so that when they call XKeycodeToKeysym taking into
+ * account the xkey.state, they will get back the original
+ * keysym.
+ */
+
+
+static void
+SetKeycodeAndState(tkwin, keySym, eventPtr)
+ Tk_Window tkwin;
+ KeySym keySym;
+ XEvent *eventPtr;
+{
+ Display *display;
+ int state;
+ KeyCode keycode;
+
+ display = Tk_Display(tkwin);
+
+ if (keySym == NoSymbol) {
+ keycode = 0;
+ } else {
+ keycode = XKeysymToKeycode(display, keySym);
+ }
+ if (keycode != 0) {
+ for (state = 0; state < 4; state++) {
+ if (XKeycodeToKeysym(display, keycode, state) == keySym) {
+ if (state & 1) {
+ eventPtr->xkey.state |= ShiftMask;
+ }
+ if (state & 2) {
+ TkDisplay *dispPtr;
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ eventPtr->xkey.state |= dispPtr->modeModMask;
+ }
+ break;
+ }
+ }
+ }
+ eventPtr->xkey.keycode = keycode;
}
/*
@@ -3590,7 +3718,7 @@ HandleEventGenerate(interp, main, argc, argv)
* 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 interp->result. Otherwise the return
+ * will be left in the interp's result. Otherwise the return
* value is a Tk_Uid that represents the virtual event.
*
* Side effects:
@@ -3636,7 +3764,7 @@ GetVirtualEventUid(interp, virtString)
* 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 interp->result contains a message describing the problem.
+ * 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
@@ -3712,8 +3840,9 @@ FindSequence(interp, patternTablePtr, object, eventString, create,
if (eventMask & VirtualEventMask) {
if (allowVirtual == 0) {
- interp->result =
- "virtual event not allowed in definition of another virtual event";
+ Tcl_SetResult(interp,
+ "virtual event not allowed in definition of another virtual event",
+ TCL_STATIC);
return NULL;
}
virtualFound = 1;
@@ -3744,11 +3873,12 @@ FindSequence(interp, patternTablePtr, object, eventString, create,
*/
if (numPats == 0) {
- interp->result = "no events specified in binding";
+ Tcl_SetResult(interp, "no events specified in binding", TCL_STATIC);
return NULL;
}
if ((numPats > 1) && (virtualFound != 0)) {
- interp->result = "virtual events may not be composed";
+ Tcl_SetResult(interp, "virtual events may not be composed",
+ TCL_STATIC);
return NULL;
}
@@ -3774,6 +3904,14 @@ FindSequence(interp, patternTablePtr, object, eventString, create,
if (new) {
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.
+ */
+
return NULL;
}
psPtr = (PatSeq *) ckalloc((unsigned) (sizeof(PatSeq)
@@ -3863,8 +4001,10 @@ ParseEventDescription(interp, eventStringPtr, patPtr,
if (isprint(UCHAR(*p))) {
patPtr->detail.keySym = *p;
} else {
- sprintf(interp->result,
- "bad ASCII character 0x%x", (unsigned char) *p);
+ char buf[64];
+
+ sprintf(buf, "bad ASCII character 0x%x", (unsigned char) *p);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return 0;
}
}
@@ -3904,11 +4044,13 @@ ParseEventDescription(interp, eventStringPtr, patPtr,
char *field = p + 1;
p = strchr(field, '>');
if (p == field) {
- interp->result = "virtual event \"<<>>\" is badly formed";
+ Tcl_SetResult(interp, "virtual event \"<<>>\" is badly formed",
+ TCL_STATIC);
return 0;
}
if ((p == NULL) || (p[1] != '>')) {
- interp->result = "missing \">\" in virtual binding";
+ Tcl_SetResult(interp, "missing \">\" in virtual binding",
+ TCL_STATIC);
return 0;
}
*p = '\0';
@@ -3995,7 +4137,8 @@ ParseEventDescription(interp, eventStringPtr, patPtr,
}
}
} else if (eventFlags == 0) {
- interp->result = "no event type or button # or keysym";
+ Tcl_SetResult(interp, "no event type or button # or keysym",
+ TCL_STATIC);
return 0;
}
@@ -4006,11 +4149,13 @@ ParseEventDescription(interp, eventStringPtr, patPtr,
while (*p != '\0') {
p++;
if (*p == '>') {
- interp->result = "extra characters after detail in binding";
+ Tcl_SetResult(interp,
+ "extra characters after detail in binding",
+ TCL_STATIC);
return 0;
}
}
- interp->result = "missing \">\" in binding";
+ Tcl_SetResult(interp, "missing \">\" in binding", TCL_STATIC);
return 0;
}
p++;
@@ -4085,7 +4230,7 @@ GetPatternString(psPtr, dsPtr)
Tcl_DString *dsPtr;
{
Pattern *patPtr;
- char c, buffer[10];
+ char c, buffer[TCL_INTEGER_SPACE];
int patsLeft, needMods;
ModInfo *modPtr;
EventInfo *eiPtr;
@@ -4506,7 +4651,7 @@ TkKeysymToString(keysym)
*
* Results:
* Returns the result of evaluating script, including both a standard
- * Tcl completion code and a string in interp->result.
+ * Tcl completion code and a string in the interp's result.
*
* Side effects:
* None.
diff --git a/generic/tkBitmap.c b/generic/tkBitmap.c
index fe46b35..25c1d37 100644
--- a/generic/tkBitmap.c
+++ b/generic/tkBitmap.c
@@ -6,12 +6,12 @@
* also avoids interactions with the X server.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkBitmap.c 1.45 97/07/24 17:27:38
+ * SCCS: @(#) tkBitmap.c 1.56 98/01/19 11:47:55
*/
#include "tkPort.h"
@@ -51,28 +51,41 @@
* "nameTable".
*/
-typedef struct {
+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. */
int width, height; /* Dimensions of bitmap. */
Display *display; /* Display for which bitmap is valid. */
- int refCount; /* Number of active uses of bitmap. */
- Tcl_HashEntry *hashPtr; /* Entry in nameTable for this structure
+ 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
+ * 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. */
+ Tcl_HashEntry *nameHashPtr; /* Entry in nameTable 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) are
+ * chained together off a single entry in
+ * nameTable. */
} TkBitmap;
/*
- * Hash table to map from a textual description of a bitmap to the
- * TkBitmap record for the bitmap, and key structure used in that
- * hash table:
+ * Hash table to map from a textual name for a bitmap to the
+ * first TkBitmap record for that name:
*/
static Tcl_HashTable nameTable;
-typedef struct {
- Tk_Uid name; /* Textual name for desired bitmap. */
- Screen *screen; /* Screen on which bitmap will be used. */
-} NameKey;
/*
* Hash table that maps from <display + bitmap id> to the TkBitmap structure
@@ -86,7 +99,7 @@ typedef struct {
} IdKey;
/*
- * Hash table create by Tk_DefineBitmap to map from a name to a
+ * 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.
@@ -96,7 +109,7 @@ Tcl_HashTable tkPredefBitmapTable;
/*
* Hash table used by Tk_GetBitmapFromData to map from a collection
- * of in-core data about a bitmap to a Tk_Uid giving an automatically-
+ * of in-core data about a bitmap to a reference giving an automatically-
* generated name for the bitmap:
*/
@@ -114,6 +127,123 @@ static int initialized = 0; /* 0 means static structures haven't been
*/
static void BitmapInit _ANSI_ARGS_((void));
+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, char *name));
+static TkBitmap * GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
+static void InitBitmapObj _ANSI_ARGS_((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.
+ */
+
+static Tcl_ObjType bitmapObjType = {
+ "bitmap", /* name */
+ FreeBitmapObjProc, /* freeIntRepProc */
+ DupBitmapObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocBitmapFromObj --
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkBitmap *bitmapPtr;
+
+ if (objPtr->typePtr != &bitmapObjType) {
+ InitBitmapObj(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 (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.
+ */
+
+ FreeBitmapObjProc(objPtr);
+ bitmapPtr = NULL;
+ } else if (Tk_Display(tkwin) == bitmapPtr->display) {
+ 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.
+ */
+
+ if (bitmapPtr != NULL) {
+ TkBitmap *firstBitmapPtr =
+ (TkBitmap *) Tcl_GetHashValue(bitmapPtr->nameHashPtr);
+ FreeBitmapObjProc(objPtr);
+ for (bitmapPtr = firstBitmapPtr; bitmapPtr != NULL;
+ bitmapPtr = bitmapPtr->nextPtr) {
+ if (Tk_Display(tkwin) == bitmapPtr->display) {
+ bitmapPtr->resourceRefCount++;
+ bitmapPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
+ return bitmapPtr->bitmap;
+ }
+ }
+ }
+
+ /*
+ * Still no luck. Call GetBitmap to allocate a new TkBitmap object.
+ */
+
+ bitmapPtr = GetBitmap(interp, tkwin, Tcl_GetString(objPtr));
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
+ if (bitmapPtr == NULL) {
+ return None;
+ }
+ bitmapPtr->objRefCount++;
+ return bitmapPtr->bitmap;
+}
/*
*----------------------------------------------------------------------
@@ -127,7 +257,7 @@ static void BitmapInit _ANSI_ARGS_((void));
* 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 interp->result. The caller should never
+ * 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.
*
@@ -145,13 +275,54 @@ Tk_GetBitmap(interp, tkwin, string)
Tcl_Interp *interp; /* Interpreter to use for error reporting,
* this may be NULL. */
Tk_Window tkwin; /* Window in which bitmap will be used. */
- Tk_Uid string; /* Description of bitmap. See manual entry
+ char *string; /* Description of bitmap. See manual entry
+ * for details on legal syntax. */
+{
+ TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string);
+ if (bitmapPtr == NULL) {
+ return None;
+ }
+ return bitmapPtr->bitmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkBitmap *
+GetBitmap(interp, tkwin, string)
+ Tcl_Interp *interp; /* Interpreter to use for error reporting,
+ * this may be NULL. */
+ Tk_Window tkwin; /* Window in which bitmap will be used. */
+ char *string; /* Description of bitmap. See manual entry
* for details on legal syntax. */
{
- NameKey nameKey;
IdKey idKey;
- Tcl_HashEntry *nameHashPtr, *idHashPtr, *predefHashPtr;
- register TkBitmap *bitmapPtr;
+ Tcl_HashEntry *nameHashPtr, *predefHashPtr;
+ TkBitmap *bitmapPtr, *existingBitmapPtr;
TkPredefBitmap *predefPtr;
int new;
Pixmap bitmap;
@@ -162,13 +333,18 @@ Tk_GetBitmap(interp, tkwin, string)
BitmapInit();
}
- nameKey.name = string;
- nameKey.screen = Tk_Screen(tkwin);
- nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
+ nameHashPtr = Tcl_CreateHashEntry(&nameTable, string, &new);
if (!new) {
- bitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
- bitmapPtr->refCount++;
- return bitmapPtr->bitmap;
+ existingBitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr);
+ for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL;
+ bitmapPtr = bitmapPtr->nextPtr) {
+ if (Tk_Display(tkwin) == bitmapPtr->display) {
+ bitmapPtr->resourceRefCount++;
+ return bitmapPtr;
+ }
+ }
+ } else {
+ existingBitmapPtr = NULL;
}
/*
@@ -194,7 +370,7 @@ Tk_GetBitmap(interp, tkwin, string)
goto error;
}
result = XReadBitmapFile(Tk_Display(tkwin),
- RootWindowOfScreen(nameKey.screen), string,
+ RootWindowOfScreen(Tk_Screen(tkwin)), string,
(unsigned int *) &width, (unsigned int *) &height,
&bitmap, &dummy2, &dummy2);
if (result != BitmapSuccess) {
@@ -236,7 +412,8 @@ Tk_GetBitmap(interp, tkwin, string)
}
} else {
bitmap = XCreateBitmapFromData(Tk_Display(tkwin),
- RootWindowOfScreen(nameKey.screen), predefPtr->source,
+ RootWindowOfScreen(Tk_Screen(tkwin)),
+ predefPtr->source,
(unsigned) width, (unsigned) height);
}
}
@@ -251,22 +428,26 @@ Tk_GetBitmap(interp, tkwin, string)
bitmapPtr->width = width;
bitmapPtr->height = height;
bitmapPtr->display = Tk_Display(tkwin);
- bitmapPtr->refCount = 1;
- bitmapPtr->hashPtr = nameHashPtr;
+ bitmapPtr->resourceRefCount = 1;
+ bitmapPtr->objRefCount = 0;
+ bitmapPtr->nameHashPtr = nameHashPtr;
idKey.display = bitmapPtr->display;
idKey.pixmap = bitmap;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
+ bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
&new);
if (!new) {
panic("bitmap already registered in Tk_GetBitmap");
}
+ bitmapPtr->nextPtr = existingBitmapPtr;
Tcl_SetHashValue(nameHashPtr, bitmapPtr);
- Tcl_SetHashValue(idHashPtr, bitmapPtr);
- return bitmapPtr->bitmap;
+ Tcl_SetHashValue(bitmapPtr->idHashPtr, bitmapPtr);
+ return bitmapPtr;
error:
- Tcl_DeleteHashEntry(nameHashPtr);
- return None;
+ if (new) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
+ return NULL;
}
/*
@@ -280,7 +461,7 @@ Tk_GetBitmap(interp, tkwin, string)
*
* Results:
* A standard Tcl result. If an error occurs then TCL_ERROR is
- * returned and a message is left in interp->result.
+ * 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
@@ -292,7 +473,7 @@ Tk_GetBitmap(interp, tkwin, string)
int
Tk_DefineBitmap(interp, name, source, width, height)
Tcl_Interp *interp; /* Interpreter to use for error reporting. */
- Tk_Uid name; /* Name to use for bitmap. Must not already
+ char *name; /* Name to use for bitmap. Must not already
* be defined as a bitmap. */
char *source; /* Address of bits for bitmap. */
int width; /* Width of bitmap. */
@@ -338,7 +519,7 @@ Tk_DefineBitmap(interp, name, source, width, height)
*--------------------------------------------------------------
*/
-Tk_Uid
+char *
Tk_NameOfBitmap(display, bitmap)
Display *display; /* Display for which bitmap was
* allocated. */
@@ -360,7 +541,7 @@ Tk_NameOfBitmap(display, bitmap)
goto unknown;
}
bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
- return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
+ return bitmapPtr->nameHashPtr->key.string;
}
/*
@@ -413,6 +594,56 @@ 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
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeBitmap(bitmapPtr)
+ TkBitmap *bitmapPtr; /* Bitmap to be released. */
+{
+ TkBitmap *prevPtr;
+
+ bitmapPtr->resourceRefCount--;
+ if (bitmapPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
+ Tcl_DeleteHashEntry(bitmapPtr->idHashPtr);
+ prevPtr = (TkBitmap *) Tcl_GetHashValue(bitmapPtr->nameHashPtr);
+ if (prevPtr == bitmapPtr) {
+ if (bitmapPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(bitmapPtr->nameHashPtr);
+ } else {
+ Tcl_SetHashValue(bitmapPtr->nameHashPtr, bitmapPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != bitmapPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = bitmapPtr->nextPtr;
+ }
+ if (bitmapPtr->objRefCount == 0) {
+ ckfree((char *) bitmapPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_FreeBitmap --
*
* This procedure is called to release a bitmap allocated by
@@ -435,7 +666,6 @@ Tk_FreeBitmap(display, bitmap)
Pixmap bitmap; /* Bitmap to be released. */
{
Tcl_HashEntry *idHashPtr;
- register TkBitmap *bitmapPtr;
IdKey idKey;
if (!initialized) {
@@ -448,13 +678,105 @@ Tk_FreeBitmap(display, bitmap)
if (idHashPtr == NULL) {
panic("Tk_FreeBitmap received unknown bitmap argument");
}
- bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
- bitmapPtr->refCount--;
- if (bitmapPtr->refCount == 0) {
- Tk_FreePixmap(bitmapPtr->display, bitmapPtr->bitmap);
- Tcl_DeleteHashEntry(idHashPtr);
- Tcl_DeleteHashEntry(bitmapPtr->hashPtr);
- ckfree((char *) bitmapPtr);
+ FreeBitmap((TkBitmap *) Tcl_GetHashValue(idHashPtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ FreeBitmap(GetBitmapFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeBitmapObjProc(objPtr)
+ Tcl_Obj *objPtr; /* The object we are releasing. */
+{
+ TkBitmap *bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (bitmapPtr != NULL) {
+ bitmapPtr->objRefCount--;
+ if ((bitmapPtr->objRefCount == 0)
+ && (bitmapPtr->resourceRefCount == 0)) {
+ ckfree((char *) bitmapPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupBitmapObjProc --
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupBitmapObjProc(srcObjPtr, dupObjPtr)
+ 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;
+
+ if (bitmapPtr != NULL) {
+ bitmapPtr->objRefCount++;
}
}
@@ -471,7 +793,7 @@ Tk_FreeBitmap(display, bitmap)
* 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
- * interp->result. The caller should never modify the bitmap that
+ * 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.
*
@@ -494,9 +816,9 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height)
{
DataKey nameKey;
Tcl_HashEntry *dataHashPtr;
- Tk_Uid name;
int new;
- char string[20];
+ char string[16 + TCL_INTEGER_SPACE];
+ char *name;
static int autoNumber = 0;
if (!initialized) {
@@ -508,11 +830,11 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height)
nameKey.height = height;
dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new);
if (!new) {
- name = (Tk_Uid) Tcl_GetHashValue(dataHashPtr);
+ name = (char *) Tcl_GetHashValue(dataHashPtr);
} else {
autoNumber++;
sprintf(string, "_tk%d", autoNumber);
- name = Tk_GetUid(string);
+ name = string;
Tcl_SetHashValue(dataHashPtr, name);
if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
Tcl_DeleteHashEntry(dataHashPtr);
@@ -525,6 +847,142 @@ 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.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_GetBitmapFromObj(tkwin, objPtr)
+ Tk_Window tkwin;
+ Tcl_Obj *objPtr; /* The object from which to get pixels. */
+{
+ TkBitmap *bitmapPtr = GetBitmapFromObj(tkwin, objPtr);
+ return bitmapPtr->bitmap;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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
+ * bitmap. */
+{
+ TkBitmap *bitmapPtr;
+ Tcl_HashEntry *hashPtr;
+
+ if (objPtr->typePtr != &bitmapObjType) {
+ InitBitmapObj(objPtr);
+ }
+
+ bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1;
+ if (bitmapPtr != NULL) {
+ if ((bitmapPtr->resourceRefCount > 0)
+ && (Tk_Display(tkwin) == bitmapPtr->display)) {
+ return bitmapPtr;
+ }
+ hashPtr = bitmapPtr->nameHashPtr;
+ FreeBitmapObjProc(objPtr);
+ } else {
+ hashPtr = Tcl_FindHashEntry(&nameTable, 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.
+ */
+
+ for (bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr);
+ bitmapPtr != NULL; bitmapPtr = bitmapPtr->nextPtr) {
+ if (Tk_Display(tkwin) == bitmapPtr->display) {
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) bitmapPtr;
+ bitmapPtr->objRefCount++;
+ return bitmapPtr;
+ }
+ }
+
+ error:
+ panic("GetBitmapFromObj called with non-existent bitmap!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitBitmapObj --
+ *
+ * Bookeeping procedure 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitBitmapObj(objPtr)
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+ objPtr->typePtr = &bitmapObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* BitmapInit --
*
* Initialize the structures used for bitmap management.
@@ -545,9 +1003,9 @@ BitmapInit()
dummy = Tcl_CreateInterp();
initialized = 1;
- Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
+ Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
- Tcl_InitHashTable(&tkPredefBitmapTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&tkPredefBitmapTable, TCL_STRING_KEYS);
/*
* The call below is tricky: can't use sizeof(IdKey) because it
@@ -583,3 +1041,51 @@ BitmapInit()
Tcl_DeleteInterp(dummy);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugBitmap --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkBitmap *bitmapPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&nameTable, name);
+ if (hashPtr != NULL) {
+ bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr);
+ if (bitmapPtr == NULL) {
+ 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_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
diff --git a/generic/tkButton.c b/generic/tkButton.c
index c9c25c2..527e761 100644
--- a/generic/tkButton.c
+++ b/generic/tkButton.c
@@ -3,199 +3,448 @@
*
* This module implements a collection of button-like
* widgets for the Tk toolkit. The widgets implemented
- * include labels, buttons, check buttons, and radio
- * buttons.
+ * include labels, buttons, checkbuttons, and radiobuttons.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkButton.c 1.144 97/07/31 09:04:57
+ * SCCS: @(#) tkButton.c 1.150 98/02/06 19:06:00
*/
#include "tkButton.h"
#include "default.h"
/*
- * Class names for buttons, indexed by one of the type values above.
+ * Class names for buttons, indexed by one of the type values defined
+ * in tkButton.h.
*/
static char *classNames[] = {"Label", "Button", "Checkbutton", "Radiobutton"};
/*
- * The class procedure table for the button widget.
+ * The following table defines the legal values for the -default option.
+ * It is used together with the "enum defaultValue" declaration in tkButton.h.
*/
-static int configFlags[] = {LABEL_MASK, BUTTON_MASK,
- CHECK_BUTTON_MASK, RADIO_BUTTON_MASK};
+static char *defaultStrings[] = {
+ "active", "disabled", "normal", (char *) NULL
+};
+
+/*
+ * The following table defines the legal values for the -state option.
+ * It is used together with the "enum state" declaration in tkButton.h.
+ */
+
+static char *stateStrings[] = {
+ "active", "disabled", "normal", (char *) NULL
+};
/*
- * Information used for parsing configuration specs:
+ * Information used for parsing configuration options. There is a
+ * separate table for each of the four widget classes.
*/
-Tk_ConfigSpec tkpButtonConfigSpecs[] = {
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_BUTTON_ACTIVE_BG_COLOR, Tk_Offset(TkButton, activeBorder),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK
- |TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_BUTTON_ACTIVE_BG_MONO, Tk_Offset(TkButton, activeBorder),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK
- |TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_BUTTON_ACTIVE_FG_COLOR, Tk_Offset(TkButton, activeFg),
- BUTTON_MASK|TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_CHKRAD_ACTIVE_FG_COLOR, Tk_Offset(TkButton, activeFg),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_BUTTON_ACTIVE_FG_MONO, Tk_Offset(TkButton, activeFg),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK
- |TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor",
- DEF_BUTTON_ANCHOR, Tk_Offset(TkButton, anchor), ALL_MASK},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_BUTTON_BG_COLOR, Tk_Offset(TkButton, normalBorder),
- ALL_MASK | TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_BUTTON_BG_MONO, Tk_Offset(TkButton, normalBorder),
- ALL_MASK | TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
- (char *) NULL, 0, ALL_MASK},
- {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
- (char *) NULL, 0, ALL_MASK},
- {TK_CONFIG_BITMAP, "-bitmap", "bitmap", "Bitmap",
- DEF_BUTTON_BITMAP, Tk_Offset(TkButton, bitmap),
- ALL_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidth), ALL_MASK},
- {TK_CONFIG_STRING, "-command", "command", "Command",
- DEF_BUTTON_COMMAND, Tk_Offset(TkButton, command),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_BUTTON_CURSOR, Tk_Offset(TkButton, cursor),
- ALL_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-default", "default", "Default",
- DEF_BUTTON_DEFAULT, Tk_Offset(TkButton, defaultState), BUTTON_MASK},
- {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
+static Tk_OptionSpec labelOptionSpecs[] = {
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {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_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) 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",
+ DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_LABEL_HIGHLIGHT_WIDTH,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, 0, 0, 0}
+};
+
+static Tk_OptionSpec buttonOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_BUTTON_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {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_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-default", "default", "Default",
+ DEF_BUTTON_DEFAULT, -1, Tk_Offset(TkButton, defaultState),
+ 0, (ClientData) defaultStrings, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "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_FONT, "-font", "font", "Font",
+ DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_BUTTON_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_BUTTON_PADX, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_BUTTON_PADY, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_BUTTON_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, (ClientData) stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, 0, 0}
+};
+
+static Tk_OptionSpec checkbuttonOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {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_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
"DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
- Tk_Offset(TkButton, disabledFg), BUTTON_MASK|CHECK_BUTTON_MASK
- |RADIO_BUTTON_MASK|TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
- "DisabledForeground", DEF_BUTTON_DISABLED_FG_MONO,
- Tk_Offset(TkButton, disabledFg), BUTTON_MASK|CHECK_BUTTON_MASK
- |RADIO_BUTTON_MASK|TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
- {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, ALL_MASK},
- {TK_CONFIG_FONT, "-font", "font", "Font",
- DEF_BUTTON_FONT, Tk_Offset(TkButton, tkfont),
- ALL_MASK},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_BUTTON_FG, Tk_Offset(TkButton, normalFg), LABEL_MASK|BUTTON_MASK},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_CHKRAD_FG, Tk_Offset(TkButton, normalFg), CHECK_BUTTON_MASK
- |RADIO_BUTTON_MASK},
- {TK_CONFIG_STRING, "-height", "height", "Height",
- DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightString), ALL_MASK},
- {TK_CONFIG_BORDER, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG,
- Tk_Offset(TkButton, highlightBorder), ALL_MASK},
- {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_BUTTON_HIGHLIGHT, Tk_Offset(TkButton, highlightColorPtr),
- ALL_MASK},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness",
- DEF_LABEL_HIGHLIGHT_WIDTH, Tk_Offset(TkButton, highlightWidth),
- LABEL_MASK},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness",
- DEF_BUTTON_HIGHLIGHT_WIDTH, Tk_Offset(TkButton, highlightWidth),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
- {TK_CONFIG_STRING, "-image", "image", "Image",
- DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imageString),
- ALL_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
- DEF_BUTTON_INDICATOR, Tk_Offset(TkButton, indicatorOn),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
- {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
- DEF_BUTTON_JUSTIFY, Tk_Offset(TkButton, justify), ALL_MASK},
- {TK_CONFIG_STRING, "-offvalue", "offValue", "Value",
- DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValue),
- CHECK_BUTTON_MASK},
- {TK_CONFIG_STRING, "-onvalue", "onValue", "Value",
- DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValue),
- CHECK_BUTTON_MASK},
- {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
- DEF_BUTTON_PADX, Tk_Offset(TkButton, padX), BUTTON_MASK},
- {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
- DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padX),
- LABEL_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
- {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
- DEF_BUTTON_PADY, Tk_Offset(TkButton, padY), BUTTON_MASK},
- {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
- DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padY),
- LABEL_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_BUTTON_RELIEF, Tk_Offset(TkButton, relief), BUTTON_MASK},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_LABCHKRAD_RELIEF, Tk_Offset(TkButton, relief),
- LABEL_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
- {TK_CONFIG_BORDER, "-selectcolor", "selectColor", "Background",
- DEF_BUTTON_SELECT_COLOR, Tk_Offset(TkButton, selectBorder),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_COLOR_ONLY
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_BORDER, "-selectcolor", "selectColor", "Background",
- DEF_BUTTON_SELECT_MONO, Tk_Offset(TkButton, selectBorder),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_MONO_ONLY
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-selectimage", "selectImage", "SelectImage",
- DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImageString),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-state", "state", "State",
- DEF_BUTTON_STATE, Tk_Offset(TkButton, state),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_LABEL_TAKE_FOCUS, Tk_Offset(TkButton, takeFocus),
- LABEL_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocus),
- BUTTON_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-text", "text", "Text",
- DEF_BUTTON_TEXT, Tk_Offset(TkButton, text), ALL_MASK},
- {TK_CONFIG_STRING, "-textvariable", "textVariable", "Variable",
- DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarName),
- ALL_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_INT, "-underline", "underline", "Underline",
- DEF_BUTTON_UNDERLINE, Tk_Offset(TkButton, underline), ALL_MASK},
- {TK_CONFIG_STRING, "-value", "value", "Value",
- DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValue),
- RADIO_BUTTON_MASK},
- {TK_CONFIG_STRING, "-variable", "variable", "Variable",
- DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarName),
- RADIO_BUTTON_MASK},
- {TK_CONFIG_STRING, "-variable", "variable", "Variable",
- DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarName),
- CHECK_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-width", "width", "Width",
- DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthString), ALL_MASK},
- {TK_CONFIG_PIXELS, "-wraplength", "wrapLength", "WrapLength",
- DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLength), ALL_MASK},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+ -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_FONT, "-font", "font", "Font",
+ DEF_BUTTON_FONT, -1, Tk_Offset(TkButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
+ DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn), 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_STRING, "-offvalue", "offValue", "Value",
+ DEF_BUTTON_OFF_VALUE, Tk_Offset(TkButton, offValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-onvalue", "onValue", "Value",
+ DEF_BUTTON_ON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
+ DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
+ TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},
+ {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
+ DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, (ClientData) stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ DEF_CHECKBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {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}
+};
+
+static Tk_OptionSpec radiobuttonOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(TkButton, activeBorder),
+ 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_CHKRAD_ACTIVE_FG_COLOR, -1, Tk_Offset(TkButton, activeFg),
+ TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_BUTTON_ANCHOR, -1, Tk_Offset(TkButton, anchor), 0, 0, 0},
+ {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_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_BUTTON_BITMAP, -1, Tk_Offset(TkButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_BUTTON_BORDER_WIDTH, Tk_Offset(TkButton, borderWidthPtr),
+ Tk_Offset(TkButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_BUTTON_COMMAND, Tk_Offset(TkButton, commandPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_BUTTON_CURSOR, -1, Tk_Offset(TkButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
+ "DisabledForeground", DEF_BUTTON_DISABLED_FG_COLOR,
+ -1, Tk_Offset(TkButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_BUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) 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",
+ DEF_CHKRAD_FG, -1, Tk_Offset(TkButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_BUTTON_HEIGHT, Tk_Offset(TkButton, heightPtr), -1, 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_BUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkButton, highlightBorder), 0,
+ (ClientData) DEF_BUTTON_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_BUTTON_HIGHLIGHT, -1, Tk_Offset(TkButton, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_BUTTON_HIGHLIGHT_WIDTH,
+ Tk_Offset(TkButton, highlightWidthPtr),
+ Tk_Offset(TkButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_BUTTON_IMAGE, Tk_Offset(TkButton, imagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
+ DEF_BUTTON_INDICATOR, -1, Tk_Offset(TkButton, indicatorOn),
+ 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkButton, justify), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_LABCHKRAD_PADX, Tk_Offset(TkButton, padXPtr),
+ Tk_Offset(TkButton, padX), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_LABCHKRAD_PADY, Tk_Offset(TkButton, padYPtr),
+ Tk_Offset(TkButton, padY), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LABCHKRAD_RELIEF, -1, Tk_Offset(TkButton, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectcolor", "selectColor", "Background",
+ DEF_BUTTON_SELECT_COLOR, -1, Tk_Offset(TkButton, selectBorder),
+ TK_OPTION_NULL_OK, (ClientData) DEF_BUTTON_SELECT_MONO, 0},
+ {TK_OPTION_STRING, "-selectimage", "selectImage", "SelectImage",
+ DEF_BUTTON_SELECT_IMAGE, Tk_Offset(TkButton, selectImagePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, (ClientData) stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_BUTTON_TAKE_FOCUS, Tk_Offset(TkButton, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_BUTTON_TEXT, Tk_Offset(TkButton, textPtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_BUTTON_TEXT_VARIABLE, Tk_Offset(TkButton, textVarNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_BUTTON_UNDERLINE, -1, Tk_Offset(TkButton, underline), 0, 0, 0},
+ {TK_OPTION_STRING, "-value", "value", "Value",
+ DEF_BUTTON_VALUE, Tk_Offset(TkButton, onValuePtr), -1, 0, 0, 0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ DEF_RADIOBUTTON_VARIABLE, Tk_Offset(TkButton, selVarNamePtr), -1,
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_BUTTON_WIDTH, Tk_Offset(TkButton, widthPtr), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_BUTTON_WRAP_LENGTH, Tk_Offset(TkButton, wrapLengthPtr),
+ Tk_Offset(TkButton, wrapLength), 0, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, 0, 0}
};
/*
- * String to print out in error messages, identifying options for
- * widget commands for different types of labels or buttons:
+ * 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 char *optionStrings[] = {
- "cget or configure",
- "cget, configure, flash, or invoke",
- "cget, configure, deselect, flash, invoke, select, or toggle",
- "cget, configure, deselect, flash, invoke, or select"
+static Tk_OptionSpec *optionSpecs[] = {
+ labelOptionSpecs,
+ buttonOptionSpecs,
+ checkbuttonOptionSpecs,
+ radiobuttonOptionSpecs
+};
+
+/*
+ * 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 char *commandNames[][8] = {
+ {"cget", "configure", (char *) NULL},
+ {"cget", "configure", "flash", "invoke", (char *) NULL},
+ {"cget", "configure", "deselect", "flash", "invoke", "select",
+ "toggle", (char *) NULL},
+ {"cget", "configure", "deselect", "flash", "invoke", "select",
+ (char *) NULL}
+};
+enum command {
+ COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE
+};
+static enum command map[][8] = {
+ {COMMAND_CGET, COMMAND_CONFIGURE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_INVOKE, COMMAND_SELECT}
};
/*
@@ -205,8 +454,8 @@ static char *optionStrings[] = {
static void ButtonCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static int ButtonCreate _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv,
- int type));
+ 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,
@@ -221,13 +470,13 @@ static char * ButtonTextVarProc _ANSI_ARGS_((ClientData clientData,
static char * ButtonVarProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, char *name1, char *name2,
int flags));
-static int ButtonWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+static int ButtonWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
static int ConfigureButton _ANSI_ARGS_((Tcl_Interp *interp,
- TkButton *butPtr, int argc, char **argv,
- int flags));
+ TkButton *butPtr, int objc,
+ Tcl_Obj *CONST objv[]));
static void DestroyButton _ANSI_ARGS_((TkButton *butPtr));
-
/*
*--------------------------------------------------------------
@@ -249,47 +498,43 @@ static void DestroyButton _ANSI_ARGS_((TkButton *butPtr));
*/
int
-Tk_ButtonCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_ButtonObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Either NULL or pointer to option table. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
- return ButtonCreate(clientData, interp, argc, argv, TYPE_BUTTON);
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_BUTTON);
}
int
-Tk_CheckbuttonCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_CheckbuttonObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Either NULL or pointer to option table. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
- return ButtonCreate(clientData, interp, argc, argv, TYPE_CHECK_BUTTON);
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_CHECK_BUTTON);
}
int
-Tk_LabelCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_LabelObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Either NULL or pointer to option table. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
- return ButtonCreate(clientData, interp, argc, argv, TYPE_LABEL);
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_LABEL);
}
int
-Tk_RadiobuttonCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_RadiobuttonObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Either NULL or pointer to option table. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
- return ButtonCreate(clientData, interp, argc, argv, TYPE_RADIO_BUTTON);
+ return ButtonCreate(clientData, interp, objc, objv, TYPE_RADIO_BUTTON);
}
/*
@@ -311,23 +556,42 @@ Tk_RadiobuttonCmd(clientData, interp, argc, argv)
*/
static int
-ButtonCreate(clientData, interp, argc, argv, type)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+ButtonCreate(clientData, interp, objc, objv, type)
+ ClientData clientData; /* Option table for this widget class, or
+ * NULL if not created yet. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ 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. */
{
- register TkButton *butPtr;
- Tk_Window tkwin = (Tk_Window) clientData;
- Tk_Window new;
+ TkButton *butPtr;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ optionTable = (Tk_OptionTable) clientData;
+ if (optionTable == NULL) {
+ Tcl_CmdInfo info;
+ char *name;
+
+ /*
+ * We haven't created the option table for this widget class
+ * yet. Do it now and save the table as the clientData for
+ * the command, so we'll have access to it in future
+ * invocations of the command.
+ */
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " pathName ?options?\"", (char *) NULL);
+ TkpButtonSetDefaults(optionSpecs[type]);
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);
+ name = Tcl_GetString(objv[0]);
+ Tcl_GetCommandInfo(interp, name, &info);
+ info.objClientData = (ClientData) optionTable;
+ Tcl_SetCommandInfo(interp, name, &info);
+ }
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
return TCL_ERROR;
}
@@ -335,39 +599,43 @@ ButtonCreate(clientData, interp, argc, argv, type)
* Create the new window.
*/
- new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
- if (new == NULL) {
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), (char *) NULL);
+ if (tkwin == NULL) {
return TCL_ERROR;
}
- Tk_SetClass(new, classNames[type]);
- butPtr = TkpCreateButton(new);
+ Tk_SetClass(tkwin, classNames[type]);
+ butPtr = TkpCreateButton(tkwin);
- TkSetClassProcs(new, &tkpButtonProcs, (ClientData) butPtr);
+ TkSetClassProcs(tkwin, &tkpButtonProcs, (ClientData) butPtr);
/*
* Initialize the data structure for the button.
*/
- butPtr->tkwin = new;
- butPtr->display = Tk_Display(new);
- butPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(butPtr->tkwin),
- ButtonWidgetCmd, (ClientData) butPtr, ButtonCmdDeletedProc);
+ butPtr->tkwin = tkwin;
+ butPtr->display = Tk_Display(tkwin);
butPtr->interp = interp;
+ butPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin),
+ ButtonWidgetObjCmd, (ClientData) butPtr, ButtonCmdDeletedProc);
butPtr->type = type;
- butPtr->text = NULL;
+ butPtr->optionTable = optionTable;
+ butPtr->textPtr = NULL;
butPtr->underline = -1;
- butPtr->textVarName = NULL;
+ butPtr->textVarNamePtr = NULL;
butPtr->bitmap = None;
- butPtr->imageString = NULL;
+ butPtr->imagePtr = NULL;
butPtr->image = NULL;
- butPtr->selectImageString = NULL;
+ butPtr->selectImagePtr = NULL;
butPtr->selectImage = NULL;
- butPtr->state = tkNormalUid;
+ butPtr->state = STATE_NORMAL;
butPtr->normalBorder = NULL;
butPtr->activeBorder = NULL;
+ butPtr->borderWidthPtr = NULL;
butPtr->borderWidth = 0;
butPtr->relief = TK_RELIEF_FLAT;
+ butPtr->highlightWidthPtr = NULL;
butPtr->highlightWidth = 0;
butPtr->highlightBorder = NULL;
butPtr->highlightColorPtr = NULL;
@@ -378,43 +646,53 @@ ButtonCreate(clientData, interp, argc, argv, type)
butPtr->disabledFg = NULL;
butPtr->normalTextGC = None;
butPtr->activeTextGC = None;
- butPtr->gray = None;
butPtr->disabledGC = None;
+ butPtr->gray = None;
butPtr->copyGC = None;
- butPtr->widthString = NULL;
- butPtr->heightString = NULL;
+ butPtr->widthPtr = NULL;
butPtr->width = 0;
+ butPtr->heightPtr = NULL;
butPtr->height = 0;
+ butPtr->wrapLengthPtr = NULL;
butPtr->wrapLength = 0;
+ butPtr->padXPtr = NULL;
butPtr->padX = 0;
+ butPtr->padYPtr = NULL;
butPtr->padY = 0;
butPtr->anchor = TK_ANCHOR_CENTER;
butPtr->justify = TK_JUSTIFY_CENTER;
- butPtr->textLayout = NULL;
butPtr->indicatorOn = 0;
butPtr->selectBorder = NULL;
+ butPtr->textWidth = 0;
+ butPtr->textHeight = 0;
+ butPtr->textLayout = NULL;
butPtr->indicatorSpace = 0;
butPtr->indicatorDiameter = 0;
- butPtr->defaultState = tkDisabledUid;
- butPtr->selVarName = NULL;
- butPtr->onValue = NULL;
- butPtr->offValue = NULL;
+ butPtr->defaultState = DEFAULT_DISABLED;
+ butPtr->selVarNamePtr = NULL;
+ butPtr->onValuePtr = NULL;
+ butPtr->offValuePtr = NULL;
butPtr->cursor = None;
- butPtr->command = NULL;
- butPtr->takeFocus = NULL;
+ butPtr->takeFocusPtr = NULL;
+ butPtr->commandPtr = NULL;
butPtr->flags = 0;
Tk_CreateEventHandler(butPtr->tkwin,
ExposureMask|StructureNotifyMask|FocusChangeMask,
ButtonEventProc, (ClientData) butPtr);
- if (ConfigureButton(interp, butPtr, argc - 2, argv + 2,
- configFlags[type]) != TCL_OK) {
+ if (Tk_InitOptions(interp, (char *) butPtr, optionTable, tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(butPtr->tkwin);
+ return TCL_ERROR;
+ }
+ if (ConfigureButton(interp, butPtr, objc - 2, objv + 2) != TCL_OK) {
Tk_DestroyWindow(butPtr->tkwin);
return TCL_ERROR;
}
- interp->result = Tk_PathName(butPtr->tkwin);
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(butPtr->tkwin),
+ -1);
return TCL_OK;
}
@@ -437,147 +715,161 @@ ButtonCreate(clientData, interp, argc, argv, type)
*/
static int
-ButtonWidgetCmd(clientData, interp, argc, argv)
+ButtonWidgetObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about button widget. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
- register TkButton *butPtr = (TkButton *) clientData;
- int result = TCL_OK;
- size_t length;
- int c;
-
- if (argc < 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s option ?arg arg ...?\"",
- argv[0]);
+ TkButton *butPtr = (TkButton *) clientData;
+ int index;
+ int result;
+ Tcl_Obj *objPtr;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
return TCL_ERROR;
}
+ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames[butPtr->type],
+ "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
Tcl_Preserve((ClientData) butPtr);
- c = argv[1][0];
- length = strlen(argv[1]);
-
- 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);
- goto error;
- }
- result = Tk_ConfigureValue(interp, butPtr->tkwin, tkpButtonConfigSpecs,
- (char *) butPtr, argv[2], configFlags[butPtr->type]);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, butPtr->tkwin,
- tkpButtonConfigSpecs, (char *) butPtr, (char *) NULL,
- configFlags[butPtr->type]);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, butPtr->tkwin,
- tkpButtonConfigSpecs, (char *) butPtr, argv[2],
- configFlags[butPtr->type]);
- } else {
- result = ConfigureButton(interp, butPtr, argc-2, argv+2,
- configFlags[butPtr->type] | TK_CONFIG_ARGV_ONLY);
- }
- } else if ((c == 'd') && (strncmp(argv[1], "deselect", length) == 0)
- && (butPtr->type >= TYPE_CHECK_BUTTON)) {
- if (argc > 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s deselect\"",
- argv[0]);
- goto error;
- }
- if (butPtr->type == TYPE_CHECK_BUTTON) {
- if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->offValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
+
+ switch (map[butPtr->type][index]) {
+ case COMMAND_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
+ goto error;
}
- } else if (butPtr->flags & SELECTED) {
- if (Tcl_SetVar(interp, butPtr->selVarName, "",
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
- };
- }
- } else if ((c == 'f') && (strncmp(argv[1], "flash", length) == 0)
- && (butPtr->type != TYPE_LABEL)) {
- int i;
-
- if (argc > 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s flash\"",
- argv[0]);
- goto error;
- }
- if (butPtr->state != tkDisabledUid) {
- for (i = 0; i < 4; i++) {
- butPtr->state = (butPtr->state == tkNormalUid)
- ? tkActiveUid : tkNormalUid;
- Tk_SetBackgroundFromBorder(butPtr->tkwin,
- (butPtr->state == tkActiveUid) ? butPtr->activeBorder
- : 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);
+ objPtr = Tk_GetOptionValue(interp, (char *) butPtr,
+ butPtr->optionTable, objv[2], butPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
}
+ break;
}
- } else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0)
- && (butPtr->type > TYPE_LABEL)) {
- if (argc > 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s invoke\"",
- argv[0]);
- goto error;
+
+ 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;
}
- if (butPtr->state != tkDisabledUid) {
- result = TkInvokeButton(butPtr);
+
+ case COMMAND_DESELECT: {
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "deselect");
+ goto error;
+ }
+ if (butPtr->type == TYPE_CHECK_BUTTON) {
+ if (Tcl_SetObjVar2(interp,
+ Tcl_GetString(butPtr->selVarNamePtr),
+ NULL, butPtr->offValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ } else if (butPtr->flags & SELECTED) {
+ if (Tcl_SetObjVar2(interp,
+ Tcl_GetString(butPtr->selVarNamePtr), NULL,
+ Tcl_NewObj(),
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ }
+ break;
}
- } else if ((c == 's') && (strncmp(argv[1], "select", length) == 0)
- && (butPtr->type >= TYPE_CHECK_BUTTON)) {
- if (argc > 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s select\"",
- argv[0]);
- goto error;
+
+ case COMMAND_FLASH: {
+ 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);
+ }
+ }
+ break;
}
- if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->onValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
+
+ case COMMAND_INVOKE: {
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "invoke");
+ goto error;
+ }
+ if (butPtr->state != STATE_DISABLED) {
+ result = TkInvokeButton(butPtr);
+ }
+ break;
}
- } else if ((c == 't') && (strncmp(argv[1], "toggle", length) == 0)
- && (length >= 2) && (butPtr->type == TYPE_CHECK_BUTTON)) {
- if (argc > 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s toggle\"",
- argv[0]);
- goto error;
+
+ case COMMAND_SELECT: {
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "select");
+ goto error;
+ }
+ if (Tcl_SetObjVar2(interp,
+ Tcl_GetString(butPtr->selVarNamePtr), NULL,
+ butPtr->onValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ break;
}
- if (butPtr->flags & SELECTED) {
- if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->offValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
+
+ case COMMAND_TOGGLE: {
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "toggle");
+ goto error;
}
- } else {
- if (Tcl_SetVar(interp, butPtr->selVarName, butPtr->onValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
+ if (Tcl_SetObjVar2(interp,
+ Tcl_GetString(butPtr->selVarNamePtr), NULL,
+ (butPtr->flags & SELECTED) ? butPtr->offValuePtr
+ : butPtr->onValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
}
+ break;
}
- } else {
- sprintf(interp->result,
- "bad option \"%.50s\": must be %s", argv[1],
- optionStrings[butPtr->type]);
- goto error;
}
Tcl_Release((ClientData) butPtr);
return result;
@@ -592,15 +884,14 @@ ButtonWidgetCmd(clientData, interp, argc, argv)
*
* DestroyButton --
*
- * 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 ButtonEventProc to free all the
+ * resources of a button and clean up its state.
*
* Results:
* None.
*
* Side effects:
- * Everything associated with the widget is freed up.
+ * Everything associated with the widget is freed.
*
*----------------------------------------------------------------------
*/
@@ -609,14 +900,22 @@ static void
DestroyButton(butPtr)
TkButton *butPtr; /* Info about button widget. */
{
+ TkpDestroyButton(butPtr);
+
+ butPtr->flags |= BUTTON_DELETED;
+ if (butPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);
+ }
+
/*
* Free up all the stuff that requires special handling, then
* let Tk_FreeOptions handle all the standard option-related
* stuff.
*/
- if (butPtr->textVarName != NULL) {
- Tcl_UntraceVar(butPtr->interp, butPtr->textVarName,
+ Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);
+ if (butPtr->textVarNamePtr != NULL) {
+ Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->textVarNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonTextVarProc, (ClientData) butPtr);
}
@@ -632,24 +931,27 @@ DestroyButton(butPtr)
if (butPtr->activeTextGC != None) {
Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
}
- if (butPtr->gray != None) {
- Tk_FreeBitmap(butPtr->display, butPtr->gray);
- }
if (butPtr->disabledGC != None) {
Tk_FreeGC(butPtr->display, butPtr->disabledGC);
}
+ if (butPtr->gray != None) {
+ Tk_FreeBitmap(butPtr->display, butPtr->gray);
+ }
if (butPtr->copyGC != None) {
Tk_FreeGC(butPtr->display, butPtr->copyGC);
}
- if (butPtr->selVarName != NULL) {
- Tcl_UntraceVar(butPtr->interp, butPtr->selVarName,
+ if (butPtr->textLayout != NULL) {
+ Tk_FreeTextLayout(butPtr->textLayout);
+ }
+ if (butPtr->selVarNamePtr != NULL) {
+ Tcl_UntraceVar(butPtr->interp, Tcl_GetString(butPtr->selVarNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonVarProc, (ClientData) butPtr);
}
- Tk_FreeTextLayout(butPtr->textLayout);
- Tk_FreeOptions(tkpButtonConfigSpecs, (char *) butPtr, butPtr->display,
- configFlags[butPtr->type]);
- Tcl_EventuallyFree((ClientData)butPtr, TCL_DYNAMIC);
+ Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable,
+ butPtr->tkwin);
+ butPtr->tkwin = NULL;
+ Tcl_EventuallyFree((ClientData) butPtr, TCL_DYNAMIC);
}
/*
@@ -657,13 +959,12 @@ DestroyButton(butPtr)
*
* ConfigureButton --
*
- * This procedure is called to process an argv/argc list, plus
- * the Tk option database, in order to configure (or
- * reconfigure) a button widget.
+ * This procedure 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 interp->result contains an error message.
+ * returned, then an error message is left in interp's result.
*
* Side effects:
* Configuration information, such as text string, colors, font,
@@ -674,199 +975,237 @@ DestroyButton(butPtr)
*/
static int
-ConfigureButton(interp, butPtr, argc, argv, flags)
+ConfigureButton(interp, butPtr, objc, objv)
Tcl_Interp *interp; /* Used for error reporting. */
register TkButton *butPtr; /* Information about widget; may or may
* not already have values for some fields. */
- int argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
- int flags; /* Flags to pass to Tk_ConfigureWidget. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
+ Tk_SavedOptions savedOptions;
+ int error;
Tk_Image image;
/*
* Eliminate any existing trace on variables monitored by the button.
*/
- if (butPtr->textVarName != NULL) {
- Tcl_UntraceVar(interp, butPtr->textVarName,
+ if (butPtr->textVarNamePtr != NULL) {
+ Tcl_UntraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonTextVarProc, (ClientData) butPtr);
}
- if (butPtr->selVarName != NULL) {
- Tcl_UntraceVar(interp, butPtr->selVarName,
+ if (butPtr->selVarNamePtr != NULL) {
+ Tcl_UntraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonVarProc, (ClientData) butPtr);
}
-
-
- if (Tk_ConfigureWidget(interp, butPtr->tkwin, tkpButtonConfigSpecs,
- argc, argv, (char *) butPtr, flags) != TCL_OK) {
- return TCL_ERROR;
- }
-
/*
- * 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.
+ * 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.
*/
- if ((butPtr->state == tkActiveUid) && !Tk_StrictMotif(butPtr->tkwin)) {
- Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);
- } else {
- Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);
- if ((butPtr->state != tkNormalUid) && (butPtr->state != tkActiveUid)
- && (butPtr->state != tkDisabledUid)) {
- Tcl_AppendResult(interp, "bad state value \"", butPtr->state,
- "\": must be normal, active, or disabled", (char *) NULL);
- butPtr->state = tkNormalUid;
- return TCL_ERROR;
- }
- }
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
- if ((butPtr->defaultState != tkActiveUid)
- && (butPtr->defaultState != tkDisabledUid)
- && (butPtr->defaultState != tkNormalUid)) {
- Tcl_AppendResult(interp, "bad -default value \"", butPtr->defaultState,
- "\": must be normal, active, or disabled", (char *) NULL);
- butPtr->defaultState = tkDisabledUid;
- return TCL_ERROR;
- }
+ if (Tk_SetOptions(interp, (char *) butPtr,
+ butPtr->optionTable, objc, objv,
+ butPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
- if (butPtr->highlightWidth < 0) {
- butPtr->highlightWidth = 0;
- }
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
- if (butPtr->padX < 0) {
- butPtr->padX = 0;
- }
- if (butPtr->padY < 0) {
- butPtr->padY = 0;
- }
+ /*
+ * 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.
+ */
- if (butPtr->type >= TYPE_CHECK_BUTTON) {
- char *value;
+ if ((butPtr->state == STATE_ACTIVE)
+ && !Tk_StrictMotif(butPtr->tkwin)) {
+ Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->activeBorder);
+ } else {
+ Tk_SetBackgroundFromBorder(butPtr->tkwin, butPtr->normalBorder);
+ }
+ if (butPtr->borderWidth < 0) {
+ butPtr->borderWidth = 0;
+ }
+ if (butPtr->highlightWidth < 0) {
+ butPtr->highlightWidth = 0;
+ }
+ if (butPtr->padX < 0) {
+ butPtr->padX = 0;
+ }
+ if (butPtr->padY < 0) {
+ butPtr->padY = 0;
+ }
- if (butPtr->selVarName == NULL) {
- butPtr->selVarName = (char *) ckalloc((unsigned)
- (strlen(Tk_Name(butPtr->tkwin)) + 1));
- strcpy(butPtr->selVarName, Tk_Name(butPtr->tkwin));
+ if (butPtr->type >= TYPE_CHECK_BUTTON) {
+ Tcl_Obj *valuePtr;
+ char *name;
+
+ if (butPtr->selVarNamePtr == NULL) {
+ butPtr->selVarNamePtr = Tcl_NewStringObj(
+ Tk_Name(butPtr->tkwin), -1);
+ Tcl_IncrRefCount(butPtr->selVarNamePtr);
+ }
+ name = Tcl_GetString(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.
+ */
+
+ valuePtr = Tcl_GetObjVar2(interp, name, NULL, TCL_GLOBAL_ONLY);
+ butPtr->flags &= ~SELECTED;
+ if (valuePtr != NULL) {
+ if (strcmp(Tcl_GetString(valuePtr),
+ Tcl_GetString(butPtr->onValuePtr)) == 0) {
+ butPtr->flags |= SELECTED;
+ }
+ } else {
+ if (Tcl_SetObjVar2(interp, name, NULL,
+ (butPtr->type == TYPE_CHECK_BUTTON)
+ ? butPtr->offValuePtr : Tcl_NewObj(),
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ continue;
+ }
+ }
}
/*
- * 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.
+ * 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.
*/
-
- value = Tcl_GetVar(interp, butPtr->selVarName, TCL_GLOBAL_ONLY);
- butPtr->flags &= ~SELECTED;
- if (value != NULL) {
- if (strcmp(value, butPtr->onValue) == 0) {
- butPtr->flags |= SELECTED;
+
+ if (butPtr->imagePtr != NULL) {
+ image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
+ Tcl_GetString(butPtr->imagePtr), ButtonImageProc,
+ (ClientData) butPtr);
+ if (image == NULL) {
+ continue;
}
} else {
- if (Tcl_SetVar(interp, butPtr->selVarName,
- (butPtr->type == TYPE_CHECK_BUTTON) ? butPtr->offValue : "",
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
+ image = NULL;
+ }
+ if (butPtr->image != NULL) {
+ Tk_FreeImage(butPtr->image);
+ }
+ butPtr->image = image;
+ if (butPtr->selectImagePtr != NULL) {
+ image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
+ Tcl_GetString(butPtr->selectImagePtr),
+ ButtonSelectImageProc, (ClientData) butPtr);
+ if (image == NULL) {
+ continue;
}
+ } else {
+ image = NULL;
}
- Tcl_TraceVar(interp, butPtr->selVarName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- ButtonVarProc, (ClientData) butPtr);
- }
-
- /*
- * 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->imageString != NULL) {
- image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
- butPtr->imageString, ButtonImageProc, (ClientData) butPtr);
- if (image == NULL) {
- return TCL_ERROR;
+ if (butPtr->selectImage != NULL) {
+ Tk_FreeImage(butPtr->selectImage);
}
- } else {
- image = NULL;
- }
- if (butPtr->image != NULL) {
- Tk_FreeImage(butPtr->image);
- }
- butPtr->image = image;
- if (butPtr->selectImageString != NULL) {
- image = Tk_GetImage(butPtr->interp, butPtr->tkwin,
- butPtr->selectImageString, ButtonSelectImageProc,
- (ClientData) butPtr);
- if (image == NULL) {
- return TCL_ERROR;
+ butPtr->selectImage = image;
+
+ if ((butPtr->imagePtr == NULL) && (butPtr->bitmap == None)
+ && (butPtr->textVarNamePtr != NULL)) {
+ /*
+ * The button must display the value of a variable: set up a trace
+ * on the variable's value, create the variable if it doesn't
+ * exist, and fetch its current value.
+ */
+
+ char *name;
+ Tcl_Obj *valuePtr;
+
+ name = Tcl_GetString(butPtr->textVarNamePtr);
+ valuePtr = Tcl_GetObjVar2(interp, name, NULL, TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
+ if (Tcl_SetObjVar2(interp, name, NULL, butPtr->textPtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ continue;
+ }
+ } else {
+ if (butPtr->textPtr != NULL) {
+ Tcl_DecrRefCount(butPtr->textPtr);
+ }
+ butPtr->textPtr = valuePtr;
+ Tcl_IncrRefCount(butPtr->textPtr);
+ }
}
- } else {
- image = NULL;
- }
- if (butPtr->selectImage != NULL) {
- Tk_FreeImage(butPtr->selectImage);
- }
- butPtr->selectImage = image;
-
- if ((butPtr->image == NULL) && (butPtr->bitmap == None)
- && (butPtr->textVarName != NULL)) {
- /*
- * The button must display the value of a variable: set up a trace
- * on the variable's value, create the variable if it doesn't
- * exist, and fetch its current value.
- */
-
- char *value;
-
- value = Tcl_GetVar(interp, butPtr->textVarName, TCL_GLOBAL_ONLY);
- if (value == NULL) {
- if (Tcl_SetVar(interp, butPtr->textVarName, butPtr->text,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- return TCL_ERROR;
+
+ if ((butPtr->bitmap != None) || (butPtr->imagePtr != NULL)) {
+ /*
+ * The button must display the contents of an image or
+ * bitmap.
+ */
+
+ if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->widthPtr,
+ &butPtr->width) != TCL_OK) {
+ widthError:
+ Tcl_AddErrorInfo(interp, "\n (processing -width option)");
+ continue;
+ }
+ if (Tk_GetPixelsFromObj(interp, butPtr->tkwin, butPtr->heightPtr,
+ &butPtr->height) != TCL_OK) {
+ heightError:
+ Tcl_AddErrorInfo(interp, "\n (processing -height option)");
+ continue;
}
} else {
- if (butPtr->text != NULL) {
- ckfree(butPtr->text);
+ /*
+ * The button displays an ordinary text string.
+ */
+
+ if (Tcl_GetIntFromObj(interp, butPtr->widthPtr, &butPtr->width)
+ != TCL_OK) {
+ goto widthError;
+ }
+ if (Tcl_GetIntFromObj(interp, butPtr->heightPtr, &butPtr->height)
+ != TCL_OK) {
+ goto heightError;
}
- butPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
- strcpy(butPtr->text, value);
}
- Tcl_TraceVar(interp, butPtr->textVarName,
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
+
+ /*
+ * Reestablish the variable traces, if they're needed.
+ */
+
+ if (butPtr->textVarNamePtr != NULL) {
+ Tcl_TraceVar(interp, Tcl_GetString(butPtr->textVarNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonTextVarProc, (ClientData) butPtr);
}
-
- if ((butPtr->bitmap != None) || (butPtr->image != NULL)) {
- if (Tk_GetPixels(interp, butPtr->tkwin, butPtr->widthString,
- &butPtr->width) != TCL_OK) {
- widthError:
- Tcl_AddErrorInfo(interp, "\n (processing -width option)");
- return TCL_ERROR;
- }
- if (Tk_GetPixels(interp, butPtr->tkwin, butPtr->heightString,
- &butPtr->height) != TCL_OK) {
- heightError:
- Tcl_AddErrorInfo(interp, "\n (processing -height option)");
- return TCL_ERROR;
- }
- } else {
- if (Tcl_GetInt(interp, butPtr->widthString, &butPtr->width)
- != TCL_OK) {
- goto widthError;
- }
- if (Tcl_GetInt(interp, butPtr->heightString, &butPtr->height)
- != TCL_OK) {
- goto heightError;
- }
+ if (butPtr->selVarNamePtr != NULL) {
+ Tcl_TraceVar(interp, Tcl_GetString(butPtr->selVarNamePtr),
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ButtonVarProc, (ClientData) butPtr);
}
TkButtonWorldChanged((ClientData) butPtr);
- return TCL_OK;
+ return (error) ? TCL_ERROR : TCL_OK;
}
/*
@@ -921,7 +1260,6 @@ TkButtonWorldChanged(instanceData)
butPtr->normalTextGC = newGC;
if (butPtr->activeFg != NULL) {
- gcValues.font = Tk_FontId(butPtr->tkfont);
gcValues.foreground = butPtr->activeFg->pixel;
gcValues.background = Tk_3DBorderColor(butPtr->activeBorder)->pixel;
mask = GCForeground | GCBackground | GCFont;
@@ -933,17 +1271,15 @@ TkButtonWorldChanged(instanceData)
}
if (butPtr->type != TYPE_LABEL) {
- gcValues.font = Tk_FontId(butPtr->tkfont);
gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
- if ((butPtr->disabledFg != NULL) && (butPtr->imageString == NULL)) {
+ if ((butPtr->disabledFg != NULL) && (butPtr->imagePtr == NULL)) {
gcValues.foreground = butPtr->disabledFg->pixel;
mask = GCForeground | GCBackground | GCFont;
} else {
gcValues.foreground = gcValues.background;
mask = GCForeground;
if (butPtr->gray == None) {
- butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin,
- Tk_GetUid("gray50"));
+ butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin, "gray50");
}
if (butPtr->gray != None) {
gcValues.fill_style = FillStippled;
@@ -1008,14 +1344,6 @@ ButtonEventProc(clientData, eventPtr)
goto redraw;
} else if (eventPtr->type == DestroyNotify) {
- TkpDestroyButton(butPtr);
- if (butPtr->tkwin != NULL) {
- butPtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(butPtr->interp, butPtr->widgetCmd);
- }
- if (butPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(TkpDisplayButton, (ClientData) butPtr);
- }
DestroyButton(butPtr);
} else if (eventPtr->type == FocusIn) {
if (eventPtr->xfocus.detail != NotifyInferior) {
@@ -1064,18 +1392,16 @@ ButtonCmdDeletedProc(clientData)
ClientData clientData; /* Pointer to widget record for widget. */
{
TkButton *butPtr = (TkButton *) clientData;
- Tk_Window tkwin = butPtr->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.
+ * 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.
*/
- if (tkwin != NULL) {
- butPtr->tkwin = NULL;
- Tk_DestroyWindow(tkwin);
+ if (!(butPtr->flags & BUTTON_DELETED)) {
+ Tk_DestroyWindow(butPtr->tkwin);
}
}
@@ -1091,7 +1417,7 @@ ButtonCmdDeletedProc(clientData)
*
* Results:
* A standard Tcl return value. Information is also left in
- * interp->result.
+ * the interp's result.
*
* Side effects:
* Depends on the button and its associated command.
@@ -1101,28 +1427,45 @@ ButtonCmdDeletedProc(clientData)
int
TkInvokeButton(butPtr)
- register TkButton *butPtr; /* Information about button. */
+ TkButton *butPtr; /* Information about button. */
{
+ char *name;
+
+ if (butPtr->selVarNamePtr != NULL) {
+ name = Tcl_GetString(butPtr->selVarNamePtr);
+ } else {
+ /*
+ * This code should be executed only if the button is a
+ * label or regular button, in which case the variable should
+ * never be used.
+ */
+
+ name = NULL;
+ }
if (butPtr->type == TYPE_CHECK_BUTTON) {
if (butPtr->flags & SELECTED) {
- if (Tcl_SetVar(butPtr->interp, butPtr->selVarName, butPtr->offValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+ if (Tcl_SetObjVar2(butPtr->interp, name, NULL, butPtr->offValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
return TCL_ERROR;
}
} else {
- if (Tcl_SetVar(butPtr->interp, butPtr->selVarName, butPtr->onValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+ if (Tcl_SetObjVar2(butPtr->interp, name, NULL, butPtr->onValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
return TCL_ERROR;
}
}
} else if (butPtr->type == TYPE_RADIO_BUTTON) {
- if (Tcl_SetVar(butPtr->interp, butPtr->selVarName, butPtr->onValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+ if (Tcl_SetObjVar2(butPtr->interp, name, NULL, butPtr->onValuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
return TCL_ERROR;
}
}
- if ((butPtr->type != TYPE_LABEL) && (butPtr->command != NULL)) {
- return TkCopyAndGlobalEval(butPtr->interp, butPtr->command);
+ if ((butPtr->type != TYPE_LABEL) && (butPtr->commandPtr != NULL)) {
+ return Tcl_EvalObj(butPtr->interp, butPtr->commandPtr,
+ TCL_EVAL_GLOBAL);
}
return TCL_OK;
}
@@ -1156,7 +1499,10 @@ ButtonVarProc(clientData, interp, name1, name2, flags)
int flags; /* Information about what happened. */
{
register TkButton *butPtr = (TkButton *) clientData;
- char *value;
+ char *name, *value;
+ Tcl_Obj *valuePtr;
+
+ name = Tcl_GetString(butPtr->selVarNamePtr);
/*
* If the variable is being unset, then just re-establish the
@@ -1166,7 +1512,7 @@ ButtonVarProc(clientData, interp, name1, name2, flags)
if (flags & TCL_TRACE_UNSETS) {
butPtr->flags &= ~SELECTED;
if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
- Tcl_TraceVar(interp, butPtr->selVarName,
+ Tcl_TraceVar(interp, name,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonVarProc, clientData);
}
@@ -1178,11 +1524,13 @@ ButtonVarProc(clientData, interp, name1, name2, flags)
* the button.
*/
- value = Tcl_GetVar(interp, butPtr->selVarName, TCL_GLOBAL_ONLY);
- if (value == NULL) {
+ valuePtr = Tcl_GetObjVar2(interp, name, NULL, TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
value = "";
+ } else {
+ value = Tcl_GetString(valuePtr);
}
- if (strcmp(value, butPtr->onValue) == 0) {
+ if (strcmp(value, Tcl_GetString(butPtr->onValuePtr)) == 0) {
if (butPtr->flags & SELECTED) {
return (char *) NULL;
}
@@ -1229,8 +1577,11 @@ ButtonTextVarProc(clientData, interp, name1, name2, flags)
char *name2; /* Not used. */
int flags; /* Information about what happened. */
{
- register TkButton *butPtr = (TkButton *) clientData;
- char *value;
+ TkButton *butPtr = (TkButton *) clientData;
+ char *name;
+ Tcl_Obj *valuePtr;
+
+ name = Tcl_GetString(butPtr->textVarNamePtr);
/*
* If the variable is unset, then immediately recreate it unless
@@ -1239,24 +1590,22 @@ ButtonTextVarProc(clientData, interp, name1, name2, flags)
if (flags & TCL_TRACE_UNSETS) {
if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
- Tcl_SetVar(interp, butPtr->textVarName, butPtr->text,
+ Tcl_SetObjVar2(interp, name, NULL, butPtr->textPtr,
TCL_GLOBAL_ONLY);
- Tcl_TraceVar(interp, butPtr->textVarName,
+ Tcl_TraceVar(interp, name,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonTextVarProc, clientData);
}
return (char *) NULL;
}
- value = Tcl_GetVar(interp, butPtr->textVarName, TCL_GLOBAL_ONLY);
- if (value == NULL) {
- value = "";
- }
- if (butPtr->text != NULL) {
- ckfree(butPtr->text);
+ valuePtr = Tcl_GetObjVar2(interp, name, NULL, TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewObj();
}
- butPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
- strcpy(butPtr->text, value);
+ Tcl_DecrRefCount(butPtr->textPtr);
+ butPtr->textPtr = valuePtr;
+ Tcl_IncrRefCount(butPtr->textPtr);
TkpComputeButtonGeometry(butPtr);
if ((butPtr->tkwin != NULL) && Tk_IsMapped(butPtr->tkwin)
@@ -1273,7 +1622,7 @@ 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 of contents
+ * for an image does something that affects the size or contents
* of an image displayed in a button.
*
* Results:
@@ -1311,7 +1660,7 @@ 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 of contents
+ * for an image does something that affects the size or contents
* of the image displayed in a button when it is selected.
*
* Results:
diff --git a/generic/tkButton.h b/generic/tkButton.h
index 0d5b928..ebc7c7a 100644
--- a/generic/tkButton.h
+++ b/generic/tkButton.h
@@ -4,12 +4,12 @@
* Declarations of types and functions used to implement
* button-like widgets.
*
- * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkButton.h 1.5 97/06/06 11:19:24
+ * SCCS: @(#) tkButton.h 1.8 98/01/09 09:48:06
*/
#ifndef _TKBUTTON
@@ -20,6 +20,22 @@
#endif
/*
+ * Legal values for the "state" field of TkButton records.
+ */
+
+enum state {
+ STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL
+};
+
+/*
+ * Legal values for the "defaultState" field of TkButton records.
+ */
+
+enum defaultState {
+ DEFAULT_ACTIVE, DEFAULT_DISABLED, DEFAULT_NORMAL
+};
+
+/*
* A data structure of the following type is kept for each
* widget managed by this file:
*/
@@ -31,69 +47,88 @@ typedef struct {
* 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: restricts operations
- * that may be performed on widget. See
- * below for possible values. */
+ int type; /* Type of widget, such as TYPE_LABEL:
+ * restricts operations that may be performed
+ * on widget. See below for legal values. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
/*
* Information about what's in the button.
*/
- char *text; /* Text to display in button (malloc'ed)
- * or NULL. */
- int underline; /* Index of character to underline. < 0 means
+ 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. */
- 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 are ignored. */
- char *imageString; /* Name of image to display (malloc'ed), or
- * NULL. If non-NULL, bitmap, text, and
- * textVarName are ignored. */
- Tk_Image image; /* Image to display in window, or NULL if
- * none. */
- char *selectImageString; /* Name of image to display when selected
- * (malloc'ed), or NULL. */
- Tk_Image selectImage; /* Image to display in window when selected,
- * or NULL if none. Ignored if image is
+ Tcl_Obj *textVarNamePtr; /* Value of -textvariable option: specifies
+ * name of variable or NULL. If non-NULL,
+ * button displays the contents of this
+ * variable. */
+ 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.*/
+ Tk_Image image; /* Derived from imagePtr by calling
+ * 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
* NULL. */
+ Tk_Image selectImage; /* Derived from selectImagePtr by calling
+ * Tk_GetImage, or NULL if selectImagePtr
+ * is NULL. */
/*
* Information used when displaying widget:
*/
- Tk_Uid 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. */
- 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.
+ 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. */
+ Tcl_Obj *borderWidthPtr; /* Value of -borderWidth option: specifies
+ * width of border in pixels. */
+ int borderWidth; /* Integer value corresponding to
+ * borderWidthPtr. Always >= 0. */
+ int relief; /* Value of -relief option: specifies 3-d
+ * effect for border, such as
+ * TK_RELIEF_RAISED. */
+ 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. */
- Tk_3DBorder highlightBorder;
- /* Structure used to draw 3-D default ring
- * and focus highlight area when highlight
- * is off. */
- XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
-
+ int highlightWidth; /* Integer value corresponding to
+ * 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. */
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; /* 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
+ 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. */
+ 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
@@ -101,36 +136,47 @@ typedef struct {
* screen. */
GC activeTextGC; /* GC for drawing text in active mode (NULL
* means use normalTextGC). */
- Pixmap gray; /* Pixmap for displaying disabled text if
- * disabledFg is NULL. */
GC disabledGC; /* Used to produce disabled effect. If
* disabledFg isn't NULL, this GC is used to
* draw button text or icon. Otherwise
* text or icon is drawn with normalGC and
* this GC is used to stipple background
* across it. For labels this is None. */
+ Pixmap gray; /* Pixmap for displaying disabled text if
+ * disabledFg is NULL. */
GC copyGC; /* Used for copying information from an
* off-screen pixmap to the screen. */
- 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
- * size of the text string or bitmap is
- * ignored in computing desired window size. */
- int wrapLength; /* Line length (in pixels) at which to wrap
+ Tcl_Obj *widthPtr; /* Value of -width option. */
+ 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. */
- int padX, padY; /* Extra space around text (pixels to leave
- * on each side). Ignored for bitmaps and
+ 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
* images. */
- Tk_Anchor anchor; /* Where text/bitmap should be displayed
- * inside button region. */
- Tk_Justify justify; /* Justification to use for multi-line text. */
- int indicatorOn; /* True means draw indicator, false means
- * don't draw it. */
- Tk_3DBorder selectBorder; /* For drawing indicator background, or perhaps
- * widget background, when selected. */
+ 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
+ * 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_3DBorder selectBorder; /* Value of -selectcolor option: specifies
+ * color for drawing indicator background, or
+ * 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,
@@ -139,36 +185,42 @@ typedef struct {
int indicatorSpace; /* Horizontal space (in pixels) allocated for
* display of indicator. */
int indicatorDiameter; /* Diameter of indicator, in pixels. */
- Tk_Uid defaultState; /* State of default ring: normal, active, or
- * disabled. */
-
+ 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. */
+
/*
* For check and radio buttons, the fields below are used
* to manage the variable indicating the button's state.
*/
- char *selVarName; /* Name of variable used to control selected
- * state of button. Malloc'ed (if
- * not NULL). */
- char *onValue; /* Value to store in variable when
- * this button is selected. Malloc'ed (if
- * not NULL). */
- char *offValue; /* Value to store in variable when this
- * button isn't selected. Malloc'ed
- * (if not NULL). Valid only for check
- * buttons. */
+ Tcl_Obj *selVarNamePtr; /* Value of -variable option: specifies name
+ * 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. */
/*
* Miscellaneous information:
*/
- Tk_Cursor cursor; /* Current cursor for window, or None. */
- char *takeFocus; /* Value of -takefocus option; not used in
+ 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
- * scripts. Malloc'ed, but may be NULL. */
- char *command; /* Command to execute when button is
- * invoked; valid for buttons only.
- * If not NULL, it's malloc-ed. */
+ * 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 flags; /* Various flags; see below for
* definitions. */
} TkButton;
@@ -195,36 +247,31 @@ typedef struct {
* 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.
*/
#define REDRAW_PENDING 1
#define SELECTED 2
#define GOT_FOCUS 4
-
-/*
- * Mask values used to selectively enable entries in the
- * configuration specs:
- */
-
-#define LABEL_MASK TK_CONFIG_USER_BIT
-#define BUTTON_MASK TK_CONFIG_USER_BIT << 1
-#define CHECK_BUTTON_MASK TK_CONFIG_USER_BIT << 2
-#define RADIO_BUTTON_MASK TK_CONFIG_USER_BIT << 3
-#define ALL_MASK (LABEL_MASK | BUTTON_MASK \
- | CHECK_BUTTON_MASK | RADIO_BUTTON_MASK)
+#define BUTTON_DELETED 0x8
/*
* Declaration of variables shared between the files in the button module.
*/
extern TkClassProcs tkpButtonProcs;
-extern Tk_ConfigSpec tkpButtonConfigSpecs[];
/*
* Declaration of procedures used in the implementation of the button
* widget.
*/
+#ifndef TkpButtonSetDefaults
+EXTERN void TkpButtonSetDefaults _ANSI_ARGS_((
+ Tk_OptionSpec *specPtr));
+#endif
EXTERN void TkButtonWorldChanged _ANSI_ARGS_((
ClientData instanceData));
EXTERN void TkpComputeButtonGeometry _ANSI_ARGS_((
diff --git a/generic/tkCanvArc.c b/generic/tkCanvArc.c
index 26b62e7..4c97876 100644
--- a/generic/tkCanvArc.c
+++ b/generic/tkCanvArc.c
@@ -4,12 +4,12 @@
* This file implements arc items for canvas widgets.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvArc.c 1.34 97/04/25 16:50:56
+ * SCCS: @(#) tkCanvArc.c 1.35 97/11/07 21:14:21
*/
#include <stdio.h>
@@ -188,7 +188,7 @@ static Tk_Uid pieSliceUid = NULL;
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is
+ * the interp's result; in this case itemPtr is
* left uninitialized, so it can be safely freed by the
* caller.
*
@@ -276,7 +276,7 @@ CreateArc(interp, canvas, itemPtr, argc, argv)
* on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -319,9 +319,10 @@ ArcCoords(interp, canvas, itemPtr, argc, argv)
}
ComputeArcBbox(canvas, arcPtr);
} else {
- sprintf(interp->result,
- "wrong # coordinates: expected 0 or 4, got %d",
- argc);
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -337,7 +338,7 @@ ArcCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information, such as colors and stipple
@@ -1574,7 +1575,7 @@ AngleInRange(x, y, start, extent)
* 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
+ * 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.
*
diff --git a/generic/tkCanvBmap.c b/generic/tkCanvBmap.c
index fff0638..4786dd6 100644
--- a/generic/tkCanvBmap.c
+++ b/generic/tkCanvBmap.c
@@ -4,12 +4,12 @@
* This file implements bitmap items for canvas widgets.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvBmap.c 1.30 96/05/03 10:49:00
+ * SCCS: @(#) tkCanvBmap.c 1.31 97/11/07 21:14:33
*/
#include <stdio.h>
@@ -129,7 +129,7 @@ Tk_ItemType tkBitmapType = {
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is left uninitialized,
+ * the interp's result; in this case itemPtr is left uninitialized,
* so it can be safely freed by the caller.
*
* Side effects:
@@ -194,7 +194,7 @@ CreateBitmap(interp, canvas, itemPtr, argc, argv)
* details on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -228,8 +228,10 @@ BitmapCoords(interp, canvas, itemPtr, argc, argv)
}
ComputeBitmapBbox(canvas, bmapPtr);
} else {
- sprintf(interp->result,
- "wrong # coordinates: expected 0 or 2, got %d", argc);
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -245,7 +247,7 @@ BitmapCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information may be set for itemPtr.
@@ -690,7 +692,7 @@ TranslateBitmap(canvas, itemPtr, deltaX, deltaY)
* 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.
+ * 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.
*
@@ -715,7 +717,7 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass)
double x, y;
int width, height, rowsAtOnce, rowsThisTime;
int curRow;
- char buffer[200];
+ char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4];
if (bmapPtr->bitmap == None) {
return TCL_OK;
@@ -749,7 +751,7 @@ BitmapToPostscript(interp, canvas, itemPtr, prepass)
if (bmapPtr->bgColor != NULL) {
sprintf(buffer,
"%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %s\n",
- x, y, width, height, -width,"0 rlineto closepath");
+ x, y, width, height, -width, "0 rlineto closepath");
Tcl_AppendResult(interp, buffer, (char *) NULL);
if (Tk_CanvasPsColor(interp, canvas, bmapPtr->bgColor) != TCL_OK) {
return TCL_ERROR;
diff --git a/generic/tkCanvImg.c b/generic/tkCanvImg.c
index 55169f7..258ca8d 100644
--- a/generic/tkCanvImg.c
+++ b/generic/tkCanvImg.c
@@ -4,12 +4,12 @@
* This file implements image items for canvas widgets.
*
* Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvImg.c 1.18 96/05/03 10:49:09
+ * SCCS: @(#) tkCanvImg.c 1.19 97/11/07 21:14:48
*/
#include <stdio.h>
@@ -126,7 +126,7 @@ Tk_ItemType tkImageType = {
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is left uninitialized,
+ * the interp's result; in this case itemPtr is left uninitialized,
* so it can be safely freed by the caller.
*
* Side effects:
@@ -190,7 +190,7 @@ CreateImage(interp, canvas, itemPtr, argc, argv)
* details on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -224,8 +224,10 @@ ImageCoords(interp, canvas, itemPtr, argc, argv)
}
ComputeImageBbox(canvas, imgPtr);
} else {
- sprintf(interp->result,
- "wrong # coordinates: expected 0 or 2, got %d", argc);
+ char buf[64];
+
+ sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -241,7 +243,7 @@ ImageCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information may be set for itemPtr.
diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c
index 97cd1f5..bf2afd9 100644
--- a/generic/tkCanvLine.c
+++ b/generic/tkCanvLine.c
@@ -4,12 +4,12 @@
* This file implements line items for canvas widgets.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvLine.c 1.46 97/04/25 16:51:02
+ * SCCS: @(#) tkCanvLine.c 1.47 97/11/07 21:14:57
*/
#include <stdio.h>
@@ -207,7 +207,7 @@ static Tk_Uid bothUid = NULL;
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is left uninitialized,
+ * the interp's result; in this case itemPtr is left uninitialized,
* so it can be safely freed by the caller.
*
* Side effects:
@@ -302,7 +302,7 @@ CreateLine(interp, canvas, itemPtr, argc, argv)
* on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -403,7 +403,7 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information, such as colors and stipple
@@ -1449,7 +1449,7 @@ ConfigureArrows(canvas, linePtr)
* 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
+ * 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.
*
@@ -1471,7 +1471,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
* final Postscript is being created. */
{
LineItem *linePtr = (LineItem *) itemPtr;
- char buffer[200];
+ char buffer[64 + TCL_INTEGER_SPACE];
char *style;
if (linePtr->fg == NULL) {
@@ -1589,7 +1589,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
* 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
+ * 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.
*
diff --git a/generic/tkCanvPoly.c b/generic/tkCanvPoly.c
index 1320438..9e672c5 100644
--- a/generic/tkCanvPoly.c
+++ b/generic/tkCanvPoly.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkCanvPoly.c 1.37 97/04/29 15:39:16
+ * SCCS: @(#) tkCanvPoly.c 1.38 97/11/07 21:15:07
*/
#include <stdio.h>
@@ -150,7 +150,7 @@ Tk_ItemType tkPolygonType = {
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is
+ * the interp's result; in this case itemPtr is
* left uninitialized, so it can be safely freed by the
* caller.
*
@@ -234,7 +234,7 @@ CreatePolygon(interp, canvas, itemPtr, argc, argv)
* on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -327,7 +327,7 @@ PolygonCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information, such as colors and stipple
@@ -919,7 +919,7 @@ TranslatePolygon(canvas, itemPtr, deltaX, deltaY)
* 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
+ * 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.
*
@@ -940,7 +940,6 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass)
* collect font information; 0 means
* final Postscript is being created. */
{
- char string[100];
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
/*
@@ -977,6 +976,8 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass)
*/
if (polyPtr->outlineColor != NULL) {
+ char string[32 + TCL_INTEGER_SPACE];
+
if (!polyPtr->smooth) {
Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
polyPtr->numPoints);
diff --git a/generic/tkCanvPs.c b/generic/tkCanvPs.c
index 9bad194..dcc6cee 100644
--- a/generic/tkCanvPs.c
+++ b/generic/tkCanvPs.c
@@ -6,12 +6,12 @@
* procedures used for generating Postscript.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvPs.c 1.57 97/10/28 18:08:39
+ * SCCS: @(#) tkCanvPs.c 1.62 98/02/10 10:28:12
*/
#include "tkInt.h"
@@ -112,6 +112,320 @@ static Tk_ConfigSpec configSpecs[] = {
};
/*
+ * The prolog data. Generated by str2c from prolog.ps
+ * This was split in small chunks by str2c because
+ * some C compiler have limitations on the size of static strings.
+ * (str2c is a small tcl script in tcl's tool directory (source release))
+ */
+static CONST char * CONST prolog[]= {
+ /* Start of part 1 (2000 characters) */
+ "%%BeginProlog\n\
+50 dict begin\n\
+\n\
+% This is a standard prolog for Postscript generated by Tk's canvas\n\
+% widget.\n\
+% SCCS: @(#) prolog.ps 1.7 96/07/08 17:52:14\n\
+\n\
+% The definitions below just define all of the variables used in\n\
+% any of the procedures here. This is needed for obscure reasons\n\
+% explained on p. 716 of the Postscript manual (Section H.2.7,\n\
+% \"Initializing Variables,\" in the section on Encapsulated Postscript).\n\
+\n\
+/baseline 0 def\n\
+/stipimage 0 def\n\
+/height 0 def\n\
+/justify 0 def\n\
+/lineLength 0 def\n\
+/spacing 0 def\n\
+/stipple 0 def\n\
+/strings 0 def\n\
+/xoffset 0 def\n\
+/yoffset 0 def\n\
+/tmpstip null def\n\
+\n\
+% Define the array ISOLatin1Encoding (which specifies how characters are\n\
+% encoded for ISO-8859-1 fonts), if it isn't already present (Postscript\n\
+% level 2 is supposed to define it, but level 1 doesn't).\n\
+\n\
+systemdict /ISOLatin1Encoding known not {\n\
+ /ISOLatin1Encoding [\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /exclam /quotedbl /numbersign /dollar /percent /ampersand\n\
+ /quoteright\n\
+ /parenleft /parenright /asterisk /plus /comma /minus /period /slash\n\
+ /zero /one /two /three /four /five /six /seven\n\
+ /eight /nine /colon /semicolon /less /equal /greater /question\n\
+ /at /A /B /C /D /E /F /G\n\
+ /H /I /J /K /L /M /N /O\n\
+ /P /Q /R /S /T /U /V /W\n\
+ /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore\n\
+ /quoteleft /a /b /c /d /e /f /g\n\
+ /h /i /j /k /l /m /n /o\n\
+ /p /q /r /s /t /u /v /w\n\
+ /x /y /z /braceleft /bar /braceright /asciitilde /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /space /space /space /space /space /space /space /space\n\
+ /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent\n\
+ /dieresis /space /ring /cedilla /space /hungarumlaut /ogonek /caron\n\
+ /space /exclamdown /cent /sterling /currency /yen /brokenbar /section\n\
+ /dieresis /copyright /ordfem",
+ /* End of part 1 */
+
+ /* Start of part 2 (2000 characters) */
+ "inine /guillemotleft /logicalnot /hyphen\n\
+ /registered /macron\n\
+ /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph\n\
+ /periodcentered\n\
+ /cedillar /onesuperior /ordmasculine /guillemotright /onequarter\n\
+ /onehalf /threequarters /questiondown\n\
+ /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n\
+ /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex\n\
+ /Idieresis\n\
+ /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n\
+ /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn\n\
+ /germandbls\n\
+ /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n\
+ /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex\n\
+ /idieresis\n\
+ /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide\n\
+ /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn\n\
+ /ydieresis\n\
+ ] def\n\
+} if\n\
+\n\
+% font ISOEncode font\n\
+% This procedure changes the encoding of a font from the default\n\
+% Postscript encoding to ISOLatin1. It's typically invoked just\n\
+% before invoking \"setfont\". The body of this procedure comes from\n\
+% Section 5.6.1 of the Postscript book.\n\
+\n\
+/ISOEncode {\n\
+ dup length dict begin\n\
+ {1 index /FID ne {def} {pop pop} ifelse} forall\n\
+ /Encoding ISOLatin1Encoding def\n\
+ currentdict\n\
+ end\n\
+\n\
+ % I'm not sure why it's necessary to use \"definefont\" on this new\n\
+ % font, but it seems to be important; just use the name \"Temporary\"\n\
+ % for the font.\n\
+\n\
+ /Temporary exch definefont\n\
+} bind def\n\
+\n\
+% StrokeClip\n\
+%\n\
+% This procedure converts the current path into a clip area under\n\
+% the assumption of stroking. It's a bit tricky because some Postscript\n\
+% interpreters get errors during strokepath for dashed lines. If\n\
+% this happens then turn off dashes and try again.\n\
+\n\
+/StrokeClip {\n\
+ {strokepath} stopped {\n\
+ (This Postscript printer gets limitcheck overflows when) =\n\
+ (stippling dashed lines; lines will be printed solid instead.) =\n\
+ [] 0 setdash strokepath} if\n\
+ clip\n\
+} bind def\n\
+\n\
+% d",
+ /* End of part 2 */
+
+ /* Start of part 3 (2000 characters) */
+ "esiredSize EvenPixels closestSize\n\
+%\n\
+% The procedure below is used for stippling. Given the optimal size\n\
+% of a dot in a stipple pattern in the current user coordinate system,\n\
+% compute the closest size that is an exact multiple of the device's\n\
+% pixel size. This allows stipple patterns to be displayed without\n\
+% aliasing effects.\n\
+\n\
+/EvenPixels {\n\
+ % Compute exact number of device pixels per stipple dot.\n\
+ dup 0 matrix currentmatrix dtransform\n\
+ dup mul exch dup mul add sqrt\n\
+\n\
+ % Round to an integer, make sure the number is at least 1, and compute\n\
+ % user coord distance corresponding to this.\n\
+ dup round dup 1 lt {pop 1} if\n\
+ exch div mul\n\
+} bind def\n\
+\n\
+% width height string StippleFill --\n\
+%\n\
+% Given a path already set up and a clipping region generated from\n\
+% it, this procedure will fill the clipping region with a stipple\n\
+% pattern. \"String\" contains a proper image description of the\n\
+% stipple pattern and \"width\" and \"height\" give its dimensions. Each\n\
+% stipple dot is assumed to be about one unit across in the current\n\
+% user coordinate system. This procedure trashes the graphics state.\n\
+\n\
+/StippleFill {\n\
+ % The following code is needed to work around a NeWSprint bug.\n\
+\n\
+ /tmpstip 1 index def\n\
+\n\
+ % Change the scaling so that one user unit in user coordinates\n\
+ % corresponds to the size of one stipple dot.\n\
+ 1 EvenPixels dup scale\n\
+\n\
+ % Compute the bounding box occupied by the path (which is now\n\
+ % the clipping region), and round the lower coordinates down\n\
+ % to the nearest starting point for the stipple pattern. Be\n\
+ % careful about negative numbers, since the rounding works\n\
+ % differently on them.\n\
+\n\
+ pathbbox\n\
+ 4 2 roll\n\
+ 5 index div dup 0 lt {1 sub} if cvi 5 index mul 4 1 roll\n\
+ 6 index div dup 0 lt {1 sub} if cvi 6 index mul 3 2 roll\n\
+\n\
+ % Stack now: width height string y1 y2 x1 x2\n\
+ % Below is a doubly-nested for loop to iterate across this area\n\
+ % in units of the stipple pattern size, going up columns then\n\
+ % acr",
+ /* End of part 3 */
+
+ /* Start of part 4 (2000 characters) */
+ "oss rows, blasting out a stipple-pattern-sized rectangle at\n\
+ % each position\n\
+\n\
+ 6 index exch {\n\
+ 2 index 5 index 3 index {\n\
+ % Stack now: width height string y1 y2 x y\n\
+\n\
+ gsave\n\
+ 1 index exch translate\n\
+ 5 index 5 index true matrix tmpstip imagemask\n\
+ grestore\n\
+ } for\n\
+ pop\n\
+ } for\n\
+ pop pop pop pop pop\n\
+} bind def\n\
+\n\
+% -- AdjustColor --\n\
+% Given a color value already set for output by the caller, adjusts\n\
+% that value to a grayscale or mono value if requested by the CL\n\
+% variable.\n\
+\n\
+/AdjustColor {\n\
+ CL 2 lt {\n\
+ currentgray\n\
+ CL 0 eq {\n\
+ .5 lt {0} {1} ifelse\n\
+ } if\n\
+ setgray\n\
+ } if\n\
+} bind def\n\
+\n\
+% x y strings spacing xoffset yoffset justify stipple DrawText --\n\
+% This procedure does all of the real work of drawing text. The\n\
+% color and font must already have been set by the caller, and the\n\
+% following arguments must be on the stack:\n\
+%\n\
+% x, y - Coordinates at which to draw text.\n\
+% strings - An array of strings, one for each line of the text item,\n\
+% in order from top to bottom.\n\
+% spacing - Spacing between lines.\n\
+% xoffset - Horizontal offset for text bbox relative to x and y: 0 for\n\
+% nw/w/sw anchor, -0.5 for n/center/s, and -1.0 for ne/e/se.\n\
+% yoffset - Vertical offset for text bbox relative to x and y: 0 for\n\
+% nw/n/ne anchor, +0.5 for w/center/e, and +1.0 for sw/s/se.\n\
+% justify - 0 for left justification, 0.5 for center, 1 for right justify.\n\
+% stipple - Boolean value indicating whether or not text is to be\n\
+% drawn in stippled fashion. If text is stippled,\n\
+% procedure StippleText must have been defined to call\n\
+% StippleFill in the right way.\n\
+%\n\
+% Also, when this procedure is invoked, the color and font must already\n\
+% have been set for the text.\n\
+\n\
+/DrawText {\n\
+ /stipple exch def\n\
+ /justify exch def\n\
+ /yoffset exch def\n\
+ /xoffset exch def\n\
+ /spacing exch def\n\
+ /strings exch def\n\
+\n\
+ % First scan through all of the text to find the widest line.\n\
+\n\
+ /lineLength 0 def\n\
+ strings {\n\
+ stringwidth pop\n\
+ dup lineLength gt {/lineLength exch def}",
+ /* End of part 4 */
+
+ /* Start of part 5 (1546 characters) */
+ " {pop} ifelse\n\
+ newpath\n\
+ } forall\n\
+\n\
+ % Compute the baseline offset and the actual font height.\n\
+\n\
+ 0 0 moveto (TXygqPZ) false charpath\n\
+ pathbbox dup /baseline exch def\n\
+ exch pop exch sub /height exch def pop\n\
+ newpath\n\
+\n\
+ % Translate coordinates first so that the origin is at the upper-left\n\
+ % corner of the text's bounding box. Remember that x and y for\n\
+ % positioning are still on the stack.\n\
+\n\
+ translate\n\
+ lineLength xoffset mul\n\
+ strings length 1 sub spacing mul height add yoffset mul translate\n\
+\n\
+ % Now use the baseline and justification information to translate so\n\
+ % that the origin is at the baseline and positioning point for the\n\
+ % first line of text.\n\
+\n\
+ justify lineLength mul baseline neg translate\n\
+\n\
+ % Iterate over each of the lines to output it. For each line,\n\
+ % compute its width again so it can be properly justified, then\n\
+ % display it.\n\
+\n\
+ strings {\n\
+ dup stringwidth pop\n\
+ justify neg mul 0 moveto\n\
+ stipple {\n\
+\n\
+ % The text is stippled, so turn it into a path and print\n\
+ % by calling StippledText, which in turn calls StippleFill.\n\
+ % Unfortunately, many Postscript interpreters will get\n\
+ % overflow errors if we try to do the whole string at\n\
+ % once, so do it a character at a time.\n\
+\n\
+ gsave\n\
+ /char (X) def\n\
+ {\n\
+ char 0 3 -1 roll put\n\
+ currentpoint\n\
+ gsave\n\
+ char true charpath clip StippleText\n\
+ grestore\n\
+ char stringwidth translate\n\
+ moveto\n\
+ } forall\n\
+ grestore\n\
+ } {show} ifelse\n\
+ 0 spacing neg translate\n\
+ } forall\n\
+} bind def\n\
+\n\
+%%EndProlog\n\
+",
+ /* End of part 5 */
+
+ NULL /* End of data marker */
+};
+
+/*
* Forward declarations for procedures defined later in this file:
*/
@@ -164,6 +478,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
Tcl_HashSearch search;
Tcl_HashEntry *hPtr;
Tcl_DString buffer;
+ CONST char * CONST *chunk;
/*
*----------------------------------------------------------------
@@ -398,7 +713,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
"%%Creator: Tk Canvas Widget\n", (char *) NULL);
#if !(defined(__WIN32__) || defined(MAC_TCL))
if (!Tcl_IsSafe(interp)) {
- struct passwd *pwPtr = getpwuid(getuid());
+ struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */
Tcl_AppendResult(canvasPtr->interp, "%%For: ",
(pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n",
(char *) NULL);
@@ -409,7 +724,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
Tk_PathName(canvasPtr->tkwin), "\n", (char *) NULL);
time(&now);
Tcl_AppendResult(canvasPtr->interp, "%%CreationDate: ",
- ctime(&now), (char *) NULL);
+ ctime(&now), (char *) NULL); /* INTL: Native. */
if (!psInfo.rotate) {
sprintf(string, "%d %d %d %d",
(int) (psInfo.pageX + psInfo.scale*deltaX),
@@ -443,16 +758,14 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
Tcl_AppendResult(canvasPtr->interp, "%%EndComments\n\n", (char *) NULL);
/*
- * Read a standard prolog file in a native way and insert it into
- * the Postscript.
+ * Insert the prolog
*/
-
- if (TkGetNativeProlog(canvasPtr->interp) != TCL_OK) {
- result = TCL_ERROR;
- goto cleanup;
+ for (chunk=prolog; *chunk; chunk++) {
+ Tcl_AppendResult(interp, *chunk, (char *) NULL);
}
+
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -499,7 +812,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
Tcl_AppendResult(canvasPtr->interp, string,
" lineto closepath clip newpath\n", (char *) NULL);
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -524,7 +837,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
result = (*itemPtr->typePtr->postscriptProc)(canvasPtr->interp,
(Tk_Canvas) canvasPtr, itemPtr, 0);
if (result != TCL_OK) {
- char msg[100];
+ char msg[64 + TCL_INTEGER_SPACE];
sprintf(msg, "\n (generating Postscript for item %d)",
itemPtr->id);
@@ -533,7 +846,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
}
Tcl_AppendResult(canvasPtr->interp, "grestore\n", (char *) NULL);
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
}
@@ -548,7 +861,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
Tcl_AppendResult(canvasPtr->interp, "restore showpage\n\n",
"%%Trailer\nend\n%%EOF\n", (char *) NULL);
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -604,9 +917,9 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*
* Results:
* Returns a standard Tcl return value. If an error occurs
- * then an error message will be left in interp->result.
+ * then an error message will be left in the interp's result.
* If no error occurs, then additional Postscript will be
- * appended to interp->result.
+ * appended to the interp's result.
*
* Side effects:
* None.
@@ -685,9 +998,9 @@ Tk_CanvasPsColor(interp, canvas, colorPtr)
*
* Results:
* Returns a standard Tcl return value. If an error occurs
- * then an error message will be left in interp->result.
+ * 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->result.
+ * appended to the interp's result.
*
* Side effects:
* The Postscript font name is entered into psInfoPtr->fontTable
@@ -707,7 +1020,7 @@ Tk_CanvasPsFont(interp, canvas, tkfont)
TkCanvas *canvasPtr = (TkCanvas *) canvas;
TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr;
char *end;
- char pointString[20];
+ char pointString[TCL_INTEGER_SPACE];
Tcl_DString ds;
int i, points;
@@ -779,9 +1092,9 @@ Tk_CanvasPsFont(interp, canvas, tkfont)
*
* Results:
* Returns a standard Tcl return value. If an error occurs
- * then an error message will be left in interp->result.
+ * then an error message will be left in the interp's result.
* If no error occurs, then additional Postscript will be
- * appended to interp->result.
+ * appended to the interp's result.
*
* Side effects:
* None.
@@ -878,9 +1191,9 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height)
*
* Results:
* Returns a standard Tcl return value. If an error occurs
- * then an error message will be left in interp->result.
+ * then an error message will be left in the interp's result.
* If no error occurs, then additional Postscript will be
- * appended to interp->result.
+ * appended to the interp's result.
*
* Side effects:
* None.
@@ -898,7 +1211,7 @@ Tk_CanvasPsStipple(interp, canvas, bitmap)
TkCanvas *canvasPtr = (TkCanvas *) canvas;
TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr;
int width, height;
- char string[100];
+ char string[TCL_INTEGER_SPACE * 2];
Window dummyRoot;
int dummyX, dummyY;
unsigned dummyBorderwidth, dummyDepth;
@@ -966,7 +1279,7 @@ Tk_CanvasPsY(canvas, y)
* commands to create the path.
*
* Results:
- * Postscript commands get appended to what's in interp->result.
+ * Postscript commands get appended to what's in the interp's result.
*
* Side effects:
* None.
@@ -1015,7 +1328,7 @@ Tk_CanvasPsPath(interp, canvas, coordPtr, numPoints)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -1072,92 +1385,3 @@ GetPostscriptPoints(interp, string, doublePtr)
*doublePtr = d;
return TCL_OK;
}
-
-/*
- *--------------------------------------------------------------
- *
- * TkGetProlog --
- *
- * Locate and load the postscript prolog.
- *
- * Results:
- * A standard Tcl Result. If everything is OK the prolog
- * will be located in the result string of the interpreter.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-int
-TkGetProlog(interp)
- Tcl_Interp *interp; /* Places the prolog in the result. */
-{
- char *libDir;
- Tcl_Channel chan;
- Tcl_DString buffer, buffer2;
- char *prologPathParts[2];
- int bufferSize;
- char *prologBuffer;
-
- libDir = Tcl_GetVar(interp, "tk_library", TCL_GLOBAL_ONLY);
- if (libDir == NULL) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "couldn't find library directory: ",
- "tk_library variable doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
- Tcl_TranslateFileName(interp, libDir, &buffer);
- prologPathParts[0] = buffer.string;
- prologPathParts[1] = "prolog.ps";
- Tcl_DStringInit(&buffer2);
- Tcl_JoinPath(2, prologPathParts, &buffer2);
- Tcl_DStringFree(&buffer);
-
- /*
- * Compute size of file by seeking to the end of the file. This will
- * overallocate if we are performing CRLF translation.
- */
-
- chan = Tcl_OpenFileChannel(NULL, buffer2.string, "r", 0);
- if (chan == NULL) {
- /*
- * We have to set the error message ourselves because the
- * interp's result need to be reset.
- */
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "couldn't open \"",
- buffer2.string, "\": ", Tcl_PosixError(interp), (char *) NULL);
- Tcl_DStringFree(&buffer2);
- return TCL_ERROR;
- }
-
- bufferSize = Tcl_Seek(chan, 0L, SEEK_END);
- (void) Tcl_Seek(chan, 0L, SEEK_SET);
- if (bufferSize < 0) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error seeking to end of file \"",
- buffer2.string, "\": ", Tcl_PosixError(interp), (char *) NULL);
- Tcl_Close(NULL, chan);
- Tcl_DStringFree(&buffer2);
- return TCL_ERROR;
-
- }
- prologBuffer = (char *) ckalloc((unsigned) bufferSize+1);
- bufferSize = Tcl_Read(chan, prologBuffer, bufferSize);
- Tcl_Close(NULL, chan);
- if (bufferSize < 0) {
- Tcl_ResetResult(interp);
- Tcl_AppendResult(interp, "error reading file \"", buffer2.string,
- "\": ", Tcl_PosixError(interp), (char *) NULL);
- Tcl_DStringFree(&buffer2);
- return TCL_ERROR;
- }
- Tcl_DStringFree(&buffer2);
- prologBuffer[bufferSize] = 0;
- Tcl_AppendResult(interp, prologBuffer, (char *) NULL);
- ckfree(prologBuffer);
-
- return TCL_OK;
-}
diff --git a/generic/tkCanvText.c b/generic/tkCanvText.c
index 2938ba1..0e624cc 100644
--- a/generic/tkCanvText.c
+++ b/generic/tkCanvText.c
@@ -4,12 +4,12 @@
* This file implements text items for canvas widgets.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvText.c 1.68 97/10/09 17:44:53
+ * SCCS: @(#) tkCanvText.c 1.70 97/11/07 21:15:29
*/
#include <stdio.h>
@@ -36,8 +36,8 @@ typedef struct TextItem {
*/
double x, y; /* Positioning point for text. */
- int insertPos; /* Insertion cursor is displayed just to left
- * of character with this index. */
+ int insertPos; /* Byte index of character just before which
+ * the insertion cursor is displayed. */
/*
* Configuration settings that are updated by Tk_ConfigureWidget.
@@ -57,7 +57,7 @@ typedef struct TextItem {
* configuration settings above.
*/
- int numChars; /* Number of non-NULL characters in text. */
+ 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
@@ -154,26 +154,26 @@ static void TranslateText _ANSI_ARGS_((Tk_Canvas canvas,
*/
Tk_ItemType tkTextType = {
- "text", /* name */
- sizeof(TextItem), /* itemSize */
- CreateText, /* createProc */
- configSpecs, /* configSpecs */
- ConfigureText, /* configureProc */
- TextCoords, /* coordProc */
- DeleteText, /* deleteProc */
- DisplayCanvText, /* displayProc */
- 0, /* alwaysRedraw */
- TextToPoint, /* pointProc */
- TextToArea, /* areaProc */
- TextToPostscript, /* postscriptProc */
- ScaleText, /* scaleProc */
- TranslateText, /* translateProc */
- GetTextIndex, /* indexProc */
- SetTextCursor, /* icursorProc */
- GetSelText, /* selectionProc */
- TextInsert, /* insertProc */
- TextDeleteChars, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ "text", /* name */
+ sizeof(TextItem), /* itemSize */
+ CreateText, /* createProc */
+ configSpecs, /* configSpecs */
+ ConfigureText, /* configureProc */
+ TextCoords, /* coordProc */
+ DeleteText, /* deleteProc */
+ DisplayCanvText, /* displayProc */
+ 0, /* alwaysRedraw */
+ TextToPoint, /* pointProc */
+ TextToArea, /* areaProc */
+ TextToPostscript, /* postscriptProc */
+ ScaleText, /* scaleProc */
+ TranslateText, /* translateProc */
+ GetTextIndex, /* indexProc */
+ SetTextCursor, /* icursorProc */
+ GetSelText, /* selectionProc */
+ TextInsert, /* insertProc */
+ TextDeleteChars, /* dTextProc */
+ (Tk_ItemType *) NULL /* nextPtr */
};
/*
@@ -187,7 +187,7 @@ Tk_ItemType tkTextType = {
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item then an error message is left in
- * interp->result; in this case itemPtr is left uninitialized
+ * the interp's result; in this case itemPtr is left uninitialized
* so it can be safely freed by the caller.
*
* Side effects:
@@ -198,12 +198,12 @@ Tk_ItemType tkTextType = {
static int
CreateText(interp, canvas, itemPtr, argc, argv)
- 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 argc; /* Number of arguments in argv. */
- char **argv; /* Arguments describing rectangle. */
+ 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 argc; /* Number of arguments in argv. */
+ char **argv; /* Arguments describing rectangle. */
{
TextItem *textPtr = (TextItem *) itemPtr;
@@ -215,8 +215,8 @@ CreateText(interp, canvas, itemPtr, argc, argv)
}
/*
- * 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 procedure.
*/
textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas);
@@ -231,7 +231,7 @@ CreateText(interp, canvas, itemPtr, argc, argv)
textPtr->text = NULL;
textPtr->width = 0;
- textPtr->numChars = 0;
+ textPtr->numBytes = 0;
textPtr->textLayout = NULL;
textPtr->leftEdge = 0;
textPtr->rightEdge = 0;
@@ -266,7 +266,7 @@ CreateText(interp, canvas, itemPtr, argc, argv)
* details on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -276,14 +276,12 @@ CreateText(interp, canvas, itemPtr, argc, argv)
static int
TextCoords(interp, canvas, itemPtr, argc, argv)
- 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 argc; /* Number of coordinates supplied in
- * argv. */
- char **argv; /* Array of coordinates: x1, y1,
- * x2, y2, ... */
+ 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 argc; /* Number of coordinates supplied in argv. */
+ char **argv; /* Array of coordinates: x1, y1, x2, y2, ... */
{
TextItem *textPtr = (TextItem *) itemPtr;
char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
@@ -300,8 +298,10 @@ TextCoords(interp, canvas, itemPtr, argc, argv)
}
ComputeTextBbox(canvas, textPtr);
} else {
- sprintf(interp->result,
- "wrong # coordinates: expected 0 or 2, got %d", argc);
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -317,7 +317,7 @@ TextCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information, such as colors and stipple
@@ -400,22 +400,25 @@ ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
* to keep them inside the item.
*/
- textPtr->numChars = strlen(textPtr->text);
+ textPtr->numBytes = strlen(textPtr->text);
if (textInfoPtr->selItemPtr == itemPtr) {
- if (textInfoPtr->selectFirst >= textPtr->numChars) {
+ int numChars;
+
+ numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);
+ if (textInfoPtr->selectFirst >= numChars) {
textInfoPtr->selItemPtr = NULL;
} else {
- if (textInfoPtr->selectLast >= textPtr->numChars) {
- textInfoPtr->selectLast = textPtr->numChars-1;
+ if (textInfoPtr->selectLast >= numChars) {
+ textInfoPtr->selectLast = numChars - 1;
}
if ((textInfoPtr->anchorItemPtr == itemPtr)
- && (textInfoPtr->selectAnchor >= textPtr->numChars)) {
- textInfoPtr->selectAnchor = textPtr->numChars-1;
+ && (textInfoPtr->selectAnchor >= numChars)) {
+ textInfoPtr->selectAnchor = numChars - 1;
}
}
}
- if (textPtr->insertPos >= textPtr->numChars) {
- textPtr->insertPos = textPtr->numChars;
+ if (textPtr->insertPos >= textPtr->numBytes) {
+ textPtr->insertPos = textPtr->numBytes;
}
ComputeTextBbox(canvas, textPtr);
@@ -441,10 +444,9 @@ ConfigureText(interp, canvas, itemPtr, argc, argv, 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. */
+ 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;
@@ -494,16 +496,15 @@ DeleteText(canvas, itemPtr, display)
static void
ComputeTextBbox(canvas, textPtr)
- Tk_Canvas canvas; /* Canvas that contains item. */
- TextItem *textPtr; /* Item whose bbos is to be
- * recomputed. */
+ 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;
Tk_FreeTextLayout(textPtr->textLayout);
textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,
- textPtr->text, textPtr->numChars, textPtr->width,
+ textPtr->text, textPtr->numBytes, textPtr->width,
textPtr->justify, 0, &width, &height);
/*
@@ -591,13 +592,12 @@ ComputeTextBbox(canvas, textPtr)
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 redisplayed (not used). */
+ 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). */
{
TextItem *textPtr;
Tk_CanvasTextInfo *textInfoPtr;
@@ -624,23 +624,31 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
selFirst = -1;
selLast = 0; /* lint. */
if (textInfoPtr->selItemPtr == itemPtr) {
- selFirst = textInfoPtr->selectFirst;
- selLast = textInfoPtr->selectLast;
- if (selLast >= textPtr->numChars) {
- selLast = textPtr->numChars - 1;
+ char *text;
+ int numChars, selFirstChar, selLastChar;
+
+ text = textPtr->text;
+ numChars = Tcl_NumUtfChars(text, textPtr->numBytes);
+ selFirstChar = textInfoPtr->selectFirst;
+ selLastChar = textInfoPtr->selectLast;
+ if (selLastChar >= numChars) {
+ selLastChar = numChars - 1;
}
- if ((selFirst >= 0) && (selFirst <= selLast)) {
+ if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {
+ int xFirst, yFirst, hFirst;
+ int xLast, yLast;
+
/*
* Draw a special background under the selection.
*/
- int xFirst, yFirst, hFirst;
- int xLast, yLast, wLast;
+ selFirst = Tcl_UtfAtIndex(text, selFirstChar) - text;
+ selLast = Tcl_UtfAtIndex(text, selLastChar + 1) - text;
- Tk_CharBbox(textPtr->textLayout, selFirst,
- &xFirst, &yFirst, NULL, &hFirst);
- Tk_CharBbox(textPtr->textLayout, selLast,
- &xLast, &yLast, &wLast, NULL);
+ Tk_CharBbox(textPtr->textLayout, selFirst, &xFirst, &yFirst,
+ NULL, &hFirst);
+ Tk_CharBbox(textPtr->textLayout, selLast, &xLast, &yLast,
+ NULL, NULL);
/*
* If the selection spans the end of this line, then display
@@ -653,7 +661,7 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
height = hFirst;
for (y = yFirst ; y <= yLast; y += height) {
if (y == yLast) {
- width = (xLast + wLast) - x;
+ width = xLast - x;
} else {
width = textPtr->rightEdge - textPtr->leftEdge - x;
}
@@ -754,36 +762,43 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
*/
static void
-TextInsert(canvas, itemPtr, beforeThis, string)
+TextInsert(canvas, itemPtr, index, string)
Tk_Canvas canvas; /* Canvas containing text item. */
Tk_Item *itemPtr; /* Text item to be modified. */
- int beforeThis; /* Index of character before which text is
+ int index; /* Character index before which string is
* to be inserted. */
char *string; /* New characters to be inserted. */
{
TextItem *textPtr = (TextItem *) itemPtr;
- int length;
- char *new;
+ int numChars, byteIndex, byteCount, charsAdded;
+ char *new, *text;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
- length = strlen(string);
- if (length == 0) {
- return;
+ text = textPtr->text;
+ numChars = Tcl_NumUtfChars(text, textPtr->numBytes);
+
+ if (index < 0) {
+ index = 0;
}
- if (beforeThis < 0) {
- beforeThis = 0;
+ if (index > numChars) {
+ index = numChars;
}
- if (beforeThis > textPtr->numChars) {
- beforeThis = textPtr->numChars;
+ byteIndex = Tcl_UtfAtIndex(text, index) - text;
+ byteCount = strlen(string);
+ if (byteCount == 0) {
+ return;
}
- new = (char *) ckalloc((unsigned) (textPtr->numChars + length + 1));
- strncpy(new, textPtr->text, (size_t) beforeThis);
- strcpy(new+beforeThis, string);
- strcpy(new+beforeThis+length, textPtr->text+beforeThis);
- ckfree(textPtr->text);
+ new = (char *) ckalloc((unsigned) textPtr->numBytes + byteCount + 1);
+ memcpy(new, text, (size_t) byteIndex);
+ strcpy(new + byteIndex, string);
+ strcpy(new + byteIndex + byteCount, text + byteIndex);
+
+ ckfree(text);
textPtr->text = new;
- textPtr->numChars += length;
+ textPtr->numBytes += byteCount;
+
+ charsAdded = Tcl_NumUtfChars(new, textPtr->numBytes) - numChars;
/*
* Inserting characters invalidates indices such as those for the
@@ -791,19 +806,19 @@ TextInsert(canvas, itemPtr, beforeThis, string)
*/
if (textInfoPtr->selItemPtr == itemPtr) {
- if (textInfoPtr->selectFirst >= beforeThis) {
- textInfoPtr->selectFirst += length;
+ if (textInfoPtr->selectFirst >= index) {
+ textInfoPtr->selectFirst += charsAdded;
}
- if (textInfoPtr->selectLast >= beforeThis) {
- textInfoPtr->selectLast += length;
+ if (textInfoPtr->selectLast >= index) {
+ textInfoPtr->selectLast += charsAdded;
}
if ((textInfoPtr->anchorItemPtr == itemPtr)
- && (textInfoPtr->selectAnchor >= beforeThis)) {
- textInfoPtr->selectAnchor += length;
+ && (textInfoPtr->selectAnchor >= index)) {
+ textInfoPtr->selectAnchor += charsAdded;
}
}
- if (textPtr->insertPos >= beforeThis) {
- textPtr->insertPos += length;
+ if (textPtr->insertPos >= byteIndex) {
+ textPtr->insertPos += byteCount;
}
ComputeTextBbox(canvas, textPtr);
}
@@ -830,31 +845,41 @@ static void
TextDeleteChars(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. */
+ int first; /* Character index of first character to
+ * delete. */
+ int last; /* Character index of last character to
+ * delete (inclusive). */
{
TextItem *textPtr = (TextItem *) itemPtr;
- int count;
- char *new;
+ int count, numChars, byteIndex, byteCount, charsRemoved;
+ char *new, *text;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ text = textPtr->text;
+ numChars = Tcl_NumUtfChars(text, textPtr->numBytes);
if (first < 0) {
first = 0;
}
- if (last >= textPtr->numChars) {
- last = textPtr->numChars-1;
+ if (last >= numChars) {
+ last = numChars - 1;
}
if (first > last) {
return;
}
count = last + 1 - first;
- new = (char *) ckalloc((unsigned) (textPtr->numChars + 1 - count));
- strncpy(new, textPtr->text, (size_t) first);
- strcpy(new+first, textPtr->text+last+1);
- ckfree(textPtr->text);
+ byteIndex = Tcl_UtfAtIndex(text, first) - text;
+ byteCount = Tcl_UtfAtIndex(text + byteIndex, count) - (text + byteIndex);
+
+ new = (char *) ckalloc((unsigned) (textPtr->numBytes + 1 - byteCount));
+ memcpy(new, text, (size_t) byteIndex);
+ strcpy(new + byteIndex, text + byteIndex + byteCount);
+
+ ckfree(text);
textPtr->text = new;
- textPtr->numChars -= count;
+ textPtr->numBytes -= byteCount;
+
+ charsRemoved = numChars - Tcl_NumUtfChars(new, textPtr->numBytes);
/*
* Update indexes for the selection and cursor to reflect the
@@ -863,15 +888,15 @@ TextDeleteChars(canvas, itemPtr, first, last)
if (textInfoPtr->selItemPtr == itemPtr) {
if (textInfoPtr->selectFirst > first) {
- textInfoPtr->selectFirst -= count;
+ textInfoPtr->selectFirst -= charsRemoved;
if (textInfoPtr->selectFirst < first) {
textInfoPtr->selectFirst = first;
}
}
if (textInfoPtr->selectLast >= first) {
- textInfoPtr->selectLast -= count;
- if (textInfoPtr->selectLast < (first-1)) {
- textInfoPtr->selectLast = (first-1);
+ textInfoPtr->selectLast -= charsRemoved;
+ if (textInfoPtr->selectLast < first - 1) {
+ textInfoPtr->selectLast = first - 1;
}
}
if (textInfoPtr->selectFirst > textInfoPtr->selectLast) {
@@ -879,16 +904,16 @@ TextDeleteChars(canvas, itemPtr, first, last)
}
if ((textInfoPtr->anchorItemPtr == itemPtr)
&& (textInfoPtr->selectAnchor > first)) {
- textInfoPtr->selectAnchor -= count;
+ textInfoPtr->selectAnchor -= charsRemoved;
if (textInfoPtr->selectAnchor < first) {
textInfoPtr->selectAnchor = first;
}
}
}
- if (textPtr->insertPos > first) {
- textPtr->insertPos -= count;
- if (textPtr->insertPos < first) {
- textPtr->insertPos = first;
+ if (textPtr->insertPos > byteIndex) {
+ textPtr->insertPos -= byteCount;
+ if (textPtr->insertPos < byteIndex) {
+ textPtr->insertPos = byteIndex;
}
}
ComputeTextBbox(canvas, textPtr);
@@ -987,11 +1012,11 @@ TextToArea(canvas, itemPtr, rectPtr)
/* 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. */
+ 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. */
{
TextItem *textPtr = (TextItem *) itemPtr;
@@ -1022,10 +1047,9 @@ ScaleText(canvas, itemPtr, originX, originY, scaleX, scaleY)
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. */
+ 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. */
{
TextItem *textPtr = (TextItem *) itemPtr;
@@ -1046,7 +1070,7 @@ TranslateText(canvas, itemPtr, deltaX, deltaY)
* 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.
+ * the interp's result.
*
* Side effects:
* None.
@@ -1062,7 +1086,8 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
* specified. */
char *string; /* Specification of a particular character
* in itemPtr's text. */
- int *indexPtr; /* Where to store converted index. */
+ int *indexPtr; /* Where to store converted character
+ * index. */
{
TextItem *textPtr = (TextItem *) itemPtr;
size_t length;
@@ -1074,25 +1099,27 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
length = strlen(string);
if ((c == 'e') && (strncmp(string, "end", length) == 0)) {
- *indexPtr = textPtr->numChars;
+ *indexPtr = Tcl_UtfAtIndex(textPtr->text, textPtr->numBytes)
+ - textPtr->text;
} else if ((c == 'i') && (strncmp(string, "insert", length) == 0)) {
- *indexPtr = textPtr->insertPos;
+ *indexPtr = Tcl_UtfAtIndex(textPtr->text, textPtr->insertPos)
+ - textPtr->text;
} else if ((c == 's') && (strncmp(string, "sel.first", length) == 0)
&& (length >= 5)) {
if (textInfoPtr->selItemPtr != itemPtr) {
- interp->result = "selection isn't in item";
+ Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC);
return TCL_ERROR;
}
*indexPtr = textInfoPtr->selectFirst;
} else if ((c == 's') && (strncmp(string, "sel.last", length) == 0)
&& (length >= 5)) {
if (textInfoPtr->selItemPtr != itemPtr) {
- interp->result = "selection isn't in item";
+ Tcl_SetResult(interp, "selection isn't in item", TCL_STATIC);
return TCL_ERROR;
}
*indexPtr = textInfoPtr->selectLast;
} else if (c == '@') {
- int x, y;
+ int x, y, byteIndex;
double tmp;
char *end, *p;
@@ -1108,18 +1135,22 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
goto badIndex;
}
y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
- *indexPtr = Tk_PointToChar(textPtr->textLayout,
+ byteIndex = Tk_PointToChar(textPtr->textLayout,
x + canvasPtr->scrollX1 - textPtr->leftEdge,
y + canvasPtr->scrollY1 - textPtr->header.y1);
+ *indexPtr = Tcl_UtfAtIndex(textPtr->text, byteIndex) - textPtr->text;
} else if (Tcl_GetInt(interp, string, indexPtr) == TCL_OK) {
+ int numChars;
+
+ numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);
if (*indexPtr < 0){
*indexPtr = 0;
- } else if (*indexPtr > textPtr->numChars) {
- *indexPtr = textPtr->numChars;
+ } else if (*indexPtr > numChars) {
+ *indexPtr = numChars;
}
} else {
/*
- * Some of the paths here leave messages in interp->result,
+ * Some of the paths here leave messages in the interp's result,
* so we have to clear it out before storing our own message.
*/
@@ -1151,18 +1182,18 @@ GetTextIndex(interp, canvas, itemPtr, string, 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; /* Index of character just before which
- * cursor is to be positioned. */
+ Tk_Canvas canvas; /* Record describing canvas widget. */
+ Tk_Item *itemPtr; /* Text item in which cursor position is to
+ * be set. */
+ int index; /* Byte 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) {
- textPtr->insertPos = textPtr->numChars;
+ } else if (index > textPtr->numBytes) {
+ textPtr->insertPos = textPtr->numBytes;
} else {
textPtr->insertPos = index;
}
@@ -1191,34 +1222,38 @@ 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; /* 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. */
+ 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
+ * character. */
{
TextItem *textPtr = (TextItem *) itemPtr;
- int count;
+ int byteCount;
+ char *text, *selStart, *selEnd;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
- count = textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst - offset;
- if (textInfoPtr->selectLast == textPtr->numChars) {
- count -= 1;
+ if ((textInfoPtr->selectFirst < 0) ||
+ (textInfoPtr->selectFirst > textInfoPtr->selectLast)) {
+ return 0;
}
- if (count > maxBytes) {
- count = maxBytes;
+ text = textPtr->text;
+ selStart = Tcl_UtfAtIndex(text, textInfoPtr->selectFirst);
+ selEnd = Tcl_UtfAtIndex(selStart,
+ textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst);
+ byteCount = selEnd - selStart - offset;
+ if (byteCount > maxBytes) {
+ byteCount = maxBytes;
}
- if (count <= 0) {
+ if (byteCount <= 0) {
return 0;
}
- strncpy(buffer, textPtr->text + textInfoPtr->selectFirst + offset,
- (size_t) count);
- buffer[count] = '\0';
- return count;
+ memcpy(buffer, selStart + offset, (size_t) byteCount);
+ buffer[byteCount] = '\0';
+ return byteCount;
}
/*
@@ -1232,7 +1267,7 @@ GetSelText(canvas, itemPtr, offset, buffer, maxBytes)
* 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
+ * 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.
*
@@ -1244,14 +1279,12 @@ 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. */
+ 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;
diff --git a/generic/tkCanvUtil.c b/generic/tkCanvUtil.c
index 9b52a80..a71b851 100644
--- a/generic/tkCanvUtil.c
+++ b/generic/tkCanvUtil.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkCanvUtil.c 1.7 96/05/03 10:54:22
+ * SCCS: @(#) tkCanvUtil.c 1.8 97/11/07 21:19:06
*/
#include "tk.h"
@@ -177,7 +177,7 @@ Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr)
* 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 interp's result.
*
* Side effects:
* None.
diff --git a/generic/tkCanvWind.c b/generic/tkCanvWind.c
index 61b21da..59f2c87 100644
--- a/generic/tkCanvWind.c
+++ b/generic/tkCanvWind.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkCanvWind.c 1.29 97/10/14 10:40:54
+ * SCCS: @(#) tkCanvWind.c 1.30 97/11/07 21:15:39
*/
#include <stdio.h>
@@ -147,7 +147,7 @@ static Tk_GeomMgr canvasGeomType = {
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is
+ * the interp's result; in this case itemPtr is
* left uninitialized, so it can be safely freed by the
* caller.
*
@@ -214,7 +214,7 @@ CreateWinItem(interp, canvas, itemPtr, argc, argv)
* details on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -248,8 +248,10 @@ WinItemCoords(interp, canvas, itemPtr, argc, argv)
}
ComputeWindowBbox(canvas, winItemPtr);
} else {
- sprintf(interp->result,
- "wrong # coordinates: expected 0 or 2, got %d", argc);
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -265,7 +267,7 @@ WinItemCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information may be set for itemPtr.
diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c
index b093226..f7e7576 100644
--- a/generic/tkCanvas.c
+++ b/generic/tkCanvas.c
@@ -6,12 +6,12 @@
* objects such as rectangles, lines, and texts.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCanvas.c 1.126 97/07/31 09:05:52
+ * SCCS: @(#) tkCanvas.c 1.128 97/12/16 16:20:11
*/
#include "default.h"
@@ -369,7 +369,7 @@ Tk_CanvasCmd(clientData, interp, argc, argv)
goto error;
}
- interp->result = Tk_PathName(canvasPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(canvasPtr->tkwin), TCL_STATIC);
return TCL_OK;
error:
@@ -472,7 +472,10 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
}
if (gotAny) {
- sprintf(interp->result, "%d %d %d %d", x1, y1, x2, y2);
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", x1, y1, x2, y2);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 'b') && (strncmp(argv[1], "bind", length) == 0)
&& (length >= 2)) {
@@ -562,15 +565,30 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
command = Tk_GetBinding(interp, canvasPtr->bindingTable,
object, argv[3]);
if (command == NULL) {
- goto error;
+ char *string;
+
+ 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.
+ */
+
+ if (string[0] != '\0') {
+ goto error;
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ } else {
+ Tcl_SetResult(interp, command, TCL_STATIC);
}
- interp->result = command;
} else {
Tk_GetAllBindings(interp, canvasPtr->bindingTable, object);
}
} else if ((c == 'c') && (strcmp(argv[1], "canvasx") == 0)) {
int x;
double grid;
+ char buf[TCL_DOUBLE_SPACE];
if ((argc < 3) || (argc > 4)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -590,10 +608,12 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
grid = 0.0;
}
x += canvasPtr->xOrigin;
- Tcl_PrintDouble(interp, GridAlign((double) x, grid), interp->result);
+ Tcl_PrintDouble(interp, GridAlign((double) x, grid), buf);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'c') && (strcmp(argv[1], "canvasy") == 0)) {
int y;
double grid;
+ char buf[TCL_DOUBLE_SPACE];
if ((argc < 3) || (argc > 4)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -613,7 +633,8 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
grid = 0.0;
}
y += canvasPtr->yOrigin;
- Tcl_PrintDouble(interp, GridAlign((double) y, grid), interp->result);
+ Tcl_PrintDouble(interp, GridAlign((double) y, grid), buf);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
&& (length >= 2)) {
if (argc != 3) {
@@ -664,6 +685,7 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
Tk_ItemType *typePtr;
Tk_ItemType *matchPtr = NULL;
Tk_Item *itemPtr;
+ char buf[TCL_INTEGER_SPACE];
if (argc < 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -713,7 +735,8 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
canvasPtr->flags |= REPICK_NEEDED;
- sprintf(interp->result, "%d", itemPtr->id);
+ sprintf(buf, "%d", itemPtr->id);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'd') && (strncmp(argv[1], "dchars", length) == 0)
&& (length >= 2)) {
int first, last;
@@ -853,7 +876,10 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
itemPtr = canvasPtr->textInfo.focusItemPtr;
if (argc == 2) {
if (itemPtr != NULL) {
- sprintf(interp->result, "%d", itemPtr->id);
+ char buf[TCL_INTEGER_SPACE];
+
+ sprintf(buf, "%d", itemPtr->id);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
goto done;
}
@@ -923,6 +949,7 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
&& (length >= 3)) {
int index;
+ char buf[TCL_INTEGER_SPACE];
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -945,7 +972,8 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
itemPtr, argv[3], &index) != TCL_OK) {
goto error;
}
- sprintf(interp->result, "%d", index);
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
&& (length >= 3)) {
int beforeThis;
@@ -1129,7 +1157,7 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
goto error;
}
if ((xScale == 0.0) || (yScale == 0.0)) {
- interp->result = "scale factor cannot be zero";
+ Tcl_SetResult(interp, "scale factor cannot be zero", TCL_STATIC);
goto error;
}
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
@@ -1264,8 +1292,10 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
goto error;
}
if (canvasPtr->textInfo.selItemPtr != NULL) {
- sprintf(interp->result, "%d",
- canvasPtr->textInfo.selItemPtr->id);
+ char buf[TCL_INTEGER_SPACE];
+
+ sprintf(buf, "%d", canvasPtr->textInfo.selItemPtr->id);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 't') && (strncmp(argv[2], "to", length) == 0)) {
if (argc != 5) {
@@ -1289,7 +1319,7 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
if (itemPtr != NULL) {
- interp->result = itemPtr->typePtr->name;
+ Tcl_SetResult(interp, itemPtr->typePtr->name, TCL_STATIC);
}
} else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) {
int count, type;
@@ -1301,7 +1331,7 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
PrintScrollFractions(canvasPtr->xOrigin + canvasPtr->inset,
canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)
- canvasPtr->inset, canvasPtr->scrollX1,
- canvasPtr->scrollX2, interp->result);
+ canvasPtr->scrollX2, Tcl_GetStringResult(interp));
} else {
type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
switch (type) {
@@ -1339,7 +1369,7 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
PrintScrollFractions(canvasPtr->yOrigin + canvasPtr->inset,
canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin)
- canvasPtr->inset, canvasPtr->scrollY1,
- canvasPtr->scrollY2, interp->result);
+ canvasPtr->scrollY2, Tcl_GetStringResult(interp));
} else {
type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
switch (type) {
@@ -1456,7 +1486,7 @@ DestroyCanvas(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
@@ -2344,7 +2374,7 @@ NextItem(searchPtr)
*
* Side effects:
* If tag is NULL then itemPtr's id is added as a list element
- * to interp->result; otherwise tag is added to itemPtr's
+ * to the interp's result; otherwise tag is added to itemPtr's
* list of tags.
*
*--------------------------------------------------------------
@@ -2366,7 +2396,8 @@ DoItem(interp, itemPtr, tag)
*/
if (tag == NULL) {
- char msg[30];
+ char msg[TCL_INTEGER_SPACE];
+
sprintf(msg, "%d", itemPtr->id);
Tcl_AppendElement(interp, msg);
return;
@@ -2420,9 +2451,9 @@ DoItem(interp, itemPtr, tag)
* 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 interp->result. If newTag is NULL, then
- * the normal interp->result is an empty string. If an error
- * occurs, then interp->result will hold an error message.
+ * 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
@@ -2445,7 +2476,7 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
char *newTag; /* If non-NULL, gives new tag to set
* on all found items; if NULL, then
* ids of found items are returned
- * in interp->result. */
+ * in the interp's result. */
char *cmdName; /* Name of original Tcl command, for
* use in error messages. */
char *option; /* For error messages: gives option
@@ -2651,9 +2682,9 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
* 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 interp->result.
- * If newTag is NULL, then the normal interp->result is an
- * empty string. If an error occurs, then interp->result will
+ * 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.
*
* Side effects:
@@ -2676,7 +2707,7 @@ FindArea(interp, canvasPtr, argv, uid, enclosed)
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 interp->result. */
+ * in the interp's result. */
int enclosed; /* 0 means overlapping or enclosed
* items are OK, 1 means only enclosed
* items are OK. */
diff --git a/generic/tkClipboard.c b/generic/tkClipboard.c
index e1c9510..5e2074d 100644
--- a/generic/tkClipboard.c
+++ b/generic/tkClipboard.c
@@ -6,12 +6,12 @@
* supplied on demand to requesting applications.
*
* Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkClipboard.c 1.15 96/05/03 10:51:08
+ * SCCS: @(#) tkClipboard.c 1.16 97/11/07 21:16:25
*/
#include "tkInt.h"
@@ -226,7 +226,7 @@ ClipboardLostSel(clientData)
*
* Results:
* A standard Tcl result. If an error occurs, an error message is
- * left in interp->result.
+ * left in the interp's result.
*
* Side effects:
* From now on, requests for the CLIPBOARD selection will be
@@ -311,7 +311,7 @@ Tk_ClipboardClear(interp, tkwin)
*
* Results:
* A standard Tcl result. If an error is returned, an error message
- * is left in interp->result.
+ * is left in the interp's result.
*
* Side effects:
* The specified buffer will be copied onto the end of the clipboard.
@@ -528,9 +528,10 @@ Tk_ClipboardCmd(clientData, interp, argc, argv)
}
return Tk_ClipboardClear(interp, tkwin);
} else {
- sprintf(interp->result,
- "bad option \"%.50s\": must be clear or append",
- argv[1]);
+ char buf[100 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "bad option \"%.50s\": must be clear or append", argv[1]);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
}
@@ -546,8 +547,8 @@ Tk_ClipboardCmd(clientData, interp, argc, argv)
*
* Results:
* The result is a standard Tcl return value, which is normally TCL_OK.
- * If an error occurs then an error message is left in interp->result
- * and TCL_ERROR is returned.
+ * If an error occurs then an error message is left in the interp's
+ * result and TCL_ERROR is returned.
*
* Side effects:
* Sets up the clipWindow and related data structures.
diff --git a/generic/tkCmds.c b/generic/tkCmds.c
index 34e2867..ab75057 100644
--- a/generic/tkCmds.c
+++ b/generic/tkCmds.c
@@ -5,12 +5,12 @@
* 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-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCmds.c 1.125 97/05/20 16:16:33
+ * SCCS: @(#) tkCmds.c 1.130 97/11/07 21:16:34
*/
#include "tkPort.h"
@@ -33,7 +33,7 @@ static void WaitWindowProc _ANSI_ARGS_((ClientData clientData,
/*
*----------------------------------------------------------------------
*
- * Tk_BellCmd --
+ * Tk_BellObjCmd --
*
* This procedure is invoked to process the "bell" Tcl command.
* See the user documentation for details on what it does.
@@ -48,29 +48,30 @@ static void WaitWindowProc _ANSI_ARGS_((ClientData clientData,
*/
int
-Tk_BellCmd(clientData, interp, argc, argv)
+Tk_BellObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
+ static char *bellOptions[] = {"-displayof", (char *) NULL};
Tk_Window tkwin = (Tk_Window) clientData;
- size_t length;
+ char *displayName;
+ int index;
- if ((argc != 1) && (argc != 3)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " ?-displayof window?\"", (char *) NULL);
+ if ((objc != 1) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window?");
return TCL_ERROR;
}
- if (argc == 3) {
- length = strlen(argv[1]);
- if ((length < 2) || (strncmp(argv[1], "-displayof", length) != 0)) {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be -displayof", (char *) NULL);
+ if (objc == 3) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], bellOptions, "option", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
- tkwin = Tk_NameToWindow(interp, argv[2], tkwin);
+ displayName = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+
+ tkwin = Tk_NameToWindow(interp, displayName, tkwin);
if (tkwin == NULL) {
return TCL_ERROR;
}
@@ -151,7 +152,7 @@ Tk_BindCmd(clientData, interp, argc, argv)
Tcl_ResetResult(interp);
return TCL_OK;
}
- interp->result = command;
+ Tcl_SetResult(interp, command, TCL_STATIC);
} else {
Tk_GetAllBindings(interp, winPtr->mainPtr->bindingTable, object);
}
@@ -595,7 +596,7 @@ Tk_TkObjCmd(clientData, interp, objc, objv)
string = Tcl_GetStringFromObj(objv[2], NULL);
winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string));
}
- Tcl_SetStringObj(Tcl_GetObjResult(interp), winPtr->nameUid, -1);
+ Tcl_AppendResult(interp, winPtr->nameUid, NULL);
break;
}
case TK_SCALING: {
@@ -797,7 +798,7 @@ WaitWindowProc(clientData, eventPtr)
/*
*----------------------------------------------------------------------
*
- * Tk_UpdateCmd --
+ * Tk_UpdateObjCmd --
*
* This procedure is invoked to process the "update" Tcl command.
* See the user documentation for details on what it does.
@@ -813,28 +814,27 @@ WaitWindowProc(clientData, eventPtr)
/* ARGSUSED */
int
-Tk_UpdateCmd(clientData, interp, argc, argv)
+Tk_UpdateObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- int flags;
+ static char *updateOptions[] = {"idletasks", (char *) NULL};
+ int flags, index;
TkDisplay *dispPtr;
- if (argc == 1) {
+ if (objc == 1) {
flags = TCL_DONT_WAIT;
- } else if (argc == 2) {
- if (strncmp(argv[1], "idletasks", strlen(argv[1])) != 0) {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be idletasks", (char *) NULL);
+ } else if (objc == 2) {
+ if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions, "option", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
flags = TCL_IDLE_EVENTS;
} else {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " ?idletasks?\"", (char *) NULL);
+ Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
return TCL_ERROR;
}
@@ -846,7 +846,7 @@ Tk_UpdateCmd(clientData, interp, argc, argv)
* Thus, don't use any information from tkwin after calling
* Tcl_DoOneEvent.
*/
-
+
while (1) {
while (Tcl_DoOneEvent(flags) != 0) {
/* Empty loop body */
@@ -895,10 +895,10 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
int index, x, y, width, height, useX, useY, class, skip;
- char buf[128];
char *string;
TkWindow *winPtr;
Tk_Window tkwin;
+ Tcl_Obj *resultPtr;
static TkStateMap visualMap[] = {
{PseudoColor, "pseudocolor"},
@@ -971,85 +971,73 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
}
}
winPtr = (TkWindow *) tkwin;
+ resultPtr = Tcl_GetObjResult(interp);
switch ((enum options) index) {
case WIN_CELLS: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- Tk_Visual(tkwin)->map_entries);
+ Tcl_SetIntObj(resultPtr, Tk_Visual(tkwin)->map_entries);
break;
}
case WIN_CHILDREN: {
Tcl_Obj *strPtr;
- Tcl_ResetResult(interp);
winPtr = winPtr->childList;
for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {
strPtr = Tcl_NewStringObj(winPtr->pathName, -1);
- Tcl_ListObjAppendElement(NULL,
- Tcl_GetObjResult(interp), strPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
}
break;
}
case WIN_CLASS: {
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_Class(tkwin), -1);
+ Tcl_SetStringObj(resultPtr, Tk_Class(tkwin), -1);
break;
}
case WIN_COLORMAPFULL: {
- Tcl_ResetResult(interp);
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+ Tcl_SetBooleanObj(resultPtr,
TkpCmapStressed(tkwin, Tk_Colormap(tkwin)));
break;
}
case WIN_DEPTH: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Depth(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_Depth(tkwin));
break;
}
case WIN_GEOMETRY: {
- Tcl_ResetResult(interp);
+ 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(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_SetStringObj(resultPtr, buf, -1);
break;
}
case WIN_HEIGHT: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Height(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_Height(tkwin));
break;
}
case WIN_ID: {
+ char buf[TCL_INTEGER_SPACE];
+
Tk_MakeWindowExist(tkwin);
TkpPrintWindowId(buf, Tk_WindowId(tkwin));
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_SetStringObj(resultPtr, buf, -1);
break;
}
case WIN_ISMAPPED: {
- Tcl_ResetResult(interp);
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
- (int) Tk_IsMapped(tkwin));
+ Tcl_SetBooleanObj(resultPtr, (int) Tk_IsMapped(tkwin));
break;
}
case WIN_MANAGER: {
- Tcl_ResetResult(interp);
if (winPtr->geomMgrPtr != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- winPtr->geomMgrPtr->name, -1);
+ Tcl_SetStringObj(resultPtr, winPtr->geomMgrPtr->name, -1);
}
break;
}
case WIN_NAME: {
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_Name(tkwin), -1);
+ Tcl_SetStringObj(resultPtr, Tk_Name(tkwin), -1);
break;
}
case WIN_PARENT: {
- Tcl_ResetResult(interp);
if (winPtr->parentPtr != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- winPtr->parentPtr->pathName, -1);
+ Tcl_SetStringObj(resultPtr, winPtr->parentPtr->pathName, -1);
}
break;
}
@@ -1075,80 +1063,66 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
} else {
TkGetPointerCoords((Tk_Window) winPtr, &x, &y);
}
- Tcl_ResetResult(interp);
if (useX & useY) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
sprintf(buf, "%d %d", x, y);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_SetStringObj(resultPtr, buf, -1);
} else if (useX) {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), x);
+ Tcl_SetIntObj(resultPtr, x);
} else {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), y);
+ Tcl_SetIntObj(resultPtr, y);
}
break;
}
case WIN_REQHEIGHT: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_ReqHeight(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_ReqHeight(tkwin));
break;
}
case WIN_REQWIDTH: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_ReqWidth(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_ReqWidth(tkwin));
break;
}
case WIN_ROOTX: {
Tk_GetRootCoords(tkwin, &x, &y);
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), x);
+ Tcl_SetIntObj(resultPtr, x);
break;
}
case WIN_ROOTY: {
Tk_GetRootCoords(tkwin, &x, &y);
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), y);
+ Tcl_SetIntObj(resultPtr, y);
break;
}
case WIN_SCREEN: {
+ char buf[TCL_INTEGER_SPACE];
+
sprintf(buf, "%d", Tk_ScreenNumber(tkwin));
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- Tk_DisplayName(tkwin), ".", buf, NULL);
+ Tcl_AppendStringsToObj(resultPtr, Tk_DisplayName(tkwin), ".",
+ buf, NULL);
break;
}
case WIN_SCREENCELLS: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- CellsOfScreen(Tk_Screen(tkwin)));
+ Tcl_SetIntObj(resultPtr, CellsOfScreen(Tk_Screen(tkwin)));
break;
}
case WIN_SCREENDEPTH: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- DefaultDepthOfScreen(Tk_Screen(tkwin)));
+ Tcl_SetIntObj(resultPtr, DefaultDepthOfScreen(Tk_Screen(tkwin)));
break;
}
case WIN_SCREENHEIGHT: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- HeightOfScreen(Tk_Screen(tkwin)));
+ Tcl_SetIntObj(resultPtr, HeightOfScreen(Tk_Screen(tkwin)));
break;
}
case WIN_SCREENWIDTH: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- WidthOfScreen(Tk_Screen(tkwin)));
+ Tcl_SetIntObj(resultPtr, WidthOfScreen(Tk_Screen(tkwin)));
break;
}
case WIN_SCREENMMHEIGHT: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- HeightMMOfScreen(Tk_Screen(tkwin)));
+ Tcl_SetIntObj(resultPtr, HeightMMOfScreen(Tk_Screen(tkwin)));
break;
}
case WIN_SCREENMMWIDTH: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp),
- WidthMMOfScreen(Tk_Screen(tkwin)));
+ Tcl_SetIntObj(resultPtr, WidthMMOfScreen(Tk_Screen(tkwin)));
break;
}
case WIN_SCREENVISUAL: {
@@ -1162,9 +1136,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
case WIN_TOPLEVEL: {
winPtr = GetToplevel(tkwin);
if (winPtr != NULL) {
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- winPtr->pathName, -1);
+ Tcl_SetStringObj(resultPtr, winPtr->pathName, -1);
}
break;
}
@@ -1181,8 +1153,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
break;
}
}
- Tcl_ResetResult(interp);
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), viewable);
+ Tcl_SetBooleanObj(resultPtr, viewable);
break;
}
case WIN_VISUAL: {
@@ -1193,54 +1164,47 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
if (string == NULL) {
string = "unknown";
}
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), string, -1);
+ Tcl_SetStringObj(resultPtr, string, -1);
break;
}
case WIN_VISUALID: {
- Tcl_ResetResult(interp);
+ char buf[TCL_INTEGER_SPACE];
+
sprintf(buf, "0x%x",
(unsigned int) XVisualIDFromVisual(Tk_Visual(tkwin)));
- Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_SetStringObj(resultPtr, buf, -1);
break;
}
case WIN_VROOTHEIGHT: {
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), height);
+ Tcl_SetIntObj(resultPtr, height);
break;
}
case WIN_VROOTWIDTH: {
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), width);
+ Tcl_SetIntObj(resultPtr, width);
break;
}
case WIN_VROOTX: {
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), x);
+ Tcl_SetIntObj(resultPtr, x);
break;
}
case WIN_VROOTY: {
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), y);
+ Tcl_SetIntObj(resultPtr, y);
break;
}
case WIN_WIDTH: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Width(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_Width(tkwin));
break;
}
case WIN_X: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_X(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_X(tkwin));
break;
}
case WIN_Y: {
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Y(tkwin));
+ Tcl_SetIntObj(resultPtr, Tk_Y(tkwin));
break;
}
@@ -1259,9 +1223,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
}
objv += skip;
string = Tcl_GetStringFromObj(objv[2], NULL);
- Tcl_ResetResult(interp);
- Tcl_SetLongObj(Tcl_GetObjResult(interp),
- (long) Tk_InternAtom(tkwin, string));
+ Tcl_SetLongObj(resultPtr, (long) Tk_InternAtom(tkwin, string));
break;
}
case WIN_ATOMNAME: {
@@ -1280,15 +1242,14 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_ResetResult(interp);
name = Tk_GetAtomName(tkwin, (Atom) id);
if (strcmp(name, "?bad atom?") == 0) {
string = Tcl_GetStringFromObj(objv[2], NULL);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_AppendStringsToObj(resultPtr,
"no atom exists with id \"", string, "\"", NULL);
return TCL_ERROR;
}
- Tcl_SetStringObj(Tcl_GetObjResult(interp), name, -1);
+ Tcl_SetStringObj(resultPtr, name, -1);
break;
}
case WIN_CONTAINING: {
@@ -1312,9 +1273,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
}
tkwin = Tk_CoordsToWindow(x, y, tkwin);
if (tkwin != NULL) {
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- Tk_PathName(tkwin), -1);
+ Tcl_SetStringObj(resultPtr, Tk_PathName(tkwin), -1);
}
break;
}
@@ -1351,9 +1310,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
Tk_IdToWindow(Tk_Display(tkwin), (Window) id);
if ((winPtr == NULL) ||
(winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "window id \"", string,
+ Tcl_AppendStringsToObj(resultPtr, "window id \"", string,
"\" doesn't exist in this application", (char *) NULL);
return TCL_ERROR;
}
@@ -1366,9 +1323,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
tkwin = (Tk_Window) winPtr;
if (Tk_PathName(tkwin) != NULL) {
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
- Tk_PathName(tkwin), -1);
+ Tcl_SetStringObj(resultPtr, Tk_PathName(tkwin), -1);
}
break;
}
@@ -1386,12 +1341,14 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
}
string = Tcl_GetStringFromObj(objv[2], NULL);
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_ResetResult(interp); /* clear any error msg */
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), alive);
+ Tcl_SetBooleanObj(resultPtr, alive);
break;
}
case WIN_FPIXELS: {
@@ -1411,9 +1368,8 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
pixels = mm * WidthOfScreen(Tk_Screen(tkwin))
- / WidthMMOfScreen(Tk_Screen(tkwin));
- Tcl_ResetResult(interp);
- Tcl_SetDoubleObj(Tcl_GetObjResult(interp), pixels);
+ / WidthMMOfScreen(Tk_Screen(tkwin));
+ Tcl_SetDoubleObj(resultPtr, pixels);
break;
}
case WIN_PIXELS: {
@@ -1432,12 +1388,12 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_ResetResult(interp);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), pixels);
+ Tcl_SetIntObj(resultPtr, pixels);
break;
}
case WIN_RGB: {
XColor *colorPtr;
+ char buf[TCL_INTEGER_SPACE * 3];
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "window colorName");
@@ -1456,16 +1412,16 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
sprintf(buf, "%d %d %d", colorPtr->red, colorPtr->green,
colorPtr->blue);
Tk_FreeColor(colorPtr);
- Tcl_ResetResult(interp);
- Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_SetStringObj(resultPtr, buf, -1);
break;
}
case WIN_VISUALSAVAILABLE: {
XVisualInfo template, *visInfoPtr;
int count, i;
- char visualIdString[16];
int includeVisualId;
Tcl_Obj *strPtr;
+ char buf[16 + TCL_INTEGER_SPACE];
+ char visualIdString[TCL_INTEGER_SPACE];
if (objc == 3) {
includeVisualId = 0;
@@ -1487,9 +1443,8 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
template.screen = Tk_ScreenNumber(tkwin);
visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask,
&template, &count);
- Tcl_ResetResult(interp);
if (visInfoPtr == NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ Tcl_SetStringObj(resultPtr,
"can't find any visuals for screen", -1);
return TCL_ERROR;
}
@@ -1506,8 +1461,7 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
strcat(buf, visualIdString);
}
strPtr = Tcl_NewStringObj(buf, -1);
- Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
- strPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
}
XFree((char *) visInfoPtr);
break;
diff --git a/generic/tkColor.c b/generic/tkColor.c
index 781971c..abaaf02 100644
--- a/generic/tkColor.c
+++ b/generic/tkColor.c
@@ -6,48 +6,33 @@
* map color names to pixel values.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkColor.c 1.44 96/11/04 13:55:25
+ * SCCS: @(#) tkColor.c 1.55 97/12/24 15:52:02
*/
-#include <tkColor.h>
+#include "tkColor.h"
/*
- * A two-level data structure is used to manage the color database.
- * The top level consists of one entry for each color name that is
- * currently active, and the bottom level contains one entry for each
- * pixel value that is still in use. The distinction between
- * levels is necessary because the same pixel may have several
- * different names. There are two hash tables, one used to index into
- * each of the data structures. The name hash table is used when
- * allocating colors, and the pixel hash table is used when freeing
- * colors.
- */
-
-
-/*
- * Hash table for name -> TkColor mapping, and key structure used to
- * index into that table:
+ * There are two global hash tables used for managing colors. The
+ * first one, nameTable, maps from string color names like "red" or
+ * "#00ff80" to TkColor structures. It is used by Tk_AllocColorFromObj
+ * Tk_GetColor. The second table, valueTable, maps from integer
+ * RGB values to TkColor structures. It is used by Tk_GetColorByValue
*/
static Tcl_HashTable nameTable;
-typedef struct {
- Tk_Uid name; /* Name of desired color. */
- Colormap colormap; /* Colormap from which color will be
- * allocated. */
- Display *display; /* Display for colormap. */
-} NameKey;
+static Tcl_HashTable valueTable;
+static int initialized = 0; /* 0 means static structures haven't been
+ * initialized yet. */
/*
- * Hash table for value -> TkColor mapping, and key structure used to
- * index into that table:
+ * Structures of the following following type are used as keys for valueTable.
*/
-static Tcl_HashTable valueTable;
typedef struct {
int red, green, blue; /* Values for desired color. */
Colormap colormap; /* Colormap from which color will be
@@ -55,14 +40,125 @@ typedef struct {
Display *display; /* Display for colormap. */
} ValueKey;
-static int initialized = 0; /* 0 means static structures haven't been
- * initialized yet. */
-
/*
* Forward declarations for procedures defined in this file:
*/
static void ColorInit _ANSI_ARGS_((void));
+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));
+
+/*
+ * 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.
+ */
+
+static Tcl_ObjType colorObjType = {
+ "color", /* name */
+ FreeColorObjProc, /* freeIntRepProc */
+ DupColorObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocColorFromObj --
+ *
+ * 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).
+ *
+ * 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
+ * aren't in use anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XColor *
+Tk_AllocColorFromObj(interp, tkwin, objPtr)
+ 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
+ * value is a color name such as "red" or
+ * "#ff0000".*/
+{
+ TkColor *tkColPtr;
+
+ if (objPtr->typePtr != &colorObjType) {
+ InitColorObj(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 (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.
+ */
+
+ FreeColorObjProc(objPtr);
+ tkColPtr = NULL;
+ } else if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ tkColPtr->resourceRefCount++;
+ return (XColor *) tkColPtr;
+ }
+ }
+
+ /*
+ * 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);
+ FreeColorObjProc(objPtr);
+ for (tkColPtr = firstColorPtr; tkColPtr != NULL;
+ tkColPtr = tkColPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ tkColPtr->resourceRefCount++;
+ tkColPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr;
+ return (XColor *) tkColPtr;
+ }
+ }
+ }
+
+ /*
+ * 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;
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount++;
+ }
+ return (XColor *) tkColPtr;
+}
/*
*----------------------------------------------------------------------
@@ -77,7 +173,7 @@ static void ColorInit _ANSI_ARGS_((void));
* 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 interp->result.
+ * 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.
@@ -93,14 +189,13 @@ 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 allocated (in form
+ char *name; /* Name of color to be allocated (in form
* suitable for passing to XParseColor). */
{
- NameKey nameKey;
Tcl_HashEntry *nameHashPtr;
int new;
TkColor *tkColPtr;
- Display *display = Tk_Display(tkwin);
+ TkColor *existingColPtr;
if (!initialized) {
ColorInit();
@@ -111,14 +206,19 @@ Tk_GetColor(interp, tkwin, name)
* name.
*/
- nameKey.name = name;
- nameKey.colormap = Tk_Colormap(tkwin);
- nameKey.display = display;
- nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
+ nameHashPtr = Tcl_CreateHashEntry(&nameTable, name, &new);
if (!new) {
- tkColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr);
- tkColPtr->refCount++;
- return &tkColPtr->color;
+ existingColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr);
+ for (tkColPtr = existingColPtr; tkColPtr != NULL;
+ tkColPtr = tkColPtr->nextPtr) {
+ if ((tkColPtr->screen == Tk_Screen(tkwin))
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ tkColPtr->resourceRefCount++;
+ return &tkColPtr->color;
+ }
+ }
+ } else {
+ existingColPtr = NULL;
}
/*
@@ -137,7 +237,9 @@ Tk_GetColor(interp, tkwin, name)
"\"", (char *) NULL);
}
}
- Tcl_DeleteHashEntry(nameHashPtr);
+ if (new) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
return (XColor *) NULL;
}
@@ -148,11 +250,13 @@ Tk_GetColor(interp, tkwin, name)
tkColPtr->magic = COLOR_MAGIC;
tkColPtr->gc = None;
tkColPtr->screen = Tk_Screen(tkwin);
- tkColPtr->colormap = nameKey.colormap;
+ tkColPtr->colormap = Tk_Colormap(tkwin);
tkColPtr->visual = Tk_Visual(tkwin);
- tkColPtr->refCount = 1;
+ tkColPtr->resourceRefCount = 1;
+ tkColPtr->objRefCount = 0;
tkColPtr->tablePtr = &nameTable;
tkColPtr->hashPtr = nameHashPtr;
+ tkColPtr->nextPtr = existingColPtr;
Tcl_SetHashValue(nameHashPtr, tkColPtr);
return &tkColPtr->color;
@@ -211,7 +315,7 @@ Tk_GetColorByValue(tkwin, colorPtr)
valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new);
if (!new) {
tkColPtr = (TkColor *) Tcl_GetHashValue(valueHashPtr);
- tkColPtr->refCount++;
+ tkColPtr->resourceRefCount++;
return &tkColPtr->color;
}
@@ -226,9 +330,11 @@ Tk_GetColorByValue(tkwin, colorPtr)
tkColPtr->screen = Tk_Screen(tkwin);
tkColPtr->colormap = valueKey.colormap;
tkColPtr->visual = Tk_Visual(tkwin);
- tkColPtr->refCount = 1;
+ tkColPtr->resourceRefCount = 1;
+ tkColPtr->objRefCount = 0;
tkColPtr->tablePtr = &valueTable;
tkColPtr->hashPtr = valueHashPtr;
+ tkColPtr->nextPtr = NULL;
Tcl_SetHashValue(valueHashPtr, tkColPtr);
return &tkColPtr->color;
}
@@ -264,7 +370,7 @@ Tk_NameOfColor(colorPtr)
if ((tkColPtr->magic == COLOR_MAGIC)
&& (tkColPtr->tablePtr == &nameTable)) {
- return ((NameKey *) tkColPtr->hashPtr->key.words)->name;
+ return tkColPtr->hashPtr->key.string;
}
sprintf(string, "#%04x%04x%04x", colorPtr->red, colorPtr->green,
colorPtr->blue);
@@ -347,8 +453,9 @@ Tk_FreeColor(colorPtr)
* allocated by Tk_GetColor or
* Tk_GetColorByValue. */
{
- register TkColor *tkColPtr = (TkColor *) colorPtr;
+ TkColor *tkColPtr = (TkColor *) colorPtr;
Screen *screen = tkColPtr->screen;
+ TkColor *prevPtr;
/*
* Do a quick sanity check to make sure this color was really
@@ -359,15 +466,45 @@ Tk_FreeColor(colorPtr)
panic("Tk_FreeColor called with bogus color");
}
- tkColPtr->refCount--;
- if (tkColPtr->refCount == 0) {
- if (tkColPtr->gc != None) {
- XFreeGC(DisplayOfScreen(screen), tkColPtr->gc);
- tkColPtr->gc = None;
+ tkColPtr->resourceRefCount--;
+ if (tkColPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ /*
+ * 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.
+ */
+
+ if (tkColPtr->gc != None) {
+ XFreeGC(DisplayOfScreen(screen), tkColPtr->gc);
+ tkColPtr->gc = None;
+ }
+ TkpFreeColor(tkColPtr);
+
+ prevPtr = (TkColor *) Tcl_GetHashValue(tkColPtr->hashPtr);
+ if (prevPtr == tkColPtr) {
+ if (tkColPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(tkColPtr->hashPtr);
+ } else {
+ Tcl_SetHashValue(tkColPtr->hashPtr, tkColPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != tkColPtr) {
+ prevPtr = prevPtr->nextPtr;
}
- TkpFreeColor(tkColPtr);
- Tcl_DeleteHashEntry(tkColPtr->hashPtr);
- tkColPtr->magic = 0;
+ prevPtr->nextPtr = tkColPtr->nextPtr;
+ }
+
+ /*
+ * 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) {
ckfree((char *) tkColPtr);
}
}
@@ -375,6 +512,221 @@ 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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_FreeColor(Tk_GetColorFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeColorObjProc(objPtr)
+ Tcl_Obj *objPtr; /* The object we are releasing. */
+{
+ TkColor *tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount--;
+ if ((tkColPtr->objRefCount == 0)
+ && (tkColPtr->resourceRefCount == 0)) {
+ ckfree((char *) tkColPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupColorObjProc --
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupColorObjProc(srcObjPtr, dupObjPtr)
+ 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;
+
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount++;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+XColor *
+Tk_GetColorFromObj(tkwin, objPtr)
+ Tk_Window tkwin; /* The window in which the color will be
+ * used. */
+ Tcl_Obj *objPtr; /* String value contains the name of the
+ * desired color. */
+{
+ TkColor *tkColPtr;
+ Tcl_HashEntry *hashPtr;
+
+ if (objPtr->typePtr != &colorObjType) {
+ InitColorObj(objPtr);
+ }
+
+ tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1;
+ if (tkColPtr != NULL) {
+ if ((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.
+ */
+
+ return (XColor *) tkColPtr;
+ }
+ hashPtr = tkColPtr->hashPtr;
+ FreeColorObjProc(objPtr);
+ } else {
+ hashPtr = Tcl_FindHashEntry(&nameTable, 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 TkColor structures. See if any of them will work.
+ */
+
+ for (tkColPtr = (TkColor *) Tcl_GetHashValue(hashPtr);
+ (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr;
+ tkColPtr->objRefCount++;
+ return (XColor *) tkColPtr;
+ }
+ }
+
+ error:
+ panic(" Tk_GetColorFromObj called with non-existent color!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitColorObj --
+ *
+ * Bookeeping procedure 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).
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitColorObj(objPtr)
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+ objPtr->typePtr = &colorObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ColorInit --
*
* Initialize the structure used for color management.
@@ -392,6 +744,54 @@ static void
ColorInit()
{
initialized = 1;
- Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
+ Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int));
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugColor --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkColor *tkColPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&nameTable, name);
+ if (hashPtr != NULL) {
+ tkColPtr = (TkColor *) Tcl_GetHashValue(hashPtr);
+ if (tkColPtr == NULL) {
+ panic("TkDebugColor found empty hash table entry");
+ }
+ for ( ; (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
+ objPtr = Tcl_NewObj();
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(tkColPtr->resourceRefCount));
+ Tcl_ListObjAppendElement(NULL, objPtr,
+ Tcl_NewIntObj(tkColPtr->objRefCount));
+ Tcl_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
diff --git a/generic/tkColor.h b/generic/tkColor.h
index 9653243..1ab252e 100644
--- a/generic/tkColor.h
+++ b/generic/tkColor.h
@@ -4,12 +4,12 @@
* Declarations of data types and functions used by the
* Tk color module.
*
- * Copyright (c) 1996 by Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkColor.h 1.1 96/10/22 16:53:09
+ * SCCS: @(#) tkColor.h 1.6 97/12/24 15:52:05
*/
#ifndef _TKCOLOR
@@ -19,8 +19,8 @@
/*
* One of the following data structures is used to keep track of
- * each color that the color module has allocated from the X display
- * server.
+ * each color that is being used by the application; typically there
+ * is a colormap entry allocated for each of these colors.
*/
#define COLOR_MAGIC ((unsigned int) 0x46140277)
@@ -38,11 +38,30 @@ typedef struct TkColor {
Colormap colormap; /* Colormap from which this entry was
* allocated. */
Visual *visual; /* Visual associated with colormap. */
- int refCount; /* Number of uses of this structure. */
+ 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
+ * 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_HashTable *tablePtr; /* Hash table that indexes this structure
* (needed when deleting structure). */
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. */
} TkColor;
/*
diff --git a/generic/tkConfig.c b/generic/tkConfig.c
index 2204714..52501d6 100644
--- a/generic/tkConfig.c
+++ b/generic/tkConfig.c
@@ -1,579 +1,1623 @@
/*
* tkConfig.c --
*
- * This file contains the Tk_ConfigureWidget procedure.
+ * This file contains procedures that manage configuration options
+ * for widgets and other things.
*
- * Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkConfig.c 1.53 96/04/26 10:29:31
+ * SCCS: @(#) tkConfig.c 1.51 98/01/19 11:49:18
*/
-#include "tkPort.h"
+/*
+ * Temporary flag for working on new config package.
+ */
+
+#define __NO_OLD_CONFIG
+
#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.
+ */
+
+#define OPTION_HASH_KEY "TkOptionTable"
/*
- * 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!
+ * The following two structures are used along with Tk_OptionSpec
+ * structures to manage configuration options. Tk_OptionSpecs are
+ * 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. */
+ 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. */
+ } extra;
+ int flags; /* Miscellaneous flag values; see
+ * below for definitions. */
+} Option;
+
+/*
+ * Flag bits defined for Option structures:
*
- * INIT - Non-zero means (char *) things have been
- * converted to Tk_Uid's.
+ * OPTION_NEEDS_FREEING - 1 means that FreeResources must be
+ * invoke to free resources associated with
+ * the option when it is no longer needed.
*/
-#define INIT 0x20
+#define OPTION_NEEDS_FREEING 1
+
+/*
+ * 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. */
+} OptionTable;
/*
* Forward declarations for procedures 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,
- Tk_ConfigSpec *specs, char *argvName,
- int needFlags, int hateFlags));
-static char * FormatConfigInfo _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_ConfigSpec *specPtr,
- char *widgRec));
-static char * FormatConfigValue _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_ConfigSpec *specPtr,
- char *widgRec, char *buffer,
- Tcl_FreeProc **freeProcPtr));
+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 * 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));
+
+/*
+ * 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 optionType = {
+ "option", /* name */
+ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
+ (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
+ (Tcl_UpdateStringProc *) NULL, /* updateStringProc */
+ SetOptionFromAny /* setFromAnyProc */
+};
/*
*--------------------------------------------------------------
*
- * Tk_ConfigureWidget --
+ * Tk_CreateOptionTable --
*
- * Process command-line options and database options to
- * fill in fields of a widget record with resources and
- * other parameters.
+ * Given a template for configuration options, this procedure
+ * creates a table that may be used to look up options efficiently.
*
* Results:
- * A standard Tcl return value. In case of an error,
- * interp->result will hold an error message.
+ * Returns a token to a structure that can be passed to procedures
+ * such as Tk_InitOptions, Tk_SetOptions, and Tk_FreeConfigOptions.
*
* 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.
+ * Storage is allocated.
*
*--------------------------------------------------------------
*/
-int
-Tk_ConfigureWidget(interp, tkwin, specs, 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 *specs; /* Describes legal options. */
- int argc; /* Number of elements in argv. */
- 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_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. */
{
- 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. */
-
- needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
- if (Tk_Depth(tkwin) <= 1) {
- hateFlags = TK_CONFIG_COLOR_ONLY;
- } else {
- hateFlags = TK_CONFIG_MONO_ONLY;
+ Tcl_HashTable *hashTablePtr;
+ Tcl_HashEntry *hashEntryPtr;
+ int newEntry;
+ OptionTable *tablePtr;
+ CONST Tk_OptionSpec *specPtr, *specPtr2;
+ Option *optionPtr;
+ 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.
+ */
+
+ hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY,
+ NULL);
+ if (hashTablePtr == NULL) {
+ hashTablePtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(hashTablePtr, TCL_ONE_WORD_KEYS);
+ Tcl_SetAssocData(interp, OPTION_HASH_KEY, DestroyOptionHashTable,
+ (ClientData) hashTablePtr);
+ }
+
+ /*
+ * See if a table has already been created for this template. If
+ * so, just reuse the existing table.
+ */
+
+ hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr,
+ &newEntry);
+ if (!newEntry) {
+ tablePtr = (OptionTable *) Tcl_GetHashValue(hashEntryPtr);
+ tablePtr->refCount++;
+ return (Tk_OptionTable) tablePtr;
+ }
+
+ /*
+ * Count the number of options in the template, then create the
+ * table structure.
+ */
+
+ numOptions = 0;
+ for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) {
+ numOptions++;
}
+ tablePtr = (OptionTable *) (ckalloc(sizeof(OptionTable)
+ + ((numOptions - 1) * sizeof(Option))));
+ tablePtr->refCount = 1;
+ tablePtr->hashEntryPtr = hashEntryPtr;
+ tablePtr->nextPtr = NULL;
+ tablePtr->numOptions = numOptions;
/*
- * Pass one: scan through all the option specs, replacing strings
- * with Tk_Uids (if this hasn't been done already) and clearing
- * the TK_CONFIG_OPTION_SPECIFIED flags.
+ * Initialize all of the Option structures in the table.
*/
- for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
- if (!(specPtr->specFlags & INIT) && (specPtr->argvName != NULL)) {
+ for (specPtr = templatePtr, optionPtr = tablePtr->options;
+ specPtr->type != TK_OPTION_END; specPtr++, optionPtr++) {
+ optionPtr->specPtr = specPtr;
+ optionPtr->dbNameUID = NULL;
+ optionPtr->dbClassUID = NULL;
+ optionPtr->defaultPtr = NULL;
+ optionPtr->extra.monoColorPtr = NULL;
+ optionPtr->flags = 0;
+
+ 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.
+ */
+
+ for (specPtr2 = templatePtr, i = 0; ; specPtr2++, i++) {
+ if (specPtr2->type == TK_OPTION_END) {
+ panic("Tk_CreateOptionTable couldn't find synonym");
+ }
+ if (strcmp(specPtr2->optionName,
+ (char *) specPtr->clientData) == 0) {
+ optionPtr->extra.synonymPtr = tablePtr->options + i;
+ break;
+ }
+ }
+ } else {
if (specPtr->dbName != NULL) {
- specPtr->dbName = Tk_GetUid(specPtr->dbName);
+ optionPtr->dbNameUID = Tk_GetUid(specPtr->dbName);
}
if (specPtr->dbClass != NULL) {
- specPtr->dbClass = Tk_GetUid(specPtr->dbClass);
+ optionPtr->dbClassUID =
+ Tk_GetUid(specPtr->dbClass);
}
if (specPtr->defValue != NULL) {
- specPtr->defValue = Tk_GetUid(specPtr->defValue);
+ optionPtr->defaultPtr =
+ Tcl_NewStringObj(specPtr->defValue, -1);
+ Tcl_IncrRefCount(optionPtr->defaultPtr);
+ }
+ if (((specPtr->type == TK_OPTION_COLOR)
+ || (specPtr->type == TK_OPTION_BORDER))
+ && (specPtr->clientData != NULL)) {
+ optionPtr->extra.monoColorPtr =
+ Tcl_NewStringObj((char *) specPtr->clientData, -1);
+ Tcl_IncrRefCount(optionPtr->extra.monoColorPtr);
}
}
- specPtr->specFlags = (specPtr->specFlags & ~TK_CONFIG_OPTION_SPECIFIED)
- | INIT;
+ if (((specPtr->type == TK_OPTION_STRING)
+ && (specPtr->internalOffset >= 0))
+ || (specPtr->type == TK_OPTION_COLOR)
+ || (specPtr->type == TK_OPTION_FONT)
+ || (specPtr->type == TK_OPTION_BITMAP)
+ || (specPtr->type == TK_OPTION_BORDER)
+ || (specPtr->type == TK_OPTION_CURSOR)) {
+ optionPtr->flags |= OPTION_NEEDS_FREEING;
+ }
}
+ tablePtr->hashEntryPtr = hashEntryPtr;
+ Tcl_SetHashValue(hashEntryPtr, tablePtr);
/*
- * Pass two: scan through all of the arguments, processing those
- * that match entries in the specs.
+ * 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).
*/
- for ( ; argc > 0; argc -= 2, argv += 2) {
- specPtr = FindConfigSpec(interp, specs, *argv, needFlags, hateFlags);
- if (specPtr == NULL) {
- return TCL_ERROR;
+ if (specPtr->clientData != NULL) {
+ tablePtr->nextPtr = (OptionTable *) Tk_CreateOptionTable(interp,
+ (Tk_OptionSpec *) specPtr->clientData);
+ }
+
+ return (Tk_OptionTable) tablePtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_DeleteOptionTable --
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_DeleteOptionTable(optionTable)
+ Tk_OptionTable optionTable; /* The option table to delete. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ int count;
+
+ tablePtr->refCount--;
+ if (tablePtr->refCount > 0) {
+ return;
+ }
+
+ if (tablePtr->nextPtr != NULL) {
+ Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr);
+ }
+
+ for (count = tablePtr->numOptions - 1, optionPtr = tablePtr->options;
+ count > 0; count--, optionPtr++) {
+ if (optionPtr->defaultPtr != NULL) {
+ Tcl_DecrRefCount(optionPtr->defaultPtr);
+ }
+ if (((optionPtr->specPtr->type == TK_OPTION_COLOR)
+ || (optionPtr->specPtr->type == TK_OPTION_BORDER))
+ && (optionPtr->extra.monoColorPtr != NULL)) {
+ Tcl_DecrRefCount(optionPtr->extra.monoColorPtr);
}
+ }
+ Tcl_DeleteHashEntry(tablePtr->hashEntryPtr);
+ ckfree((char *) tablePtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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 */
+{
+ Tcl_HashTable *hashTablePtr = (Tcl_HashTable *) clientData;
+ Tcl_HashSearch search;
+ Tcl_HashEntry *hashEntryPtr;
+ OptionTable *tablePtr;
+
+ for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);
+ hashEntryPtr != NULL;
+ hashEntryPtr = Tcl_NextHashEntry(&search)) {
+ tablePtr = (OptionTable *) Tcl_GetHashValue(hashEntryPtr);
/*
- * Process the entry.
+ * 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).
*/
- if (argc < 2) {
- Tcl_AppendResult(interp, "value for \"", *argv,
- "\" missing", (char *) NULL);
- return TCL_ERROR;
- }
- if (DoConfig(interp, tkwin, specPtr, argv[1], 0, widgRec) != TCL_OK) {
- char msg[100];
+ tablePtr->refCount = 1;
+ tablePtr->nextPtr = NULL;
+ Tk_DeleteOptionTable((Tk_OptionTable) tablePtr);
+ }
+ Tcl_DeleteHashTable(hashTablePtr);
+ ckfree((char *) hashTablePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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).
+ *
+ * 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.
+ *
+ * Side effects:
+ * Fields of recordPtr are filled in with initial values.
+ *
+ *--------------------------------------------------------------
+ */
- sprintf(msg, "\n (processing \"%.40s\" option)",
- specPtr->argvName);
- Tcl_AddErrorInfo(interp, msg);
+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. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ int count;
+ char *value;
+ Tcl_Obj *valuePtr;
+ enum {
+ OPTION_DATABASE, SYSTEM_DEFAULT, TABLE_DEFAULT
+ } source;
+
+ /*
+ * 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.
+ */
+
+ if (tablePtr->nextPtr != NULL) {
+ if (Tk_InitOptions(interp, recordPtr,
+ (Tk_OptionTable) tablePtr->nextPtr, tkwin) != TCL_OK) {
return TCL_ERROR;
}
- specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED;
}
/*
- * Pass three: 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.
+ * Iterate over all of the options in the table, initializing each in
+ * turn.
*/
- if (!(flags & TK_CONFIG_ARGV_ONLY)) {
- for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
- if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
- || (specPtr->argvName == NULL)
- || (specPtr->type == TK_CONFIG_SYNONYM)) {
- continue;
+ for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
+ count > 0; optionPtr++, count--) {
+
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ continue;
+ }
+ source = TABLE_DEFAULT;
+
+ /*
+ * We look in three places for the initial value, using the first
+ * non-NULL value that we find. First, check the option database.
+ */
+
+ valuePtr = NULL;
+ if (optionPtr->dbNameUID != NULL) {
+ value = Tk_GetOption(tkwin, optionPtr->dbNameUID,
+ optionPtr->dbClassUID);
+ if (value != NULL) {
+ valuePtr = Tcl_NewStringObj(value, -1);
+ source = OPTION_DATABASE;
}
- if (((specPtr->specFlags & needFlags) != needFlags)
- || (specPtr->specFlags & hateFlags)) {
- continue;
+ }
+
+ /*
+ * Second, check for a system-specific default value.
+ */
+
+ if ((valuePtr == NULL)
+ && (optionPtr->dbNameUID != NULL)) {
+ valuePtr = TkpGetSystemDefault(tkwin, optionPtr->dbNameUID,
+ optionPtr->dbClassUID);
+ if (valuePtr != NULL) {
+ source = SYSTEM_DEFAULT;
}
- value = NULL;
- if (specPtr->dbName != NULL) {
- value = Tk_GetOption(tkwin, specPtr->dbName, specPtr->dbClass);
+ }
+
+ /*
+ * 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)
+ && ((optionPtr->specPtr->type == TK_OPTION_COLOR)
+ || (optionPtr->specPtr->type == TK_OPTION_BORDER))
+ && (Tk_Depth(tkwin) <= 1)
+ && (optionPtr->extra.monoColorPtr != NULL)) {
+ valuePtr = optionPtr->extra.monoColorPtr;
+ } else {
+ valuePtr = optionPtr->defaultPtr;
}
- if (value != NULL) {
- if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
- TCL_OK) {
- char msg[200];
+ }
+
+ if (valuePtr == NULL) {
+ continue;
+ }
+
+ if (DoObjConfig(interp, recordPtr, optionPtr, valuePtr, tkwin,
+ (Tk_SavedOption *) NULL) != TCL_OK) {
+ if (interp != NULL) {
+ char msg[200];
- sprintf(msg, "\n (%s \"%.50s\" in widget \"%.50s\")",
- "database entry for",
- specPtr->dbName, Tk_PathName(tkwin));
- Tcl_AddErrorInfo(interp, msg);
- return TCL_ERROR;
+ 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);
}
- } else {
- value = specPtr->defValue;
- if ((value != NULL) && !(specPtr->specFlags
- & TK_CONFIG_DONT_SET_DEFAULT)) {
- if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
- TCL_OK) {
- char msg[200];
-
- sprintf(msg,
- "\n (%s \"%.50s\" in widget \"%.50s\")",
- "default value for",
- specPtr->dbName, Tk_PathName(tkwin));
- Tcl_AddErrorInfo(interp, msg);
- return TCL_ERROR;
- }
+ if (tkwin != NULL) {
+ sprintf(msg + strlen(msg) - 1, " in widget \"%.50s\")",
+ Tk_PathName(tkwin));
}
+ Tcl_AddErrorInfo(interp, msg);
}
+ return TCL_ERROR;
}
}
-
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
- * FindConfigSpec --
+ * DoObjConfig --
*
- * Search through a table of configuration specs, looking for
- * one that matches a given argvName.
+ * This procedure applies a new value for a configuration option
+ * to the record being configured.
*
* 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 interp->result.
+ * 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.
*
* Side effects:
- * None.
+ * 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 Tk_ConfigSpec *
-FindConfigSpec(interp, specs, argvName, needFlags, hateFlags)
- Tcl_Interp *interp; /* Used for reporting errors. */
- Tk_ConfigSpec *specs; /* Pointer to table of configuration
- * specifications for a widget. */
- char *argvName; /* Name (suitable for use in a "config"
- * command) identifying particular option. */
- int needFlags; /* Flags that must be present in matching
- * entry. */
- int hateFlags; /* Flags that must NOT be present in
- * matching entry. */
+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
+ * 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
+ * to allocate resources for some options).
+ * 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
+ * of the caller (the caller must eventually
+ * free the old value). */
{
- register Tk_ConfigSpec *specPtr;
- register char c; /* First character of current argument. */
- Tk_ConfigSpec *matchPtr; /* Matching spec, or NULL. */
- size_t length;
-
- c = argvName[1];
- length = strlen(argvName);
- matchPtr = NULL;
- for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
- if (specPtr->argvName == NULL) {
- continue;
+ Tcl_Obj **slotPtrPtr, *oldPtr;
+ 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. */
+ CONST Tk_OptionSpec *specPtr;
+ int nullOK;
+
+ /*
+ * Save the old object form for the value, if there is one.
+ */
+
+ specPtr = optionPtr->specPtr;
+ if (specPtr->objOffset >= 0) {
+ slotPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
+ oldPtr = *slotPtrPtr;
+ } else {
+ slotPtrPtr = NULL;
+ oldPtr = NULL;
+ }
+
+ /*
+ * Apply the new value in a type-specific way. Also remember the
+ * old object and internal forms, if they exist.
+ */
+
+ if (specPtr->internalOffset >= 0) {
+ internalPtr = recordPtr + specPtr->internalOffset;
+ } else {
+ internalPtr = NULL;
+ }
+ if (savedOptionPtr != NULL) {
+ savedOptionPtr->optionPtr = optionPtr;
+ savedOptionPtr->valuePtr = oldPtr;
+ oldInternalPtr = (char *) &savedOptionPtr->internalForm;
+ } else {
+ oldInternalPtr = (char *) &internal.internalForm;
+ }
+ nullOK = (optionPtr->specPtr->flags & TK_OPTION_NULL_OK);
+ switch (optionPtr->specPtr->type) {
+ case TK_OPTION_BOOLEAN: {
+ int new;
+
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &new)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = new;
+ }
+ break;
}
- if ((specPtr->argvName[1] != c)
- || (strncmp(specPtr->argvName, argvName, length) != 0)) {
- continue;
+ 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 (((specPtr->specFlags & needFlags) != needFlags)
- || (specPtr->specFlags & hateFlags)) {
- continue;
+ case TK_OPTION_DOUBLE: {
+ double new;
+
+ if (Tcl_GetDoubleFromObj(interp, valuePtr, &new)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((double *) oldInternalPtr) = *((double *) internalPtr);
+ *((double *) internalPtr) = new;
+ }
+ break;
+ }
+ 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 (specPtr->argvName[length] == 0) {
- matchPtr = specPtr;
- goto gotMatch;
+ case TK_OPTION_STRING_TABLE: {
+ int new;
+
+ if (Tcl_GetIndexFromObj(interp, valuePtr,
+ (char **) optionPtr->specPtr->clientData,
+ optionPtr->specPtr->optionName+1, 0, &new) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = new;
+ }
+ break;
}
- if (matchPtr != NULL) {
- Tcl_AppendResult(interp, "ambiguous option \"", argvName,
- "\"", (char *) NULL);
- return (Tk_ConfigSpec *) NULL;
+ 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;
}
- matchPtr = specPtr;
- }
+ case TK_OPTION_FONT: {
+ Tk_Font new;
- if (matchPtr == NULL) {
- Tcl_AppendResult(interp, "unknown option \"", argvName,
- "\"", (char *) NULL);
- return (Tk_ConfigSpec *) NULL;
+ if (nullOK && ObjectIsEmpty(valuePtr)) {
+ valuePtr = NULL;
+ new = NULL;
+ } else {
+ new = Tk_AllocFontFromObj(interp, tkwin, valuePtr);
+ if (new == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (internalPtr != NULL) {
+ *((Tk_Font *) oldInternalPtr) = *((Tk_Font *) internalPtr);
+ *((Tk_Font *) internalPtr) = new;
+ }
+ break;
+ }
+ case TK_OPTION_BITMAP: {
+ Pixmap new;
+
+ 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;
+ }
+ break;
+ }
+ case TK_OPTION_BORDER: {
+ Tk_3DBorder new;
+
+ 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;
+ }
+ break;
+ }
+ case TK_OPTION_RELIEF: {
+ int new;
+
+ if (Tk_GetReliefFromObj(interp, valuePtr, &new) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = new;
+ }
+ break;
+ }
+ case TK_OPTION_CURSOR: {
+ Tk_Cursor new;
+
+ 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;
+ }
+ Tk_DefineCursor(tkwin, new);
+ break;
+ }
+ case TK_OPTION_JUSTIFY: {
+ Tk_Justify new;
+
+ if (Tk_GetJustifyFromObj(interp, valuePtr, &new) != TCL_OK) {
+ 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 (Tk_GetAnchorFromObj(interp, valuePtr, &new) != 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 (Tk_GetPixelsFromObj(interp, tkwin, valuePtr,
+ &new) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (internalPtr != NULL) {
+ *((int *) oldInternalPtr) = *((int *) internalPtr);
+ *((int *) internalPtr) = new;
+ }
+ break;
+ }
+ case TK_OPTION_WINDOW: {
+ Tk_Window new;
+
+ 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;
+ }
+ break;
+ }
+ default: {
+ sprintf(interp->result, "bad config table: unknown type %d",
+ optionPtr->specPtr->type);
+ return TCL_ERROR;
+ }
}
/*
- * Found a matching entry. If it's a synonym, then find the
- * entry that it's a synonym for.
+ * 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.
*/
- 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;
- }
- if ((specPtr->dbName == matchPtr->dbName)
- && (specPtr->type != TK_CONFIG_SYNONYM)
- && ((specPtr->specFlags & needFlags) == needFlags)
- && !(specPtr->specFlags & hateFlags)) {
- break;
- }
+ if (savedOptionPtr == NULL) {
+ if (optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
+ }
+ if (oldPtr != NULL) {
+ Tcl_DecrRefCount(oldPtr);
+ }
+ }
+ if (slotPtrPtr != NULL) {
+ *slotPtrPtr = valuePtr;
+ if (valuePtr != NULL) {
+ Tcl_IncrRefCount(valuePtr);
}
}
- return specPtr;
+ return TCL_OK;
}
/*
- *--------------------------------------------------------------
+ *----------------------------------------------------------------------
*
- * DoConfig --
+ * ObjectIsEmpty --
*
- * This procedure applies a single configuration option
- * to a widget record.
+ * This procedure tests whether the string value of an object is
+ * empty.
*
* Results:
- * A standard Tcl return value.
+ * The return value is 1 if the string value of objPtr has length
+ * zero, and 0 otherwise.
*
* Side effects:
- * WidgRec is modified as indicated by specPtr and value.
- * The old value is recycled, if that is appropriate for
- * the value type.
+ * None.
*
- *--------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
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. */
- char *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. */
+ObjectIsEmpty(objPtr)
+ Tcl_Obj *objPtr; /* Object to test. May be NULL. */
{
- char *ptr;
- Tk_Uid uid;
- int nullValue;
+ int length;
- nullValue = 0;
- if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) {
- nullValue = 1;
+ if (objPtr == NULL) {
+ return 1;
+ }
+ if (objPtr->bytes != NULL) {
+ return (objPtr->length == 0);
}
+ Tcl_GetStringFromObj(objPtr, &length);
+ return (length == 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetOptionFromObj --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * Information about the matching entry is cached in the object
+ * containing the name, so that future lookups can proceed more
+ * quickly.
+ *
+ *----------------------------------------------------------------------
+ */
- 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;
+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. */
+{
+ Option *bestPtr, *optionPtr;
+ OptionTable *tablePtr2;
+ char *p1, *p2, *name;
+ int count;
- if (nullValue) {
- new = NULL;
- } else {
- new = (char *) ckalloc((unsigned) (strlen(value) + 1));
- strcpy(new, value);
- }
- old = *((char **) ptr);
- if (old != NULL) {
- ckfree(old);
+ /*
+ * First, check to see if the object already has the answer cached.
+ */
+
+ if (objPtr->typePtr == &optionType) {
+ if (objPtr->internalRep.twoPtrValue.ptr1 == (VOID *) tablePtr) {
+ return (Option *) objPtr->internalRep.twoPtrValue.ptr2;
+ }
+ }
+
+ /*
+ * The answer isn't cached. 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.
+ */
+
+ bestPtr = NULL;
+ name = Tcl_GetStringFromObj(objPtr, (int *) NULL);
+ for (tablePtr2 = tablePtr; tablePtr2 != NULL;
+ tablePtr2 = tablePtr2->nextPtr) {
+ for (optionPtr = tablePtr2->options, count = tablePtr2->numOptions;
+ count > 0; optionPtr++, count--) {
+ for (p1 = name, p2 = optionPtr->specPtr->optionName;
+ *p1 == *p2; p1++, p2++) {
+ if (*p1 == 0) {
+ /*
+ * This is an exact match. We're done.
+ */
+
+ bestPtr = optionPtr;
+ goto done;
}
- *((char **) ptr) = new;
- break;
}
- 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 (*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.
+ */
- if (nullValue) {
- newPtr = NULL;
+ if (bestPtr == NULL) {
+ bestPtr = optionPtr;
} else {
- uid = valueIsUid ? (Tk_Uid) value : Tk_GetUid(value);
- newPtr = Tk_GetColor(interp, tkwin, uid);
- if (newPtr == NULL) {
- return TCL_ERROR;
+ if (strcmp(bestPtr->specPtr->optionName,
+ optionPtr->specPtr->optionName) != 0) {
+ goto error;
}
}
- oldPtr = *((XColor **) ptr);
- if (oldPtr != NULL) {
- Tk_FreeColor(oldPtr);
- }
- *((XColor **) ptr) = newPtr;
- break;
}
- case TK_CONFIG_FONT: {
- Tk_Font new;
+ }
+ }
+ if (bestPtr == NULL) {
+ goto error;
+ }
- 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;
+ done:
+ if ((objPtr->typePtr != NULL)
+ && (objPtr->typePtr->freeIntRepProc != NULL)) {
+ objPtr->typePtr->freeIntRepProc(objPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tablePtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) bestPtr;
+ objPtr->typePtr = &optionType;
+ return bestPtr;
+
+ error:
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unknown option \"", name,
+ "\"", (char *) NULL);
+ }
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetOptionFromAny(interp, objPtr)
+ 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",
+ -1);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SetOptions --
+ *
+ * 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
+ * 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+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. */
+{
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ Tk_SavedOptions *lastSavePtr, *newSavePtr;
+ int mask;
+
+ if (savePtr != NULL) {
+ savePtr->recordPtr = recordPtr;
+ savePtr->tkwin = tkwin;
+ savePtr->numItems = 0;
+ savePtr->nextPtr = NULL;
+ }
+ lastSavePtr = savePtr;
+
+ /*
+ * Scan through all of the arguments, processing those
+ * that match entries in the option table.
+ */
+
+ mask = 0;
+ for ( ; objc > 0; objc -= 2, objv += 2) {
+ optionPtr = GetOptionFromObj(interp, objv[0], tablePtr);
+ if (optionPtr == NULL) {
+ goto error;
+ }
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ optionPtr = optionPtr->extra.synonymPtr;
+ }
+
+ if (objc < 2) {
+ if (interp != NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "value for \"", Tcl_GetStringFromObj(*objv, NULL),
+ "\" missing", (char *) NULL);
+ goto error;
}
- case TK_CONFIG_BITMAP: {
- Pixmap new, old;
+ }
+ if ((savePtr != NULL)
+ && (lastSavePtr->numItems >= TK_NUM_SAVED_OPTIONS)) {
+ /*
+ * We've run out of space for saving old option values. Allocate
+ * more space.
+ */
- 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;
- }
+ newSavePtr = (Tk_SavedOptions *) ckalloc(sizeof(
+ Tk_SavedOptions));
+ newSavePtr->recordPtr = recordPtr;
+ newSavePtr->tkwin = tkwin;
+ newSavePtr->numItems = 0;
+ newSavePtr->nextPtr = NULL;
+ lastSavePtr->nextPtr = newSavePtr;
+ lastSavePtr = newSavePtr;
+ }
+ if (DoObjConfig(interp, recordPtr, optionPtr, objv[1], tkwin,
+ (savePtr != NULL) ? &lastSavePtr->items[lastSavePtr->numItems]
+ : (Tk_SavedOption *) NULL) != TCL_OK) {
+ char msg[100];
+
+ sprintf(msg, "\n (processing \"%.40s\" option)",
+ Tcl_GetStringFromObj(*objv, NULL));
+ Tcl_AddErrorInfo(interp, msg);
+ goto error;
+ }
+ if (savePtr != NULL) {
+ lastSavePtr->numItems++;
+ }
+ mask |= optionPtr->specPtr->typeMask;
+ }
+ if (maskPtr != NULL) {
+ *maskPtr = mask;
+ }
+ return TCL_OK;
+
+ error:
+ if (savePtr != NULL) {
+ Tk_RestoreSavedOptions(savePtr);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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. */
+{
+ int i;
+ Option *optionPtr;
+ Tcl_Obj *newPtr; /* New object value of option, which we
+ * replace with old value and free. Taken
+ * from record. */
+ char *internalPtr; /* Points to internal value of option in
+ * 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.
+ */
+
+ if (savePtr->nextPtr != NULL) {
+ Tk_RestoreSavedOptions(savePtr->nextPtr);
+ ckfree((char *) savePtr->nextPtr);
+ savePtr->nextPtr = NULL;
+ }
+ for (i = savePtr->numItems - 1; i >= 0; i--) {
+ optionPtr = savePtr->items[i].optionPtr;
+ specPtr = optionPtr->specPtr;
+
+ /*
+ * First free the new value of the option, which is currently
+ * in the record.
+ */
+
+ if (specPtr->objOffset >= 0) {
+ newPtr = *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset));
+ } else {
+ newPtr = NULL;
+ }
+ if (specPtr->internalOffset >= 0) {
+ internalPtr = savePtr->recordPtr + specPtr->internalOffset;
+ } else {
+ internalPtr = NULL;
+ }
+ if (optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(optionPtr, newPtr, internalPtr, savePtr->tkwin);
+ }
+ if (newPtr != NULL) {
+ Tcl_DecrRefCount(newPtr);
+ }
+
+ /*
+ * Now restore the old value of the option.
+ */
+
+ if (specPtr->objOffset >= 0) {
+ *((Tcl_Obj **) (savePtr->recordPtr + specPtr->objOffset))
+ = savePtr->items[i].valuePtr;
+ }
+ if (specPtr->internalOffset >= 0) {
+ switch (specPtr->type) {
+ case TK_OPTION_BOOLEAN: {
+ *((int *) internalPtr)
+ = *((int *) &savePtr->items[i].internalForm);
+ break;
}
- old = *((Pixmap *) ptr);
- if (old != None) {
- Tk_FreeBitmap(Tk_Display(tkwin), old);
+ case TK_OPTION_INT: {
+ *((int *) internalPtr)
+ = *((int *) &savePtr->items[i].internalForm);
+ break;
}
- *((Pixmap *) ptr) = new;
- break;
- }
- 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;
- }
+ case TK_OPTION_DOUBLE: {
+ *((double *) internalPtr)
+ = *((double *) &savePtr->items[i].internalForm);
+ break;
}
- old = *((Tk_3DBorder *) ptr);
- if (old != NULL) {
- Tk_Free3DBorder(old);
+ case TK_OPTION_STRING: {
+ *((char **) internalPtr)
+ = *((char **) &savePtr->items[i].internalForm);
+ break;
}
- *((Tk_3DBorder *) ptr) = new;
- 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;
+ case TK_OPTION_STRING_TABLE: {
+ *((int *) internalPtr)
+ = *((int *) &savePtr->items[i].internalForm);
+ break;
}
- 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;
- }
+ case TK_OPTION_COLOR: {
+ *((XColor **) internalPtr)
+ = *((XColor **) &savePtr->items[i].internalForm);
+ break;
}
- old = *((Tk_Cursor *) ptr);
- if (old != None) {
- Tk_FreeCursor(Tk_Display(tkwin), old);
+ case TK_OPTION_FONT: {
+ *((Tk_Font *) internalPtr)
+ = *((Tk_Font *) &savePtr->items[i].internalForm);
+ break;
}
- *((Tk_Cursor *) ptr) = new;
- if (specPtr->type == TK_CONFIG_ACTIVE_CURSOR) {
- Tk_DefineCursor(tkwin, new);
+ case TK_OPTION_BITMAP: {
+ *((Pixmap *) internalPtr)
+ = *((Pixmap *) &savePtr->items[i].internalForm);
+ break;
}
- 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;
+ case TK_OPTION_BORDER: {
+ *((Tk_3DBorder *) internalPtr)
+ = *((Tk_3DBorder *) &savePtr->items[i].internalForm);
+ break;
}
- 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;
+ case TK_OPTION_RELIEF: {
+ *((int *) internalPtr)
+ = *((int *) &savePtr->items[i].internalForm);
+ break;
}
- 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;
+ case TK_OPTION_CURSOR: {
+ *((Tk_Cursor *) internalPtr)
+ = *((Tk_Cursor *) &savePtr->items[i].internalForm);
+ Tk_DefineCursor(savePtr->tkwin,
+ *((Tk_Cursor *) internalPtr));
+ break;
}
- 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;
+ case TK_OPTION_JUSTIFY: {
+ *((Tk_Justify *) internalPtr)
+ = *((Tk_Justify *) &savePtr->items[i].internalForm);
+ break;
}
- break;
- case TK_CONFIG_PIXELS:
- if (Tk_GetPixels(interp, tkwin, value, (int *) ptr)
- != TCL_OK) {
- return TCL_ERROR;
+ case TK_OPTION_ANCHOR: {
+ *((Tk_Anchor *) internalPtr)
+ = *((Tk_Anchor *) &savePtr->items[i].internalForm);
+ break;
}
- break;
- case TK_CONFIG_MM:
- if (Tk_GetScreenMM(interp, tkwin, value, (double *) ptr)
- != TCL_OK) {
- return TCL_ERROR;
+ 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;
+ }
+ default: {
+ panic("bad option type in Tk_RestoreSavedOptions");
}
- break;
- case TK_CONFIG_WINDOW: {
- Tk_Window tkwin2;
+ }
+ }
+ }
+ savePtr->numItems = 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_FreeSavedOptions --
+ *
+ * Free all of the saved configuration option values from a
+ * previous call to Tk_SetOptions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Storage and system resources are freed.
+ *
+ *--------------------------------------------------------------
+ */
- if (nullValue) {
- tkwin2 = NULL;
- } else {
- tkwin2 = Tk_NameToWindow(interp, value, tkwin);
- if (tkwin2 == NULL) {
- return TCL_ERROR;
- }
+void
+Tk_FreeSavedOptions(savePtr)
+ Tk_SavedOptions *savePtr; /* Contains options saved in a previous
+ * call to Tk_SetOptions. */
+{
+ int count;
+ Tk_SavedOption *savedOptionPtr;
+
+ if (savePtr->nextPtr != NULL) {
+ Tk_FreeSavedOptions(savePtr->nextPtr);
+ ckfree((char *) savePtr->nextPtr);
+ }
+ for (count = savePtr->numItems,
+ savedOptionPtr = &savePtr->items[savePtr->numItems-1];
+ count > 0; count--, savedOptionPtr--) {
+ if (savedOptionPtr->optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(savedOptionPtr->optionPtr, savedOptionPtr->valuePtr,
+ (char *) &savedOptionPtr->internalForm, savePtr->tkwin);
+ }
+ if (savedOptionPtr->valuePtr != NULL) {
+ Tcl_DecrRefCount(savedOptionPtr->valuePtr);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeConfigOptions --
+ *
+ * Free all resources associated with configuration options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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
+ * for freeing some options. */
+{
+ OptionTable *tablePtr;
+ Option *optionPtr;
+ int count;
+ Tcl_Obj **oldPtrPtr, *oldPtr;
+ char *oldInternalPtr;
+ CONST Tk_OptionSpec *specPtr;
+
+ for (tablePtr = (OptionTable *) optionTable; tablePtr != NULL;
+ tablePtr = tablePtr->nextPtr) {
+ for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
+ count > 0; optionPtr++, count--) {
+ specPtr = optionPtr->specPtr;
+ if (specPtr->type == TK_OPTION_SYNONYM) {
+ continue;
+ }
+ if (specPtr->objOffset >= 0) {
+ oldPtrPtr = (Tcl_Obj **) (recordPtr + specPtr->objOffset);
+ oldPtr = *oldPtrPtr;
+ *oldPtrPtr = NULL;
+ } else {
+ oldPtr = NULL;
+ }
+ if (specPtr->internalOffset >= 0) {
+ oldInternalPtr = recordPtr + specPtr->internalOffset;
+ } else {
+ oldInternalPtr = NULL;
+ }
+ if (optionPtr->flags & OPTION_NEEDS_FREEING) {
+ FreeResources(optionPtr, oldPtr, oldInternalPtr, tkwin);
+ }
+ if (oldPtr != NULL) {
+ Tcl_DecrRefCount(oldPtr);
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeResources --
+ *
+ * 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,
+ * 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
+ * as an object. */
+ char *internalPtr; /* A pointer to an internal representation for
+ * the option's value, such as an int or
+ * (XColor *). Only valid if
+ * optionPtr->specPtr->internalOffset >= 0. */
+ 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.
+ */
+
+ 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;
}
- *((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;
+ case TK_OPTION_COLOR:
+ if (internalFormExists) {
+ if (*((XColor **) internalPtr) != NULL) {
+ Tk_FreeColor(*((XColor **) internalPtr));
+ *((XColor **) internalPtr) = NULL;
}
- break;
- default: {
- sprintf(interp->result, "bad config table: unknown type %d",
- specPtr->type);
- return TCL_ERROR;
+ } else if (objPtr != NULL) {
+ Tk_FreeColorFromObj(tkwin, objPtr);
}
- }
- specPtr++;
- } while ((specPtr->argvName == NULL) && (specPtr->type != TK_CONFIG_END));
- return TCL_OK;
+ 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_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;
+ default:
+ break;
+ }
}
/*
*--------------------------------------------------------------
*
- * Tk_ConfigureInfo --
+ * Tk_GetOptionInfo --
*
- * Return information about the configuration options
- * for a window, and their current values.
+ * Returns a list object containing complete information about
+ * either a single option or all the configuration options in a
+ * table.
*
* Results:
- * Always returns TCL_OK. Interp->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).
+ * 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.
*
* Side effects:
* None.
@@ -581,47 +1625,40 @@ 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
+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. */
- 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. */
+ 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. */
{
- register Tk_ConfigSpec *specPtr;
- int needFlags, hateFlags;
- char *list;
- char *leader = "{";
-
- needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
- if (Tk_Depth(tkwin) <= 1) {
- hateFlags = TK_CONFIG_COLOR_ONLY;
- } else {
- hateFlags = TK_CONFIG_MONO_ONLY;
- }
+ Tcl_Obj *resultPtr;
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ int count;
/*
* If information is only wanted for a single configuration
* spec, then handle that one spec specially.
*/
- Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
- if (argvName != NULL) {
- specPtr = FindConfigSpec(interp, specs, argvName, needFlags,
- hateFlags);
- if (specPtr == NULL) {
- return TCL_ERROR;
+ if (namePtr != NULL) {
+ optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
+ if (optionPtr == NULL) {
+ return (Tcl_Obj *) NULL;
+ }
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ optionPtr = optionPtr->extra.synonymPtr;
}
- interp->result = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
- interp->freeProc = TCL_DYNAMIC;
- return TCL_OK;
+ return GetConfigList(recordPtr, optionPtr, tkwin);
}
/*
@@ -629,29 +1666,21 @@ Tk_ConfigureInfo(interp, tkwin, specs, widgRec, argvName, flags)
* their information.
*/
- for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
- if ((argvName != NULL) && (specPtr->argvName != argvName)) {
- continue;
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ for (; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
+ for (optionPtr = tablePtr->options, count = tablePtr->numOptions;
+ count > 0; optionPtr++, count--) {
+ Tcl_ListObjAppendElement(interp, resultPtr,
+ GetConfigList(recordPtr, optionPtr, tkwin));
}
- if (((specPtr->specFlags & needFlags) != needFlags)
- || (specPtr->specFlags & hateFlags)) {
- continue;
- }
- if (specPtr->argvName == NULL) {
- continue;
- }
- list = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
- Tcl_AppendResult(interp, leader, list, "}", (char *) NULL);
- ckfree(list);
- leader = " {";
}
- return TCL_OK;
+ return resultPtr;
}
/*
*--------------------------------------------------------------
*
- * FormatConfigInfo --
+ * GetConfigList --
*
* Create a valid Tcl list holding the configuration information
* for a single configuration option.
@@ -666,67 +1695,78 @@ 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. */
+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
+ * particular option. */
+ Tk_Window tkwin; /* Window corresponding to recordPtr. */
{
- char *argv[6], *result;
- char buffer[200];
- Tcl_FreeProc *freeProc = (Tcl_FreeProc *) NULL;
-
- argv[0] = specPtr->argvName;
- argv[1] = specPtr->dbName;
- argv[2] = specPtr->dbClass;
- argv[3] = specPtr->defValue;
- if (specPtr->type == TK_CONFIG_SYNONYM) {
- return Tcl_Merge(2, argv);
- }
- argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
- &freeProc);
- if (argv[1] == NULL) {
- argv[1] = "";
- }
- if (argv[2] == NULL) {
- argv[2] = "";
- }
- if (argv[3] == NULL) {
- argv[3] = "";
- }
- if (argv[4] == NULL) {
- argv[4] = "";
- }
- result = Tcl_Merge(5, argv);
- if (freeProc != NULL) {
- if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) {
- ckfree(argv[4]);
+ Tcl_Obj *listPtr, *elementPtr;
+
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ Tcl_ListObjAppendElement((Tcl_Interp *) 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);
+ } else {
+ if (optionPtr->dbNameUID == NULL) {
+ elementPtr = Tcl_NewObj();
+ } else {
+ elementPtr = Tcl_NewStringObj(optionPtr->dbNameUID, -1);
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
+
+ if (optionPtr->dbClassUID == NULL) {
+ elementPtr = Tcl_NewObj();
} else {
- (*freeProc)(argv[4]);
+ elementPtr = Tcl_NewStringObj(optionPtr->dbClassUID, -1);
}
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
+
+ if ((tkwin != NULL) && ((optionPtr->specPtr->type == TK_OPTION_COLOR)
+ || (optionPtr->specPtr->type == TK_OPTION_BORDER))
+ && (Tk_Depth(tkwin) <= 1)
+ && (optionPtr->extra.monoColorPtr != NULL)) {
+ elementPtr = optionPtr->extra.monoColorPtr;
+ } else if (optionPtr->defaultPtr != NULL) {
+ elementPtr = optionPtr->defaultPtr;
+ } else {
+ elementPtr = Tcl_NewObj();
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
+
+ if (optionPtr->specPtr->objOffset >= 0) {
+ elementPtr = *((Tcl_Obj **) (recordPtr
+ + optionPtr->specPtr->objOffset));
+ if (elementPtr == NULL) {
+ elementPtr = Tcl_NewObj();
+ }
+ } else {
+ elementPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, listPtr, elementPtr);
}
- return result;
+ return listPtr;
}
/*
*----------------------------------------------------------------------
*
- * FormatConfigValue --
+ * GetObjectForOption --
*
- * This procedure formats the current value of a configuration
- * option.
+ * 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.
*
* 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 a pointer to a Tcl object. The caller
+ * must call Tcl_IncrRefCount on this object to preserve it.
*
* Side effects:
* None.
@@ -734,146 +1774,130 @@ FormatConfigInfo(interp, tkwin, specPtr, widgRec)
*----------------------------------------------------------------------
*/
-static 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.
- * 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.
- * 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. */
+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. */
{
- char *ptr, *result;
-
- *freeProcPtr = NULL;
- ptr = widgRec + specPtr->offset;
- result = "";
- switch (specPtr->type) {
- case TK_CONFIG_BOOLEAN:
- if (*((int *) ptr) == 0) {
- result = "0";
- } else {
- result = "1";
- }
+ Tcl_Obj *objPtr;
+ char *internalPtr; /* Points to internal value of option in
+ * record. */
+
+ internalPtr = recordPtr + optionPtr->specPtr->internalOffset;
+ objPtr = NULL;
+ switch (optionPtr->specPtr->type) {
+ case TK_OPTION_BOOLEAN: {
+ objPtr = Tcl_NewIntObj(*((int *) internalPtr));
break;
- case TK_CONFIG_INT:
- sprintf(buffer, "%d", *((int *) ptr));
- result = buffer;
+ }
+ case TK_OPTION_INT: {
+ objPtr = Tcl_NewIntObj(*((int *) internalPtr));
break;
- case TK_CONFIG_DOUBLE:
- Tcl_PrintDouble(interp, *((double *) ptr), buffer);
- result = buffer;
+ }
+ case TK_OPTION_DOUBLE: {
+ objPtr = Tcl_NewDoubleObj(*((double *) internalPtr));
break;
- case TK_CONFIG_STRING:
- result = (*(char **) ptr);
- if (result == NULL) {
- result = "";
- }
+ }
+ case TK_OPTION_STRING: {
+ objPtr = Tcl_NewStringObj(*((char **) internalPtr), -1);
break;
- case TK_CONFIG_UID: {
- Tk_Uid uid = *((Tk_Uid *) ptr);
- if (uid != NULL) {
- result = uid;
- }
+ }
+ case TK_OPTION_STRING_TABLE: {
+ objPtr = Tcl_NewStringObj(
+ ((char **) optionPtr->specPtr->clientData)[
+ *((int *) internalPtr)], -1);
break;
}
- case TK_CONFIG_COLOR: {
- XColor *colorPtr = *((XColor **) ptr);
+ case TK_OPTION_COLOR: {
+ XColor *colorPtr = *((XColor **) internalPtr);
if (colorPtr != NULL) {
- result = Tk_NameOfColor(colorPtr);
+ objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);
}
break;
}
- case TK_CONFIG_FONT: {
- Tk_Font tkfont = *((Tk_Font *) ptr);
+ case TK_OPTION_FONT: {
+ Tk_Font tkfont = *((Tk_Font *) internalPtr);
if (tkfont != NULL) {
- result = Tk_NameOfFont(tkfont);
+ objPtr = Tcl_NewStringObj(Tk_NameOfFont(tkfont), -1);
}
break;
}
- case TK_CONFIG_BITMAP: {
- Pixmap pixmap = *((Pixmap *) ptr);
+ case TK_OPTION_BITMAP: {
+ Pixmap pixmap = *((Pixmap *) internalPtr);
if (pixmap != None) {
- result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);
+ objPtr = Tcl_NewStringObj(Tk_NameOfBitmap(Tk_Display(tkwin),
+ pixmap), -1);
}
break;
}
- case TK_CONFIG_BORDER: {
- Tk_3DBorder border = *((Tk_3DBorder *) ptr);
+ case TK_OPTION_BORDER: {
+ Tk_3DBorder border = *((Tk_3DBorder *) internalPtr);
if (border != NULL) {
- result = Tk_NameOf3DBorder(border);
+ objPtr = Tcl_NewStringObj(Tk_NameOf3DBorder(border), -1);
}
break;
}
- case TK_CONFIG_RELIEF:
- result = Tk_NameOfRelief(*((int *) ptr));
+ case TK_OPTION_RELIEF: {
+ objPtr = Tcl_NewStringObj(Tk_NameOfRelief(
+ *((int *) internalPtr)), -1);
break;
- case TK_CONFIG_CURSOR:
- case TK_CONFIG_ACTIVE_CURSOR: {
- Tk_Cursor cursor = *((Tk_Cursor *) ptr);
+ }
+ case TK_OPTION_CURSOR: {
+ Tk_Cursor cursor = *((Tk_Cursor *) internalPtr);
if (cursor != None) {
- result = Tk_NameOfCursor(Tk_Display(tkwin), cursor);
+ objPtr = Tcl_NewStringObj(
+ Tk_NameOfCursor(Tk_Display(tkwin), cursor), -1);
}
break;
}
- case TK_CONFIG_JUSTIFY:
- result = Tk_NameOfJustify(*((Tk_Justify *) ptr));
+ case TK_OPTION_JUSTIFY: {
+ objPtr = Tcl_NewStringObj(Tk_NameOfJustify(
+ *((Tk_Justify *) internalPtr)), -1);
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;
+ }
+ case TK_OPTION_ANCHOR: {
+ objPtr = Tcl_NewStringObj(Tk_NameOfAnchor(
+ *((Tk_Anchor *) internalPtr)), -1);
break;
- case TK_CONFIG_MM:
- Tcl_PrintDouble(interp, *((double *) ptr), buffer);
- result = buffer;
+ }
+ case TK_OPTION_PIXELS: {
+ objPtr = Tcl_NewIntObj(*((int *) internalPtr));
break;
- case TK_CONFIG_WINDOW: {
- Tk_Window tkwin;
-
- tkwin = *((Tk_Window *) ptr);
+ }
+ case TK_OPTION_WINDOW: {
+ Tk_Window tkwin = *((Tk_Window *) internalPtr);
if (tkwin != NULL) {
- result = Tk_PathName(tkwin);
+ objPtr = Tcl_NewStringObj(Tk_PathName(tkwin), -1);
}
break;
}
- case TK_CONFIG_CUSTOM:
- result = (*specPtr->customPtr->printProc)(
- specPtr->customPtr->clientData, tkwin, widgRec,
- specPtr->offset, freeProcPtr);
- break;
- default:
- result = "?? unknown type ??";
+ default: {
+ panic("bad option type in GetObjectForOption");
+ }
+ }
+ if (objPtr == NULL) {
+ objPtr = Tcl_NewObj();
}
- return result;
+ return objPtr;
}
/*
*----------------------------------------------------------------------
*
- * Tk_ConfigureValue --
+ * Tk_GetOptionValue --
*
* This procedure returns the current value of a configuration
- * option for a widget.
+ * option.
*
* Results:
- * The return value is a standard Tcl completion code (TCL_OK or
- * TCL_ERROR). Interp->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).
+ * 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.
@@ -881,110 +1905,113 @@ 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
+Tcl_Obj *
+Tk_GetOptionValue(interp, recordPtr, optionTable, namePtr, tkwin)
+ 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. */
- char *argvName; /* Gives the command-line name for the
+ Tk_OptionTable optionTable; /* Describes legal options. */
+ Tcl_Obj *namePtr; /* 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_Window tkwin; /* Window corresponding to recordPtr. */
{
- Tk_ConfigSpec *specPtr;
- int needFlags, hateFlags;
+ OptionTable *tablePtr = (OptionTable *) optionTable;
+ Option *optionPtr;
+ Tcl_Obj *resultPtr;
- needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
- if (Tk_Depth(tkwin) <= 1) {
- hateFlags = TK_CONFIG_COLOR_ONLY;
- } else {
- hateFlags = TK_CONFIG_MONO_ONLY;
+ optionPtr = GetOptionFromObj(interp, namePtr, tablePtr);
+ if (optionPtr == NULL) {
+ return NULL;
}
- specPtr = FindConfigSpec(interp, specs, argvName, needFlags, hateFlags);
- if (specPtr == NULL) {
- return TCL_ERROR;
+ if (optionPtr->specPtr->type == TK_OPTION_SYNONYM) {
+ optionPtr = optionPtr->extra.synonymPtr;
}
- interp->result = FormatConfigValue(interp, tkwin, specPtr, widgRec,
- interp->result, &interp->freeProc);
- return TCL_OK;
+ if (optionPtr->specPtr->objOffset >= 0) {
+ 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.
+ */
+
+ resultPtr = Tcl_NewObj();
+ }
+ } else {
+ resultPtr = GetObjectForOption(recordPtr, optionPtr, tkwin);
+ }
+ return resultPtr;
}
/*
*----------------------------------------------------------------------
*
- * Tk_FreeOptions --
+ * TkDebugConfig --
*
- * Free up all resources associated with configuration options.
+ * This is a debugging procedure that returns information about
+ * one of the configuration tables that currently exists for an
+ * interpreter.
*
* Results:
- * None.
+ * 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:
- * Any resource in widgRec that is controlled by a configuration
- * option (e.g. a Tk_3DBorder or XColor) is freed in the appropriate
- * fashion.
+ * None.
*
*----------------------------------------------------------------------
*/
- /* 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
- * resources. */
- int needFlags; /* Used to specify additional flags
- * that must be present in config specs
- * for them to be considered. */
+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. */
{
- register Tk_ConfigSpec *specPtr;
- char *ptr;
+ OptionTable *tablePtr = (OptionTable *) table;
+ Tcl_HashTable *hashTablePtr;
+ Tcl_HashEntry *hashEntryPtr;
+ Tcl_HashSearch search;
+ Tcl_Obj *objPtr;
- for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
- if ((specPtr->specFlags & needFlags) != needFlags) {
- continue;
- }
- 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;
- }
+ objPtr = Tcl_NewObj();
+ hashTablePtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, OPTION_HASH_KEY,
+ NULL);
+ if (hashTablePtr == NULL) {
+ return objPtr;
+ }
+
+ /*
+ * Scan all the tables for this interpreter to make sure that the
+ * one we want still is valid.
+ */
+
+ for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search);
+ hashEntryPtr != NULL;
+ hashEntryPtr = Tcl_NextHashEntry(&search)) {
+ if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) {
+ for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) {
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_NewIntObj(tablePtr->refCount));
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_NewIntObj(tablePtr->numOptions));
+ Tcl_ListObjAppendElement((Tcl_Interp *) NULL, objPtr,
+ Tcl_NewStringObj(
+ tablePtr->options[0].specPtr->optionName,
+ -1));
+ }
+ break;
}
}
+ return objPtr;
}
diff --git a/generic/tkConsole.c b/generic/tkConsole.c
index c213371..6c721e5 100644
--- a/generic/tkConsole.c
+++ b/generic/tkConsole.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkConsole.c 1.54 97/10/17 10:46:08
+ * SCCS: @(#) tkConsole.c 1.55 98/01/02 17:40:37
*/
#include "tk.h"
@@ -29,6 +29,8 @@ typedef struct ConsoleInfo {
static Tcl_Interp *gStdoutInterp = NULL;
+EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0));
+
/*
* Forward declarations for procedures defined later in this file:
*
@@ -100,11 +102,14 @@ TkConsoleCreate()
{
Tcl_Channel consoleChannel;
+ TclInitSubsystems(NULL);
+
consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console0",
(ClientData) TCL_STDIN, TCL_READABLE);
if (consoleChannel != NULL) {
Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
}
Tcl_SetStdChannel(consoleChannel, TCL_STDIN);
consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
@@ -112,6 +117,7 @@ TkConsoleCreate()
if (consoleChannel != NULL) {
Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
}
Tcl_SetStdChannel(consoleChannel, TCL_STDOUT);
consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
@@ -119,6 +125,7 @@ TkConsoleCreate()
if (consoleChannel != NULL) {
Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ Tcl_SetChannelOption(NULL, consoleChannel, "-encoding", "utf-8");
}
Tcl_SetStdChannel(consoleChannel, TCL_STDERR);
}
diff --git a/generic/tkCursor.c b/generic/tkCursor.c
index e185109..9a8f971 100644
--- a/generic/tkCursor.c
+++ b/generic/tkCursor.c
@@ -6,12 +6,12 @@
* also avoids round-trips to the X server.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkCursor.c 1.27 96/02/15 18:52:40
+ * SCCS: @(#) tkCursor.c 1.35 98/01/19 11:50:15
*/
#include "tkPort.h"
@@ -25,16 +25,11 @@
*/
/*
- * Hash table to map from a textual description of a cursor to the
- * TkCursor record for the cursor, and key structure used in that
- * hash table:
+ * Hash table to map from a string name for a cursor to the TkCursor
+ * record for the cursor:
*/
static Tcl_HashTable nameTable;
-typedef struct {
- Tk_Uid name; /* Textual name for desired cursor. */
- Display *display; /* Display for which cursor will be used. */
-} NameKey;
/*
* Hash table to map from a collection of in-core data about a
@@ -71,6 +66,125 @@ static int initialized = 0; /* 0 means static structures haven't been
*/
static void CursorInit _ANSI_ARGS_((void));
+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 * GetCursor _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, char *name));
+static TkCursor * GetCursorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
+static void InitCursorObj _ANSI_ARGS_((Tcl_Obj *objPtr));
+
+/*
+ * The following structure defines the implementation of the "cursor" Tcl
+ * object, used for drawing. The color object remembers the hash table
+ * entry associated with a color. The actual allocation and deallocation
+ * of the color should be done by the configuration package when the cursor
+ * option is set.
+ */
+
+static Tcl_ObjType cursorObjType = {
+ "cursor", /* name */
+ FreeCursorObjProc, /* freeIntRepProc */
+ DupCursorObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_AllocCursorFromObj --
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkCursor *cursorPtr;
+
+ if (objPtr->typePtr != &cursorObjType) {
+ InitCursorObj(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 (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.
+ */
+ FreeCursorObjProc(objPtr);
+ cursorPtr = NULL;
+ } else if (Tk_Display(tkwin) == cursorPtr->display) {
+ cursorPtr->resourceRefCount++;
+ return cursorPtr->cursor;
+ }
+ }
+
+ /*
+ * 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);
+ 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;
+ return cursorPtr->cursor;
+ }
+ }
+ }
+
+ /*
+ * Still no luck. Call GetCursor to allocate a new TkCursor object.
+ */
+
+ cursorPtr = GetCursor(interp, tkwin, Tcl_GetString(objPtr));
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) cursorPtr;
+ if (cursorPtr == NULL) {
+ return None;
+ } else {
+ cursorPtr->objRefCount++;
+ return cursorPtr->cursor;
+ }
+}
/*
*----------------------------------------------------------------------
@@ -83,7 +197,7 @@ static void CursorInit _ANSI_ARGS_((void));
* 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 interp->result.
+ * 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.
@@ -101,52 +215,104 @@ 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
+ char *string; /* Description of cursor. See manual entry
+ * for details on legal syntax. */
+{
+ TkCursor *cursorPtr = GetCursor(interp, tkwin, string);
+ if (cursorPtr == NULL) {
+ return None;
+ }
+ return cursorPtr->cursor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCursor --
+ *
+ * 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.
+ *
+ * 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
+ * aren't needed anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static TkCursor *
+GetCursor(interp, tkwin, string)
+ Tcl_Interp *interp; /* Interpreter to use for error reporting. */
+ Tk_Window tkwin; /* Window in which cursor will be used. */
+ char *string; /* Description of cursor. See manual entry
* for details on legal syntax. */
{
- NameKey nameKey;
IdKey idKey;
- Tcl_HashEntry *nameHashPtr, *idHashPtr;
+ Tcl_HashEntry *nameHashPtr;
register TkCursor *cursorPtr;
+ TkCursor *existingCursorPtr = NULL;
int new;
if (!initialized) {
CursorInit();
}
- nameKey.name = string;
- nameKey.display = Tk_Display(tkwin);
- nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
+ nameHashPtr = Tcl_CreateHashEntry(&nameTable, string, &new);
if (!new) {
- cursorPtr = (TkCursor *) Tcl_GetHashValue(nameHashPtr);
- cursorPtr->refCount++;
- return cursorPtr->cursor;
+ existingCursorPtr = (TkCursor *) Tcl_GetHashValue(nameHashPtr);
+ for (cursorPtr = existingCursorPtr; cursorPtr != NULL;
+ cursorPtr = cursorPtr->nextPtr) {
+ if (Tk_Display(tkwin) == cursorPtr->display) {
+ cursorPtr->resourceRefCount++;
+ return cursorPtr;
+ }
+ }
+ } else {
+ existingCursorPtr = NULL;
}
cursorPtr = TkGetCursorByName(interp, tkwin, string);
if (cursorPtr == NULL) {
- Tcl_DeleteHashEntry(nameHashPtr);
- return None;
+ if (new) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
+ return NULL;
}
/*
* Add information about this cursor to our database.
*/
- cursorPtr->refCount = 1;
+ cursorPtr->display = Tk_Display(tkwin);
+ cursorPtr->resourceRefCount = 1;
+ cursorPtr->objRefCount = 0;
cursorPtr->otherTable = &nameTable;
cursorPtr->hashPtr = nameHashPtr;
- idKey.display = nameKey.display;
+ idKey.display = Tk_Display(tkwin);
idKey.cursor = cursorPtr->cursor;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
+ cursorPtr->idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
+ &new);
if (!new) {
panic("cursor already registered in Tk_GetCursor");
}
+ cursorPtr->nextPtr = existingCursorPtr;
Tcl_SetHashValue(nameHashPtr, cursorPtr);
- Tcl_SetHashValue(idHashPtr, cursorPtr);
+ Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr);
- return cursorPtr->cursor;
+ return cursorPtr;
}
/*
@@ -160,7 +326,7 @@ Tk_GetCursor(interp, tkwin, string)
* 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 interp->result. The
+ * 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.
@@ -188,7 +354,7 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
{
DataKey dataKey;
IdKey idKey;
- Tcl_HashEntry *dataHashPtr, *idHashPtr;
+ Tcl_HashEntry *dataHashPtr;
register TkCursor *cursorPtr;
int new;
XColor fgColor, bgColor;
@@ -209,7 +375,7 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &dataKey, &new);
if (!new) {
cursorPtr = (TkCursor *) Tcl_GetHashValue(dataHashPtr);
- cursorPtr->refCount++;
+ cursorPtr->resourceRefCount++;
return cursorPtr->cursor;
}
@@ -236,17 +402,19 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
goto error;
}
- cursorPtr->refCount = 1;
+ cursorPtr->resourceRefCount = 1;
cursorPtr->otherTable = &dataTable;
cursorPtr->hashPtr = dataHashPtr;
+ cursorPtr->objRefCount = 0;
idKey.display = dataKey.display;
idKey.cursor = cursorPtr->cursor;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
+ cursorPtr->idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
+ &new);
if (!new) {
panic("cursor already registered in Tk_GetCursorFromData");
}
Tcl_SetHashValue(dataHashPtr, cursorPtr);
- Tcl_SetHashValue(idHashPtr, cursorPtr);
+ Tcl_SetHashValue(cursorPtr->idHashPtr, cursorPtr);
return cursorPtr->cursor;
error:
@@ -301,7 +469,57 @@ Tk_NameOfCursor(display, cursor)
if (cursorPtr->otherTable != &nameTable) {
goto printid;
}
- return ((NameKey *) cursorPtr->hashPtr->key.words)->name;
+ return cursorPtr->hashPtr->key.string;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeCursor --
+ *
+ * This procedure is invoked by both Tk_FreeCursor and
+ * Tk_FreeCursorFromObj; 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FreeCursor(cursorPtr)
+ TkCursor *cursorPtr; /* Cursor to be released. */
+{
+ TkCursor *prevPtr;
+
+ cursorPtr->resourceRefCount--;
+ if (cursorPtr->resourceRefCount > 0) {
+ return;
+ }
+
+ Tcl_DeleteHashEntry(cursorPtr->idHashPtr);
+ prevPtr = (TkCursor *) Tcl_GetHashValue(cursorPtr->hashPtr);
+ if (prevPtr == cursorPtr) {
+ if (cursorPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(cursorPtr->hashPtr);
+ } else {
+ Tcl_SetHashValue(cursorPtr->hashPtr, cursorPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != cursorPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = cursorPtr->nextPtr;
+ }
+ TkpFreeCursor(cursorPtr);
+ if (cursorPtr->objRefCount == 0) {
+ ckfree((char *) cursorPtr);
+ }
}
/*
@@ -329,7 +547,6 @@ Tk_FreeCursor(display, cursor)
{
IdKey idKey;
Tcl_HashEntry *idHashPtr;
- register TkCursor *cursorPtr;
if (!initialized) {
panic("Tk_FreeCursor called before Tk_GetCursor");
@@ -341,18 +558,245 @@ Tk_FreeCursor(display, cursor)
if (idHashPtr == NULL) {
panic("Tk_FreeCursor received unknown cursor argument");
}
- cursorPtr = (TkCursor *) Tcl_GetHashValue(idHashPtr);
- cursorPtr->refCount--;
- if (cursorPtr->refCount == 0) {
- Tcl_DeleteHashEntry(cursorPtr->hashPtr);
- Tcl_DeleteHashEntry(idHashPtr);
- TkFreeCursor(cursorPtr);
+ FreeCursor((TkCursor *) Tcl_GetHashValue(idHashPtr));
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ FreeCursor(GetCursorFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeCursorObjProc(objPtr)
+ Tcl_Obj *objPtr; /* The object we are releasing. */
+{
+ TkCursor *cursorPtr = (TkCursor *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (cursorPtr != NULL) {
+ cursorPtr->objRefCount--;
+ if ((cursorPtr->objRefCount == 0)
+ && (cursorPtr->resourceRefCount == 0)) {
+ ckfree((char *) cursorPtr);
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupCursorObjProc --
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupCursorObjProc(srcObjPtr, dupObjPtr)
+ 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;
+
+ if (cursorPtr != NULL) {
+ cursorPtr->objRefCount++;
}
}
/*
*----------------------------------------------------------------------
*
+ * 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
+ * Tk_GetCursor.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_Cursor
+Tk_GetCursorFromObj(tkwin, objPtr)
+ Tk_Window tkwin;
+ Tcl_Obj *objPtr; /* The object from which to get pixels. */
+{
+ TkCursor *cursorPtr = GetCursorFromObj(tkwin, objPtr);
+ return cursorPtr->cursor;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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
+ * cursor. */
+{
+ TkCursor *cursorPtr;
+ Tcl_HashEntry *hashPtr;
+
+ if (objPtr->typePtr != &cursorObjType) {
+ InitCursorObj(objPtr);
+ }
+
+ cursorPtr = (TkCursor *) objPtr->internalRep.twoPtrValue.ptr1;
+ if (cursorPtr != NULL) {
+ if (Tk_Display(tkwin) == cursorPtr->display) {
+ return cursorPtr;
+ }
+ hashPtr = cursorPtr->hashPtr;
+ } else {
+ hashPtr = Tcl_FindHashEntry(&nameTable, 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 TkCursor structures. See if any of them will work.
+ */
+
+ for (cursorPtr = (TkCursor *) Tcl_GetHashValue(hashPtr);
+ cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) {
+ if (Tk_Display(tkwin) != cursorPtr->display) {
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) cursorPtr;
+ cursorPtr->objRefCount++;
+ return cursorPtr;
+ }
+ }
+
+ error:
+ panic("GetCursorFromObj called with non-existent cursor!");
+ /*
+ * The following code isn't reached; it's just there to please compilers.
+ */
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * InitCursorObj --
+ *
+ * Bookeeping procedure 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitCursorObj(objPtr)
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+ objPtr->typePtr = &cursorObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* CursorInit --
*
* Initialize the structures used for cursor management.
@@ -370,7 +814,7 @@ static void
CursorInit()
{
initialized = 1;
- Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
+ Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
/*
@@ -382,3 +826,51 @@ CursorInit()
Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Tk_Cursor))
/sizeof(int));
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugCursor --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkCursor *cursorPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&nameTable, name);
+ if (hashPtr != NULL) {
+ cursorPtr = (TkCursor *) Tcl_GetHashValue(hashPtr);
+ if (cursorPtr == NULL) {
+ 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_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 35cc66c..e64f661 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -6,12 +6,12 @@
* the string to be edited.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkEntry.c 1.112 97/11/06 16:56:16
+ * SCCS: @(#) tkEntry.c 1.119 98/01/21 22:20:55
*/
#include "tkInt.h"
@@ -39,17 +39,17 @@ typedef struct {
char *string; /* Pointer to storage for string;
* NULL-terminated; malloc-ed. */
- int insertPos; /* Index of character before which next
- * typed character will be inserted. */
+ int insertPos; /* Character index before which next typed
+ * character will be inserted. */
/*
* Information about what's selected, if any.
*/
- int selectFirst; /* Index of first selected character (-1 means
- * nothing selected. */
- int selectLast; /* Index of last 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"
* operation will use this as one end of the
* selection). */
@@ -60,8 +60,8 @@ typedef struct {
int scanMarkX; /* X-position at which scan started (e.g.
* button was pressed here). */
- int scanMarkIndex; /* Index of character that was at left of
- * window when scan started. */
+ int scanMarkIndex; /* Character index of character that was at
+ * left of window when scan started. */
/*
* Configuration settings that are updated by Tk_ConfigureWidget.
@@ -118,20 +118,27 @@ typedef struct {
* configuration settings above.
*/
- int numChars; /* Number of non-NULL characters in
- * string (may be 0). */
- char *displayString; /* If non-NULL, points to string with same
+ 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. */
+ 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. Malloc'ed. */
+ * are all equal to showChar. */
+ 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). */
Tk_TextLayout textLayout; /* Cached text layout information. */
int layoutX, layoutY; /* Origin for layout. */
- int leftIndex; /* Index of left-most character visible in
- * window. */
int leftX; /* X position at which character at leftIndex
* is drawn (varies depending on justify). */
+ int leftIndex; /* Character index of left-most character
+ * visible in window. */
Tcl_TimerToken insertBlinkHandler;
/* Timer handler used to blink cursor on and
* off. */
@@ -357,12 +364,12 @@ Tk_EntryCmd(clientData, interp, argc, argv)
char **argv; /* Argument strings. */
{
Tk_Window tkwin = (Tk_Window) clientData;
- register Entry *entryPtr;
+ Entry *entryPtr;
Tk_Window new;
if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " pathName ?options?\"", (char *) NULL);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " pathName ?options?\"", (char *) NULL);
return TCL_ERROR;
}
@@ -419,14 +426,16 @@ Tk_EntryCmd(clientData, interp, argc, argv)
entryPtr->prefWidth = 0;
entryPtr->scrollCmd = NULL;
+ entryPtr->numBytes = 0;
entryPtr->numChars = 0;
- entryPtr->displayString = NULL;
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->numDisplayBytes = 0;
entryPtr->inset = XPAD;
entryPtr->textLayout = NULL;
entryPtr->layoutX = 0;
entryPtr->layoutY = 0;
- entryPtr->leftIndex = 0;
entryPtr->leftX = 0;
+ entryPtr->leftIndex = 0;
entryPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
entryPtr->textGC = None;
entryPtr->selTextGC = None;
@@ -445,7 +454,7 @@ Tk_EntryCmd(clientData, interp, argc, argv)
goto error;
}
- interp->result = Tk_PathName(entryPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(entryPtr->tkwin), TCL_STATIC);
return TCL_OK;
error:
@@ -473,12 +482,12 @@ Tk_EntryCmd(clientData, interp, argc, argv)
static int
EntryWidgetCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Information about entry widget. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ ClientData clientData; /* Information about entry widget. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int argc; /* Number of arguments. */
+ char **argv; /* Argument strings. */
{
- register Entry *entryPtr = (Entry *) clientData;
+ Entry *entryPtr = (Entry *) clientData;
int result = TCL_OK;
size_t length;
int c;
@@ -492,8 +501,9 @@ EntryWidgetCmd(clientData, interp, argc, argv)
c = argv[1][0];
length = strlen(argv[1]);
if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) {
- int index;
- int x, y, width, height;
+ int index, byteIndex, x, y, width, height;
+ char *string;
+ char buf[TCL_INTEGER_SPACE * 4];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -507,9 +517,12 @@ EntryWidgetCmd(clientData, interp, argc, argv)
if ((index == entryPtr->numChars) && (index > 0)) {
index--;
}
- Tk_CharBbox(entryPtr->textLayout, index, &x, &y, &width, &height);
- sprintf(interp->result, "%d %d %d %d",
- x + entryPtr->layoutX, y + entryPtr->layoutY, width, height);
+ string = entryPtr->displayString;
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ Tk_CharBbox(entryPtr->textLayout, byteIndex, &x, &y, &width, &height);
+ sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX,
+ y + entryPtr->layoutY, width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
&& (length >= 2)) {
if (argc != 3) {
@@ -545,14 +558,14 @@ EntryWidgetCmd(clientData, interp, argc, argv)
goto error;
}
if (argc == 3) {
- last = first+1;
+ last = first + 1;
} else {
if (GetEntryIndex(interp, entryPtr, argv[3], &last) != TCL_OK) {
goto error;
}
}
if ((last >= first) && (entryPtr->state == tkNormalUid)) {
- DeleteChars(entryPtr, first, last-first);
+ DeleteChars(entryPtr, first, last - first);
}
} else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
if (argc != 2) {
@@ -560,7 +573,7 @@ EntryWidgetCmd(clientData, interp, argc, argv)
argv[0], " get\"", (char *) NULL);
goto error;
}
- interp->result = entryPtr->string;
+ Tcl_SetResult(interp, entryPtr->string, TCL_STATIC);
} else if ((c == 'i') && (strncmp(argv[1], "icursor", length) == 0)
&& (length >= 2)) {
if (argc != 3) {
@@ -577,6 +590,7 @@ EntryWidgetCmd(clientData, interp, argc, argv)
} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
&& (length >= 3)) {
int index;
+ char buf[TCL_INTEGER_SPACE];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -586,7 +600,8 @@ EntryWidgetCmd(clientData, interp, argc, argv)
if (GetEntryIndex(interp, entryPtr, argv[2], &index) != TCL_OK) {
goto error;
}
- sprintf(interp->result, "%d", index);
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
&& (length >= 3)) {
int index;
@@ -644,8 +659,9 @@ EntryWidgetCmd(clientData, interp, argc, argv)
argv[0], " selection clear\"", (char *) NULL);
goto error;
}
- if (entryPtr->selectFirst != -1) {
- entryPtr->selectFirst = entryPtr->selectLast = -1;
+ if (entryPtr->selectFirst >= 0) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
EventuallyRedraw(entryPtr);
}
goto done;
@@ -655,10 +671,10 @@ EntryWidgetCmd(clientData, interp, argc, argv)
argv[0], " selection present\"", (char *) NULL);
goto error;
}
- if (entryPtr->selectFirst == -1) {
- interp->result = "0";
+ if (entryPtr->selectFirst < 0) {
+ Tcl_SetResult(interp, "0", TCL_STATIC);
} else {
- interp->result = "1";
+ Tcl_SetResult(interp, "1", TCL_STATIC);
}
goto done;
}
@@ -676,7 +692,7 @@ EntryWidgetCmd(clientData, interp, argc, argv)
}
if (entryPtr->selectFirst >= 0) {
int half1, half2;
-
+
half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;
half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;
if (index < half1) {
@@ -710,7 +726,8 @@ EntryWidgetCmd(clientData, interp, argc, argv)
goto error;
}
if (index >= index2) {
- entryPtr->selectFirst = entryPtr->selectLast = -1;
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
} else {
entryPtr->selectFirst = index;
entryPtr->selectLast = index2;
@@ -737,41 +754,52 @@ EntryWidgetCmd(clientData, interp, argc, argv)
goto error;
}
} else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) {
- int index, type, count, charsPerPage;
- double fraction, first, last;
+ int index;
if (argc == 2) {
+ double first, last;
+ char buf[TCL_DOUBLE_SPACE * 2];
+
EntryVisibleRange(entryPtr, &first, &last);
- sprintf(interp->result, "%g %g", first, last);
+ sprintf(buf, "%g %g", first, last);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
goto done;
} else if (argc == 3) {
if (GetEntryIndex(interp, entryPtr, argv[2], &index) != TCL_OK) {
goto error;
}
} else {
- type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
+ double fraction;
+ int count;
+
index = entryPtr->leftIndex;
- switch (type) {
- case TK_SCROLL_ERROR:
+ switch (Tk_GetScrollInfo(interp, argc, argv, &fraction, &count)) {
+ case TK_SCROLL_ERROR: {
goto error;
- case TK_SCROLL_MOVETO:
+ }
+ case TK_SCROLL_MOVETO: {
index = (int) ((fraction * entryPtr->numChars) + 0.5);
break;
- case TK_SCROLL_PAGES:
+ }
+ case TK_SCROLL_PAGES: {
+ int charsPerPage;
+
charsPerPage = ((Tk_Width(entryPtr->tkwin)
- - 2*entryPtr->inset) / entryPtr->avgWidth) - 2;
+ - 2 * entryPtr->inset) / entryPtr->avgWidth) - 2;
if (charsPerPage < 1) {
charsPerPage = 1;
}
- index += charsPerPage*count;
+ index += count * charsPerPage;
break;
- case TK_SCROLL_UNITS:
+ }
+ case TK_SCROLL_UNITS: {
index += count;
break;
+ }
}
}
if (index >= entryPtr->numChars) {
- index = entryPtr->numChars-1;
+ index = entryPtr->numChars - 1;
}
if (index < 0) {
index = 0;
@@ -818,7 +846,7 @@ static void
DestroyEntry(memPtr)
char *memPtr; /* Info about entry widget. */
{
- register Entry *entryPtr = (Entry *) memPtr;
+ Entry *entryPtr = (Entry *) memPtr;
/*
* Free up all the stuff that requires special handling, then
@@ -839,7 +867,7 @@ DestroyEntry(memPtr)
Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
}
Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);
- if (entryPtr->displayString != NULL) {
+ if (entryPtr->displayString != entryPtr->string) {
ckfree(entryPtr->displayString);
}
Tk_FreeTextLayout(entryPtr->textLayout);
@@ -858,7 +886,7 @@ DestroyEntry(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
@@ -871,8 +899,8 @@ DestroyEntry(memPtr)
static int
ConfigureEntry(interp, entryPtr, argc, argv, flags)
Tcl_Interp *interp; /* Used for error reporting. */
- register Entry *entryPtr; /* Information about widget; may or may
- * not already have values for some fields. */
+ Entry *entryPtr; /* Information about widget; may or may not
+ * already have values for some fields. */
int argc; /* Number of valid entries in argv. */
char **argv; /* Arguments. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
@@ -1057,13 +1085,14 @@ static void
DisplayEntry(clientData)
ClientData clientData; /* Information about window. */
{
- register Entry *entryPtr = (Entry *) clientData;
- register Tk_Window tkwin = entryPtr->tkwin;
- int baseY, selStartX, selEndX, cursorX, x, w;
+ Entry *entryPtr = (Entry *) clientData;
+ Tk_Window tkwin = entryPtr->tkwin;
+ int baseY, selStartX, selEndX, cursorX;
int xBound;
Tk_FontMetrics fm;
Pixmap pixmap;
- int showSelection;
+ int showSelection, selFirstByte, selLastByte, leftByte;
+ char *string;
entryPtr->flags &= ~REDRAW_PENDING;
if ((entryPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
@@ -1118,18 +1147,25 @@ DisplayEntry(clientData)
Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->normalBorder,
0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
- if (showSelection && (entryPtr->selectLast > entryPtr->leftIndex)) {
+
+ string = entryPtr->displayString;
+ if (showSelection
+ && (entryPtr->selectLast > entryPtr->leftIndex)) {
if (entryPtr->selectFirst <= entryPtr->leftIndex) {
selStartX = entryPtr->leftX;
} else {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->selectFirst,
- &x, NULL, NULL, NULL);
- selStartX = x + entryPtr->layoutX;
+ selFirstByte = Tcl_UtfAtIndex(string, entryPtr->selectFirst)
+ - string;
+ Tk_CharBbox(entryPtr->textLayout, selFirstByte, &selStartX, NULL,
+ NULL, NULL);
+ selStartX += entryPtr->layoutX;
}
if ((selStartX - entryPtr->selBorderWidth) < xBound) {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->selectLast - 1,
- &x, NULL, &w, NULL);
- selEndX = x + w + entryPtr->layoutX;
+ selLastByte = Tcl_UtfAtIndex(string, entryPtr->selectLast)
+ - string;
+ Tk_CharBbox(entryPtr->textLayout, selLastByte, &selEndX, NULL,
+ NULL, NULL);
+ selEndX += entryPtr->layoutX;
Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->selBorder,
selStartX - entryPtr->selBorderWidth,
baseY - fm.ascent - entryPtr->selBorderWidth,
@@ -1151,30 +1187,24 @@ DisplayEntry(clientData)
if ((entryPtr->insertPos >= entryPtr->leftIndex)
&& (entryPtr->state == tkNormalUid)
&& (entryPtr->flags & GOT_FOCUS)) {
- if (entryPtr->insertPos == 0) {
- cursorX = 0;
- } else if (entryPtr->insertPos >= entryPtr->numChars) {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->numChars - 1,
- &x, NULL, &w, NULL);
- cursorX = x + w;
- } else {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos,
- &x, NULL, NULL, NULL);
- cursorX = x;
- }
+ int insertByte;
+
+ insertByte = Tcl_UtfAtIndex(string, entryPtr->insertPos)
+ - string;
+ Tk_CharBbox(entryPtr->textLayout, insertByte, &cursorX, NULL,
+ NULL, NULL);
cursorX += entryPtr->layoutX;
cursorX -= (entryPtr->insertWidth)/2;
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);
+ 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, entryPtr->normalBorder,
- cursorX, baseY - fm.ascent,
- entryPtr->insertWidth, fm.ascent + fm.descent,
- 0, TK_RELIEF_FLAT);
+ cursorX, baseY - fm.ascent, entryPtr->insertWidth,
+ fm.ascent + fm.descent, 0, TK_RELIEF_FLAT);
}
}
}
@@ -1184,22 +1214,25 @@ DisplayEntry(clientData)
* selected portion on top of it.
*/
+ leftByte = Tcl_UtfAtIndex(string, entryPtr->leftIndex) - string;
Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
- entryPtr->leftIndex, entryPtr->numChars);
-
- if (showSelection && (entryPtr->selTextGC != entryPtr->textGC) &&
- (entryPtr->selectFirst < entryPtr->selectLast)) {
- int first;
+ leftByte, entryPtr->numDisplayBytes);
- if (entryPtr->selectFirst - entryPtr->leftIndex < 0) {
- first = entryPtr->leftIndex;
+ if (showSelection
+ && (entryPtr->selTextGC != entryPtr->textGC)
+ && (entryPtr->selectFirst < entryPtr->selectLast)) {
+ if (entryPtr->selectFirst < entryPtr->leftIndex) {
+ selFirstByte = leftByte;
} else {
- first = entryPtr->selectFirst;
+ selFirstByte = Tcl_UtfAtIndex(string, entryPtr->selectFirst)
+ - string;
}
+ selLastByte = Tcl_UtfAtIndex(string, entryPtr->selectLast)
+ - string;
Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,
entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
- first, entryPtr->selectLast);
+ selFirstByte, selLastByte);
}
/*
@@ -1210,8 +1243,8 @@ DisplayEntry(clientData)
if (entryPtr->relief != TK_RELIEF_FLAT) {
Tk_Draw3DRectangle(tkwin, pixmap, entryPtr->normalBorder,
entryPtr->highlightWidth, entryPtr->highlightWidth,
- Tk_Width(tkwin) - 2*entryPtr->highlightWidth,
- Tk_Height(tkwin) - 2*entryPtr->highlightWidth,
+ Tk_Width(tkwin) - 2 * entryPtr->highlightWidth,
+ Tk_Height(tkwin) - 2 * entryPtr->highlightWidth,
entryPtr->borderWidth, entryPtr->relief);
}
if (entryPtr->highlightWidth != 0) {
@@ -1259,38 +1292,45 @@ DisplayEntry(clientData)
static void
EntryComputeGeometry(entryPtr)
- Entry *entryPtr; /* Widget record for entry. */
+ Entry *entryPtr; /* Widget record for entry. */
{
int totalLength, overflow, maxOffScreen, rightX;
- int height, width, i;
+ int height, width, i, leftByte;
Tk_FontMetrics fm;
- char *p, *displayString;
+ char *p;
+
+ if (entryPtr->displayString != entryPtr->string) {
+ ckfree(entryPtr->displayString);
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
/*
* If we're displaying a special character instead of the value of
* the entry, recompute the displayString.
*/
- if (entryPtr->displayString != NULL) {
- ckfree(entryPtr->displayString);
- entryPtr->displayString = NULL;
- }
if (entryPtr->showChar != NULL) {
- entryPtr->displayString = (char *) ckalloc((unsigned)
- (entryPtr->numChars + 1));
- for (p = entryPtr->displayString, i = entryPtr->numChars; i > 0;
- i--, p++) {
- *p = entryPtr->showChar[0];
- }
- *p = 0;
- displayString = entryPtr->displayString;
- } else {
- displayString = entryPtr->string;
+ Tcl_UniChar ch;
+ char buf[TCL_UTF_MAX];
+ int size;
+
+ Tcl_UtfToUniChar(entryPtr->showChar, &ch);
+ size = Tcl_UniCharToUtf(ch, buf);
+ entryPtr->numDisplayBytes = entryPtr->numChars * size;
+ entryPtr->displayString =
+ (char *) ckalloc((unsigned) (entryPtr->numDisplayBytes + 1));
+
+ p = entryPtr->displayString;
+ for (i = entryPtr->numChars; --i >= 0; ) {
+ p += Tcl_UniCharToUtf(ch, p);
+ }
+ *p = '\0';
}
Tk_FreeTextLayout(entryPtr->textLayout);
entryPtr->textLayout = Tk_ComputeTextLayout(entryPtr->tkfont,
- displayString, entryPtr->numChars, 0, entryPtr->justify,
- TK_IGNORE_NEWLINES, &totalLength, &height);
+ entryPtr->displayString, entryPtr->numDisplayBytes, 0,
+ entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);
entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2;
@@ -1325,13 +1365,14 @@ EntryComputeGeometry(entryPtr)
Tk_CharBbox(entryPtr->textLayout, maxOffScreen,
&rightX, NULL, NULL, NULL);
if (rightX < overflow) {
- maxOffScreen += 1;
+ maxOffScreen++;
}
if (entryPtr->leftIndex > maxOffScreen) {
entryPtr->leftIndex = maxOffScreen;
}
- Tk_CharBbox(entryPtr->textLayout, entryPtr->leftIndex,
- &rightX, NULL, NULL, NULL);
+ leftByte = Tcl_UtfAtIndex(entryPtr->displayString, entryPtr->leftIndex)
+ - entryPtr->displayString;
+ Tk_CharBbox(entryPtr->textLayout, leftByte, &rightX, NULL, NULL, NULL);
entryPtr->leftX = entryPtr->inset;
entryPtr->layoutX = entryPtr->leftX - rightX;
}
@@ -1368,28 +1409,51 @@ EntryComputeGeometry(entryPtr)
*/
static void
-InsertChars(entryPtr, index, string)
- register Entry *entryPtr; /* Entry that is to get the new
- * elements. */
+InsertChars(entryPtr, index, value)
+ Entry *entryPtr; /* Entry that is to get the new elements. */
int index; /* Add the new elements before this
- * element. */
- char *string; /* New characters to add (NULL-terminated
+ * character index. */
+ char *value; /* New characters to add (NULL-terminated
* string). */
{
- int length;
- char *new;
+ int byteIndex, byteCount, oldChars, charsAdded, newByteCount;
+ char *new, *string;
- length = strlen(string);
- if (length == 0) {
+ string = entryPtr->string;
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ byteCount = strlen(value);
+ if (byteCount == 0) {
return;
}
- new = (char *) ckalloc((unsigned) (entryPtr->numChars + length + 1));
- strncpy(new, entryPtr->string, (size_t) index);
- strcpy(new+index, string);
- strcpy(new+index+length, entryPtr->string+index);
- ckfree(entryPtr->string);
+
+ 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);
+
+ ckfree(string);
entryPtr->string = new;
- entryPtr->numChars += length;
+
+ /*
+ * 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 were are in the string now minus the number that
+ * used to be there.
+ */
+
+ oldChars = entryPtr->numChars;
+ entryPtr->numChars = Tcl_NumUtfChars(new, -1);
+ charsAdded = entryPtr->numChars - oldChars;
+ entryPtr->numBytes += byteCount;
+
+ if (entryPtr->displayString == string) {
+ entryPtr->displayString = new;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
/*
* Inserting characters invalidates all indexes into the string.
@@ -1400,19 +1464,20 @@ InsertChars(entryPtr, index, string)
*/
if (entryPtr->selectFirst >= index) {
- entryPtr->selectFirst += length;
+ entryPtr->selectFirst += charsAdded;
}
if (entryPtr->selectLast > index) {
- entryPtr->selectLast += length;
+ entryPtr->selectLast += charsAdded;
}
- if ((entryPtr->selectAnchor > index) || (entryPtr->selectFirst >= index)) {
- entryPtr->selectAnchor += length;
+ if ((entryPtr->selectAnchor > index)
+ || (entryPtr->selectFirst >= index)) {
+ entryPtr->selectAnchor += charsAdded;
}
if (entryPtr->leftIndex > index) {
- entryPtr->leftIndex += length;
+ entryPtr->leftIndex += charsAdded;
}
if (entryPtr->insertPos >= index) {
- entryPtr->insertPos += length;
+ entryPtr->insertPos += charsAdded;
}
EntryValueChanged(entryPtr);
}
@@ -1436,11 +1501,12 @@ InsertChars(entryPtr, index, string)
static void
DeleteChars(entryPtr, index, count)
- register Entry *entryPtr; /* Entry widget to modify. */
+ Entry *entryPtr; /* Entry widget to modify. */
int index; /* Index of first character to delete. */
int count; /* How many characters to delete. */
{
- char *new;
+ int byteIndex, byteCount, newByteCount;
+ char *new, *string;
if ((index + count) > entryPtr->numChars) {
count = entryPtr->numChars - index;
@@ -1449,12 +1515,24 @@ DeleteChars(entryPtr, index, count)
return;
}
- new = (char *) ckalloc((unsigned) (entryPtr->numChars + 1 - count));
- strncpy(new, entryPtr->string, (size_t) index);
- strcpy(new+index, entryPtr->string+index+count);
+ string = entryPtr->string;
+ byteIndex = Tcl_UtfAtIndex(string, index) - string;
+ 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);
+
ckfree(entryPtr->string);
entryPtr->string = new;
entryPtr->numChars -= count;
+ entryPtr->numBytes -= byteCount;
+
+ if (entryPtr->displayString == string) {
+ entryPtr->displayString = new;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
/*
* Deleting characters results in the remaining characters being
@@ -1463,21 +1541,22 @@ DeleteChars(entryPtr, index, count)
*/
if (entryPtr->selectFirst >= index) {
- if (entryPtr->selectFirst >= (index+count)) {
+ if (entryPtr->selectFirst >= (index + count)) {
entryPtr->selectFirst -= count;
} else {
entryPtr->selectFirst = index;
}
}
if (entryPtr->selectLast >= index) {
- if (entryPtr->selectLast >= (index+count)) {
+ if (entryPtr->selectLast >= (index + count)) {
entryPtr->selectLast -= count;
} else {
entryPtr->selectLast = index;
}
}
if (entryPtr->selectLast <= entryPtr->selectFirst) {
- entryPtr->selectFirst = entryPtr->selectLast = -1;
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
}
if (entryPtr->selectAnchor >= index) {
if (entryPtr->selectAnchor >= (index+count)) {
@@ -1487,14 +1566,14 @@ DeleteChars(entryPtr, index, count)
}
}
if (entryPtr->leftIndex > index) {
- if (entryPtr->leftIndex >= (index+count)) {
+ if (entryPtr->leftIndex >= (index + count)) {
entryPtr->leftIndex -= count;
} else {
entryPtr->leftIndex = index;
}
}
if (entryPtr->insertPos >= index) {
- if (entryPtr->insertPos >= (index+count)) {
+ if (entryPtr->insertPos >= (index + count)) {
entryPtr->insertPos -= count;
} else {
entryPtr->insertPos = index;
@@ -1580,24 +1659,37 @@ EntryValueChanged(entryPtr)
static void
EntrySetValue(entryPtr, value)
- register Entry *entryPtr; /* Entry whose value is to be
- * changed. */
- char *value; /* New text to display in entry. */
+ Entry *entryPtr; /* Entry whose value is to be changed. */
+ char *value; /* New text to display in entry. */
{
+ char *oldSource;
+
+ oldSource = entryPtr->string;
+
ckfree(entryPtr->string);
- entryPtr->numChars = strlen(value);
- entryPtr->string = (char *) ckalloc((unsigned) (entryPtr->numChars + 1));
+ entryPtr->numBytes = strlen(value);
+ entryPtr->numChars = Tcl_NumUtfChars(value, entryPtr->numBytes);
+ entryPtr->string =
+ (char *) ckalloc((unsigned) (entryPtr->numBytes + 1));
strcpy(entryPtr->string, value);
- if (entryPtr->selectFirst != -1) {
+
+ if (entryPtr->displayString == oldSource) {
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->numDisplayBytes = entryPtr->numBytes;
+ }
+
+ if (entryPtr->selectFirst >= 0) {
if (entryPtr->selectFirst >= entryPtr->numChars) {
- entryPtr->selectFirst = entryPtr->selectLast = -1;
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
} else if (entryPtr->selectLast > entryPtr->numChars) {
entryPtr->selectLast = entryPtr->numChars;
}
}
if (entryPtr->leftIndex >= entryPtr->numChars) {
- entryPtr->leftIndex = entryPtr->numChars-1;
- if (entryPtr->leftIndex < 0) {
+ if (entryPtr->numChars > 0) {
+ entryPtr->leftIndex = entryPtr->numChars - 1;
+ } else {
entryPtr->leftIndex = 0;
}
}
@@ -1702,7 +1794,7 @@ EntryCmdDeletedProc(clientData)
}
/*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* GetEntryIndex --
*
@@ -1710,16 +1802,16 @@ EntryCmdDeletedProc(clientData)
* or an error.
*
* Results:
- * A standard Tcl result. If all went well, then *indexPtr is
+ * A standard Tcl result. If all went well, then *byteIndexPtr is
* filled in with the 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 interp->result.
+ * the number of bytes in the string, inclusive. If an
+ * error occurs then an error message is left in the interp's result.
*
* Side effects:
* None.
*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
static int
@@ -1728,7 +1820,8 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
Entry *entryPtr; /* Entry for which the index is being
* specified. */
char *string; /* Specifies character in entryPtr. */
- int *indexPtr; /* Where to store converted index. */
+ int *indexPtr; /* Where to store converted character
+ * index. */
{
size_t length;
@@ -1741,7 +1834,7 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
badIndex:
/*
- * Some of the paths here leave messages in interp->result,
+ * Some of the paths here leave messages in the interp's result,
* so we have to clear it out before storing our own message.
*/
@@ -1763,8 +1856,8 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
goto badIndex;
}
} else if (string[0] == 's') {
- if (entryPtr->selectFirst == -1) {
- interp->result = "selection isn't in entry";
+ if (entryPtr->selectFirst < 0) {
+ Tcl_SetResult(interp, "selection isn't in entry", TCL_STATIC);
return TCL_ERROR;
}
if (length < 5) {
@@ -1778,9 +1871,9 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
goto badIndex;
}
} else if (string[0] == '@') {
- int x, roundUp;
+ int x, roundUp, byteIndex;
- if (Tcl_GetInt(interp, string+1, &x) != TCL_OK) {
+ if (Tcl_GetInt(interp, string + 1, &x) != TCL_OK) {
goto badIndex;
}
if (x < entryPtr->inset) {
@@ -1791,8 +1884,9 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
x = Tk_Width(entryPtr->tkwin) - entryPtr->inset - 1;
roundUp = 1;
}
- *indexPtr = Tk_PointToChar(entryPtr->textLayout,
+ byteIndex = Tk_PointToChar(entryPtr->textLayout,
x - entryPtr->layoutX, 0);
+ *indexPtr = Tcl_NumUtfChars(entryPtr->displayString, byteIndex);
/*
* Special trick: if the x-position was off-screen to the right,
@@ -1812,7 +1906,7 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
*indexPtr = 0;
} else if (*indexPtr > entryPtr->numChars) {
*indexPtr = entryPtr->numChars;
- }
+ }
}
return TCL_OK;
}
@@ -1836,9 +1930,8 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
static void
EntryScanTo(entryPtr, x)
- register Entry *entryPtr; /* Information about widget. */
- int x; /* X-coordinate to use for scan
- * operation. */
+ Entry *entryPtr; /* Information about widget. */
+ int x; /* X-coordinate to use for scan operation. */
{
int newLeftIndex;
@@ -1854,19 +1947,24 @@ EntryScanTo(entryPtr, x)
*/
newLeftIndex = entryPtr->scanMarkIndex
- - (10*(x - entryPtr->scanMarkX))/entryPtr->avgWidth;
+ - (10 * (x - entryPtr->scanMarkX)) / entryPtr->avgWidth;
if (newLeftIndex >= entryPtr->numChars) {
- newLeftIndex = entryPtr->scanMarkIndex = entryPtr->numChars-1;
+ newLeftIndex = entryPtr->scanMarkIndex = entryPtr->numChars - 1;
entryPtr->scanMarkX = x;
}
if (newLeftIndex < 0) {
newLeftIndex = entryPtr->scanMarkIndex = 0;
entryPtr->scanMarkX = x;
}
+
if (newLeftIndex != entryPtr->leftIndex) {
entryPtr->leftIndex = newLeftIndex;
entryPtr->flags |= UPDATE_SCROLLBAR;
EntryComputeGeometry(entryPtr);
+ if (newLeftIndex != entryPtr->leftIndex) {
+ entryPtr->scanMarkIndex = entryPtr->leftIndex;
+ entryPtr->scanMarkX = x;
+ }
EventuallyRedraw(entryPtr);
}
}
@@ -1890,10 +1988,9 @@ EntryScanTo(entryPtr, x)
static void
EntrySelectTo(entryPtr, index)
- register Entry *entryPtr; /* Information about widget. */
- int index; /* Index of element that is to
- * become the "other" end of the
- * selection. */
+ Entry *entryPtr; /* Information about widget. */
+ int index; /* Character index of element that is to
+ * become the "other" end of the selection. */
{
int newFirst, newLast;
@@ -1956,38 +2053,35 @@ EntrySelectTo(entryPtr, index)
static int
EntryFetchSelection(clientData, offset, buffer, maxBytes)
- ClientData clientData; /* Information about entry 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. */
+ 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. */
{
Entry *entryPtr = (Entry *) clientData;
- int count;
- char *displayString;
+ int byteCount;
+ char *string, *selStart, *selEnd;
if ((entryPtr->selectFirst < 0) || !(entryPtr->exportSelection)) {
return -1;
}
- count = entryPtr->selectLast - entryPtr->selectFirst - offset;
- if (count > maxBytes) {
- count = maxBytes;
+ string = entryPtr->displayString;
+ selStart = Tcl_UtfAtIndex(string, entryPtr->selectFirst);
+ selEnd = Tcl_UtfAtIndex(selStart,
+ entryPtr->selectLast - entryPtr->selectFirst);
+ byteCount = selEnd - selStart - offset;
+ if (byteCount > maxBytes) {
+ byteCount = maxBytes;
}
- if (count <= 0) {
+ if (byteCount <= 0) {
return 0;
}
- if (entryPtr->displayString == NULL) {
- displayString = entryPtr->string;
- } else {
- displayString = entryPtr->displayString;
- }
- strncpy(buffer, displayString + entryPtr->selectFirst + offset,
- (size_t) count);
- buffer[count] = '\0';
- return count;
+ memcpy(buffer, selStart + offset, (size_t) byteCount);
+ buffer[byteCount] = '\0';
+ return byteCount;
}
/*
@@ -2010,7 +2104,7 @@ EntryFetchSelection(clientData, offset, buffer, maxBytes)
static void
EntryLostSelection(clientData)
- ClientData clientData; /* Information about entry widget. */
+ ClientData clientData; /* Information about entry widget. */
{
Entry *entryPtr = (Entry *) clientData;
@@ -2023,7 +2117,7 @@ EntryLostSelection(clientData)
*/
#ifdef ALWAYS_SHOW_SELECTION
- if ((entryPtr->selectFirst != -1) && entryPtr->exportSelection) {
+ if ((entryPtr->selectFirst >= 0) && entryPtr->exportSelection) {
entryPtr->selectFirst = -1;
entryPtr->selectLast = -1;
EventuallyRedraw(entryPtr);
@@ -2052,7 +2146,7 @@ EntryLostSelection(clientData)
static void
EventuallyRedraw(entryPtr)
- register Entry *entryPtr; /* Information about widget. */
+ Entry *entryPtr; /* Information about widget. */
{
if ((entryPtr->tkwin == NULL) || !Tk_IsMapped(entryPtr->tkwin)) {
return;
@@ -2091,36 +2185,38 @@ 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 visible one. */
+ 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;
+ int bytesInWindow, leftByte, charsInWindow;
+ char *string;
if (entryPtr->numChars == 0) {
*firstPtr = 0.0;
*lastPtr = 1.0;
} else {
- charsInWindow = Tk_PointToChar(entryPtr->textLayout,
+ string = entryPtr->displayString;
+
+ bytesInWindow = Tk_PointToChar(entryPtr->textLayout,
Tk_Width(entryPtr->tkwin) - entryPtr->inset
- - entryPtr->layoutX - 1, 0) + 1;
- if (charsInWindow > entryPtr->numChars) {
- /*
- * If all chars were visible, then charsInWindow will be
- * the index just after the last char that was visible.
- */
-
- charsInWindow = entryPtr->numChars;
+ - entryPtr->layoutX - 1, 0);
+ if (bytesInWindow < entryPtr->numDisplayBytes) {
+ bytesInWindow = Tcl_UtfNext(string + bytesInWindow) - string;
}
- charsInWindow -= entryPtr->leftIndex;
- if (charsInWindow == 0) {
- charsInWindow = 1;
+ bytesInWindow -= entryPtr->leftIndex;
+ if (bytesInWindow == 0) {
+ bytesInWindow = 1;
}
- *firstPtr = ((double) entryPtr->leftIndex)/entryPtr->numChars;
- *lastPtr = ((double) (entryPtr->leftIndex + charsInWindow))
- /entryPtr->numChars;
+
+ leftByte = Tcl_UtfAtIndex(string, entryPtr->leftIndex) - string;
+ charsInWindow = Tcl_NumUtfChars(string + leftByte, bytesInWindow);
+
+ *firstPtr = (double) entryPtr->leftIndex / entryPtr->numChars;
+ *lastPtr = (double) (entryPtr->leftIndex + charsInWindow)
+ / entryPtr->numChars;
}
}
@@ -2148,7 +2244,7 @@ static void
EntryUpdateScrollbar(entryPtr)
Entry *entryPtr; /* Information about widget. */
{
- char args[100];
+ char args[TCL_DOUBLE_SPACE * 2];
int code;
double first, last;
Tcl_Interp *interp;
@@ -2193,7 +2289,7 @@ static void
EntryBlinkProc(clientData)
ClientData clientData; /* Pointer to record describing entry. */
{
- register Entry *entryPtr = (Entry *) clientData;
+ Entry *entryPtr = (Entry *) clientData;
if (!(entryPtr->flags & GOT_FOCUS) || (entryPtr->insertOffTime == 0)) {
return;
@@ -2230,7 +2326,7 @@ EntryBlinkProc(clientData)
static void
EntryFocusProc(entryPtr, gotFocus)
- register Entry *entryPtr; /* Entry that got or lost focus. */
+ Entry *entryPtr; /* Entry that got or lost focus. */
int gotFocus; /* 1 means window is getting focus, 0 means
* it's losing it. */
{
@@ -2276,7 +2372,7 @@ EntryTextVarProc(clientData, interp, name1, name2, flags)
char *name2; /* Not used. */
int flags; /* Information about what happened. */
{
- register Entry *entryPtr = (Entry *) clientData;
+ Entry *entryPtr = (Entry *) clientData;
char *value;
/*
diff --git a/generic/tkFileFilter.c b/generic/tkFileFilter.c
index 1b7e61a..8f25149 100644
--- a/generic/tkFileFilter.c
+++ b/generic/tkFileFilter.c
@@ -9,8 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkFileFilter.c 1.6 97/04/30 15:55:35
- *
+ * SCCS: @(#) tkFileFilter.c 1.7 97/05/06 13:49:51
*/
#include "tkInt.h"
diff --git a/generic/tkFocus.c b/generic/tkFocus.c
index fe8f2c5..f4085da 100644
--- a/generic/tkFocus.c
+++ b/generic/tkFocus.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkFocus.c 1.48 97/10/31 09:55:22
+ * SCCS: @(#) tkFocus.c 1.51 97/11/07 21:16:51
*/
#include "tkInt.h"
@@ -106,7 +106,7 @@ static void SetFocus _ANSI_ARGS_((TkWindow *winPtr, int force));
/*
*--------------------------------------------------------------
*
- * Tk_FocusCmd --
+ * Tk_FocusObjCmd --
*
* This procedure is invoked to process the "focus" Tcl command.
* See the user documentation for details on what it does.
@@ -121,28 +121,30 @@ static void SetFocus _ANSI_ARGS_((TkWindow *winPtr, int force));
*/
int
-Tk_FocusCmd(clientData, interp, argc, argv)
+Tk_FocusObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
+ static char *focusOptions[] = {"-displayof", "-force", "-lastfor",
+ (char *) NULL};
Tk_Window tkwin = (Tk_Window) clientData;
TkWindow *winPtr = (TkWindow *) clientData;
TkWindow *newPtr, *focusWinPtr, *topLevelPtr;
ToplevelFocusInfo *tlFocusPtr;
- char c;
- size_t length;
+ char *windowName;
+ int index;
/*
* If invoked with no arguments, just return the current focus window.
*/
- if (argc == 1) {
+ if (objc == 1) {
focusWinPtr = TkGetFocusWin(winPtr);
if (focusWinPtr != NULL) {
- interp->result = focusWinPtr->pathName;
+ Tcl_SetResult(interp, focusWinPtr->pathName, TCL_STATIC);
}
return TCL_OK;
}
@@ -152,12 +154,18 @@ Tk_FocusCmd(clientData, interp, argc, argv)
* on that window.
*/
- if (argc == 2) {
- if (argv[1][0] == 0) {
+ if (objc == 2) {
+ windowName = Tcl_GetStringFromObj(objv[1], (int *) NULL);
+
+ /*
+ * The empty string case exists for backwards compatibility.
+ */
+
+ if (windowName[0] == '\0') {
return TCL_OK;
}
- if (argv[1][0] == '.') {
- newPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
+ if (windowName[0] == '.') {
+ newPtr = (TkWindow *) Tk_NameToWindow(interp, windowName, tkwin);
if (newPtr == NULL) {
return TCL_ERROR;
}
@@ -168,65 +176,72 @@ Tk_FocusCmd(clientData, interp, argc, argv)
}
}
- length = strlen(argv[1]);
- c = argv[1][1];
- if ((c == 'd') && (strncmp(argv[1], "-displayof", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " -displayof window\"", (char *) NULL);
- return TCL_ERROR;
- }
- newPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
- if (newPtr == NULL) {
- return TCL_ERROR;
- }
- newPtr = TkGetFocusWin(newPtr);
- if (newPtr != NULL) {
- interp->result = newPtr->pathName;
- }
- } else if ((c == 'f') && (strncmp(argv[1], "-force", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " -force window\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (argv[2][0] == 0) {
- return TCL_OK;
- }
- newPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
- if (newPtr == NULL) {
- return TCL_ERROR;
- }
- SetFocus(newPtr, 1);
- } else if ((c == 'l') && (strncmp(argv[1], "-lastfor", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " -lastfor window\"", (char *) NULL);
- return TCL_ERROR;
+ if (Tcl_GetIndexFromObj(interp, objv[1], focusOptions, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window");
+ return TCL_ERROR;
+ }
+ switch (index) {
+ case 0: { /* -displayof */
+ windowName = Tcl_GetStringFromObj(objv[2], (int *) 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;
}
- newPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
- if (newPtr == NULL) {
- return TCL_ERROR;
+ case 1: { /* -force */
+ windowName = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+
+ /*
+ * 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;
+ }
+ SetFocus(newPtr, 1);
+ break;
}
- for (topLevelPtr = newPtr; topLevelPtr != NULL;
- topLevelPtr = topLevelPtr->parentPtr) {
- if (topLevelPtr->flags & TK_TOP_LEVEL) {
- for (tlFocusPtr = newPtr->mainPtr->tlFocusPtr;
- tlFocusPtr != NULL;
- tlFocusPtr = tlFocusPtr->nextPtr) {
- if (tlFocusPtr->topLevelPtr == topLevelPtr) {
- interp->result = tlFocusPtr->focusWinPtr->pathName;
- return TCL_OK;
+ case 2: { /* -lastfor */
+ windowName = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+ 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_LEVEL) {
+ 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);
+ return TCL_OK;
}
- interp->result = topLevelPtr->pathName;
- return TCL_OK;
}
+ break;
+ }
+ default: {
+ panic("bad const entries to focusOptions in focus command");
}
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be -displayof, -force, or -lastfor", (char *) NULL);
- return TCL_ERROR;
}
return TCL_OK;
}
diff --git a/generic/tkFont.c b/generic/tkFont.c
index 11929b6..593c506 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -6,14 +6,15 @@
* displaying text.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkFont.c 1.74 97/10/10 14:34:11
+ * SCCS: @(#) tkFont.c 1.88 98/02/11 17:44:51
*/
+#include "tkPort.h"
#include "tkInt.h"
#include "tkFont.h"
@@ -25,26 +26,19 @@
typedef struct TkFontInfo {
Tcl_HashTable fontCache; /* Map a string to an existing Tk_Font.
- * Keys are CachedFontKey structs, values are
- * TkFont structs. */
+ * 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
- * Tk_Uids, values are NamedFont structs. */
+ * strings, values are NamedFont pointers. */
TkMainInfo *mainPtr; /* Application that owns this structure. */
- int updatePending;
+ int updatePending; /* Non-zero when a World Changed event has
+ * already been queued to handle a change to
+ * a named font. */
} TkFontInfo;
/*
- * The following structure is used as a key in the fontCache.
- */
-
-typedef struct CachedFontKey {
- Display *display; /* Display for which font was constructed. */
- Tk_Uid string; /* String that describes font. */
-} CachedFontKey;
-
-/*
* 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
* when the last reference to it goes away.
@@ -168,13 +162,6 @@ static TkStateMap xlfdSetwidthMap[] = {
{TK_SW_UNKNOWN, NULL}
};
-static TkStateMap xlfdCharsetMap[] = {
- {TK_CS_NORMAL, "iso8859"},
- {TK_CS_SYMBOL, "adobe"},
- {TK_CS_SYMBOL, "sun"},
- {TK_CS_OTHER, NULL}
-};
-
/*
* The following structure and defines specify the valid builtin options
* when configuring a set of font attributes.
@@ -196,7 +183,135 @@ static char *fontOpt[] = {
#define FONT_SLANT 3
#define FONT_UNDERLINE 4
#define FONT_OVERSTRIKE 5
-#define FONT_NUMFIELDS 6 /* Length of fontOpt array. */
+#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.
+ */
+
+static char *timesAliases[] = {
+ "Times", /* Unix. */
+ "Times New Roman", /* Windows. */
+ "New York", /* Mac. */
+ NULL
+};
+
+static char *helveticaAliases[] = {
+ "Helvetica", /* Unix. */
+ "Arial", /* Windows. */
+ "Geneva", /* Mac. */
+ NULL
+};
+
+static char *courierAliases[] = {
+ "Courier", /* Unix and Mac. */
+ "Courier New", /* Windows. */
+ NULL
+};
+
+static char *minchoAliases[] = {
+ "mincho", /* Unix. */
+ "\357\274\255\357\274\263 \346\230\216\346\234\235",
+ /* Windows (MS mincho). */
+ "\346\234\254\346\230\216\346\234\235\342\210\222\357\274\255",
+ /* Mac (honmincho-M). */
+ NULL
+};
+
+static char *gothicAliases[] = {
+ "gothic", /* Unix. */
+ "\357\274\255\357\274\263 \343\202\264\343\202\267\343\203\203\343\202\257",
+ /* 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
+};
+
+static char *dingbatsAliases[] = {
+ "dingbats", "zapfdingbats", "itc zapfdingbats",
+ /* Unix. */
+ /* Windows. */
+ "zapf dingbats", /* Mac. */
+ NULL
+};
+
+static char **fontAliases[] = {
+ timesAliases,
+ helveticaAliases,
+ courierAliases,
+ minchoAliases,
+ 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.
+ */
+
+static char *systemClass[] = {
+ "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. */
+ NULL
+};
+
+static char *sansClass[] = {
+ "helvetica", "gothic", /* All platforms. */
+ /* Unix. */
+ "ms sans serif", "traditional arabic",
+ /* Windows. */
+ "bastion", /* Mac. */
+ NULL
+};
+
+static char *monoClass[] = {
+ "courier", "gothic", /* All platforms. */
+ "fangsong ti", /* Unix. */
+ "simplified arabic fixed", /* Windows. */
+ "monaco", "pryamoy", /* Mac. */
+ NULL
+};
+
+static char *symbolClass[] = {
+ "symbol", "dingbats", "wingdings", NULL
+};
+
+static char **fontFallbacks[] = {
+ systemClass,
+ serifClass,
+ sansClass,
+ monoClass,
+ symbolClass,
+ NULL
+};
+
+/*
+ * 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[] = {
+ "symbol", /* All platforms. */
+ /* Unix. */
+ "lucida sans unicode", /* Windows. */
+ "chicago", /* Mac. */
+ NULL
+};
#define GetFontAttributes(tkfont) \
((CONST TkFontAttributes *) &((TkFont *) (tkfont))->fa)
@@ -208,7 +323,13 @@ static char *fontOpt[] = {
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,
@@ -218,12 +339,27 @@ 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 UpdateDependantFonts _ANSI_ARGS_((TkFontInfo *fiPtr,
+static void UpdateDependentFonts _ANSI_ARGS_((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.
+ */
+
+static Tcl_ObjType fontObjType = {
+ "font", /* name */
+ FreeFontObjProc, /* freeIntRepProc */
+ DupFontObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetFontFromAny /* setFromAnyProc */
+};
/*
@@ -236,8 +372,8 @@ static void UpdateDependantFonts _ANSI_ARGS_((TkFontInfo *fiPtr,
* package on a per application basis.
*
* Results:
- * Returns a token that must be stored in the TkMainInfo for this
- * application.
+ * Stores a token in the mainPtr to hold information needed by this
+ * package on a per application basis.
*
* Side effects:
* Memory allocated.
@@ -251,11 +387,13 @@ TkFontPkgInit(mainPtr)
TkFontInfo *fiPtr;
fiPtr = (TkFontInfo *) ckalloc(sizeof(TkFontInfo));
- Tcl_InitHashTable(&fiPtr->fontCache, sizeof(CachedFontKey) / sizeof(int));
- Tcl_InitHashTable(&fiPtr->namedTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&fiPtr->fontCache, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&fiPtr->namedTable, TCL_STRING_KEYS);
fiPtr->mainPtr = mainPtr;
fiPtr->updatePending = 0;
mainPtr->fontInfoPtr = fiPtr;
+
+ TkpFontPkgInit(mainPtr);
}
/*
@@ -281,12 +419,21 @@ TkFontPkgFree(mainPtr)
TkMainInfo *mainPtr; /* The application being deleted. */
{
TkFontInfo *fiPtr;
- Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr, *searchPtr;
Tcl_HashSearch search;
+ int fontsLeft;
fiPtr = mainPtr->fontInfoPtr;
- if (fiPtr->fontCache.numEntries != 0) {
+ fontsLeft = 0;
+ for (searchPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
+ searchPtr != NULL;
+ searchPtr = Tcl_NextHashEntry(&search)) {
+ fontsLeft++;
+ fprintf(stderr, "Font %s still in cache.\n",
+ Tcl_GetHashKey(&fiPtr->fontCache, searchPtr));
+ }
+ if (fontsLeft) {
panic("TkFontPkgFree: all fonts should have been freed already");
}
Tcl_DeleteHashTable(&fiPtr->fontCache);
@@ -368,7 +515,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
"font ?-displayof window? ?option?");
return TCL_ERROR;
}
- tkfont = Tk_GetFontFromObj(interp, tkwin, objv[2]);
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
if (tkfont == NULL) {
return TCL_ERROR;
}
@@ -394,14 +541,14 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
Tcl_WrongNumArgs(interp, 2, objv, "fontname ?options?");
return TCL_ERROR;
}
- string = Tk_GetUid(Tcl_GetStringFromObj(objv[2], NULL));
+ 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_AppendStringsToObj(Tcl_GetObjResult(interp), "named font \"", string,
+ Tcl_AppendResult(interp, "named font \"", string,
"\" doesn't exist", NULL);
return TCL_ERROR;
}
@@ -412,7 +559,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
} else {
result = ConfigAttributesObj(interp, tkwin, objc - 3,
objv + 3, &nfPtr->fa);
- UpdateDependantFonts(fiPtr, tkwin, namedHashPtr);
+ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);
return result;
}
return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr);
@@ -420,7 +567,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
case FONT_CREATE: {
int skip, i;
char *name;
- char buf[32];
+ char buf[16 + TCL_INTEGER_SPACE];
TkFontAttributes fa;
Tcl_HashEntry *namedHashPtr;
@@ -428,7 +575,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
if (objc < 3) {
name = NULL;
} else {
- name = Tcl_GetStringFromObj(objv[2], NULL);
+ name = Tcl_GetString(objv[2]);
if (name[0] == '-') {
name = NULL;
}
@@ -440,8 +587,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
for (i = 1; ; i++) {
sprintf(buf, "font%d", i);
- namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable,
- Tk_GetUid(buf));
+ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, buf);
if (namedHashPtr == NULL) {
break;
}
@@ -454,10 +600,10 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
&fa) != TCL_OK) {
return TCL_ERROR;
}
- if (TkCreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) {
+ if (CreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_SetStringObj(Tcl_GetObjResult(interp), name, -1);
+ Tcl_AppendResult(interp, name, NULL);
break;
}
case FONT_DELETE: {
@@ -476,10 +622,10 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
for (i = 2; i < objc; i++) {
- string = Tk_GetUid(Tcl_GetStringFromObj(objv[i], NULL));
+ string = Tcl_GetString(objv[i]);
namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string);
if (namedHashPtr == NULL) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "named font \"", string,
+ Tcl_AppendResult(interp, "named font \"", string,
"\" doesn't exist", (char *) NULL);
return TCL_ERROR;
}
@@ -511,6 +657,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
char *string;
Tk_Font tkfont;
int length, skip;
+ Tcl_Obj *resultPtr;
skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin);
if (skip < 0) {
@@ -521,17 +668,17 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
"font ?-displayof window? text");
return TCL_ERROR;
}
- tkfont = Tk_GetFontFromObj(interp, tkwin, objv[2]);
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
if (tkfont == NULL) {
return TCL_ERROR;
}
string = Tcl_GetStringFromObj(objv[3 + skip], &length);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_TextWidth(tkfont, string, length));
+ resultPtr = Tcl_GetObjResult(interp);
+ Tcl_SetIntObj(resultPtr, Tk_TextWidth(tkfont, string, length));
Tk_FreeFont(tkfont);
break;
}
case FONT_METRICS: {
- char buf[64];
Tk_Font tkfont;
int skip, index, i;
CONST TkFontMetrics *fmPtr;
@@ -548,7 +695,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
"font ?-displayof window? ?option?");
return TCL_ERROR;
}
- tkfont = Tk_GetFontFromObj(interp, tkwin, objv[2]);
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
if (tkfont == NULL) {
return TCL_ERROR;
}
@@ -556,11 +703,13 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
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_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
+ Tcl_AppendResult(interp, buf, NULL);
} else {
if (Tcl_GetIndexFromObj(interp, objv[3], switches,
"metric", 0, &index) != TCL_OK) {
@@ -582,22 +731,23 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
}
case FONT_NAMES: {
char *string;
- Tcl_Obj *strPtr;
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, Tcl_GetObjResult(interp), strPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
}
namedHashPtr = Tcl_NextHashEntry(&search);
}
@@ -610,7 +760,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
/*
*---------------------------------------------------------------------------
*
- * UpdateDependantFonts, TheWorldHasChanged, RecomputeWidgets --
+ * 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
@@ -627,7 +777,7 @@ Tk_FontObjCmd(clientData, interp, objc, objv)
*/
static void
-UpdateDependantFonts(fiPtr, tkwin, namedHashPtr)
+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. */
@@ -647,15 +797,16 @@ UpdateDependantFonts(fiPtr, tkwin, namedHashPtr)
return;
}
-
cacheHashPtr = Tcl_FirstHashEntry(&fiPtr->fontCache, &search);
while (cacheHashPtr != NULL) {
- fontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
- if (fontPtr->namedHashPtr == namedHashPtr) {
- TkpGetFontFromAttributes(fontPtr, tkwin, &nfPtr->fa);
- if (fiPtr->updatePending == 0) {
- fiPtr->updatePending = 1;
- Tcl_DoWhenIdle(TheWorldHasChanged, (ClientData) fiPtr);
+ for (fontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
+ fontPtr->nextPtr != NULL; fontPtr = fontPtr->nextPtr) {
+ if (fontPtr->namedHashPtr == namedHashPtr) {
+ TkpGetFontFromAttributes(fontPtr, tkwin, &nfPtr->fa);
+ if (fiPtr->updatePending == 0) {
+ fiPtr->updatePending = 1;
+ Tcl_DoWhenIdle(TheWorldHasChanged, (ClientData) fiPtr);
+ }
}
}
cacheHashPtr = Tcl_NextHashEntry(&search);
@@ -690,7 +841,7 @@ RecomputeWidgets(winPtr)
/*
*---------------------------------------------------------------------------
*
- * TkCreateNamedFont --
+ * CreateNamedFont --
*
* Create the specified named font with the given attributes in the
* named font table associated with the interp.
@@ -698,7 +849,7 @@ RecomputeWidgets(winPtr)
* 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 interp->result.
+ * error message is left in the interp's result.
*
* Side effects:
* Assume there used to exist a named font by the specified name, and
@@ -711,8 +862,8 @@ RecomputeWidgets(winPtr)
*---------------------------------------------------------------------------
*/
-int
-TkCreateNamedFont(interp, tkwin, name, faPtr)
+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. */
@@ -725,14 +876,13 @@ TkCreateNamedFont(interp, tkwin, name, faPtr)
fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
- name = Tk_GetUid(name);
namedHashPtr = Tcl_CreateHashEntry(&fiPtr->namedTable, name, &new);
if (new == 0) {
nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
if (nfPtr->deletePending == 0) {
- interp->result[0] = '\0';
- Tcl_AppendResult(interp, "font \"", name,
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "named font \"", name,
"\" already exists", (char *) NULL);
return TCL_ERROR;
}
@@ -745,7 +895,7 @@ TkCreateNamedFont(interp, tkwin, name, faPtr)
nfPtr->fa = *faPtr;
nfPtr->deletePending = 0;
- UpdateDependantFonts(fiPtr, tkwin, namedHashPtr);
+ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);
return TCL_OK;
}
@@ -769,13 +919,13 @@ TkCreateNamedFont(interp, tkwin, name, faPtr)
* 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->result.
+ * error message will be left in the interp's result.
*
* Side effects:
- * Calls Tk_GetFontFromObj(), which modifies interp's result object,
- * then copies the string from the result object into interp->result.
- * This procedure will go away when Tk_ConfigureWidget() is
- * made into an object command.
+ * 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.
*
*---------------------------------------------------------------------------
*/
@@ -787,26 +937,20 @@ Tk_GetFont(interp, tkwin, string)
CONST char *string; /* String describing font, as: named font,
* native format, or parseable string. */
{
+ Tk_Font tkfont;
Tcl_Obj *strPtr;
- Tk_Font tkfont;
-
- strPtr = Tcl_NewStringObj((char *) string, -1);
-
- tkfont = Tk_GetFontFromObj(interp, tkwin, strPtr);
- if (tkfont == NULL) {
- Tcl_SetResult(interp,
- Tcl_GetStringFromObj(Tcl_GetObjResult(interp), NULL),
- TCL_VOLATILE);
- }
- Tcl_DecrRefCount(strPtr); /* done with object */
+ strPtr = Tcl_NewStringObj((char *) string, -1);
+ Tcl_IncrRefCount(strPtr);
+ tkfont = Tk_AllocFontFromObj(interp, tkwin, strPtr);
+ Tcl_DecrRefCount(strPtr);
return tkfont;
}
/*
*---------------------------------------------------------------------------
*
- * Tk_GetFontFromObj --
+ * Tk_AllocFontFromObj --
*
* Given a string description of a font, map the description to a
* corresponding Tk_Font that represents the font.
@@ -819,46 +963,77 @@ Tk_GetFont(interp, tkwin, string)
* 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() so that the database is cleaned up when
- * fonts aren't in use anymore.
+ * 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_GetFontFromObj(interp, tkwin, objPtr)
+Tk_AllocFontFromObj(interp, tkwin, objPtr)
Tcl_Interp *interp; /* Interp for database and error return. */
- Tk_Window tkwin; /* For display on which font will be used. */
+ 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;
- CachedFontKey key;
Tcl_HashEntry *cacheHashPtr, *namedHashPtr;
- TkFont *fontPtr;
+ TkFont *fontPtr, *firstFontPtr, *oldFontPtr;
int new, descent;
NamedFont *nfPtr;
- char *string;
-
+
fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
- string = Tcl_GetStringFromObj(objPtr, NULL);
+ if (objPtr->typePtr != &fontObjType) {
+ SetFontFromAny(interp, objPtr);
+ }
- key.display = Tk_Display(tkwin);
- key.string = Tk_GetUid(string);
- cacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache, (char *) &key, &new);
+ oldFontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1;
- if (new == 0) {
- /*
- * We have already constructed a font with this description for
- * this display. Bump the reference count of the cached font.
- */
+ 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.
+ */
+
+ FreeFontObjProc(objPtr);
+ oldFontPtr = NULL;
+ } else if (Tk_Screen(tkwin) == oldFontPtr->screen) {
+ oldFontPtr->resourceRefCount++;
+ return (Tk_Font) oldFontPtr;
+ }
+ }
+
+ /*
+ * Next, search the list of fonts that have the name we want, to see
+ * if one of them is for the right screen.
+ */
- fontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
- fontPtr->refCount++;
- return (Tk_Font) fontPtr;
+ new = 0;
+ if (oldFontPtr != NULL) {
+ cacheHashPtr = oldFontPtr->cacheHashPtr;
+ FreeFontObjProc(objPtr);
+ } else {
+ cacheHashPtr = Tcl_CreateHashEntry(&fiPtr->fontCache,
+ Tcl_GetString(objPtr), &new);
+ }
+ firstFontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
+ for (fontPtr = firstFontPtr; (fontPtr != NULL);
+ fontPtr = fontPtr->nextPtr) {
+ if (Tk_Screen(tkwin) == fontPtr->screen) {
+ fontPtr->resourceRefCount++;
+ fontPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr;
+ return (Tk_Font) fontPtr;
+ }
}
- namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, key.string);
+ /*
+ * The desired font isn't in the table. Make a new one.
+ */
+
+ namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable,
+ Tcl_GetString(objPtr));
if (namedHashPtr != NULL) {
/*
* Construct a font based on a named font.
@@ -873,15 +1048,19 @@ Tk_GetFontFromObj(interp, tkwin, objPtr)
* Native font?
*/
- fontPtr = TkpGetNativeFont(tkwin, string);
+ fontPtr = TkpGetNativeFont(tkwin, Tcl_GetString(objPtr));
if (fontPtr == NULL) {
TkFontAttributes fa;
+ Tcl_Obj *dupObjPtr = Tcl_DuplicateObj(objPtr);
- TkInitFontAttributes(&fa);
- if (ParseFontNameObj(interp, tkwin, objPtr, &fa) != TCL_OK) {
- Tcl_DeleteHashEntry(cacheHashPtr);
+ if (ParseFontNameObj(interp, tkwin, dupObjPtr, &fa) != TCL_OK) {
+ if (new) {
+ Tcl_DeleteHashEntry(cacheHashPtr);
+ }
+ Tcl_DecrRefCount(dupObjPtr);
return NULL;
}
+ Tcl_DecrRefCount(dupObjPtr);
/*
* String contained the attributes inline.
@@ -890,13 +1069,16 @@ Tk_GetFontFromObj(interp, tkwin, objPtr)
fontPtr = TkpGetFontFromAttributes(NULL, tkwin, &fa);
}
}
- Tcl_SetHashValue(cacheHashPtr, fontPtr);
- fontPtr->refCount = 1;
- fontPtr->cacheHashPtr = cacheHashPtr;
- fontPtr->namedHashPtr = namedHashPtr;
+ fontPtr->resourceRefCount = 1;
+ fontPtr->objRefCount = 1;
+ fontPtr->cacheHashPtr = cacheHashPtr;
+ fontPtr->namedHashPtr = namedHashPtr;
+ fontPtr->screen = Tk_Screen(tkwin);
+ fontPtr->nextPtr = firstFontPtr;
+ Tcl_SetHashValue(cacheHashPtr, fontPtr);
- Tk_MeasureChars((Tk_Font) fontPtr, "0", 1, 0, 0, &fontPtr->tabWidth);
+ Tk_MeasureChars((Tk_Font) fontPtr, "0", 1, -1, 0, &fontPtr->tabWidth);
if (fontPtr->tabWidth == 0) {
fontPtr->tabWidth = fontPtr->fm.maxWidth;
}
@@ -918,7 +1100,7 @@ Tk_GetFontFromObj(interp, tkwin, objPtr)
descent = fontPtr->fm.descent;
fontPtr->underlinePos = descent / 2;
- fontPtr->underlineHeight = fontPtr->fa.pointsize / 10;
+ fontPtr->underlineHeight = TkFontGetPixels(tkwin, fontPtr->fa.size) / 10;
if (fontPtr->underlineHeight == 0) {
fontPtr->underlineHeight = 1;
}
@@ -936,10 +1118,125 @@ Tk_GetFontFromObj(interp, tkwin, objPtr)
}
}
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr;
return (Tk_Font) fontPtr;
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetFontFromObj --
+ *
+ * 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.
+ *
+ * Side effects:
+ * 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. */
+{
+ TkFontInfo *fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr;
+ TkFont *fontPtr;
+ Tcl_HashEntry *hashPtr;
+
+ if (objPtr->typePtr != &fontObjType) {
+ SetFontFromAny((Tcl_Interp *) NULL, objPtr);
+ }
+
+ fontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ 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.
+ */
+
+ FreeFontObjProc(objPtr);
+ fontPtr = NULL;
+ } else if (Tk_Screen(tkwin) == fontPtr->screen) {
+ return (Tk_Font) fontPtr;
+ }
+ }
+
+ /*
+ * 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) {
+ hashPtr = fontPtr->cacheHashPtr;
+ FreeFontObjProc(objPtr);
+ } else {
+ hashPtr = Tcl_FindHashEntry(&fiPtr->fontCache, Tcl_GetString(objPtr));
+ }
+ if (hashPtr != NULL) {
+ for (fontPtr = (TkFont *) Tcl_GetHashValue(hashPtr); fontPtr != NULL;
+ fontPtr = fontPtr->nextPtr) {
+ if (Tk_Screen(tkwin) == fontPtr->screen) {
+ fontPtr->objRefCount++;
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) fontPtr;
+ return (Tk_Font) fontPtr;
+ }
+ }
+ }
+
+ panic("Tk_GetFontFromObj called with non-existent font!");
+ return NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetFontFromAny --
+ *
+ * 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 fontObjType.
+ * 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. */
+{
+ Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetString(objPtr);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+ objPtr->typePtr = &fontObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+
+ return TCL_OK;
+}
+
+/*
*---------------------------------------------------------------------------
*
* Tk_NameOfFont --
@@ -963,14 +1260,9 @@ Tk_NameOfFont(tkfont)
Tk_Font tkfont; /* Font whose name is desired. */
{
TkFont *fontPtr;
- Tcl_HashEntry *hPtr;
- CachedFontKey *keyPtr;
fontPtr = (TkFont *) tkfont;
- hPtr = fontPtr->cacheHashPtr;
-
- keyPtr = (CachedFontKey *) Tcl_GetHashKey(hPtr->tablePtr, hPtr);
- return (char *) keyPtr->string;
+ return fontPtr->cacheHashPtr->key.string;
}
/*
@@ -994,30 +1286,144 @@ void
Tk_FreeFont(tkfont)
Tk_Font tkfont; /* Font to be released. */
{
- TkFont *fontPtr;
+ TkFont *fontPtr, *prevPtr;
NamedFont *nfPtr;
if (tkfont == NULL) {
return;
}
fontPtr = (TkFont *) tkfont;
- fontPtr->refCount--;
- if (fontPtr->refCount == 0) {
- if (fontPtr->namedHashPtr != NULL) {
- /*
- * The font is being deleted. Determine if the associated named
- * font definition should and/or can be deleted too.
- */
+ fontPtr->resourceRefCount--;
+ if (fontPtr->resourceRefCount > 0) {
+ return;
+ }
+ if (fontPtr->namedHashPtr != NULL) {
+ /*
+ * This font derived from a named font. Reduce the reference
+ * count on the named font and free it if no-one else is
+ * using it.
+ */
- nfPtr = (NamedFont *) Tcl_GetHashValue(fontPtr->namedHashPtr);
- nfPtr->refCount--;
- if ((nfPtr->refCount == 0) && (nfPtr->deletePending != 0)) {
- Tcl_DeleteHashEntry(fontPtr->namedHashPtr);
- ckfree((char *) nfPtr);
- }
+ nfPtr = (NamedFont *) Tcl_GetHashValue(fontPtr->namedHashPtr);
+ nfPtr->refCount--;
+ if ((nfPtr->refCount == 0) && (nfPtr->deletePending != 0)) {
+ Tcl_DeleteHashEntry(fontPtr->namedHashPtr);
+ ckfree((char *) nfPtr);
+ }
+ }
+
+ prevPtr = (TkFont *) Tcl_GetHashValue(fontPtr->cacheHashPtr);
+ if (prevPtr == fontPtr) {
+ if (fontPtr->nextPtr == NULL) {
+ Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);
+ } else {
+ Tcl_SetHashValue(fontPtr->cacheHashPtr, fontPtr->nextPtr);
+ }
+ } else {
+ while (prevPtr->nextPtr != fontPtr) {
+ prevPtr = prevPtr->nextPtr;
+ }
+ prevPtr->nextPtr = fontPtr->nextPtr;
+ }
+
+ TkpDeleteFont(fontPtr);
+ if (fontPtr->objRefCount == 0) {
+ ckfree((char *) fontPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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_FreeFont(Tk_GetFontFromObj(tkwin, objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FreeFontObjProc(objPtr)
+ Tcl_Obj *objPtr; /* The object we are releasing. */
+{
+ TkFont *fontPtr = (TkFont *) objPtr->internalRep.twoPtrValue.ptr1;
+
+ if (fontPtr != NULL) {
+ fontPtr->objRefCount--;
+ if ((fontPtr->resourceRefCount == 0) && (fontPtr->objRefCount == 0)) {
+ ckfree((char *) fontPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
}
- Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);
- TkpDeleteFont(fontPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupFontObjProc --
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DupFontObjProc(srcObjPtr, dupObjPtr)
+ 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;
+
+ if (fontPtr != NULL) {
+ fontPtr->objRefCount++;
}
}
@@ -1112,7 +1518,6 @@ Tk_GetFontMetrics(tkfont, fmPtr)
*---------------------------------------------------------------------------
*/
-
int
Tk_PostscriptFontName(tkfont, dsPtr)
Tk_Font tkfont; /* Font in which text will be printed. */
@@ -1154,6 +1559,8 @@ Tk_PostscriptFontName(tkfont, dsPtr)
} else if (strcasecmp(family, "ZapfDingbats") == 0) {
family = "ZapfDingbats";
} else {
+ Tcl_UniChar ch;
+
/*
* Inline, capitalize the first letter of each word, lowercase the
* rest of the letters in each word, and then take out the spaces
@@ -1165,16 +1572,19 @@ Tk_PostscriptFontName(tkfont, dsPtr)
src = dest = Tcl_DStringValue(dsPtr) + len;
upper = 1;
- for (; *src != '\0'; src++, dest++) {
- while (isspace(UCHAR(*src))) {
+ for (; *src != '\0'; ) {
+ while (isspace(UCHAR(*src))) { /* INTL: ISO space */
src++;
upper = 1;
}
- *dest = *src;
- if ((upper != 0) && (islower(UCHAR(*src)))) {
- *dest = toupper(UCHAR(*src));
+ src += Tcl_UtfToUniChar(src, &ch);
+ if (upper) {
+ ch = Tcl_UniCharToUpper(ch);
+ upper = 0;
+ } else {
+ ch = Tcl_UniCharToLower(ch);
}
- upper = 0;
+ dest += Tcl_UniCharToUtf(ch, dest);
}
*dest = '\0';
Tcl_DStringSetLength(dsPtr, dest - Tcl_DStringValue(dsPtr));
@@ -1251,7 +1661,7 @@ Tk_PostscriptFontName(tkfont, dsPtr)
}
}
- return fontPtr->fa.pointsize;
+ return fontPtr->fa.size;
}
/*
@@ -1284,7 +1694,7 @@ Tk_TextWidth(tkfont, string, numChars)
if (numChars < 0) {
numChars = strlen(string);
}
- Tk_MeasureChars(tkfont, string, numChars, 0, 0, &width);
+ Tk_MeasureChars(tkfont, string, numChars, -1, 0, &width);
return width;
}
@@ -1332,8 +1742,8 @@ Tk_UnderlineChars(display, drawable, gc, tkfont, string, x, y, firstChar,
fontPtr = (TkFont *) tkfont;
- Tk_MeasureChars(tkfont, string, firstChar, 0, 0, &startX);
- Tk_MeasureChars(tkfont, string, lastChar, 0, 0, &endX);
+ Tk_MeasureChars(tkfont, string, firstChar, -1, 0, &startX);
+ Tk_MeasureChars(tkfont, string, lastChar, -1, 0, &endX);
XFillRectangle(display, drawable, gc, x + startX,
y + fontPtr->underlinePos, (unsigned int) (endX - startX),
@@ -1399,13 +1809,11 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
TextLayout *layoutPtr;
LayoutChunk *chunkPtr;
CONST TkFontMetrics *fmPtr;
-#define MAX_LINES 50
- int staticLineLengths[MAX_LINES];
+ Tcl_DString lineBuffer;
int *lineLengths;
- int maxLines, curLine, layoutHeight;
+ int curLine, layoutHeight;
- lineLengths = staticLineLengths;
- maxLines = MAX_LINES;
+ Tcl_DStringInit(&lineBuffer);
fontPtr = (TkFont *) tkfont;
fmPtr = &fontPtr->fm;
@@ -1415,6 +1823,9 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
if (numChars < 0) {
numChars = strlen(string);
}
+ if (wrapLength == 0) {
+ wrapLength = -1;
+ }
maxChunks = 1;
@@ -1438,7 +1849,6 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
flags &= TK_IGNORE_TABS | TK_IGNORE_NEWLINES;
flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE;
- curLine = 0;
for (start = string; start < end; ) {
if (start >= special) {
/*
@@ -1515,7 +1925,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
* Consume all extra spaces at end of line.
*/
- while ((start < end) && isspace(UCHAR(*start))) {
+ while ((start < end) && isspace(UCHAR(*start))) { /* INTL: ISO space */
if (!(flags & TK_IGNORE_NEWLINES)) {
if ((*start == '\n') || (*start == '\r')) {
break;
@@ -1537,7 +1947,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
if (charsThisChunk > 0) {
chunkPtr->numChars += Tk_MeasureChars(tkfont,
chunkPtr->start + chunkPtr->numChars, charsThisChunk,
- 0, 0, &chunkPtr->totalWidth);
+ -1, 0, &chunkPtr->totalWidth);
chunkPtr->totalWidth += curX;
}
}
@@ -1559,19 +1969,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
* can be centered or right justified, if necessary.
*/
- if (curLine >= maxLines) {
- int *newLengths;
-
- newLengths = (int *) ckalloc(2 * maxLines * sizeof(int));
- memcpy((void *) newLengths, lineLengths, maxLines * sizeof(int));
- if (lineLengths != staticLineLengths) {
- ckfree((char *) lineLengths);
- }
- lineLengths = newLengths;
- maxLines *= 2;
- }
- lineLengths[curLine] = curX;
- curLine++;
+ Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));
curX = 0;
baseline += height;
@@ -1588,6 +1986,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, 0, curX,
1000000000, baseline);
chunkPtr->numDisplayChars = -1;
+ Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));
baseline += height;
}
}
@@ -1600,6 +1999,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
curLine = 0;
chunkPtr = layoutPtr->chunks;
y = chunkPtr->y;
+ lineLengths = (int *) Tcl_DStringValue(&lineBuffer);
for (n = 0; n < layoutPtr->numChunks; n++) {
int extra;
@@ -1643,9 +2043,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
if (heightPtr != NULL) {
*heightPtr = layoutHeight;
}
- if (lineLengths != staticLineLengths) {
- ckfree((char *) lineLengths);
- }
+ Tcl_DStringFree(&lineBuffer);
return (Tk_TextLayout) layoutPtr;
}
@@ -1737,7 +2135,7 @@ Tk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar)
firstChar = 0;
} else {
Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start, firstChar,
- 0, 0, &drawX);
+ -1, 0, &drawX);
}
if (lastChar < numDisplayChars) {
numDisplayChars = lastChar;
@@ -1910,9 +2308,9 @@ Tk_PointToChar(layout, x, y)
return chunkPtr->start - layoutPtr->string;
}
n = Tk_MeasureChars((Tk_Font) fontPtr, chunkPtr->start,
- chunkPtr->numChars, x + 1 - chunkPtr->x,
- TK_PARTIAL_OK, &dummy);
- return (chunkPtr->start + n - 1) - layoutPtr->string;
+ chunkPtr->numChars, x - chunkPtr->x,
+ 0, &dummy);
+ return (chunkPtr->start + n) - layoutPtr->string;
}
lastPtr = chunkPtr;
chunkPtr++;
@@ -2016,11 +2414,11 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr)
}
} else if (index < chunkPtr->numChars) {
if (xPtr != NULL) {
- Tk_MeasureChars(tkfont, chunkPtr->start, index, 0, 0, &x);
+ Tk_MeasureChars(tkfont, chunkPtr->start, index, -1, 0, &x);
x += chunkPtr->x;
}
if (widthPtr != NULL) {
- Tk_MeasureChars(tkfont, chunkPtr->start + index, 1, 0, 0, &w);
+ Tk_MeasureChars(tkfont, chunkPtr->start + index, 1, -1, 0, &w);
}
goto check;
}
@@ -2276,7 +2674,7 @@ Tk_IntersectTextLayout(layout, x, y, width, height)
* location of the baseline for the string.
*
* Results:
- * Interp->result is modified to hold the Postscript code that
+ * The interp's result is modified to hold the Postscript code that
* will render the text layout.
*
* Side effects:
@@ -2359,36 +2757,6 @@ Tk_TextLayoutToPostscript(interp, layout)
/*
*---------------------------------------------------------------------------
*
- * TkInitFontAttributes --
- *
- * Initialize the font attributes structure to contain sensible
- * values. This must be called before using any other font
- * attributes functions.
- *
- * Results:
- * None.
- *
- * Side effects.
- * None.
- *
- *---------------------------------------------------------------------------
- */
-
-void
-TkInitFontAttributes(faPtr)
- TkFontAttributes *faPtr; /* The attributes structure to initialize. */
-{
- faPtr->family = NULL;
- faPtr->pointsize = 0;
- faPtr->weight = TK_FW_NORMAL;
- faPtr->slant = TK_FS_ROMAN;
- faPtr->underline = 0;
- faPtr->overstrike = 0;
-}
-
-/*
- *---------------------------------------------------------------------------
- *
* ConfigAttributesObj --
*
* Process command line options to fill in fields of a properly
@@ -2419,68 +2787,74 @@ ConfigAttributesObj(interp, tkwin, objc, objv, faPtr)
* be properly initialized. */
{
int i, n, index;
- Tcl_Obj *value;
- char *option, *string;
+ Tcl_Obj *optionPtr, *valuePtr;
+ char *value;
- if (objc & 1) {
- string = Tcl_GetStringFromObj(objv[objc - 1], NULL);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "missing value for \"",
- string, "\" option", (char *) NULL);
- return TCL_ERROR;
- }
-
for (i = 0; i < objc; i += 2) {
- option = Tcl_GetStringFromObj(objv[i], NULL);
- value = objv[i + 1];
+ optionPtr = objv[i];
+ valuePtr = objv[i + 1];
- if (Tcl_GetIndexFromObj(interp, objv[i], fontOpt, "option", 1,
+ if (Tcl_GetIndexFromObj(interp, optionPtr, fontOpt, "option", 1,
&index) != TCL_OK) {
return TCL_ERROR;
}
+ if (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.
+ */
+
+ Tcl_AppendResult(interp, "value for \"",
+ Tcl_GetString(optionPtr), "\" option missing",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
switch (index) {
- case FONT_FAMILY:
- string = Tcl_GetStringFromObj(value, NULL);
- faPtr->family = Tk_GetUid(string);
+ case FONT_FAMILY: {
+ value = Tcl_GetString(valuePtr);
+ faPtr->family = Tk_GetUid(value);
break;
-
- case FONT_SIZE:
- if (Tcl_GetIntFromObj(interp, value, &n) != TCL_OK) {
+ }
+ case FONT_SIZE: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &n) != TCL_OK) {
return TCL_ERROR;
}
- faPtr->pointsize = n;
+ faPtr->size = n;
break;
-
- case FONT_WEIGHT:
- string = Tcl_GetStringFromObj(value, NULL);
- n = TkFindStateNum(interp, option, weightMap, string);
+ }
+ case FONT_WEIGHT: {
+ n = TkFindStateNumObj(interp, optionPtr, weightMap, valuePtr);
if (n == TK_FW_UNKNOWN) {
return TCL_ERROR;
}
faPtr->weight = n;
break;
-
- case FONT_SLANT:
- string = Tcl_GetStringFromObj(value, NULL);
- n = TkFindStateNum(interp, option, slantMap, string);
+ }
+ case FONT_SLANT: {
+ n = TkFindStateNumObj(interp, optionPtr, slantMap, valuePtr);
if (n == TK_FS_UNKNOWN) {
return TCL_ERROR;
}
faPtr->slant = n;
break;
-
- case FONT_UNDERLINE:
- if (Tcl_GetBooleanFromObj(interp, value, &n) != TCL_OK) {
+ }
+ case FONT_UNDERLINE: {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) {
return TCL_ERROR;
}
faPtr->underline = n;
break;
-
- case FONT_OVERSTRIKE:
- if (Tcl_GetBooleanFromObj(interp, value, &n) != TCL_OK) {
+ }
+ case FONT_OVERSTRIKE: {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &n) != TCL_OK) {
return TCL_ERROR;
}
faPtr->overstrike = n;
break;
+ }
}
}
return TCL_OK;
@@ -2515,18 +2889,19 @@ GetAttributeInfoObj(interp, faPtr, objPtr)
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. */
+ * returned. Otherwise information is
+ * returned for all options. */
{
- int i, index, start, end, num;
+ int i, index, start, end;
char *str;
- Tcl_Obj *newPtr;
+ Tcl_Obj *optionPtr, *valuePtr, *resultPtr;
+
+ resultPtr = Tcl_GetObjResult(interp);
start = 0;
end = FONT_NUMFIELDS;
if (objPtr != NULL) {
- if (Tcl_GetIndexFromObj(interp, objPtr, fontOpt, "option", 1,
+ if (Tcl_GetIndexFromObj(interp, objPtr, fontOpt, "option", TCL_EXACT,
&index) != TCL_OK) {
return TCL_ERROR;
}
@@ -2534,55 +2909,43 @@ GetAttributeInfoObj(interp, faPtr, objPtr)
end = index + 1;
}
+ valuePtr = NULL;
for (i = start; i < end; i++) {
- str = NULL;
- num = 0; /* Needed only to prevent compiler
- * warning. */
switch (i) {
case FONT_FAMILY:
str = faPtr->family;
- if (str == NULL) {
- str = "";
- }
+ valuePtr = Tcl_NewStringObj(str, ((str == NULL) ? 0 : -1));
break;
case FONT_SIZE:
- num = faPtr->pointsize;
+ 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_UNDERLINE:
- num = faPtr->underline;
+ valuePtr = Tcl_NewBooleanObj(faPtr->underline);
break;
case FONT_OVERSTRIKE:
- num = faPtr->overstrike;
+ valuePtr = Tcl_NewBooleanObj(faPtr->overstrike);
break;
}
- if (objPtr == NULL) {
- Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
- Tcl_NewStringObj(fontOpt[i], -1));
- if (str != NULL) {
- newPtr = Tcl_NewStringObj(str, -1);
- } else {
- newPtr = Tcl_NewIntObj(num);
- }
- Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
- newPtr);
- } else {
- if (str != NULL) {
- Tcl_SetStringObj(Tcl_GetObjResult(interp), str, -1);
- } else {
- Tcl_SetIntObj(Tcl_GetObjResult(interp), num);
- }
+ if (objPtr != NULL) {
+ Tcl_SetObjResult(interp, valuePtr);
+ return TCL_OK;
}
+ optionPtr = Tcl_NewStringObj(fontOpt[i], -1);
+ Tcl_ListObjAppendElement(NULL, resultPtr, optionPtr);
+ Tcl_ListObjAppendElement(NULL, resultPtr, valuePtr);
}
return TCL_OK;
}
@@ -2597,7 +2960,7 @@ GetAttributeInfoObj(interp, faPtr, objPtr)
*
* The string rep of the object can be one of the following forms:
* XLFD (see X documentation)
- * "Family [size [style] [style ...]]"
+ * "family [size] [style1 [style2 ...]"
* "-option value [-option value ...]"
*
* Results:
@@ -2614,20 +2977,25 @@ GetAttributeInfoObj(interp, faPtr, objPtr)
static int
ParseFontNameObj(interp, tkwin, objPtr, faPtr)
- Tcl_Interp *interp; /* Interp for error return. */
+ Tcl_Interp *interp; /* Interp for error return. Must not be
+ * NULL. */
Tk_Window tkwin; /* For display on which font is used. */
Tcl_Obj *objPtr; /* Parseable font description object. */
- TkFontAttributes *faPtr; /* Font attributes structure whose fields
- * are to be modified. Structure must already
- * be properly initialized. */
+ TkFontAttributes *faPtr; /* Filled with attributes parsed from font
+ * name. Any attributes that were not
+ * specified in font name are filled with
+ * default values. */
{
char *dash;
int objc, result, i, n;
Tcl_Obj **objv;
- TkXLFDAttributes xa;
+ Tcl_Obj *resultPtr;
char *string;
- string = Tcl_GetStringFromObj(objPtr, NULL);
+ TkInitFontAttributes(faPtr);
+ resultPtr = Tcl_GetObjResult(interp);
+
+ string = Tcl_GetString(objPtr);
if (*string == '-') {
/*
* This may be an XLFD or an "-option value" string.
@@ -2640,7 +3008,8 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
goto xlfd;
}
dash = strchr(string + 1, '-');
- if ((dash != NULL) && (!isspace(UCHAR(dash[-1])))) {
+ if ((dash != NULL)
+ && (!isspace(UCHAR(dash[-1])))) { /* INTL: ISO space */
goto xlfd;
}
@@ -2653,15 +3022,16 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
if (*string == '*') {
/*
- * This appears to be an XLFD.
+ * 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:
- xa.fa = *faPtr;
- result = TkParseXLFD(string, &xa);
+ result = TkFontParseXLFD(string, faPtr, NULL);
if (result == TCL_OK) {
- *faPtr = xa.fa;
- return result;
+ return TCL_OK;
}
}
@@ -2670,21 +3040,19 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
* "font size style" list.
*/
- if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
- return TCL_ERROR;
- }
- if (objc < 1) {
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "font \"", string,
- "\" doesn't exist", (char *) NULL);
+ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK)
+ || (objc < 1)) {
+ Tcl_AppendResult(interp, "font \"", string, "\" doesn't exist",
+ (char *) NULL);
return TCL_ERROR;
}
- faPtr->family = Tk_GetUid(Tcl_GetStringFromObj(objv[0], NULL));
+ faPtr->family = Tk_GetUid(Tcl_GetString(objv[0]));
if (objc > 1) {
if (Tcl_GetIntFromObj(interp, objv[1], &n) != TCL_OK) {
return TCL_ERROR;
}
- faPtr->pointsize = n;
+ faPtr->size = n;
}
i = 2;
@@ -2695,23 +3063,22 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
i = 0;
}
for ( ; i < objc; i++) {
- string = Tcl_GetStringFromObj(objv[i], NULL);
- n = TkFindStateNum(NULL, NULL, weightMap, string);
+ n = TkFindStateNumObj(NULL, NULL, weightMap, objv[i]);
if (n != TK_FW_UNKNOWN) {
faPtr->weight = n;
continue;
}
- n = TkFindStateNum(NULL, NULL, slantMap, string);
+ n = TkFindStateNumObj(NULL, NULL, slantMap, objv[i]);
if (n != TK_FS_UNKNOWN) {
faPtr->slant = n;
continue;
}
- n = TkFindStateNum(NULL, NULL, underlineMap, string);
+ n = TkFindStateNumObj(NULL, NULL, underlineMap, objv[i]);
if (n != 0) {
faPtr->underline = n;
continue;
}
- n = TkFindStateNum(NULL, NULL, overstrikeMap, string);
+ n = TkFindStateNumObj(NULL, NULL, overstrikeMap, objv[i]);
if (n != 0) {
faPtr->overstrike = n;
continue;
@@ -2721,9 +3088,8 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
* Unknown style.
*/
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "unknown font style \"", string, "\"",
- (char *) NULL);
+ Tcl_AppendResult(interp, "unknown font style \"",
+ Tcl_GetString(objv[i]), "\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -2732,7 +3098,67 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
/*
*---------------------------------------------------------------------------
*
- * TkParseXLFD --
+ * NewChunk --
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
+static LayoutChunk *
+NewChunk(layoutPtrPtr, maxPtr, start, numChars, curX, newX, y)
+ TextLayout **layoutPtrPtr;
+ int *maxPtr;
+ CONST char *start;
+ int numChars;
+ int curX;
+ int newX;
+ int y;
+{
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ int maxChunks;
+ size_t s;
+
+ layoutPtr = *layoutPtrPtr;
+ maxChunks = *maxPtr;
+ if (layoutPtr->numChunks == maxChunks) {
+ maxChunks *= 2;
+ s = sizeof(TextLayout) + ((maxChunks - 1) * sizeof(LayoutChunk));
+ layoutPtr = (TextLayout *) ckrealloc((char *) layoutPtr, s);
+
+ *layoutPtrPtr = layoutPtr;
+ *maxPtr = maxChunks;
+ }
+ chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks];
+ chunkPtr->start = start;
+ chunkPtr->numChars = numChars;
+ chunkPtr->numDisplayChars = numChars;
+ chunkPtr->x = curX;
+ chunkPtr->y = y;
+ chunkPtr->totalWidth = newX - curX;
+ chunkPtr->displayWidth = newX - curX;
+ layoutPtr->numChunks++;
+
+ return chunkPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontParseXLFD --
*
* Break up a fully specified XLFD into a set of font attributes.
*
@@ -2748,18 +3174,31 @@ ParseFontNameObj(interp, tkwin, objPtr, faPtr)
*/
int
-TkParseXLFD(string, xaPtr)
+TkFontParseXLFD(string, faPtr, xaPtr)
CONST char *string; /* Parseable font description string. */
- TkXLFDAttributes *xaPtr; /* XLFD attributes structure whose fields
- * are to be modified. Structure must already
- * be properly initialized. */
+ 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
+ * not specified in font name are filled with
+ * default values. May be NULL if such
+ * information is not desired. */
{
char *src;
CONST char *str;
int i, j;
char *field[XLFD_NUMFIELDS + 2];
Tcl_DString ds;
+ TkXLFDAttributes xa;
+ if (xaPtr == NULL) {
+ xaPtr = &xa;
+ }
+ TkInitFontAttributes(faPtr);
+ TkInitXLFDAttributes(xaPtr);
+
memset(field, '\0', sizeof(field));
str = string;
@@ -2773,27 +3212,32 @@ TkParseXLFD(string, xaPtr)
field[0] = src;
for (i = 0; *src != '\0'; src++) {
- if (isupper(UCHAR(*src))) {
- *src = tolower(UCHAR(*src));
+ if (!(*src & 0x90)
+ && isupper(UCHAR(*src))) { /* INTL: 7-bit ISO only. */
+ *src = tolower(UCHAR(*src)); /* INTL: 7-bit ISO only. */
}
if (*src == '-') {
i++;
- if (i > XLFD_NUMFIELDS) {
- break;
+ if (i == XLFD_NUMFIELDS) {
+ continue;
}
*src = '\0';
field[i] = src + 1;
+ if (i > XLFD_NUMFIELDS) {
+ break;
+ }
}
}
/*
- * An XLFD of the form -adobe-times-medium-r-*-12-*-* is pretty common,
+ * 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 up by one, so the number gets interpreted
+ * 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, but gives a syntax error under Windows".
+ * 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]))) {
@@ -2820,19 +3264,19 @@ TkParseXLFD(string, xaPtr)
}
if (FieldSpecified(field[XLFD_FAMILY])) {
- xaPtr->fa.family = Tk_GetUid(field[XLFD_FAMILY]);
+ faPtr->family = Tk_GetUid(field[XLFD_FAMILY]);
}
if (FieldSpecified(field[XLFD_WEIGHT])) {
- xaPtr->fa.weight = TkFindStateNum(NULL, NULL, xlfdWeightMap,
+ faPtr->weight = TkFindStateNum(NULL, NULL, xlfdWeightMap,
field[XLFD_WEIGHT]);
}
if (FieldSpecified(field[XLFD_SLANT])) {
xaPtr->slant = TkFindStateNum(NULL, NULL, xlfdSlantMap,
field[XLFD_SLANT]);
if (xaPtr->slant == TK_FS_ROMAN) {
- xaPtr->fa.slant = TK_FS_ROMAN;
+ faPtr->slant = TK_FS_ROMAN;
} else {
- xaPtr->fa.slant = TK_FS_ITALIC;
+ faPtr->slant = TK_FS_ITALIC;
}
}
if (FieldSpecified(field[XLFD_SETWIDTH])) {
@@ -2843,9 +3287,12 @@ TkParseXLFD(string, xaPtr)
/* XLFD_ADD_STYLE ignored. */
/*
- * Pointsize in tenths of a point, but treat it as tenths of a pixel.
+ * Pointsize in tenths of a point, but treat it as tenths of a pixel
+ * for historical compatibility.
*/
+ faPtr->size = 12;
+
if (FieldSpecified(field[XLFD_POINT_SIZE])) {
if (field[XLFD_POINT_SIZE][0] == '[') {
/*
@@ -2858,10 +3305,10 @@ TkParseXLFD(string, xaPtr)
* the purpose of, so I ignore them.
*/
- xaPtr->fa.pointsize = atoi(field[XLFD_POINT_SIZE] + 1);
+ faPtr->size = atoi(field[XLFD_POINT_SIZE] + 1);
} else if (Tcl_GetInt(NULL, field[XLFD_POINT_SIZE],
- &xaPtr->fa.pointsize) == TCL_OK) {
- xaPtr->fa.pointsize /= 10;
+ &faPtr->size) == TCL_OK) {
+ faPtr->size /= 10;
} else {
return TCL_ERROR;
}
@@ -2883,14 +3330,14 @@ TkParseXLFD(string, xaPtr)
* the purpose of, so I ignore them.
*/
- xaPtr->fa.pointsize = atoi(field[XLFD_PIXEL_SIZE] + 1);
+ faPtr->size = atoi(field[XLFD_PIXEL_SIZE] + 1);
} else if (Tcl_GetInt(NULL, field[XLFD_PIXEL_SIZE],
- &xaPtr->fa.pointsize) != TCL_OK) {
+ &faPtr->size) != TCL_OK) {
return TCL_ERROR;
}
}
- xaPtr->fa.pointsize = -xaPtr->fa.pointsize;
+ faPtr->size = -faPtr->size;
/* XLFD_RESOLUTION_X ignored. */
@@ -2900,14 +3347,9 @@ TkParseXLFD(string, xaPtr)
/* XLFD_AVERAGE_WIDTH ignored. */
- if (FieldSpecified(field[XLFD_REGISTRY])) {
- xaPtr->charset = TkFindStateNum(NULL, NULL, xlfdCharsetMap,
- field[XLFD_REGISTRY]);
+ if (FieldSpecified(field[XLFD_CHARSET])) {
+ xaPtr->charset = Tk_GetUid(field[XLFD_CHARSET]);
}
- if (FieldSpecified(field[XLFD_ENCODING])) {
- xaPtr->encoding = atoi(field[XLFD_ENCODING]);
- }
-
Tcl_DStringFree(&ds);
return TCL_OK;
}
@@ -2949,60 +3391,223 @@ FieldSpecified(field)
/*
*---------------------------------------------------------------------------
*
- * NewChunk --
+ * TkFontGetPixels --
*
- * Helper function for Tk_ComputeTextLayout(). Encapsulates a
- * measured set of characters in a chunk that can be quickly
- * drawn.
+ * Given a font size specification (as described in the TkFontAttributes
+ * structure) return the number of pixels it represents.
*
* Results:
- * A pointer to the new chunk in the text layout.
+ * As above.
*
* Side effects:
- * The text layout is reallocated to hold more chunks as necessary.
+ * None.
*
- * 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.
+ *---------------------------------------------------------------------------
+ */
+
+int
+TkFontGetPixels(tkwin, size)
+ Tk_Window tkwin; /* For point->pixel conversion factor. */
+ int size; /* Font size. */
+{
+ double d;
+
+ if (size < 0) {
+ return -size;
+ }
+
+ d = size * 25.4 / 72.0;
+ d *= WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ return (int) (d + 0.5);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkFontGetPoints --
+ *
+ * Given a font size specification (as described in the TkFontAttributes
+ * structure) return the number of points it represents.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
*
*---------------------------------------------------------------------------
*/
-static LayoutChunk *
-NewChunk(layoutPtrPtr, maxPtr, start, numChars, curX, newX, y)
- TextLayout **layoutPtrPtr;
- int *maxPtr;
- CONST char *start;
- int numChars;
- int curX;
- int newX;
- int y;
+
+int
+TkFontGetPoints(tkwin, size)
+ Tk_Window tkwin; /* For pixel->point conversion factor. */
+ int size; /* Font size. */
{
- TextLayout *layoutPtr;
- LayoutChunk *chunkPtr;
- int maxChunks;
- size_t s;
-
- layoutPtr = *layoutPtrPtr;
- maxChunks = *maxPtr;
- if (layoutPtr->numChunks == maxChunks) {
- maxChunks *= 2;
- s = sizeof(TextLayout) + ((maxChunks - 1) * sizeof(LayoutChunk));
- layoutPtr = (TextLayout *) ckrealloc((char *) layoutPtr, s);
+ double d;
- *layoutPtrPtr = layoutPtr;
- *maxPtr = maxChunks;
+ if (size >= 0) {
+ return size;
}
- chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks];
- chunkPtr->start = start;
- chunkPtr->numChars = numChars;
- chunkPtr->numDisplayChars = numChars;
- chunkPtr->x = curX;
- chunkPtr->y = y;
- chunkPtr->totalWidth = newX - curX;
- chunkPtr->displayWidth = newX - curX;
- layoutPtr->numChunks++;
- return chunkPtr;
+ d = -size * 72.0 / 25.4;
+ d *= WidthMMOfScreen(Tk_Screen(tkwin));
+ d /= WidthOfScreen(Tk_Screen(tkwin));
+ return (int) (d + 0.5);
}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * 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. */
+{
+ int i, j;
+ for (i = 0; fontAliases[i] != NULL; i++) {
+ for (j = 0; fontAliases[i][j] != NULL; j++) {
+ if (strcasecmp(faceName, fontAliases[i][j]) == 0) {
+ return fontAliases[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+char ***
+TkFontGetFallbacks()
+{
+ return fontFallbacks;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkFontGetGlobalClass --
+ *
+ * Get the list of fonts to try if the requested font name does not
+ * exist and no fallbacks for that font name could be used either.
+ * The names in this list are considered preferred over all the other
+ * font names in the system when looking for a last-ditch fallback.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+char **
+TkFontGetGlobalClass()
+{
+ return globalFontClass;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * TkFontGetSymbolClass --
+ *
+ * Get the list of fonts that are symbolic; used if the operating
+ * system cannot apriori identify symbolic fonts on its own.
+ *
+ * Results:
+ * As above.
+ *
+ * Side effects:
+ * None.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+char **
+TkFontGetSymbolClass()
+{
+ return symbolClass;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkDebugFont --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkFont *fontPtr;
+ Tcl_HashEntry *hashPtr;
+ Tcl_Obj *resultPtr, *objPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(
+ &((TkWindow *) tkwin)->mainPtr->fontInfoPtr->fontCache, name);
+ if (hashPtr != NULL) {
+ fontPtr = (TkFont *) Tcl_GetHashValue(hashPtr);
+ if (fontPtr == NULL) {
+ 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_ListObjAppendElement(NULL, resultPtr, objPtr);
+ }
+ }
+ return resultPtr;
+}
diff --git a/generic/tkFont.h b/generic/tkFont.h
index 758c329..05b116e 100644
--- a/generic/tkFont.h
+++ b/generic/tkFont.h
@@ -5,12 +5,12 @@
* specific parts of the font package. This information is not
* visible outside of the font package.
*
- * Copyright (c) 1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkFont.h 1.11 97/05/07 14:44:13
+ * SCCS: @(#) tkFont.h 1.16 97/12/23 15:00:07
*/
#ifndef _TKFONT
@@ -23,8 +23,9 @@
*/
typedef struct TkFontAttributes {
- Tk_Uid family; /* Font family. The most important field. */
- int pointsize; /* Pointsize of font, 0 for default size, or
+ 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. */
@@ -86,13 +87,25 @@ typedef struct TkFont {
* Fields used and maintained exclusively by generic code.
*/
- int refCount; /* Number of users of the 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. */
+ int objRefCount; /* The number of Tcl objects that reference
+ * this structure. */
Tcl_HashEntry *cacheHashPtr;/* Entry in font cache for this structure,
* used when deleting it. */
Tcl_HashEntry *namedHashPtr;/* Pointer to hash table entry that
* corresponds to the named font that the
* tkfont was based on, or NULL if the 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
@@ -101,7 +114,7 @@ typedef struct TkFont {
* underlines on a non-underlined font). */
/*
- * Fields in the generic font structure that are filled in by
+ * Fields used in the generic code that are filled in by
* platform-specific code.
*/
@@ -116,6 +129,11 @@ typedef struct TkFont {
* 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. */
} TkFont;
/*
@@ -125,16 +143,12 @@ typedef struct TkFont {
*/
typedef struct TkXLFDAttributes {
- TkFontAttributes fa; /* Standard set of font attributes. */
Tk_Uid foundry; /* The foundry of the font. */
int slant; /* The tristate value for the slant, which
* is significant under X. */
int setwidth; /* The proportionate width, see below for
* definition. */
- int charset; /* The character set encoding (the glyph
- * family), see below for definition. */
- int encoding; /* Variations within a charset for the
- * glyphs above character 127. */
+ Tk_Uid charset; /* The actual charset string. */
} TkXLFDAttributes;
/*
@@ -150,15 +164,6 @@ typedef struct TkXLFDAttributes {
* stored in the setwidth field. */
/*
- * Possible values for the "charset" field in a TkXLFDAttributes structure.
- * The charset is the set of glyphs that are used in the font.
- */
-
-#define TK_CS_NORMAL 0
-#define TK_CS_SYMBOL 1
-#define TK_CS_OTHER 2
-
-/*
* The following defines specify the meaning of the fields in a fully
* qualified XLFD.
*/
@@ -175,28 +180,33 @@ typedef struct TkXLFDAttributes {
#define XLFD_RESOLUTION_Y 9
#define XLFD_SPACING 10
#define XLFD_AVERAGE_WIDTH 11
-#define XLFD_REGISTRY 12
-#define XLFD_ENCODING 13
-#define XLFD_NUMFIELDS 14 /* Number of fields in XLFD. */
+#define XLFD_CHARSET 12
+#define XLFD_NUMFIELDS 13 /* Number of fields in XLFD. */
/*
- * Exported from generic code to platform-specific code.
+ * Low-level API exported by generic code to platform-specific code.
*/
-EXTERN int TkCreateNamedFont _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, CONST char *name,
- TkFontAttributes *faPtr));
-EXTERN void TkInitFontAttributes _ANSI_ARGS_((
- TkFontAttributes *faPtr));
-EXTERN int TkParseXLFD _ANSI_ARGS_((CONST char *string,
- TkXLFDAttributes *xaPtr));
+#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));
/*
- * Common APIs exported to tkFont.c from all platform-specific
- * implementations.
+ * 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));
diff --git a/generic/tkFrame.c b/generic/tkFrame.c
index a11f566..0709a69 100644
--- a/generic/tkFrame.c
+++ b/generic/tkFrame.c
@@ -7,12 +7,12 @@
* attributes.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkFrame.c 1.82 97/08/08 17:26:26
+ * SCCS: @(#) tkFrame.c 1.83 97/11/07 21:18:51
*/
#include "default.h"
@@ -441,7 +441,7 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
if (toplevel) {
Tcl_DoWhenIdle(MapFrame, (ClientData) framePtr);
}
- interp->result = Tk_PathName(new);
+ Tcl_SetResult(interp, Tk_PathName(new), TCL_STATIC);
return TCL_OK;
error:
@@ -597,7 +597,7 @@ DestroyFrame(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as text string, colors, font,
diff --git a/generic/tkGet.c b/generic/tkGet.c
index 56258a6..a980199 100644
--- a/generic/tkGet.c
+++ b/generic/tkGet.c
@@ -8,18 +8,27 @@
* files.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkGet.c 1.13 96/04/26 10:25:46
+ * SCCS: @(#) tkGet.c 1.15 97/12/22 11:04:29
*/
#include "tkInt.h"
#include "tkPort.h"
/*
+ * The following tables defines the string values for reliefs, which are
+ * used by Tk_GetAnchorFromObj and Tk_GetJustifyFromObj.
+ */
+
+static char *anchorStrings[] = {"n", "ne", "e", "se", "s", "sw", "w", "nw",
+ "center", (char *) NULL};
+static char *justifyStrings[] = {"left", "right", "center", (char *) NULL};
+
+/*
* The hash table below is used to keep track of all the Tk_Uids created
* so far.
*/
@@ -28,6 +37,43 @@ static Tcl_HashTable uidTable;
static int initialized = 0;
/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetAnchorFromObj --
+ *
+ * Return a Tk_Anchor value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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
+ * corresponds to the string value of
+ * objPtr. */
+{
+ int index, code;
+
+ code = Tcl_GetIndexFromObj(interp, objPtr, anchorStrings, "anchor", 0,
+ &index);
+ if (code == TCL_OK) {
+ *anchorPtr = (Tk_Anchor) index;
+ }
+ return code;
+}
+
+/*
*--------------------------------------------------------------
*
* Tk_GetAnchor --
@@ -39,7 +85,7 @@ static int initialized = 0;
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -155,7 +201,7 @@ Tk_NameOfAnchor(anchor)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -237,7 +283,7 @@ Tk_NameOfJoinStyle(join)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -308,6 +354,43 @@ Tk_NameOfCapStyle(cap)
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetJustifyFromObj --
+ *
+ * Return a Tk_Justify value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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
+ * corresponds to the string value of
+ * objPtr. */
+{
+ int index, code;
+
+ code = Tcl_GetIndexFromObj(interp, objPtr, justifyStrings,
+ "justification", 0, &index);
+ if (code == TCL_OK) {
+ *justifyPtr = (Tk_Justify) index;
+ }
+ return code;
+}
+
+/*
*--------------------------------------------------------------
*
* Tk_GetJustify --
@@ -319,7 +402,7 @@ Tk_NameOfCapStyle(cap)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -439,7 +522,7 @@ Tk_GetUid(string)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -515,7 +598,7 @@ Tk_GetScreenMM(interp, tkwin, string, doublePtr)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
diff --git a/generic/tkGrab.c b/generic/tkGrab.c
index 869e0b3..b088563 100644
--- a/generic/tkGrab.c
+++ b/generic/tkGrab.c
@@ -4,12 +4,12 @@
* This file provides procedures that implement grabs for Tk.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkGrab.c 1.52 97/03/21 11:14:34
+ * SCCS: @(#) tkGrab.c 1.53 97/11/07 21:19:38
*/
#include "tkPort.h"
@@ -238,7 +238,8 @@ Tk_GrabCmd(clientData, interp, argc, argv)
}
dispPtr = ((TkWindow *) tkwin)->dispPtr;
if (dispPtr->eventualGrabWinPtr != NULL) {
- interp->result = dispPtr->eventualGrabWinPtr->pathName;
+ Tcl_SetResult(interp, dispPtr->eventualGrabWinPtr->pathName,
+ TCL_STATIC);
}
} else {
for (dispPtr = tkDisplayList; dispPtr != NULL;
@@ -303,11 +304,11 @@ Tk_GrabCmd(clientData, interp, argc, argv)
}
dispPtr = winPtr->dispPtr;
if (dispPtr->eventualGrabWinPtr != winPtr) {
- interp->result = "none";
+ Tcl_SetResult(interp, "none", TCL_STATIC);
} else if (dispPtr->grabFlags & GRAB_GLOBAL) {
- interp->result = "global";
+ Tcl_SetResult(interp, "global", TCL_STATIC);
} else {
- interp->result = "local";
+ Tcl_SetResult(interp, "local", TCL_STATIC);
}
} else {
Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1],
@@ -329,7 +330,7 @@ Tk_GrabCmd(clientData, interp, argc, argv)
* 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 interp->result will hold an error message.
+ * and the interp's result will hold an error message.
*
* Side effects:
* Once this call completes successfully, no window outside the
@@ -366,7 +367,8 @@ Tk_Grab(interp, tkwin, grabGlobal)
}
if (dispPtr->eventualGrabWinPtr->mainPtr != winPtr->mainPtr) {
alreadyGrabbed:
- interp->result = "grab failed: another application has grab";
+ Tcl_SetResult(interp, "grab failed: another application has grab",
+ TCL_STATIC);
return TCL_ERROR;
}
Tk_Ungrab((Tk_Window) dispPtr->eventualGrabWinPtr);
@@ -432,15 +434,18 @@ Tk_Grab(interp, tkwin, grabGlobal)
if (grabResult != 0) {
grabError:
if (grabResult == GrabNotViewable) {
- interp->result = "grab failed: window not viewable";
+ Tcl_SetResult(interp, "grab failed: window not viewable",
+ TCL_STATIC);
} else if (grabResult == AlreadyGrabbed) {
goto alreadyGrabbed;
} else if (grabResult == GrabFrozen) {
- interp->result = "grab failed: keyboard or pointer frozen";
+ Tcl_SetResult(interp,
+ "grab failed: keyboard or pointer frozen", TCL_STATIC);
} else if (grabResult == GrabInvalidTime) {
- interp->result = "grab failed: invalid time";
+ Tcl_SetResult(interp, "grab failed: invalid time",
+ TCL_STATIC);
} else {
- char msg[100];
+ char msg[64 + TCL_INTEGER_SPACE];
sprintf(msg, "grab failed for unknown reason (code %d)",
grabResult);
diff --git a/generic/tkGrid.c b/generic/tkGrid.c
index ea11a01..f21782f 100644
--- a/generic/tkGrid.c
+++ b/generic/tkGrid.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkGrid.c 1.39 97/10/10 10:12:03
+ * SCCS: @(#) tkGrid.c 1.40 97/11/07 21:18:05
*/
#include "tkInt.h"
@@ -314,6 +314,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
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 */
+ char buf[TCL_INTEGER_SPACE * 4];
if (argc!=3 && argc != 5 && argc != 7) {
Tcl_AppendResult(interp, "wrong number of arguments: ",
@@ -351,7 +352,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
gridPtr = masterPtr->masterDataPtr;
if (gridPtr == NULL) {
- sprintf(interp->result, "%d %d %d %d",0,0,0,0);
+ Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC);
return(TCL_OK);
}
@@ -360,7 +361,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
endY = MAX(gridPtr->rowEnd, gridPtr->rowMax);
if ((endX == 0) || (endY == 0)) {
- sprintf(interp->result, "%d %d %d %d",0,0,0,0);
+ Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC);
return(TCL_OK);
}
if (argc == 3) {
@@ -406,8 +407,9 @@ Tk_GridCmd(clientData, interp, argc, argv)
height = gridPtr->rowPtr[row2].offset - y;
}
- sprintf(interp->result, "%d %d %d %d",
- x + gridPtr->startX, y + gridPtr->startY, width, height);
+ sprintf(buf, "%d %d %d %d", x + gridPtr->startX, y + gridPtr->startY,
+ width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) {
if (argv[2][0] != '.') {
Tcl_AppendResult(interp, "bad argument \"", argv[2],
@@ -456,7 +458,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
} else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) {
register Gridder *slavePtr;
Tk_Window slave;
- char buffer[70];
+ char buffer[64 + TCL_INTEGER_SPACE * 4];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -469,7 +471,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
}
slavePtr = GetGrid(slave);
if (slavePtr->masterPtr == NULL) {
- interp->result[0] = '\0';
+ Tcl_ResetResult(interp);
return TCL_OK;
}
@@ -491,6 +493,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
int x, y; /* Offset in pixels, from edge of parent. */
int i, j; /* Corresponding column and row indeces. */
int endX, endY; /* end of grid */
+ char buf[TCL_INTEGER_SPACE * 2];
if (argc != 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -512,7 +515,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
masterPtr = GetGrid(master);
if (masterPtr->masterDataPtr == NULL) {
- sprintf(interp->result, "%d %d", -1, -1);
+ Tcl_SetResult(interp, "-1 -1", TCL_STATIC);
return TCL_OK;
}
gridPtr = masterPtr->masterDataPtr;
@@ -551,7 +554,8 @@ Tk_GridCmd(clientData, interp, argc, argv)
}
}
- sprintf(interp->result, "%d %d", i, j);
+ sprintf(buf, "%d %d", i, j);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'p') && (strncmp(argv[1], "propagate", length) == 0)) {
Tk_Window master;
int propagate;
@@ -568,7 +572,9 @@ Tk_GridCmd(clientData, interp, argc, argv)
}
masterPtr = GetGrid(master);
if (argc == 3) {
- interp->result = (masterPtr->flags & DONT_PROPAGATE) ? "0" : "1";
+ Tcl_SetResult(interp,
+ ((masterPtr->flags & DONT_PROPAGATE) ? "0" : "1"),
+ TCL_STATIC);
return TCL_OK;
}
if (Tcl_GetBoolean(interp, argv[3], &propagate) != TCL_OK) {
@@ -606,13 +612,16 @@ Tk_GridCmd(clientData, interp, argc, argv)
masterPtr = GetGrid(master);
if (masterPtr->masterDataPtr != NULL) {
+ char buf[TCL_INTEGER_SPACE * 2];
+
SetGridSize(masterPtr);
gridPtr = masterPtr->masterDataPtr;
- sprintf(interp->result, "%d %d",
- MAX(gridPtr->columnEnd, gridPtr->columnMax),
- MAX(gridPtr->rowEnd, gridPtr->rowMax));
+ sprintf(buf, "%d %d",
+ MAX(gridPtr->columnEnd, gridPtr->columnMax),
+ MAX(gridPtr->rowEnd, gridPtr->rowMax));
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else {
- sprintf(interp->result, "%d %d",0, 0);
+ Tcl_SetResult(interp, "0 0", TCL_STATIC);
}
} else if ((c == 's') && (strncmp(argv[1], "slaves", length) == 0)
&& (length > 1)) {
@@ -754,12 +763,16 @@ Tk_GridCmd(clientData, interp, argc, argv)
Tcl_Free((char *)argvPtr);
}
if ((argc == 4) && (ok == TCL_OK)) {
- sprintf(interp->result,"-minsize %d -pad %d -weight %d",
+ char buf[64 + TCL_INTEGER_SPACE * 3];
+
+ sprintf(buf, "-minsize %d -pad %d -weight %d",
slotPtr[slot].minSize,slotPtr[slot].pad,
slotPtr[slot].weight);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return (TCL_OK);
} else if (argc == 4) {
- sprintf(interp->result,"-minsize %d -pad %d -weight %d", 0,0,0);
+ Tcl_SetResult(interp, "-minsize 0 -pad 0 -weight 0",
+ TCL_STATIC);
return (TCL_OK);
}
@@ -780,8 +793,12 @@ Tk_GridCmd(clientData, interp, argc, argv)
}
if (strncmp(argv[i], "-minsize", length) == 0) {
if (argc == 5) {
- int value = ok == TCL_OK ? slotPtr[slot].minSize : 0;
- sprintf(interp->result,"%d",value);
+ char buf[TCL_INTEGER_SPACE];
+ int value;
+
+ value = (ok == TCL_OK) ? slotPtr[slot].minSize : 0;
+ sprintf(buf, "%d", value);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if (Tk_GetPixels(interp, master, argv[i+1], &size)
!= TCL_OK) {
Tcl_Free((char *)argvPtr);
@@ -793,8 +810,12 @@ Tk_GridCmd(clientData, interp, argc, argv)
else if (strncmp(argv[i], "-weight", length) == 0) {
int wt;
if (argc == 5) {
- int value = ok == TCL_OK ? slotPtr[slot].weight : 0;
- sprintf(interp->result,"%d",value);
+ char buf[TCL_INTEGER_SPACE];
+ int value;
+
+ value = (ok == TCL_OK) ? slotPtr[slot].weight : 0;
+ sprintf(buf, "%d", value);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if (Tcl_GetInt(interp, argv[i+1], &wt) != TCL_OK) {
Tcl_Free((char *)argvPtr);
return TCL_ERROR;
@@ -809,8 +830,12 @@ Tk_GridCmd(clientData, interp, argc, argv)
}
else if (strncmp(argv[i], "-pad", length) == 0) {
if (argc == 5) {
- int value = ok == TCL_OK ? slotPtr[slot].pad : 0;
- sprintf(interp->result,"%d",value);
+ char buf[TCL_INTEGER_SPACE];
+ int value;
+
+ value = (ok == TCL_OK) ? slotPtr[slot].pad : 0;
+ sprintf(buf, "%d", value);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if (Tk_GetPixels(interp, master, argv[i+1], &size)
!= TCL_OK) {
Tcl_Free((char *)argvPtr);
@@ -2107,7 +2132,7 @@ GridStructureProc(clientData, eventPtr)
*
* Results:
* TCL_OK is returned if all went well. Otherwise, TCL_ERROR is
- * returned and interp->result is set to contain an error message.
+ * returned and the interp's result is set to contain an error message.
*
* Side effects:
* Slave windows get taken over by the grid.
@@ -2281,7 +2306,8 @@ ConfigureSlaves(interp, tkwin, argc, argv)
return TCL_ERROR;
}
if (other == slave) {
- sprintf(interp->result,"Window can't be managed in itself");
+ Tcl_SetResult(interp, "Window can't be managed in itself",
+ TCL_STATIC);
return TCL_ERROR;
}
masterPtr = GetGrid(other);
diff --git a/generic/tkImage.c b/generic/tkImage.c
index 251fe30..47a8c1b 100644
--- a/generic/tkImage.c
+++ b/generic/tkImage.c
@@ -6,12 +6,12 @@
* widgets.
*
* Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkImage.c 1.15 97/10/09 09:57:50
+ * SCCS: @(#) tkImage.c 1.16 97/11/07 21:17:09
*/
#include "tkInt.h"
@@ -146,7 +146,7 @@ Tk_ImageCmd(clientData, interp, argc, argv)
Image *imagePtr;
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- char idString[30], *name;
+ char idString[16 + TCL_INTEGER_SPACE], *name;
static int id = 0;
if (argc < 2) {
@@ -248,7 +248,9 @@ Tk_ImageCmd(clientData, interp, argc, argv)
imagePtr->instanceData = (*typePtr->getProc)(
imagePtr->tkwin, masterPtr->masterData);
}
- interp->result = Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr);
+ Tcl_SetResult(interp,
+ Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),
+ TCL_STATIC);
} else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
for (i = 2; i < argc; i++) {
hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[i]);
@@ -261,6 +263,8 @@ Tk_ImageCmd(clientData, interp, argc, argv)
DeleteImage(masterPtr);
}
} else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) {
+ char buf[TCL_INTEGER_SPACE];
+
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" height name\"", (char *) NULL);
@@ -273,7 +277,8 @@ Tk_ImageCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- sprintf(interp->result, "%d", masterPtr->height);
+ sprintf(buf, "%d", masterPtr->height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) {
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -299,7 +304,7 @@ Tk_ImageCmd(clientData, interp, argc, argv)
}
masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
if (masterPtr->typePtr != NULL) {
- interp->result = masterPtr->typePtr->name;
+ Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);
}
} else if ((c == 't') && (strcmp(argv[1], "types") == 0)) {
if (argc != 2) {
@@ -312,6 +317,8 @@ Tk_ImageCmd(clientData, interp, argc, argv)
Tcl_AppendElement(interp, typePtr->name);
}
} else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) {
+ char buf[TCL_INTEGER_SPACE];
+
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" width name\"", (char *) NULL);
@@ -324,7 +331,8 @@ Tk_ImageCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- sprintf(interp->result, "%d", masterPtr->width);
+ sprintf(buf, "%d", masterPtr->width);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be create, delete, height, names, type, types,",
@@ -416,7 +424,7 @@ Tk_NameOfImage(imageMaster)
* 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 interp->result.
+ * left in the interp's result.
*
* Side effects:
* Tk records the fact that the widget is using the image, and
diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c
index f8a1d6e..4a09afc 100644
--- a/generic/tkImgBmap.c
+++ b/generic/tkImgBmap.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkImgBmap.c 1.33 97/07/31 09:08:22
+ * SCCS: @(#) tkImgBmap.c 1.34 97/11/07 21:17:15
*/
#include "tkInt.h"
@@ -227,7 +227,7 @@ ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)
*
* Results:
* A standard Tcl return value. If TCL_ERROR is returned then
- * an error message is left in masterPtr->interp->result.
+ * an error message is left in the masterPtr->interp's result.
*
* Side effects:
* Existing instances of the image will be redisplayed to match
@@ -278,7 +278,8 @@ ImgBmapConfigureMaster(masterPtr, argc, argv, flags)
if ((masterPtr->maskFileString != NULL)
|| (masterPtr->maskDataString != NULL)) {
if (masterPtr->data == NULL) {
- masterPtr->interp->result = "can't have mask without bitmap";
+ Tcl_SetResult(masterPtr->interp, "can't have mask without bitmap",
+ TCL_STATIC);
return TCL_ERROR;
}
masterPtr->maskData = TkGetBitmapData(masterPtr->interp,
@@ -291,7 +292,8 @@ ImgBmapConfigureMaster(masterPtr, argc, argv, flags)
|| (maskHeight != masterPtr->height)) {
ckfree(masterPtr->maskData);
masterPtr->maskData = NULL;
- masterPtr->interp->result = "bitmap and mask have different sizes";
+ Tcl_SetResult(masterPtr->interp,
+ "bitmap and mask have different sizes", TCL_STATIC);
return TCL_ERROR;
}
}
@@ -451,7 +453,7 @@ ImgBmapConfigureInstance(instancePtr)
* *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 interp->result.
+ * left in the interp's result.
*
* Side effects:
* A bitmap is created.
@@ -615,7 +617,7 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr,
return data;
error:
- interp->result = "format error in bitmap data";
+ Tcl_SetResult(interp, "format error in bitmap data", TCL_STATIC);
errorCleanup:
if (data != NULL) {
ckfree(data);
@@ -725,9 +727,8 @@ ImgBmapCmd(clientData, interp, argc, argv)
size_t length;
if (argc < 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s option ?arg arg ...?\"",
- argv[0]);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " option ?arg arg ...?\"", (char *) NULL);
return TCL_ERROR;
}
c = argv[1][0];
diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c
index a2ad081..34ea255 100644
--- a/generic/tkImgGIF.c
+++ b/generic/tkImgGIF.c
@@ -27,7 +27,7 @@
* | provided "as is" without express or implied warranty. |
* +-------------------------------------------------------------------+
*
- * SCCS: @(#) tkImgGIF.c 1.19 97/08/13 15:23:45
+ * SCCS: @(#) tkImgGIF.c 1.20 97/11/07 21:20:21
*/
/*
@@ -184,7 +184,7 @@ FileMatchGIF(chan, fileName, formatString, widthPtr, heightPtr)
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
+ * 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
@@ -287,12 +287,14 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
*/
if (Fread(buf, 1, 1, chan) != 1) {
- interp->result =
- "error reading extension function code in GIF image";
+ Tcl_SetResult(interp,
+ "error reading extension function code in GIF image",
+ TCL_STATIC);
goto error;
}
if (DoExtension(chan, buf[0], &transparent) < 0) {
- interp->result = "error reading extension in GIF image";
+ Tcl_SetResult(interp, "error reading extension in GIF image",
+ TCL_STATIC);
goto error;
}
continue;
@@ -306,7 +308,9 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
}
if (Fread(buf, 1, 9, chan) != 9) {
- interp->result = "couldn't read left/top/width/height in GIF image";
+ Tcl_SetResult(interp,
+ "couldn't read left/top/width/height in GIF image",
+ TCL_STATIC);
goto error;
}
@@ -418,7 +422,7 @@ StringMatchGIF(string, formatString, widthPtr, heightPtr)
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
+ * then an error message is left in the interp's result.
*
* Side effects:
* new data is added to the image given by imageHandle. This
@@ -619,7 +623,7 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
}
if (LWZReadByte(chan, 1, c) < 0) {
- interp->result = "format error in GIF image";
+ Tcl_SetResult(interp, "format error in GIF image", TCL_STATIC);
return TCL_ERROR;
}
diff --git a/generic/tkImgPPM.c b/generic/tkImgPPM.c
index 3a54003..8beaf8d 100644
--- a/generic/tkImgPPM.c
+++ b/generic/tkImgPPM.c
@@ -13,7 +13,7 @@
* Department of Computer Science,
* Australian National University.
*
- * SCCS: @(#) tkImgPPM.c 1.16 97/10/28 14:51:46
+ * SCCS: @(#) tkImgPPM.c 1.17 97/11/07 21:18:55
*/
#include "tkInt.h"
@@ -110,7 +110,7 @@ FileMatchPPM(chan, fileName, formatString, widthPtr, heightPtr)
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
+ * 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
@@ -151,7 +151,7 @@ FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
return TCL_ERROR;
}
if ((maxIntensity <= 0) || (maxIntensity >= 256)) {
- char buffer[30];
+ char buffer[TCL_INTEGER_SPACE];
sprintf(buffer, "%d", maxIntensity);
Tcl_AppendResult(interp, "PPM image file \"", fileName,
@@ -243,7 +243,7 @@ FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
*
* Results:
* A standard TCL completion code. If TCL_ERROR is returned
- * then an error message is left in interp->result.
+ * then an error message is left in the interp's result.
*
* Side effects:
* Data is written to the file given by "fileName".
@@ -262,7 +262,7 @@ FileWritePPM(interp, fileName, formatString, blockPtr)
int w, h;
int greenOffset, blueOffset, nBytes;
unsigned char *pixelPtr, *pixLinePtr;
- char header[30];
+ char header[16 + TCL_INTEGER_SPACE * 2];
chan = Tcl_OpenFileChannel(interp, fileName, "w", 0666);
if (chan == NULL) {
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index 86fbf80..8a89b48 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -15,7 +15,7 @@
* Department of Computer Science,
* Australian National University.
*
- * SCCS: @(#) tkImgPhoto.c 1.60 97/08/08 11:32:46
+ * SCCS: @(#) tkImgPhoto.c 1.61 97/11/07 21:19:00
*/
#include "tkInt.h"
@@ -522,7 +522,6 @@ ImgPhotoCmd(clientData, interp, argc, argv)
unsigned char *pixelPtr;
Tk_PhotoImageBlock block;
Tk_Window tkwin;
- char string[16];
XColor color;
Tk_PhotoImageFormat *imageFormat;
int imageWidth, imageHeight;
@@ -678,6 +677,8 @@ ImgPhotoCmd(clientData, interp, argc, argv)
* photo get command - first parse and check parameters.
*/
+ char string[TCL_INTEGER_SPACE * 3];
+
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" get x y\"", (char *) NULL);
@@ -1254,7 +1255,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
*
* Results:
* A standard Tcl return value. If TCL_ERROR is returned then
- * an error message is left in masterPtr->interp->result.
+ * an error message is left in the masterPtr->interp's result.
*
* Side effects:
* Existing instances of the image will be redisplayed to match
@@ -1597,7 +1598,7 @@ ImgPhotoGet(tkwin, masterData)
int mono, nRed, nGreen, nBlue;
XVisualInfo visualInfo, *visInfoPtr;
XRectangle validBox;
- char buf[16];
+ char buf[TCL_INTEGER_SPACE * 3];
int numVisuals;
XColor *white, *black;
XGCValues gcValues;
diff --git a/generic/tkInitScript.h b/generic/tkInitScript.h
index e86d16e..3809a01 100644
--- a/generic/tkInitScript.h
+++ b/generic/tkInitScript.h
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkInitScript.h 1.3 97/08/11 19:12:28
+ * SCCS: @(#) tkInitScript.h 1.4 98/01/09 13:37:34
*/
@@ -22,10 +22,15 @@
* initialization.
* When called from a safe interpreter, it does not use file exists.
* we don't use pwd either because of safe interpreters.
+ *
+ * We leave the door open to the application by using an existing
+ * tkInit proc which if it exists is responsible for finding and sourcing
+ * tk.tcl themselves. With that, an application that wish to ignore
+ * the env(TK_LIBRARY) or have special initialization need can do it.
*/
-static char initScript[] =
-"proc tkInit {} {\n\
+static char initScript[] = "if {[info proc tkInit]==\"\"} {\n\
+ proc tkInit {} {\n\
global tk_library tk_version tk_patchLevel env errorInfo\n\
rename tkInit {}\n\
set errors \"\"\n\
@@ -68,6 +73,7 @@ static char initScript[] =
append msg \"$errors\n\n\"\n\
append msg \"This probably means that Tk wasn't installed properly.\n\"\n\
error $msg\n\
+ }\n\
}\n\
tkInit";
diff --git a/generic/tkInt.h b/generic/tkInt.h
index b5dd92d..cf9eb5e 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkInt.h 1.204 97/10/31 09:55:20
+ * SCCS: @(#) tkInt.h 1.212 98/02/10 10:34:03
*/
#ifndef _TKINT
@@ -81,11 +81,30 @@ typedef struct TkClassProcs {
typedef struct TkCursor {
Tk_Cursor cursor; /* System specific identifier for cursor. */
- int refCount; /* Number of active uses of cursor. */
+ Display *display; /* Display containing cursor. Needed for
+ * 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_GetPreserve).
+ * 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). */
+ 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. */
} TkCursor;
/*
@@ -409,10 +428,10 @@ typedef struct TkMainInfo {
/* Used in conjunction with "bind" command
* to bind events to Tcl commands. */
TkBindInfo bindInfo; /* Information used by tkBind.c on a per
- * interpreter basis. */
+ * application basis. */
struct TkFontInfo *fontInfoPtr;
- /* Hold named font tables. Used only by
- * tkFont.c. */
+ /* Information used by tkFont.c on a per
+ * application basis. */
/*
* Information used only by tkFocus.c and tk*Embed.c:
@@ -744,6 +763,7 @@ EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData,
int toplevel, char *appName));
EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp *interp,
char *screenName, char *baseName));
+EXTERN int TkCreateMenuCmd _ANSI_ARGS_((Tcl_Interp *interp));
#ifndef TkCreateRegion
EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void));
#endif
@@ -751,6 +771,18 @@ EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay *dispPtr));
EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo *mainPtr));
+EXTERN Tcl_Obj * TkDebugBitmap _ANSI_ARGS_(( Tk_Window tkwin,
+ char *name));
+EXTERN Tcl_Obj * TkDebugBorder _ANSI_ARGS_(( Tk_Window tkwin,
+ char *name));
+EXTERN Tcl_Obj * TkDebugCursor _ANSI_ARGS_(( Tk_Window tkwin,
+ char *name));
+EXTERN Tcl_Obj * TkDebugColor _ANSI_ARGS_(( Tk_Window tkwin,
+ char *name));
+EXTERN Tcl_Obj * TkDebugConfig _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_OptionTable table));
+EXTERN Tcl_Obj * TkDebugFont _ANSI_ARGS_(( Tk_Window tkwin,
+ char *name));
#ifndef TkDestroyRegion
EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn));
#endif
@@ -767,6 +799,9 @@ EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas,
EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *option, CONST TkStateMap *mapPtr,
CONST char *strKey));
+EXTERN int TkFindStateNumObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *optionPtr, CONST TkStateMap *mapPtr,
+ Tcl_Obj *keyPtr));
EXTERN char * TkFindStateString _ANSI_ARGS_((
CONST TkStateMap *mapPtr, int numKey));
EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
@@ -777,7 +812,6 @@ EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow *winPtr,
EXTERN void TkFontPkgInit _ANSI_ARGS_((TkMainInfo *mainPtr));
EXTERN void TkFontPkgFree _ANSI_ARGS_((TkMainInfo *mainPtr));
EXTERN void TkFreeBindingTags _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkFreeCursor _ANSI_ARGS_((TkCursor *cursorPtr));
EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay *dispPtr,
Window w));
EXTERN void TkGenerateActivateEvents _ANSI_ARGS_((
@@ -802,14 +836,13 @@ EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp *interp,
EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], double p2[],
double p3[], double width, double m1[],
double m2[]));
-#ifndef TkGetNativeProlog
-EXTERN int TkGetNativeProlog _ANSI_ARGS_((Tcl_Interp *interp));
-#endif
EXTERN void TkGetPointerCoords _ANSI_ARGS_((Tk_Window tkwin,
int *xPtr, int *yPtr));
-EXTERN int TkGetProlog _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN void TkGetServerInfo _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin));
+EXTERN int TkGetWindowFromObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr,
+ Tk_Window *windowPtr));
EXTERN void TkGrabDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
EXTERN int TkGrabState _ANSI_ARGS_((TkWindow *winPtr));
EXTERN TkWindow * TkIDToWindow _ANSI_ARGS_((Window window,
@@ -867,6 +900,7 @@ EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void));
#endif
EXTERN void TkpDisplayWarning _ANSI_ARGS_((char *msg,
char *title));
+EXTERN void TkpFreeCursor _ANSI_ARGS_((TkCursor *cursorPtr));
EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_DString *name));
EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void));
@@ -875,6 +909,12 @@ EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display *display,
char *name, int *width, int *height));
#endif
EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow *winPtr));
+EXTERN char * TkpGetString _ANSI_ARGS_((TkWindow *winPtr,
+ XEvent *eventPtr, Tcl_DString *dsPtr));
+EXTERN void TkpGetSubFonts _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Font tkfont));
+EXTERN Tcl_Obj * TkpGetSystemDefault _ANSI_ARGS_((Tk_Window tkwin,
+ char *dbName, char *className));
EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow *winPtr));
EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_((
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index 234130d..84b8b0c 100644
--- a/generic/tkListbox.c
+++ b/generic/tkListbox.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkListbox.c 1.120 97/10/29 13:06:59
+ * SCCS: @(#) tkListbox.c 1.122 98/02/11 18:00:20
*/
#include "tkPort.h"
@@ -428,7 +428,7 @@ Tk_ListboxCmd(clientData, interp, argc, argv)
goto error;
}
- interp->result = Tk_PathName(listPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(listPtr->tkwin), TCL_STATIC);
return TCL_OK;
error:
@@ -518,12 +518,14 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
if ((index >= listPtr->topIndex) && (index < listPtr->numElements)
&& (index < (listPtr->topIndex + listPtr->fullLines
+ listPtr->partialLine))) {
+ char buf[TCL_INTEGER_SPACE * 4];
+
x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
y = ((index - listPtr->topIndex)*listPtr->lineHeight)
+ listPtr->inset + listPtr->selBorderWidth;
Tk_GetFontMetrics(listPtr->tkfont, &fm);
- sprintf(interp->result, "%d %d %d %d", x, y, elPtr->pixelWidth,
- fm.linespace);
+ sprintf(buf, "%d %d %d %d", x, y, elPtr->pixelWidth, fm.linespace);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
&& (length >= 2)) {
@@ -550,7 +552,6 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
} else if ((c == 'c') && (strncmp(argv[1], "curselection", length) == 0)
&& (length >= 2)) {
int i, count;
- char index[20];
Element *elPtr;
if (argc != 2) {
@@ -563,6 +564,8 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
for (i = 0, elPtr = listPtr->firstPtr; elPtr != NULL;
i++, elPtr = elPtr->nextPtr) {
if (elPtr->selected) {
+ char index[TCL_INTEGER_SPACE];
+
sprintf(index, "%d", i);
Tcl_AppendElement(interp, index);
count++;
@@ -609,8 +612,10 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
if (GetListboxIndex(interp, listPtr, argv[2], 0, &first) != TCL_OK) {
goto error;
}
- if ((argc == 4) && (GetListboxIndex(interp, listPtr, argv[3],
- 0, &last) != TCL_OK)) {
+ last = first;
+ if ((argc == 4)
+ && (GetListboxIndex(interp, listPtr, argv[3], 0,
+ &last) != TCL_OK)) {
goto error;
}
if (first >= listPtr->numElements) {
@@ -627,7 +632,7 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
if (elPtr != NULL) {
if (argc == 3) {
if (first >= 0) {
- interp->result = elPtr->text;
+ Tcl_SetResult(interp, elPtr->text, TCL_STATIC);
}
} else {
for ( ; i <= last; i++, elPtr = elPtr->nextPtr) {
@@ -638,6 +643,7 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
&& (length >= 3)) {
int index;
+ char buf[TCL_INTEGER_SPACE];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -649,7 +655,8 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
!= TCL_OK) {
goto error;
}
- sprintf(interp->result, "%d", index);
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
&& (length >= 3)) {
int index;
@@ -667,6 +674,7 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
InsertEls(listPtr, index, argc-3, argv+3);
} else if ((c == 'n') && (strncmp(argv[1], "nearest", length) == 0)) {
int index, y;
+ char buf[TCL_INTEGER_SPACE];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -677,7 +685,8 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
goto error;
}
index = NearestListboxElement(listPtr, y);
- sprintf(interp->result, "%d", index);
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 's') && (length >= 2)
&& (strncmp(argv[1], "scan", length) == 0)) {
int x, y;
@@ -788,7 +797,7 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
goto error;
}
if ((first < 0) || (first >= listPtr->numElements)) {
- interp->result = "0";
+ Tcl_SetResult(interp, "0", TCL_STATIC);
goto done;
}
for (elPtr = listPtr->firstPtr, i = 0; i < first;
@@ -796,9 +805,9 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
/* Empty loop body. */
}
if (elPtr->selected) {
- interp->result = "1";
+ Tcl_SetResult(interp, "1", TCL_STATIC);
} else {
- interp->result = "0";
+ Tcl_SetResult(interp, "0", TCL_STATIC);
}
} else if ((c == 's') && (strncmp(argv[2], "set", length) == 0)) {
ListboxSelect(listPtr, first, last, 1);
@@ -810,12 +819,15 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
}
} else if ((c == 's') && (length >= 2)
&& (strncmp(argv[1], "size", length) == 0)) {
+ char buf[TCL_INTEGER_SPACE];
+
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " size\"", (char *) NULL);
goto error;
}
- sprintf(interp->result, "%d", listPtr->numElements);
+ sprintf(buf, "%d", listPtr->numElements);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) {
int index, count, type, windowWidth, windowUnits;
int offset = 0; /* Initialized to stop gcc warnings. */
@@ -825,15 +837,18 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
- 2*(listPtr->inset + listPtr->selBorderWidth);
if (argc == 2) {
if (listPtr->maxWidth == 0) {
- interp->result = "0 1";
+ Tcl_SetResult(interp, "0 1", TCL_STATIC);
} else {
+ char buf[TCL_DOUBLE_SPACE * 2];
+
fraction = listPtr->xOffset/((double) listPtr->maxWidth);
fraction2 = (listPtr->xOffset + windowWidth)
/((double) listPtr->maxWidth);
if (fraction2 > 1.0) {
fraction2 = 1.0;
}
- sprintf(interp->result, "%g %g", fraction, fraction2);
+ sprintf(buf, "%g %g", fraction, fraction2);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if (argc == 3) {
if (Tcl_GetInt(interp, argv[2], &index) != TCL_OK) {
@@ -869,15 +884,18 @@ ListboxWidgetCmd(clientData, interp, argc, argv)
if (argc == 2) {
if (listPtr->numElements == 0) {
- interp->result = "0 1";
+ Tcl_SetResult(interp, "0 1", TCL_STATIC);
} else {
+ char buf[TCL_DOUBLE_SPACE * 2];
+
fraction = listPtr->topIndex/((double) listPtr->numElements);
fraction2 = (listPtr->topIndex+listPtr->fullLines)
/((double) listPtr->numElements);
if (fraction2 > 1.0) {
fraction2 = 1.0;
}
- sprintf(interp->result, "%g %g", fraction, fraction2);
+ sprintf(buf, "%g %g", fraction, fraction2);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if (argc == 3) {
if (GetListboxIndex(interp, listPtr, argv[2], 0, &index)
@@ -986,7 +1004,7 @@ DestroyListbox(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
@@ -1718,7 +1736,7 @@ ListboxCmdDeletedProc(clientData)
* 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 interp->result.
+ * string. Otherwise an error message is left in the interp's result.
*
* Side effects:
* None.
diff --git a/generic/tkMacWinMenu.c b/generic/tkMacWinMenu.c
index 8ae403b..e66fa48 100644
--- a/generic/tkMacWinMenu.c
+++ b/generic/tkMacWinMenu.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkMacWinMenu.c 1.39 97/04/09 14:56:59
+ * SCCS: @(#) tkMacWinMenu.c 1.41 97/10/22 15:05:23
*/
#include "tkMenu.h"
@@ -67,7 +67,7 @@ PreprocessMenu(menuPtr)
finished = 1;
for (index = 0; index < menuPtr->numEntries; index++) {
if ((menuPtr->entries[index]->type == CASCADE_ENTRY)
- && (menuPtr->entries[index]->name != NULL)) {
+ && (menuPtr->entries[index]->namePtr != NULL)) {
if ((menuPtr->entries[index]->childMenuRefPtr != NULL)
&& (menuPtr->entries[index]->childMenuRefPtr->menuPtr
!= NULL)) {
diff --git a/generic/tkMain.c b/generic/tkMain.c
index ed823bd..e34067d 100644
--- a/generic/tkMain.c
+++ b/generic/tkMain.c
@@ -8,12 +8,12 @@
* for Tk applications.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkMain.c 1.154 97/08/29 10:40:43
+ * SCCS: @(#) tkMain.c 1.158 98/01/20 22:46:33
*/
#include <ctype.h>
@@ -93,10 +93,11 @@ Tk_Main(argc, argv, appInitProc)
* to execute commands. */
{
char *args, *fileName;
- char buf[20];
+ char buf[TCL_INTEGER_SPACE];
int code;
size_t length;
Tcl_Channel inChannel, outChannel;
+ Tcl_DString argString;
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
@@ -131,12 +132,19 @@ Tk_Main(argc, argv, appInitProc)
*/
args = Tcl_Merge(argc-1, argv+1);
+ Tcl_ExternalToUtfDString(NULL, args, -1, &argString);
Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
+ Tcl_DStringFree(&argString);
ckfree(args);
sprintf(buf, "%d", argc-1);
+
+ if (fileName == NULL) {
+ Tcl_ExternalToUtfDString(NULL, argv[0], -1, &argString);
+ } else {
+ fileName = Tcl_ExternalToUtfDString(NULL, fileName, -1, &argString);
+ }
Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
- TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);
/*
* Set the "tcl_interactive" variable.
@@ -162,7 +170,8 @@ Tk_Main(argc, argv, appInitProc)
*/
if ((*appInitProc)(interp) != TCL_OK) {
- TkpDisplayWarning(interp->result, "Application initialization failed");
+ TkpDisplayWarning(Tcl_GetStringResult(interp),
+ "Application initialization failed");
}
/*
@@ -205,6 +214,7 @@ Tk_Main(argc, argv, appInitProc)
Prompt(interp, 0);
}
}
+ Tcl_DStringFree(&argString);
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
if (outChannel) {
@@ -294,16 +304,13 @@ StdinProc(clientData, mask)
(ClientData) chan);
}
Tcl_DStringFree(&command);
- if (*interp->result != 0) {
+ if (Tcl_GetStringResult(interp)[0] != '\0') {
if ((code != TCL_OK) || (tty)) {
- /*
- * The statement below used to call "printf", but that resulted
- * in core dumps under Solaris 2.3 if the result was very long.
- *
- * NOTE: This probably will not work under Windows either.
- */
-
- puts(interp->result);
+ chan = Tcl_GetStdChannel(TCL_STDOUT);
+ if (chan) {
+ Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(chan, "\n", 1);
+ }
}
}
@@ -361,7 +368,7 @@ defaultPrompt:
outChannel = Tcl_GetChannel(interp, "stdout", NULL);
if (outChannel != (Tcl_Channel) NULL) {
- Tcl_Write(outChannel, "% ", 2);
+ Tcl_WriteChars(outChannel, "% ", 2);
}
}
} else {
@@ -377,8 +384,8 @@ defaultPrompt:
errChannel = Tcl_GetChannel(interp, "stderr", NULL);
if (errChannel != (Tcl_Channel) NULL) {
- Tcl_Write(errChannel, interp->result, -1);
- Tcl_Write(errChannel, "\n", 1);
+ Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(errChannel, "\n", 1);
}
goto defaultPrompt;
}
diff --git a/generic/tkMenu.c b/generic/tkMenu.c
index 05a6b4a..f7b0880 100644
--- a/generic/tkMenu.c
+++ b/generic/tkMenu.c
@@ -7,12 +7,12 @@
* 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-1997 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkMenu.c 1.148 97/10/29 09:22:00
+ * SCCS: @(#) tkMenu.c 1.165 98/02/11 19:02:31
*/
/*
@@ -68,6 +68,7 @@
*
*/
+#define __NO_OLD_CONFIG
#include "tkPort.h"
#include "tkMenu.h"
@@ -81,161 +82,213 @@ static int menusInitialized; /* Whether or not the hash tables, etc., have
* to update code in TkpMenuInit that changes the font string entry.
*/
-Tk_ConfigSpec tkMenuEntryConfigSpecs[] = {
- {TK_CONFIG_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorder),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_ACTIVE_FG, Tk_Offset(TkMenuEntry, activeFg),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-accelerator", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_ACCELERATOR, Tk_Offset(TkMenuEntry, accel),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_BORDER, "-background", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_BG, Tk_Offset(TkMenuEntry, border),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |SEPARATOR_MASK|TEAROFF_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_BITMAP, Tk_Offset(TkMenuEntry, bitmap),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_COLUMN_BREAK, Tk_Offset(TkMenuEntry, columnBreak),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
- {TK_CONFIG_STRING, "-command", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_COMMAND, Tk_Offset(TkMenuEntry, command),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_FONT, Tk_Offset(TkMenuEntry, tkfont),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_FG, Tk_Offset(TkMenuEntry, fg),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_HIDE_MARGIN, Tk_Offset(TkMenuEntry, hideMargin),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |SEPARATOR_MASK|TEAROFF_MASK},
- {TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_IMAGE, Tk_Offset(TkMenuEntry, imageString),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_INDICATOR, Tk_Offset(TkMenuEntry, indicatorOn),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_STRING, "-label", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_LABEL, Tk_Offset(TkMenuEntry, label),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK},
- {TK_CONFIG_STRING, "-menu", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_MENU, Tk_Offset(TkMenuEntry, name),
- CASCADE_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-offvalue", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_OFF_VALUE, Tk_Offset(TkMenuEntry, offValue),
- CHECK_BUTTON_MASK},
- {TK_CONFIG_STRING, "-onvalue", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_ON_VALUE, Tk_Offset(TkMenuEntry, onValue),
- CHECK_BUTTON_MASK},
- {TK_CONFIG_COLOR, "-selectcolor", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_SELECT, Tk_Offset(TkMenuEntry, indicatorFg),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-selectimage", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_SELECT_IMAGE, Tk_Offset(TkMenuEntry, selectImageString),
- CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-state", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_STATE, Tk_Offset(TkMenuEntry, state),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TEAROFF_MASK|TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_STRING, "-value", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_VALUE, Tk_Offset(TkMenuEntry, onValue),
- RADIO_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-variable", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_CHECK_VARIABLE, Tk_Offset(TkMenuEntry, name),
- CHECK_BUTTON_MASK|TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-variable", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_RADIO_VARIABLE, Tk_Offset(TkMenuEntry, name),
- RADIO_BUTTON_MASK},
- {TK_CONFIG_INT, "-underline", (char *) NULL, (char *) NULL,
- DEF_MENU_ENTRY_UNDERLINE, Tk_Offset(TkMenuEntry, underline),
- COMMAND_MASK|CHECK_BUTTON_MASK|RADIO_BUTTON_MASK|CASCADE_MASK
- |TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+char *tkMenuStateStrings[] = {"active", "normal", "disabled", (char *) NULL};
+
+static char *menuEntryTypeStrings[] = {"cascade", "checkbutton", "command",
+ "radiobutton", "separator", (char *) NULL};
+
+Tk_OptionSpec tkBasicMenuEntryConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_ACTIVE_BG, Tk_Offset(TkMenuEntry, activeBorderPtr), -1,
+ TK_OPTION_NULL_OK},
+ {TK_OPTION_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_ACTIVE_FG,
+ Tk_Offset(TkMenuEntry, activeFgPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING, "-accelerator", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_ACCELERATOR,
+ Tk_Offset(TkMenuEntry, accelPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_BG,
+ Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_BITMAP,
+ Tk_Offset(TkMenuEntry, bitmapPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_BOOLEAN, "-columnbreak", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_COLUMN_BREAK,
+ Tk_Offset(TkMenuEntry, columnBreakPtr), -1},
+ {TK_OPTION_STRING, "-command", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_COMMAND,
+ Tk_Offset(TkMenuEntry, commandPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_FONT,
+ Tk_Offset(TkMenuEntry, fontPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_COLOR, "-foreground", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_FG,
+ Tk_Offset(TkMenuEntry, fgPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_BOOLEAN, "-hidemargin", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_HIDE_MARGIN,
+ Tk_Offset(TkMenuEntry, hideMarginPtr), -1},
+ {TK_OPTION_STRING, "-image", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_IMAGE,
+ Tk_Offset(TkMenuEntry, imagePtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING, "-label", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_LABEL,
+ Tk_Offset(TkMenuEntry, labelPtr), -1, 0},
+ {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_STATE,
+ Tk_Offset(TkMenuEntry, statePtr), -1, 0,
+ (ClientData) tkMenuStateStrings},
+ {TK_OPTION_INT, "-underline", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_UNDERLINE, -1, Tk_Offset(TkMenuEntry, underline)},
+ {TK_OPTION_END}
};
+Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_BG,
+ Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_END}
+};
+
+Tk_OptionSpec tkCheckButtonEntryConfigSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_INDICATOR,
+ Tk_Offset(TkMenuEntry, indicatorOnPtr), -1},
+ {TK_OPTION_STRING, "-offvalue", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_OFF_VALUE,
+ Tk_Offset(TkMenuEntry, offValuePtr), -1},
+ {TK_OPTION_STRING, "-onvalue", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_ON_VALUE,
+ Tk_Offset(TkMenuEntry, onValuePtr), -1},
+ {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) 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_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) 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_OptionSpec tkRadioButtonEntryConfigSpecs[] = {
+ {TK_OPTION_BOOLEAN, "-indicatoron", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_INDICATOR,
+ Tk_Offset(TkMenuEntry, indicatorOnPtr), -1},
+ {TK_OPTION_COLOR, "-selectcolor", (char *) NULL, (char *) 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_Offset(TkMenuEntry, selectImagePtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING, "-value", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_VALUE,
+ Tk_Offset(TkMenuEntry, onValuePtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING, "-variable", (char *) NULL, (char *) 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_OptionSpec tkCascadeEntryConfigSpecs[] = {
+ {TK_OPTION_STRING, "-menu", (char *) NULL, (char *) 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_OptionSpec tkTearoffEntryConfigSpecs[] = {
+ {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_BG,
+ Tk_Offset(TkMenuEntry, borderPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING_TABLE, "-state", (char *) NULL, (char *) NULL,
+ DEF_MENU_ENTRY_STATE, Tk_Offset(TkMenuEntry, statePtr), -1, 0,
+ (ClientData) tkMenuStateStrings},
+ {TK_OPTION_END}
+};
+
+static Tk_OptionSpec *specsArray[] = {
+ tkCascadeEntryConfigSpecs, tkCheckButtonEntryConfigSpecs,
+ tkBasicMenuEntryConfigSpecs, tkRadioButtonEntryConfigSpecs,
+ tkSeparatorEntryConfigSpecs, tkTearoffEntryConfigSpecs};
+
/*
- * Configuration specs valid for the menu as a whole. If this changes, be sure
- * to update code in TkpMenuInit that changes the font string entry.
+ * Menu type strings for use with Tcl_GetIndexFromObj.
*/
-Tk_ConfigSpec tkMenuConfigSpecs[] = {
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_MENU_ACTIVE_BG_COLOR, Tk_Offset(TkMenu, activeBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_MENU_ACTIVE_BG_MONO, Tk_Offset(TkMenu, activeBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_PIXELS, "-activeborderwidth", "activeBorderWidth",
+static char *menuTypeStrings[] = {"normal", "tearoff", "menubar",
+ (char *) NULL};
+
+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, activeBorderWidth), 0},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_MENU_ACTIVE_FG_COLOR, Tk_Offset(TkMenu, activeFg),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_MENU_ACTIVE_FG_MONO, Tk_Offset(TkMenu, activeFg),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_MENU_BG_COLOR, Tk_Offset(TkMenu, border), TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_MENU_BG_MONO, Tk_Offset(TkMenu, 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_MENU_BORDER_WIDTH, Tk_Offset(TkMenu, borderWidth), 0},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_MENU_CURSOR, Tk_Offset(TkMenu, cursor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
+ 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_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_MENU_BORDER_WIDTH,
+ Tk_Offset(TkMenu, borderWidthPtr), -1, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_MENU_CURSOR,
+ Tk_Offset(TkMenu, cursorPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
"DisabledForeground", DEF_MENU_DISABLED_FG_COLOR,
- Tk_Offset(TkMenu, disabledFg), TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
- "DisabledForeground", DEF_MENU_DISABLED_FG_MONO,
- Tk_Offset(TkMenu, disabledFg), TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
- {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_FONT, "-font", "font", "Font",
- DEF_MENU_FONT, Tk_Offset(TkMenu, tkfont), 0},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_MENU_FG, Tk_Offset(TkMenu, fg), 0},
- {TK_CONFIG_STRING, "-postcommand", "postCommand", "Command",
- DEF_MENU_POST_COMMAND, Tk_Offset(TkMenu, postCommand),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_MENU_RELIEF, Tk_Offset(TkMenu, relief), 0},
- {TK_CONFIG_COLOR, "-selectcolor", "selectColor", "Background",
- DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFg),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-selectcolor", "selectColor", "Background",
- DEF_MENU_SELECT_MONO, Tk_Offset(TkMenu, indicatorFg),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_MENU_TAKE_FOCUS, Tk_Offset(TkMenu, takeFocus), TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-tearoff", "tearOff", "TearOff",
- DEF_MENU_TEAROFF, Tk_Offset(TkMenu, tearOff), 0},
- {TK_CONFIG_STRING, "-tearoffcommand", "tearOffCommand", "TearOffCommand",
- DEF_MENU_TEAROFF_CMD, Tk_Offset(TkMenu, tearOffCommand),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-title", "title", "Title",
- DEF_MENU_TITLE, Tk_Offset(TkMenu, title), TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-type", "type", "Type",
- DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypeName), TK_CONFIG_NULL_OK},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+ 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_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,
+ Tk_Offset(TkMenu, postCommandPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_MENU_RELIEF, Tk_Offset(TkMenu, reliefPtr), -1},
+ {TK_OPTION_COLOR, "-selectcolor", "selectColor", "Background",
+ DEF_MENU_SELECT_COLOR, Tk_Offset(TkMenu, indicatorFgPtr), -1, 0,
+ (ClientData) DEF_MENU_SELECT_MONO},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_MENU_TAKE_FOCUS,
+ Tk_Offset(TkMenu, takeFocusPtr), -1, TK_OPTION_NULL_OK},
+ {TK_OPTION_BOOLEAN, "-tearoff", "tearOff", "TearOff",
+ DEF_MENU_TEAROFF,
+ Tk_Offset(TkMenu, tearoffPtr), -1},
+ {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,
+ TK_OPTION_NULL_OK},
+ {TK_OPTION_STRING_TABLE, "-type", "type", "Type",
+ DEF_MENU_TYPE, Tk_Offset(TkMenu, menuTypePtr), -1, TK_OPTION_NULL_OK,
+ (ClientData) menuTypeStrings},
+ {TK_OPTION_END}
+};
+
+/*
+ * Command line options. Put here because MenuCmd has to look at them
+ * along with MenuWidgetObjCmd.
+ */
+
+static char *menuOptions[] = {
+ "activate", "add", "cget", "clone", "configure", "delete", "entrycget",
+ "entryconfigure", "index", "insert", "invoke", "post", "postcascade",
+ "type", "unpost", "yposition", (char *) 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
};
/*
@@ -243,15 +296,14 @@ Tk_ConfigSpec tkMenuConfigSpecs[] = {
*/
static int CloneMenu _ANSI_ARGS_((TkMenu *menuPtr,
- char *newMenuName, char *newMenuTypeString));
+ Tcl_Obj *newMenuName, Tcl_Obj *newMenuTypeString));
static int ConfigureMenu _ANSI_ARGS_((Tcl_Interp *interp,
- TkMenu *menuPtr, int argc, char **argv,
- int flags));
+ TkMenu *menuPtr, int objc, Tcl_Obj *CONST objv[]));
static int ConfigureMenuCloneEntries _ANSI_ARGS_((
Tcl_Interp *interp, TkMenu *menuPtr, int index,
- int argc, char **argv, int flags));
+ int objc, Tcl_Obj *CONST objv[]));
static int ConfigureMenuEntry _ANSI_ARGS_((TkMenuEntry *mePtr,
- int argc, char **argv, int flags));
+ int objc, Tcl_Obj *CONST objv[]));
static void DeleteMenuCloneEntries _ANSI_ARGS_((TkMenu *menuPtr,
int first, int last));
static void DestroyMenuHashTable _ANSI_ARGS_((
@@ -262,10 +314,13 @@ static int GetIndexFromCoords
_ANSI_ARGS_((Tcl_Interp *interp, TkMenu *menuPtr,
char *string, int *indexPtr));
static int MenuDoYPosition _ANSI_ARGS_((Tcl_Interp *interp,
- TkMenu *menuPtr, char *arg));
+ TkMenu *menuPtr, Tcl_Obj *objPtr));
static int MenuAddOrInsert _ANSI_ARGS_((Tcl_Interp *interp,
- TkMenu *menuPtr, char *indexString, int argc,
- char **argv));
+ 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,
@@ -273,10 +328,12 @@ static TkMenuEntry * MenuNewEntry _ANSI_ARGS_((TkMenu *menuPtr, int index,
static char * MenuVarProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, char *name1, char *name2,
int flags));
-static int MenuWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+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));
@@ -290,13 +347,61 @@ static TkClassProcs menuClass = {
NULL, /* createProc. */
MenuWorldChanged /* geometryProc. */
};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateMenuCmd --
+ *
+ * Called by Tk at initialization time to create the menu
+ * command.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+int
+TkCreateMenuCmd(interp)
+ Tcl_Interp *interp; /* Interpreter we are creating the
+ * command in. */
+{
+ TkMenuOptionTables *optionTablesPtr =
+ (TkMenuOptionTables *) ckalloc(sizeof(TkMenuOptionTables));
+
+ optionTablesPtr->menuOptionTable =
+ Tk_CreateOptionTable(interp, tkMenuConfigSpecs);
+ optionTablesPtr->entryOptionTables[TEAROFF_ENTRY] =
+ Tk_CreateOptionTable(interp, specsArray[TEAROFF_ENTRY]);
+ optionTablesPtr->entryOptionTables[COMMAND_ENTRY] =
+ Tk_CreateOptionTable(interp, specsArray[COMMAND_ENTRY]);
+ optionTablesPtr->entryOptionTables[CASCADE_ENTRY] =
+ Tk_CreateOptionTable(interp, specsArray[CASCADE_ENTRY]);
+ optionTablesPtr->entryOptionTables[SEPARATOR_ENTRY] =
+ Tk_CreateOptionTable(interp, specsArray[SEPARATOR_ENTRY]);
+ optionTablesPtr->entryOptionTables[RADIO_BUTTON_ENTRY] =
+ Tk_CreateOptionTable(interp, specsArray[RADIO_BUTTON_ENTRY]);
+ optionTablesPtr->entryOptionTables[CHECK_BUTTON_ENTRY] =
+ Tk_CreateOptionTable(interp, specsArray[CHECK_BUTTON_ENTRY]);
+
+ Tcl_CreateObjCommand(interp, "menu", MenuCmd,
+ (ClientData) optionTablesPtr, NULL);
+
+ if (Tcl_IsSafe(interp)) {
+ Tcl_HideCommand(interp, "menu", "menu");
+ }
+ return TCL_OK;
+}
/*
*--------------------------------------------------------------
*
- * Tk_MenuCmd --
+ * MenuCmd --
*
* This procedure is invoked to process the "menu" Tcl
* command. See the user documentation for details on
@@ -311,48 +416,45 @@ static TkClassProcs menuClass = {
*--------------------------------------------------------------
*/
-int
-Tk_MenuCmd(clientData, interp, argc, argv)
+static int
+MenuCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument strings. */
{
- Tk_Window tkwin = (Tk_Window) clientData;
+ Tk_Window tkwin = Tk_MainWindow(interp);
Tk_Window new;
register TkMenu *menuPtr;
TkMenuReferences *menuRefPtr;
- int i, len;
- char *arg, c;
+ int i, index;
int toplevel;
+ char *windowName;
+ static char *typeStringList[] = {"-type", (char *) NULL};
+ TkMenuOptionTables *optionTablesPtr = (TkMenuOptionTables *) clientData;
- 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;
}
TkMenuInit();
toplevel = 1;
- for (i = 2; i < argc; i += 2) {
- arg = argv[i];
- len = strlen(arg);
- if (len < 2) {
- continue;
- }
- c = arg[1];
- if ((c == 't') && (strncmp(arg, "-type", strlen(arg)) == 0)
- && (len >= 3)) {
- if (strcmp(argv[i + 1], "menubar") == 0) {
+ for (i = 2; i < (objc - 1); i++) {
+ if (Tcl_GetIndexFromObj(NULL, objv[i], typeStringList, NULL, 0, &index)
+ != TCL_ERROR) {
+ if ((Tcl_GetIndexFromObj(NULL, objv[i + 1], menuTypeStrings, NULL,
+ 0, &index) == TCL_OK) && (index == MENUBAR)) {
toplevel = 0;
}
break;
}
}
- new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], toplevel ? ""
+ windowName = Tcl_GetStringFromObj(objv[1], NULL);
+ new = Tk_CreateWindowFromPath(interp, tkwin, windowName, toplevel ? ""
: NULL);
if (new == NULL) {
return TCL_ERROR;
@@ -366,27 +468,27 @@ Tk_MenuCmd(clientData, interp, argc, argv)
menuPtr->tkwin = new;
menuPtr->display = Tk_Display(new);
menuPtr->interp = interp;
- menuPtr->widgetCmd = Tcl_CreateCommand(interp,
- Tk_PathName(menuPtr->tkwin), MenuWidgetCmd,
+ menuPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(menuPtr->tkwin), MenuWidgetObjCmd,
(ClientData) menuPtr, MenuCmdDeletedProc);
menuPtr->entries = NULL;
menuPtr->numEntries = 0;
menuPtr->active = -1;
- menuPtr->border = NULL;
- menuPtr->borderWidth = 0;
- menuPtr->relief = TK_RELIEF_FLAT;
- menuPtr->activeBorder = NULL;
- menuPtr->activeBorderWidth = 0;
- menuPtr->tkfont = NULL;
- menuPtr->fg = NULL;
- menuPtr->disabledFg = NULL;
- menuPtr->activeFg = NULL;
- menuPtr->indicatorFg = NULL;
- menuPtr->tearOff = 1;
- menuPtr->tearOffCommand = NULL;
- menuPtr->cursor = None;
- menuPtr->takeFocus = NULL;
- menuPtr->postCommand = NULL;
+ menuPtr->borderPtr = NULL;
+ menuPtr->borderWidthPtr = NULL;
+ menuPtr->reliefPtr = NULL;
+ menuPtr->activeBorderPtr = NULL;
+ menuPtr->activeBorderWidthPtr = NULL;
+ menuPtr->fontPtr = NULL;
+ menuPtr->fgPtr = NULL;
+ menuPtr->disabledFgPtr = NULL;
+ menuPtr->activeFgPtr = NULL;
+ menuPtr->indicatorFgPtr = NULL;
+ menuPtr->tearoffPtr = NULL;
+ menuPtr->tearoffCommandPtr = NULL;
+ menuPtr->cursorPtr = None;
+ menuPtr->takeFocusPtr = NULL;
+ menuPtr->postCommandPtr = NULL;
menuPtr->postCommandGeneration = 0;
menuPtr->postedCascade = NULL;
menuPtr->nextInstancePtr = NULL;
@@ -394,24 +496,38 @@ Tk_MenuCmd(clientData, interp, argc, argv)
menuPtr->menuType = UNKNOWN_TYPE;
menuPtr->menuFlags = 0;
menuPtr->parentTopLevelPtr = NULL;
- menuPtr->menuTypeName = NULL;
- menuPtr->title = NULL;
+ menuPtr->menuTypePtr = NULL;
+ menuPtr->titlePtr = NULL;
+ menuPtr->errorStructPtr = NULL;
+ menuPtr->optionTablesPtr = optionTablesPtr;
TkMenuInitializeDrawingFields(menuPtr);
+ Tk_SetClass(menuPtr->tkwin, "Menu");
+ TkSetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
+ if (Tk_InitOptions(interp, (char *) menuPtr,
+ menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin)
+ != TCL_OK) {
+ Tk_DestroyWindow(menuPtr->tkwin);
+ ckfree((char *) menuPtr);
+ return TCL_ERROR;
+ }
+
+
menuRefPtr = TkCreateMenuReferences(menuPtr->interp,
Tk_PathName(menuPtr->tkwin));
menuRefPtr->menuPtr = menuPtr;
menuPtr->menuRefPtr = menuRefPtr;
if (TCL_OK != TkpNewMenu(menuPtr)) {
- goto error;
+ Tk_DestroyWindow(menuPtr->tkwin);
+ ckfree((char *) menuPtr);
+ return TCL_ERROR;
}
- Tk_SetClass(menuPtr->tkwin, "Menu");
- TkSetClassProcs(menuPtr->tkwin, &menuClass, (ClientData) menuPtr);
Tk_CreateEventHandler(new, ExposureMask|StructureNotifyMask|ActivateMask,
TkMenuEventProc, (ClientData) menuPtr);
- if (ConfigureMenu(interp, menuPtr, argc-2, argv+2, 0) != TCL_OK) {
- goto error;
+ if (ConfigureMenu(interp, menuPtr, objc - 2, objv + 2) != TCL_OK) {
+ Tk_DestroyWindow(menuPtr->tkwin);
+ return TCL_ERROR;
}
/*
@@ -434,8 +550,8 @@ Tk_MenuCmd(clientData, interp, argc, argv)
if (menuRefPtr->parentEntryPtr != NULL) {
TkMenuEntry *cascadeListPtr = menuRefPtr->parentEntryPtr;
TkMenuEntry *nextCascadePtr;
- char *newMenuName;
- char *newArgv[2];
+ Tcl_Obj *newMenuName;
+ Tcl_Obj *newObjv[2];
while (cascadeListPtr != NULL) {
@@ -454,28 +570,38 @@ Tk_MenuCmd(clientData, interp, argc, argv)
|| ((menuPtr->masterMenuPtr == menuPtr)
&& ((cascadeListPtr->menuPtr->masterMenuPtr
== cascadeListPtr->menuPtr)))) {
- newArgv[0] = "-menu";
- newArgv[1] = Tk_PathName(menuPtr->tkwin);
- ConfigureMenuEntry(cascadeListPtr, 2, newArgv,
- TK_CONFIG_ARGV_ONLY);
+ newObjv[0] = Tcl_NewStringObj("-menu", -1);
+ newObjv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ Tcl_IncrRefCount(newObjv[1]);
+ ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
} else {
+ Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
+ Tcl_Obj *windowNamePtr = Tcl_NewStringObj(
+ Tk_PathName(cascadeListPtr->menuPtr->tkwin), -1);
+
+ Tcl_IncrRefCount(normalPtr);
+ Tcl_IncrRefCount(windowNamePtr);
newMenuName = TkNewMenuName(menuPtr->interp,
- Tk_PathName(cascadeListPtr->menuPtr->tkwin),
- menuPtr);
- CloneMenu(menuPtr, newMenuName, "normal");
+ windowNamePtr, menuPtr);
+ Tcl_IncrRefCount(newMenuName);
+ CloneMenu(menuPtr, newMenuName, normalPtr);
/*
* Now we can set the new menu instance to be the cascade entry
* of the parent's instance.
*/
- newArgv[0] = "-menu";
- newArgv[1] = newMenuName;
- ConfigureMenuEntry(cascadeListPtr, 2, newArgv,
- TK_CONFIG_ARGV_ONLY);
- if (newMenuName != NULL) {
- ckfree(newMenuName);
- }
+ newObjv[0] = Tcl_NewStringObj("-menu", -1);
+ newObjv[1] = newMenuName;
+ Tcl_IncrRefCount(newObjv[0]);
+ ConfigureMenuEntry(cascadeListPtr, 2, newObjv);
+ Tcl_DecrRefCount(normalPtr);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(windowNamePtr);
}
cascadeListPtr = nextCascadePtr;
}
@@ -507,18 +633,14 @@ Tk_MenuCmd(clientData, interp, argc, argv)
}
}
- interp->result = Tk_PathName(menuPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(menuPtr->tkwin), TCL_STATIC);
return TCL_OK;
-
- error:
- Tk_DestroyWindow(menuPtr->tkwin);
- return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
- * MenuWidgetCmd --
+ * MenuWidgetObjCmd --
*
* This procedure is invoked to process the Tcl command
* that corresponds to a widget managed by this module.
@@ -534,317 +656,358 @@ Tk_MenuCmd(clientData, interp, argc, argv)
*/
static int
-MenuWidgetCmd(clientData, interp, argc, argv)
+MenuWidgetObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about menu widget. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument strings. */
{
register TkMenu *menuPtr = (TkMenu *) clientData;
register TkMenuEntry *mePtr;
int result = TCL_OK;
- size_t length;
- int c;
+ int option;
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option ?arg arg ...?\"", (char *) NULL);
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], menuOptions, "option", 0,
+ &option) != TCL_OK) {
return TCL_ERROR;
}
Tcl_Preserve((ClientData) menuPtr);
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)
- && (length >= 2)) {
- int index;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " activate index\"", (char *) NULL);
- goto error;
- }
- if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (menuPtr->active == index) {
- goto done;
- }
- if (index >= 0) {
- if ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
- || (menuPtr->entries[index]->state == tkDisabledUid)) {
- index = -1;
+
+ switch ((enum options) option) {
+ 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) {
+ if (menuPtr->entries[index]->type == SEPARATOR_ENTRY) {
+ int state;
+
+ Tcl_GetIndexFromObj(interp,
+ menuPtr->entries[index]->statePtr,
+ tkMenuStateStrings, NULL, 0, &state);
+ if (state == ENTRY_DISABLED) {
+ index = -1;
+ }
+ }
+ }
+ result = TkActivateMenuEntry(menuPtr, index);
+ break;
}
- result = TkActivateMenuEntry(menuPtr, index);
- } else if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)
- && (length >= 2)) {
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " add type ?options?\"", (char *) NULL);
- 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 (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget 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;
}
- if (MenuAddOrInsert(interp, menuPtr, (char *) NULL,
- argc-2, argv+2) != TCL_OK) {
- goto error;
+ 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);
+ }
+ } else {
+ result = ConfigureMenu(interp, menuPtr, objc - 2, objv + 2);
+ }
+ if (result != TCL_OK) {
+ goto error;
+ }
+ break;
}
- } 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);
- goto error;
+ case MENU_DELETE: {
+ int first, last, tearoff;
+
+ 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;
+ }
+ }
+ Tcl_GetBooleanFromObj(interp, menuPtr->tearoffPtr, &tearoff);
+ if (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;
}
- result = Tk_ConfigureValue(interp, menuPtr->tkwin, tkMenuConfigSpecs,
- (char *) menuPtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "clone", length) == 0)
- && (length >=2)) {
- if ((argc < 3) || (argc > 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " clone newMenuName ?menuType?\"",
- (char *) NULL);
- goto error;
- }
- result = CloneMenu(menuPtr, argv[2], (argc == 3) ? NULL : argv[3]);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
- tkMenuConfigSpecs, (char *) menuPtr, (char *) NULL, 0);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
- tkMenuConfigSpecs, (char *) menuPtr, argv[2], 0);
- } else {
- result = ConfigureMenu(interp, menuPtr, argc-2, argv+2,
- TK_CONFIG_ARGV_ONLY);
+ 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;
+ }
+ 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;
}
- } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
- int first, last;
+ case MENU_ENTRYCONFIGURE: {
+ int index;
+ Tcl_Obj *resultPtr;
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " delete first ?last?\"", (char *) NULL);
- goto error;
+ 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 (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &first) != TCL_OK) {
- goto error;
+ case MENU_INDEX: {
+ 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_SetObjResult(interp, Tcl_NewStringObj("none", -1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ }
+ break;
}
- if (argc == 3) {
- last = first;
- } else {
- if (TkGetMenuIndex(interp, menuPtr, argv[3], 0, &last) != TCL_OK) {
- 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 (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 (menuPtr->tearOff && (first == 0)) {
+ 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;
+ }
/*
- * Sorry, can't delete the tearoff entry; must reconfigure
- * the menu.
+ * 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.
*/
- first = 1;
- }
- if ((first < 0) || (last < first)) {
- goto done;
- }
- DeleteMenuCloneEntries(menuPtr, first, last);
- } else if ((c == 'e') && (length >= 7)
- && (strncmp(argv[1], "entrycget", length) == 0)) {
- int index;
-
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " entrycget index option\"",
- (char *) NULL);
- goto error;
- }
- if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index < 0) {
- goto done;
- }
- mePtr = menuPtr->entries[index];
- Tcl_Preserve((ClientData) mePtr);
- result = Tk_ConfigureValue(interp, menuPtr->tkwin,
- tkMenuEntryConfigSpecs, (char *) mePtr, argv[3],
- COMMAND_MASK << mePtr->type);
- Tcl_Release((ClientData) mePtr);
- } else if ((c == 'e') && (length >= 7)
- && (strncmp(argv[1], "entryconfigure", length) == 0)) {
- int index;
-
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " entryconfigure index ?option value ...?\"",
- (char *) NULL);
- goto error;
- }
- if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index < 0) {
- goto done;
- }
- mePtr = menuPtr->entries[index];
- Tcl_Preserve((ClientData) mePtr);
- if (argc == 3) {
- result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
- tkMenuEntryConfigSpecs, (char *) mePtr, (char *) NULL,
- COMMAND_MASK << mePtr->type);
- } else if (argc == 4) {
- result = Tk_ConfigureInfo(interp, menuPtr->tkwin,
- tkMenuEntryConfigSpecs, (char *) mePtr, argv[3],
- COMMAND_MASK << mePtr->type);
- } else {
- result = ConfigureMenuCloneEntries(interp, menuPtr, index,
- argc-3, argv+3,
- TK_CONFIG_ARGV_ONLY | COMMAND_MASK << mePtr->type);
- }
- Tcl_Release((ClientData) mePtr);
- } else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
- && (length >= 3)) {
- int index;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " index string\"", (char *) NULL);
- goto error;
- }
- if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index < 0) {
- interp->result = "none";
- } else {
- sprintf(interp->result, "%d", index);
- }
- } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
- && (length >= 3)) {
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " insert index type ?options?\"", (char *) NULL);
- goto error;
- }
- if (MenuAddOrInsert(interp, menuPtr, argv[2],
- argc-3, argv+3) != TCL_OK) {
- goto error;
+ if (menuPtr->menuType != TEAROFF_MENU) {
+ result = TkpPostMenu(interp, menuPtr, x, y);
+ } else {
+ result = TkPostTearoffMenu(interp, menuPtr, x, y);
+ }
+ break;
}
- } else if ((c == 'i') && (strncmp(argv[1], "invoke", length) == 0)
- && (length >= 3)) {
- int index;
+ case MENU_POSTCASCADE: {
+ int index;
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " invoke index\"", (char *) NULL);
- goto error;
- }
- if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index < 0) {
- goto done;
- }
- result = TkInvokeMenu(interp, menuPtr, index);
- } else if ((c == 'p') && (strncmp(argv[1], "post", length) == 0)
- && (length == 4)) {
- int x, y;
-
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " post x y\"", (char *) NULL);
- goto error;
- }
- if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
- goto error;
- }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "postcascade index");
+ 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.
- */
-
- if (menuPtr->menuType != TEAROFF_MENU) {
- result = TkpPostMenu(interp, menuPtr, x, y);
- } else {
- result = TkPostTearoffMenu(interp, menuPtr, x, y);
- }
- } else if ((c == 'p') && (strncmp(argv[1], "postcascade", length) == 0)
- && (length > 4)) {
- int index;
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " postcascade index\"", (char *) NULL);
- 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, argv[2], 0, &index) != TCL_OK) {
- goto error;
+ 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_SetObjResult(interp, Tcl_NewStringObj("tearoff", -1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ menuEntryTypeStrings[menuPtr->entries[index]->type],
+ -1));
+ }
+ break;
}
- if ((index < 0) || (menuPtr->entries[index]->type != CASCADE_ENTRY)) {
+ case MENU_UNPOST:
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "unpost");
+ goto error;
+ }
+ Tk_UnmapWindow(menuPtr->tkwin);
result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
- } else {
- result = TkPostSubmenu(interp, menuPtr, menuPtr->entries[index]);
- }
- } else if ((c == 't') && (strncmp(argv[1], "type", length) == 0)) {
- int index;
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " type index\"", (char *) NULL);
- goto error;
- }
- if (TkGetMenuIndex(interp, menuPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index < 0) {
- goto done;
- }
- mePtr = menuPtr->entries[index];
- switch (mePtr->type) {
- case COMMAND_ENTRY:
- interp->result = "command";
- break;
- case SEPARATOR_ENTRY:
- interp->result = "separator";
- break;
- case CHECK_BUTTON_ENTRY:
- interp->result = "checkbutton";
- break;
- case RADIO_BUTTON_ENTRY:
- interp->result = "radiobutton";
- break;
- case CASCADE_ENTRY:
- interp->result = "cascade";
- break;
- case TEAROFF_ENTRY:
- interp->result = "tearoff";
- break;
- }
- } else if ((c == 'u') && (strncmp(argv[1], "unpost", length) == 0)) {
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " unpost\"", (char *) NULL);
- goto error;
- }
- Tk_UnmapWindow(menuPtr->tkwin);
- result = TkPostSubmenu(interp, menuPtr, (TkMenuEntry *) NULL);
- } else if ((c == 'y') && (strncmp(argv[1], "yposition", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " yposition index\"", (char *) NULL);
- goto error;
- }
- result = MenuDoYPosition(interp, menuPtr, argv[2]);
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be activate, add, cget, clone, configure, delete, ",
- "entrycget, entryconfigure, index, insert, invoke, ",
- "post, postcascade, type, unpost, or yposition",
- (char *) NULL);
- goto error;
+ break;
+ case MENU_YPOSITION:
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "yposition index");
+ goto error;
+ }
+ result = MenuDoYPosition(interp, menuPtr, objv[2]);
+ break;
}
done:
Tcl_Release((ClientData) menuPtr);
@@ -854,7 +1017,6 @@ MenuWidgetCmd(clientData, interp, argc, argv)
Tcl_Release((ClientData) menuPtr);
return TCL_ERROR;
}
-
/*
*----------------------------------------------------------------------
@@ -883,50 +1045,74 @@ TkInvokeMenu(interp, menuPtr, index)
{
int result = TCL_OK;
TkMenuEntry *mePtr;
+ int state;
if (index < 0) {
goto done;
}
mePtr = menuPtr->entries[index];
- if (mePtr->state == tkDisabledUid) {
+ Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings, NULL, 0,
+ &state);
+ if (state == ENTRY_DISABLED) {
goto done;
}
Tcl_Preserve((ClientData) mePtr);
if (mePtr->type == TEAROFF_ENTRY) {
- Tcl_DString commandDString;
-
- Tcl_DStringInit(&commandDString);
- Tcl_DStringAppendElement(&commandDString, "tkTearOffMenu");
- Tcl_DStringAppendElement(&commandDString, Tk_PathName(menuPtr->tkwin));
- result = Tcl_Eval(interp, Tcl_DStringValue(&commandDString));
- Tcl_DStringFree(&commandDString);
- } else if (mePtr->type == CHECK_BUTTON_ENTRY) {
+ Tcl_Obj *objv[2];
+
+ objv[0] = Tcl_NewStringObj("tkTearOffMenu", -1);
+ Tcl_IncrRefCount(objv[0]);
+ objv[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
+ Tcl_IncrRefCount(objv[1]);
+ result = Tcl_EvalObjv(interp, 2, objv, "", -1, 0);
+ Tcl_DecrRefCount(objv[0]);
+ Tcl_DecrRefCount(objv[1]);
+ } else if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ && (mePtr->namePtr != NULL)) {
+ Tcl_Obj *valuePtr;
+ char *name;
+
if (mePtr->entryFlags & ENTRY_SELECTED) {
- if (Tcl_SetVar(interp, mePtr->name, mePtr->offValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
- }
+ valuePtr = mePtr->offValuePtr;
} else {
- if (Tcl_SetVar(interp, mePtr->name, mePtr->onValue,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
- }
+ valuePtr = mePtr->onValuePtr;
}
- } else if (mePtr->type == RADIO_BUTTON_ENTRY) {
- if (Tcl_SetVar(interp, mePtr->name, mePtr->onValue,
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewStringObj("", -1);
+ }
+ Tcl_IncrRefCount(valuePtr);
+ name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ if (Tcl_SetObjVar2(interp, name, NULL, valuePtr,
TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
}
+ Tcl_DecrRefCount(valuePtr);
+ } else if ((mePtr->type == RADIO_BUTTON_ENTRY)
+ && (mePtr->namePtr != NULL)) {
+ Tcl_Obj *valuePtr = mePtr->onValuePtr;
+ char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewStringObj("", -1);
+ }
+ Tcl_IncrRefCount(valuePtr);
+ if (Tcl_SetObjVar2(interp, name, NULL, valuePtr,
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
+ result = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(valuePtr);
}
- if ((result == TCL_OK) && (mePtr->command != NULL)) {
- result = TkCopyAndGlobalEval(interp, mePtr->command);
+ if ((result == TCL_OK) && (mePtr->commandPtr != NULL)) {
+ Tcl_Obj *commandPtr = mePtr->commandPtr;
+
+ Tcl_IncrRefCount(commandPtr);
+ result = Tcl_EvalObj(interp, commandPtr, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(commandPtr);
}
Tcl_Release((ClientData) mePtr);
done:
return result;
}
-
-
/*
*----------------------------------------------------------------------
@@ -951,13 +1137,12 @@ static void
DestroyMenuInstance(menuPtr)
TkMenu *menuPtr; /* Info about menu widget. */
{
- int i, numEntries = menuPtr->numEntries;
+ int i;
TkMenu *menuInstancePtr;
TkMenuEntry *cascadePtr, *nextCascadePtr;
- char *newArgv[2];
+ Tcl_Obj *newObjv[2];
TkMenu *parentMasterMenuPtr;
TkMenuEntry *parentMasterEntryPtr;
- TkMenu *parentMenuPtr;
/*
* If the menu has any cascade menu entries pointing to it, the cascade
@@ -979,18 +1164,23 @@ DestroyMenuInstance(menuPtr)
TkFreeMenuReferences(menuPtr->menuRefPtr);
for (; cascadePtr != NULL; cascadePtr = nextCascadePtr) {
- parentMenuPtr = cascadePtr->menuPtr;
nextCascadePtr = cascadePtr->nextCascadePtr;
if (menuPtr->masterMenuPtr != menuPtr) {
+ Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
+
parentMasterMenuPtr = cascadePtr->menuPtr->masterMenuPtr;
parentMasterEntryPtr =
parentMasterMenuPtr->entries[cascadePtr->index];
- newArgv[0] = "-menu";
- newArgv[1] = parentMasterEntryPtr->name;
- ConfigureMenuEntry(cascadePtr, 2, newArgv, TK_CONFIG_ARGV_ONLY);
+ newObjv[0] = menuNamePtr;
+ newObjv[1] = parentMasterEntryPtr->namePtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ Tcl_IncrRefCount(newObjv[1]);
+ ConfigureMenuEntry(cascadePtr, 2, newObjv);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
} else {
- ConfigureMenuEntry(cascadePtr, 0, (char **) NULL, 0);
+ ConfigureMenuEntry(cascadePtr, 0, (Tcl_Obj **) NULL);
}
}
@@ -1010,20 +1200,27 @@ DestroyMenuInstance(menuPtr)
/*
* Free up all the stuff that requires special handling, then
- * let Tk_FreeOptions handle all the standard option-related
+ * let Tk_FreeConfigurationOptions handle all the standard option-related
* stuff.
*/
- for (i = numEntries - 1; i >= 0; i--) {
+ 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.
+ */
+
DestroyMenuEntry((char *) menuPtr->entries[i]);
+ menuPtr->numEntries = i;
}
if (menuPtr->entries != NULL) {
ckfree((char *) menuPtr->entries);
}
TkMenuFreeDrawOptions(menuPtr);
- Tk_FreeOptions(tkMenuConfigSpecs, (char *) menuPtr, menuPtr->display, 0);
-
- Tcl_EventuallyFree((ClientData) menuPtr, TCL_DYNAMIC);
+ Tk_FreeConfigOptions((char *) menuPtr,
+ menuPtr->optionTablesPtr->menuOptionTable, menuPtr->tkwin);
}
/*
@@ -1202,7 +1399,7 @@ DestroyMenuEntry(memPtr)
/*
* Free up all the stuff that requires special handling, then
- * let Tk_FreeOptions handle all the standard option-related
+ * let Tk_FreeConfigurationOptions handle all the standard option-related
* stuff.
*/
@@ -1215,15 +1412,17 @@ DestroyMenuEntry(memPtr)
if (mePtr->selectImage != NULL) {
Tk_FreeImage(mePtr->selectImage);
}
- if (mePtr->name != NULL) {
- Tcl_UntraceVar(menuPtr->interp, mePtr->name,
+ if (((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY))
+ && (mePtr->namePtr != NULL)) {
+ char *varName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ Tcl_UntraceVar(menuPtr->interp, varName,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
MenuVarProc, (ClientData) mePtr);
}
TkpDestroyMenuEntry(mePtr);
TkMenuEntryFreeDrawOptions(mePtr);
- Tk_FreeOptions(tkMenuEntryConfigSpecs, (char *) mePtr, menuPtr->display,
- (COMMAND_MASK << mePtr->type));
+ Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable, menuPtr->tkwin);
ckfree((char *) mePtr);
}
@@ -1259,7 +1458,6 @@ MenuWorldChanged(instanceData)
TkpConfigureMenuEntry(menuPtr->entries[i]);
}
}
-
/*
*----------------------------------------------------------------------
@@ -1272,7 +1470,7 @@ MenuWorldChanged(instanceData)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, font, etc. get set
@@ -1282,23 +1480,33 @@ MenuWorldChanged(instanceData)
*/
static int
-ConfigureMenu(interp, menuPtr, argc, argv, flags)
+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 argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
- int flags; /* Flags to pass to Tk_ConfigureWidget. */
+ int objc; /* Number of valid entries in argv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
{
int i;
- TkMenu* menuListPtr;
+ TkMenu *menuListPtr, *cleanupPtr;
+ int result;
+ int tearoff;
for (menuListPtr = menuPtr->masterMenuPtr; menuListPtr != NULL;
menuListPtr = menuListPtr->nextInstancePtr) {
-
- if (Tk_ConfigureWidget(interp, menuListPtr->tkwin,
- tkMenuConfigSpecs, argc, argv, (char *) menuListPtr,
- flags) != TCL_OK) {
+ 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);
+ if (result != TCL_OK) {
+ for (cleanupPtr = menuPtr->masterMenuPtr;
+ cleanupPtr != menuListPtr;
+ cleanupPtr = cleanupPtr->nextInstancePtr) {
+ Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree((char *) cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
return TCL_ERROR;
}
@@ -1310,33 +1518,58 @@ ConfigureMenu(interp, menuPtr, argc, argv, flags)
*/
if (menuListPtr->menuType == UNKNOWN_TYPE) {
- if (strcmp(menuListPtr->menuTypeName, "menubar") == 0) {
- menuListPtr->menuType = MENUBAR;
- } else if (strcmp(menuListPtr->menuTypeName, "tearoff") == 0) {
- menuListPtr->menuType = TEAROFF_MENU;
- } else {
- menuListPtr->menuType = MASTER_MENU;
+ 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
+ * 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) {
+ TkpMakeMenuWindow(menuListPtr->tkwin, 0);
}
}
-
+
+
/*
* 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) {
+ Tcl_GetBooleanFromObj(NULL, menuListPtr->tearoffPtr, &tearoff);
+ if (tearoff) {
if ((menuListPtr->numEntries == 0)
|| (menuListPtr->entries[0]->type != TEAROFF_ENTRY)) {
if (MenuNewEntry(menuListPtr, 0, TEAROFF_ENTRY) == NULL) {
+ if (menuListPtr->errorStructPtr != NULL) {
+ for (cleanupPtr = menuPtr->masterMenuPtr;
+ cleanupPtr != menuListPtr;
+ cleanupPtr = cleanupPtr->nextInstancePtr) {
+ Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree((char *) cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
+ Tk_RestoreSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree((char *) cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
return TCL_ERROR;
}
}
} else if ((menuListPtr->numEntries > 0)
&& (menuListPtr->entries[0]->type == TEAROFF_ENTRY)) {
int i;
-
+
Tcl_EventuallyFree((ClientData) menuListPtr->entries[0],
DestroyMenuEntry);
+
for (i = 0; i < menuListPtr->numEntries - 1; i++) {
menuListPtr->entries[i] = menuListPtr->entries[i + 1];
menuListPtr->entries[i]->index = i;
@@ -1349,21 +1582,6 @@ ConfigureMenu(interp, menuPtr, argc, argv, flags)
}
TkMenuConfigureDrawOptions(menuListPtr);
-
- /*
- * 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 (strcmp(menuListPtr->menuTypeName, "normal") == 0) {
- TkpMakeMenuWindow(menuListPtr->tkwin, 1);
- } else if (strcmp(menuListPtr->menuTypeName, "tearoff") == 0) {
- TkpMakeMenuWindow(menuListPtr->tkwin, 0);
- }
/*
* After reconfiguring a menu, we need to reconfigure all of the
@@ -1376,28 +1594,35 @@ ConfigureMenu(interp, menuPtr, argc, argv, flags)
TkMenuEntry *mePtr;
mePtr = menuListPtr->entries[i];
- ConfigureMenuEntry(mePtr, 0,
- (char **) NULL, TK_CONFIG_ARGV_ONLY
- | COMMAND_MASK << mePtr->type);
+ ConfigureMenuEntry(mePtr, 0, (Tcl_Obj **) NULL);
}
TkEventuallyRecomputeMenu(menuListPtr);
}
+ for (cleanupPtr = menuPtr->masterMenuPtr; cleanupPtr != NULL;
+ cleanupPtr = cleanupPtr->nextInstancePtr) {
+ Tk_FreeSavedOptions(cleanupPtr->errorStructPtr);
+ ckfree((char *) cleanupPtr->errorStructPtr);
+ cleanupPtr->errorStructPtr = NULL;
+ }
+
return TCL_OK;
}
+
/*
*----------------------------------------------------------------------
*
- * ConfigureMenuEntry --
+ * PostProcessEntry --
*
- * This procedure is called to process an argv/argc list in order
- * to configure (or reconfigure) one entry in a menu.
+ * 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.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information such as label and accelerator get
@@ -1407,55 +1632,29 @@ ConfigureMenu(interp, menuPtr, argc, argv, flags)
*/
static int
-ConfigureMenuEntry(mePtr, argc, argv, flags)
- register TkMenuEntry *mePtr; /* Information about menu entry; may
- * or may not already have values for
- * some fields. */
- int argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
- int flags; /* Additional flags to pass to
- * Tk_ConfigureWidget. */
+PostProcessEntry(mePtr)
+ TkMenuEntry *mePtr; /* The entry we are configuring. */
{
TkMenu *menuPtr = mePtr->menuPtr;
int index = mePtr->index;
+ char *name;
Tk_Image image;
/*
- * If this entry is a check button or radio button, then remove
- * its old trace procedure.
- */
-
- if ((mePtr->name != NULL)
- && ((mePtr->type == CHECK_BUTTON_ENTRY)
- || (mePtr->type == RADIO_BUTTON_ENTRY))) {
- Tcl_UntraceVar(menuPtr->interp, mePtr->name,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- MenuVarProc, (ClientData) mePtr);
- }
-
- if (menuPtr->tkwin != NULL) {
- if (Tk_ConfigureWidget(menuPtr->interp, menuPtr->tkwin,
- tkMenuEntryConfigSpecs, argc, argv, (char *) mePtr,
- flags | (COMMAND_MASK << mePtr->type)) != TCL_OK) {
- return TCL_ERROR;
- }
- }
-
- /*
* 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->label == NULL) {
+ if (mePtr->labelPtr == NULL) {
mePtr->labelLength = 0;
} else {
- mePtr->labelLength = strlen(mePtr->label);
+ Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength);
}
- if (mePtr->accel == NULL) {
+ if (mePtr->accelPtr == NULL) {
mePtr->accelLength = 0;
} else {
- mePtr->accelLength = strlen(mePtr->accel);
+ Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength);
}
/*
@@ -1464,9 +1663,8 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
* cascades have to be updated.
*/
- if ((mePtr->type == CASCADE_ENTRY) && (mePtr->name != NULL)) {
+ if ((mePtr->type == CASCADE_ENTRY) && (mePtr->namePtr != NULL)) {
TkMenuEntry *cascadeEntryPtr;
- TkMenu *cascadeMenuPtr;
int alreadyThere;
TkMenuReferences *menuRefPtr;
char *oldHashKey = NULL; /* Initialization only needed to
@@ -1482,19 +1680,18 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
* BUG: We are not recloning for special case #3 yet.
*/
+ name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
if (mePtr->childMenuRefPtr != NULL) {
oldHashKey = Tcl_GetHashKey(TkGetMenuHashTable(menuPtr->interp),
mePtr->childMenuRefPtr->hashEntryPtr);
- if (strcmp(oldHashKey, mePtr->name) != 0) {
+ if (strcmp(oldHashKey, name) != 0) {
UnhookCascadeEntry(mePtr);
}
}
if ((mePtr->childMenuRefPtr == NULL)
- || (strcmp(oldHashKey, mePtr->name) != 0)) {
- menuRefPtr = TkCreateMenuReferences(menuPtr->interp,
- mePtr->name);
- cascadeMenuPtr = menuRefPtr->menuPtr;
+ || (strcmp(oldHashKey, name) != 0)) {
+ menuRefPtr = TkCreateMenuReferences(menuPtr->interp, name);
mePtr->childMenuRefPtr = menuRefPtr;
if (menuRefPtr->parentEntryPtr == NULL) {
@@ -1531,52 +1728,15 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
return TCL_ERROR;
}
- if ((mePtr->type == CHECK_BUTTON_ENTRY)
- || (mePtr->type == RADIO_BUTTON_ENTRY)) {
- char *value;
-
- if (mePtr->name == NULL) {
- mePtr->name =
- (char *) ckalloc((unsigned) (mePtr->labelLength + 1));
- strcpy(mePtr->name, (mePtr->label == NULL) ? "" : mePtr->label);
- }
- if (mePtr->onValue == NULL) {
- mePtr->onValue = (char *) ckalloc((unsigned)
- (mePtr->labelLength + 1));
- strcpy(mePtr->onValue, (mePtr->label == NULL) ? "" : mePtr->label);
- }
-
- /*
- * 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.
- */
-
- value = Tcl_GetVar(menuPtr->interp, mePtr->name, TCL_GLOBAL_ONLY);
- mePtr->entryFlags &= ~ENTRY_SELECTED;
- if (value != NULL) {
- if (strcmp(value, mePtr->onValue) == 0) {
- mePtr->entryFlags |= ENTRY_SELECTED;
- }
- } else {
- Tcl_SetVar(menuPtr->interp, mePtr->name,
- (mePtr->type == CHECK_BUTTON_ENTRY) ? mePtr->offValue : "",
- TCL_GLOBAL_ONLY);
- }
- Tcl_TraceVar(menuPtr->interp, mePtr->name,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- MenuVarProc, (ClientData) mePtr);
- }
-
/*
* 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->imageString != NULL) {
- image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, mePtr->imageString,
+ if (mePtr->imagePtr != NULL) {
+ char *imageString = Tcl_GetStringFromObj(mePtr->imagePtr, NULL);
+ image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, imageString,
TkMenuImageProc, (ClientData) mePtr);
if (image == NULL) {
return TCL_ERROR;
@@ -1588,8 +1748,10 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
Tk_FreeImage(mePtr->image);
}
mePtr->image = image;
- if (mePtr->selectImageString != NULL) {
- image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, mePtr->selectImageString,
+ if (mePtr->selectImagePtr != NULL) {
+ char *selectImageString = Tcl_GetStringFromObj(
+ mePtr->selectImagePtr, NULL);
+ image = Tk_GetImage(menuPtr->interp, menuPtr->tkwin, selectImageString,
TkMenuSelectImageProc, (ClientData) mePtr);
if (image == NULL) {
return TCL_ERROR;
@@ -1602,7 +1764,71 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
}
mePtr->selectImage = image;
- TkEventuallyRecomputeMenu(menuPtr);
+ if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY)) {
+ Tcl_Obj *valuePtr;
+ char *name;
+
+ if (mePtr->namePtr == NULL) {
+ if (mePtr->labelPtr == NULL) {
+ mePtr->namePtr = NULL;
+ } else {
+ mePtr->namePtr = Tcl_DuplicateObj(mePtr->labelPtr);
+ Tcl_IncrRefCount(mePtr->namePtr);
+ }
+ }
+ if (mePtr->onValuePtr == NULL) {
+ if (mePtr->labelPtr == NULL) {
+ mePtr->onValuePtr = NULL;
+ } else {
+ mePtr->onValuePtr = Tcl_DuplicateObj(mePtr->labelPtr);
+ Tcl_IncrRefCount(mePtr->onValuePtr);
+ }
+ }
+
+ /*
+ * 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) {
+ char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ valuePtr = Tcl_GetObjVar2(menuPtr->interp, name, NULL,
+ TCL_GLOBAL_ONLY);
+ } else {
+ valuePtr = NULL;
+ }
+ mePtr->entryFlags &= ~ENTRY_SELECTED;
+ if (valuePtr != NULL) {
+ if (mePtr->onValuePtr != NULL) {
+ char *value = Tcl_GetStringFromObj(valuePtr, NULL);
+ char *onValue = Tcl_GetStringFromObj(mePtr->onValuePtr,
+ NULL);
+
+
+ if (strcmp(value, onValue) == 0) {
+ mePtr->entryFlags |= ENTRY_SELECTED;
+ }
+ }
+ } else {
+ if (mePtr->namePtr != NULL) {
+ char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ Tcl_SetObjVar2(menuPtr->interp, name, NULL,
+ (mePtr->type == CHECK_BUTTON_ENTRY)
+ ? mePtr->offValuePtr :
+ Tcl_NewStringObj("", 0),
+ TCL_GLOBAL_ONLY);
+ }
+ }
+ if (mePtr->namePtr != NULL) {
+ name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ Tcl_TraceVar(menuPtr->interp, name,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, (ClientData) mePtr);
+ }
+ }
return TCL_OK;
}
@@ -1610,13 +1836,78 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
/*
*----------------------------------------------------------------------
*
+ * ConfigureMenuEntry --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * 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. */
+{
+ 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 ((mePtr->namePtr != NULL)
+ && ((mePtr->type == CHECK_BUTTON_ENTRY)
+ || (mePtr->type == RADIO_BUTTON_ENTRY))) {
+ char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ Tcl_UntraceVar(menuPtr->interp, name,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuVarProc, (ClientData) mePtr);
+ }
+
+ result = TCL_OK;
+ if (menuPtr->tkwin != NULL) {
+ if (Tk_SetOptions(menuPtr->interp, (char *) mePtr,
+ mePtr->optionTable, objc, objv, menuPtr->tkwin,
+ &errorStruct, (int *) NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ result = PostProcessEntry(mePtr);
+ if (result != TCL_OK) {
+ Tk_RestoreSavedOptions(&errorStruct);
+ PostProcessEntry(mePtr);
+ }
+ Tk_FreeSavedOptions(&errorStruct);
+ }
+
+ TkEventuallyRecomputeMenu(menuPtr);
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ConfigureMenuCloneEntries --
*
* Calls ConfigureMenuEntry for each menu in the clone chain.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information such as label and accelerator get
@@ -1626,22 +1917,21 @@ ConfigureMenuEntry(mePtr, argc, argv, flags)
*/
static int
-ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
+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 argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
- int flags; /* Additional flags to pass to
- * Tk_ConfigureWidget. */
+ int objc; /* Number of valid entries in argv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
{
TkMenuEntry *mePtr;
TkMenu *menuListPtr;
- char *oldCascadeName = NULL, *newMenuName = NULL;
- int cascadeEntryChanged;
+ int cascadeEntryChanged = 0;
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
@@ -1653,21 +1943,47 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
mePtr = menuPtr->masterMenuPtr->entries[index];
if (mePtr->type == CASCADE_ENTRY) {
- oldCascadeName = mePtr->name;
+ oldCascadePtr = mePtr->namePtr;
+ if (oldCascadePtr != NULL) {
+ Tcl_IncrRefCount(oldCascadePtr);
+ }
}
- if (ConfigureMenuEntry(mePtr, argc, argv, flags) != TCL_OK) {
+ if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- cascadeEntryChanged = (mePtr->type == CASCADE_ENTRY)
- && (oldCascadeName != mePtr->name);
+ if (mePtr->type == CASCADE_ENTRY) {
+ char *oldCascadeName;
+
+ if (mePtr->namePtr != NULL) {
+ newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ } else {
+ newCascadeName = NULL;
+ }
+
+ if ((oldCascadePtr == NULL) && (mePtr->namePtr == NULL)) {
+ cascadeEntryChanged = 0;
+ } else if (((oldCascadePtr == NULL) && (mePtr->namePtr != NULL))
+ || ((oldCascadePtr != NULL)
+ && (mePtr->namePtr == NULL))) {
+ cascadeEntryChanged = 1;
+ } else {
+ oldCascadeName = Tcl_GetStringFromObj(oldCascadePtr,
+ NULL);
+ cascadeEntryChanged = (strcmp(oldCascadeName, newCascadeName)
+ == 0);
+ }
+ if (oldCascadePtr != NULL) {
+ Tcl_DecrRefCount(oldCascadePtr);
+ }
+ }
if (cascadeEntryChanged) {
- newMenuName = mePtr->name;
- if (newMenuName != NULL) {
+ if (mePtr->namePtr != NULL) {
+ newCascadeName = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
cascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp,
- mePtr->name);
+ newCascadeName);
}
}
@@ -1677,9 +1993,9 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
mePtr = menuListPtr->entries[index];
- if (cascadeEntryChanged && (mePtr->name != NULL)) {
- oldCascadeMenuRefPtr = TkFindMenuReferences(menuPtr->interp,
- mePtr->name);
+ if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
+ oldCascadeMenuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
+ mePtr->namePtr);
if ((oldCascadeMenuRefPtr != NULL)
&& (oldCascadeMenuRefPtr->menuPtr != NULL)) {
@@ -1687,25 +2003,36 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
}
}
- if (ConfigureMenuEntry(mePtr, argc, argv, flags) != TCL_OK) {
+ if (ConfigureMenuEntry(mePtr, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- if (cascadeEntryChanged && (newMenuName != NULL)) {
+ if (cascadeEntryChanged && (mePtr->namePtr != NULL)) {
if (cascadeMenuRefPtr->menuPtr != NULL) {
- char *newArgV[2];
- char *newCloneName;
-
- newCloneName = TkNewMenuName(menuPtr->interp,
- Tk_PathName(menuListPtr->tkwin),
+ Tcl_Obj *newObjv[2];
+ Tcl_Obj *newCloneNamePtr;
+ Tcl_Obj *pathNamePtr = Tcl_NewStringObj(
+ Tk_PathName(menuListPtr->tkwin), -1);
+ Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
+ Tcl_Obj *menuObjPtr = Tcl_NewStringObj("menu", -1);
+
+ Tcl_IncrRefCount(pathNamePtr);
+ newCloneNamePtr = TkNewMenuName(menuPtr->interp,
+ pathNamePtr,
cascadeMenuRefPtr->menuPtr);
- CloneMenu(cascadeMenuRefPtr->menuPtr, newCloneName,
- "normal");
-
- newArgV[0] = "-menu";
- newArgV[1] = newCloneName;
- ConfigureMenuEntry(mePtr, 2, newArgV, flags);
- ckfree(newCloneName);
+ Tcl_IncrRefCount(newCloneNamePtr);
+ Tcl_IncrRefCount(normalPtr);
+ CloneMenu(cascadeMenuRefPtr->menuPtr, newCloneNamePtr,
+ normalPtr);
+
+ newObjv[0] = menuObjPtr;
+ newObjv[1] = newCloneNamePtr;
+ Tcl_IncrRefCount(menuObjPtr);
+ ConfigureMenuEntry(mePtr, 2, newObjv);
+ Tcl_DecrRefCount(newCloneNamePtr);
+ Tcl_DecrRefCount(pathNamePtr);
+ Tcl_DecrRefCount(normalPtr);
+ Tcl_DecrRefCount(menuObjPtr);
}
}
}
@@ -1724,7 +2051,7 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
* 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 interp->result.
+ * one). Otherwise an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -1733,38 +2060,39 @@ ConfigureMenuCloneEntries(interp, menuPtr, index, argc, argv, flags)
*/
int
-TkGetMenuIndex(interp, menuPtr, string, lastOK, indexPtr)
+TkGetMenuIndex(interp, menuPtr, objPtr, lastOK, indexPtr)
Tcl_Interp *interp; /* For error messages. */
TkMenu *menuPtr; /* Menu for which the index is being
* specified. */
- char *string; /* 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 relief. */
+ int *indexPtr; /* Where to store converted index. */
{
int i;
+ char *string = Tcl_GetStringFromObj(objPtr, NULL);
if ((string[0] == 'a') && (strcmp(string, "active") == 0)) {
*indexPtr = menuPtr->active;
- return TCL_OK;
+ goto success;
}
if (((string[0] == 'l') && (strcmp(string, "last") == 0))
|| ((string[0] == 'e') && (strcmp(string, "end") == 0))) {
*indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1);
- return TCL_OK;
+ goto success;
}
if ((string[0] == 'n') && (strcmp(string, "none") == 0)) {
*indexPtr = -1;
- return TCL_OK;
+ goto success;
}
if (string[0] == '@') {
if (GetIndexFromCoords(interp, menuPtr, string, indexPtr)
== TCL_OK) {
- return TCL_OK;
+ goto success;
}
}
@@ -1780,25 +2108,29 @@ TkGetMenuIndex(interp, menuPtr, string, lastOK, indexPtr)
i = -1;
}
*indexPtr = i;
- return TCL_OK;
+ goto success;
}
Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
}
for (i = 0; i < menuPtr->numEntries; i++) {
- char *label;
-
- label = menuPtr->entries[i]->label;
+ Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr;
+ char *label = (labelPtr == NULL) ? NULL
+ : Tcl_GetStringFromObj(labelPtr, NULL);
+
if ((label != NULL)
- && (Tcl_StringMatch(menuPtr->entries[i]->label, string))) {
+ && (Tcl_StringMatch(label, string))) {
*indexPtr = i;
- return TCL_OK;
+ goto success;
}
}
Tcl_AppendResult(interp, "bad menu entry index \"",
string, "\"", (char *) NULL);
return TCL_ERROR;
+
+success:
+ return TCL_OK;
}
/*
@@ -1834,7 +2166,6 @@ MenuCmdDeletedProc(clientData)
*/
if (tkwin != NULL) {
- menuPtr->tkwin = NULL;
Tk_DestroyWindow(tkwin);
}
}
@@ -1890,41 +2221,53 @@ MenuNewEntry(menuPtr, index, type)
mePtr = (TkMenuEntry *) ckalloc(sizeof(TkMenuEntry));
menuPtr->entries[index] = mePtr;
mePtr->type = type;
+ mePtr->optionTable = menuPtr->optionTablesPtr->entryOptionTables[type];
mePtr->menuPtr = menuPtr;
- mePtr->label = NULL;
+ mePtr->labelPtr = NULL;
mePtr->labelLength = 0;
mePtr->underline = -1;
- mePtr->bitmap = None;
- mePtr->imageString = NULL;
+ mePtr->bitmapPtr = NULL;
+ mePtr->imagePtr = NULL;
mePtr->image = NULL;
- mePtr->selectImageString = NULL;
+ mePtr->selectImagePtr = NULL;
mePtr->selectImage = NULL;
- mePtr->accel = NULL;
+ mePtr->accelPtr = NULL;
mePtr->accelLength = 0;
- mePtr->state = tkNormalUid;
- mePtr->border = NULL;
- mePtr->fg = NULL;
- mePtr->activeBorder = NULL;
- mePtr->activeFg = NULL;
- mePtr->tkfont = NULL;
- mePtr->indicatorOn = 1;
- mePtr->indicatorFg = NULL;
- mePtr->columnBreak = 0;
- mePtr->hideMargin = 0;
- mePtr->command = NULL;
- mePtr->name = NULL;
+ mePtr->statePtr = Tcl_NewStringObj("disabled", -1);
+ Tcl_IncrRefCount(mePtr->statePtr);
+ mePtr->borderPtr = NULL;
+ mePtr->fgPtr = NULL;
+ mePtr->activeBorderPtr = NULL;
+ mePtr->activeFgPtr = NULL;
+ mePtr->fontPtr = NULL;
+ mePtr->indicatorOnPtr = Tcl_NewBooleanObj(1);
+ Tcl_IncrRefCount(mePtr->indicatorOnPtr);
+ mePtr->indicatorFgPtr = NULL;
+ mePtr->columnBreakPtr = Tcl_NewBooleanObj(0);
+ Tcl_IncrRefCount(mePtr->columnBreakPtr);
+ mePtr->hideMarginPtr = Tcl_NewBooleanObj(0);
+ Tcl_IncrRefCount(mePtr->hideMarginPtr);
+ mePtr->commandPtr = NULL;
+ mePtr->namePtr = NULL;
mePtr->childMenuRefPtr = NULL;
- mePtr->onValue = NULL;
- mePtr->offValue = NULL;
+ mePtr->onValuePtr = NULL;
+ mePtr->offValuePtr = NULL;
mePtr->entryFlags = 0;
mePtr->index = index;
mePtr->nextCascadePtr = NULL;
+ if (Tk_InitOptions(menuPtr->interp, (char *) mePtr,
+ mePtr->optionTable, menuPtr->tkwin) != TCL_OK) {
+ ckfree((char *) mePtr);
+ return NULL;
+ }
TkMenuInitializeEntryDrawingFields(mePtr);
if (TkpMenuNewEntry(mePtr) != TCL_OK) {
+ Tk_FreeConfigOptions((char *) mePtr, mePtr->optionTable,
+ menuPtr->tkwin);
ckfree((char *) mePtr);
return NULL;
}
-
+
return mePtr;
}
@@ -1946,25 +2289,25 @@ MenuNewEntry(menuPtr, index, type)
*/
static int
-MenuAddOrInsert(interp, menuPtr, indexString, argc, argv)
+MenuAddOrInsert(interp, menuPtr, indexPtr, objc, objv)
Tcl_Interp *interp; /* Used for error reporting. */
TkMenu *menuPtr; /* Widget in which to create new
* entry. */
- char *indexString; /* String describing index at which
+ Tcl_Obj *indexPtr; /* Object describing index at which
* to insert. NULL means insert at
* end. */
- int argc; /* Number of elements in argv. */
- char **argv; /* Arguments to command: first arg
+ 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 c, type, index;
- size_t length;
+ int type, index;
TkMenuEntry *mePtr;
TkMenu *menuListPtr;
+ int tearoff;
- if (indexString != NULL) {
- if (TkGetMenuIndex(interp, menuPtr, indexString, 1, &index)
+ if (indexPtr != NULL) {
+ if (TkGetMenuIndex(interp, menuPtr, indexPtr, 1, &index)
!= TCL_OK) {
return TCL_ERROR;
}
@@ -1972,11 +2315,13 @@ MenuAddOrInsert(interp, menuPtr, indexString, argc, argv)
index = menuPtr->numEntries;
}
if (index < 0) {
+ char *indexString = Tcl_GetStringFromObj(indexPtr, NULL);
Tcl_AppendResult(interp, "bad index \"", indexString, "\"",
(char *) NULL);
return TCL_ERROR;
}
- if (menuPtr->tearOff && (index == 0)) {
+ Tcl_GetBooleanFromObj(NULL, menuPtr->tearoffPtr, &tearoff);
+ if (tearoff && (index == 0)) {
index = 1;
}
@@ -1984,30 +2329,11 @@ MenuAddOrInsert(interp, menuPtr, indexString, argc, argv)
* Figure out the type of the new entry.
*/
- c = argv[0][0];
- length = strlen(argv[0]);
- if ((c == 'c') && (strncmp(argv[0], "cascade", length) == 0)
- && (length >= 2)) {
- type = CASCADE_ENTRY;
- } else if ((c == 'c') && (strncmp(argv[0], "checkbutton", length) == 0)
- && (length >= 2)) {
- type = CHECK_BUTTON_ENTRY;
- } else if ((c == 'c') && (strncmp(argv[0], "command", length) == 0)
- && (length >= 2)) {
- type = COMMAND_ENTRY;
- } else if ((c == 'r')
- && (strncmp(argv[0], "radiobutton", length) == 0)) {
- type = RADIO_BUTTON_ENTRY;
- } else if ((c == 's')
- && (strncmp(argv[0], "separator", length) == 0)) {
- type = SEPARATOR_ENTRY;
- } else {
- Tcl_AppendResult(interp, "bad menu entry type \"",
- argv[0], "\": must be cascade, checkbutton, ",
- "command, radiobutton, or separator", (char *) NULL);
+ if (Tcl_GetIndexFromObj(interp, objv[0], menuEntryTypeStrings,
+ "menu entry type", 0, &type) != TCL_OK) {
return TCL_ERROR;
}
-
+
/*
* Now we have to add an entry for every instance related to this menu.
*/
@@ -2019,9 +2345,9 @@ MenuAddOrInsert(interp, menuPtr, indexString, argc, argv)
if (mePtr == NULL) {
return TCL_ERROR;
}
- if (ConfigureMenuEntry(mePtr, argc-1, argv+1, 0) != TCL_OK) {
+ if (ConfigureMenuEntry(mePtr, objc - 1, objv + 1) != TCL_OK) {
TkMenu *errorMenuPtr;
- int i;
+ int i;
for (errorMenuPtr = menuPtr->masterMenuPtr;
errorMenuPtr != NULL;
@@ -2054,28 +2380,40 @@ MenuAddOrInsert(interp, menuPtr, indexString, argc, argv)
*/
if ((menuPtr != menuListPtr) && (type == CASCADE_ENTRY)) {
- if ((mePtr->name != NULL) && (mePtr->childMenuRefPtr != NULL)
+ if ((mePtr->namePtr != NULL)
+ && (mePtr->childMenuRefPtr != NULL)
&& (mePtr->childMenuRefPtr->menuPtr != NULL)) {
TkMenu *cascadeMenuPtr =
mePtr->childMenuRefPtr->menuPtr->masterMenuPtr;
- char *newCascadeName;
- char *newArgv[2];
+ Tcl_Obj *newCascadePtr;
+ Tcl_Obj *menuNamePtr = Tcl_NewStringObj("-menu", -1);
+ Tcl_Obj *windowNamePtr =
+ Tcl_NewStringObj(Tk_PathName(menuListPtr->tkwin), -1);
+ Tcl_Obj *normalPtr = Tcl_NewStringObj("normal", -1);
+ Tcl_Obj *newObjv[2];
TkMenuReferences *menuRefPtr;
-
- newCascadeName = TkNewMenuName(menuListPtr->interp,
- Tk_PathName(menuListPtr->tkwin),
- cascadeMenuPtr);
- CloneMenu(cascadeMenuPtr, newCascadeName, "normal");
+
+ Tcl_IncrRefCount(windowNamePtr);
+ newCascadePtr = TkNewMenuName(menuListPtr->interp,
+ windowNamePtr, cascadeMenuPtr);
+ Tcl_IncrRefCount(newCascadePtr);
+ Tcl_IncrRefCount(normalPtr);
+ CloneMenu(cascadeMenuPtr, newCascadePtr, normalPtr);
- menuRefPtr = TkFindMenuReferences(menuListPtr->interp,
- newCascadeName);
+ menuRefPtr = TkFindMenuReferencesObj(menuListPtr->interp,
+ newCascadePtr);
if (menuRefPtr == NULL) {
panic("CloneMenu failed inside of MenuAddOrInsert.");
}
- newArgv[0] = "-menu";
- newArgv[1] = newCascadeName;
- ConfigureMenuEntry(mePtr, 2, newArgv, 0);
- ckfree(newCascadeName);
+ newObjv[0] = menuNamePtr;
+ newObjv[1] = newCascadePtr;
+ Tcl_IncrRefCount(menuNamePtr);
+ Tcl_IncrRefCount(newCascadePtr);
+ ConfigureMenuEntry(mePtr, 2, newObjv);
+ Tcl_DecrRefCount(newCascadePtr);
+ Tcl_DecrRefCount(menuNamePtr);
+ Tcl_DecrRefCount(windowNamePtr);
+ Tcl_DecrRefCount(normalPtr);
}
}
}
@@ -2112,6 +2450,8 @@ MenuVarProc(clientData, interp, name1, name2, flags)
TkMenuEntry *mePtr = (TkMenuEntry *) clientData;
TkMenu *menuPtr;
char *value;
+ char *name = Tcl_GetStringFromObj(mePtr->namePtr, NULL);
+ char *onValue;
menuPtr = mePtr->menuPtr;
@@ -2123,7 +2463,7 @@ MenuVarProc(clientData, interp, name1, name2, flags)
if (flags & TCL_TRACE_UNSETS) {
mePtr->entryFlags &= ~ENTRY_SELECTED;
if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
- Tcl_TraceVar(interp, mePtr->name,
+ Tcl_TraceVar(interp, name,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
MenuVarProc, clientData);
}
@@ -2137,17 +2477,22 @@ MenuVarProc(clientData, interp, name1, name2, flags)
* the menu entry.
*/
- value = Tcl_GetVar(interp, mePtr->name, TCL_GLOBAL_ONLY);
+ value = Tcl_GetVar(interp, name, TCL_GLOBAL_ONLY);
if (value == NULL) {
value = "";
}
- if (strcmp(value, mePtr->onValue) == 0) {
- if (mePtr->entryFlags & ENTRY_SELECTED) {
+ if (mePtr->onValuePtr != NULL) {
+ onValue = Tcl_GetStringFromObj(mePtr->onValuePtr, NULL);
+ if (strcmp(value, onValue) == 0) {
+ if (mePtr->entryFlags & ENTRY_SELECTED) {
+ return (char *) NULL;
+ }
+ mePtr->entryFlags |= ENTRY_SELECTED;
+ } else if (mePtr->entryFlags & ENTRY_SELECTED) {
+ mePtr->entryFlags &= ~ENTRY_SELECTED;
+ } else {
return (char *) NULL;
}
- mePtr->entryFlags |= ENTRY_SELECTED;
- } else if (mePtr->entryFlags & ENTRY_SELECTED) {
- mePtr->entryFlags &= ~ENTRY_SELECTED;
} else {
return (char *) NULL;
}
@@ -2184,6 +2529,7 @@ TkActivateMenuEntry(menuPtr, index)
{
register TkMenuEntry *mePtr;
int result = TCL_OK;
+ int state;
if (menuPtr->active >= 0) {
mePtr = menuPtr->entries[menuPtr->active];
@@ -2193,15 +2539,21 @@ TkActivateMenuEntry(menuPtr, index)
* might already have been changed to disabled).
*/
- if (mePtr->state == tkActiveUid) {
- mePtr->state = tkNormalUid;
+ Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
+ NULL, 0, &state);
+ if (state == ENTRY_ACTIVE) {
+ Tcl_DecrRefCount(mePtr->statePtr);
+ mePtr->statePtr = Tcl_NewStringObj("normal", -1);
+ Tcl_IncrRefCount(mePtr->statePtr);
}
TkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]);
}
menuPtr->active = index;
if (index >= 0) {
mePtr = menuPtr->entries[index];
- mePtr->state = tkActiveUid;
+ Tcl_DecrRefCount(mePtr->statePtr);
+ mePtr->statePtr = Tcl_NewStringObj("active", -1);
+ Tcl_IncrRefCount(mePtr->statePtr);
TkEventuallyRedrawMenu(menuPtr, mePtr);
}
return result;
@@ -2237,9 +2589,13 @@ TkPostCommand(menuPtr)
* the menu's geometry if needed.
*/
- if (menuPtr->postCommand != NULL) {
- result = TkCopyAndGlobalEval(menuPtr->interp,
- menuPtr->postCommand);
+ if (menuPtr->postCommandPtr != NULL) {
+ Tcl_Obj *postCommandPtr = menuPtr->postCommandPtr;
+
+ Tcl_IncrRefCount(postCommandPtr);
+ result = Tcl_EvalObj(menuPtr->interp, postCommandPtr,
+ TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(postCommandPtr);
if (result != TCL_OK) {
return result;
}
@@ -2269,64 +2625,54 @@ TkPostCommand(menuPtr)
*/
static int
-CloneMenu(menuPtr, newMenuName, newMenuTypeString)
+CloneMenu(menuPtr, newMenuNamePtr, newMenuTypePtr)
TkMenu *menuPtr; /* The menu we are going to clone */
- char *newMenuName; /* The name to give the new menu */
- char *newMenuTypeString; /* What kind of menu is this, a normal menu
+ 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;
- size_t length;
+ int menuType, i;
TkMenuReferences *menuRefPtr;
- Tcl_Obj *commandObjPtr;
+ Tcl_Obj *menuDupCommandArray[4];
- if (newMenuTypeString == NULL) {
+ if (newMenuTypePtr == NULL) {
menuType = MASTER_MENU;
} else {
- length = strlen(newMenuTypeString);
- if (strncmp(newMenuTypeString, "normal", length) == 0) {
- menuType = MASTER_MENU;
- } else if (strncmp(newMenuTypeString, "tearoff", length) == 0) {
- menuType = TEAROFF_MENU;
- } else if (strncmp(newMenuTypeString, "menubar", length) == 0) {
- menuType = MENUBAR;
- } else {
- Tcl_AppendResult(menuPtr->interp,
- "bad menu type - must be normal, tearoff, or menubar",
- (char *) NULL);
- return TCL_ERROR;
- }
+ if (Tcl_GetIndexFromObj(menuPtr->interp, newMenuTypePtr,
+ menuTypeStrings, "menu type", 0, &menuType) != TCL_OK) {
+ return TCL_ERROR;
+ }
}
- commandObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
- Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
- Tcl_NewStringObj("tkMenuDup", -1));
- Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
- Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1));
- Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
- Tcl_NewStringObj(newMenuName, -1));
- if ((newMenuTypeString == NULL) || (newMenuTypeString[0] == '\0')) {
- Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
- Tcl_NewStringObj("normal", -1));
+ menuDupCommandArray[0] = Tcl_NewStringObj("tkMenuDup", -1);
+ menuDupCommandArray[1] = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
+ menuDupCommandArray[2] = newMenuNamePtr;
+ if (newMenuTypePtr == NULL) {
+ menuDupCommandArray[3] = Tcl_NewStringObj("normal", -1);
} else {
- Tcl_ListObjAppendElement(menuPtr->interp, commandObjPtr,
- Tcl_NewStringObj(newMenuTypeString, -1));
+ menuDupCommandArray[3] = newMenuTypePtr;
+ }
+ for (i = 0; i < 4; i++) {
+ Tcl_IncrRefCount(menuDupCommandArray[i]);
}
- Tcl_IncrRefCount(commandObjPtr);
Tcl_Preserve((ClientData) menuPtr);
- returnResult = Tcl_EvalObj(menuPtr->interp, commandObjPtr);
- Tcl_DecrRefCount(commandObjPtr);
+ returnResult = Tcl_EvalObjv(menuPtr->interp, 4, menuDupCommandArray, "",
+ -1, 0);
+ for (i = 0; i < 4; i++) {
+ Tcl_DecrRefCount(menuDupCommandArray[i]);
+ }
/*
* Make sure the tcl command actually created the clone.
*/
if ((returnResult == TCL_OK) &&
- ((menuRefPtr = TkFindMenuReferences(menuPtr->interp, newMenuName))
- != (TkMenuReferences *) NULL)
+ ((menuRefPtr = TkFindMenuReferencesObj(menuPtr->interp,
+ newMenuNamePtr)) != (TkMenuReferences *) NULL)
&& (menuPtr->numEntries == menuRefPtr->menuPtr->numEntries)) {
TkMenu *newMenuPtr = menuRefPtr->menuPtr;
+ Tcl_Obj *newObjv[3];
char *newArgv[3];
int i, numElements;
@@ -2359,8 +2705,8 @@ CloneMenu(menuPtr, newMenuName, newMenuTypeString)
if (Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin,
newMenuPtr->interp, 2, newArgv) == TCL_OK) {
char *windowName;
- Tcl_Obj *bindingsPtr =
- Tcl_NewStringObj(newMenuPtr->interp->result, -1);
+ Tcl_Obj *bindingsPtr =
+ Tcl_DuplicateObj(Tcl_GetObjResult(newMenuPtr->interp));
Tcl_Obj *elementPtr;
Tcl_ListObjLength(newMenuPtr->interp, bindingsPtr, &numElements);
@@ -2372,11 +2718,12 @@ CloneMenu(menuPtr, newMenuName, newMenuTypeString)
== 0) {
Tcl_Obj *newElementPtr = Tcl_NewStringObj(
Tk_PathName(newMenuPtr->masterMenuPtr->tkwin), -1);
+ Tcl_IncrRefCount(newElementPtr);
Tcl_ListObjReplace(menuPtr->interp, bindingsPtr,
i + 1, 0, 1, &newElementPtr);
newArgv[2] = Tcl_GetStringFromObj(bindingsPtr, NULL);
- Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin,
- menuPtr->interp, 3, newArgv);
+ Tk_BindtagsCmd((ClientData)newMenuPtr->tkwin,
+ menuPtr->interp, 3, newArgv);
break;
}
}
@@ -2389,30 +2736,35 @@ CloneMenu(menuPtr, newMenuName, newMenuTypeString)
*/
for (i = 0; i < menuPtr->numEntries; i++) {
- char *newCascadeName;
TkMenuReferences *cascadeRefPtr;
TkMenu *oldCascadePtr;
if ((menuPtr->entries[i]->type == CASCADE_ENTRY)
- && (menuPtr->entries[i]->name != NULL)) {
+ && (menuPtr->entries[i]->namePtr != NULL)) {
cascadeRefPtr =
- TkFindMenuReferences(menuPtr->interp,
- menuPtr->entries[i]->name);
+ TkFindMenuReferencesObj(menuPtr->interp,
+ menuPtr->entries[i]->namePtr);
if ((cascadeRefPtr != NULL) && (cascadeRefPtr->menuPtr)) {
- char *nameString;
+ Tcl_Obj *windowNamePtr =
+ Tcl_NewStringObj(Tk_PathName(newMenuPtr->tkwin),
+ -1);
+ Tcl_Obj *newCascadePtr;
oldCascadePtr = cascadeRefPtr->menuPtr;
- nameString = Tk_PathName(newMenuPtr->tkwin);
- newCascadeName = TkNewMenuName(menuPtr->interp,
- nameString, oldCascadePtr);
- CloneMenu(oldCascadePtr, newCascadeName, NULL);
-
- newArgv[0] = "-menu";
- newArgv[1] = newCascadeName;
- ConfigureMenuEntry(newMenuPtr->entries[i], 2, newArgv,
- TK_CONFIG_ARGV_ONLY);
- ckfree(newCascadeName);
+ Tcl_IncrRefCount(windowNamePtr);
+ newCascadePtr = TkNewMenuName(menuPtr->interp,
+ windowNamePtr, oldCascadePtr);
+ Tcl_IncrRefCount(newCascadePtr);
+ CloneMenu(oldCascadePtr, newCascadePtr, NULL);
+
+ newObjv[0] = Tcl_NewStringObj("-menu", -1);
+ newObjv[1] = newCascadePtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ ConfigureMenuEntry(newMenuPtr->entries[i], 2, newObjv);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newCascadePtr);
+ Tcl_DecrRefCount(windowNamePtr);
}
}
}
@@ -2442,22 +2794,24 @@ CloneMenu(menuPtr, newMenuName, newMenuTypeString)
*/
static int
-MenuDoYPosition(interp, menuPtr, arg)
+MenuDoYPosition(interp, menuPtr, objPtr)
Tcl_Interp *interp;
TkMenu *menuPtr;
- char *arg;
+ Tcl_Obj *objPtr;
{
int index;
TkRecomputeMenu(menuPtr);
- if (TkGetMenuIndex(interp, menuPtr, arg, 0, &index) != TCL_OK) {
+ if (TkGetMenuIndex(interp, menuPtr, objPtr, 0, &index) != TCL_OK) {
goto error;
}
+ Tcl_ResetResult(interp);
if (index < 0) {
- interp->result = "0";
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
} else {
- sprintf(interp->result, "%d", menuPtr->entries[index]->y);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(menuPtr->entries[index]->y));
}
+
return TCL_OK;
error:
@@ -2507,7 +2861,8 @@ GetIndexFromCoords(interp, menuPtr, string, indexPtr)
goto error;
}
} else {
- x = menuPtr->borderWidth;
+ Tk_GetPixelsFromObj(interp, menuPtr->tkwin,
+ menuPtr->borderWidthPtr, &x);
}
for (i = 0; i < menuPtr->numEntries; i++) {
@@ -2583,65 +2938,66 @@ RecursivelyDeleteMenu(menuPtr)
*----------------------------------------------------------------------
*/
-char *
-TkNewMenuName(interp, parentName, menuPtr)
+Tcl_Obj *
+TkNewMenuName(interp, parentPtr, menuPtr)
Tcl_Interp *interp; /* The interp the new name has to live in.*/
- char *parentName; /* The prefix path of the new name. */
+ Tcl_Obj *parentPtr; /* The prefix path of the new name. */
TkMenu *menuPtr; /* The menu we are cloning. */
{
- Tcl_DString resultDString;
- Tcl_DString childDString;
+ Tcl_Obj *resultPtr = NULL; /* Initialization needed only to prevent
+ * compiler warning. */
+ Tcl_Obj *childPtr;
char *destString;
- int offset, i;
- int doDot = parentName[strlen(parentName) - 1] != '.';
+ int i;
+ int doDot;
Tcl_CmdInfo cmdInfo;
- char *returnString;
Tcl_HashTable *nameTablePtr = NULL;
TkWindow *winPtr = (TkWindow *) menuPtr->tkwin;
+ char *parentName = Tcl_GetStringFromObj(parentPtr, NULL);
+
if (winPtr->mainPtr != NULL) {
nameTablePtr = &(winPtr->mainPtr->nameTable);
}
-
- Tcl_DStringInit(&childDString);
- Tcl_DStringAppend(&childDString, Tk_PathName(menuPtr->tkwin), -1);
- for (destString = Tcl_DStringValue(&childDString);
+
+ doDot = parentName[strlen(parentName) - 1] != '.';
+
+ childPtr = Tcl_NewStringObj(Tk_PathName(menuPtr->tkwin), -1);
+ for (destString = Tcl_GetStringFromObj(childPtr, NULL);
*destString != '\0'; destString++) {
if (*destString == '.') {
*destString = '#';
}
}
- offset = 0;
-
for (i = 0; ; i++) {
if (i == 0) {
- Tcl_DStringInit(&resultDString);
- Tcl_DStringAppend(&resultDString, parentName, -1);
+ resultPtr = Tcl_DuplicateObj(parentPtr);
if (doDot) {
- Tcl_DStringAppend(&resultDString, ".", -1);
+ Tcl_AppendToObj(resultPtr, ".", -1);
}
- Tcl_DStringAppend(&resultDString,
- Tcl_DStringValue(&childDString), -1);
- destString = Tcl_DStringValue(&resultDString);
+ Tcl_AppendObjToObj(resultPtr, childPtr);
} else {
- if (i == 1) {
- offset = Tcl_DStringLength(&resultDString);
- Tcl_DStringSetLength(&resultDString, offset + 10);
- destString = Tcl_DStringValue(&resultDString);
- }
- sprintf(destString + offset, "%d", i);
+ Tcl_Obj *intPtr;
+
+ Tcl_DecrRefCount(resultPtr);
+ resultPtr = Tcl_DuplicateObj(parentPtr);
+ if (doDot) {
+ Tcl_AppendToObj(resultPtr, ".", -1);
+ }
+ Tcl_AppendObjToObj(resultPtr, childPtr);
+ intPtr = Tcl_NewIntObj(i);
+ Tcl_AppendObjToObj(resultPtr, intPtr);
+ Tcl_DecrRefCount(intPtr);
}
+ destString = Tcl_GetStringFromObj(resultPtr, NULL);
if ((Tcl_GetCommandInfo(interp, destString, &cmdInfo) == 0)
&& ((nameTablePtr == NULL)
|| (Tcl_FindHashEntry(nameTablePtr, destString) == NULL))) {
break;
}
}
- returnString = ckalloc(strlen(destString) + 1);
- strcpy(returnString, destString);
- Tcl_DStringFree(&resultDString);
- Tcl_DStringFree(&childDString);
- return returnString;
+ Tcl_DecrRefCount(childPtr);
+ return resultPtr;
}
/*
@@ -2756,32 +3112,45 @@ TkSetWindowMenuBar(interp, tkwin, oldMenuName, menuName)
menuPtr = menuRefPtr->menuPtr;
if (menuPtr != NULL) {
- char *cloneMenuName;
+ Tcl_Obj *cloneMenuPtr;
TkMenuReferences *cloneMenuRefPtr;
- char *newArgv[4];
+ Tcl_Obj *newObjv[4];
+ 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.
*/
- cloneMenuName = TkNewMenuName(interp, Tk_PathName(tkwin),
+ Tcl_IncrRefCount(windowNamePtr);
+ cloneMenuPtr = TkNewMenuName(interp, windowNamePtr,
menuPtr);
- CloneMenu(menuPtr, cloneMenuName, "menubar");
+ Tcl_IncrRefCount(cloneMenuPtr);
+ Tcl_IncrRefCount(menubarPtr);
+ CloneMenu(menuPtr, cloneMenuPtr, menubarPtr);
- cloneMenuRefPtr = TkFindMenuReferences(interp, cloneMenuName);
+ cloneMenuRefPtr = TkFindMenuReferencesObj(interp, cloneMenuPtr);
if ((cloneMenuRefPtr != NULL)
&& (cloneMenuRefPtr->menuPtr != NULL)) {
+ Tcl_Obj *cursorPtr = Tcl_NewStringObj("-cursor", -1);
+ Tcl_Obj *nullPtr = Tcl_NewStringObj("", -1);
cloneMenuRefPtr->menuPtr->parentTopLevelPtr = tkwin;
menuBarPtr = cloneMenuRefPtr->menuPtr;
- newArgv[0] = "-cursor";
- newArgv[1] = "";
+ newObjv[0] = cursorPtr;
+ newObjv[1] = nullPtr;
+ Tcl_IncrRefCount(cursorPtr);
+ Tcl_IncrRefCount(nullPtr);
ConfigureMenu(menuPtr->interp, cloneMenuRefPtr->menuPtr,
- 2, newArgv, TK_CONFIG_ARGV_ONLY);
+ 2, newObjv);
+ Tcl_DecrRefCount(cursorPtr);
+ Tcl_DecrRefCount(nullPtr);
}
TkpSetWindowMenuBar(tkwin, menuBarPtr);
-
- ckfree(cloneMenuName);
+ Tcl_DecrRefCount(cloneMenuPtr);
+ Tcl_DecrRefCount(menubarPtr);
+ Tcl_DecrRefCount(windowNamePtr);
} else {
TkpSetWindowMenuBar(tkwin, NULL);
}
@@ -2948,6 +3317,35 @@ TkFindMenuReferences(interp, pathName)
/*
*----------------------------------------------------------------------
*
+ * TkFindMenuReferencesObj --
+ *
+ * Given a pathname, gives back a pointer to the TkMenuReferences
+ * structure.
+ *
+ * Results:
+ * 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkMenuReferences *
+TkFindMenuReferencesObj(interp, objPtr)
+ 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);
+ return TkFindMenuReferences(interp, pathName);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkFreeMenuReferences --
*
* This is called after one of the fields in a menu reference
diff --git a/generic/tkMenu.h b/generic/tkMenu.h
index 6f30d72..0a55913 100644
--- a/generic/tkMenu.h
+++ b/generic/tkMenu.h
@@ -3,12 +3,12 @@
*
* Declarations shared among all of the files that implement menu widgets.
*
- * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkMenu.h 1.60 97/06/20 14:43:21
+ * SCCS: @(#) tkMenu.h 1.71 98/01/20 16:39:03
*/
#ifndef _TKMENU
@@ -42,55 +42,59 @@ typedef struct TkMenuEntry {
int type; /* Type of menu entry; see below for
* valid types. */
struct TkMenu *menuPtr; /* Menu with which this entry is associated. */
- char *label; /* Main text label displayed in entry (NULL
- * if no label). Malloc'ed. */
+ Tk_OptionTable optionTable; /* Option table for this menu entry. */
+ Tcl_Obj *labelPtr; /* Main text label displayed in entry (NULL
+ * if no label). */
int labelLength; /* Number of non-NULL characters in label. */
- Tk_Uid state; /* State of button for display purposes:
+ Tcl_Obj *statePtr; /* State of button for display purposes:
* normal, active, or disabled. */
- int underline; /* Index of character to underline. */
- Pixmap bitmap; /* Bitmap to display in menu entry, or None.
+ int underline; /* Value of -underline option: specifies index
+ * of character to underline (<0 means don't
+ * underline anything). */
+ 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. */
- char *imageString; /* Name of image to display (malloc'ed), or
+ Tcl_Obj *imagePtr; /* Name of image to display, or
* NULL. If non-NULL, bitmap, text, and
* textVarName are ignored. */
Tk_Image image; /* Image to display in menu entry, or NULL if
* none. */
- char *selectImageString; /* Name of image to display when selected
- * (malloc'ed), or NULL. */
+ 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. */
- char *accel; /* Accelerator string displayed at right
+ 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
+ Tcl_Obj *indicatorOnPtr; /* True means draw indicator, false means
* don't draw it. */
/*
* Display attributes
*/
- Tk_3DBorder border; /* Structure used to draw background for
+ Tcl_Obj *borderPtr; /* Structure used to draw background for
* entry. NULL means use overall border
* for menu. */
- XColor *fg; /* Foreground color to use for entry. NULL
+ Tcl_Obj *fgPtr; /* Foreground color to use for entry. NULL
* means use foreground color from menu. */
- Tk_3DBorder activeBorder; /* Used to draw background and border when
+ Tcl_Obj *activeBorderPtr; /* Used to draw background and border when
* element is active. NULL means use
* activeBorder from menu. */
- XColor *activeFg; /* Foreground color to use when entry is
+ Tcl_Obj *activeFgPtr; /* Foreground color to use when entry is
* active. NULL means use active foreground
* from menu. */
- XColor *indicatorFg; /* Color for indicators in radio and check
+ Tcl_Obj *indicatorFgPtr; /* Color for indicators in radio and check
* button entries. NULL means use indicatorFg
* GC from menu. */
- Tk_Font tkfont; /* Text font for menu entries. NULL means
+ 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
+ Tcl_Obj *columnBreakPtr; /* If this is 0, this item appears below
* the item in front of it. If this is
* 1, this item starts a new column. */
- int hideMargin; /* If this is 0, then the item has enough
+ Tcl_Obj *hideMarginPtr; /* 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.
@@ -109,15 +113,15 @@ typedef struct TkMenuEntry {
* Information used to implement this entry's action:
*/
- char *command; /* Command to invoke when entry is invoked.
+ Tcl_Obj *commandPtr; /* Command to invoke when entry is invoked.
* Malloc'ed. */
- char *name; /* Name of variable (for check buttons and
+ Tcl_Obj *namePtr; /* Name of variable (for check buttons and
* radio buttons) or menu (for cascade
* entries). Malloc'ed.*/
- char *onValue; /* Value to store in variable when selected
+ Tcl_Obj *onValuePtr; /* Value to store in variable when selected
* (only for radio and check buttons).
* Malloc'ed. */
- char *offValue; /* Value to store in variable when not
+ Tcl_Obj *offValuePtr; /* Value to store in variable when not
* selected (only for check buttons).
* Malloc'ed. */
@@ -174,7 +178,7 @@ typedef struct TkMenuEntry {
* does not yet exist. */
TkMenuPlatformEntryData platformEntryData;
/* The data for the specific type of menu.
- * Depends on platform and menu type what
+ * Depends on platform and menu type what
* kind of options are in this structure.
*/
} TkMenuEntry;
@@ -186,9 +190,9 @@ typedef struct TkMenuEntry {
* 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 to
- * be filled.
+ * ENTRY_LAST_COLUMN: Used by the drawing code. If the entry is in
+ * the last column, the space to its right needs
+ * to be filled.
* ENTRY_PLATFORM_FLAG1 - 4 These flags are reserved for use by the
* platform-dependent implementation of menus
* and should not be used by anything else.
@@ -206,25 +210,22 @@ typedef struct TkMenuEntry {
* Types defined for MenuEntries:
*/
-#define COMMAND_ENTRY 0
-#define SEPARATOR_ENTRY 1
-#define CHECK_BUTTON_ENTRY 2
-#define RADIO_BUTTON_ENTRY 3
-#define CASCADE_ENTRY 4
-#define TEAROFF_ENTRY 5
+#define CASCADE_ENTRY 0
+#define CHECK_BUTTON_ENTRY 1
+#define COMMAND_ENTRY 2
+#define RADIO_BUTTON_ENTRY 3
+#define SEPARATOR_ENTRY 4
+#define TEAROFF_ENTRY 5
/*
- * Mask bits for above types:
+ * Menu states
*/
-#define COMMAND_MASK TK_CONFIG_USER_BIT
-#define SEPARATOR_MASK (TK_CONFIG_USER_BIT << 1)
-#define CHECK_BUTTON_MASK (TK_CONFIG_USER_BIT << 2)
-#define RADIO_BUTTON_MASK (TK_CONFIG_USER_BIT << 3)
-#define CASCADE_MASK (TK_CONFIG_USER_BIT << 4)
-#define TEAROFF_MASK (TK_CONFIG_USER_BIT << 5)
-#define ALL_MASK (COMMAND_MASK | SEPARATOR_MASK \
- | CHECK_BUTTON_MASK | RADIO_BUTTON_MASK | CASCADE_MASK | TEAROFF_MASK)
+EXTERN 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
@@ -248,7 +249,7 @@ typedef struct TkMenu {
* nothing active. */
int menuType; /* MASTER_MENU, TEAROFF_MENU, or MENUBAR.
* See below for definitions. */
- char *menuTypeName; /* Used to control whether created tkwin
+ Tcl_Obj *menuTypePtr; /* Used to control whether created tkwin
* is a toplevel or not. "normal", "menubar",
* or "toplevel" */
@@ -256,20 +257,21 @@ typedef struct TkMenu {
* Information used when displaying widget:
*/
- Tk_3DBorder border; /* Structure used to draw 3-D
+ Tcl_Obj *borderPtr; /* Structure used to draw 3-D
* border and background for menu. */
- int borderWidth; /* Width of border around whole menu. */
- Tk_3DBorder activeBorder; /* Used to draw background and border for
+ Tcl_Obj *borderWidthPtr; /* Width of border around whole menu. */
+ Tcl_Obj *activeBorderPtr; /* Used to draw background and border for
* active element (if any). */
- int activeBorderWidth; /* Width of border around active element. */
- int relief; /* 3-d effect: TK_RELIEF_RAISED, etc. */
- Tk_Font tkfont; /* Text font for menu entries. */
- XColor *fg; /* Foreground color for entries. */
- XColor *disabledFg; /* Foreground color when disabled. NULL
+ Tcl_Obj *activeBorderWidthPtr;
+ /* Width of border around active element. */
+ 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. */
- XColor *activeFg; /* Foreground color for active entry. */
- XColor *indicatorFg; /* Color for indicators in radio and check
+ 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
@@ -300,7 +302,7 @@ typedef struct TkMenu {
* Miscellaneous information:
*/
- int tearOff; /* 1 means this menu can be torn off. On some
+ Tcl_Obj *tearoffPtr; /* 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
@@ -308,17 +310,17 @@ typedef struct TkMenu {
* indicator (such as a dashed stripe) is
* drawn, and when the menu is selected, the
* tearoff is created. */
- char *title; /* The title to use when this menu is torn
+ 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. */
- char *tearOffCommand; /* If non-NULL, points to a command to
+ Tcl_Obj *tearoffCommandPtr; /* If non-NULL, points to a command to
* run whenever the menu is torn-off. */
- char *takeFocus; /* Value of -takefocus option; not used in
+ 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. */
- Tk_Cursor cursor; /* Current cursor for window, or None. */
- char *postCommand; /* Used to detect cycles in cascade hierarchy
+ 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. */
@@ -336,6 +338,9 @@ typedef struct TkMenu {
/* A pointer to the original menu for this
* 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. */
Tk_Window parentTopLevelPtr;/* If this menu is a menubar, this is the
* toplevel that owns the menu. Only applicable
* for menubar clones.
@@ -355,6 +360,13 @@ typedef struct TkMenu {
* 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
+ * multiple menus get changed during one
+ * ConfigureMenu call. */
} TkMenu;
/*
@@ -402,6 +414,16 @@ typedef struct TkMenuReferences {
} TkMenuReferences;
/*
+ * 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. */
+} TkMenuOptionTables;
+
+/*
* Flag bits for menus:
*
* REDRAW_PENDING: Non-zero means a DoWhenIdle handler
@@ -448,13 +470,6 @@ typedef struct TkMenuReferences {
#define DECORATION_BORDER_WIDTH 2
/*
- * Configuration specs. Needed for platform-specific default initializations.
- */
-
-EXTERN Tk_ConfigSpec tkMenuEntryConfigSpecs[];
-EXTERN Tk_ConfigSpec tkMenuConfigSpecs[];
-
-/*
* Menu-related procedures that are shared among Tk modules but not exported
* to the outside world:
*/
@@ -465,21 +480,26 @@ EXTERN void TkBindMenu _ANSI_ARGS_((
Tk_Window tkwin, TkMenu *menuPtr));
EXTERN TkMenuReferences *
TkCreateMenuReferences _ANSI_ARGS_((Tcl_Interp *interp,
- char *pathName));
+ char *name));
EXTERN void TkDestroyMenu _ANSI_ARGS_((TkMenu *menuPtr));
-EXTERN void TkEventuallyRecomputeMenu _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 *pathName));
+ char *name));
+EXTERN TkMenuReferences *
+ TkFindMenuReferencesObj _ANSI_ARGS_((
+ Tcl_Interp *interp, Tcl_Obj *namePtr));
EXTERN void TkFreeMenuReferences _ANSI_ARGS_((
TkMenuReferences *menuRefPtr));
EXTERN Tcl_HashTable * TkGetMenuHashTable _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN int TkGetMenuIndex _ANSI_ARGS_((Tcl_Interp *interp,
- TkMenu *menuPtr, char *string, int lastOK,
+ TkMenu *menuPtr, Tcl_Obj *objPtr, int lastOK,
int *indexPtr));
-EXTERN void TkMenuInitializeDrawingFields _ANSI_ARGS_((TkMenu *menuPtr));
+EXTERN void TkMenuInitializeDrawingFields _ANSI_ARGS_((
+ TkMenu *menuPtr));
EXTERN void TkMenuInitializeEntryDrawingFields _ANSI_ARGS_((
TkMenuEntry *mePtr));
EXTERN int TkInvokeMenu _ANSI_ARGS_((Tcl_Interp *interp,
@@ -501,8 +521,8 @@ EXTERN void TkMenuSelectImageProc _ANSI_ARGS_
((ClientData clientData, int x, int y,
int width, int height, int imgWidth,
int imgHeight));
-EXTERN char * TkNewMenuName _ANSI_ARGS_((Tcl_Interp *interp,
- char *parentName, TkMenu *menuPtr));
+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));
@@ -516,7 +536,8 @@ EXTERN void TkRecomputeMenu _ANSI_ARGS_((TkMenu *menuPtr));
* common code.
*/
-EXTERN void TkpComputeMenubarGeometry _ANSI_ARGS_((TkMenu *menuPtr));
+EXTERN void TkpComputeMenubarGeometry _ANSI_ARGS_((
+ TkMenu *menuPtr));
EXTERN void TkpComputeStandardMenuGeometry _ANSI_ARGS_
((TkMenu *menuPtr));
EXTERN int TkpConfigureMenuEntry
diff --git a/generic/tkMenuDraw.c b/generic/tkMenuDraw.c
index be218a0..373d59d 100644
--- a/generic/tkMenuDraw.c
+++ b/generic/tkMenuDraw.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkMenuDraw.c 1.46 97/10/28 14:26:00
+ * SCCS: @(#) tkMenuDraw.c 1.52 98/01/12 16:27:29
*/
#include "tkMenu.h"
@@ -31,7 +31,7 @@ static void DisplayMenu _ANSI_ARGS_((ClientData clientData));
* TkMenuInitializeDrawingFields --
*
* Fills in drawing fields of a new menu. Called when new menu is
- * created by Tk_MenuCmd.
+ * created by MenuCmd.
*
* Results:
* None.
@@ -188,6 +188,9 @@ TkMenuConfigureDrawOptions(menuPtr)
XGCValues gcValues;
GC newGC;
unsigned long mask;
+ Tk_3DBorder border, activeBorder;
+ Tk_Font tkfont;
+ XColor *fg, *activeFg, *indicatorFg;
/*
* A few options need special processing, such as setting the
@@ -195,11 +198,14 @@ TkMenuConfigureDrawOptions(menuPtr)
* defaults that couldn't be specified to Tk_ConfigureWidget.
*/
- Tk_SetBackgroundFromBorder(menuPtr->tkwin, menuPtr->border);
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
+ Tk_SetBackgroundFromBorder(menuPtr->tkwin, border);
- gcValues.font = Tk_FontId(menuPtr->tkfont);
- gcValues.foreground = menuPtr->fg->pixel;
- gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel;
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ gcValues.font = Tk_FontId(tkfont);
+ fg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->fgPtr);
+ gcValues.foreground = fg->pixel;
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
&gcValues);
if (menuPtr->textGC != None) {
@@ -207,17 +213,21 @@ TkMenuConfigureDrawOptions(menuPtr)
}
menuPtr->textGC = newGC;
- gcValues.font = Tk_FontId(menuPtr->tkfont);
- gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel;
- if (menuPtr->disabledFg != NULL) {
- gcValues.foreground = menuPtr->disabledFg->pixel;
+ gcValues.font = Tk_FontId(tkfont);
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
+ if (menuPtr->disabledFgPtr != NULL) {
+ XColor *disabledFg;
+
+ disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->disabledFgPtr);
+ gcValues.foreground = disabledFg->pixel;
mask = GCForeground|GCBackground|GCFont;
} else {
gcValues.foreground = gcValues.background;
mask = GCForeground;
if (menuPtr->gray == None) {
menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,
- Tk_GetUid("gray50"));
+ "gray50");
}
if (menuPtr->gray != None) {
gcValues.fill_style = FillStippled;
@@ -231,10 +241,10 @@ TkMenuConfigureDrawOptions(menuPtr)
}
menuPtr->disabledGC = newGC;
- gcValues.foreground = Tk_3DBorderColor(menuPtr->border)->pixel;
+ gcValues.foreground = Tk_3DBorderColor(border)->pixel;
if (menuPtr->gray == None) {
menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin,
- Tk_GetUid("gray50"));
+ "gray50");
}
if (menuPtr->gray != None) {
gcValues.fill_style = FillStippled;
@@ -247,10 +257,12 @@ TkMenuConfigureDrawOptions(menuPtr)
}
menuPtr->disabledImageGC = newGC;
- gcValues.font = Tk_FontId(menuPtr->tkfont);
- gcValues.foreground = menuPtr->activeFg->pixel;
- gcValues.background =
- Tk_3DBorderColor(menuPtr->activeBorder)->pixel;
+ gcValues.font = Tk_FontId(tkfont);
+ activeFg = Tk_GetColorFromObj(menuPtr->tkwin, menuPtr->activeFgPtr);
+ gcValues.foreground = activeFg->pixel;
+ activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ menuPtr->activeBorderPtr);
+ gcValues.background = Tk_3DBorderColor(activeBorder)->pixel;
newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
&gcValues);
if (menuPtr->activeGC != None) {
@@ -258,8 +270,10 @@ TkMenuConfigureDrawOptions(menuPtr)
}
menuPtr->activeGC = newGC;
- gcValues.foreground = menuPtr->indicatorFg->pixel;
- gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel;
+ indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->indicatorFgPtr);
+ gcValues.foreground = indicatorFg->pixel;
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
&gcValues);
if (menuPtr->indicatorGC != None) {
@@ -296,10 +310,14 @@ TkMenuConfigureEntryDrawOptions(mePtr, index)
unsigned long mask;
Tk_Font tkfont;
TkMenu *menuPtr = mePtr->menuPtr;
+ int state;
- tkfont = (mePtr->tkfont == NULL) ? menuPtr->tkfont : mePtr->tkfont;
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
+ (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr);
- if (mePtr->state == tkActiveUid) {
+ Tcl_GetIndexFromObj(NULL, mePtr->statePtr, tkMenuStateStrings,
+ NULL, 0, &state);
+ if (state == ENTRY_ACTIVE) {
if (index != menuPtr->active) {
TkActivateMenuEntry(menuPtr, index);
}
@@ -307,30 +325,24 @@ TkMenuConfigureEntryDrawOptions(mePtr, index)
if (index == menuPtr->active) {
TkActivateMenuEntry(menuPtr, -1);
}
- if ((mePtr->state != tkNormalUid)
- && (mePtr->state != tkDisabledUid)) {
- Tcl_AppendResult(menuPtr->interp, "bad state value \"",
- mePtr->state,
- "\": must be normal, active, or disabled", (char *) NULL);
- mePtr->state = tkNormalUid;
- return TCL_ERROR;
- }
}
- if ((mePtr->tkfont != NULL)
- || (mePtr->border != NULL)
- || (mePtr->fg != NULL)
- || (mePtr->activeBorder != NULL)
- || (mePtr->activeFg != NULL)
- || (mePtr->indicatorFg != NULL)) {
- gcValues.foreground = (mePtr->fg != NULL)
- ? mePtr->fg->pixel
- : menuPtr->fg->pixel;
- gcValues.background = Tk_3DBorderColor(
- (mePtr->border != NULL)
- ? mePtr->border
- : menuPtr->border)
- ->pixel;
+ if ((mePtr->fontPtr != NULL)
+ || (mePtr->borderPtr != NULL)
+ || (mePtr->fgPtr != NULL)
+ || (mePtr->activeBorderPtr != NULL)
+ || (mePtr->activeFgPtr != NULL)
+ || (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
+ : menuPtr->borderPtr);
+ gcValues.background = Tk_3DBorderColor(border)->pixel;
gcValues.font = Tk_FontId(tkfont);
@@ -345,17 +357,20 @@ TkMenuConfigureEntryDrawOptions(mePtr, index)
GCForeground|GCBackground|GCFont|GCGraphicsExposures,
&gcValues);
- if (mePtr->indicatorFg != NULL) {
- gcValues.foreground = mePtr->indicatorFg->pixel;
- } else if (menuPtr->indicatorFg != NULL) {
- gcValues.foreground = menuPtr->indicatorFg->pixel;
- }
+ indicatorFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ (mePtr->indicatorFgPtr != NULL) ? mePtr->indicatorFgPtr
+ : menuPtr->indicatorFgPtr);
+ gcValues.foreground = indicatorFg->pixel;
newIndicatorGC = Tk_GetGC(menuPtr->tkwin,
GCForeground|GCBackground|GCGraphicsExposures,
&gcValues);
- if ((menuPtr->disabledFg != NULL) || (mePtr->image != NULL)) {
- gcValues.foreground = menuPtr->disabledFg->pixel;
+ if ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) {
+ XColor *disabledFg;
+
+ disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->disabledFgPtr);
+ gcValues.foreground = disabledFg->pixel;
mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures;
} else {
gcValues.foreground = gcValues.background;
@@ -365,13 +380,15 @@ TkMenuConfigureEntryDrawOptions(mePtr, index)
}
newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
- gcValues.foreground = (mePtr->activeFg != NULL)
- ? mePtr->activeFg->pixel
- : menuPtr->activeFg->pixel;
- gcValues.background = Tk_3DBorderColor(
- (mePtr->activeBorder != NULL)
- ? mePtr->activeBorder
- : menuPtr->activeBorder)->pixel;
+ activeFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ (mePtr->activeFgPtr != NULL) ? mePtr->activeFgPtr
+ : menuPtr->activeFgPtr);
+ 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,
GCForeground|GCBackground|GCFont|GCGraphicsExposures,
&gcValues);
@@ -475,7 +492,7 @@ TkRecomputeMenu(menuPtr)
void
TkEventuallyRedrawMenu(menuPtr, mePtr)
register TkMenu *menuPtr; /* Information about menu to redraw. */
- register TkMenuEntry *mePtr; /* Entry to redraw. NULL means redraw
+ register TkMenuEntry *mePtr;/* Entry to redraw. NULL means redraw
* all the entries in the menu. */
{
int i;
@@ -616,21 +633,31 @@ DisplayMenu(clientData)
register TkMenuEntry *mePtr;
register Tk_Window tkwin = menuPtr->tkwin;
int index, strictMotif;
- Tk_Font tkfont = menuPtr->tkfont;
+ Tk_Font tkfont;
Tk_FontMetrics menuMetrics;
int width;
+ int borderWidth;
+ int columnBreak;
+ Tk_3DBorder border;
+ int activeBorderWidth;
+ int relief;
+
menuPtr->menuFlags &= ~REDRAW_PENDING;
if ((menuPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return;
}
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
+ &borderWidth);
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr);
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+
if (menuPtr->menuType == MENUBAR) {
- Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), menuPtr->border,
- menuPtr->borderWidth, menuPtr->borderWidth,
- Tk_Width(tkwin) - 2 * menuPtr->borderWidth,
- Tk_Height(tkwin) - 2 * menuPtr->borderWidth, 0,
- TK_RELIEF_FLAT);
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, borderWidth,
+ borderWidth, Tk_Width(tkwin) - 2 * borderWidth,
+ Tk_Height(tkwin) - 2 * borderWidth, 0, TK_RELIEF_FLAT);
}
strictMotif = Tk_StrictMotif(menuPtr->tkwin);
@@ -640,7 +667,8 @@ DisplayMenu(clientData)
* all of the time.
*/
- Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics);
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr);
+ Tk_GetFontMetrics(tkfont, &menuMetrics);
/*
* Loop through all of the entries, drawing them one at a time.
@@ -660,22 +688,22 @@ DisplayMenu(clientData)
} else {
if (mePtr->entryFlags & ENTRY_LAST_COLUMN) {
width = Tk_Width(menuPtr->tkwin) - mePtr->x
- - menuPtr->activeBorderWidth;
+ - activeBorderWidth;
} else {
- width = mePtr->width + menuPtr->borderWidth;
+ width = mePtr->width + borderWidth;
}
}
TkpDrawMenuEntry(mePtr, Tk_WindowId(menuPtr->tkwin), tkfont,
&menuMetrics, mePtr->x, mePtr->y, width,
mePtr->height, strictMotif, 1);
- if ((index > 0) && (menuPtr->menuType != MENUBAR)
- && mePtr->columnBreak) {
+ Tcl_GetBooleanFromObj(NULL, mePtr->columnBreakPtr, &columnBreak);
+ if ((index > 0) && (menuPtr->menuType != MENUBAR) && columnBreak) {
mePtr = menuPtr->entries[index - 1];
- Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), menuPtr->border,
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border,
mePtr->x, mePtr->y + mePtr->height,
mePtr->width,
- Tk_Height(tkwin) - mePtr->y - mePtr->height
- - menuPtr->activeBorderWidth, 0,
+ Tk_Height(tkwin) - mePtr->y - mePtr->height -
+ activeBorderWidth, 0,
TK_RELIEF_FLAT);
}
}
@@ -684,28 +712,29 @@ DisplayMenu(clientData)
int x, y, height;
if (menuPtr->numEntries == 0) {
- x = y = menuPtr->borderWidth;
- width = Tk_Width(tkwin) - 2 * menuPtr->activeBorderWidth;
- height = Tk_Height(tkwin) - 2 * menuPtr->activeBorderWidth;
+ x = y = borderWidth;
+ width = Tk_Width(tkwin) - 2 * activeBorderWidth;
+ height = Tk_Height(tkwin) - 2 * activeBorderWidth;
} else {
mePtr = menuPtr->entries[menuPtr->numEntries - 1];
Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
- menuPtr->border, mePtr->x, mePtr->y + mePtr->height,
- mePtr->width, Tk_Height(tkwin) - mePtr->y - mePtr->height
- - menuPtr->activeBorderWidth, 0,
+ border, mePtr->x, mePtr->y + mePtr->height, mePtr->width,
+ Tk_Height(tkwin) - mePtr->y - mePtr->height
+ - activeBorderWidth, 0,
TK_RELIEF_FLAT);
x = mePtr->x + mePtr->width;
y = mePtr->y + mePtr->height;
- width = Tk_Width(tkwin) - x - menuPtr->activeBorderWidth;
- height = Tk_Height(tkwin) - y - menuPtr->activeBorderWidth;
+ width = Tk_Width(tkwin) - x - activeBorderWidth;
+ height = Tk_Height(tkwin) - y - activeBorderWidth;
}
- Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), menuPtr->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),
- menuPtr->border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin),
- menuPtr->borderWidth, menuPtr->relief);
+ border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), borderWidth,
+ relief);
}
/*
@@ -739,11 +768,12 @@ TkMenuEventProc(clientData, eventPtr)
TkEventuallyRecomputeMenu(menuPtr);
TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
} else if (eventPtr->type == ActivateNotify) {
- if (menuPtr->menuType == TEAROFF_MENU) {
- TkpSetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL);
- }
+ if (menuPtr->menuType == TEAROFF_MENU) {
+ TkpSetMainMenubar(menuPtr->interp, menuPtr->tkwin, NULL);
+ }
} else if (eventPtr->type == DestroyNotify) {
if (menuPtr->tkwin != NULL) {
+ TkDestroyMenu(menuPtr);
menuPtr->tkwin = NULL;
Tcl_DeleteCommandFromToken(menuPtr->interp, menuPtr->widgetCmd);
}
@@ -753,7 +783,7 @@ TkMenuEventProc(clientData, eventPtr)
if (menuPtr->menuFlags & RESIZE_PENDING) {
Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr);
}
- TkDestroyMenu(menuPtr);
+ Tcl_EventuallyFree((ClientData) menuPtr, TCL_DYNAMIC);
}
}
@@ -921,7 +951,6 @@ TkPostSubmenu(interp, menuPtr, mePtr)
* posted. NULL means make sure that
* no submenu is posted. */
{
- char string[30];
int result, x, y;
if (mePtr == menuPtr->postedCascade) {
@@ -929,6 +958,8 @@ TkPostSubmenu(interp, menuPtr, mePtr)
}
if (menuPtr->postedCascade != NULL) {
+ char *name = Tcl_GetStringFromObj(menuPtr->postedCascade->namePtr,
+ NULL);
/*
* Note: when unposting a submenu, we have to redraw the entire
@@ -948,17 +979,15 @@ TkPostSubmenu(interp, menuPtr, mePtr)
*/
TkEventuallyRedrawMenu(menuPtr, (TkMenuEntry *) NULL);
- result = Tcl_VarEval(interp, menuPtr->postedCascade->name,
- " unpost", (char *) NULL);
+ result = Tcl_VarEval(interp, name, " unpost", (char *) NULL);
menuPtr->postedCascade = NULL;
if (result != TCL_OK) {
return result;
}
}
- if ((mePtr != NULL) && (mePtr->name != NULL)
+ 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
@@ -967,10 +996,13 @@ TkPostSubmenu(interp, menuPtr, mePtr)
* The menu has to redrawn so that the entry can change relief.
*/
+ 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);
- result = Tcl_VarEval(interp, mePtr->name, " post ", string,
- (char *) NULL);
+ result = Tcl_VarEval(interp, name, " post ", string, (char *) NULL);
if (result != TCL_OK) {
return result;
}
@@ -1009,10 +1041,15 @@ AdjustMenuCoords(menuPtr, mePtr, xPtr, yPtr, string)
*xPtr += mePtr->x;
*yPtr += mePtr->y + mePtr->height;
} else {
- *xPtr += Tk_Width(menuPtr->tkwin) - menuPtr->borderWidth
- - menuPtr->activeBorderWidth - 2;
- *yPtr += mePtr->y
- + menuPtr->activeBorderWidth + 2;
+ int borderWidth, activeBorderWidth;
+
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr,
+ &borderWidth);
+ Tk_GetPixelsFromObj(NULL, menuPtr->tkwin,
+ menuPtr->activeBorderWidthPtr, &activeBorderWidth);
+ *xPtr += Tk_Width(menuPtr->tkwin) - borderWidth - activeBorderWidth
+ - 2;
+ *yPtr += mePtr->y + activeBorderWidth + 2;
}
sprintf(string, "%d %d", *xPtr, *yPtr);
}
diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c
index ca2070e..8b5ba1b 100644
--- a/generic/tkMenubutton.c
+++ b/generic/tkMenubutton.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkMenubutton.c 1.94 97/07/31 09:10:37
+ * SCCS: @(#) tkMenubutton.c 1.95 97/11/07 21:20:06
*/
#include "tkMenubutton.h"
@@ -267,7 +267,7 @@ Tk_MenubuttonCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
- interp->result = Tk_PathName(mbPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(mbPtr->tkwin), TCL_STATIC);
return TCL_OK;
}
@@ -409,7 +409,7 @@ DestroyMenuButton(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as text string, colors, font,
diff --git a/generic/tkMessage.c b/generic/tkMessage.c
index 1984bac..0a0e214 100644
--- a/generic/tkMessage.c
+++ b/generic/tkMessage.c
@@ -6,12 +6,12 @@
* in a window according to a particular aspect ratio.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkMessage.c 1.75 97/07/31 09:11:14
+ * SCCS: @(#) tkMessage.c 1.76 97/11/07 21:20:11
*/
#include "tkPort.h"
@@ -274,7 +274,7 @@ Tk_MessageCmd(clientData, interp, argc, argv)
goto error;
}
- interp->result = Tk_PathName(msgPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(msgPtr->tkwin), TCL_STATIC);
return TCL_OK;
error:
@@ -401,7 +401,7 @@ DestroyMessage(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as text string, colors, font,
diff --git a/generic/tkObj.c b/generic/tkObj.c
new file mode 100644
index 0000000..35149eb
--- /dev/null
+++ b/generic/tkObj.c
@@ -0,0 +1,659 @@
+/*
+ * tkObj.c --
+ *
+ * This file contains procedures 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.
+ *
+ * SCCS: @(#) tkObj.c 1.14 98/01/19 12:00:30
+ */
+
+#include "tkInt.h"
+
+/*
+ * The following structure is the internal representation for pixel objects.
+ */
+
+typedef struct PixelRep {
+ double value;
+ int units;
+ Tk_Window tkwin;
+ int returnValue;
+} PixelRep;
+
+#define SIMPLE_PIXELREP(objPtr) \
+ ((objPtr)->internalRep.twoPtrValue.ptr2 == 0)
+
+#define SET_SIMPLEPIXEL(objPtr, intval) \
+ (objPtr)->internalRep.twoPtrValue.ptr1 = (VOID *) (intval); \
+ (objPtr)->internalRep.twoPtrValue.ptr2 = 0
+
+#define GET_SIMPLEPIXEL(objPtr) \
+ ((int) (objPtr)->internalRep.twoPtrValue.ptr1)
+
+#define SET_COMPLEXPIXEL(objPtr, repPtr) \
+ (objPtr)->internalRep.twoPtrValue.ptr1 = 0; \
+ (objPtr)->internalRep.twoPtrValue.ptr2 = (VOID *) repPtr
+
+#define GET_COMPLEXPIXEL(objPtr) \
+ ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2)
+
+
+/*
+ * The following structure is the internal representation for mm objects.
+ */
+
+typedef struct MMRep {
+ double value;
+ int units;
+ Tk_Window tkwin;
+ double returnValue;
+} MMRep;
+
+/*
+ * Prototypes for procedures 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 FreeMMInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
+static void FreePixelInternalRep _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));
+
+/*
+ * 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 = {
+ "pixel", /* name */
+ FreePixelInternalRep, /* freeIntRepProc */
+ DupPixelInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetPixelFromAny /* setFromAnyProc */
+};
+
+/*
+ * The following structure defines the implementation of the "pixel"
+ * Tcl object, used for measuring distances. The pixel object remembers
+ * its initial display-independant settings.
+ */
+
+static Tcl_ObjType mmObjType = {
+ "mm", /* name */
+ FreeMMInternalRep, /* freeIntRepProc */
+ DupMMInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetMMFromAny /* setFromAnyProc */
+};
+
+/*
+ * The following structure defines the implementation of the "window"
+ * Tcl object.
+ */
+
+static Tcl_ObjType windowObjType = {
+ "window", /* name */
+ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
+ (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetWindowFromAny /* setFromAnyProc */
+};
+
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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(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. */
+{
+ int result;
+ double d;
+ PixelRep *pixelPtr;
+ static double bias[] = {
+ 1.0, 10.0, 25.4, 25.4 / 72.0
+ };
+
+ if (objPtr->typePtr != &pixelObjType) {
+ result = SetPixelFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ if (SIMPLE_PIXELREP(objPtr)) {
+ *intPtr = GET_SIMPLEPIXEL(objPtr);
+ } else {
+ pixelPtr = GET_COMPLEXPIXEL(objPtr);
+ if (pixelPtr->tkwin != tkwin) {
+ 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->tkwin = tkwin;
+ }
+ *intPtr = pixelPtr->returnValue;
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreePixelInternalRep --
+ *
+ * Deallocate the storage associated with a pixel object's internal
+ * representation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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. */
+{
+ PixelRep *pixelPtr;
+
+ if (!SIMPLE_PIXELREP(objPtr)) {
+ pixelPtr = GET_COMPLEXPIXEL(objPtr);
+ ckfree((char *) pixelPtr);
+ }
+ SET_SIMPLEPIXEL(objPtr, 0);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupPixelInternalRep --
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ PixelRep *oldPtr, *newPtr;
+
+ copyPtr->typePtr = srcPtr->typePtr;
+
+ if (SIMPLE_PIXELREP(srcPtr)) {
+ SET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr));
+ } else {
+ oldPtr = GET_COMPLEXPIXEL(srcPtr);
+ newPtr = (PixelRep *) ckalloc(sizeof(PixelRep));
+ newPtr->value = oldPtr->value;
+ newPtr->units = oldPtr->units;
+ newPtr->tkwin = oldPtr->tkwin;
+ newPtr->returnValue = oldPtr->returnValue;
+ SET_COMPLEXPIXEL(copyPtr, newPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetPixelFromAny --
+ *
+ * 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
+ * conversion, an error message is left in the interpreter's result
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetPixelFromAny(interp, objPtr)
+ Tcl_Interp *interp; /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ 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;
+ }
+ 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;
+ }
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+
+ objPtr->typePtr = &pixelObjType;
+
+ i = (int) d;
+ if ((units < 0) && (i == d)) {
+ SET_SIMPLEPIXEL(objPtr, i);
+ } else {
+ pixelPtr = (PixelRep *) ckalloc(sizeof(PixelRep));
+ pixelPtr->value = d;
+ pixelPtr->units = units;
+ pixelPtr->tkwin = NULL;
+ pixelPtr->returnValue = i;
+ SET_COMPLEXPIXEL(objPtr, pixelPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetMMFromObj --
+ *
+ * Attempt to return an mm value from the Tcl object "objPtr". If the
+ * object is not already an mm 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_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. */
+{
+ int result;
+ double d;
+ MMRep *mmPtr;
+ static double bias[] = {
+ 10.0, 25.4, 1.0, 25.4 / 72.0
+ };
+
+ if (objPtr->typePtr != &mmObjType) {
+ result = SetMMFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ mmPtr = (MMRep *) objPtr->internalRep.otherValuePtr;
+ if (mmPtr->tkwin != tkwin) {
+ d = mmPtr->value;
+ if (mmPtr->units == -1) {
+ d /= WidthOfScreen(Tk_Screen(tkwin));
+ d *= WidthMMOfScreen(Tk_Screen(tkwin));
+ } else {
+ d *= bias[mmPtr->units];
+ }
+ mmPtr->tkwin = tkwin;
+ mmPtr->returnValue = d;
+ }
+ *doublePtr = mmPtr->returnValue;
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FreeMMInternalRep --
+ *
+ * Deallocate the storage associated with a mm object's internal
+ * representation.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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. */
+{
+ ckfree((char *) objPtr->internalRep.otherValuePtr);
+ objPtr->internalRep.otherValuePtr = NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DupMMInternalRep --
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+{
+ MMRep *oldPtr, *newPtr;
+
+ copyPtr->typePtr = srcPtr->typePtr;
+ oldPtr = (MMRep *) srcPtr->internalRep.otherValuePtr;
+ newPtr = (MMRep *) ckalloc(sizeof(MMRep));
+ newPtr->value = oldPtr->value;
+ newPtr->units = oldPtr->units;
+ newPtr->tkwin = oldPtr->tkwin;
+ newPtr->returnValue = oldPtr->returnValue;
+ copyPtr->internalRep.otherValuePtr = (VOID *) newPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetMMFromAny --
+ *
+ * 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
+ * conversion, an error message is left in the interpreter's result
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetMMFromAny(interp, objPtr)
+ Tcl_Interp *interp; /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *typePtr;
+ char *string, *rest;
+ double d;
+ int units;
+ MMRep *mmPtr;
+
+ 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 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;
+ }
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+
+ objPtr->typePtr = &mmObjType;
+
+ mmPtr = (MMRep *) ckalloc(sizeof(MMRep));
+ mmPtr->value = d;
+ mmPtr->units = units;
+ mmPtr->tkwin = NULL;
+ mmPtr->returnValue = d;
+ objPtr->internalRep.otherValuePtr = (VOID *) mmPtr;
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetWindowFromObj --
+ *
+ * Attempt to return a Tk_Window from the Tcl object "objPtr". If the
+ * object is not already a Tk_Window, 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 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. */
+ register Tcl_Obj *objPtr; /* The object from which to get boolean. */
+ Tk_Window *windowPtr; /* Place to store resulting window. */
+{
+ register int result;
+ Tk_Window lastWindow;
+
+ result = SetWindowFromAny(interp, objPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ lastWindow = (Tk_Window) objPtr->internalRep.twoPtrValue.ptr1;
+ if (tkwin != lastWindow) {
+ Tk_Window foundWindow = Tk_NameToWindow(interp,
+ Tcl_GetStringFromObj(objPtr, NULL), tkwin);
+
+ if (foundWindow == NULL) {
+ return TCL_ERROR;
+ }
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkwin;
+ objPtr->internalRep.twoPtrValue.ptr2 = (VOID *) foundWindow;
+ }
+ *windowPtr = (Tk_Window) objPtr->internalRep.twoPtrValue.ptr2;
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetWindowFromAny --
+ *
+ * Attempt to generate a Tk_Window internal form for the Tcl object
+ * "objPtr".
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * If no error occurs, a standard window value is stored as "objPtr"s
+ * internal representation and the type of "objPtr" is set to Tk_Window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetWindowFromAny(interp, objPtr)
+ Tcl_Interp *interp; /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr; /* The object to convert. */
+{
+ Tcl_ObjType *typePtr;
+
+ /*
+ * Free the old internalRep before setting the new one.
+ */
+
+ Tcl_GetStringFromObj(objPtr, NULL);
+ typePtr = objPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(objPtr);
+ }
+ objPtr->typePtr = &windowObjType;
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+
+ return TCL_OK;
+}
diff --git a/generic/tkOldConfig.c b/generic/tkOldConfig.c
new file mode 100644
index 0000000..c171521
--- /dev/null
+++ b/generic/tkOldConfig.c
@@ -0,0 +1,996 @@
+/*
+ * 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.
+ *
+ * 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.
+ *
+ * SCCS: @(#) tkOldConfig.c 1.56 98/02/11 17:46:46
+ */
+
+#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!
+ *
+ * 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:
+ */
+
+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,
+ Tk_ConfigSpec *specs, char *argvName,
+ int needFlags, int hateFlags));
+static char * FormatConfigInfo _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_ConfigSpec *specPtr,
+ char *widgRec));
+static char * FormatConfigValue _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_ConfigSpec *specPtr,
+ char *widgRec, char *buffer,
+ Tcl_FreeProc **freeProcPtr));
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigureWidget --
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ConfigureWidget(interp, tkwin, specs, 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 *specs; /* Describes legal options. */
+ int argc; /* Number of elements in argv. */
+ 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 *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. */
+
+ needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = TK_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = TK_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * Pass one: scan through all the option specs, replacing strings
+ * with Tk_Uids (if this hasn't been done already) and clearing
+ * the TK_CONFIG_OPTION_SPECIFIED flags.
+ */
+
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if (!(specPtr->specFlags & INIT) && (specPtr->argvName != NULL)) {
+ if (specPtr->dbName != NULL) {
+ specPtr->dbName = Tk_GetUid(specPtr->dbName);
+ }
+ if (specPtr->dbClass != NULL) {
+ specPtr->dbClass = Tk_GetUid(specPtr->dbClass);
+ }
+ if (specPtr->defValue != NULL) {
+ specPtr->defValue = Tk_GetUid(specPtr->defValue);
+ }
+ }
+ specPtr->specFlags = (specPtr->specFlags & ~TK_CONFIG_OPTION_SPECIFIED)
+ | INIT;
+ }
+
+ /*
+ * Pass two: scan through all of the arguments, processing those
+ * that match entries in the specs.
+ */
+
+ for ( ; argc > 0; argc -= 2, argv += 2) {
+ specPtr = FindConfigSpec(interp, specs, *argv, needFlags, hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Process the entry.
+ */
+
+ if (argc < 2) {
+ Tcl_AppendResult(interp, "value for \"", *argv,
+ "\" missing", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (DoConfig(interp, tkwin, specPtr, argv[1], 0, widgRec) != TCL_OK) {
+ char msg[100];
+
+ sprintf(msg, "\n (processing \"%.40s\" option)",
+ specPtr->argvName);
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ specPtr->specFlags |= TK_CONFIG_OPTION_SPECIFIED;
+ }
+
+ /*
+ * Pass three: 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)) {
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if ((specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)
+ || (specPtr->argvName == NULL)
+ || (specPtr->type == TK_CONFIG_SYNONYM)) {
+ continue;
+ }
+ if (((specPtr->specFlags & needFlags) != needFlags)
+ || (specPtr->specFlags & hateFlags)) {
+ continue;
+ }
+ value = NULL;
+ if (specPtr->dbName != NULL) {
+ value = Tk_GetOption(tkwin, specPtr->dbName, specPtr->dbClass);
+ }
+ if (value != NULL) {
+ if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
+ TCL_OK) {
+ char msg[200];
+
+ sprintf(msg, "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "database entry for",
+ specPtr->dbName, Tk_PathName(tkwin));
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ } else {
+ value = specPtr->defValue;
+ if ((value != NULL) && !(specPtr->specFlags
+ & TK_CONFIG_DONT_SET_DEFAULT)) {
+ if (DoConfig(interp, tkwin, specPtr, value, 1, widgRec) !=
+ TCL_OK) {
+ char msg[200];
+
+ sprintf(msg,
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "default value for",
+ specPtr->dbName, Tk_PathName(tkwin));
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FindConfigSpec --
+ *
+ * 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_ConfigSpec *
+FindConfigSpec(interp, specs, argvName, needFlags, hateFlags)
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_ConfigSpec *specs; /* Pointer to table of configuration
+ * specifications for a widget. */
+ char *argvName; /* Name (suitable for use in a "config"
+ * command) identifying particular option. */
+ int needFlags; /* Flags that must 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. */
+ Tk_ConfigSpec *matchPtr; /* Matching spec, or NULL. */
+ size_t length;
+
+ c = argvName[1];
+ length = strlen(argvName);
+ matchPtr = NULL;
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if (specPtr->argvName == NULL) {
+ continue;
+ }
+ if ((specPtr->argvName[1] != c)
+ || (strncmp(specPtr->argvName, argvName, length) != 0)) {
+ continue;
+ }
+ if (((specPtr->specFlags & needFlags) != needFlags)
+ || (specPtr->specFlags & hateFlags)) {
+ continue;
+ }
+ if (specPtr->argvName[length] == 0) {
+ matchPtr = specPtr;
+ goto gotMatch;
+ }
+ if (matchPtr != NULL) {
+ Tcl_AppendResult(interp, "ambiguous option \"", argvName,
+ "\"", (char *) NULL);
+ return (Tk_ConfigSpec *) NULL;
+ }
+ matchPtr = specPtr;
+ }
+
+ if (matchPtr == NULL) {
+ Tcl_AppendResult(interp, "unknown option \"", argvName,
+ "\"", (char *) NULL);
+ return (Tk_ConfigSpec *) NULL;
+ }
+
+ /*
+ * Found a matching entry. If it's a synonym, then find the
+ * entry that it's a synonym for.
+ */
+
+ 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;
+ }
+ if ((specPtr->dbName == matchPtr->dbName)
+ && (specPtr->type != TK_CONFIG_SYNONYM)
+ && ((specPtr->specFlags & needFlags) == needFlags)
+ && !(specPtr->specFlags & hateFlags)) {
+ break;
+ }
+ }
+ }
+ return specPtr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DoConfig --
+ *
+ * This procedure 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+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. */
+ char *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;
+ int nullValue;
+
+ nullValue = 0;
+ if ((*value == 0) && (specPtr->specFlags & TK_CONFIG_NULL_OK)) {
+ nullValue = 1;
+ }
+
+ 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_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;
+ }
+ case TK_CONFIG_FONT: {
+ Tk_Font new;
+
+ 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;
+ }
+ 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;
+ }
+ 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;
+ }
+ 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 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) {
+ 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;
+ }
+ }
+ *((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));
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigureInfo --
+ *
+ * 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).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+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. */
+ 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. */
+{
+ register Tk_ConfigSpec *specPtr;
+ int needFlags, hateFlags;
+ char *list;
+ char *leader = "{";
+
+ needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = TK_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = TK_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * If information is only wanted for a single configuration
+ * spec, then handle that one spec specially.
+ */
+
+ Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
+ if (argvName != NULL) {
+ specPtr = FindConfigSpec(interp, specs, argvName, needFlags,
+ hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetResult(interp,
+ FormatConfigInfo(interp, tkwin, specPtr, widgRec),
+ TCL_DYNAMIC);
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through all the specs, creating a big list with all
+ * their information.
+ */
+
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if ((argvName != NULL) && (specPtr->argvName != argvName)) {
+ continue;
+ }
+ if (((specPtr->specFlags & needFlags) != needFlags)
+ || (specPtr->specFlags & hateFlags)) {
+ continue;
+ }
+ if (specPtr->argvName == NULL) {
+ continue;
+ }
+ list = FormatConfigInfo(interp, tkwin, specPtr, widgRec);
+ Tcl_AppendResult(interp, leader, list, "}", (char *) NULL);
+ ckfree(list);
+ leader = " {";
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FormatConfigInfo --
+ *
+ * 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.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *--------------------------------------------------------------
+ */
+
+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. */
+{
+ char *argv[6], *result;
+ char buffer[200];
+ Tcl_FreeProc *freeProc = (Tcl_FreeProc *) NULL;
+
+ argv[0] = specPtr->argvName;
+ argv[1] = specPtr->dbName;
+ argv[2] = specPtr->dbClass;
+ argv[3] = specPtr->defValue;
+ if (specPtr->type == TK_CONFIG_SYNONYM) {
+ return Tcl_Merge(2, argv);
+ }
+ argv[4] = FormatConfigValue(interp, tkwin, specPtr, widgRec, buffer,
+ &freeProc);
+ if (argv[1] == NULL) {
+ argv[1] = "";
+ }
+ if (argv[2] == NULL) {
+ argv[2] = "";
+ }
+ if (argv[3] == NULL) {
+ argv[3] = "";
+ }
+ if (argv[4] == NULL) {
+ argv[4] = "";
+ }
+ result = Tcl_Merge(5, argv);
+ if (freeProc != NULL) {
+ if ((freeProc == TCL_DYNAMIC) || (freeProc == (Tcl_FreeProc *) free)) {
+ ckfree(argv[4]);
+ } else {
+ (*freeProc)(argv[4]);
+ }
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FormatConfigValue --
+ *
+ * This procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static 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.
+ * 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.
+ * 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. */
+{
+ char *ptr, *result;
+
+ *freeProcPtr = NULL;
+ 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_COLOR: {
+ XColor *colorPtr = *((XColor **) ptr);
+ if (colorPtr != NULL) {
+ result = Tk_NameOfColor(colorPtr);
+ }
+ break;
+ }
+ case TK_CONFIG_FONT: {
+ Tk_Font tkfont = *((Tk_Font *) ptr);
+ if (tkfont != NULL) {
+ result = Tk_NameOfFont(tkfont);
+ }
+ break;
+ }
+ case TK_CONFIG_BITMAP: {
+ Pixmap pixmap = *((Pixmap *) ptr);
+ if (pixmap != None) {
+ result = Tk_NameOfBitmap(Tk_Display(tkwin), pixmap);
+ }
+ break;
+ }
+ case TK_CONFIG_BORDER: {
+ Tk_3DBorder border = *((Tk_3DBorder *) ptr);
+ if (border != NULL) {
+ result = Tk_NameOf3DBorder(border);
+ }
+ 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;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_ConfigureValue --
+ *
+ * This procedure 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).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+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. */
+ 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;
+
+ needFlags = flags & ~(TK_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = TK_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = TK_CONFIG_MONO_ONLY;
+ }
+ specPtr = FindConfigSpec(interp, specs, argvName, needFlags, hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+ interp->result = FormatConfigValue(interp, tkwin, specPtr, widgRec,
+ interp->result, &interp->freeProc);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeOptions --
+ *
+ * Free up all resources associated with configuration options.
+ *
+ * Results:
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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
+ * resources. */
+ 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;
+
+ for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
+ if ((specPtr->specFlags & needFlags) != needFlags) {
+ continue;
+ }
+ 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;
+ }
+ }
+ }
+}
diff --git a/generic/tkOption.c b/generic/tkOption.c
index b2bef64..3815f85 100644
--- a/generic/tkOption.c
+++ b/generic/tkOption.c
@@ -6,12 +6,12 @@
* with windows either by name or by class or both.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkOption.c 1.57 96/10/17 15:16:45
+ * SCCS: @(#) tkOption.c 1.59 97/11/17 12:53:36
*/
#include "tkPort.h"
@@ -530,7 +530,7 @@ Tk_OptionCmd(clientData, interp, argc, argv)
}
value = Tk_GetOption(window, argv[3], argv[4]);
if (value != NULL) {
- interp->result = value;
+ Tcl_SetResult(interp, value, TCL_STATIC);
}
return TCL_OK;
} else if ((c == 'r') && (strncmp(argv[1], "readfile", length) == 0)) {
@@ -674,7 +674,7 @@ TkOptionClassChanged(winPtr)
* 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 interp->result.
+ * In this case, an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -734,7 +734,7 @@ ParsePriority(interp, string)
* 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 interp->result. The memory at
+ * 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.
*
@@ -797,8 +797,10 @@ AddFromString(interp, tkwin, string, priority)
dst = name = src;
while (*src != ':') {
if ((*src == '\0') || (*src == '\n')) {
- sprintf(interp->result, "missing colon on line %d",
- lineNum);
+ char buf[32 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "missing colon on line %d", lineNum);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
if ((src[0] == '\\') && (src[1] == '\n')) {
@@ -830,7 +832,10 @@ AddFromString(interp, tkwin, string, priority)
src++;
}
if (*src == '\0') {
- sprintf(interp->result, "missing value on line %d", lineNum);
+ char buf[32 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "missing value on line %d", lineNum);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
@@ -842,8 +847,10 @@ AddFromString(interp, tkwin, string, priority)
dst = value = src;
while (*src != '\n') {
if (*src == '\0') {
- sprintf(interp->result, "missing newline on line %d",
- lineNum);
+ char buf[32 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "missing newline on line %d", lineNum);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
if ((src[0] == '\\') && (src[1] == '\n')) {
@@ -879,7 +886,7 @@ AddFromString(interp, tkwin, string, priority)
* 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 interp->result.
+ * error message will be left in the interp's result.
*
* Side effects:
* None.
diff --git a/generic/tkPack.c b/generic/tkPack.c
index 4ff1049..2a7361c 100644
--- a/generic/tkPack.c
+++ b/generic/tkPack.c
@@ -5,12 +5,12 @@
* geometry manager for Tk.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkPack.c 1.64 96/05/03 10:51:52
+ * SCCS: @(#) tkPack.c 1.65 97/11/07 21:17:36
*/
#include "tkPort.h"
@@ -281,7 +281,7 @@ Tk_PackCmd(clientData, interp, argc, argv)
} else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) {
register Packer *slavePtr;
Tk_Window slave;
- char buffer[300];
+ char buffer[64 + TCL_INTEGER_SPACE * 4];
static char *sideNames[] = {"top", "bottom", "left", "right"};
if (argc != 3) {
@@ -342,9 +342,9 @@ Tk_PackCmd(clientData, interp, argc, argv)
masterPtr = GetPacker(master);
if (argc == 3) {
if (masterPtr->flags & DONT_PROPAGATE) {
- interp->result = "0";
+ Tcl_SetResult(interp, "0", TCL_STATIC);
} else {
- interp->result = "1";
+ Tcl_SetResult(interp, "1", TCL_STATIC);
}
return TCL_OK;
}
@@ -1398,7 +1398,7 @@ PackStructureProc(clientData, eventPtr)
*
* Results:
* TCL_OK is returned if all went well. Otherwise, TCL_ERROR is
- * returned and interp->result is set to contain an error message.
+ * returned and the interp's result is set to contain an error message.
*
* Side effects:
* Slave windows get taken over by the packer.
diff --git a/generic/tkPlace.c b/generic/tkPlace.c
index 15ddcef..b3f8b08 100644
--- a/generic/tkPlace.c
+++ b/generic/tkPlace.c
@@ -5,12 +5,12 @@
* for Tk based on absolute placement or "rubber-sheet" placement.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkPlace.c 1.27 96/08/20 17:05:31
+ * SCCS: @(#) tkPlace.c 1.28 97/11/07 21:17:41
*/
#include "tkPort.h"
@@ -243,7 +243,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv)
Tk_UnmapWindow(tkwin);
ckfree((char *) slavePtr);
} else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) {
- char buffer[50];
+ char buffer[32 + TCL_INTEGER_SPACE];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -467,7 +467,7 @@ FindMaster(tkwin)
*
* Results:
* A standard Tcl result. If an error occurs then a message is
- * left in interp->result.
+ * left in the interp's result.
*
* Side effects:
* Information in slavePtr may change, and slavePtr's master is
diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c
index d1ba71c..5d2bd95 100644
--- a/generic/tkRectOval.c
+++ b/generic/tkRectOval.c
@@ -5,12 +5,12 @@
* widgets.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkRectOval.c 1.40 96/05/03 10:52:21
+ * SCCS: @(#) tkRectOval.c 1.41 97/11/07 21:17:51
*/
#include <stdio.h>
@@ -157,7 +157,7 @@ Tk_ItemType tkOvalType = {
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
- * interp->result; in this case itemPtr is left uninitialized,
+ * the interp's result; in this case itemPtr is left uninitialized,
* so it can be safely freed by the caller.
*
* Side effects:
@@ -230,7 +230,7 @@ CreateRectOval(interp, canvas, itemPtr, argc, argv)
* for details on what it does.
*
* Results:
- * Returns TCL_OK or TCL_ERROR, and sets interp->result.
+ * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
*
* Side effects:
* The coordinates for the given item may be changed.
@@ -273,9 +273,10 @@ RectOvalCoords(interp, canvas, itemPtr, argc, argv)
}
ComputeRectOvalBbox(canvas, rectOvalPtr);
} else {
- sprintf(interp->result,
- "wrong # coordinates: expected 0 or 4, got %d",
- argc);
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return TCL_ERROR;
}
return TCL_OK;
@@ -292,7 +293,7 @@ RectOvalCoords(interp, canvas, itemPtr, argc, argv)
*
* Results:
* A standard Tcl result code. If an error occurs, then
- * an error message is left in interp->result.
+ * an error message is left in the interp's result.
*
* Side effects:
* Configuration information, such as colors and stipple
@@ -942,7 +943,7 @@ TranslateRectOval(canvas, itemPtr, deltaX, deltaY)
* 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.
+ * 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.
*
@@ -962,7 +963,7 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass)
* collect font information; 0 means
* final Postscript is being created. */
{
- char pathCmd[500], string[100];
+ char pathCmd[500];
RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
double y1, y2;
@@ -1016,6 +1017,8 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass)
*/
if (rectOvalPtr->outlineColor != NULL) {
+ char string[32 + TCL_INTEGER_SPACE];
+
Tcl_AppendResult(interp, pathCmd, (char *) NULL);
sprintf(string, "%d setlinewidth", rectOvalPtr->width);
Tcl_AppendResult(interp, string,
diff --git a/generic/tkScale.c b/generic/tkScale.c
index 6c78150..ba75549 100644
--- a/generic/tkScale.c
+++ b/generic/tkScale.c
@@ -12,12 +12,12 @@
* permission.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkScale.c 1.88 97/07/31 09:11:57
+ * SCCS: @(#) tkScale.c 1.89 97/11/07 21:20:16
*/
#include "tkPort.h"
@@ -261,7 +261,7 @@ Tk_ScaleCmd(clientData, interp, argc, argv)
goto error;
}
- interp->result = Tk_PathName(scalePtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(scalePtr->tkwin), TCL_STATIC);
return TCL_OK;
error:
@@ -334,6 +334,7 @@ ScaleWidgetCmd(clientData, interp, argc, argv)
&& (length >= 3)) {
int x, y ;
double value;
+ char buf[TCL_INTEGER_SPACE * 2];
if ((argc != 2) && (argc != 3)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -356,10 +357,12 @@ ScaleWidgetCmd(clientData, interp, argc, argv)
y = scalePtr->horizTroughY + scalePtr->width/2
+ scalePtr->borderWidth;
}
- sprintf(interp->result, "%d %d", x, y);
+ sprintf(buf, "%d %d", x, y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
double value;
int x, y;
+ char buf[TCL_DOUBLE_SPACE];
if ((argc != 2) && (argc != 4)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -375,7 +378,8 @@ ScaleWidgetCmd(clientData, interp, argc, argv)
}
value = TkpPixelToValue(scalePtr, x, y);
}
- sprintf(interp->result, scalePtr->format, value);
+ sprintf(buf, scalePtr->format, value);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {
int x, y, thing;
@@ -390,9 +394,15 @@ ScaleWidgetCmd(clientData, interp, argc, argv)
}
thing = TkpScaleElement(scalePtr, x,y);
switch (thing) {
- case TROUGH1: interp->result = "trough1"; break;
- case SLIDER: interp->result = "slider"; break;
- case TROUGH2: interp->result = "trough2"; break;
+ 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;
}
} else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) {
double value;
@@ -481,7 +491,7 @@ DestroyScale(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
diff --git a/generic/tkScrollbar.c b/generic/tkScrollbar.c
index 3025a78..fa0094a 100644
--- a/generic/tkScrollbar.c
+++ b/generic/tkScrollbar.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkScrollbar.c 1.94 97/07/31 09:12:44
+ * SCCS: @(#) tkScrollbar.c 1.95 97/11/07 21:18:28
*/
#include "tkPort.h"
@@ -193,7 +193,7 @@ Tk_ScrollbarCmd(clientData, interp, argc, argv)
return TCL_ERROR;
}
- interp->result = Tk_PathName(scrollPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(scrollPtr->tkwin), TCL_STATIC);
return TCL_OK;
}
@@ -240,9 +240,15 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
int oldActiveField;
if (argc == 2) {
switch (scrollPtr->activeField) {
- case TOP_ARROW: interp->result = "arrow1"; break;
- case SLIDER: interp->result = "slider"; break;
- case BOTTOM_ARROW: interp->result = "arrow2"; 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;
}
@@ -292,6 +298,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
} else if ((c == 'd') && (strncmp(argv[1], "delta", length) == 0)) {
int xDelta, yDelta, pixels, length;
double fraction;
+ char buf[TCL_DOUBLE_SPACE];
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -316,10 +323,12 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
} else {
fraction = ((double) pixels / (double) length);
}
- sprintf(interp->result, "%g", fraction);
+ sprintf(buf, "%g", fraction);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
} else if ((c == 'f') && (strncmp(argv[1], "fraction", length) == 0)) {
int x, y, pos, length;
double fraction;
+ char buf[TCL_DOUBLE_SPACE];
if (argc != 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -349,7 +358,8 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
} else if (fraction > 1.0) {
fraction = 1.0;
}
- sprintf(interp->result, "%g", fraction);
+ sprintf(buf, "%g", fraction);
+ 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 \"",
@@ -363,9 +373,12 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
Tcl_PrintDouble(interp, scrollPtr->lastFraction, last);
Tcl_AppendResult(interp, first, " ", last, (char *) NULL);
} else {
- sprintf(interp->result, "%d %d %d %d", scrollPtr->totalUnits,
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", scrollPtr->totalUnits,
scrollPtr->windowUnits, scrollPtr->firstUnit,
scrollPtr->lastUnit);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {
int x, y, thing;
@@ -381,11 +394,21 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
}
thing = TkpScrollbarPosition(scrollPtr, x,y);
switch (thing) {
- case TOP_ARROW: interp->result = "arrow1"; break;
- case TOP_GAP: interp->result = "trough1"; break;
- case SLIDER: interp->result = "slider"; break;
- case BOTTOM_GAP: interp->result = "trough2"; break;
- case BOTTOM_ARROW: interp->result = "arrow2"; 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;
@@ -488,7 +511,7 @@ ScrollbarWidgetCmd(clientData, interp, argc, argv)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
diff --git a/generic/tkSelect.c b/generic/tkSelect.c
index 7263e30..d43c121 100644
--- a/generic/tkSelect.c
+++ b/generic/tkSelect.c
@@ -6,12 +6,12 @@
* and Tcl commands.
*
* Copyright (c) 1990-1993 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkSelect.c 1.57 96/05/03 10:52:40
+ * SCCS: @(#) tkSelect.c 1.58 97/11/07 21:17:56
*/
#include "tkInt.h"
@@ -431,7 +431,7 @@ Tk_ClearSelection(tkwin, selection)
* 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 interp->result.
+ * then an error message is left in the interp's result.
*
* Side effects:
* The standard X11 protocols are used to retrieve the
@@ -457,7 +457,7 @@ Tk_ClearSelection(tkwin, selection)
* 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 interp->result; the
+ * TCL_ERROR and leave an error message in the interp's result; the
* remainder of the selection retrieval will be aborted.
*
*--------------------------------------------------------------
@@ -602,9 +602,8 @@ Tk_SelectionCmd(clientData, interp, argc, argv)
char **args;
if (argc < 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s option ?arg arg ...?\"",
- argv[0]);
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " option ?arg arg ...?\"", (char *) NULL);
return TCL_ERROR;
}
c = argv[1][0];
@@ -854,7 +853,7 @@ Tk_SelectionCmd(clientData, interp, argc, argv)
if ((infoPtr != NULL)
&& (infoPtr->owner != winPtr->dispPtr->clipWindow)) {
- interp->result = Tk_PathName(infoPtr->owner);
+ Tcl_SetResult(interp, Tk_PathName(infoPtr->owner), TCL_STATIC);
}
return TCL_OK;
}
@@ -878,9 +877,8 @@ Tk_SelectionCmd(clientData, interp, argc, argv)
Tk_OwnSelection(tkwin, selection, LostSelection, (ClientData) lostPtr);
return TCL_OK;
} else {
- sprintf(interp->result,
- "bad option \"%.50s\": must be clear, get, handle, or own",
- argv[1]);
+ Tcl_AppendResult(interp, "bad option \"", argv[1],
+ "\": must be clear, get, handle, or own", (char *) NULL);
return TCL_ERROR;
}
}
@@ -1155,11 +1153,12 @@ HandleTclCommand(clientData, offset, buffer, maxBytes)
Tcl_DStringInit(&oldResult);
Tcl_DStringGetResult(interp, &oldResult);
if (TkCopyAndGlobalEval(interp, command) == TCL_OK) {
- length = strlen(interp->result);
+ length = strlen(Tcl_GetStringResult(interp));
if (length > maxBytes) {
length = maxBytes;
}
- memcpy((VOID *) buffer, (VOID *) interp->result, (size_t) length);
+ memcpy((VOID *) buffer, (VOID *) Tcl_GetStringResult(interp),
+ (size_t) length);
buffer[length] = '\0';
} else {
length = -1;
@@ -1302,8 +1301,7 @@ LostSelection(clientData)
ClientData clientData; /* Pointer to CommandInfo structure. */
{
LostCommand *lostPtr = (LostCommand *) clientData;
- char *oldResultString;
- Tcl_FreeProc *oldFreeProc;
+ Tcl_Obj *objPtr;
Tcl_Interp *interp;
interp = lostPtr->interp;
@@ -1314,22 +1312,16 @@ LostSelection(clientData)
* restore it after executing the command.
*/
- oldFreeProc = interp->freeProc;
- if (oldFreeProc != TCL_STATIC) {
- oldResultString = interp->result;
- } else {
- oldResultString = (char *) ckalloc((unsigned)
- (strlen(interp->result) + 1));
- strcpy(oldResultString, interp->result);
- oldFreeProc = TCL_DYNAMIC;
- }
- interp->freeProc = TCL_STATIC;
+ objPtr = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(objPtr);
+ Tcl_ResetResult(interp);
+
if (TkCopyAndGlobalEval(interp, lostPtr->command) != TCL_OK) {
Tcl_BackgroundError(interp);
}
- Tcl_FreeResult(interp);
- interp->result = oldResultString;
- interp->freeProc = oldFreeProc;
+
+ Tcl_SetObjResult(interp, objPtr);
+ Tcl_DecrRefCount(objPtr);
Tcl_Release((ClientData) interp);
diff --git a/generic/tkSquare.c b/generic/tkSquare.c
index eff8181..bdb9e29 100644
--- a/generic/tkSquare.c
+++ b/generic/tkSquare.c
@@ -1,23 +1,24 @@
/*
* tkSquare.c --
*
- * This module implements "square" widgets. A "square" is
- * a widget that displays a single square that can be moved
- * around and resized. This file is intended as an example
+ * 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) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkSquare.c 1.19 97/07/31 09:13:13
+ * SCCS: @(#) tkSquare.c 1.25 97/12/22 11:05:09
*/
#include "tkPort.h"
+#define __NO_OLD_CONFIG
#include "tk.h"
+#include "tkInt.h"
/*
* A data structure of the following type is kept for each square
@@ -31,22 +32,24 @@ typedef struct {
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. */
- int x, y; /* Position of square's upper-left corner
+ Tk_OptionTable optionTable; /* Token representing the configuration
+ * specifications. */
+ Tcl_Obj *xPtr, *yPtr; /* Position of square's upper-left corner
* within widget. */
- int size; /* Width and height of square. */
+ int x, y;
+ Tcl_Obj *sizeObjPtr; /* Width and height of square. */
/*
* Information used when displaying widget:
*/
- int borderWidth; /* Width of 3-D border around whole widget. */
- Tk_3DBorder bgBorder; /* Used for drawing background. */
- Tk_3DBorder fgBorder; /* For drawing square. */
- int relief; /* Indicates whether window as a whole is
- * raised, sunken, or flat. */
+ Tcl_Obj *borderWidthPtr; /* Width of 3-D border around whole widget. */
+ Tcl_Obj *bgBorderPtr;
+ Tcl_Obj *fgBorderPtr;
+ Tcl_Obj *reliefPtr;
GC gc; /* Graphics context for copying from
* off-screen pixmap onto screen. */
- int doubleBuffer; /* Non-zero means double-buffer redisplay
+ 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
@@ -57,49 +60,52 @@ typedef struct {
* Information used for argv parsing.
*/
-static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- "#d9d9d9", Tk_Offset(Square, bgBorder), TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- "white", Tk_Offset(Square, 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_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- "2", Tk_Offset(Square, borderWidth), 0},
- {TK_CONFIG_INT, "-dbl", "doubleBuffer", "DoubleBuffer",
- "1", Tk_Offset(Square, doubleBuffer), 0},
- {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground",
- "#b03060", Tk_Offset(Square, fgBorder), TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground",
- "black", Tk_Offset(Square, fgBorder), TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- "raised", Tk_Offset(Square, relief), 0},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+static Tk_OptionSpec configSpecs[] = {
+ {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_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_BORDER, "-foreground", "foreground", "Foreground",
+ "#b03060", Tk_Offset(Square, fgBorderPtr), -1, 0,
+ (ClientData) "black"},
+ {TK_OPTION_PIXELS, "-posx", "posx", "PosX", "0",
+ Tk_Offset(Square, xPtr), -1},
+ {TK_OPTION_PIXELS, "-posy", "posy", "PosY", "0",
+ Tk_Offset(Square, yPtr), -1},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ "raised", Tk_Offset(Square, reliefPtr), -1},
+ {TK_OPTION_PIXELS, "-size", "size", "Size", "20",
+ Tk_Offset(Square, sizeObjPtr), -1},
+ {TK_OPTION_END}
};
/*
* Forward declarations for procedures defined later in this file:
*/
-int SquareCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-static void SquareCmdDeletedProc _ANSI_ARGS_((
+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, int argc, char **argv,
- int flags));
+ 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 SquareEventProc _ANSI_ARGS_((ClientData clientData,
+static void SquareObjEventProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
static int SquareWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *, int argc, char **argv));
+ Tcl_Interp *, int objc, Tcl_Obj * CONST objv[]));
/*
*--------------------------------------------------------------
@@ -119,24 +125,41 @@ static int SquareWidgetCmd _ANSI_ARGS_((ClientData clientData,
*/
int
-SquareCmd(clientData, interp, argc, argv)
+SquareObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
{
- Tk_Window main = (Tk_Window) clientData;
Square *squarePtr;
Tk_Window tkwin;
+ Tk_OptionTable optionTable = (Tk_OptionTable) clientData;
+ Tcl_CmdInfo info;
+ char *commandName;
+
+ if (optionTable == NULL) {
+ /*
+ * The first time this procedure is invoked, optionTable will
+ * be NULL. We then create the option table from the template
+ * and store the table pointer as the command's clinical so
+ * we'll have easy access to it in the future.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, configSpecs);
+ commandName = Tcl_GetStringFromObj(objv[0], (int *) NULL);
+ Tcl_GetCommandInfo(interp, commandName, &info);
+ info.clientData = (ClientData) optionTable;
+ Tcl_SetCommandInfo(interp, commandName, &info);
+ }
- 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;
}
- tkwin = Tk_CreateWindowFromPath(interp, main, argv[1], (char *) NULL);
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetStringFromObj(objv[1], NULL), (char *) NULL);
if (tkwin == NULL) {
return TCL_ERROR;
}
@@ -150,29 +173,47 @@ SquareCmd(clientData, interp, argc, argv)
squarePtr->tkwin = tkwin;
squarePtr->display = Tk_Display(tkwin);
squarePtr->interp = interp;
- squarePtr->widgetCmd = Tcl_CreateCommand(interp,
+ squarePtr->widgetCmd = Tcl_CreateObjCommand(interp,
Tk_PathName(squarePtr->tkwin), SquareWidgetCmd,
- (ClientData) squarePtr, SquareCmdDeletedProc);
+ (ClientData) squarePtr, SquareDeletedProc);
+ squarePtr->xPtr = NULL;
+ squarePtr->yPtr = NULL;
squarePtr->x = 0;
squarePtr->y = 0;
- squarePtr->size = 20;
- squarePtr->borderWidth = 0;
- squarePtr->bgBorder = NULL;
- squarePtr->fgBorder = NULL;
- squarePtr->relief = TK_RELIEF_FLAT;
+ squarePtr->sizeObjPtr = NULL;
+ squarePtr->borderWidthPtr = NULL;
+ squarePtr->bgBorderPtr = NULL;
+ squarePtr->fgBorderPtr = NULL;
+ squarePtr->reliefPtr = NULL;
squarePtr->gc = None;
- squarePtr->doubleBuffer = 1;
+ squarePtr->doubleBufferPtr = NULL;
squarePtr->updatePending = 0;
+ squarePtr->optionTable = optionTable;
- Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask,
- SquareEventProc, (ClientData) squarePtr);
- if (SquareConfigure(interp, squarePtr, argc-2, argv+2, 0) != TCL_OK) {
+ if (Tk_InitOptions(interp, (char *) squarePtr, optionTable, tkwin)
+ != TCL_OK) {
Tk_DestroyWindow(squarePtr->tkwin);
+ ckfree((char *) squarePtr);
return TCL_ERROR;
}
- interp->result = Tk_PathName(squarePtr->tkwin);
+ 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) {
+ goto error;
+ }
+ if (SquareConfigure(interp, squarePtr) != TCL_OK) {
+ goto error;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(squarePtr->tkwin),
+ -1));
return TCL_OK;
+
+error:
+ Tk_DestroyWindow(squarePtr->tkwin);
+ return TCL_ERROR;
}
/*
@@ -194,92 +235,79 @@ SquareCmd(clientData, interp, argc, argv)
*/
static int
-SquareWidgetCmd(clientData, interp, argc, argv)
+SquareWidgetCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about square widget. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj * CONST objv[]; /* Argument objects. */
{
Square *squarePtr = (Square *) clientData;
int result = TCL_OK;
- size_t length;
- char c;
+ static char *squareOptions[] = {"cget", "configure", (char *) NULL};
+ enum {
+ SQUARE_CGET, SQUARE_CONFIGURE
+ };
+ Tcl_Obj *resultObjPtr;
+ int index;
+
+ 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], squareOptions, "command",
+ 0, &index) != TCL_OK) {
return TCL_ERROR;
}
+
Tcl_Preserve((ClientData) squarePtr);
- c = argv[1][0];
- length = strlen(argv[1]);
- 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);
- goto error;
- }
- result = Tk_ConfigureValue(interp, squarePtr->tkwin, configSpecs,
- (char *) squarePtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, squarePtr->tkwin, configSpecs,
- (char *) squarePtr, (char *) NULL, 0);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, squarePtr->tkwin, configSpecs,
- (char *) squarePtr, argv[2], 0);
- } else {
- result = SquareConfigure(interp, squarePtr, argc-2, argv+2,
- TK_CONFIG_ARGV_ONLY);
- }
- } else if ((c == 'p') && (strncmp(argv[1], "position", length) == 0)) {
- if ((argc != 2) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " position ?x y?\"", (char *) NULL);
- goto error;
- }
- if (argc == 4) {
- if ((Tk_GetPixels(interp, squarePtr->tkwin, argv[2],
- &squarePtr->x) != TCL_OK) || (Tk_GetPixels(interp,
- squarePtr->tkwin, argv[3], &squarePtr->y) != TCL_OK)) {
+
+ switch (index) {
+ case SQUARE_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
goto error;
}
- KeepInWindow(squarePtr);
- }
- sprintf(interp->result, "%d %d", squarePtr->x, squarePtr->y);
- } else if ((c == 's') && (strncmp(argv[1], "size", length) == 0)) {
- if ((argc != 2) && (argc != 3)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " size ?amount?\"", (char *) NULL);
- 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;
}
- if (argc == 3) {
- int i;
-
- if (Tk_GetPixels(interp, squarePtr->tkwin, argv[2], &i) != TCL_OK) {
- goto error;
+ 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;
+ }
}
- if ((i <= 0) || (i > 100)) {
- Tcl_AppendResult(interp, "bad size \"", argv[2],
- "\"", (char *) NULL);
- goto error;
+ if (resultObjPtr != NULL) {
+ Tcl_SetObjResult(interp, resultObjPtr);
}
- squarePtr->size = i;
- KeepInWindow(squarePtr);
}
- sprintf(interp->result, "%d", squarePtr->size);
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be cget, configure, position, or size",
- (char *) NULL);
- goto error;
- }
- if (!squarePtr->updatePending) {
- Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr);
- squarePtr->updatePending = 1;
}
Tcl_Release((ClientData) squarePtr);
return result;
@@ -300,7 +328,7 @@ SquareWidgetCmd(clientData, interp, argc, argv)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as colors, border width,
@@ -311,27 +339,25 @@ SquareWidgetCmd(clientData, interp, argc, argv)
*/
static int
-SquareConfigure(interp, squarePtr, argc, argv, flags)
+SquareConfigure(interp, squarePtr)
Tcl_Interp *interp; /* Used for error reporting. */
Square *squarePtr; /* Information about widget. */
- int argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
- int flags; /* Flags to pass to
- * Tk_ConfigureWidget. */
{
- if (Tk_ConfigureWidget(interp, squarePtr->tkwin, configSpecs,
- argc, argv, (char *) squarePtr, flags) != TCL_OK) {
- return TCL_ERROR;
- }
+ int borderWidth;
+ Tk_3DBorder bgBorder;
+ int doubleBuffer;
/*
* Set the background for the window and create a graphics context
* for use during redisplay.
*/
+ bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
+ squarePtr->bgBorderPtr);
Tk_SetWindowBackground(squarePtr->tkwin,
- Tk_3DBorderColor(squarePtr->bgBorder)->pixel);
- if ((squarePtr->gc == None) && (squarePtr->doubleBuffer)) {
+ Tk_3DBorderColor(bgBorder)->pixel);
+ Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
+ if ((squarePtr->gc == None) && (doubleBuffer)) {
XGCValues gcValues;
gcValues.function = GXcopy;
gcValues.graphics_exposures = False;
@@ -345,18 +371,21 @@ SquareConfigure(interp, squarePtr, argc, argv, flags)
*/
Tk_GeometryRequest(squarePtr->tkwin, 200, 150);
- Tk_SetInternalBorder(squarePtr->tkwin, squarePtr->borderWidth);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
+ &borderWidth);
+ Tk_SetInternalBorder(squarePtr->tkwin, borderWidth);
if (!squarePtr->updatePending) {
Tcl_DoWhenIdle(SquareDisplay, (ClientData) squarePtr);
squarePtr->updatePending = 1;
}
+ KeepInWindow(squarePtr);
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
- * SquareEventProc --
+ * SquareObjEventProc --
*
* This procedure is invoked by the Tk dispatcher for various
* events on squares.
@@ -372,7 +401,7 @@ SquareConfigure(interp, squarePtr, argc, argv, flags)
*/
static void
-SquareEventProc(clientData, eventPtr)
+SquareObjEventProc(clientData, eventPtr)
ClientData clientData; /* Information about window. */
XEvent *eventPtr; /* Information about event. */
{
@@ -391,6 +420,11 @@ SquareEventProc(clientData, eventPtr)
}
} else if (eventPtr->type == DestroyNotify) {
if (squarePtr->tkwin != NULL) {
+ Tk_FreeConfigOptions((char *) squarePtr, squarePtr->optionTable,
+ squarePtr->tkwin);
+ if (squarePtr->gc != None) {
+ Tk_FreeGC(squarePtr->display, squarePtr->gc);
+ }
squarePtr->tkwin = NULL;
Tcl_DeleteCommandFromToken(squarePtr->interp,
squarePtr->widgetCmd);
@@ -405,7 +439,7 @@ SquareEventProc(clientData, eventPtr)
/*
*----------------------------------------------------------------------
*
- * SquareCmdDeletedProc --
+ * SquareDeletedProc --
*
* This procedure is invoked when a widget command is deleted. If
* the widget isn't already in the process of being destroyed,
@@ -421,7 +455,7 @@ SquareEventProc(clientData, eventPtr)
*/
static void
-SquareCmdDeletedProc(clientData)
+SquareDeletedProc(clientData)
ClientData clientData; /* Pointer to widget record for widget. */
{
Square *squarePtr = (Square *) clientData;
@@ -435,7 +469,6 @@ SquareCmdDeletedProc(clientData)
*/
if (tkwin != NULL) {
- squarePtr->tkwin = NULL;
Tk_DestroyWindow(tkwin);
}
}
@@ -466,6 +499,9 @@ SquareDisplay(clientData)
Tk_Window tkwin = squarePtr->tkwin;
Pixmap pm = None;
Drawable d;
+ int borderWidth, size, relief;
+ Tk_3DBorder bgBorder, fgBorder;
+ int doubleBuffer;
squarePtr->updatePending = 0;
if (!Tk_IsMapped(tkwin)) {
@@ -476,7 +512,8 @@ SquareDisplay(clientData)
* Create a pixmap for double-buffering, if necessary.
*/
- if (squarePtr->doubleBuffer) {
+ Tcl_GetBooleanFromObj(NULL, squarePtr->doubleBufferPtr, &doubleBuffer);
+ if (doubleBuffer) {
pm = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
Tk_Width(tkwin), Tk_Height(tkwin),
DefaultDepthOfScreen(Tk_Screen(tkwin)));
@@ -489,22 +526,29 @@ SquareDisplay(clientData)
* Redraw the widget's background and border.
*/
- Tk_Fill3DRectangle(tkwin, d, squarePtr->bgBorder, 0, 0, Tk_Width(tkwin),
- Tk_Height(tkwin), squarePtr->borderWidth, squarePtr->relief);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
+ &borderWidth);
+ bgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
+ squarePtr->bgBorderPtr);
+ Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);
+ Tk_Fill3DRectangle(tkwin, d, bgBorder, 0, 0, Tk_Width(tkwin),
+ Tk_Height(tkwin), borderWidth, relief);
/*
* Display the square.
*/
- Tk_Fill3DRectangle(tkwin, d, squarePtr->fgBorder, squarePtr->x,
- squarePtr->y, squarePtr->size, squarePtr->size,
- squarePtr->borderWidth, TK_RELIEF_RAISED);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);
+ fgBorder = Tk_Get3DBorderFromObj(squarePtr->tkwin,
+ squarePtr->fgBorderPtr);
+ Tk_Fill3DRectangle(tkwin, d, fgBorder, squarePtr->x, squarePtr->y, size,
+ size, borderWidth, TK_RELIEF_RAISED);
/*
* If double-buffered, copy to the screen and release the pixmap.
*/
- if (squarePtr->doubleBuffer) {
+ if (doubleBuffer) {
XCopyArea(Tk_Display(tkwin), pm, Tk_WindowId(tkwin), squarePtr->gc,
0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
0, 0);
@@ -535,11 +579,7 @@ SquareDestroy(memPtr)
char *memPtr; /* Info about square widget. */
{
Square *squarePtr = (Square *) memPtr;
-
- Tk_FreeOptions(configSpecs, (char *) squarePtr, squarePtr->display, 0);
- if (squarePtr->gc != None) {
- Tk_FreeGC(squarePtr->display, squarePtr->gc);
- }
+
ckfree((char *) squarePtr);
}
@@ -565,16 +605,26 @@ static void
KeepInWindow(squarePtr)
register Square *squarePtr; /* Pointer to widget record. */
{
- int i, bd;
+ int i, bd, relief;
+ int borderWidth, size;
+
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->borderWidthPtr,
+ &borderWidth);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->xPtr,
+ &squarePtr->x);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->yPtr,
+ &squarePtr->y);
+ Tk_GetPixelsFromObj(NULL, squarePtr->tkwin, squarePtr->sizeObjPtr, &size);
+ Tk_GetReliefFromObj(NULL, squarePtr->reliefPtr, &relief);
bd = 0;
- if (squarePtr->relief != TK_RELIEF_FLAT) {
- bd = squarePtr->borderWidth;
+ if (relief != TK_RELIEF_FLAT) {
+ bd = borderWidth;
}
- i = (Tk_Width(squarePtr->tkwin) - bd) - (squarePtr->x + squarePtr->size);
+ i = (Tk_Width(squarePtr->tkwin) - bd) - (squarePtr->x + size);
if (i < 0) {
squarePtr->x += i;
}
- i = (Tk_Height(squarePtr->tkwin) - bd) - (squarePtr->y + squarePtr->size);
+ i = (Tk_Height(squarePtr->tkwin) - bd) - (squarePtr->y + size);
if (i < 0) {
squarePtr->y += i;
}
diff --git a/generic/tkTest.c b/generic/tkTest.c
index dab43d0..173e1b7 100644
--- a/generic/tkTest.c
+++ b/generic/tkTest.c
@@ -12,11 +12,12 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkTest.c 1.50 97/11/06 16:56:32
+ * SCCS: @(#) tkTest.c 1.57 98/01/30 15:27:07
*/
#include "tkInt.h"
-#include "tkPort.h"
+#include "tkPort.h"
+#include "tkText.h"
#ifdef __WIN32__
#include "tkWinInt.h"
@@ -102,8 +103,8 @@ static NewApp *newAppPtr = NULL;
* Declaration for the square widget's class command procedure:
*/
-extern int SquareCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char *argv[]));
+extern int SquareObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
typedef struct CBinding {
Tcl_Interp *interp;
@@ -112,6 +113,32 @@ typedef struct CBinding {
} CBinding;
/*
+ * Header for trivial configuration command items.
+ */
+
+#define ODD TK_CONFIG_USER_BIT
+#define EVEN (TK_CONFIG_USER_BIT << 1)
+
+enum {
+ NONE,
+ 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. */
+} TrivialCommandHeader;
+
+
+
+/*
* Forward declarations for procedures defined later in this file:
*/
@@ -124,12 +151,23 @@ static int ImageCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
static int TestcbindCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
-#ifdef __WIN32__
-static int TestclipboardCmd _ANSI_ARGS_((ClientData dummy,
- Tcl_Interp *interp, int argc, char **argv));
-#endif
+static int TestbitmapObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * CONST objv[]));
+static int TestborderObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * CONST objv[]));
+static int TestcolorObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * CONST objv[]));
+static int TestcursorObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * CONST objv[]));
static int TestdeleteappsCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
+static int TestfontObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
static int TestmakeexistCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
static int TestmenubarCmd _ANSI_ARGS_((ClientData dummy,
@@ -138,14 +176,26 @@ static int TestmenubarCmd _ANSI_ARGS_((ClientData dummy,
static int TestmetricsCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
#endif
+static int TestobjconfigObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * CONST objv[]));
+static int TestpropCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int argc, char **argv));
static int TestsendCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
-static int TestpropCmd _ANSI_ARGS_((ClientData dummy,
+static int TesttextCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
#if !(defined(__WIN32__) || defined(MAC_TCL))
static int TestwrapperCmd _ANSI_ARGS_((ClientData dummy,
Tcl_Interp *interp, int argc, char **argv));
#endif
+static void TrivialCmdDeletedProc _ANSI_ARGS_((
+ ClientData clientData));
+static int TrivialConfigObjCmd _ANSI_ARGS_((ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj * CONST objv[]));
+static void TrivialEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
/*
* External (platform specific) initialization routine:
@@ -153,7 +203,7 @@ static int TestwrapperCmd _ANSI_ARGS_((ClientData dummy,
EXTERN int TkplatformtestInit _ANSI_ARGS_((
Tcl_Interp *interp));
-#ifndef MAC_TCL
+#if !(defined(__WIN32__) || defined(MAC_TCL))
#define TkplatformtestInit(x) TCL_OK
#endif
@@ -167,7 +217,7 @@ EXTERN int TkplatformtestInit _ANSI_ARGS_((
*
* Results:
* Returns a standard Tcl completion code, and leaves an error
- * message in interp->result if an error occurs.
+ * message in the interp's result if an error occurs.
*
* Side effects:
* Creates several test commands.
@@ -189,18 +239,26 @@ Tktest_Init(interp)
return TCL_ERROR;
}
- Tcl_CreateCommand(interp, "square", SquareCmd,
+ Tcl_CreateObjCommand(interp, "square", SquareObjCmd,
+ (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, "testcbind", TestcbindCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
-#ifdef __WIN32__
- Tcl_CreateCommand(interp, "testclipboard", TestclipboardCmd,
+ Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
-#endif
- Tcl_CreateCommand(interp, "testcbind", TestcbindCmd,
+ Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateObjCommand(interp, "testcursor", TestcursorObjCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testdeleteapps", TestdeleteappsCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testembed", TkpTestembedCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateObjCommand(interp, "testobjconfig", TestobjconfigObjCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testmakeexist", TestmakeexistCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testmenubar", TestmenubarCmd,
@@ -213,6 +271,8 @@ Tktest_Init(interp)
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
Tcl_CreateCommand(interp, "testsend", TestsendCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
+ Tcl_CreateCommand(interp, "testtext", TesttextCmd,
+ (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
#if !(defined(__WIN32__) || defined(MAC_TCL))
Tcl_CreateCommand(interp, "testwrapper", TestwrapperCmd,
(ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
@@ -237,48 +297,6 @@ Tktest_Init(interp)
/*
*----------------------------------------------------------------------
*
- * TestclipboardCmd --
- *
- * This procedure implements the testclipboard command. It provides
- * a way to determine the actual contents of the Windows clipboard.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-#ifdef __WIN32__
-static int
-TestclipboardCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window for application. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
-{
- TkWindow *winPtr = (TkWindow *) clientData;
- HGLOBAL handle;
- char *data;
-
- if (OpenClipboard(NULL)) {
- handle = GetClipboardData(CF_TEXT);
- if (handle != NULL) {
- data = GlobalLock(handle);
- Tcl_AppendResult(interp, data, (char *) NULL);
- GlobalUnlock(handle);
- }
- CloseClipboard();
- }
- return TCL_OK;
-}
-#endif
-
-/*
- *----------------------------------------------------------------------
- *
* TestcbindCmd --
*
* This procedure implements the "testcbinding" command. It provides
@@ -386,6 +404,146 @@ CBindingFreeProc(clientData)
/*
*----------------------------------------------------------------------
*
+ * TestbitmapObjCmd --
+ *
+ * This procedure implements the "testbitmap" command, which is used
+ * to test color resource handling in tkBitmap tmp.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "bitmap");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugBitmap(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestborderObjCmd --
+ *
+ * This procedure implements the "testborder" command, which is used
+ * to test color resource handling in tkBorder.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "border");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugBorder(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestcolorObjCmd --
+ *
+ * This procedure implements the "testcolor" command, which is used
+ * to test color resource handling in tkColor.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "color");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugColor(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestcursorObjCmd --
+ *
+ * This procedure implements the "testcursor" command, which is used
+ * to test color resource handling in tkCursor.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cursor");
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, TkDebugCursor(Tk_MainWindow(interp),
+ Tcl_GetString(objv[1])));
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TestdeleteappsCmd --
*
* This procedure implements the "testdeleteapps" command. It cleans
@@ -424,6 +582,956 @@ TestdeleteappsCmd(clientData, interp, argc, argv)
/*
*----------------------------------------------------------------------
*
+ * TestobjconfigObjCmd --
+ *
+ * This procedure implements the "testobjconfig" command,
+ * which is used to test the procedures in tkConfig.c.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+ static char *options[] = {"alltypes", "chain1", "chain2",
+ "configerror", "delete", "info", "internal", "new",
+ "notenoughparams", "twowindows", (char *) NULL};
+ enum {
+ ALL_TYPES,
+ CHAIN1,
+ CHAIN2,
+ CONFIG_ERROR,
+ DEL, /* Can't use DELETE: VC++ compiler barfs. */
+ 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. */
+ 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:
+ */
+
+ typedef struct ExtensionWidgetRecord {
+ TrivialCommandHeader header;
+ Tcl_Obj *base1ObjPtr;
+ Tcl_Obj *base2ObjPtr;
+ Tcl_Obj *extension3ObjPtr;
+ Tcl_Obj *extension4ObjPtr;
+ Tcl_Obj *extension5ObjPtr;
+ } ExtensionWidgetRecord;
+ static Tk_OptionSpec baseSpecs[] = {
+ {TK_OPTION_STRING,
+ "-one", "one", "One", "one",
+ Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1},
+ {TK_OPTION_STRING,
+ "-two", "two", "Two", "two",
+ Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1},
+ {TK_OPTION_END}
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "command");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, &index)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ 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;
+ } 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_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;
+ 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 {
+ 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;
+
+ 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);
+ }
+ }
+ 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 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;
+
+ 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 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 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 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 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;
+ } 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_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;
+ 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 {
+ Tk_DestroyWindow(tkwin);
+ ckfree((char *) recordPtr);
+ }
+ if (result == TCL_OK) {
+ Tcl_SetObjResult(interp, objv[2]);
+ }
+ 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 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;
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ 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);
+ 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);
+ }
+
+ }
+ }
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TrivialConfigObjCmd --
+ *
+ * This command is used to test the configuration package. It only
+ * handles the "configure" and "cget" subcommands.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+ int result = TCL_OK;
+ static char *options[] = {"cget", "configure", "csave", (char *) NULL};
+ enum {
+ CGET, CONFIGURE, CSAVE
+ };
+ Tcl_Obj *resultObjPtr;
+ int index, mask;
+ TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
+ Tk_Window tkwin = headerPtr->tkwin;
+ Tk_SavedOptions saved;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ 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");
+ 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, (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);
+ }
+ }
+ 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:
+ Tcl_Release(clientData);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The widget is destroyed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+TrivialCmdDeletedProc(clientData)
+ ClientData clientData; /* Pointer to widget record for widget. */
+{
+ TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
+ Tk_Window tkwin = headerPtr->tkwin;
+
+ if (tkwin != NULL) {
+ 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.
+ */
+
+ Tk_FreeConfigOptions((char *) clientData,
+ headerPtr->optionTable, (Tk_Window) NULL);
+ Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TrivialEventProc --
+ *
+ * A dummy event proc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * 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. */
+{
+ TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ if (headerPtr->tkwin != NULL) {
+ Tk_FreeConfigOptions((char *) clientData,
+ headerPtr->optionTable, headerPtr->tkwin);
+ headerPtr->optionTable = NULL;
+ headerPtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(headerPtr->interp,
+ headerPtr->widgetCmd);
+ }
+ Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TestfontObjCmd --
+ *
+ * This procedure implements the "testfont" command, which is used
+ * to test TkFont objects.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* 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. */
+{
+ static char *options[] = {"counts", "subfonts", (char *) NULL};
+ enum option {COUNTS, SUBFONTS};
+ int index;
+ Tk_Window tkwin;
+ Tk_Font tkfont;
+
+ tkwin = (Tk_Window) clientData;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option fontName");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, &index)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ 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;
+ }
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ImageCreate --
*
* This procedure is called by the Tk image code to create "test"
@@ -523,7 +1631,8 @@ ImageCmd(clientData, interp, argc, argv)
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",
+ argv[0],
+ " changed x y width height imageWidth imageHeight",
(char *) NULL);
return TCL_ERROR;
}
@@ -617,7 +1726,7 @@ ImageDisplay(clientData, display, drawable, imageX, imageY, width, height,
* imageX and imageY. */
{
TImageInstance *instPtr = (TImageInstance *) clientData;
- char buffer[200];
+ char buffer[200 + TCL_INTEGER_SPACE * 6];
sprintf(buffer, "%s display %d %d %d %d %d %d",
instPtr->masterPtr->imageName, imageX, imageY, width, height,
@@ -734,12 +1843,12 @@ TestmakeexistCmd(clientData, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- Tk_Window main = (Tk_Window) clientData;
+ Tk_Window mainWin = (Tk_Window) clientData;
int i;
Tk_Window tkwin;
for (i = 1; i < argc; i++) {
- tkwin = Tk_NameToWindow(interp, argv[i], main);
+ tkwin = Tk_NameToWindow(interp, argv[i], mainWin);
if (tkwin == NULL) {
return TCL_ERROR;
}
@@ -776,7 +1885,7 @@ TestmenubarCmd(clientData, interp, argc, argv)
char **argv; /* Argument strings. */
{
#ifdef __UNIX__
- Tk_Window main = (Tk_Window) clientData;
+ Tk_Window mainWin = (Tk_Window) clientData;
Tk_Window tkwin, menubar;
if (argc < 2) {
@@ -791,14 +1900,14 @@ TestmenubarCmd(clientData, interp, argc, argv)
"window toplevel menubar\"", (char *) NULL);
return TCL_ERROR;
}
- tkwin = Tk_NameToWindow(interp, argv[2], main);
+ tkwin = Tk_NameToWindow(interp, argv[2], mainWin);
if (tkwin == NULL) {
return TCL_ERROR;
}
if (argv[3][0] == 0) {
TkUnixSetMenubar(tkwin, NULL);
} else {
- menubar = Tk_NameToWindow(interp, argv[3], main);
+ menubar = Tk_NameToWindow(interp, argv[3], mainWin);
if (menubar == NULL) {
return TCL_ERROR;
}
@@ -812,7 +1921,8 @@ TestmenubarCmd(clientData, interp, argc, argv)
return TCL_OK;
#else
- interp->result = "testmenubar is supported only under Unix";
+ Tcl_SetResult(interp, "testmenubar is supported only under Unix",
+ TCL_STATIC);
return TCL_ERROR;
#endif
}
@@ -842,7 +1952,7 @@ TestmetricsCmd(clientData, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- char buf[200];
+ char buf[TCL_INTEGER_SPACE];
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0],
@@ -874,7 +1984,7 @@ TestmetricsCmd(clientData, interp, argc, argv)
{
Tk_Window tkwin = (Tk_Window) clientData;
TkWindow *winPtr;
- char buf[200];
+ char buf[TCL_INTEGER_SPACE];
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0],
@@ -927,7 +2037,7 @@ TestpropCmd(clientData, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- Tk_Window main = (Tk_Window) clientData;
+ Tk_Window mainWin = (Tk_Window) clientData;
int result, actualFormat;
unsigned long bytesAfter, length, value;
Atom actualType, propName;
@@ -942,9 +2052,9 @@ TestpropCmd(clientData, interp, argc, argv)
}
w = strtoul(argv[1], &end, 0);
- propName = Tk_InternAtom(main, argv[2]);
+ propName = Tk_InternAtom(mainWin, argv[2]);
property = NULL;
- result = XGetWindowProperty(Tk_Display(main),
+ result = XGetWindowProperty(Tk_Display(mainWin),
w, propName, 0, 100000, False, AnyPropertyType,
&actualType, &actualFormat, &length,
&bytesAfter, (unsigned char **) &property);
@@ -1005,7 +2115,9 @@ TestsendCmd(clientData, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
+#if !(defined(__WIN32__) || defined(MAC_TCL))
TkWindow *winPtr = (TkWindow *) clientData;
+#endif
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args; must be \"", argv[0],
@@ -1073,7 +2185,10 @@ TestsendCmd(clientData, interp, argc, argv)
}
}
} else if (strcmp(argv[1], "serial") == 0) {
- sprintf(interp->result, "%d", tkSendSerial+1);
+ 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);
@@ -1083,6 +2198,85 @@ TestsendCmd(clientData, interp, argc, argv)
return TCL_OK;
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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. */
+ 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))
/*
*----------------------------------------------------------------------
@@ -1127,7 +2321,10 @@ TestwrapperCmd(clientData, interp, argc, argv)
wrapperPtr = TkpGetWrapperWindow(winPtr);
if (wrapperPtr != NULL) {
- TkpPrintWindowId(interp->result, Tk_WindowId(wrapperPtr));
+ char buf[TCL_INTEGER_SPACE];
+
+ TkpPrintWindowId(buf, Tk_WindowId(wrapperPtr));
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
return TCL_OK;
}
diff --git a/generic/tkText.c b/generic/tkText.c
index 643aea0..3e15552 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkText.c 1.104 97/10/13 15:18:24
+ * SCCS: @(#) tkText.c 1.108 98/01/12 15:55:43
*/
#include "default.h"
@@ -290,7 +290,7 @@ Tk_TextCmd(clientData, interp, argc, argv)
textPtr->prevWidth = Tk_Width(new);
textPtr->prevHeight = Tk_Height(new);
TkTextCreateDInfo(textPtr);
- TkTextMakeIndex(textPtr->tree, 0, 0, &startIndex);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &startIndex);
TkTextSetYView(textPtr, &startIndex, 0);
textPtr->selTagPtr = NULL;
textPtr->selBorder = NULL;
@@ -322,7 +322,8 @@ Tk_TextCmd(clientData, interp, argc, argv)
*/
textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel");
- textPtr->selTagPtr->reliefString = (char *) ckalloc(7);
+ textPtr->selTagPtr->reliefString =
+ (char *) ckalloc(sizeof(DEF_TEXT_SELECT_RELIEF));
strcpy(textPtr->selTagPtr->reliefString, DEF_TEXT_SELECT_RELIEF);
textPtr->selTagPtr->relief = TK_RELIEF_RAISED;
textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &startIndex);
@@ -343,7 +344,7 @@ Tk_TextCmd(clientData, interp, argc, argv)
Tk_DestroyWindow(textPtr->tkwin);
return TCL_ERROR;
}
- interp->result = Tk_PathName(textPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(textPtr->tkwin), TCL_STATIC);
return TCL_OK;
}
@@ -401,7 +402,10 @@ TextWidgetCmd(clientData, interp, argc, argv)
goto done;
}
if (TkTextCharBbox(textPtr, &index1, &x, &y, &width, &height) == 0) {
- sprintf(interp->result, "%d %d %d %d", x, y, width, height);
+ 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)) {
@@ -459,7 +463,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
} else {
goto compareError;
}
- interp->result = (value) ? "1" : "0";
+ Tcl_SetResult(interp, ((value) ? "1" : "0"), TCL_STATIC);
} else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
&& (length >= 3)) {
if (argc == 2) {
@@ -481,7 +485,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
goto done;
}
if (argc == 2) {
- interp->result = (tkBTreeDebug) ? "1" : "0";
+ Tcl_SetResult(interp, ((tkBTreeDebug) ? "1" : "0"), TCL_STATIC);
} else {
if (Tcl_GetBoolean(interp, argv[2], &tkBTreeDebug) != TCL_OK) {
result = TCL_ERROR;
@@ -517,8 +521,10 @@ TextWidgetCmd(clientData, interp, argc, argv)
}
if (TkTextDLineInfo(textPtr, &index1, &x, &y, &width, &height, &base)
== 0) {
- sprintf(interp->result, "%d %d %d %d %d", x, y, width,
- height, base);
+ char buf[TCL_INTEGER_SPACE * 5];
+
+ sprintf(buf, "%d %d %d %d %d", x, y, width, height, base);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
if ((argc != 3) && (argc != 4)) {
@@ -551,10 +557,10 @@ TextWidgetCmd(clientData, interp, argc, argv)
if (index1.linePtr == index2.linePtr) {
int last2;
- if (index2.charIndex == index1.charIndex) {
+ if (index2.byteIndex == index1.byteIndex) {
break;
}
- last2 = index2.charIndex - index1.charIndex + offset;
+ last2 = index2.byteIndex - index1.byteIndex + offset;
if (last2 < last) {
last = last2;
}
@@ -566,10 +572,12 @@ TextWidgetCmd(clientData, interp, argc, argv)
(char *) NULL);
segPtr->body.chars[last] = savedChar;
}
- TkTextIndexForwChars(&index1, last-offset, &index1);
+ TkTextIndexForwBytes(&index1, last-offset, &index1);
}
} else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
&& (length >= 3)) {
+ char buf[200];
+
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " index index\"",
@@ -581,7 +589,8 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- TkTextPrintIndex(&index1, interp->result);
+ 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;
@@ -604,7 +613,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
for (j = 3; j < argc; j += 2) {
InsertChars(textPtr, &index1, argv[j]);
if (argc > (j+1)) {
- TkTextIndexForwChars(&index1, (int) strlen(argv[j]),
+ TkTextIndexForwBytes(&index1, (int) strlen(argv[j]),
&index2);
oldTagArrayPtr = TkBTreeGetTags(&index1, &numTags);
if (oldTagArrayPtr != NULL) {
@@ -745,7 +754,7 @@ DestroyText(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as text string, colors, font,
@@ -882,8 +891,8 @@ ConfigureText(interp, textPtr, argc, argv, flags)
TkTextSearch search;
TkTextIndex first, last;
- TkTextMakeIndex(textPtr->tree, 0, 0, &first);
- TkTextMakeIndex(textPtr->tree,
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
+ TkTextMakeByteIndex(textPtr->tree,
TkBTreeNumLines(textPtr->tree), 0, &last);
TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search);
if (TkBTreeCharTagged(&first, textPtr->selTagPtr)
@@ -1114,7 +1123,7 @@ InsertChars(textPtr, indexPtr, string)
lineIndex = TkBTreeLineIndex(indexPtr->linePtr);
if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
lineIndex--;
- TkTextMakeIndex(textPtr->tree, lineIndex, 1000000, indexPtr);
+ TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, indexPtr);
}
/*
@@ -1127,16 +1136,16 @@ InsertChars(textPtr, indexPtr, string)
resetView = offset = 0;
if (indexPtr->linePtr == textPtr->topIndex.linePtr) {
resetView = 1;
- offset = textPtr->topIndex.charIndex;
- if (offset > indexPtr->charIndex) {
+ offset = textPtr->topIndex.byteIndex;
+ if (offset > indexPtr->byteIndex) {
offset += strlen(string);
}
}
TkTextChanged(textPtr, indexPtr, indexPtr);
TkBTreeInsertChars(indexPtr, string);
if (resetView) {
- TkTextMakeIndex(textPtr->tree, lineIndex, 0, &newTop);
- TkTextIndexForwChars(&newTop, offset, &newTop);
+ TkTextMakeByteIndex(textPtr->tree, lineIndex, 0, &newTop);
+ TkTextIndexForwBytes(&newTop, offset, &newTop);
TkTextSetYView(textPtr, &newTop, 0);
}
@@ -1175,7 +1184,7 @@ DeleteChars(textPtr, index1String, index2String)
* delete the one character given by
* index1String. */
{
- int line1, line2, line, charIndex, resetView;
+ int line1, line2, line, byteIndex, resetView;
TkTextIndex index1, index2;
/*
@@ -1226,7 +1235,7 @@ DeleteChars(textPtr, index1String, index2String)
oldIndex2 = index2;
TkTextIndexBackChars(&oldIndex2, 1, &index2);
line2--;
- if ((index1.charIndex == 0) && (line1 != 0)) {
+ if ((index1.byteIndex == 0) && (line1 != 0)) {
TkTextIndexBackChars(&index1, 1, &index1);
line1--;
}
@@ -1249,7 +1258,9 @@ DeleteChars(textPtr, index1String, index2String)
*/
TkTextChanged(textPtr, &index1, &index2);
- resetView = line = charIndex = 0;
+ resetView = 0;
+ line = 0;
+ byteIndex = 0;
if (TkTextIndexCmp(&index2, &textPtr->topIndex) >= 0) {
if (TkTextIndexCmp(&index1, &textPtr->topIndex) <= 0) {
/*
@@ -1259,7 +1270,7 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line1;
- charIndex = index1.charIndex;
+ byteIndex = index1.byteIndex;
} else if (index1.linePtr == textPtr->topIndex.linePtr) {
/*
* Deletion range starts on top line but after topIndex.
@@ -1268,7 +1279,7 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line1;
- charIndex = textPtr->topIndex.charIndex;
+ byteIndex = textPtr->topIndex.byteIndex;
}
} else if (index2.linePtr == textPtr->topIndex.linePtr) {
/*
@@ -1279,16 +1290,16 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line2;
- charIndex = textPtr->topIndex.charIndex;
+ byteIndex = textPtr->topIndex.byteIndex;
if (index1.linePtr != index2.linePtr) {
- charIndex -= index2.charIndex;
+ byteIndex -= index2.byteIndex;
} else {
- charIndex -= (index2.charIndex - index1.charIndex);
+ byteIndex -= (index2.byteIndex - index1.byteIndex);
}
}
TkBTreeDeleteChars(&index1, &index2);
if (resetView) {
- TkTextMakeIndex(textPtr->tree, line, charIndex, &index1);
+ TkTextMakeByteIndex(textPtr->tree, line, byteIndex, &index1);
TkTextSetYView(textPtr, &index1, 0);
}
@@ -1352,12 +1363,12 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
*/
if (offset == 0) {
- TkTextMakeIndex(textPtr->tree, 0, 0, &textPtr->selIndex);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &textPtr->selIndex);
textPtr->abortSelections = 0;
} else if (textPtr->abortSelections) {
return 0;
}
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &eof);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &eof);
TkBTreeStartSearch(&textPtr->selIndex, &eof, textPtr->selTagPtr, &search);
if (!TkBTreeCharTagged(&textPtr->selIndex, textPtr->selTagPtr)) {
if (!TkBTreeNextTag(&search)) {
@@ -1404,8 +1415,8 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
if (textPtr->selIndex.linePtr == search.curIndex.linePtr) {
int leftInRange;
- leftInRange = search.curIndex.charIndex
- - textPtr->selIndex.charIndex;
+ leftInRange = search.curIndex.byteIndex
+ - textPtr->selIndex.byteIndex;
if (leftInRange < chunkSize) {
chunkSize = leftInRange;
if (chunkSize <= 0) {
@@ -1420,7 +1431,7 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
maxBytes -= chunkSize;
count += chunkSize;
}
- TkTextIndexForwChars(&textPtr->selIndex, chunkSize,
+ TkTextIndexForwBytes(&textPtr->selIndex, chunkSize,
&textPtr->selIndex);
}
@@ -1477,8 +1488,8 @@ TkTextLostSelection(clientData)
* just remove the "sel" tag from everything in the widget.
*/
- TkTextMakeIndex(textPtr->tree, 0, 0, &start);
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &end);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &start);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &end);
TkTextRedrawTag(textPtr, &start, &end, textPtr->selTagPtr, 1);
TkBTreeTag(&start, &end, textPtr->selTagPtr, 0);
#endif
@@ -1556,8 +1567,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
{
int backwards, exact, c, i, argsLeft, noCase, leftToScan;
size_t length;
- int numLines, startingLine, startingChar, lineNum, firstChar, lastChar;
- int code, matchLength, matchChar, passes, stopLine, searchWholeText;
+ int numLines, startingLine, startingByte, lineNum, firstByte, lastByte;
+ int code, matchLength, matchByte, passes, stopLine, searchWholeText;
int patLength;
char *arg, *pattern, *varName, *p, *startOfLine;
char buffer[20];
@@ -1594,7 +1605,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
backwards = 1;
} else if ((c == 'c') && (strncmp(argv[i], "-count", length) == 0)) {
if (i >= (argc-1)) {
- interp->result = "no value given for \"-count\" option";
+ Tcl_SetResult(interp, "no value given for \"-count\" option",
+ TCL_STATIC);
return TCL_ERROR;
}
i++;
@@ -1631,11 +1643,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
Tcl_DStringInit(&patDString);
Tcl_DStringAppend(&patDString, pattern, -1);
pattern = Tcl_DStringValue(&patDString);
- for (p = pattern; *p != 0; p++) {
- if (isupper(UCHAR(*p))) {
- *p = tolower(UCHAR(*p));
- }
- }
+ Tcl_UtfToLower(pattern);
}
if (TkTextGetIndex(interp, textPtr, argv[i+1], &index) != TCL_OK) {
@@ -1643,15 +1651,15 @@ TextSearchCmd(textPtr, interp, argc, argv)
}
numLines = TkBTreeNumLines(textPtr->tree);
startingLine = TkBTreeLineIndex(index.linePtr);
- startingChar = index.charIndex;
+ startingByte = index.byteIndex;
if (startingLine >= numLines) {
if (backwards) {
startingLine = TkBTreeNumLines(textPtr->tree) - 1;
- startingChar = TkBTreeCharsInLine(TkBTreeFindLine(textPtr->tree,
+ startingByte = TkBTreeBytesInLine(TkBTreeFindLine(textPtr->tree,
startingLine));
} else {
startingLine = 0;
- startingChar = 0;
+ startingByte = 0;
}
}
if (argsLeft == 1) {
@@ -1719,11 +1727,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
if (noCase) {
- for (p = Tcl_DStringValue(&line); *p != 0; p++) {
- if (isupper(UCHAR(*p))) {
- *p = tolower(UCHAR(*p));
- }
- }
+ Tcl_DStringSetLength(&line,
+ Tcl_UtfToLower(Tcl_DStringValue(&line)));
}
/*
@@ -1732,9 +1737,9 @@ TextSearchCmd(textPtr, interp, argc, argv)
* in the line.
*/
- matchChar = -1;
- firstChar = 0;
- lastChar = INT_MAX;
+ matchByte = -1;
+ firstByte = 0;
+ lastByte = INT_MAX;
if (lineNum == startingLine) {
int indexInDString;
@@ -1748,8 +1753,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
* character.
*/
- indexInDString = startingChar;
- for (segPtr = linePtr->segPtr, leftToScan = startingChar;
+ indexInDString = startingByte;
+ for (segPtr = linePtr->segPtr, leftToScan = startingByte;
leftToScan > 0; segPtr = segPtr->nextPtr) {
if (segPtr->typePtr != &tkTextCharType) {
indexInDString -= segPtr->size;
@@ -1763,8 +1768,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Only use the last part of the line.
*/
- firstChar = indexInDString;
- if (firstChar >= Tcl_DStringLength(&line)) {
+ firstByte = indexInDString;
+ if (firstByte >= Tcl_DStringLength(&line)) {
goto nextLine;
}
} else {
@@ -1772,13 +1777,14 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Use only the first part of the line.
*/
- lastChar = indexInDString;
+ lastByte = indexInDString;
}
}
do {
int thisLength;
if (exact) {
- p = strstr(startOfLine + firstChar, pattern);
+ p = strstr(startOfLine + firstByte, /* INTL: Native. */
+ pattern);
if (p == NULL) {
break;
}
@@ -1789,7 +1795,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
int match;
match = Tcl_RegExpExec(interp, regexp,
- startOfLine + firstChar, startOfLine);
+ startOfLine + firstByte, startOfLine);
if (match < 0) {
code = TCL_ERROR;
goto done;
@@ -1801,12 +1807,12 @@ TextSearchCmd(textPtr, interp, argc, argv)
i = start - startOfLine;
thisLength = end - start;
}
- if (i >= lastChar) {
+ if (i >= lastByte) {
break;
}
- matchChar = i;
+ matchByte = i;
matchLength = thisLength;
- firstChar = matchChar+1;
+ firstByte = matchByte + 1;
} while (backwards);
/*
@@ -1815,7 +1821,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
* specified.
*/
- if (matchChar >= 0) {
+ if (matchByte >= 0) {
/*
* The index information returned by the regular expression
* parser only considers textual information: it doesn't
@@ -1824,10 +1830,10 @@ TextSearchCmd(textPtr, interp, argc, argv)
* matchChar and matchCount.
*/
- for (segPtr = linePtr->segPtr, leftToScan = matchChar;
+ for (segPtr = linePtr->segPtr, leftToScan = matchByte;
leftToScan >= 0; segPtr = segPtr->nextPtr) {
if (segPtr->typePtr != &tkTextCharType) {
- matchChar += segPtr->size;
+ matchByte += segPtr->size;
continue;
}
leftToScan -= segPtr->size;
@@ -1840,7 +1846,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
}
leftToScan -= segPtr->size;
}
- TkTextMakeIndex(textPtr->tree, lineNum, matchChar, &index);
+ TkTextMakeByteIndex(textPtr->tree, lineNum, matchByte, &index);
if (!searchWholeText) {
if (!backwards && (TkTextIndexCmp(&index, &stopIndex) >= 0)) {
goto done;
@@ -1857,7 +1863,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
goto done;
}
}
- TkTextPrintIndex(&index, interp->result);
+ TkTextPrintIndex(&index, buffer);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
goto done;
}
@@ -1906,7 +1913,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* Memory is allocated for the structure that is returned. It is
@@ -2104,10 +2111,10 @@ TextDumpCmd(textPtr, interp, argc, argv)
}
if (index1.linePtr == index2.linePtr) {
DumpLine(interp, textPtr, what, index1.linePtr,
- index1.charIndex, index2.charIndex, lineno, command);
+ index1.byteIndex, index2.byteIndex, lineno, command);
} else {
DumpLine(interp, textPtr, what, index1.linePtr,
- index1.charIndex, 32000000, lineno, command);
+ index1.byteIndex, 32000000, lineno, command);
linePtr = index1.linePtr;
while ((linePtr = TkBTreeNextLine(linePtr)) != (TkTextLine *)NULL) {
lineno++;
@@ -2118,14 +2125,14 @@ TextDumpCmd(textPtr, interp, argc, argv)
lineno, command);
}
DumpLine(interp, textPtr, what, index2.linePtr, 0,
- index2.charIndex, lineno, command);
+ 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);
+ 0, 1, lineno, command);
}
return TCL_OK;
@@ -2143,12 +2150,12 @@ TextDumpCmd(textPtr, interp, argc, argv)
* None, but see DumpSegment.
*/
static void
-DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
+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 start, end; /* Character range to dump */
+ int startByte, endByte; /* Byte range to dump */
int lineno; /* Line number for indices dump */
char *command; /* Script to apply to the segment */
{
@@ -2163,25 +2170,25 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
* window
*/
for (offset = 0, segPtr = linePtr->segPtr ;
- (offset < end) && (segPtr != (TkTextSegment *)NULL) ;
+ (offset < endByte) && (segPtr != (TkTextSegment *)NULL) ;
offset += segPtr->size, segPtr = segPtr->nextPtr) {
if ((what & TK_DUMP_TEXT) && (segPtr->typePtr == &tkTextCharType) &&
- (offset + segPtr->size > start)) {
+ (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 > end) {
- last = end - offset;
+ if (offset + segPtr->size > endByte) {
+ last = endByte - offset;
}
- if (start > offset) {
- first = start - offset;
+ if (startByte > offset) {
+ first = startByte - offset;
}
savedChar = segPtr->body.chars[last];
segPtr->body.chars[last] = '\0';
DumpSegment(interp, "text", segPtr->body.chars + first,
command, lineno, offset + first, what);
segPtr->body.chars[last] = savedChar;
- } else if ((offset >= start)) {
+ } 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);
@@ -2237,11 +2244,11 @@ DumpSegment(interp, key, value, command, lineno, offset, what)
char *value; /* Segment value */
char *command; /* Script callback */
int lineno; /* Line number for indices dump */
- int offset; /* Character position */
+ int offset; /* Byte position */
int what; /* Look for TK_DUMP_INDEX bit */
{
char buffer[30];
- sprintf(buffer, "%d.%d", lineno, offset);
+ sprintf(buffer, "%d.%d", lineno, offset);
if (command == (char *) NULL) {
Tcl_AppendElement(interp, key);
Tcl_AppendElement(interp, value);
diff --git a/generic/tkText.h b/generic/tkText.h
index a7999d2..5648fb9 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkText.h 1.46 96/11/25 11:26:12
+ * SCCS: @(#) tkText.h 1.47 98/01/08 13:41:18
*/
#ifndef _TKTEXT
@@ -176,7 +176,7 @@ typedef struct TkTextIndex {
TkTextBTree tree; /* Tree containing desired position. */
TkTextLine *linePtr; /* Pointer to line containing position
* of interest. */
- int charIndex; /* Index within line of desired
+ int byteIndex; /* Index within line of desired
* character (0 means first one). */
} TkTextIndex;
@@ -241,7 +241,7 @@ struct TkTextDispChunk {
* a given x-location. */
Tk_ChunkBboxProc *bboxProc; /* Procedure to find bounding box
* of character in chunk. */
- int numChars; /* Number of characters that will be
+ int numBytes; /* Number of bytes that will be
* displayed in the chunk. */
int minAscent; /* Minimum space above the baseline
* needed by this chunk. */
@@ -256,7 +256,7 @@ struct TkTextDispChunk {
* of line. */
int breakIndex; /* Index within chunk of last
* acceptable position for a line
- * (break just before this character).
+ * (break just before this byte index).
* <= 0 means don't break during or
* immediately after this chunk. */
ClientData clientData; /* Additional information for use
@@ -730,6 +730,7 @@ 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,
@@ -784,23 +785,35 @@ extern int TkTextGetIndex _ANSI_ARGS_((Tcl_Interp *interp,
TkTextIndex *indexPtr));
extern TkTextTabArray * TkTextGetTabs _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Window tkwin, char *string));
-extern void TkTextIndexBackChars _ANSI_ARGS_((TkTextIndex *srcPtr,
- int count, TkTextIndex *dstPtr));
-extern int TkTextIndexCmp _ANSI_ARGS_((TkTextIndex *index1Ptr,
- TkTextIndex *index2Ptr));
-extern void TkTextIndexForwChars _ANSI_ARGS_((TkTextIndex *srcPtr,
- int count, TkTextIndex *dstPtr));
-extern TkTextSegment * TkTextIndexToSeg _ANSI_ARGS_((TkTextIndex *indexPtr,
- int *offsetPtr));
+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 * TkTextMakeIndex _ANSI_ARGS_((TkTextBTree tree,
+extern TkTextIndex * TkTextMakeCharIndex _ANSI_ARGS_((TkTextBTree tree,
int lineIndex, int charIndex,
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, char **argv));
extern int TkTextMarkNameToIndex _ANSI_ARGS_((TkText *textPtr,
@@ -812,8 +825,8 @@ 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_((TkTextIndex *indexPtr,
- char *string));
+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,
@@ -824,8 +837,9 @@ extern int TkTextScanCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
extern int TkTextSeeCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextSegToOffset _ANSI_ARGS_((TkTextSegment *segPtr,
- TkTextLine *linePtr));
+extern int TkTextSegToOffset _ANSI_ARGS_((
+ CONST TkTextSegment *segPtr,
+ CONST TkTextLine *linePtr));
extern TkTextSegment * TkTextSetMark _ANSI_ARGS_((TkText *textPtr, char *name,
TkTextIndex *indexPtr));
extern void TkTextSetYView _ANSI_ARGS_((TkText *textPtr,
diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c
index 2fd7deb..907b7d9 100644
--- a/generic/tkTextBTree.c
+++ b/generic/tkTextBTree.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkTextBTree.c 1.37 97/04/25 16:52:00
+ * SCCS: @(#) tkTextBTree.c 1.38 98/01/08 13:40:24
*/
#include "tkInt.h"
@@ -535,7 +535,7 @@ SplitSeg(indexPtr)
TkTextSegment *prevPtr, *segPtr;
int count;
- for (count = indexPtr->charIndex, prevPtr = NULL,
+ for (count = indexPtr->byteIndex, prevPtr = NULL,
segPtr = indexPtr->linePtr->segPtr; segPtr != NULL;
count -= segPtr->size, prevPtr = segPtr, segPtr = segPtr->nextPtr) {
if (segPtr->size > count) {
@@ -1530,7 +1530,7 @@ FindTagStart(tree, tagPtr, indexPtr)
*/
indexPtr->tree = tree;
indexPtr->linePtr = linePtr;
- indexPtr->charIndex = offset;
+ indexPtr->byteIndex = offset;
return segPtr;
}
}
@@ -1619,7 +1619,7 @@ FindTagEnd(tree, tagPtr, indexPtr)
}
indexPtr->tree = tree;
indexPtr->linePtr = lastLinePtr;
- indexPtr->charIndex = lastoffset2;
+ indexPtr->byteIndex = lastoffset2;
return last2SegPtr;
}
@@ -1694,7 +1694,7 @@ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr)
searchPtr->curIndex = *index1Ptr;
searchPtr->segPtr = NULL;
searchPtr->nextPtr = TkTextIndexToSeg(index1Ptr, &offset);
- searchPtr->curIndex.charIndex -= offset;
+ searchPtr->curIndex.byteIndex -= offset;
}
searchPtr->lastPtr = TkTextIndexToSeg(index2Ptr, (int *) NULL);
searchPtr->tagPtr = tagPtr;
@@ -1709,9 +1709,9 @@ TkBTreeStartSearch(index1Ptr, index2Ptr, tagPtr, searchPtr)
* the range, unless the range is artificially moved up to index0.
*/
if (((index1Ptr == &index0) &&
- (index1Ptr->charIndex > index2Ptr->charIndex)) ||
+ (index1Ptr->byteIndex > index2Ptr->byteIndex)) ||
((index1Ptr != &index0) &&
- (index1Ptr->charIndex >= index2Ptr->charIndex))) {
+ (index1Ptr->byteIndex >= index2Ptr->byteIndex))) {
searchPtr->linesLeft = 0;
}
}
@@ -1793,7 +1793,7 @@ TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr)
}
searchPtr->segPtr = NULL;
searchPtr->nextPtr = TkTextIndexToSeg(&searchPtr->curIndex, &offset);
- searchPtr->curIndex.charIndex -= offset;
+ searchPtr->curIndex.byteIndex -= offset;
/*
* Adjust the end of the search so it does find toggles that are right
@@ -1801,7 +1801,7 @@ TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr)
*/
if ((TkBTreeLineIndex(index2Ptr->linePtr) == 0) &&
- (index2Ptr->charIndex == 0)) {
+ (index2Ptr->byteIndex == 0)) {
backOne = *index2Ptr;
searchPtr->lastPtr = NULL; /* Signals special case for 1.0 */
} else {
@@ -1819,7 +1819,7 @@ TkBTreeStartSearchBack(index1Ptr, index2Ptr, tagPtr, searchPtr)
* first.
*/
- if (index1Ptr->charIndex <= backOne.charIndex) {
+ if (index1Ptr->byteIndex <= backOne.byteIndex) {
searchPtr->linesLeft = 0;
}
}
@@ -1889,7 +1889,7 @@ TkBTreeNextTag(searchPtr)
searchPtr->tagPtr = segPtr->body.toggle.tagPtr;
return 1;
}
- searchPtr->curIndex.charIndex += segPtr->size;
+ searchPtr->curIndex.byteIndex += segPtr->size;
}
/*
@@ -1906,7 +1906,7 @@ TkBTreeNextTag(searchPtr)
}
if (searchPtr->curIndex.linePtr != NULL) {
segPtr = searchPtr->curIndex.linePtr->segPtr;
- searchPtr->curIndex.charIndex = 0;
+ searchPtr->curIndex.byteIndex = 0;
continue;
}
if (nodePtr == searchPtr->tagPtr->tagRootPtr) {
@@ -1972,7 +1972,7 @@ TkBTreeNextTag(searchPtr)
*/
searchPtr->curIndex.linePtr = nodePtr->children.linePtr;
- searchPtr->curIndex.charIndex = 0;
+ searchPtr->curIndex.byteIndex = 0;
segPtr = searchPtr->curIndex.linePtr->segPtr;
if (searchPtr->linesLeft <= 0) {
goto searchOver;
@@ -2022,7 +2022,7 @@ TkBTreePrevTag(searchPtr)
register TkTextLine *linePtr, *prevLinePtr;
register Node *nodePtr, *node2Ptr, *prevNodePtr;
register Summary *summaryPtr;
- int charIndex;
+ int byteIndex;
int pastLast; /* Saw last marker during scan */
int linesSkipped;
@@ -2041,7 +2041,7 @@ TkBTreePrevTag(searchPtr)
/*
* Check for the last toggle before the current segment on this line.
*/
- charIndex = 0;
+ byteIndex = 0;
if (searchPtr->lastPtr == NULL) {
/*
* Search back to the very beginning, so pastLast is irrelevent.
@@ -2058,13 +2058,13 @@ TkBTreePrevTag(searchPtr)
&& (searchPtr->allTags
|| (segPtr->body.toggle.tagPtr == searchPtr->tagPtr))) {
prevPtr = segPtr;
- searchPtr->curIndex.charIndex = charIndex;
+ searchPtr->curIndex.byteIndex = byteIndex;
}
if (segPtr == searchPtr->lastPtr) {
prevPtr = NULL; /* Segments earlier than last don't count */
pastLast = 1;
}
- charIndex += segPtr->size;
+ byteIndex += segPtr->size;
}
if (prevPtr != NULL) {
if (searchPtr->linesLeft == 1 && !pastLast) {
@@ -2191,7 +2191,7 @@ TkBTreePrevTag(searchPtr)
/* empty loop body */ ;
}
searchPtr->curIndex.linePtr = prevLinePtr;
- searchPtr->curIndex.charIndex = 0;
+ searchPtr->curIndex.byteIndex = 0;
if (searchPtr->linesLeft <= 0) {
goto searchOver;
}
@@ -2241,7 +2241,7 @@ TkBTreeCharTagged(indexPtr, tagPtr)
toggleSegPtr = NULL;
for (index = 0, segPtr = indexPtr->linePtr->segPtr;
- (index + segPtr->size) <= indexPtr->charIndex;
+ (index + segPtr->size) <= indexPtr->byteIndex;
index += segPtr->size, segPtr = segPtr->nextPtr) {
if (((segPtr->typePtr == &tkTextToggleOnType)
|| (segPtr->typePtr == &tkTextToggleOffType))
@@ -2360,7 +2360,7 @@ TkBTreeGetTags(indexPtr, numTagsPtr)
*/
for (index = 0, segPtr = indexPtr->linePtr->segPtr;
- (index + segPtr->size) <= indexPtr->charIndex;
+ (index + segPtr->size) <= indexPtr->byteIndex;
index += segPtr->size, segPtr = segPtr->nextPtr) {
if ((segPtr->typePtr == &tkTextToggleOnType)
|| (segPtr->typePtr == &tkTextToggleOffType)) {
@@ -3588,6 +3588,25 @@ TkBTreeCharsInLine(linePtr)
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 8d9c022..8193440 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkTextDisp.c 1.124 97/07/11 18:01:03
+ * SCCS: @(#) tkTextDisp.c 1.127 98/01/08 13:41:28
*/
#include "tkPort.h"
@@ -98,7 +98,7 @@ typedef struct TextStyle {
typedef struct DLine {
TkTextIndex index; /* Identifies first character in text
* that is displayed on this line. */
- int count; /* Number of characters accounted for by this
+ 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
@@ -199,7 +199,7 @@ typedef struct TextDInfo {
* Information used for scrolling:
*/
- int newCharOffset; /* Desired x scroll position, measured as the
+ 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. */
@@ -222,8 +222,9 @@ typedef struct TextDInfo {
* The following information is used to implement scanning:
*/
- int scanMarkChar; /* Character that was at the left edge of
- * the window when the scan started. */
+ int scanMarkIndex; /* Byte index of character that was at the
+ * 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
* occurred since scanMarkY was set. */
@@ -254,9 +255,9 @@ typedef struct TextDInfo {
*/
typedef struct CharInfo {
- int numChars; /* Number of characters to display. */
- char chars[4]; /* Characters to display. Actual size
- * will be numChars, not 4. THIS MUST BE
+ 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. */
} CharInfo;
@@ -331,7 +332,7 @@ static void GetYView _ANSI_ARGS_((Tcl_Interp *interp,
static DLine * LayoutDLine _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr));
static int MeasureChars _ANSI_ARGS_((Tk_Font tkfont,
- CONST char *source, int maxChars, int startX,
+ CONST char *source, int maxBytes, int startX,
int maxX, int tabOrigin, int *nextXPtr));
static void MeasureUp _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *srcPtr, int distance,
@@ -381,14 +382,14 @@ TkTextCreateDInfo(textPtr)
dInfoPtr->scrollGC = Tk_GetGC(textPtr->tkwin, GCGraphicsExposures,
&gcValues);
dInfoPtr->topOfEof = 0;
- dInfoPtr->newCharOffset = 0;
+ dInfoPtr->newByteOffset = 0;
dInfoPtr->curPixelOffset = 0;
dInfoPtr->maxLength = 0;
dInfoPtr->xScrollFirst = -1;
dInfoPtr->xScrollLast = -1;
dInfoPtr->yScrollFirst = -1;
dInfoPtr->yScrollLast = -1;
- dInfoPtr->scanMarkChar = 0;
+ dInfoPtr->scanMarkIndex = 0;
dInfoPtr->scanMarkX = 0;
dInfoPtr->scanTotalScroll = 0;
dInfoPtr->scanMarkY = 0;
@@ -739,12 +740,14 @@ LayoutDLine(textPtr, indexPtr)
* point, if any. */
TkTextIndex breakIndex; /* Index of first character in
* breakChunkPtr. */
- int breakCharOffset; /* Character within breakChunkPtr just
- * to right of best break point. */
+ 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 first character in line. */
+ * style for the first character in
+ * line. */
int jIndent; /* Additional indentation (beyond
* margins) due to justification. */
int rMargin; /* Right margin width for line. */
@@ -758,17 +761,18 @@ LayoutDLine(textPtr, indexPtr)
* contains a tab. */
TkTextDispChunk *tabChunkPtr; /* Pointer to the chunk containing
* the previous tab stop. */
- int maxChars; /* Maximum number of characters to
+ int maxBytes; /* Maximum number of bytes to
* include in this chunk. */
- TkTextTabArray *tabArrayPtr; /* Tab stops for line; taken from
- * style for first character on line. */
+ 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 numChars > 0. Used to
+ * lines with numBytes > 0. Used to
* drop 0-sized chunks from the end
* of the line. */
- int offset, ascent, descent, code;
+ int byteOffset, ascent, descent, code;
StyleValues *sValuePtr;
/*
@@ -777,7 +781,7 @@ LayoutDLine(textPtr, indexPtr)
dlPtr = (DLine *) ckalloc(sizeof(DLine));
dlPtr->index = *indexPtr;
- dlPtr->count = 0;
+ dlPtr->byteCount = 0;
dlPtr->y = 0;
dlPtr->oldY = -1;
dlPtr->height = 0;
@@ -798,7 +802,7 @@ LayoutDLine(textPtr, indexPtr)
chunkPtr = NULL;
noCharsYet = 1;
breakChunkPtr = NULL;
- breakCharOffset = 0;
+ breakByteOffset = 0;
justify = TK_JUSTIFY_LEFT;
tabIndex = -1;
tabChunkPtr = NULL;
@@ -814,16 +818,16 @@ LayoutDLine(textPtr, indexPtr)
* with zero size (such as the insertion cursor's mark).
*/
- for (offset = curIndex.charIndex, segPtr = curIndex.linePtr->segPtr;
- (offset > 0) && (offset >= segPtr->size);
- offset -= segPtr->size, segPtr = segPtr->nextPtr) {
+ for (byteOffset = curIndex.byteIndex, segPtr = curIndex.linePtr->segPtr;
+ (byteOffset > 0) && (byteOffset >= segPtr->size);
+ byteOffset -= segPtr->size, segPtr = segPtr->nextPtr) {
/* Empty loop body. */
}
while (segPtr != NULL) {
if (segPtr->typePtr->layoutProc == NULL) {
segPtr = segPtr->nextPtr;
- offset = 0;
+ byteOffset = 0;
continue;
}
if (chunkPtr == NULL) {
@@ -843,11 +847,11 @@ LayoutDLine(textPtr, indexPtr)
justify = chunkPtr->stylePtr->sValuePtr->justify;
rMargin = chunkPtr->stylePtr->sValuePtr->rMargin;
wrapMode = chunkPtr->stylePtr->sValuePtr->wrapMode;
- x = ((curIndex.charIndex == 0)
+ x = ((curIndex.byteIndex == 0)
? chunkPtr->stylePtr->sValuePtr->lMargin1
: chunkPtr->stylePtr->sValuePtr->lMargin2);
if (wrapMode == tkTextNoneUid) {
- maxX = INT_MAX;
+ maxX = -1;
} else {
maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x
- rMargin;
@@ -863,14 +867,14 @@ LayoutDLine(textPtr, indexPtr)
*/
gotTab = 0;
- maxChars = segPtr->size - offset;
+ maxBytes = segPtr->size - byteOffset;
if (justify == TK_JUSTIFY_LEFT) {
if (segPtr->typePtr == &tkTextCharType) {
char *p;
- for (p = segPtr->body.chars + offset; *p != 0; p++) {
+ for (p = segPtr->body.chars + byteOffset; *p != 0; p++) {
if (*p == '\t') {
- maxChars = (p + 1 - segPtr->body.chars) - offset;
+ maxBytes = (p + 1 - segPtr->body.chars) - byteOffset;
gotTab = 1;
break;
}
@@ -880,7 +884,7 @@ LayoutDLine(textPtr, indexPtr)
chunkPtr->x = x;
code = (*segPtr->typePtr->layoutProc)(textPtr, &curIndex, segPtr,
- offset, maxX-tabSize, maxChars, noCharsYet, wrapMode,
+ byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode,
chunkPtr);
if (code <= 0) {
FreeStyle(textPtr, chunkPtr->stylePtr);
@@ -891,7 +895,7 @@ LayoutDLine(textPtr, indexPtr)
*/
segPtr = segPtr->nextPtr;
- offset = 0;
+ byteOffset = 0;
continue;
}
@@ -905,7 +909,7 @@ LayoutDLine(textPtr, indexPtr)
}
break;
}
- if (chunkPtr->numChars > 0) {
+ if (chunkPtr->numBytes > 0) {
noCharsYet = 0;
lastCharChunkPtr = chunkPtr;
}
@@ -917,11 +921,11 @@ LayoutDLine(textPtr, indexPtr)
lastChunkPtr = chunkPtr;
x += chunkPtr->width;
if (chunkPtr->breakIndex > 0) {
- breakCharOffset = chunkPtr->breakIndex;
+ breakByteOffset = chunkPtr->breakIndex;
breakIndex = curIndex;
breakChunkPtr = chunkPtr;
}
- if (chunkPtr->numChars != maxChars) {
+ if (chunkPtr->numBytes != maxBytes) {
break;
}
@@ -940,14 +944,14 @@ LayoutDLine(textPtr, indexPtr)
tabIndex++;
tabChunkPtr = chunkPtr;
tabSize = SizeOfTab(textPtr, tabArrayPtr, tabIndex, x, maxX);
- if (tabSize >= (maxX - x)) {
+ if ((maxX >= 0) && (tabSize >= maxX - x)) {
break;
}
}
- curIndex.charIndex += chunkPtr->numChars;
- offset += chunkPtr->numChars;
- if (offset >= segPtr->size) {
- offset = 0;
+ curIndex.byteIndex += chunkPtr->numBytes;
+ byteOffset += chunkPtr->numBytes;
+ if (byteOffset >= segPtr->size) {
+ byteOffset = 0;
segPtr = segPtr->nextPtr;
}
chunkPtr = NULL;
@@ -973,10 +977,10 @@ LayoutDLine(textPtr, indexPtr)
*/
breakChunkPtr = lastCharChunkPtr;
- breakCharOffset = breakChunkPtr->numChars;
+ breakByteOffset = breakChunkPtr->numBytes;
}
if ((breakChunkPtr != NULL) && ((lastChunkPtr != breakChunkPtr)
- || (breakCharOffset != lastChunkPtr->numChars))) {
+ || (breakByteOffset != lastChunkPtr->numBytes))) {
while (1) {
chunkPtr = breakChunkPtr->nextPtr;
if (chunkPtr == NULL) {
@@ -987,11 +991,11 @@ LayoutDLine(textPtr, indexPtr)
(*chunkPtr->undisplayProc)(textPtr, chunkPtr);
ckfree((char *) chunkPtr);
}
- if (breakCharOffset != breakChunkPtr->numChars) {
+ if (breakByteOffset != breakChunkPtr->numBytes) {
(*breakChunkPtr->undisplayProc)(textPtr, breakChunkPtr);
- segPtr = TkTextIndexToSeg(&breakIndex, &offset);
+ segPtr = TkTextIndexToSeg(&breakIndex, &byteOffset);
(*segPtr->typePtr->layoutProc)(textPtr, &breakIndex,
- segPtr, offset, maxX, breakCharOffset, 0,
+ segPtr, byteOffset, maxX, breakByteOffset, 0,
wrapMode, breakChunkPtr);
}
lastChunkPtr = breakChunkPtr;
@@ -1008,7 +1012,7 @@ LayoutDLine(textPtr, indexPtr)
/*
* Make one more pass over the line to recompute various things
- * like its height, length, and total number of characters. Also
+ * 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,
@@ -1034,7 +1038,7 @@ LayoutDLine(textPtr, indexPtr)
for (chunkPtr = dlPtr->chunkPtr; chunkPtr != NULL;
chunkPtr = chunkPtr->nextPtr) {
chunkPtr->x += jIndent;
- dlPtr->count += chunkPtr->numChars;
+ dlPtr->byteCount += chunkPtr->numBytes;
if (chunkPtr->minAscent > ascent) {
ascent = chunkPtr->minAscent;
}
@@ -1057,7 +1061,7 @@ LayoutDLine(textPtr, indexPtr)
dlPtr->baseline = ascent + (dlPtr->height - ascent - descent)/2;
}
sValuePtr = dlPtr->chunkPtr->stylePtr->sValuePtr;
- if (dlPtr->index.charIndex == 0) {
+ if (dlPtr->index.byteIndex == 0) {
dlPtr->spaceAbove = sValuePtr->spacing1;
} else {
dlPtr->spaceAbove = sValuePtr->spacing2 - sValuePtr->spacing2/2;
@@ -1210,7 +1214,7 @@ UpdateDisplayInfo(textPtr)
* index within the line.
*/
- if (index.charIndex == dlPtr->index.charIndex) {
+ if (index.byteIndex == dlPtr->index.byteIndex) {
/*
* Case (a) -- can use existing display line as-is.
*/
@@ -1221,7 +1225,7 @@ UpdateDisplayInfo(textPtr)
}
goto lineOK;
}
- if (index.charIndex < dlPtr->index.charIndex) {
+ if (index.byteIndex < dlPtr->index.byteIndex) {
goto makeNewDLine;
}
@@ -1248,7 +1252,7 @@ UpdateDisplayInfo(textPtr)
lineOK:
dlPtr->y = y;
y += dlPtr->height;
- TkTextIndexForwChars(&index, dlPtr->count, &index);
+ TkTextIndexForwBytes(&index, dlPtr->byteCount, &index);
prevPtr = dlPtr;
dlPtr = dlPtr->nextPtr;
@@ -1299,7 +1303,7 @@ UpdateDisplayInfo(textPtr)
*/
if (y < maxY) {
- int lineNum, spaceLeft, charsToCount;
+ int lineNum, spaceLeft, bytesToCount;
DLine *lowestPtr;
/*
@@ -1312,22 +1316,22 @@ UpdateDisplayInfo(textPtr)
spaceLeft = maxY - y;
lineNum = TkBTreeLineIndex(dInfoPtr->dLinePtr->index.linePtr);
- charsToCount = dInfoPtr->dLinePtr->index.charIndex;
- if (charsToCount == 0) {
- charsToCount = INT_MAX;
+ 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.charIndex = 0;
+ index.byteIndex = 0;
lowestPtr = NULL;
do {
dlPtr = LayoutDLine(textPtr, &index);
dlPtr->nextPtr = lowestPtr;
lowestPtr = dlPtr;
- TkTextIndexForwChars(&index, dlPtr->count, &index);
- charsToCount -= dlPtr->count;
- } while ((charsToCount > 0)
+ TkTextIndexForwBytes(&index, dlPtr->byteCount, &index);
+ bytesToCount -= dlPtr->byteCount;
+ } while ((bytesToCount > 0)
&& (index.linePtr == lowestPtr->index.linePtr));
/*
@@ -1354,7 +1358,7 @@ UpdateDisplayInfo(textPtr)
}
}
FreeDLines(textPtr, lowestPtr, (DLine *) NULL, 0);
- charsToCount = INT_MAX;
+ bytesToCount = INT_MAX;
}
/*
@@ -1441,13 +1445,13 @@ UpdateDisplayInfo(textPtr)
}
maxOffset = (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x)
+ textPtr->charWidth - 1)/textPtr->charWidth;
- if (dInfoPtr->newCharOffset > maxOffset) {
- dInfoPtr->newCharOffset = maxOffset;
+ if (dInfoPtr->newByteOffset > maxOffset) {
+ dInfoPtr->newByteOffset = maxOffset;
}
- if (dInfoPtr->newCharOffset < 0) {
- dInfoPtr->newCharOffset = 0;
+ if (dInfoPtr->newByteOffset < 0) {
+ dInfoPtr->newByteOffset = 0;
}
- pixelOffset = dInfoPtr->newCharOffset * textPtr->charWidth;
+ pixelOffset = dInfoPtr->newByteOffset * textPtr->charWidth;
if (pixelOffset != dInfoPtr->curPixelOffset) {
dInfoPtr->curPixelOffset = pixelOffset;
for (dlPtr = dInfoPtr->dLinePtr; dlPtr != NULL;
@@ -2591,7 +2595,7 @@ TkTextChanged(textPtr, index1Ptr, index2Ptr)
*/
rounded = *index1Ptr;
- rounded.charIndex = 0;
+ rounded.byteIndex = 0;
firstPtr = FindDLine(dInfoPtr->dLinePtr, &rounded);
if (firstPtr == NULL) {
return;
@@ -2667,7 +2671,7 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag)
*/
if (index2Ptr == NULL) {
- index2Ptr = TkTextMakeIndex(textPtr->tree,
+ index2Ptr = TkTextMakeByteIndex(textPtr->tree,
TkBTreeNumLines(textPtr->tree), 0, &endOfText);
}
@@ -2721,13 +2725,13 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag)
* previous character.
*/
- if (curIndexPtr->charIndex == 0) {
+ if (curIndexPtr->byteIndex == 0) {
dlPtr = FindDLine(dlPtr, curIndexPtr);
} else {
TkTextIndex tmp;
tmp = *curIndexPtr;
- tmp.charIndex -= 1;
+ tmp.byteIndex -= 1;
dlPtr = FindDLine(dlPtr, &tmp);
}
if (dlPtr == NULL) {
@@ -2746,7 +2750,7 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag)
}
endPtr = FindDLine(dlPtr, endIndexPtr);
if ((endPtr != NULL) && (endPtr->index.linePtr == endIndexPtr->linePtr)
- && (endPtr->index.charIndex < endIndexPtr->charIndex)) {
+ && (endPtr->index.byteIndex < endIndexPtr->byteIndex)) {
endPtr = endPtr->nextPtr;
}
@@ -2858,7 +2862,7 @@ TkTextRelayoutWindow(textPtr)
* or options could change the way lines wrap.
*/
- if (textPtr->topIndex.charIndex != 0) {
+ if (textPtr->topIndex.byteIndex != 0) {
MeasureUp(textPtr, &textPtr->topIndex, 0, &textPtr->topIndex);
}
@@ -2925,7 +2929,7 @@ TkTextSetYView(textPtr, indexPtr, pickPlace)
* without redisplaying it all.
*/
- if (indexPtr->charIndex == 0) {
+ if (indexPtr->byteIndex == 0) {
textPtr->topIndex = *indexPtr;
} else {
MeasureUp(textPtr, indexPtr, 0, &textPtr->topIndex);
@@ -2953,7 +2957,7 @@ TkTextSetYView(textPtr, indexPtr, pickPlace)
dlPtr = NULL;
} else if ((dlPtr->index.linePtr == indexPtr->linePtr)
- && (dlPtr->index.charIndex <= indexPtr->charIndex)) {
+ && (dlPtr->index.byteIndex <= indexPtr->byteIndex)) {
return;
}
}
@@ -3051,37 +3055,37 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr)
TkTextIndex *dstPtr; /* Index to fill in with result. */
{
int lineNum; /* Number of current line. */
- int charsToCount; /* Maximum number of characters to measure
- * in current line. */
+ int bytesToCount; /* Maximum number of bytes to measure in
+ * current line. */
TkTextIndex bestIndex; /* Best candidate seen so far for result. */
TkTextIndex index;
DLine *dlPtr, *lowestPtr;
int noBestYet; /* 1 means bestIndex hasn't been set. */
noBestYet = 1;
- charsToCount = srcPtr->charIndex + 1;
+ bytesToCount = srcPtr->byteIndex + 1;
index.tree = srcPtr->tree;
for (lineNum = TkBTreeLineIndex(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 (charsToCount is non-infinite to
+ * 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.charIndex = 0;
+ index.byteIndex = 0;
lowestPtr = NULL;
do {
dlPtr = LayoutDLine(textPtr, &index);
dlPtr->nextPtr = lowestPtr;
lowestPtr = dlPtr;
- TkTextIndexForwChars(&index, dlPtr->count, &index);
- charsToCount -= dlPtr->count;
- } while ((charsToCount > 0) && (index.linePtr == dlPtr->index.linePtr));
+ TkTextIndexForwBytes(&index, dlPtr->byteCount, &index);
+ bytesToCount -= dlPtr->byteCount;
+ } while ((bytesToCount > 0) && (index.linePtr == dlPtr->index.linePtr));
/*
* Scan through the display lines to see if we've covered enough
@@ -3108,7 +3112,7 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr)
if (distance < 0) {
return;
}
- charsToCount = INT_MAX; /* Consider all chars. in next line. */
+ bytesToCount = INT_MAX; /* Consider all chars. in next line. */
}
/*
@@ -3116,7 +3120,7 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr)
* in the text.
*/
- TkTextMakeIndex(textPtr->tree, 0, 0, dstPtr);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, dstPtr);
}
/*
@@ -3148,7 +3152,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
{
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
TkTextIndex index;
- int x, y, width, height, lineWidth, charCount, oneThird, delta;
+ int x, y, width, height, lineWidth, byteCount, oneThird, delta;
DLine *dlPtr;
TkTextDispChunk *chunkPtr;
@@ -3193,12 +3197,12 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
*/
dlPtr = FindDLine(dInfoPtr->dLinePtr, &index);
- charCount = index.charIndex - dlPtr->index.charIndex;
+ byteCount = index.byteIndex - dlPtr->index.byteIndex;
for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) {
- if (charCount < chunkPtr->numChars) {
+ if (byteCount < chunkPtr->numBytes) {
break;
}
- charCount -= chunkPtr->numChars;
+ byteCount -= chunkPtr->numBytes;
}
/*
@@ -3206,7 +3210,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
* the character within the chunk.
*/
- (*chunkPtr->bboxProc)(chunkPtr, charCount, dlPtr->y + dlPtr->spaceAbove,
+ (*chunkPtr->bboxProc)(chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove,
dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width,
&height);
@@ -3214,18 +3218,18 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
oneThird = lineWidth/3;
if (delta < 0) {
if (delta < -oneThird) {
- dInfoPtr->newCharOffset = (x - lineWidth/2)/textPtr->charWidth;
+ dInfoPtr->newByteOffset = (x - lineWidth/2)/textPtr->charWidth;
} else {
- dInfoPtr->newCharOffset -= ((-delta) + textPtr->charWidth - 1)
+ dInfoPtr->newByteOffset -= ((-delta) + textPtr->charWidth - 1)
/ textPtr->charWidth;
}
} else {
delta -= (lineWidth - width);
if (delta > 0) {
if (delta > oneThird) {
- dInfoPtr->newCharOffset = (x - lineWidth/2)/textPtr->charWidth;
+ dInfoPtr->newByteOffset = (x - lineWidth/2)/textPtr->charWidth;
} else {
- dInfoPtr->newCharOffset += (delta + textPtr->charWidth - 1)
+ dInfoPtr->newByteOffset += (delta + textPtr->charWidth - 1)
/ textPtr->charWidth;
}
} else {
@@ -3280,7 +3284,7 @@ TkTextXviewCmd(textPtr, interp, argc, argv)
return TCL_OK;
}
- newOffset = dInfoPtr->newCharOffset;
+ newOffset = dInfoPtr->newByteOffset;
type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
switch (type) {
case TK_SCROLL_ERROR:
@@ -3301,14 +3305,14 @@ TkTextXviewCmd(textPtr, interp, argc, argv)
if (charsPerPage < 1) {
charsPerPage = 1;
}
- newOffset += charsPerPage*count;
+ newOffset += charsPerPage * count;
break;
case TK_SCROLL_UNITS:
newOffset += count;
break;
}
- dInfoPtr->newCharOffset = newOffset;
+ dInfoPtr->newByteOffset = newOffset;
dInfoPtr->flags |= DINFO_OUT_OF_DATE;
if (!(dInfoPtr->flags & REDRAW_PENDING)) {
dInfoPtr->flags |= REDRAW_PENDING;
@@ -3344,7 +3348,7 @@ ScrollByLines(textPtr, offset)
* means that information earlier in the
* text becomes visible. */
{
- int i, charsToCount, lineNum;
+ int i, bytesToCount, lineNum;
TkTextIndex new, index;
TkTextLine *lastLinePtr;
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
@@ -3357,21 +3361,21 @@ ScrollByLines(textPtr, offset)
* it counts lines instead of pixels.
*/
- charsToCount = textPtr->topIndex.charIndex + 1;
+ bytesToCount = textPtr->topIndex.byteIndex + 1;
index.tree = textPtr->tree;
offset--; /* Skip line containing topIndex. */
for (lineNum = TkBTreeLineIndex(textPtr->topIndex.linePtr);
lineNum >= 0; lineNum--) {
index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
- index.charIndex = 0;
+ index.byteIndex = 0;
lowestPtr = NULL;
do {
dlPtr = LayoutDLine(textPtr, &index);
dlPtr->nextPtr = lowestPtr;
lowestPtr = dlPtr;
- TkTextIndexForwChars(&index, dlPtr->count, &index);
- charsToCount -= dlPtr->count;
- } while ((charsToCount > 0)
+ TkTextIndexForwBytes(&index, dlPtr->byteCount, &index);
+ bytesToCount -= dlPtr->byteCount;
+ } while ((bytesToCount > 0)
&& (index.linePtr == dlPtr->index.linePtr));
for (dlPtr = lowestPtr; dlPtr != NULL; dlPtr = dlPtr->nextPtr) {
@@ -3391,7 +3395,7 @@ ScrollByLines(textPtr, offset)
if (offset >= 0) {
goto scheduleUpdate;
}
- charsToCount = INT_MAX;
+ bytesToCount = INT_MAX;
}
/*
@@ -3399,7 +3403,7 @@ ScrollByLines(textPtr, offset)
* in the text.
*/
- TkTextMakeIndex(textPtr->tree, 0, 0, &textPtr->topIndex);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &textPtr->topIndex);
} else {
/*
* Scrolling down, to show later information in the text.
@@ -3411,7 +3415,7 @@ ScrollByLines(textPtr, offset)
for (i = 0; i < offset; i++) {
dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);
dlPtr->nextPtr = NULL;
- TkTextIndexForwChars(&textPtr->topIndex, dlPtr->count, &new);
+ TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount, &new);
FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0);
if (new.linePtr == lastLinePtr) {
break;
@@ -3455,7 +3459,7 @@ TkTextYviewCmd(textPtr, interp, argc, argv)
* argv[1] is "yview". */
{
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
- int pickPlace, lineNum, type, charsInLine;
+ int pickPlace, lineNum, type, bytesInLine;
Tk_FontMetrics fm;
int pixels, count;
size_t switchLength;
@@ -3493,7 +3497,7 @@ TkTextYviewCmd(textPtr, interp, argc, argv)
}
if ((argc == 3) || pickPlace) {
if (Tcl_GetInt(interp, argv[2+pickPlace], &lineNum) == TCL_OK) {
- TkTextMakeIndex(textPtr->tree, lineNum, 0, &index);
+ TkTextMakeByteIndex(textPtr->tree, lineNum, 0, &index);
TkTextSetYView(textPtr, &index, 0);
return TCL_OK;
}
@@ -3528,11 +3532,11 @@ TkTextYviewCmd(textPtr, interp, argc, argv)
}
fraction *= TkBTreeNumLines(textPtr->tree);
lineNum = (int) fraction;
- TkTextMakeIndex(textPtr->tree, lineNum, 0, &index);
- charsInLine = TkBTreeCharsInLine(index.linePtr);
- index.charIndex = (int)((charsInLine * (fraction-lineNum)) + 0.5);
- if (index.charIndex >= charsInLine) {
- TkTextMakeIndex(textPtr->tree, lineNum+1, 0, &index);
+ 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;
@@ -3570,7 +3574,7 @@ TkTextYviewCmd(textPtr, interp, argc, argv)
do {
dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);
dlPtr->nextPtr = NULL;
- TkTextIndexForwChars(&textPtr->topIndex, dlPtr->count,
+ TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount,
&new);
pixels -= dlPtr->height;
FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0);
@@ -3622,7 +3626,7 @@ TkTextScanCmd(textPtr, interp, argc, argv)
{
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
TkTextIndex index;
- int c, x, y, totalScroll, newChar, maxChar;
+ int c, x, y, totalScroll, newByte, maxByte;
Tk_FontMetrics fm;
size_t length;
@@ -3652,18 +3656,20 @@ TkTextScanCmd(textPtr, interp, argc, argv)
* moving again).
*/
- newChar = dInfoPtr->scanMarkChar + (10*(dInfoPtr->scanMarkX - x))
+ newByte = dInfoPtr->scanMarkIndex + (10*(dInfoPtr->scanMarkX - x))
/ (textPtr->charWidth);
- maxChar = 1 + (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x)
+ maxByte = 1 + (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x)
+ textPtr->charWidth - 1)/textPtr->charWidth;
- if (newChar < 0) {
- dInfoPtr->scanMarkChar = newChar = 0;
+ if (newByte < 0) {
+ newByte = 0;
+ dInfoPtr->scanMarkIndex = 0;
dInfoPtr->scanMarkX = x;
- } else if (newChar > maxChar) {
- dInfoPtr->scanMarkChar = newChar = maxChar;
+ } else if (newByte > maxByte) {
+ newByte = maxByte;
+ dInfoPtr->scanMarkIndex = maxByte;
dInfoPtr->scanMarkX = x;
}
- dInfoPtr->newCharOffset = newChar;
+ dInfoPtr->newByteOffset = newByte;
Tk_GetFontMetrics(textPtr->tkfont, &fm);
totalScroll = (10*(dInfoPtr->scanMarkY - y)) / fm.linespace;
@@ -3672,13 +3678,13 @@ TkTextScanCmd(textPtr, interp, argc, argv)
ScrollByLines(textPtr, totalScroll-dInfoPtr->scanTotalScroll);
dInfoPtr->scanTotalScroll = totalScroll;
if ((index.linePtr == textPtr->topIndex.linePtr) &&
- (index.charIndex == textPtr->topIndex.charIndex)) {
+ (index.byteIndex == textPtr->topIndex.byteIndex)) {
dInfoPtr->scanTotalScroll = 0;
dInfoPtr->scanMarkY = y;
}
}
} else if ((c == 'm') && (strncmp(argv[2], "mark", length) == 0)) {
- dInfoPtr->scanMarkChar = dInfoPtr->newCharOffset;
+ dInfoPtr->scanMarkIndex = dInfoPtr->newByteOffset;
dInfoPtr->scanMarkX = x;
dInfoPtr->scanTotalScroll = 0;
dInfoPtr->scanMarkY = y;
@@ -3705,11 +3711,11 @@ TkTextScanCmd(textPtr, interp, argc, argv)
* Tcl script to report them to the text's associated scrollbar.
*
* Results:
- * If report is zero, then interp->result is filled in with
+ * 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 interp->result isn't modified
+ * 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).
@@ -3724,13 +3730,13 @@ static void
GetXView(interp, textPtr, report)
Tcl_Interp *interp; /* If "report" is FALSE, string
* describing visible range gets
- * stored in interp->result. */
+ * 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[200];
+ char buffer[TCL_DOUBLE_SPACE * 2];
double first, last;
int code;
@@ -3747,7 +3753,8 @@ GetXView(interp, textPtr, report)
last = 1.0;
}
if (!report) {
- sprintf(interp->result, "%g %g", first, last);
+ sprintf(buffer, "%g %g", first, last);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
return;
}
if ((first == dInfoPtr->xScrollFirst) && (last == dInfoPtr->xScrollLast)) {
@@ -3775,11 +3782,11 @@ GetXView(interp, textPtr, report)
* Tcl script to report them to the text's associated scrollbar.
*
* Results:
- * If report is zero, then interp->result is filled in with
+ * 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 interp->result isn't modified directly,
+ * 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).
@@ -3794,22 +3801,22 @@ static void
GetYView(interp, textPtr, report)
Tcl_Interp *interp; /* If "report" is FALSE, string
* describing visible range gets
- * stored in interp->result. */
+ * 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[200];
+ char buffer[TCL_DOUBLE_SPACE * 2];
double first, last;
DLine *dlPtr;
int totalLines, code, count;
dlPtr = dInfoPtr->dLinePtr;
totalLines = TkBTreeNumLines(textPtr->tree);
- first = ((double) TkBTreeLineIndex(dlPtr->index.linePtr))
- + ((double) dlPtr->index.charIndex)
- / (TkBTreeCharsInLine(dlPtr->index.linePtr));
+ 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) {
@@ -3821,17 +3828,18 @@ GetYView(interp, textPtr, report)
break;
}
if (dlPtr->nextPtr == NULL) {
- count = dlPtr->count;
+ count = dlPtr->byteCount;
break;
}
dlPtr = dlPtr->nextPtr;
}
last = ((double) TkBTreeLineIndex(dlPtr->index.linePtr))
- + ((double) (dlPtr->index.charIndex + count))
- / (TkBTreeCharsInLine(dlPtr->index.linePtr));
+ + ((double) (dlPtr->index.byteIndex + count))
+ / (TkBTreeBytesInLine(dlPtr->index.linePtr));
last /= totalLines;
if (!report) {
- sprintf(interp->result, "%g %g", first, last);
+ sprintf(buffer, "%g %g", first, last);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
return;
}
if ((first == dInfoPtr->yScrollFirst) && (last == dInfoPtr->yScrollLast)) {
@@ -3840,8 +3848,7 @@ GetYView(interp, textPtr, report)
dInfoPtr->yScrollFirst = first;
dInfoPtr->yScrollLast = last;
sprintf(buffer, " %g %g", first, last);
- code = Tcl_VarEval(interp, textPtr->yScrollCmd,
- buffer, (char *) NULL);
+ code = Tcl_VarEval(interp, textPtr->yScrollCmd, buffer, (char *) NULL);
if (code != TCL_OK) {
Tcl_AddErrorInfo(interp,
"\n (vertical scrolling command executed by text)");
@@ -3913,7 +3920,7 @@ FindDLine(dlPtr, indexPtr)
* Now get to the right position within the text line.
*/
- while (indexPtr->charIndex >= (dlPtr->index.charIndex + dlPtr->count)) {
+ while (indexPtr->byteIndex >= (dlPtr->index.byteIndex + dlPtr->byteCount)) {
dlPtr = dlPtr->nextPtr;
if ((dlPtr == NULL) || (dlPtr->index.linePtr != indexPtr->linePtr)) {
break;
@@ -4005,21 +4012,22 @@ TkTextPixelIndex(textPtr, x, y, indexPtr)
*indexPtr = dlPtr->index;
x = x - dInfoPtr->x + dInfoPtr->curPixelOffset;
for (chunkPtr = dlPtr->chunkPtr; x >= (chunkPtr->x + chunkPtr->width);
- indexPtr->charIndex += chunkPtr->numChars,
+ indexPtr->byteIndex += chunkPtr->numBytes,
chunkPtr = chunkPtr->nextPtr) {
if (chunkPtr->nextPtr == NULL) {
- indexPtr->charIndex += chunkPtr->numChars - 1;
+ indexPtr->byteIndex += chunkPtr->numBytes;
+ TkTextIndexBackChars(indexPtr, 1, indexPtr);
return;
}
}
/*
- * If the chunk has more than one character in it, ask it which
+ * If the chunk has more than one byte in it, ask it which
* character is at the desired location.
*/
- if (chunkPtr->numChars > 1) {
- indexPtr->charIndex += (*chunkPtr->measureProc)(chunkPtr, x);
+ if (chunkPtr->numBytes > 1) {
+ indexPtr->byteIndex += (*chunkPtr->measureProc)(chunkPtr, x);
}
}
@@ -4056,7 +4064,7 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr)
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
DLine *dlPtr;
register TkTextDispChunk *chunkPtr;
- int index;
+ int byteIndex;
/*
* Make sure that all of the screen layout information is up to date.
@@ -4080,15 +4088,15 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr)
* index.
*/
- index = indexPtr->charIndex - dlPtr->index.charIndex;
+ byteIndex = indexPtr->byteIndex - dlPtr->index.byteIndex;
for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) {
if (chunkPtr == NULL) {
return -1;
}
- if (index < chunkPtr->numChars) {
+ if (byteIndex < chunkPtr->numBytes) {
break;
}
- index -= chunkPtr->numChars;
+ byteIndex -= chunkPtr->numBytes;
}
/*
@@ -4099,12 +4107,12 @@ TkTextCharBbox(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr)
* horizontal scrolling.
*/
- (*chunkPtr->bboxProc)(chunkPtr, index, dlPtr->y + dlPtr->spaceAbove,
+ (*chunkPtr->bboxProc)(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 ((index == (chunkPtr->numChars-1)) && (chunkPtr->nextPtr == NULL)) {
+ if ((byteIndex == (chunkPtr->numBytes - 1)) && (chunkPtr->nextPtr == NULL)) {
/*
* Last character in display line. Give it all the space up to
* the line.
@@ -4203,7 +4211,7 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr)
*
* This procedure is the "layoutProc" for character segments.
*
- * Results:
+n * 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
@@ -4220,17 +4228,17 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr)
*/
int
-TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
+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
* (corresponds to segPtr and offset). */
TkTextSegment *segPtr; /* Segment being layed out. */
- int offset; /* Offset within segment of first character
- * to consider. */
+ int byteOffset; /* Byte offset within segment of first
+ * character to consider. */
int maxX; /* Chunk must not occupy pixels at this
* position or higher. */
- int maxChars; /* Chunk must not include more than this
+ 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. */
@@ -4242,7 +4250,7 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
* been set by the caller. */
{
Tk_Font tkfont;
- int nextX, charsThatFit, count;
+ int nextX, bytesThatFit, count;
CharInfo *ciPtr;
char *p;
TkTextSegment *nextPtr;
@@ -4260,17 +4268,19 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
* is a white space character.
*/
- p = segPtr->body.chars + offset;
+ p = segPtr->body.chars + byteOffset;
tkfont = chunkPtr->stylePtr->sValuePtr->tkfont;
- charsThatFit = MeasureChars(tkfont, p, maxChars, chunkPtr->x, maxX, 0,
+ bytesThatFit = MeasureChars(tkfont, p, maxBytes, chunkPtr->x, maxX, 0,
&nextX);
- if (charsThatFit < maxChars) {
- if ((charsThatFit == 0) && noCharsYet) {
- charsThatFit = 1;
- MeasureChars(tkfont, p, 1, chunkPtr->x, INT_MAX, 0, &nextX);
+ if (bytesThatFit < maxBytes) {
+ if ((bytesThatFit == 0) && noCharsYet) {
+ Tcl_UniChar ch;
+
+ bytesThatFit = MeasureChars(tkfont, p, Tcl_UtfToUniChar(p, &ch),
+ chunkPtr->x, -1, 0, &nextX);
}
- if ((nextX < maxX) && ((p[charsThatFit] == ' ')
- || (p[charsThatFit] == '\t'))) {
+ 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
@@ -4278,17 +4288,17 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
*/
nextX = maxX;
- charsThatFit++;
+ bytesThatFit++;
}
- if (p[charsThatFit] == '\n') {
+ if (p[bytesThatFit] == '\n') {
/*
* A newline character takes up no space, so if the previous
* character fits then so does the newline.
*/
- charsThatFit++;
+ bytesThatFit++;
}
- if (charsThatFit == 0) {
+ if (bytesThatFit == 0) {
return 0;
}
}
@@ -4305,19 +4315,19 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
chunkPtr->undisplayProc = CharUndisplayProc;
chunkPtr->measureProc = CharMeasureProc;
chunkPtr->bboxProc = CharBboxProc;
- chunkPtr->numChars = charsThatFit;
+ chunkPtr->numBytes = bytesThatFit;
chunkPtr->minAscent = fm.ascent + chunkPtr->stylePtr->sValuePtr->offset;
chunkPtr->minDescent = fm.descent - chunkPtr->stylePtr->sValuePtr->offset;
chunkPtr->minHeight = 0;
chunkPtr->width = nextX - chunkPtr->x;
chunkPtr->breakIndex = -1;
ciPtr = (CharInfo *) ckalloc((unsigned)
- (sizeof(CharInfo) - 3 + charsThatFit));
+ (sizeof(CharInfo) - 3 + bytesThatFit));
chunkPtr->clientData = (ClientData) ciPtr;
- ciPtr->numChars = charsThatFit;
- strncpy(ciPtr->chars, p, (size_t) charsThatFit);
- if (p[charsThatFit-1] == '\n') {
- ciPtr->numChars--;
+ ciPtr->numBytes = bytesThatFit;
+ strncpy(ciPtr->chars, p, (size_t) bytesThatFit);
+ if (p[bytesThatFit - 1] == '\n') {
+ ciPtr->numBytes--;
}
/*
@@ -4328,21 +4338,21 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
*/
if (wrapMode != tkTextWordUid) {
- chunkPtr->breakIndex = chunkPtr->numChars;
+ chunkPtr->breakIndex = chunkPtr->numBytes;
} else {
- for (count = charsThatFit, p += charsThatFit-1; count > 0;
+ for (count = bytesThatFit, p += bytesThatFit - 1; count > 0;
count--, p--) {
if (isspace(UCHAR(*p))) {
chunkPtr->breakIndex = count;
break;
}
}
- if ((charsThatFit+offset) == segPtr->size) {
+ if ((bytesThatFit + byteOffset) == segPtr->size) {
for (nextPtr = segPtr->nextPtr; nextPtr != NULL;
nextPtr = nextPtr->nextPtr) {
if (nextPtr->size != 0) {
if (nextPtr->typePtr != &tkTextCharType) {
- chunkPtr->breakIndex = chunkPtr->numChars;
+ chunkPtr->breakIndex = chunkPtr->numBytes;
}
break;
}
@@ -4389,7 +4399,7 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY)
CharInfo *ciPtr = (CharInfo *) chunkPtr->clientData;
TextStyle *stylePtr;
StyleValues *sValuePtr;
- int offsetChars, offsetX;
+ int offsetBytes, offsetX;
if ((x + chunkPtr->width) <= 0) {
/*
@@ -4411,30 +4421,29 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY)
*/
offsetX = x;
- offsetChars = 0;
+ offsetBytes = 0;
if (x < 0) {
- offsetChars = MeasureChars(sValuePtr->tkfont, ciPtr->chars,
- ciPtr->numChars, x, 0, x - chunkPtr->x, &offsetX);
+ offsetBytes = MeasureChars(sValuePtr->tkfont, ciPtr->chars,
+ ciPtr->numBytes, x, 0, x - chunkPtr->x, &offsetX);
}
/*
* Draw the text, underline, and overstrike for this chunk.
*/
- if (ciPtr->numChars > offsetChars) {
- int numChars = ciPtr->numChars - offsetChars;
- char *string = ciPtr->chars + offsetChars;
+ if (ciPtr->numBytes > offsetBytes) {
+ int numBytes = ciPtr->numBytes - offsetBytes;
+ char *string = ciPtr->chars + offsetBytes;
- if ((numChars > 0) && (string[numChars - 1] == '\t')) {
- numChars--;
+ if ((numBytes > 0) && (string[numBytes - 1] == '\t')) {
+ numBytes--;
}
Tk_DrawChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont, string,
- numChars, offsetX, y + baseline - sValuePtr->offset);
+ numBytes, offsetX, y + baseline - sValuePtr->offset);
if (sValuePtr->underline) {
Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont,
- ciPtr->chars + offsetChars, offsetX,
- y + baseline - sValuePtr->offset,
- 0, numChars);
+ ciPtr->chars + offsetBytes, offsetX,
+ y + baseline - sValuePtr->offset, 0, numBytes);
}
if (sValuePtr->overstrike) {
@@ -4442,10 +4451,10 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY)
Tk_GetFontMetrics(sValuePtr->tkfont, &fm);
Tk_UnderlineChars(display, dst, stylePtr->fgGC, sValuePtr->tkfont,
- ciPtr->chars + offsetChars, offsetX,
+ ciPtr->chars + offsetBytes, offsetX,
y + baseline - sValuePtr->offset
- fm.descent - (fm.ascent * 3) / 10,
- 0, numChars);
+ 0, numBytes);
}
}
}
@@ -4507,7 +4516,8 @@ CharMeasureProc(chunkPtr, x)
int endX;
return MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars,
- chunkPtr->numChars-1, chunkPtr->x, x, 0, &endX);
+ chunkPtr->numBytes - 1, chunkPtr->x, x, 0, &endX);
+ /* CHAR OFFSET */
}
/*
@@ -4534,11 +4544,11 @@ CharMeasureProc(chunkPtr, x)
*/
static void
-CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
+CharBboxProc(chunkPtr, byteIndex, y, lineHeight, baseline, xPtr, yPtr,
widthPtr, heightPtr)
TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */
- int index; /* Index of desired character within
- * the chunk. */
+ 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. */
@@ -4557,10 +4567,10 @@ CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
int maxX;
maxX = chunkPtr->width + chunkPtr->x;
- MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars, index,
- chunkPtr->x, 1000000, 0, xPtr);
+ MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont, ciPtr->chars,
+ byteIndex, chunkPtr->x, -1, 0, xPtr);
- if (index == ciPtr->numChars) {
+ 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
@@ -4568,8 +4578,8 @@ CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
*/
*widthPtr = maxX - *xPtr;
- } else if ((ciPtr->chars[index] == '\t')
- && (index == (ciPtr->numChars-1))) {
+ } 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.
@@ -4578,7 +4588,7 @@ CharBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
*widthPtr = maxX - *xPtr;
} else {
MeasureChars(chunkPtr->stylePtr->sValuePtr->tkfont,
- ciPtr->chars + index, 1, *xPtr, 1000000, 0, widthPtr);
+ ciPtr->chars + byteIndex, 1, *xPtr, -1, 0, widthPtr);
if (*widthPtr > maxX) {
*widthPtr = maxX - *xPtr;
} else {
@@ -4713,7 +4723,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr)
continue;
}
ciPtr = (CharInfo *) chunkPtr2->clientData;
- for (p = ciPtr->chars, i = 0; i < ciPtr->numChars; p++, i++) {
+ for (p = ciPtr->chars, i = 0; i < ciPtr->numBytes; p++, i++) {
if (isdigit(UCHAR(*p))) {
gotDigit = 1;
} else if ((*p == '.') || (*p == ',')) {
@@ -4734,7 +4744,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr)
ciPtr = (CharInfo *) decimalChunkPtr->clientData;
MeasureChars(decimalChunkPtr->stylePtr->sValuePtr->tkfont,
- ciPtr->chars, decimal, decimalChunkPtr->x, 1000000, 0, &curX);
+ ciPtr->chars, decimal, decimalChunkPtr->x, -1, 0, &curX);
desired = tabX - (curX - x);
goto update;
} else {
@@ -4759,7 +4769,7 @@ AdjustForTab(textPtr, tabArrayPtr, index, chunkPtr)
update:
delta = desired - x;
- MeasureChars(textPtr->tkfont, " ", 1, 0, INT_MAX, 0, &spaceWidth);
+ MeasureChars(textPtr->tkfont, " ", 1, 0, -1, 0, &spaceWidth);
if (delta < spaceWidth) {
delta = spaceWidth;
}
@@ -4864,7 +4874,7 @@ SizeOfTab(textPtr, tabArrayPtr, index, x, maxX)
}
done:
- MeasureChars(textPtr->tkfont, " ", 1, 0, INT_MAX, 0, &spaceWidth);
+ MeasureChars(textPtr->tkfont, " ", 1, 0, -1, 0, &spaceWidth);
if (result < spaceWidth) {
result = spaceWidth;
}
@@ -4934,7 +4944,7 @@ NextTabStop(tkfont, x, tabOrigin)
* is specified.
*
* Results:
- * The return value is the number of characters from source
+ * 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
@@ -4947,11 +4957,11 @@ NextTabStop(tkfont, x, tabOrigin)
*/
static int
-MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr)
+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 maxChars; /* Maximum # of characters to consider from
+ int maxBytes; /* Maximum # of bytes to consider from
* source. */
int startX; /* X-position at which first character will
* be drawn. */
@@ -4968,7 +4978,7 @@ MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr)
ch = 0; /* lint. */
curX = startX;
special = source;
- end = source + maxChars;
+ end = source + maxBytes;
for (start = source; start < end; ) {
if (start >= special) {
/*
@@ -4988,7 +4998,7 @@ MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr)
* string). Process characters between start and special.
*/
- if (curX >= maxX) {
+ if ((maxX >= 0) && (curX >= maxX)) {
break;
}
start += Tk_MeasureChars(tkfont, start, special - start, maxX - curX,
diff --git a/generic/tkTextImage.c b/generic/tkTextImage.c
index b5e363f..dae1751 100644
--- a/generic/tkTextImage.c
+++ b/generic/tkTextImage.c
@@ -5,12 +5,12 @@
* nested inside text widgets. It also implements the "image"
* widget command for texts.
*
- * Copyright (c) 1996 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkTextImage.c 1.7 97/08/25 15:47:27
+ * SCCS: @(#) tkTextImage.c 1.10 98/01/08 13:41:36
*/
#include "tk.h"
@@ -221,7 +221,7 @@ TkTextImageCmd(textPtr, interp, argc, argv)
lineIndex = TkBTreeLineIndex(index.linePtr);
if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
lineIndex--;
- TkTextMakeIndex(textPtr->tree, lineIndex, 1000000, &index);
+ TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
}
/*
@@ -288,7 +288,7 @@ TkTextImageCmd(textPtr, interp, argc, argv)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message..
+ * returned, then the interp's result contains an error message..
*
* Side effects:
* Configuration information for the embedded image changes,
@@ -384,7 +384,7 @@ EmbImageConfigure(textPtr, eiPtr, argc, argv)
Tcl_DStringAppend(&newName,name, -1);
if (conflict) {
- char buf[10];
+ char buf[4 + TCL_INTEGER_SPACE];
sprintf(buf, "#%d",count+1);
Tcl_DStringAppend(&newName,buf, -1);
}
@@ -642,7 +642,7 @@ EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars,
chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL;
chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
chunkPtr->bboxProc = EmbImageBboxProc;
- chunkPtr->numChars = 1;
+ chunkPtr->numBytes = 1;
if (eiPtr->body.ei.align == ALIGN_BASELINE) {
chunkPtr->minAscent = height - eiPtr->body.ei.padY;
chunkPtr->minDescent = eiPtr->body.ei.padY;
@@ -857,7 +857,7 @@ TkTextImageIndex(textPtr, name, indexPtr)
eiPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
indexPtr->tree = textPtr->tree;
indexPtr->linePtr = eiPtr->body.ei.linePtr;
- indexPtr->charIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);
+ indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr);
return 1;
}
@@ -893,6 +893,6 @@ EmbImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
index.tree = eiPtr->body.ei.textPtr->tree;
index.linePtr = eiPtr->body.ei.linePtr;
- index.charIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);
+ index.byteIndex = TkTextSegToOffset(eiPtr, eiPtr->body.ei.linePtr);
TkTextChanged(eiPtr->body.ei.textPtr, &index, &index);
}
diff --git a/generic/tkTextIndex.c b/generic/tkTextIndex.c
index d88d88a..8805a29 100644
--- a/generic/tkTextIndex.c
+++ b/generic/tkTextIndex.c
@@ -5,12 +5,12 @@
* text widgets.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkTextIndex.c 1.15 97/06/17 17:49:24
+ * SCCS: @(#) tkTextIndex.c 1.18 98/01/12 15:33:45
*/
#include "default.h"
@@ -34,27 +34,118 @@ static char * StartEnd _ANSI_ARGS_(( char *string,
TkTextIndex *indexPtr));
/*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
- * TkTextMakeIndex --
+ * TkTextMakeByteIndex --
*
- * 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 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 character at lineIndex and charIndex (or the
- * closest existing character, if the specified one doesn't
- * exist), and indexPtr is returned as result.
+ * The structure at *indexPtr is filled in with information about the
+ * character at lineIndex and byteIndex (or the closest existing
+ * character, if the specified one doesn't exist), and indexPtr is
+ * returned as result.
*
* Side effects:
* None.
*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
TkTextIndex *
-TkTextMakeIndex(tree, lineIndex, charIndex, indexPtr)
+TkTextMakeByteIndex(tree, lineIndex, byteIndex, indexPtr)
+ TkTextBTree tree; /* Tree that lineIndex and charIndex 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. */
+{
+ TkTextSegment *segPtr;
+ int index;
+ char *p, *start;
+ Tcl_UniChar ch;
+
+ indexPtr->tree = tree;
+ if (lineIndex < 0) {
+ lineIndex = 0;
+ byteIndex = 0;
+ }
+ if (byteIndex < 0) {
+ byteIndex = 0;
+ }
+ indexPtr->linePtr = TkBTreeFindLine(tree, lineIndex);
+ if (indexPtr->linePtr == NULL) {
+ indexPtr->linePtr = TkBTreeFindLine(tree, TkBTreeNumLines(tree));
+ byteIndex = 0;
+ }
+ if (byteIndex == 0) {
+ indexPtr->byteIndex = byteIndex;
+ return indexPtr;
+ }
+
+ /*
+ * 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.
+ */
+
+ indexPtr->byteIndex = index - sizeof(char);
+ break;
+ }
+ if (index + segPtr->size > byteIndex) {
+ indexPtr->byteIndex = byteIndex;
+ 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
+ * falls in the middle of a UTF-8 character, it will be
+ * adjusted to the end of that UTF-8 character.
+ */
+
+ start = segPtr->body.chars + (byteIndex - index);
+ p = Tcl_UtfPrev(start, segPtr->body.chars);
+ p += Tcl_UtfToUniChar(p, &ch);
+ indexPtr->byteIndex += p - start;
+ }
+ break;
+ }
+ index += segPtr->size;
+ }
+ return indexPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextMakeCharIndex --
+ *
+ * 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
+ * character at lineIndex and charIndex (or the closest existing
+ * character, if the specified one doesn't exist), and indexPtr is
+ * returned as result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+TkTextIndex *
+TkTextMakeCharIndex(tree, lineIndex, charIndex, indexPtr)
TkTextBTree tree; /* Tree that lineIndex and charIndex refer
* to. */
int lineIndex; /* Index of desired line (0 means first
@@ -63,7 +154,9 @@ TkTextMakeIndex(tree, lineIndex, charIndex, indexPtr)
TkTextIndex *indexPtr; /* Structure to fill in. */
{
register TkTextSegment *segPtr;
- int index;
+ char *p, *start, *end;
+ int index, offset;
+ Tcl_UniChar ch;
indexPtr->tree = tree;
if (lineIndex < 0) {
@@ -84,53 +177,76 @@ TkTextMakeIndex(tree, lineIndex, charIndex, indexPtr)
* If not, just use the index of the last character in the line.
*/
- for (index = 0, segPtr = indexPtr->linePtr->segPtr; ;
- segPtr = segPtr->nextPtr) {
+ index = 0;
+ for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) {
if (segPtr == NULL) {
- indexPtr->charIndex = index-1;
+ /*
+ * 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;
}
- index += segPtr->size;
- if (index > charIndex) {
- indexPtr->charIndex = charIndex;
- break;
+ if (segPtr->typePtr == &tkTextCharType) {
+ /*
+ * Turn character offset into a byte offset.
+ */
+
+ start = segPtr->body.chars;
+ end = start + segPtr->size;
+ for (p = start; p < end; p += offset) {
+ if (charIndex == 0) {
+ indexPtr->byteIndex = index;
+ return indexPtr;
+ }
+ charIndex--;
+ offset = Tcl_UtfToUniChar(p, &ch);
+ index += offset;
+ }
+ } else {
+ if (charIndex < segPtr->size) {
+ indexPtr->byteIndex = index;
+ break;
+ }
+ charIndex -= segPtr->size;
+ index += segPtr->size;
}
}
return indexPtr;
}
/*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* TkTextIndexToSeg --
*
- * Given an index, this procedure returns the segment and
- * offset within segment for the index.
+ * Given an index, this procedure 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.
*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
TkTextSegment *
TkTextIndexToSeg(indexPtr, offsetPtr)
- TkTextIndex *indexPtr; /* Text index. */
- int *offsetPtr; /* Where to store offset within
- * segment, or NULL if offset isn't
- * wanted. */
+ CONST TkTextIndex *indexPtr;/* Text index. */
+ int *offsetPtr; /* Where to store offset within segment, or
+ * NULL if offset isn't wanted. */
{
- register TkTextSegment *segPtr;
+ TkTextSegment *segPtr;
int offset;
- for (offset = indexPtr->charIndex, segPtr = indexPtr->linePtr->segPtr;
+ for (offset = indexPtr->byteIndex, segPtr = indexPtr->linePtr->segPtr;
offset >= segPtr->size;
offset -= segPtr->size, segPtr = segPtr->nextPtr) {
/* Empty loop body. */
@@ -142,30 +258,29 @@ TkTextIndexToSeg(indexPtr, offsetPtr)
}
/*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* TkTextSegToOffset --
*
- * Given a segment pointer and the line containing it, this
- * procedure returns the offset of the segment within its
- * line.
+ * Given a segment pointer and the line containing it, this procedure
+ * returns the offset of the segment within its line.
*
* Results:
- * The return value is the offset (within its line) of the
- * first character in segPtr.
+ * The return value is the offset (within its line) of the first
+ * character in segPtr.
*
* Side effects:
* None.
*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
int
TkTextSegToOffset(segPtr, linePtr)
- TkTextSegment *segPtr; /* Segment whose offset is desired. */
- TkTextLine *linePtr; /* Line containing segPtr. */
+ CONST TkTextSegment *segPtr;/* Segment whose offset is desired. */
+ CONST TkTextLine *linePtr; /* Line containing segPtr. */
{
- TkTextSegment *segPtr2;
+ CONST TkTextSegment *segPtr2;
int offset;
offset = 0;
@@ -177,23 +292,22 @@ TkTextSegToOffset(segPtr, linePtr)
}
/*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* TkTextGetIndex --
*
- * Given a string, return the line and character indices that
- * it describes.
+ * 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 interp->result.
+ * 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.
*
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
int
@@ -203,8 +317,7 @@ TkTextGetIndex(interp, textPtr, string, indexPtr)
char *string; /* Textual description of position. */
TkTextIndex *indexPtr; /* Index structure to fill in. */
{
- register char *p;
- char *end, *endOfBase;
+ char *p, *end, *endOfBase;
Tcl_HashEntry *hPtr;
TkTextTag *tagPtr;
TkTextSearch search;
@@ -259,8 +372,8 @@ TkTextGetIndex(interp, textPtr, string, indexPtr)
goto tryxy;
}
tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr);
- TkTextMakeIndex(textPtr->tree, 0, 0, &first);
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0,
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0,
&last);
TkBTreeStartSearch(&first, &last, tagPtr, &search);
if (!TkBTreeCharTagged(&first, tagPtr) && !TkBTreeNextTag(&search)) {
@@ -324,7 +437,7 @@ TkTextGetIndex(interp, textPtr, string, indexPtr)
}
endOfBase = end;
}
- TkTextMakeIndex(textPtr->tree, lineIndex, charIndex, indexPtr);
+ TkTextMakeCharIndex(textPtr->tree, lineIndex, charIndex, indexPtr);
goto gotBase;
}
@@ -353,7 +466,7 @@ TkTextGetIndex(interp, textPtr, string, indexPtr)
* Base position is end of text.
*/
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
0, indexPtr);
goto gotBase;
} else {
@@ -420,13 +533,12 @@ TkTextGetIndex(interp, textPtr, string, indexPtr)
}
/*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* TkTextPrintIndex --
- *
*
- * This procedure generates a string description of an index,
- * suitable for reading in again later.
+ * This procedure generates a string description of an index, suitable
+ * for reading in again later.
*
* Results:
* The characters pointed to by string are modified.
@@ -434,49 +546,69 @@ TkTextGetIndex(interp, textPtr, string, indexPtr)
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
void
TkTextPrintIndex(indexPtr, string)
- TkTextIndex *indexPtr; /* Pointer to index. */
+ CONST TkTextIndex *indexPtr;/* Pointer to index. */
char *string; /* Place to store the position. Must have
* at least TK_POS_CHARS characters. */
{
+ TkTextSegment *segPtr;
+ int numBytes, charIndex;
+
+ numBytes = indexPtr->byteIndex;
+ charIndex = 0;
+ for (segPtr = indexPtr->linePtr->segPtr; ; segPtr = segPtr->nextPtr) {
+ if (numBytes < segPtr->size) {
+ break;
+ }
+ if (segPtr->typePtr == &tkTextCharType) {
+ charIndex += Tcl_NumUtfChars(segPtr->body.chars, segPtr->size);
+ } else {
+ charIndex += segPtr->size;
+ }
+ 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,
- indexPtr->charIndex);
+ charIndex);
}
/*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* TkTextIndexCmp --
*
- * Compare two indices to see which one is earlier in
- * the text.
+ * Compare two indices to see which one is earlier in the text.
*
* Results:
- * The return value is 0 if index1Ptr and index2Ptr refer
- * to the same position in the file, -1 if index1Ptr refers
- * to an earlier position than index2Ptr, and 1 otherwise.
+ * The return value is 0 if index1Ptr and index2Ptr refer to the same
+ * position in the file, -1 if index1Ptr refers to an earlier position
+ * than index2Ptr, and 1 otherwise.
*
* Side effects:
* None.
*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
int
TkTextIndexCmp(index1Ptr, index2Ptr)
- TkTextIndex *index1Ptr; /* First index. */
- TkTextIndex *index2Ptr; /* Second index. */
+ CONST TkTextIndex *index1Ptr; /* First index. */
+ CONST TkTextIndex *index2Ptr; /* Second index. */
{
int line1, line2;
if (index1Ptr->linePtr == index2Ptr->linePtr) {
- if (index1Ptr->charIndex < index2Ptr->charIndex) {
+ if (index1Ptr->byteIndex < index2Ptr->byteIndex) {
return -1;
- } else if (index1Ptr->charIndex > index2Ptr->charIndex) {
+ } else if (index1Ptr->byteIndex > index2Ptr->byteIndex) {
return 1;
} else {
return 0;
@@ -494,23 +626,23 @@ TkTextIndexCmp(index1Ptr, index2Ptr)
}
/*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* ForwBack --
*
- * This procedure handles +/- modifiers for indices to adjust
- * the index forwards or backwards.
+ * This procedure 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.
*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
static char *
@@ -550,7 +682,7 @@ ForwBack(string, indexPtr)
*/
units = p;
- while ((*p != 0) && !isspace(UCHAR(*p)) && (*p != '+') && (*p != '-')) {
+ while ((*p != '\0') && !isspace(UCHAR(*p)) && (*p != '+') && (*p != '-')) {
p++;
}
length = p - units;
@@ -578,7 +710,18 @@ ForwBack(string, indexPtr)
lineIndex = 0;
}
}
- TkTextMakeIndex(indexPtr->tree, lineIndex, indexPtr->charIndex,
+ /*
+ * 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);
} else {
return NULL;
@@ -587,44 +730,42 @@ ForwBack(string, indexPtr)
}
/*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
- * TkTextIndexForwChars --
+ * TkTextIndexForwBytes --
*
- * 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 procedure creates a new
+ * index that points "count" bytes ahead of the source index.
*
* Results:
- * *dstPtr is modified to refer to the character "count" characters
- * after srcPtr, or to the last character in the file if there aren't
- * "count" characters left in the file.
+ * *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.
*
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
- /* ARGSUSED */
void
-TkTextIndexForwChars(srcPtr, count, dstPtr)
- TkTextIndex *srcPtr; /* Source index. */
- int count; /* How many characters forward to
- * move. May be negative. */
- TkTextIndex *dstPtr; /* Destination index: gets modified. */
+TkTextIndexForwBytes(srcPtr, byteCount, dstPtr)
+ CONST TkTextIndex *srcPtr; /* Source index. */
+ int byteCount; /* How many bytes forward to move. May be
+ * negative. */
+ TkTextIndex *dstPtr; /* Destination index: gets modified. */
{
TkTextLine *linePtr;
TkTextSegment *segPtr;
int lineLength;
- if (count < 0) {
- TkTextIndexBackChars(srcPtr, -count, dstPtr);
+ if (byteCount < 0) {
+ TkTextIndexBackBytes(srcPtr, -byteCount, dstPtr);
return;
}
*dstPtr = *srcPtr;
- dstPtr->charIndex += count;
+ dstPtr->byteIndex += byteCount;
while (1) {
/*
* Compute the length of the current line.
@@ -641,13 +782,13 @@ TkTextIndexForwChars(srcPtr, count, dstPtr)
* Otherwise go on to the next line.
*/
- if (dstPtr->charIndex < lineLength) {
+ if (dstPtr->byteIndex < lineLength) {
return;
}
- dstPtr->charIndex -= lineLength;
+ dstPtr->byteIndex -= lineLength;
linePtr = TkBTreeNextLine(dstPtr->linePtr);
if (linePtr == NULL) {
- dstPtr->charIndex = lineLength - 1;
+ dstPtr->byteIndex = lineLength - 1;
return;
}
dstPtr->linePtr = linePtr;
@@ -655,44 +796,133 @@ TkTextIndexForwChars(srcPtr, count, dstPtr)
}
/*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
- * TkTextIndexBackChars --
+ * TkTextIndexForwChars --
*
- * 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 procedure creates a new
+ * index that points "count" characters ahead of the source index.
*
* 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.
+ * after srcPtr, or to the last character in the TkText if there
+ * aren't "count" characters left in the file.
*
* Side effects:
* None.
*
- *----------------------------------------------------------------------
+ *---------------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkTextLine *linePtr;
+ TkTextSegment *segPtr;
+ int byteOffset;
+ char *start, *end, *p;
+ Tcl_UniChar ch;
+
+ if (charCount < 0) {
+ TkTextIndexBackChars(srcPtr, -charCount, dstPtr);
+ return;
+ }
+
+ *dstPtr = *srcPtr;
+
+ /*
+ * Find seg that contains src byteIndex.
+ * Move forward specified number of chars.
+ */
+
+ segPtr = TkTextIndexToSeg(dstPtr, &byteOffset);
+ while (1) {
+ /*
+ * Go through each segment in line looking for specified character
+ * index.
+ */
+
+ 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;
+ }
+ charCount--;
+ }
+ } else {
+ if (charCount < segPtr->size - byteOffset) {
+ dstPtr->byteIndex += charCount;
+ return;
+ }
+ 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.
+ */
+
+ linePtr = TkBTreeNextLine(dstPtr->linePtr);
+ if (linePtr == NULL) {
+ dstPtr->byteIndex -= sizeof(char);
+ return;
+ }
+ dstPtr->linePtr = linePtr;
+ dstPtr->byteIndex = 0;
+ segPtr = dstPtr->linePtr->segPtr;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexBackBytes --
+ *
+ * Given an index for a text widget, this procedure 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
*/
void
-TkTextIndexBackChars(srcPtr, count, dstPtr)
- TkTextIndex *srcPtr; /* Source index. */
- int count; /* How many characters backward to
- * move. May be negative. */
- TkTextIndex *dstPtr; /* Destination index: gets modified. */
+TkTextIndexBackBytes(srcPtr, byteCount, dstPtr)
+ CONST TkTextIndex *srcPtr; /* Source index. */
+ int byteCount; /* How many bytes backward to move. May be
+ * negative. */
+ TkTextIndex *dstPtr; /* Destination index: gets modified. */
{
TkTextSegment *segPtr;
int lineIndex;
- if (count < 0) {
- TkTextIndexForwChars(srcPtr, -count, dstPtr);
+ if (byteCount < 0) {
+ TkTextIndexForwBytes(srcPtr, -byteCount, dstPtr);
return;
}
*dstPtr = *srcPtr;
- dstPtr->charIndex -= count;
+ dstPtr->byteIndex -= byteCount;
lineIndex = -1;
- while (dstPtr->charIndex < 0) {
+ 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.
@@ -702,7 +932,7 @@ TkTextIndexBackChars(srcPtr, count, dstPtr)
lineIndex = TkBTreeLineIndex(dstPtr->linePtr);
}
if (lineIndex == 0) {
- dstPtr->charIndex = 0;
+ dstPtr->byteIndex = 0;
return;
}
lineIndex--;
@@ -714,8 +944,124 @@ TkTextIndexBackChars(srcPtr, count, dstPtr)
for (segPtr = dstPtr->linePtr->segPtr; segPtr != NULL;
segPtr = segPtr->nextPtr) {
- dstPtr->charIndex += segPtr->size;
+ dstPtr->byteIndex += segPtr->size;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkTextIndexBackChars --
+ *
+ * Given an index for a text widget, this procedure creates a new
+ * index that points "count" characters earlier than the source index.
+ *
+ * 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.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+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. */
+{
+ TkTextSegment *segPtr, *oldPtr;
+ int lineIndex, segSize;
+ char *p, *start, *end;
+
+ if (charCount <= 0) {
+ TkTextIndexForwChars(srcPtr, -charCount, dstPtr);
+ return;
+ }
+
+ *dstPtr = *srcPtr;
+
+ /*
+ * 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;
+ }
+ segSize -= segPtr->size;
+ }
+ 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 (p == start) {
+ break;
+ }
+ charCount--;
+ }
+ } else {
+ if (charCount < segSize) {
+ dstPtr->byteIndex -= charCount;
+ return;
+ }
+ charCount -= segSize;
+ }
+ dstPtr->byteIndex -= segSize;
+
+ /*
+ * Move back into previous segment.
+ */
+
+ oldPtr = segPtr;
+ segPtr = dstPtr->linePtr->segPtr;
+ if (segPtr != oldPtr) {
+ for ( ; segPtr->nextPtr != oldPtr; segPtr = segPtr->nextPtr) {
+ /* Empty body. */
+ }
+ segSize = segPtr->size;
+ continue;
+ }
+
+ /*
+ * Move back to previous line.
+ */
+
+ if (lineIndex < 0) {
+ lineIndex = TkBTreeLineIndex(dstPtr->linePtr);
+ }
+ if (lineIndex == 0) {
+ dstPtr->byteIndex = 0;
+ return;
+ }
+ lineIndex--;
+ dstPtr->linePtr = TkBTreeFindLine(dstPtr->tree, lineIndex);
+
+ /*
+ * Compute the length of the line and add that to dstPtr->byteIndex.
+ */
+
+ oldPtr = dstPtr->linePtr->segPtr;
+ for (segPtr = oldPtr; segPtr != NULL; segPtr = segPtr->nextPtr) {
+ dstPtr->byteIndex += segPtr->size;
+ oldPtr = segPtr;
}
+ segPtr = oldPtr;
+ segSize = segPtr->size;
}
}
@@ -762,15 +1108,15 @@ StartEnd(string, indexPtr)
length = p-string;
if ((*string == 'l') && (strncmp(string, "lineend", length) == 0)
&& (length >= 5)) {
- indexPtr->charIndex = 0;
+ indexPtr->byteIndex = 0;
for (segPtr = indexPtr->linePtr->segPtr; segPtr != NULL;
segPtr = segPtr->nextPtr) {
- indexPtr->charIndex += segPtr->size;
+ indexPtr->byteIndex += segPtr->size;
}
- indexPtr->charIndex -= 1;
+ indexPtr->byteIndex -= sizeof(char);
} else if ((*string == 'l') && (strncmp(string, "linestart", length) == 0)
&& (length >= 5)) {
- indexPtr->charIndex = 0;
+ indexPtr->byteIndex = 0;
} else if ((*string == 'w') && (strncmp(string, "wordend", length) == 0)
&& (length >= 5)) {
int firstChar = 1;
@@ -791,7 +1137,7 @@ StartEnd(string, indexPtr)
firstChar = 0;
}
offset += 1;
- indexPtr->charIndex += 1;
+ indexPtr->byteIndex += sizeof(char);
if (offset >= segPtr->size) {
segPtr = TkTextIndexToSeg(indexPtr, &offset);
}
@@ -820,10 +1166,10 @@ StartEnd(string, indexPtr)
firstChar = 0;
}
offset -= 1;
- indexPtr->charIndex -= 1;
+ indexPtr->byteIndex -= sizeof(char);
if (offset < 0) {
- if (indexPtr->charIndex < 0) {
- indexPtr->charIndex = 0;
+ if (indexPtr->byteIndex < 0) {
+ indexPtr->byteIndex = 0;
goto done;
}
segPtr = TkTextIndexToSeg(indexPtr, &offset);
diff --git a/generic/tkTextMark.c b/generic/tkTextMark.c
index 0d12c98..cf16c49 100644
--- a/generic/tkTextMark.c
+++ b/generic/tkTextMark.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkTextMark.c 1.18 97/10/20 11:12:50
+ * SCCS: @(#) tkTextMark.c 1.20 98/01/08 13:40:45
*/
#include "tkInt.h"
@@ -134,9 +134,9 @@ TkTextMarkCmd(textPtr, interp, argc, argv)
markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
if (argc == 4) {
if (markPtr->typePtr == &tkTextRightMarkType) {
- interp->result = "right";
+ Tcl_SetResult(interp, "right", TCL_STATIC);
} else {
- interp->result = "left";
+ Tcl_SetResult(interp, "left", TCL_STATIC);
}
return TCL_OK;
}
@@ -319,10 +319,10 @@ TkTextMarkSegToIndex(textPtr, markPtr, indexPtr)
indexPtr->tree = textPtr->tree;
indexPtr->linePtr = markPtr->body.mark.linePtr;
- indexPtr->charIndex = 0;
+ indexPtr->byteIndex = 0;
for (segPtr = indexPtr->linePtr->segPtr; segPtr != markPtr;
segPtr = segPtr->nextPtr) {
- indexPtr->charIndex += segPtr->size;
+ indexPtr->byteIndex += segPtr->size;
}
}
@@ -468,7 +468,7 @@ MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
chunkPtr->undisplayProc = InsertUndisplayProc;
chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
chunkPtr->bboxProc = (Tk_ChunkBboxProc *) NULL;
- chunkPtr->numChars = 0;
+ chunkPtr->numBytes = 0;
chunkPtr->minAscent = 0;
chunkPtr->minDescent = 0;
chunkPtr->minHeight = 0;
@@ -669,7 +669,7 @@ MarkFindNext(interp, textPtr, string)
return TCL_ERROR;
}
for (offset = 0, segPtr = index.linePtr->segPtr;
- segPtr != NULL && offset < index.charIndex;
+ segPtr != NULL && offset < index.byteIndex;
offset += segPtr->size, segPtr = segPtr->nextPtr) {
/* Empty loop body */ ;
}
@@ -692,7 +692,7 @@ MarkFindNext(interp, textPtr, string)
if (index.linePtr == (TkTextLine *) NULL) {
return TCL_OK;
}
- index.charIndex = 0;
+ index.byteIndex = 0;
segPtr = index.linePtr->segPtr;
}
}
@@ -742,7 +742,7 @@ MarkFindPrev(interp, textPtr, string)
return TCL_ERROR;
}
for (offset = 0, segPtr = index.linePtr->segPtr;
- segPtr != NULL && offset < index.charIndex;
+ segPtr != NULL && offset < index.byteIndex;
offset += segPtr->size, segPtr = segPtr->nextPtr) {
/* Empty loop body */ ;
}
diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c
index b5b04be..61c817e 100644
--- a/generic/tkTextTag.c
+++ b/generic/tkTextTag.c
@@ -6,12 +6,12 @@
* related to tags.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkTextTag.c 1.39 97/02/07 13:51:52
+ * SCCS: @(#) tkTextTag.c 1.42 98/01/12 15:55:55
*/
#include "default.h"
@@ -235,9 +235,22 @@ TkTextTagCmd(textPtr, interp, argc, argv)
command = Tk_GetBinding(interp, textPtr->bindingTable,
(ClientData) tagPtr, argv[4]);
if (command == NULL) {
- return TCL_ERROR;
+ 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.
+ */
+
+ if (string[0] != '\0') {
+ return TCL_ERROR;
+ } else {
+ Tcl_ResetResult(interp);
+ }
+ } else {
+ Tcl_SetResult(interp, command, TCL_STATIC);
}
- interp->result = command;
} else {
Tk_GetAllBindings(interp, textPtr->bindingTable,
(ClientData) tagPtr);
@@ -448,10 +461,10 @@ TkTextTagCmd(textPtr, interp, argc, argv)
TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
(TkTextIndex *) NULL, tagPtr, 1);
}
- TkBTreeTag(TkTextMakeIndex(textPtr->tree, 0, 0, &first),
- TkTextMakeIndex(textPtr->tree,
- TkBTreeNumLines(textPtr->tree), 0, &last),
- tagPtr, 0);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
+ 0, &last),
+ TkBTreeTag(&first, &last, tagPtr, 0);
Tcl_DeleteHashEntry(hPtr);
if (textPtr->bindingTable != NULL) {
Tk_DeleteAllBindings(textPtr->bindingTable,
@@ -552,7 +565,7 @@ TkTextTagCmd(textPtr, interp, argc, argv)
if (TkTextGetIndex(interp, textPtr, argv[4], &index1) != TCL_OK) {
return TCL_ERROR;
}
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
0, &last);
if (argc == 5) {
index2 = last;
@@ -582,7 +595,7 @@ TkTextTagCmd(textPtr, interp, argc, argv)
* skip to the end of this tagged range.
*/
- for (segPtr = index1.linePtr->segPtr, offset = index1.charIndex;
+ for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex;
offset >= 0;
offset -= segPtr->size, segPtr = segPtr->nextPtr) {
if ((offset == 0) && (segPtr->typePtr == &tkTextToggleOnType)
@@ -631,7 +644,7 @@ TkTextTagCmd(textPtr, interp, argc, argv)
return TCL_ERROR;
}
if (argc == 5) {
- TkTextMakeIndex(textPtr->tree, 0, 0, &index2);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &index2);
} else if (TkTextGetIndex(interp, textPtr, argv[5], &index2)
!= TCL_OK) {
return TCL_ERROR;
@@ -651,7 +664,7 @@ TkTextTagCmd(textPtr, interp, argc, argv)
}
if (tSearch.segPtr->typePtr == &tkTextToggleOnType) {
TkTextPrintIndex(&tSearch.curIndex, position1);
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
0, &last);
TkBTreeStartSearch(&tSearch.curIndex, &last, tagPtr, &tSearch);
TkBTreeNextTag(&tSearch);
@@ -711,8 +724,8 @@ TkTextTagCmd(textPtr, interp, argc, argv)
if (tagPtr == NULL) {
return TCL_OK;
}
- TkTextMakeIndex(textPtr->tree, 0, 0, &first);
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
0, &last);
TkBTreeStartSearch(&first, &last, tagPtr, &tSearch);
if (TkBTreeCharTagged(&first, tagPtr)) {
@@ -828,7 +841,7 @@ TkTextCreateTag(textPtr, tagName)
* 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 interp->result unless interp
+ * error message is recorded in the interp's result unless interp
* is NULL.
*
* Side effects:
diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c
index 6452d13..c8a3a13 100644
--- a/generic/tkTextWind.c
+++ b/generic/tkTextWind.c
@@ -6,12 +6,12 @@
* widget command for texts.
*
* Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkTextWind.c 1.14 97/04/25 16:52:09
+ * SCCS: @(#) tkTextWind.c 1.16 98/01/08 13:41:05
*/
#include "tk.h"
@@ -244,7 +244,7 @@ TkTextWindowCmd(textPtr, interp, argc, argv)
lineIndex = TkBTreeLineIndex(index.linePtr);
if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
lineIndex--;
- TkTextMakeIndex(textPtr->tree, lineIndex, 1000000, &index);
+ TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
}
/*
@@ -311,7 +311,7 @@ TkTextWindowCmd(textPtr, interp, argc, argv)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message..
+ * returned, then the interp's result contains an error message..
*
* Side effects:
* Configuration information for the embedded window changes,
@@ -541,7 +541,7 @@ EmbWinStructureProc(clientData, eventPtr)
ewPtr->body.ew.tkwin = NULL;
index.tree = ewPtr->body.ew.textPtr->tree;
index.linePtr = ewPtr->body.ew.linePtr;
- index.charIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
+ index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
}
@@ -575,7 +575,7 @@ EmbWinRequestProc(clientData, tkwin)
index.tree = ewPtr->body.ew.textPtr->tree;
index.linePtr = ewPtr->body.ew.linePtr;
- index.charIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
+ index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
}
@@ -620,7 +620,7 @@ EmbWinLostSlaveProc(clientData, tkwin)
ewPtr->body.ew.tkwin = NULL;
index.tree = ewPtr->body.ew.textPtr->tree;
index.linePtr = ewPtr->body.ew.linePtr;
- index.charIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
+ index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
TkTextChanged(ewPtr->body.ew.textPtr, &index, &index);
}
@@ -778,7 +778,7 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
goto gotWindow;
}
Tcl_DStringInit(&name);
- Tcl_DStringAppend(&name, textPtr->interp->result, -1);
+ Tcl_DStringAppend(&name, Tcl_GetStringResult(textPtr->interp), -1);
Tcl_ResetResult(textPtr->interp);
ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,
Tcl_DStringValue(&name), textPtr->tkwin);
@@ -847,7 +847,7 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
chunkPtr->undisplayProc = EmbWinUndisplayProc;
chunkPtr->measureProc = (Tk_ChunkMeasureProc *) NULL;
chunkPtr->bboxProc = EmbWinBboxProc;
- chunkPtr->numChars = 1;
+ chunkPtr->numBytes = 1;
if (ewPtr->body.ew.align == ALIGN_BASELINE) {
chunkPtr->minAscent = height - ewPtr->body.ew.padY;
chunkPtr->minDescent = ewPtr->body.ew.padY;
@@ -1171,6 +1171,6 @@ TkTextWindowIndex(textPtr, name, indexPtr)
ewPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
indexPtr->tree = textPtr->tree;
indexPtr->linePtr = ewPtr->body.ew.linePtr;
- indexPtr->charIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
+ indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr);
return 1;
}
diff --git a/generic/tkTrig.c b/generic/tkTrig.c
index 52dd8ba..f3976d5 100644
--- a/generic/tkTrig.c
+++ b/generic/tkTrig.c
@@ -7,12 +7,12 @@
* used by canvases.
*
* Copyright (c) 1992-1994 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkTrig.c 1.27 97/03/07 11:34:35
+ * SCCS: @(#) tkTrig.c 1.28 97/11/07 21:18:39
*/
#include <stdio.h>
@@ -1195,7 +1195,7 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints)
*
* Results:
* None. Postscript commands to generate the path are appended
- * to interp->result.
+ * to the interp's result.
*
* Side effects:
* None.
diff --git a/generic/tkUtil.c b/generic/tkUtil.c
index ddb3db0..f0d2e0c 100644
--- a/generic/tkUtil.c
+++ b/generic/tkUtil.c
@@ -6,16 +6,30 @@
* a focus highlight.
*
* Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkUtil.c 1.13 97/06/06 11:16:22
+ * SCCS: @(#) tkUtil.c 1.17 98/01/02 17:39:19
*/
#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.
+ */
+
+static Tcl_ObjType stateKeyType = {
+ "statekey", /* name */
+ (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
+ (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
+ (Tcl_UpdateStringProc *) NULL, /* updateStringProc */
+ (Tcl_SetFromAnyProc *) NULL /* setFromAnyProc */
+};
+
/*
*----------------------------------------------------------------------
@@ -132,7 +146,7 @@ Tk_DrawFocusHighlight(tkwin, gc, width, drawable)
* 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, interp->result contains an
+ * negative); if TK_SCROLL_ERROR, the interp's result contains an
* error message.
*
* Side effects:
@@ -310,7 +324,7 @@ TkFindStateString(mapPtr, numKey)
* 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 interp->result (if interp is not NULL).
+ * also left in the interp's result (if interp is not NULL).
*
* Side effects.
* None.
@@ -319,29 +333,70 @@ TkFindStateString(mapPtr, numKey)
*/
int
-TkFindStateNum(interp, field, mapPtr, strKey)
+TkFindStateNum(interp, option, mapPtr, strKey)
Tcl_Interp *interp; /* Interp for error reporting. */
- CONST char *field; /* String to use when constructing error. */
+ 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;
- if (mapPtr->strKey == NULL) {
- panic("TkFindStateNum: no choices in lookup table");
+ for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
+ if (strcmp(strKey, mPtr->strKey) == 0) {
+ return mPtr->numKey;
+ }
+ }
+ if (interp != NULL) {
+ mPtr = mapPtr;
+ Tcl_AppendResult(interp, "bad ", option, " value \"", strKey,
+ "\": must be ", mPtr->strKey, (char *) NULL);
+ for (mPtr++; mPtr->strKey != NULL; mPtr++) {
+ Tcl_AppendResult(interp,
+ ((mPtr[1].strKey != NULL) ? ", " : ", or "),
+ mPtr->strKey, (char *) 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. */
+{
+ CONST TkStateMap *mPtr;
+ CONST char *key;
+ CONST Tcl_ObjType *typePtr;
+
+ if ((keyPtr->typePtr == &stateKeyType)
+ && (keyPtr->internalRep.twoPtrValue.ptr1 == (VOID *) mapPtr)) {
+ return (int) keyPtr->internalRep.twoPtrValue.ptr2;
}
+ key = Tcl_GetStringFromObj(keyPtr, NULL);
for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
- if (strcmp(strKey, mPtr->strKey) == 0) {
+ if (strcmp(key, mPtr->strKey) == 0) {
+ typePtr = keyPtr->typePtr;
+ if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
+ (*typePtr->freeIntRepProc)(keyPtr);
+ }
+ keyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) mapPtr;
+ keyPtr->internalRep.twoPtrValue.ptr2 = (VOID *) mPtr->numKey;
+ keyPtr->typePtr = &stateKeyType;
return mPtr->numKey;
}
}
if (interp != NULL) {
mPtr = mapPtr;
- Tcl_AppendResult(interp, "bad ", field, " value \"", strKey,
+ Tcl_AppendResult(interp, "bad ",
+ Tcl_GetStringFromObj(optionPtr, NULL), " value \"", key,
"\": must be ", mPtr->strKey, (char *) NULL);
for (mPtr++; mPtr->strKey != NULL; mPtr++) {
- Tcl_AppendResult(interp, ", ", mPtr->strKey, (char *) NULL);
+ Tcl_AppendResult(interp,
+ ((mPtr[1].strKey != NULL) ? ", " : ", or "),
+ mPtr->strKey, (char *) NULL);
}
}
return mPtr->numKey;
diff --git a/generic/tkVisual.c b/generic/tkVisual.c
index 207b905..cd3e5d4 100644
--- a/generic/tkVisual.c
+++ b/generic/tkVisual.c
@@ -6,12 +6,12 @@
* prototype implementation by Paul Mackerras.
*
* Copyright (c) 1994 The Regents of the University of California.
- * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ * 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.
*
- * SCCS: @(#) tkVisual.c 1.19 97/04/25 16:52:17
+ * SCCS: @(#) tkVisual.c 1.20 97/11/07 21:18:48
*/
#include "tkInt.h"
@@ -74,7 +74,7 @@ struct TkColormap {
* 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 interp->result. The depth of the
+ * 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
@@ -243,7 +243,8 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr)
visInfoList = XGetVisualInfo(Tk_Display(tkwin), mask, &template,
&numVisuals);
if (visInfoList == NULL) {
- interp->result = "couldn't find an appropriate visual";
+ Tcl_SetResult(interp, "couldn't find an appropriate visual",
+ TCL_STATIC);
return NULL;
}
@@ -352,7 +353,7 @@ Tk_GetVisual(interp, tkwin, string, depthPtr, colormapPtr)
* 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 interp->result.
+ * message is placed in the interp's result.
*
* Side effects:
* A reference count is incremented for the colormap, so
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index fc9060a..8efc8d6 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * SCCS: @(#) tkWindow.c 1.233 97/10/31 09:55:23
+ * SCCS: @(#) tkWindow.c 1.237 98/01/12 15:56:12
*/
#include "tkPort.h"
@@ -94,6 +94,10 @@ typedef struct {
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. */
} TkCmd;
static TkCmd commands[] = {
@@ -101,62 +105,67 @@ static TkCmd commands[] = {
* Commands that are part of the intrinsics:
*/
- {"bell", Tk_BellCmd, NULL, 0},
- {"bind", Tk_BindCmd, NULL, 1},
- {"bindtags", Tk_BindtagsCmd, NULL, 1},
- {"clipboard", Tk_ClipboardCmd, NULL, 0},
- {"destroy", Tk_DestroyCmd, NULL, 1},
- {"event", Tk_EventCmd, NULL, 1},
- {"focus", Tk_FocusCmd, NULL, 1},
- {"font", NULL, Tk_FontObjCmd, 1},
- {"grab", Tk_GrabCmd, NULL, 0},
- {"grid", Tk_GridCmd, NULL, 1},
- {"image", Tk_ImageCmd, NULL, 1},
- {"lower", Tk_LowerCmd, NULL, 1},
- {"option", Tk_OptionCmd, NULL, 1},
- {"pack", Tk_PackCmd, NULL, 1},
- {"place", Tk_PlaceCmd, NULL, 1},
- {"raise", Tk_RaiseCmd, NULL, 1},
- {"selection", Tk_SelectionCmd, NULL, 0},
- {"tk", NULL, Tk_TkObjCmd, 0},
- {"tkwait", Tk_TkwaitCmd, NULL, 1},
- {"tk_chooseColor", Tk_ChooseColorCmd, NULL, 0},
- {"tk_getOpenFile", Tk_GetOpenFileCmd, NULL, 0},
- {"tk_getSaveFile", Tk_GetSaveFileCmd, NULL, 0},
- {"tk_messageBox", Tk_MessageBoxCmd, NULL, 0},
- {"update", Tk_UpdateCmd, NULL, 1},
- {"winfo", NULL, Tk_WinfoObjCmd, 1},
- {"wm", Tk_WmCmd, NULL, 0},
+ {"bell", NULL, Tk_BellObjCmd, 0, 1},
+ {"bind", Tk_BindCmd, NULL, 1, 1},
+ {"bindtags", Tk_BindtagsCmd, NULL, 1, 1},
+ {"clipboard", Tk_ClipboardCmd, NULL, 0, 1},
+ {"destroy", Tk_DestroyCmd, NULL, 1, 1},
+ {"event", NULL, Tk_EventObjCmd, 1, 1},
+ {"focus", NULL, Tk_FocusObjCmd, 1, 1},
+ {"font", NULL, Tk_FontObjCmd, 1, 1},
+ {"grab", Tk_GrabCmd, NULL, 0, 1},
+ {"grid", Tk_GridCmd, NULL, 1, 1},
+ {"image", Tk_ImageCmd, NULL, 1, 1},
+ {"lower", Tk_LowerCmd, NULL, 1, 1},
+ {"option", Tk_OptionCmd, NULL, 1, 1},
+ {"pack", Tk_PackCmd, NULL, 1, 1},
+ {"place", Tk_PlaceCmd, NULL, 1, 1},
+ {"raise", Tk_RaiseCmd, NULL, 1, 1},
+ {"selection", Tk_SelectionCmd, NULL, 0, 1},
+ {"tk", NULL, Tk_TkObjCmd, 0, 1},
+ {"tkwait", Tk_TkwaitCmd, NULL, 1, 1},
+#if defined(__WIN32__) || defined(MAC_TCL)
+ {"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
+#ifdef __WIN32__
+ {"tk_messageBox", NULL, Tk_MessageBoxObjCmd, 0, 1},
+#endif
+ {"update", NULL, Tk_UpdateObjCmd, 1, 1},
+ {"winfo", NULL, Tk_WinfoObjCmd, 1, 1},
+ {"wm", Tk_WmCmd, NULL, 0, 1},
/*
* Widget class commands.
*/
- {"button", Tk_ButtonCmd, NULL, 1},
- {"canvas", Tk_CanvasCmd, NULL, 1},
- {"checkbutton", Tk_CheckbuttonCmd, NULL, 1},
- {"entry", Tk_EntryCmd, NULL, 1},
- {"frame", Tk_FrameCmd, NULL, 1},
- {"label", Tk_LabelCmd, NULL, 1},
- {"listbox", Tk_ListboxCmd, NULL, 1},
- {"menu", Tk_MenuCmd, NULL, 0},
- {"menubutton", Tk_MenubuttonCmd, NULL, 1},
- {"message", Tk_MessageCmd, NULL, 1},
- {"radiobutton", Tk_RadiobuttonCmd, NULL, 1},
- {"scale", Tk_ScaleCmd, NULL, 1},
- {"scrollbar", Tk_ScrollbarCmd, NULL, 1},
- {"text", Tk_TextCmd, NULL, 1},
- {"toplevel", Tk_ToplevelCmd, NULL, 0},
+
+ {"button", NULL, Tk_ButtonObjCmd, 1, 0},
+ {"canvas", Tk_CanvasCmd, NULL, 1, 1},
+ {"checkbutton", NULL, Tk_CheckbuttonObjCmd, 1, 0},
+ {"entry", Tk_EntryCmd, NULL, 1, 1},
+ {"frame", Tk_FrameCmd, NULL, 1, 1},
+ {"label", NULL, Tk_LabelObjCmd, 1, 0},
+ {"listbox", Tk_ListboxCmd, NULL, 1, 1},
+ {"menubutton", Tk_MenubuttonCmd, NULL, 1, 1},
+ {"message", Tk_MessageCmd, NULL, 1, 1},
+ {"radiobutton", NULL, Tk_RadiobuttonObjCmd, 1, 0},
+ {"scale", Tk_ScaleCmd, NULL, 1, 1},
+ {"scrollbar", Tk_ScrollbarCmd, NULL, 1, 1},
+ {"text", Tk_TextCmd, NULL, 1, 1},
+ {"toplevel", Tk_ToplevelCmd, NULL, 0, 1},
/*
* Misc.
*/
#ifdef MAC_TCL
- {"unsupported1", TkUnsupported1Cmd, NULL, 1},
+ {"unsupported1", TkUnsupported1Cmd, NULL, 1, 1},
#endif
{(char *) NULL, (int (*) _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **))) NULL, NULL, 0}
};
-
+
/*
* The variables and table below are used to parse arguments from
* the "argv" variable in Tk_Init.
@@ -221,7 +230,7 @@ static void UnlinkWindow _ANSI_ARGS_((TkWindow *winPtr));
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* A new window structure is allocated locally. An X
@@ -331,7 +340,7 @@ CreateTopLevelWindow(interp, parent, name, screenName)
* 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 interp->result. The location at
+ * error message is left in the interp's result. The location at
* *screenPtr is overwritten with the screen number parsed from
* screenName.
*
@@ -364,8 +373,9 @@ GetScreen(interp, screenName, screenPtr)
screenName = TkGetDefaultScreenName(interp, screenName);
if (screenName == NULL) {
- interp->result =
- "no display name and no $DISPLAY environment variable";
+ Tcl_SetResult(interp,
+ "no display name and no $DISPLAY environment variable",
+ TCL_STATIC);
return (TkDisplay *) NULL;
}
length = strlen(screenName);
@@ -442,7 +452,10 @@ GetScreen(interp, screenName, screenPtr)
}
}
if (screenId >= ScreenCount(dispPtr->display)) {
- sprintf(interp->result, "bad screen number \"%d\"", screenId);
+ char buf[32 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "bad screen number \"%d\"", screenId);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
return (TkDisplay *) NULL;
}
*screenPtr = screenId;
@@ -675,7 +688,7 @@ NameWindow(interp, winPtr, parentPtr, name)
* 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
- * interp->result.
+ * the interp's result.
*
* Side effects:
* A new window structure is allocated locally; "interp" is
@@ -703,6 +716,7 @@ TkCreateMainWindow(interp, screenName, baseName)
register TkMainInfo *mainPtr;
register TkWindow *winPtr;
register TkCmd *cmdPtr;
+ ClientData clientData;
/*
* Panic if someone updated the TkWindow structure without
@@ -774,12 +788,17 @@ TkCreateMainWindow(interp, screenName, baseName)
if ((cmdPtr->cmdProc == NULL) && (cmdPtr->objProc == NULL)) {
panic("TkCreateMainWindow: builtin command with NULL string and object procs");
}
+ if (cmdPtr->passMainWindow) {
+ clientData = (ClientData) tkwin;
+ } else {
+ clientData = (ClientData) NULL;
+ }
if (cmdPtr->cmdProc != NULL) {
Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
- (ClientData) tkwin, (void (*) _ANSI_ARGS_((ClientData))) NULL);
+ clientData, (void (*) _ANSI_ARGS_((ClientData))) NULL);
} else {
Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc,
- (ClientData) tkwin, NULL);
+ clientData, NULL);
}
if (isSafe) {
if (!(cmdPtr->isSafe)) {
@@ -788,6 +807,8 @@ TkCreateMainWindow(interp, screenName, baseName)
}
}
+ TkCreateMenuCmd(interp);
+
/*
* Set variables for the intepreter.
*/
@@ -811,7 +832,7 @@ TkCreateMainWindow(interp, screenName, baseName)
* 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 interp->result and
+ * screen), then an error message is left in the interp's result and
* NULL is returned.
*
* Side effects:
@@ -825,7 +846,7 @@ TkCreateMainWindow(interp, screenName, baseName)
Tk_Window
Tk_CreateWindow(interp, parent, name, screenName)
Tcl_Interp *interp; /* Interpreter to use for error reporting.
- * Interp->result is assumed to be
+ * the interp's result is assumed to be
* initialized by the caller. */
Tk_Window parent; /* Token for parent of new window. */
char *name; /* Name for new window. Must be unique
@@ -878,7 +899,7 @@ Tk_CreateWindow(interp, parent, name, screenName)
* 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 interp->result and
+ * screen), then an error message is left in the interp's result and
* NULL is returned.
*
* Side effects:
@@ -892,7 +913,7 @@ Tk_CreateWindow(interp, parent, name, screenName)
Tk_Window
Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName)
Tcl_Interp *interp; /* Interpreter to use for error reporting.
- * Interp->result is assumed to be
+ * 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. */
@@ -1993,7 +2014,7 @@ TkSetClassProcs(tkwin, procs, instanceData)
* 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 interp->result.
+ * window. In this case, an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -2274,7 +2295,7 @@ Tk_RestackWindow(tkwin, aboveBelow, other)
* 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 interp->result.
+ * returned and an error message is left in the interp's result.
*
* Side effects:
* None.
@@ -2296,7 +2317,7 @@ Tk_MainWindow(interp)
return (Tk_Window) mainPtr->winPtr;
}
}
- interp->result = "this isn't a Tk application";
+ Tcl_SetResult(interp, "this isn't a Tk application", TCL_STATIC);
return NULL;
}
@@ -2504,7 +2525,7 @@ DeleteWindowsExitProc(clientData)
* the arguments that are extracted).
*
* Results:
- * Returns a standard Tcl completion code and sets interp->result
+ * Returns a standard Tcl completion code and sets the interp's result
* if there is an error.
*
* Side effects:
@@ -2529,7 +2550,7 @@ Tk_Init(interp)
* invokes the internal procedure that does the real work.
*
* Results:
- * Returns a standard Tcl completion code and sets interp->result
+ * Returns a standard Tcl completion code and sets the interp's result
* if there is an error.
*
* Side effects:
@@ -2589,8 +2610,8 @@ Tk_SafeInit(interp)
*
*
* Results:
- * A standard Tcl result. Also leaves an error message in interp->result
- * if there was an error.
+ * A standard Tcl result. Also leaves an error message in the interp's
+ * result if there was an error.
*
* Side effects:
* Depends on the initialization scripts that are invoked.
@@ -2606,7 +2627,6 @@ Initialize(interp)
int argc, code;
char **argv, *args[20];
Tcl_DString class;
- char buffer[30];
/*
* Start by initializing all the static variables to default acceptable
@@ -2624,14 +2644,89 @@ Initialize(interp)
rest = 0;
/*
- * 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.
+ * 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.
+ */
+ 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.
+ */
+ Tcl_Interp *master = interp;
- p = Tcl_GetVar2(interp, "argv", (char *) NULL, TCL_GLOBAL_ONLY);
+ while (1) {
+ master = Tcl_GetMaster(master);
+ if (master == NULL) {
+ Tcl_DStringFree(&ds);
+ Tcl_AppendResult(interp, "NULL master", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (!Tcl_IsSafe(master)) {
+ /* Found the trusted master. */
+ break;
+ }
+ }
+ /*
+ * Construct the name (rewalk...)
+ */
+ if (Tcl_GetInterpPath(master, interp) != TCL_OK) {
+ Tcl_AppendResult(interp, "error in Tcl_GetInterpPath",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * 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.
+ */
+
+ if (Tcl_Eval(master, Tcl_DStringValue(&ds)) != TCL_OK) {
+ /*
+ * We might want to transfer the error message or not.
+ * We don't. (no API to do it and maybe security reasons).
+ */
+ Tcl_DStringFree(&ds);
+ Tcl_AppendResult(interp,
+ "not allowed to start Tk by master's safe::TkInit",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ 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.
+ */
+
+ p = 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.
+ */
+
+ p = Tcl_GetVar2(interp, "argv", (char *) NULL, TCL_GLOBAL_ONLY);
+ }
argv = NULL;
if (p != NULL) {
+ char buffer[TCL_INTEGER_SPACE];
+
if (Tcl_SplitList(interp, p, &argc, &argv) != TCL_OK) {
argError:
Tcl_AddErrorInfo(interp,
@@ -2668,8 +2763,8 @@ Initialize(interp)
}
p = Tcl_DStringValue(&class);
- if (islower(UCHAR(*p))) {
- *p = toupper(UCHAR(*p));
+ if (*p) {
+ Tcl_UtfToTitle(p);
}
/*