summaryrefslogtreecommitdiff
path: root/tk/generic
diff options
context:
space:
mode:
Diffstat (limited to 'tk/generic')
-rw-r--r--tk/generic/default.h4
-rw-r--r--tk/generic/ks_names.h4
-rw-r--r--tk/generic/patchlevel.h23
-rw-r--r--tk/generic/prolog.ps285
-rw-r--r--tk/generic/tk.decls1215
-rw-r--r--tk/generic/tk.h1058
-rw-r--r--tk/generic/tk3d.c659
-rw-r--r--tk/generic/tk3d.h32
-rw-r--r--tk/generic/tkArgv.c23
-rw-r--r--tk/generic/tkAtom.c1
-rw-r--r--tk/generic/tkBind.c1566
-rw-r--r--tk/generic/tkBitmap.c854
-rw-r--r--tk/generic/tkButton.c1549
-rw-r--r--tk/generic/tkButton.h242
-rw-r--r--tk/generic/tkCanvArc.c841
-rw-r--r--tk/generic/tkCanvBmap.c286
-rw-r--r--tk/generic/tkCanvImg.c303
-rw-r--r--tk/generic/tkCanvLine.c1260
-rw-r--r--tk/generic/tkCanvPoly.c1304
-rw-r--r--tk/generic/tkCanvPs.c1000
-rw-r--r--tk/generic/tkCanvText.c638
-rw-r--r--tk/generic/tkCanvUtil.c1103
-rw-r--r--tk/generic/tkCanvWind.c342
-rw-r--r--tk/generic/tkCanvas.c2933
-rw-r--r--tk/generic/tkCanvas.h56
-rw-r--r--tk/generic/tkClipboard.c24
-rw-r--r--tk/generic/tkCmds.c572
-rw-r--r--tk/generic/tkColor.c650
-rw-r--r--tk/generic/tkColor.h50
-rw-r--r--tk/generic/tkConfig.c2424
-rw-r--r--tk/generic/tkConsole.c270
-rw-r--r--tk/generic/tkCursor.c676
-rw-r--r--tk/generic/tkDecls.h2050
-rw-r--r--tk/generic/tkEntry.c2103
-rw-r--r--tk/generic/tkError.c1
-rw-r--r--tk/generic/tkEvent.c188
-rw-r--r--tk/generic/tkFileFilter.c2
-rw-r--r--tk/generic/tkFileFilter.h1
-rw-r--r--tk/generic/tkFocus.c185
-rw-r--r--tk/generic/tkFont.c1534
-rw-r--r--tk/generic/tkFont.h76
-rw-r--r--tk/generic/tkFrame.c216
-rw-r--r--tk/generic/tkGC.c123
-rw-r--r--tk/generic/tkGeometry.c33
-rw-r--r--tk/generic/tkGet.c188
-rw-r--r--tk/generic/tkGrab.c34
-rw-r--r--tk/generic/tkGrid.c152
-rw-r--r--tk/generic/tkImage.c564
-rw-r--r--tk/generic/tkImgBmap.c242
-rw-r--r--tk/generic/tkImgGIF.c1513
-rw-r--r--tk/generic/tkImgPPM.c27
-rw-r--r--tk/generic/tkImgPhoto.c1104
-rw-r--r--tk/generic/tkImgUtil.c1
-rw-r--r--tk/generic/tkInitScript.h13
-rw-r--r--tk/generic/tkInt.decls1932
-rw-r--r--tk/generic/tkInt.h847
-rw-r--r--tk/generic/tkIntDecls.h1485
-rw-r--r--tk/generic/tkIntPlatDecls.h885
-rw-r--r--tk/generic/tkIntXlibDecls.h1674
-rw-r--r--tk/generic/tkListbox.c2728
-rw-r--r--tk/generic/tkMacWinMenu.c22
-rw-r--r--tk/generic/tkMain.c174
-rw-r--r--tk/generic/tkMenu.c2219
-rw-r--r--tk/generic/tkMenu.h190
-rw-r--r--tk/generic/tkMenuDraw.c280
-rw-r--r--tk/generic/tkMenubutton.c691
-rw-r--r--tk/generic/tkMenubutton.h24
-rw-r--r--tk/generic/tkMessage.c54
-rw-r--r--tk/generic/tkObj.c660
-rw-r--r--tk/generic/tkOldConfig.c1023
-rw-r--r--tk/generic/tkOption.c429
-rw-r--r--tk/generic/tkPack.c50
-rw-r--r--tk/generic/tkPatch.h23
-rw-r--r--tk/generic/tkPlace.c76
-rw-r--r--tk/generic/tkPlatDecls.h208
-rw-r--r--tk/generic/tkPointer.c171
-rw-r--r--tk/generic/tkPort.h1
-rw-r--r--tk/generic/tkRectOval.c604
-rw-r--r--tk/generic/tkScale.c1105
-rw-r--r--tk/generic/tkScale.h93
-rw-r--r--tk/generic/tkScrollbar.c83
-rw-r--r--tk/generic/tkScrollbar.h3
-rw-r--r--tk/generic/tkSelect.c228
-rw-r--r--tk/generic/tkSelect.h18
-rw-r--r--tk/generic/tkSend.c1867
-rw-r--r--tk/generic/tkSquare.c389
-rw-r--r--tk/generic/tkStubImg.c75
-rw-r--r--tk/generic/tkStubInit.c954
-rw-r--r--tk/generic/tkStubLib.c110
-rw-r--r--tk/generic/tkTest.c1414
-rw-r--r--tk/generic/tkText.c531
-rw-r--r--tk/generic/tkText.h215
-rw-r--r--tk/generic/tkTextBTree.c200
-rw-r--r--tk/generic/tkTextDisp.c711
-rw-r--r--tk/generic/tkTextImage.c23
-rw-r--r--tk/generic/tkTextIndex.c615
-rw-r--r--tk/generic/tkTextMark.c21
-rw-r--r--tk/generic/tkTextTag.c77
-rw-r--r--tk/generic/tkTextWind.c27
-rw-r--r--tk/generic/tkTrig.c13
-rw-r--r--tk/generic/tkUtil.c659
-rw-r--r--tk/generic/tkVisual.c10
-rw-r--r--tk/generic/tkWindow.c457
-rw-r--r--tk/generic/tkXId.c495
104 files changed, 46826 insertions, 12614 deletions
diff --git a/tk/generic/default.h b/tk/generic/default.h
index 1315608f33a..8db5f297b58 100644
--- a/tk/generic/default.h
+++ b/tk/generic/default.h
@@ -16,7 +16,8 @@
#ifndef _DEFAULT
#define _DEFAULT
-#if defined(__WIN32__) || defined(_WIN32)
+#if defined(__WIN32__) || defined(_WIN32) || \
+ defined(__CYGWIN__) || defined(__MINGW32__)
# include "tkWinDefault.h"
#else
# if defined(MAC_TCL)
@@ -27,3 +28,4 @@
#endif
#endif /* _DEFAULT */
+
diff --git a/tk/generic/ks_names.h b/tk/generic/ks_names.h
index 759becc7b06..7c299e8b5f6 100644
--- a/tk/generic/ks_names.h
+++ b/tk/generic/ks_names.h
@@ -8,6 +8,8 @@
{ "Clear", 0xFF0B },
{ "Return", 0xFF0D },
{ "Pause", 0xFF13 },
+{ "Scroll_Lock", 0xFF14 },
+{ "Sys_Req", 0xFF15 },
{ "Escape", 0xFF1B },
{ "Delete", 0xFFFF },
{ "Multi_key", 0xFF20 },
@@ -919,3 +921,5 @@
{ "hebrew_shin", 0xcf9 },
{ "hebrew_taf", 0xcfa },
{ "Hebrew_switch", 0xFF7E },
+
+
diff --git a/tk/generic/patchlevel.h b/tk/generic/patchlevel.h
new file mode 100644
index 00000000000..8053233c2bf
--- /dev/null
+++ b/tk/generic/patchlevel.h
@@ -0,0 +1,23 @@
+/*
+ * patchlevel.h --
+ *
+ * This file does nothing except define a "patch level" for Tk.
+ * The patch level has the form "X.YpZ" where X.Y is the base
+ * release, and Z is a serial number that is used to sequence
+ * patches for a given release. Thus 4.0p1 is the first patch
+ * to release 4.0, 4.0p2 is the patch that follows 4.0p1, and
+ * so on. The "pZ" is omitted in an original new release, and
+ * it is replaced with "bZ" for beta releases or "aZ" for alpha
+ * releases (e.g. 4.0b1 is the first beta release of Tk 4.0).
+ * The patch level ensures that patches are applied in the
+ * correct order and only to appropriate sources.
+ *
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) patchlevel.h 1.16 96/04/10 14:30:23
+ */
+
+#define TK_PATCH_LEVEL "4.1"
diff --git a/tk/generic/prolog.ps b/tk/generic/prolog.ps
new file mode 100644
index 00000000000..2ab137266ef
--- /dev/null
+++ b/tk/generic/prolog.ps
@@ -0,0 +1,285 @@
+%%BeginProlog
+50 dict begin
+
+% This is a standard prolog for Postscript generated by Tk's canvas
+% widget.
+% RCS: @(#) $Id$
+
+% 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/tk/generic/tk.decls b/tk/generic/tk.decls
new file mode 100644
index 00000000000..51679e2ad3d
--- /dev/null
+++ b/tk/generic/tk.decls
@@ -0,0 +1,1215 @@
+# tk.decls --
+#
+# This file contains the declarations for all supported public
+# functions that are exported by the Tk library via the stubs table.
+# This file is used to generate the tkDecls.h, tkPlatDecls.h,
+# tkStub.c, and tkPlatStub.c files.
+#
+#
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id$
+
+library tk
+
+# Define the tk interface with 3 sub interfaces:
+# tkPlat - platform specific public
+# tkInt - generic private
+# tkPlatInt - platform specific private
+
+interface tk
+hooks {tkPlat tkInt tkIntPlat tkIntXlib}
+
+# Declare each of the functions in the public Tk interface. Note that
+# the an index should never be reused for a different function in order
+# to preserve backwards compatibility.
+
+declare 0 generic {
+ void Tk_MainLoop (void)
+}
+
+declare 1 generic {
+ XColor *Tk_3DBorderColor (Tk_3DBorder border)
+}
+
+declare 2 generic {
+ GC Tk_3DBorderGC (Tk_Window tkwin, Tk_3DBorder border, \
+ int which)
+}
+
+declare 3 generic {
+ void Tk_3DHorizontalBevel (Tk_Window tkwin, \
+ Drawable drawable, Tk_3DBorder border, int x, \
+ int y, int width, int height, int leftIn, \
+ int rightIn, int topBevel, int relief)
+}
+
+declare 4 generic {
+ void Tk_3DVerticalBevel (Tk_Window tkwin, \
+ Drawable drawable, Tk_3DBorder border, int x, \
+ int y, int width, int height, int leftBevel, \
+ int relief)
+}
+
+declare 5 generic {
+ void Tk_AddOption (Tk_Window tkwin, char *name, \
+ char *value, int priority)
+}
+
+declare 6 generic {
+ void Tk_BindEvent (Tk_BindingTable bindingTable, \
+ XEvent *eventPtr, Tk_Window tkwin, int numObjects, \
+ ClientData *objectPtr)
+}
+
+declare 7 generic {
+ void Tk_CanvasDrawableCoords (Tk_Canvas canvas, \
+ double x, double y, short *drawableXPtr, \
+ short *drawableYPtr)
+}
+
+declare 8 generic {
+ void Tk_CanvasEventuallyRedraw (Tk_Canvas canvas, int x1, int y1, \
+ int x2, int y2)
+}
+
+declare 9 generic {
+ int Tk_CanvasGetCoord (Tcl_Interp *interp, \
+ Tk_Canvas canvas, char *str, double *doublePtr)
+}
+
+declare 10 generic {
+ Tk_CanvasTextInfo *Tk_CanvasGetTextInfo (Tk_Canvas canvas)
+}
+
+declare 11 generic {
+ int Tk_CanvasPsBitmap (Tcl_Interp *interp, \
+ Tk_Canvas canvas, Pixmap bitmap, int x, int y, \
+ int width, int height)
+}
+
+declare 12 generic {
+ int Tk_CanvasPsColor (Tcl_Interp *interp, \
+ Tk_Canvas canvas, XColor *colorPtr)
+}
+
+declare 13 generic {
+ int Tk_CanvasPsFont (Tcl_Interp *interp, \
+ Tk_Canvas canvas, Tk_Font font)
+}
+
+declare 14 generic {
+ void Tk_CanvasPsPath (Tcl_Interp *interp, \
+ Tk_Canvas canvas, double *coordPtr, int numPoints)
+}
+
+declare 15 generic {
+ int Tk_CanvasPsStipple (Tcl_Interp *interp, \
+ Tk_Canvas canvas, Pixmap bitmap)
+}
+
+declare 16 generic {
+ double Tk_CanvasPsY (Tk_Canvas canvas, double y)
+}
+
+declare 17 generic {
+ void Tk_CanvasSetStippleOrigin (Tk_Canvas canvas, GC gc)
+}
+
+declare 18 generic {
+ int Tk_CanvasTagsParseProc (ClientData clientData, Tcl_Interp *interp, \
+ Tk_Window tkwin, char *value, char *widgRec, int offset)
+}
+
+declare 19 generic {
+ char * Tk_CanvasTagsPrintProc (ClientData clientData, Tk_Window tkwin, \
+ char *widgRec, int offset, Tcl_FreeProc **freeProcPtr)
+}
+
+declare 20 generic {
+ Tk_Window Tk_CanvasTkwin (Tk_Canvas canvas)
+}
+
+declare 21 generic {
+ void Tk_CanvasWindowCoords (Tk_Canvas canvas, double x, double y, \
+ short *screenXPtr, short *screenYPtr)
+}
+
+declare 22 generic {
+ void Tk_ChangeWindowAttributes (Tk_Window tkwin, unsigned long valueMask, \
+ XSetWindowAttributes *attsPtr)
+}
+
+declare 23 generic {
+ int Tk_CharBbox (Tk_TextLayout layout, int index, int *xPtr, \
+ int *yPtr, int *widthPtr, int *heightPtr)
+}
+
+declare 24 generic {
+ void Tk_ClearSelection (Tk_Window tkwin, Atom selection)
+}
+
+declare 25 generic {
+ int Tk_ClipboardAppend (Tcl_Interp *interp,Tk_Window tkwin, \
+ Atom target, Atom format, char* buffer)
+}
+
+declare 26 generic {
+ int Tk_ClipboardClear (Tcl_Interp *interp, Tk_Window tkwin)
+}
+
+declare 27 generic {
+ int Tk_ConfigureInfo (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tk_ConfigSpec *specs, \
+ char *widgRec, char *argvName, int flags)
+}
+
+declare 28 generic {
+ int Tk_ConfigureValue (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tk_ConfigSpec *specs, \
+ char *widgRec, char *argvName, int flags)
+}
+
+declare 29 generic {
+ int Tk_ConfigureWidget (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tk_ConfigSpec *specs, \
+ int argc, char **argv, char *widgRec, \
+ int flags)
+}
+
+declare 30 generic {
+ void Tk_ConfigureWindow (Tk_Window tkwin, \
+ unsigned int valueMask, XWindowChanges *valuePtr)
+}
+
+declare 31 generic {
+ Tk_TextLayout Tk_ComputeTextLayout (Tk_Font font, \
+ CONST char *str, int numChars, int wrapLength, \
+ Tk_Justify justify, int flags, int *widthPtr, \
+ int *heightPtr)
+}
+
+declare 32 generic {
+ Tk_Window Tk_CoordsToWindow (int rootX, int rootY, Tk_Window tkwin)
+}
+
+declare 33 generic {
+ unsigned long Tk_CreateBinding (Tcl_Interp *interp, \
+ Tk_BindingTable bindingTable, ClientData object, \
+ char *eventStr, char *command, int append)
+}
+
+declare 34 generic {
+ Tk_BindingTable Tk_CreateBindingTable (Tcl_Interp *interp)
+}
+
+declare 35 generic {
+ Tk_ErrorHandler Tk_CreateErrorHandler (Display *display, \
+ int errNum, int request, int minorCode, \
+ Tk_ErrorProc *errorProc, ClientData clientData)
+}
+
+declare 36 generic {
+ void Tk_CreateEventHandler (Tk_Window token, \
+ unsigned long mask, Tk_EventProc *proc, \
+ ClientData clientData)
+}
+
+declare 37 generic {
+ void Tk_CreateGenericHandler (Tk_GenericProc *proc, ClientData clientData)
+}
+
+declare 38 generic {
+ void Tk_CreateImageType (Tk_ImageType *typePtr)
+}
+
+declare 39 generic {
+ void Tk_CreateItemType (Tk_ItemType *typePtr)
+}
+
+declare 40 generic {
+ void Tk_CreatePhotoImageFormat (Tk_PhotoImageFormat *formatPtr)
+}
+
+declare 41 generic {
+ void Tk_CreateSelHandler (Tk_Window tkwin, \
+ Atom selection, Atom target, \
+ Tk_SelectionProc *proc, ClientData clientData, \
+ Atom format)
+}
+
+declare 42 generic {
+ Tk_Window Tk_CreateWindow (Tcl_Interp *interp, \
+ Tk_Window parent, char *name, char *screenName)
+}
+
+declare 43 generic {
+ Tk_Window Tk_CreateWindowFromPath (Tcl_Interp *interp, Tk_Window tkwin, \
+ char *pathName, char *screenName)
+}
+
+declare 44 generic {
+ int Tk_DefineBitmap (Tcl_Interp *interp, CONST char *name, char *source, \
+ int width, int height)
+}
+
+declare 45 generic {
+ void Tk_DefineCursor (Tk_Window window, Tk_Cursor cursor)
+}
+
+declare 46 generic {
+ void Tk_DeleteAllBindings (Tk_BindingTable bindingTable, ClientData object)
+}
+
+declare 47 generic {
+ int Tk_DeleteBinding (Tcl_Interp *interp, \
+ Tk_BindingTable bindingTable, ClientData object, \
+ char *eventStr)
+}
+
+declare 48 generic {
+ void Tk_DeleteBindingTable (Tk_BindingTable bindingTable)
+}
+
+declare 49 generic {
+ void Tk_DeleteErrorHandler (Tk_ErrorHandler handler)
+}
+
+declare 50 generic {
+ void Tk_DeleteEventHandler (Tk_Window token, \
+ unsigned long mask, Tk_EventProc *proc, \
+ ClientData clientData)
+}
+
+declare 51 generic {
+ void Tk_DeleteGenericHandler (Tk_GenericProc *proc, ClientData clientData)
+}
+
+declare 52 generic {
+ void Tk_DeleteImage (Tcl_Interp *interp, char *name)
+}
+
+declare 53 generic {
+ void Tk_DeleteSelHandler (Tk_Window tkwin, Atom selection, Atom target)
+}
+
+declare 54 generic {
+ void Tk_DestroyWindow (Tk_Window tkwin)
+}
+
+declare 55 generic {
+ char * Tk_DisplayName (Tk_Window tkwin)
+}
+
+declare 56 generic {
+ int Tk_DistanceToTextLayout (Tk_TextLayout layout, int x, int y)
+}
+
+declare 57 generic {
+ void Tk_Draw3DPolygon (Tk_Window tkwin, \
+ Drawable drawable, Tk_3DBorder border, \
+ XPoint *pointPtr, int numPoints, int borderWidth, \
+ int leftRelief)
+}
+
+declare 58 generic {
+ void Tk_Draw3DRectangle (Tk_Window tkwin, Drawable drawable, \
+ Tk_3DBorder border, int x, int y, int width, int height, \
+ int borderWidth, int relief)
+}
+
+declare 59 generic {
+ void Tk_DrawChars (Display *display, Drawable drawable, GC gc, \
+ Tk_Font tkfont, CONST char *source, int numBytes, int x, int y)
+}
+
+declare 60 generic {
+ void Tk_DrawFocusHighlight (Tk_Window tkwin, GC gc, int width, \
+ Drawable drawable)
+}
+
+declare 61 generic {
+ void Tk_DrawTextLayout (Display *display, \
+ Drawable drawable, GC gc, Tk_TextLayout layout, \
+ int x, int y, int firstChar, int lastChar)
+}
+
+declare 62 generic {
+ void Tk_Fill3DPolygon (Tk_Window tkwin, \
+ Drawable drawable, Tk_3DBorder border, \
+ XPoint *pointPtr, int numPoints, int borderWidth, \
+ int leftRelief)
+}
+
+declare 63 generic {
+ void Tk_Fill3DRectangle (Tk_Window tkwin, \
+ Drawable drawable, Tk_3DBorder border, int x, \
+ int y, int width, int height, int borderWidth, \
+ int relief)
+}
+
+declare 64 generic {
+ Tk_PhotoHandle Tk_FindPhoto (Tcl_Interp *interp, char *imageName)
+}
+
+declare 65 generic {
+ Font Tk_FontId (Tk_Font font)
+}
+
+declare 66 generic {
+ void Tk_Free3DBorder (Tk_3DBorder border)
+}
+
+declare 67 generic {
+ void Tk_FreeBitmap (Display *display, Pixmap bitmap)
+}
+
+declare 68 generic {
+ void Tk_FreeColor (XColor *colorPtr)
+}
+
+declare 69 generic {
+ void Tk_FreeColormap (Display *display, Colormap colormap)
+}
+
+declare 70 generic {
+ void Tk_FreeCursor (Display *display, Tk_Cursor cursor)
+}
+
+declare 71 generic {
+ void Tk_FreeFont (Tk_Font f)
+}
+
+declare 72 generic {
+ void Tk_FreeGC (Display *display, GC gc)
+}
+
+declare 73 generic {
+ void Tk_FreeImage (Tk_Image image)
+}
+
+declare 74 generic {
+ void Tk_FreeOptions (Tk_ConfigSpec *specs, \
+ char *widgRec, Display *display, int needFlags)
+}
+
+declare 75 generic {
+ void Tk_FreePixmap (Display *display, Pixmap pixmap)
+}
+
+declare 76 generic {
+ void Tk_FreeTextLayout (Tk_TextLayout textLayout)
+}
+
+declare 77 generic {
+ void Tk_FreeXId (Display *display, XID xid)
+}
+
+declare 78 generic {
+ GC Tk_GCForColor (XColor *colorPtr, Drawable drawable)
+}
+
+declare 79 generic {
+ void Tk_GeometryRequest (Tk_Window tkwin, int reqWidth, int reqHeight)
+}
+
+declare 80 generic {
+ Tk_3DBorder Tk_Get3DBorder (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tk_Uid colorName)
+}
+
+declare 81 generic {
+ void Tk_GetAllBindings (Tcl_Interp *interp, \
+ Tk_BindingTable bindingTable, ClientData object)
+}
+
+declare 82 generic {
+ int Tk_GetAnchor (Tcl_Interp *interp, \
+ char *str, Tk_Anchor *anchorPtr)
+}
+
+declare 83 generic {
+ char * Tk_GetAtomName (Tk_Window tkwin, Atom atom)
+}
+
+declare 84 generic {
+ char * Tk_GetBinding (Tcl_Interp *interp, \
+ Tk_BindingTable bindingTable, ClientData object, \
+ char *eventStr)
+}
+
+declare 85 generic {
+ Pixmap Tk_GetBitmap (Tcl_Interp *interp, Tk_Window tkwin, CONST char * str)
+}
+
+declare 86 generic {
+ Pixmap Tk_GetBitmapFromData (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *source, int width, int height)
+}
+
+declare 87 generic {
+ int Tk_GetCapStyle (Tcl_Interp *interp, char *str, int *capPtr)
+}
+
+declare 88 generic {
+ XColor * Tk_GetColor (Tcl_Interp *interp, Tk_Window tkwin, Tk_Uid name)
+}
+
+declare 89 generic {
+ XColor * Tk_GetColorByValue (Tk_Window tkwin, XColor *colorPtr)
+}
+
+declare 90 generic {
+ Colormap Tk_GetColormap (Tcl_Interp *interp, Tk_Window tkwin, char *str)
+}
+
+declare 91 generic {
+ Tk_Cursor Tk_GetCursor (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tk_Uid str)
+}
+
+declare 92 generic {
+ Tk_Cursor Tk_GetCursorFromData (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *source, char *mask, \
+ int width, int height, int xHot, int yHot, \
+ Tk_Uid fg, Tk_Uid bg)
+}
+
+declare 93 generic {
+ Tk_Font Tk_GetFont (Tcl_Interp *interp, \
+ Tk_Window tkwin, CONST char *str)
+}
+
+declare 94 generic {
+ Tk_Font Tk_GetFontFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 95 generic {
+ void Tk_GetFontMetrics (Tk_Font font, Tk_FontMetrics *fmPtr)
+}
+
+declare 96 generic {
+ GC Tk_GetGC (Tk_Window tkwin, unsigned long valueMask, XGCValues *valuePtr)
+}
+
+declare 97 generic {
+ Tk_Image Tk_GetImage (Tcl_Interp *interp, Tk_Window tkwin, char *name, \
+ Tk_ImageChangedProc *changeProc, ClientData clientData)
+}
+
+declare 98 generic {
+ ClientData Tk_GetImageMasterData (Tcl_Interp *interp, \
+ char *name, Tk_ImageType **typePtrPtr)
+}
+
+declare 99 generic {
+ Tk_ItemType * Tk_GetItemTypes (void)
+}
+
+declare 100 generic {
+ int Tk_GetJoinStyle (Tcl_Interp *interp, char *str, int *joinPtr)
+}
+
+declare 101 generic {
+ int Tk_GetJustify (Tcl_Interp *interp, \
+ char *str, Tk_Justify *justifyPtr)
+}
+
+declare 102 generic {
+ int Tk_GetNumMainWindows (void)
+}
+
+declare 103 generic {
+ Tk_Uid Tk_GetOption (Tk_Window tkwin, char *name, char *className)
+}
+
+declare 104 generic {
+ int Tk_GetPixels (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *str, int *intPtr)
+}
+
+declare 105 generic {
+ Pixmap Tk_GetPixmap (Display *display, Drawable d, \
+ int width, int height, int depth)
+}
+
+declare 106 generic {
+ int Tk_GetRelief (Tcl_Interp *interp, char *name, int *reliefPtr)
+}
+
+declare 107 generic {
+ void Tk_GetRootCoords (Tk_Window tkwin, int *xPtr, int *yPtr)
+}
+
+declare 108 generic {
+ int Tk_GetScrollInfo (Tcl_Interp *interp, \
+ int argc, char **argv, double *dblPtr, int *intPtr)
+}
+
+declare 109 generic {
+ int Tk_GetScreenMM (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *str, double *doublePtr)
+}
+
+declare 110 generic {
+ int Tk_GetSelection (Tcl_Interp *interp, \
+ Tk_Window tkwin, Atom selection, Atom target, \
+ Tk_GetSelProc *proc, ClientData clientData)
+}
+
+declare 111 generic {
+ Tk_Uid Tk_GetUid (CONST char *str)
+}
+
+declare 112 generic {
+ Visual * Tk_GetVisual (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *str, int *depthPtr, \
+ Colormap *colormapPtr)
+}
+
+declare 113 generic {
+ void Tk_GetVRootGeometry (Tk_Window tkwin, \
+ int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)
+}
+
+declare 114 generic {
+ int Tk_Grab (Tcl_Interp *interp, Tk_Window tkwin, int grabGlobal)
+}
+
+declare 115 generic {
+ void Tk_HandleEvent (XEvent *eventPtr)
+}
+
+declare 116 generic {
+ Tk_Window Tk_IdToWindow (Display *display, Window window)
+}
+
+declare 117 generic {
+ void Tk_ImageChanged (Tk_ImageMaster master, int x, int y, \
+ int width, int height, int imageWidth, int imageHeight)
+}
+
+declare 118 generic {
+ int Tk_Init (Tcl_Interp *interp)
+}
+
+declare 119 generic {
+ Atom Tk_InternAtom (Tk_Window tkwin, char *name)
+}
+
+declare 120 generic {
+ int Tk_IntersectTextLayout (Tk_TextLayout layout, int x, int y, \
+ int width, int height)
+}
+
+declare 121 generic {
+ void Tk_MaintainGeometry (Tk_Window slave, \
+ Tk_Window master, int x, int y, int width, int height)
+}
+
+declare 122 generic {
+ Tk_Window Tk_MainWindow (Tcl_Interp *interp)
+}
+
+declare 123 generic {
+ void Tk_MakeWindowExist (Tk_Window tkwin)
+}
+
+declare 124 generic {
+ void Tk_ManageGeometry (Tk_Window tkwin, \
+ Tk_GeomMgr *mgrPtr, ClientData clientData)
+}
+
+declare 125 generic {
+ void Tk_MapWindow (Tk_Window tkwin)
+}
+
+declare 126 generic {
+ int Tk_MeasureChars (Tk_Font tkfont, \
+ CONST char *source, int numBytes, int maxPixels, \
+ int flags, int *lengthPtr)
+}
+
+declare 127 generic {
+ void Tk_MoveResizeWindow (Tk_Window tkwin, \
+ int x, int y, int width, int height)
+}
+
+declare 128 generic {
+ void Tk_MoveWindow (Tk_Window tkwin, int x, int y)
+}
+
+declare 129 generic {
+ void Tk_MoveToplevelWindow (Tk_Window tkwin, int x, int y)
+}
+
+declare 130 generic {
+ char * Tk_NameOf3DBorder (Tk_3DBorder border)
+}
+
+declare 131 generic {
+ char * Tk_NameOfAnchor (Tk_Anchor anchor)
+}
+
+declare 132 generic {
+ char * Tk_NameOfBitmap (Display *display, Pixmap bitmap)
+}
+
+declare 133 generic {
+ char * Tk_NameOfCapStyle (int cap)
+}
+
+declare 134 generic {
+ char * Tk_NameOfColor (XColor *colorPtr)
+}
+
+declare 135 generic {
+ char * Tk_NameOfCursor (Display *display, Tk_Cursor cursor)
+}
+
+declare 136 generic {
+ char * Tk_NameOfFont (Tk_Font font)
+}
+
+declare 137 generic {
+ char * Tk_NameOfImage (Tk_ImageMaster imageMaster)
+}
+
+declare 138 generic {
+ char * Tk_NameOfJoinStyle (int join)
+}
+
+declare 139 generic {
+ char * Tk_NameOfJustify (Tk_Justify justify)
+}
+
+declare 140 generic {
+ char * Tk_NameOfRelief (int relief)
+}
+
+declare 141 generic {
+ Tk_Window Tk_NameToWindow (Tcl_Interp *interp, \
+ char *pathName, Tk_Window tkwin)
+}
+
+declare 142 generic {
+ void Tk_OwnSelection (Tk_Window tkwin, \
+ Atom selection, Tk_LostSelProc *proc, \
+ ClientData clientData)
+}
+
+declare 143 generic {
+ int Tk_ParseArgv (Tcl_Interp *interp, \
+ Tk_Window tkwin, int *argcPtr, char **argv, \
+ Tk_ArgvInfo *argTable, int flags)
+}
+
+declare 144 generic {
+ void Tk_PhotoPutBlock (Tk_PhotoHandle handle, \
+ Tk_PhotoImageBlock *blockPtr, int x, int y, \
+ int width, int height)
+}
+
+declare 145 generic {
+ void Tk_PhotoPutZoomedBlock (Tk_PhotoHandle handle, \
+ Tk_PhotoImageBlock *blockPtr, int x, int y, \
+ int width, int height, int zoomX, int zoomY, \
+ int subsampleX, int subsampleY)
+}
+
+declare 146 generic {
+ int Tk_PhotoGetImage (Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr)
+}
+
+declare 147 generic {
+ void Tk_PhotoBlank (Tk_PhotoHandle handle)
+}
+
+declare 148 generic {
+ void Tk_PhotoExpand (Tk_PhotoHandle handle, int width, int height )
+}
+
+declare 149 generic {
+ void Tk_PhotoGetSize (Tk_PhotoHandle handle, int *widthPtr, int *heightPtr)
+}
+
+declare 150 generic {
+ void Tk_PhotoSetSize (Tk_PhotoHandle handle, int width, int height)
+}
+
+declare 151 generic {
+ int Tk_PointToChar (Tk_TextLayout layout, int x, int y)
+}
+
+declare 152 generic {
+ int Tk_PostscriptFontName (Tk_Font tkfont, Tcl_DString *dsPtr)
+}
+
+declare 153 generic {
+ void Tk_PreserveColormap (Display *display, Colormap colormap)
+}
+
+declare 154 generic {
+ void Tk_QueueWindowEvent (XEvent *eventPtr, Tcl_QueuePosition position)
+}
+
+declare 155 generic {
+ void Tk_RedrawImage (Tk_Image image, int imageX, \
+ int imageY, int width, int height, \
+ Drawable drawable, int drawableX, int drawableY)
+}
+
+declare 156 generic {
+ void Tk_ResizeWindow (Tk_Window tkwin, int width, int height)
+}
+
+declare 157 generic {
+ int Tk_RestackWindow (Tk_Window tkwin, int aboveBelow, Tk_Window other)
+}
+
+declare 158 generic {
+ Tk_RestrictProc *Tk_RestrictEvents (Tk_RestrictProc *proc, \
+ ClientData arg, ClientData *prevArgPtr)
+}
+
+declare 159 generic {
+ int Tk_SafeInit (Tcl_Interp *interp)
+}
+
+declare 160 generic {
+ char * Tk_SetAppName (Tk_Window tkwin, char *name)
+}
+
+declare 161 generic {
+ void Tk_SetBackgroundFromBorder (Tk_Window tkwin, Tk_3DBorder border)
+}
+
+declare 162 generic {
+ void Tk_SetClass (Tk_Window tkwin, char *className)
+}
+
+declare 163 generic {
+ void Tk_SetGrid (Tk_Window tkwin, int reqWidth, int reqHeight, \
+ int gridWidth, int gridHeight)
+}
+
+declare 164 generic {
+ void Tk_SetInternalBorder (Tk_Window tkwin, int width)
+}
+
+declare 165 generic {
+ void Tk_SetWindowBackground (Tk_Window tkwin, unsigned long pixel)
+}
+
+declare 166 generic {
+ void Tk_SetWindowBackgroundPixmap (Tk_Window tkwin, Pixmap pixmap)
+}
+
+declare 167 generic {
+ void Tk_SetWindowBorder (Tk_Window tkwin, unsigned long pixel)
+}
+
+declare 168 generic {
+ void Tk_SetWindowBorderWidth (Tk_Window tkwin, int width)
+}
+
+declare 169 generic {
+ void Tk_SetWindowBorderPixmap (Tk_Window tkwin, Pixmap pixmap)
+}
+
+declare 170 generic {
+ void Tk_SetWindowColormap (Tk_Window tkwin, Colormap colormap)
+}
+
+declare 171 generic {
+ int Tk_SetWindowVisual (Tk_Window tkwin, Visual *visual, int depth,\
+ Colormap colormap)
+}
+
+declare 172 generic {
+ void Tk_SizeOfBitmap (Display *display, Pixmap bitmap, int *widthPtr, \
+ int *heightPtr)
+}
+
+declare 173 generic {
+ void Tk_SizeOfImage (Tk_Image image, int *widthPtr, int *heightPtr)
+}
+
+declare 174 generic {
+ int Tk_StrictMotif (Tk_Window tkwin)
+}
+
+declare 175 generic {
+ void Tk_TextLayoutToPostscript (Tcl_Interp *interp, Tk_TextLayout layout)
+}
+
+declare 176 generic {
+ int Tk_TextWidth (Tk_Font font, CONST char *str, int numBytes)
+}
+
+declare 177 generic {
+ void Tk_UndefineCursor (Tk_Window window)
+}
+
+declare 178 generic {
+ void Tk_UnderlineChars (Display *display, \
+ Drawable drawable, GC gc, Tk_Font tkfont, \
+ CONST char *source, int x, int y, int firstByte, \
+ int lastByte)
+}
+
+declare 179 generic {
+ void Tk_UnderlineTextLayout (Display *display, Drawable drawable, GC gc, \
+ Tk_TextLayout layout, int x, int y, \
+ int underline)
+}
+
+declare 180 generic {
+ void Tk_Ungrab (Tk_Window tkwin)
+}
+
+declare 181 generic {
+ void Tk_UnmaintainGeometry (Tk_Window slave, Tk_Window master)
+}
+
+declare 182 generic {
+ void Tk_UnmapWindow (Tk_Window tkwin)
+}
+
+declare 183 generic {
+ void Tk_UnsetGrid (Tk_Window tkwin)
+}
+
+declare 184 generic {
+ void Tk_UpdatePointer (Tk_Window tkwin, int x, int y, int state)
+}
+
+# new functions for 8.1
+
+declare 185 generic {
+ Pixmap Tk_AllocBitmapFromObj (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tcl_Obj *objPtr)
+}
+
+declare 186 generic {
+ Tk_3DBorder Tk_Alloc3DBorderFromObj (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tcl_Obj *objPtr)
+}
+
+declare 187 generic {
+ XColor * Tk_AllocColorFromObj (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tcl_Obj *objPtr)
+}
+
+declare 188 generic {
+ Tk_Cursor Tk_AllocCursorFromObj (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tcl_Obj *objPtr)
+}
+
+declare 189 generic {
+ Tk_Font Tk_AllocFontFromObj (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tcl_Obj *objPtr)
+
+}
+
+declare 190 generic {
+ Tk_OptionTable Tk_CreateOptionTable (Tcl_Interp *interp, \
+ CONST Tk_OptionSpec *templatePtr)
+}
+
+declare 191 generic {
+ void Tk_DeleteOptionTable (Tk_OptionTable optionTable)
+}
+
+declare 192 generic {
+ void Tk_Free3DBorderFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 193 generic {
+ void Tk_FreeBitmapFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 194 generic {
+ void Tk_FreeColorFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 195 generic {
+ void Tk_FreeConfigOptions (char *recordPtr, Tk_OptionTable optionToken, \
+ Tk_Window tkwin)
+
+}
+
+declare 196 generic {
+ void Tk_FreeSavedOptions (Tk_SavedOptions *savePtr)
+}
+
+declare 197 generic {
+ void Tk_FreeCursorFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 198 generic {
+ void Tk_FreeFontFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 199 generic {
+ Tk_3DBorder Tk_Get3DBorderFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 200 generic {
+ int Tk_GetAnchorFromObj (Tcl_Interp *interp, Tcl_Obj *objPtr, \
+ Tk_Anchor *anchorPtr)
+}
+
+declare 201 generic {
+ Pixmap Tk_GetBitmapFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 202 generic {
+ XColor * Tk_GetColorFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 203 generic {
+ Tk_Cursor Tk_GetCursorFromObj (Tk_Window tkwin, Tcl_Obj *objPtr)
+}
+
+declare 204 generic {
+ Tcl_Obj * Tk_GetOptionInfo (Tcl_Interp *interp, \
+ char *recordPtr, Tk_OptionTable optionTable, \
+ Tcl_Obj *namePtr, Tk_Window tkwin)
+}
+
+declare 205 generic {
+ Tcl_Obj * Tk_GetOptionValue (Tcl_Interp *interp, char *recordPtr, \
+ Tk_OptionTable optionTable, Tcl_Obj *namePtr, Tk_Window tkwin)
+}
+
+declare 206 generic {
+ int Tk_GetJustifyFromObj (Tcl_Interp *interp, \
+ Tcl_Obj *objPtr, Tk_Justify *justifyPtr)
+}
+
+declare 207 generic {
+ int Tk_GetMMFromObj (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr)
+}
+
+declare 208 generic {
+ int Tk_GetPixelsFromObj (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tcl_Obj *objPtr, int *intPtr)
+}
+
+declare 209 generic {
+ int Tk_GetReliefFromObj (Tcl_Interp *interp, \
+ Tcl_Obj *objPtr, int *resultPtr)
+}
+
+declare 210 generic {
+ int Tk_GetScrollInfoObj (Tcl_Interp *interp, \
+ int objc, Tcl_Obj *CONST objv[], double *dblPtr, int *intPtr)
+}
+
+declare 211 generic {
+ int Tk_InitOptions (
+ Tcl_Interp *interp, char *recordPtr, \
+ Tk_OptionTable optionToken, Tk_Window tkwin)
+}
+
+declare 212 generic {
+ void Tk_MainEx (int argc, char **argv, Tcl_AppInitProc *appInitProc, \
+ Tcl_Interp *interp)
+}
+
+declare 213 generic {
+ void Tk_RestoreSavedOptions (Tk_SavedOptions *savePtr)
+}
+
+declare 214 generic {
+ int Tk_SetOptions (Tcl_Interp *interp, char *recordPtr, \
+ Tk_OptionTable optionTable, int objc, \
+ Tcl_Obj *CONST objv[], Tk_Window tkwin, \
+ Tk_SavedOptions *savePtr, int *maskPtr)
+}
+
+declare 215 generic {
+ void Tk_InitConsoleChannels (Tcl_Interp *interp)
+}
+
+declare 216 generic {
+ int Tk_CreateConsoleWindow (Tcl_Interp *interp)
+}
+
+declare 217 generic {
+ void Tk_CreateSmoothMethod (Tcl_Interp *interp, Tk_SmoothMethod *method)
+}
+
+#declare 218 generic {
+# void Tk_CreateCanvasVisitor (Tcl_Interp *interp, VOID *typePtr)
+#}
+
+#declare 219 generic {
+# VOID *Tk_GetCanvasVisitor (Tcl_Interp *interp, CONST char *name)
+#}
+
+declare 220 generic {
+ int Tk_GetDash (Tcl_Interp *interp, CONST char *value, Tk_Dash *dash)
+}
+declare 221 generic {
+ void Tk_CreateOutline (Tk_Outline *outline)
+}
+declare 222 generic {
+ void Tk_DeleteOutline (Display *display, Tk_Outline *outline)
+}
+declare 223 generic {
+ int Tk_ConfigOutlineGC (XGCValues *gcValues, Tk_Canvas canvas, \
+ Tk_Item *item, Tk_Outline *outline)
+}
+declare 224 generic {
+ int Tk_ChangeOutlineGC (Tk_Canvas canvas, Tk_Item *item, \
+ Tk_Outline *outline)
+}
+declare 225 generic {
+ int Tk_ResetOutlineGC (Tk_Canvas canvas, Tk_Item *item, \
+ Tk_Outline *outline)
+}
+declare 226 generic {
+ int Tk_CanvasPsOutline (Tk_Canvas canvas, Tk_Item *item, \
+ Tk_Outline *outline)
+}
+declare 227 generic {
+ void Tk_SetTSOrigin (Tk_Window tkwin, GC gc, int x, int y)
+}
+declare 228 generic {
+ int Tk_CanvasGetCoordFromObj (Tcl_Interp *interp, Tk_Canvas canvas, \
+ Tcl_Obj *obj, double *doublePtr)
+}
+declare 229 generic {
+ void Tk_CanvasSetOffset (Tk_Canvas canvas, GC gc, Tk_TSOffset *offset)
+}
+declare 230 generic {
+ void Tk_DitherPhoto (Tk_PhotoHandle handle, int x, int y, int width, \
+ int height)
+}
+declare 231 generic {
+ int Tk_PostscriptBitmap (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, \
+ int startY, int width, int height)
+}
+declare 232 generic {
+ int Tk_PostscriptColor (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
+ XColor *colorPtr)
+}
+declare 233 generic {
+ int Tk_PostscriptFont (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
+ Tk_Font font)
+}
+declare 234 generic {
+ int Tk_PostscriptImage (Tk_Image image, Tcl_Interp *interp, \
+ Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, \
+ int width, int height, int prepass)
+}
+declare 235 generic {
+ void Tk_PostscriptPath (Tcl_Interp *interp, Tk_PostscriptInfo psInfo, \
+ double *coordPtr, int numPoints)
+}
+declare 236 generic {
+ int Tk_PostscriptStipple (Tcl_Interp *interp, Tk_Window tkwin, \
+ Tk_PostscriptInfo psInfo, Pixmap bitmap)
+}
+declare 237 generic {
+ double Tk_PostscriptY (double y, Tk_PostscriptInfo psInfo)
+}
+declare 238 generic {
+ int Tk_PostscriptPhoto (Tcl_Interp *interp, \
+ Tk_PhotoImageBlock *blockPtr, Tk_PostscriptInfo psInfo, \
+ int width, int height)
+}
+
+# Define the platform specific public Tk interface. These functions are
+# only available on the designated platform.
+
+interface tkPlat
+
+# Unix specific functions
+# (none)
+
+# Windows specific functions
+
+declare 0 win {
+ Window Tk_AttachHWND (Tk_Window tkwin, HWND hwnd)
+}
+
+declare 1 win {
+ HINSTANCE Tk_GetHINSTANCE (void)
+}
+
+declare 2 win {
+ HWND Tk_GetHWND (Window window)
+}
+
+declare 3 win {
+ Tk_Window Tk_HWNDToWindow (HWND hwnd)
+}
+
+declare 4 win {
+ void Tk_PointerEvent (HWND hwnd, int x, int y)
+}
+
+declare 5 win {
+ int Tk_TranslateWinEvent (HWND hwnd, \
+ UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
+}
+
+# Mac specific functions
+
+declare 0 mac {
+ void Tk_MacSetEmbedHandler ( \
+ Tk_MacEmbedRegisterWinProc *registerWinProcPtr, \
+ Tk_MacEmbedGetGrafPortProc *getPortProcPtr, \
+ Tk_MacEmbedMakeContainerExistProc *containerExistProcPtr, \
+ Tk_MacEmbedGetClipProc *getClipProc, \
+ Tk_MacEmbedGetOffsetInParentProc *getOffsetProc)
+}
+
+declare 1 mac {
+ void Tk_MacTurnOffMenus (void)
+}
+
+declare 2 mac {
+ void Tk_MacTkOwnsCursor (int tkOwnsIt)
+}
+
+declare 3 mac {
+ void TkMacInitMenus (Tcl_Interp *interp)
+}
+
+declare 4 mac {
+ void TkMacInitAppleEvents (Tcl_Interp *interp)
+}
+
+declare 5 mac {
+ int TkMacConvertEvent (EventRecord *eventPtr)
+}
+
+declare 6 mac {
+ int TkMacConvertTkEvent (EventRecord *eventPtr, Window window)
+}
+
+declare 7 mac {
+ void TkGenWMConfigureEvent (Tk_Window tkwin, \
+ int x, int y, int width, int height, int flags)
+}
+
+declare 8 mac {
+ void TkMacInvalClipRgns (TkWindow *winPtr)
+}
+
+declare 9 mac {
+ int TkMacHaveAppearance (void)
+}
+
+declare 10 mac {
+ GWorldPtr TkMacGetDrawablePort (Drawable drawable)
+}
+
diff --git a/tk/generic/tk.h b/tk/generic/tk.h
index 5d1a05603dc..c4eb7145d56 100644
--- a/tk/generic/tk.h
+++ b/tk/generic/tk.h
@@ -6,8 +6,8 @@
*
* 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) 1998 by Scriptics Corporation.
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 Ajuba Solutions.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -19,41 +19,39 @@
#define _TK
/*
+ * For C++ compilers, use extern "C"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
* When version numbers change here, you must also go into the following files
* and update the version numbers:
*
- * README
- * unix/configure.in
- * win/makefile.bc (Not for patch release updates)
- * win/makefile.vc (Not for patch release updates)
- * win/README
- * library/tk.tcl
- *
- * 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
- * "a", "b", or "p" in the patch level; for example, if the patch level
- * is 4.3b2, TK_RELEASE_SERIAL is 2. It restarts at 1 whenever the
- * release level is changed, except for the final release, which should
- * be 0.
+ * library/tk.tcl (only if Major.minor changes, not patchlevel)
+ * unix/configure.in (2 LOC Major, 2 LOC minor, 1 LOC patch)
+ * win/configure.in (as above)
+ * win/makefile.vc (not patchlevel)
+ * README (sections 0 and 1)
+ * mac/README (not patchlevel)
+ * win/README (not patchlevel)
+ * unix/README (not patchlevel)
+ * unix/tk.spec (3 LOC Major/Minor, 2 LOC patch)
+ * win/aclocal.m4 (not patchlevel)
*
* You may also need to update some of these files when the numbers change
* for the version of Tcl that this release of Tk is compiled against.
*/
#define TK_MAJOR_VERSION 8
-#define TK_MINOR_VERSION 0
-#define TK_RELEASE_LEVEL 2
-#define TK_RELEASE_SERIAL 4
-
-#define TK_VERSION "8.0"
-#define TK_PATCH_LEVEL "8.0.4"
+#define TK_MINOR_VERSION 3
+#define TK_RELEASE_LEVEL TCL_FINAL_RELEASE
+#define TK_RELEASE_SERIAL 2
-/*
- * A special definition used to allow this header file to be included
- * in resource files.
- */
-
-#ifndef RESOURCE_INCLUDED
+#define TK_VERSION "8.3"
+#define TK_PATCH_LEVEL "8.3.2"
/*
* The following definitions set up the proper options for Macintosh
@@ -69,6 +67,14 @@
#ifndef _TCL
# include <tcl.h>
#endif
+
+/*
+ * A special definition used to allow this header file to be included
+ * in resource files.
+ */
+
+#ifndef RESOURCE_INCLUDED
+
#ifndef _XLIB_H
# ifdef MAC_TCL
# include <Xlib.h>
@@ -105,6 +111,8 @@ 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_PostscriptInfo_ *Tk_PostscriptInfo;
typedef struct Tk_TextLayout_ *Tk_TextLayout;
typedef struct Tk_Window_ *Tk_Window;
typedef struct Tk_3DBorder_ *Tk_3DBorder;
@@ -116,56 +124,167 @@ 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,
+/* CYGNUS LOCAL: Support -version argument. */
+ TK_OPTION_VERSION,
+ 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
-/* CYGNUS LOCAL: Support -version argument. */
-#define TK_ARGV_VERSION 27
-#define TK_ARGV_END 28
+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
+#define TK_OPTION_DONT_SET_DEFAULT 8
+
+/*
+ * Macro to use to fill in "offset" fields of the Tk_OptionSpec.
+ * struct. Computes number of bytes from beginning of structure
+ * to a given field.
+ */
+
+#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));
@@ -219,60 +338,82 @@ 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:
*/
#define TK_CONFIG_ARGV_ONLY 1
+#define TK_CONFIG_OBJS 0x80
/*
- * 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
+/* CYGNUS LOCAL: Support -version argument. */
+#define TK_ARGV_VERSION 27
+#define TK_ARGV_END 28
+
+/*
+ * 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
@@ -297,12 +438,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:
@@ -638,6 +779,21 @@ typedef struct Tk_FakeWin {
*--------------------------------------------------------------
*/
+typedef enum {
+ TK_STATE_NULL = -1, TK_STATE_ACTIVE, TK_STATE_DISABLED,
+ TK_STATE_NORMAL, TK_STATE_HIDDEN
+} Tk_State;
+
+typedef struct Tk_SmoothMethod {
+ char *name;
+ int (*coordProc) _ANSI_ARGS_((Tk_Canvas canvas,
+ double *pointPtr, int numPoints, int numSteps,
+ XPoint xPoints[], double dblPoints[]));
+ void (*postscriptProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, double *coordPtr,
+ int numPoints, int numSteps));
+} Tk_SmoothMethod;
+
/*
* For each item in a canvas widget there exists one record with
* the following structure. Each actual item is represented by
@@ -677,9 +833,9 @@ typedef struct Tk_Item {
* items in this canvas. Later items
* in list are drawn just below earlier
* ones. */
- int reserved1; /* This padding is for compatibility */
- char *reserved2; /* with Jan Nijtmans dash patch */
- int reserved3;
+ Tk_State state; /* state of item */
+ char *reserved1; /* reserved for future use */
+ int redraw_flags; /* some flags used in the canvas */
/*
*------------------------------------------------------------------
@@ -692,11 +848,25 @@ typedef struct Tk_Item {
} Tk_Item;
/*
+ * Flag bits for canvases (redraw_flags):
+ *
+ * TK_ITEM_STATE_DEPENDANT - 1 means that object needs to be
+ * redrawn if the canvas state changes.
+ * TK_ITEM_DONT_REDRAW - 1 means that the object redraw is already
+ * been prepared, so the general canvas code
+ * doesn't need to do that any more.
+ */
+
+#define TK_ITEM_STATE_DEPENDANT 1
+#define TK_ITEM_DONT_REDRAW 2
+
+/*
* Records of the following type are used to describe a type of
* item (e.g. lines, circles, etc.) that can form part of a
* canvas widget.
*/
+#ifdef USE_OLD_CANVAS
typedef int Tk_ItemCreateProc _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
char **argv));
@@ -706,6 +876,17 @@ typedef int Tk_ItemConfigureProc _ANSI_ARGS_((Tcl_Interp *interp,
typedef int Tk_ItemCoordProc _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
char **argv));
+#else
+typedef int Tk_ItemCreateProc _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
+ Tcl_Obj *CONST objv[]));
+typedef int Tk_ItemConfigureProc _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
+ Tcl_Obj *CONST objv[], int flags));
+typedef int Tk_ItemCoordProc _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
+ Tcl_Obj *CONST argv[]));
+#endif
typedef void Tk_ItemDeleteProc _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
typedef void Tk_ItemDisplayProc _ANSI_ARGS_((Tk_Canvas canvas,
@@ -735,6 +916,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". */
@@ -755,7 +938,7 @@ typedef struct Tk_ItemType {
* this type. */
int alwaysRedraw; /* Non-zero means displayProc should
* be called even when the item has
- * been moved off-screen. */
+ * been moved off-screen. */
Tk_ItemPointProc *pointProc; /* Computes distance from item to
* a given point. */
Tk_ItemAreaProc *areaProc; /* Computes whether item is inside,
@@ -788,6 +971,8 @@ typedef struct Tk_ItemType {
char *reserved4;
} Tk_ItemType;
+#endif
+
/*
* The following structure provides information about the selection and
* the insertion cursor. It is needed by only a few items, such as
@@ -806,16 +991,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
@@ -833,6 +1019,59 @@ typedef struct Tk_CanvasTextInfo {
} Tk_CanvasTextInfo;
/*
+ * Structures used for Dashing and Outline.
+ */
+
+typedef struct Tk_Dash {
+ int number;
+ union {
+ char *pt;
+ char array[sizeof(char *)];
+ } pattern;
+} Tk_Dash;
+
+typedef struct Tk_TSOffset {
+ int flags; /* flags; see below for possible values */
+ int xoffset; /* x offset */
+ int yoffset; /* y offset */
+} Tk_TSOffset;
+
+/*
+ * Bit fields in Tk_Offset->flags:
+ */
+
+#define TK_OFFSET_INDEX 1
+#define TK_OFFSET_RELATIVE 2
+#define TK_OFFSET_LEFT 4
+#define TK_OFFSET_CENTER 8
+#define TK_OFFSET_RIGHT 16
+#define TK_OFFSET_TOP 32
+#define TK_OFFSET_MIDDLE 64
+#define TK_OFFSET_BOTTOM 128
+
+typedef struct Tk_Outline {
+ GC gc; /* Graphics context. */
+ double width; /* Width of outline. */
+ double activeWidth; /* Width of outline. */
+ double disabledWidth; /* Width of outline. */
+ int offset; /* Dash offset */
+ Tk_Dash dash; /* Dash pattern */
+ Tk_Dash activeDash; /* Dash pattern if state is active*/
+ Tk_Dash disabledDash; /* Dash pattern if state is disabled*/
+ VOID *reserved1; /* reserved for future expansion */
+ VOID *reserved2;
+ VOID *reserved3;
+ Tk_TSOffset tsoffset; /* stipple offset for outline*/
+ XColor *color; /* Outline color. */
+ XColor *activeColor; /* Outline color if state is active. */
+ XColor *disabledColor; /* Outline color if state is disabled. */
+ Pixmap stipple; /* Outline Stipple pattern. */
+ Pixmap activeStipple; /* Outline Stipple pattern if state is active. */
+ Pixmap disabledStipple; /* Outline Stipple pattern if state is disabled. */
+} Tk_Outline;
+
+
+/*
*--------------------------------------------------------------
*
* Procedure prototypes and structures used for managing images:
@@ -841,9 +1080,15 @@ typedef struct Tk_CanvasTextInfo {
*/
typedef struct Tk_ImageType Tk_ImageType;
+#ifdef USE_OLD_IMAGE
+typedef int (Tk_ImageCreateProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ char *name, int argc, char **argv, Tk_ImageType *typePtr,
+ Tk_ImageMaster master, ClientData *masterDataPtr));
+#else
typedef int (Tk_ImageCreateProc) _ANSI_ARGS_((Tcl_Interp *interp,
char *name, int objc, Tcl_Obj *CONST objv[], Tk_ImageType *typePtr,
Tk_ImageMaster master, ClientData *masterDataPtr));
+#endif
typedef ClientData (Tk_ImageGetProc) _ANSI_ARGS_((Tk_Window tkwin,
ClientData masterData));
typedef void (Tk_ImageDisplayProc) _ANSI_ARGS_((ClientData instanceData,
@@ -855,6 +1100,9 @@ typedef void (Tk_ImageDeleteProc) _ANSI_ARGS_((ClientData masterData));
typedef void (Tk_ImageChangedProc) _ANSI_ARGS_((ClientData clientData,
int x, int y, int width, int height, int imageWidth,
int imageHeight));
+typedef int (Tk_ImagePostscriptProc) _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo,
+ int x, int y, int width, int height, int prepass));
/*
* The following structure represents a particular type of image
@@ -884,6 +1132,9 @@ struct Tk_ImageType {
* will not be called until after freeProc
* has been called for each instance of the
* image. */
+ Tk_ImagePostscriptProc *postscriptProc;
+ /* Procedure to call to produce postscript
+ * output for the image. */
struct Tk_ImageType *nextPtr;
/* Next in list of all image types currently
* known. Filled in by Tk, not by image
@@ -918,10 +1169,9 @@ typedef struct Tk_PhotoImageBlock {
* pixels in successive lines. */
int pixelSize; /* Address difference between successive
* pixels in the same line. */
- int offset[3]; /* Address differences between the red, green
- * and blue components of the pixel and the
- * pixel as a whole. */
- int reserved; /* Reserved for extensions (dash patch) */
+ int offset[4]; /* Address differences between the red, green,
+ * blue and alpha components of the pixel and
+ * the pixel as a whole. */
} Tk_PhotoImageBlock;
/*
@@ -930,6 +1180,7 @@ typedef struct Tk_PhotoImageBlock {
*/
typedef struct Tk_PhotoImageFormat Tk_PhotoImageFormat;
+#ifdef USE_OLD_IMAGE
typedef int (Tk_ImageFileMatchProc) _ANSI_ARGS_((Tcl_Channel chan,
char *fileName, char *formatString, int *widthPtr, int *heightPtr));
typedef int (Tk_ImageStringMatchProc) _ANSI_ARGS_((Tcl_Obj *dataObj,
@@ -946,6 +1197,25 @@ typedef int (Tk_ImageFileWriteProc) _ANSI_ARGS_((Tcl_Interp *interp,
typedef int (Tk_ImageStringWriteProc) _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_DString *dataPtr, char *formatString,
Tk_PhotoImageBlock *blockPtr));
+#else
+typedef int (Tk_ImageFileMatchProc) _ANSI_ARGS_((Tcl_Channel chan,
+ CONST char *fileName, Tcl_Obj *format, int *widthPtr,
+ int *heightPtr, Tcl_Interp *interp));
+typedef int (Tk_ImageStringMatchProc) _ANSI_ARGS_((Tcl_Obj *dataObj,
+ Tcl_Obj *format, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp));
+typedef int (Tk_ImageFileReadProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Channel chan, CONST char *fileName, Tcl_Obj *format,
+ Tk_PhotoHandle imageHandle, int destX, int destY,
+ int width, int height, int srcX, int srcY));
+typedef int (Tk_ImageStringReadProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *dataObj, Tcl_Obj *format, Tk_PhotoHandle imageHandle,
+ int destX, int destY, int width, int height, int srcX, int srcY));
+typedef int (Tk_ImageFileWriteProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ CONST char *fileName, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr));
+typedef int (Tk_ImageStringWriteProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr));
+#endif
/*
* The following structure represents a particular file format for
@@ -980,6 +1250,17 @@ struct Tk_PhotoImageFormat {
* currently known. Filled in by Tk, not
* by image format handler. */
};
+
+EXTERN void Tk_CreateOldImageType _ANSI_ARGS_((
+ Tk_ImageType *typePtr));
+EXTERN void Tk_CreateOldPhotoImageFormat _ANSI_ARGS_((
+ Tk_PhotoImageFormat *formatPtr));
+
+#if !defined(USE_TK_STUBS) && defined(USE_OLD_IMAGE)
+#define Tk_CreateImageType Tk_CreateOldImageType
+#define Tk_CreatePhotoImageFormat Tk_CreateOldPhotoImageFormat
+#endif
+
/*
*--------------------------------------------------------------
@@ -1018,11 +1299,35 @@ struct Tk_PhotoImageFormat {
#define Tk_DoWhenIdle Tcl_DoWhenIdle
#define Tk_Sleep Tcl_Sleep
+/* Additional stuff that has moved to Tcl: */
+
+#define Tk_AfterCmd Tcl_AfterCmd
#define Tk_EventuallyFree Tcl_EventuallyFree
#define Tk_FreeProc Tcl_FreeProc
#define Tk_Preserve Tcl_Preserve
#define Tk_Release Tcl_Release
-#define Tk_FileeventCmd Tcl_FileEventCmd
+
+/* Removed Tk_Main, use macro instead */
+#define Tk_Main(argc, argv, proc) \
+ Tk_MainEx(argc, argv, proc, Tcl_CreateInterp())
+
+char *Tk_InitStubs _ANSI_ARGS_((Tcl_Interp *interp, char *version, int exact));
+
+#ifndef USE_TK_STUBS
+
+#define Tk_InitStubs(interp, version, exact) \
+ Tcl_PkgRequire(interp, "Tk", version, exact)
+
+#endif
+
+void Tk_InitImageArgs _ANSI_ARGS_((Tcl_Interp *interp, int argc, char ***argv));
+
+#if !defined(USE_TK_STUBS) || !defined(USE_OLD_IMAGE)
+
+#define Tk_InitImageArgs(interp, argc, argv) /**/
+
+#endif
+
/*
*--------------------------------------------------------------
@@ -1046,6 +1351,7 @@ typedef Tk_RestrictAction (Tk_RestrictProc) _ANSI_ARGS_((
typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData,
int offset, char *buffer, int maxBytes));
+
/*
*--------------------------------------------------------------
*
@@ -1054,512 +1360,26 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData,
*--------------------------------------------------------------
*/
-EXTERN XColor * Tk_3DBorderColor _ANSI_ARGS_((Tk_3DBorder border));
-EXTERN GC Tk_3DBorderGC _ANSI_ARGS_((Tk_Window tkwin,
- Tk_3DBorder border, int which));
-EXTERN void Tk_3DHorizontalBevel _ANSI_ARGS_((Tk_Window tkwin,
- Drawable drawable, Tk_3DBorder border, int x,
- int y, int width, int height, int leftIn,
- int rightIn, int topBevel, int relief));
-EXTERN void Tk_3DVerticalBevel _ANSI_ARGS_((Tk_Window tkwin,
- Drawable drawable, Tk_3DBorder border, int x,
- int y, int width, int height, int leftBevel,
- int relief));
-EXTERN void Tk_AddOption _ANSI_ARGS_((Tk_Window tkwin, char *name,
- char *value, int priority));
-EXTERN void Tk_BindEvent _ANSI_ARGS_((Tk_BindingTable bindingTable,
- XEvent *eventPtr, Tk_Window tkwin, int numObjects,
- ClientData *objectPtr));
-EXTERN void Tk_CanvasDrawableCoords _ANSI_ARGS_((Tk_Canvas canvas,
- double x, double y, short *drawableXPtr,
- short *drawableYPtr));
-EXTERN void Tk_CanvasEventuallyRedraw _ANSI_ARGS_((
- Tk_Canvas canvas, int x1, int y1, int x2,
- int y2));
-EXTERN int Tk_CanvasGetCoord _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, char *string,
- double *doublePtr));
-EXTERN Tk_CanvasTextInfo *Tk_CanvasGetTextInfo _ANSI_ARGS_((Tk_Canvas canvas));
-EXTERN int Tk_CanvasPsBitmap _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, Pixmap bitmap, int x, int y,
- int width, int height));
-EXTERN int Tk_CanvasPsColor _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, XColor *colorPtr));
-EXTERN int Tk_CanvasPsFont _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, Tk_Font font));
-EXTERN void Tk_CanvasPsPath _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, double *coordPtr, int numPoints));
-EXTERN int Tk_CanvasPsStipple _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, Pixmap bitmap));
-EXTERN double Tk_CanvasPsY _ANSI_ARGS_((Tk_Canvas canvas, double y));
-EXTERN void Tk_CanvasSetStippleOrigin _ANSI_ARGS_((
- Tk_Canvas canvas, GC gc));
-EXTERN int Tk_CanvasTagsParseProc _ANSI_ARGS_((
- ClientData clientData, Tcl_Interp *interp,
- Tk_Window tkwin, char *value, char *widgRec,
- int offset));
-EXTERN char * Tk_CanvasTagsPrintProc _ANSI_ARGS_((
- ClientData clientData, Tk_Window tkwin,
- char *widgRec, int offset,
- Tcl_FreeProc **freeProcPtr));
-EXTERN Tk_Window Tk_CanvasTkwin _ANSI_ARGS_((Tk_Canvas canvas));
-EXTERN void Tk_CanvasWindowCoords _ANSI_ARGS_((Tk_Canvas canvas,
- double x, double y, short *screenXPtr,
- short *screenYPtr));
-EXTERN void Tk_ChangeWindowAttributes _ANSI_ARGS_((Tk_Window tkwin,
- unsigned long valueMask,
- XSetWindowAttributes *attsPtr));
-EXTERN int Tk_CharBbox _ANSI_ARGS_((Tk_TextLayout layout,
- int index, int *xPtr, int *yPtr, int *widthPtr,
- int *heightPtr));
-EXTERN void Tk_ClearSelection _ANSI_ARGS_((Tk_Window tkwin,
- Atom selection));
-EXTERN int Tk_ClipboardAppend _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Atom target, Atom format,
- char* buffer));
-EXTERN int Tk_ClipboardClear _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin));
-EXTERN int Tk_ConfigureInfo _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_ConfigSpec *specs,
- char *widgRec, char *argvName, int flags));
-EXTERN int Tk_ConfigureValue _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_ConfigSpec *specs,
- char *widgRec, char *argvName, int flags));
-EXTERN int Tk_ConfigureWidget _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_ConfigSpec *specs,
- int argc, char **argv, char *widgRec,
- int flags));
-EXTERN void Tk_ConfigureWindow _ANSI_ARGS_((Tk_Window tkwin,
- unsigned int valueMask, XWindowChanges *valuePtr));
-EXTERN Tk_TextLayout Tk_ComputeTextLayout _ANSI_ARGS_((Tk_Font font,
- CONST char *string, int numChars, int wrapLength,
- Tk_Justify justify, int flags, int *widthPtr,
- int *heightPtr));
-EXTERN Tk_Window Tk_CoordsToWindow _ANSI_ARGS_((int rootX, int rootY,
- Tk_Window tkwin));
-EXTERN unsigned long Tk_CreateBinding _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_BindingTable bindingTable, ClientData object,
- char *eventString, char *command, int append));
-EXTERN Tk_BindingTable Tk_CreateBindingTable _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN Tk_ErrorHandler Tk_CreateErrorHandler _ANSI_ARGS_((Display *display,
- int errNum, int request, int minorCode,
- Tk_ErrorProc *errorProc, ClientData clientData));
-EXTERN void Tk_CreateEventHandler _ANSI_ARGS_((Tk_Window token,
- unsigned long mask, Tk_EventProc *proc,
- ClientData clientData));
-EXTERN void Tk_CreateGenericHandler _ANSI_ARGS_((
- Tk_GenericProc *proc, ClientData clientData));
-EXTERN void Tk_CreateImageType _ANSI_ARGS_((
- Tk_ImageType *typePtr));
-EXTERN void Tk_CreateItemType _ANSI_ARGS_((Tk_ItemType *typePtr));
-EXTERN void Tk_CreatePhotoImageFormat _ANSI_ARGS_((
- Tk_PhotoImageFormat *formatPtr));
-EXTERN void Tk_CreateSelHandler _ANSI_ARGS_((Tk_Window tkwin,
- Atom selection, Atom target,
- Tk_SelectionProc *proc, ClientData clientData,
- Atom format));
-EXTERN Tk_Window Tk_CreateWindow _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window parent, char *name, char *screenName));
-EXTERN Tk_Window Tk_CreateWindowFromPath _ANSI_ARGS_((
- Tcl_Interp *interp, Tk_Window tkwin,
- char *pathName, char *screenName));
-EXTERN int Tk_DefineBitmap _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Uid name, char *source, int width,
- int height));
-EXTERN void Tk_DefineCursor _ANSI_ARGS_((Tk_Window window,
- Tk_Cursor cursor));
-EXTERN void Tk_DeleteAllBindings _ANSI_ARGS_((
- Tk_BindingTable bindingTable, ClientData object));
-EXTERN int Tk_DeleteBinding _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_BindingTable bindingTable, ClientData object,
- char *eventString));
-EXTERN void Tk_DeleteBindingTable _ANSI_ARGS_((
- Tk_BindingTable bindingTable));
-EXTERN void Tk_DeleteErrorHandler _ANSI_ARGS_((
- Tk_ErrorHandler handler));
-EXTERN void Tk_DeleteEventHandler _ANSI_ARGS_((Tk_Window token,
- unsigned long mask, Tk_EventProc *proc,
- ClientData clientData));
-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_DeleteSelHandler _ANSI_ARGS_((Tk_Window tkwin,
- Atom selection, Atom target));
-EXTERN void Tk_DestroyWindow _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN char * Tk_DisplayName _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN int Tk_DistanceToTextLayout _ANSI_ARGS_((
- Tk_TextLayout layout, int x, int y));
-EXTERN void Tk_Draw3DPolygon _ANSI_ARGS_((Tk_Window tkwin,
- Drawable drawable, Tk_3DBorder border,
- XPoint *pointPtr, int numPoints, int borderWidth,
- int leftRelief));
-EXTERN void Tk_Draw3DRectangle _ANSI_ARGS_((Tk_Window tkwin,
- Drawable drawable, Tk_3DBorder border, int x,
- int y, int width, int height, int borderWidth,
- int relief));
-EXTERN void Tk_DrawChars _ANSI_ARGS_((Display *display,
- Drawable drawable, GC gc, Tk_Font tkfont,
- CONST char *source, int numChars, int x,
- int y));
-EXTERN void Tk_DrawFocusHighlight _ANSI_ARGS_((Tk_Window tkwin,
- GC gc, int width, Drawable drawable));
-EXTERN void Tk_DrawTextLayout _ANSI_ARGS_((Display *display,
- Drawable drawable, GC gc, Tk_TextLayout layout,
- int x, int y, int firstChar, int lastChar));
-EXTERN void Tk_Fill3DPolygon _ANSI_ARGS_((Tk_Window tkwin,
- Drawable drawable, Tk_3DBorder border,
- XPoint *pointPtr, int numPoints, int borderWidth,
- int leftRelief));
-EXTERN void Tk_Fill3DRectangle _ANSI_ARGS_((Tk_Window tkwin,
- Drawable drawable, Tk_3DBorder border, int x,
- int y, int width, int height, int borderWidth,
- int relief));
-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_FreeBitmap _ANSI_ARGS_((Display *display,
- Pixmap bitmap));
-EXTERN void Tk_FreeColor _ANSI_ARGS_((XColor *colorPtr));
-EXTERN void Tk_FreeColormap _ANSI_ARGS_((Display *display,
- Colormap colormap));
-EXTERN void Tk_FreeCursor _ANSI_ARGS_((Display *display,
- Tk_Cursor cursor));
-EXTERN void Tk_FreeFont _ANSI_ARGS_((Tk_Font));
-EXTERN void Tk_FreeGC _ANSI_ARGS_((Display *display, GC gc));
-EXTERN void Tk_FreeImage _ANSI_ARGS_((Tk_Image image));
-EXTERN void Tk_FreeOptions _ANSI_ARGS_((Tk_ConfigSpec *specs,
- char *widgRec, Display *display, int needFlags));
-EXTERN void Tk_FreePixmap _ANSI_ARGS_((Display *display,
- Pixmap pixmap));
-EXTERN void Tk_FreeTextLayout _ANSI_ARGS_((
- Tk_TextLayout textLayout));
-EXTERN void Tk_FreeXId _ANSI_ARGS_((Display *display, XID xid));
-EXTERN GC Tk_GCForColor _ANSI_ARGS_((XColor *colorPtr,
- Drawable drawable));
-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));
-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 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));
-EXTERN Pixmap Tk_GetBitmapFromData _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *source,
- int width, int height));
-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));
-EXTERN XColor * Tk_GetColorByValue _ANSI_ARGS_((Tk_Window tkwin,
- XColor *colorPtr));
-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));
-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_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 void Tk_GetFontMetrics _ANSI_ARGS_((Tk_Font font,
- Tk_FontMetrics *fmPtr));
-EXTERN GC Tk_GetGC _ANSI_ARGS_((Tk_Window tkwin,
- unsigned long valueMask, XGCValues *valuePtr));
-/* CYGNUS LOCAL. */
-EXTERN GC Tk_GetGCColor _ANSI_ARGS_((Tk_Window tkwin,
- unsigned long valueMask, XGCValues *valuePtr,
- XColor *foreground, XColor *background));
-EXTERN Tk_Image Tk_GetImage _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *name,
- Tk_ImageChangedProc *changeProc,
- ClientData clientData));
-EXTERN ClientData Tk_GetImageMasterData _ANSI_ARGS_ ((Tcl_Interp *interp,
- char *name, Tk_ImageType **typePtrPtr));
-EXTERN Tk_ItemType * Tk_GetItemTypes _ANSI_ARGS_((void));
-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_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 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 void Tk_GetRootCoords _ANSI_ARGS_ ((Tk_Window tkwin,
- int *xPtr, int *yPtr));
-EXTERN int Tk_GetScrollInfo _ANSI_ARGS_((Tcl_Interp *interp,
- int argc, char **argv, double *dblPtr,
- int *intPtr));
-EXTERN int Tk_GetScreenMM _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *string, double *doublePtr));
-EXTERN int Tk_GetSelection _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Atom selection, Atom target,
- Tk_GetSelProc *proc, ClientData clientData));
-EXTERN Tk_Uid Tk_GetUid _ANSI_ARGS_((CONST char *string));
-EXTERN Visual * Tk_GetVisual _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *string, int *depthPtr,
- Colormap *colormapPtr));
-EXTERN void Tk_GetVRootGeometry _ANSI_ARGS_((Tk_Window tkwin,
- int *xPtr, int *yPtr, int *widthPtr,
- int *heightPtr));
-EXTERN int Tk_Grab _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, int grabGlobal));
-EXTERN void Tk_HandleEvent _ANSI_ARGS_((XEvent *eventPtr));
-EXTERN Tk_Window Tk_IdToWindow _ANSI_ARGS_((Display *display,
- Window window));
-EXTERN void Tk_ImageChanged _ANSI_ARGS_((
- Tk_ImageMaster master, int x, int y,
- int width, int height, int imageWidth,
- int imageHeight));
-EXTERN int Tk_Init _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN Atom Tk_InternAtom _ANSI_ARGS_((Tk_Window tkwin,
- char *name));
-EXTERN int Tk_IntersectTextLayout _ANSI_ARGS_((
- Tk_TextLayout layout, int x, int y, int width,
- int height));
-EXTERN void Tk_Main _ANSI_ARGS_((int argc, char **argv,
- Tcl_AppInitProc *appInitProc));
-EXTERN void Tk_MainLoop _ANSI_ARGS_((void));
-EXTERN void Tk_MaintainGeometry _ANSI_ARGS_((Tk_Window slave,
- Tk_Window master, int x, int y, int width,
- int height));
-EXTERN Tk_Window Tk_MainWindow _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN void Tk_MakeWindowExist _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void Tk_ManageGeometry _ANSI_ARGS_((Tk_Window tkwin,
- Tk_GeomMgr *mgrPtr, ClientData clientData));
-EXTERN void Tk_MapWindow _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN int Tk_MeasureChars _ANSI_ARGS_((Tk_Font tkfont,
- CONST char *source, int maxChars, int maxPixels,
- int flags, int *lengthPtr));
-EXTERN void Tk_MoveResizeWindow _ANSI_ARGS_((Tk_Window tkwin,
- int x, int y, int width, int height));
-EXTERN void Tk_MoveWindow _ANSI_ARGS_((Tk_Window tkwin, int x,
- int y));
-EXTERN void Tk_MoveToplevelWindow _ANSI_ARGS_((Tk_Window tkwin,
- int x, int y));
-EXTERN char * Tk_NameOf3DBorder _ANSI_ARGS_((Tk_3DBorder border));
-EXTERN char * Tk_NameOfAnchor _ANSI_ARGS_((Tk_Anchor anchor));
-EXTERN char * Tk_NameOfBitmap _ANSI_ARGS_((Display *display,
- Pixmap bitmap));
-EXTERN char * Tk_NameOfCapStyle _ANSI_ARGS_((int cap));
-EXTERN char * Tk_NameOfColor _ANSI_ARGS_((XColor *colorPtr));
-EXTERN char * Tk_NameOfCursor _ANSI_ARGS_((Display *display,
- Tk_Cursor cursor));
-EXTERN char * Tk_NameOfFont _ANSI_ARGS_((Tk_Font font));
-EXTERN char * Tk_NameOfImage _ANSI_ARGS_((
- Tk_ImageMaster imageMaster));
-EXTERN char * Tk_NameOfJoinStyle _ANSI_ARGS_((int join));
-EXTERN char * Tk_NameOfJustify _ANSI_ARGS_((Tk_Justify justify));
-EXTERN char * Tk_NameOfRelief _ANSI_ARGS_((int relief));
-EXTERN Tk_Window Tk_NameToWindow _ANSI_ARGS_((Tcl_Interp *interp,
- char *pathName, Tk_Window tkwin));
-EXTERN void Tk_OwnSelection _ANSI_ARGS_((Tk_Window tkwin,
- Atom selection, Tk_LostSelProc *proc,
- ClientData clientData));
-EXTERN int Tk_ParseArgv _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, int *argcPtr, char **argv,
- Tk_ArgvInfo *argTable, int flags));
-EXTERN void Tk_PhotoPutBlock _ANSI_ARGS_((Tk_PhotoHandle handle,
- Tk_PhotoImageBlock *blockPtr, int x, int y,
- int width, int height));
-EXTERN void Tk_PhotoPutZoomedBlock _ANSI_ARGS_((
- Tk_PhotoHandle handle,
- Tk_PhotoImageBlock *blockPtr, int x, int y,
- int width, int height, int zoomX, int zoomY,
- int subsampleX, int subsampleY));
-EXTERN int Tk_PhotoGetImage _ANSI_ARGS_((Tk_PhotoHandle handle,
- Tk_PhotoImageBlock *blockPtr));
-EXTERN void Tk_PhotoBlank _ANSI_ARGS_((Tk_PhotoHandle handle));
-EXTERN void Tk_PhotoExpand _ANSI_ARGS_((Tk_PhotoHandle handle,
- int width, int height ));
-EXTERN void Tk_PhotoGetSize _ANSI_ARGS_((Tk_PhotoHandle handle,
- int *widthPtr, int *heightPtr));
-EXTERN void Tk_PhotoSetSize _ANSI_ARGS_((Tk_PhotoHandle handle,
- int width, int height));
-EXTERN int Tk_PointToChar _ANSI_ARGS_((Tk_TextLayout layout,
- int x, int y));
-EXTERN int Tk_PostscriptFontName _ANSI_ARGS_((Tk_Font tkfont,
- Tcl_DString *dsPtr));
-EXTERN void Tk_PreserveColormap _ANSI_ARGS_((Display *display,
- Colormap colormap));
-EXTERN void Tk_QueueWindowEvent _ANSI_ARGS_((XEvent *eventPtr,
- Tcl_QueuePosition position));
-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_ResizeWindow _ANSI_ARGS_((Tk_Window tkwin,
- int width, int height));
-EXTERN int Tk_RestackWindow _ANSI_ARGS_((Tk_Window tkwin,
- int aboveBelow, Tk_Window other));
-EXTERN Tk_RestrictProc *Tk_RestrictEvents _ANSI_ARGS_((Tk_RestrictProc *proc,
- ClientData arg, ClientData *prevArgPtr));
-EXTERN int Tk_SafeInit _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN char * Tk_SetAppName _ANSI_ARGS_((Tk_Window tkwin,
- char *name));
-EXTERN void Tk_SetBackgroundFromBorder _ANSI_ARGS_((
- Tk_Window tkwin, Tk_3DBorder border));
-EXTERN void Tk_SetClass _ANSI_ARGS_((Tk_Window tkwin,
- char *className));
-EXTERN void Tk_SetGrid _ANSI_ARGS_((Tk_Window tkwin,
- int reqWidth, int reqHeight, int gridWidth,
- int gridHeight));
-EXTERN void Tk_SetInternalBorder _ANSI_ARGS_((Tk_Window tkwin,
- int width));
-EXTERN void Tk_SetWindowBackground _ANSI_ARGS_((Tk_Window tkwin,
- unsigned long pixel));
-EXTERN void Tk_SetWindowBackgroundPixmap _ANSI_ARGS_((
- Tk_Window tkwin, Pixmap pixmap));
-EXTERN void Tk_SetWindowBorder _ANSI_ARGS_((Tk_Window tkwin,
- unsigned long pixel));
-EXTERN void Tk_SetWindowBorderWidth _ANSI_ARGS_((Tk_Window tkwin,
- int width));
-EXTERN void Tk_SetWindowBorderPixmap _ANSI_ARGS_((Tk_Window tkwin,
- Pixmap pixmap));
-EXTERN void Tk_SetWindowColormap _ANSI_ARGS_((Tk_Window tkwin,
- Colormap colormap));
-EXTERN int Tk_SetWindowVisual _ANSI_ARGS_((Tk_Window tkwin,
- Visual *visual, int depth,
- Colormap colormap));
-EXTERN void Tk_SizeOfBitmap _ANSI_ARGS_((Display *display,
- Pixmap bitmap, int *widthPtr,
- int *heightPtr));
-EXTERN void Tk_SizeOfImage _ANSI_ARGS_((Tk_Image image,
- int *widthPtr, int *heightPtr));
-EXTERN int Tk_StrictMotif _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void Tk_TextLayoutToPostscript _ANSI_ARGS_((
- Tcl_Interp *interp, Tk_TextLayout layout));
-EXTERN int Tk_TextWidth _ANSI_ARGS_((Tk_Font font,
- CONST char *string, int numChars));
-EXTERN void Tk_UndefineCursor _ANSI_ARGS_((Tk_Window window));
-EXTERN void Tk_UnderlineChars _ANSI_ARGS_((Display *display,
- Drawable drawable, GC gc, Tk_Font tkfont,
- CONST char *source, int x, int y, int firstChar,
- int lastChar));
-EXTERN void Tk_UnderlineTextLayout _ANSI_ARGS_((
- Display *display, Drawable drawable, GC gc,
- Tk_TextLayout layout, int x, int y,
- int underline));
-EXTERN void Tk_Ungrab _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void Tk_UnmaintainGeometry _ANSI_ARGS_((Tk_Window slave,
- Tk_Window master));
-EXTERN void Tk_UnmapWindow _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void Tk_UnsetGrid _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void Tk_UpdatePointer _ANSI_ARGS_((Tk_Window tkwin,
- int x, int y, int state));
+#include "tkDecls.h"
/*
* Tcl commands exported by Tk:
*/
-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_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_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_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_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_FontObjCmd _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, Tcl_Obj *CONST objv[]));
-EXTERN int Tk_LabelCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-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_MessageCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_OptionCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-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_RaiseCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_ScaleCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_ScrollbarCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-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_TextCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-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_WinfoObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
-EXTERN int Tk_WmCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
#endif /* RESOURCE_INCLUDED */
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
+/*
+ * end block for C++
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _TK */
+
+
diff --git a/tk/generic/tk3d.c b/tk/generic/tk3d.c
index 62139b5e333..3073d2dfcbd 100644
--- a/tk/generic/tk3d.c
+++ b/tk/generic/tk3d.c
@@ -13,33 +13,150 @@
* RCS: @(#) $Id$
*/
-#include <tk3d.h>
+#include "tk3d.h"
/*
- * Hash table to map from a border's values (color, etc.) to a
- * Border structure for those values.
+ * The following table defines the string values for reliefs, which are
+ * used by Tk_GetReliefFromObj.
*/
-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. */
+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 BorderInit _ANSI_ARGS_((TkDisplay *dispPtr));
+static void DupBorderObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr));
+static void FreeBorderObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
static int Intersect _ANSI_ARGS_((XPoint *a1Ptr, XPoint *a2Ptr,
XPoint *b1Ptr, XPoint *b2Ptr, XPoint *iPtr));
+static void InitBorderObj _ANSI_ARGS_((Tcl_Obj *objPtr));
static void ShiftLine _ANSI_ARGS_((XPoint *p1Ptr, XPoint *p2Ptr,
int distance, XPoint *p3Ptr));
+
+/*
+ * 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_Alloc3DBorderFromObj --
+ *
+ * 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 FreeBorderObjProc so that the database is
+ * cleaned up when borders aren't in use anymore.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tk_3DBorder
+Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr)
+ Tcl_Interp *interp; /* Interp for error results. */
+ Tk_Window tkwin; /* Need the screen the border is used on.*/
+ Tcl_Obj *objPtr; /* Object giving name of color for window
+ * 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 +166,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,71 +185,75 @@ 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;
+ TkDisplay *dispPtr;
- if (!initialized) {
- BorderInit();
- }
-
- /*
- * First, check to see if there's already a border that will work
- * for this request.
- */
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
- key.colorName = colorName;
- key.colormap = Tk_Colormap(tkwin);
- key.screen = Tk_Screen(tkwin);
+ if (!dispPtr->borderInit) {
+ BorderInit(dispPtr);
+ }
- hashPtr = Tcl_CreateHashEntry(&borderTable, (char *) &key, &new);
+ hashPtr = Tcl_CreateHashEntry(&dispPtr->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_GetGCColor(tkwin, GCForeground, &gcValues,
- borderPtr->bgColorPtr, NULL);
+ 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;
}
@@ -209,7 +329,7 @@ Tk_NameOf3DBorder(border)
{
TkBorder *borderPtr = (TkBorder *) border;
- return ((BorderKey *) borderPtr->hashPtr->key.words)->colorName;
+ return borderPtr->hashPtr->key.string;
}
/*
@@ -304,34 +424,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);
}
}
@@ -339,6 +476,106 @@ 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(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
@@ -366,6 +603,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
@@ -408,8 +674,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;
@@ -707,6 +976,17 @@ Tk_Fill3DRectangle(tkwin, drawable, border, x, y, width,
if (relief == TK_RELIEF_FLAT) {
borderWidth = 0;
+ } else {
+ /*
+ * We need to make this extra check, otherwise we will leave
+ * garbage in thin frames [Bug: 3596]
+ */
+ if (width < 2*borderWidth) {
+ borderWidth = width/2;
+ }
+ if (height < 2*borderWidth) {
+ borderWidth = height/2;
+ }
}
doubleBorder = 2*borderWidth;
@@ -783,10 +1063,11 @@ Tk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints,
*/
static void
-BorderInit()
+BorderInit(dispPtr)
+ TkDisplay * dispPtr; /* Used to access thread-specific data. */
{
- initialized = 1;
- Tcl_InitHashTable(&borderTable, sizeof(BorderKey)/sizeof(int));
+ dispPtr->borderInit = 1;
+ Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS);
}
/*
@@ -948,3 +1229,181 @@ 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (objPtr->typePtr != &borderObjType) {
+ InitBorderObj(objPtr);
+ }
+
+ /*
+ * If we are lucky (and the user doesn't use too many different
+ * displays, screens, or colormaps...) then the TkBorder
+ * structure we need will be cached in the internal
+ * representation of the Tcl_Obj. Check it out...
+ */
+
+ borderPtr = (TkBorder *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((borderPtr != NULL)
+ && (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;
+ }
+
+ /*
+ * If we make it here, it means we aren't so lucky. Either there
+ * was no cached TkBorder in the Tcl_Obj, or the TkBorder that was
+ * there is for the wrong screen/colormap. Either way, we have
+ * to search for the right TkBorder. For each color name, there is
+ * linked list of TkBorder structures, one structure for each
+ * screen/colormap combination. The head of the linked list is
+ * recorded in a hash table (where the key is the color name)
+ * attached to the TkDisplay structure. Walk this list to find
+ * the right TkBorder structure.
+ */
+
+ hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ for (borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr);
+ (borderPtr != NULL); borderPtr = borderPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == borderPtr->screen)
+ && (Tk_Colormap(tkwin) == borderPtr->colormap)) {
+ FreeBorderObjProc(objPtr);
+ 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->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/tk/generic/tk3d.h b/tk/generic/tk3d.h
index 71115f2cf5f..c62cf12de5a 100644
--- a/tk/generic/tk3d.h
+++ b/tk/generic/tk3d.h
@@ -4,7 +4,7 @@
* 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.
@@ -23,13 +23,13 @@
#endif
/*
- * 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. */
@@ -37,8 +37,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). */
@@ -63,6 +73,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;
@@ -85,3 +100,4 @@ EXTERN void TkpFreeBorder _ANSI_ARGS_((TkBorder *borderPtr));
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TK3D */
+
diff --git a/tk/generic/tkArgv.c b/tk/generic/tkArgv.c
index b44939ed7c4..ee86ad75cd4 100644
--- a/tk/generic/tkArgv.c
+++ b/tk/generic/tkArgv.c
@@ -5,7 +5,7 @@
* 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.
@@ -24,8 +24,8 @@
static Tk_ArgvInfo defaultTable[] = {
{"-help", TK_ARGV_HELP, (char *) NULL, (char *) NULL,
"Print summary of command-line options and abort"},
- {"-version", TK_ARGV_VERSION, (char *) NULL, (char *) NULL,
- "Print version number and abort"},
+ {"-version", TK_ARGV_VERSION, (char *) NULL, (char *) NULL,
+ "Print version number and abort"},
{NULL, TK_ARGV_END, (char *) NULL, (char *) NULL,
(char *) NULL}
};
@@ -47,7 +47,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
@@ -294,13 +294,17 @@ Tk_ParseArgv(interp, tkwin, argcPtr, argv, argTable, flags)
argc -= 2;
break;
case TK_ARGV_VERSION:
- Tcl_AppendResult(interp, "Tk version ", TK_VERSION, "-foundry-971110",
+ Tcl_AppendResult(interp, "Tk version ", TK_VERSION, "-snavigator-99r1",
(char *) NULL);
return TCL_ERROR;
- 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;
+ }
}
}
@@ -334,7 +338,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.
@@ -359,7 +363,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
@@ -437,3 +441,4 @@ PrintUsage(interp, argTable, flags)
(char *) NULL);
}
}
+
diff --git a/tk/generic/tkAtom.c b/tk/generic/tkAtom.c
index 7bd2a1e80ff..45260d940e0 100644
--- a/tk/generic/tkAtom.c
+++ b/tk/generic/tkAtom.c
@@ -215,3 +215,4 @@ AtomInit(dispPtr)
}
}
}
+
diff --git a/tk/generic/tkBind.c b/tk/generic/tkBind.c
index 38a39b7e5b1..233f3c308c4 100644
--- a/tk/generic/tkBind.c
+++ b/tk/generic/tkBind.c
@@ -5,18 +5,22 @@
* 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.
* Copyright (c) 1998 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id$
+ * RCS: @(#) $Id$
*/
#include "tkPort.h"
#include "tkInt.h"
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+
/*
* File structure:
*
@@ -340,6 +344,8 @@ typedef struct BindInfo {
PendingBinding *pendingList;/* The list of pending C bindings, kept in
* case a C or Tcl binding causes the target
* window to be deleted. */
+ int deleted; /* 1 the application has been deleted but
+ * the structure has been preserved. */
} BindInfo;
/*
@@ -374,6 +380,7 @@ static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */
*/
static int initialized = 0;
+TCL_DECLARE_MUTEX(bindMutex)
/*
* A hash table is kept to map from the string names of event
@@ -396,19 +403,15 @@ typedef struct {
* e.g. for double-clicks.
* TRIPLE - Non-zero means triplicate this event,
* e.g. for triple-clicks.
+ * QUADRUPLE - Non-zero means quadruple this event,
+ * e.g. for 4-fold-clicks.
+ * MULT_CLICKS - Combination of all of above.
*/
#define DOUBLE 1
#define TRIPLE 2
-
-/*
- * The following special modifier mask bits are defined, to indicate
- * logical modifiers such as Meta and Alt that may float among the
- * actual modifier bits.
- */
-
-#define META_MASK (AnyModifier<<1)
-#define ALT_MASK (AnyModifier<<2)
+#define QUADRUPLE 4
+#define MULT_CLICKS 7
static ModInfo modArray[] = {
{"Control", ControlMask, 0},
@@ -441,6 +444,7 @@ static ModInfo modArray[] = {
{"M5", Mod5Mask, 0},
{"Double", 0, DOUBLE},
{"Triple", 0, TRIPLE},
+ {"Quadruple", 0, QUADRUPLE},
{"Any", 0, 0}, /* Ignored: historical relic. */
{NULL, 0, 0}
};
@@ -574,6 +578,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
@@ -638,8 +656,6 @@ static PatSeq * FindSequence _ANSI_ARGS_((Tcl_Interp *interp,
static void GetAllVirtualEvents _ANSI_ARGS_((Tcl_Interp *interp,
VirtualEventTable *vetPtr));
static char * GetField _ANSI_ARGS_((char *p, char *copy, int size));
-static KeySym GetKeySym _ANSI_ARGS_((TkDisplay *dispPtr,
- XEvent *eventPtr));
static void GetPatternString _ANSI_ARGS_((PatSeq *psPtr,
Tcl_DString *dsPtr));
static int GetVirtualEvent _ANSI_ARGS_((Tcl_Interp *interp,
@@ -647,17 +663,21 @@ 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));
-static void InitKeymapInfo _ANSI_ARGS_((TkDisplay *dispPtr));
+ Tk_Window main, int objc,
+ Tcl_Obj *CONST objv[]));
static void InitVirtualEventTable _ANSI_ARGS_((
VirtualEventTable *vetPtr));
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 DoWarp _ANSI_ARGS_((ClientData clientData));
/*
* The following define is used as a short circuit for the callback
@@ -705,37 +725,41 @@ TkBindInit(mainPtr)
*/
if (!initialized) {
- Tcl_HashEntry *hPtr;
- ModInfo *modPtr;
- EventInfo *eiPtr;
- int dummy;
+ Tcl_MutexLock(&bindMutex);
+ if (!initialized) {
+ Tcl_HashEntry *hPtr;
+ ModInfo *modPtr;
+ EventInfo *eiPtr;
+ int dummy;
#ifdef REDO_KEYSYM_LOOKUP
- KeySymInfo *kPtr;
-
- Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS);
- Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS);
- for (kPtr = keyArray; kPtr->name != NULL; kPtr++) {
- hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &dummy);
- Tcl_SetHashValue(hPtr, kPtr->value);
- hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value,
- &dummy);
- Tcl_SetHashValue(hPtr, kPtr->name);
- }
+ KeySymInfo *kPtr;
+
+ Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS);
+ for (kPtr = keyArray; kPtr->name != NULL; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &dummy);
+ Tcl_SetHashValue(hPtr, kPtr->value);
+ hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value,
+ &dummy);
+ Tcl_SetHashValue(hPtr, kPtr->name);
+ }
#endif /* REDO_KEYSYM_LOOKUP */
- Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);
- for (modPtr = modArray; modPtr->name != NULL; modPtr++) {
- hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &dummy);
- Tcl_SetHashValue(hPtr, modPtr);
- }
+ Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);
+ for (modPtr = modArray; modPtr->name != NULL; modPtr++) {
+ hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &dummy);
+ Tcl_SetHashValue(hPtr, modPtr);
+ }
- Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS);
- for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) {
- hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &dummy);
- Tcl_SetHashValue(hPtr, eiPtr);
+ Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS);
+ for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) {
+ hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &dummy);
+ Tcl_SetHashValue(hPtr, eiPtr);
+ }
+ initialized = 1;
}
- initialized = 1;
+ Tcl_MutexUnlock(&bindMutex);
}
mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp);
@@ -746,6 +770,7 @@ TkBindInit(mainPtr)
bindInfoPtr->screenInfo.curScreenIndex = -1;
bindInfoPtr->screenInfo.bindingDepth = 0;
bindInfoPtr->pendingList = NULL;
+ bindInfoPtr->deleted = 0;
mainPtr->bindInfo = (TkBindInfo) bindInfoPtr;
TkpInitializeMenuBindings(mainPtr->interp, mainPtr->bindingTable);
@@ -779,6 +804,8 @@ TkBindFree(mainPtr)
bindInfoPtr = (BindInfo *) mainPtr->bindInfo;
DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable);
+ bindInfoPtr->deleted = 1;
+ Tcl_EventuallyFree((ClientData) bindInfoPtr, Tcl_Free);
mainPtr->bindInfo = NULL;
}
@@ -791,7 +818,7 @@ TkBindFree(mainPtr)
*
* Results:
* The return value is a token for the new table, which must
- * be passed to procedures like Tk_CreatBinding.
+ * be passed to procedures like Tk_CreateBinding.
*
* Side effects:
* Memory is allocated for the new table.
@@ -893,7 +920,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
@@ -998,7 +1025,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
@@ -1082,7 +1109,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
@@ -1177,7 +1204,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:
@@ -1220,7 +1247,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.
@@ -1384,9 +1411,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;
@@ -1496,7 +1523,7 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
detail.clientData = 0;
flags = flagArray[ringPtr->type];
if (flags & KEY) {
- detail.keySym = GetKeySym(dispPtr, ringPtr);
+ detail.keySym = TkpGetKeySym(dispPtr, ringPtr);
if (detail.keySym == NoSymbol) {
detail.keySym = 0;
}
@@ -1617,12 +1644,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) {
@@ -1653,7 +1680,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,
@@ -1684,6 +1711,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;
@@ -1703,10 +1737,20 @@ 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.
+ */
+
+ Tcl_Preserve((ClientData) bindInfoPtr);
while (p < end) {
int code;
- screenPtr->bindingDepth++;
+ if (!bindInfoPtr->deleted) {
+ screenPtr->bindingDepth++;
+ }
Tcl_AllowExceptions(interp);
if (*p == '\0') {
@@ -1732,7 +1776,10 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
p += strlen(p);
}
p++;
- screenPtr->bindingDepth--;
+
+ if (!bindInfoPtr->deleted) {
+ screenPtr->bindingDepth--;
+ }
if (code != TCL_OK) {
if (code == TCL_CONTINUE) {
/*
@@ -1762,8 +1809,8 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
}
}
- if ((screenPtr->bindingDepth != 0) &&
- ((oldDispPtr != screenPtr->curDispPtr)
+ if (!bindInfoPtr->deleted && (screenPtr->bindingDepth != 0)
+ && ((oldDispPtr != screenPtr->curDispPtr)
|| (oldScreen != screenPtr->curScreenIndex))) {
/*
@@ -1780,19 +1827,27 @@ Tk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)
Tcl_DStringFree(&scripts);
if (matchCount > 0) {
- PendingBinding **curPtrPtr;
+ if (!bindInfoPtr->deleted) {
+ /*
+ * 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);
}
}
+ Tcl_Release((ClientData) bindInfoPtr);
}
/*
@@ -2016,6 +2071,14 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr)
if ((modMask & ALT_MASK) && (dispPtr->altModMask != 0)) {
modMask = (modMask & ~ALT_MASK) | dispPtr->altModMask;
}
+
+ if ((state & META_MASK) && (dispPtr->metaModMask != 0)) {
+ state = (state & ~META_MASK) | dispPtr->metaModMask;
+ }
+ if ((state & ALT_MASK) && (dispPtr->altModMask != 0)) {
+ state = (state & ~ALT_MASK) | dispPtr->altModMask;
+ }
+
if ((state & modMask) != modMask) {
goto nextSequence;
}
@@ -2167,7 +2230,8 @@ MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr)
bestPtr = matchPtr;
bestSourcePtr = sourcePtr;
- nextSequence: continue;
+ nextSequence:
+ continue;
}
*sourcePtrPtr = bestSourcePtr;
@@ -2211,8 +2275,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 {
@@ -2246,8 +2313,10 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr)
number = eventPtr->xany.serial;
goto doNumber;
case 'a':
- TkpPrintWindowId(numStorage, eventPtr->xconfigure.above);
- string = numStorage;
+ if (flags & CONFIG) {
+ TkpPrintWindowId(numStorage, eventPtr->xconfigure.above);
+ string = numStorage;
+ }
goto doString;
case 'b':
number = eventPtr->xbutton.button;
@@ -2361,37 +2430,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':
@@ -2492,6 +2532,7 @@ ExpandPercents(winPtr, before, eventPtr, keySym, dsPtr)
Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
before += 2;
}
+ Tcl_DStringFree(&buf);
}
/*
@@ -2524,7 +2565,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);
@@ -2558,87 +2599,96 @@ 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);
}
- 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;
+ }
}
- } else {
- badopt:
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": should be add, delete, generate, info", (char *) NULL);
- return TCL_ERROR;
}
return TCL_OK;
}
@@ -2725,8 +2775,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
@@ -2831,7 +2881,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.
*
@@ -2883,7 +2933,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;
}
}
@@ -2924,7 +2977,7 @@ DeleteVirtualEvent(interp, vetPtr, virtString, eventString)
} else {
for ( ; ; prevPtr = prevPtr->nextSeqPtr) {
if (prevPtr == NULL) {
- panic("Tk_DeleteVirtualEvent couldn't find on hash chain");
+ panic("DeleteVirtualEvent couldn't find on hash chain");
}
if (prevPtr->nextSeqPtr == psPtr) {
prevPtr->nextSeqPtr = psPtr->nextSeqPtr;
@@ -2985,12 +3038,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.
@@ -3042,7 +3095,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.
*
@@ -3111,56 +3164,75 @@ GetAllVirtualEvents(interp, vetPtr)
*---------------------------------------------------------------------------
*/
static int
-HandleEventGenerate(interp, mainwin, argc, argv)
- Tcl_Interp *interp; /* Interp for error messages and name lookup. */
- Tk_Window mainwin; /* Main window associated with interp. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+HandleEventGenerate(interp, mainWin, objc, objv)
+ Tcl_Interp *interp; /* Interp for errors return and name lookup. */
+ Tk_Window mainWin; /* Main window associated with interp. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
+ XEvent event;
+ char *name, *p, *windowName;
+ int count, flags, synch, i, number, warp;
+ 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", "-delta", "-detail", "-focus",
+ "-height",
+ "-keycode", "-keysym", "-mode", "-override",
+ "-place", "-root", "-rootx", "-rooty",
+ "-sendevent", "-serial", "-state", "-subwindow",
+ "-time", "-warp", "-width", "-window",
+ "-x", "-y", NULL
+ };
+ enum field {
+ EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON,
+ EVENT_COUNT, EVENT_DELTA, EVENT_DETAIL, EVENT_FOCUS,
+ EVENT_HEIGHT,
+ EVENT_KEYCODE, EVENT_KEYSYM, EVENT_MODE, EVENT_OVERRIDE,
+ EVENT_PLACE, EVENT_ROOT, EVENT_ROOTX, EVENT_ROOTY,
+ EVENT_SEND, EVENT_SERIAL, EVENT_STATE, EVENT_SUBWINDOW,
+ EVENT_TIME, EVENT_WARP, EVENT_WIDTH, EVENT_WINDOW,
+ EVENT_X, EVENT_Y
+ };
+
+ windowName = Tcl_GetStringFromObj(objv[0], NULL);
+ if (!windowName[0]) {
+ tkwin = mainWin;
+ } else if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) {
+ return TCL_ERROR;
+ }
- if (argv[0][0] == '.') {
- tkwin = Tk_NameToWindow(interp, argv[0], mainwin);
- 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(mainwin), (Window) i);
- if ((tkwin == NULL) || (((TkWindow *) mainwin)->mainPtr
- != ((TkWindow *) tkwin)->mainPtr)) {
- Tcl_AppendResult(interp, "window id \"", argv[0],
- "\" doesn't exist in this application", (char *) NULL);
- return TCL_ERROR;
- }
+ mainPtr = (TkWindow *) mainWin;
+ if ((tkwin == NULL)
+ || (mainPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
+ char *name;
+
+ name = Tcl_GetStringFromObj(objv[0], NULL);
+ Tcl_AppendResult(interp, "window id \"", name,
+ "\" doesn't exist in this application", (char *) NULL);
+ return TCL_ERROR;
}
- p = argv[1];
+ name = Tcl_GetStringFromObj(objv[1], NULL);
+
+ p = name;
+ eventMask = 0;
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;
}
@@ -3168,41 +3240,18 @@ HandleEventGenerate(interp, mainwin, argc, argv)
event.xany.type = pat.eventType;
event.xany.serial = NextRequest(Tk_Display(tkwin));
event.xany.send_event = False;
- event.xany.window = Tk_WindowId(tkwin);
+ if (windowName[0]) {
+ event.xany.window = Tk_WindowId(tkwin);
+ } else {
+ event.xany.window = RootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
+ }
event.xany.display = Tk_Display(tkwin);
flags = flagArray[event.xany.type];
if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) {
event.xkey.state = pat.needMods;
if ((flags & KEY) && (event.xany.type != MouseWheelEvent)) {
- /*
- * 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;
- }
- }
- }
+ TkpSetKeycodeAndState(tkwin, pat.detail.keySym, &event);
} else if (flags & BUTTON) {
event.xbutton.button = pat.detail.button;
} else if (flags & VIRTUAL) {
@@ -3219,383 +3268,495 @@ HandleEventGenerate(interp, mainwin, argc, argv)
*/
synch = 1;
+ warp = 0;
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;
- synch = 0;
- } else {
- Tcl_AppendResult(interp, "bad position \"", value,
- "\": should be now, head, mark, tail", (char *) NULL);
- return TCL_ERROR;
- }
- } else if (strcmp(field, "-above") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, mainwin);
- if (tkwin2 == NULL) {
- 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 & (CREATE|CONFIG)) {
- event.xcreatewindow.border_width = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-button") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & BUTTON) {
- event.xbutton.button = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-count") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & EXPOSE) {
- event.xexpose.count = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-delta") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if ((flags & KEY) && (event.xkey.type == MouseWheelEvent)) {
- event.xkey.keycode = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-detail") == 0) {
- number = TkFindStateNum(interp, field, notifyDetail, value);
- if (number < 0) {
- return TCL_ERROR;
- }
- if (flags & FOCUS) {
- event.xfocus.detail = number;
- } else if (flags & CROSSING) {
- event.xcrossing.detail = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-focus") == 0) {
- if (Tcl_GetBoolean(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & CROSSING) {
- event.xcrossing.focus = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-height") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if (flags & EXPOSE) {
- event.xexpose.height = number;
- } else if (flags & CONFIG) {
- event.xconfigure.height = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-keycode") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
- }
- if ((flags & KEY) && (event.xkey.type != MouseWheelEvent)) {
- event.xkey.keycode = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-keysym") == 0) {
- keysym = TkStringToKeysym(value);
- if (keysym == NoSymbol) {
- Tcl_AppendResult(interp, "unknown keysym \"", value,
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
+ 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) {
/*
- * 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.
+ * 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.
*/
- 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;
- }
- if (state & 2) {
- TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- event.xkey.state |= dispPtr->modeModMask;
- }
- break;
+ Tcl_AppendResult(interp, "value for \"",
+ Tcl_GetStringFromObj(optionPtr, NULL), "\" missing",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ switch ((enum field) index) {
+ case EVENT_WARP: {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) {
+ return TCL_ERROR;
}
- }
- if ((flags & KEY) && (event.xkey.type != MouseWheelEvent)) {
- 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;
+ if (!(flags & (KEY_BUTTON_MOTION_VIRTUAL))) {
+ goto badopt;
+ }
+ break;
}
- } else if (strcmp(field, "-override") == 0) {
- if (Tcl_GetBoolean(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_WHEN: {
+ pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr,
+ queuePosition, valuePtr);
+ if ((int) pos < -1) {
+ return TCL_ERROR;
+ }
+ synch = 0;
+ if ((int) pos == -1) {
+ synch = 1;
+ }
+ break;
}
- if (flags & 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;
+ case EVENT_ABOVE: {
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & CONFIG) {
+ event.xconfigure.above = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
}
- } else if (strcmp(field, "-place") == 0) {
- number = TkFindStateNum(interp, field, circPlace, value);
- if (number < 0) {
- return TCL_ERROR;
+ case EVENT_BORDER: {
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & (CREATE|CONFIG)) {
+ event.xcreatewindow.border_width = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- if (flags & CIRC) {
- event.xcirculate.place = number;
- } else {
- goto badopt;
+ 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;
}
- } else if (strcmp(field, "-root") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, mainwin);
- if (tkwin2 == NULL) {
+ case EVENT_COUNT: {
+ 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 & EXPOSE) {
+ event.xexpose.count = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.root = number;
- } else {
- goto badopt;
+ case EVENT_DELTA: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((flags & KEY) && (event.xkey.type == MouseWheelEvent)) {
+ event.xkey.keycode = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- } else if (strcmp(field, "-rootx") == 0) {
- if (Tk_GetPixels(interp, tkwin, 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 & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.x_root = 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, "-rooty") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_HEIGHT: {
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & EXPOSE) {
+ event.xexpose.height = number;
+ } else if (flags & CONFIG) {
+ event.xconfigure.height = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.y_root = number;
- } else {
- goto badopt;
+ case EVENT_KEYCODE: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((flags & KEY) && (event.xkey.type != MouseWheelEvent)) {
+ event.xkey.keycode = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- } 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_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;
}
- } else {
- if (Tcl_GetBoolean(interp, value, &number) != TCL_OK) {
+
+ TkpSetKeycodeAndState(tkwin, keysym, &event);
+ if (event.xkey.keycode == 0) {
+ Tcl_AppendResult(interp, "no keycode for keysym \"", value,
+ "\"", (char *) NULL);
return TCL_ERROR;
}
+ if (!(flags & KEY) || (event.xkey.type == MouseWheelEvent)) {
+ goto badopt;
+ }
+ break;
}
- event.xany.send_event = number;
- } else if (strcmp(field, "-serial") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_MODE: {
+ number = TkFindStateNumObj(interp, optionPtr, notifyMode,
+ valuePtr);
+ if (number < 0) {
+ return TCL_ERROR;
+ }
+ if (flags & CROSSING) {
+ event.xcrossing.mode = number;
+ } else if (flags & FOCUS) {
+ event.xfocus.mode = number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- 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_OVERRIDE: {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &number) != TCL_OK) {
return TCL_ERROR;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) {
- event.xkey.state = number;
+ 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 {
- event.xcrossing.state = number;
+ goto badopt;
}
- } else if (flags & VISIBILITY) {
- number = TkFindStateNum(interp, field, visNotify, value);
+ break;
+ }
+ case EVENT_PLACE: {
+ number = TkFindStateNumObj(interp, optionPtr, circPlace,
+ valuePtr);
if (number < 0) {
return TCL_ERROR;
}
- event.xvisibility.state = number;
- } else {
- goto badopt;
- }
- } else if (strcmp(field, "-subwindow") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, mainwin);
- if (tkwin2 == NULL) {
+ if (flags & CIRC) {
+ event.xcirculate.place = number;
+ } else {
+ goto badopt;
+ }
+ break;
+ }
+ case EVENT_ROOT: {
+ 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 & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.root = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.subwindow = 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, "-time") == 0) {
- if (Tcl_GetInt(interp, value, &number) != TCL_OK) {
- 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;
}
- if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
- event.xkey.time = (Time) number;
- } else if (flags & PROP) {
- event.xproperty.time = (Time) number;
- } else {
- goto badopt;
+ case EVENT_SEND: {
+ CONST char *value;
+
+ value = Tcl_GetStringFromObj(valuePtr, NULL);
+ if (isdigit(UCHAR(value[0]))) {
+ /*
+ * Allow arbitrary integer values for the field; they
+ * are needed by a few of the tests in the Tk test suite.
+ */
+
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &number)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ event.xany.send_event = number;
+ break;
}
- } else if (strcmp(field, "-width") == 0) {
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_SERIAL: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ event.xany.serial = number;
+ break;
}
- if (flags & EXPOSE) {
- event.xexpose.width = number;
- } else if (flags & (CREATE|CONFIG)) {
- event.xcreatewindow.width = 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, "-window") == 0) {
- if (value[0] == '.') {
- tkwin2 = Tk_NameToWindow(interp, value, mainwin);
- if (tkwin2 == NULL) {
+ case EVENT_SUBWINDOW: {
+ 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 & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.subwindow = Tk_WindowId(tkwin2);
+ } else {
+ goto badopt;
+ }
+ break;
}
- if (flags & (CREATE|DESTROY|UNMAP|MAP|REPARENT|CONFIG
- |GRAVITY|CIRC)) {
- event.xcreatewindow.window = number;
- } else {
- goto badopt;
+ case EVENT_TIME: {
+ if (Tcl_GetIntFromObj(interp, valuePtr, &number) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) {
+ event.xkey.time = (Time) number;
+ } else if (flags & PROP) {
+ event.xproperty.time = (Time) number;
+ } else {
+ goto badopt;
+ }
+ break;
}
- } else if (strcmp(field, "-x") == 0) {
- int rootX, rootY;
- if (Tk_GetPixels(interp, tkwin, value, &number) != TCL_OK) {
- return TCL_ERROR;
+ case EVENT_WIDTH: {
+ if (Tk_GetPixelsFromObj(interp, tkwin, valuePtr, &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;
}
- 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;
+ case EVENT_WINDOW: {
+ if (NameToWindow(interp, tkwin, valuePtr, &tkwin2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ 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 {
Tk_QueueWindowEvent(&event, pos);
}
+ /*
+ * We only allow warping if the window is mapped
+ */
+ if ((warp != 0) && Tk_IsMapped(tkwin)) {
+ TkDisplay *dispPtr;
+ dispPtr = TkGetDisplay(event.xmotion.display);
+ if (!dispPtr->warpInProgress) {
+ Tcl_DoWhenIdle(DoWarp, (ClientData) dispPtr);
+ dispPtr->warpInProgress = 1;
+ }
+ dispPtr->warpWindow = event.xany.window;
+ dispPtr->warpX = event.xkey.x;
+ dispPtr->warpY = event.xkey.y;
+ }
Tcl_ResetResult(interp);
return TCL_OK;
+
+}
+static int
+NameToWindow(interp, mainWin, objPtr, tkwinPtr)
+ Tcl_Interp *interp; /* Interp for error return and name lookup. */
+ Tk_Window mainWin; /* Main window of application. */
+ Tcl_Obj *objPtr; /* Contains name or id string of window. */
+ Tk_Window *tkwinPtr; /* Filled with token for window. */
+{
+ char *name;
+ Tk_Window tkwin;
+ int id;
+
+ name = Tcl_GetStringFromObj(objPtr, NULL);
+ if (name[0] == '.') {
+ tkwin = Tk_NameToWindow(interp, name, mainWin);
+ 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(mainWin), (Window) id);
+ }
+ return TCL_OK;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
+ * DoWarp --
+ *
+ * Perform Warping of X pointer. Executed as an idle handler only.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * X Pointer will move to a new location.
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+DoWarp(clientData)
+ ClientData clientData;
+{
+ TkDisplay *dispPtr = (TkDisplay *) clientData;
+
+ XWarpPointer(dispPtr->display, (Window) None, (Window) dispPtr->warpWindow,
+ 0, 0, 0, 0, (int) dispPtr->warpX, (int) dispPtr->warpY);
+ XForceScreenSaver(dispPtr->display, ScreenSaverReset);
+ dispPtr->warpInProgress = 0;
}
/*
@@ -3609,7 +3770,7 @@ HandleEventGenerate(interp, mainwin, 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:
@@ -3655,7 +3816,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
@@ -3731,27 +3892,23 @@ 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;
}
/*
- * Replicate events for DOUBLE and TRIPLE.
+ * Replicate events for DOUBLE, TRIPLE, QUADRUPLE.
*/
- if ((count > 1) && (numPats < EVENT_BUFFER_SIZE-1)) {
+ while ((count-- > 1) && (numPats < EVENT_BUFFER_SIZE-1)) {
flags |= PAT_NEARBY;
patPtr[-1] = patPtr[0];
patPtr--;
numPats++;
- if ((count == 3) && (numPats < EVENT_BUFFER_SIZE-1)) {
- patPtr[-1] = patPtr[0];
- patPtr--;
- numPats++;
- }
}
}
@@ -3763,11 +3920,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;
}
@@ -3793,6 +3951,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)
@@ -3882,8 +4048,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;
}
}
@@ -3923,11 +4091,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';
@@ -3957,12 +4127,10 @@ ParseEventDescription(interp, eventStringPtr, patPtr,
}
modPtr = (ModInfo *) Tcl_GetHashValue(hPtr);
patPtr->needMods |= modPtr->mask;
- if (modPtr->flags & (DOUBLE|TRIPLE)) {
- if (modPtr->flags & DOUBLE) {
- count = 2;
- } else {
- count = 3;
- }
+ if (modPtr->flags & (MULT_CLICKS)) {
+ int i = modPtr->flags & MULT_CLICKS;
+ count = 2;
+ while (i >>= 1) count++;
}
while ((*p == '-') || isspace(UCHAR(*p))) {
p++;
@@ -4014,7 +4182,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;
}
@@ -4025,11 +4194,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++;
@@ -4104,7 +4275,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;
@@ -4147,8 +4318,8 @@ GetPatternString(psPtr, dsPtr)
/*
* It's a more general event specification. First check
- * for "Double" or "Triple", then modifiers, then event type,
- * then keysym or button detail.
+ * for "Double", "Triple", "Quadruple", then modifiers,
+ * then event type, then keysym or button detail.
*/
Tcl_DStringAppend(dsPtr, "<", 1);
@@ -4161,7 +4332,14 @@ GetPatternString(psPtr, dsPtr)
(char *) (patPtr-1), sizeof(Pattern)) == 0)) {
patsLeft--;
patPtr--;
- Tcl_DStringAppend(dsPtr, "Triple-", 7);
+ if ((patsLeft > 1) && (memcmp((char *) patPtr,
+ (char *) (patPtr-1), sizeof(Pattern)) == 0)) {
+ patsLeft--;
+ patPtr--;
+ Tcl_DStringAppend(dsPtr, "Quadruple-", 10);
+ } else {
+ Tcl_DStringAppend(dsPtr, "Triple-", 7);
+ }
} else {
Tcl_DStringAppend(dsPtr, "Double-", 7);
}
@@ -4203,220 +4381,6 @@ GetPatternString(psPtr, dsPtr)
}
/*
- *----------------------------------------------------------------------
- *
- * GetKeySym --
- *
- * Given an X KeyPress or KeyRelease event, map the
- * keycode in the event into a KeySym.
- *
- * Results:
- * The return value is the KeySym corresponding to
- * eventPtr, or NoSymbol if no matching Keysym could be
- * found.
- *
- * Side effects:
- * In the first call for a given display, keycode-to-
- * KeySym maps get loaded.
- *
- *----------------------------------------------------------------------
- */
-
-static KeySym
-GetKeySym(dispPtr, eventPtr)
- TkDisplay *dispPtr; /* Display in which to
- * map keycode. */
- XEvent *eventPtr; /* Description of X event. */
-{
- KeySym sym;
- int index;
-
- /*
- * Refresh the mapping information if it's stale
- */
-
- if (dispPtr->bindInfoStale) {
- InitKeymapInfo(dispPtr);
- }
-
- /*
- * Figure out which of the four slots in the keymap vector to
- * use for this key. Refer to Xlib documentation for more info
- * on how this computation works.
- */
-
- index = 0;
- if (eventPtr->xkey.state & dispPtr->modeModMask) {
- index = 2;
- }
- if ((eventPtr->xkey.state & ShiftMask)
- || ((dispPtr->lockUsage != LU_IGNORE)
- && (eventPtr->xkey.state & LockMask))) {
- index += 1;
- }
- sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
-
- /*
- * Special handling: if the key was shifted because of Lock, but
- * lock is only caps lock, not shift lock, and the shifted keysym
- * isn't upper-case alphabetic, then switch back to the unshifted
- * keysym.
- */
-
- if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
- && (dispPtr->lockUsage == LU_CAPS)) {
- if (!(((sym >= XK_A) && (sym <= XK_Z))
- || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
- || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
- index &= ~1;
- sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
- index);
- }
- }
-
- /*
- * Another bit of special handling: if this is a shifted key and there
- * is no keysym defined, then use the keysym for the unshifted key.
- */
-
- if ((index & 1) && (sym == NoSymbol)) {
- sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
- index & ~1);
- }
- return sym;
-}
-
-/*
- *--------------------------------------------------------------
- *
- * InitKeymapInfo --
- *
- * This procedure is invoked to scan keymap information
- * to recompute stuff that's important for binding, such
- * as the modifier key (if any) that corresponds to "mode
- * switch".
- *
- * Results:
- * None.
- *
- * Side effects:
- * Keymap-related information in dispPtr is updated.
- *
- *--------------------------------------------------------------
- */
-
-static void
-InitKeymapInfo(dispPtr)
- TkDisplay *dispPtr; /* Display for which to recompute keymap
- * information. */
-{
- XModifierKeymap *modMapPtr;
- KeyCode *codePtr;
- KeySym keysym;
- int count, i, j, max, arraySize;
-#define KEYCODE_ARRAY_SIZE 20
-
- dispPtr->bindInfoStale = 0;
- modMapPtr = XGetModifierMapping(dispPtr->display);
-
- /*
- * Check the keycodes associated with the Lock modifier. If
- * any of them is associated with the XK_Shift_Lock modifier,
- * then Lock has to be interpreted as Shift Lock, not Caps Lock.
- */
-
- dispPtr->lockUsage = LU_IGNORE;
- codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
- for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
- keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
- if (keysym == XK_Shift_Lock) {
- dispPtr->lockUsage = LU_SHIFT;
- break;
- }
- if (keysym == XK_Caps_Lock) {
- dispPtr->lockUsage = LU_CAPS;
- break;
- }
- }
-
- /*
- * Look through the keycodes associated with modifiers to see if
- * the the "mode switch", "meta", or "alt" keysyms are associated
- * with any modifiers. If so, remember their modifier mask bits.
- */
-
- dispPtr->modeModMask = 0;
- dispPtr->metaModMask = 0;
- dispPtr->altModMask = 0;
- codePtr = modMapPtr->modifiermap;
- max = 8*modMapPtr->max_keypermod;
- for (i = 0; i < max; i++, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
- keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
- if (keysym == XK_Mode_switch) {
- dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
- dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
- dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- }
-
- /*
- * Create an array of the keycodes for all modifier keys.
- */
-
- if (dispPtr->modKeyCodes != NULL) {
- ckfree((char *) dispPtr->modKeyCodes);
- }
- dispPtr->numModKeyCodes = 0;
- arraySize = KEYCODE_ARRAY_SIZE;
- dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
- (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
- for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
-
- /*
- * Make sure that the keycode isn't already in the array.
- */
-
- for (j = 0; j < dispPtr->numModKeyCodes; j++) {
- if (dispPtr->modKeyCodes[j] == *codePtr) {
- goto nextModCode;
- }
- }
- if (dispPtr->numModKeyCodes >= arraySize) {
- KeyCode *new;
-
- /*
- * Ran out of space in the array; grow it.
- */
-
- arraySize *= 2;
- new = (KeyCode *) ckalloc((unsigned)
- (arraySize * sizeof(KeyCode)));
- memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
- (dispPtr->numModKeyCodes * sizeof(KeyCode)));
- ckfree((char *) dispPtr->modKeyCodes);
- dispPtr->modKeyCodes = new;
- }
- dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
- dispPtr->numModKeyCodes++;
- nextModCode: continue;
- }
- XFreeModifiermap(modMapPtr);
-}
-
-/*
*---------------------------------------------------------------------------
*
* EvalTclBinding --
@@ -4525,7 +4489,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.
@@ -4550,3 +4514,5 @@ TkCopyAndGlobalEval(interp, script)
}
+
+
diff --git a/tk/generic/tkBitmap.c b/tk/generic/tkBitmap.c
index 431fa56db42..ff8e7e3e5a2 100644
--- a/tk/generic/tkBitmap.c
+++ b/tk/generic/tkBitmap.c
@@ -6,7 +6,7 @@
* 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.
@@ -51,69 +51,180 @@
* "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:
+/*
+ * Used in bitmapDataTable, stored in the TkDisplay structure, to map
+ * between in-core data about a bitmap to its TkBitmap structure.
*/
-static Tcl_HashTable nameTable;
typedef struct {
- Tk_Uid name; /* Textual name for desired bitmap. */
- Screen *screen; /* Screen on which bitmap will be used. */
-} NameKey;
+ char *source; /* Bitmap bits. */
+ int width, height; /* Dimensions of bitmap. */
+} DataKey;
+
+typedef struct ThreadSpecificData {
+ int initialized; /* 0 means table below needs initializing. */
+ Tcl_HashTable predefBitmapTable;
+ /* Hash table created by Tk_DefineBitmap
+ * to map from a name to a collection
+ * of in-core data about a bitmap. The
+ * table is indexed by the address of the
+ * data for the bitmap, and the entries
+ * contain pointers to TkPredefBitmap
+ * structures. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
- * Hash table that maps from <display + bitmap id> to the TkBitmap structure
- * for the bitmap. This table is used by Tk_FreeBitmap.
+ * Forward declarations for procedures defined in this file:
*/
-static Tcl_HashTable idTable;
-typedef struct {
- Display *display; /* Display for which bitmap was allocated. */
- Pixmap pixmap; /* X identifier for pixmap. */
-} IdKey;
+static void BitmapInit _ANSI_ARGS_((TkDisplay *dispPtr));
+static void DupBitmapObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr));
+static void FreeBitmap _ANSI_ARGS_((TkBitmap *bitmapPtr));
+static void FreeBitmapObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
+static TkBitmap * GetBitmap _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *name));
+static TkBitmap * GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj *objPtr));
+static void InitBitmapObj _ANSI_ARGS_((Tcl_Obj *objPtr));
/*
- * Hash table create 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.
+ * 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.
*/
-Tcl_HashTable tkPredefBitmapTable;
-
+static Tcl_ObjType bitmapObjType = {
+ "bitmap", /* name */
+ FreeBitmapObjProc, /* freeIntRepProc */
+ DupBitmapObjProc, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
/*
- * 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-
- * generated name for the bitmap:
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
*/
-static Tcl_HashTable dataTable;
-typedef struct {
- char *source; /* Bitmap bits. */
- int width, height; /* Dimensions of bitmap. */
-} DataKey;
+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;
-static int initialized = 0; /* 0 means static structures haven't been
- * initialized yet. */
+ if (objPtr->typePtr != &bitmapObjType) {
+ InitBitmapObj(objPtr);
+ }
+ bitmapPtr = (TkBitmap *) objPtr->internalRep.twoPtrValue.ptr1;
-/*
- * Forward declarations for procedures defined in this file:
- */
+ /*
+ * 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.
+ */
-static void BitmapInit _ANSI_ARGS_((void));
+ 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 +238,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,30 +256,78 @@ 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
+ CONST char *string; /* Description of bitmap. See manual entry
+ * for details on legal syntax. */
+{
+ TkBitmap *bitmapPtr = GetBitmap(interp, tkwin, string);
+ if (bitmapPtr == NULL) {
+ return None;
+ }
+ 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. */
+ CONST 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;
int width, height;
int dummy2;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (!initialized) {
- BitmapInit();
+ if (!dispPtr->bitmapInit) {
+ BitmapInit(dispPtr);
}
- nameKey.name = string;
- nameKey.screen = Tk_Screen(tkwin);
- nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
+ nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, 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;
}
/*
@@ -179,7 +338,7 @@ Tk_GetBitmap(interp, tkwin, string)
* defined by a call to Tk_DefineBitmap.
*/
- if (*string == '@') {
+ if (*string == '@') { /* INTL: ISO char */
Tcl_DString buffer;
int result;
@@ -188,13 +347,19 @@ Tk_GetBitmap(interp, tkwin, string)
" safe interpreter", (char *) NULL);
goto error;
}
-
- string = Tcl_TranslateFileName(interp, string + 1, &buffer);
+
+ /*
+ * Note that we need to cast away the CONST from the string because
+ * Tcl_TranslateFileName is non const, even though it doesn't modify
+ * the string.
+ */
+
+ string = Tcl_TranslateFileName(interp, (char *) string + 1, &buffer);
if (string == NULL) {
goto error;
}
result = TkReadBitmapFile(Tk_Display(tkwin),
- RootWindowOfScreen(nameKey.screen), string,
+ RootWindowOfScreen(Tk_Screen(tkwin)), string,
(unsigned int *) &width, (unsigned int *) &height,
&bitmap, &dummy2, &dummy2);
if (result != BitmapSuccess) {
@@ -207,7 +372,8 @@ Tk_GetBitmap(interp, tkwin, string)
}
Tcl_DStringFree(&buffer);
} else {
- predefHashPtr = Tcl_FindHashEntry(&tkPredefBitmapTable, string);
+ predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable,
+ string);
if (predefHashPtr == NULL) {
/*
* The following platform specific call allows the user to
@@ -236,7 +402,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 +418,24 @@ Tk_GetBitmap(interp, tkwin, string)
bitmapPtr->width = width;
bitmapPtr->height = height;
bitmapPtr->display = Tk_Display(tkwin);
- bitmapPtr->refCount = 1;
- bitmapPtr->hashPtr = nameHashPtr;
- idKey.display = bitmapPtr->display;
- idKey.pixmap = bitmap;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey,
- &new);
+ bitmapPtr->resourceRefCount = 1;
+ bitmapPtr->objRefCount = 0;
+ bitmapPtr->nameHashPtr = nameHashPtr;
+ bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable,
+ (char *) bitmap, &new);
if (!new) {
panic("bitmap already registered in Tk_GetBitmap");
}
+ bitmapPtr->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 +449,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 +461,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
+ CONST 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. */
@@ -301,12 +470,23 @@ Tk_DefineBitmap(interp, name, source, width, height)
int new;
Tcl_HashEntry *predefHashPtr;
TkPredefBitmap *predefPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Initialize the Bitmap module if not initialized already for this
+ * thread. Since the current TkDisplay structure cannot be
+ * introspected from here, pass a NULL pointer to BitmapInit,
+ * which will know to initialize only the data in the
+ * ThreadSpecificData structure for the current thread.
+ */
- if (!initialized) {
- BitmapInit();
+ if (!tsdPtr->initialized) {
+ BitmapInit((TkDisplay *) NULL);
}
- predefHashPtr = Tcl_CreateHashEntry(&tkPredefBitmapTable, name, &new);
+ predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable,
+ name, &new);
if (!new) {
Tcl_AppendResult(interp, "bitmap \"", name,
"\" is already defined", (char *) NULL);
@@ -338,29 +518,27 @@ Tk_DefineBitmap(interp, name, source, width, height)
*--------------------------------------------------------------
*/
-Tk_Uid
+char *
Tk_NameOfBitmap(display, bitmap)
Display *display; /* Display for which bitmap was
* allocated. */
Pixmap bitmap; /* Bitmap whose name is wanted. */
{
- IdKey idKey;
Tcl_HashEntry *idHashPtr;
TkBitmap *bitmapPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
- if (!initialized) {
+ if (dispPtr == NULL || !dispPtr->bitmapInit) {
unknown:
panic("Tk_NameOfBitmap received unknown bitmap argument");
}
- idKey.display = display;
- idKey.pixmap = bitmap;
- idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
if (idHashPtr == NULL) {
goto unknown;
}
bitmapPtr = (TkBitmap *) Tcl_GetHashValue(idHashPtr);
- return ((NameKey *) bitmapPtr->hashPtr->key.words)->name;
+ return bitmapPtr->nameHashPtr->key.string;
}
/*
@@ -390,18 +568,16 @@ Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr)
int *widthPtr; /* Store bitmap width here. */
int *heightPtr; /* Store bitmap height here. */
{
- IdKey idKey;
Tcl_HashEntry *idHashPtr;
TkBitmap *bitmapPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
- if (!initialized) {
+ if (!dispPtr->bitmapInit) {
unknownBitmap:
panic("Tk_SizeOfBitmap received unknown bitmap argument");
}
- idKey.display = display;
- idKey.pixmap = bitmap;
- idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap);
if (idHashPtr == NULL) {
goto unknownBitmap;
}
@@ -413,6 +589,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,26 +661,115 @@ Tk_FreeBitmap(display, bitmap)
Pixmap bitmap; /* Bitmap to be released. */
{
Tcl_HashEntry *idHashPtr;
- register TkBitmap *bitmapPtr;
- IdKey idKey;
+ TkDisplay *dispPtr = TkGetDisplay(display);
- if (!initialized) {
+ if (!dispPtr->bitmapInit) {
panic("Tk_FreeBitmap called before Tk_GetBitmap");
}
- idKey.display = display;
- idKey.pixmap = bitmap;
- idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) 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 +786,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,25 +809,24 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height)
{
DataKey nameKey;
Tcl_HashEntry *dataHashPtr;
- Tk_Uid name;
int new;
- char string[20];
- static int autoNumber = 0;
+ char string[16 + TCL_INTEGER_SPACE];
+ char *name;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- BitmapInit();
- }
+ BitmapInit(dispPtr);
nameKey.source = source;
nameKey.width = width;
nameKey.height = height;
- dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new);
+ dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable,
+ (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);
+ dispPtr->bitmapAutoNumber++;
+ sprintf(string, "_tk%d", dispPtr->bitmapAutoNumber);
+ name = string;
Tcl_SetHashValue(dataHashPtr, name);
if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) {
Tcl_DeleteHashEntry(dataHashPtr);
@@ -525,63 +839,226 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height)
/*
*----------------------------------------------------------------------
*
- * BitmapInit --
+ * 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.
*
- * Initialize the structures used for bitmap management.
+ *----------------------------------------------------------------------
+ */
+
+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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ 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(&dispPtr->bitmapNameTable,
+ Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ }
+
+ /*
+ * At this point we've got a hash table entry, off of which hang
+ * one or more TkBitmap structures. See if any of them will work.
+ */
+
+ 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 --
+ * Initializes hash tables used by this module. Initializes
+ * tables stored in TkDisplay structure if a TkDisplay pointer
+ * is passed in. Iinitializes the thread-local data
+ * in the current thread's ThreadSpecificData structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
* Read the code.
*
*----------------------------------------------------------------------
*/
static void
-BitmapInit()
+BitmapInit(dispPtr)
+ TkDisplay *dispPtr; /* TkDisplay structure encapsulating
+ * thread-specific data used by this
+ * module, or NULL if unavailable. */
{
Tcl_Interp *dummy;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- dummy = Tcl_CreateInterp();
- initialized = 1;
- Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
- Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
- Tcl_InitHashTable(&tkPredefBitmapTable, TCL_ONE_WORD_KEYS);
+ /*
+ * First initialize the data in the ThreadSpecificData strucuture,
+ * if needed.
+ */
+
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
+ dummy = Tcl_CreateInterp();
+ Tcl_InitHashTable(&tsdPtr->predefBitmapTable, TCL_STRING_KEYS);
+
+ Tk_DefineBitmap(dummy, "error", (char *) error_bits,
+ error_width, error_height);
+ Tk_DefineBitmap(dummy, "gray75", (char *) gray75_bits,
+ gray75_width, gray75_height);
+ Tk_DefineBitmap(dummy, "gray50", (char *) gray50_bits,
+ gray50_width, gray50_height);
+ Tk_DefineBitmap(dummy, "gray25", (char *) gray25_bits,
+ gray25_width, gray25_height);
+ Tk_DefineBitmap(dummy, "gray12", (char *) gray12_bits,
+ gray12_width, gray12_height);
+ Tk_DefineBitmap(dummy, "hourglass", (char *) hourglass_bits,
+ hourglass_width, hourglass_height);
+ Tk_DefineBitmap(dummy, "info", (char *) info_bits,
+ info_width, info_height);
+ Tk_DefineBitmap(dummy, "questhead", (char *) questhead_bits,
+ questhead_width, questhead_height);
+ Tk_DefineBitmap(dummy, "question", (char *) question_bits,
+ question_width, question_height);
+ Tk_DefineBitmap(dummy, "warning", (char *) warning_bits,
+ warning_width, warning_height);
+
+ TkpDefineNativeBitmaps();
+ Tcl_DeleteInterp(dummy);
+ }
/*
- * The call below is tricky: can't use sizeof(IdKey) because it
- * gets padded with extra unpredictable bytes on some 64-bit
- * machines.
+ * Was a valid TkDisplay pointer passed? If so, initialize the
+ * Bitmap module tables in that structure.
*/
- Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Pixmap))
- /sizeof(int));
-
- Tk_DefineBitmap(dummy, Tk_GetUid("error"), (char *) error_bits,
- error_width, error_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("gray75"), (char *) gray75_bits,
- gray75_width, gray75_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *) gray50_bits,
- gray50_width, gray50_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), (char *) gray25_bits,
- gray25_width, gray25_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("gray12"), (char *) gray12_bits,
- gray12_width, gray12_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), (char *) hourglass_bits,
- hourglass_width, hourglass_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("info"), (char *) info_bits,
- info_width, info_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), (char *) questhead_bits,
- questhead_width, questhead_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("question"), (char *) question_bits,
- question_width, question_height);
- Tk_DefineBitmap(dummy, Tk_GetUid("warning"), (char *) warning_bits,
- warning_width, warning_height);
-
- TkpDefineNativeBitmaps();
-
- Tcl_DeleteInterp(dummy);
+ if (dispPtr != NULL) {
+ dispPtr->bitmapInit = 1;
+ Tcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->bitmapDataTable, sizeof(DataKey)
+ /sizeof(int));
+
+ /*
+ * The call below is tricky: can't use sizeof(IdKey) because it
+ * gets padded with extra unpredictable bytes on some 64-bit
+ * machines.
+ */
+
+ /*
+ * The comment above doesn't make sense...
+ */
+ Tcl_InitHashTable(&dispPtr->bitmapIdTable, TCL_ONE_WORD_KEYS);
+ }
}
/*
@@ -627,4 +1104,83 @@ TkReadBitmapFile(display, d, filename, width_return, height_return,
ckfree(data);
return BitmapSuccess;
+ }
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, 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;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetBitmapPredefTable --
+ * This procedure is used by tkMacBitmap.c to access the thread-
+ * specific predefBitmap table that maps from the names of
+ * the predefined bitmaps to data associated with those
+ * bitmaps. It is required because the table is allocated in
+ * thread-local storage and is not visible outside this file.
+
+ * Results:
+ * Returns a pointer to the predefined bitmap hash table for
+ * the current thread.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+Tcl_HashTable *
+TkGetBitmapPredefTable()
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return &tsdPtr->predefBitmapTable;
}
+
diff --git a/tk/generic/tkButton.c b/tk/generic/tkButton.c
index b493be03a0c..8a52f91217c 100644
--- a/tk/generic/tkButton.c
+++ b/tk/generic/tkButton.c
@@ -3,11 +3,10 @@
*
* 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.
@@ -19,183 +18,446 @@
#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_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_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_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_TABLE, "-state", "state", "State",
+ DEF_BUTTON_STATE, -1, Tk_Offset(TkButton, state),
+ 0, (ClientData) stateStrings, 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}
+};
+
+/*
+ * The following table maps from one of the type values defined in
+ * tkButton.h, such as TYPE_LABEL, to the option template for that
+ * class of widgets.
+ */
+
+static Tk_OptionSpec *optionSpecs[] = {
+ labelOptionSpecs,
+ buttonOptionSpecs,
+ checkbuttonOptionSpecs,
+ radiobuttonOptionSpecs
};
/*
- * String to print out in error messages, identifying options for
- * widget commands for different types of labels or buttons:
+ * 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 *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 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 +467,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 +483,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 +511,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 +569,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.
+ */
+
+ 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 (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;
}
@@ -335,39 +612,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 +659,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 +728,155 @@ 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_ObjSetVar2(interp, butPtr->selVarNamePtr, NULL,
+ butPtr->offValuePtr, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ } else if (butPtr->flags & SELECTED) {
+ if (Tcl_ObjSetVar2(interp,
+ butPtr->selVarNamePtr, NULL, Tcl_NewObj(),
+ TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ goto error;
+ }
+ }
+ 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_ObjSetVar2(interp, 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_ObjSetVar2(interp, 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 +891,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 +907,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 +938,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 +966,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 +982,244 @@ 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;
+ Tcl_Obj *errorResult = NULL;
+ 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;
- }
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ 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_SetOptions.
+ */
- 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, *namePtr;
+
+ if (butPtr->selVarNamePtr == NULL) {
+ butPtr->selVarNamePtr = Tcl_NewStringObj(
+ Tk_Name(butPtr->tkwin), -1);
+ Tcl_IncrRefCount(butPtr->selVarNamePtr);
+ }
+ namePtr = butPtr->selVarNamePtr;
+
+ /*
+ * Select the button if the associated variable has the
+ * appropriate value, initialize the variable if it doesn't
+ * exist, then set a trace on the variable to monitor future
+ * changes to its value.
+ */
+
+ valuePtr = Tcl_ObjGetVar2(interp, namePtr, 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_ObjSetVar2(interp, namePtr, 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.
+ */
+
+ Tcl_Obj *valuePtr, *namePtr;
+
+ namePtr = butPtr->textVarNamePtr;
+ valuePtr = Tcl_ObjGetVar2(interp, namePtr, NULL, TCL_GLOBAL_ONLY);
+ if (valuePtr == NULL) {
+ if (Tcl_ObjSetVar2(interp, namePtr, 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;
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
}
/*
@@ -914,60 +1267,48 @@ TkButtonWorldChanged(instanceData)
gcValues.graphics_exposures = False;
mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
- newGC = Tk_GetGCColor(butPtr->tkwin, mask, &gcValues,
- butPtr->normalFg,
- Tk_3DBorderColor(butPtr->normalBorder));
+ newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
if (butPtr->normalTextGC != None) {
Tk_FreeGC(butPtr->display, butPtr->normalTextGC);
}
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;
- newGC = Tk_GetGCColor(butPtr->tkwin, mask, &gcValues,
- butPtr->activeFg,
- Tk_3DBorderColor(butPtr->activeBorder));
+ newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
if (butPtr->activeTextGC != None) {
Tk_FreeGC(butPtr->display, butPtr->activeTextGC);
}
butPtr->activeTextGC = newGC;
}
- if (butPtr->type != TYPE_LABEL) {
- XColor *foreground, *background;
-
- gcValues.font = Tk_FontId(butPtr->tkfont);
- background = Tk_3DBorderColor(butPtr->normalBorder);
- gcValues.background = background->pixel;
- if ((butPtr->disabledFg != NULL) && (butPtr->imageString == NULL)) {
- foreground = butPtr->disabledFg;
- gcValues.foreground = foreground->pixel;
- mask = GCForeground | GCBackground | GCFont;
- } else {
- foreground = background;
- background = NULL;
- gcValues.foreground = gcValues.background;
- mask = GCForeground;
- if (butPtr->gray == None) {
- butPtr->gray = Tk_GetBitmap(NULL, butPtr->tkwin,
- Tk_GetUid("gray50"));
- }
- if (butPtr->gray != None) {
- gcValues.fill_style = FillStippled;
- gcValues.stipple = butPtr->gray;
- mask |= GCFillStyle | GCStipple;
- }
+ /*
+ * Allocate the disabled graphics context, for drawing the widget in
+ * its disabled state
+ */
+ gcValues.background = Tk_3DBorderColor(butPtr->normalBorder)->pixel;
+ 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, "gray50");
}
- newGC = Tk_GetGCColor(butPtr->tkwin, mask, &gcValues, foreground,
- background);
- if (butPtr->disabledGC != None) {
- Tk_FreeGC(butPtr->display, butPtr->disabledGC);
+ if (butPtr->gray != None) {
+ gcValues.fill_style = FillStippled;
+ gcValues.stipple = butPtr->gray;
+ mask |= GCFillStyle | GCStipple;
}
- butPtr->disabledGC = newGC;
}
+ newGC = Tk_GetGC(butPtr->tkwin, mask, &gcValues);
+ if (butPtr->disabledGC != None) {
+ Tk_FreeGC(butPtr->display, butPtr->disabledGC);
+ }
+ butPtr->disabledGC = newGC;
if (butPtr->copyGC == None) {
butPtr->copyGC = Tk_GetGC(butPtr->tkwin, 0, &gcValues);
@@ -1019,14 +1360,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) {
@@ -1075,18 +1408,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);
}
}
@@ -1102,7 +1433,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.
@@ -1112,28 +1443,34 @@ ButtonCmdDeletedProc(clientData)
int
TkInvokeButton(butPtr)
- register TkButton *butPtr; /* Information about button. */
+ TkButton *butPtr; /* Information about button. */
{
+ Tcl_Obj *namePtr = butPtr->selVarNamePtr;
+
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_ObjSetVar2(butPtr->interp, namePtr, 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_ObjSetVar2(butPtr->interp, namePtr, 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_ObjSetVar2(butPtr->interp, namePtr, 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_EvalObjEx(butPtr->interp, butPtr->commandPtr,
+ TCL_EVAL_GLOBAL);
}
return TCL_OK;
}
@@ -1167,7 +1504,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
@@ -1177,7 +1517,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);
}
@@ -1189,11 +1529,13 @@ ButtonVarProc(clientData, interp, name1, name2, flags)
* the button.
*/
- value = Tcl_GetVar(interp, butPtr->selVarName, TCL_GLOBAL_ONLY);
- if (value == NULL) {
+ valuePtr = Tcl_GetVar2Ex(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;
}
@@ -1240,8 +1582,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
@@ -1250,24 +1595,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_SetVar2Ex(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_GetVar2Ex(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)
@@ -1284,7 +1627,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:
@@ -1322,7 +1665,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/tk/generic/tkButton.h b/tk/generic/tkButton.h
index 6236fc74c30..d0e28822c16 100644
--- a/tk/generic/tkButton.h
+++ b/tk/generic/tkButton.h
@@ -4,7 +4,7 @@
* 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.
@@ -25,6 +25,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:
*/
@@ -36,69 +52,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
@@ -106,36 +141,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. */
+ 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. */
- 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 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,
@@ -144,36 +190,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;
@@ -200,36 +252,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_((
@@ -247,3 +294,4 @@ EXTERN int TkInvokeButton _ANSI_ARGS_((TkButton *butPtr));
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKBUTTON */
+
diff --git a/tk/generic/tkCanvArc.c b/tk/generic/tkCanvArc.c
index cec4ef2b5fb..e2c3504fd1e 100644
--- a/tk/generic/tkCanvArc.c
+++ b/tk/generic/tkCanvArc.c
@@ -4,7 +4,7 @@
* 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.
@@ -15,14 +15,19 @@
#include <stdio.h>
#include "tkPort.h"
#include "tkInt.h"
-
+#include "tkCanvas.h"
/*
* The structure below defines the record for each arc item.
*/
+typedef enum {
+ PIESLICE_STYLE, CHORD_STYLE, ARC_STYLE
+} Style;
+
typedef struct ArcItem {
Tk_Item header; /* Generic stuff that's the same for all
* types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
double bbox[4]; /* Coordinates (x1, y1, x2, y2) of bounding
* box for oval of which arc is a piece. */
double start; /* Angle at which arc begins, in degrees
@@ -38,16 +43,22 @@ typedef struct ArcItem {
* for a chord). Malloc'ed. */
int numOutlinePoints; /* Number of points at outlinePtr. Zero
* means no space allocated. */
- int width; /* Width of outline (in pixels). */
- XColor *outlineColor; /* Color for outline. NULL means don't
- * draw outline. */
+ Tk_TSOffset tsoffset;
XColor *fillColor; /* Color for filling arc (used for drawing
* outline too when style is "arc"). NULL
* means don't fill arc. */
+ XColor *activeFillColor; /* Color for filling arc (used for drawing
+ * outline too when style is "arc" and state
+ * is "active"). NULL means use fillColor. */
+ XColor *disabledFillColor; /* Color for filling arc (used for drawing
+ * outline too when style is "arc" and state
+ * is "disabled". NULL means use fillColor */
Pixmap fillStipple; /* Stipple bitmap for filling item. */
- Pixmap outlineStipple; /* Stipple bitmap for outline. */
- Tk_Uid style; /* How to draw arc: arc, chord, or pieslice. */
- GC outlineGC; /* Graphics context for outline. */
+ Pixmap activeFillStipple; /* Stipple bitmap for filling item if state
+ * is active. */
+ Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state
+ * is disabled. */
+ Style style; /* How to draw arc: arc, chord, or pieslice. */
GC fillGC; /* Graphics context for filling item. */
double center1[2]; /* Coordinates of center of arc outline at
* start (see ComputeArcOutline). */
@@ -68,29 +79,112 @@ typedef struct ArcItem {
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static int StyleParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value,
+ char *widgRec, int offset));
+static char * StylePrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption styleOption = {
+ (Tk_OptionParseProc *) StyleParseProc,
+ StylePrintProc, (ClientData) NULL
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
+static Tk_CustomOption dashOption = {
+ (Tk_OptionParseProc *) TkCanvasDashParseProc,
+ TkCanvasDashPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc, (ClientData) (TK_OFFSET_RELATIVE)
+};
+static Tk_CustomOption pixelOption = {
+ (Tk_OptionParseProc *) TkPixelParseProc,
+ TkPixelPrintProc, (ClientData) NULL
+};
static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, activeFillColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.activeColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, activeFillStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(ArcItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(ArcItem, outline.offset), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, disabledFillColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, disabledFillStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(ArcItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_DOUBLE, "-extent", (char *) NULL, (char *) NULL,
"90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(ArcItem, tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
{TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
- "black", Tk_Offset(ArcItem, outlineColor), TK_CONFIG_NULL_OK},
+ "black", Tk_Offset(ArcItem, outline.color), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(ArcItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
{TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(ArcItem, outlineStipple), TK_CONFIG_NULL_OK},
+ (char *) NULL, Tk_Offset(ArcItem, outline.stipple),
+ TK_CONFIG_NULL_OK},
{TK_CONFIG_DOUBLE, "-start", (char *) NULL, (char *) NULL,
"0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-style", (char *) NULL, (char *) NULL,
- "pieslice", Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-style", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT,
+ &styleOption},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
- {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
- "1", Tk_Offset(ArcItem, width), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
+ "1.0", Tk_Offset(ArcItem, outline.width), TK_CONFIG_DONT_SET_DEFAULT,
+ &pixelOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
@@ -103,10 +197,10 @@ static void ComputeArcBbox _ANSI_ARGS_((Tk_Canvas canvas,
ArcItem *arcPtr));
static int ConfigureArc _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int CreateArc _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteArc _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayArc _ANSI_ARGS_((Tk_Canvas canvas,
@@ -114,7 +208,7 @@ static void DisplayArc _ANSI_ARGS_((Tk_Canvas canvas,
int x, int y, int width, int height));
static int ArcCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv));
+ Tcl_Obj *CONST argv[]));
static int ArcToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double ArcToPoint _ANSI_ARGS_((Tk_Canvas canvas,
@@ -128,7 +222,8 @@ static void TranslateArc _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double deltaX, double deltaY));
static int AngleInRange _ANSI_ARGS_((double x, double y,
double start, double extent));
-static void ComputeArcOutline _ANSI_ARGS_((ArcItem *arcPtr));
+static void ComputeArcOutline _ANSI_ARGS_((Tk_Canvas canvas,
+ ArcItem *arcPtr));
static int HorizLineToArc _ANSI_ARGS_((double x1, double x2,
double y, double rx, double ry,
double start, double extent));
@@ -150,7 +245,7 @@ Tk_ItemType tkArcType = {
ArcCoords, /* coordProc */
DeleteArc, /* deleteProc */
DisplayArc, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
ArcToPoint, /* pointProc */
ArcToArea, /* areaProc */
ArcToPostscript, /* postscriptProc */
@@ -161,21 +256,13 @@ Tk_ItemType tkArcType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
#ifndef PI
# define PI 3.14159265358979323846
#endif
-/*
- * The uid's below comprise the legal values for the "-style"
- * option for arcs.
- */
-
-static Tk_Uid arcUid = NULL;
-static Tk_Uid chordUid = NULL;
-static Tk_Uid pieSliceUid = NULL;
/*
*--------------------------------------------------------------
@@ -188,7 +275,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.
*
@@ -205,11 +292,23 @@ CreateArc(interp, canvas, itemPtr, argc, argv)
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 arc. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing arc. */
{
ArcItem *arcPtr = (ArcItem *) itemPtr;
+ int i;
- if (argc < 4) {
+ if (argc==1) {
+ i = 1;
+ } else {
+ char *arg = Tcl_GetStringFromObj(argv[1], NULL);
+ if ((argc>1) && (arg[0] == '-')
+ && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ } else {
+ i = 4;
+ }
+ }
+ if (argc < i) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",
@@ -218,52 +317,40 @@ CreateArc(interp, canvas, itemPtr, argc, argv)
}
/*
- * Carry out once-only initialization.
- */
-
- if (arcUid == NULL) {
- arcUid = Tk_GetUid("arc");
- chordUid = Tk_GetUid("chord");
- pieSliceUid = Tk_GetUid("pieslice");
- }
-
- /*
* Carry out initialization that is needed in order to clean
* up after errors during the the remainder of this procedure.
*/
+ Tk_CreateOutline(&(arcPtr->outline));
arcPtr->start = 0;
arcPtr->extent = 90;
arcPtr->outlinePtr = NULL;
arcPtr->numOutlinePoints = 0;
- arcPtr->width = 1;
- arcPtr->outlineColor = NULL;
+ arcPtr->tsoffset.flags = 0;
+ arcPtr->tsoffset.xoffset = 0;
+ arcPtr->tsoffset.yoffset = 0;
arcPtr->fillColor = NULL;
+ arcPtr->activeFillColor = NULL;
+ arcPtr->disabledFillColor = NULL;
arcPtr->fillStipple = None;
- arcPtr->outlineStipple = None;
- arcPtr->style = pieSliceUid;
- arcPtr->outlineGC = None;
+ arcPtr->activeFillStipple = None;
+ arcPtr->disabledFillStipple = None;
+ arcPtr->style = PIESLICE_STYLE;
arcPtr->fillGC = None;
/*
* Process the arguments to fill in the item record.
*/
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &arcPtr->bbox[0]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
- &arcPtr->bbox[1]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[2],
- &arcPtr->bbox[2]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[3],
- &arcPtr->bbox[3]) != TCL_OK)) {
- return TCL_ERROR;
+ if ((ArcCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
+ goto error;
}
-
- if (ConfigureArc(interp, canvas, itemPtr, argc-4, argv+4, 0) != TCL_OK) {
- DeleteArc(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
- return TCL_ERROR;
+ if (ConfigureArc(interp, canvas, itemPtr, argc-4, argv+4, 0) == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
+ error:
+ DeleteArc(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
}
/*
@@ -276,7 +363,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.
@@ -292,36 +379,51 @@ ArcCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
ArcItem *arcPtr = (ArcItem *) itemPtr;
- char c0[TCL_DOUBLE_SPACE], c1[TCL_DOUBLE_SPACE];
- char c2[TCL_DOUBLE_SPACE], c3[TCL_DOUBLE_SPACE];
if (argc == 0) {
- Tcl_PrintDouble(interp, arcPtr->bbox[0], c0);
- Tcl_PrintDouble(interp, arcPtr->bbox[1], c1);
- Tcl_PrintDouble(interp, arcPtr->bbox[2], c2);
- Tcl_PrintDouble(interp, arcPtr->bbox[3], c3);
- Tcl_AppendResult(interp, c0, " ", c1, " ", c2, " ", c3,
- (char *) NULL);
- } else if (argc == 4) {
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0],
- &arcPtr->bbox[0]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(arcPtr->bbox[0]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(arcPtr->bbox[1]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(arcPtr->bbox[2]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(arcPtr->bbox[3]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ } else if ((argc == 1)||(argc == 4)) {
+ if (argc==1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (argc != 4) {
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 4, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0],
+ &arcPtr->bbox[0]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
&arcPtr->bbox[1]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[2],
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[2],
&arcPtr->bbox[2]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[3],
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[3],
&arcPtr->bbox[3]) != TCL_OK)) {
return TCL_ERROR;
}
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 +439,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
@@ -352,7 +454,7 @@ ConfigureArc(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Arc item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
ArcItem *arcPtr = (ArcItem *) itemPtr;
@@ -361,18 +463,52 @@ ConfigureArc(interp, canvas, itemPtr, argc, argv, flags)
unsigned long mask;
int i;
Tk_Window tkwin;
+ Tk_TSOffset *tsoffset;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) arcPtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) arcPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
+ state = itemPtr->state;
+
/*
* A few of the options require additional processing, such as
* style and graphics contexts.
*/
+ if (arcPtr->outline.activeWidth > arcPtr->outline.width ||
+ arcPtr->outline.activeDash.number != 0 ||
+ arcPtr->outline.activeColor != NULL ||
+ arcPtr->outline.activeStipple != None ||
+ arcPtr->activeFillColor != NULL ||
+ arcPtr->activeFillStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ tsoffset = &arcPtr->outline.tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[2] + 0.5);
+ }
+
i = (int) (arcPtr->start/360.0);
arcPtr->start -= i*360.0;
if (arcPtr->start < 0) {
@@ -381,60 +517,87 @@ ConfigureArc(interp, canvas, itemPtr, argc, argv, flags)
i = (int) (arcPtr->extent/360.0);
arcPtr->extent -= i*360.0;
- if ((arcPtr->style != arcUid) && (arcPtr->style != chordUid)
- && (arcPtr->style != pieSliceUid)) {
- Tcl_AppendResult(interp, "bad -style option \"",
- arcPtr->style, "\": must be arc, chord, or pieslice",
- (char *) NULL);
- arcPtr->style = pieSliceUid;
- return TCL_ERROR;
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(arcPtr->outline));
+ if (mask) {
+ gcValues.cap_style = CapButt;
+ mask |= GCCapStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = None;
}
-
- if (arcPtr->width < 0) {
- arcPtr->width = 1;
+ if (arcPtr->outline.gc != None) {
+ Tk_FreeGC(Tk_Display(tkwin), arcPtr->outline.gc);
}
- if (arcPtr->outlineColor == NULL) {
- newGC = None;
- } else {
- gcValues.foreground = arcPtr->outlineColor->pixel;
- gcValues.cap_style = CapButt;
- gcValues.line_width = arcPtr->width;
- mask = GCForeground|GCCapStyle|GCLineWidth;
- if (arcPtr->outlineStipple != None) {
- gcValues.stipple = arcPtr->outlineStipple;
- gcValues.fill_style = FillStippled;
- mask |= GCStipple|GCFillStyle;
- }
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, arcPtr->outlineColor,
- NULL);
+ arcPtr->outline.gc = newGC;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
}
- if (arcPtr->outlineGC != None) {
- Tk_FreeGC(Tk_Display(tkwin), arcPtr->outlineGC);
+ if (state==TK_STATE_HIDDEN) {
+ ComputeArcBbox(canvas, arcPtr);
+ return TCL_OK;
}
- arcPtr->outlineGC = newGC;
- if ((arcPtr->fillColor == NULL) || (arcPtr->style == arcUid)) {
+ color = arcPtr->fillColor;
+ stipple = arcPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->activeFillColor!=NULL) {
+ color = arcPtr->activeFillColor;
+ }
+ if (arcPtr->activeFillStipple!=None) {
+ stipple = arcPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->disabledFillColor!=NULL) {
+ color = arcPtr->disabledFillColor;
+ }
+ if (arcPtr->disabledFillStipple!=None) {
+ stipple = arcPtr->disabledFillStipple;
+ }
+ }
+
+ if (arcPtr->style == ARC_STYLE) {
+ newGC = None;
+ } else if (color == NULL) {
newGC = None;
} else {
- gcValues.foreground = arcPtr->fillColor->pixel;
- if (arcPtr->style == chordUid) {
+ gcValues.foreground = color->pixel;
+ if (arcPtr->style == CHORD_STYLE) {
gcValues.arc_mode = ArcChord;
} else {
gcValues.arc_mode = ArcPieSlice;
}
mask = GCForeground|GCArcMode;
- if (arcPtr->fillStipple != None) {
- gcValues.stipple = arcPtr->fillStipple;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
gcValues.fill_style = FillStippled;
mask |= GCStipple|GCFillStyle;
}
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, arcPtr->fillColor, NULL);
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
}
if (arcPtr->fillGC != None) {
Tk_FreeGC(Tk_Display(tkwin), arcPtr->fillGC);
}
arcPtr->fillGC = newGC;
+ tsoffset = &arcPtr->tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int) ((arcPtr->bbox[0]+arcPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (arcPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int) ((arcPtr->bbox[1]+arcPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (arcPtr->bbox[3] + 0.5);
+ }
+
ComputeArcBbox(canvas, arcPtr);
return TCL_OK;
}
@@ -465,23 +628,27 @@ DeleteArc(canvas, itemPtr, display)
{
ArcItem *arcPtr = (ArcItem *) itemPtr;
+ Tk_DeleteOutline(display, &(arcPtr->outline));
if (arcPtr->numOutlinePoints != 0) {
ckfree((char *) arcPtr->outlinePtr);
}
- if (arcPtr->outlineColor != NULL) {
- Tk_FreeColor(arcPtr->outlineColor);
- }
if (arcPtr->fillColor != NULL) {
Tk_FreeColor(arcPtr->fillColor);
}
+ if (arcPtr->activeFillColor != NULL) {
+ Tk_FreeColor(arcPtr->activeFillColor);
+ }
+ if (arcPtr->disabledFillColor != NULL) {
+ Tk_FreeColor(arcPtr->disabledFillColor);
+ }
if (arcPtr->fillStipple != None) {
Tk_FreeBitmap(display, arcPtr->fillStipple);
}
- if (arcPtr->outlineStipple != None) {
- Tk_FreeBitmap(display, arcPtr->outlineStipple);
+ if (arcPtr->activeFillStipple != None) {
+ Tk_FreeBitmap(display, arcPtr->activeFillStipple);
}
- if (arcPtr->outlineGC != None) {
- Tk_FreeGC(display, arcPtr->outlineGC);
+ if (arcPtr->disabledFillStipple != None) {
+ Tk_FreeBitmap(display, arcPtr->disabledFillStipple);
}
if (arcPtr->fillGC != None) {
Tk_FreeGC(display, arcPtr->fillGC);
@@ -514,6 +681,30 @@ ComputeArcBbox(canvas, arcPtr)
* recomputed. */
{
double tmp, center[2], point[2];
+ double width;
+ Tk_State state = arcPtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = arcPtr->outline.width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ arcPtr->header.x1 = arcPtr->header.x2 =
+ arcPtr->header.y1 = arcPtr->header.y2 = -1;
+ return;
+ } else if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *) arcPtr) {
+ if (arcPtr->outline.activeWidth>width) {
+ width = arcPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>0) {
+ width = arcPtr->outline.disabledWidth;
+ }
+ }
/*
* Make sure that the first coordinates are the lowest ones.
@@ -532,7 +723,7 @@ ComputeArcBbox(canvas, arcPtr)
arcPtr->bbox[0] = tmp;
}
- ComputeArcOutline(arcPtr);
+ ComputeArcOutline(canvas,arcPtr);
/*
* To compute the bounding box, start with the the bbox formed
@@ -546,7 +737,7 @@ ComputeArcBbox(canvas, arcPtr)
TkIncludePoint((Tk_Item *) arcPtr, arcPtr->center2);
center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2;
center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2;
- if (arcPtr->style == pieSliceUid) {
+ if (arcPtr->style == PIESLICE_STYLE) {
TkIncludePoint((Tk_Item *) arcPtr, center);
}
@@ -592,10 +783,10 @@ ComputeArcBbox(canvas, arcPtr)
* being drawn) and add one extra pixel just for safety.
*/
- if (arcPtr->outlineColor == NULL) {
+ if (arcPtr->outline.gc == None) {
tmp = 1;
} else {
- tmp = (arcPtr->width + 1)/2 + 1;
+ tmp = (int) ((width + 1.0)/2.0 + 1);
}
arcPtr->header.x1 -= (int) tmp;
arcPtr->header.y1 -= (int) tmp;
@@ -633,7 +824,41 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height)
{
ArcItem *arcPtr = (ArcItem *) itemPtr;
short x1, y1, x2, y2;
- int start, extent;
+ int start, extent, dashnumber;
+ double lineWidth;
+ Tk_State state = itemPtr->state;
+ Pixmap stipple;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ lineWidth = arcPtr->outline.width;
+ if (lineWidth < 1.0) {
+ lineWidth = 1.0;
+ }
+ dashnumber = arcPtr->outline.dash.number;
+ stipple = arcPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeWidth>lineWidth) {
+ lineWidth = arcPtr->outline.activeWidth;
+ }
+ if (arcPtr->outline.activeDash.number != 0) {
+ dashnumber = arcPtr->outline.activeDash.number;
+ }
+ if (arcPtr->activeFillStipple != None) {
+ stipple = arcPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth > 0) {
+ lineWidth = arcPtr->outline.disabledWidth;
+ }
+ if (arcPtr->outline.disabledDash.number != 0) {
+ dashnumber = arcPtr->outline.disabledDash.number;
+ }
+ if (arcPtr->disabledFillStipple != None) {
+ stipple = arcPtr->disabledFillStipple;
+ }
+ }
/*
* Compute the screen coordinates of the bounding box for the item,
@@ -660,65 +885,86 @@ DisplayArc(canvas, itemPtr, display, drawable, x, y, width, height)
*/
if ((arcPtr->fillGC != None) && (extent != 0)) {
- if (arcPtr->fillStipple != None) {
- Tk_CanvasSetStippleOrigin(canvas, arcPtr->fillGC);
+ if (stipple != None) {
+ int w=0; int h=0;
+ Tk_TSOffset *tsoffset = &arcPtr->tsoffset;
+ int flags = tsoffset->flags;
+ if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
+ Tk_SizeOfBitmap(display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, arcPtr->fillGC, tsoffset);
+ if (tsoffset) {
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ }
}
XFillArc(display, drawable, arcPtr->fillGC, x1, y1, (unsigned) (x2-x1),
(unsigned) (y2-y1), start, extent);
- if (arcPtr->fillStipple != None) {
+ if (stipple != None) {
XSetTSOrigin(display, arcPtr->fillGC, 0, 0);
}
}
- if (arcPtr->outlineGC != None) {
- if (arcPtr->outlineStipple != None) {
- Tk_CanvasSetStippleOrigin(canvas, arcPtr->outlineGC);
- }
+ if (arcPtr->outline.gc != None) {
+ Tk_ChangeOutlineGC(canvas, itemPtr, &(arcPtr->outline));
+
if (extent != 0) {
- XDrawArc(display, drawable, arcPtr->outlineGC, x1, y1,
+ XDrawArc(display, drawable, arcPtr->outline.gc, x1, y1,
(unsigned) (x2-x1), (unsigned) (y2-y1), start, extent);
}
/*
* If the outline width is very thin, don't use polygons to draw
* the linear parts of the outline (this often results in nothing
- * being displayed); just draw lines instead.
+ * being displayed); just draw lines instead. The same is done if
+ * the outline is dashed, because then polygons don't work.
*/
- if (arcPtr->width <= 2) {
+ if (lineWidth < 1.5 || dashnumber != 0) {
Tk_CanvasDrawableCoords(canvas, arcPtr->center1[0],
arcPtr->center1[1], &x1, &y1);
Tk_CanvasDrawableCoords(canvas, arcPtr->center2[0],
arcPtr->center2[1], &x2, &y2);
- if (arcPtr->style == chordUid) {
- XDrawLine(display, drawable, arcPtr->outlineGC,
+ if (arcPtr->style == CHORD_STYLE) {
+ XDrawLine(display, drawable, arcPtr->outline.gc,
x1, y1, x2, y2);
- } else if (arcPtr->style == pieSliceUid) {
+ } else if (arcPtr->style == PIESLICE_STYLE) {
short cx, cy;
Tk_CanvasDrawableCoords(canvas,
(arcPtr->bbox[0] + arcPtr->bbox[2])/2.0,
(arcPtr->bbox[1] + arcPtr->bbox[3])/2.0, &cx, &cy);
- XDrawLine(display, drawable, arcPtr->outlineGC,
+ XDrawLine(display, drawable, arcPtr->outline.gc,
cx, cy, x1, y1);
- XDrawLine(display, drawable, arcPtr->outlineGC,
+ XDrawLine(display, drawable, arcPtr->outline.gc,
cx, cy, x2, y2);
}
} else {
- if (arcPtr->style == chordUid) {
+ if (arcPtr->style == CHORD_STYLE) {
TkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
- display, drawable, arcPtr->outlineGC, None);
- } else if (arcPtr->style == pieSliceUid) {
+ display, drawable, arcPtr->outline.gc, None);
+ } else if (arcPtr->style == PIESLICE_STYLE) {
TkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
- display, drawable, arcPtr->outlineGC, None);
+ display, drawable, arcPtr->outline.gc, None);
TkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
- PIE_OUTLINE2_PTS, display, drawable, arcPtr->outlineGC,
+ PIE_OUTLINE2_PTS, display, drawable, arcPtr->outline.gc,
None);
}
}
- if (arcPtr->outlineStipple != None) {
- XSetTSOrigin(display, arcPtr->outlineGC, 0, 0);
- }
+
+ Tk_ResetOutlineGC(canvas, itemPtr, &(arcPtr->outline));
}
}
@@ -756,6 +1002,22 @@ ArcToPoint(canvas, itemPtr, pointPtr)
double vertex[2], pointAngle, diff, dist, newDist;
double poly[8], polyDist, width, t1, t2;
int filled, angleInRange;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = (double) arcPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeWidth>width) {
+ width = (double) arcPtr->outline.activeWidth;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>0) {
+ width = (double) arcPtr->outline.disabledWidth;
+ }
+ }
/*
* See if the point is within the angular range of the arc.
@@ -766,8 +1028,14 @@ ArcToPoint(canvas, itemPtr, pointPtr)
vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
- t1 = (pointPtr[1] - vertex[1])/(arcPtr->bbox[3] - arcPtr->bbox[1]);
- t2 = (pointPtr[0] - vertex[0])/(arcPtr->bbox[2] - arcPtr->bbox[0]);
+ t1 = arcPtr->bbox[3] - arcPtr->bbox[1];
+ if (t1 != 0.0) {
+ t1 = (pointPtr[1] - vertex[1]) / t1;
+ }
+ t2 = arcPtr->bbox[2] - arcPtr->bbox[0];
+ if (t2 != 0.0) {
+ t2 = (pointPtr[0] - vertex[0]) / t2;
+ }
if ((t1 == 0.0) && (t2 == 0.0)) {
pointAngle = 0;
} else {
@@ -786,9 +1054,9 @@ ArcToPoint(canvas, itemPtr, pointPtr)
* we're dealing with.
*/
- if (arcPtr->style == arcUid) {
+ if (arcPtr->style == ARC_STYLE) {
if (angleInRange) {
- return TkOvalToPoint(arcPtr->bbox, (double) arcPtr->width,
+ return TkOvalToPoint(arcPtr->bbox, width,
0, pointPtr);
}
dist = hypot(pointPtr[0] - arcPtr->center1[0],
@@ -801,18 +1069,16 @@ ArcToPoint(canvas, itemPtr, pointPtr)
return dist;
}
- if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
+ if ((arcPtr->fillGC != None) || (arcPtr->outline.gc == None)) {
filled = 1;
} else {
filled = 0;
}
- if (arcPtr->outlineGC == None) {
+ if (arcPtr->outline.gc == None) {
width = 0.0;
- } else {
- width = arcPtr->width;
}
- if (arcPtr->style == pieSliceUid) {
+ if (arcPtr->style == PIESLICE_STYLE) {
if (width > 1.0) {
dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
pointPtr);
@@ -917,16 +1183,29 @@ ArcToArea(canvas, itemPtr, rectPtr)
* every test so far shows arc to be outside
* of rectangle. */
int newInside;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = (double) arcPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeWidth>width) {
+ width = (double) arcPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>0) {
+ width = (double) arcPtr->outline.disabledWidth;
+ }
+ }
- if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
+ if ((arcPtr->fillGC != None) || (arcPtr->outline.gc == None)) {
filled = 1;
} else {
filled = 0;
}
- if (arcPtr->outlineGC == None) {
+ if (arcPtr->outline.gc == None) {
width = 0.0;
- } else {
- width = arcPtr->width;
}
/*
@@ -967,7 +1246,7 @@ ArcToArea(canvas, itemPtr, rectPtr)
numPoints = 2;
pointPtr += 4;
- if ((arcPtr->style == pieSliceUid) && (arcPtr->extent < 180.0)) {
+ if ((arcPtr->style == PIESLICE_STYLE) && (arcPtr->extent < 180.0)) {
pointPtr[0] = 0.0;
pointPtr[1] = 0.0;
numPoints++;
@@ -1041,7 +1320,7 @@ ArcToArea(canvas, itemPtr, rectPtr)
* polygon(s) forming the sides of a chord or pie-slice.
*/
- if (arcPtr->style == pieSliceUid) {
+ if (arcPtr->style == PIESLICE_STYLE) {
if (width >= 1.0) {
if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
rectPtr) != -1) {
@@ -1057,7 +1336,7 @@ ArcToArea(canvas, itemPtr, rectPtr)
return 0;
}
}
- } else if (arcPtr->style == chordUid) {
+ } else if (arcPtr->style == CHORD_STYLE) {
if (width >= 1.0) {
if (TkPolygonToArea(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
rectPtr) != -1) {
@@ -1209,13 +1488,16 @@ TranslateArc(canvas, itemPtr, deltaX, deltaY)
*/
static void
-ComputeArcOutline(arcPtr)
+ComputeArcOutline(canvas,arcPtr)
+ Tk_Canvas canvas; /* Information about overall canvas. */
ArcItem *arcPtr; /* Information about arc. */
{
- double sin1, cos1, sin2, cos2, angle, halfWidth;
+ double sin1, cos1, sin2, cos2, angle, width, halfWidth;
double boxWidth, boxHeight;
double vertex[2], corner1[2], corner2[2];
double *outlinePtr;
+ Tk_State state = arcPtr->header.state;
+
/*
* Make sure that the outlinePtr array is large enough to hold
@@ -1229,6 +1511,10 @@ ComputeArcOutline(arcPtr)
}
outlinePtr = arcPtr->outlinePtr;
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
/*
* First compute the two points that lie at the centers of
* the ends of the curved arc segment, which are marked with
@@ -1285,7 +1571,18 @@ ComputeArcOutline(arcPtr)
* the oval.
*/
- halfWidth = arcPtr->width/2.0;
+ width = arcPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *) arcPtr) {
+ if (arcPtr->outline.activeWidth>arcPtr->outline.width) {
+ width = arcPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledWidth>arcPtr->outline.width) {
+ width = arcPtr->outline.disabledWidth;
+ }
+ }
+ halfWidth = width/2.0;
+
if (((boxWidth*sin1) == 0.0) && ((boxHeight*cos1) == 0.0)) {
angle = 0.0;
} else {
@@ -1308,11 +1605,11 @@ ComputeArcOutline(arcPtr)
* center point. The second point is the corner point.
*/
- if (arcPtr->style == chordUid) {
+ if (arcPtr->style == CHORD_STYLE) {
outlinePtr[0] = outlinePtr[12] = corner1[0];
outlinePtr[1] = outlinePtr[13] = corner1[1];
TkGetButtPoints(arcPtr->center2, arcPtr->center1,
- (double) arcPtr->width, 0, outlinePtr+10, outlinePtr+2);
+ width, 0, outlinePtr+10, outlinePtr+2);
outlinePtr[4] = arcPtr->center2[0] + outlinePtr[2]
- arcPtr->center1[0];
outlinePtr[5] = arcPtr->center2[1] + outlinePtr[3]
@@ -1323,7 +1620,7 @@ ComputeArcOutline(arcPtr)
- arcPtr->center1[0];
outlinePtr[9] = arcPtr->center2[1] + outlinePtr[11]
- arcPtr->center1[1];
- } else if (arcPtr->style == pieSliceUid) {
+ } else if (arcPtr->style == PIESLICE_STYLE) {
/*
* For pie slices, generate two polygons, one for each side
* of the pie slice. The first arm has a shape like this,
@@ -1339,7 +1636,7 @@ ComputeArcOutline(arcPtr)
*
*/
- TkGetButtPoints(arcPtr->center1, vertex, (double) arcPtr->width, 0,
+ TkGetButtPoints(arcPtr->center1, vertex, width, 0,
outlinePtr, outlinePtr+2);
outlinePtr[4] = arcPtr->center1[0] + outlinePtr[2] - vertex[0];
outlinePtr[5] = arcPtr->center1[1] + outlinePtr[3] - vertex[1];
@@ -1368,7 +1665,7 @@ ComputeArcOutline(arcPtr)
* first two points of the first arm, depending on extent.
*/
- TkGetButtPoints(arcPtr->center2, vertex, (double) arcPtr->width, 0,
+ TkGetButtPoints(arcPtr->center2, vertex, width, 0,
outlinePtr+12, outlinePtr+16);
if ((arcPtr->extent > 180) ||
((arcPtr->extent < 0) && (arcPtr->extent > -180))) {
@@ -1575,7 +1872,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.
*
@@ -1599,6 +1896,11 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
ArcItem *arcPtr = (ArcItem *) itemPtr;
char buffer[400];
double y1, y2, ang1, ang2;
+ XColor *color;
+ Pixmap stipple;
+ XColor *fillColor;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
y1 = Tk_CanvasPsY(canvas, arcPtr->bbox[1]);
y2 = Tk_CanvasPsY(canvas, arcPtr->bbox[3]);
@@ -1609,6 +1911,41 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
ang2 = arcPtr->start;
}
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ color = arcPtr->outline.color;
+ stipple = arcPtr->outline.stipple;
+ fillColor = arcPtr->fillColor;
+ fillStipple = arcPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (arcPtr->outline.activeColor!=NULL) {
+ color = arcPtr->outline.activeColor;
+ }
+ if (arcPtr->outline.activeStipple!=None) {
+ stipple = arcPtr->outline.activeStipple;
+ }
+ if (arcPtr->activeFillColor!=NULL) {
+ fillColor = arcPtr->activeFillColor;
+ }
+ if (arcPtr->activeFillStipple!=None) {
+ fillStipple = arcPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (arcPtr->outline.disabledColor!=NULL) {
+ color = arcPtr->outline.disabledColor;
+ }
+ if (arcPtr->outline.disabledStipple!=None) {
+ stipple = arcPtr->outline.disabledStipple;
+ }
+ if (arcPtr->disabledFillColor!=NULL) {
+ fillColor = arcPtr->disabledFillColor;
+ }
+ if (arcPtr->disabledFillStipple!=None) {
+ fillStipple = arcPtr->disabledFillStipple;
+ }
+ }
+
/*
* If the arc is filled, output Postscript for the interior region
* of the arc.
@@ -1619,7 +1956,7 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
(arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
(arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
Tcl_AppendResult(interp, buffer, (char *) NULL);
- if (arcPtr->style == chordUid) {
+ if (arcPtr->style == CHORD_STYLE) {
sprintf(buffer, "0 0 1 %.15g %.15g arc closepath\nsetmatrix\n",
ang1, ang2);
} else {
@@ -1628,16 +1965,16 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
ang1, ang2);
}
Tcl_AppendResult(interp, buffer, (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, arcPtr->fillColor) != TCL_OK) {
+ if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
return TCL_ERROR;
};
- if (arcPtr->fillStipple != None) {
+ if (fillStipple != None) {
Tcl_AppendResult(interp, "clip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, arcPtr->fillStipple)
+ if (Tk_CanvasPsStipple(interp, canvas, fillStipple)
!= TCL_OK) {
return TCL_ERROR;
}
- if (arcPtr->outlineGC != None) {
+ if (arcPtr->outline.gc != None) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
}
} else {
@@ -1649,44 +1986,34 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
* If there's an outline for the arc, draw it.
*/
- if (arcPtr->outlineGC != None) {
+ if (arcPtr->outline.gc != None) {
sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n",
(arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2,
(arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2);
Tcl_AppendResult(interp, buffer, (char *) NULL);
- sprintf(buffer, "0 0 1 %.15g %.15g arc\nsetmatrix\n", ang1, ang2);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- sprintf(buffer, "%d setlinewidth\n0 setlinecap\n", arcPtr->width);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor)
- != TCL_OK) {
+ sprintf(buffer, "0 0 1 %.15g %.15g", ang1, ang2);
+ Tcl_AppendResult(interp, buffer,
+ " arc\nsetmatrix\n0 setlinecap\n", (char *) NULL);
+ if (Tk_CanvasPsOutline(canvas, itemPtr,
+ &(arcPtr->outline)) != TCL_OK) {
return TCL_ERROR;
}
- if (arcPtr->outlineStipple != None) {
- Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas,
- arcPtr->outlineStipple) != TCL_OK) {
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
- }
- if (arcPtr->style != arcUid) {
+ if (arcPtr->style != ARC_STYLE) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
- if (arcPtr->style == chordUid) {
+ if (arcPtr->style == CHORD_STYLE) {
Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
CHORD_OUTLINE_PTS);
} else {
Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr,
PIE_OUTLINE1_PTS);
- if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor)
+ if (Tk_CanvasPsColor(interp, canvas, color)
!= TCL_OK) {
return TCL_ERROR;
}
- if (arcPtr->outlineStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "clip ", (char *) NULL);
if (Tk_CanvasPsStipple(interp, canvas,
- arcPtr->outlineStipple) != TCL_OK) {
+ stipple) != TCL_OK) {
return TCL_ERROR;
}
} else {
@@ -1697,14 +2024,14 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
PIE_OUTLINE2_PTS);
}
- if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor)
+ if (Tk_CanvasPsColor(interp, canvas, color)
!= TCL_OK) {
return TCL_ERROR;
}
- if (arcPtr->outlineStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "clip ", (char *) NULL);
if (Tk_CanvasPsStipple(interp, canvas,
- arcPtr->outlineStipple) != TCL_OK) {
+ stipple) != TCL_OK) {
return TCL_ERROR;
}
} else {
@@ -1715,3 +2042,107 @@ ArcToPostscript(interp, canvas, itemPtr, prepass)
return TCL_OK;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * StyleParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-style" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The state for a given item gets replaced by the state
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+StyleParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register Style *stylePtr = (Style *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *stylePtr = PIESLICE_STYLE;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'a') && (strncmp(value, "arc", length) == 0)) {
+ *stylePtr = ARC_STYLE;
+ return TCL_OK;
+ }
+ if ((c == 'c') && (strncmp(value, "chord", length) == 0)) {
+ *stylePtr = CHORD_STYLE;
+ return TCL_OK;
+ }
+ if ((c == 'p') && (strncmp(value, "pieslice", length) == 0)) {
+ *stylePtr = PIESLICE_STYLE;
+ return TCL_OK;
+ }
+
+ Tcl_AppendResult(interp, "bad -style option \"",
+ value, "\": must be arc, chord, or pieslice",
+ (char *) NULL);
+ *stylePtr = PIESLICE_STYLE;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * StylePrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-style"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the state for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static char *
+StylePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Ignored. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register Style *stylePtr = (Style *) (widgRec + offset);
+
+ if (*stylePtr==ARC_STYLE) {
+ return "arc";
+ } else if (*stylePtr==CHORD_STYLE) {
+ return "chord";
+ } else {
+ return "pieslice";
+ }
+}
+
diff --git a/tk/generic/tkCanvBmap.c b/tk/generic/tkCanvBmap.c
index 74087e2db57..dc35890505d 100644
--- a/tk/generic/tkCanvBmap.c
+++ b/tk/generic/tkCanvBmap.c
@@ -4,7 +4,7 @@
* 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.
@@ -29,8 +29,14 @@ typedef struct BitmapItem {
Tk_Anchor anchor; /* Where to anchor bitmap relative to
* (x,y). */
Pixmap bitmap; /* Bitmap to display in window. */
+ Pixmap activeBitmap; /* Bitmap to display in window. */
+ Pixmap disabledBitmap; /* Bitmap to display in window. */
XColor *fgColor; /* Foreground color to use for bitmap. */
+ XColor *activeFgColor; /* Foreground color to use for bitmap. */
+ XColor *disabledFgColor; /* Foreground color to use for bitmap. */
XColor *bgColor; /* Background color to use for bitmap. */
+ XColor *activeBgColor; /* Background color to use for bitmap. */
+ XColor *disabledBgColor; /* Background color to use for bitmap. */
GC gc; /* Graphics context to use for drawing
* bitmap on screen. */
} BitmapItem;
@@ -39,19 +45,42 @@ typedef struct BitmapItem {
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_COLOR, "-activebackground", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(BitmapItem, activeBgColor), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activebitmap", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(BitmapItem, activeBitmap), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-activeforeground", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(BitmapItem, activeFgColor), TK_CONFIG_NULL_OK},
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
"center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_COLOR, "-background", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK},
{TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-disabledbackground", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(BitmapItem, disabledBgColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledbitmap", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(BitmapItem, disabledBitmap),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-disabledforeground", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(BitmapItem, disabledFgColor),
+ TK_CONFIG_NULL_OK},
{TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
"black", Tk_Offset(BitmapItem, fgColor), 0},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
@@ -64,7 +93,7 @@ static Tk_ConfigSpec configSpecs[] = {
static int BitmapCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv));
+ Tcl_Obj *CONST argv[]));
static int BitmapToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double BitmapToPoint _ANSI_ARGS_((Tk_Canvas canvas,
@@ -75,10 +104,10 @@ static void ComputeBitmapBbox _ANSI_ARGS_((Tk_Canvas canvas,
BitmapItem *bmapPtr));
static int ConfigureBitmap _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
-static int tkCreateBitmap _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *CONST argv[], int flags));
+static int CreateBitmap _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteBitmap _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayBitmap _ANSI_ARGS_((Tk_Canvas canvas,
@@ -98,13 +127,13 @@ static void TranslateBitmap _ANSI_ARGS_((Tk_Canvas canvas,
Tk_ItemType tkBitmapType = {
"bitmap", /* name */
sizeof(BitmapItem), /* itemSize */
- tkCreateBitmap, /* createProc */
+ CreateBitmap, /* createProc */
configSpecs, /* configSpecs */
ConfigureBitmap, /* configureProc */
BitmapCoords, /* coordProc */
DeleteBitmap, /* deleteProc */
DisplayBitmap, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
BitmapToPoint, /* pointProc */
BitmapToArea, /* areaProc */
BitmapToPostscript, /* postscriptProc */
@@ -115,13 +144,13 @@ Tk_ItemType tkBitmapType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
*--------------------------------------------------------------
*
- * tkCreateBitmap --
+ * CreateBitmap --
*
* This procedure is invoked to create a new bitmap
* item in a canvas.
@@ -129,7 +158,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:
@@ -139,17 +168,30 @@ Tk_ItemType tkBitmapType = {
*/
static int
-tkCreateBitmap(interp, canvas, itemPtr, argc, argv)
+CreateBitmap(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_Obj *CONST argv[]; /* Arguments describing rectangle. */
{
BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
+ int i;
+
+ if (argc==1) {
+ i = 1;
+ } else {
+ char *arg = Tcl_GetStringFromObj(argv[1], NULL);
+ if (((argc>1) && (arg[0] == '-')
+ && (arg[1] >= 'a') && (arg[1] <= 'z'))) {
+ i = 1;
+ } else {
+ i = 2;
+ }
+ }
- if (argc < 2) {
+ if (argc < i) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
itemPtr->typePtr->name, " x y ?options?\"",
@@ -163,25 +205,30 @@ tkCreateBitmap(interp, canvas, itemPtr, argc, argv)
bmapPtr->anchor = TK_ANCHOR_CENTER;
bmapPtr->bitmap = None;
+ bmapPtr->activeBitmap = None;
+ bmapPtr->disabledBitmap = None;
bmapPtr->fgColor = NULL;
+ bmapPtr->activeFgColor = NULL;
+ bmapPtr->disabledFgColor = NULL;
bmapPtr->bgColor = NULL;
+ bmapPtr->activeBgColor = NULL;
+ bmapPtr->disabledBgColor = NULL;
bmapPtr->gc = None;
/*
* Process the arguments to fill in the item record.
*/
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1], &bmapPtr->y)
- != TCL_OK)) {
- return TCL_ERROR;
+ if ((BitmapCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
+ goto error;
}
-
- if (ConfigureBitmap(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
- DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
- return TCL_ERROR;
+ if (ConfigureBitmap(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
+
+ error:
+ DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
}
/*
@@ -194,7 +241,7 @@ tkCreateBitmap(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.
@@ -210,26 +257,42 @@ BitmapCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
- char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
if (argc == 0) {
- Tcl_PrintDouble(interp, bmapPtr->x, x);
- Tcl_PrintDouble(interp, bmapPtr->y, y);
- Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
- } else if (argc == 2) {
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1], &bmapPtr->y)
- != TCL_OK)) {
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(bmapPtr->x);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(bmapPtr->y);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ } else if (argc <3) {
+ if (argc==1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (argc != 2) {
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1], &bmapPtr->y)
+ != TCL_OK)) {
return TCL_ERROR;
}
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 +308,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.
@@ -259,7 +322,7 @@ ConfigureBitmap(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Bitmap item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
@@ -267,10 +330,14 @@ ConfigureBitmap(interp, canvas, itemPtr, argc, argv, flags)
GC newGC;
Tk_Window tkwin;
unsigned long mask;
+ XColor *fgColor;
+ XColor *bgColor;
+ Pixmap bitmap;
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) bmapPtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) bmapPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -279,17 +346,67 @@ ConfigureBitmap(interp, canvas, itemPtr, argc, argv, flags)
* that determine the graphics context.
*/
- gcValues.foreground = bmapPtr->fgColor->pixel;
+ state = itemPtr->state;
+
+ if (bmapPtr->activeFgColor!=NULL ||
+ bmapPtr->activeBgColor!=NULL ||
+ bmapPtr->activeBitmap!=None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ ComputeBitmapBbox(canvas, bmapPtr);
+ return TCL_OK;
+ }
+ fgColor = bmapPtr->fgColor;
+ bgColor = bmapPtr->bgColor;
+ bitmap = bmapPtr->bitmap;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (bmapPtr->activeFgColor!=NULL) {
+ fgColor = bmapPtr->activeFgColor;
+ }
+ if (bmapPtr->activeBgColor!=NULL) {
+ bgColor = bmapPtr->activeBgColor;
+ }
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (bmapPtr->disabledFgColor!=NULL) {
+ fgColor = bmapPtr->disabledFgColor;
+ }
+ if (bmapPtr->disabledBgColor!=NULL) {
+ bgColor = bmapPtr->disabledBgColor;
+ }
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
+
+ if (state==TK_STATE_DISABLED || bitmap == None) {
+ ComputeBitmapBbox(canvas, bmapPtr);
+ return TCL_OK;
+ }
+
+ gcValues.foreground = fgColor->pixel;
mask = GCForeground;
- if (bmapPtr->bgColor != NULL) {
- gcValues.background = bmapPtr->bgColor->pixel;
+ if (bgColor != NULL) {
+ gcValues.background = bgColor->pixel;
mask |= GCBackground;
} else {
- gcValues.clip_mask = bmapPtr->bitmap;
+ gcValues.clip_mask = bitmap;
mask |= GCClipMask;
}
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, bmapPtr->fgColor,
- bmapPtr->bgColor);
+ if (bitmap == None) {
+ newGC = None;
+ } else {
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
if (bmapPtr->gc != None) {
Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
}
@@ -329,12 +446,30 @@ DeleteBitmap(canvas, itemPtr, display)
if (bmapPtr->bitmap != None) {
Tk_FreeBitmap(display, bmapPtr->bitmap);
}
+ if (bmapPtr->activeBitmap != None) {
+ Tk_FreeBitmap(display, bmapPtr->activeBitmap);
+ }
+ if (bmapPtr->disabledBitmap != None) {
+ Tk_FreeBitmap(display, bmapPtr->disabledBitmap);
+ }
if (bmapPtr->fgColor != NULL) {
Tk_FreeColor(bmapPtr->fgColor);
}
+ if (bmapPtr->activeFgColor != NULL) {
+ Tk_FreeColor(bmapPtr->activeFgColor);
+ }
+ if (bmapPtr->disabledFgColor != NULL) {
+ Tk_FreeColor(bmapPtr->disabledFgColor);
+ }
if (bmapPtr->bgColor != NULL) {
Tk_FreeColor(bmapPtr->bgColor);
}
+ if (bmapPtr->activeBgColor != NULL) {
+ Tk_FreeColor(bmapPtr->activeBgColor);
+ }
+ if (bmapPtr->disabledBgColor != NULL) {
+ Tk_FreeColor(bmapPtr->disabledBgColor);
+ }
if (bmapPtr->gc != NULL) {
Tk_FreeGC(display, bmapPtr->gc);
}
@@ -369,11 +504,27 @@ ComputeBitmapBbox(canvas, bmapPtr)
{
int width, height;
int x, y;
+ Pixmap bitmap;
+ Tk_State state = bmapPtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ bitmap = bmapPtr->bitmap;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)bmapPtr) {
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5));
y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5));
- if (bmapPtr->bitmap == None) {
+ if (state==TK_STATE_HIDDEN || bitmap == None) {
bmapPtr->header.x1 = bmapPtr->header.x2 = x;
bmapPtr->header.y1 = bmapPtr->header.y2 = y;
return;
@@ -459,6 +610,10 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height)
BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
int bmapX, bmapY, bmapWidth, bmapHeight;
short drawableX, drawableY;
+ XColor *fgColor;
+ XColor *bgColor;
+ Pixmap bitmap;
+ Tk_State state = itemPtr->state;
/*
* If the area being displayed doesn't cover the whole bitmap,
@@ -466,7 +621,35 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height)
* redisplay.
*/
- if (bmapPtr->bitmap != None) {
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ fgColor = bmapPtr->fgColor;
+ bgColor = bmapPtr->bgColor;
+ bitmap = bmapPtr->bitmap;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (bmapPtr->activeFgColor!=NULL) {
+ fgColor = bmapPtr->activeFgColor;
+ }
+ if (bmapPtr->activeBgColor!=NULL) {
+ bgColor = bmapPtr->activeBgColor;
+ }
+ if (bmapPtr->activeBitmap!=None) {
+ bitmap = bmapPtr->activeBitmap;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (bmapPtr->disabledFgColor!=NULL) {
+ fgColor = bmapPtr->disabledFgColor;
+ }
+ if (bmapPtr->disabledBgColor!=NULL) {
+ bgColor = bmapPtr->disabledBgColor;
+ }
+ if (bmapPtr->disabledBitmap!=None) {
+ bitmap = bmapPtr->disabledBitmap;
+ }
+ }
+
+ if (bitmap != None) {
if (x > bmapPtr->header.x1) {
bmapX = x - bmapPtr->header.x1;
bmapWidth = bmapPtr->header.x2 - x;
@@ -502,9 +685,10 @@ DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height)
XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
drawableY - bmapY);
- XCopyPlane(display, bmapPtr->bitmap, drawable,
+ XCopyPlane(display, bitmap, drawable,
bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
(unsigned int) bmapHeight, drawableX, drawableY, 1);
+ XSetClipOrigin(display, bmapPtr->gc, 0, 0);
}
}
@@ -691,7 +875,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.
*
@@ -716,7 +900,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;
@@ -750,7 +934,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/tk/generic/tkCanvImg.c b/tk/generic/tkCanvImg.c
index eb3df385c6b..ebfed526748 100644
--- a/tk/generic/tkCanvImg.c
+++ b/tk/generic/tkCanvImg.c
@@ -4,7 +4,7 @@
* 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.
@@ -31,23 +31,45 @@ typedef struct ImageItem {
* (x,y). */
char *imageString; /* String describing -image option (malloc-ed).
* NULL means no image right now. */
+ char *activeImageString; /* String describing -activeimage option.
+ * NULL means no image right now. */
+ char *disabledImageString; /* String describing -disabledimage option.
+ * NULL means no image right now. */
Tk_Image image; /* Image to display in window, or NULL if
* no image at present. */
+ Tk_Image activeImage; /* Image to display in window, or NULL if
+ * no image at present. */
+ Tk_Image disabledImage; /* Image to display in window, or NULL if
+ * no image at present. */
} ImageItem;
/*
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_STRING, "-activeimage", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ImageItem, activeImageString),
+ TK_CONFIG_NULL_OK},
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
"center", Tk_Offset(ImageItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_STRING, "-disabledimage", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(ImageItem, disabledImageString),
+ TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-image", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(ImageItem, imageString), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
@@ -63,19 +85,21 @@ static void ImageChangedProc _ANSI_ARGS_((ClientData clientData,
int imgHeight));
static int ImageCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv));
+ Tcl_Obj *CONST argv[]));
static int ImageToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double ImageToPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *coordPtr));
+static int ImageToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
static void ComputeImageBbox _ANSI_ARGS_((Tk_Canvas canvas,
ImageItem *imgPtr));
static int ConfigureImage _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int CreateImage _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteImage _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayImage _ANSI_ARGS_((Tk_Canvas canvas,
@@ -101,10 +125,10 @@ Tk_ItemType tkImageType = {
ImageCoords, /* coordProc */
DeleteImage, /* deleteProc */
DisplayImage, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
ImageToPoint, /* pointProc */
ImageToArea, /* areaProc */
- (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */
+ ImageToPostscript, /* postscriptProc */
ScaleImage, /* scaleProc */
TranslateImage, /* translateProc */
(Tk_ItemIndexProc *) NULL, /* indexProc */
@@ -112,7 +136,7 @@ Tk_ItemType tkImageType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -126,7 +150,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:
@@ -142,11 +166,24 @@ CreateImage(interp, canvas, itemPtr, argc, argv)
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_Obj *CONST argv[]; /* Arguments describing rectangle. */
{
ImageItem *imgPtr = (ImageItem *) itemPtr;
+ int i;
- if (argc < 2) {
+ if (argc==1) {
+ i = 1;
+ } else {
+ char *arg = Tcl_GetStringFromObj((Tcl_Obj *) argv[1], NULL);
+ if (((argc>1) && (arg[0] == '-')
+ && (arg[1] >= 'a') && (arg[1] <= 'z'))) {
+ i = 1;
+ } else {
+ i = 2;
+ }
+ }
+
+ if (argc < i) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
itemPtr->typePtr->name, " x y ?options?\"",
@@ -161,23 +198,26 @@ CreateImage(interp, canvas, itemPtr, argc, argv)
imgPtr->canvas = canvas;
imgPtr->anchor = TK_ANCHOR_CENTER;
imgPtr->imageString = NULL;
+ imgPtr->activeImageString = NULL;
+ imgPtr->disabledImageString = NULL;
imgPtr->image = NULL;
+ imgPtr->activeImage = NULL;
+ imgPtr->disabledImage = NULL;
/*
* Process the arguments to fill in the item record.
*/
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1], &imgPtr->y)
- != TCL_OK)) {
- return TCL_ERROR;
+ if ((ImageCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
+ goto error;
}
-
- if (ConfigureImage(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
- DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
- return TCL_ERROR;
+ if (ConfigureImage(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
+
+ error:
+ DeleteImage(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
}
/*
@@ -190,7 +230,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.
@@ -206,26 +246,42 @@ ImageCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
ImageItem *imgPtr = (ImageItem *) itemPtr;
- char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
if (argc == 0) {
- Tcl_PrintDouble(interp, imgPtr->x, x);
- Tcl_PrintDouble(interp, imgPtr->y, y);
- Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
- } else if (argc == 2) {
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
- &imgPtr->y) != TCL_OK)) {
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(imgPtr->x);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(imgPtr->y);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ } else if (argc < 3) {
+ if (argc==1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (argc != 2) {
+ char buf[64];
+
+ sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &imgPtr->x) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
+ &imgPtr->y) != TCL_OK)) {
return TCL_ERROR;
}
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 +297,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.
@@ -255,7 +311,7 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Image item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
ImageItem *imgPtr = (ImageItem *) itemPtr;
@@ -263,8 +319,8 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags)
Tk_Image image;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc,
- argv, (char *) imgPtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) imgPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -275,6 +331,11 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags)
* if it hasn't changed.
*/
+ if (imgPtr->activeImageString != NULL) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
if (imgPtr->imageString != NULL) {
image = Tk_GetImage(interp, tkwin, imgPtr->imageString,
ImageChangedProc, (ClientData) imgPtr);
@@ -288,6 +349,32 @@ ConfigureImage(interp, canvas, itemPtr, argc, argv, flags)
Tk_FreeImage(imgPtr->image);
}
imgPtr->image = image;
+ if (imgPtr->activeImageString != NULL) {
+ image = Tk_GetImage(interp, tkwin, imgPtr->activeImageString,
+ ImageChangedProc, (ClientData) imgPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (imgPtr->activeImage != NULL) {
+ Tk_FreeImage(imgPtr->activeImage);
+ }
+ imgPtr->activeImage = image;
+ if (imgPtr->disabledImageString != NULL) {
+ image = Tk_GetImage(interp, tkwin, imgPtr->disabledImageString,
+ ImageChangedProc, (ClientData) imgPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (imgPtr->disabledImage != NULL) {
+ Tk_FreeImage(imgPtr->disabledImage);
+ }
+ imgPtr->disabledImage = image;
ComputeImageBbox(canvas, imgPtr);
return TCL_OK;
}
@@ -321,9 +408,21 @@ DeleteImage(canvas, itemPtr, display)
if (imgPtr->imageString != NULL) {
ckfree(imgPtr->imageString);
}
+ if (imgPtr->activeImageString != NULL) {
+ ckfree(imgPtr->activeImageString);
+ }
+ if (imgPtr->disabledImageString != NULL) {
+ ckfree(imgPtr->disabledImageString);
+ }
if (imgPtr->image != NULL) {
Tk_FreeImage(imgPtr->image);
}
+ if (imgPtr->activeImage != NULL) {
+ Tk_FreeImage(imgPtr->activeImage);
+ }
+ if (imgPtr->disabledImage != NULL) {
+ Tk_FreeImage(imgPtr->disabledImage);
+ }
}
/*
@@ -355,11 +454,27 @@ ComputeImageBbox(canvas, imgPtr)
{
int width, height;
int x, y;
+ Tk_Image image;
+ Tk_State state = imgPtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ image = imgPtr->image;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)imgPtr) {
+ if (imgPtr->activeImage != NULL) {
+ image = imgPtr->activeImage;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (imgPtr->disabledImage != NULL) {
+ image = imgPtr->disabledImage;
+ }
+ }
x = (int) (imgPtr->x + ((imgPtr->x >= 0) ? 0.5 : - 0.5));
y = (int) (imgPtr->y + ((imgPtr->y >= 0) ? 0.5 : - 0.5));
- if (imgPtr->image == None) {
+ if ((state == TK_STATE_HIDDEN) || (image == None)) {
imgPtr->header.x1 = imgPtr->header.x2 = x;
imgPtr->header.y1 = imgPtr->header.y2 = y;
return;
@@ -369,7 +484,7 @@ ComputeImageBbox(canvas, imgPtr)
* Compute location and size of image, using anchor information.
*/
- Tk_SizeOfImage(imgPtr->image, &width, &height);
+ Tk_SizeOfImage(image, &width, &height);
switch (imgPtr->anchor) {
case TK_ANCHOR_N:
x -= width/2;
@@ -443,8 +558,25 @@ DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height)
{
ImageItem *imgPtr = (ImageItem *) itemPtr;
short drawableX, drawableY;
+ Tk_Image image;
+ Tk_State state = itemPtr->state;
- if (imgPtr->image == NULL) {
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ image = imgPtr->image;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (imgPtr->activeImage != NULL) {
+ image = imgPtr->activeImage;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (imgPtr->disabledImage != NULL) {
+ image = imgPtr->disabledImage;
+ }
+ }
+
+ if (image == NULL) {
return;
}
@@ -454,7 +586,7 @@ DisplayImage(canvas, itemPtr, display, drawable, x, y, width, height)
Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,
&drawableX, &drawableY);
- Tk_RedrawImage(imgPtr->image, x - imgPtr->header.x1, y - imgPtr->header.y1,
+ Tk_RedrawImage(image, x - imgPtr->header.x1, y - imgPtr->header.y1,
width, height, drawable, drawableX, drawableY);
}
@@ -563,6 +695,96 @@ ImageToArea(canvas, itemPtr, rectPtr)
/*
*--------------------------------------------------------------
*
+ * ImageToPostscript --
+ *
+ * This procedure is called to generate Postscript for
+ * image items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error
+ * occurs in generating Postscript then an error message is
+ * left in interp->result, replacing whatever used to be there.
+ * If no error occurs, then Postscript for the item is appended
+ * to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ImageToPostscript(interp, canvas, itemPtr, prepass)
+ Tcl_Interp *interp; /* Leave Postscript or error message
+ * here. */
+ Tk_Canvas canvas; /* Information about overall canvas. */
+ Tk_Item *itemPtr; /* Item for which Postscript is
+ * wanted. */
+ int prepass; /* 1 means this is a prepass to
+ * collect font information; 0 means
+ * final Postscript is being created.*/
+{
+ ImageItem *imgPtr = (ImageItem *)itemPtr;
+ Tk_Window canvasWin = Tk_CanvasTkwin(canvas);
+
+ char buffer[256];
+ double x, y;
+ int width, height;
+ Tk_Image image;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ image = imgPtr->image;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (imgPtr->activeImage != NULL) {
+ image = imgPtr->activeImage;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (imgPtr->disabledImage != NULL) {
+ image = imgPtr->disabledImage;
+ }
+ }
+ Tk_SizeOfImage(image, &width, &height);
+
+ /*
+ * Compute the coordinates of the lower-left corner of the image,
+ * taking into account the anchor position for the image.
+ */
+
+ x = imgPtr->x;
+ y = Tk_CanvasPsY(canvas, imgPtr->y);
+
+ switch (imgPtr->anchor) {
+ case TK_ANCHOR_NW: y -= height; break;
+ case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
+ case TK_ANCHOR_NE: x -= width; y -= height; break;
+ case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
+ case TK_ANCHOR_SE: x -= width; break;
+ case TK_ANCHOR_S: x -= width/2.0; break;
+ case TK_ANCHOR_SW: break;
+ case TK_ANCHOR_W: y -= height/2.0; break;
+ case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
+ }
+
+ if (image == NULL) {
+ return TCL_OK;
+ }
+
+ if (!prepass) {
+ sprintf(buffer, "%.15g %.15g", x, y);
+ Tcl_AppendResult(interp, buffer, " translate\n", (char *) NULL);
+ }
+
+ return Tk_PostscriptImage(image, interp, canvasWin,
+ ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* ScaleImage --
*
* This procedure is invoked to rescale an item.
@@ -675,3 +897,4 @@ ImageChangedProc(clientData, x, y, width, height, imgWidth, imgHeight)
imgPtr->header.y1 + y, (int) (imgPtr->header.x1 + x + width),
(int) (imgPtr->header.y1 + y + height));
}
+
diff --git a/tk/generic/tkCanvLine.c b/tk/generic/tkCanvLine.c
index 2125446742d..fc2174b710b 100644
--- a/tk/generic/tkCanvLine.c
+++ b/tk/generic/tkCanvLine.c
@@ -4,7 +4,8 @@
* 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.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -15,17 +16,23 @@
#include <stdio.h>
#include "tkInt.h"
#include "tkPort.h"
+#include "tkCanvas.h"
/*
* The structure below defines the record for each line item.
*/
+typedef enum {
+ ARROWS_NONE, ARROWS_FIRST, ARROWS_LAST, ARROWS_BOTH
+} Arrows;
+
typedef struct LineItem {
Tk_Item header; /* Generic stuff that's the same for all
* types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
Tk_Canvas canvas; /* Canvas containing item. Needed for
* parsing arrow shapes. */
- int numPoints; /* Number of points in line (always >= 2). */
+ int numPoints; /* Number of points in line (always >= 0). */
double *coordPtr; /* Pointer to malloc-ed array containing
* x- and y-coords of all points in line.
* X-coords are even-valued indices, y-coords
@@ -36,14 +43,10 @@ typedef struct LineItem {
* their tips. The actual endpoints are
* stored in the *firstArrowPtr and
* *lastArrowPtr, if they exist. */
- int width; /* Width of line. */
- XColor *fg; /* Foreground color for line. */
- Pixmap fillStipple; /* Stipple bitmap for filling line. */
int capStyle; /* Cap style for line. */
int joinStyle; /* Join style for line. */
- GC gc; /* Graphics context for filling line. */
GC arrowGC; /* Graphics context for drawing arrowheads. */
- Tk_Uid arrow; /* Indicates whether or not to draw arrowheads:
+ Arrows arrow; /* Indicates whether or not to draw arrowheads:
* "none", "first", "last", or "both". */
float arrowShapeA; /* Distance from tip of arrowhead to center. */
float arrowShapeB; /* Distance from tip of arrowhead to trailing
@@ -59,7 +62,7 @@ typedef struct LineItem {
* point in line (PTS_IN_ARROW points, first
* of which is tip). Malloc'ed. NULL means
* no arrowhead at last point. */
- int smooth; /* Non-zero means draw line smoothed (i.e.
+ Tk_SmoothMethod *smooth; /* Non-zero means draw line smoothed (i.e.
* with Bezier splines). */
int splineSteps; /* Number of steps in each spline segment. */
} LineItem;
@@ -81,29 +84,42 @@ static void ComputeLineBbox _ANSI_ARGS_((Tk_Canvas canvas,
LineItem *linePtr));
static int ConfigureLine _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int ConfigureArrows _ANSI_ARGS_((Tk_Canvas canvas,
LineItem *linePtr));
static int CreateLine _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteLine _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayLine _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display, Drawable dst,
int x, int y, int width, int height));
+static int GetLineIndex _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ Tcl_Obj *obj, int *indexPtr));
static int LineCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
+static void LineDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr, int first, int last));
+static void LineInsert _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj));
static int LineToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double LineToPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *coordPtr));
static int LineToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
+static int ArrowParseProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST char *value, char *recordPtr, int offset));
+static char * ArrowPrintProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *recordPtr, int offset,
+ Tcl_FreeProc **freeProcPtr));
static int ParseArrowShape _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, Tk_Window tkwin, char *value,
- char *recordPtr, int offset));
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST char *value, char *recordPtr, int offset));
static char * PrintArrowShape _ANSI_ARGS_((ClientData clientData,
Tk_Window tkwin, char *recordPtr, int offset,
Tcl_FreeProc **freeProcPtr));
@@ -119,34 +135,101 @@ static void TranslateLine _ANSI_ARGS_((Tk_Canvas canvas,
* values in CreateLine.
*/
-static Tk_CustomOption arrowShapeOption = {ParseArrowShape,
- PrintArrowShape, (ClientData) NULL};
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption arrowShapeOption = {
+ (Tk_OptionParseProc *) ParseArrowShape,
+ PrintArrowShape, (ClientData) NULL
+};
+static Tk_CustomOption arrowOption = {
+ (Tk_OptionParseProc *) ArrowParseProc,
+ ArrowPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption smoothOption = {
+ (Tk_OptionParseProc *) TkSmoothParseProc,
+ TkSmoothPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
+static Tk_CustomOption dashOption = {
+ (Tk_OptionParseProc *) TkCanvasDashParseProc,
+ TkCanvasDashPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc,
+ (ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
+};
+static Tk_CustomOption pixelOption = {
+ (Tk_OptionParseProc *) TkPixelParseProc,
+ TkPixelPrintProc, (ClientData) NULL
+};
static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_UID, "-arrow", (char *) NULL, (char *) NULL,
- "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.activeColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(LineItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-arrow", (char *) NULL, (char *) NULL,
+ "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT, &arrowOption},
{TK_CONFIG_CUSTOM, "-arrowshape", (char *) NULL, (char *) NULL,
"8 10 3", Tk_Offset(LineItem, arrowShapeA),
TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},
{TK_CONFIG_CAP_STYLE, "-capstyle", (char *) NULL, (char *) NULL,
"butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
- "black", Tk_Offset(LineItem, fg), TK_CONFIG_NULL_OK},
+ "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(LineItem, outline.offset),
+ TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(LineItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL,
"round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_BOOLEAN, "-smooth", (char *) NULL, (char *) NULL,
- "0", Tk_Offset(LineItem, smooth), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(LineItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(LineItem, smooth),
+ TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
{TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
"12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(LineItem, fillStipple), TK_CONFIG_NULL_OK},
+ (char *) NULL, Tk_Offset(LineItem, outline.stipple),
+ TK_CONFIG_NULL_OK},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
- {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
- "1", Tk_Offset(LineItem, width), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
+ "1.0", Tk_Offset(LineItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
@@ -165,30 +248,21 @@ Tk_ItemType tkLineType = {
LineCoords, /* coordProc */
DeleteLine, /* deleteProc */
DisplayLine, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
LineToPoint, /* pointProc */
LineToArea, /* areaProc */
LineToPostscript, /* postscriptProc */
ScaleLine, /* scaleProc */
TranslateLine, /* translateProc */
- (Tk_ItemIndexProc *) NULL, /* indexProc */
+ (Tk_ItemIndexProc *) GetLineIndex, /* indexProc */
(Tk_ItemCursorProc *) NULL, /* icursorProc */
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
- (Tk_ItemInsertProc *) NULL, /* insertProc */
- (Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemInsertProc *) LineInsert, /* insertProc */
+ LineDeleteCoords, /* dTextProc */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
- * The Tk_Uid's below refer to uids for the various arrow types:
- */
-
-static Tk_Uid noneUid = NULL;
-static Tk_Uid firstUid = NULL;
-static Tk_Uid lastUid = NULL;
-static Tk_Uid bothUid = NULL;
-
-/*
* The definition below determines how large are static arrays
* used to hold spline points (splines larger than this have to
* have their arrays malloc-ed).
@@ -207,7 +281,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:
@@ -223,48 +297,31 @@ CreateLine(interp, canvas, itemPtr, argc, argv)
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 line. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing line. */
{
LineItem *linePtr = (LineItem *) itemPtr;
int i;
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
- itemPtr->typePtr->name, " x1 y1 x2 y2 ?x3 y3 ...? ?options?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
/*
* Carry out initialization that is needed to set defaults and to
* allow proper cleanup after errors during the the remainder of
* this procedure.
*/
+ Tk_CreateOutline(&(linePtr->outline));
linePtr->canvas = canvas;
linePtr->numPoints = 0;
linePtr->coordPtr = NULL;
- linePtr->width = 1;
- linePtr->fg = None;
- linePtr->fillStipple = None;
linePtr->capStyle = CapButt;
linePtr->joinStyle = JoinRound;
- linePtr->gc = None;
linePtr->arrowGC = None;
- if (noneUid == NULL) {
- noneUid = Tk_GetUid("none");
- firstUid = Tk_GetUid("first");
- lastUid = Tk_GetUid("last");
- bothUid = Tk_GetUid("both");
- }
- linePtr->arrow = noneUid;
+ linePtr->arrow = ARROWS_NONE;
linePtr->arrowShapeA = (float)8.0;
linePtr->arrowShapeB = (float)10.0;
linePtr->arrowShapeC = (float)3.0;
linePtr->firstArrowPtr = NULL;
linePtr->lastArrowPtr = NULL;
- linePtr->smooth = 0;
+ linePtr->smooth = (Tk_SmoothMethod *) NULL;
linePtr->splineSteps = 12;
/*
@@ -273,14 +330,14 @@ CreateLine(interp, canvas, itemPtr, argc, argv)
* start with a digit or a minus sign followed by a digit.
*/
- for (i = 4; i < (argc-1); i+=2) {
- if ((!isdigit(UCHAR(argv[i][0]))) &&
- ((argv[i][0] != '-')
- || ((argv[i][1] != '.') && !isdigit(UCHAR(argv[i][1]))))) {
+ for (i = 0; i < argc; i++) {
+ char *arg = Tcl_GetStringFromObj(argv[i], NULL);
+ if ((arg[0] == '-') && (arg[1] >= 'a')
+ && (arg[1] <= 'z')) {
break;
}
}
- if (LineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK) {
+ if (i && (LineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
goto error;
}
if (ConfigureLine(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
@@ -302,7 +359,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.
@@ -318,16 +375,16 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
LineItem *linePtr = (LineItem *) itemPtr;
- char buffer[TCL_DOUBLE_SPACE];
int i, numPoints;
+ double *coordPtr;
if (argc == 0) {
- double *coordPtr;
int numCoords;
+ Tcl_Obj *subobj, *obj = Tcl_NewObj();
numCoords = 2*linePtr->numPoints;
if (linePtr->firstArrowPtr != NULL) {
@@ -342,35 +399,46 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
if ((linePtr->lastArrowPtr != NULL) && (i == (numCoords-2))) {
coordPtr = linePtr->lastArrowPtr;
}
- Tcl_PrintDouble(interp, *coordPtr, buffer);
- Tcl_AppendElement(interp, buffer);
+ subobj = Tcl_NewDoubleObj(*coordPtr);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
}
- } else if (argc < 4) {
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+ }
+ if (argc == 1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (argc & 1) {
Tcl_AppendResult(interp,
- "too few coordinates for line: must have at least 4",
+ "odd number of coordinates specified for line",
(char *) NULL);
return TCL_ERROR;
- } else if (argc & 1) {
+ } else if (argc < 4) {
Tcl_AppendResult(interp,
- "odd number of coordinates specified for line",
+ "too few coordinates specified for line",
(char *) NULL);
return TCL_ERROR;
} else {
numPoints = argc/2;
if (linePtr->numPoints != numPoints) {
+ coordPtr = (double *) ckalloc((unsigned)
+ (sizeof(double) * argc));
if (linePtr->coordPtr != NULL) {
ckfree((char *) linePtr->coordPtr);
}
- linePtr->coordPtr = (double *) ckalloc((unsigned)
- (sizeof(double) * argc));
+ linePtr->coordPtr = coordPtr;
linePtr->numPoints = numPoints;
}
- for (i = argc-1; i >= 0; i--) {
- if (Tk_CanvasGetCoord(interp, canvas, argv[i],
- &linePtr->coordPtr[i]) != TCL_OK) {
- return TCL_ERROR;
- }
- }
+ coordPtr = linePtr->coordPtr;
+ for (i = 0; i <argc; i++) {
+ if (Tk_CanvasGetCoordFromObj(interp, canvas, argv[i],
+ coordPtr++) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
/*
* Update arrowheads by throwing away any existing arrow-head
@@ -385,7 +453,7 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
ckfree((char *) linePtr->lastArrowPtr);
linePtr->lastArrowPtr = NULL;
}
- if (linePtr->arrow != noneUid) {
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
ComputeLineBbox(canvas, linePtr);
@@ -403,7 +471,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
@@ -418,7 +486,7 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Line item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
LineItem *linePtr = (LineItem *) itemPtr;
@@ -426,10 +494,11 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
GC newGC, arrowGC;
unsigned long mask;
Tk_Window tkwin;
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) linePtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) linePtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -438,36 +507,42 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
* graphics contexts.
*/
- if (linePtr->fg == NULL) {
- newGC = arrowGC = None;
+ state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (linePtr->outline.activeWidth > linePtr->outline.width ||
+ linePtr->outline.activeDash.number != 0 ||
+ linePtr->outline.activeColor != NULL ||
+ linePtr->outline.activeStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
} else {
- gcValues.foreground = linePtr->fg->pixel;
- gcValues.join_style = linePtr->joinStyle;
- if (linePtr->width < 0) {
- linePtr->width = 1;
- }
- gcValues.line_width = linePtr->width;
- mask = GCForeground|GCJoinStyle|GCLineWidth;
- if (linePtr->fillStipple != None) {
- gcValues.stipple = linePtr->fillStipple;
- gcValues.fill_style = FillStippled;
- mask |= GCStipple|GCFillStyle;
- }
- if (linePtr->arrow == noneUid) {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(linePtr->outline));
+ if (mask) {
+ if (linePtr->arrow == ARROWS_NONE) {
gcValues.cap_style = linePtr->capStyle;
mask |= GCCapStyle;
}
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, linePtr->fg, NULL);
+ gcValues.join_style = linePtr->joinStyle;
+ mask |= GCJoinStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
gcValues.line_width = 0;
- arrowGC = Tk_GetGCColor(tkwin, mask, &gcValues, linePtr->fg, NULL);
+ arrowGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = arrowGC = None;
}
- if (linePtr->gc != None) {
- Tk_FreeGC(Tk_Display(tkwin), linePtr->gc);
+ if (linePtr->outline.gc != None) {
+ Tk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);
}
if (linePtr->arrowGC != None) {
Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);
}
- linePtr->gc = newGC;
+ linePtr->outline.gc = newGC;
linePtr->arrowGC = arrowGC;
/*
@@ -480,21 +555,26 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
linePtr->splineSteps = 100;
}
+ if ((!linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {
+ ComputeLineBbox(canvas, linePtr);
+ return TCL_OK;
+ }
+
/*
* Setup arrowheads, if needed. If arrowheads are turned off,
* restore the line's endpoints (they were shortened when the
* arrowheads were added).
*/
- if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != firstUid)
- && (linePtr->arrow != bothUid)) {
+ if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST)
+ && (linePtr->arrow != ARROWS_BOTH)) {
linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
ckfree((char *) linePtr->firstArrowPtr);
linePtr->firstArrowPtr = NULL;
}
- if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != lastUid)
- && (linePtr->arrow != bothUid)) {
+ if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != ARROWS_LAST)
+ && (linePtr->arrow != ARROWS_BOTH)) {
int i;
i = 2*(linePtr->numPoints-1);
@@ -503,15 +583,7 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
ckfree((char *) linePtr->lastArrowPtr);
linePtr->lastArrowPtr = NULL;
}
- if (linePtr->arrow != noneUid) {
- if ((linePtr->arrow != firstUid) && (linePtr->arrow != lastUid)
- && (linePtr->arrow != bothUid)) {
- Tcl_AppendResult(interp, "bad arrow spec \"",
- linePtr->arrow, "\": must be none, first, last, or both",
- (char *) NULL);
- linePtr->arrow = noneUid;
- return TCL_ERROR;
- }
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
@@ -550,18 +622,10 @@ DeleteLine(canvas, itemPtr, display)
{
LineItem *linePtr = (LineItem *) itemPtr;
+ Tk_DeleteOutline(display, &(linePtr->outline));
if (linePtr->coordPtr != NULL) {
ckfree((char *) linePtr->coordPtr);
}
- if (linePtr->fg != NULL) {
- Tk_FreeColor(linePtr->fg);
- }
- if (linePtr->fillStipple != None) {
- Tk_FreeBitmap(display, linePtr->fillStipple);
- }
- if (linePtr->gc != None) {
- Tk_FreeGC(display, linePtr->gc);
- }
if (linePtr->arrowGC != None) {
Tk_FreeGC(display, linePtr->arrowGC);
}
@@ -598,7 +662,33 @@ ComputeLineBbox(canvas, linePtr)
* recomputed. */
{
double *coordPtr;
- int i, width;
+ int i, intWidth;
+ double width;
+ Tk_State state = linePtr->header.state;
+ Tk_TSOffset *tsoffset;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (!(linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {
+ linePtr->header.x1 = -1;
+ linePtr->header.x2 = -1;
+ linePtr->header.y1 = -1;
+ linePtr->header.y2 = -1;
+ return;
+ }
+
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
coordPtr = linePtr->coordPtr;
linePtr->header.x1 = linePtr->header.x2 = (int) *coordPtr;
@@ -618,14 +708,66 @@ ComputeLineBbox(canvas, linePtr)
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
}
- width = linePtr->width;
- if (width < 1) {
- width = 1;
+ width = linePtr->outline.width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
+ TkIncludePoint((Tk_Item *) linePtr, linePtr->firstArrowPtr);
+ }
+ if (linePtr->arrow != ARROWS_FIRST) {
+ TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);
+ }
+ }
+
+ tsoffset = &linePtr->outline.tsoffset;
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ double *coordPtr = linePtr->coordPtr + (tsoffset->flags & ~TK_OFFSET_INDEX);
+ if (tsoffset->flags <= 0) {
+ coordPtr = linePtr->coordPtr;
+ if ((linePtr->arrow == ARROWS_FIRST) || (linePtr->arrow == ARROWS_BOTH)) {
+ coordPtr = linePtr->firstArrowPtr;
+ }
+ }
+ if (tsoffset->flags > (linePtr->numPoints * 2)) {
+ coordPtr = linePtr->coordPtr + (linePtr->numPoints * 2);
+ if ((linePtr->arrow == ARROWS_LAST) || (linePtr->arrow == ARROWS_BOTH)) {
+ coordPtr = linePtr->lastArrowPtr;
+ }
+ }
+ tsoffset->xoffset = (int) (coordPtr[0] + 0.5);
+ tsoffset->yoffset = (int) (coordPtr[1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = linePtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (linePtr->header.x1 + linePtr->header.x2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = linePtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = linePtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (linePtr->header.y1 + linePtr->header.y2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = linePtr->header.y2;
+ }
+ }
+
+ intWidth = (int) (width + 0.5);
+ linePtr->header.x1 -= intWidth;
+ linePtr->header.x2 += intWidth;
+ linePtr->header.y1 -= intWidth;
+ linePtr->header.y2 += intWidth;
+
+ if (linePtr->numPoints==1) {
+ linePtr->header.x1 -= 1;
+ linePtr->header.x2 += 1;
+ linePtr->header.y1 -= 1;
+ linePtr->header.y2 += 1;
+ return;
}
- linePtr->header.x1 -= width;
- linePtr->header.x2 += width;
- linePtr->header.y1 -= width;
- linePtr->header.y2 += width;
/*
* For mitered lines, make a second pass through all the points.
@@ -640,7 +782,7 @@ ComputeLineBbox(canvas, linePtr)
int j;
if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
- (double) width, miter, miter+2)) {
+ width, miter, miter+2)) {
for (j = 0; j < 4; j += 2) {
TkIncludePoint((Tk_Item *) linePtr, miter+j);
}
@@ -652,14 +794,14 @@ ComputeLineBbox(canvas, linePtr)
* Add in the sizes of arrowheads, if any.
*/
- if (linePtr->arrow != noneUid) {
- if (linePtr->arrow != lastUid) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
}
}
- if (linePtr->arrow != firstUid) {
+ if (linePtr->arrow != ARROWS_FIRST) {
for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
@@ -710,13 +852,34 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
XPoint staticPoints[MAX_STATIC_POINTS];
XPoint *pointPtr;
XPoint *pPtr;
- double *coordPtr;
+ double *coordPtr, linewidth;
int i, numPoints;
+ Tk_State state = itemPtr->state;
+ Pixmap stipple = linePtr->outline.stipple;
- if (linePtr->gc == None) {
+ if ((!linePtr->numPoints)||(linePtr->outline.gc==None)) {
return;
}
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ linewidth = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ if (linePtr->outline.activeWidth>linewidth) {
+ linewidth = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ if (linePtr->outline.disabledWidth>linewidth) {
+ linewidth = linePtr->outline.activeWidth;
+ }
+ }
/*
* Build up an array of points in screen coordinates. Use a
* static array unless the line has an enormous number of points;
@@ -725,7 +888,9 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
*/
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
} else {
numPoints = linePtr->numPoints;
}
@@ -737,7 +902,7 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
}
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, pointPtr,
(double *) NULL);
} else {
@@ -755,12 +920,21 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
* GC is supposed to be read-only.
*/
- if (linePtr->fillStipple != None) {
- Tk_CanvasSetStippleOrigin(canvas, linePtr->gc);
- Tk_CanvasSetStippleOrigin(canvas, linePtr->arrowGC);
+ if (Tk_ChangeOutlineGC(canvas, itemPtr, &(linePtr->outline))) {
+ Tk_CanvasSetOffset(canvas, linePtr->arrowGC, &linePtr->outline.tsoffset);
}
- XDrawLines(display, drawable, linePtr->gc, pointPtr, numPoints,
+ if (numPoints>1) {
+ XDrawLines(display, drawable, linePtr->outline.gc, pointPtr, numPoints,
CoordModeOrigin);
+ } else {
+ int intwidth = (int) (linewidth + 0.5);
+ if (intwidth<1) {
+ intwidth=1;
+ }
+ XFillArc(display, drawable, linePtr->outline.gc,
+ pointPtr->x - intwidth/2, pointPtr->y - intwidth/2,
+ (unsigned int)intwidth+1, (unsigned int)intwidth+1, 0, 64*360);
+ }
if (pointPtr != staticPoints) {
ckfree((char *) pointPtr);
}
@@ -771,14 +945,13 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
if (linePtr->firstArrowPtr != NULL) {
TkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW,
- display, drawable, linePtr->gc, NULL);
+ display, drawable, linePtr->arrowGC, NULL);
}
if (linePtr->lastArrowPtr != NULL) {
TkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW,
- display, drawable, linePtr->gc, NULL);
+ display, drawable, linePtr->arrowGC, NULL);
}
- if (linePtr->fillStipple != None) {
- XSetTSOrigin(display, linePtr->gc, 0, 0);
+ if (Tk_ResetOutlineGC(canvas, itemPtr, &(linePtr->outline))) {
XSetTSOrigin(display, linePtr->arrowGC, 0, 0);
}
}
@@ -786,6 +959,325 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
/*
*--------------------------------------------------------------
*
+ * LineInsert --
+ *
+ * Insert coords into a line item at a given index.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The coords in the given item is modified.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+LineInsert(canvas, itemPtr, beforeThis, obj)
+ Tk_Canvas canvas; /* Canvas containing text item. */
+ Tk_Item *itemPtr; /* Line item to be modified. */
+ int beforeThis; /* Index before which new coordinates
+ * are to be inserted. */
+ Tcl_Obj *obj; /* New coordinates to be inserted. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int length, argc, i;
+ double *new, *coordPtr;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj **objv;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &argc, &objv) != TCL_OK)
+ || !argc || argc&1) {
+ return;
+ }
+ length = 2*linePtr->numPoints;
+ if (beforeThis < 0) {
+ beforeThis = 0;
+ }
+ if (beforeThis > length) {
+ beforeThis = length;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
+ }
+ new = (double *) ckalloc((unsigned)(sizeof(double) * (length + argc)));
+ for(i=0; i<beforeThis; i++) {
+ new[i] = linePtr->coordPtr[i];
+ }
+ for(i=0; i<argc; i++) {
+ if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i],
+ new+(i+beforeThis))!=TCL_OK) {
+ Tcl_ResetResult(((TkCanvas *)canvas)->interp);
+ ckfree((char *) new);
+ return;
+ }
+ }
+
+ for(i=beforeThis; i<length; i++) {
+ new[i+argc] = linePtr->coordPtr[i];
+ }
+ if(linePtr->coordPtr) ckfree((char *)linePtr->coordPtr);
+ linePtr->coordPtr = new;
+ linePtr->numPoints = (length + argc)/2;
+
+ if ((length>3) && (state != TK_STATE_HIDDEN)) {
+ /*
+ * This is some optimizing code that will result that only the part
+ * of the polygon that changed (and the objects that are overlapping
+ * with that part) need to be redrawn. A special flag is set that
+ * instructs the general canvas code not to redraw the whole
+ * object. If this flag is not set, the canvas will do the redrawing,
+ * otherwise I have to do it here.
+ */
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+
+ if (beforeThis>0) {beforeThis -= 2; argc+=2; }
+ if ((beforeThis+argc)<length) argc+=2;
+ if (linePtr->smooth) {
+ if(beforeThis>0) {
+ beforeThis-=2; argc+=2;
+ }
+ if((beforeThis+argc+2)<length) {
+ argc+=2;
+ }
+ }
+ itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];
+ itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];
+ if ((linePtr->firstArrowPtr != NULL) && (beforeThis<1)) {
+ /* include old first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)>=length)) {
+ /* include old last arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ coordPtr = linePtr->coordPtr+beforeThis+2;
+ for(i=2; i<argc; i+=2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ coordPtr+=2;
+ }
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree((char *) linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree((char *) linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+
+ if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
+ double width;
+ int intWidth;
+ if ((linePtr->firstArrowPtr != NULL) && (beforeThis>2)) {
+ /* include new first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)<(length-2))) {
+ /* include new right arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;
+ itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;
+ Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineDeleteCoords --
+ *
+ * Delete one or more coordinates from a line item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters between "first" and "last", inclusive, get
+ * deleted from itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+LineDeleteCoords(canvas, itemPtr, first, last)
+ Tk_Canvas canvas; /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr; /* Item in which to delete characters. */
+ int first; /* Index of first character to delete. */
+ int last; /* Index of last character to delete. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int count, i, first1, last1;
+ int length = 2*linePtr->numPoints;
+ double *coordPtr;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ first &= -2;
+ last &= -2;
+
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= length) {
+ last = length-2;
+ }
+ if (first > last) {
+ return;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
+ }
+ first1 = first; last1 = last;
+ if(first1>0) first1 -= 2;
+ if(last1<length-2) last1 += 2;
+ if (linePtr->smooth) {
+ if(first1>0) first1 -= 2;
+ if(last1<length-2) last1 += 2;
+ }
+
+ if((first1<2) && (last1 >= length-2)) {
+ /*
+ * This is some optimizing code that will result that only the part
+ * of the line that changed (and the objects that are overlapping
+ * with that part) need to be redrawn. A special flag is set that
+ * instructs the general canvas code not to redraw the whole
+ * object. If this flag is set, the redrawing has to be done here,
+ * otherwise the general Canvas code will take care of it.
+ */
+
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+ itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1];
+ itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1];
+ if ((linePtr->firstArrowPtr != NULL) && (first1<2)) {
+ /* include old first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (last1>=length-2)) {
+ /* include old last arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ coordPtr = linePtr->coordPtr+first1+2;
+ for (i=first1+2; i<=last1; i+=2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ coordPtr+=2;
+ }
+ }
+
+ count = last + 2 - first;
+ for (i=last+2; i<length; i++) {
+ linePtr->coordPtr[i-count] = linePtr->coordPtr[i];
+ }
+ linePtr->numPoints -= count/2;
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree((char *) linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree((char *) linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+ if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
+ double width;
+ int intWidth;
+ if ((linePtr->firstArrowPtr != NULL) && (first1<4)) {
+ /* include new first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (last1>(length-4))) {
+ /* include new right arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;
+ itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;
+ Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* LineToPoint --
*
* Computes the distance from a given point to a given
@@ -810,11 +1302,12 @@ LineToPoint(canvas, itemPtr, pointPtr)
Tk_Item *itemPtr; /* Item to check against point. */
double *pointPtr; /* Pointer to x and y coordinates. */
{
+ Tk_State state = itemPtr->state;
LineItem *linePtr = (LineItem *) itemPtr;
double *coordPtr, *linePoints;
double staticSpace[2*MAX_STATIC_POINTS];
double poly[10];
- double bestDist, dist;
+ double bestDist, dist, width;
int numPoints, count;
int changedMiterToBevel; /* Non-zero means that a mitered corner
* had to be treated as beveled after all
@@ -827,15 +1320,32 @@ LineToPoint(canvas, itemPtr, pointPtr)
* against which to do the check.
*/
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
linePoints = staticSpace;
} else {
linePoints = (double *) ckalloc((unsigned)
(2*numPoints*sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
linePoints);
} else {
@@ -843,6 +1353,19 @@ LineToPoint(canvas, itemPtr, pointPtr)
linePoints = linePtr->coordPtr;
}
+ if (width < 1.0) {
+ width = 1.0;
+ }
+
+ if (!numPoints || itemPtr->state==TK_STATE_HIDDEN) {
+ return bestDist;
+ } else if (numPoints == 1) {
+ bestDist = hypot(linePoints[0] - pointPtr[0], linePoints[1] - pointPtr[1])
+ - width/2.0;
+ if (bestDist < 0) bestDist = 0;
+ return bestDist;
+ }
+
/*
* The overall idea is to iterate through all of the edges of
* the line, computing a polygon for each edge and testing the
@@ -863,7 +1386,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
|| ((linePtr->joinStyle == JoinRound)
&& (count != numPoints))) {
dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
- - linePtr->width/2.0;
+ - width/2.0;
if (dist <= 0.0) {
bestDist = 0.0;
goto done;
@@ -879,7 +1402,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
*/
if (count == numPoints) {
- TkGetButtPoints(coordPtr+2, coordPtr, (double) linePtr->width,
+ TkGetButtPoints(coordPtr+2, coordPtr, width,
linePtr->capStyle == CapProjecting, poly, poly+2);
} else if ((linePtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
poly[0] = poly[6];
@@ -887,7 +1410,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
poly[2] = poly[4];
poly[3] = poly[5];
} else {
- TkGetButtPoints(coordPtr+2, coordPtr, (double) linePtr->width, 0,
+ TkGetButtPoints(coordPtr+2, coordPtr, width, 0,
poly, poly+2);
/*
@@ -911,17 +1434,17 @@ LineToPoint(canvas, itemPtr, pointPtr)
}
}
if (count == 2) {
- TkGetButtPoints(coordPtr, coordPtr+2, (double) linePtr->width,
+ TkGetButtPoints(coordPtr, coordPtr+2, width,
linePtr->capStyle == CapProjecting, poly+4, poly+6);
} else if (linePtr->joinStyle == JoinMiter) {
if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
- (double) linePtr->width, poly+4, poly+6) == 0) {
+ width, poly+4, poly+6) == 0) {
changedMiterToBevel = 1;
- TkGetButtPoints(coordPtr, coordPtr+2, (double) linePtr->width,
+ TkGetButtPoints(coordPtr, coordPtr+2, width,
0, poly+4, poly+6);
}
} else {
- TkGetButtPoints(coordPtr, coordPtr+2, (double) linePtr->width, 0,
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0,
poly+4, poly+6);
}
poly[8] = poly[0];
@@ -942,7 +1465,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
if (linePtr->capStyle == CapRound) {
dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
- - linePtr->width/2.0;
+ - width/2.0;
if (dist <= 0.0) {
bestDist = 0.0;
goto done;
@@ -955,8 +1478,8 @@ LineToPoint(canvas, itemPtr, pointPtr)
* If there are arrowheads, check the distance to the arrowheads.
*/
- if (linePtr->arrow != noneUid) {
- if (linePtr->arrow != lastUid) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,
pointPtr);
if (dist <= 0.0) {
@@ -966,7 +1489,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
bestDist = dist;
}
}
- if (linePtr->arrow != firstUid) {
+ if (linePtr->arrow != ARROWS_FIRST) {
dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,
pointPtr);
if (dist <= 0.0) {
@@ -1016,6 +1539,35 @@ LineToArea(canvas, itemPtr, rectPtr)
double staticSpace[2*MAX_STATIC_POINTS];
double *linePoints;
int numPoints, result;
+ double radius, width;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
+ radius = (width+1.0)/2.0;
+
+ if ((state==TK_STATE_HIDDEN) || !linePtr->numPoints) {
+ return -1;
+ } else if (linePtr->numPoints == 1) {
+ double oval[4];
+ oval[0] = linePtr->coordPtr[0]-radius;
+ oval[1] = linePtr->coordPtr[1]-radius;
+ oval[2] = linePtr->coordPtr[0]+radius;
+ oval[3] = linePtr->coordPtr[1]+radius;
+ return TkOvalToArea(oval, rectPtr);
+ }
/*
* Handle smoothed lines by generating an expanded set of points
@@ -1023,14 +1575,16 @@ LineToArea(canvas, itemPtr, rectPtr)
*/
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
linePoints = staticSpace;
} else {
linePoints = (double *) ckalloc((unsigned)
(2*numPoints*sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
linePoints);
} else {
@@ -1042,8 +1596,12 @@ LineToArea(canvas, itemPtr, rectPtr)
* Check the segments of the line.
*/
+ if (width < 1.0) {
+ width = 1.0;
+ }
+
result = TkThickPolyLineToArea(linePoints, numPoints,
- (double) linePtr->width, linePtr->capStyle, linePtr->joinStyle,
+ width, linePtr->capStyle, linePtr->joinStyle,
rectPtr);
if (result == 0) {
goto done;
@@ -1053,15 +1611,15 @@ LineToArea(canvas, itemPtr, rectPtr)
* Check arrowheads, if any.
*/
- if (linePtr->arrow != noneUid) {
- if (linePtr->arrow != lastUid) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,
rectPtr) != result) {
result = 0;
goto done;
}
}
- if (linePtr->arrow != firstUid) {
+ if (linePtr->arrow != ARROWS_FIRST) {
if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,
rectPtr) != result) {
result = 0;
@@ -1134,7 +1692,7 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)
coordPtr[0] = originX + scaleX*(*coordPtr - originX);
coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
}
- if (linePtr->arrow != noneUid) {
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
ComputeLineBbox(canvas, linePtr);
@@ -1143,6 +1701,96 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)
/*
*--------------------------------------------------------------
*
+ * GetLineIndex --
+ *
+ * Parse an index into a line item and return either its value
+ * or an error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is
+ * filled in with the index (into itemPtr) corresponding to
+ * string. Otherwise an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetLineIndex(interp, canvas, itemPtr, obj, indexPtr)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ Tk_Canvas canvas; /* Canvas containing item. */
+ Tk_Item *itemPtr; /* Item for which the index is being
+ * specified. */
+ Tcl_Obj *obj; /* Specification of a particular coord
+ * in itemPtr's line. */
+ int *indexPtr; /* Where to store converted index. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ size_t length;
+ char *string = Tcl_GetStringFromObj(obj, (int *) &length);
+
+ if (string[0] == 'e') {
+ if (strncmp(string, "end", length) == 0) {
+ *indexPtr = 2*linePtr->numPoints;
+ } else {
+ badIndex:
+
+ /*
+ * Some of the paths here leave messages in interp->result,
+ * so we have to clear it out before storing our own message.
+ */
+
+ Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
+ Tcl_AppendResult(interp, "bad index \"", string, "\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else if (string[0] == '@') {
+ int i;
+ double x ,y, bestDist, dist, *coordPtr;
+ char *end, *p;
+
+ p = string+1;
+ x = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ p = end+1;
+ y = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ bestDist = 1.0e36;
+ coordPtr = linePtr->coordPtr;
+ *indexPtr = 0;
+ for(i=0; i<linePtr->numPoints; i++) {
+ dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
+ if (dist<bestDist) {
+ bestDist = dist;
+ *indexPtr = 2*i;
+ }
+ coordPtr += 2;
+ }
+ } else {
+ if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ *indexPtr &= -2; /* if index is odd, make it even */
+ if (*indexPtr < 0){
+ *indexPtr = 0;
+ } else if (*indexPtr > (2*linePtr->numPoints)) {
+ *indexPtr = (2*linePtr->numPoints);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* TranslateLine --
*
* This procedure is called to move a line by a given amount.
@@ -1216,7 +1864,7 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)
ClientData clientData; /* Not used. */
Tcl_Interp *interp; /* Used for error reporting. */
Tk_Window tkwin; /* Not used. */
- char *value; /* Textual specification of arrow shape. */
+ CONST char *value; /* Textual specification of arrow shape. */
char *recordPtr; /* Pointer to item record in which to
* store arrow information. */
int offset; /* Offset of shape information in widget
@@ -1231,7 +1879,7 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)
panic("ParseArrowShape received bogus offset");
}
- if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
+ if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
syntaxError:
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "bad arrow shape \"", value,
@@ -1296,6 +1944,117 @@ PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr)
return buffer;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-arrow" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The arrow for a given item gets replaced by the arrow
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ArrowParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *arrowPtr = ARROWS_NONE;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'n') && (strncmp(value, "none", length) == 0)) {
+ *arrowPtr = ARROWS_NONE;
+ return TCL_OK;
+ }
+ if ((c == 'f') && (strncmp(value, "first", length) == 0)) {
+ *arrowPtr = ARROWS_FIRST;
+ return TCL_OK;
+ }
+ if ((c == 'l') && (strncmp(value, "last", length) == 0)) {
+ *arrowPtr = ARROWS_LAST;
+ return TCL_OK;
+ }
+ if ((c == 'b') && (strncmp(value, "both", length) == 0)) {
+ *arrowPtr = ARROWS_BOTH;
+ return TCL_OK;
+ }
+
+ Tcl_AppendResult(interp, "bad arrow spec \"", value,
+ "\": must be none, first, last, or both",
+ (char *) NULL);
+ *arrowPtr = ARROWS_NONE;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-arrow"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the arrows for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static char *
+ArrowPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
+
+ switch (*arrowPtr) {
+ case ARROWS_FIRST:
+ return "first";
+ case ARROWS_LAST:
+ return "last";
+ case ARROWS_BOTH:
+ return "both";
+ default:
+ return "none";
+ }
+}
+
/*
*--------------------------------------------------------------
*
@@ -1335,6 +2094,27 @@ ConfigureArrows(canvas, linePtr)
double vertX, vertY; /* Position of arrowhead vertex. */
double shapeA, shapeB, shapeC; /* Adjusted coordinates (see
* explanation below). */
+ double width;
+ Tk_State state = linePtr->header.state;
+
+ if (linePtr->numPoints <2) {
+ return TCL_OK;
+ }
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
/*
* The code below makes a tiny increase in the shape parameters
@@ -1345,7 +2125,7 @@ ConfigureArrows(canvas, linePtr)
shapeA = linePtr->arrowShapeA + 0.001;
shapeB = linePtr->arrowShapeB + 0.001;
- shapeC = linePtr->arrowShapeC + linePtr->width/2.0 + 0.001;
+ shapeC = linePtr->arrowShapeC + width/2.0 + 0.001;
/*
* If there's an arrowhead on the first point of the line, compute
@@ -1353,9 +2133,9 @@ ConfigureArrows(canvas, linePtr)
* line doesn't stick out past the leading edge of the arrowhead.
*/
- fracHeight = (linePtr->width/2.0)/shapeC;
+ fracHeight = (width/2.0)/shapeC;
backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;
- if (linePtr->arrow != lastUid) {
+ if (linePtr->arrow != ARROWS_LAST) {
poly = linePtr->firstArrowPtr;
if (poly == NULL) {
poly = (double *) ckalloc((unsigned)
@@ -1400,7 +2180,7 @@ ConfigureArrows(canvas, linePtr)
* Similar arrowhead calculation for the last point of the line.
*/
- if (linePtr->arrow != firstUid) {
+ if (linePtr->arrow != ARROWS_FIRST) {
coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);
poly = linePtr->lastArrowPtr;
if (poly == NULL) {
@@ -1449,7 +2229,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,24 +2251,78 @@ 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) {
+ double width;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ color = linePtr->outline.color;
+ stipple = linePtr->outline.stipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ if (linePtr->outline.activeColor!=NULL) {
+ color = linePtr->outline.activeColor;
+ }
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ if (linePtr->outline.disabledColor!=NULL) {
+ color = linePtr->outline.disabledColor;
+ }
+ if (linePtr->outline.disabledStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ }
+
+ if (color == NULL || linePtr->numPoints<1 || linePtr->coordPtr==NULL) {
return TCL_OK;
}
+ if (linePtr->numPoints==1) {
+ sprintf(buffer, "%.15g %.15g translate %.15g %.15g",
+ linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),
+ width/2.0, width/2.0);
+ Tcl_AppendResult(interp, "matrix currentmatrix\n",buffer,
+ " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL);
+ if (Tk_CanvasPsColor(interp, canvas, color)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (stipple != None) {
+ Tcl_AppendResult(interp, "clip ", (char *) NULL);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "fill\n", (char *) NULL);
+ }
+ return TCL_OK;
+ }
/*
* Generate a path for the line's center-line (do this differently
* for straight lines and smoothed lines).
*/
- if ((!linePtr->smooth) || (linePtr->numPoints <= 2)) {
+ if ((!linePtr->smooth) || (linePtr->numPoints < 3)) {
Tk_CanvasPsPath(interp, canvas, linePtr->coordPtr, linePtr->numPoints);
} else {
- if (linePtr->fillStipple == None) {
- TkMakeBezierPostscript(interp, canvas, linePtr->coordPtr,
- linePtr->numPoints);
+ if ((stipple == None) && linePtr->smooth->postscriptProc) {
+ linePtr->smooth->postscriptProc(interp, canvas,
+ linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps);
} else {
/*
* Special hack: Postscript printers don't appear to be able
@@ -1503,13 +2337,15 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
double *pointPtr;
int numPoints;
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
pointPtr = staticPoints;
if (numPoints > MAX_STATIC_POINTS) {
pointPtr = (double *) ckalloc((unsigned)
(numPoints * 2 * sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
pointPtr);
Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints);
@@ -1523,8 +2359,6 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
* Set other line-drawing parameters and stroke out the line.
*/
- sprintf(buffer, "%d setlinewidth\n", linePtr->width);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
style = "0 setlinecap\n";
if (linePtr->capStyle == CapRound) {
style = "1 setlinecap\n";
@@ -1539,17 +2373,10 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
style = "2 setlinejoin\n";
}
Tcl_AppendResult(interp, style, (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, linePtr->fg) != TCL_OK) {
+
+ if (Tk_CanvasPsOutline(canvas, itemPtr,
+ &(linePtr->outline)) != TCL_OK) {
return TCL_ERROR;
- };
- if (linePtr->fillStipple != None) {
- Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, linePtr->fillStipple)
- != TCL_OK) {
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
}
/*
@@ -1557,7 +2384,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
*/
if (linePtr->firstArrowPtr != NULL) {
- if (linePtr->fillStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "grestore gsave\n",
(char *) NULL);
}
@@ -1567,7 +2394,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
}
}
if (linePtr->lastArrowPtr != NULL) {
- if (linePtr->fillStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
}
if (ArrowheadPostscript(interp, canvas, linePtr,
@@ -1589,7 +2416,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.
*
@@ -1609,10 +2436,28 @@ ArrowheadPostscript(interp, canvas, linePtr, arrowPtr)
double *arrowPtr; /* Pointer to first of five points
* describing arrowhead polygon. */
{
+ Pixmap stipple;
+ Tk_State state = linePtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ stipple = linePtr->outline.stipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ }
+
Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);
- if (linePtr->fillStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "clip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, linePtr->fillStipple)
+ if (Tk_CanvasPsStipple(interp, canvas, stipple)
!= TCL_OK) {
return TCL_ERROR;
}
@@ -1621,3 +2466,4 @@ ArrowheadPostscript(interp, canvas, linePtr, arrowPtr)
}
return TCL_OK;
}
+
diff --git a/tk/generic/tkCanvPoly.c b/tk/generic/tkCanvPoly.c
index 79c7b6c50b4..60616e173b9 100644
--- a/tk/generic/tkCanvPoly.c
+++ b/tk/generic/tkCanvPoly.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-2000 Ajuba Solutions.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -15,6 +16,7 @@
#include <stdio.h>
#include "tkInt.h"
#include "tkPort.h"
+#include "tkCanvas.h"
/*
* The structure below defines the record for each polygon item.
@@ -23,7 +25,8 @@
typedef struct PolygonItem {
Tk_Item header; /* Generic stuff that's the same for all
* types. MUST BE FIRST IN STRUCTURE. */
- int numPoints; /* Number of points in polygon (always >= 3).
+ Tk_Outline outline; /* Outline structure */
+ int numPoints; /* Number of points in polygon.
* Polygon is always closed. */
int pointsAllocated; /* Number of points for which space is
* allocated at *coordPtr. */
@@ -31,13 +34,16 @@ typedef struct PolygonItem {
* x- and y-coords of all points in polygon.
* X-coords are even-valued indices, y-coords
* are corresponding odd-valued indices. */
- int width; /* Width of outline. */
- XColor *outlineColor; /* Color for outline. */
- GC outlineGC; /* Graphics context for drawing outline. */
+ int joinStyle; /* Join style for outline */
+ Tk_TSOffset tsoffset;
XColor *fillColor; /* Foreground color for polygon. */
+ XColor *activeFillColor; /* Foreground color for polygon if state is active. */
+ XColor *disabledFillColor; /* Foreground color for polygon if state is disabled. */
Pixmap fillStipple; /* Stipple bitmap for filling polygon. */
+ Pixmap activeFillStipple; /* Stipple bitmap for filling polygon if state is active. */
+ Pixmap disabledFillStipple; /* Stipple bitmap for filling polygon if state is disabled. */
GC fillGC; /* Graphics context for filling polygon. */
- int smooth; /* Non-zero means draw shape smoothed (i.e.
+ Tk_SmoothMethod *smooth; /* Non-zero means draw shape smoothed (i.e.
* with Bezier splines). */
int splineSteps; /* Number of steps in each spline segment. */
int autoClosed; /* Zero means the given polygon was closed,
@@ -48,25 +54,106 @@ typedef struct PolygonItem {
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption smoothOption = {
+ (Tk_OptionParseProc *) TkSmoothParseProc,
+ TkSmoothPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
+static Tk_CustomOption dashOption = {
+ (Tk_OptionParseProc *) TkCanvasDashParseProc,
+ TkCanvasDashPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc,
+ (ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
+};
+static Tk_CustomOption pixelOption = {
+ (Tk_OptionParseProc *) TkPixelParseProc,
+ TkPixelPrintProc, (ClientData) NULL
+};
static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, activeFillColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.activeColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, activeFillStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(PolygonItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(PolygonItem, outline.offset),
+ TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, disabledFillColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, disabledFillStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(PolygonItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
"black", Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL,
+ "round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(PolygonItem, tsoffset),
+ TK_CONFIG_NULL_OK, &offsetOption},
{TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(PolygonItem, outlineColor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-smooth", (char *) NULL, (char *) NULL,
- "0", Tk_Offset(PolygonItem, smooth), TK_CONFIG_DONT_SET_DEFAULT},
+ (char *) NULL, Tk_Offset(PolygonItem, outline.color),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(PolygonItem, outline.tsoffset),
+ TK_CONFIG_NULL_OK, &offsetOption},
+ {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(PolygonItem, outline.stipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(PolygonItem, smooth),
+ TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
{TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
"12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
- {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
- "1", Tk_Offset(PolygonItem, width), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
+ "1.0", Tk_Offset(PolygonItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
@@ -79,18 +166,25 @@ static void ComputePolygonBbox _ANSI_ARGS_((Tk_Canvas canvas,
PolygonItem *polyPtr));
static int ConfigurePolygon _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int CreatePolygon _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeletePolygon _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayPolygon _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display, Drawable dst,
int x, int y, int width, int height));
+static int GetPolygonIndex _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ Tcl_Obj *obj, int *indexPtr));
static int PolygonCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
+static void PolygonDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr, int first, int last));
+static void PolygonInsert _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj));
static int PolygonToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double PolygonToPoint _ANSI_ARGS_((Tk_Canvas canvas,
@@ -117,18 +211,18 @@ Tk_ItemType tkPolygonType = {
PolygonCoords, /* coordProc */
DeletePolygon, /* deleteProc */
DisplayPolygon, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
PolygonToPoint, /* pointProc */
PolygonToArea, /* areaProc */
PolygonToPostscript, /* postscriptProc */
ScalePolygon, /* scaleProc */
TranslatePolygon, /* translateProc */
- (Tk_ItemIndexProc *) NULL, /* indexProc */
+ (Tk_ItemIndexProc *) GetPolygonIndex,/* indexProc */
(Tk_ItemCursorProc *) NULL, /* icursorProc */
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
- (Tk_ItemInsertProc *) NULL, /* insertProc */
- (Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemInsertProc *) PolygonInsert,/* insertProc */
+ PolygonDeleteCoords, /* dTextProc */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -150,7 +244,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.
*
@@ -167,34 +261,32 @@ CreatePolygon(interp, canvas, itemPtr, argc, argv)
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 polygon. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing polygon. */
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
int i;
- if (argc < 6) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
- itemPtr->typePtr->name,
- " x1 y1 x2 y2 x3 y3 ?x4 y4 ...? ?options?\"", (char *) NULL);
- return TCL_ERROR;
- }
-
/*
* Carry out initialization that is needed in order to clean
* up after errors during the the remainder of this procedure.
*/
+ Tk_CreateOutline(&(polyPtr->outline));
polyPtr->numPoints = 0;
polyPtr->pointsAllocated = 0;
polyPtr->coordPtr = NULL;
- polyPtr->width = 1;
- polyPtr->outlineColor = NULL;
- polyPtr->outlineGC = None;
+ polyPtr->joinStyle = JoinRound;
+ polyPtr->tsoffset.flags = 0;
+ polyPtr->tsoffset.xoffset = 0;
+ polyPtr->tsoffset.yoffset = 0;
polyPtr->fillColor = NULL;
+ polyPtr->activeFillColor = NULL;
+ polyPtr->disabledFillColor = NULL;
polyPtr->fillStipple = None;
+ polyPtr->activeFillStipple = None;
+ polyPtr->disabledFillStipple = None;
polyPtr->fillGC = None;
- polyPtr->smooth = 0;
+ polyPtr->smooth = (Tk_SmoothMethod *) NULL;
polyPtr->splineSteps = 12;
polyPtr->autoClosed = 0;
@@ -204,13 +296,14 @@ CreatePolygon(interp, canvas, itemPtr, argc, argv)
* start with a digit or a minus sign followed by a digit.
*/
- for (i = 4; i < (argc-1); i+=2) {
- if ((!isdigit(UCHAR(argv[i][0]))) &&
- ((argv[i][0] != '-') || (!isdigit(UCHAR(argv[i][1]))))) {
+ for (i = 0; i < argc; i++) {
+ char *arg = Tcl_GetStringFromObj((Tcl_Obj *) argv[i], NULL);
+ if ((arg[0] == '-') && (arg[1] >= 'a')
+ && (arg[1] <= 'z')) {
break;
}
}
- if (PolygonCoords(interp, canvas, itemPtr, i, argv) != TCL_OK) {
+ if (i && PolygonCoords(interp, canvas, itemPtr, i, argv) != TCL_OK) {
goto error;
}
@@ -234,7 +327,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.
@@ -250,11 +343,10 @@ PolygonCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
- char buffer[TCL_DOUBLE_SPACE];
int i, numPoints;
if (argc == 0) {
@@ -262,16 +354,21 @@ PolygonCoords(interp, canvas, itemPtr, argc, argv)
* Print the coords used to create the polygon. If we auto
* closed the polygon then we don't report the last point.
*/
+ Tcl_Obj *subobj, *obj = Tcl_NewObj();
for (i = 0; i < 2*(polyPtr->numPoints - polyPtr->autoClosed); i++) {
- Tcl_PrintDouble(interp, polyPtr->coordPtr[i], buffer);
- Tcl_AppendElement(interp, buffer);
+ subobj = Tcl_NewDoubleObj(polyPtr->coordPtr[i]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
}
- } else if (argc < 6) {
- Tcl_AppendResult(interp,
- "too few coordinates for polygon: must have at least 6",
- (char *) NULL);
- return TCL_ERROR;
- } else if (argc & 1) {
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+ }
+ if (argc == 1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (argc & 1) {
Tcl_AppendResult(interp,
"odd number of coordinates specified for polygon",
(char *) NULL);
@@ -284,8 +381,8 @@ PolygonCoords(interp, canvas, itemPtr, argc, argv)
}
/*
- * One extra point gets allocated here, just in case we have
- * to add another point to close the polygon.
+ * One extra point gets allocated here, because we always
+ * add another point to close the polygon.
*/
polyPtr->coordPtr = (double *) ckalloc((unsigned)
@@ -293,20 +390,20 @@ PolygonCoords(interp, canvas, itemPtr, argc, argv)
polyPtr->pointsAllocated = numPoints+1;
}
for (i = argc-1; i >= 0; i--) {
- if (Tk_CanvasGetCoord(interp, canvas, argv[i],
+ if (Tk_CanvasGetCoordFromObj(interp, canvas, argv[i],
&polyPtr->coordPtr[i]) != TCL_OK) {
return TCL_ERROR;
}
}
polyPtr->numPoints = numPoints;
polyPtr->autoClosed = 0;
-
+
/*
* Close the polygon if it isn't already closed.
*/
- if ((polyPtr->coordPtr[argc-2] != polyPtr->coordPtr[0])
- || (polyPtr->coordPtr[argc-1] != polyPtr->coordPtr[1])) {
+ if (argc>2 && ((polyPtr->coordPtr[argc-2] != polyPtr->coordPtr[0])
+ || (polyPtr->coordPtr[argc-1] != polyPtr->coordPtr[1]))) {
polyPtr->autoClosed = 1;
polyPtr->numPoints++;
polyPtr->coordPtr[argc] = polyPtr->coordPtr[0];
@@ -327,7 +424,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
@@ -342,7 +439,7 @@ ConfigurePolygon(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Polygon item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
@@ -350,10 +447,13 @@ ConfigurePolygon(interp, canvas, itemPtr, argc, argv, flags)
GC newGC;
unsigned long mask;
Tk_Window tkwin;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) polyPtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) polyPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -362,37 +462,70 @@ ConfigurePolygon(interp, canvas, itemPtr, argc, argv, flags)
* graphics contexts.
*/
- if (polyPtr->width < 1) {
- polyPtr->width = 1;
- }
- if (polyPtr->outlineColor == NULL) {
- newGC = None;
+ state = itemPtr->state;
+
+ if (polyPtr->outline.activeWidth > polyPtr->outline.width ||
+ polyPtr->outline.activeDash.number != 0 ||
+ polyPtr->outline.activeColor != NULL ||
+ polyPtr->outline.activeStipple != None ||
+ polyPtr->activeFillColor != NULL ||
+ polyPtr->activeFillStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
} else {
- gcValues.foreground = polyPtr->outlineColor->pixel;
- gcValues.line_width = polyPtr->width;
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ ComputePolygonBbox(canvas, polyPtr);
+ return TCL_OK;
+ }
+
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(polyPtr->outline));
+ if (mask) {
gcValues.cap_style = CapRound;
- gcValues.join_style = JoinRound;
- mask = GCForeground|GCLineWidth|GCCapStyle|GCJoinStyle;
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, polyPtr->outlineColor,
- NULL);
+ gcValues.join_style = polyPtr->joinStyle;
+ mask |= GCCapStyle|GCJoinStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = None;
+ }
+ if (polyPtr->outline.gc != None) {
+ Tk_FreeGC(Tk_Display(tkwin), polyPtr->outline.gc);
}
- if (polyPtr->outlineGC != None) {
- Tk_FreeGC(Tk_Display(tkwin), polyPtr->outlineGC);
+ polyPtr->outline.gc = newGC;
+
+ color = polyPtr->fillColor;
+ stipple = polyPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->activeFillColor!=NULL) {
+ color = polyPtr->activeFillColor;
+ }
+ if (polyPtr->activeFillStipple!=None) {
+ stipple = polyPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->disabledFillColor!=NULL) {
+ color = polyPtr->disabledFillColor;
+ }
+ if (polyPtr->disabledFillStipple!=None) {
+ stipple = polyPtr->disabledFillStipple;
+ }
}
- polyPtr->outlineGC = newGC;
- if (polyPtr->fillColor == NULL) {
+ if (color == NULL) {
newGC = None;
} else {
- gcValues.foreground = polyPtr->fillColor->pixel;
+ gcValues.foreground = color->pixel;
mask = GCForeground;
- if (polyPtr->fillStipple != None) {
- gcValues.stipple = polyPtr->fillStipple;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
gcValues.fill_style = FillStippled;
mask |= GCStipple|GCFillStyle;
}
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, polyPtr->fillColor,
- NULL);
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
}
if (polyPtr->fillGC != None) {
Tk_FreeGC(Tk_Display(tkwin), polyPtr->fillGC);
@@ -439,20 +572,27 @@ DeletePolygon(canvas, itemPtr, display)
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ Tk_DeleteOutline(display,&(polyPtr->outline));
if (polyPtr->coordPtr != NULL) {
ckfree((char *) polyPtr->coordPtr);
}
if (polyPtr->fillColor != NULL) {
Tk_FreeColor(polyPtr->fillColor);
}
+ if (polyPtr->activeFillColor != NULL) {
+ Tk_FreeColor(polyPtr->activeFillColor);
+ }
+ if (polyPtr->disabledFillColor != NULL) {
+ Tk_FreeColor(polyPtr->disabledFillColor);
+ }
if (polyPtr->fillStipple != None) {
Tk_FreeBitmap(display, polyPtr->fillStipple);
}
- if (polyPtr->outlineColor != NULL) {
- Tk_FreeColor(polyPtr->outlineColor);
+ if (polyPtr->activeFillStipple != None) {
+ Tk_FreeBitmap(display, polyPtr->activeFillStipple);
}
- if (polyPtr->outlineGC != None) {
- Tk_FreeGC(display, polyPtr->outlineGC);
+ if (polyPtr->disabledFillStipple != None) {
+ Tk_FreeBitmap(display, polyPtr->disabledFillStipple);
}
if (polyPtr->fillGC != None) {
Tk_FreeGC(display, polyPtr->fillGC);
@@ -485,27 +625,159 @@ ComputePolygonBbox(canvas, polyPtr)
{
double *coordPtr;
int i;
+ double width;
+ Tk_State state = polyPtr->header.state;
+ Tk_TSOffset *tsoffset;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ if (polyPtr->coordPtr == NULL || (polyPtr->numPoints < 1) || (state==TK_STATE_HIDDEN)) {
+ polyPtr->header.x1 = polyPtr->header.x2 =
+ polyPtr->header.y1 = polyPtr->header.y2 = -1;
+ return;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)polyPtr) {
+ if (polyPtr->outline.activeWidth>width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth>0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
coordPtr = polyPtr->coordPtr;
polyPtr->header.x1 = polyPtr->header.x2 = (int) *coordPtr;
polyPtr->header.y1 = polyPtr->header.y2 = (int) coordPtr[1];
- for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints;
+ /*
+ * Compute the bounding box of all the points in the polygon,
+ * then expand in all directions by the outline's width to take
+ * care of butting or rounded corners and projecting or
+ * rounded caps. This expansion is an overestimate (worst-case
+ * is square root of two over two) but it's simple. Don't do
+ * anything special for curves. This causes an additional
+ * overestimate in the bounding box, but is faster.
+ */
+
+ for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints-1;
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) polyPtr, coordPtr);
}
+ tsoffset = &polyPtr->tsoffset;
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ int index = tsoffset->flags & ~TK_OFFSET_INDEX;
+ if (tsoffset->flags == INT_MAX) {
+ index = (polyPtr->numPoints - polyPtr->autoClosed) * 2;
+ if (index < 0) {
+ index = 0;
+ }
+ }
+ index %= (polyPtr->numPoints - polyPtr->autoClosed) * 2;
+ if (index <0) {
+ index += (polyPtr->numPoints - polyPtr->autoClosed) * 2;
+ }
+ tsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);
+ tsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = polyPtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (polyPtr->header.x1 + polyPtr->header.x2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = polyPtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = polyPtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (polyPtr->header.y1 + polyPtr->header.y2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = polyPtr->header.y2;
+ }
+ }
+
+ if (polyPtr->outline.gc != None) {
+ tsoffset = &polyPtr->outline.tsoffset;
+ if (tsoffset) {
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ int index = tsoffset->flags & ~TK_OFFSET_INDEX;
+ if (tsoffset->flags == INT_MAX) {
+ index = (polyPtr->numPoints - 1) * 2;
+ }
+ index %= (polyPtr->numPoints - 1) * 2;
+ if (index <0) {
+ index += (polyPtr->numPoints - 1) * 2;
+ }
+ tsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);
+ tsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = polyPtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (polyPtr->header.x1 + polyPtr->header.x2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = polyPtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = polyPtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (polyPtr->header.y1 + polyPtr->header.y2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = polyPtr->header.y2;
+ }
+ }
+ }
+
+ i = (int) ((width+1.5)/2.0);
+ polyPtr->header.x1 -= i;
+ polyPtr->header.x2 += i;
+ polyPtr->header.y1 -= i;
+ polyPtr->header.y2 += i;
+
+ /*
+ * For mitered lines, make a second pass through all the points.
+ * Compute the locations of the two miter vertex points and add
+ * those into the bounding box.
+ */
+
+ if (polyPtr->joinStyle == JoinMiter) {
+ double miter[4];
+ int j;
+ coordPtr = polyPtr->coordPtr;
+ if (polyPtr->numPoints>3) {
+ if (TkGetMiterPoints(coordPtr+2*(polyPtr->numPoints-2),
+ coordPtr, coordPtr+2, width,
+ miter, miter+2)) {
+ for (j = 0; j < 4; j += 2) {
+ TkIncludePoint((Tk_Item *) polyPtr, miter+j);
+ }
+ }
+ }
+ for (i = polyPtr->numPoints ; i >= 3;
+ i--, coordPtr += 2) {
+
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ width, miter, miter+2)) {
+ for (j = 0; j < 4; j += 2) {
+ TkIncludePoint((Tk_Item *) polyPtr, miter+j);
+ }
+ }
+ }
+ }
+ }
+
/*
- * Expand bounding box in all directions to account for the outline,
- * which can stick out beyond the polygon. Add one extra pixel of
- * fudge, just in case X rounds differently than we do.
+ * Add one more pixel of fudge factor just to be safe (e.g.
+ * X may round differently than we do).
*/
- i = (polyPtr->width+1)/2 + 1;
- polyPtr->header.x1 -= i;
- polyPtr->header.x2 += i;
- polyPtr->header.y1 -= i;
- polyPtr->header.y2 += i;
+ polyPtr->header.x1 -= 1;
+ polyPtr->header.x2 += 1;
+ polyPtr->header.y1 -= 1;
+ polyPtr->header.y2 += 1;
}
/*
@@ -569,7 +841,7 @@ TkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC)
* allocated.
*/
- if (gc != None) {
+ if (gc != None && numPoints>3) {
XFillPolygon(display, drawable, gc, pointPtr, numPoints, Complex,
CoordModeOrigin);
}
@@ -611,24 +883,80 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height)
* must be redisplayed (not used). */
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ Tk_State state = itemPtr->state;
+ Pixmap stipple = polyPtr->fillStipple;
+ double linewidth = polyPtr->outline.width;
- if ((polyPtr->fillGC == None) && (polyPtr->outlineGC == None)) {
+ if (((polyPtr->fillGC == None) && (polyPtr->outline.gc == None)) ||
+ (polyPtr->numPoints < 1) ||
+ (polyPtr->numPoints < 3 && polyPtr->outline.gc == None)) {
return;
}
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth>linewidth) {
+ linewidth = polyPtr->outline.activeWidth;
+ }
+ if (polyPtr->activeFillStipple != None) {
+ stipple = polyPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth>0.0) {
+ linewidth = polyPtr->outline.disabledWidth;
+ }
+ if (polyPtr->disabledFillStipple != None) {
+ stipple = polyPtr->disabledFillStipple;
+ }
+ }
/*
* If we're stippling then modify the stipple offset in the GC. Be
* sure to reset the offset when done, since the GC is supposed to be
* read-only.
*/
- if ((polyPtr->fillStipple != None) && (polyPtr->fillGC != None)) {
- Tk_CanvasSetStippleOrigin(canvas, polyPtr->fillGC);
+ if ((stipple != None) && (polyPtr->fillGC != None)) {
+ Tk_TSOffset *tsoffset = &polyPtr->tsoffset;
+ int w=0; int h=0;
+ int flags = tsoffset->flags;
+ if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
+ Tk_SizeOfBitmap(display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, polyPtr->fillGC, tsoffset);
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
}
+ Tk_ChangeOutlineGC(canvas, itemPtr, &(polyPtr->outline));
- if (!polyPtr->smooth) {
+ if(polyPtr->numPoints < 3) {
+ short x,y;
+ int intLineWidth = (int) (linewidth + 0.5);
+ if (intLineWidth < 1) {
+ intLineWidth = 1;
+ }
+ Tk_CanvasDrawableCoords(canvas, polyPtr->coordPtr[0],
+ polyPtr->coordPtr[1], &x,&y);
+ XFillArc(display, drawable, polyPtr->outline.gc,
+ x - intLineWidth/2, y - intLineWidth/2,
+ (unsigned int)intLineWidth+1, (unsigned int)intLineWidth+1,
+ 0, 64*360);
+ } else if (!polyPtr->smooth || polyPtr->numPoints < 4) {
TkFillPolygon(canvas, polyPtr->coordPtr, polyPtr->numPoints,
- display, drawable, polyPtr->fillGC, polyPtr->outlineGC);
+ display, drawable, polyPtr->fillGC, polyPtr->outline.gc);
} else {
int numPoints;
XPoint staticPoints[MAX_STATIC_POINTS];
@@ -639,29 +967,32 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height)
* spline points rather than the original points.
*/
- numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
+ numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL,
+ polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
pointPtr = staticPoints;
} else {
pointPtr = (XPoint *) ckalloc((unsigned)
(numPoints * sizeof(XPoint)));
}
- numPoints = TkMakeBezierCurve(canvas, polyPtr->coordPtr,
+ numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
polyPtr->numPoints, polyPtr->splineSteps, pointPtr,
(double *) NULL);
if (polyPtr->fillGC != None) {
XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr,
numPoints, Complex, CoordModeOrigin);
}
- if (polyPtr->outlineGC != None) {
- XDrawLines(display, drawable, polyPtr->outlineGC, pointPtr,
+ if (polyPtr->outline.gc != None) {
+ XDrawLines(display, drawable, polyPtr->outline.gc, pointPtr,
numPoints, CoordModeOrigin);
}
if (pointPtr != staticPoints) {
ckfree((char *) pointPtr);
}
}
- if ((polyPtr->fillStipple != None) && (polyPtr->fillGC != None)) {
+ Tk_ResetOutlineGC(canvas, itemPtr, &(polyPtr->outline));
+ if ((stipple != None) && (polyPtr->fillGC != None)) {
XSetTSOrigin(display, polyPtr->fillGC, 0, 0);
}
}
@@ -669,6 +1000,203 @@ DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height)
/*
*--------------------------------------------------------------
*
+ * PolygonInsert --
+ *
+ * Insert coords into a polugon item at a given index.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The coords in the given item is modified.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PolygonInsert(canvas, itemPtr, beforeThis, obj)
+ Tk_Canvas canvas; /* Canvas containing text item. */
+ Tk_Item *itemPtr; /* Line item to be modified. */
+ int beforeThis; /* Index before which new coordinates
+ * are to be inserted. */
+ Tcl_Obj *obj; /* New coordinates to be inserted. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int length, argc, i;
+ Tcl_Obj **objv;
+ double *new;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &argc, &objv) != TCL_OK)
+ || !argc || argc&1) {
+ return;
+ }
+ length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+ while(beforeThis>length) beforeThis-=length;
+ while(beforeThis<0) beforeThis+=length;
+ new = (double *) ckalloc((unsigned)(sizeof(double) * (length + 2 + argc)));
+ for (i=0; i<beforeThis; i++) {
+ new[i] = polyPtr->coordPtr[i];
+ }
+ for (i=0; i<argc; i++) {
+ if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i],
+ new+(i+beforeThis))!=TCL_OK) {
+ ckfree((char *) new);
+ return;
+ }
+ }
+
+ for(i=beforeThis; i<length; i++) {
+ new[i+argc] = polyPtr->coordPtr[i];
+ }
+ if(polyPtr->coordPtr) ckfree((char *) polyPtr->coordPtr);
+ length+=argc;
+ polyPtr->coordPtr = new;
+ polyPtr->numPoints = (length/2) + polyPtr->autoClosed;
+
+ /*
+ * Close the polygon if it isn't already closed, or remove autoclosing
+ * if the user's coordinates are now closed.
+ */
+
+ if (polyPtr->autoClosed) {
+ if ((new[length-2] == new[0]) && (new[length-1] == new[1])) {
+ polyPtr->autoClosed = 0;
+ polyPtr->numPoints--;
+ }
+ }
+ else {
+ if ((new[length-2] != new[0]) || (new[length-1] != new[1])) {
+ polyPtr->autoClosed = 1;
+ polyPtr->numPoints++;
+ }
+ }
+
+ new[length] = new[0];
+ new[length+1] = new[1];
+ if (((length-argc)>3) && (state != TK_STATE_HIDDEN)) {
+ /*
+ * This is some optimizing code that will result that only the part
+ * of the polygon that changed (and the objects that are overlapping
+ * with that part) need to be redrawn. A special flag is set that
+ * instructs the general canvas code not to redraw the whole
+ * object. If this flag is not set, the canvas will do the redrawing,
+ * otherwise I have to do it here.
+ */
+ double width;
+ int j;
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+
+ /*
+ * The header elements that normally are used for the
+ * bounding box, are now used to calculate the bounding
+ * box for only the part that has to be redrawn. That
+ * doesn't matter, because afterwards the bounding
+ * box has to be re-calculated anyway.
+ */
+
+ itemPtr->x1 = itemPtr->x2 = (int) polyPtr->coordPtr[beforeThis];
+ itemPtr->y1 = itemPtr->y2 = (int) polyPtr->coordPtr[beforeThis+1];
+ beforeThis-=2; argc+=4;
+ if(polyPtr->smooth) {
+ beforeThis-=2; argc+=4;
+ } /* be carefull; beforeThis could now be negative */
+ for(i=beforeThis; i<beforeThis+argc; i+=2) {
+ j=i;
+ if(j<0) j+=length;
+ if(j>=length) j-=length;
+ TkIncludePoint(itemPtr, polyPtr->coordPtr+j);
+ }
+ width = polyPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth>width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth>0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+ itemPtr->x1 -= (int) width; itemPtr->y1 -= (int) width;
+ itemPtr->x2 += (int) width; itemPtr->y2 += (int) width;
+ Tk_CanvasEventuallyRedraw(canvas,
+ itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+
+ ComputePolygonBbox(canvas, polyPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * PolygonDeleteCoords --
+ *
+ * Delete one or more coordinates from a polygon item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters between "first" and "last", inclusive, get
+ * deleted from itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+PolygonDeleteCoords(canvas, itemPtr, first, last)
+ Tk_Canvas canvas; /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr; /* Item in which to delete characters. */
+ int first; /* Index of first character to delete. */
+ int last; /* Index of last character to delete. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ int count, i;
+ int length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+
+ while(first>=length) first-=length;
+ while(first<0) first+=length;
+ while(last>=length) last-=length;
+ while(last<0) last+=length;
+
+ first &= -2;
+ last &= -2;
+
+ count = last + 2 - first;
+ if(count<=0) count +=length;
+
+ if(count >= length) {
+ polyPtr->numPoints = 0;
+ if(polyPtr->coordPtr != NULL) {
+ ckfree((char *) polyPtr->coordPtr);
+ }
+ ComputePolygonBbox(canvas, polyPtr);
+ return;
+ }
+
+ if(last>=first) {
+ for(i=last+2; i<length; i++) {
+ polyPtr->coordPtr[i-count] = polyPtr->coordPtr[i];
+ }
+ } else {
+ for(i=last; i<=first; i++) {
+ polyPtr->coordPtr[i-last] = polyPtr->coordPtr[i];
+ }
+ }
+ polyPtr->coordPtr[length-count] = polyPtr->coordPtr[0];
+ polyPtr->coordPtr[length-count+1] = polyPtr->coordPtr[1];
+ polyPtr->numPoints -= count/2;
+ ComputePolygonBbox(canvas, polyPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* PolygonToPoint --
*
* Computes the distance from a given point to a given
@@ -694,41 +1222,169 @@ PolygonToPoint(canvas, itemPtr, pointPtr)
double *pointPtr; /* Pointer to x and y coordinates. */
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
- double *coordPtr, distance;
+ double *coordPtr, *polyPoints;
double staticSpace[2*MAX_STATIC_POINTS];
- int numPoints;
+ double poly[10];
+ double radius;
+ double bestDist, dist;
+ int numPoints, count;
+ int changedMiterToBevel; /* Non-zero means that a mitered corner
+ * had to be treated as beveled after all
+ * because the angle was < 11 degrees. */
+ double width;
+ Tk_State state = itemPtr->state;
+
+ bestDist = 1.0e36;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth>width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth>0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+ radius = width/2.0;
- if (!polyPtr->smooth) {
- distance = TkPolygonToPoint(polyPtr->coordPtr, polyPtr->numPoints,
- pointPtr);
- } else {
- /*
- * Smoothed polygon. Generate a new set of points and use them
- * for comparison.
- */
-
- numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
+ /*
+ * Handle smoothed polygons by generating an expanded set of points
+ * against which to do the check.
+ */
+
+ if ((polyPtr->smooth) && (polyPtr->numPoints>2)) {
+ numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL,
+ polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
- coordPtr = staticSpace;
+ polyPoints = staticSpace;
} else {
- coordPtr = (double *) ckalloc((unsigned)
+ polyPoints = (double *) ckalloc((unsigned)
(2*numPoints*sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, polyPtr->coordPtr,
+ numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
- coordPtr);
- distance = TkPolygonToPoint(coordPtr, numPoints, pointPtr);
- if (coordPtr != staticSpace) {
- ckfree((char *) coordPtr);
+ polyPoints);
+ } else {
+ numPoints = polyPtr->numPoints;
+ polyPoints = polyPtr->coordPtr;
+ }
+
+ bestDist = TkPolygonToPoint(polyPoints, numPoints, pointPtr);
+ if (bestDist<=0.0) {
+ goto donepoint;
+ }
+ if ((polyPtr->outline.gc != None) && (polyPtr->joinStyle == JoinRound)) {
+ dist = bestDist - radius;
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else {
+ bestDist = dist;
}
}
- if (polyPtr->outlineColor != NULL) {
- distance -= polyPtr->width/2.0;
- if (distance < 0) {
- distance = 0;
+
+ if ((polyPtr->outline.gc == None) || (width <= 1)) goto donepoint;
+
+ /*
+ * The overall idea is to iterate through all of the edges of
+ * the line, computing a polygon for each edge and testing the
+ * point against that polygon. In addition, there are additional
+ * tests to deal with rounded joints and caps.
+ */
+
+ changedMiterToBevel = 0;
+ for (count = numPoints, coordPtr = polyPoints; count >= 2;
+ count--, coordPtr += 2) {
+
+ /*
+ * If rounding is done around the first point then compute
+ * the distance between the point and the point.
+ */
+
+ if (polyPtr->joinStyle == JoinRound) {
+ dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
+ - radius;
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
}
+
+ /*
+ * Compute the polygonal shape corresponding to this edge,
+ * consisting of two points for the first point of the edge
+ * and two points for the last point of the edge.
+ */
+
+ if (count == numPoints) {
+ TkGetButtPoints(coordPtr+2, coordPtr, (double) width,
+ 0, poly, poly+2);
+ } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
+ poly[0] = poly[6];
+ poly[1] = poly[7];
+ poly[2] = poly[4];
+ poly[3] = poly[5];
+ } else {
+ TkGetButtPoints(coordPtr+2, coordPtr, (double) width, 0,
+ poly, poly+2);
+
+ /*
+ * If this line uses beveled joints, then check the distance
+ * to a polygon comprising the last two points of the previous
+ * polygon and the first two from this polygon; this checks
+ * the wedges that fill the mitered joint.
+ */
+
+ if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ dist = TkPolygonToPoint(poly, 5, pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ changedMiterToBevel = 0;
+ }
+ }
+ if (count == 2) {
+ TkGetButtPoints(coordPtr, coordPtr+2, (double) width,
+ 0, poly+4, poly+6);
+ } else if (polyPtr->joinStyle == JoinMiter) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ (double) width, poly+4, poly+6) == 0) {
+ changedMiterToBevel = 1;
+ TkGetButtPoints(coordPtr, coordPtr+2, (double) width,
+ 0, poly+4, poly+6);
+ }
+ } else {
+ TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0,
+ poly+4, poly+6);
+ }
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ dist = TkPolygonToPoint(poly, 5, pointPtr);
+ if (dist <= 0.0) {
+ bestDist = 0.0;
+ goto donepoint;
+ } else if (dist < bestDist) {
+ bestDist = dist;
+ }
+ }
+
+ donepoint:
+ if ((polyPoints != staticSpace) && polyPoints != polyPtr->coordPtr) {
+ ckfree((char *) polyPoints);
}
- return distance;
+ return bestDist;
}
/*
@@ -761,75 +1417,179 @@ PolygonToArea(canvas, itemPtr, rectPtr)
* area. */
{
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
- double *coordPtr, rect2[4], halfWidth;
+ double *coordPtr;
double staticSpace[2*MAX_STATIC_POINTS];
- int numPoints, result;
+ double *polyPoints, poly[10];
+ double radius;
+ int numPoints, count;
+ int changedMiterToBevel; /* Non-zero means that a mitered corner
+ * had to be treated as beveled after all
+ * because the angle was < 11 degrees. */
+ int inside; /* Tentative guess about what to return,
+ * based on all points seen so far: one
+ * means everything seen so far was
+ * inside the area; -1 means everything
+ * was outside the area. 0 means overlap
+ * has been found. */
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth>width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth>0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ }
+
+ radius = width/2.0;
+ inside = -1;
+
+ if ((state==TK_STATE_HIDDEN) || polyPtr->numPoints<2) {
+ return -1;
+ } else if (polyPtr->numPoints <3) {
+ double oval[4];
+ oval[0] = polyPtr->coordPtr[0]-radius;
+ oval[1] = polyPtr->coordPtr[1]-radius;
+ oval[2] = polyPtr->coordPtr[0]+radius;
+ oval[3] = polyPtr->coordPtr[1]+radius;
+ return TkOvalToArea(oval, rectPtr);
+ }
/*
* Handle smoothed polygons by generating an expanded set of points
* against which to do the check.
*/
if (polyPtr->smooth) {
- numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
+ numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL,
+ polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
- coordPtr = staticSpace;
+ polyPoints = staticSpace;
} else {
- coordPtr = (double *) ckalloc((unsigned)
+ polyPoints = (double *) ckalloc((unsigned)
(2*numPoints*sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, polyPtr->coordPtr,
+ numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
- coordPtr);
+ polyPoints);
} else {
numPoints = polyPtr->numPoints;
- coordPtr = polyPtr->coordPtr;
+ polyPoints = polyPtr->coordPtr;
}
- if (polyPtr->width <= 1) {
- /*
- * The outline of the polygon doesn't stick out, so we can
- * do a simple check.
- */
-
- result = TkPolygonToArea(coordPtr, numPoints, rectPtr);
+ if (polyPtr->fillGC != None) {
+ inside = TkPolygonToArea(polyPoints, numPoints, rectPtr);
+ if (inside==0) goto donearea;
} else {
+ if ((polyPoints[0] >= rectPtr[0])
+ && (polyPoints[0] <= rectPtr[2])
+ && (polyPoints[1] >= rectPtr[1])
+ && (polyPoints[1] <= rectPtr[3])) {
+ inside = 1;
+ }
+ }
+
+ if (polyPtr->outline.gc == None) goto donearea ;
+
+
+ /*
+ * Iterate through all of the edges of the line, computing a polygon
+ * for each edge and testing the area against that polygon. In
+ * addition, there are additional tests to deal with rounded joints
+ * and caps.
+ */
+
+ changedMiterToBevel = 0;
+ for (count = numPoints, coordPtr = polyPoints; count >= 2;
+ count--, coordPtr += 2) {
+
/*
- * The polygon has a wide outline, so the check is more complicated.
- * First, check the line segments to see if they overlap the area.
+ * If rounding is done around the first point of the edge
+ * then test a circular region around the point with the
+ * area.
*/
- result = TkThickPolyLineToArea(coordPtr, numPoints,
- (double) polyPtr->width, CapRound, JoinRound, rectPtr);
- if (result >= 0) {
- goto done;
+ if (polyPtr->joinStyle == JoinRound) {
+ poly[0] = coordPtr[0] - radius;
+ poly[1] = coordPtr[1] - radius;
+ poly[2] = coordPtr[0] + radius;
+ poly[3] = coordPtr[1] + radius;
+ if (TkOvalToArea(poly, rectPtr) != inside) {
+ inside = 0;
+ goto donearea;
+ }
}
/*
- * There is no overlap between the polygon's outline and the
- * rectangle. This means either the rectangle is entirely outside
- * the polygon or entirely inside. To tell the difference,
- * see whether the polygon (with 0 outline width) overlaps the
- * rectangle bloated by half the outline width.
+ * Compute the polygonal shape corresponding to this edge,
+ * consisting of two points for the first point of the edge
+ * and two points for the last point of the edge.
*/
- halfWidth = polyPtr->width/2.0;
- rect2[0] = rectPtr[0] - halfWidth;
- rect2[1] = rectPtr[1] - halfWidth;
- rect2[2] = rectPtr[2] + halfWidth;
- rect2[3] = rectPtr[3] + halfWidth;
- if (TkPolygonToArea(coordPtr, numPoints, rect2) == -1) {
- result = -1;
+ if (count == numPoints) {
+ TkGetButtPoints(coordPtr+2, coordPtr, width,
+ 0, poly, poly+2);
+ } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
+ poly[0] = poly[6];
+ poly[1] = poly[7];
+ poly[2] = poly[4];
+ poly[3] = poly[5];
+ } else {
+ TkGetButtPoints(coordPtr+2, coordPtr, width, 0,
+ poly, poly+2);
+
+ /*
+ * If the last joint was beveled, then also check a
+ * polygon comprising the last two points of the previous
+ * polygon and the first two from this polygon; this checks
+ * the wedges that fill the beveled joint.
+ */
+
+ if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
+ inside = 0;
+ goto donearea;
+ }
+ changedMiterToBevel = 0;
+ }
+ }
+ if (count == 2) {
+ TkGetButtPoints(coordPtr, coordPtr+2, width,
+ 0, poly+4, poly+6);
+ } else if (polyPtr->joinStyle == JoinMiter) {
+ if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
+ width, poly+4, poly+6) == 0) {
+ changedMiterToBevel = 1;
+ TkGetButtPoints(coordPtr, coordPtr+2, width,
+ 0, poly+4, poly+6);
+ }
} else {
- result = 0;
+ TkGetButtPoints(coordPtr, coordPtr+2, width, 0,
+ poly+4, poly+6);
+ }
+ poly[8] = poly[0];
+ poly[9] = poly[1];
+ if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
+ inside = 0;
+ goto donearea;
}
}
- done:
- if ((coordPtr != staticSpace) && (coordPtr != polyPtr->coordPtr)) {
- ckfree((char *) coordPtr);
+ donearea:
+ if ((polyPoints != staticSpace) && (polyPoints != polyPtr->coordPtr)) {
+ ckfree((char *) polyPoints);
}
- return result;
+ return inside;
}
/*
@@ -875,6 +1635,101 @@ ScalePolygon(canvas, itemPtr, originX, originY, scaleX, scaleY)
/*
*--------------------------------------------------------------
*
+ * GetPolygonIndex --
+ *
+ * Parse an index into a polygon item and return either its value
+ * or an error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is
+ * filled in with the index (into itemPtr) corresponding to
+ * string. Otherwise an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetPolygonIndex(interp, canvas, itemPtr, obj, indexPtr)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ Tk_Canvas canvas; /* Canvas containing item. */
+ Tk_Item *itemPtr; /* Item for which the index is being
+ * specified. */
+ Tcl_Obj *obj; /* Specification of a particular coord
+ * in itemPtr's line. */
+ int *indexPtr; /* Where to store converted index. */
+{
+ PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ size_t length;
+ char *string = Tcl_GetStringFromObj(obj, (int *) &length);
+
+ if (string[0] == 'e') {
+ if (strncmp(string, "end", length) == 0) {
+ *indexPtr = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+ } else {
+ badIndex:
+
+ /*
+ * Some of the paths here leave messages in interp->result,
+ * so we have to clear it out before storing our own message.
+ */
+
+ Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
+ Tcl_AppendResult(interp, "bad index \"", string, "\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else if (string[0] == '@') {
+ int i;
+ double x ,y, bestDist, dist, *coordPtr;
+ char *end, *p;
+
+ p = string+1;
+ x = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ p = end+1;
+ y = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ bestDist = 1.0e36;
+ coordPtr = polyPtr->coordPtr;
+ *indexPtr = 0;
+ for(i=0; i<(polyPtr->numPoints-1); i++) {
+ dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
+ if (dist<bestDist) {
+ bestDist = dist;
+ *indexPtr = 2*i;
+ }
+ coordPtr += 2;
+ }
+ } else {
+ int count = 2*(polyPtr->numPoints - polyPtr->autoClosed);
+ if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ *indexPtr &= -2; /* if odd, make it even */
+ if (count) {
+ if (*indexPtr > 0) {
+ *indexPtr = ((*indexPtr - 2) % count) + 2;
+ } else {
+ *indexPtr = -((-(*indexPtr)) % count);
+ }
+ } else {
+ *indexPtr = 0;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* TranslatePolygon --
*
* This procedure is called to move a polygon by a given
@@ -921,7 +1776,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.
*
@@ -942,31 +1797,104 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass)
* collect font information; 0 means
* final Postscript is being created. */
{
- char string[100];
PolygonItem *polyPtr = (PolygonItem *) itemPtr;
+ char *style;
+ XColor *color;
+ XColor *fillColor;
+ Pixmap stipple;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
+ double width;
+
+ if (polyPtr->numPoints<2 || polyPtr->coordPtr==NULL) {
+ return TCL_OK;
+ }
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = polyPtr->outline.width;
+ color = polyPtr->outline.color;
+ stipple = polyPtr->fillStipple;
+ fillColor = polyPtr->fillColor;
+ fillStipple = polyPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (polyPtr->outline.activeWidth>width) {
+ width = polyPtr->outline.activeWidth;
+ }
+ if (polyPtr->outline.activeColor!=NULL) {
+ color = polyPtr->outline.activeColor;
+ }
+ if (polyPtr->outline.activeStipple!=None) {
+ stipple = polyPtr->outline.activeStipple;
+ }
+ if (polyPtr->activeFillColor!=NULL) {
+ fillColor = polyPtr->activeFillColor;
+ }
+ if (polyPtr->activeFillStipple!=None) {
+ fillStipple = polyPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (polyPtr->outline.disabledWidth>0.0) {
+ width = polyPtr->outline.disabledWidth;
+ }
+ if (polyPtr->outline.disabledColor!=NULL) {
+ color = polyPtr->outline.disabledColor;
+ }
+ if (polyPtr->outline.disabledStipple!=None) {
+ stipple = polyPtr->outline.disabledStipple;
+ }
+ if (polyPtr->disabledFillColor!=NULL) {
+ fillColor = polyPtr->disabledFillColor;
+ }
+ if (polyPtr->disabledFillStipple!=None) {
+ fillStipple = polyPtr->disabledFillStipple;
+ }
+ }
+ if (polyPtr->numPoints==2) {
+ char string[128];
+ sprintf(string, "%.15g %.15g translate %.15g %.15g",
+ polyPtr->coordPtr[0], Tk_CanvasPsY(canvas, polyPtr->coordPtr[1]),
+ width/2.0, width/2.0);
+ Tcl_AppendResult(interp, "matrix currentmatrix\n",string,
+ " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL);
+ if (Tk_CanvasPsColor(interp, canvas, color)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (stipple != None) {
+ Tcl_AppendResult(interp, "clip ", (char *) NULL);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "fill\n", (char *) NULL);
+ }
+ return TCL_OK;
+ }
/*
* Fill the area of the polygon.
*/
- if (polyPtr->fillColor != NULL) {
- if (!polyPtr->smooth) {
+ if (fillColor != NULL && polyPtr->numPoints>3) {
+ if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
polyPtr->numPoints);
} else {
- TkMakeBezierPostscript(interp, canvas, polyPtr->coordPtr,
- polyPtr->numPoints);
+ polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps);
}
- if (Tk_CanvasPsColor(interp, canvas, polyPtr->fillColor) != TCL_OK) {
+ if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
return TCL_ERROR;
}
- if (polyPtr->fillStipple != None) {
+ if (fillStipple != None) {
Tcl_AppendResult(interp, "eoclip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, polyPtr->fillStipple)
+ if (Tk_CanvasPsStipple(interp, canvas, fillStipple)
!= TCL_OK) {
return TCL_ERROR;
}
- if (polyPtr->outlineColor != NULL) {
+ if (color != NULL) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
}
} else {
@@ -978,23 +1906,31 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass)
* Now draw the outline, if there is one.
*/
- if (polyPtr->outlineColor != NULL) {
- if (!polyPtr->smooth) {
+ if (color != NULL) {
+
+ if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
polyPtr->numPoints);
} else {
- TkMakeBezierPostscript(interp, canvas, polyPtr->coordPtr,
- polyPtr->numPoints);
+ polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
+ polyPtr->numPoints, polyPtr->splineSteps);
}
- sprintf(string, "%d setlinewidth\n", polyPtr->width);
- Tcl_AppendResult(interp, string,
- "1 setlinecap\n1 setlinejoin\n", (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, polyPtr->outlineColor)
- != TCL_OK) {
+ if (polyPtr->joinStyle == JoinRound) {
+ style = "1";
+ } else if (polyPtr->joinStyle == JoinBevel) {
+ style = "2";
+ } else {
+ style = "0";
+ }
+ Tcl_AppendResult(interp, style," setlinejoin 1 setlinecap\n",
+ (char *) NULL);
+ if (Tk_CanvasPsOutline(canvas, itemPtr,
+ &(polyPtr->outline)) != TCL_OK) {
return TCL_ERROR;
}
- Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
}
return TCL_OK;
}
+
+
diff --git a/tk/generic/tkCanvPs.c b/tk/generic/tkCanvPs.c
index eb45f87b80b..66b1cc9d7df 100644
--- a/tk/generic/tkCanvPs.c
+++ b/tk/generic/tkCanvPs.c
@@ -6,7 +6,7 @@
* 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.
@@ -68,6 +68,8 @@ typedef struct TkPostscriptInfo {
* the pre-pass that collects font information,
* so the Postscript generated isn't
* relevant. */
+ int prolog; /* Non-zero means output should contain
+ the file prolog.ps in the header. */
} TkPostscriptInfo;
/*
@@ -99,6 +101,8 @@ static Tk_ConfigSpec configSpecs[] = {
"", Tk_Offset(TkPostscriptInfo, pageXString), 0},
{TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL,
"", Tk_Offset(TkPostscriptInfo, pageYString), 0},
+ {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL,
+ "", Tk_Offset(TkPostscriptInfo, prolog), 0},
{TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL,
"", Tk_Offset(TkPostscriptInfo, rotate), 0},
{TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
@@ -115,6 +119,7 @@ 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) */
@@ -460,13 +465,15 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
* to know that argv[1] is
* "postscript". */
{
- TkPostscriptInfo psInfo, *oldInfoPtr;
+ TkPostscriptInfo psInfo;
+ Tk_PostscriptInfo oldInfoPtr;
int result;
Tk_Item *itemPtr;
#define STRING_LENGTH 400
char string[STRING_LENGTH+1], *p;
time_t now;
size_t length;
+ Tk_Window tkwin = canvasPtr->tkwin;
int deltaX = 0, deltaY = 0; /* Offset of lower-left corner of
* area to be marked up, measured
* in canvas units from the positioning
@@ -486,8 +493,8 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*----------------------------------------------------------------
*/
- oldInfoPtr = canvasPtr->psInfoPtr;
- canvasPtr->psInfoPtr = &psInfo;
+ oldInfoPtr = canvasPtr->psInfo;
+ canvasPtr->psInfo = (Tk_PostscriptInfo) &psInfo;
psInfo.x = canvasPtr->xOrigin;
psInfo.y = canvasPtr->yOrigin;
psInfo.width = -1;
@@ -509,8 +516,9 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
psInfo.channelName = NULL;
psInfo.chan = NULL;
psInfo.prepass = 0;
+ psInfo.prolog = 1;
Tcl_InitHashTable(&psInfo.fontTable, TCL_STRING_KEYS);
- result = Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
+ result = Tk_ConfigureWidget(interp, tkwin,
configSpecs, argc-2, argv+2, (char *) &psInfo,
TK_CONFIG_ARGV_ONLY);
if (result != TCL_OK) {
@@ -518,41 +526,41 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
}
if (psInfo.width == -1) {
- psInfo.width = Tk_Width(canvasPtr->tkwin);
+ psInfo.width = Tk_Width(tkwin);
}
if (psInfo.height == -1) {
- psInfo.height = Tk_Height(canvasPtr->tkwin);
+ psInfo.height = Tk_Height(tkwin);
}
psInfo.x2 = psInfo.x + psInfo.width;
psInfo.y2 = psInfo.y + psInfo.height;
if (psInfo.pageXString != NULL) {
- if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageXString,
+ if (GetPostscriptPoints(interp, psInfo.pageXString,
&psInfo.pageX) != TCL_OK) {
goto cleanup;
}
}
if (psInfo.pageYString != NULL) {
- if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageYString,
+ if (GetPostscriptPoints(interp, psInfo.pageYString,
&psInfo.pageY) != TCL_OK) {
goto cleanup;
}
}
if (psInfo.pageWidthString != NULL) {
- if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageWidthString,
+ if (GetPostscriptPoints(interp, psInfo.pageWidthString,
&psInfo.scale) != TCL_OK) {
goto cleanup;
}
psInfo.scale /= psInfo.width;
} else if (psInfo.pageHeightString != NULL) {
- if (GetPostscriptPoints(canvasPtr->interp, psInfo.pageHeightString,
+ if (GetPostscriptPoints(interp, psInfo.pageHeightString,
&psInfo.scale) != TCL_OK) {
goto cleanup;
}
psInfo.scale /= psInfo.height;
} else {
- psInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(canvasPtr->tkwin));
- psInfo.scale /= WidthOfScreen(Tk_Screen(canvasPtr->tkwin));
+ psInfo.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin));
+ psInfo.scale /= WidthOfScreen(Tk_Screen(tkwin));
}
switch (psInfo.pageAnchor) {
case TK_ANCHOR_NW:
@@ -600,7 +608,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
} else if (strncmp(psInfo.colorMode, "color", length) == 0) {
psInfo.colorLevel = 2;
} else {
- Tcl_AppendResult(canvasPtr->interp, "bad color mode \"",
+ Tcl_AppendResult(interp, "bad color mode \"",
psInfo.colorMode, "\": must be monochrome, ",
"gray, or color", (char *) NULL);
goto cleanup;
@@ -614,7 +622,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*/
if (psInfo.channelName != NULL) {
- Tcl_AppendResult(canvasPtr->interp, "can't specify both -file",
+ Tcl_AppendResult(interp, "can't specify both -file",
" and -channel", (char *) NULL);
result = TCL_ERROR;
goto cleanup;
@@ -625,18 +633,18 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
* the -file specification.
*/
- if (Tcl_IsSafe(canvasPtr->interp)) {
- Tcl_AppendResult(canvasPtr->interp, "can't specify -file in a",
+ if (Tcl_IsSafe(interp)) {
+ Tcl_AppendResult(interp, "can't specify -file in a",
" safe interpreter", (char *) NULL);
result = TCL_ERROR;
goto cleanup;
}
- p = Tcl_TranslateFileName(canvasPtr->interp, psInfo.fileName, &buffer);
+ p = Tcl_TranslateFileName(interp, psInfo.fileName, &buffer);
if (p == NULL) {
goto cleanup;
}
- psInfo.chan = Tcl_OpenFileChannel(canvasPtr->interp, p, "w", 0666);
+ psInfo.chan = Tcl_OpenFileChannel(interp, p, "w", 0666);
Tcl_DStringFree(&buffer);
if (psInfo.chan == NULL) {
goto cleanup;
@@ -651,14 +659,14 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
* is open for writing.
*/
- psInfo.chan = Tcl_GetChannel(canvasPtr->interp, psInfo.channelName,
+ psInfo.chan = Tcl_GetChannel(interp, psInfo.channelName,
&mode);
if (psInfo.chan == (Tcl_Channel) NULL) {
result = TCL_ERROR;
goto cleanup;
}
if ((mode & TCL_WRITABLE) == 0) {
- Tcl_AppendResult(canvasPtr->interp, "channel \"",
+ Tcl_AppendResult(interp, "channel \"",
psInfo.channelName, "\" wasn't opened for writing",
(char *) NULL);
result = TCL_ERROR;
@@ -686,9 +694,9 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
if (itemPtr->typePtr->postscriptProc == NULL) {
continue;
}
- result = (*itemPtr->typePtr->postscriptProc)(canvasPtr->interp,
+ result = (*itemPtr->typePtr->postscriptProc)(interp,
(Tk_Canvas) canvasPtr, itemPtr, 1);
- Tcl_ResetResult(canvasPtr->interp);
+ Tcl_ResetResult(interp);
if (result != TCL_OK) {
/*
* An error just occurred. Just skip out of this loop.
@@ -708,22 +716,23 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*--------------------------------------------------------
*/
- Tcl_AppendResult(canvasPtr->interp, "%!PS-Adobe-3.0 EPSF-3.0\n",
+ if (psInfo.prolog) {
+ Tcl_AppendResult(interp, "%!PS-Adobe-3.0 EPSF-3.0\n",
"%%Creator: Tk Canvas Widget\n", (char *) NULL);
-#if !(defined(__WIN32__) || defined(MAC_TCL))
+#ifdef HAVE_PW_GECOS
if (!Tcl_IsSafe(interp)) {
- struct passwd *pwPtr = getpwuid(getuid());
- Tcl_AppendResult(canvasPtr->interp, "%%For: ",
+ struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */
+ Tcl_AppendResult(interp, "%%For: ",
(pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n",
(char *) NULL);
endpwent();
}
-#endif /* __WIN32__ || MAC_TCL */
- Tcl_AppendResult(canvasPtr->interp, "%%Title: Window ",
- Tk_PathName(canvasPtr->tkwin), "\n", (char *) NULL);
+#endif /* HAVE_PW_GECOS */
+ Tcl_AppendResult(interp, "%%Title: Window ",
+ Tk_PathName(tkwin), "\n", (char *) NULL);
time(&now);
- Tcl_AppendResult(canvasPtr->interp, "%%CreationDate: ",
- ctime(&now), (char *) NULL);
+ Tcl_AppendResult(interp, "%%CreationDate: ",
+ ctime(&now), (char *) NULL); /* INTL: Native. */
if (!psInfo.rotate) {
sprintf(string, "%d %d %d %d",
(int) (psInfo.pageX + psInfo.scale*deltaX),
@@ -740,21 +749,21 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
(int) (psInfo.pageY + psInfo.scale*(deltaX + psInfo.width)
+ 1.0));
}
- Tcl_AppendResult(canvasPtr->interp, "%%BoundingBox: ", string,
+ Tcl_AppendResult(interp, "%%BoundingBox: ", string,
"\n", (char *) NULL);
- Tcl_AppendResult(canvasPtr->interp, "%%Pages: 1\n",
+ Tcl_AppendResult(interp, "%%Pages: 1\n",
"%%DocumentData: Clean7Bit\n", (char *) NULL);
- Tcl_AppendResult(canvasPtr->interp, "%%Orientation: ",
+ Tcl_AppendResult(interp, "%%Orientation: ",
psInfo.rotate ? "Landscape\n" : "Portrait\n", (char *) NULL);
p = "%%DocumentNeededResources: font ";
for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);
hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- Tcl_AppendResult(canvasPtr->interp, p,
+ Tcl_AppendResult(interp, p,
Tcl_GetHashKey(&psInfo.fontTable, hPtr),
"\n", (char *) NULL);
p = "%%+ font ";
}
- Tcl_AppendResult(canvasPtr->interp, "%%EndComments\n\n", (char *) NULL);
+ Tcl_AppendResult(interp, "%%EndComments\n\n", (char *) NULL);
/*
* Insert the prolog
@@ -764,7 +773,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
}
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -775,14 +784,14 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*/
sprintf(string, "/CL %d def\n", psInfo.colorLevel);
- Tcl_AppendResult(canvasPtr->interp, "%%BeginSetup\n", string,
+ Tcl_AppendResult(interp, "%%BeginSetup\n", string,
(char *) NULL);
for (hPtr = Tcl_FirstHashEntry(&psInfo.fontTable, &search);
hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- Tcl_AppendResult(canvasPtr->interp, "%%IncludeResource: font ",
+ Tcl_AppendResult(interp, "%%IncludeResource: font ",
Tcl_GetHashKey(&psInfo.fontTable, hPtr), "\n", (char *) NULL);
}
- Tcl_AppendResult(canvasPtr->interp, "%%EndSetup\n\n", (char *) NULL);
+ Tcl_AppendResult(interp, "%%EndSetup\n\n", (char *) NULL);
/*
*-----------------------------------------------------------
@@ -792,26 +801,31 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*-----------------------------------------------------------
*/
- Tcl_AppendResult(canvasPtr->interp, "%%Page: 1 1\n", "save\n",
+ Tcl_AppendResult(interp, "%%Page: 1 1\n", "save\n",
(char *) NULL);
sprintf(string, "%.1f %.1f translate\n", psInfo.pageX, psInfo.pageY);
- Tcl_AppendResult(canvasPtr->interp, string, (char *) NULL);
+ Tcl_AppendResult(interp, string, (char *) NULL);
if (psInfo.rotate) {
- Tcl_AppendResult(canvasPtr->interp, "90 rotate\n", (char *) NULL);
+ Tcl_AppendResult(interp, "90 rotate\n", (char *) NULL);
}
sprintf(string, "%.4g %.4g scale\n", psInfo.scale, psInfo.scale);
- Tcl_AppendResult(canvasPtr->interp, string, (char *) NULL);
+ Tcl_AppendResult(interp, string, (char *) NULL);
sprintf(string, "%d %d translate\n", deltaX - psInfo.x, deltaY);
- Tcl_AppendResult(canvasPtr->interp, string, (char *) NULL);
+ Tcl_AppendResult(interp, string, (char *) NULL);
sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g",
- psInfo.x, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y),
- psInfo.x2, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y),
- psInfo.x2, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y2),
- psInfo.x, Tk_CanvasPsY((Tk_Canvas) canvasPtr, (double) psInfo.y2));
- Tcl_AppendResult(canvasPtr->interp, string,
+ psInfo.x,
+ Tk_PostscriptY((double) psInfo.y, (Tk_PostscriptInfo) &psInfo),
+ psInfo.x2,
+ Tk_PostscriptY((double) psInfo.y, (Tk_PostscriptInfo) &psInfo),
+ psInfo.x2,
+ Tk_PostscriptY((double) psInfo.y2, (Tk_PostscriptInfo) &psInfo),
+ psInfo.x,
+ Tk_PostscriptY((double) psInfo.y2, (Tk_PostscriptInfo) &psInfo));
+ Tcl_AppendResult(interp, string,
" lineto closepath clip newpath\n", (char *) NULL);
+ }
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -832,21 +846,24 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
if (itemPtr->typePtr->postscriptProc == NULL) {
continue;
}
- Tcl_AppendResult(canvasPtr->interp, "gsave\n", (char *) NULL);
- result = (*itemPtr->typePtr->postscriptProc)(canvasPtr->interp,
+ if (itemPtr->state == TK_STATE_HIDDEN) {
+ continue;
+ }
+ Tcl_AppendResult(interp, "gsave\n", (char *) NULL);
+ result = (*itemPtr->typePtr->postscriptProc)(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);
- Tcl_AddErrorInfo(canvasPtr->interp, msg);
+ Tcl_AddErrorInfo(interp, msg);
goto cleanup;
}
- Tcl_AppendResult(canvasPtr->interp, "grestore\n", (char *) NULL);
+ Tcl_AppendResult(interp, "grestore\n", (char *) NULL);
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, canvasPtr->interp->result, -1);
- Tcl_ResetResult(canvasPtr->interp);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
+ Tcl_ResetResult(interp);
}
}
@@ -857,10 +874,12 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*---------------------------------------------------------------------
*/
- Tcl_AppendResult(canvasPtr->interp, "restore showpage\n\n",
+ if (psInfo.prolog) {
+ Tcl_AppendResult(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(interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -894,20 +913,20 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
ckfree(psInfo.fileName);
}
if ((psInfo.chan != NULL) && (psInfo.channelName == NULL)) {
- Tcl_Close(canvasPtr->interp, psInfo.chan);
+ Tcl_Close(interp, psInfo.chan);
}
if (psInfo.channelName != NULL) {
ckfree(psInfo.channelName);
}
Tcl_DeleteHashTable(&psInfo.fontTable);
- canvasPtr->psInfoPtr = oldInfoPtr;
+ canvasPtr->psInfo = (Tk_PostscriptInfo) oldInfoPtr;
return result;
}
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsColor --
+ * Tk_PostscriptColor --
*
* This procedure is called by individual canvas items when
* they want to set a color value for output. Given information
@@ -916,9 +935,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.
@@ -927,14 +946,12 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
*/
int
-Tk_CanvasPsColor(interp, canvas, colorPtr)
- Tcl_Interp *interp; /* Interpreter for returning Postscript
- * or error message. */
- Tk_Canvas canvas; /* Information about canvas. */
+Tk_PostscriptColor(interp, psInfo, colorPtr)
+ Tcl_Interp *interp;
+ Tk_PostscriptInfo psInfo; /* Postscript info. */
XColor *colorPtr; /* Information about color. */
{
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr;
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
int tmp;
double red, green, blue;
char string[200];
@@ -988,7 +1005,7 @@ Tk_CanvasPsColor(interp, canvas, colorPtr)
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsFont --
+ * Tk_PostscriptFont --
*
* This procedure is called by individual canvas items when
* they want to output text. Given information about an X
@@ -997,9 +1014,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
@@ -1009,17 +1026,15 @@ Tk_CanvasPsColor(interp, canvas, colorPtr)
*/
int
-Tk_CanvasPsFont(interp, canvas, tkfont)
- Tcl_Interp *interp; /* Interpreter for returning Postscript
- * or error message. */
- Tk_Canvas canvas; /* Information about canvas. */
+Tk_PostscriptFont(interp, psInfo, tkfont)
+ Tcl_Interp *interp;
+ Tk_PostscriptInfo psInfo; /* Postscript Info. */
Tk_Font tkfont; /* Information about font in which text
* is to be printed. */
{
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr;
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
char *end;
- char pointString[20];
+ char pointString[TCL_INTEGER_SPACE];
Tcl_DString ds;
int i, points;
@@ -1082,7 +1097,7 @@ Tk_CanvasPsFont(interp, canvas, tkfont)
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsBitmap --
+ * Tk_PostscriptBitmap --
*
* This procedure is called to output the contents of a
* sub-region of a bitmap in proper image data format for
@@ -1091,9 +1106,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.
@@ -1102,18 +1117,18 @@ Tk_CanvasPsFont(interp, canvas, tkfont)
*/
int
-Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height)
- Tcl_Interp *interp; /* Interpreter for returning Postscript
- * or error message. */
- Tk_Canvas canvas; /* Information about canvas. */
+Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, startX, startY, width,
+ height)
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+ Tk_PostscriptInfo psInfo; /* Postscript info. */
Pixmap bitmap; /* Bitmap for which to generate
* Postscript. */
int startX, startY; /* Coordinates of upper-left corner
* of rectangular region to output. */
int width, height; /* Height of rectangular region. */
{
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr;
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
XImage *imagePtr;
int charsInLine, x, y, lastX, lastY, value, mask;
unsigned int totalWidth, totalHeight;
@@ -1134,10 +1149,10 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height)
* it shouldn't matter here.
*/
- XGetGeometry(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &dummyRoot,
+ XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot,
(int *) &dummyX, (int *) &dummyY, (unsigned int *) &totalWidth,
(unsigned int *) &totalHeight, &dummyBorderwidth, &dummyDepth);
- imagePtr = XGetImage(Tk_Display(canvasPtr->tkwin), bitmap, 0, 0,
+ imagePtr = XGetImage(Tk_Display(tkwin), bitmap, 0, 0,
totalWidth, totalHeight, 1, XYPixmap);
Tcl_AppendResult(interp, "<", (char *) NULL);
mask = 0x80;
@@ -1179,7 +1194,7 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height)
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsStipple --
+ * Tk_PostscriptStipple --
*
* This procedure is called by individual canvas items when
* they have created a path that they'd like to be filled with
@@ -1190,9 +1205,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.
@@ -1201,16 +1216,16 @@ Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height)
*/
int
-Tk_CanvasPsStipple(interp, canvas, bitmap)
- Tcl_Interp *interp; /* Interpreter for returning Postscript
+Tk_PostscriptStipple(interp, tkwin, psInfo, bitmap)
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+ Tk_PostscriptInfo psInfo; /* Interpreter for returning Postscript
* or error message. */
- Tk_Canvas canvas; /* Information about canvas. */
Pixmap bitmap; /* Bitmap to use for stippling. */
{
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- TkPostscriptInfo *psInfoPtr = canvasPtr->psInfoPtr;
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
int width, height;
- char string[100];
+ char string[TCL_INTEGER_SPACE * 2];
Window dummyRoot;
int dummyX, dummyY;
unsigned dummyBorderwidth, dummyDepth;
@@ -1227,12 +1242,12 @@ Tk_CanvasPsStipple(interp, canvas, bitmap)
* it shouldn't matter here.
*/
- XGetGeometry(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &dummyRoot,
+ XGetGeometry(Tk_Display(tkwin), bitmap, &dummyRoot,
(int *) &dummyX, (int *) &dummyY, (unsigned *) &width,
(unsigned *) &height, &dummyBorderwidth, &dummyDepth);
sprintf(string, "%d %d ", width, height);
Tcl_AppendResult(interp, string, (char *) NULL);
- if (Tk_CanvasPsBitmap(interp, (Tk_Canvas) canvasPtr, bitmap, 0, 0,
+ if (Tk_PostscriptBitmap(interp, tkwin, psInfo, bitmap, 0, 0,
width, height) != TCL_OK) {
return TCL_ERROR;
}
@@ -1243,9 +1258,9 @@ Tk_CanvasPsStipple(interp, canvas, bitmap)
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsY --
+ * Tk_PostscriptY --
*
- * Given a y-coordinate in canvas coordinates, this procedure
+ * Given a y-coordinate in local coordinates, this procedure
* returns a y-coordinate to use for Postscript output.
*
* Results:
@@ -1259,12 +1274,11 @@ Tk_CanvasPsStipple(interp, canvas, bitmap)
*/
double
-Tk_CanvasPsY(canvas, y)
- Tk_Canvas canvas; /* Token for canvas on whose behalf
- * Postscript is being generated. */
+Tk_PostscriptY(y, psInfo)
double y; /* Y-coordinate in canvas coords. */
+ Tk_PostscriptInfo psInfo; /* Postscript info */
{
- TkPostscriptInfo *psInfoPtr = ((TkCanvas *) canvas)->psInfoPtr;
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
return psInfoPtr->y2 - y;
}
@@ -1272,13 +1286,13 @@ Tk_CanvasPsY(canvas, y)
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsPath --
+ * Tk_PostscriptPath --
*
* Given an array of points for a path, generate Postscript
* commands to create the path.
*
* Results:
- * Postscript commands get appended to what's in interp->result.
+ * Postscript commands get appended to what's in the interp's result.
*
* Side effects:
* None.
@@ -1287,29 +1301,28 @@ Tk_CanvasPsY(canvas, y)
*/
void
-Tk_CanvasPsPath(interp, canvas, coordPtr, numPoints)
- Tcl_Interp *interp; /* Put generated Postscript in this
- * interpreter's result field. */
- Tk_Canvas canvas; /* Canvas on whose behalf Postscript
+Tk_PostscriptPath(interp, psInfo, coordPtr, numPoints)
+ Tcl_Interp *interp;
+ Tk_PostscriptInfo psInfo; /* Canvas on whose behalf Postscript
* is being generated. */
double *coordPtr; /* Pointer to first in array of
* 2*numPoints coordinates giving
* points for path. */
int numPoints; /* Number of points at *coordPtr. */
{
- TkPostscriptInfo *psInfoPtr = ((TkCanvas *) canvas)->psInfoPtr;
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
char buffer[200];
if (psInfoPtr->prepass) {
return;
}
sprintf(buffer, "%.15g %.15g moveto\n", coordPtr[0],
- Tk_CanvasPsY(canvas, coordPtr[1]));
+ Tk_PostscriptY(coordPtr[1], psInfo));
Tcl_AppendResult(interp, buffer, (char *) NULL);
for (numPoints--, coordPtr += 2; numPoints > 0;
numPoints--, coordPtr += 2) {
sprintf(buffer, "%.15g %.15g lineto\n", coordPtr[0],
- Tk_CanvasPsY(canvas, coordPtr[1]));
+ Tk_PostscriptY(coordPtr[1], psInfo));
Tcl_AppendResult(interp, buffer, (char *) NULL);
}
}
@@ -1327,7 +1340,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.
@@ -1384,3 +1397,750 @@ GetPostscriptPoints(interp, string, doublePtr)
*doublePtr = d;
return TCL_OK;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkImageGetColor --
+ *
+ * This procedure converts a pixel value to three floating
+ * point numbers, representing the amount of red, green, and
+ * blue in that pixel on the screen. It makes use of colormap
+ * data passed as an argument, and should work for all Visual
+ * types.
+ *
+ * Results:
+ * Returns red, green, and blue color values in the range
+ * 0 to 1. There are no error returns.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TkImageGetColor(cdata, pixel, red, green, blue)
+ TkColormapData *cdata; /* Colormap data */
+ unsigned long pixel; /* Pixel value to look up */
+ double *red, *green, *blue; /* Color data to return */
+{
+ if (cdata->separated) {
+ int r = (pixel & cdata->red_mask) >> cdata->red_shift;
+ int g = (pixel & cdata->green_mask) >> cdata->green_shift;
+ int b = (pixel & cdata->blue_mask) >> cdata->blue_shift;
+ *red = cdata->colors[r].red / 65535.0;
+ *green = cdata->colors[g].green / 65535.0;
+ *blue = cdata->colors[b].blue / 65535.0;
+ } else {
+ *red = cdata->colors[pixel].red / 65535.0;
+ *green = cdata->colors[pixel].green / 65535.0;
+ *blue = cdata->colors[pixel].blue / 65535.0;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPostscriptImage --
+ *
+ * This procedure is called to output the contents of an
+ * image in Postscript, using a format appropriate for the
+ * current color mode (i.e. one bit per pixel in monochrome,
+ * one byte per pixel in gray, and three bytes per pixel in
+ * color).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkPostscriptImage(interp, tkwin, psInfo, ximage, x, y, width, height)
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+ Tk_PostscriptInfo psInfo; /* postscript info */
+ XImage *ximage; /* Image to draw */
+ int x, y; /* First pixel to output */
+ int width, height; /* Width and height of area */
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ char buffer[256];
+ int xx, yy, band, maxRows;
+ double red, green, blue;
+ int bytesPerLine=0, maxWidth=0;
+ int level = psInfoPtr->colorLevel;
+ Colormap cmap;
+ int i, depth, ncolors;
+ Visual *visual;
+ TkColormapData cdata;
+
+ if (psInfoPtr->prepass) {
+ return TCL_OK;
+ }
+
+ cmap = Tk_Colormap(tkwin);
+ depth = Tk_Depth(tkwin);
+ visual = Tk_Visual(tkwin);
+
+ /*
+ * Obtain information about the colormap, ie the mapping between
+ * pixel values and RGB values. The code below should work
+ * for all Visual types.
+ */
+
+ ncolors = visual->map_entries;
+ cdata.colors = (XColor *) ckalloc(sizeof(XColor) * ncolors);
+ cdata.ncolors = ncolors;
+
+ if (visual->class == DirectColor || visual->class == TrueColor) {
+ cdata.separated = 1;
+ cdata.red_mask = visual->red_mask;
+ cdata.green_mask = visual->green_mask;
+ cdata.blue_mask = visual->blue_mask;
+ cdata.red_shift = 0;
+ cdata.green_shift = 0;
+ cdata.blue_shift = 0;
+ while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0)
+ cdata.red_shift ++;
+ while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0)
+ cdata.green_shift ++;
+ while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0)
+ cdata.blue_shift ++;
+ for (i = 0; i < ncolors; i ++)
+ cdata.colors[i].pixel =
+ ((i << cdata.red_shift) & cdata.red_mask) |
+ ((i << cdata.green_shift) & cdata.green_mask) |
+ ((i << cdata.blue_shift) & cdata.blue_mask);
+ } else {
+ cdata.separated=0;
+ for (i = 0; i < ncolors; i ++)
+ cdata.colors[i].pixel = i;
+ }
+ if (visual->class == StaticGray || visual->class == GrayScale)
+ cdata.color = 0;
+ else
+ cdata.color = 1;
+
+
+ XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors);
+
+ /*
+ * Figure out which color level to use (possibly lower than the
+ * one specified by the user). For example, if the user specifies
+ * color with monochrome screen, use gray or monochrome mode instead.
+ */
+
+ if (!cdata.color && level == 2) {
+ level = 1;
+ }
+
+ if (!cdata.color && cdata.ncolors == 2) {
+ level = 0;
+ }
+
+ /*
+ * Check that at least one row of the image can be represented
+ * with a string less than 64 KB long (this is a limit in the
+ * Postscript interpreter).
+ */
+
+ switch (level)
+ {
+ case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
+ case 1: bytesPerLine = width; maxWidth = 60000; break;
+ case 2: bytesPerLine = 3 * width; maxWidth = 20000; break;
+ }
+
+ if (bytesPerLine > 60000) {
+ Tcl_ResetResult(interp);
+ sprintf(buffer,
+ "Can't generate Postscript for images more than %d pixels wide",
+ maxWidth);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ ckfree((char *) cdata.colors);
+ return TCL_ERROR;
+ }
+
+ maxRows = 60000 / bytesPerLine;
+
+ for (band = height-1; band >= 0; band -= maxRows) {
+ int rows = (band >= maxRows) ? maxRows : band + 1;
+ int lineLen = 0;
+ switch (level) {
+ case 0:
+ sprintf(buffer, "%d %d 1 matrix {\n<", width, rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ break;
+ case 1:
+ sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ break;
+ case 2:
+ sprintf(buffer, "%d %d 8 matrix {\n<",
+ width, rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ break;
+ }
+ for (yy = band; yy > band - rows; yy--) {
+ switch (level) {
+ case 0: {
+ /*
+ * Generate data for image in monochrome mode.
+ * No attempt at dithering is made--instead, just
+ * set a threshold.
+ */
+ unsigned char mask=0x80;
+ unsigned char data=0x00;
+ for (xx = x; xx< x+width; xx++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5)
+ data |= mask;
+ mask >>= 1;
+ if (mask == 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ mask=0x80;
+ data=0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ mask=0x80;
+ data=0x00;
+ }
+ break;
+ }
+ case 1: {
+ /*
+ * Generate data in gray mode--in this case, take a
+ * weighted sum of the red, green, and blue values.
+ */
+ for (xx = x; xx < x+width; xx ++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 *
+ (0.30 * red +
+ 0.59 * green +
+ 0.11 * blue)));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ case 2: {
+ /*
+ * Finally, color mode. Here, just output the red, green,
+ * and blue values directly.
+ */
+ for (xx = x; xx < x+width; xx++) {
+ TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
+ &red, &green, &blue);
+ sprintf(buffer, "%02X%02X%02X",
+ (int) floor(0.5 + 255.0 * red),
+ (int) floor(0.5 + 255.0 * green),
+ (int) floor(0.5 + 255.0 * blue));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 6;
+ if (lineLen > 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ }
+ }
+ switch (level) {
+ case 0: sprintf(buffer, ">\n} image\n"); break;
+ case 1: sprintf(buffer, ">\n} image\n"); break;
+ case 2: sprintf(buffer, ">\n} false 3 colorimage\n"); break;
+ }
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ sprintf(buffer, "0 %d translate\n", rows);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ }
+ ckfree((char *) cdata.colors);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_PostscriptPhoto --
+ *
+ * This procedure is called to output the contents of a
+ * photo image in Postscript, using a format appropriate for
+ * the requested postscript color mode (i.e. one byte per pixel
+ * in gray, and three bytes per pixel in color).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to the interpreter's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Tk_PostscriptPhoto(interp, blockPtr, psInfo, width, height)
+ Tcl_Interp *interp;
+ Tk_PhotoImageBlock *blockPtr;
+ Tk_PostscriptInfo psInfo;
+ int width, height;
+{
+ TkPostscriptInfo *psInfoPtr = (TkPostscriptInfo *) psInfo;
+ int colorLevel = psInfoPtr->colorLevel;
+ static int codeIncluded = 0;
+
+ unsigned char *pixelPtr;
+ char buffer[256], cspace[40], decode[40];
+ int bpc;
+ int xx, yy, lineLen;
+ float red, green, blue;
+ int alpha;
+ int bytesPerLine=0, maxWidth=0;
+
+ unsigned char opaque = 255;
+ unsigned char *alphaPtr;
+ int alphaOffset, alphaPitch, alphaIncr;
+
+ if (psInfoPtr->prepass) {
+ codeIncluded = 0;
+ return TCL_OK;
+ }
+
+ /*
+ * Define the "TkPhoto" function, which is a modified version
+ * of the original "transparentimage" function posted
+ * by ian@five-d.com (Ian Kemmish) to comp.lang.postscript.
+ * For a monochrome colorLevel this is a slightly different
+ * version that uses the imagemask command instead of image.
+ */
+
+ if( !codeIncluded && (colorLevel != 0) ) {
+ /*
+ * Color and gray-scale code.
+ */
+
+ codeIncluded = !0;
+ Tcl_AppendResult( interp,
+ "/TkPhoto { \n",
+ " gsave \n",
+ " 32 dict begin \n",
+ " /tinteger exch def \n",
+ " /transparent 1 string def \n",
+ " transparent 0 tinteger put \n",
+ " /olddict exch def \n",
+ " olddict /DataSource get dup type /filetype ne { \n",
+ " olddict /DataSource 3 -1 roll \n",
+ " 0 () /SubFileDecode filter put \n",
+ " } { \n",
+ " pop \n",
+ " } ifelse \n",
+ " /newdict olddict maxlength dict def \n",
+ " olddict newdict copy pop \n",
+ " /w newdict /Width get def \n",
+ " /crpp newdict /Decode get length 2 idiv def \n",
+ " /str w string def \n",
+ " /pix w crpp mul string def \n",
+ " /substrlen 2 w log 2 log div floor exp cvi def \n",
+ " /substrs [ \n",
+ " { \n",
+ " substrlen string \n",
+ " 0 1 substrlen 1 sub { \n",
+ " 1 index exch tinteger put \n",
+ " } for \n",
+ " /substrlen substrlen 2 idiv def \n",
+ " substrlen 0 eq {exit} if \n",
+ " } loop \n",
+ " ] def \n",
+ " /h newdict /Height get def \n",
+ " 1 w div 1 h div matrix scale \n",
+ " olddict /ImageMatrix get exch matrix concatmatrix \n",
+ " matrix invertmatrix concat \n",
+ " newdict /Height 1 put \n",
+ " newdict /DataSource pix put \n",
+ " /mat [w 0 0 h 0 0] def \n",
+ " newdict /ImageMatrix mat put \n",
+ " 0 1 h 1 sub { \n",
+ " mat 5 3 -1 roll neg put \n",
+ " olddict /DataSource get str readstring pop pop \n",
+ " /tail str def \n",
+ " /x 0 def \n",
+ " olddict /DataSource get pix readstring pop pop \n",
+ " { \n",
+ " tail transparent search dup /done exch not def \n",
+ " {exch pop exch pop} if \n",
+ " /w1 exch length def \n",
+ " w1 0 ne { \n",
+ " newdict /DataSource ",
+ " pix x crpp mul w1 crpp mul getinterval put \n",
+ " newdict /Width w1 put \n",
+ " mat 4 x neg put \n",
+ " /x x w1 add def \n",
+ " newdict image \n",
+ " /tail tail w1 tail length w1 sub getinterval def \n",
+ " } if \n",
+ " done {exit} if \n",
+ " tail substrs { \n",
+ " anchorsearch {pop} if \n",
+ " } forall \n",
+ " /tail exch def \n",
+ " tail length 0 eq {exit} if \n",
+ " /x w tail length sub def \n",
+ " } loop \n",
+ " } for \n",
+ " end \n",
+ " grestore \n",
+ "} bind def \n\n\n", (char *) NULL);
+ } else if( !codeIncluded && (colorLevel == 0) ) {
+ /*
+ * Monochrome-only code
+ */
+
+ codeIncluded = !0;
+ Tcl_AppendResult( interp,
+ "/TkPhoto { \n",
+ " gsave \n",
+ " 32 dict begin \n",
+ " /dummyInteger exch def \n",
+ " /olddict exch def \n",
+ " olddict /DataSource get dup type /filetype ne { \n",
+ " olddict /DataSource 3 -1 roll \n",
+ " 0 () /SubFileDecode filter put \n",
+ " } { \n",
+ " pop \n",
+ " } ifelse \n",
+ " /newdict olddict maxlength dict def \n",
+ " olddict newdict copy pop \n",
+ " /w newdict /Width get def \n",
+ " /pix w 7 add 8 idiv string def \n",
+ " /h newdict /Height get def \n",
+ " 1 w div 1 h div matrix scale \n",
+ " olddict /ImageMatrix get exch matrix concatmatrix \n",
+ " matrix invertmatrix concat \n",
+ " newdict /Height 1 put \n",
+ " newdict /DataSource pix put \n",
+ " /mat [w 0 0 h 0 0] def \n",
+ " newdict /ImageMatrix mat put \n",
+ " 0 1 h 1 sub { \n",
+ " mat 5 3 -1 roll neg put \n",
+ " 0.000 0.000 0.000 setrgbcolor \n",
+ " olddict /DataSource get pix readstring pop pop \n",
+ " newdict /DataSource pix put \n",
+ " newdict imagemask \n",
+ " 1.000 1.000 1.000 setrgbcolor \n",
+ " olddict /DataSource get pix readstring pop pop \n",
+ " newdict /DataSource pix put \n",
+ " newdict imagemask \n",
+ " } for \n",
+ " end \n",
+ " grestore \n",
+ "} bind def \n\n\n", (char *) NULL);
+ }
+
+ /*
+ * Check that at least one row of the image can be represented
+ * with a string less than 64 KB long (this is a limit in the
+ * Postscript interpreter).
+ */
+
+ switch (colorLevel)
+ {
+ case 0: bytesPerLine = (width + 7) / 8; maxWidth = 240000; break;
+ case 1: bytesPerLine = width; maxWidth = 60000; break;
+ case 2: bytesPerLine = 3 * width; maxWidth = 20000; break;
+ }
+ if (bytesPerLine > 60000) {
+ Tcl_ResetResult(interp);
+ sprintf(buffer,
+ "Can't generate Postscript for images more than %d pixels wide",
+ maxWidth);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Set up the postscript code except for the image-data stream.
+ */
+
+ switch (colorLevel) {
+ case 0:
+ strcpy( cspace, "/DeviceGray");
+ strcpy( decode, "[1 0]");
+ bpc = 1;
+ break;
+ case 1:
+ strcpy( cspace, "/DeviceGray");
+ strcpy( decode, "[0 1]");
+ bpc = 8;
+ break;
+ default:
+ strcpy( cspace, "/DeviceRGB");
+ strcpy( decode, "[0 1 0 1 0 1]");
+ bpc = 8;
+ break;
+ }
+
+
+ Tcl_AppendResult(interp,
+ cspace, " setcolorspace\n\n", (char *) NULL);
+
+ sprintf(buffer,
+ " /Width %d\n /Height %d\n /BitsPerComponent %d\n",
+ width, height, bpc);
+ Tcl_AppendResult(interp,
+ "<<\n /ImageType 1\n", buffer,
+ " /DataSource currentfile",
+ " /ASCIIHexDecode filter\n", (char *) NULL);
+
+
+ sprintf(buffer,
+ " /ImageMatrix [1 0 0 -1 0 %d]\n", height);
+ Tcl_AppendResult(interp, buffer,
+ " /Decode ", decode, "\n>>\n1 TkPhoto\n", (char *) NULL);
+
+
+ /*
+ * Check the PhotoImageBlock information.
+ * We assume that:
+ * if pixelSize is 1,2 or 4, the image is R,G,B,A;
+ * if pixelSize is 3, the image is R,G,B and offset[3] is bogus.
+ */
+
+ if (blockPtr->pixelSize == 3) {
+ /*
+ * No alpha information: the whole image is opaque.
+ */
+
+ alphaPtr = &opaque;
+ alphaPitch = alphaIncr = alphaOffset = 0;
+ } else {
+ /*
+ * Set up alpha handling.
+ */
+
+ alphaPtr = blockPtr->pixelPtr;
+ alphaPitch = blockPtr->pitch;
+ alphaIncr = blockPtr->pixelSize;
+ alphaOffset = blockPtr->offset[3];
+ }
+
+
+ for (yy = 0, lineLen=0; yy < height; yy++) {
+ switch (colorLevel) {
+ case 0: {
+ /*
+ * Generate data for image in monochrome mode.
+ * No attempt at dithering is made--instead, just
+ * set a threshold.
+ * To handle transparecies we need to output two lines:
+ * one for the black pixels, one for the white ones.
+ */
+
+ unsigned char mask=0x80;
+ unsigned char data=0x00;
+ for (xx = 0; xx< width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr
+ + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+
+ /*
+ * If pixel is less than threshold, then it is black.
+ */
+
+ if ((alpha != 0) &&
+ ( 0.3086 * red
+ + 0.6094 * green
+ + 0.082 * blue < 128)) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ mask=0x80;
+ data=0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ mask=0x80;
+ data=0x00;
+ }
+
+ mask=0x80;
+ data=0x00;
+ for (xx = 0; xx< width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr
+ + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+
+ /*
+ * If pixel is greater than threshold, then it is white.
+ */
+
+ if ((alpha != 0) &&
+ ( 0.3086 * red
+ + 0.6094 * green
+ + 0.082 * blue >= 128)) {
+ data |= mask;
+ }
+ mask >>= 1;
+ if (mask == 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ mask=0x80;
+ data=0x00;
+ }
+ }
+ if ((width % 8) != 0) {
+ sprintf(buffer, "%02X", data);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ mask=0x80;
+ data=0x00;
+ }
+ break;
+ }
+ case 1: {
+ /*
+ * Generate transparency data.
+ * We must prevent a transparent value of 0
+ * because of a bug in some HP printers.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+ sprintf(buffer, "%02X", alpha | 0x01);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+
+
+ /*
+ * Generate data in gray mode--in this case, take a
+ * weighted sum of the red, green, and blue values.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr
+ + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ red = pixelPtr[blockPtr->offset[0]];
+ green = pixelPtr[blockPtr->offset[1]];
+ blue = pixelPtr[blockPtr->offset[2]];
+
+ sprintf(buffer, "%02X", (int) floor(0.5 +
+ ( 0.3086 * red + 0.6094 * green + 0.0820 * blue)));
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ default: {
+ /*
+ * Generate transparency data.
+ * We must prevent a transparent value of 0
+ * because of a bug in some HP printers.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ alpha = *(alphaPtr + (yy * alphaPitch)
+ + (xx * alphaIncr) + alphaOffset);
+ sprintf(buffer, "%02X", alpha | 0x01);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 2;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+
+
+ /*
+ * Finally, color mode. Here, just output the red, green,
+ * and blue values directly.
+ */
+
+ for (xx = 0; xx < width; xx ++) {
+ pixelPtr = blockPtr->pixelPtr
+ + (yy * blockPtr->pitch)
+ + (xx *blockPtr->pixelSize);
+
+ sprintf(buffer, "%02X%02X%02X",
+ pixelPtr[blockPtr->offset[0]],
+ pixelPtr[blockPtr->offset[1]],
+ pixelPtr[blockPtr->offset[2]]);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ lineLen += 6;
+ if (lineLen >= 60) {
+ lineLen = 0;
+ Tcl_AppendResult(interp, "\n", (char *) NULL);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ Tcl_AppendResult(interp, ">\n", (char *) NULL);
+ return TCL_OK;
+}
+
diff --git a/tk/generic/tkCanvText.c b/tk/generic/tkCanvText.c
index fc1dc4c0190..688d86b6b05 100644
--- a/tk/generic/tkCanvText.c
+++ b/tk/generic/tkCanvText.c
@@ -4,7 +4,7 @@
* 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.
@@ -36,18 +36,23 @@ 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; /* Character index of character just before
+ * which the insertion cursor is displayed. */
/*
* Configuration settings that are updated by Tk_ConfigureWidget.
*/
Tk_Anchor anchor; /* Where to anchor text relative to (x,y). */
+ Tk_TSOffset tsoffset;
XColor *color; /* Color for text. */
+ XColor *activeColor; /* Color for text. */
+ XColor *disabledColor; /* Color for text. */
Tk_Font tkfont; /* Font for drawing text. */
Tk_Justify justify; /* Justification mode for text. */
Pixmap stipple; /* Stipple bitmap for text, or None. */
+ Pixmap activeStipple; /* Stipple bitmap for text, or None. */
+ Pixmap disabledStipple; /* Stipple bitmap for text, or None. */
char *text; /* Text for item (malloc-ed). */
int width; /* Width of lines for word-wrap, pixels.
* Zero means no word-wrap. */
@@ -57,7 +62,8 @@ typedef struct TextItem {
* configuration settings above.
*/
- int numChars; /* Number of non-NULL characters in text. */
+ int numChars; /* Length of text in characters. */
+ int numBytes; /* Length of text in bytes. */
Tk_TextLayout textLayout; /* Cached text layout information. */
int leftEdge; /* Pixel location of the left edge of the
* text item; where the left border of the
@@ -77,14 +83,31 @@ typedef struct TextItem {
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc, (ClientData) (TK_OFFSET_RELATIVE)
+};
static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(TextItem, activeColor), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(TextItem, activeStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
"center", Tk_Offset(TextItem, anchor),
TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(TextItem, disabledColor), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(TextItem, disabledStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
"black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK},
{TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
@@ -92,6 +115,12 @@ static Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_JUSTIFY, "-justify", (char *) NULL, (char *) NULL,
"left", Tk_Offset(TextItem, justify),
TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(TextItem, tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
@@ -112,10 +141,10 @@ static void ComputeTextBbox _ANSI_ARGS_((Tk_Canvas canvas,
TextItem *textPtr));
static int ConfigureText _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int CreateText _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteText _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayCanvText _ANSI_ARGS_((Tk_Canvas canvas,
@@ -126,7 +155,7 @@ static int GetSelText _ANSI_ARGS_((Tk_Canvas canvas,
int maxBytes));
static int GetTextIndex _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
- char *indexString, int *indexPtr));
+ Tcl_Obj *obj, int *indexPtr));
static void ScaleText _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double originX, double originY,
double scaleX, double scaleY));
@@ -134,7 +163,7 @@ static void SetTextCursor _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, int index));
static int TextCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void TextDeleteChars _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, int first, int last));
static void TextInsert _ANSI_ARGS_((Tk_Canvas canvas,
@@ -154,26 +183,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 */
+ TK_CONFIG_OBJS, /* flags */
+ TextToPoint, /* pointProc */
+ TextToArea, /* areaProc */
+ TextToPostscript, /* postscriptProc */
+ ScaleText, /* scaleProc */
+ TranslateText, /* translateProc */
+ (Tk_ItemIndexProc *) GetTextIndex,/* indexProc */
+ SetTextCursor, /* icursorProc */
+ GetSelText, /* selectionProc */
+ TextInsert, /* insertProc */
+ TextDeleteChars, /* dTextProc */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -187,7 +216,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,16 +227,29 @@ 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. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing rectangle. */
{
TextItem *textPtr = (TextItem *) itemPtr;
+ int i;
+
+ if (argc==1) {
+ i = 1;
+ } else {
+ char *arg = Tcl_GetStringFromObj(argv[1], NULL);
+ if ((argc>1) && (arg[0] == '-')
+ && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ } else {
+ i = 2;
+ }
+ }
- if (argc < 2) {
+ if (argc < i) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
itemPtr->typePtr->name, " x y ?options?\"", (char *) NULL);
@@ -215,8 +257,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);
@@ -224,14 +266,22 @@ CreateText(interp, canvas, itemPtr, argc, argv)
textPtr->insertPos = 0;
textPtr->anchor = TK_ANCHOR_CENTER;
+ textPtr->tsoffset.flags = 0;
+ textPtr->tsoffset.xoffset = 0;
+ textPtr->tsoffset.yoffset = 0;
textPtr->color = NULL;
+ textPtr->activeColor = NULL;
+ textPtr->disabledColor = NULL;
textPtr->tkfont = NULL;
textPtr->justify = TK_JUSTIFY_LEFT;
textPtr->stipple = None;
+ textPtr->activeStipple = None;
+ textPtr->disabledStipple = None;
textPtr->text = NULL;
textPtr->width = 0;
textPtr->numChars = 0;
+ textPtr->numBytes = 0;
textPtr->textLayout = NULL;
textPtr->leftEdge = 0;
textPtr->rightEdge = 0;
@@ -243,17 +293,16 @@ CreateText(interp, canvas, itemPtr, argc, argv)
* Process the arguments to fill in the item record.
*/
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &textPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1], &textPtr->y)
- != TCL_OK)) {
- return TCL_ERROR;
+ if ((TextCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
+ goto error;
}
-
- if (ConfigureText(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
- DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
- return TCL_ERROR;
+ if (ConfigureText(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
+
+ error:
+ DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
}
/*
@@ -266,7 +315,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,32 +325,46 @@ 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. */
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1, x2, y2, ... */
{
TextItem *textPtr = (TextItem *) itemPtr;
- char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
if (argc == 0) {
- Tcl_PrintDouble(interp, textPtr->x, x);
- Tcl_PrintDouble(interp, textPtr->y, y);
- Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
- } else if (argc == 2) {
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &textPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
- &textPtr->y) != TCL_OK)) {
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(textPtr->x);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(textPtr->y);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ } else if (argc < 3) {
+ if (argc==1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (argc != 2) {
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &textPtr->x) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
+ &textPtr->y) != TCL_OK)) {
return TCL_ERROR;
}
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 +380,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
@@ -332,7 +395,7 @@ ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Rectangle item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
TextItem *textPtr = (TextItem *) itemPtr;
@@ -342,10 +405,13 @@ ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
Tk_Window tkwin;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
XColor *selBgColorPtr;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) textPtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) textPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -354,20 +420,59 @@ ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
* graphics contexts.
*/
+ state = itemPtr->state;
+
+ if (textPtr->activeColor != NULL ||
+ textPtr->activeStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
+ } else {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ color = textPtr->color;
+ stipple = textPtr->stipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (textPtr->activeColor!=NULL) {
+ color = textPtr->activeColor;
+ }
+ if (textPtr->activeStipple!=None) {
+ stipple = textPtr->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (textPtr->disabledColor!=NULL) {
+ color = textPtr->disabledColor;
+ }
+ if (textPtr->disabledStipple!=None) {
+ stipple = textPtr->disabledStipple;
+ }
+ }
+
newGC = newSelGC = None;
- if ((textPtr->color != NULL) && (textPtr->tkfont != NULL)) {
- gcValues.foreground = textPtr->color->pixel;
+ if (textPtr->tkfont != NULL) {
gcValues.font = Tk_FontId(textPtr->tkfont);
- mask = GCForeground|GCFont;
- if (textPtr->stipple != None) {
- gcValues.stipple = textPtr->stipple;
+ mask = GCFont;
+ if (color != NULL) {
+ gcValues.foreground = color->pixel;
+ mask |= GCForeground;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
+ gcValues.fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
+ mask &= ~(GCTile|GCFillStyle|GCStipple);
+ if (stipple != None) {
+ gcValues.stipple = stipple;
gcValues.fill_style = FillStippled;
- mask |= GCForeground|GCStipple|GCFillStyle;
+ mask |= GCStipple|GCFillStyle;
}
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, textPtr->color, NULL);
gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;
- newSelGC = Tk_GetGCColor(tkwin, mask, &gcValues,
- textInfoPtr->selFgColorPtr, NULL);
+ newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);
}
if (textPtr->gc != None) {
Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);
@@ -401,17 +506,19 @@ ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
* to keep them inside the item.
*/
- textPtr->numChars = strlen(textPtr->text);
+ textPtr->numBytes = strlen(textPtr->text);
+ textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes);
if (textInfoPtr->selItemPtr == itemPtr) {
+
if (textInfoPtr->selectFirst >= textPtr->numChars) {
textInfoPtr->selItemPtr = NULL;
} else {
if (textInfoPtr->selectLast >= textPtr->numChars) {
- textInfoPtr->selectLast = textPtr->numChars-1;
+ textInfoPtr->selectLast = textPtr->numChars - 1;
}
if ((textInfoPtr->anchorItemPtr == itemPtr)
&& (textInfoPtr->selectAnchor >= textPtr->numChars)) {
- textInfoPtr->selectAnchor = textPtr->numChars-1;
+ textInfoPtr->selectAnchor = textPtr->numChars - 1;
}
}
}
@@ -442,20 +549,31 @@ 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;
if (textPtr->color != NULL) {
Tk_FreeColor(textPtr->color);
}
+ if (textPtr->activeColor != NULL) {
+ Tk_FreeColor(textPtr->activeColor);
+ }
+ if (textPtr->disabledColor != NULL) {
+ Tk_FreeColor(textPtr->disabledColor);
+ }
Tk_FreeFont(textPtr->tkfont);
if (textPtr->stipple != None) {
Tk_FreeBitmap(display, textPtr->stipple);
}
+ if (textPtr->activeStipple != None) {
+ Tk_FreeBitmap(display, textPtr->activeStipple);
+ }
+ if (textPtr->disabledStipple != None) {
+ Tk_FreeBitmap(display, textPtr->disabledStipple);
+ }
if (textPtr->text != NULL) {
ckfree(textPtr->text);
}
@@ -495,18 +613,26 @@ 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_State state = textPtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
Tk_FreeTextLayout(textPtr->textLayout);
textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,
textPtr->text, textPtr->numChars, textPtr->width,
textPtr->justify, 0, &width, &height);
+ if (state == TK_STATE_HIDDEN || textPtr->color == NULL) {
+ width = height = 0;
+ }
+
/*
* Use overall geometry information to compute the top-left corner
* of the bounding box for the text item.
@@ -592,22 +718,37 @@ 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;
- int selFirst, selLast;
+ int selFirstChar, selLastChar;
short drawableX, drawableY;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
textPtr = (TextItem *) itemPtr;
textInfoPtr = textPtr->textInfoPtr;
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ stipple = textPtr->stipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (textPtr->activeStipple!=None) {
+ stipple = textPtr->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (textPtr->disabledStipple!=None) {
+ stipple = textPtr->disabledStipple;
+ }
+ }
+
if (textPtr->gc == None) {
return;
}
@@ -618,30 +759,31 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
* read-only.
*/
- if (textPtr->stipple != None) {
- Tk_CanvasSetStippleOrigin(canvas, textPtr->gc);
+ if (stipple != None) {
+ Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);
}
- selFirst = -1;
- selLast = 0; /* lint. */
+ selFirstChar = -1;
+ selLastChar = 0; /* lint. */
+
if (textInfoPtr->selItemPtr == itemPtr) {
- selFirst = textInfoPtr->selectFirst;
- selLast = textInfoPtr->selectLast;
- if (selLast >= textPtr->numChars) {
- selLast = textPtr->numChars - 1;
+ selFirstChar = textInfoPtr->selectFirst;
+ selLastChar = textInfoPtr->selectLast;
+ if (selLastChar > textPtr->numChars) {
+ selLastChar = textPtr->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;
-
- Tk_CharBbox(textPtr->textLayout, selFirst,
- &xFirst, &yFirst, NULL, &hFirst);
- Tk_CharBbox(textPtr->textLayout, selLast,
- &xLast, &yLast, &wLast, NULL);
+ Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst,
+ NULL, &hFirst);
+ Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast,
+ NULL, NULL);
/*
* If the selection spans the end of this line, then display
@@ -654,7 +796,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;
}
@@ -725,13 +867,13 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
drawableX, drawableY, 0, -1);
- if ((selFirst >= 0) && (textPtr->selTextGC != textPtr->gc)) {
+ if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {
Tk_DrawTextLayout(display, drawable, textPtr->selTextGC,
- textPtr->textLayout, drawableX, drawableY, selFirst,
- selLast + 1);
+ textPtr->textLayout, drawableX, drawableY, selFirstChar,
+ selLastChar + 1);
}
- if (textPtr->stipple != None) {
+ if (stipple != None) {
XSetTSOrigin(display, textPtr->gc, 0, 0);
}
}
@@ -755,36 +897,44 @@ 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 byteIndex, byteCount, charsAdded;
+ char *new, *text;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
- length = strlen(string);
- if (length == 0) {
- return;
+ string = Tcl_GetStringFromObj((Tcl_Obj *) string, &byteCount);
+
+ text = textPtr->text;
+
+ if (index < 0) {
+ index = 0;
}
- if (beforeThis < 0) {
- beforeThis = 0;
+ if (index > textPtr->numChars) {
+ index = textPtr->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;
+ charsAdded = Tcl_NumUtfChars(string, byteCount);
+ textPtr->numChars += charsAdded;
+ textPtr->numBytes += byteCount;
/*
* Inserting characters invalidates indices such as those for the
@@ -792,19 +942,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 >= index) {
+ textPtr->insertPos += charsAdded;
}
ComputeTextBbox(canvas, textPtr);
}
@@ -831,31 +981,40 @@ 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 byteIndex, byteCount, charsRemoved;
+ char *new, *text;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ text = textPtr->text;
if (first < 0) {
first = 0;
}
if (last >= textPtr->numChars) {
- last = textPtr->numChars-1;
+ last = textPtr->numChars - 1;
}
if (first > last) {
return;
}
- count = last + 1 - first;
+ charsRemoved = 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, charsRemoved)
+ - (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->numChars -= charsRemoved;
+ textPtr->numBytes -= byteCount;
/*
* Update indexes for the selection and cursor to reflect the
@@ -864,15 +1023,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) {
@@ -880,14 +1039,14 @@ 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;
+ textPtr->insertPos -= charsRemoved;
if (textPtr->insertPos < first) {
textPtr->insertPos = first;
}
@@ -923,11 +1082,22 @@ TextToPoint(canvas, itemPtr, pointPtr)
double *pointPtr; /* Pointer to x and y coordinates. */
{
TextItem *textPtr;
+ Tk_State state = itemPtr->state;
+ double value;
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
textPtr = (TextItem *) itemPtr;
- return (double) Tk_DistanceToTextLayout(textPtr->textLayout,
+ value = (double) Tk_DistanceToTextLayout(textPtr->textLayout,
(int) pointPtr[0] - textPtr->leftEdge,
(int) pointPtr[1] - textPtr->header.y1);
+
+ if ((state == TK_STATE_HIDDEN) || (textPtr->color == NULL) ||
+ (textPtr->text == NULL) || (*textPtr->text == 0)) {
+ value = 1.0e36;
+ }
+ return value;
}
/*
@@ -959,6 +1129,11 @@ TextToArea(canvas, itemPtr, rectPtr)
* area. */
{
TextItem *textPtr;
+ Tk_State state = itemPtr->state;
+
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
textPtr = (TextItem *) itemPtr;
return Tk_IntersectTextLayout(textPtr->textLayout,
@@ -988,11 +1163,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;
@@ -1023,10 +1198,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;
@@ -1047,7 +1221,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.
@@ -1056,20 +1230,22 @@ TranslateText(canvas, itemPtr, deltaX, deltaY)
*/
static int
-GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
+GetTextIndex(interp, canvas, itemPtr, obj, indexPtr)
Tcl_Interp *interp; /* Used for error reporting. */
Tk_Canvas canvas; /* Canvas containing item. */
Tk_Item *itemPtr; /* Item for which the index is being
* specified. */
- char *string; /* Specification of a particular character
+ Tcl_Obj *obj; /* 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;
int c;
TkCanvas *canvasPtr = (TkCanvas *) canvas;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ char *string = Tcl_GetStringFromObj(obj, (int *) &length);
c = string[0];
length = strlen(string);
@@ -1081,14 +1257,14 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
} 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;
@@ -1112,7 +1288,7 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
*indexPtr = Tk_PointToChar(textPtr->textLayout,
x + canvasPtr->scrollX1 - textPtr->leftEdge,
y + canvasPtr->scrollY1 - textPtr->header.y1);
- } else if (Tcl_GetInt(interp, string, indexPtr) == TCL_OK) {
+ } else if (Tcl_GetIntFromObj((Tcl_Interp *)NULL, obj, indexPtr) == TCL_OK) {
if (*indexPtr < 0){
*indexPtr = 0;
} else if (*indexPtr > textPtr->numChars) {
@@ -1120,7 +1296,7 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
}
} 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.
*/
@@ -1152,11 +1328,11 @@ 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; /* Character index of character just before
+ * which cursor is to be positioned. */
{
TextItem *textPtr = (TextItem *) itemPtr;
@@ -1192,34 +1368,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;
}
/*
@@ -1233,7 +1413,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.
*
@@ -1245,23 +1425,44 @@ 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;
Tk_FontMetrics fm;
char *justify;
char buffer[500];
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
- if (textPtr->color == NULL) {
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ color = textPtr->color;
+ stipple = textPtr->stipple;
+ if (state == TK_STATE_HIDDEN || textPtr->color == NULL ||
+ textPtr->text == NULL || *textPtr->text == 0) {
return TCL_OK;
+ } else if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (textPtr->activeColor!=NULL) {
+ color = textPtr->activeColor;
+ }
+ if (textPtr->activeStipple!=None) {
+ stipple = textPtr->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (textPtr->disabledColor!=NULL) {
+ color = textPtr->disabledColor;
+ }
+ if (textPtr->disabledStipple!=None) {
+ stipple = textPtr->disabledStipple;
+ }
}
if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) {
@@ -1270,13 +1471,13 @@ TextToPostscript(interp, canvas, itemPtr, prepass)
if (prepass != 0) {
return TCL_OK;
}
- if (Tk_CanvasPsColor(interp, canvas, textPtr->color) != TCL_OK) {
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
return TCL_ERROR;
}
- if (textPtr->stipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "/StippleText {\n ",
(char *) NULL);
- Tk_CanvasPsStipple(interp, canvas, textPtr->stipple);
+ Tk_CanvasPsStipple(interp, canvas, stipple);
Tcl_AppendResult(interp, "} bind def\n", (char *) NULL);
}
@@ -1307,8 +1508,9 @@ TextToPostscript(interp, canvas, itemPtr, prepass)
Tk_GetFontMetrics(textPtr->tkfont, &fm);
sprintf(buffer, "] %d %g %g %s %s DrawText\n",
fm.linespace, x / -2.0, y / 2.0, justify,
- ((textPtr->stipple == None) ? "false" : "true"));
+ ((stipple == None) ? "false" : "true"));
Tcl_AppendResult(interp, buffer, (char *) NULL);
return TCL_OK;
}
+
diff --git a/tk/generic/tkCanvUtil.c b/tk/generic/tkCanvUtil.c
index a78ae194ec0..0abf9665574 100644
--- a/tk/generic/tkCanvUtil.c
+++ b/tk/generic/tkCanvUtil.c
@@ -13,7 +13,7 @@
* RCS: @(#) $Id$
*/
-#include "tk.h"
+#include "tkInt.h"
#include "tkCanvas.h"
#include "tkPort.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.
@@ -201,6 +201,44 @@ Tk_CanvasGetCoord(interp, canvas, string, doublePtr)
*doublePtr *= canvasPtr->pixelsPerMM;
return TCL_OK;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasGetCoordFromObj --
+ *
+ * Given a string, returns a floating-point canvas coordinate
+ * corresponding to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If
+ * TCL_OK is returned, then everything went well and the
+ * canvas coordinate is stored at *doublePtr; otherwise
+ * TCL_ERROR is returned and an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr)
+ Tcl_Interp *interp; /* Interpreter for error reporting. */
+ Tk_Canvas canvas; /* Canvas to which coordinate applies. */
+ Tcl_Obj *obj; /* Describes coordinate (any screen
+ * coordinate form may be used here). */
+ double *doublePtr; /* Place to store converted coordinate. */
+{
+ TkCanvas *canvasPtr = (TkCanvas *) canvas;
+ if (Tk_GetMMFromObj(canvasPtr->interp, canvasPtr->tkwin, obj,
+ doublePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *doublePtr *= canvasPtr->pixelsPerMM;
+ return TCL_OK;
+}
/*
*----------------------------------------------------------------------
@@ -237,6 +275,50 @@ Tk_CanvasSetStippleOrigin(canvas, gc)
/*
*----------------------------------------------------------------------
*
+ * Tk_CanvasSetOffset--
+ *
+ * This procedure sets the stipple offset in a graphics
+ * context so that stipples drawn with the GC will
+ * line up with other stipples with the same offset.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The graphics context is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasSetOffset(canvas, gc, offset)
+ Tk_Canvas canvas; /* Token for a canvas. */
+ GC gc; /* Graphics context that is about to be
+ * used to draw a stippled pattern as
+ * part of redisplaying the canvas. */
+ Tk_TSOffset *offset; /* offset (may be NULL pointer)*/
+{
+ TkCanvas *canvasPtr = (TkCanvas *) canvas;
+ int flags = 0;
+ int x = - canvasPtr->drawableXOrigin;
+ int y = - canvasPtr->drawableYOrigin;
+
+ if (offset != NULL) {
+ flags = offset->flags;
+ x += offset->xoffset;
+ y += offset->yoffset;
+ }
+ if ((flags & TK_OFFSET_RELATIVE) && !(flags & TK_OFFSET_INDEX)) {
+ Tk_SetTSOrigin(canvasPtr->tkwin, gc, x - canvasPtr->xOrigin,
+ y - canvasPtr->yOrigin);
+ } else {
+ XSetTSOrigin(canvasPtr->display, gc, x, y);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_CanvasGetTextInfo --
*
* This procedure returns a pointer to a structure containing
@@ -374,3 +456,1020 @@ Tk_CanvasTagsPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
*freeProcPtr = TCL_DYNAMIC;
return Tcl_Merge(itemPtr->numTags, (char **) itemPtr->tagPtr);
}
+
+
+static int DashConvert _ANSI_ARGS_((char *l, CONST char *p,
+ int n, double width));
+#define ABS(a) ((a>=0)?(a):(-(a)))
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvasDashParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * "-dash", "-activedash" and "-disableddash" options for canvas
+ * objects.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The dash list for a given canvas object gets replaced by
+ * those indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* Not used.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ return Tk_GetDash(interp, value, (Tk_Dash *)(widgRec+offset));
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvasDashPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-dash", "-activedash"
+ * and "-disableddash" configuration options for canvas items.
+ *
+ * Results:
+ * The return value is a string describing all the dash list for
+ * the item referred to by "widgRec"and "offset". In addition,
+ * *freeProcPtr is filled in with the address of a procedure to
+ * call to free the result string when it's no longer needed (or
+ * NULL to indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset in record for item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);
+ char *buffer;
+ char *p;
+ int i = dash->number;
+
+ if (i < 0) {
+ i = -i;
+ *freeProcPtr = TCL_DYNAMIC;
+ buffer = (char *) ckalloc((unsigned int) (i+1));
+ p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ memcpy(buffer, p, (unsigned int) i);
+ buffer[i] = 0;
+ return buffer;
+ } else if (!i) {
+ *freeProcPtr = (Tcl_FreeProc *) NULL;
+ return "";
+ }
+ buffer = (char *)ckalloc((unsigned int) (4*i));
+ *freeProcPtr = TCL_DYNAMIC;
+
+ p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ sprintf(buffer, "%d", *p++ & 0xff);
+ while(--i) {
+ sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff);
+ }
+ return buffer;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateSmoothMethod --
+ *
+ * This procedure is invoked to add additional values
+ * for the "-smooth" option to the list.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * In the future "-smooth <name>" will be accepted as
+ * smooth method for the line and polygon.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_SmoothMethod tkBezierSmoothMethod = {
+ "bezier",
+ TkMakeBezierCurve,
+ (void (*) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas,
+ double *coordPtr, int numPoints, int numSteps)))
+ TkMakeBezierPostscript,
+};
+
+static void SmoothMethodCleanupProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp));
+
+typedef struct SmoothAssocData {
+ struct SmoothAssocData *nextPtr; /* pointer to next SmoothAssocData */
+ Tk_SmoothMethod smooth; /* name and functions associated with this
+ * option */
+} SmoothAssocData;
+
+void
+Tk_CreateSmoothMethod(interp, smooth)
+ Tcl_Interp *interp;
+ Tk_SmoothMethod *smooth;
+{
+ SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;
+ methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
+ (Tcl_InterpDeleteProc **) NULL);
+
+ /*
+ * If there's already a smooth method with the given name, remove it.
+ */
+
+ for (typePtr2 = methods, prevPtr = NULL; typePtr2 != NULL;
+ prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
+ if (!strcmp(typePtr2->smooth.name, smooth->name)) {
+ if (prevPtr == NULL) {
+ methods = typePtr2->nextPtr;
+ } else {
+ prevPtr->nextPtr = typePtr2->nextPtr;
+ }
+ ckfree((char *) typePtr2);
+ break;
+ }
+ }
+ ptr = (SmoothAssocData *) ckalloc(sizeof(SmoothAssocData));
+ ptr->smooth.name = smooth->name;
+ ptr->smooth.coordProc = smooth->coordProc;
+ ptr->smooth.postscriptProc = smooth->postscriptProc;
+ ptr->nextPtr = methods;
+ Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc,
+ (ClientData) ptr);
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * SmoothMethodCleanupProc --
+ *
+ * This procedure is invoked whenever an interpreter is deleted
+ * to cleanup the smooth methods.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Smooth methods are removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SmoothMethodCleanupProc(clientData, interp)
+ ClientData clientData; /* Points to "smoothMethod" AssocData
+ * for the interpreter. */
+ Tcl_Interp *interp; /* Interpreter that is being deleted. */
+{
+ SmoothAssocData *ptr, *methods = (SmoothAssocData *) clientData;
+
+ while (methods != NULL) {
+ methods = (ptr = methods)->nextPtr;
+ ckfree((char *) ptr);
+ }
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSmoothParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-smooth" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The smooth option for a given item gets replaced by the value
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ register Tk_SmoothMethod **smoothPtr =
+ (Tk_SmoothMethod **) (widgRec + offset);
+ Tk_SmoothMethod *smooth = NULL;
+ int b;
+ size_t length;
+ SmoothAssocData *methods;
+
+ if (value == NULL || *value == 0) {
+ *smoothPtr = (Tk_SmoothMethod *) NULL;
+ return TCL_OK;
+ }
+ length = strlen(value);
+ methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
+ (Tcl_InterpDeleteProc **) NULL);
+ while (methods != (SmoothAssocData *) NULL) {
+ if (strncmp(value, methods->smooth.name, length) == 0) {
+ if (smooth != (Tk_SmoothMethod *) NULL) {
+ Tcl_AppendResult(interp, "ambigeous smooth method \"", value,
+ "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ smooth = &methods->smooth;
+ }
+ methods = methods->nextPtr;
+ }
+ if (smooth) {
+ *smoothPtr = smooth;
+ return TCL_OK;
+ }
+
+ if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *smoothPtr = b ? &tkBezierSmoothMethod : (Tk_SmoothMethod*) NULL;
+ return TCL_OK;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSmoothPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-smooth"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the smooth option for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register Tk_SmoothMethod **smoothPtr = (Tk_SmoothMethod **) (widgRec + offset);
+
+ return (*smoothPtr) ? (*smoothPtr)->name : "0";
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetDash
+ *
+ * This procedure is used to parse a string, assuming
+ * it is dash information.
+ *
+ * Results:
+ * The return value is a standard Tcl result: TCL_OK means
+ * that the dash information was parsed ok, and
+ * TCL_ERROR means it couldn't be parsed.
+ *
+ * Side effects:
+ * Dash information in the dash structure is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetDash(interp, value, dash)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ CONST char *value; /* Textual specification of dash list. */
+ Tk_Dash *dash; /* Pointer to record in which to
+ * store dash information. */
+{
+ int argc, i;
+ char **largv, **argv = NULL;
+ char *pt;
+
+ if ((value==(char *) NULL) || (*value==0) ) {
+ dash->number = 0;
+ return TCL_OK;
+ }
+ if ((*value == '.') || (*value == ',') ||
+ (*value == '-') || (*value == '_')) {
+ i = DashConvert((char *) NULL, value, -1, 0.0);
+ if (i>0) {
+ i = strlen(value);
+ } else {
+ goto badDashList;
+ }
+ if (i > sizeof(char *)) {
+ dash->pattern.pt = pt = (char *) ckalloc(strlen(value));
+ } else {
+ pt = dash->pattern.array;
+ }
+ memcpy(pt,value, (unsigned int) i);
+ dash->number = -i;
+ return TCL_OK;
+ }
+ if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ badDashList:
+ Tcl_AppendResult(interp, "bad dash list \"", value,
+ "\": must be a list of integers or a format like \"-..\"",
+ (char *) NULL);
+ syntaxError:
+ if (argv != NULL) {
+ ckfree((char *) argv);
+ }
+ if (ABS(dash->number) > sizeof(char *))
+ ckfree((char *) dash->pattern.pt);
+ dash->number = 0;
+ return TCL_ERROR;
+ }
+
+ if (ABS(dash->number) > sizeof(char *)) {
+ ckfree((char *) dash->pattern.pt);
+ }
+ if (argc > sizeof(char *)) {
+ dash->pattern.pt = pt = (char *) ckalloc((unsigned int) argc);
+ } else {
+ pt = dash->pattern.array;
+ }
+ dash->number = argc;
+
+ largv = argv;
+ while(argc>0) {
+ if (Tcl_GetInt(interp, *largv, &i) != TCL_OK ||
+ i < 1 || i>255) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "expected integer in the range 1..255 but got \"",
+ *largv, "\"", (char *) NULL);
+ goto syntaxError;
+ }
+ *pt++ = i;
+ argc--; largv++;
+ }
+
+ if (argv != NULL) {
+ ckfree((char *) argv);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateOutline
+ *
+ * This procedure initializes the Tk_Outline structure
+ * with default values.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void Tk_CreateOutline(outline)
+ Tk_Outline *outline;
+{
+ outline->gc = None;
+ outline->width = 1.0;
+ outline->activeWidth = 0.0;
+ outline->disabledWidth = 0.0;
+ outline->offset = 0;
+ outline->dash.number = 0;
+ outline->activeDash.number = 0;
+ outline->disabledDash.number = 0;
+ outline->tsoffset.flags = 0;
+ outline->tsoffset.xoffset = 0;
+ outline->tsoffset.yoffset = 0;
+ outline->color = NULL;
+ outline->activeColor = NULL;
+ outline->disabledColor = NULL;
+ outline->stipple = None;
+ outline->activeStipple = None;
+ outline->disabledStipple = None;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteOutline
+ *
+ * This procedure frees all memory that might be
+ * allocated and referenced in the Tk_Outline structure.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void Tk_DeleteOutline(display, outline)
+ Display *display; /* Display containing window */
+ Tk_Outline *outline;
+{
+ if (outline->gc != None) {
+ Tk_FreeGC(display, outline->gc);
+ }
+ if (ABS(outline->dash.number) > sizeof(char *)) {
+ ckfree((char *) outline->dash.pattern.pt);
+ }
+ if (ABS(outline->activeDash.number) > sizeof(char *)) {
+ ckfree((char *) outline->activeDash.pattern.pt);
+ }
+ if (ABS(outline->disabledDash.number) > sizeof(char *)) {
+ ckfree((char *) outline->disabledDash.pattern.pt);
+ }
+ if (outline->color != NULL) {
+ Tk_FreeColor(outline->color);
+ }
+ if (outline->activeColor != NULL) {
+ Tk_FreeColor(outline->activeColor);
+ }
+ if (outline->disabledColor != NULL) {
+ Tk_FreeColor(outline->disabledColor);
+ }
+ if (outline->stipple != None) {
+ Tk_FreeBitmap(display, outline->stipple);
+ }
+ if (outline->activeStipple != None) {
+ Tk_FreeBitmap(display, outline->activeStipple);
+ }
+ if (outline->disabledStipple != None) {
+ Tk_FreeBitmap(display, outline->disabledStipple);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigOutlineGC
+ *
+ * This procedure should be called in the canvas object
+ * during the configure command. The graphics context
+ * description in gcValues is updated according to the
+ * information in the dash structure, as far as possible.
+ *
+ * Results:
+ * The return-value is a mask, indicating which
+ * elements of gcValues have been updated.
+ * 0 means there is no outline.
+ *
+ * Side effects:
+ * GC information in gcValues is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int Tk_ConfigOutlineGC(gcValues, canvas, item, outline)
+ XGCValues *gcValues;
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ int mask = 0;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ if (outline->width < 0.0) {
+ outline->width = 0.0;
+ }
+ if (outline->activeWidth < 0.0) {
+ outline->activeWidth = 0.0;
+ }
+ if (outline->disabledWidth < 0) {
+ outline->disabledWidth = 0.0;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ return 0;
+ }
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (outline->disabledWidth>0) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+
+ if (color==NULL) {
+ return 0;
+ }
+
+ gcValues->line_width = (int) (width + 0.5);
+ if (color != NULL) {
+ gcValues->foreground = color->pixel;
+ mask = GCForeground|GCLineWidth;
+ if (stipple != None) {
+ gcValues->stipple = stipple;
+ gcValues->fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ }
+ if (mask && (dash->number != 0)) {
+ gcValues->line_style = LineOnOffDash;
+ gcValues->dash_offset = outline->offset;
+ if (dash->number >= 2) {
+ gcValues->dashes = 4;
+ } else if (dash->number > 0) {
+ gcValues->dashes = dash->pattern.array[0];
+ } else {
+ gcValues->dashes = (char) (4 * width);
+ }
+ mask |= GCLineStyle|GCDashList|GCDashOffset;
+ }
+ return mask;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ChangeOutlineGC
+ *
+ * Updates the GC to represent the full information of
+ * the dash structure. Partly this is already done in
+ * Tk_ConfigOutlineGC().
+ * This function should be called just before drawing
+ * the dashed item.
+ *
+ * Results:
+ * 1 if there is a stipple pattern.
+ * 0 otherwise.
+ *
+ * Side effects:
+ * GC is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ChangeOutlineGC(canvas, item, outline)
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ CONST char *p;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth > width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor != NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple != None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (outline->disabledWidth > width) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor != NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple != None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ if (color==NULL) {
+ return 0;
+ }
+
+ if ((dash->number<-1) || ((dash->number == -1) && (dash->pattern.array[1]!=','))) {
+ char *q;
+ int i = -dash->number;
+
+ p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ q = (char *) ckalloc(2*(unsigned int)i);
+ i = DashConvert(q, p, i, width);
+ XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, q, i);
+ ckfree(q);
+ } else if ( dash->number>2 || (dash->number==2 &&
+ (dash->pattern.array[0]!=dash->pattern.array[1]))) {
+ p = (char *) (dash->number > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, p, dash->number);
+ }
+ if (stipple!=None) {
+ int w=0; int h=0;
+ Tk_TSOffset *tsoffset = &outline->tsoffset;
+ int flags = tsoffset->flags;
+ if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
+ Tk_SizeOfBitmap(((TkCanvas *)canvas)->display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, outline->gc, tsoffset);
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ResetOutlineGC
+ *
+ * Restores the GC to the situation before
+ * Tk_ChangeDashGC() was called.
+ * This function should be called just after the dashed
+ * item is drawn, because the GC is supposed to be
+ * read-only.
+ *
+ * Results:
+ * 1 if there is a stipple pattern.
+ * 0 otherwise.
+ *
+ * Side effects:
+ * GC is updated.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Tk_ResetOutlineGC(canvas, item, outline)
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ char dashList;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (outline->disabledWidth>width) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ if (color==NULL) {
+ return 0;
+ }
+
+ if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 &&
+ (dash->pattern.array[0] != dash->pattern.array[1])) ||
+ ((dash->number == -1) && (dash->pattern.array[1] != ','))) {
+ if (dash->number < 0) {
+ dashList = (int) (4 * width + 0.5);
+ } else if (dash->number<3) {
+ dashList = dash->pattern.array[0];
+ } else {
+ dashList = 4;
+ }
+ XSetDashes(((TkCanvas *)canvas)->display, outline->gc,
+ outline->offset, &dashList , 1);
+ }
+ if (stipple != None) {
+ XSetTSOrigin(((TkCanvas *)canvas)->display, outline->gc, 0, 0);
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsOutline
+ *
+ * Creates the postscript command for the correct
+ * Outline-information (width, dash, color and stipple).
+ *
+ * Results:
+ * TCL_OK if succeeded, otherwise TCL_ERROR.
+ *
+ * Side effects:
+ * canvas->interp->result contains the postscript string,
+ * or an error message if the result was TCL_ERROR.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Tk_CanvasPsOutline(canvas, item, outline)
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ char string[41];
+ char pattern[11];
+ int i;
+ char *ptr;
+ char *str = string;
+ char *lptr = pattern;
+ Tcl_Interp *interp = ((TkCanvas *)canvas)->interp;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth > width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number > 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor != NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple != None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state == TK_STATE_DISABLED) {
+ if (outline->disabledWidth > 0) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number > 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor != NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple != None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ sprintf(string, "%.15g setlinewidth\n", width);
+ Tcl_AppendResult(interp, string, (char *) NULL);
+
+ if (dash->number > 10) {
+ str = (char *)ckalloc((unsigned int) (1 + 4*dash->number));
+ } else if (dash->number < -5) {
+ str = (char *)ckalloc((unsigned int) (1 - 8*dash->number));
+ lptr = (char *)ckalloc((unsigned int) (1 - 2*dash->number));
+ }
+ ptr = (char *) ((ABS(dash->number) > sizeof(char *)) ) ?
+ dash->pattern.pt : dash->pattern.array;
+ if (dash->number > 0) {
+ char *ptr0 = ptr;
+ sprintf(str, "[%d", *ptr++ & 0xff);
+ i = dash->number-1;
+ while (i--) {
+ sprintf(str+strlen(str), " %d", *ptr++ & 0xff);
+ }
+ Tcl_AppendResult(interp, str, (char *)NULL);
+ if (dash->number&1) {
+ Tcl_AppendResult(interp, " ", str+1, (char *)NULL);
+ }
+ sprintf(str, "] %d setdash\n", outline->offset);
+ Tcl_AppendResult(interp, str, (char *)NULL);
+ ptr = ptr0;
+ } else if (dash->number < 0) {
+ if ((i = DashConvert(lptr, ptr, -dash->number, width)) != 0) {
+ char *lptr0 = lptr;
+ sprintf(str, "[%d", *lptr++ & 0xff);
+ while (--i) {
+ sprintf(str+strlen(str), " %d", *lptr++ & 0xff);
+ }
+ Tcl_AppendResult(interp, str, (char *)NULL);
+ sprintf(str, "] %d setdash\n", outline->offset);
+ Tcl_AppendResult(interp, str, (char *)NULL);
+ lptr = lptr0;
+ } else {
+ Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL);
+ }
+ } else {
+ Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL);
+ }
+ if (str != string) {
+ ckfree(str);
+ }
+ if (lptr != pattern) {
+ ckfree(lptr);
+ }
+ if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (stipple != None) {
+ Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
+ }
+
+ return TCL_OK;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DashConvert
+ *
+ * Converts a character-like dash-list (e.g. "-..")
+ * into an X11-style. l must point to a string that
+ * holds room to at least 2*n characters. if
+ * l == NULL, this function can be used for
+ * syntax checking only.
+ *
+ * Results:
+ * The length of the resulting X11 compatible
+ * dash-list. -1 if failed.
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+DashConvert (l, p, n, width)
+ char *l;
+ CONST char *p;
+ int n;
+ double width;
+{
+ int result = 0;
+ int size, intWidth;
+
+ if (n<0) {
+ n = strlen(p);
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ while (n-- && *p) {
+ switch (*p++) {
+ case ' ':
+ if (result) {
+ if (l) {
+ l[-1] += intWidth + 1;
+ }
+ continue;
+ } else {
+ return 0;
+ }
+ break;
+ case '_':
+ size = 8;
+ break;
+ case '-':
+ size = 6;
+ break;
+ case ',':
+ size = 4;
+ break;
+ case '.':
+ size = 2;
+ break;
+ default:
+ return -1;
+ }
+ if (l) {
+ *l++ = size * intWidth;
+ *l++ = 4 * intWidth;
+ }
+ result += 2;
+ }
+ return result;
+}
+
diff --git a/tk/generic/tkCanvWind.c b/tk/generic/tkCanvWind.c
index 1aa81620210..8a452b70d39 100644
--- a/tk/generic/tkCanvWind.c
+++ b/tk/generic/tkCanvWind.c
@@ -41,7 +41,12 @@ typedef struct WindowItem {
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
@@ -50,6 +55,9 @@ static Tk_ConfigSpec configSpecs[] = {
"center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
"0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
{TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
@@ -68,10 +76,10 @@ static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas,
WindowItem *winItemPtr));
static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas,
@@ -84,7 +92,7 @@ static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double deltaX, double deltaY));
static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv));
+ Tcl_Obj *CONST argv[]));
static void WinItemLostSlaveProc _ANSI_ARGS_((
ClientData clientData, Tk_Window tkwin));
static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData,
@@ -93,8 +101,17 @@ static void WinItemStructureProc _ANSI_ARGS_((
ClientData clientData, XEvent *eventPtr));
static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
+static int WinItemToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *pointPtr));
+#ifdef X_GetImage
+static int xerrorhandler _ANSI_ARGS_((ClientData clientData,
+ XErrorEvent *e));
+#endif
+static int CanvasPsWindow _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_Canvas canvas, double x,
+ double y, int width, int height));
/*
* The structure below defines the window item type by means of procedures
@@ -110,10 +127,10 @@ Tk_ItemType tkWindowType = {
WinItemCoords, /* coordProc */
DeleteWinItem, /* deleteProc */
DisplayWinItem, /* displayProc */
- 1, /* alwaysRedraw */
+ 1|TK_CONFIG_OBJS, /* flags */
WinItemToPoint, /* pointProc */
WinItemToArea, /* areaProc */
- (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */
+ WinItemToPostscript, /* postscriptProc */
ScaleWinItem, /* scaleProc */
TranslateWinItem, /* translateProc */
(Tk_ItemIndexProc *) NULL, /* indexProc */
@@ -121,7 +138,7 @@ Tk_ItemType tkWindowType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
@@ -147,7 +164,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.
*
@@ -164,11 +181,24 @@ CreateWinItem(interp, canvas, itemPtr, argc, argv)
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_Obj *CONST argv[]; /* Arguments describing window. */
{
WindowItem *winItemPtr = (WindowItem *) itemPtr;
+ int i;
+
+ if (argc==1) {
+ i = 1;
+ } else {
+ char *arg = Tcl_GetStringFromObj(argv[1], NULL);
+ if (((argc>1) && (arg[0] == '-')
+ && (arg[1] >= 'a') && (arg[1] <= 'z'))) {
+ i = 1;
+ } else {
+ i = 2;
+ }
+ }
- if (argc < 2) {
+ if (argc < i) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
itemPtr->typePtr->name, " x y ?options?\"",
@@ -190,18 +220,16 @@ CreateWinItem(interp, canvas, itemPtr, argc, argv)
* Process the arguments to fill in the item record.
*/
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
- &winItemPtr->y) != TCL_OK)) {
- return TCL_ERROR;
+ if ((WinItemCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
+ goto error;
}
-
- if (ConfigureWinItem(interp, canvas, itemPtr, argc-2, argv+2, 0)
- != TCL_OK) {
- DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
- return TCL_ERROR;
+ if (ConfigureWinItem(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
+
+ error:
+ DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
}
/*
@@ -214,7 +242,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.
@@ -230,26 +258,42 @@ WinItemCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
WindowItem *winItemPtr = (WindowItem *) itemPtr;
- char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
if (argc == 0) {
- Tcl_PrintDouble(interp, winItemPtr->x, x);
- Tcl_PrintDouble(interp, winItemPtr->y, y);
- Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
- } else if (argc == 2) {
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x)
- != TCL_OK) || (Tk_CanvasGetCoord(interp, canvas, argv[1],
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(winItemPtr->x);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(winItemPtr->y);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ } else if (argc < 3) {
+ if (argc==1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (argc != 2) {
+ char buf[64 + TCL_INTEGER_SPACE];
+
+ sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &winItemPtr->x)
+ != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
&winItemPtr->y) != TCL_OK)) {
return TCL_ERROR;
}
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 +309,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.
@@ -279,7 +323,7 @@ ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Window item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
WindowItem *winItemPtr = (WindowItem *) itemPtr;
@@ -288,8 +332,8 @@ ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags)
oldWindow = winItemPtr->tkwin;
canvasTkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, argv,
- (char *) winItemPtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, (char **) argv,
+ (char *) winItemPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -415,11 +459,15 @@ ComputeWindowBbox(canvas, winItemPtr)
* recomputed. */
{
int width, height, x, y;
+ Tk_State state = winItemPtr->header.state;
x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));
y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));
- if (winItemPtr->tkwin == NULL) {
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) {
/*
* There is no window for this item yet. Just give it a 1x1
* bounding box. Don't give it a 0x0 bounding box; there are
@@ -540,11 +588,18 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY,
int width, height;
short x, y;
Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
+ Tk_State state = itemPtr->state;
if (winItemPtr->tkwin == NULL) {
return;
}
-
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (state == TK_STATE_HIDDEN) {
+ Tk_UnmapWindow(winItemPtr->tkwin);
+ return;
+ }
Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
(double) winItemPtr->header.y1, &x, &y);
width = winItemPtr->header.x2 - winItemPtr->header.x1;
@@ -591,7 +646,7 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY,
* WinItemToPoint --
*
* Computes the distance from a given point to a given
- * rectangle, in canvas units.
+ * window, in canvas units.
*
* Results:
* The return value is 0 if the point whose x and y coordinates
@@ -620,7 +675,7 @@ WinItemToPoint(canvas, itemPtr, pointPtr)
y2 = winItemPtr->header.y2;
/*
- * Point is outside rectangle.
+ * Point is outside window.
*/
if (pointPtr[0] < x1) {
@@ -690,16 +745,203 @@ WinItemToArea(canvas, itemPtr, rectPtr)
/*
*--------------------------------------------------------------
*
+ * xerrorhandler --
+ *
+ * This is a dummy function to catch X11 errors during an
+ * attempt to print a canvas window.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+#ifdef X_GetImage
+static int
+xerrorhandler(clientData, e)
+ ClientData clientData;
+ XErrorEvent *e;
+{
+ return 0;
+}
+#endif
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WinItemToPostscript --
+ *
+ * This procedure is called to generate Postscript for
+ * window items.
+ *
+ * Results:
+ * The return value is a standard Tcl result. If an error
+ * occurs in generating Postscript then an error message is
+ * left in interp->result, replacing whatever used to be there.
+ * If no error occurs, then Postscript for the item is appended
+ * to the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+WinItemToPostscript(interp, canvas, itemPtr, prepass)
+ Tcl_Interp *interp; /* Leave Postscript or error message
+ * here. */
+ Tk_Canvas canvas; /* Information about overall canvas. */
+ Tk_Item *itemPtr; /* Item for which Postscript is
+ * wanted. */
+ int prepass; /* 1 means this is a prepass to
+ * collect font information; 0 means
+ * final Postscript is being created.*/
+{
+ WindowItem *winItemPtr = (WindowItem *)itemPtr;
+
+ double x, y;
+ int width, height;
+ Tk_Window tkwin = winItemPtr->tkwin;
+
+ if (prepass || winItemPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ width = Tk_Width(tkwin);
+ height = Tk_Height(tkwin);
+
+ /*
+ * Compute the coordinates of the lower-left corner of the window,
+ * taking into account the anchor position for the window.
+ */
+
+ x = winItemPtr->x;
+ y = Tk_CanvasPsY(canvas, winItemPtr->y);
+
+ switch (winItemPtr->anchor) {
+ case TK_ANCHOR_NW: y -= height; break;
+ case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
+ case TK_ANCHOR_NE: x -= width; y -= height; break;
+ case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
+ case TK_ANCHOR_SE: x -= width; break;
+ case TK_ANCHOR_S: x -= width/2.0; break;
+ case TK_ANCHOR_SW: break;
+ case TK_ANCHOR_W: y -= height/2.0; break;
+ case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
+ }
+
+ return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height);
+}
+
+static int
+CanvasPsWindow(interp, tkwin, canvas, x, y, width, height)
+ Tcl_Interp *interp; /* Leave Postscript or error message
+ * here. */
+ Tk_Window tkwin; /* window to be printed */
+ Tk_Canvas canvas; /* Information about overall canvas. */
+ double x, y; /* origin of window. */
+ int width, height; /* width/height of window. */
+{
+ char buffer[256];
+ TkWindow *winPtr;
+ XImage *ximage;
+ int result;
+ Tcl_DString buffer1, buffer2;
+#ifdef X_GetImage
+ Tk_ErrorHandler handle;
+#endif
+
+ sprintf(buffer, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n",
+ Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+
+ /* first try if the widget has its own "postscript" command. If it
+ * exists, this will produce much better postscript than
+ * when a pixmap is used.
+ */
+
+ Tcl_DStringInit(&buffer1);
+ Tcl_DStringInit(&buffer2);
+ Tcl_DStringGetResult(interp, &buffer2);
+ sprintf (buffer, "%s postscript -prolog 0\n", Tk_PathName(tkwin));
+ result = Tcl_Eval(interp, buffer);
+ Tcl_DStringGetResult(interp, &buffer1);
+ Tcl_DStringResult(interp, &buffer2);
+ Tcl_DStringFree(&buffer2);
+
+ if (result == TCL_OK) {
+ Tcl_AppendResult(interp,
+ "50 dict begin\nsave\ngsave\n",
+ (char *) NULL);
+ sprintf (buffer,
+ "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
+ height, width, height, width);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ Tcl_AppendResult(interp, " 0 rlineto closepath\n",
+ "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
+ Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n",
+ (char *) NULL);
+ Tcl_DStringFree(&buffer1);
+
+ for (winPtr = ((TkWindow *) tkwin)->childList; winPtr != NULL;
+ winPtr = winPtr->nextPtr) {
+ if (Tk_IsMapped(winPtr)) {
+/* printf("child window: %s\n", winPtr->pathName);*/
+ }
+ }
+ return result;
+ }
+ Tcl_DStringFree(&buffer1);
+
+ /*
+ * If the window is off the screen it will generate an BadMatch/XError
+ * We catch any BadMatch errors here
+ */
+#ifdef X_GetImage
+ handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch,
+ X_GetImage, -1, xerrorhandler, (ClientData) tkwin);
+#endif
+
+ /*
+ * Generate an XImage from the window. We can then read pixel
+ * values out of the XImage.
+ */
+
+ ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0,
+ (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
+
+#ifdef X_GetImage
+ Tk_DeleteErrorHandler(handle);
+#endif
+
+ if (ximage == (XImage*) NULL) {
+ return TCL_OK;
+ }
+
+ result = TkPostscriptImage(interp, tkwin,
+ ((TkCanvas *)canvas)->psInfo, ximage, 0, 0, width, height);
+
+ XDestroyImage(ximage);
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* ScaleWinItem --
*
- * This procedure is invoked to rescale a rectangle or oval
- * item.
+ * This procedure is invoked to rescale a window item.
*
* Results:
* None.
*
* Side effects:
- * The rectangle or oval referred to by itemPtr is rescaled
+ * The window referred to by itemPtr is rescaled
* so that the following transformation is applied to all
* point coordinates:
* x' = originX + scaleX*(x-originX)
@@ -710,9 +952,9 @@ WinItemToArea(canvas, itemPtr, rectPtr)
static void
ScaleWinItem(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. */
+ Tk_Canvas canvas; /* Canvas containing window. */
+ Tk_Item *itemPtr; /* Window to be scaled. */
+ double originX, originY; /* Origin about which to scale window. */
double scaleX; /* Amount to scale in X direction. */
double scaleY; /* Amount to scale in Y direction. */
{
@@ -734,16 +976,15 @@ ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY)
*
* TranslateWinItem --
*
- * This procedure is called to move a rectangle or oval by a
- * given amount.
+ * This procedure is called to move a window by a given amount.
*
* Results:
* None.
*
* Side effects:
- * The position of the rectangle or oval is offset by
- * (xDelta, yDelta), and the bounding box is updated in the
- * generic part of the item structure.
+ * The position of the window is offset by (xDelta, yDelta),
+ * and the bounding box is updated in the generic part of the
+ * item structure.
*
*--------------------------------------------------------------
*/
@@ -860,3 +1101,4 @@ WinItemLostSlaveProc(clientData, tkwin)
Tk_UnmapWindow(winItemPtr->tkwin);
winItemPtr->tkwin = NULL;
}
+
diff --git a/tk/generic/tkCanvas.c b/tk/generic/tkCanvas.c
index 9455014c030..aea03485631 100644
--- a/tk/generic/tkCanvas.c
+++ b/tk/generic/tkCanvas.c
@@ -6,8 +6,8 @@
* 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) 1998 by Scriptics Corporation.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -15,6 +15,8 @@
* RCS: @(#) $Id$
*/
+/* #define USE_OLD_TAG_SEARCH 1 */
+
#include "default.h"
#include "tkInt.h"
#include "tkPort.h"
@@ -24,6 +26,7 @@
* See tkCanvas.h for key data structures used to implement canvases.
*/
+#ifdef USE_OLD_TAG_SEARCH
/*
* The structure defined below is used to keep track of a tag search
* in progress. No field should be accessed by anyone other than
@@ -43,6 +46,65 @@ typedef struct TagSearch {
* return NULL. */
} TagSearch;
+#else /* USE_OLD_TAG_SEARCH */
+/*
+ * The structure defined below is used to keep track of a tag search
+ * in progress. No field should be accessed by anyone other than
+ * TagSearchScan, TagSearchFirst, TagSearchNext,
+ * TagSearchScanExpr, TagSearchEvalExpr,
+ * TagSearchExprInit, TagSearchExprDestroy,
+ * TagSearchDestroy.
+ * (
+ * Not quite accurate: the TagSearch structure is also accessed from:
+ * CanvasWidgetCmd, FindItems, RelinkItems
+ * The only instances of the structure are owned by:
+ * CanvasWidgetCmd
+ * CanvasWidgetCmd is the only function that calls:
+ * FindItems, RelinkItems
+ * CanvasWidgetCmd, FindItems, RelinkItems, are the only functions that call
+ * TagSearch*
+ * )
+ */
+
+typedef struct TagSearch {
+ TkCanvas *canvasPtr; /* Canvas widget being searched. */
+ Tk_Item *currentPtr; /* Pointer to last item returned. */
+ Tk_Item *lastPtr; /* The item right before the currentPtr
+ * is tracked so if the currentPtr is
+ * deleted we don't have to start from the
+ * beginning. */
+ int searchOver; /* Non-zero means NextItem should always
+ * return NULL. */
+ int type; /* search type */
+ int id; /* item id for searches by id */
+
+ char *string; /* tag expression string */
+ int stringIndex; /* current position in string scan */
+ int stringLength; /* length of tag expression string */
+
+ char *rewritebuffer; /* tag string (after removing escapes) */
+ unsigned int rewritebufferAllocated; /* available space for rewrites */
+
+ TagSearchExpr *expr; /* compiled tag expression */
+} TagSearch;
+#endif /* USE_OLD_TAG_SEARCH */
+
+/*
+ * Custom option for handling "-state" and "-offset"
+ */
+
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc,
+ (ClientData) NULL /* only "normal" and "disabled" */
+};
+
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc,
+ (ClientData) TK_OFFSET_RELATIVE
+};
+
/*
* Information used for argv parsing.
*/
@@ -90,6 +152,9 @@ static Tk_ConfigSpec configSpecs[] = {
DEF_CANVAS_INSERT_ON_TIME, Tk_Offset(TkCanvas, insertOnTime), 0},
{TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
DEF_CANVAS_INSERT_WIDTH, Tk_Offset(TkCanvas, textInfo.insertWidth), 0},
+ {TK_CONFIG_CUSTOM, "-offset", "offset", "Offset", "0,0",
+ Tk_Offset(TkCanvas, tsoffset),TK_CONFIG_DONT_SET_DEFAULT,
+ &offsetOption},
{TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
DEF_CANVAS_RELIEF, Tk_Offset(TkCanvas, relief), 0},
{TK_CONFIG_STRING, "-scrollregion", "scrollRegion", "ScrollRegion",
@@ -113,6 +178,9 @@ static Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
TK_CONFIG_MONO_ONLY},
+ {TK_CONFIG_CUSTOM, "-state", "state", "State",
+ "normal", Tk_Offset(TkCanvas, canvas_state), TK_CONFIG_DONT_SET_DEFAULT,
+ &stateOption},
{TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
DEF_CANVAS_TAKE_FOCUS, Tk_Offset(TkCanvas, takeFocus),
TK_CONFIG_NULL_OK},
@@ -143,27 +211,30 @@ static Tk_ConfigSpec configSpecs[] = {
static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't
* been done yet. */
+#ifndef USE_OLD_TAG_SEARCH
/*
- * Standard item types provided by Tk:
+ * Uids for operands in compiled advanced tag search expressions
+ * Initialization is done by InitCanvas()
*/
-
-extern Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType;
-extern Tk_ItemType tkOvalType, tkPolygonType;
-extern Tk_ItemType tkRectangleType, tkTextType, tkWindowType;
-
-/*
- * Various Tk_Uid's used by this module (set up during initialization):
- */
-
static Tk_Uid allUid = NULL;
static Tk_Uid currentUid = NULL;
+static Tk_Uid andUid = NULL;
+static Tk_Uid orUid = NULL;
+static Tk_Uid xorUid = NULL;
+static Tk_Uid parenUid = NULL;
+static Tk_Uid negparenUid = NULL;
+static Tk_Uid endparenUid = NULL;
+static Tk_Uid tagvalUid = NULL;
+static Tk_Uid negtagvalUid = NULL;
+#endif /* USE_OLD_TAG_SEARCH */
/*
- * Statistics counters:
+ * Standard item types provided by Tk:
*/
-static int numIdSearches;
-static int numSlowSearches;
+extern Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType;
+extern Tk_ItemType tkOvalType, tkPolygonType;
+extern Tk_ItemType tkRectangleType, tkTextType, tkWindowType;
/*
* Prototypes for procedures defined later in this file:
@@ -194,34 +265,65 @@ static void CanvasSetOrigin _ANSI_ARGS_((TkCanvas *canvasPtr,
static void CanvasUpdateScrollbars _ANSI_ARGS_((
TkCanvas *canvasPtr));
static int CanvasWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+ Tcl_Interp *interp, int argc, Tcl_Obj *CONST *argv));
static void CanvasWorldChanged _ANSI_ARGS_((
ClientData instanceData));
static int ConfigureCanvas _ANSI_ARGS_((Tcl_Interp *interp,
- TkCanvas *canvasPtr, int argc, char **argv,
+ TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
int flags));
static void DestroyCanvas _ANSI_ARGS_((char *memPtr));
static void DisplayCanvas _ANSI_ARGS_((ClientData clientData));
static void DoItem _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Item *itemPtr, Tk_Uid tag));
+static void EventuallyRedrawItem _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr));
+#ifdef USE_OLD_TAG_SEARCH
+static int FindItems _ANSI_ARGS_((Tcl_Interp *interp,
+ TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
+ Tcl_Obj *newTagObj, int first));
+#else /* USE_OLD_TAG_SEARCH */
static int FindItems _ANSI_ARGS_((Tcl_Interp *interp,
- TkCanvas *canvasPtr, int argc, char **argv,
- char *newTag, char *cmdName, char *option));
+ TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
+ Tcl_Obj *newTagObj, int first,
+ TagSearch **searchPtrPtr));
+#endif /* USE_OLD_TAG_SEARCH */
static int FindArea _ANSI_ARGS_((Tcl_Interp *interp,
- TkCanvas *canvasPtr, char **argv, Tk_Uid uid,
+ TkCanvas *canvasPtr, Tcl_Obj *CONST *argv, Tk_Uid uid,
int enclosed));
static double GridAlign _ANSI_ARGS_((double coord, double spacing));
+static char** GetStringsFromObjs _ANSI_ARGS_((int argc,
+ Tcl_Obj *CONST *objv));
static void InitCanvas _ANSI_ARGS_((void));
+#ifdef USE_OLD_TAG_SEARCH
static Tk_Item * NextItem _ANSI_ARGS_((TagSearch *searchPtr));
+#endif /* USE_OLD_TAG_SEARCH */
static void PickCurrentItem _ANSI_ARGS_((TkCanvas *canvasPtr,
XEvent *eventPtr));
static void PrintScrollFractions _ANSI_ARGS_((int screen1,
int screen2, int object1, int object2,
char *string));
+#ifdef USE_OLD_TAG_SEARCH
static void RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr,
- char *tag, Tk_Item *prevPtr));
+ Tcl_Obj *tag, Tk_Item *prevPtr));
static Tk_Item * StartTagSearch _ANSI_ARGS_((TkCanvas *canvasPtr,
- char *tag, TagSearch *searchPtr));
+ Tcl_Obj *tag, TagSearch *searchPtr));
+#else /* USE_OLD_TAG_SEARCH */
+static int RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr,
+ Tcl_Obj *tag, Tk_Item *prevPtr,
+ TagSearch **searchPtrPtr));
+static void TagSearchExprInit _ANSI_ARGS_ ((
+ TagSearchExpr **exprPtrPtr));
+static void TagSearchExprDestroy _ANSI_ARGS_((TagSearchExpr *expr));
+static void TagSearchDestroy _ANSI_ARGS_((TagSearch *searchPtr));
+static int TagSearchScan _ANSI_ARGS_((TkCanvas *canvasPtr,
+ Tcl_Obj *tag, TagSearch **searchPtrPtr));
+static int TagSearchScanExpr _ANSI_ARGS_((Tcl_Interp *interp,
+ TagSearch *searchPtr, TagSearchExpr *expr));
+static int TagSearchEvalExpr _ANSI_ARGS_((TagSearchExpr *expr,
+ Tk_Item *itemPtr));
+static Tk_Item * TagSearchFirst _ANSI_ARGS_((TagSearch *searchPtr));
+static Tk_Item * TagSearchNext _ANSI_ARGS_((TagSearch *searchPtr));
+#endif /* USE_OLD_TAG_SEARCH */
/*
* The structure below defines canvas class behavior by means of procedures
@@ -238,7 +340,7 @@ static TkClassProcs canvasClass = {
/*
*--------------------------------------------------------------
*
- * Tk_CanvasCmd --
+ * Tk_CanvasObjCmd --
*
* This procedure is invoked to process the "canvas" Tcl
* command. See the user documentation for details on what
@@ -254,12 +356,12 @@ static TkClassProcs canvasClass = {
*/
int
-Tk_CanvasCmd(clientData, interp, argc, argv)
+Tk_CanvasObjCmd(clientData, interp, argc, argv)
ClientData clientData; /* Main window associated with
* interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ Tcl_Obj *CONST argv[]; /* Argument objects. */
{
Tk_Window tkwin = (Tk_Window) clientData;
TkCanvas *canvasPtr;
@@ -270,12 +372,12 @@ Tk_CanvasCmd(clientData, interp, argc, argv)
}
if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " pathName ?options?\"", (char *) NULL);
+ Tcl_WrongNumArgs(interp, 1, argv, "pathName ?options?");
return TCL_ERROR;
}
- new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
+ new = Tk_CreateWindowFromPath(interp, tkwin,
+ Tcl_GetString(argv[1]), (char *) NULL);
if (new == NULL) {
return TCL_ERROR;
}
@@ -290,7 +392,7 @@ Tk_CanvasCmd(clientData, interp, argc, argv)
canvasPtr->tkwin = new;
canvasPtr->display = Tk_Display(new);
canvasPtr->interp = interp;
- canvasPtr->widgetCmd = Tcl_CreateCommand(interp,
+ canvasPtr->widgetCmd = Tcl_CreateObjCommand(interp,
Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd,
(ClientData) canvasPtr, CanvasCmdDeletedProc);
canvasPtr->firstItemPtr = NULL;
@@ -354,9 +456,16 @@ Tk_CanvasCmd(clientData, interp, argc, argv)
canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(new));
canvasPtr->flags = 0;
canvasPtr->nextId = 1;
- canvasPtr->psInfoPtr = NULL;
+ canvasPtr->psInfo = NULL;
+ canvasPtr->canvas_state = TK_STATE_NORMAL;
+ canvasPtr->tsoffset.flags = 0;
+ canvasPtr->tsoffset.xoffset = 0;
+ canvasPtr->tsoffset.yoffset = 0;
+#ifndef USE_OLD_TAG_SEARCH
+ canvasPtr->bindTagExprs = NULL;
+#endif
Tcl_InitHashTable(&canvasPtr->idTable, TCL_ONE_WORD_KEYS);
-
+
Tk_SetClass(canvasPtr->tkwin, "Canvas");
TkSetClassProcs(canvasPtr->tkwin, &canvasClass, (ClientData) canvasPtr);
Tk_CreateEventHandler(canvasPtr->tkwin,
@@ -372,7 +481,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:
@@ -404,50 +513,93 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
* widget. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ Tcl_Obj *CONST argv[]; /* Argument objects. */
{
TkCanvas *canvasPtr = (TkCanvas *) clientData;
- size_t length;
+ unsigned int length;
int c, result;
Tk_Item *itemPtr = NULL; /* Initialization needed only to
* prevent compiler warning. */
+#ifdef USE_OLD_TAG_SEARCH
TagSearch search;
+#else /* USE_OLD_TAG_SEARCH */
+ TagSearch *searchPtr = NULL; /* Allocated by first TagSearchScan
+ * Freed by TagSearchDestroy */
+#endif /* USE_OLD_TAG_SEARCH */
+
+ int index;
+ static char *optionStrings[] = {
+ "addtag", "bbox", "bind", "canvasx",
+ "canvasy", "cget", "configure", "coords",
+ "create", "dchars", "delete", "dtag",
+ "find", "focus", "gettags", "icursor",
+ "index", "insert", "itemcget", "itemconfigure",
+ "lower", "move", "postscript", "raise",
+ "scale", "scan", "select", "type",
+ "xview", "yview",
+ NULL
+ };
+ enum options {
+ CANV_ADDTAG, CANV_BBOX, CANV_BIND, CANV_CANVASX,
+ CANV_CANVASY, CANV_CGET, CANV_CONFIGURE, CANV_COORDS,
+ CANV_CREATE, CANV_DCHARS, CANV_DELETE, CANV_DTAG,
+ CANV_FIND, CANV_FOCUS, CANV_GETTAGS, CANV_ICURSOR,
+ CANV_INDEX, CANV_INSERT, CANV_ITEMCGET, CANV_ITEMCONFIGURE,
+ CANV_LOWER, CANV_MOVE, CANV_POSTSCRIPT,CANV_RAISE,
+ CANV_SCALE, CANV_SCAN, CANV_SELECT, CANV_TYPE,
+ CANV_XVIEW, CANV_YVIEW
+ };
if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " option ?arg arg ...?\"", (char *) NULL);
+ Tcl_WrongNumArgs(interp, 1, argv, "option ?arg arg ...?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, argv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
Tcl_Preserve((ClientData) canvasPtr);
+
result = TCL_OK;
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 'a') && (strncmp(argv[1], "addtag", length) == 0)) {
+ switch ((enum options) index) {
+ case CANV_ADDTAG: {
if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " addtags tag searchCommand ?arg arg ...?\"",
- (char *) NULL);
- goto error;
- }
- result = FindItems(interp, canvasPtr, argc-3, argv+3, argv[2], argv[0],
- " addtag tag");
- } else if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)
- && (length >= 2)) {
+ Tcl_WrongNumArgs(interp, 2, argv, "tag searchCommand ?arg arg ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+#ifdef USE_OLD_TAG_SEARCH
+ result = FindItems(interp, canvasPtr, argc, argv, argv[2], 3);
+#else /* USE_OLD_TAG_SEARCH */
+ result = FindItems(interp, canvasPtr, argc, argv, argv[2], 3, &searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
+ break;
+ }
+
+ case CANV_BBOX: {
int i, gotAny;
int x1 = 0, y1 = 0, x2 = 0, y2 = 0; /* Initializations needed
* only to prevent compiler
* warnings. */
if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " bbox tagOrId ?tagOrId ...?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?tagOrId ...?");
+ result = TCL_ERROR;
+ goto done;
}
gotAny = 0;
for (i = 2; i < argc; i++) {
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[i], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[i], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
+
if ((itemPtr->x1 >= itemPtr->x2)
|| (itemPtr->y1 >= itemPtr->y2)) {
continue;
@@ -475,17 +627,20 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
}
if (gotAny) {
- sprintf(interp->result, "%d %d %d %d", x1, y1, x2, y2);
- }
- } else if ((c == 'b') && (strncmp(argv[1], "bind", length) == 0)
- && (length >= 2)) {
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", x1, y1, x2, y2);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ }
+ break;
+ }
+ case CANV_BIND: {
ClientData object;
if ((argc < 3) || (argc > 5)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " bind tagOrId ?sequence? ?command?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?sequence? ?command?");
+ result = TCL_ERROR;
+ goto done;
}
/*
@@ -494,12 +649,13 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
*/
object = 0;
- if (isdigit(UCHAR(argv[2][0]))) {
+#ifdef USE_OLD_TAG_SEARCH
+ if (isdigit(UCHAR(Tcl_GetString(argv[2])[0]))) {
int id;
char *end;
Tcl_HashEntry *entryPtr;
- id = strtoul(argv[2], &end, 0);
+ id = strtoul(Tcl_GetString(argv[2]), &end, 0);
if (*end != 0) {
goto bindByTag;
}
@@ -510,14 +666,38 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
if (object == 0) {
- Tcl_AppendResult(interp, "item \"", argv[2],
+ Tcl_AppendResult(interp, "item \"", Tcl_GetString(argv[2]),
"\" doesn't exist", (char *) NULL);
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
} else {
bindByTag:
- object = (ClientData) Tk_GetUid(argv[2]);
+ object = (ClientData) Tk_GetUid(Tcl_GetString(argv[2]));
+ }
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ if (searchPtr->type == 1) {
+ Tcl_HashEntry *entryPtr;
+
+ entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) searchPtr->id);
+ if (entryPtr != NULL) {
+ itemPtr = (Tk_Item *) Tcl_GetHashValue(entryPtr);
+ object = (ClientData) itemPtr;
+ }
+
+ if (object == 0) {
+ Tcl_AppendResult(interp, "item \"", Tcl_GetString(argv[2]),
+ "\" doesn't exist", (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ object = (ClientData) searchPtr->expr->uid;
}
+#endif /* USE_OLD_TAG_SEARCH */
/*
* Make a binding table if the canvas doesn't already have
@@ -531,20 +711,51 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
if (argc == 5) {
int append = 0;
unsigned long mask;
+ char* argv4 = Tcl_GetStringFromObj(argv[4],NULL);
- if (argv[4][0] == 0) {
+ if (argv4[0] == 0) {
result = Tk_DeleteBinding(interp, canvasPtr->bindingTable,
- object, argv[3]);
+ object, Tcl_GetStringFromObj(argv[3], NULL));
goto done;
}
- if (argv[4][0] == '+') {
- argv[4]++;
+#ifndef USE_OLD_TAG_SEARCH
+ if (searchPtr->type == 4) {
+ /*
+ * if new tag expression, then insert in linked list
+ */
+ TagSearchExpr *expr, **lastPtr;
+
+ lastPtr = &(canvasPtr->bindTagExprs);
+ while ((expr = *lastPtr) != NULL) {
+ if (expr->uid == searchPtr->expr->uid) {
+ break;
+ }
+ lastPtr = &(expr->next);
+ }
+ if (!expr) {
+ /*
+ * transfer ownership of expr to bindTagExprs list
+ */
+ *lastPtr = searchPtr->expr;
+ searchPtr->expr->next = NULL;
+
+ /*
+ * flag in TagSearch that expr has changed ownership
+ * so that TagSearchDestroy doesn't try to free it
+ */
+ searchPtr->expr = NULL;
+ }
+ }
+#endif /* not USE_OLD_TAG_SEARCH */
+ if (argv4[0] == '+') {
+ argv4++;
append = 1;
}
mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,
- object, argv[3], argv[4], append);
+ object, Tcl_GetStringFromObj(argv[3],NULL), argv4, append);
if (mask == 0) {
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
|Button2MotionMask|Button3MotionMask|Button4MotionMask
@@ -552,140 +763,183 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
|EnterWindowMask|LeaveWindowMask|KeyPressMask
|KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
Tk_DeleteBinding(interp, canvasPtr->bindingTable,
- object, argv[3]);
+ object, Tcl_GetStringFromObj(argv[3], NULL));
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "requested illegal events; ",
"only key, button, motion, enter, leave, and virtual ",
"events may be used", (char *) NULL);
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
} else if (argc == 4) {
char *command;
command = Tk_GetBinding(interp, canvasPtr->bindingTable,
- object, argv[3]);
+ object, Tcl_GetStringFromObj(argv[3], NULL));
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') {
+ result = TCL_ERROR;
+ goto done;
+ } 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)) {
+ break;
+ }
+ case CANV_CANVASX: {
int x;
double grid;
+ char buf[TCL_DOUBLE_SPACE];
if ((argc < 3) || (argc > 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " canvasx screenx ?gridspacing?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "screenx ?gridspacing?");
+ result = TCL_ERROR;
+ goto done;
}
- if (Tk_GetPixels(interp, canvasPtr->tkwin, argv[2], &x) != TCL_OK) {
- goto error;
+ if (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, argv[2], &x) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
}
if (argc == 4) {
- if (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[3],
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[3],
&grid) != TCL_OK) {
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
} else {
grid = 0.0;
}
x += canvasPtr->xOrigin;
- Tcl_PrintDouble(interp, GridAlign((double) x, grid), interp->result);
- } else if ((c == 'c') && (strcmp(argv[1], "canvasy") == 0)) {
+ Tcl_PrintDouble(interp, GridAlign((double) x, grid), buf);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ case CANV_CANVASY: {
int y;
double grid;
+ char buf[TCL_DOUBLE_SPACE];
if ((argc < 3) || (argc > 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " canvasy screeny ?gridspacing?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "screeny ?gridspacing?");
+ result = TCL_ERROR;
+ goto done;
}
- if (Tk_GetPixels(interp, canvasPtr->tkwin, argv[2], &y) != TCL_OK) {
- goto error;
+ if (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, argv[2], &y) != TCL_OK) {
+ result = TCL_ERROR;
+ goto done;
}
if (argc == 4) {
- if (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr,
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
argv[3], &grid) != TCL_OK) {
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
} else {
grid = 0.0;
}
y += canvasPtr->yOrigin;
- Tcl_PrintDouble(interp, GridAlign((double) y, grid), interp->result);
- } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
- && (length >= 2)) {
+ Tcl_PrintDouble(interp, GridAlign((double) y, grid), buf);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ case CANV_CGET: {
if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " cget option\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "option");
+ result = TCL_ERROR;
+ goto done;
}
result = Tk_ConfigureValue(interp, canvasPtr->tkwin, configSpecs,
- (char *) canvasPtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 3)) {
+ (char *) canvasPtr, Tcl_GetString(argv[2]), 0);
+ break;
+ }
+ case CANV_CONFIGURE: {
if (argc == 2) {
result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,
(char *) canvasPtr, (char *) NULL, 0);
} else if (argc == 3) {
result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,
- (char *) canvasPtr, argv[2], 0);
+ (char *) canvasPtr, Tcl_GetString(argv[2]), 0);
} else {
result = ConfigureCanvas(interp, canvasPtr, argc-2, argv+2,
TK_CONFIG_ARGV_ONLY);
}
- } else if ((c == 'c') && (strncmp(argv[1], "coords", length) == 0)
- && (length >= 3)) {
+ break;
+ }
+ case CANV_COORDS: {
if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " coords tagOrId ?x y x y ...?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?x y x y ...?");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ itemPtr = TagSearchFirst(searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr != NULL) {
if (argc != 3) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
}
if (itemPtr->typePtr->coordProc != NULL) {
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
result = (*itemPtr->typePtr->coordProc)(interp,
(Tk_Canvas) canvasPtr, itemPtr, argc-3, argv+3);
+ } else {
+ char **args = GetStringsFromObjs(argc-3, argv+3);
+ result = (*itemPtr->typePtr->coordProc)(interp,
+ (Tk_Canvas) canvasPtr, itemPtr, argc-3, (Tcl_Obj **) args);
+ if (args) ckfree((char *) args);
+ }
}
if (argc != 3) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
}
}
- } else if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)
- && (length >= 2)) {
+ break;
+ }
+ case CANV_CREATE: {
Tk_ItemType *typePtr;
Tk_ItemType *matchPtr = NULL;
Tk_Item *itemPtr;
+ char buf[TCL_INTEGER_SPACE];
int isNew = 0;
Tcl_HashEntry *entryPtr;
-
+ char *arg;
+
if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " create type ?arg arg ...?\"", (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "type ?arg arg ...?");
+ result = TCL_ERROR;
+ goto done;
}
- c = argv[2][0];
- length = strlen(argv[2]);
+ arg = Tcl_GetStringFromObj(argv[2], (int *) &length);
+ c = arg[0];
for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->nextPtr) {
if ((c == typePtr->name[0])
- && (strncmp(argv[2], typePtr->name, length) == 0)) {
+ && (strncmp(arg, typePtr->name, length) == 0)) {
if (matchPtr != NULL) {
badType:
Tcl_AppendResult(interp,
"unknown or ambiguous item type \"",
- argv[2], "\"", (char *) NULL);
- goto error;
+ arg, "\"", (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
}
matchPtr = typePtr;
}
@@ -701,10 +955,21 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
itemPtr->tagSpace = TK_TAG_SPACE;
itemPtr->numTags = 0;
itemPtr->typePtr = typePtr;
- if ((*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, argc-3, argv+3) != TCL_OK) {
+ itemPtr->state = TK_STATE_NULL;
+ itemPtr->redraw_flags = 0;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = (*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, argc-3, argv+3);
+ } else {
+ char **args = GetStringsFromObjs(argc-3, argv+3);
+ result = (*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, argc-3, (Tcl_Obj **) args);
+ if (args) ckfree((char *) args);
+ }
+ if (result != TCL_OK) {
ckfree((char *) itemPtr);
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
itemPtr->nextPtr = NULL;
entryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable,
@@ -719,35 +984,56 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
canvasPtr->lastItemPtr->nextPtr = itemPtr;
}
canvasPtr->lastItemPtr = itemPtr;
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ itemPtr->redraw_flags |= FORCE_REDRAW;
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
canvasPtr->flags |= REPICK_NEEDED;
- sprintf(interp->result, "%d", itemPtr->id);
- } else if ((c == 'd') && (strncmp(argv[1], "dchars", length) == 0)
- && (length >= 2)) {
+ sprintf(buf, "%d", itemPtr->id);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ case CANV_DCHARS: {
int first, last;
+ int x1,x2,y1,y2;
if ((argc != 4) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " dchars tagOrId first ?last?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId first ?last?");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if ((itemPtr->typePtr->indexProc == NULL)
|| (itemPtr->typePtr->dCharsProc == NULL)) {
continue;
}
- if ((*itemPtr->typePtr->indexProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, argv[3], &first) != TCL_OK) {
- goto error;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (char *) argv[3], &first);
+ } else {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, Tcl_GetStringFromObj(argv[3], NULL), &first);
+ }
+ if (result != TCL_OK) {
+ goto done;
}
if (argc == 5) {
- if ((*itemPtr->typePtr->indexProc)(interp,
- (Tk_Canvas) canvasPtr, itemPtr, argv[4], &last)
- != TCL_OK) {
- goto error;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (char *) argv[4], &last);
+ } else {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, Tcl_GetStringFromObj(argv[4], NULL), &last);
+ }
+ if (result != TCL_OK) {
+ goto done;
}
} else {
last = first;
@@ -756,26 +1042,40 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
/*
* Redraw both item's old and new areas: it's possible
* that a delete could result in a new area larger than
- * the old area.
+ * the old area. Except if the insertProc sets the
+ * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.
*/
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ x1 = itemPtr->x1; y1 = itemPtr->y1;
+ x2 = itemPtr->x2; y2 = itemPtr->y2;
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
(*itemPtr->typePtr->dCharsProc)((Tk_Canvas) canvasPtr,
itemPtr, first, last);
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) {
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ x1, y1, x2, y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
+ }
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
}
- } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)
- && (length >= 2)) {
+ break;
+ }
+ case CANV_DELETE: {
int i;
Tcl_HashEntry *entryPtr;
for (i = 2; i < argc; i++) {
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[i], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[i], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
if (canvasPtr->bindingTable != NULL) {
Tk_DeleteAllBindings(canvasPtr->bindingTable,
(ClientData) itemPtr);
@@ -824,24 +1124,32 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
}
}
- } else if ((c == 'd') && (strncmp(argv[1], "dtag", length) == 0)
- && (length >= 2)) {
+ break;
+ }
+ case CANV_DTAG: {
Tk_Uid tag;
int i;
if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " dtag tagOrId ?tagToDelete?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?tagToDelete?");
+ result = TCL_ERROR;
+ goto done;
}
if (argc == 4) {
- tag = Tk_GetUid(argv[3]);
+ tag = Tk_GetUid(Tcl_GetStringFromObj(argv[3], NULL));
} else {
- tag = Tk_GetUid(argv[2]);
+ tag = Tk_GetUid(Tcl_GetStringFromObj(argv[2], NULL));
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
for (i = itemPtr->numTags-1; i >= 0; i--) {
if (itemPtr->tagPtr[i] == tag) {
itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1];
@@ -849,41 +1157,55 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
}
}
- } else if ((c == 'f') && (strncmp(argv[1], "find", length) == 0)
- && (length >= 2)) {
+ break;
+ }
+ case CANV_FIND: {
if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " find searchCommand ?arg arg ...?\"",
- (char *) NULL);
- goto error;
- }
- result = FindItems(interp, canvasPtr, argc-2, argv+2, (char *) NULL,
- argv[0]," find");
- } else if ((c == 'f') && (strncmp(argv[1], "focus", length) == 0)
- && (length >= 2)) {
+ Tcl_WrongNumArgs(interp, 2, argv, "searchCommand ?arg arg ...?");
+ result = TCL_ERROR;
+ goto done;
+ }
+#ifdef USE_OLD_TAG_SEARCH
+ result = FindItems(interp, canvasPtr, argc, argv, (Tcl_Obj *) NULL, 2);
+#else /* USE_OLD_TAG_SEARCH */
+ result = FindItems(interp, canvasPtr, argc, argv,
+ (Tcl_Obj *) NULL, 2, &searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
+ break;
+ }
+ case CANV_FOCUS: {
if (argc > 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " focus ?tagOrId?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "?tagOrId?");
+ result = TCL_ERROR;
+ goto done;
}
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;
}
if ((itemPtr != NULL) && (canvasPtr->textInfo.gotFocus)) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
}
- if (argv[2][0] == 0) {
+ if (Tcl_GetStringFromObj(argv[2], NULL)[0] == 0) {
canvasPtr->textInfo.focusItemPtr = NULL;
goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr->typePtr->icursorProc != NULL) {
break;
}
@@ -893,134 +1215,214 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
canvasPtr->textInfo.focusItemPtr = itemPtr;
if (canvasPtr->textInfo.gotFocus) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
}
- } else if ((c == 'g') && (strncmp(argv[1], "gettags", length) == 0)) {
+ break;
+ }
+ case CANV_GETTAGS: {
if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " gettags tagOrId\"", (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ itemPtr = TagSearchFirst(searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr != NULL) {
int i;
for (i = 0; i < itemPtr->numTags; i++) {
Tcl_AppendElement(interp, (char *) itemPtr->tagPtr[i]);
}
}
- } else if ((c == 'i') && (strncmp(argv[1], "icursor", length) == 0)
- && (length >= 2)) {
+ break;
+ }
+ case CANV_ICURSOR: {
int index;
if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " icursor tagOrId index\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if ((itemPtr->typePtr->indexProc == NULL)
|| (itemPtr->typePtr->icursorProc == NULL)) {
goto done;
}
- if ((*itemPtr->typePtr->indexProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, argv[3], &index) != TCL_OK) {
- goto error;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (char *) argv[3], &index);
+ } else {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, Tcl_GetStringFromObj(argv[3], NULL), &index);
+ }
+ if (result != TCL_OK) {
+ goto done;
}
(*itemPtr->typePtr->icursorProc)((Tk_Canvas) canvasPtr, itemPtr,
index);
if ((itemPtr == canvasPtr->textInfo.focusItemPtr)
&& (canvasPtr->textInfo.cursorOn)) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
}
}
- } else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
- && (length >= 3)) {
+ break;
+ }
+ case CANV_INDEX: {
+
int index;
+ char buf[TCL_INTEGER_SPACE];
if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " index tagOrId string\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId string");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr->typePtr->indexProc != NULL) {
break;
}
}
if (itemPtr == NULL) {
Tcl_AppendResult(interp, "can't find an indexable item \"",
- argv[2], "\"", (char *) NULL);
- goto error;
+ Tcl_GetStringFromObj(argv[2], NULL), "\"", (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
}
- if ((*itemPtr->typePtr->indexProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, argv[3], &index) != TCL_OK) {
- goto error;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (char *) argv[3], &index);
+ } else {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, Tcl_GetStringFromObj(argv[3], NULL), &index);
}
- sprintf(interp->result, "%d", index);
- } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
- && (length >= 3)) {
+ if (result != TCL_OK) {
+ goto done;
+ }
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ case CANV_INSERT: {
int beforeThis;
+ int x1,x2,y1,y2;
if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " insert tagOrId beforeThis string\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId beforeThis string");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if ((itemPtr->typePtr->indexProc == NULL)
|| (itemPtr->typePtr->insertProc == NULL)) {
continue;
}
- if ((*itemPtr->typePtr->indexProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, argv[3], &beforeThis) != TCL_OK) {
- goto error;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (char *) argv[3], &beforeThis);
+ } else {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, Tcl_GetStringFromObj(argv[3], NULL), &beforeThis);
+ }
+ if (result != TCL_OK) {
+ goto done;
}
/*
* Redraw both item's old and new areas: it's possible
* that an insertion could result in a new area either
- * larger or smaller than the old area.
+ * larger or smaller than the old area. Except if the
+ * insertProc sets the TK_ITEM_DONT_REDRAW flag, nothing
+ * more needs to be done.
*/
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
- (*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr,
- itemPtr, beforeThis, argv[4]);
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, itemPtr->x1,
- itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ x1 = itemPtr->x1; y1 = itemPtr->y1;
+ x2 = itemPtr->x2; y2 = itemPtr->y2;
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ (*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr,
+ itemPtr, beforeThis, (char *) argv[4]);
+ } else {
+ (*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr,
+ itemPtr, beforeThis, Tcl_GetStringFromObj(argv[4], NULL));
+ }
+ if (!(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW)) {
+ Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
+ x1, y1, x2, y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
+ }
+ itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
}
- } else if ((c == 'i') && (strncmp(argv[1], "itemcget", length) == 0)
- && (length >= 6)) {
+ break;
+ }
+ case CANV_ITEMCGET: {
if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " itemcget tagOrId option\"",
- (char *) NULL);
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId option");
return TCL_ERROR;
}
+#ifdef USE_OLD_TAG_SEARCH
itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ itemPtr = TagSearchFirst(searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr != NULL) {
result = Tk_ConfigureValue(canvasPtr->interp, canvasPtr->tkwin,
itemPtr->typePtr->configSpecs, (char *) itemPtr,
- argv[3], 0);
+ Tcl_GetStringFromObj(argv[3], NULL), 0);
}
- } else if ((c == 'i') && (strncmp(argv[1], "itemconfigure", length) == 0)
- && (length >= 6)) {
+ break;
+ }
+ case CANV_ITEMCONFIGURE: {
if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " itemconfigure tagOrId ?option value ...?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?option value ...?");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if (argc == 3) {
result = Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin,
itemPtr->typePtr->configSpecs, (char *) itemPtr,
@@ -1028,29 +1430,36 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
} else if (argc == 4) {
result = Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin,
itemPtr->typePtr->configSpecs, (char *) itemPtr,
- argv[3], 0);
+ Tcl_GetString(argv[3]), 0);
} else {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
result = (*itemPtr->typePtr->configProc)(interp,
(Tk_Canvas) canvasPtr, itemPtr, argc-3, argv+3,
TK_CONFIG_ARGV_ONLY);
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ } else {
+ char **args = GetStringsFromObjs(argc-3, argv+3);
+ result = (*itemPtr->typePtr->configProc)(interp,
+ (Tk_Canvas) canvasPtr, itemPtr, argc-3, (Tcl_Obj **) args,
+ TK_CONFIG_ARGV_ONLY);
+ if (args) ckfree((char *) args);
+ }
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
canvasPtr->flags |= REPICK_NEEDED;
}
if ((result != TCL_OK) || (argc < 5)) {
break;
}
}
- } else if ((c == 'l') && (strncmp(argv[1], "lower", length) == 0)) {
+ break;
+ }
+ case CANV_LOWER: {
Tk_Item *itemPtr;
if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " lower tagOrId ?belowThis?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?belowThis?");
+ result = TCL_ERROR;
+ goto done;
}
/*
@@ -1061,49 +1470,75 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
if (argc == 3) {
itemPtr = NULL;
} else {
+#ifdef USE_OLD_TAG_SEARCH
itemPtr = StartTagSearch(canvasPtr, argv[3], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[3], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ itemPtr = TagSearchFirst(searchPtr);
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr == NULL) {
- Tcl_AppendResult(interp, "tag \"", argv[3],
+ Tcl_AppendResult(interp, "tag \"", Tcl_GetString(argv[3]),
"\" doesn't match any items", (char *) NULL);
- goto error;
+ goto done;
}
itemPtr = itemPtr->prevPtr;
}
+#ifdef USE_OLD_TAG_SEARCH
RelinkItems(canvasPtr, argv[2], itemPtr);
- } else if ((c == 'm') && (strncmp(argv[1], "move", length) == 0)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = RelinkItems(canvasPtr, argv[2], itemPtr, &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+#endif /* USE_OLD_TAG_SEARCH */
+ break;
+ }
+ case CANV_MOVE: {
double xAmount, yAmount;
if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " move tagOrId xAmount yAmount\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId xAmount yAmount");
+ result = TCL_ERROR;
+ goto done;
}
- if ((Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[3],
- &xAmount) != TCL_OK) || (Tk_CanvasGetCoord(interp,
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[3],
+ &xAmount) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp,
(Tk_Canvas) canvasPtr, argv[4], &yAmount) != TCL_OK)) {
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
(void) (*itemPtr->typePtr->translateProc)((Tk_Canvas) canvasPtr,
itemPtr, xAmount, yAmount);
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
canvasPtr->flags |= REPICK_NEEDED;
}
- } else if ((c == 'p') && (strncmp(argv[1], "postscript", length) == 0)) {
- result = TkCanvPostscriptCmd(canvasPtr, interp, argc, argv);
- } else if ((c == 'r') && (strncmp(argv[1], "raise", length) == 0)) {
+ break;
+ }
+ case CANV_POSTSCRIPT: {
+ char **args = GetStringsFromObjs(argc, argv);
+ result = TkCanvPostscriptCmd(canvasPtr, interp, argc, args);
+ if (args) ckfree((char *) args);
+ break;
+ }
+ case CANV_RAISE: {
Tk_Item *prevPtr;
if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " raise tagOrId ?aboveThis?\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId ?aboveThis?");
+ result = TCL_ERROR;
+ goto done;
}
/*
@@ -1115,70 +1550,106 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
prevPtr = canvasPtr->lastItemPtr;
} else {
prevPtr = NULL;
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[3], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[3], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
prevPtr = itemPtr;
}
if (prevPtr == NULL) {
- Tcl_AppendResult(interp, "tagOrId \"", argv[3],
+ Tcl_AppendResult(interp, "tagOrId \"", Tcl_GetStringFromObj(argv[3], NULL),
"\" doesn't match any items", (char *) NULL);
- goto error;
+ result = TCL_ERROR;
+ goto done;
}
}
+#ifdef USE_OLD_TAG_SEARCH
RelinkItems(canvasPtr, argv[2], prevPtr);
- } else if ((c == 's') && (strncmp(argv[1], "scale", length) == 0)
- && (length >= 3)) {
+#else /* USE_OLD_TAG_SEARCH */
+ result = RelinkItems(canvasPtr, argv[2], prevPtr, &searchPtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+#endif /* USE_OLD_TAG_SEARCH */
+ break;
+ }
+ case CANV_SCALE: {
double xOrigin, yOrigin, xScale, yScale;
if (argc != 7) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " scale tagOrId xOrigin yOrigin xScale yScale\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId xOrigin yOrigin xScale yScale");
+ result = TCL_ERROR;
+ goto done;
}
- if ((Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr,
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
argv[3], &xOrigin) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr,
+ || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
argv[4], &yOrigin) != TCL_OK)
- || (Tcl_GetDouble(interp, argv[5], &xScale) != TCL_OK)
- || (Tcl_GetDouble(interp, argv[6], &yScale) != TCL_OK)) {
- goto error;
+ || (Tcl_GetDoubleFromObj(interp, argv[5], &xScale) != TCL_OK)
+ || (Tcl_GetDoubleFromObj(interp, argv[6], &yScale) != TCL_OK)) {
+ result = TCL_ERROR;
+ goto done;
}
if ((xScale == 0.0) || (yScale == 0.0)) {
- interp->result = "scale factor cannot be zero";
- goto error;
+ Tcl_SetResult(interp, "scale factor cannot be zero", TCL_STATIC);
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
(void) (*itemPtr->typePtr->scaleProc)((Tk_Canvas) canvasPtr,
itemPtr, xOrigin, yOrigin, xScale, yScale);
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
canvasPtr->flags |= REPICK_NEEDED;
}
- } else if ((c == 's') && (strncmp(argv[1], "scan", length) == 0)
- && (length >= 3)) {
- int x, y;
+ break;
+ }
+ case CANV_SCAN: {
+ int x, y, gain=10;
+ static char *optionStrings[] = {
+ "mark", "dragto", NULL
+ };
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " scan mark|dragto x y\"", (char *) NULL);
- goto error;
+ if (Tcl_GetIndexFromObj(interp, argv[2], optionStrings, "scan option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
}
- if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){
- goto error;
+
+ if ((argc != 5) && (argc != 5+index)) {
+ Tcl_WrongNumArgs(interp, 3, argv, index?"x y ?gain?":"x y");
+ result = TCL_ERROR;
+ goto done;
+ }
+ if ((Tcl_GetIntFromObj(interp, argv[3], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, argv[4], &y) != TCL_OK)){
+ result = TCL_ERROR;
+ goto done;
}
- if ((argv[2][0] == 'm')
- && (strncmp(argv[2], "mark", strlen(argv[2])) == 0)) {
+ if ((argc == 6) && (Tcl_GetIntFromObj(interp, argv[5], &gain) != TCL_OK)) {
+ result = TCL_ERROR;
+ goto done;
+ }
+ if (!index) {
canvasPtr->scanX = x;
canvasPtr->scanXOrigin = canvasPtr->xOrigin;
canvasPtr->scanY = y;
canvasPtr->scanYOrigin = canvasPtr->yOrigin;
- } else if ((argv[2][0] == 'd')
- && (strncmp(argv[2], "dragto", strlen(argv[2])) == 0)) {
+ } else {
int newXOrigin, newYOrigin, tmp;
/*
@@ -1186,30 +1657,41 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
* mouse motion.
*/
- tmp = canvasPtr->scanXOrigin - 10*(x - canvasPtr->scanX)
+ tmp = canvasPtr->scanXOrigin - gain*(x - canvasPtr->scanX)
- canvasPtr->scrollX1;
newXOrigin = canvasPtr->scrollX1 + tmp;
- tmp = canvasPtr->scanYOrigin - 10*(y - canvasPtr->scanY)
+ tmp = canvasPtr->scanYOrigin - gain*(y - canvasPtr->scanY)
- canvasPtr->scrollY1;
newYOrigin = canvasPtr->scrollY1 + tmp;
CanvasSetOrigin(canvasPtr, newXOrigin, newYOrigin);
- } else {
- Tcl_AppendResult(interp, "bad scan option \"", argv[2],
- "\": must be mark or dragto", (char *) NULL);
- goto error;
}
- } else if ((c == 's') && (strncmp(argv[1], "select", length) == 0)
- && (length >= 2)) {
- int index;
+ break;
+ }
+ case CANV_SELECT: {
+ int index, optionindex;
+ static char *optionStrings[] = {
+ "adjust", "clear", "from", "item", "to", NULL
+ };
+ enum options {
+ CANV_ADJUST, CANV_CLEAR, CANV_FROM, CANV_ITEM, CANV_TO
+ };
if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select option ?tagOrId? ?arg?\"", (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "option ?tagOrId? ?arg?");
+ result = TCL_ERROR;
+ goto done;
}
if (argc >= 4) {
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, argv[3], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[3], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ for (itemPtr = TagSearchFirst(searchPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if ((itemPtr->typePtr->indexProc != NULL)
&& (itemPtr->typePtr->selectionProc != NULL)){
break;
@@ -1218,24 +1700,33 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
if (itemPtr == NULL) {
Tcl_AppendResult(interp,
"can't find an indexable and selectable item \"",
- argv[3], "\"", (char *) NULL);
- goto error;
+ Tcl_GetStringFromObj(argv[3], NULL), "\"", (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
}
}
if (argc == 5) {
- if ((*itemPtr->typePtr->indexProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, argv[4], &index) != TCL_OK) {
- goto error;
+ if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, (char *) argv[4], &index);
+ } else {
+ result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
+ itemPtr, Tcl_GetStringFromObj(argv[4], NULL), &index);
}
+ if (result != TCL_OK) {
+ goto done;
+ }
+ }
+ if (Tcl_GetIndexFromObj(interp, argv[2], optionStrings, "select option", 0,
+ &optionindex) != TCL_OK) {
+ return TCL_ERROR;
}
- length = strlen(argv[2]);
- c = argv[2][0];
- if ((c == 'a') && (strncmp(argv[2], "adjust", length) == 0)) {
+ switch ((enum options) optionindex) {
+ case CANV_ADJUST: {
if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select adjust tagOrId index\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 3, argv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
}
if (canvasPtr->textInfo.selItemPtr == itemPtr) {
if (index < (canvasPtr->textInfo.selectFirst
@@ -1248,66 +1739,78 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
}
CanvasSelectTo(canvasPtr, itemPtr, index);
- } else if ((c == 'c') && (argv[2] != NULL)
- && (strncmp(argv[2], "clear", length) == 0)) {
+ break;
+ }
+ case CANV_CLEAR: {
if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select clear\"", (char *) NULL);
- goto error;
+ Tcl_AppendResult(interp, 3, argv, (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
}
if (canvasPtr->textInfo.selItemPtr != NULL) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->textInfo.selItemPtr->x1,
- canvasPtr->textInfo.selItemPtr->y1,
- canvasPtr->textInfo.selItemPtr->x2,
- canvasPtr->textInfo.selItemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr,
+ canvasPtr->textInfo.selItemPtr);
canvasPtr->textInfo.selItemPtr = NULL;
}
goto done;
- } else if ((c == 'f') && (strncmp(argv[2], "from", length) == 0)) {
+ break;
+ }
+ case CANV_FROM: {
if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select from tagOrId index\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 3, argv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
}
canvasPtr->textInfo.anchorItemPtr = itemPtr;
canvasPtr->textInfo.selectAnchor = index;
- } else if ((c == 'i') && (strncmp(argv[2], "item", length) == 0)) {
+ break;
+ }
+ case CANV_ITEM: {
if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select item\"", (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 3, argv, (char *) NULL);
+ result = TCL_ERROR;
+ goto done;
}
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)) {
+ break;
+ }
+ case CANV_TO: {
if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select to tagOrId index\"",
- (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tagOrId index");
+ result = TCL_ERROR;
+ goto done;
}
CanvasSelectTo(canvasPtr, itemPtr, index);
- } else {
- Tcl_AppendResult(interp, "bad select option \"", argv[2],
- "\": must be adjust, clear, from, item, or to",
- (char *) NULL);
- goto error;
+ break;
+ }
}
- } else if ((c == 't') && (strncmp(argv[1], "type", length) == 0)) {
+ break;
+ }
+ case CANV_TYPE: {
if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " type tag\"", (char *) NULL);
- goto error;
+ Tcl_WrongNumArgs(interp, 2, argv, "tag");
+ result = TCL_ERROR;
+ goto done;
}
+#ifdef USE_OLD_TAG_SEARCH
itemPtr = StartTagSearch(canvasPtr, argv[2], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if ((result = TagSearchScan(canvasPtr, argv[2], &searchPtr)) != TCL_OK) {
+ goto done;
+ }
+ itemPtr = TagSearchFirst(searchPtr);
+#endif /* USE_OLD_TAG_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)) {
+ break;
+ }
+ case CANV_XVIEW: {
int count, type;
int newX = 0; /* Initialization needed only to prevent
* gcc warnings. */
@@ -1317,12 +1820,15 @@ 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);
+ char **args = GetStringsFromObjs(argc, argv);
+ type = Tk_GetScrollInfo(interp, argc, args, &fraction, &count);
+ if (args) ckfree((char *) args);
switch (type) {
case TK_SCROLL_ERROR:
- goto error;
+ result = TCL_ERROR;
+ goto done;
case TK_SCROLL_MOVETO:
newX = canvasPtr->scrollX1 - canvasPtr->inset
+ (int) (fraction * (canvasPtr->scrollX2
@@ -1345,7 +1851,9 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
CanvasSetOrigin(canvasPtr, newX, canvasPtr->yOrigin);
}
- } else if ((c == 'y') && (strncmp(argv[1], "yview", length) == 0)) {
+ break;
+ }
+ case CANV_YVIEW: {
int count, type;
int newY = 0; /* Initialization needed only to prevent
* gcc warnings. */
@@ -1355,12 +1863,15 @@ 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);
+ char **args = GetStringsFromObjs(argc, argv);
+ type = Tk_GetScrollInfo(interp, argc, args, &fraction, &count);
+ if (args) ckfree((char *) args);
switch (type) {
case TK_SCROLL_ERROR:
- goto error;
+ result = TCL_ERROR;
+ goto done;
case TK_SCROLL_MOVETO:
newY = canvasPtr->scrollY1 - canvasPtr->inset
+ (int) (fraction*(canvasPtr->scrollY2
@@ -1384,24 +1895,15 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
}
CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY);
}
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be addtag, bbox, bind, ",
- "canvasx, canvasy, cget, configure, coords, create, ",
- "dchars, delete, dtag, find, focus, ",
- "gettags, icursor, index, insert, itemcget, itemconfigure, ",
- "lower, move, postscript, raise, scale, scan, ",
- "select, type, xview, or yview",
- (char *) NULL);
- goto error;
+ break;
+ }
}
done:
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchDestroy(searchPtr);
+#endif /* not USE_OLD_TAG_SEARCH */
Tcl_Release((ClientData) canvasPtr);
return result;
-
- error:
- Tcl_Release((ClientData) canvasPtr);
- return TCL_ERROR;
}
/*
@@ -1429,6 +1931,13 @@ DestroyCanvas(memPtr)
TkCanvas *canvasPtr = (TkCanvas *) memPtr;
Tk_Item *itemPtr;
+ if (canvasPtr->tkwin != NULL) {
+ Tcl_DeleteCommandFromToken(canvasPtr->interp, canvasPtr->widgetCmd);
+ }
+ if (canvasPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayCanvas, (ClientData) canvasPtr);
+ }
+
/*
* Free up all of the items in the canvas.
*/
@@ -1454,11 +1963,24 @@ DestroyCanvas(memPtr)
if (canvasPtr->pixmapGC != None) {
Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
}
+#ifndef USE_OLD_TAG_SEARCH
+ {
+ TagSearchExpr *expr, *next;
+
+ expr = canvasPtr->bindTagExprs;
+ while (expr) {
+ next = expr->next;
+ TagSearchExprDestroy(expr);
+ expr = next;
+ }
+ }
+#endif
Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
if (canvasPtr->bindingTable != NULL) {
Tk_DeleteBindingTable(canvasPtr->bindingTable);
}
Tk_FreeOptions(configSpecs, (char *) canvasPtr, canvasPtr->display, 0);
+ canvasPtr->tkwin = NULL;
ckfree((char *) canvasPtr);
}
@@ -1473,7 +1995,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,
@@ -1489,14 +2011,14 @@ ConfigureCanvas(interp, canvasPtr, argc, argv, flags)
TkCanvas *canvasPtr; /* Information about widget; may or may
* not already have values for some fields. */
int argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
+ Tcl_Obj *CONST argv[]; /* Argument objects. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
XGCValues gcValues;
GC new;
if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
- argc, argv, (char *) canvasPtr, flags) != TCL_OK) {
+ argc, (char **) argv, (char *) canvasPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -1514,11 +2036,10 @@ ConfigureCanvas(interp, canvasPtr, argc, argv, flags)
canvasPtr->inset = canvasPtr->borderWidth + canvasPtr->highlightWidth;
gcValues.function = GXcopy;
- gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
gcValues.graphics_exposures = False;
- new = Tk_GetGCColor(canvasPtr->tkwin,
- GCFunction|GCForeground|GCGraphicsExposures, &gcValues,
- Tk_3DBorderColor(canvasPtr->bgBorder), NULL);
+ gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
+ new = Tk_GetGC(canvasPtr->tkwin,
+ GCFunction|GCGraphicsExposures|GCForeground, &gcValues);
if (canvasPtr->pixmapGC != None) {
Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
}
@@ -1578,6 +2099,22 @@ ConfigureCanvas(interp, canvasPtr, argc, argv, flags)
ckfree((char *) argv2);
}
+ flags = canvasPtr->tsoffset.flags;
+ if (flags & TK_OFFSET_LEFT) {
+ canvasPtr->tsoffset.xoffset = 0;
+ } else if (flags & TK_OFFSET_CENTER) {
+ canvasPtr->tsoffset.xoffset = canvasPtr->width/2;
+ } else if (flags & TK_OFFSET_RIGHT) {
+ canvasPtr->tsoffset.xoffset = canvasPtr->width;
+ }
+ if (flags & TK_OFFSET_TOP) {
+ canvasPtr->tsoffset.yoffset = 0;
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ canvasPtr->tsoffset.yoffset = canvasPtr->height/2;
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ canvasPtr->tsoffset.yoffset = canvasPtr->height;
+ }
+
/*
* Reset the canvas's origin (this is a no-op unless confine
* mode has just been turned on or the scroll region has changed).
@@ -1668,6 +2205,7 @@ DisplayCanvas(clientData)
if (canvasPtr->tkwin == NULL) {
return;
}
+
if (!Tk_IsMapped(tkwin)) {
goto done;
}
@@ -1689,6 +2227,20 @@ DisplayCanvas(clientData)
}
/*
+ * Scan through the item list, registering the bounding box
+ * for all items that didn't do that for the final coordinates
+ * yet. This can be determined by the FORCE_REDRAW flag.
+ */
+
+ for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
+ itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->redraw_flags & FORCE_REDRAW) {
+ itemPtr->redraw_flags &= ~FORCE_REDRAW;
+ EventuallyRedrawItem((Tk_Canvas)canvasPtr, itemPtr);
+ itemPtr->redraw_flags &= ~FORCE_REDRAW;
+ }
+ }
+ /*
* Compute the intersection between the area that needs redrawing
* and the area that's visible on the screen.
*/
@@ -1780,7 +2332,7 @@ DisplayCanvas(clientData)
|| (itemPtr->y1 >= screenY2)
|| (itemPtr->x2 < screenX1)
|| (itemPtr->y2 < screenY1)) {
- if (!itemPtr->typePtr->alwaysRedraw
+ if (!(itemPtr->typePtr->alwaysRedraw & 1)
|| (itemPtr->x1 >= canvasPtr->redrawX2)
|| (itemPtr->y1 >= canvasPtr->redrawY2)
|| (itemPtr->x2 < canvasPtr->redrawX1)
@@ -1788,6 +2340,11 @@ DisplayCanvas(clientData)
continue;
}
}
+ if (itemPtr->state == TK_STATE_HIDDEN ||
+ (itemPtr->state == TK_STATE_NULL &&
+ canvasPtr->canvas_state == TK_STATE_HIDDEN)) {
+ continue;
+ }
(*itemPtr->typePtr->displayProc)((Tk_Canvas) canvasPtr, itemPtr,
canvasPtr->display, pixmap, screenX1, screenY1, width,
height);
@@ -1824,22 +2381,24 @@ DisplayCanvas(clientData)
canvasPtr->borderWidth, canvasPtr->relief);
}
if (canvasPtr->highlightWidth != 0) {
- GC gc;
-
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(canvasPtr->highlightBgColorPtr,
+ Tk_WindowId(tkwin));
if (canvasPtr->textInfo.gotFocus) {
- gc = Tk_GCForColor(canvasPtr->highlightColorPtr,
+ fgGC = Tk_GCForColor(canvasPtr->highlightColorPtr,
Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC,
+ canvasPtr->highlightWidth, Tk_WindowId(tkwin));
} else {
- gc = Tk_GCForColor(canvasPtr->highlightBgColorPtr,
- Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC,
+ canvasPtr->highlightWidth, Tk_WindowId(tkwin));
}
- Tk_DrawFocusHighlight(tkwin, gc, canvasPtr->highlightWidth,
- Tk_WindowId(tkwin));
}
}
done:
- canvasPtr->flags &= ~REDRAW_PENDING;
+ canvasPtr->flags &= ~(REDRAW_PENDING|BBOX_NOT_EMPTY);
canvasPtr->redrawX1 = canvasPtr->redrawX2 = 0;
canvasPtr->redrawY1 = canvasPtr->redrawY2 = 0;
if (canvasPtr->flags & UPDATE_SCROLLBARS) {
@@ -1889,15 +2448,7 @@ CanvasEventProc(clientData, eventPtr)
canvasPtr->flags |= REDRAW_BORDERS;
}
} else if (eventPtr->type == DestroyNotify) {
- if (canvasPtr->tkwin != NULL) {
- canvasPtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(canvasPtr->interp,
- canvasPtr->widgetCmd);
- }
- if (canvasPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(DisplayCanvas, (ClientData) canvasPtr);
- }
- Tcl_EventuallyFree((ClientData) canvasPtr, DestroyCanvas);
+ DestroyCanvas((char *) canvasPtr);
} else if (eventPtr->type == ConfigureNotify) {
canvasPtr->flags |= UPDATE_SCROLLBARS;
@@ -1931,7 +2482,7 @@ CanvasEventProc(clientData, eventPtr)
for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
itemPtr = itemPtr->nextPtr) {
- if (itemPtr->typePtr->alwaysRedraw) {
+ if (itemPtr->typePtr->alwaysRedraw & 1) {
(*itemPtr->typePtr->displayProc)((Tk_Canvas) canvasPtr,
itemPtr, canvasPtr->display, None, 0, 0, 0, 0);
}
@@ -2003,10 +2554,21 @@ Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2)
* Pixels on edge are not redrawn. */
{
TkCanvas *canvasPtr = (TkCanvas *) canvas;
- if ((x1 == x2) || (y1 == y2)) {
+ /*
+ * If tkwin is NULL, the canvas has been destroyed, so we can't really
+ * redraw it.
+ */
+ if (canvasPtr->tkwin == NULL) {
return;
}
- if (canvasPtr->flags & REDRAW_PENDING) {
+
+ if ((x1 >= x2) || (y1 >= y2) ||
+ (x2 < canvasPtr->xOrigin) || (y2 < canvasPtr->yOrigin) ||
+ (x1 >= canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)) ||
+ (y1 >= canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin))) {
+ return;
+ }
+ if (canvasPtr->flags & BBOX_NOT_EMPTY) {
if (x1 <= canvasPtr->redrawX1) {
canvasPtr->redrawX1 = x1;
}
@@ -2024,6 +2586,70 @@ Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2)
canvasPtr->redrawY1 = y1;
canvasPtr->redrawX2 = x2;
canvasPtr->redrawY2 = y2;
+ canvasPtr->flags |= BBOX_NOT_EMPTY;
+ }
+ if (!(canvasPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayCanvas, (ClientData) canvasPtr);
+ canvasPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EventuallyRedrawItem --
+ *
+ * Arrange for part or all of a canvas widget to redrawn at
+ * some convenient time in the future.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The screen will eventually be refreshed.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+EventuallyRedrawItem(canvas, itemPtr)
+ Tk_Canvas canvas; /* Information about widget. */
+ Tk_Item *itemPtr; /* item to be redrawn. */
+{
+ TkCanvas *canvasPtr = (TkCanvas *) canvas;
+ if ((itemPtr->x1 >= itemPtr->x2) || (itemPtr->y1 >= itemPtr->y2) ||
+ (itemPtr->x2 < canvasPtr->xOrigin) ||
+ (itemPtr->y2 < canvasPtr->yOrigin) ||
+ (itemPtr->x1 >= canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)) ||
+ (itemPtr->y1 >= canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin))) {
+ if (!(itemPtr->typePtr->alwaysRedraw & 1)) {
+ return;
+ }
+ }
+ if (!(itemPtr->redraw_flags & FORCE_REDRAW)) {
+ if (canvasPtr->flags & BBOX_NOT_EMPTY) {
+ if (itemPtr->x1 <= canvasPtr->redrawX1) {
+ canvasPtr->redrawX1 = itemPtr->x1;
+ }
+ if (itemPtr->y1 <= canvasPtr->redrawY1) {
+ canvasPtr->redrawY1 = itemPtr->y1;
+ }
+ if (itemPtr->x2 >= canvasPtr->redrawX2) {
+ canvasPtr->redrawX2 = itemPtr->x2;
+ }
+ if (itemPtr->y2 >= canvasPtr->redrawY2) {
+ canvasPtr->redrawY2 = itemPtr->y2;
+ }
+ } else {
+ canvasPtr->redrawX1 = itemPtr->x1;
+ canvasPtr->redrawY1 = itemPtr->y1;
+ canvasPtr->redrawX2 = itemPtr->x2;
+ canvasPtr->redrawY2 = itemPtr->y2;
+ canvasPtr->flags |= BBOX_NOT_EMPTY;
+ }
+ itemPtr->redraw_flags |= FORCE_REDRAW;
+ }
+ if (!(canvasPtr->flags & REDRAW_PENDING)) {
Tcl_DoWhenIdle(DisplayCanvas, (ClientData) canvasPtr);
canvasPtr->flags |= REDRAW_PENDING;
}
@@ -2142,10 +2768,21 @@ InitCanvas()
tkBitmapType.nextPtr = &tkArcType;
tkArcType.nextPtr = &tkWindowType;
tkWindowType.nextPtr = NULL;
+#ifndef USE_OLD_TAG_SEARCH
allUid = Tk_GetUid("all");
currentUid = Tk_GetUid("current");
+ andUid = Tk_GetUid("&&");
+ orUid = Tk_GetUid("||");
+ xorUid = Tk_GetUid("^");
+ parenUid = Tk_GetUid("(");
+ endparenUid = Tk_GetUid(")");
+ negparenUid = Tk_GetUid("!(");
+ tagvalUid = Tk_GetUid("!!");
+ negtagvalUid = Tk_GetUid("!");
+#endif /* USE_OLD_TAG_SEARCH */
}
+#ifdef USE_OLD_TAG_SEARCH
/*
*--------------------------------------------------------------
*
@@ -2172,10 +2809,10 @@ InitCanvas()
*/
static Tk_Item *
-StartTagSearch(canvasPtr, tag, searchPtr)
+StartTagSearch(canvasPtr, tagObj, searchPtr)
TkCanvas *canvasPtr; /* Canvas whose items are to be
* searched. */
- char *tag; /* String giving tag value. */
+ Tcl_Obj *tagObj; /* Object giving tag value. */
TagSearch *searchPtr; /* Record describing tag search;
* will be initialized here. */
{
@@ -2183,7 +2820,13 @@ StartTagSearch(canvasPtr, tag, searchPtr)
Tk_Item *itemPtr, *lastPtr;
Tk_Uid *tagPtr;
Tk_Uid uid;
+ char *tag = Tcl_GetString(tagObj);
int count;
+ TkWindow *tkwin;
+ TkDisplay *dispPtr;
+
+ tkwin = (TkWindow *) canvasPtr->tkwin;
+ dispPtr = tkwin->dispPtr;
/*
* Initialize the search.
@@ -2202,15 +2845,15 @@ StartTagSearch(canvasPtr, tag, searchPtr)
if (isdigit(UCHAR(*tag))) {
char *end;
Tcl_HashEntry *entryPtr;
-
- numIdSearches++;
+
+ dispPtr->numIdSearches++;
id = strtoul(tag, &end, 0);
if (*end == 0) {
itemPtr = canvasPtr->hotPtr;
- lastPtr = canvasPtr->hotPrevPtr;
+ lastPtr = canvasPtr->hotPrevPtr;
if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL)
|| (lastPtr->nextPtr != itemPtr)) {
- numSlowSearches++;
+ dispPtr->numSlowSearches++;
entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id);
if (entryPtr != NULL) {
itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);
@@ -2228,8 +2871,7 @@ StartTagSearch(canvasPtr, tag, searchPtr)
}
searchPtr->tag = uid = Tk_GetUid(tag);
- if (uid == allUid) {
-
+ if (uid == Tk_GetUid("all")) {
/*
* All items match.
*/
@@ -2348,6 +2990,853 @@ NextItem(searchPtr)
return NULL;
}
+#else /* USE_OLD_TAG_SEARCH */
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchExprInit --
+ *
+ * This procedure allocates and initializes one TagSearchExpr struct.
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagSearchExprInit(exprPtrPtr)
+TagSearchExpr **exprPtrPtr;
+{
+ TagSearchExpr* expr = *exprPtrPtr;
+
+ if (! expr) {
+ expr = (TagSearchExpr *) ckalloc(sizeof(TagSearchExpr));
+ expr->allocated = 0;
+ expr->uids = NULL;
+ expr->next = NULL;
+ }
+ expr->uid = NULL;
+ expr->index = 0;
+ expr->length = 0;
+ *exprPtrPtr = expr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchExprDestroy --
+ *
+ * This procedure destroys one TagSearchExpr structure.
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagSearchExprDestroy(expr)
+ TagSearchExpr *expr;
+{
+ if (expr) {
+ if (expr->uids) {
+ ckfree((char *)expr->uids);
+ }
+ ckfree((char *)expr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchScan --
+ *
+ * This procedure is called to initiate an enumeration of
+ * all items in a given canvas that contain a tag that matches
+ * the tagOrId expression.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression
+ * was successfully scanned (syntax).
+ * The information at *searchPtr is initialized
+ * such that a call to TagSearchFirst, followed by
+ * successive calls to TagSearchNext will return items
+ * that match tag.
+ *
+ * Side effects:
+ * SearchPtr is linked into a list of searches in progress
+ * on canvasPtr, so that elements can safely be deleted
+ * while the search is in progress.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TagSearchScan(canvasPtr, tagObj, searchPtrPtr)
+ TkCanvas *canvasPtr; /* Canvas whose items are to be
+ * searched. */
+ Tcl_Obj *tagObj; /* Object giving tag value. */
+ TagSearch **searchPtrPtr; /* Record describing tag search;
+ * will be initialized here. */
+{
+ char *tag = Tcl_GetStringFromObj(tagObj,NULL);
+ int i;
+ TagSearch *searchPtr;
+
+ /*
+ * Initialize the search.
+ */
+
+ if (*searchPtrPtr) {
+ searchPtr = *searchPtrPtr;
+ } else {
+ /* Allocate primary search struct on first call */
+ *searchPtrPtr = searchPtr = (TagSearch *) ckalloc(sizeof(TagSearch));
+ searchPtr->expr = NULL;
+
+ /* Allocate buffer for rewritten tags (after de-escaping) */
+ searchPtr->rewritebufferAllocated = 100;
+ searchPtr->rewritebuffer =
+ ckalloc(searchPtr->rewritebufferAllocated);
+ }
+ TagSearchExprInit(&(searchPtr->expr));
+
+ /* How long is the tagOrId ? */
+ searchPtr->stringLength = strlen(tag);
+
+ /* Make sure there is enough buffer to hold rewritten tags */
+ if ((unsigned int)searchPtr->stringLength >=
+ searchPtr->rewritebufferAllocated) {
+ searchPtr->rewritebufferAllocated = searchPtr->stringLength + 100;
+ searchPtr->rewritebuffer =
+ ckrealloc(searchPtr->rewritebuffer,
+ searchPtr->rewritebufferAllocated);
+ }
+
+ /* Initialize search */
+ searchPtr->canvasPtr = canvasPtr;
+ searchPtr->searchOver = 0;
+ searchPtr->type = 0;
+
+ /*
+ * Find the first matching item in one of several ways. If the tag
+ * is a number then it selects the single item with the matching
+ * identifier. In this case see if the item being requested is the
+ * hot item, in which case the search can be skipped.
+ */
+
+ if (searchPtr->stringLength && isdigit(UCHAR(*tag))) {
+ char *end;
+
+ searchPtr->id = strtoul(tag, &end, 0);
+ if (*end == 0) {
+ searchPtr->type = 1;
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * For all other tags and tag expressions convert to a UID.
+ * This UID is kept forever, but this should be thought of
+ * as a cache rather than as a memory leak.
+ */
+ searchPtr->expr->uid = Tk_GetUid(tag);
+
+ /* short circuit impossible searches for null tags */
+ if (searchPtr->stringLength == 0) {
+ return TCL_OK;
+ }
+
+ /*
+ * Pre-scan tag for at least one unquoted "&&" "||" "^" "!"
+ * if not found then use string as simple tag
+ */
+ for (i = 0; i < searchPtr->stringLength ; i++) {
+ if (tag[i] == '"') {
+ i++;
+ for ( ; i < searchPtr->stringLength; i++) {
+ if (tag[i] == '\\') {
+ i++;
+ continue;
+ }
+ if (tag[i] == '"') {
+ break;
+ }
+ }
+ } else {
+ if ((tag[i] == '&' && tag[i+1] == '&')
+ || (tag[i] == '|' && tag[i+1] == '|')
+ || (tag[i] == '^')
+ || (tag[i] == '!')) {
+ searchPtr->type = 4;
+ break;
+ }
+ }
+ }
+
+ searchPtr->string = tag;
+ searchPtr->stringIndex = 0;
+ if (searchPtr->type == 4) {
+ /*
+ * an operator was found in the prescan, so
+ * now compile the tag expression into array of Tk_Uid
+ * flagging any syntax errors found
+ */
+ if (TagSearchScanExpr(canvasPtr->interp, searchPtr, searchPtr->expr) != TCL_OK) {
+ /* Syntax error in tag expression */
+ /* Result message set by TagSearchScanExpr */
+ return TCL_ERROR;
+ }
+ searchPtr->expr->length = searchPtr->expr->index;
+ } else {
+ if (searchPtr->expr->uid == allUid) {
+ /*
+ * All items match.
+ */
+ searchPtr->type = 2;
+ } else {
+ /*
+ * Optimized single-tag search
+ */
+ searchPtr->type = 3;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchDestroy --
+ *
+ * This procedure destroys any dynamic structures that
+ * may have been allocated by TagSearchScan.
+ *
+ * Results:
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TagSearchDestroy(searchPtr)
+ TagSearch *searchPtr; /* Record describing tag search */
+{
+ if (searchPtr) {
+ TagSearchExprDestroy(searchPtr->expr);
+ ckfree((char *)searchPtr->rewritebuffer);
+ ckfree((char *)searchPtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchScanExpr --
+ *
+ * This recursive procedure is called to scan a tag expression
+ * and compile it into an array of Tk_Uids.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression
+ * was successfully scanned (syntax).
+ * The information at *searchPtr is initialized
+ * such that a call to TagSearchFirst, followed by
+ * successive calls to TagSearchNext will return items
+ * that match tag.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TagSearchScanExpr(interp, searchPtr, expr)
+ Tcl_Interp *interp; /* Current interpreter. */
+ TagSearch *searchPtr; /* Search data */
+ TagSearchExpr *expr; /* compiled expression result */
+{
+ int looking_for_tag; /* When true, scanner expects
+ * next char(s) to be a tag,
+ * else operand expected */
+ int found_tag; /* One or more tags found */
+ int found_endquote; /* For quoted tag string parsing */
+ int negate_result; /* Pending negation of next tag value */
+ char *tag; /* tag from tag expression string */
+ char c;
+
+ negate_result = 0;
+ found_tag = 0;
+ looking_for_tag = 1;
+ while (searchPtr->stringIndex < searchPtr->stringLength) {
+ c = searchPtr->string[searchPtr->stringIndex++];
+
+ if (expr->allocated == expr->index) {
+ expr->allocated += 15;
+ if (expr->uids) {
+ expr->uids =
+ (Tk_Uid *) ckrealloc((char *)(expr->uids),
+ (expr->allocated)*sizeof(Tk_Uid));
+ } else {
+ expr->uids =
+ (Tk_Uid *) ckalloc((expr->allocated)*sizeof(Tk_Uid));
+ }
+ }
+
+ if (looking_for_tag) {
+
+ switch (c) {
+ case ' ' : /* ignore unquoted whitespace */
+ case '\t' :
+ case '\n' :
+ case '\r' :
+ break;
+
+ case '!' : /* negate next tag or subexpr */
+ if (looking_for_tag > 1) {
+ Tcl_AppendResult(interp,
+ "Too many '!' in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ looking_for_tag++;
+ negate_result = 1;
+ break;
+
+ case '(' : /* scan (negated) subexpr recursively */
+ if (negate_result) {
+ expr->uids[expr->index++] = negparenUid;
+ negate_result = 0;
+ } else {
+ expr->uids[expr->index++] = parenUid;
+ }
+ if (TagSearchScanExpr(interp, searchPtr, expr) != TCL_OK) {
+ /* Result string should be already set
+ * by nested call to tag_expr_scan() */
+ return TCL_ERROR;
+ }
+ looking_for_tag = 0;
+ found_tag = 1;
+ break;
+
+ case '"' : /* quoted tag string */
+ if (negate_result) {
+ expr->uids[expr->index++] = negtagvalUid;
+ negate_result = 0;
+ } else {
+ expr->uids[expr->index++] = tagvalUid;
+ }
+ tag = searchPtr->rewritebuffer;
+ found_endquote = 0;
+ while (searchPtr->stringIndex < searchPtr->stringLength) {
+ c = searchPtr->string[searchPtr->stringIndex++];
+ if (c == '\\') {
+ c = searchPtr->string[searchPtr->stringIndex++];
+ }
+ if (c == '"') {
+ found_endquote = 1;
+ break;
+ }
+ *tag++ = c;
+ }
+ if (! found_endquote) {
+ Tcl_AppendResult(interp,
+ "Missing endquote in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (! (tag - searchPtr->rewritebuffer)) {
+ Tcl_AppendResult(interp,
+ "Null quoted tag string in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ *tag++ = '\0';
+ expr->uids[expr->index++] =
+ Tk_GetUid(searchPtr->rewritebuffer);
+ looking_for_tag = 0;
+ found_tag = 1;
+ break;
+
+ case '&' : /* illegal chars when looking for tag */
+ case '|' :
+ case '^' :
+ case ')' :
+ Tcl_AppendResult(interp,
+ "Unexpected operator in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+
+ default : /* unquoted tag string */
+ if (negate_result) {
+ expr->uids[expr->index++] = negtagvalUid;
+ negate_result = 0;
+ } else {
+ expr->uids[expr->index++] = tagvalUid;
+ }
+ tag = searchPtr->rewritebuffer;
+ *tag++ = c;
+ /* copy rest of tag, including any embedded whitespace */
+ while (searchPtr->stringIndex < searchPtr->stringLength) {
+ c = searchPtr->string[searchPtr->stringIndex];
+ if (c == '!' || c == '&' || c == '|' || c == '^'
+ || c == '(' || c == ')' || c == '"') {
+ break;
+ }
+ *tag++ = c;
+ searchPtr->stringIndex++;
+ }
+ /* remove trailing whitespace */
+ while (1) {
+ c = *--tag;
+ /* there must have been one non-whitespace char,
+ * so this will terminate */
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
+ break;
+ }
+ }
+ *++tag = '\0';
+ expr->uids[expr->index++] =
+ Tk_GetUid(searchPtr->rewritebuffer);
+ looking_for_tag = 0;
+ found_tag = 1;
+ }
+
+ } else { /* ! looking_for_tag */
+
+ switch (c) {
+ case ' ' : /* ignore whitespace */
+ case '\t' :
+ case '\n' :
+ case '\r' :
+ break;
+
+ case '&' : /* AND operator */
+ c = searchPtr->string[searchPtr->stringIndex++];
+ if (c != '&') {
+ Tcl_AppendResult(interp,
+ "Singleton '&' in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ expr->uids[expr->index++] = andUid;
+ looking_for_tag = 1;
+ break;
+
+ case '|' : /* OR operator */
+ c = searchPtr->string[searchPtr->stringIndex++];
+ if (c != '|') {
+ Tcl_AppendResult(interp,
+ "Singleton '|' in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ expr->uids[expr->index++] = orUid;
+ looking_for_tag = 1;
+ break;
+
+ case '^' : /* XOR operator */
+ expr->uids[expr->index++] = xorUid;
+ looking_for_tag = 1;
+ break;
+
+ case ')' : /* end subexpression */
+ expr->uids[expr->index++] = endparenUid;
+ goto breakwhile;
+
+ default : /* syntax error */
+ Tcl_AppendResult(interp,
+ "Invalid boolean operator in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ breakwhile:
+ if (found_tag && ! looking_for_tag) {
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "Missing tag in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchEvalExpr --
+ *
+ * This recursive procedure is called to eval a tag expression.
+ *
+ * Results:
+ * The return value indicates if the tagOrId expression
+ * successfully matched the tags of the current item.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+TagSearchEvalExpr(expr, itemPtr)
+ TagSearchExpr *expr; /* Search expression */
+ Tk_Item *itemPtr; /* Item being test for match */
+{
+ int looking_for_tag; /* When true, scanner expects
+ * next char(s) to be a tag,
+ * else operand expected */
+ int negate_result; /* Pending negation of next tag value */
+ Tk_Uid uid;
+ Tk_Uid *tagPtr;
+ int count;
+ int result; /* Value of expr so far */
+ int parendepth;
+
+ result = 0; /* just to keep the compiler quiet */
+
+ negate_result = 0;
+ looking_for_tag = 1;
+ while (expr->index < expr->length) {
+ uid = expr->uids[expr->index++];
+ if (looking_for_tag) {
+ if (uid == tagvalUid) {
+/*
+ * assert(expr->index < expr->length);
+ */
+ uid = expr->uids[expr->index++];
+ result = 0;
+ /*
+ * set result 1 if tag is found in item's tags
+ */
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ result = 1;
+ break;
+ }
+ }
+
+ } else if (uid == negtagvalUid) {
+ negate_result = ! negate_result;
+/*
+ * assert(expr->index < expr->length);
+ */
+ uid = expr->uids[expr->index++];
+ result = 0;
+ /*
+ * set result 1 if tag is found in item's tags
+ */
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ result = 1;
+ break;
+ }
+ }
+
+ } else if (uid == parenUid) {
+ /*
+ * evaluate subexpressions with recursion
+ */
+ result = TagSearchEvalExpr(expr, itemPtr);
+
+ } else if (uid == negparenUid) {
+ negate_result = ! negate_result;
+ /*
+ * evaluate subexpressions with recursion
+ */
+ result = TagSearchEvalExpr(expr, itemPtr);
+/*
+ * } else {
+ * assert(0);
+ */
+ }
+ if (negate_result) {
+ result = ! result;
+ negate_result = 0;
+ }
+ looking_for_tag = 0;
+ } else { /* ! looking_for_tag */
+ if (((uid == andUid) && (!result)) || ((uid == orUid) && result)) {
+ /*
+ * short circuit expression evaluation
+ *
+ * if result before && is 0, or result before || is 1,
+ * then the expression is decided and no further
+ * evaluation is needed.
+ */
+
+ parendepth = 0;
+ while (expr->index < expr->length) {
+ uid = expr->uids[expr->index++];
+ if (uid == tagvalUid || uid == negtagvalUid) {
+ expr->index++;
+ continue;
+ }
+ if (uid == parenUid || uid == negparenUid) {
+ parendepth++;
+ continue;
+ }
+ if (uid == endparenUid) {
+ parendepth--;
+ if (parendepth < 0) {
+ break;
+ }
+ }
+ }
+ return result;
+
+ } else if (uid == xorUid) {
+ /*
+ * if the previous result was 1
+ * then negate the next result
+ */
+ negate_result = result;
+
+ } else if (uid == endparenUid) {
+ return result;
+/*
+ * } else {
+ * assert(0);
+ */
+ }
+ looking_for_tag = 1;
+ }
+ }
+/*
+ * assert(! looking_for_tag);
+ */
+ return result;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchFirst --
+ *
+ * This procedure is called to get the first item
+ * item that matches a preestablished search predicate
+ * that was set by TagSearchScan.
+ *
+ * Results:
+ * The return value is a pointer to the first item, or NULL
+ * if there is no such item. The information at *searchPtr
+ * is updated such that successive calls to TagSearchNext
+ * will return successive items.
+ *
+ * Side effects:
+ * SearchPtr is linked into a list of searches in progress
+ * on canvasPtr, so that elements can safely be deleted
+ * while the search is in progress.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_Item *
+TagSearchFirst(searchPtr)
+ TagSearch *searchPtr; /* Record describing tag search */
+{
+ Tk_Item *itemPtr, *lastPtr;
+ Tk_Uid uid, *tagPtr;
+ int count;
+
+ /* short circuit impossible searches for null tags */
+ if (searchPtr->stringLength == 0) {
+ return NULL;
+ }
+
+ /*
+ * Find the first matching item in one of several ways. If the tag
+ * is a number then it selects the single item with the matching
+ * identifier. In this case see if the item being requested is the
+ * hot item, in which case the search can be skipped.
+ */
+
+ if (searchPtr->type == 1) {
+ Tcl_HashEntry *entryPtr;
+
+ itemPtr = searchPtr->canvasPtr->hotPtr;
+ lastPtr = searchPtr->canvasPtr->hotPrevPtr;
+ if ((itemPtr == NULL) || (itemPtr->id != searchPtr->id) || (lastPtr == NULL)
+ || (lastPtr->nextPtr != itemPtr)) {
+ entryPtr = Tcl_FindHashEntry(&searchPtr->canvasPtr->idTable,
+ (char *) searchPtr->id);
+ if (entryPtr != NULL) {
+ itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);
+ lastPtr = itemPtr->prevPtr;
+ } else {
+ lastPtr = itemPtr = NULL;
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ searchPtr->canvasPtr->hotPtr = itemPtr;
+ searchPtr->canvasPtr->hotPrevPtr = lastPtr;
+ return itemPtr;
+ }
+
+ if (searchPtr->type == 2) {
+
+ /*
+ * All items match.
+ */
+
+ searchPtr->lastPtr = NULL;
+ searchPtr->currentPtr = searchPtr->canvasPtr->firstItemPtr;
+ return searchPtr->canvasPtr->firstItemPtr;
+ }
+
+ if (searchPtr->type == 3) {
+
+ /*
+ * Optimized single-tag search
+ */
+
+ uid = searchPtr->expr->uid;
+ for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ } else {
+
+ /*
+ * None of the above. Search for an item matching the tag expression.
+ */
+
+ for (lastPtr = NULL, itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ searchPtr->expr->index = 0;
+ if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TagSearchNext --
+ *
+ * This procedure returns successive items that match a given
+ * tag; it should be called only after TagSearchFirst has been
+ * used to begin a search.
+ *
+ * Results:
+ * The return value is a pointer to the next item that matches
+ * the tag expr specified to TagSearchScan, or NULL if no such
+ * item exists. *SearchPtr is updated so that the next call
+ * to this procedure will return the next item.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static Tk_Item *
+TagSearchNext(searchPtr)
+ TagSearch *searchPtr; /* Record describing search in
+ * progress. */
+{
+ Tk_Item *itemPtr, *lastPtr;
+ Tk_Uid uid, *tagPtr;
+ int count;
+
+ /*
+ * Find next item in list (this may not actually be a suitable
+ * one to return), and return if there are no items left.
+ */
+
+ lastPtr = searchPtr->lastPtr;
+ if (lastPtr == NULL) {
+ itemPtr = searchPtr->canvasPtr->firstItemPtr;
+ } else {
+ itemPtr = lastPtr->nextPtr;
+ }
+ if ((itemPtr == NULL) || (searchPtr->searchOver)) {
+ searchPtr->searchOver = 1;
+ return NULL;
+ }
+ if (itemPtr != searchPtr->currentPtr) {
+ /*
+ * The structure of the list has changed. Probably the
+ * previously-returned item was removed from the list.
+ * In this case, don't advance lastPtr; just return
+ * its new successor (i.e. do nothing here).
+ */
+ } else {
+ lastPtr = itemPtr;
+ itemPtr = lastPtr->nextPtr;
+ }
+
+ if (searchPtr->type == 2) {
+
+ /*
+ * All items match.
+ */
+
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+
+ if (searchPtr->type == 3) {
+
+ /*
+ * Optimized single-tag search
+ */
+
+ uid = searchPtr->expr->uid;
+ for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags;
+ count > 0; tagPtr++, count--) {
+ if (*tagPtr == uid) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+ }
+
+ /*
+ * Else.... evaluate tag expression
+ */
+
+ for ( ; itemPtr != NULL; lastPtr = itemPtr, itemPtr = itemPtr->nextPtr) {
+ searchPtr->expr->index = 0;
+ if (TagSearchEvalExpr(searchPtr->expr, itemPtr)) {
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->currentPtr = itemPtr;
+ return itemPtr;
+ }
+ }
+ searchPtr->lastPtr = lastPtr;
+ searchPtr->searchOver = 1;
+ return NULL;
+}
+#endif /* USE_OLD_TAG_SEARCH */
+
/*
*--------------------------------------------------------------
*
@@ -2363,7 +3852,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.
*
*--------------------------------------------------------------
@@ -2385,7 +3874,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;
@@ -2439,9 +3929,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
@@ -2452,58 +3942,81 @@ DoItem(interp, itemPtr, tag)
*/
static int
-FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
+#ifdef USE_OLD_TAG_SEARCH
+FindItems(interp, canvasPtr, argc, argv, newTag, first)
+#else /* USE_OLD_TAG_SEARCH */
+FindItems(interp, canvasPtr, argc, argv, newTag, first, searchPtrPtr)
+#endif /* USE_OLD_TAG_SEARCH */
Tcl_Interp *interp; /* Interpreter for error reporting. */
TkCanvas *canvasPtr; /* Canvas whose items are to be
* searched. */
int argc; /* Number of entries in argv. Must be
* greater than zero. */
- char **argv; /* Arguments that describe what items
+ Tcl_Obj *CONST *argv; /* Arguments that describe what items
* to search for (see user doc on
* "find" and "addtag" options). */
- char *newTag; /* If non-NULL, gives new tag to set
+ Tcl_Obj *newTag; /* If non-NULL, gives new tag to set
* on all found items; if NULL, then
* ids of found items are returned
- * in interp->result. */
- char *cmdName; /* Name of original Tcl command, for
- * use in error messages. */
- char *option; /* For error messages: gives option
- * from Tcl command and other stuff
- * up to what's in argc/argv. */
+ * in the interp's result. */
+ int first; /* For error messages: gives number
+ * of elements of argv which are already
+ * handled. */
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearch **searchPtrPtr; /* From CanvasWidgetCmd local vars*/
+#endif /* not USE_OLD_TAG_SEARCH */
{
- int c;
- size_t length;
+#ifdef USE_OLD_TAG_SEARCH
TagSearch search;
+#endif /* USE_OLD_TAG_SEARCH */
Tk_Item *itemPtr;
Tk_Uid uid;
+ int index;
+ static char *optionStrings[] = {
+ "above", "all", "below", "closest",
+ "enclosed", "overlapping", "withtag", NULL
+ };
+ enum options {
+ CANV_ABOVE, CANV_ALL, CANV_BELOW, CANV_CLOSEST,
+ CANV_ENCLOSED, CANV_OVERLAPPING, CANV_WITHTAG
+ };
if (newTag != NULL) {
- uid = Tk_GetUid(newTag);
+ uid = Tk_GetUid(Tcl_GetStringFromObj(newTag, NULL));
} else {
uid = NULL;
}
- c = argv[0][0];
- length = strlen(argv[0]);
- if ((c == 'a') && (strncmp(argv[0], "above", length) == 0)
- && (length >= 2)) {
+ if (Tcl_GetIndexFromObj(interp, argv[first], optionStrings, "search command", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch ((enum options) index) {
+ case CANV_ABOVE: {
Tk_Item *lastPtr = NULL;
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " above tagOrId", (char *) NULL);
+ if (argc != first+2) {
+ Tcl_WrongNumArgs(interp, first+1, argv, "tagOrId");
return TCL_ERROR;
}
- for (itemPtr = StartTagSearch(canvasPtr, argv[1], &search);
+#ifdef USE_OLD_TAG_SEARCH
+ for (itemPtr = StartTagSearch(canvasPtr, argv[first+1], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if (TagSearchScan(canvasPtr, argv[first+1], searchPtrPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (itemPtr = TagSearchFirst(*searchPtrPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(*searchPtrPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
lastPtr = itemPtr;
}
if ((lastPtr != NULL) && (lastPtr->nextPtr != NULL)) {
DoItem(interp, lastPtr->nextPtr, uid);
}
- } else if ((c == 'a') && (strncmp(argv[0], "all", length) == 0)
- && (length >= 2)) {
- if (argc != 1) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " all", (char *) NULL);
+ break;
+ }
+ case CANV_ALL: {
+ if (argc != first+1) {
+ Tcl_WrongNumArgs(interp, first+1, argv, (char *) NULL);
return TCL_ERROR;
}
@@ -2511,43 +4024,53 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
itemPtr = itemPtr->nextPtr) {
DoItem(interp, itemPtr, uid);
}
- } else if ((c == 'b') && (strncmp(argv[0], "below", length) == 0)) {
+ break;
+ }
+ case CANV_BELOW: {
Tk_Item *itemPtr;
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " below tagOrId", (char *) NULL);
+ if (argc != first+2) {
+ Tcl_WrongNumArgs(interp, first+1, argv, "tagOrId");
return TCL_ERROR;
}
- itemPtr = StartTagSearch(canvasPtr, argv[1], &search);
- if (itemPtr->prevPtr != NULL) {
- DoItem(interp, itemPtr->prevPtr, uid);
+#ifdef USE_OLD_TAG_SEARCH
+ itemPtr = StartTagSearch(canvasPtr, argv[first+1], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if (TagSearchScan(canvasPtr, argv[first+1], searchPtrPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ itemPtr = TagSearchFirst(*searchPtrPtr);
+#endif /* USE_OLD_TAG_SEARCH */
+ if (itemPtr != NULL) {
+ if (itemPtr->prevPtr != NULL) {
+ DoItem(interp, itemPtr->prevPtr, uid);
+ }
}
- } else if ((c == 'c') && (strncmp(argv[0], "closest", length) == 0)) {
+ break;
+ }
+ case CANV_CLOSEST: {
double closestDist;
Tk_Item *startPtr, *closestPtr;
double coords[2], halo;
int x1, y1, x2, y2;
- if ((argc < 3) || (argc > 5)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " closest x y ?halo? ?start?",
- (char *) NULL);
+ if ((argc < first+3) || (argc > first+5)) {
+ Tcl_WrongNumArgs(interp, first+1, argv, "x y ?halo? ?start?");
return TCL_ERROR;
}
- if ((Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[1],
- &coords[0]) != TCL_OK) || (Tk_CanvasGetCoord(interp,
- (Tk_Canvas) canvasPtr, argv[2], &coords[1]) != TCL_OK)) {
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[first+1],
+ &coords[0]) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp,
+ (Tk_Canvas) canvasPtr, argv[first+2], &coords[1]) != TCL_OK)) {
return TCL_ERROR;
}
- if (argc > 3) {
- if (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[3],
+ if (argc > first+3) {
+ if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[first+3],
&halo) != TCL_OK) {
return TCL_ERROR;
}
if (halo < 0.0) {
Tcl_AppendResult(interp, "can't have negative halo value \"",
- argv[3], "\"", (char *) NULL);
+ Tcl_GetString(argv[3]), "\"", (char *) NULL);
return TCL_ERROR;
}
} else {
@@ -2559,8 +4082,15 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
*/
startPtr = canvasPtr->firstItemPtr;
- if (argc == 5) {
- itemPtr = StartTagSearch(canvasPtr, argv[4], &search);
+ if (argc == first+5) {
+#ifdef USE_OLD_TAG_SEARCH
+ itemPtr = StartTagSearch(canvasPtr, argv[first+4], &search);
+#else /* USE_OLD_TAG_SEARCH */
+ if (TagSearchScan(canvasPtr, argv[first+4], searchPtrPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ itemPtr = TagSearchFirst(*searchPtrPtr);
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr != NULL) {
startPtr = itemPtr;
}
@@ -2575,6 +4105,10 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
*/
itemPtr = startPtr;
+ while(itemPtr && (itemPtr->state == TK_STATE_HIDDEN ||
+ (itemPtr->state == TK_STATE_NULL && canvasPtr->canvas_state == TK_STATE_HIDDEN))) {
+ itemPtr = itemPtr->nextPtr;
+ }
if (itemPtr == NULL) {
return TCL_OK;
}
@@ -2612,6 +4146,10 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
DoItem(interp, closestPtr, uid);
return TCL_OK;
}
+ if (itemPtr->state == TK_STATE_HIDDEN || (itemPtr->state == TK_STATE_NULL &&
+ canvasPtr->canvas_state == TK_STATE_HIDDEN)) {
+ continue;
+ }
if ((itemPtr->x1 >= x2) || (itemPtr->x2 <= x1)
|| (itemPtr->y1 >= y2) || (itemPtr->y2 <= y1)) {
continue;
@@ -2627,36 +4165,40 @@ FindItems(interp, canvasPtr, argc, argv, newTag, cmdName, option)
}
}
}
- } else if ((c == 'e') && (strncmp(argv[0], "enclosed", length) == 0)) {
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " enclosed x1 y1 x2 y2", (char *) NULL);
+ break;
+ }
+ case CANV_ENCLOSED: {
+ if (argc != first+5) {
+ Tcl_WrongNumArgs(interp, first+1, argv, "x1 y1 x2 y2");
return TCL_ERROR;
}
- return FindArea(interp, canvasPtr, argv+1, uid, 1);
- } else if ((c == 'o') && (strncmp(argv[0], "overlapping", length) == 0)) {
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " overlapping x1 y1 x2 y2",
- (char *) NULL);
+ return FindArea(interp, canvasPtr, argv+first+1, uid, 1);
+ }
+ case CANV_OVERLAPPING: {
+ if (argc != first+5) {
+ Tcl_WrongNumArgs(interp, first+1, argv, "x1 y1 x2 y2");
return TCL_ERROR;
}
- return FindArea(interp, canvasPtr, argv+1, uid, 0);
- } else if ((c == 'w') && (strncmp(argv[0], "withtag", length) == 0)) {
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- cmdName, option, " withtag tagOrId", (char *) NULL);
+ return FindArea(interp, canvasPtr, argv+first+1, uid, 0);
+ }
+ case CANV_WITHTAG: {
+ if (argc != first+2) {
+ Tcl_WrongNumArgs(interp, first+1, argv, "tagOrId");
return TCL_ERROR;
}
- for (itemPtr = StartTagSearch(canvasPtr, argv[1], &search);
+#ifdef USE_OLD_TAG_SEARCH
+ for (itemPtr = StartTagSearch(canvasPtr, argv[first+1], &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if (TagSearchScan(canvasPtr, argv[first+1], searchPtrPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (itemPtr = TagSearchFirst(*searchPtrPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(*searchPtrPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
DoItem(interp, itemPtr, uid);
}
- } else {
- Tcl_AppendResult(interp, "bad search command \"", argv[0],
- "\": must be above, all, below, closest, enclosed, ",
- "overlapping, or withtag", (char *) NULL);
- return TCL_ERROR;
+ }
}
return TCL_OK;
}
@@ -2672,9 +4214,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:
@@ -2691,13 +4233,13 @@ FindArea(interp, canvasPtr, argv, uid, enclosed)
* and result storing. */
TkCanvas *canvasPtr; /* Canvas whose items are to be
* searched. */
- char **argv; /* Array of four arguments that
+ Tcl_Obj *CONST *argv; /* Array of four arguments that
* give the coordinates of the
* rectangular area to search. */
Tk_Uid uid; /* If non-NULL, gives new tag to set
* on all found items; if NULL, then
* ids of found items are returned
- * in interp->result. */
+ * in the interp's result. */
int enclosed; /* 0 means overlapping or enclosed
* items are OK, 1 means only enclosed
* items are OK. */
@@ -2706,13 +4248,13 @@ FindArea(interp, canvasPtr, argv, uid, enclosed)
int x1, y1, x2, y2;
Tk_Item *itemPtr;
- if ((Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[0],
+ if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[0],
&rect[0]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[1],
+ || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[1],
&rect[1]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[2],
+ || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[2],
&rect[2]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, (Tk_Canvas) canvasPtr, argv[3],
+ || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, argv[3],
&rect[3]) != TCL_OK)) {
return TCL_ERROR;
}
@@ -2734,6 +4276,10 @@ FindArea(interp, canvasPtr, argv, uid, enclosed)
y2 = (int) (rect[3]+1.0);
for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->state == TK_STATE_HIDDEN || (itemPtr->state == TK_STATE_NULL &&
+ canvasPtr->canvas_state == TK_STATE_HIDDEN)) {
+ continue;
+ }
if ((itemPtr->x1 >= x2) || (itemPtr->x2 <= x1)
|| (itemPtr->y1 >= y2) || (itemPtr->y2 <= y1)) {
continue;
@@ -2766,17 +4312,27 @@ FindArea(interp, canvasPtr, argv, uid, enclosed)
*--------------------------------------------------------------
*/
+#ifdef USE_OLD_TAG_SEARCH
static void
RelinkItems(canvasPtr, tag, prevPtr)
+#else /* USE_OLD_TAG_SEARCH */
+static int
+RelinkItems(canvasPtr, tag, prevPtr, searchPtrPtr)
+#endif /* USE_OLD_TAG_SEARCH */
TkCanvas *canvasPtr; /* Canvas to be modified. */
- char *tag; /* Tag identifying items to be moved
+ Tcl_Obj *tag; /* Tag identifying items to be moved
* in the redisplay list. */
Tk_Item *prevPtr; /* Reposition the items so that they
* go just after this item (NULL means
* put at beginning of list). */
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearch **searchPtrPtr; /* From CanvasWidgetCmd local vars */
+#endif /* not USE_OLD_TAG_SEARCH */
{
Tk_Item *itemPtr;
+#ifdef USE_OLD_TAG_SEARCH
TagSearch search;
+#endif /* USE_OLD_TAG_SEARCH */
Tk_Item *firstMovePtr, *lastMovePtr;
/*
@@ -2786,8 +4342,16 @@ RelinkItems(canvasPtr, tag, prevPtr)
*/
firstMovePtr = lastMovePtr = NULL;
+#ifdef USE_OLD_TAG_SEARCH
for (itemPtr = StartTagSearch(canvasPtr, tag, &search);
itemPtr != NULL; itemPtr = NextItem(&search)) {
+#else /* USE_OLD_TAG_SEARCH */
+ if (TagSearchScan(canvasPtr, tag, searchPtrPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (itemPtr = TagSearchFirst(*searchPtrPtr);
+ itemPtr != NULL; itemPtr = TagSearchNext(*searchPtrPtr)) {
+#endif /* USE_OLD_TAG_SEARCH */
if (itemPtr == prevPtr) {
/*
* Item after which insertion is to occur is being
@@ -2818,8 +4382,7 @@ RelinkItems(canvasPtr, tag, prevPtr)
lastMovePtr->nextPtr = itemPtr;
}
lastMovePtr = itemPtr;
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, itemPtr->x1, itemPtr->y1,
- itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
canvasPtr->flags |= REPICK_NEEDED;
}
@@ -2829,7 +4392,11 @@ RelinkItems(canvasPtr, tag, prevPtr)
*/
if (firstMovePtr == NULL) {
+#ifdef USE_OLD_TAG_SEARCH
return;
+#else /* USE_OLD_TAG_SEARCH */
+ return TCL_OK;
+#endif /* USE_OLD_TAG_SEARCH */
}
if (prevPtr == NULL) {
if (canvasPtr->firstItemPtr != NULL) {
@@ -2850,6 +4417,9 @@ RelinkItems(canvasPtr, tag, prevPtr)
if (canvasPtr->lastItemPtr == prevPtr) {
canvasPtr->lastItemPtr = lastMovePtr;
}
+#ifndef USE_OLD_TAG_SEARCH
+ return TCL_OK;
+#endif /* not USE_OLD_TAG_SEARCH */
}
/*
@@ -2967,8 +4537,9 @@ CanvasBindProc(clientData, eventPtr)
* Find the topmost item in a canvas that contains a given
* location and mark the the current item. If the current
* item has changed, generate a fake exit event on the old
- * current item and a fake enter event on the new current
- * item.
+ * current item, a fake enter event on the new current item
+ * item and force a redraw of the two items. Canvas items
+ * that are hidden or disabled are ignored.
*
* Results:
* None.
@@ -2994,6 +4565,7 @@ PickCurrentItem(canvasPtr, eventPtr)
{
double coords[2];
int buttonDown;
+ Tk_Item *prevItemPtr;
/*
* Check whether or not a button is down. If so, we'll log entry
@@ -3115,7 +4687,11 @@ PickCurrentItem(canvasPtr, eventPtr)
if ((itemPtr == canvasPtr->currentItemPtr) && !buttonDown) {
for (i = itemPtr->numTags-1; i >= 0; i--) {
+#ifdef USE_OLD_TAG_SEARCH
+ if (itemPtr->tagPtr[i] == Tk_GetUid("current")) {
+#else /* USE_OLD_TAG_SEARCH */
if (itemPtr->tagPtr[i] == currentUid) {
+#endif /* USE_OLD_TAG_SEARCH */
itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1];
itemPtr->numTags--;
break;
@@ -3140,12 +4716,33 @@ PickCurrentItem(canvasPtr, eventPtr)
* if LEFT_GRABBED_ITEM was set.
*/
+ prevItemPtr = canvasPtr->currentItemPtr;
canvasPtr->flags &= ~LEFT_GRABBED_ITEM;
canvasPtr->currentItemPtr = canvasPtr->newCurrentPtr;
+ if (prevItemPtr != NULL && prevItemPtr != canvasPtr->currentItemPtr &&
+ (prevItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT)) {
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, prevItemPtr);
+ (*prevItemPtr->typePtr->configProc)(canvasPtr->interp,
+ (Tk_Canvas) canvasPtr, prevItemPtr, 0, (Tcl_Obj **) NULL,
+ TK_CONFIG_ARGV_ONLY);
+ }
if (canvasPtr->currentItemPtr != NULL) {
XEvent event;
+#ifdef USE_OLD_TAG_SEARCH
+ DoItem((Tcl_Interp *) NULL, canvasPtr->currentItemPtr,
+ Tk_GetUid("current"));
+#else /* USE_OLD_TAG_SEARCH */
DoItem((Tcl_Interp *) NULL, canvasPtr->currentItemPtr, currentUid);
+#endif /* USE_OLD_TAG_SEA */
+ if ((canvasPtr->currentItemPtr->redraw_flags & TK_ITEM_STATE_DEPENDANT &&
+ prevItemPtr != canvasPtr->currentItemPtr)) {
+ (*canvasPtr->currentItemPtr->typePtr->configProc)(canvasPtr->interp,
+ (Tk_Canvas) canvasPtr, canvasPtr->currentItemPtr, 0, (Tcl_Obj **) NULL,
+ TK_CONFIG_ARGV_ONLY);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr,
+ canvasPtr->currentItemPtr);
+ }
event = canvasPtr->pickEvent;
event.type = EnterNotify;
event.xcrossing.detail = NotifyAncestor;
@@ -3159,7 +4756,8 @@ PickCurrentItem(canvasPtr, eventPtr)
* CanvasFindClosest --
*
* Given x and y coordinates, find the topmost canvas item that
- * is "close" to the coordinates.
+ * is "close" to the coordinates. Canvas items that are hidden
+ * or disabled are ignored.
*
* Results:
* The return value is a pointer to the topmost item that is
@@ -3189,6 +4787,11 @@ CanvasFindClosest(canvasPtr, coords)
bestPtr = NULL;
for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->state == TK_STATE_HIDDEN || itemPtr->state==TK_STATE_DISABLED ||
+ (itemPtr->state == TK_STATE_NULL && (canvasPtr->canvas_state == TK_STATE_HIDDEN ||
+ canvasPtr->canvas_state == TK_STATE_DISABLED))) {
+ continue;
+ }
if ((itemPtr->x1 > x2) || (itemPtr->x2 < x1)
|| (itemPtr->y1 > y2) || (itemPtr->y2 < y1)) {
continue;
@@ -3233,6 +4836,10 @@ CanvasDoEvent(canvasPtr, eventPtr)
ClientData *objectPtr;
int numObjects, i;
Tk_Item *itemPtr;
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchExpr *expr;
+ int numExprs;
+#endif /* not USE_OLD_TAG_SEARCH */
if (canvasPtr->bindingTable == NULL) {
return;
@@ -3246,6 +4853,7 @@ CanvasDoEvent(canvasPtr, eventPtr)
return;
}
+#ifdef USE_OLD_TAG_SEARCH
/*
* Set up an array with all the relevant objects for processing
* this event. The relevant objects are (a) the event's item,
@@ -3255,17 +4863,63 @@ CanvasDoEvent(canvasPtr, eventPtr)
*/
numObjects = itemPtr->numTags + 2;
+#else /* USE_OLD_TAG_SEARCH */
+ /*
+ * Set up an array with all the relevant objects for processing
+ * this event. The relevant objects are:
+ * (a) the event's item,
+ * (b) the tags associated with the event's item,
+ * (c) the expressions that are true for the event's item's tags, and
+ * (d) the tag "all".
+ *
+ * If there are a lot of tags then malloc an array to hold all of
+ * the objects.
+ */
+
+ /*
+ * flag and count all expressions that match item's tags
+ */
+ numExprs = 0;
+ expr = canvasPtr->bindTagExprs;
+ while (expr) {
+ expr->index = 0;
+ expr->match = TagSearchEvalExpr(expr, itemPtr);
+ if (expr->match) {
+ numExprs++;
+ }
+ expr = expr->next;
+ }
+
+ numObjects = itemPtr->numTags + numExprs + 2;
+#endif /* not USE_OLD_TAG_SEARCH */
if (numObjects <= NUM_STATIC) {
objectPtr = staticObjects;
} else {
objectPtr = (ClientData *) ckalloc((unsigned)
(numObjects * sizeof(ClientData)));
}
+#ifdef USE_OLD_TAG_SEARCH
+ objectPtr[0] = (ClientData) Tk_GetUid("all");
+#else /* USE_OLD_TAG_SEARCH */
objectPtr[0] = (ClientData) allUid;
+#endif /* USE_OLD_TAG_SEARCH */
for (i = itemPtr->numTags-1; i >= 0; i--) {
objectPtr[i+1] = (ClientData) itemPtr->tagPtr[i];
}
objectPtr[itemPtr->numTags+1] = (ClientData) itemPtr;
+#ifndef USE_OLD_TAG_SEARCH
+ /*
+ * copy uids of matching expressions into object array
+ */
+ i = itemPtr->numTags+2;
+ expr = canvasPtr->bindTagExprs;
+ while (expr) {
+ if (expr->match) {
+ objectPtr[i++] = (int *) expr->uid;
+ }
+ expr = expr->next;
+ }
+#endif /* not USE_OLD_TAG_SEARCH */
/*
* Invoke the binding system, then free up the object array if
@@ -3320,11 +4974,8 @@ CanvasBlinkProc(clientData)
(ClientData) canvasPtr);
}
if (canvasPtr->textInfo.focusItemPtr != NULL) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->textInfo.focusItemPtr->x1,
- canvasPtr->textInfo.focusItemPtr->y1,
- canvasPtr->textInfo.focusItemPtr->x2,
- canvasPtr->textInfo.focusItemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr,
+ canvasPtr->textInfo.focusItemPtr);
}
}
@@ -3367,11 +5018,8 @@ CanvasFocusProc(canvasPtr, gotFocus)
canvasPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
}
if (canvasPtr->textInfo.focusItemPtr != NULL) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->textInfo.focusItemPtr->x1,
- canvasPtr->textInfo.focusItemPtr->y1,
- canvasPtr->textInfo.focusItemPtr->x2,
- canvasPtr->textInfo.focusItemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr,
+ canvasPtr->textInfo.focusItemPtr);
}
if (canvasPtr->highlightWidth > 0) {
canvasPtr->flags |= REDRAW_BORDERS;
@@ -3421,11 +5069,8 @@ CanvasSelectTo(canvasPtr, itemPtr, index)
Tk_OwnSelection(canvasPtr->tkwin, XA_PRIMARY, CanvasLostSelection,
(ClientData) canvasPtr);
} else if (canvasPtr->textInfo.selItemPtr != itemPtr) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->textInfo.selItemPtr->x1,
- canvasPtr->textInfo.selItemPtr->y1,
- canvasPtr->textInfo.selItemPtr->x2,
- canvasPtr->textInfo.selItemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr,
+ canvasPtr->textInfo.selItemPtr);
}
canvasPtr->textInfo.selItemPtr = itemPtr;
@@ -3443,8 +5088,7 @@ CanvasSelectTo(canvasPtr, itemPtr, index)
if ((canvasPtr->textInfo.selectFirst != oldFirst)
|| (canvasPtr->textInfo.selectLast != oldLast)
|| (itemPtr != oldSelPtr)) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- itemPtr->x1, itemPtr->y1, itemPtr->x2, itemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
}
}
@@ -3518,11 +5162,8 @@ CanvasLostSelection(clientData)
TkCanvas *canvasPtr = (TkCanvas *) clientData;
if (canvasPtr->textInfo.selItemPtr != NULL) {
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->textInfo.selItemPtr->x1,
- canvasPtr->textInfo.selItemPtr->y1,
- canvasPtr->textInfo.selItemPtr->x2,
- canvasPtr->textInfo.selItemPtr->y2);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr,
+ canvasPtr->textInfo.selItemPtr);
}
canvasPtr->textInfo.selItemPtr = NULL;
}
@@ -3827,3 +5468,237 @@ CanvasSetOrigin(canvasPtr, xOrigin, yOrigin)
canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetStringsFromObjs
+ *
+ * Results:
+ * Converts object list into string list.
+ *
+ * Side effects:
+ * Memory is allocated for the argv array, which must
+ * be freed using ckfree() when no longer needed.
+ *
+ *----------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char **
+GetStringsFromObjs(argc, objv)
+ int argc;
+ Tcl_Obj *CONST objv[];
+{
+ register int i;
+ char **argv;
+ if (argc <= 0) {
+ return NULL;
+ }
+ argv = (char **) ckalloc((argc+1) * sizeof(char *));
+ for (i = 0; i < argc; i++) {
+ argv[i]=Tcl_GetStringFromObj(objv[i], (int *) NULL);
+ }
+ argv[argc] = 0;
+ return argv;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsColor --
+ *
+ * This procedure is called by individual canvas items when
+ * they want to set a color value for output. Given information
+ * about an X color, this procedure will generate Postscript
+ * commands to set up an appropriate color in Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsColor(interp, canvas, colorPtr)
+ Tcl_Interp *interp; /* Interpreter for returning Postscript
+ * or error message. */
+ Tk_Canvas canvas; /* Information about canvas. */
+ XColor *colorPtr; /* Information about color. */
+{
+ return Tk_PostscriptColor(interp, ((TkCanvas *) canvas)->psInfo,
+ colorPtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsFont --
+ *
+ * This procedure is called by individual canvas items when
+ * they want to output text. Given information about an X
+ * font, this procedure will generate Postscript commands
+ * to set up an appropriate font in Postscript.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to the interp->result.
+ *
+ * Side effects:
+ * The Postscript font name is entered into psInfoPtr->fontTable
+ * if it wasn't already there.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsFont(interp, canvas, tkfont)
+ Tcl_Interp *interp; /* Interpreter for returning Postscript
+ * or error message. */
+ Tk_Canvas canvas; /* Information about canvas. */
+ Tk_Font tkfont; /* Information about font in which text
+ * is to be printed. */
+{
+ return Tk_PostscriptFont(interp, ((TkCanvas *) canvas)->psInfo, tkfont);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsBitmap --
+ *
+ * This procedure is called to output the contents of a
+ * sub-region of a bitmap in proper image data format for
+ * Postscript (i.e. data between angle brackets, one bit
+ * per pixel).
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsBitmap(interp, canvas, bitmap, startX, startY, width, height)
+ Tcl_Interp *interp; /* Interpreter for returning Postscript
+ * or error message. */
+ Tk_Canvas canvas; /* Information about canvas. */
+ Pixmap bitmap; /* Bitmap for which to generate
+ * Postscript. */
+ int startX, startY; /* Coordinates of upper-left corner
+ * of rectangular region to output. */
+ int width, height; /* Height of rectangular region. */
+{
+ return Tk_PostscriptBitmap(interp, ((TkCanvas *) canvas)->tkwin,
+ ((TkCanvas *) canvas)->psInfo, bitmap, startX, startY,
+ width, height);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsStipple --
+ *
+ * This procedure is called by individual canvas items when
+ * they have created a path that they'd like to be filled with
+ * a stipple pattern. Given information about an X bitmap,
+ * this procedure will generate Postscript commands to fill
+ * the current clip region using a stipple pattern defined by the
+ * bitmap.
+ *
+ * Results:
+ * Returns a standard Tcl return value. If an error occurs
+ * then an error message will be left in interp->result.
+ * If no error occurs, then additional Postscript will be
+ * appended to interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasPsStipple(interp, canvas, bitmap)
+ Tcl_Interp *interp; /* Interpreter for returning Postscript
+ * or error message. */
+ Tk_Canvas canvas; /* Information about canvas. */
+ Pixmap bitmap; /* Bitmap to use for stippling. */
+{
+ return Tk_PostscriptStipple(interp, ((TkCanvas *) canvas)->tkwin,
+ ((TkCanvas *) canvas)->psInfo, bitmap);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsY --
+ *
+ * Given a y-coordinate in canvas coordinates, this procedure
+ * returns a y-coordinate to use for Postscript output.
+ *
+ * Results:
+ * Returns the Postscript coordinate that corresponds to
+ * "y".
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+double
+Tk_CanvasPsY(canvas, y)
+ Tk_Canvas canvas; /* Token for canvas on whose behalf
+ * Postscript is being generated. */
+ double y; /* Y-coordinate in canvas coords. */
+{
+ return Tk_PostscriptY(y, ((TkCanvas *) canvas)->psInfo);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsPath --
+ *
+ * Given an array of points for a path, generate Postscript
+ * commands to create the path.
+ *
+ * Results:
+ * Postscript commands get appended to what's in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CanvasPsPath(interp, canvas, coordPtr, numPoints)
+ Tcl_Interp *interp; /* Put generated Postscript in this
+ * interpreter's result field. */
+ Tk_Canvas canvas; /* Canvas on whose behalf Postscript
+ * is being generated. */
+ double *coordPtr; /* Pointer to first in array of
+ * 2*numPoints coordinates giving
+ * points for path. */
+ int numPoints; /* Number of points at *coordPtr. */
+{
+ Tk_PostscriptPath(interp, ((TkCanvas *) canvas)->psInfo,
+ coordPtr, numPoints);
+}
+
+
diff --git a/tk/generic/tkCanvas.h b/tk/generic/tkCanvas.h
index 3899225a5fd..103c874aee1 100644
--- a/tk/generic/tkCanvas.h
+++ b/tk/generic/tkCanvas.h
@@ -21,6 +21,20 @@
#include "tk.h"
#endif
+#ifndef USE_OLD_TAG_SEARCH
+typedef struct TagSearchExpr_s TagSearchExpr;
+
+struct TagSearchExpr_s {
+ TagSearchExpr *next; /* for linked lists of expressions - used in bindings */
+ Tk_Uid uid; /* the uid of the whole expression */
+ Tk_Uid *uids; /* expresion compiled to an array of uids */
+ int allocated; /* available space for array of uids */
+ int length; /* length of expression */
+ int index; /* current position in expression evaluation */
+ int match; /* this expression matches event's item's tags*/
+};
+#endif /* not USE_OLD_TAG_SEARCH */
+
/*
* The record below describes a canvas widget. It is made available
* to the item procedures so they can access certain shared fields such
@@ -204,12 +218,23 @@ typedef struct TkCanvas {
* definitions. */
int nextId; /* Number to use as id for next item
* created in widget. */
- struct TkPostscriptInfo *psInfoPtr;
+ Tk_PostscriptInfo psInfo;
/* Pointer to information used for generating
* Postscript for the canvas. NULL means
* no Postscript is currently being
* generated. */
Tcl_HashTable idTable; /* Table of integer indices. */
+ /*
+ * Additional information, added by the 'dash'-patch
+ */
+ VOID *reserved1;
+ Tk_State canvas_state; /* state of canvas */
+ VOID *reserved2;
+ VOID *reserved3;
+ Tk_TSOffset tsoffset;
+#ifndef USE_OLD_TAG_SEARCH
+ TagSearchExpr *bindTagExprs; /* linked list of tag expressions used in bindings */
+#endif
} TkCanvas;
/*
@@ -237,6 +262,8 @@ typedef struct TkCanvas {
* REPICK_IN_PROGRESS - 1 means PickCurrentItem is currently
* executing. If it should be called recursively,
* it should simply return immediately.
+ * BBOX_NOT_EMPTY - 1 means that the bounding box of the area
+ * that should be redrawn is not empty.
*/
#define REDRAW_PENDING 1
@@ -247,6 +274,18 @@ typedef struct TkCanvas {
#define UPDATE_SCROLLBARS 0x20
#define LEFT_GRABBED_ITEM 0x40
#define REPICK_IN_PROGRESS 0x100
+#define BBOX_NOT_EMPTY 0x200
+
+/*
+ * Flag bits for canvas items (redraw_flags):
+ *
+ * FORCE_REDRAW - 1 means that the new coordinates of some
+ * item are not yet registered using
+ * Tk_CanvasEventuallyRedraw(). It should still
+ * be done by the general canvas code.
+ */
+
+#define FORCE_REDRAW 8
/*
* Canvas-related procedures that are shared among Tk modules but not
@@ -256,4 +295,19 @@ typedef struct TkCanvas {
extern int TkCanvPostscriptCmd _ANSI_ARGS_((TkCanvas *canvasPtr,
Tcl_Interp *interp, int argc, char **argv));
+/*
+ * The following definition is shared between tkCanvPs.c and tkCanvImg.c,
+ * and is used in generating postscript for images and windows.
+ */
+
+typedef struct TkColormapData { /* Hold color information for a window */
+ int separated; /* Whether to use separate color bands */
+ int color; /* Whether window is color or black/white */
+ int ncolors; /* Number of color values stored */
+ XColor *colors; /* Pixel value -> RGB mappings */
+ int red_mask, green_mask, blue_mask; /* Masks and shifts for each */
+ int red_shift, green_shift, blue_shift; /* color band */
+} TkColormapData;
+
#endif /* _TKCANVAS */
+
diff --git a/tk/generic/tkClipboard.c b/tk/generic/tkClipboard.c
index c50a80e7c8a..c1a8c81ba5f 100644
--- a/tk/generic/tkClipboard.c
+++ b/tk/generic/tkClipboard.c
@@ -6,7 +6,7 @@
* 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.
@@ -222,18 +222,18 @@ ClipboardLostSel(clientData)
*
* Take control of the clipboard and clear out the previous
* contents. This procedure must be invoked before any
- * calls to Tk_AppendToClipboard.
+ * calls to Tk_ClipboardAppend.
*
* 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
* directed to the clipboard manager routines associated with
* clipWindow for the display of tkwin. In order to guarantee
* atomicity, no event handling should occur between
- * Tk_ClipboardClear and the following Tk_AppendToClipboard
+ * Tk_ClipboardClear and the following Tk_ClipboardAppend
* calls. This procedure may cause a user-defined LostSel command
* to be invoked when the CLIPBOARD is claimed, so any calling
* function should be reentrant at the point Tk_ClipboardClear is
@@ -307,11 +307,11 @@ Tk_ClipboardClear(interp, tkwin)
* be returned. Tk_ClipboardClear must be called before a sequence
* of Tk_ClipboardAppend calls can be issued. In order to guarantee
* atomicity, no event handling should occur between Tk_ClipboardClear
- * and the following Tk_AppendToClipboard calls.
+ * and the following Tk_ClipboardAppend calls.
*
* 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.
@@ -604,3 +605,4 @@ TkClipInit(interp, dispPtr)
(ClientData) dispPtr, XA_STRING);
return TCL_OK;
}
+
diff --git a/tk/generic/tkCmds.c b/tk/generic/tkCmds.c
index b64c9809f03..78f44ca294a 100644
--- a/tk/generic/tkCmds.c
+++ b/tk/generic/tkCmds.c
@@ -5,8 +5,7 @@
* 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) 1998 by Scriptics Corporation.
+ * 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.
@@ -18,6 +17,14 @@
#include "tkInt.h"
#include <errno.h>
+#if defined(__WIN32__)
+#include "tkWinInt.h"
+#elif defined(MAC_TCL)
+#include "tkMacInt.h"
+#else
+#include "tkUnixInt.h"
+#endif
+
/*
* Forward declarations for procedures defined later in this file:
*/
@@ -55,12 +62,10 @@ Tk_BellObjCmd(clientData, interp, objc, objv)
int objc; /* Number of arguments. */
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
+ static char *bellOptions[] = {"-displayof", (char *) NULL};
Tk_Window tkwin = (Tk_Window) clientData;
+ char *displayName;
int index;
- char *string;
- static char *optionStrings[] = {
- "-displayof", NULL
- };
if ((objc != 1) && (objc != 3)) {
Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window?");
@@ -68,12 +73,13 @@ Tk_BellObjCmd(clientData, interp, objc, objv)
}
if (objc == 3) {
- if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ if (Tcl_GetIndexFromObj(interp, objv[1], bellOptions, "option", 0,
&index) != TCL_OK) {
return TCL_ERROR;
}
- string = Tcl_GetStringFromObj(objv[2], NULL);
- tkwin = Tk_NameToWindow(interp, string, tkwin);
+ displayName = Tcl_GetStringFromObj(objv[2], (int *) NULL);
+
+ tkwin = Tk_NameToWindow(interp, displayName, tkwin);
if (tkwin == NULL) {
return TCL_ERROR;
}
@@ -154,7 +160,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);
}
@@ -186,7 +192,6 @@ TkBindEventProc(winPtr, eventPtr)
{
#define MAX_OBJS 20
ClientData objects[MAX_OBJS], *objPtr;
- static Tk_Uid allUid = NULL;
TkWindow *topLevPtr;
int i, count;
char *p;
@@ -234,10 +239,7 @@ TkBindEventProc(winPtr, eventPtr)
} else {
count = 3;
}
- if (allUid == NULL) {
- allUid = Tk_GetUid("all");
- }
- objPtr[count-1] = (ClientData) allUid;
+ objPtr[count-1] = (ClientData) Tk_GetUid("all");
}
Tk_BindEvent(winPtr->mainPtr->bindingTable, eventPtr, (Tk_Window) winPtr,
count, objPtr);
@@ -383,7 +385,7 @@ TkFreeBindingTags(winPtr)
/*
*----------------------------------------------------------------------
*
- * Tk_DestroyCmd --
+ * Tk_DestroyObjCmd --
*
* This procedure is invoked to process the "destroy" Tcl command.
* See the user documentation for details on what it does.
@@ -398,19 +400,19 @@ TkFreeBindingTags(winPtr)
*/
int
-Tk_DestroyCmd(clientData, interp, argc, argv)
+Tk_DestroyObjCmd(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 window;
Tk_Window tkwin = (Tk_Window) clientData;
int i;
- for (i = 1; i < argc; i++) {
- window = Tk_NameToWindow(interp, argv[i], tkwin);
+ for (i = 1; i < objc; i++) {
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);
if (window == NULL) {
Tcl_ResetResult(interp);
continue;
@@ -432,7 +434,7 @@ Tk_DestroyCmd(clientData, interp, argc, argv)
/*
*----------------------------------------------------------------------
*
- * Tk_LowerCmd --
+ * Tk_LowerObjCmd --
*
* This procedure is invoked to process the "lower" Tcl command.
* See the user documentation for details on what it does.
@@ -448,37 +450,37 @@ Tk_DestroyCmd(clientData, interp, argc, argv)
/* ARGSUSED */
int
-Tk_LowerCmd(clientData, interp, argc, argv)
+Tk_LowerObjCmd(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 mainwin = (Tk_Window) clientData;
Tk_Window tkwin, other;
- if ((argc != 2) && (argc != 3)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window ?belowThis?\"", (char *) NULL);
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?belowThis?");
return TCL_ERROR;
}
- tkwin = Tk_NameToWindow(interp, argv[1], mainwin);
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);
if (tkwin == NULL) {
return TCL_ERROR;
}
- if (argc == 2) {
+ if (objc == 2) {
other = NULL;
} else {
- other = Tk_NameToWindow(interp, argv[2], mainwin);
+ other = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);
if (other == NULL) {
return TCL_ERROR;
}
}
if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) {
- Tcl_AppendResult(interp, "can't lower \"", argv[1], "\" below \"",
- argv[2], "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "can't lower \"", Tcl_GetString(objv[1]),
+ "\" below \"", (other ? Tcl_GetString(objv[2]) : ""),
+ "\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -487,7 +489,7 @@ Tk_LowerCmd(clientData, interp, argc, argv)
/*
*----------------------------------------------------------------------
*
- * Tk_RaiseCmd --
+ * Tk_RaiseObjCmd --
*
* This procedure is invoked to process the "raise" Tcl command.
* See the user documentation for details on what it does.
@@ -503,37 +505,37 @@ Tk_LowerCmd(clientData, interp, argc, argv)
/* ARGSUSED */
int
-Tk_RaiseCmd(clientData, interp, argc, argv)
+Tk_RaiseObjCmd(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 mainwin = (Tk_Window) clientData;
Tk_Window tkwin, other;
- if ((argc != 2) && (argc != 3)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " window ?aboveThis?\"", (char *) NULL);
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "window ?aboveThis?");
return TCL_ERROR;
}
- tkwin = Tk_NameToWindow(interp, argv[1], mainwin);
+ tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);
if (tkwin == NULL) {
return TCL_ERROR;
}
- if (argc == 2) {
+ if (objc == 2) {
other = NULL;
} else {
- other = Tk_NameToWindow(interp, argv[2], mainwin);
+ other = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);
if (other == NULL) {
return TCL_ERROR;
}
}
if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) {
- Tcl_AppendResult(interp, "can't raise \"", argv[1], "\" above \"",
- argv[2], "\"", (char *) NULL);
+ Tcl_AppendResult(interp, "can't raise \"", Tcl_GetString(objv[1]),
+ "\" above \"", (other ? Tcl_GetString(objv[2]) : ""),
+ "\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
@@ -566,10 +568,10 @@ Tk_TkObjCmd(clientData, interp, objc, objv)
int index;
Tk_Window tkwin;
static char *optionStrings[] = {
- "appname", "scaling", NULL
+ "appname", "scaling", "useinputmethods", NULL
};
enum options {
- TK_APPNAME, TK_SCALING
+ TK_APPNAME, TK_SCALING, TK_USE_IM
};
tkwin = (Tk_Window) clientData;
@@ -598,14 +600,14 @@ 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: {
Screen *screenPtr;
int skip, width, height;
double d;
-
+
screenPtr = Tk_Screen(tkwin);
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
@@ -618,7 +620,7 @@ Tk_TkObjCmd(clientData, interp, objc, objv)
d /= WidthMMOfScreen(screenPtr);
Tcl_SetDoubleObj(Tcl_GetObjResult(interp), d);
} else if (objc - skip == 3) {
- if (Tcl_GetDoubleFromObj(interp, objv[2 + skip], &d) != TCL_OK) {
+ if (Tcl_GetDoubleFromObj(interp, objv[2+skip], &d) != TCL_OK) {
return TCL_ERROR;
}
d = (25.4 / 72) / d;
@@ -639,6 +641,40 @@ Tk_TkObjCmd(clientData, interp, objc, objv)
}
break;
}
+ case TK_USE_IM: {
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ int skip;
+
+ skip = TkGetDisplayOf(interp, objc-2, objv+2, &tkwin);
+ if (skip < 0) {
+ return TCL_ERROR;
+ } else if (skip) {
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ }
+ if ((objc - skip) == 3) {
+ /*
+ * In the case where TK_USE_INPUT_METHODS is not defined,
+ * this will be ignored and we will always return 0.
+ * That will indicate to the user that input methods
+ * are just not available.
+ */
+ int bool;
+ if (Tcl_GetBooleanFromObj(interp, objv[2+skip], &bool)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+#ifdef TK_USE_INPUT_METHODS
+ dispPtr->useInputMethods = bool;
+#endif /* TK_USE_INPUT_METHODS */
+ } else if ((objc - skip) != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "?-displayof window? ?boolean?");
+ return TCL_ERROR;
+ }
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
+ dispPtr->useInputMethods);
+ break;
+ }
}
return TCL_OK;
}
@@ -800,7 +836,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.
@@ -816,28 +852,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;
}
@@ -849,12 +884,12 @@ 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 */
}
- for (dispPtr = tkDisplayList; dispPtr != NULL;
+ for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
dispPtr = dispPtr->nextPtr) {
XSync(dispPtr->display, False);
}
@@ -898,10 +933,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"},
@@ -974,85 +1009,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;
}
@@ -1078,80 +1101,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: {
@@ -1165,16 +1174,12 @@ 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;
}
case WIN_VIEWABLE: {
- int viewable;
-
- viewable = 0;
+ int viewable = 0;
for ( ; ; winPtr = winPtr->parentPtr) {
if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) {
break;
@@ -1184,8 +1189,8 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
break;
}
}
- Tcl_ResetResult(interp);
- Tcl_SetBooleanObj(Tcl_GetObjResult(interp), viewable);
+
+ Tcl_SetBooleanObj(resultPtr, viewable);
break;
}
case WIN_VISUAL: {
@@ -1196,54 +1201,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;
}
@@ -1262,9 +1260,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: {
@@ -1283,15 +1279,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: {
@@ -1315,9 +1310,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;
}
@@ -1354,9 +1347,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;
}
@@ -1369,9 +1360,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;
}
@@ -1389,12 +1378,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: {
@@ -1414,9 +1405,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: {
@@ -1435,12 +1425,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");
@@ -1459,16 +1449,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;
@@ -1490,9 +1480,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;
}
@@ -1509,8 +1498,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;
@@ -1519,6 +1507,221 @@ Tk_WinfoObjCmd(clientData, interp, objc, objv)
return TCL_OK;
}
+#if 0
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_WmObjCmd --
+ *
+ * This procedure is invoked to process the "wm" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+Tk_WmObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Main window associated with
+ * interpreter. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+{
+ Tk_Window tkwin;
+ TkWindow *winPtr;
+
+ static char *optionStrings[] = {
+ "aspect", "client", "command", "deiconify",
+ "focusmodel", "frame", "geometry", "grid",
+ "group", "iconbitmap", "iconify", "iconmask",
+ "iconname", "iconposition", "iconwindow", "maxsize",
+ "minsize", "overrideredirect", "positionfrom", "protocol",
+ "resizable", "sizefrom", "state", "title",
+ "tracing", "transient", "withdraw", (char *) NULL
+ };
+ enum options {
+ TKWM_ASPECT, TKWM_CLIENT, TKWM_COMMAND, TKWM_DEICONIFY,
+ TKWM_FOCUSMOD, TKWM_FRAME, TKWM_GEOMETRY, TKWM_GRID,
+ TKWM_GROUP, TKWM_ICONBMP, TKWM_ICONIFY, TKWM_ICONMASK,
+ TKWM_ICONNAME, TKWM_ICONPOS, TKWM_ICONWIN, TKWM_MAXSIZE,
+ TKWM_MINSIZE, TKWM_OVERRIDE, TKWM_POSFROM, TKWM_PROTOCOL,
+ TKWM_RESIZABLE, TKWM_SIZEFROM, TKWM_STATE, TKWM_TITLE,
+ TKWM_TRACING, TKWM_TRANSIENT, TKWM_WITHDRAW
+ };
+
+ tkwin = (Tk_Window) clientData;
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg?");
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (index == TKWM_TRACING) {
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "tracing ?boolean?");
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(dispPtr->wmTracing));
+ return TCL_OK;
+ }
+ return Tcl_GetBooleanFromObj(interp, objv[2], &dispPtr->wmTracing);
+ }
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window ?arg?");
+ return TCL_ERROR;
+ }
+
+ winPtr = (TkWindow *) Tk_NameToWindow(interp,
+ Tcl_GetString(objv[2]), tkwin);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (!(winPtr->flags & TK_TOP_LEVEL)) {
+ Tcl_AppendResult(interp, "window \"", winPtr->pathName,
+ "\" isn't a top-level window", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ switch ((enum options) index) {
+ case TKWM_ASPECT: {
+ TkpWmAspectCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_CLIENT: {
+ TkpWmClientCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_COMMAND: {
+ TkpWmCommandCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_DEICONIFY: {
+ TkpWmDeiconifyCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_FOCUSMOD: {
+ TkpWmFocusmodCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_FRAME: {
+ TkpWmFrameCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_GEOMETRY: {
+ TkpWmGeometryCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_GRID: {
+ TkpWmGridCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_GROUP: {
+ TkpWmGroupCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_ICONBMP: {
+ TkpWmIconbitmapCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_ICONIFY: {
+ TkpWmIconifyCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_ICONMASK: {
+ TkpWmIconmaskCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_ICONNAME: {
+ /* slight Unix variation */
+ TkpWmIconnameCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_ICONPOS: {
+ /* nearly same - 1 line more on Unix */
+ TkpWmIconpositionCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_ICONWIN: {
+ TkpWmIconwindowCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_MAXSIZE: {
+ /* nearly same, win diffs */
+ TkpWmMaxsizeCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_MINSIZE: {
+ /* nearly same, win diffs */
+ TkpWmMinsizeCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_OVERRIDE: {
+ /* almost same */
+ TkpWmOverrideCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_POSFROM: {
+ /* Equal across platforms */
+ TkpWmPositionfromCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_PROTOCOL: {
+ /* Equal across platforms */
+ TkpWmProtocolCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_RESIZABLE: {
+ /* almost same */
+ TkpWmResizableCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_SIZEFROM: {
+ /* Equal across platforms */
+ TkpWmSizefromCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_STATE: {
+ TkpWmStateCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_TITLE: {
+ TkpWmTitleCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_TRANSIENT: {
+ TkpWmTransientCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ case TKWM_WITHDRAW: {
+ TkpWmWithdrawCmd(interp, tkwin, winPtr, objc, objv);
+ break;
+ }
+ }
+
+ updateGeom:
+ if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
+ Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
+ wmPtr->flags |= WM_UPDATE_PENDING;
+ }
+ return TCL_OK;
+}
+#endif
+
/*
*----------------------------------------------------------------------
*
@@ -1567,7 +1770,8 @@ TkGetDisplayOf(interp, objc, objv, tkwinPtr)
return 0;
}
string = Tcl_GetStringFromObj(objv[0], &length);
- if ((length >= 2) && (strncmp(string, "-displayof", (unsigned) length) == 0)) {
+ if ((length >= 2) &&
+ (strncmp(string, "-displayof", (unsigned) length) == 0)) {
if (objc < 2) {
Tcl_SetStringObj(Tcl_GetObjResult(interp),
"value for \"-displayof\" missing", -1);
@@ -1647,3 +1851,5 @@ GetToplevel(tkwin)
}
return winPtr;
}
+
+
diff --git a/tk/generic/tkColor.c b/tk/generic/tkColor.c
index c5844781015..19659fcf159 100644
--- a/tk/generic/tkColor.c
+++ b/tk/generic/tkColor.c
@@ -6,7 +6,7 @@
* 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.
@@ -14,72 +14,149 @@
* RCS: @(#) $Id$
*/
-#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.
+ * Structures of the following following type are used as keys for
+ * colorValueTable (in TkDisplay).
*/
-
-/*
- * Hash table for name -> TkColor mapping, and key structure used to
- * index into that table:
- */
-
-static Tcl_HashTable nameTable;
typedef struct {
- Tk_Uid name; /* Name of desired color. */
+ int red, green, blue; /* Values for desired color. */
Colormap colormap; /* Colormap from which color will be
* allocated. */
Display *display; /* Display for colormap. */
-} NameKey;
+} ValueKey;
+
/*
- * Hash table for value -> TkColor mapping, and key structure used to
- * index into that table:
+ * The structure below is used to allocate thread-local data.
*/
-static Tcl_HashTable valueTable;
-typedef struct {
- int red, green, blue; /* Values for desired color. */
- Colormap colormap; /* Colormap from which color will be
- * allocated. */
- Display *display; /* Display for colormap. */
-} ValueKey;
-
-static int initialized = 0; /* 0 means static structures haven't been
- * initialized yet. */
+typedef struct ThreadSpecificData {
+ char rgbString[20]; /* */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations for procedures defined in this file:
*/
-static void ColorInit _ANSI_ARGS_((void));
+static void ColorInit _ANSI_ARGS_((TkDisplay *dispPtr));
+static void DupColorObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr));
+static void FreeColorObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
+static void InitColorObj _ANSI_ARGS_((Tcl_Obj *objPtr));
-/* CYGNUS LOCAL. */
-
-/* A linked list of GC structures. */
+/*
+ * 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.
+ */
-struct TkGCList {
- /* Next item on list. */
- TkGCList *next;
- /* The display for the GC. */
- Display *display;
- /* The GC. */
- GC gc;
- /* GCForeground or GCBackground. */
- unsigned long mask;
+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.
+ *
+ *----------------------------------------------------------------------
+ */
-/* END CYGNUS LOCAL */
+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;
+}
/*
*----------------------------------------------------------------------
@@ -94,7 +171,7 @@ struct TkGCList {
* 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.
@@ -110,17 +187,17 @@ 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- ColorInit();
+ if (!dispPtr->colorInit) {
+ ColorInit(dispPtr);
}
/*
@@ -128,14 +205,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(&dispPtr->colorNameTable, 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;
}
/*
@@ -154,22 +236,27 @@ Tk_GetColor(interp, tkwin, name)
"\"", (char *) NULL);
}
}
- Tcl_DeleteHashEntry(nameHashPtr);
+ if (new) {
+ Tcl_DeleteHashEntry(nameHashPtr);
+ }
return (XColor *) NULL;
}
/*
- * Now create a new TkColor structure and add it to nameTable.
+ * Now create a new TkColor structure and add it to colorNameTable
+ * (in TkDisplay).
*/
tkColPtr->magic = COLOR_MAGIC;
tkColPtr->gc = None;
tkColPtr->screen = Tk_Screen(tkwin);
- tkColPtr->colormap = nameKey.colormap;
+ tkColPtr->colormap = Tk_Colormap(tkwin);
tkColPtr->visual = Tk_Visual(tkwin);
- tkColPtr->refCount = 1;
- tkColPtr->tablePtr = &nameTable;
+ tkColPtr->resourceRefCount = 1;
+ tkColPtr->objRefCount = 0;
+ tkColPtr->type = TK_COLOR_BY_NAME;
tkColPtr->hashPtr = nameHashPtr;
+ tkColPtr->nextPtr = existingColPtr;
tkColPtr->gcList = NULL;
Tcl_SetHashValue(nameHashPtr, tkColPtr);
@@ -211,9 +298,10 @@ Tk_GetColorByValue(tkwin, colorPtr)
int new;
TkColor *tkColPtr;
Display *display = Tk_Display(tkwin);
+ TkDisplay *dispPtr = TkGetDisplay(display);
- if (!initialized) {
- ColorInit();
+ if (!dispPtr->colorInit) {
+ ColorInit(dispPtr);
}
/*
@@ -226,16 +314,17 @@ Tk_GetColorByValue(tkwin, colorPtr)
valueKey.blue = colorPtr->blue;
valueKey.colormap = Tk_Colormap(tkwin);
valueKey.display = display;
- valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new);
+ valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable,
+ (char *) &valueKey, &new);
if (!new) {
tkColPtr = (TkColor *) Tcl_GetHashValue(valueHashPtr);
- tkColPtr->refCount++;
+ tkColPtr->resourceRefCount++;
return &tkColPtr->color;
}
/*
* The name isn't currently known. Find a pixel value for this
- * color and add a new structure to valueTable.
+ * color and add a new structure to colorValueTable (in TkDisplay).
*/
tkColPtr = TkpGetColorByValue(tkwin, colorPtr);
@@ -244,9 +333,11 @@ Tk_GetColorByValue(tkwin, colorPtr)
tkColPtr->screen = Tk_Screen(tkwin);
tkColPtr->colormap = valueKey.colormap;
tkColPtr->visual = Tk_Visual(tkwin);
- tkColPtr->refCount = 1;
- tkColPtr->tablePtr = &valueTable;
+ tkColPtr->resourceRefCount = 1;
+ tkColPtr->objRefCount = 0;
+ tkColPtr->type = TK_COLOR_BY_VALUE;
tkColPtr->hashPtr = valueHashPtr;
+ tkColPtr->nextPtr = NULL;
tkColPtr->gcList = NULL;
Tcl_SetHashValue(valueHashPtr, tkColPtr);
return &tkColPtr->color;
@@ -279,15 +370,17 @@ Tk_NameOfColor(colorPtr)
XColor *colorPtr; /* Color whose name is desired. */
{
register TkColor *tkColPtr = (TkColor *) colorPtr;
- static char string[20];
-
- if ((tkColPtr->magic == COLOR_MAGIC)
- && (tkColPtr->tablePtr == &nameTable)) {
- return ((NameKey *) tkColPtr->hashPtr->key.words)->name;
+
+ if ((tkColPtr->magic == COLOR_MAGIC) &&
+ (tkColPtr->type == TK_COLOR_BY_NAME)) {
+ return tkColPtr->hashPtr->key.string;
+ } else {
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red,
+ colorPtr->green, colorPtr->blue);
+ return tsdPtr->rgbString;
}
- sprintf(string, "#%04x%04x%04x", colorPtr->red, colorPtr->green,
- colorPtr->blue);
- return string;
}
/*
@@ -314,8 +407,7 @@ Tk_NameOfColor(colorPtr)
GC
Tk_GCForColor(colorPtr, drawable)
XColor *colorPtr; /* Color for which a GC is desired. Must
- * have been allocated by Tk_GetColor or
- * Tk_GetColorByName. */
+ * have been allocated by Tk_GetColor. */
Drawable drawable; /* Drawable in which the color will be
* used (must have same screen and depth
* as the one for which the color was
@@ -366,8 +458,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
@@ -378,15 +471,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);
}
}
@@ -394,131 +517,300 @@ Tk_FreeColor(colorPtr)
/*
*----------------------------------------------------------------------
*
- * ColorInit --
+ * Tk_FreeColorFromObj --
*
- * Initialize the structure used for color management.
+ * 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:
- * Read the code.
+ * 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.
*
*----------------------------------------------------------------------
*/
-static void
-ColorInit()
+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. */
{
- initialized = 1;
- Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
- Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int));
+ Tk_FreeColor(Tk_GetColorFromObj(tkwin, objPtr));
+ FreeColorObjProc(objPtr);
}
-/* CYGNUS LOCAL: Call a function on every named color. This is used
- on Windows to change the colors when the user changes them via the
- control panel. */
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *---------------------------------------------------------------------------
+ */
-void
-TkMapOverColors(func)
- void (*func) _ANSI_ARGS_((TkColor *));
+static void
+FreeColorObjProc(objPtr)
+ Tcl_Obj *objPtr; /* The object we are releasing. */
{
- Tcl_HashEntry *nameHashPtr;
- Tcl_HashSearch search;
- TkColor *tkColPtr;
+ TkColor *tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1;
- nameHashPtr = Tcl_FirstHashEntry(&nameTable, &search);
- while (nameHashPtr != NULL) {
- tkColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr);
- (*func)(tkColPtr);
- nameHashPtr = Tcl_NextHashEntry(&search);
+ 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.
+ *
+ *---------------------------------------------------------------------------
+ */
-/* CYGNUS LOCAL: For each color, we keep a list of GCs that use that
- color as the foreground or background. This is so that we can
- change them on Windows when the user changes the system colors. */
-
-void
-TkRegisterColorGC(colorPtr, display, gc, valueMask)
- XColor *colorPtr;
- Display *display;
- GC gc;
- unsigned long valueMask;
+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 *) colorPtr;
- TkGCList *gcListPtr;
+ TkColor *tkColPtr = (TkColor *) srcObjPtr->internalRep.twoPtrValue.ptr1;
+
+ dupObjPtr->typePtr = srcObjPtr->typePtr;
+ dupObjPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr;
- if (tkColPtr->magic != COLOR_MAGIC) {
- return;
+ if (tkColPtr != NULL) {
+ tkColPtr->objRefCount++;
}
-
- gcListPtr = (TkGCList *) ckalloc(sizeof(TkGCList));
- gcListPtr->display = display;
- gcListPtr->gc = gc;
- gcListPtr->mask = valueMask;
- gcListPtr->next = tkColPtr->gcList;
- tkColPtr->gcList = gcListPtr;
-
- /* Each GC added to the list counts as a reference to the color,
- so that we don't free the color before freeing the GC. */
-
- tkColPtr->refCount++;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
+ */
-/* This is called when a GC with a registered color is deleted. */
-
-void
-TkDeregisterColorGC(colorPtr, gc, valueMask)
- XColor *colorPtr;
- GC gc;
- unsigned long valueMask;
+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 = (TkColor *) colorPtr;
- TkGCList **gcListPtrPtr, *gcListPtr;
+ TkColor *tkColPtr;
+ Tcl_HashEntry *hashPtr;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (tkColPtr->magic != COLOR_MAGIC) {
- return;
+ if (objPtr->typePtr != &colorObjType) {
+ InitColorObj(objPtr);
+ }
+
+ /*
+ * First check to see if the internal representation of the object
+ * is defined and is a color that is valid for the current screen
+ * and color map. If it is, we are done.
+ */
+ tkColPtr = (TkColor *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((tkColPtr != NULL)
+ && (tkColPtr->resourceRefCount > 0)
+ && (Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ /*
+ * The object already points to the right TkColor structure.
+ * Just return it.
+ */
+
+ return (XColor *) tkColPtr;
}
- for (gcListPtrPtr = &tkColPtr->gcList;
- *gcListPtrPtr != NULL;
- gcListPtrPtr = &(*gcListPtrPtr)->next) {
- if ((*gcListPtrPtr)->gc == gc && (*gcListPtrPtr)->mask == valueMask) {
- gcListPtr = *gcListPtrPtr;
- *gcListPtrPtr = gcListPtr->next;
- ckfree((char *) gcListPtr);
- Tk_FreeColor((XColor *) tkColPtr);
- break;
+ /*
+ * If we reach this point, it means that the TkColor structure
+ * that we have cached in the internal representation is not valid
+ * for the current screen and colormap. But there is a list of
+ * other TkColor structures attached to the TkDisplay. Walk this
+ * list looking for the right TkColor structure.
+ */
+
+ hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable,
+ Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ for (tkColPtr = (TkColor *) Tcl_GetHashValue(hashPtr);
+ (tkColPtr != NULL); tkColPtr = tkColPtr->nextPtr) {
+ if ((Tk_Screen(tkwin) == tkColPtr->screen)
+ && (Tk_Colormap(tkwin) == tkColPtr->colormap)) {
+ FreeColorObjProc(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = (VOID *) tkColPtr;
+ tkColPtr->objRefCount++;
+ return (XColor *) tkColPtr;
}
}
-}
-/* This is called when a color is changed by the user on Windows. */
+ 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).
+ *
+ *----------------------------------------------------------------------
+ */
-void
-TkColorChanged(tkColPtr)
- TkColor *tkColPtr;
+static void
+InitColorObj(objPtr)
+ Tcl_Obj *objPtr; /* The object to convert. */
{
- TkGCList *gcListPtr;
- XGCValues gcValues;
+ Tcl_ObjType *typePtr;
- for (gcListPtr = tkColPtr->gcList;
- gcListPtr != NULL;
- gcListPtr = gcListPtr->next) {
- if (gcListPtr->mask == GCForeground) {
- gcValues.foreground = tkColPtr->color.pixel;
- } else {
- gcValues.background = tkColPtr->color.pixel;
- }
+ /*
+ * Free the old internalRep before setting the new one.
+ */
- XChangeGC(gcListPtr->display, gcListPtr->gc, gcListPtr->mask,
- &gcValues);
+ 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.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Read the code.
+ *
+ *----------------------------------------------------------------------
+ */
- if (tkColPtr->gc != None) {
- gcValues.foreground = tkColPtr->color.pixel;
- XChangeGC(DisplayOfScreen(tkColPtr->screen), tkColPtr->gc,
- GCForeground, &gcValues);
+static void
+ColorInit(dispPtr)
+ TkDisplay *dispPtr;
+{
+ if (!dispPtr->colorInit) {
+ dispPtr->colorInit = 1;
+ Tcl_InitHashTable(&dispPtr->colorNameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->colorValueTable,
+ 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, 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/tk/generic/tkColor.h b/tk/generic/tkColor.h
index 8a72d7eb9e3..2f38ac4db65 100644
--- a/tk/generic/tkColor.h
+++ b/tk/generic/tkColor.h
@@ -4,7 +4,7 @@
* 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.
@@ -23,14 +23,31 @@
#endif
/* CYGNUS LOCAL. */
-typedef struct TkGCList TkGCList;
+
+/* A linked list of GC structures. */
+
+typedef struct TkGCList {
+ /* Next item on list. */
+ struct TkGCList *next;
+ /* The display for the GC. */
+ Display *display;
+ /* The GC. */
+ GC gc;
+ /* GCForeground or GCBackground. */
+ unsigned long mask;
+} TkGCList;
+
+/* END CYGNUS LOCAL */
/*
* 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 TK_COLOR_BY_NAME 1
+#define TK_COLOR_BY_VALUE 2
+
#define COLOR_MAGIC ((unsigned int) 0x46140277)
typedef struct TkColor {
@@ -46,11 +63,29 @@ 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. */
- Tcl_HashTable *tablePtr; /* Hash table that indexes this structure
- * (needed when deleting 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. */
+ int type; /* TK_COLOR_BY_NAME or TK_COLOR_BY_VALUE */
Tcl_HashEntry *hashPtr; /* Pointer to hash table entry for this
* structure. (for use in deleting entry). */
+ struct TkColor *nextPtr; /* Points to the next TkColor structure with
+ * the same color name. Colors with the
+ * same name but different screens or
+ * colormaps are chained together off a
+ * single entry in nameTable. For colors in
+ * valueTable (those allocated by
+ * Tk_GetColorByValue) this field is always
+ * NULL. */
/* CYGNUS LOCAL */
TkGCList *gcList; /* List of GCs which use this color. */
} TkColor;
@@ -75,3 +110,4 @@ EXTERN void TkColorChanged _ANSI_ARGS_((TkColor *));
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKCOLOR */
+
diff --git a/tk/generic/tkConfig.c b/tk/generic/tkConfig.c
index 4efac5e9089..f12893607c7 100644
--- a/tk/generic/tkConfig.c
+++ b/tk/generic/tkConfig.c
@@ -1,10 +1,10 @@
/*
* 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.
@@ -12,568 +12,1625 @@
* RCS: @(#) $Id$
*/
-#include "tkPort.h"
+/*
+ * Temporary flag for working on new config package.
+ */
+
+#if 0
+
+/*
+ * used only for removing the old config code
+ */
+
+#define __NO_OLD_CONFIG
+#endif
+
#include "tk.h"
+#include "tkInt.h"
+#include "tkPort.h"
+#include "tkFont.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!
+ * The following definition is an AssocData key used to keep track of
+ * all of the option tables that have been created for an interpreter.
+ */
+
+#define OPTION_HASH_KEY "TkOptionTable"
+
+/*
+ * The following two structures are used along with Tk_OptionSpec
+ * structures to manage configuration options. Tk_OptionSpec is
+ * static templates that are compiled into the code of a widget
+ * or other object manager. However, to look up options efficiently
+ * we need to supplement the static information with additional
+ * dynamic information, and this dynamic information may be different
+ * for each application. Thus we create structures of the following
+ * two types to hold all of the dynamic information; this is done
+ * by Tk_CreateOptionTable.
+ *
+ * One of the following structures corresponds to each Tk_OptionSpec.
+ * These structures exist as arrays inside TkOptionTable structures.
+ */
+
+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);
}
/*
- * 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.
+ * See if a table has already been created for this template. If
+ * so, just reuse the existing table.
*/
- for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
- if (!(specPtr->specFlags & INIT) && (specPtr->argvName != NULL)) {
+ 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;
+
+ /*
+ * Initialize all of the Option structures in the table.
+ */
+
+ 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 we specify TK_OPTION_DONT_SET_DEFAULT, then the user has
+ * processed and set a default for this already.
+ */
+ if ((optionPtr->specPtr->type == TK_OPTION_SYNONYM) ||
+ (optionPtr->specPtr->flags & TK_OPTION_DONT_SET_DEFAULT)) {
+ continue;
+ }
+ 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;
}
- if (specPtr->argvName[length] == 0) {
- matchPtr = specPtr;
- goto gotMatch;
+ 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 (matchPtr != NULL) {
- Tcl_AppendResult(interp, "ambiguous option \"", argvName,
- "\"", (char *) NULL);
- return (Tk_ConfigSpec *) NULL;
+ 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;
}
- matchPtr = specPtr;
- }
+ case TK_OPTION_COLOR: {
+ XColor *newPtr;
- if (matchPtr == NULL) {
- Tcl_AppendResult(interp, "unknown option \"", argvName,
- "\"", (char *) NULL);
- return (Tk_ConfigSpec *) NULL;
+ 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;
+ }
+ case TK_OPTION_FONT: {
+ Tk_Font new;
+
+ 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: {
+ char buf[40+TCL_INTEGER_SPACE];
+ sprintf(buf, "bad config table: unknown type %d",
+ optionPtr->specPtr->type);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ 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 +1638,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 +1679,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;
- }
- if (((specPtr->specFlags & needFlags) != needFlags)
- || (specPtr->specFlags & hateFlags)) {
- 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->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 +1708,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 +1787,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));
- break;
- case TK_CONFIG_ANCHOR:
- result = Tk_NameOfAnchor(*((Tk_Anchor *) ptr));
+ case TK_OPTION_JUSTIFY: {
+ objPtr = Tcl_NewStringObj(Tk_NameOfJustify(
+ *((Tk_Justify *) internalPtr)), -1);
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");
+ }
}
- return result;
+ if (objPtr == NULL) {
+ objPtr = Tcl_NewObj();
+ }
+ 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 +1918,115 @@ 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/tk/generic/tkConsole.c b/tk/generic/tkConsole.c
index 2294368e1ca..69b113b13ba 100644
--- a/tk/generic/tkConsole.c
+++ b/tk/generic/tkConsole.c
@@ -16,6 +16,8 @@
#include "tk.h"
#include <string.h>
+#include "tkInt.h"
+
/*
* A data structure of the following type holds information for each console
* which a handler (i.e. a Tcl command) has been defined for a particular
@@ -27,7 +29,17 @@ typedef struct ConsoleInfo {
Tcl_Interp *interp; /* Interpreter to send console commands. */
} ConsoleInfo;
-static Tcl_Interp *gStdoutInterp = NULL;
+typedef struct ThreadSpecificData {
+ Tcl_Interp *gStdoutInterp;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+static int consoleInitialized = 0;
+
+/*
+ * The Mutex below is used to lock access to the consoleIntialized flag
+ */
+
+TCL_DECLARE_MUTEX(consoleMutex)
/*
* Forward declarations for procedures defined later in this file:
@@ -35,8 +47,6 @@ static Tcl_Interp *gStdoutInterp = NULL;
* The first three will be used in the tk app shells...
*/
-void TkConsoleCreate _ANSI_ARGS_((void));
-int TkConsoleInit _ANSI_ARGS_((Tcl_Interp *interp));
void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp,
int devId, char *buffer, long size));
@@ -75,11 +85,111 @@ static Tcl_ChannelType consoleChannelType = {
ConsoleWatch, /* Watch for events on console. */
ConsoleHandle, /* Get a handle from the device. */
};
+
+
+#ifdef __WIN32__
+
+#include <windows.h>
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ShouldUseConsoleChannel
+ *
+ * Check to see if console window should be used for a given
+ * standard channel
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates the console channel and installs it as the standard
+ * channels.
+ *
+ *----------------------------------------------------------------------
+ */
+static int ShouldUseConsoleChannel(type)
+ int type;
+{
+ DWORD handleId; /* Standard handle to retrieve. */
+ DCB dcb;
+ DWORD consoleParams;
+ DWORD fileType;
+ int mode;
+ char *bufMode;
+ HANDLE handle;
+
+ switch (type) {
+ case TCL_STDIN:
+ handleId = STD_INPUT_HANDLE;
+ mode = TCL_READABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDOUT:
+ handleId = STD_OUTPUT_HANDLE;
+ mode = TCL_WRITABLE;
+ bufMode = "line";
+ break;
+ case TCL_STDERR:
+ handleId = STD_ERROR_HANDLE;
+ mode = TCL_WRITABLE;
+ bufMode = "none";
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ handle = GetStdHandle(handleId);
+
+ /*
+ * Note that we need to check for 0 because Windows will return 0 if this
+ * is not a console mode application, even though this is not a valid
+ * handle.
+ */
+
+ if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) {
+ return 1;
+ }
+ fileType = GetFileType(handle);
+
+ /*
+ * If the file is a character device, we need to try to figure out
+ * whether it is a serial port, a console, or something else. We
+ * test for the console case first because this is more common.
+ */
+
+ if (fileType == FILE_TYPE_CHAR) {
+ dcb.DCBlength = sizeof( DCB ) ;
+ if (!GetConsoleMode(handle, &consoleParams) &&
+ !GetCommState(handle, &dcb)) {
+ /*
+ * Don't use a CHAR type channel for stdio, otherwise Tk
+ * runs into trouble with the MS DevStudio debugger.
+ */
+
+ return 1;
+ }
+ } else if (fileType == FILE_TYPE_UNKNOWN) {
+ return 1;
+ } else if (Tcl_GetStdChannel(type) == NULL) {
+ return 1;
+ }
+
+ return 0;
+}
+#else
+/*
+ * Mac should always use a console channel, Unix should if it's trying to
+ */
+
+#define ShouldUseConsoleChannel(chan) (1)
+#endif
/*
*----------------------------------------------------------------------
*
- * TkConsoleCreate --
+ * Tk_InitConsoleChannels --
*
* Create the console channels and install them as the standard
* channels. All I/O will be discarded until TkConsoleInit is
@@ -96,37 +206,95 @@ static Tcl_ChannelType consoleChannelType = {
*/
void
-TkConsoleCreate()
+Tk_InitConsoleChannels(interp)
+ Tcl_Interp *interp;
{
Tcl_Channel consoleChannel;
- 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_SetStdChannel(consoleChannel, TCL_STDIN);
- consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
- (ClientData) TCL_STDOUT, TCL_WRITABLE);
- if (consoleChannel != NULL) {
- Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
- Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+ /*
+ * Ensure that we are getting the matching version of Tcl. This is
+ * really only an issue when Tk is loaded dynamically.
+ */
+
+ if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ return;
}
- Tcl_SetStdChannel(consoleChannel, TCL_STDOUT);
- consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
- (ClientData) TCL_STDERR, TCL_WRITABLE);
- if (consoleChannel != NULL) {
- Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
- Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
+
+ Tcl_MutexLock(&consoleMutex);
+ if (!consoleInitialized) {
+
+ consoleInitialized = 1;
+
+ /*
+ * check for STDIN, otherwise create it
+ *
+ * Don't do this check on the Mac, because it is hard to prevent
+ * callbacks from the SIOUX layer from opening stdout & stdin, but
+ * we don't want to use the SIOUX console. Since the console is not
+ * actually created till something is written to the channel, it is
+ * okay to just ignore it here.
+ *
+ * This is still a bit of a hack, however, and should be cleaned up
+ * when we have a better abstraction for the console.
+ */
+
+ if (ShouldUseConsoleChannel(TCL_STDIN)) {
+ 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);
+ }
+
+ /*
+ * check for STDOUT, otherwise create it
+ */
+
+ if (ShouldUseConsoleChannel(TCL_STDOUT)) {
+ consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
+ (ClientData) TCL_STDOUT, TCL_WRITABLE);
+ 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);
+ }
+
+ /*
+ * check for STDERR, otherwise create it
+ */
+
+ if (ShouldUseConsoleChannel(TCL_STDERR)) {
+ consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
+ (ClientData) TCL_STDERR, TCL_WRITABLE);
+ 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);
+ }
}
- Tcl_SetStdChannel(consoleChannel, TCL_STDERR);
+ Tcl_MutexUnlock(&consoleMutex);
}
/*
*----------------------------------------------------------------------
*
- * TkConsoleInit --
+ * Tk_CreateConsoleWindow --
*
* Initialize the console. This code actually creates a new
* application and associated interpreter. This effectivly hides
@@ -142,12 +310,14 @@ TkConsoleCreate()
*/
int
-TkConsoleInit(interp)
+Tk_CreateConsoleWindow(interp)
Tcl_Interp *interp; /* Interpreter to use for prompting. */
{
Tcl_Interp *consoleInterp;
ConsoleInfo *info;
Tk_Window mainWindow = Tk_MainWindow(interp);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
#ifdef MAC_TCL
static char initCmd[] = "source -rsrc {Console}";
#else
@@ -169,7 +339,7 @@ TkConsoleInit(interp)
if (Tk_Init(consoleInterp) != TCL_OK) {
goto error;
}
- gStdoutInterp = interp;
+ tsdPtr->gStdoutInterp = interp;
/*
* Add console commands to the interp
@@ -225,11 +395,15 @@ ConsoleOutput(instanceData, buf, toWrite, errorCode)
int toWrite; /* How many bytes to write? */
int *errorCode; /* Where to store error code. */
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
*errorCode = 0;
Tcl_SetErrno(0);
- if (gStdoutInterp != NULL) {
- TkConsolePrint(gStdoutInterp, (int) instanceData, buf, toWrite);
+ if (tsdPtr->gStdoutInterp != NULL) {
+ TkConsolePrint(tsdPtr->gStdoutInterp, (int) instanceData, buf,
+ toWrite);
}
return toWrite;
@@ -373,9 +547,10 @@ ConsoleCmd(clientData, interp, argc, argv)
{
ConsoleInfo *info = (ConsoleInfo *) clientData;
char c;
- int length;
+ size_t length;
int result;
Tcl_Interp *consoleInterp;
+ Tcl_DString dString;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
@@ -388,23 +563,25 @@ ConsoleCmd(clientData, interp, argc, argv)
result = TCL_OK;
consoleInterp = info->consoleInterp;
Tcl_Preserve((ClientData) consoleInterp);
+ Tcl_DStringInit(&dString);
+
if ((c == 't') && (strncmp(argv[1], "title", length)) == 0) {
- Tcl_DString dString;
-
- Tcl_DStringInit(&dString);
Tcl_DStringAppend(&dString, "wm title . ", -1);
if (argc == 3) {
Tcl_DStringAppendElement(&dString, argv[2]);
}
Tcl_Eval(consoleInterp, Tcl_DStringValue(&dString));
- Tcl_DStringFree(&dString);
} else if ((c == 'h') && (strncmp(argv[1], "hide", length)) == 0) {
- Tcl_Eval(info->consoleInterp, "wm withdraw .");
+ Tcl_DStringAppend(&dString, "wm withdraw . ", -1);
+ Tcl_Eval(consoleInterp, Tcl_DStringValue(&dString));
} else if ((c == 's') && (strncmp(argv[1], "show", length)) == 0) {
- Tcl_Eval(info->consoleInterp, "wm deiconify .");
+ Tcl_DStringAppend(&dString, "wm deiconify . ", -1);
+ Tcl_Eval(consoleInterp, Tcl_DStringValue(&dString));
} else if ((c == 'e') && (strncmp(argv[1], "eval", length)) == 0) {
if (argc == 3) {
- Tcl_Eval(info->consoleInterp, argv[2]);
+ result = Tcl_Eval(consoleInterp, argv[2]);
+ Tcl_AppendResult(interp, Tcl_GetStringResult(consoleInterp),
+ (char *) NULL);
} else {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" eval command\"", (char *) NULL);
@@ -416,6 +593,7 @@ ConsoleCmd(clientData, interp, argc, argv)
(char *) NULL);
result = TCL_ERROR;
}
+ Tcl_DStringFree(&dString);
Tcl_Release((ClientData) consoleInterp);
return result;
}
@@ -446,7 +624,7 @@ InterpreterCmd(clientData, interp, argc, argv)
{
ConsoleInfo *info = (ConsoleInfo *) clientData;
char c;
- int length;
+ size_t length;
int result;
Tcl_Interp *otherInterp;
@@ -466,6 +644,7 @@ InterpreterCmd(clientData, interp, argc, argv)
} else if ((c == 'r') && (strncmp(argv[1], "record", length)) == 0) {
Tcl_RecordAndEval(otherInterp, argv[2], TCL_EVAL_GLOBAL);
result = TCL_OK;
+ Tcl_ResetResult(interp);
Tcl_AppendResult(interp, otherInterp->result, (char *) NULL);
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
@@ -494,7 +673,7 @@ InterpreterCmd(clientData, interp, argc, argv)
*----------------------------------------------------------------------
*/
-void
+static void
ConsoleDeleteProc(clientData)
ClientData clientData;
{
@@ -530,9 +709,13 @@ ConsoleEventProc(clientData, eventPtr)
{
ConsoleInfo *info = (ConsoleInfo *) clientData;
Tcl_Interp *consoleInterp;
+ Tcl_DString dString;
if (eventPtr->type == DestroyNotify) {
- consoleInterp = info->consoleInterp;
+
+ Tcl_DStringInit(&dString);
+
+ consoleInterp = info->consoleInterp;
/*
* It is possible that the console interpreter itself has
@@ -545,7 +728,9 @@ ConsoleEventProc(clientData, eventPtr)
return;
}
Tcl_Preserve((ClientData) consoleInterp);
- Tcl_Eval(consoleInterp, "tkConsoleExit");
+ Tcl_DStringAppend(&dString, "tkConsoleExit", -1);
+ Tcl_Eval(consoleInterp, Tcl_DStringValue(&dString));
+ Tcl_DStringFree(&dString);
Tcl_Release((ClientData) consoleInterp);
}
}
@@ -603,7 +788,7 @@ TkConsolePrint(interp, devId, buffer, size)
Tcl_DStringAppend(&output, buffer, size);
Tcl_DStringInit(&command);
- Tcl_DStringAppend(&command, cmd, strlen(cmd));
+ Tcl_DStringAppend(&command, cmd, (int) strlen(cmd));
Tcl_DStringAppendElement(&command, output.string);
consoleInterp = info->consoleInterp;
@@ -614,3 +799,4 @@ TkConsolePrint(interp, devId, buffer, size)
Tcl_DStringFree(&command);
Tcl_DStringFree(&output);
}
+
diff --git a/tk/generic/tkCursor.c b/tk/generic/tkCursor.c
index 31d2d1ca736..6782550b3ba 100644
--- a/tk/generic/tkCursor.c
+++ b/tk/generic/tkCursor.c
@@ -6,7 +6,7 @@
* 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.
@@ -20,28 +20,11 @@
/*
* A TkCursor structure exists for each cursor that is currently
* active. Each structure is indexed with two hash tables defined
- * below. One of the tables is idTable, and the other is either
- * nameTable or dataTable, also defined below.
+ * below. One of the tables is cursorIdTable, and the other is either
+ * cursorNameTable or cursorDataTable, each of which are stored in the
+ * TkDisplay structure for the current thread.
*/
-/*
- * 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:
- */
-
-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
- * cursor (bitmap contents, etc.) to a TkCursor structure:
- */
-
-static Tcl_HashTable dataTable;
typedef struct {
char *source; /* Cursor bits. */
char *mask; /* Mask bits. */
@@ -53,24 +36,129 @@ typedef struct {
} DataKey;
/*
- * Hash table that maps from <display + cursor id> to the TkCursor structure
- * for the cursor. This table is used by Tk_FreeCursor.
+ * Forward declarations for procedures defined in this file:
*/
-static Tcl_HashTable idTable;
-typedef struct {
- Display *display; /* Display for which cursor was allocated. */
- Tk_Cursor cursor; /* Cursor identifier. */
-} IdKey;
+static void CursorInit _ANSI_ARGS_((TkDisplay *dispPtr));
+static void DupCursorObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr,
+ Tcl_Obj *dupObjPtr));
+static void FreeCursor _ANSI_ARGS_((TkCursor *cursorPtr));
+static void FreeCursorObjProc _ANSI_ARGS_((Tcl_Obj *objPtr));
+static TkCursor * 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));
-static int initialized = 0; /* 0 means static structures haven't been
- * initialized yet. */
+/*
+ * 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 */
+};
+
/*
- * Forward declarations for procedures defined in this file:
+ *----------------------------------------------------------------------
+ *
+ * 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.
+ *
+ *----------------------------------------------------------------------
*/
-static void CursorInit _ANSI_ARGS_((void));
+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 +171,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 +189,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. */
{
- NameKey nameKey;
- IdKey idKey;
- Tcl_HashEntry *nameHashPtr, *idHashPtr;
+ 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. */
+{
+ Tcl_HashEntry *nameHashPtr;
register TkCursor *cursorPtr;
+ TkCursor *existingCursorPtr = NULL;
int new;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- CursorInit();
+ if (!dispPtr->cursorInit) {
+ CursorInit(dispPtr);
}
- nameKey.name = string;
- nameKey.display = Tk_Display(tkwin);
- nameHashPtr = Tcl_CreateHashEntry(&nameTable, (char *) &nameKey, &new);
+ nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable,
+ 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->otherTable = &nameTable;
+ cursorPtr->display = Tk_Display(tkwin);
+ cursorPtr->resourceRefCount = 1;
+ cursorPtr->objRefCount = 0;
+ cursorPtr->otherTable = &dispPtr->cursorNameTable;
cursorPtr->hashPtr = nameHashPtr;
- idKey.display = nameKey.display;
- idKey.cursor = cursorPtr->cursor;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
+ cursorPtr->nextPtr = NULL;
+ cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable,
+ (char *) cursorPtr->cursor, &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 +300,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.
@@ -187,14 +327,15 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
Tk_Uid bg; /* Background color for cursor. */
{
DataKey dataKey;
- IdKey idKey;
- Tcl_HashEntry *dataHashPtr, *idHashPtr;
+ Tcl_HashEntry *dataHashPtr;
register TkCursor *cursorPtr;
int new;
XColor fgColor, bgColor;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- CursorInit();
+
+ if (!dispPtr->cursorInit) {
+ CursorInit(dispPtr);
}
dataKey.source = source;
@@ -206,10 +347,11 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
dataKey.fg = fg;
dataKey.bg = bg;
dataKey.display = Tk_Display(tkwin);
- dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &dataKey, &new);
+ dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable,
+ (char *) &dataKey, &new);
if (!new) {
cursorPtr = (TkCursor *) Tcl_GetHashValue(dataHashPtr);
- cursorPtr->refCount++;
+ cursorPtr->resourceRefCount++;
return cursorPtr->cursor;
}
@@ -236,17 +378,18 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height,
goto error;
}
- cursorPtr->refCount = 1;
- cursorPtr->otherTable = &dataTable;
+ cursorPtr->resourceRefCount = 1;
+ cursorPtr->otherTable = &dispPtr->cursorDataTable;
cursorPtr->hashPtr = dataHashPtr;
- idKey.display = dataKey.display;
- idKey.cursor = cursorPtr->cursor;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
+ cursorPtr->objRefCount = 0;
+ cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable,
+ (char *) cursorPtr->cursor, &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:
@@ -281,27 +424,77 @@ Tk_NameOfCursor(display, cursor)
Tk_Cursor cursor; /* Identifier for cursor whose name is
* wanted. */
{
- IdKey idKey;
Tcl_HashEntry *idHashPtr;
TkCursor *cursorPtr;
- static char string[20];
+ TkDisplay *dispPtr;
- if (!initialized) {
+ dispPtr = TkGetDisplay(display);
+
+ if (!dispPtr->cursorInit) {
printid:
- sprintf(string, "cursor id 0x%x", (unsigned int) cursor);
- return string;
+ sprintf(dispPtr->cursorString, "cursor id 0x%x",
+ (unsigned int) cursor);
+ return dispPtr->cursorString;
}
- idKey.display = display;
- idKey.cursor = cursor;
- idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor);
if (idHashPtr == NULL) {
goto printid;
}
cursorPtr = (TkCursor *) Tcl_GetHashValue(idHashPtr);
- if (cursorPtr->otherTable != &nameTable) {
+ if (cursorPtr->otherTable != &dispPtr->cursorNameTable) {
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);
+ }
}
/*
@@ -327,27 +520,258 @@ Tk_FreeCursor(display, cursor)
Display *display; /* Display for which cursor was allocated. */
Tk_Cursor cursor; /* Identifier for cursor to be released. */
{
- IdKey idKey;
Tcl_HashEntry *idHashPtr;
- register TkCursor *cursorPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
- if (!initialized) {
+ if (!dispPtr->cursorInit) {
panic("Tk_FreeCursor called before Tk_GetCursor");
}
- idKey.display = display;
- idKey.cursor = cursor;
- idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) 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));
+ FreeCursorObjProc(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);
+ /* GetCursorFromObj should never return NULL */
+ 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ if (objPtr->typePtr != &cursorObjType) {
+ InitCursorObj(objPtr);
+ }
+
+ /*
+ * The internal representation is a cache of the last cursor used
+ * with the given name. But there can be lots different cursors
+ * for each cursor name; one cursor for each display. Check to
+ * see if the cursor we have cached is the one that is needed.
+ */
+ cursorPtr = (TkCursor *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((cursorPtr != NULL) && (Tk_Display(tkwin) == cursorPtr->display)) {
+ return cursorPtr;
+ }
+
+ /*
+ * If we get to here, it means the cursor we need is not in the cache.
+ * Try to look up the cursor in the TkDisplay structure of the window.
+ */
+
+ hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable,
+ Tcl_GetString(objPtr));
+ if (hashPtr == NULL) {
+ goto error;
+ }
+ for (cursorPtr = (TkCursor *) Tcl_GetHashValue(hashPtr);
+ cursorPtr != NULL; cursorPtr = cursorPtr->nextPtr) {
+ if (Tk_Display(tkwin) == cursorPtr->display) {
+ FreeCursorObjProc(objPtr);
+ 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;
}
/*
@@ -367,11 +791,11 @@ Tk_FreeCursor(display, cursor)
*/
static void
-CursorInit()
+CursorInit(dispPtr)
+ TkDisplay *dispPtr; /* Display used to store thread-specific data. */
{
- initialized = 1;
- Tcl_InitHashTable(&nameTable, sizeof(NameKey)/sizeof(int));
- Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int));
+ Tcl_InitHashTable(&dispPtr->cursorNameTable, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&dispPtr->cursorDataTable, sizeof(DataKey)/sizeof(int));
/*
* The call below is tricky: can't use sizeof(IdKey) because it
@@ -379,6 +803,68 @@ CursorInit()
* machines.
*/
- Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Tk_Cursor))
- /sizeof(int));
+ /*
+ * Old code....
+ * Tcl_InitHashTable(&dispPtr->cursorIdTable, sizeof(Display *)
+ * /sizeof(int));
+ *
+ * The comment above doesn't make sense.
+ * However, XIDs should only be 32 bits, by the definition of X,
+ * so the code above causes Tk to crash. Here is the real code:
+ */
+
+ Tcl_InitHashTable(&dispPtr->cursorIdTable, TCL_ONE_WORD_KEYS);
+
+ dispPtr->cursorInit = 1;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
+
+ resultPtr = Tcl_NewObj();
+ hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable, 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/tk/generic/tkDecls.h b/tk/generic/tkDecls.h
new file mode 100644
index 00000000000..c60345ad2f7
--- /dev/null
+++ b/tk/generic/tkDecls.h
@@ -0,0 +1,2050 @@
+/*
+ * tkDecls.h --
+ *
+ * Declarations of functions in the platform independent public Tcl API.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifndef _TKDECLS
+#define _TKDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tk.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+EXTERN void Tk_MainLoop _ANSI_ARGS_((void));
+/* 1 */
+EXTERN XColor * Tk_3DBorderColor _ANSI_ARGS_((Tk_3DBorder border));
+/* 2 */
+EXTERN GC Tk_3DBorderGC _ANSI_ARGS_((Tk_Window tkwin,
+ Tk_3DBorder border, int which));
+/* 3 */
+EXTERN void Tk_3DHorizontalBevel _ANSI_ARGS_((Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int leftIn,
+ int rightIn, int topBevel, int relief));
+/* 4 */
+EXTERN void Tk_3DVerticalBevel _ANSI_ARGS_((Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height, int leftBevel,
+ int relief));
+/* 5 */
+EXTERN void Tk_AddOption _ANSI_ARGS_((Tk_Window tkwin,
+ char * name, char * value, int priority));
+/* 6 */
+EXTERN void Tk_BindEvent _ANSI_ARGS_((
+ Tk_BindingTable bindingTable,
+ XEvent * eventPtr, Tk_Window tkwin,
+ int numObjects, ClientData * objectPtr));
+/* 7 */
+EXTERN void Tk_CanvasDrawableCoords _ANSI_ARGS_((
+ Tk_Canvas canvas, double x, double y,
+ short * drawableXPtr, short * drawableYPtr));
+/* 8 */
+EXTERN void Tk_CanvasEventuallyRedraw _ANSI_ARGS_((
+ Tk_Canvas canvas, int x1, int y1, int x2,
+ int y2));
+/* 9 */
+EXTERN int Tk_CanvasGetCoord _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Canvas canvas, char * str,
+ double * doublePtr));
+/* 10 */
+EXTERN Tk_CanvasTextInfo * Tk_CanvasGetTextInfo _ANSI_ARGS_((
+ Tk_Canvas canvas));
+/* 11 */
+EXTERN int Tk_CanvasPsBitmap _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Canvas canvas, Pixmap bitmap, int x,
+ int y, int width, int height));
+/* 12 */
+EXTERN int Tk_CanvasPsColor _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Canvas canvas, XColor * colorPtr));
+/* 13 */
+EXTERN int Tk_CanvasPsFont _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Canvas canvas, Tk_Font font));
+/* 14 */
+EXTERN void Tk_CanvasPsPath _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Canvas canvas, double * coordPtr,
+ int numPoints));
+/* 15 */
+EXTERN int Tk_CanvasPsStipple _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Canvas canvas, Pixmap bitmap));
+/* 16 */
+EXTERN double Tk_CanvasPsY _ANSI_ARGS_((Tk_Canvas canvas, double y));
+/* 17 */
+EXTERN void Tk_CanvasSetStippleOrigin _ANSI_ARGS_((
+ Tk_Canvas canvas, GC gc));
+/* 18 */
+EXTERN int Tk_CanvasTagsParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp * interp,
+ Tk_Window tkwin, char * value,
+ char * widgRec, int offset));
+/* 19 */
+EXTERN char * Tk_CanvasTagsPrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char * widgRec, int offset,
+ Tcl_FreeProc ** freeProcPtr));
+/* 20 */
+EXTERN Tk_Window Tk_CanvasTkwin _ANSI_ARGS_((Tk_Canvas canvas));
+/* 21 */
+EXTERN void Tk_CanvasWindowCoords _ANSI_ARGS_((Tk_Canvas canvas,
+ double x, double y, short * screenXPtr,
+ short * screenYPtr));
+/* 22 */
+EXTERN void Tk_ChangeWindowAttributes _ANSI_ARGS_((
+ Tk_Window tkwin, unsigned long valueMask,
+ XSetWindowAttributes * attsPtr));
+/* 23 */
+EXTERN int Tk_CharBbox _ANSI_ARGS_((Tk_TextLayout layout,
+ int index, int * xPtr, int * yPtr,
+ int * widthPtr, int * heightPtr));
+/* 24 */
+EXTERN void Tk_ClearSelection _ANSI_ARGS_((Tk_Window tkwin,
+ Atom selection));
+/* 25 */
+EXTERN int Tk_ClipboardAppend _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Atom target, Atom format,
+ char* buffer));
+/* 26 */
+EXTERN int Tk_ClipboardClear _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin));
+/* 27 */
+EXTERN int Tk_ConfigureInfo _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_ConfigSpec * specs,
+ char * widgRec, char * argvName, int flags));
+/* 28 */
+EXTERN int Tk_ConfigureValue _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_ConfigSpec * specs,
+ char * widgRec, char * argvName, int flags));
+/* 29 */
+EXTERN int Tk_ConfigureWidget _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_ConfigSpec * specs,
+ int argc, char ** argv, char * widgRec,
+ int flags));
+/* 30 */
+EXTERN void Tk_ConfigureWindow _ANSI_ARGS_((Tk_Window tkwin,
+ unsigned int valueMask,
+ XWindowChanges * valuePtr));
+/* 31 */
+EXTERN Tk_TextLayout Tk_ComputeTextLayout _ANSI_ARGS_((Tk_Font font,
+ CONST char * str, int numChars,
+ int wrapLength, Tk_Justify justify,
+ int flags, int * widthPtr, int * heightPtr));
+/* 32 */
+EXTERN Tk_Window Tk_CoordsToWindow _ANSI_ARGS_((int rootX, int rootY,
+ Tk_Window tkwin));
+/* 33 */
+EXTERN unsigned long Tk_CreateBinding _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, char * eventStr,
+ char * command, int append));
+/* 34 */
+EXTERN Tk_BindingTable Tk_CreateBindingTable _ANSI_ARGS_((
+ Tcl_Interp * interp));
+/* 35 */
+EXTERN Tk_ErrorHandler Tk_CreateErrorHandler _ANSI_ARGS_((Display * display,
+ int errNum, int request, int minorCode,
+ Tk_ErrorProc * errorProc,
+ ClientData clientData));
+/* 36 */
+EXTERN void Tk_CreateEventHandler _ANSI_ARGS_((Tk_Window token,
+ unsigned long mask, Tk_EventProc * proc,
+ ClientData clientData));
+/* 37 */
+EXTERN void Tk_CreateGenericHandler _ANSI_ARGS_((
+ Tk_GenericProc * proc, ClientData clientData));
+/* 38 */
+EXTERN void Tk_CreateImageType _ANSI_ARGS_((
+ Tk_ImageType * typePtr));
+/* 39 */
+EXTERN void Tk_CreateItemType _ANSI_ARGS_((Tk_ItemType * typePtr));
+/* 40 */
+EXTERN void Tk_CreatePhotoImageFormat _ANSI_ARGS_((
+ Tk_PhotoImageFormat * formatPtr));
+/* 41 */
+EXTERN void Tk_CreateSelHandler _ANSI_ARGS_((Tk_Window tkwin,
+ Atom selection, Atom target,
+ Tk_SelectionProc * proc,
+ ClientData clientData, Atom format));
+/* 42 */
+EXTERN Tk_Window Tk_CreateWindow _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window parent, char * name,
+ char * screenName));
+/* 43 */
+EXTERN Tk_Window Tk_CreateWindowFromPath _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ char * pathName, char * screenName));
+/* 44 */
+EXTERN int Tk_DefineBitmap _ANSI_ARGS_((Tcl_Interp * interp,
+ CONST char * name, char * source, int width,
+ int height));
+/* 45 */
+EXTERN void Tk_DefineCursor _ANSI_ARGS_((Tk_Window window,
+ Tk_Cursor cursor));
+/* 46 */
+EXTERN void Tk_DeleteAllBindings _ANSI_ARGS_((
+ Tk_BindingTable bindingTable,
+ ClientData object));
+/* 47 */
+EXTERN int Tk_DeleteBinding _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, char * eventStr));
+/* 48 */
+EXTERN void Tk_DeleteBindingTable _ANSI_ARGS_((
+ Tk_BindingTable bindingTable));
+/* 49 */
+EXTERN void Tk_DeleteErrorHandler _ANSI_ARGS_((
+ Tk_ErrorHandler handler));
+/* 50 */
+EXTERN void Tk_DeleteEventHandler _ANSI_ARGS_((Tk_Window token,
+ unsigned long mask, Tk_EventProc * proc,
+ ClientData clientData));
+/* 51 */
+EXTERN void Tk_DeleteGenericHandler _ANSI_ARGS_((
+ Tk_GenericProc * proc, ClientData clientData));
+/* 52 */
+EXTERN void Tk_DeleteImage _ANSI_ARGS_((Tcl_Interp * interp,
+ char * name));
+/* 53 */
+EXTERN void Tk_DeleteSelHandler _ANSI_ARGS_((Tk_Window tkwin,
+ Atom selection, Atom target));
+/* 54 */
+EXTERN void Tk_DestroyWindow _ANSI_ARGS_((Tk_Window tkwin));
+/* 55 */
+EXTERN char * Tk_DisplayName _ANSI_ARGS_((Tk_Window tkwin));
+/* 56 */
+EXTERN int Tk_DistanceToTextLayout _ANSI_ARGS_((
+ Tk_TextLayout layout, int x, int y));
+/* 57 */
+EXTERN void Tk_Draw3DPolygon _ANSI_ARGS_((Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border,
+ XPoint * pointPtr, int numPoints,
+ int borderWidth, int leftRelief));
+/* 58 */
+EXTERN void Tk_Draw3DRectangle _ANSI_ARGS_((Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height,
+ int borderWidth, int relief));
+/* 59 */
+EXTERN void Tk_DrawChars _ANSI_ARGS_((Display * display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ CONST char * source, int numBytes, int x,
+ int y));
+/* 60 */
+EXTERN void Tk_DrawFocusHighlight _ANSI_ARGS_((Tk_Window tkwin,
+ GC gc, int width, Drawable drawable));
+/* 61 */
+EXTERN void Tk_DrawTextLayout _ANSI_ARGS_((Display * display,
+ Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ int firstChar, int lastChar));
+/* 62 */
+EXTERN void Tk_Fill3DPolygon _ANSI_ARGS_((Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border,
+ XPoint * pointPtr, int numPoints,
+ int borderWidth, int leftRelief));
+/* 63 */
+EXTERN void Tk_Fill3DRectangle _ANSI_ARGS_((Tk_Window tkwin,
+ Drawable drawable, Tk_3DBorder border, int x,
+ int y, int width, int height,
+ int borderWidth, int relief));
+/* 64 */
+EXTERN Tk_PhotoHandle Tk_FindPhoto _ANSI_ARGS_((Tcl_Interp * interp,
+ char * imageName));
+/* 65 */
+EXTERN Font Tk_FontId _ANSI_ARGS_((Tk_Font font));
+/* 66 */
+EXTERN void Tk_Free3DBorder _ANSI_ARGS_((Tk_3DBorder border));
+/* 67 */
+EXTERN void Tk_FreeBitmap _ANSI_ARGS_((Display * display,
+ Pixmap bitmap));
+/* 68 */
+EXTERN void Tk_FreeColor _ANSI_ARGS_((XColor * colorPtr));
+/* 69 */
+EXTERN void Tk_FreeColormap _ANSI_ARGS_((Display * display,
+ Colormap colormap));
+/* 70 */
+EXTERN void Tk_FreeCursor _ANSI_ARGS_((Display * display,
+ Tk_Cursor cursor));
+/* 71 */
+EXTERN void Tk_FreeFont _ANSI_ARGS_((Tk_Font f));
+/* 72 */
+EXTERN void Tk_FreeGC _ANSI_ARGS_((Display * display, GC gc));
+/* 73 */
+EXTERN void Tk_FreeImage _ANSI_ARGS_((Tk_Image image));
+/* 74 */
+EXTERN void Tk_FreeOptions _ANSI_ARGS_((Tk_ConfigSpec * specs,
+ char * widgRec, Display * display,
+ int needFlags));
+/* 75 */
+EXTERN void Tk_FreePixmap _ANSI_ARGS_((Display * display,
+ Pixmap pixmap));
+/* 76 */
+EXTERN void Tk_FreeTextLayout _ANSI_ARGS_((
+ Tk_TextLayout textLayout));
+/* 77 */
+EXTERN void Tk_FreeXId _ANSI_ARGS_((Display * display, XID xid));
+/* 78 */
+EXTERN GC Tk_GCForColor _ANSI_ARGS_((XColor * colorPtr,
+ Drawable drawable));
+/* 79 */
+EXTERN void Tk_GeometryRequest _ANSI_ARGS_((Tk_Window tkwin,
+ int reqWidth, int reqHeight));
+/* 80 */
+EXTERN Tk_3DBorder Tk_Get3DBorder _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_Uid colorName));
+/* 81 */
+EXTERN void Tk_GetAllBindings _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_BindingTable bindingTable,
+ ClientData object));
+/* 82 */
+EXTERN int Tk_GetAnchor _ANSI_ARGS_((Tcl_Interp * interp,
+ char * str, Tk_Anchor * anchorPtr));
+/* 83 */
+EXTERN char * Tk_GetAtomName _ANSI_ARGS_((Tk_Window tkwin,
+ Atom atom));
+/* 84 */
+EXTERN char * Tk_GetBinding _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, char * eventStr));
+/* 85 */
+EXTERN Pixmap Tk_GetBitmap _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, CONST char * str));
+/* 86 */
+EXTERN Pixmap Tk_GetBitmapFromData _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ char * source, int width, int height));
+/* 87 */
+EXTERN int Tk_GetCapStyle _ANSI_ARGS_((Tcl_Interp * interp,
+ char * str, int * capPtr));
+/* 88 */
+EXTERN XColor * Tk_GetColor _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_Uid name));
+/* 89 */
+EXTERN XColor * Tk_GetColorByValue _ANSI_ARGS_((Tk_Window tkwin,
+ XColor * colorPtr));
+/* 90 */
+EXTERN Colormap Tk_GetColormap _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * str));
+/* 91 */
+EXTERN Tk_Cursor Tk_GetCursor _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_Uid str));
+/* 92 */
+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));
+/* 93 */
+EXTERN Tk_Font Tk_GetFont _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, CONST char * str));
+/* 94 */
+EXTERN Tk_Font Tk_GetFontFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 95 */
+EXTERN void Tk_GetFontMetrics _ANSI_ARGS_((Tk_Font font,
+ Tk_FontMetrics * fmPtr));
+/* 96 */
+EXTERN GC Tk_GetGC _ANSI_ARGS_((Tk_Window tkwin,
+ unsigned long valueMask,
+ XGCValues * valuePtr));
+/* 97 */
+EXTERN Tk_Image Tk_GetImage _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * name,
+ Tk_ImageChangedProc * changeProc,
+ ClientData clientData));
+/* 98 */
+EXTERN ClientData Tk_GetImageMasterData _ANSI_ARGS_((
+ Tcl_Interp * interp, char * name,
+ Tk_ImageType ** typePtrPtr));
+/* 99 */
+EXTERN Tk_ItemType * Tk_GetItemTypes _ANSI_ARGS_((void));
+/* 100 */
+EXTERN int Tk_GetJoinStyle _ANSI_ARGS_((Tcl_Interp * interp,
+ char * str, int * joinPtr));
+/* 101 */
+EXTERN int Tk_GetJustify _ANSI_ARGS_((Tcl_Interp * interp,
+ char * str, Tk_Justify * justifyPtr));
+/* 102 */
+EXTERN int Tk_GetNumMainWindows _ANSI_ARGS_((void));
+/* 103 */
+EXTERN Tk_Uid Tk_GetOption _ANSI_ARGS_((Tk_Window tkwin,
+ char * name, char * className));
+/* 104 */
+EXTERN int Tk_GetPixels _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * str, int * intPtr));
+/* 105 */
+EXTERN Pixmap Tk_GetPixmap _ANSI_ARGS_((Display * display,
+ Drawable d, int width, int height, int depth));
+/* 106 */
+EXTERN int Tk_GetRelief _ANSI_ARGS_((Tcl_Interp * interp,
+ char * name, int * reliefPtr));
+/* 107 */
+EXTERN void Tk_GetRootCoords _ANSI_ARGS_((Tk_Window tkwin,
+ int * xPtr, int * yPtr));
+/* 108 */
+EXTERN int Tk_GetScrollInfo _ANSI_ARGS_((Tcl_Interp * interp,
+ int argc, char ** argv, double * dblPtr,
+ int * intPtr));
+/* 109 */
+EXTERN int Tk_GetScreenMM _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * str,
+ double * doublePtr));
+/* 110 */
+EXTERN int Tk_GetSelection _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Atom selection, Atom target,
+ Tk_GetSelProc * proc, ClientData clientData));
+/* 111 */
+EXTERN Tk_Uid Tk_GetUid _ANSI_ARGS_((CONST char * str));
+/* 112 */
+EXTERN Visual * Tk_GetVisual _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * str, int * depthPtr,
+ Colormap * colormapPtr));
+/* 113 */
+EXTERN void Tk_GetVRootGeometry _ANSI_ARGS_((Tk_Window tkwin,
+ int * xPtr, int * yPtr, int * widthPtr,
+ int * heightPtr));
+/* 114 */
+EXTERN int Tk_Grab _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, int grabGlobal));
+/* 115 */
+EXTERN void Tk_HandleEvent _ANSI_ARGS_((XEvent * eventPtr));
+/* 116 */
+EXTERN Tk_Window Tk_IdToWindow _ANSI_ARGS_((Display * display,
+ Window window));
+/* 117 */
+EXTERN void Tk_ImageChanged _ANSI_ARGS_((Tk_ImageMaster master,
+ int x, int y, int width, int height,
+ int imageWidth, int imageHeight));
+/* 118 */
+EXTERN int Tk_Init _ANSI_ARGS_((Tcl_Interp * interp));
+/* 119 */
+EXTERN Atom Tk_InternAtom _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 120 */
+EXTERN int Tk_IntersectTextLayout _ANSI_ARGS_((
+ Tk_TextLayout layout, int x, int y,
+ int width, int height));
+/* 121 */
+EXTERN void Tk_MaintainGeometry _ANSI_ARGS_((Tk_Window slave,
+ Tk_Window master, int x, int y, int width,
+ int height));
+/* 122 */
+EXTERN Tk_Window Tk_MainWindow _ANSI_ARGS_((Tcl_Interp * interp));
+/* 123 */
+EXTERN void Tk_MakeWindowExist _ANSI_ARGS_((Tk_Window tkwin));
+/* 124 */
+EXTERN void Tk_ManageGeometry _ANSI_ARGS_((Tk_Window tkwin,
+ Tk_GeomMgr * mgrPtr, ClientData clientData));
+/* 125 */
+EXTERN void Tk_MapWindow _ANSI_ARGS_((Tk_Window tkwin));
+/* 126 */
+EXTERN int Tk_MeasureChars _ANSI_ARGS_((Tk_Font tkfont,
+ CONST char * source, int numBytes,
+ int maxPixels, int flags, int * lengthPtr));
+/* 127 */
+EXTERN void Tk_MoveResizeWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y, int width, int height));
+/* 128 */
+EXTERN void Tk_MoveWindow _ANSI_ARGS_((Tk_Window tkwin, int x,
+ int y));
+/* 129 */
+EXTERN void Tk_MoveToplevelWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y));
+/* 130 */
+EXTERN char * Tk_NameOf3DBorder _ANSI_ARGS_((Tk_3DBorder border));
+/* 131 */
+EXTERN char * Tk_NameOfAnchor _ANSI_ARGS_((Tk_Anchor anchor));
+/* 132 */
+EXTERN char * Tk_NameOfBitmap _ANSI_ARGS_((Display * display,
+ Pixmap bitmap));
+/* 133 */
+EXTERN char * Tk_NameOfCapStyle _ANSI_ARGS_((int cap));
+/* 134 */
+EXTERN char * Tk_NameOfColor _ANSI_ARGS_((XColor * colorPtr));
+/* 135 */
+EXTERN char * Tk_NameOfCursor _ANSI_ARGS_((Display * display,
+ Tk_Cursor cursor));
+/* 136 */
+EXTERN char * Tk_NameOfFont _ANSI_ARGS_((Tk_Font font));
+/* 137 */
+EXTERN char * Tk_NameOfImage _ANSI_ARGS_((
+ Tk_ImageMaster imageMaster));
+/* 138 */
+EXTERN char * Tk_NameOfJoinStyle _ANSI_ARGS_((int join));
+/* 139 */
+EXTERN char * Tk_NameOfJustify _ANSI_ARGS_((Tk_Justify justify));
+/* 140 */
+EXTERN char * Tk_NameOfRelief _ANSI_ARGS_((int relief));
+/* 141 */
+EXTERN Tk_Window Tk_NameToWindow _ANSI_ARGS_((Tcl_Interp * interp,
+ char * pathName, Tk_Window tkwin));
+/* 142 */
+EXTERN void Tk_OwnSelection _ANSI_ARGS_((Tk_Window tkwin,
+ Atom selection, Tk_LostSelProc * proc,
+ ClientData clientData));
+/* 143 */
+EXTERN int Tk_ParseArgv _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, int * argcPtr, char ** argv,
+ Tk_ArgvInfo * argTable, int flags));
+/* 144 */
+EXTERN void Tk_PhotoPutBlock _ANSI_ARGS_((Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock * blockPtr, int x, int y,
+ int width, int height));
+/* 145 */
+EXTERN void Tk_PhotoPutZoomedBlock _ANSI_ARGS_((
+ Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock * blockPtr, int x, int y,
+ int width, int height, int zoomX, int zoomY,
+ int subsampleX, int subsampleY));
+/* 146 */
+EXTERN int Tk_PhotoGetImage _ANSI_ARGS_((Tk_PhotoHandle handle,
+ Tk_PhotoImageBlock * blockPtr));
+/* 147 */
+EXTERN void Tk_PhotoBlank _ANSI_ARGS_((Tk_PhotoHandle handle));
+/* 148 */
+EXTERN void Tk_PhotoExpand _ANSI_ARGS_((Tk_PhotoHandle handle,
+ int width, int height));
+/* 149 */
+EXTERN void Tk_PhotoGetSize _ANSI_ARGS_((Tk_PhotoHandle handle,
+ int * widthPtr, int * heightPtr));
+/* 150 */
+EXTERN void Tk_PhotoSetSize _ANSI_ARGS_((Tk_PhotoHandle handle,
+ int width, int height));
+/* 151 */
+EXTERN int Tk_PointToChar _ANSI_ARGS_((Tk_TextLayout layout,
+ int x, int y));
+/* 152 */
+EXTERN int Tk_PostscriptFontName _ANSI_ARGS_((Tk_Font tkfont,
+ Tcl_DString * dsPtr));
+/* 153 */
+EXTERN void Tk_PreserveColormap _ANSI_ARGS_((Display * display,
+ Colormap colormap));
+/* 154 */
+EXTERN void Tk_QueueWindowEvent _ANSI_ARGS_((XEvent * eventPtr,
+ Tcl_QueuePosition position));
+/* 155 */
+EXTERN void Tk_RedrawImage _ANSI_ARGS_((Tk_Image image,
+ int imageX, int imageY, int width,
+ int height, Drawable drawable, int drawableX,
+ int drawableY));
+/* 156 */
+EXTERN void Tk_ResizeWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int width, int height));
+/* 157 */
+EXTERN int Tk_RestackWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int aboveBelow, Tk_Window other));
+/* 158 */
+EXTERN Tk_RestrictProc * Tk_RestrictEvents _ANSI_ARGS_((
+ Tk_RestrictProc * proc, ClientData arg,
+ ClientData * prevArgPtr));
+/* 159 */
+EXTERN int Tk_SafeInit _ANSI_ARGS_((Tcl_Interp * interp));
+/* 160 */
+EXTERN char * Tk_SetAppName _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 161 */
+EXTERN void Tk_SetBackgroundFromBorder _ANSI_ARGS_((
+ Tk_Window tkwin, Tk_3DBorder border));
+/* 162 */
+EXTERN void Tk_SetClass _ANSI_ARGS_((Tk_Window tkwin,
+ char * className));
+/* 163 */
+EXTERN void Tk_SetGrid _ANSI_ARGS_((Tk_Window tkwin,
+ int reqWidth, int reqHeight, int gridWidth,
+ int gridHeight));
+/* 164 */
+EXTERN void Tk_SetInternalBorder _ANSI_ARGS_((Tk_Window tkwin,
+ int width));
+/* 165 */
+EXTERN void Tk_SetWindowBackground _ANSI_ARGS_((Tk_Window tkwin,
+ unsigned long pixel));
+/* 166 */
+EXTERN void Tk_SetWindowBackgroundPixmap _ANSI_ARGS_((
+ Tk_Window tkwin, Pixmap pixmap));
+/* 167 */
+EXTERN void Tk_SetWindowBorder _ANSI_ARGS_((Tk_Window tkwin,
+ unsigned long pixel));
+/* 168 */
+EXTERN void Tk_SetWindowBorderWidth _ANSI_ARGS_((Tk_Window tkwin,
+ int width));
+/* 169 */
+EXTERN void Tk_SetWindowBorderPixmap _ANSI_ARGS_((
+ Tk_Window tkwin, Pixmap pixmap));
+/* 170 */
+EXTERN void Tk_SetWindowColormap _ANSI_ARGS_((Tk_Window tkwin,
+ Colormap colormap));
+/* 171 */
+EXTERN int Tk_SetWindowVisual _ANSI_ARGS_((Tk_Window tkwin,
+ Visual * visual, int depth,
+ Colormap colormap));
+/* 172 */
+EXTERN void Tk_SizeOfBitmap _ANSI_ARGS_((Display * display,
+ Pixmap bitmap, int * widthPtr,
+ int * heightPtr));
+/* 173 */
+EXTERN void Tk_SizeOfImage _ANSI_ARGS_((Tk_Image image,
+ int * widthPtr, int * heightPtr));
+/* 174 */
+EXTERN int Tk_StrictMotif _ANSI_ARGS_((Tk_Window tkwin));
+/* 175 */
+EXTERN void Tk_TextLayoutToPostscript _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_TextLayout layout));
+/* 176 */
+EXTERN int Tk_TextWidth _ANSI_ARGS_((Tk_Font font,
+ CONST char * str, int numBytes));
+/* 177 */
+EXTERN void Tk_UndefineCursor _ANSI_ARGS_((Tk_Window window));
+/* 178 */
+EXTERN void Tk_UnderlineChars _ANSI_ARGS_((Display * display,
+ Drawable drawable, GC gc, Tk_Font tkfont,
+ CONST char * source, int x, int y,
+ int firstByte, int lastByte));
+/* 179 */
+EXTERN void Tk_UnderlineTextLayout _ANSI_ARGS_((
+ Display * display, Drawable drawable, GC gc,
+ Tk_TextLayout layout, int x, int y,
+ int underline));
+/* 180 */
+EXTERN void Tk_Ungrab _ANSI_ARGS_((Tk_Window tkwin));
+/* 181 */
+EXTERN void Tk_UnmaintainGeometry _ANSI_ARGS_((Tk_Window slave,
+ Tk_Window master));
+/* 182 */
+EXTERN void Tk_UnmapWindow _ANSI_ARGS_((Tk_Window tkwin));
+/* 183 */
+EXTERN void Tk_UnsetGrid _ANSI_ARGS_((Tk_Window tkwin));
+/* 184 */
+EXTERN void Tk_UpdatePointer _ANSI_ARGS_((Tk_Window tkwin, int x,
+ int y, int state));
+/* 185 */
+EXTERN Pixmap Tk_AllocBitmapFromObj _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 186 */
+EXTERN Tk_3DBorder Tk_Alloc3DBorderFromObj _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 187 */
+EXTERN XColor * Tk_AllocColorFromObj _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 188 */
+EXTERN Tk_Cursor Tk_AllocCursorFromObj _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 189 */
+EXTERN Tk_Font Tk_AllocFontFromObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tcl_Obj * objPtr));
+/* 190 */
+EXTERN Tk_OptionTable Tk_CreateOptionTable _ANSI_ARGS_((
+ Tcl_Interp * interp,
+ CONST Tk_OptionSpec * templatePtr));
+/* 191 */
+EXTERN void Tk_DeleteOptionTable _ANSI_ARGS_((
+ Tk_OptionTable optionTable));
+/* 192 */
+EXTERN void Tk_Free3DBorderFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 193 */
+EXTERN void Tk_FreeBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 194 */
+EXTERN void Tk_FreeColorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 195 */
+EXTERN void Tk_FreeConfigOptions _ANSI_ARGS_((char * recordPtr,
+ Tk_OptionTable optionToken, Tk_Window tkwin));
+/* 196 */
+EXTERN void Tk_FreeSavedOptions _ANSI_ARGS_((
+ Tk_SavedOptions * savePtr));
+/* 197 */
+EXTERN void Tk_FreeCursorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 198 */
+EXTERN void Tk_FreeFontFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 199 */
+EXTERN Tk_3DBorder Tk_Get3DBorderFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 200 */
+EXTERN int Tk_GetAnchorFromObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_Obj * objPtr, Tk_Anchor * anchorPtr));
+/* 201 */
+EXTERN Pixmap Tk_GetBitmapFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 202 */
+EXTERN XColor * Tk_GetColorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 203 */
+EXTERN Tk_Cursor Tk_GetCursorFromObj _ANSI_ARGS_((Tk_Window tkwin,
+ Tcl_Obj * objPtr));
+/* 204 */
+EXTERN Tcl_Obj * Tk_GetOptionInfo _ANSI_ARGS_((Tcl_Interp * interp,
+ char * recordPtr, Tk_OptionTable optionTable,
+ Tcl_Obj * namePtr, Tk_Window tkwin));
+/* 205 */
+EXTERN Tcl_Obj * Tk_GetOptionValue _ANSI_ARGS_((Tcl_Interp * interp,
+ char * recordPtr, Tk_OptionTable optionTable,
+ Tcl_Obj * namePtr, Tk_Window tkwin));
+/* 206 */
+EXTERN int Tk_GetJustifyFromObj _ANSI_ARGS_((
+ Tcl_Interp * interp, Tcl_Obj * objPtr,
+ Tk_Justify * justifyPtr));
+/* 207 */
+EXTERN int Tk_GetMMFromObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tcl_Obj * objPtr,
+ double * doublePtr));
+/* 208 */
+EXTERN int Tk_GetPixelsFromObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tcl_Obj * objPtr,
+ int * intPtr));
+/* 209 */
+EXTERN int Tk_GetReliefFromObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_Obj * objPtr, int * resultPtr));
+/* 210 */
+EXTERN int Tk_GetScrollInfoObj _ANSI_ARGS_((Tcl_Interp * interp,
+ int objc, Tcl_Obj *CONST objv[],
+ double * dblPtr, int * intPtr));
+/* 211 */
+EXTERN int Tk_InitOptions _ANSI_ARGS_((Tcl_Interp * interp,
+ char * recordPtr, Tk_OptionTable optionToken,
+ Tk_Window tkwin));
+/* 212 */
+EXTERN void Tk_MainEx _ANSI_ARGS_((int argc, char ** argv,
+ Tcl_AppInitProc * appInitProc,
+ Tcl_Interp * interp));
+/* 213 */
+EXTERN void Tk_RestoreSavedOptions _ANSI_ARGS_((
+ Tk_SavedOptions * savePtr));
+/* 214 */
+EXTERN int Tk_SetOptions _ANSI_ARGS_((Tcl_Interp * interp,
+ char * recordPtr, Tk_OptionTable optionTable,
+ int objc, Tcl_Obj *CONST objv[],
+ Tk_Window tkwin, Tk_SavedOptions * savePtr,
+ int * maskPtr));
+/* 215 */
+EXTERN void Tk_InitConsoleChannels _ANSI_ARGS_((
+ Tcl_Interp * interp));
+/* 216 */
+EXTERN int Tk_CreateConsoleWindow _ANSI_ARGS_((
+ Tcl_Interp * interp));
+/* 217 */
+EXTERN void Tk_CreateSmoothMethod _ANSI_ARGS_((
+ Tcl_Interp * interp,
+ Tk_SmoothMethod * method));
+/* Slot 218 is reserved */
+/* Slot 219 is reserved */
+/* 220 */
+EXTERN int Tk_GetDash _ANSI_ARGS_((Tcl_Interp * interp,
+ CONST char * value, Tk_Dash * dash));
+/* 221 */
+EXTERN void Tk_CreateOutline _ANSI_ARGS_((Tk_Outline * outline));
+/* 222 */
+EXTERN void Tk_DeleteOutline _ANSI_ARGS_((Display * display,
+ Tk_Outline * outline));
+/* 223 */
+EXTERN int Tk_ConfigOutlineGC _ANSI_ARGS_((XGCValues * gcValues,
+ Tk_Canvas canvas, Tk_Item * item,
+ Tk_Outline * outline));
+/* 224 */
+EXTERN int Tk_ChangeOutlineGC _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item * item, Tk_Outline * outline));
+/* 225 */
+EXTERN int Tk_ResetOutlineGC _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item * item, Tk_Outline * outline));
+/* 226 */
+EXTERN int Tk_CanvasPsOutline _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item * item, Tk_Outline * outline));
+/* 227 */
+EXTERN void Tk_SetTSOrigin _ANSI_ARGS_((Tk_Window tkwin, GC gc,
+ int x, int y));
+/* 228 */
+EXTERN int Tk_CanvasGetCoordFromObj _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Canvas canvas,
+ Tcl_Obj * obj, double * doublePtr));
+/* 229 */
+EXTERN void Tk_CanvasSetOffset _ANSI_ARGS_((Tk_Canvas canvas,
+ GC gc, Tk_TSOffset * offset));
+/* 230 */
+EXTERN void Tk_DitherPhoto _ANSI_ARGS_((Tk_PhotoHandle handle,
+ int x, int y, int width, int height));
+/* 231 */
+EXTERN int Tk_PostscriptBitmap _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_PostscriptInfo psInfo,
+ Pixmap bitmap, int startX, int startY,
+ int width, int height));
+/* 232 */
+EXTERN int Tk_PostscriptColor _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_PostscriptInfo psInfo, XColor * colorPtr));
+/* 233 */
+EXTERN int Tk_PostscriptFont _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_PostscriptInfo psInfo, Tk_Font font));
+/* 234 */
+EXTERN int Tk_PostscriptImage _ANSI_ARGS_((Tk_Image image,
+ Tcl_Interp * interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psinfo, int x, int y,
+ int width, int height, int prepass));
+/* 235 */
+EXTERN void Tk_PostscriptPath _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_PostscriptInfo psInfo, double * coordPtr,
+ int numPoints));
+/* 236 */
+EXTERN int Tk_PostscriptStipple _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, Pixmap bitmap));
+/* 237 */
+EXTERN double Tk_PostscriptY _ANSI_ARGS_((double y,
+ Tk_PostscriptInfo psInfo));
+/* 238 */
+EXTERN int Tk_PostscriptPhoto _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_PhotoImageBlock * blockPtr,
+ Tk_PostscriptInfo psInfo, int width,
+ int height));
+
+typedef struct TkStubHooks {
+ struct TkPlatStubs *tkPlatStubs;
+ struct TkIntStubs *tkIntStubs;
+ struct TkIntPlatStubs *tkIntPlatStubs;
+ struct TkIntXlibStubs *tkIntXlibStubs;
+} TkStubHooks;
+
+typedef struct TkStubs {
+ int magic;
+ struct TkStubHooks *hooks;
+
+ void (*tk_MainLoop) _ANSI_ARGS_((void)); /* 0 */
+ XColor * (*tk_3DBorderColor) _ANSI_ARGS_((Tk_3DBorder border)); /* 1 */
+ GC (*tk_3DBorderGC) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 2 */
+ void (*tk_3DHorizontalBevel) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftIn, int rightIn, int topBevel, int relief)); /* 3 */
+ void (*tk_3DVerticalBevel) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int leftBevel, int relief)); /* 4 */
+ void (*tk_AddOption) _ANSI_ARGS_((Tk_Window tkwin, char * name, char * value, int priority)); /* 5 */
+ void (*tk_BindEvent) _ANSI_ARGS_((Tk_BindingTable bindingTable, XEvent * eventPtr, Tk_Window tkwin, int numObjects, ClientData * objectPtr)); /* 6 */
+ void (*tk_CanvasDrawableCoords) _ANSI_ARGS_((Tk_Canvas canvas, double x, double y, short * drawableXPtr, short * drawableYPtr)); /* 7 */
+ void (*tk_CanvasEventuallyRedraw) _ANSI_ARGS_((Tk_Canvas canvas, int x1, int y1, int x2, int y2)); /* 8 */
+ int (*tk_CanvasGetCoord) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, char * str, double * doublePtr)); /* 9 */
+ Tk_CanvasTextInfo * (*tk_CanvasGetTextInfo) _ANSI_ARGS_((Tk_Canvas canvas)); /* 10 */
+ int (*tk_CanvasPsBitmap) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, Pixmap bitmap, int x, int y, int width, int height)); /* 11 */
+ int (*tk_CanvasPsColor) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, XColor * colorPtr)); /* 12 */
+ int (*tk_CanvasPsFont) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, Tk_Font font)); /* 13 */
+ void (*tk_CanvasPsPath) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, double * coordPtr, int numPoints)); /* 14 */
+ int (*tk_CanvasPsStipple) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, Pixmap bitmap)); /* 15 */
+ double (*tk_CanvasPsY) _ANSI_ARGS_((Tk_Canvas canvas, double y)); /* 16 */
+ void (*tk_CanvasSetStippleOrigin) _ANSI_ARGS_((Tk_Canvas canvas, GC gc)); /* 17 */
+ int (*tk_CanvasTagsParseProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, Tk_Window tkwin, char * value, char * widgRec, int offset)); /* 18 */
+ char * (*tk_CanvasTagsPrintProc) _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char * widgRec, int offset, Tcl_FreeProc ** freeProcPtr)); /* 19 */
+ Tk_Window (*tk_CanvasTkwin) _ANSI_ARGS_((Tk_Canvas canvas)); /* 20 */
+ void (*tk_CanvasWindowCoords) _ANSI_ARGS_((Tk_Canvas canvas, double x, double y, short * screenXPtr, short * screenYPtr)); /* 21 */
+ void (*tk_ChangeWindowAttributes) _ANSI_ARGS_((Tk_Window tkwin, unsigned long valueMask, XSetWindowAttributes * attsPtr)); /* 22 */
+ int (*tk_CharBbox) _ANSI_ARGS_((Tk_TextLayout layout, int index, int * xPtr, int * yPtr, int * widthPtr, int * heightPtr)); /* 23 */
+ void (*tk_ClearSelection) _ANSI_ARGS_((Tk_Window tkwin, Atom selection)); /* 24 */
+ int (*tk_ClipboardAppend) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Atom target, Atom format, char* buffer)); /* 25 */
+ int (*tk_ClipboardClear) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 26 */
+ int (*tk_ConfigureInfo) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_ConfigSpec * specs, char * widgRec, char * argvName, int flags)); /* 27 */
+ int (*tk_ConfigureValue) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_ConfigSpec * specs, char * widgRec, char * argvName, int flags)); /* 28 */
+ int (*tk_ConfigureWidget) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_ConfigSpec * specs, int argc, char ** argv, char * widgRec, int flags)); /* 29 */
+ void (*tk_ConfigureWindow) _ANSI_ARGS_((Tk_Window tkwin, unsigned int valueMask, XWindowChanges * valuePtr)); /* 30 */
+ Tk_TextLayout (*tk_ComputeTextLayout) _ANSI_ARGS_((Tk_Font font, CONST char * str, int numChars, int wrapLength, Tk_Justify justify, int flags, int * widthPtr, int * heightPtr)); /* 31 */
+ Tk_Window (*tk_CoordsToWindow) _ANSI_ARGS_((int rootX, int rootY, Tk_Window tkwin)); /* 32 */
+ unsigned long (*tk_CreateBinding) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, char * eventStr, char * command, int append)); /* 33 */
+ Tk_BindingTable (*tk_CreateBindingTable) _ANSI_ARGS_((Tcl_Interp * interp)); /* 34 */
+ Tk_ErrorHandler (*tk_CreateErrorHandler) _ANSI_ARGS_((Display * display, int errNum, int request, int minorCode, Tk_ErrorProc * errorProc, ClientData clientData)); /* 35 */
+ void (*tk_CreateEventHandler) _ANSI_ARGS_((Tk_Window token, unsigned long mask, Tk_EventProc * proc, ClientData clientData)); /* 36 */
+ void (*tk_CreateGenericHandler) _ANSI_ARGS_((Tk_GenericProc * proc, ClientData clientData)); /* 37 */
+ void (*tk_CreateImageType) _ANSI_ARGS_((Tk_ImageType * typePtr)); /* 38 */
+ void (*tk_CreateItemType) _ANSI_ARGS_((Tk_ItemType * typePtr)); /* 39 */
+ void (*tk_CreatePhotoImageFormat) _ANSI_ARGS_((Tk_PhotoImageFormat * formatPtr)); /* 40 */
+ void (*tk_CreateSelHandler) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Atom target, Tk_SelectionProc * proc, ClientData clientData, Atom format)); /* 41 */
+ Tk_Window (*tk_CreateWindow) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window parent, char * name, char * screenName)); /* 42 */
+ Tk_Window (*tk_CreateWindowFromPath) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * pathName, char * screenName)); /* 43 */
+ int (*tk_DefineBitmap) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, char * source, int width, int height)); /* 44 */
+ void (*tk_DefineCursor) _ANSI_ARGS_((Tk_Window window, Tk_Cursor cursor)); /* 45 */
+ void (*tk_DeleteAllBindings) _ANSI_ARGS_((Tk_BindingTable bindingTable, ClientData object)); /* 46 */
+ int (*tk_DeleteBinding) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, char * eventStr)); /* 47 */
+ void (*tk_DeleteBindingTable) _ANSI_ARGS_((Tk_BindingTable bindingTable)); /* 48 */
+ void (*tk_DeleteErrorHandler) _ANSI_ARGS_((Tk_ErrorHandler handler)); /* 49 */
+ void (*tk_DeleteEventHandler) _ANSI_ARGS_((Tk_Window token, unsigned long mask, Tk_EventProc * proc, ClientData clientData)); /* 50 */
+ void (*tk_DeleteGenericHandler) _ANSI_ARGS_((Tk_GenericProc * proc, ClientData clientData)); /* 51 */
+ void (*tk_DeleteImage) _ANSI_ARGS_((Tcl_Interp * interp, char * name)); /* 52 */
+ void (*tk_DeleteSelHandler) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Atom target)); /* 53 */
+ void (*tk_DestroyWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 54 */
+ char * (*tk_DisplayName) _ANSI_ARGS_((Tk_Window tkwin)); /* 55 */
+ int (*tk_DistanceToTextLayout) _ANSI_ARGS_((Tk_TextLayout layout, int x, int y)); /* 56 */
+ void (*tk_Draw3DPolygon) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint * pointPtr, int numPoints, int borderWidth, int leftRelief)); /* 57 */
+ void (*tk_Draw3DRectangle) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief)); /* 58 */
+ void (*tk_DrawChars) _ANSI_ARGS_((Display * display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char * source, int numBytes, int x, int y)); /* 59 */
+ void (*tk_DrawFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable)); /* 60 */
+ void (*tk_DrawTextLayout) _ANSI_ARGS_((Display * display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int firstChar, int lastChar)); /* 61 */
+ void (*tk_Fill3DPolygon) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, XPoint * pointPtr, int numPoints, int borderWidth, int leftRelief)); /* 62 */
+ void (*tk_Fill3DRectangle) _ANSI_ARGS_((Tk_Window tkwin, Drawable drawable, Tk_3DBorder border, int x, int y, int width, int height, int borderWidth, int relief)); /* 63 */
+ Tk_PhotoHandle (*tk_FindPhoto) _ANSI_ARGS_((Tcl_Interp * interp, char * imageName)); /* 64 */
+ Font (*tk_FontId) _ANSI_ARGS_((Tk_Font font)); /* 65 */
+ void (*tk_Free3DBorder) _ANSI_ARGS_((Tk_3DBorder border)); /* 66 */
+ void (*tk_FreeBitmap) _ANSI_ARGS_((Display * display, Pixmap bitmap)); /* 67 */
+ void (*tk_FreeColor) _ANSI_ARGS_((XColor * colorPtr)); /* 68 */
+ void (*tk_FreeColormap) _ANSI_ARGS_((Display * display, Colormap colormap)); /* 69 */
+ void (*tk_FreeCursor) _ANSI_ARGS_((Display * display, Tk_Cursor cursor)); /* 70 */
+ void (*tk_FreeFont) _ANSI_ARGS_((Tk_Font f)); /* 71 */
+ void (*tk_FreeGC) _ANSI_ARGS_((Display * display, GC gc)); /* 72 */
+ void (*tk_FreeImage) _ANSI_ARGS_((Tk_Image image)); /* 73 */
+ void (*tk_FreeOptions) _ANSI_ARGS_((Tk_ConfigSpec * specs, char * widgRec, Display * display, int needFlags)); /* 74 */
+ void (*tk_FreePixmap) _ANSI_ARGS_((Display * display, Pixmap pixmap)); /* 75 */
+ void (*tk_FreeTextLayout) _ANSI_ARGS_((Tk_TextLayout textLayout)); /* 76 */
+ void (*tk_FreeXId) _ANSI_ARGS_((Display * display, XID xid)); /* 77 */
+ GC (*tk_GCForColor) _ANSI_ARGS_((XColor * colorPtr, Drawable drawable)); /* 78 */
+ void (*tk_GeometryRequest) _ANSI_ARGS_((Tk_Window tkwin, int reqWidth, int reqHeight)); /* 79 */
+ Tk_3DBorder (*tk_Get3DBorder) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid colorName)); /* 80 */
+ void (*tk_GetAllBindings) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object)); /* 81 */
+ int (*tk_GetAnchor) _ANSI_ARGS_((Tcl_Interp * interp, char * str, Tk_Anchor * anchorPtr)); /* 82 */
+ char * (*tk_GetAtomName) _ANSI_ARGS_((Tk_Window tkwin, Atom atom)); /* 83 */
+ char * (*tk_GetBinding) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, char * eventStr)); /* 84 */
+ Pixmap (*tk_GetBitmap) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, CONST char * str)); /* 85 */
+ Pixmap (*tk_GetBitmapFromData) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * source, int width, int height)); /* 86 */
+ int (*tk_GetCapStyle) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * capPtr)); /* 87 */
+ XColor * (*tk_GetColor) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid name)); /* 88 */
+ XColor * (*tk_GetColorByValue) _ANSI_ARGS_((Tk_Window tkwin, XColor * colorPtr)); /* 89 */
+ Colormap (*tk_GetColormap) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * str)); /* 90 */
+ Tk_Cursor (*tk_GetCursor) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid str)); /* 91 */
+ Tk_Cursor (*tk_GetCursorFromData) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * source, char * mask, int width, int height, int xHot, int yHot, Tk_Uid fg, Tk_Uid bg)); /* 92 */
+ Tk_Font (*tk_GetFont) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, CONST char * str)); /* 93 */
+ Tk_Font (*tk_GetFontFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 94 */
+ void (*tk_GetFontMetrics) _ANSI_ARGS_((Tk_Font font, Tk_FontMetrics * fmPtr)); /* 95 */
+ GC (*tk_GetGC) _ANSI_ARGS_((Tk_Window tkwin, unsigned long valueMask, XGCValues * valuePtr)); /* 96 */
+ Tk_Image (*tk_GetImage) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * name, Tk_ImageChangedProc * changeProc, ClientData clientData)); /* 97 */
+ ClientData (*tk_GetImageMasterData) _ANSI_ARGS_((Tcl_Interp * interp, char * name, Tk_ImageType ** typePtrPtr)); /* 98 */
+ Tk_ItemType * (*tk_GetItemTypes) _ANSI_ARGS_((void)); /* 99 */
+ int (*tk_GetJoinStyle) _ANSI_ARGS_((Tcl_Interp * interp, char * str, int * joinPtr)); /* 100 */
+ int (*tk_GetJustify) _ANSI_ARGS_((Tcl_Interp * interp, char * str, Tk_Justify * justifyPtr)); /* 101 */
+ int (*tk_GetNumMainWindows) _ANSI_ARGS_((void)); /* 102 */
+ Tk_Uid (*tk_GetOption) _ANSI_ARGS_((Tk_Window tkwin, char * name, char * className)); /* 103 */
+ int (*tk_GetPixels) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * str, int * intPtr)); /* 104 */
+ Pixmap (*tk_GetPixmap) _ANSI_ARGS_((Display * display, Drawable d, int width, int height, int depth)); /* 105 */
+ int (*tk_GetRelief) _ANSI_ARGS_((Tcl_Interp * interp, char * name, int * reliefPtr)); /* 106 */
+ void (*tk_GetRootCoords) _ANSI_ARGS_((Tk_Window tkwin, int * xPtr, int * yPtr)); /* 107 */
+ int (*tk_GetScrollInfo) _ANSI_ARGS_((Tcl_Interp * interp, int argc, char ** argv, double * dblPtr, int * intPtr)); /* 108 */
+ int (*tk_GetScreenMM) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * str, double * doublePtr)); /* 109 */
+ int (*tk_GetSelection) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Atom selection, Atom target, Tk_GetSelProc * proc, ClientData clientData)); /* 110 */
+ Tk_Uid (*tk_GetUid) _ANSI_ARGS_((CONST char * str)); /* 111 */
+ Visual * (*tk_GetVisual) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * str, int * depthPtr, Colormap * colormapPtr)); /* 112 */
+ void (*tk_GetVRootGeometry) _ANSI_ARGS_((Tk_Window tkwin, int * xPtr, int * yPtr, int * widthPtr, int * heightPtr)); /* 113 */
+ int (*tk_Grab) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, int grabGlobal)); /* 114 */
+ void (*tk_HandleEvent) _ANSI_ARGS_((XEvent * eventPtr)); /* 115 */
+ Tk_Window (*tk_IdToWindow) _ANSI_ARGS_((Display * display, Window window)); /* 116 */
+ void (*tk_ImageChanged) _ANSI_ARGS_((Tk_ImageMaster master, int x, int y, int width, int height, int imageWidth, int imageHeight)); /* 117 */
+ int (*tk_Init) _ANSI_ARGS_((Tcl_Interp * interp)); /* 118 */
+ Atom (*tk_InternAtom) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 119 */
+ int (*tk_IntersectTextLayout) _ANSI_ARGS_((Tk_TextLayout layout, int x, int y, int width, int height)); /* 120 */
+ void (*tk_MaintainGeometry) _ANSI_ARGS_((Tk_Window slave, Tk_Window master, int x, int y, int width, int height)); /* 121 */
+ Tk_Window (*tk_MainWindow) _ANSI_ARGS_((Tcl_Interp * interp)); /* 122 */
+ void (*tk_MakeWindowExist) _ANSI_ARGS_((Tk_Window tkwin)); /* 123 */
+ void (*tk_ManageGeometry) _ANSI_ARGS_((Tk_Window tkwin, Tk_GeomMgr * mgrPtr, ClientData clientData)); /* 124 */
+ void (*tk_MapWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 125 */
+ int (*tk_MeasureChars) _ANSI_ARGS_((Tk_Font tkfont, CONST char * source, int numBytes, int maxPixels, int flags, int * lengthPtr)); /* 126 */
+ void (*tk_MoveResizeWindow) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height)); /* 127 */
+ void (*tk_MoveWindow) _ANSI_ARGS_((Tk_Window tkwin, int x, int y)); /* 128 */
+ void (*tk_MoveToplevelWindow) _ANSI_ARGS_((Tk_Window tkwin, int x, int y)); /* 129 */
+ char * (*tk_NameOf3DBorder) _ANSI_ARGS_((Tk_3DBorder border)); /* 130 */
+ char * (*tk_NameOfAnchor) _ANSI_ARGS_((Tk_Anchor anchor)); /* 131 */
+ char * (*tk_NameOfBitmap) _ANSI_ARGS_((Display * display, Pixmap bitmap)); /* 132 */
+ char * (*tk_NameOfCapStyle) _ANSI_ARGS_((int cap)); /* 133 */
+ char * (*tk_NameOfColor) _ANSI_ARGS_((XColor * colorPtr)); /* 134 */
+ char * (*tk_NameOfCursor) _ANSI_ARGS_((Display * display, Tk_Cursor cursor)); /* 135 */
+ char * (*tk_NameOfFont) _ANSI_ARGS_((Tk_Font font)); /* 136 */
+ char * (*tk_NameOfImage) _ANSI_ARGS_((Tk_ImageMaster imageMaster)); /* 137 */
+ char * (*tk_NameOfJoinStyle) _ANSI_ARGS_((int join)); /* 138 */
+ char * (*tk_NameOfJustify) _ANSI_ARGS_((Tk_Justify justify)); /* 139 */
+ char * (*tk_NameOfRelief) _ANSI_ARGS_((int relief)); /* 140 */
+ Tk_Window (*tk_NameToWindow) _ANSI_ARGS_((Tcl_Interp * interp, char * pathName, Tk_Window tkwin)); /* 141 */
+ void (*tk_OwnSelection) _ANSI_ARGS_((Tk_Window tkwin, Atom selection, Tk_LostSelProc * proc, ClientData clientData)); /* 142 */
+ int (*tk_ParseArgv) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, int * argcPtr, char ** argv, Tk_ArgvInfo * argTable, int flags)); /* 143 */
+ void (*tk_PhotoPutBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height)); /* 144 */
+ void (*tk_PhotoPutZoomedBlock) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY)); /* 145 */
+ int (*tk_PhotoGetImage) _ANSI_ARGS_((Tk_PhotoHandle handle, Tk_PhotoImageBlock * blockPtr)); /* 146 */
+ void (*tk_PhotoBlank) _ANSI_ARGS_((Tk_PhotoHandle handle)); /* 147 */
+ void (*tk_PhotoExpand) _ANSI_ARGS_((Tk_PhotoHandle handle, int width, int height)); /* 148 */
+ void (*tk_PhotoGetSize) _ANSI_ARGS_((Tk_PhotoHandle handle, int * widthPtr, int * heightPtr)); /* 149 */
+ void (*tk_PhotoSetSize) _ANSI_ARGS_((Tk_PhotoHandle handle, int width, int height)); /* 150 */
+ int (*tk_PointToChar) _ANSI_ARGS_((Tk_TextLayout layout, int x, int y)); /* 151 */
+ int (*tk_PostscriptFontName) _ANSI_ARGS_((Tk_Font tkfont, Tcl_DString * dsPtr)); /* 152 */
+ void (*tk_PreserveColormap) _ANSI_ARGS_((Display * display, Colormap colormap)); /* 153 */
+ void (*tk_QueueWindowEvent) _ANSI_ARGS_((XEvent * eventPtr, Tcl_QueuePosition position)); /* 154 */
+ void (*tk_RedrawImage) _ANSI_ARGS_((Tk_Image image, int imageX, int imageY, int width, int height, Drawable drawable, int drawableX, int drawableY)); /* 155 */
+ void (*tk_ResizeWindow) _ANSI_ARGS_((Tk_Window tkwin, int width, int height)); /* 156 */
+ int (*tk_RestackWindow) _ANSI_ARGS_((Tk_Window tkwin, int aboveBelow, Tk_Window other)); /* 157 */
+ Tk_RestrictProc * (*tk_RestrictEvents) _ANSI_ARGS_((Tk_RestrictProc * proc, ClientData arg, ClientData * prevArgPtr)); /* 158 */
+ int (*tk_SafeInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 159 */
+ char * (*tk_SetAppName) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 160 */
+ void (*tk_SetBackgroundFromBorder) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border)); /* 161 */
+ void (*tk_SetClass) _ANSI_ARGS_((Tk_Window tkwin, char * className)); /* 162 */
+ void (*tk_SetGrid) _ANSI_ARGS_((Tk_Window tkwin, int reqWidth, int reqHeight, int gridWidth, int gridHeight)); /* 163 */
+ void (*tk_SetInternalBorder) _ANSI_ARGS_((Tk_Window tkwin, int width)); /* 164 */
+ void (*tk_SetWindowBackground) _ANSI_ARGS_((Tk_Window tkwin, unsigned long pixel)); /* 165 */
+ void (*tk_SetWindowBackgroundPixmap) _ANSI_ARGS_((Tk_Window tkwin, Pixmap pixmap)); /* 166 */
+ void (*tk_SetWindowBorder) _ANSI_ARGS_((Tk_Window tkwin, unsigned long pixel)); /* 167 */
+ void (*tk_SetWindowBorderWidth) _ANSI_ARGS_((Tk_Window tkwin, int width)); /* 168 */
+ void (*tk_SetWindowBorderPixmap) _ANSI_ARGS_((Tk_Window tkwin, Pixmap pixmap)); /* 169 */
+ void (*tk_SetWindowColormap) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 170 */
+ int (*tk_SetWindowVisual) _ANSI_ARGS_((Tk_Window tkwin, Visual * visual, int depth, Colormap colormap)); /* 171 */
+ void (*tk_SizeOfBitmap) _ANSI_ARGS_((Display * display, Pixmap bitmap, int * widthPtr, int * heightPtr)); /* 172 */
+ void (*tk_SizeOfImage) _ANSI_ARGS_((Tk_Image image, int * widthPtr, int * heightPtr)); /* 173 */
+ int (*tk_StrictMotif) _ANSI_ARGS_((Tk_Window tkwin)); /* 174 */
+ void (*tk_TextLayoutToPostscript) _ANSI_ARGS_((Tcl_Interp * interp, Tk_TextLayout layout)); /* 175 */
+ int (*tk_TextWidth) _ANSI_ARGS_((Tk_Font font, CONST char * str, int numBytes)); /* 176 */
+ void (*tk_UndefineCursor) _ANSI_ARGS_((Tk_Window window)); /* 177 */
+ void (*tk_UnderlineChars) _ANSI_ARGS_((Display * display, Drawable drawable, GC gc, Tk_Font tkfont, CONST char * source, int x, int y, int firstByte, int lastByte)); /* 178 */
+ void (*tk_UnderlineTextLayout) _ANSI_ARGS_((Display * display, Drawable drawable, GC gc, Tk_TextLayout layout, int x, int y, int underline)); /* 179 */
+ void (*tk_Ungrab) _ANSI_ARGS_((Tk_Window tkwin)); /* 180 */
+ void (*tk_UnmaintainGeometry) _ANSI_ARGS_((Tk_Window slave, Tk_Window master)); /* 181 */
+ void (*tk_UnmapWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 182 */
+ void (*tk_UnsetGrid) _ANSI_ARGS_((Tk_Window tkwin)); /* 183 */
+ void (*tk_UpdatePointer) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int state)); /* 184 */
+ Pixmap (*tk_AllocBitmapFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr)); /* 185 */
+ Tk_3DBorder (*tk_Alloc3DBorderFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr)); /* 186 */
+ XColor * (*tk_AllocColorFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr)); /* 187 */
+ Tk_Cursor (*tk_AllocCursorFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr)); /* 188 */
+ Tk_Font (*tk_AllocFontFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr)); /* 189 */
+ Tk_OptionTable (*tk_CreateOptionTable) _ANSI_ARGS_((Tcl_Interp * interp, CONST Tk_OptionSpec * templatePtr)); /* 190 */
+ void (*tk_DeleteOptionTable) _ANSI_ARGS_((Tk_OptionTable optionTable)); /* 191 */
+ void (*tk_Free3DBorderFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 192 */
+ void (*tk_FreeBitmapFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 193 */
+ void (*tk_FreeColorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 194 */
+ void (*tk_FreeConfigOptions) _ANSI_ARGS_((char * recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin)); /* 195 */
+ void (*tk_FreeSavedOptions) _ANSI_ARGS_((Tk_SavedOptions * savePtr)); /* 196 */
+ void (*tk_FreeCursorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 197 */
+ void (*tk_FreeFontFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 198 */
+ Tk_3DBorder (*tk_Get3DBorderFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 199 */
+ int (*tk_GetAnchorFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tk_Anchor * anchorPtr)); /* 200 */
+ Pixmap (*tk_GetBitmapFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 201 */
+ XColor * (*tk_GetColorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 202 */
+ Tk_Cursor (*tk_GetCursorFromObj) _ANSI_ARGS_((Tk_Window tkwin, Tcl_Obj * objPtr)); /* 203 */
+ Tcl_Obj * (*tk_GetOptionInfo) _ANSI_ARGS_((Tcl_Interp * interp, char * recordPtr, Tk_OptionTable optionTable, Tcl_Obj * namePtr, Tk_Window tkwin)); /* 204 */
+ Tcl_Obj * (*tk_GetOptionValue) _ANSI_ARGS_((Tcl_Interp * interp, char * recordPtr, Tk_OptionTable optionTable, Tcl_Obj * namePtr, Tk_Window tkwin)); /* 205 */
+ int (*tk_GetJustifyFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, Tk_Justify * justifyPtr)); /* 206 */
+ int (*tk_GetMMFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr, double * doublePtr)); /* 207 */
+ int (*tk_GetPixelsFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr, int * intPtr)); /* 208 */
+ int (*tk_GetReliefFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int * resultPtr)); /* 209 */
+ int (*tk_GetScrollInfoObj) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], double * dblPtr, int * intPtr)); /* 210 */
+ int (*tk_InitOptions) _ANSI_ARGS_((Tcl_Interp * interp, char * recordPtr, Tk_OptionTable optionToken, Tk_Window tkwin)); /* 211 */
+ void (*tk_MainEx) _ANSI_ARGS_((int argc, char ** argv, Tcl_AppInitProc * appInitProc, Tcl_Interp * interp)); /* 212 */
+ void (*tk_RestoreSavedOptions) _ANSI_ARGS_((Tk_SavedOptions * savePtr)); /* 213 */
+ int (*tk_SetOptions) _ANSI_ARGS_((Tcl_Interp * interp, char * recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *CONST objv[], Tk_Window tkwin, Tk_SavedOptions * savePtr, int * maskPtr)); /* 214 */
+ void (*tk_InitConsoleChannels) _ANSI_ARGS_((Tcl_Interp * interp)); /* 215 */
+ int (*tk_CreateConsoleWindow) _ANSI_ARGS_((Tcl_Interp * interp)); /* 216 */
+ void (*tk_CreateSmoothMethod) _ANSI_ARGS_((Tcl_Interp * interp, Tk_SmoothMethod * method)); /* 217 */
+ void *reserved218;
+ void *reserved219;
+ int (*tk_GetDash) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * value, Tk_Dash * dash)); /* 220 */
+ void (*tk_CreateOutline) _ANSI_ARGS_((Tk_Outline * outline)); /* 221 */
+ void (*tk_DeleteOutline) _ANSI_ARGS_((Display * display, Tk_Outline * outline)); /* 222 */
+ int (*tk_ConfigOutlineGC) _ANSI_ARGS_((XGCValues * gcValues, Tk_Canvas canvas, Tk_Item * item, Tk_Outline * outline)); /* 223 */
+ int (*tk_ChangeOutlineGC) _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item * item, Tk_Outline * outline)); /* 224 */
+ int (*tk_ResetOutlineGC) _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item * item, Tk_Outline * outline)); /* 225 */
+ int (*tk_CanvasPsOutline) _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item * item, Tk_Outline * outline)); /* 226 */
+ void (*tk_SetTSOrigin) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y)); /* 227 */
+ int (*tk_CanvasGetCoordFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, Tcl_Obj * obj, double * doublePtr)); /* 228 */
+ void (*tk_CanvasSetOffset) _ANSI_ARGS_((Tk_Canvas canvas, GC gc, Tk_TSOffset * offset)); /* 229 */
+ void (*tk_DitherPhoto) _ANSI_ARGS_((Tk_PhotoHandle handle, int x, int y, int width, int height)); /* 230 */
+ int (*tk_PostscriptBitmap) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap, int startX, int startY, int width, int height)); /* 231 */
+ int (*tk_PostscriptColor) _ANSI_ARGS_((Tcl_Interp * interp, Tk_PostscriptInfo psInfo, XColor * colorPtr)); /* 232 */
+ int (*tk_PostscriptFont) _ANSI_ARGS_((Tcl_Interp * interp, Tk_PostscriptInfo psInfo, Tk_Font font)); /* 233 */
+ int (*tk_PostscriptImage) _ANSI_ARGS_((Tk_Image image, Tcl_Interp * interp, Tk_Window tkwin, Tk_PostscriptInfo psinfo, int x, int y, int width, int height, int prepass)); /* 234 */
+ void (*tk_PostscriptPath) _ANSI_ARGS_((Tcl_Interp * interp, Tk_PostscriptInfo psInfo, double * coordPtr, int numPoints)); /* 235 */
+ int (*tk_PostscriptStipple) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo, Pixmap bitmap)); /* 236 */
+ double (*tk_PostscriptY) _ANSI_ARGS_((double y, Tk_PostscriptInfo psInfo)); /* 237 */
+ int (*tk_PostscriptPhoto) _ANSI_ARGS_((Tcl_Interp * interp, Tk_PhotoImageBlock * blockPtr, Tk_PostscriptInfo psInfo, int width, int height)); /* 238 */
+} TkStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern TkStubs *tkStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifndef Tk_MainLoop
+#define Tk_MainLoop \
+ (tkStubsPtr->tk_MainLoop) /* 0 */
+#endif
+#ifndef Tk_3DBorderColor
+#define Tk_3DBorderColor \
+ (tkStubsPtr->tk_3DBorderColor) /* 1 */
+#endif
+#ifndef Tk_3DBorderGC
+#define Tk_3DBorderGC \
+ (tkStubsPtr->tk_3DBorderGC) /* 2 */
+#endif
+#ifndef Tk_3DHorizontalBevel
+#define Tk_3DHorizontalBevel \
+ (tkStubsPtr->tk_3DHorizontalBevel) /* 3 */
+#endif
+#ifndef Tk_3DVerticalBevel
+#define Tk_3DVerticalBevel \
+ (tkStubsPtr->tk_3DVerticalBevel) /* 4 */
+#endif
+#ifndef Tk_AddOption
+#define Tk_AddOption \
+ (tkStubsPtr->tk_AddOption) /* 5 */
+#endif
+#ifndef Tk_BindEvent
+#define Tk_BindEvent \
+ (tkStubsPtr->tk_BindEvent) /* 6 */
+#endif
+#ifndef Tk_CanvasDrawableCoords
+#define Tk_CanvasDrawableCoords \
+ (tkStubsPtr->tk_CanvasDrawableCoords) /* 7 */
+#endif
+#ifndef Tk_CanvasEventuallyRedraw
+#define Tk_CanvasEventuallyRedraw \
+ (tkStubsPtr->tk_CanvasEventuallyRedraw) /* 8 */
+#endif
+#ifndef Tk_CanvasGetCoord
+#define Tk_CanvasGetCoord \
+ (tkStubsPtr->tk_CanvasGetCoord) /* 9 */
+#endif
+#ifndef Tk_CanvasGetTextInfo
+#define Tk_CanvasGetTextInfo \
+ (tkStubsPtr->tk_CanvasGetTextInfo) /* 10 */
+#endif
+#ifndef Tk_CanvasPsBitmap
+#define Tk_CanvasPsBitmap \
+ (tkStubsPtr->tk_CanvasPsBitmap) /* 11 */
+#endif
+#ifndef Tk_CanvasPsColor
+#define Tk_CanvasPsColor \
+ (tkStubsPtr->tk_CanvasPsColor) /* 12 */
+#endif
+#ifndef Tk_CanvasPsFont
+#define Tk_CanvasPsFont \
+ (tkStubsPtr->tk_CanvasPsFont) /* 13 */
+#endif
+#ifndef Tk_CanvasPsPath
+#define Tk_CanvasPsPath \
+ (tkStubsPtr->tk_CanvasPsPath) /* 14 */
+#endif
+#ifndef Tk_CanvasPsStipple
+#define Tk_CanvasPsStipple \
+ (tkStubsPtr->tk_CanvasPsStipple) /* 15 */
+#endif
+#ifndef Tk_CanvasPsY
+#define Tk_CanvasPsY \
+ (tkStubsPtr->tk_CanvasPsY) /* 16 */
+#endif
+#ifndef Tk_CanvasSetStippleOrigin
+#define Tk_CanvasSetStippleOrigin \
+ (tkStubsPtr->tk_CanvasSetStippleOrigin) /* 17 */
+#endif
+#ifndef Tk_CanvasTagsParseProc
+#define Tk_CanvasTagsParseProc \
+ (tkStubsPtr->tk_CanvasTagsParseProc) /* 18 */
+#endif
+#ifndef Tk_CanvasTagsPrintProc
+#define Tk_CanvasTagsPrintProc \
+ (tkStubsPtr->tk_CanvasTagsPrintProc) /* 19 */
+#endif
+#ifndef Tk_CanvasTkwin
+#define Tk_CanvasTkwin \
+ (tkStubsPtr->tk_CanvasTkwin) /* 20 */
+#endif
+#ifndef Tk_CanvasWindowCoords
+#define Tk_CanvasWindowCoords \
+ (tkStubsPtr->tk_CanvasWindowCoords) /* 21 */
+#endif
+#ifndef Tk_ChangeWindowAttributes
+#define Tk_ChangeWindowAttributes \
+ (tkStubsPtr->tk_ChangeWindowAttributes) /* 22 */
+#endif
+#ifndef Tk_CharBbox
+#define Tk_CharBbox \
+ (tkStubsPtr->tk_CharBbox) /* 23 */
+#endif
+#ifndef Tk_ClearSelection
+#define Tk_ClearSelection \
+ (tkStubsPtr->tk_ClearSelection) /* 24 */
+#endif
+#ifndef Tk_ClipboardAppend
+#define Tk_ClipboardAppend \
+ (tkStubsPtr->tk_ClipboardAppend) /* 25 */
+#endif
+#ifndef Tk_ClipboardClear
+#define Tk_ClipboardClear \
+ (tkStubsPtr->tk_ClipboardClear) /* 26 */
+#endif
+#ifndef Tk_ConfigureInfo
+#define Tk_ConfigureInfo \
+ (tkStubsPtr->tk_ConfigureInfo) /* 27 */
+#endif
+#ifndef Tk_ConfigureValue
+#define Tk_ConfigureValue \
+ (tkStubsPtr->tk_ConfigureValue) /* 28 */
+#endif
+#ifndef Tk_ConfigureWidget
+#define Tk_ConfigureWidget \
+ (tkStubsPtr->tk_ConfigureWidget) /* 29 */
+#endif
+#ifndef Tk_ConfigureWindow
+#define Tk_ConfigureWindow \
+ (tkStubsPtr->tk_ConfigureWindow) /* 30 */
+#endif
+#ifndef Tk_ComputeTextLayout
+#define Tk_ComputeTextLayout \
+ (tkStubsPtr->tk_ComputeTextLayout) /* 31 */
+#endif
+#ifndef Tk_CoordsToWindow
+#define Tk_CoordsToWindow \
+ (tkStubsPtr->tk_CoordsToWindow) /* 32 */
+#endif
+#ifndef Tk_CreateBinding
+#define Tk_CreateBinding \
+ (tkStubsPtr->tk_CreateBinding) /* 33 */
+#endif
+#ifndef Tk_CreateBindingTable
+#define Tk_CreateBindingTable \
+ (tkStubsPtr->tk_CreateBindingTable) /* 34 */
+#endif
+#ifndef Tk_CreateErrorHandler
+#define Tk_CreateErrorHandler \
+ (tkStubsPtr->tk_CreateErrorHandler) /* 35 */
+#endif
+#ifndef Tk_CreateEventHandler
+#define Tk_CreateEventHandler \
+ (tkStubsPtr->tk_CreateEventHandler) /* 36 */
+#endif
+#ifndef Tk_CreateGenericHandler
+#define Tk_CreateGenericHandler \
+ (tkStubsPtr->tk_CreateGenericHandler) /* 37 */
+#endif
+#ifndef Tk_CreateImageType
+#define Tk_CreateImageType \
+ (tkStubsPtr->tk_CreateImageType) /* 38 */
+#endif
+#ifndef Tk_CreateItemType
+#define Tk_CreateItemType \
+ (tkStubsPtr->tk_CreateItemType) /* 39 */
+#endif
+#ifndef Tk_CreatePhotoImageFormat
+#define Tk_CreatePhotoImageFormat \
+ (tkStubsPtr->tk_CreatePhotoImageFormat) /* 40 */
+#endif
+#ifndef Tk_CreateSelHandler
+#define Tk_CreateSelHandler \
+ (tkStubsPtr->tk_CreateSelHandler) /* 41 */
+#endif
+#ifndef Tk_CreateWindow
+#define Tk_CreateWindow \
+ (tkStubsPtr->tk_CreateWindow) /* 42 */
+#endif
+#ifndef Tk_CreateWindowFromPath
+#define Tk_CreateWindowFromPath \
+ (tkStubsPtr->tk_CreateWindowFromPath) /* 43 */
+#endif
+#ifndef Tk_DefineBitmap
+#define Tk_DefineBitmap \
+ (tkStubsPtr->tk_DefineBitmap) /* 44 */
+#endif
+#ifndef Tk_DefineCursor
+#define Tk_DefineCursor \
+ (tkStubsPtr->tk_DefineCursor) /* 45 */
+#endif
+#ifndef Tk_DeleteAllBindings
+#define Tk_DeleteAllBindings \
+ (tkStubsPtr->tk_DeleteAllBindings) /* 46 */
+#endif
+#ifndef Tk_DeleteBinding
+#define Tk_DeleteBinding \
+ (tkStubsPtr->tk_DeleteBinding) /* 47 */
+#endif
+#ifndef Tk_DeleteBindingTable
+#define Tk_DeleteBindingTable \
+ (tkStubsPtr->tk_DeleteBindingTable) /* 48 */
+#endif
+#ifndef Tk_DeleteErrorHandler
+#define Tk_DeleteErrorHandler \
+ (tkStubsPtr->tk_DeleteErrorHandler) /* 49 */
+#endif
+#ifndef Tk_DeleteEventHandler
+#define Tk_DeleteEventHandler \
+ (tkStubsPtr->tk_DeleteEventHandler) /* 50 */
+#endif
+#ifndef Tk_DeleteGenericHandler
+#define Tk_DeleteGenericHandler \
+ (tkStubsPtr->tk_DeleteGenericHandler) /* 51 */
+#endif
+#ifndef Tk_DeleteImage
+#define Tk_DeleteImage \
+ (tkStubsPtr->tk_DeleteImage) /* 52 */
+#endif
+#ifndef Tk_DeleteSelHandler
+#define Tk_DeleteSelHandler \
+ (tkStubsPtr->tk_DeleteSelHandler) /* 53 */
+#endif
+#ifndef Tk_DestroyWindow
+#define Tk_DestroyWindow \
+ (tkStubsPtr->tk_DestroyWindow) /* 54 */
+#endif
+#ifndef Tk_DisplayName
+#define Tk_DisplayName \
+ (tkStubsPtr->tk_DisplayName) /* 55 */
+#endif
+#ifndef Tk_DistanceToTextLayout
+#define Tk_DistanceToTextLayout \
+ (tkStubsPtr->tk_DistanceToTextLayout) /* 56 */
+#endif
+#ifndef Tk_Draw3DPolygon
+#define Tk_Draw3DPolygon \
+ (tkStubsPtr->tk_Draw3DPolygon) /* 57 */
+#endif
+#ifndef Tk_Draw3DRectangle
+#define Tk_Draw3DRectangle \
+ (tkStubsPtr->tk_Draw3DRectangle) /* 58 */
+#endif
+#ifndef Tk_DrawChars
+#define Tk_DrawChars \
+ (tkStubsPtr->tk_DrawChars) /* 59 */
+#endif
+#ifndef Tk_DrawFocusHighlight
+#define Tk_DrawFocusHighlight \
+ (tkStubsPtr->tk_DrawFocusHighlight) /* 60 */
+#endif
+#ifndef Tk_DrawTextLayout
+#define Tk_DrawTextLayout \
+ (tkStubsPtr->tk_DrawTextLayout) /* 61 */
+#endif
+#ifndef Tk_Fill3DPolygon
+#define Tk_Fill3DPolygon \
+ (tkStubsPtr->tk_Fill3DPolygon) /* 62 */
+#endif
+#ifndef Tk_Fill3DRectangle
+#define Tk_Fill3DRectangle \
+ (tkStubsPtr->tk_Fill3DRectangle) /* 63 */
+#endif
+#ifndef Tk_FindPhoto
+#define Tk_FindPhoto \
+ (tkStubsPtr->tk_FindPhoto) /* 64 */
+#endif
+#ifndef Tk_FontId
+#define Tk_FontId \
+ (tkStubsPtr->tk_FontId) /* 65 */
+#endif
+#ifndef Tk_Free3DBorder
+#define Tk_Free3DBorder \
+ (tkStubsPtr->tk_Free3DBorder) /* 66 */
+#endif
+#ifndef Tk_FreeBitmap
+#define Tk_FreeBitmap \
+ (tkStubsPtr->tk_FreeBitmap) /* 67 */
+#endif
+#ifndef Tk_FreeColor
+#define Tk_FreeColor \
+ (tkStubsPtr->tk_FreeColor) /* 68 */
+#endif
+#ifndef Tk_FreeColormap
+#define Tk_FreeColormap \
+ (tkStubsPtr->tk_FreeColormap) /* 69 */
+#endif
+#ifndef Tk_FreeCursor
+#define Tk_FreeCursor \
+ (tkStubsPtr->tk_FreeCursor) /* 70 */
+#endif
+#ifndef Tk_FreeFont
+#define Tk_FreeFont \
+ (tkStubsPtr->tk_FreeFont) /* 71 */
+#endif
+#ifndef Tk_FreeGC
+#define Tk_FreeGC \
+ (tkStubsPtr->tk_FreeGC) /* 72 */
+#endif
+#ifndef Tk_FreeImage
+#define Tk_FreeImage \
+ (tkStubsPtr->tk_FreeImage) /* 73 */
+#endif
+#ifndef Tk_FreeOptions
+#define Tk_FreeOptions \
+ (tkStubsPtr->tk_FreeOptions) /* 74 */
+#endif
+#ifndef Tk_FreePixmap
+#define Tk_FreePixmap \
+ (tkStubsPtr->tk_FreePixmap) /* 75 */
+#endif
+#ifndef Tk_FreeTextLayout
+#define Tk_FreeTextLayout \
+ (tkStubsPtr->tk_FreeTextLayout) /* 76 */
+#endif
+#ifndef Tk_FreeXId
+#define Tk_FreeXId \
+ (tkStubsPtr->tk_FreeXId) /* 77 */
+#endif
+#ifndef Tk_GCForColor
+#define Tk_GCForColor \
+ (tkStubsPtr->tk_GCForColor) /* 78 */
+#endif
+#ifndef Tk_GeometryRequest
+#define Tk_GeometryRequest \
+ (tkStubsPtr->tk_GeometryRequest) /* 79 */
+#endif
+#ifndef Tk_Get3DBorder
+#define Tk_Get3DBorder \
+ (tkStubsPtr->tk_Get3DBorder) /* 80 */
+#endif
+#ifndef Tk_GetAllBindings
+#define Tk_GetAllBindings \
+ (tkStubsPtr->tk_GetAllBindings) /* 81 */
+#endif
+#ifndef Tk_GetAnchor
+#define Tk_GetAnchor \
+ (tkStubsPtr->tk_GetAnchor) /* 82 */
+#endif
+#ifndef Tk_GetAtomName
+#define Tk_GetAtomName \
+ (tkStubsPtr->tk_GetAtomName) /* 83 */
+#endif
+#ifndef Tk_GetBinding
+#define Tk_GetBinding \
+ (tkStubsPtr->tk_GetBinding) /* 84 */
+#endif
+#ifndef Tk_GetBitmap
+#define Tk_GetBitmap \
+ (tkStubsPtr->tk_GetBitmap) /* 85 */
+#endif
+#ifndef Tk_GetBitmapFromData
+#define Tk_GetBitmapFromData \
+ (tkStubsPtr->tk_GetBitmapFromData) /* 86 */
+#endif
+#ifndef Tk_GetCapStyle
+#define Tk_GetCapStyle \
+ (tkStubsPtr->tk_GetCapStyle) /* 87 */
+#endif
+#ifndef Tk_GetColor
+#define Tk_GetColor \
+ (tkStubsPtr->tk_GetColor) /* 88 */
+#endif
+#ifndef Tk_GetColorByValue
+#define Tk_GetColorByValue \
+ (tkStubsPtr->tk_GetColorByValue) /* 89 */
+#endif
+#ifndef Tk_GetColormap
+#define Tk_GetColormap \
+ (tkStubsPtr->tk_GetColormap) /* 90 */
+#endif
+#ifndef Tk_GetCursor
+#define Tk_GetCursor \
+ (tkStubsPtr->tk_GetCursor) /* 91 */
+#endif
+#ifndef Tk_GetCursorFromData
+#define Tk_GetCursorFromData \
+ (tkStubsPtr->tk_GetCursorFromData) /* 92 */
+#endif
+#ifndef Tk_GetFont
+#define Tk_GetFont \
+ (tkStubsPtr->tk_GetFont) /* 93 */
+#endif
+#ifndef Tk_GetFontFromObj
+#define Tk_GetFontFromObj \
+ (tkStubsPtr->tk_GetFontFromObj) /* 94 */
+#endif
+#ifndef Tk_GetFontMetrics
+#define Tk_GetFontMetrics \
+ (tkStubsPtr->tk_GetFontMetrics) /* 95 */
+#endif
+#ifndef Tk_GetGC
+#define Tk_GetGC \
+ (tkStubsPtr->tk_GetGC) /* 96 */
+#endif
+#ifndef Tk_GetImage
+#define Tk_GetImage \
+ (tkStubsPtr->tk_GetImage) /* 97 */
+#endif
+#ifndef Tk_GetImageMasterData
+#define Tk_GetImageMasterData \
+ (tkStubsPtr->tk_GetImageMasterData) /* 98 */
+#endif
+#ifndef Tk_GetItemTypes
+#define Tk_GetItemTypes \
+ (tkStubsPtr->tk_GetItemTypes) /* 99 */
+#endif
+#ifndef Tk_GetJoinStyle
+#define Tk_GetJoinStyle \
+ (tkStubsPtr->tk_GetJoinStyle) /* 100 */
+#endif
+#ifndef Tk_GetJustify
+#define Tk_GetJustify \
+ (tkStubsPtr->tk_GetJustify) /* 101 */
+#endif
+#ifndef Tk_GetNumMainWindows
+#define Tk_GetNumMainWindows \
+ (tkStubsPtr->tk_GetNumMainWindows) /* 102 */
+#endif
+#ifndef Tk_GetOption
+#define Tk_GetOption \
+ (tkStubsPtr->tk_GetOption) /* 103 */
+#endif
+#ifndef Tk_GetPixels
+#define Tk_GetPixels \
+ (tkStubsPtr->tk_GetPixels) /* 104 */
+#endif
+#ifndef Tk_GetPixmap
+#define Tk_GetPixmap \
+ (tkStubsPtr->tk_GetPixmap) /* 105 */
+#endif
+#ifndef Tk_GetRelief
+#define Tk_GetRelief \
+ (tkStubsPtr->tk_GetRelief) /* 106 */
+#endif
+#ifndef Tk_GetRootCoords
+#define Tk_GetRootCoords \
+ (tkStubsPtr->tk_GetRootCoords) /* 107 */
+#endif
+#ifndef Tk_GetScrollInfo
+#define Tk_GetScrollInfo \
+ (tkStubsPtr->tk_GetScrollInfo) /* 108 */
+#endif
+#ifndef Tk_GetScreenMM
+#define Tk_GetScreenMM \
+ (tkStubsPtr->tk_GetScreenMM) /* 109 */
+#endif
+#ifndef Tk_GetSelection
+#define Tk_GetSelection \
+ (tkStubsPtr->tk_GetSelection) /* 110 */
+#endif
+#ifndef Tk_GetUid
+#define Tk_GetUid \
+ (tkStubsPtr->tk_GetUid) /* 111 */
+#endif
+#ifndef Tk_GetVisual
+#define Tk_GetVisual \
+ (tkStubsPtr->tk_GetVisual) /* 112 */
+#endif
+#ifndef Tk_GetVRootGeometry
+#define Tk_GetVRootGeometry \
+ (tkStubsPtr->tk_GetVRootGeometry) /* 113 */
+#endif
+#ifndef Tk_Grab
+#define Tk_Grab \
+ (tkStubsPtr->tk_Grab) /* 114 */
+#endif
+#ifndef Tk_HandleEvent
+#define Tk_HandleEvent \
+ (tkStubsPtr->tk_HandleEvent) /* 115 */
+#endif
+#ifndef Tk_IdToWindow
+#define Tk_IdToWindow \
+ (tkStubsPtr->tk_IdToWindow) /* 116 */
+#endif
+#ifndef Tk_ImageChanged
+#define Tk_ImageChanged \
+ (tkStubsPtr->tk_ImageChanged) /* 117 */
+#endif
+#ifndef Tk_Init
+#define Tk_Init \
+ (tkStubsPtr->tk_Init) /* 118 */
+#endif
+#ifndef Tk_InternAtom
+#define Tk_InternAtom \
+ (tkStubsPtr->tk_InternAtom) /* 119 */
+#endif
+#ifndef Tk_IntersectTextLayout
+#define Tk_IntersectTextLayout \
+ (tkStubsPtr->tk_IntersectTextLayout) /* 120 */
+#endif
+#ifndef Tk_MaintainGeometry
+#define Tk_MaintainGeometry \
+ (tkStubsPtr->tk_MaintainGeometry) /* 121 */
+#endif
+#ifndef Tk_MainWindow
+#define Tk_MainWindow \
+ (tkStubsPtr->tk_MainWindow) /* 122 */
+#endif
+#ifndef Tk_MakeWindowExist
+#define Tk_MakeWindowExist \
+ (tkStubsPtr->tk_MakeWindowExist) /* 123 */
+#endif
+#ifndef Tk_ManageGeometry
+#define Tk_ManageGeometry \
+ (tkStubsPtr->tk_ManageGeometry) /* 124 */
+#endif
+#ifndef Tk_MapWindow
+#define Tk_MapWindow \
+ (tkStubsPtr->tk_MapWindow) /* 125 */
+#endif
+#ifndef Tk_MeasureChars
+#define Tk_MeasureChars \
+ (tkStubsPtr->tk_MeasureChars) /* 126 */
+#endif
+#ifndef Tk_MoveResizeWindow
+#define Tk_MoveResizeWindow \
+ (tkStubsPtr->tk_MoveResizeWindow) /* 127 */
+#endif
+#ifndef Tk_MoveWindow
+#define Tk_MoveWindow \
+ (tkStubsPtr->tk_MoveWindow) /* 128 */
+#endif
+#ifndef Tk_MoveToplevelWindow
+#define Tk_MoveToplevelWindow \
+ (tkStubsPtr->tk_MoveToplevelWindow) /* 129 */
+#endif
+#ifndef Tk_NameOf3DBorder
+#define Tk_NameOf3DBorder \
+ (tkStubsPtr->tk_NameOf3DBorder) /* 130 */
+#endif
+#ifndef Tk_NameOfAnchor
+#define Tk_NameOfAnchor \
+ (tkStubsPtr->tk_NameOfAnchor) /* 131 */
+#endif
+#ifndef Tk_NameOfBitmap
+#define Tk_NameOfBitmap \
+ (tkStubsPtr->tk_NameOfBitmap) /* 132 */
+#endif
+#ifndef Tk_NameOfCapStyle
+#define Tk_NameOfCapStyle \
+ (tkStubsPtr->tk_NameOfCapStyle) /* 133 */
+#endif
+#ifndef Tk_NameOfColor
+#define Tk_NameOfColor \
+ (tkStubsPtr->tk_NameOfColor) /* 134 */
+#endif
+#ifndef Tk_NameOfCursor
+#define Tk_NameOfCursor \
+ (tkStubsPtr->tk_NameOfCursor) /* 135 */
+#endif
+#ifndef Tk_NameOfFont
+#define Tk_NameOfFont \
+ (tkStubsPtr->tk_NameOfFont) /* 136 */
+#endif
+#ifndef Tk_NameOfImage
+#define Tk_NameOfImage \
+ (tkStubsPtr->tk_NameOfImage) /* 137 */
+#endif
+#ifndef Tk_NameOfJoinStyle
+#define Tk_NameOfJoinStyle \
+ (tkStubsPtr->tk_NameOfJoinStyle) /* 138 */
+#endif
+#ifndef Tk_NameOfJustify
+#define Tk_NameOfJustify \
+ (tkStubsPtr->tk_NameOfJustify) /* 139 */
+#endif
+#ifndef Tk_NameOfRelief
+#define Tk_NameOfRelief \
+ (tkStubsPtr->tk_NameOfRelief) /* 140 */
+#endif
+#ifndef Tk_NameToWindow
+#define Tk_NameToWindow \
+ (tkStubsPtr->tk_NameToWindow) /* 141 */
+#endif
+#ifndef Tk_OwnSelection
+#define Tk_OwnSelection \
+ (tkStubsPtr->tk_OwnSelection) /* 142 */
+#endif
+#ifndef Tk_ParseArgv
+#define Tk_ParseArgv \
+ (tkStubsPtr->tk_ParseArgv) /* 143 */
+#endif
+#ifndef Tk_PhotoPutBlock
+#define Tk_PhotoPutBlock \
+ (tkStubsPtr->tk_PhotoPutBlock) /* 144 */
+#endif
+#ifndef Tk_PhotoPutZoomedBlock
+#define Tk_PhotoPutZoomedBlock \
+ (tkStubsPtr->tk_PhotoPutZoomedBlock) /* 145 */
+#endif
+#ifndef Tk_PhotoGetImage
+#define Tk_PhotoGetImage \
+ (tkStubsPtr->tk_PhotoGetImage) /* 146 */
+#endif
+#ifndef Tk_PhotoBlank
+#define Tk_PhotoBlank \
+ (tkStubsPtr->tk_PhotoBlank) /* 147 */
+#endif
+#ifndef Tk_PhotoExpand
+#define Tk_PhotoExpand \
+ (tkStubsPtr->tk_PhotoExpand) /* 148 */
+#endif
+#ifndef Tk_PhotoGetSize
+#define Tk_PhotoGetSize \
+ (tkStubsPtr->tk_PhotoGetSize) /* 149 */
+#endif
+#ifndef Tk_PhotoSetSize
+#define Tk_PhotoSetSize \
+ (tkStubsPtr->tk_PhotoSetSize) /* 150 */
+#endif
+#ifndef Tk_PointToChar
+#define Tk_PointToChar \
+ (tkStubsPtr->tk_PointToChar) /* 151 */
+#endif
+#ifndef Tk_PostscriptFontName
+#define Tk_PostscriptFontName \
+ (tkStubsPtr->tk_PostscriptFontName) /* 152 */
+#endif
+#ifndef Tk_PreserveColormap
+#define Tk_PreserveColormap \
+ (tkStubsPtr->tk_PreserveColormap) /* 153 */
+#endif
+#ifndef Tk_QueueWindowEvent
+#define Tk_QueueWindowEvent \
+ (tkStubsPtr->tk_QueueWindowEvent) /* 154 */
+#endif
+#ifndef Tk_RedrawImage
+#define Tk_RedrawImage \
+ (tkStubsPtr->tk_RedrawImage) /* 155 */
+#endif
+#ifndef Tk_ResizeWindow
+#define Tk_ResizeWindow \
+ (tkStubsPtr->tk_ResizeWindow) /* 156 */
+#endif
+#ifndef Tk_RestackWindow
+#define Tk_RestackWindow \
+ (tkStubsPtr->tk_RestackWindow) /* 157 */
+#endif
+#ifndef Tk_RestrictEvents
+#define Tk_RestrictEvents \
+ (tkStubsPtr->tk_RestrictEvents) /* 158 */
+#endif
+#ifndef Tk_SafeInit
+#define Tk_SafeInit \
+ (tkStubsPtr->tk_SafeInit) /* 159 */
+#endif
+#ifndef Tk_SetAppName
+#define Tk_SetAppName \
+ (tkStubsPtr->tk_SetAppName) /* 160 */
+#endif
+#ifndef Tk_SetBackgroundFromBorder
+#define Tk_SetBackgroundFromBorder \
+ (tkStubsPtr->tk_SetBackgroundFromBorder) /* 161 */
+#endif
+#ifndef Tk_SetClass
+#define Tk_SetClass \
+ (tkStubsPtr->tk_SetClass) /* 162 */
+#endif
+#ifndef Tk_SetGrid
+#define Tk_SetGrid \
+ (tkStubsPtr->tk_SetGrid) /* 163 */
+#endif
+#ifndef Tk_SetInternalBorder
+#define Tk_SetInternalBorder \
+ (tkStubsPtr->tk_SetInternalBorder) /* 164 */
+#endif
+#ifndef Tk_SetWindowBackground
+#define Tk_SetWindowBackground \
+ (tkStubsPtr->tk_SetWindowBackground) /* 165 */
+#endif
+#ifndef Tk_SetWindowBackgroundPixmap
+#define Tk_SetWindowBackgroundPixmap \
+ (tkStubsPtr->tk_SetWindowBackgroundPixmap) /* 166 */
+#endif
+#ifndef Tk_SetWindowBorder
+#define Tk_SetWindowBorder \
+ (tkStubsPtr->tk_SetWindowBorder) /* 167 */
+#endif
+#ifndef Tk_SetWindowBorderWidth
+#define Tk_SetWindowBorderWidth \
+ (tkStubsPtr->tk_SetWindowBorderWidth) /* 168 */
+#endif
+#ifndef Tk_SetWindowBorderPixmap
+#define Tk_SetWindowBorderPixmap \
+ (tkStubsPtr->tk_SetWindowBorderPixmap) /* 169 */
+#endif
+#ifndef Tk_SetWindowColormap
+#define Tk_SetWindowColormap \
+ (tkStubsPtr->tk_SetWindowColormap) /* 170 */
+#endif
+#ifndef Tk_SetWindowVisual
+#define Tk_SetWindowVisual \
+ (tkStubsPtr->tk_SetWindowVisual) /* 171 */
+#endif
+#ifndef Tk_SizeOfBitmap
+#define Tk_SizeOfBitmap \
+ (tkStubsPtr->tk_SizeOfBitmap) /* 172 */
+#endif
+#ifndef Tk_SizeOfImage
+#define Tk_SizeOfImage \
+ (tkStubsPtr->tk_SizeOfImage) /* 173 */
+#endif
+#ifndef Tk_StrictMotif
+#define Tk_StrictMotif \
+ (tkStubsPtr->tk_StrictMotif) /* 174 */
+#endif
+#ifndef Tk_TextLayoutToPostscript
+#define Tk_TextLayoutToPostscript \
+ (tkStubsPtr->tk_TextLayoutToPostscript) /* 175 */
+#endif
+#ifndef Tk_TextWidth
+#define Tk_TextWidth \
+ (tkStubsPtr->tk_TextWidth) /* 176 */
+#endif
+#ifndef Tk_UndefineCursor
+#define Tk_UndefineCursor \
+ (tkStubsPtr->tk_UndefineCursor) /* 177 */
+#endif
+#ifndef Tk_UnderlineChars
+#define Tk_UnderlineChars \
+ (tkStubsPtr->tk_UnderlineChars) /* 178 */
+#endif
+#ifndef Tk_UnderlineTextLayout
+#define Tk_UnderlineTextLayout \
+ (tkStubsPtr->tk_UnderlineTextLayout) /* 179 */
+#endif
+#ifndef Tk_Ungrab
+#define Tk_Ungrab \
+ (tkStubsPtr->tk_Ungrab) /* 180 */
+#endif
+#ifndef Tk_UnmaintainGeometry
+#define Tk_UnmaintainGeometry \
+ (tkStubsPtr->tk_UnmaintainGeometry) /* 181 */
+#endif
+#ifndef Tk_UnmapWindow
+#define Tk_UnmapWindow \
+ (tkStubsPtr->tk_UnmapWindow) /* 182 */
+#endif
+#ifndef Tk_UnsetGrid
+#define Tk_UnsetGrid \
+ (tkStubsPtr->tk_UnsetGrid) /* 183 */
+#endif
+#ifndef Tk_UpdatePointer
+#define Tk_UpdatePointer \
+ (tkStubsPtr->tk_UpdatePointer) /* 184 */
+#endif
+#ifndef Tk_AllocBitmapFromObj
+#define Tk_AllocBitmapFromObj \
+ (tkStubsPtr->tk_AllocBitmapFromObj) /* 185 */
+#endif
+#ifndef Tk_Alloc3DBorderFromObj
+#define Tk_Alloc3DBorderFromObj \
+ (tkStubsPtr->tk_Alloc3DBorderFromObj) /* 186 */
+#endif
+#ifndef Tk_AllocColorFromObj
+#define Tk_AllocColorFromObj \
+ (tkStubsPtr->tk_AllocColorFromObj) /* 187 */
+#endif
+#ifndef Tk_AllocCursorFromObj
+#define Tk_AllocCursorFromObj \
+ (tkStubsPtr->tk_AllocCursorFromObj) /* 188 */
+#endif
+#ifndef Tk_AllocFontFromObj
+#define Tk_AllocFontFromObj \
+ (tkStubsPtr->tk_AllocFontFromObj) /* 189 */
+#endif
+#ifndef Tk_CreateOptionTable
+#define Tk_CreateOptionTable \
+ (tkStubsPtr->tk_CreateOptionTable) /* 190 */
+#endif
+#ifndef Tk_DeleteOptionTable
+#define Tk_DeleteOptionTable \
+ (tkStubsPtr->tk_DeleteOptionTable) /* 191 */
+#endif
+#ifndef Tk_Free3DBorderFromObj
+#define Tk_Free3DBorderFromObj \
+ (tkStubsPtr->tk_Free3DBorderFromObj) /* 192 */
+#endif
+#ifndef Tk_FreeBitmapFromObj
+#define Tk_FreeBitmapFromObj \
+ (tkStubsPtr->tk_FreeBitmapFromObj) /* 193 */
+#endif
+#ifndef Tk_FreeColorFromObj
+#define Tk_FreeColorFromObj \
+ (tkStubsPtr->tk_FreeColorFromObj) /* 194 */
+#endif
+#ifndef Tk_FreeConfigOptions
+#define Tk_FreeConfigOptions \
+ (tkStubsPtr->tk_FreeConfigOptions) /* 195 */
+#endif
+#ifndef Tk_FreeSavedOptions
+#define Tk_FreeSavedOptions \
+ (tkStubsPtr->tk_FreeSavedOptions) /* 196 */
+#endif
+#ifndef Tk_FreeCursorFromObj
+#define Tk_FreeCursorFromObj \
+ (tkStubsPtr->tk_FreeCursorFromObj) /* 197 */
+#endif
+#ifndef Tk_FreeFontFromObj
+#define Tk_FreeFontFromObj \
+ (tkStubsPtr->tk_FreeFontFromObj) /* 198 */
+#endif
+#ifndef Tk_Get3DBorderFromObj
+#define Tk_Get3DBorderFromObj \
+ (tkStubsPtr->tk_Get3DBorderFromObj) /* 199 */
+#endif
+#ifndef Tk_GetAnchorFromObj
+#define Tk_GetAnchorFromObj \
+ (tkStubsPtr->tk_GetAnchorFromObj) /* 200 */
+#endif
+#ifndef Tk_GetBitmapFromObj
+#define Tk_GetBitmapFromObj \
+ (tkStubsPtr->tk_GetBitmapFromObj) /* 201 */
+#endif
+#ifndef Tk_GetColorFromObj
+#define Tk_GetColorFromObj \
+ (tkStubsPtr->tk_GetColorFromObj) /* 202 */
+#endif
+#ifndef Tk_GetCursorFromObj
+#define Tk_GetCursorFromObj \
+ (tkStubsPtr->tk_GetCursorFromObj) /* 203 */
+#endif
+#ifndef Tk_GetOptionInfo
+#define Tk_GetOptionInfo \
+ (tkStubsPtr->tk_GetOptionInfo) /* 204 */
+#endif
+#ifndef Tk_GetOptionValue
+#define Tk_GetOptionValue \
+ (tkStubsPtr->tk_GetOptionValue) /* 205 */
+#endif
+#ifndef Tk_GetJustifyFromObj
+#define Tk_GetJustifyFromObj \
+ (tkStubsPtr->tk_GetJustifyFromObj) /* 206 */
+#endif
+#ifndef Tk_GetMMFromObj
+#define Tk_GetMMFromObj \
+ (tkStubsPtr->tk_GetMMFromObj) /* 207 */
+#endif
+#ifndef Tk_GetPixelsFromObj
+#define Tk_GetPixelsFromObj \
+ (tkStubsPtr->tk_GetPixelsFromObj) /* 208 */
+#endif
+#ifndef Tk_GetReliefFromObj
+#define Tk_GetReliefFromObj \
+ (tkStubsPtr->tk_GetReliefFromObj) /* 209 */
+#endif
+#ifndef Tk_GetScrollInfoObj
+#define Tk_GetScrollInfoObj \
+ (tkStubsPtr->tk_GetScrollInfoObj) /* 210 */
+#endif
+#ifndef Tk_InitOptions
+#define Tk_InitOptions \
+ (tkStubsPtr->tk_InitOptions) /* 211 */
+#endif
+#ifndef Tk_MainEx
+#define Tk_MainEx \
+ (tkStubsPtr->tk_MainEx) /* 212 */
+#endif
+#ifndef Tk_RestoreSavedOptions
+#define Tk_RestoreSavedOptions \
+ (tkStubsPtr->tk_RestoreSavedOptions) /* 213 */
+#endif
+#ifndef Tk_SetOptions
+#define Tk_SetOptions \
+ (tkStubsPtr->tk_SetOptions) /* 214 */
+#endif
+#ifndef Tk_InitConsoleChannels
+#define Tk_InitConsoleChannels \
+ (tkStubsPtr->tk_InitConsoleChannels) /* 215 */
+#endif
+#ifndef Tk_CreateConsoleWindow
+#define Tk_CreateConsoleWindow \
+ (tkStubsPtr->tk_CreateConsoleWindow) /* 216 */
+#endif
+#ifndef Tk_CreateSmoothMethod
+#define Tk_CreateSmoothMethod \
+ (tkStubsPtr->tk_CreateSmoothMethod) /* 217 */
+#endif
+/* Slot 218 is reserved */
+/* Slot 219 is reserved */
+#ifndef Tk_GetDash
+#define Tk_GetDash \
+ (tkStubsPtr->tk_GetDash) /* 220 */
+#endif
+#ifndef Tk_CreateOutline
+#define Tk_CreateOutline \
+ (tkStubsPtr->tk_CreateOutline) /* 221 */
+#endif
+#ifndef Tk_DeleteOutline
+#define Tk_DeleteOutline \
+ (tkStubsPtr->tk_DeleteOutline) /* 222 */
+#endif
+#ifndef Tk_ConfigOutlineGC
+#define Tk_ConfigOutlineGC \
+ (tkStubsPtr->tk_ConfigOutlineGC) /* 223 */
+#endif
+#ifndef Tk_ChangeOutlineGC
+#define Tk_ChangeOutlineGC \
+ (tkStubsPtr->tk_ChangeOutlineGC) /* 224 */
+#endif
+#ifndef Tk_ResetOutlineGC
+#define Tk_ResetOutlineGC \
+ (tkStubsPtr->tk_ResetOutlineGC) /* 225 */
+#endif
+#ifndef Tk_CanvasPsOutline
+#define Tk_CanvasPsOutline \
+ (tkStubsPtr->tk_CanvasPsOutline) /* 226 */
+#endif
+#ifndef Tk_SetTSOrigin
+#define Tk_SetTSOrigin \
+ (tkStubsPtr->tk_SetTSOrigin) /* 227 */
+#endif
+#ifndef Tk_CanvasGetCoordFromObj
+#define Tk_CanvasGetCoordFromObj \
+ (tkStubsPtr->tk_CanvasGetCoordFromObj) /* 228 */
+#endif
+#ifndef Tk_CanvasSetOffset
+#define Tk_CanvasSetOffset \
+ (tkStubsPtr->tk_CanvasSetOffset) /* 229 */
+#endif
+#ifndef Tk_DitherPhoto
+#define Tk_DitherPhoto \
+ (tkStubsPtr->tk_DitherPhoto) /* 230 */
+#endif
+#ifndef Tk_PostscriptBitmap
+#define Tk_PostscriptBitmap \
+ (tkStubsPtr->tk_PostscriptBitmap) /* 231 */
+#endif
+#ifndef Tk_PostscriptColor
+#define Tk_PostscriptColor \
+ (tkStubsPtr->tk_PostscriptColor) /* 232 */
+#endif
+#ifndef Tk_PostscriptFont
+#define Tk_PostscriptFont \
+ (tkStubsPtr->tk_PostscriptFont) /* 233 */
+#endif
+#ifndef Tk_PostscriptImage
+#define Tk_PostscriptImage \
+ (tkStubsPtr->tk_PostscriptImage) /* 234 */
+#endif
+#ifndef Tk_PostscriptPath
+#define Tk_PostscriptPath \
+ (tkStubsPtr->tk_PostscriptPath) /* 235 */
+#endif
+#ifndef Tk_PostscriptStipple
+#define Tk_PostscriptStipple \
+ (tkStubsPtr->tk_PostscriptStipple) /* 236 */
+#endif
+#ifndef Tk_PostscriptY
+#define Tk_PostscriptY \
+ (tkStubsPtr->tk_PostscriptY) /* 237 */
+#endif
+#ifndef Tk_PostscriptPhoto
+#define Tk_PostscriptPhoto \
+ (tkStubsPtr->tk_PostscriptPhoto) /* 238 */
+#endif
+
+#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKDECLS */
+
+
diff --git a/tk/generic/tkEntry.c b/tk/generic/tkEntry.c
index 86da2fd92e2..6ed11d6f9b7 100644
--- a/tk/generic/tkEntry.c
+++ b/tk/generic/tkEntry.c
@@ -6,7 +6,7 @@
* 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.
@@ -32,6 +32,9 @@ typedef struct {
* freed even after tkwin has gone away. */
Tcl_Interp *interp; /* Interpreter associated with entry. */
Tcl_Command widgetCmd; /* Token for entry's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+
/*
* Fields that are set by widget commands other than "configure".
@@ -39,17 +42,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 +63,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.
@@ -99,7 +102,7 @@ typedef struct {
char *showChar; /* Value of -show option. If non-NULL, first
* character is used for displaying all
* characters in entry. Malloc'ed. */
- Tk_Uid state; /* Normal or disabled. Entry is read-only
+ int state; /* Normal or disabled. Entry is read-only
* when disabled. */
char *textVarName; /* Name of variable (malloc'ed) or NULL.
* If non-NULL, entry's string tracks the
@@ -118,20 +121,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. */
@@ -141,6 +151,14 @@ typedef struct {
int avgWidth; /* Width of average character. */
int flags; /* Miscellaneous flags; see below for
* definitions. */
+ Tk_TSOffset tsoffset;
+
+ char *validateCmd; /* Command prefix to use when invoking
+ * validate command. NULL means don't
+ * invoke commands. Malloc'ed. */
+ int validate; /* Non-zero means try to validate */
+ char *invalidCmd; /* Command called when a validation returns 0
+ * (successfully fails), defaults to {}. */
} Entry;
/*
@@ -159,6 +177,12 @@ typedef struct {
* UPDATE_SCROLLBAR: Non-zero means scrollbar should be updated
* during next redisplay operation.
* GOT_SELECTION: Non-zero means we've claimed the selection.
+ * ENTRY_DELETED: This entry has been effectively destroyed.
+ * VALIDATING: Non-zero means we are in a validateCmd
+ * VALIDATE_VAR: Non-zero means we are attempting to validate
+ * the entry's textvariable with validateCmd
+ * VALIDATE_ABORT: Non-zero if validatecommand signals an abort
+ * for current procedure and make no changes
*/
#define REDRAW_PENDING 1
@@ -167,6 +191,10 @@ typedef struct {
#define GOT_FOCUS 8
#define UPDATE_SCROLLBAR 0x10
#define GOT_SELECTION 0x20
+#define ENTRY_DELETED 0x40
+#define VALIDATING 0x80
+#define VALIDATE_VAR 0x100
+#define VALIDATE_ABORT 0x200
/*
* The following macro defines how many extra pixels to leave on each
@@ -177,93 +205,139 @@ typedef struct {
#define YPAD 1
/*
+ * The following enum is used to define a type for the -state option
+ * of the Entry widget. These values are used as indices into the
+ * string table below.
+ */
+
+enum state {
+ STATE_DISABLED, STATE_NORMAL
+};
+
+static char *stateStrings[] = {
+ "disabled", "normal", (char *) NULL
+};
+
+/*
+ * Definitions for -validate option values:
+ */
+
+static char *validateStrings[] = {
+ "all", "key", "focus", "focusin", "focusout", "none", (char *) NULL
+};
+enum validateType {
+ VALIDATE_ALL, VALIDATE_KEY, VALIDATE_FOCUS,
+ VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT, VALIDATE_NONE,
+ /*
+ * These extra enums are for use with EntryValidateChange
+ */
+ VALIDATE_FORCED, VALIDATE_DELETE, VALIDATE_INSERT
+};
+#define DEF_ENTRY_VALIDATE "none"
+#define DEF_ENTRY_INVALIDCMD ""
+
+/*
* Information used for argv parsing.
*/
-static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_ENTRY_BG_COLOR, Tk_Offset(Entry, normalBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_ENTRY_BG_MONO, Tk_Offset(Entry, normalBorder),
- 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_ENTRY_BORDER_WIDTH, Tk_Offset(Entry, borderWidth), 0},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_ENTRY_CURSOR, Tk_Offset(Entry, cursor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection",
- "ExportSelection", DEF_ENTRY_EXPORT_SELECTION,
- Tk_Offset(Entry, exportSelection), 0},
- {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_FONT, "-font", "font", "Font",
- DEF_ENTRY_FONT, Tk_Offset(Entry, tkfont), 0},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_ENTRY_FG, Tk_Offset(Entry, fgColorPtr), 0},
- {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
+static Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
+ 0, (ClientData) DEF_ENTRY_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth),
+ 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
+ Tk_Offset(Entry, exportSelection), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0,
+ 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
"HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
- Tk_Offset(Entry, highlightBgColorPtr), 0},
- {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_ENTRY_HIGHLIGHT, Tk_Offset(Entry, highlightColorPtr), 0},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness",
- DEF_ENTRY_HIGHLIGHT_WIDTH, Tk_Offset(Entry, highlightWidth), 0},
- {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground",
- DEF_ENTRY_INSERT_BG, Tk_Offset(Entry, insertBorder), 0},
- {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
- DEF_ENTRY_INSERT_BD_COLOR, Tk_Offset(Entry, insertBorderWidth),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
- DEF_ENTRY_INSERT_BD_MONO, Tk_Offset(Entry, insertBorderWidth),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
- DEF_ENTRY_INSERT_OFF_TIME, Tk_Offset(Entry, insertOffTime), 0},
- {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
- DEF_ENTRY_INSERT_ON_TIME, Tk_Offset(Entry, insertOnTime), 0},
- {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
- DEF_ENTRY_INSERT_WIDTH, Tk_Offset(Entry, insertWidth), 0},
- {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
- DEF_ENTRY_JUSTIFY, Tk_Offset(Entry, justify), 0},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_ENTRY_RELIEF, Tk_Offset(Entry, relief), 0},
- {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_ENTRY_SELECT_COLOR, Tk_Offset(Entry, selBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_ENTRY_SELECT_MONO, Tk_Offset(Entry, selBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
- DEF_ENTRY_SELECT_BD_COLOR, Tk_Offset(Entry, selBorderWidth),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
- DEF_ENTRY_SELECT_BD_MONO, Tk_Offset(Entry, selBorderWidth),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_ENTRY_SELECT_FG_COLOR, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_ENTRY_SELECT_FG_MONO, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_STRING, "-show", "show", "Show",
- DEF_ENTRY_SHOW, Tk_Offset(Entry, showChar), TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-state", "state", "State",
- DEF_ENTRY_STATE, Tk_Offset(Entry, state), 0},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_ENTRY_TAKE_FOCUS, Tk_Offset(Entry, takeFocus), TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-textvariable", "textVariable", "Variable",
- DEF_ENTRY_TEXT_VARIABLE, Tk_Offset(Entry, textVarName),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_INT, "-width", "width", "Width",
- DEF_ENTRY_WIDTH, Tk_Offset(Entry, prefWidth), 0},
- {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- DEF_ENTRY_SCROLL_COMMAND, Tk_Offset(Entry, scrollCmd),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+ -1, Tk_Offset(Entry, highlightBgColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Entry, highlightWidth), 0, 0, 0},
+ {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
+ DEF_ENTRY_INSERT_BG,
+ -1, Tk_Offset(Entry, insertBorder),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
+ "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
+ Tk_Offset(Entry, insertBorderWidth), 0,
+ (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
+ {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
+ DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
+ DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
+ DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth),
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
+ DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-invcmd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief),
+ 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
+ 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
+ Tk_Offset(Entry, selBorderWidth),
+ 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
+ 0, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
+ {TK_OPTION_STRING, "-show", "show", "Show",
+ DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
+ 0, (ClientData) stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
+ DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
+ 0, (ClientData) validateStrings, 0},
+ {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand",
+ (char *) NULL, -1, Tk_Offset(Entry, validateCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-vcmd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-validatecommand", 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, 0, 0}
};
/*
@@ -274,12 +348,38 @@ static Tk_ConfigSpec configSpecs[] = {
#define LAST_PLUS_ONE_OK 2
/*
+ * The following tables define the entry widget commands (and sub-
+ * commands) and map the indexes into the string tables into
+ * enumerated types used to dispatch the entry widget command.
+ */
+
+static char *commandNames[] = {
+ "bbox", "cget", "configure", "delete", "get", "icursor", "index",
+ "insert", "scan", "selection", "validate", "xview", (char *) NULL
+};
+
+enum command {
+ COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE,
+ COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT,
+ COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW
+};
+
+static char *selCommandNames[] = {
+ "adjust", "clear", "from", "present", "range", "to", (char *) NULL
+};
+
+enum selcommand {
+ SELECTION_ADJUST, SELECTION_CLEAR, SELECTION_FROM,
+ SELECTION_PRESENT, SELECTION_RANGE, SELECTION_TO
+};
+
+/*
* Forward declarations for procedures defined later in this file:
*/
static int ConfigureEntry _ANSI_ARGS_((Tcl_Interp *interp,
- Entry *entryPtr, int argc, char **argv,
- int flags));
+ Entry *entryPtr, int objc,
+ Tcl_Obj *CONST objv[], int flags));
static void DeleteChars _ANSI_ARGS_((Entry *entryPtr, int index,
int count));
static void DestroyEntry _ANSI_ARGS_((char *memPtr));
@@ -306,11 +406,19 @@ static char * EntryTextVarProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, char *name1, char *name2,
int flags));
static void EntryUpdateScrollbar _ANSI_ARGS_((Entry *entryPtr));
+static int EntryValidate _ANSI_ARGS_((Entry *entryPtr,
+ char *cmd));
+static int EntryValidateChange _ANSI_ARGS_((Entry *entryPtr,
+ char *change, char *new, int index, int type));
+static void ExpandPercents _ANSI_ARGS_((Entry *entryPtr,
+ char *before, char *change, char *new,
+ int index, int type, Tcl_DString *dsPtr));
static void EntryValueChanged _ANSI_ARGS_((Entry *entryPtr));
static void EntryVisibleRange _ANSI_ARGS_((Entry *entryPtr,
double *firstPtr, double *lastPtr));
-static int EntryWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+static int EntryWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
static void EntryWorldChanged _ANSI_ARGS_((
ClientData instanceData));
static int GetEntryIndex _ANSI_ARGS_((Tcl_Interp *interp,
@@ -333,7 +441,7 @@ static TkClassProcs entryClass = {
/*
*--------------------------------------------------------------
*
- * Tk_EntryCmd --
+ * Tk_EntryObjCmd --
*
* This procedure is invoked to process the "entry" Tcl
* command. See the user documentation for details on what
@@ -349,25 +457,43 @@ static TkClassProcs entryClass = {
*/
int
-Tk_EntryCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_EntryObjCmd(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 objects. */
{
- Tk_Window tkwin = (Tk_Window) clientData;
register Entry *entryPtr;
- Tk_Window new;
+ 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.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+ name = Tcl_GetString(objv[0]);
+ Tcl_GetCommandInfo(interp, name, &info);
+ info.objClientData = (ClientData) optionTable;
+ Tcl_SetCommandInfo(interp, name, &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;
}
- 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;
}
@@ -377,62 +503,67 @@ Tk_EntryCmd(clientData, interp, argc, argv)
* initialized already (e.g. resource pointers).
*/
- entryPtr = (Entry *) ckalloc(sizeof(Entry));
- entryPtr->tkwin = new;
- entryPtr->display = Tk_Display(new);
- entryPtr->interp = interp;
- entryPtr->widgetCmd = Tcl_CreateCommand(interp,
- Tk_PathName(entryPtr->tkwin), EntryWidgetCmd,
+ entryPtr = (Entry *) ckalloc(sizeof(Entry));
+ entryPtr->tkwin = tkwin;
+ entryPtr->display = Tk_Display(tkwin);
+ entryPtr->interp = interp;
+ entryPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(entryPtr->tkwin), EntryWidgetObjCmd,
(ClientData) entryPtr, EntryCmdDeletedProc);
- entryPtr->string = (char *) ckalloc(1);
- entryPtr->string[0] = '\0';
- entryPtr->insertPos = 0;
- entryPtr->selectFirst = -1;
- entryPtr->selectLast = -1;
- entryPtr->selectAnchor = 0;
- entryPtr->scanMarkX = 0;
- entryPtr->scanMarkIndex = 0;
-
- entryPtr->normalBorder = NULL;
- entryPtr->borderWidth = 0;
- entryPtr->cursor = None;
- entryPtr->exportSelection = 1;
- entryPtr->tkfont = NULL;
- entryPtr->fgColorPtr = NULL;
- entryPtr->highlightBgColorPtr = NULL;
- entryPtr->highlightColorPtr = NULL;
- entryPtr->highlightWidth = 0;
- entryPtr->insertBorder = NULL;
- entryPtr->insertBorderWidth = 0;
- entryPtr->insertOffTime = 0;
- entryPtr->insertOnTime = 0;
- entryPtr->insertWidth = 0;
- entryPtr->justify = TK_JUSTIFY_LEFT;
- entryPtr->relief = TK_RELIEF_FLAT;
- entryPtr->selBorder = NULL;
- entryPtr->selBorderWidth = 0;
- entryPtr->selFgColorPtr = NULL;
- entryPtr->showChar = NULL;
- entryPtr->state = tkNormalUid;
- entryPtr->textVarName = NULL;
- entryPtr->takeFocus = NULL;
- entryPtr->prefWidth = 0;
- entryPtr->scrollCmd = NULL;
-
- entryPtr->numChars = 0;
- entryPtr->displayString = NULL;
- entryPtr->inset = XPAD;
- entryPtr->textLayout = NULL;
- entryPtr->layoutX = 0;
- entryPtr->layoutY = 0;
- entryPtr->leftIndex = 0;
- entryPtr->leftX = 0;
- entryPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
- entryPtr->textGC = None;
- entryPtr->selTextGC = None;
- entryPtr->highlightGC = None;
- entryPtr->avgWidth = 1;
- entryPtr->flags = 0;
+ entryPtr->optionTable = optionTable;
+ entryPtr->string = (char *) ckalloc(1);
+ entryPtr->string[0] = '\0';
+ entryPtr->insertPos = 0;
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ entryPtr->selectAnchor = 0;
+ entryPtr->scanMarkX = 0;
+ entryPtr->scanMarkIndex = 0;
+
+ entryPtr->normalBorder = NULL;
+ entryPtr->borderWidth = 0;
+ entryPtr->cursor = None;
+ entryPtr->exportSelection = 1;
+ entryPtr->tkfont = NULL;
+ entryPtr->fgColorPtr = NULL;
+ entryPtr->highlightBgColorPtr = NULL;
+ entryPtr->highlightColorPtr = NULL;
+ entryPtr->highlightWidth = 0;
+ entryPtr->insertBorder = NULL;
+ entryPtr->insertBorderWidth = 0;
+ entryPtr->insertOffTime = 0;
+ entryPtr->insertOnTime = 0;
+ entryPtr->insertWidth = 0;
+ entryPtr->justify = TK_JUSTIFY_LEFT;
+ entryPtr->relief = TK_RELIEF_FLAT;
+ entryPtr->selBorder = NULL;
+ entryPtr->selBorderWidth = 0;
+ entryPtr->selFgColorPtr = NULL;
+ entryPtr->showChar = NULL;
+ entryPtr->state = STATE_NORMAL;
+ entryPtr->textVarName = NULL;
+ entryPtr->takeFocus = NULL;
+ entryPtr->prefWidth = 0;
+ entryPtr->scrollCmd = NULL;
+ entryPtr->numBytes = 0;
+ entryPtr->numChars = 0;
+ entryPtr->displayString = entryPtr->string;
+ entryPtr->numDisplayBytes = 0;
+ entryPtr->inset = XPAD;
+ entryPtr->textLayout = NULL;
+ entryPtr->layoutX = 0;
+ entryPtr->layoutY = 0;
+ entryPtr->leftX = 0;
+ entryPtr->leftIndex = 0;
+ entryPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
+ entryPtr->textGC = None;
+ entryPtr->selTextGC = None;
+ entryPtr->highlightGC = None;
+ entryPtr->avgWidth = 1;
+ entryPtr->flags = 0;
+ entryPtr->validateCmd = NULL;
+ entryPtr->validate = VALIDATE_NONE;
+ entryPtr->invalidCmd = NULL;
Tk_SetClass(entryPtr->tkwin, "Entry");
TkSetClassProcs(entryPtr->tkwin, &entryClass, (ClientData) entryPtr);
@@ -441,22 +572,22 @@ Tk_EntryCmd(clientData, interp, argc, argv)
EntryEventProc, (ClientData) entryPtr);
Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,
EntryFetchSelection, (ClientData) entryPtr, XA_STRING);
- if (ConfigureEntry(interp, entryPtr, argc-2, argv+2, 0) != TCL_OK) {
- goto error;
- }
- interp->result = Tk_PathName(entryPtr->tkwin);
+ if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin)
+ != TCL_OK) ||
+ (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK)) {
+ Tk_DestroyWindow(entryPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetResult(interp, Tk_PathName(entryPtr->tkwin), TCL_STATIC);
return TCL_OK;
-
- error:
- Tk_DestroyWindow(entryPtr->tkwin);
- return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
- * EntryWidgetCmd --
+ * EntryWidgetObjCmd --
*
* This procedure is invoked to process the Tcl command
* that corresponds to a widget managed by this module.
@@ -472,321 +603,414 @@ 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. */
+EntryWidgetObjCmd(clientData, interp, objc, objv)
+ ClientData clientData; /* Information about entry widget. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
{
- register Entry *entryPtr = (Entry *) clientData;
- int result = TCL_OK;
- size_t length;
- int c;
+ Entry *entryPtr = (Entry *) clientData;
+ int cmdIndex, selIndex, result;
+ Tcl_Obj *objPtr;
- 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;
}
Tcl_Preserve((ClientData) entryPtr);
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) {
- int index;
- int x, y, width, height;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " bbox index\"",
- (char *) NULL);
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, argv[2], &index) != TCL_OK) {
- goto error;
- }
- 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);
- } 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;
- }
- result = Tk_ConfigureValue(interp, entryPtr->tkwin, configSpecs,
- (char *) entryPtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, entryPtr->tkwin, configSpecs,
- (char *) entryPtr, (char *) NULL, 0);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, entryPtr->tkwin, configSpecs,
- (char *) entryPtr, argv[2], 0);
- } else {
- result = ConfigureEntry(interp, entryPtr, argc-2, argv+2,
- TK_CONFIG_ARGV_ONLY);
- }
- } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
- int first, last;
-
- if ((argc < 3) || (argc > 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " delete firstIndex ?lastIndex?\"",
- (char *) NULL);
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, argv[2], &first) != TCL_OK) {
- goto error;
- }
- if (argc == 3) {
- last = first+1;
- } else {
- if (GetEntryIndex(interp, entryPtr, argv[3], &last) != TCL_OK) {
+
+ /*
+ * Parse the widget command by looking up the second token in
+ * the list of valid command names.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
+ "option", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ switch (cmdIndex) {
+ case COMMAND_BBOX: {
+ int index, x, y, width, height;
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
goto error;
}
- }
- if ((last >= first) && (entryPtr->state == tkNormalUid)) {
- DeleteChars(entryPtr, first, last-first);
- }
- } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " get\"", (char *) NULL);
- goto error;
- }
- interp->result = entryPtr->string;
- } else if ((c == 'i') && (strncmp(argv[1], "icursor", length) == 0)
- && (length >= 2)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " icursor pos\"",
- (char *) NULL);
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, argv[2], &entryPtr->insertPos)
- != TCL_OK) {
- goto error;
- }
- EventuallyRedraw(entryPtr);
- } 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 (GetEntryIndex(interp, entryPtr, argv[2], &index) != TCL_OK) {
- goto error;
- }
- sprintf(interp->result, "%d", index);
- } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
- && (length >= 3)) {
- int index;
-
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " insert index text\"",
- (char *) NULL);
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, argv[2], &index) != TCL_OK) {
- goto error;
- }
- if (entryPtr->state == tkNormalUid) {
- InsertChars(entryPtr, index, argv[3]);
- }
- } else if ((c == 's') && (length >= 2)
- && (strncmp(argv[1], "scan", length) == 0)) {
- int x;
-
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " scan mark|dragto x\"", (char *) NULL);
- goto error;
- }
- if (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) {
- goto error;
- }
- if ((argv[2][0] == 'm')
- && (strncmp(argv[2], "mark", strlen(argv[2])) == 0)) {
- entryPtr->scanMarkX = x;
- entryPtr->scanMarkIndex = entryPtr->leftIndex;
- } else if ((argv[2][0] == 'd')
- && (strncmp(argv[2], "dragto", strlen(argv[2])) == 0)) {
- EntryScanTo(entryPtr, x);
- } else {
- Tcl_AppendResult(interp, "bad scan option \"", argv[2],
- "\": must be mark or dragto", (char *) NULL);
- goto error;
- }
- } else if ((c == 's') && (length >= 2)
- && (strncmp(argv[1], "selection", length) == 0)) {
- int index, index2;
-
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " select option ?index?\"", (char *) NULL);
- goto error;
- }
- length = strlen(argv[2]);
- c = argv[2][0];
- if ((c == 'c') && (strncmp(argv[2], "clear", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection clear\"", (char *) NULL);
- goto error;
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
}
- if (entryPtr->selectFirst != -1) {
- entryPtr->selectFirst = entryPtr->selectLast = -1;
- EventuallyRedraw(entryPtr);
+ if ((index == entryPtr->numChars) && (index > 0)) {
+ index--;
}
- goto done;
- } else if ((c == 'p') && (strncmp(argv[2], "present", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection present\"", (char *) NULL);
+ Tk_CharBbox(entryPtr->textLayout, index, &x, &y,
+ &width, &height);
+ sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX,
+ y + entryPtr->layoutY, width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+
+ case COMMAND_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
goto error;
}
- if (entryPtr->selectFirst == -1) {
- interp->result = "0";
+
+ objPtr = Tk_GetOptionValue(interp, (char *) entryPtr,
+ entryPtr->optionTable, objv[2], entryPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
} else {
- interp->result = "1";
+ Tcl_SetObjResult(interp, objPtr);
}
- goto done;
+ break;
}
- if (argc >= 4) {
- if (GetEntryIndex(interp, entryPtr, argv[3], &index) != TCL_OK) {
- goto error;
+
+ case COMMAND_CONFIGURE: {
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr,
+ entryPtr->optionTable,
+ (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
+ entryPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ } else {
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0);
}
+ break;
}
- if ((c == 'a') && (strncmp(argv[2], "adjust", length) == 0)) {
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection adjust index\"",
- (char *) NULL);
+
+ case COMMAND_DELETE: {
+ int first, last;
+
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
goto error;
}
- if (entryPtr->selectFirst >= 0) {
- int half1, half2;
-
- half1 = (entryPtr->selectFirst + entryPtr->selectLast)/2;
- half2 = (entryPtr->selectFirst + entryPtr->selectLast + 1)/2;
- if (index < half1) {
- entryPtr->selectAnchor = entryPtr->selectLast;
- } else if (index > half2) {
- entryPtr->selectAnchor = entryPtr->selectFirst;
- } else {
- /*
- * We're at about the halfway point in the selection;
- * just keep the existing anchor.
- */
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &first) != TCL_OK) {
+ goto error;
+ }
+ if (objc == 3) {
+ last = first + 1;
+ } else {
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]),
+ &last) != TCL_OK) {
+ goto error;
}
}
- EntrySelectTo(entryPtr, index);
- } else if ((c == 'f') && (strncmp(argv[2], "from", length) == 0)) {
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection from index\"",
- (char *) NULL);
+ if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
+ DeleteChars(entryPtr, first, last - first);
+ }
+ break;
+ }
+
+ case COMMAND_GET: {
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
goto error;
}
- entryPtr->selectAnchor = index;
- } else if ((c == 'r') && (strncmp(argv[2], "range", length) == 0)) {
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection range start end\"",
- (char *) NULL);
+ Tcl_SetResult(interp, entryPtr->string, TCL_STATIC);
+ break;
+ }
+
+ case COMMAND_ICURSOR: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pos");
goto error;
}
- if (GetEntryIndex(interp, entryPtr, argv[4], &index2) != TCL_OK) {
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &entryPtr->insertPos) != TCL_OK) {
+ goto error;
+ }
+ EventuallyRedraw(entryPtr);
+ break;
+ }
+
+ case COMMAND_INDEX: {
+ int index;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "string");
goto error;
}
- if (index >= index2) {
- entryPtr->selectFirst = entryPtr->selectLast = -1;
- } else {
- entryPtr->selectFirst = index;
- entryPtr->selectLast = index2;
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
}
- if (!(entryPtr->flags & GOT_SELECTION)
- && (entryPtr->exportSelection)) {
- Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,
- EntryLostSelection, (ClientData) entryPtr);
- entryPtr->flags |= GOT_SELECTION;
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
+ break;
+ }
+
+ case COMMAND_INSERT: {
+ int index;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index text");
+ goto error;
}
- EventuallyRedraw(entryPtr);
- } else if ((c == 't') && (strncmp(argv[2], "to", length) == 0)) {
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection to index\"",
- (char *) NULL);
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->state == STATE_NORMAL) {
+ InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ }
+ break;
+ }
+
+ case COMMAND_SCAN: {
+ int x;
+ char *minorCmd;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x");
goto error;
}
- EntrySelectTo(entryPtr, index);
- } else {
- Tcl_AppendResult(interp, "bad selection option \"", argv[2],
- "\": must be adjust, clear, from, present, range, or to",
- (char *) NULL);
- goto error;
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ goto error;
+ }
+
+ minorCmd = Tcl_GetString(objv[2]);
+ if (minorCmd[0] == 'm'
+ && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) {
+ entryPtr->scanMarkX = x;
+ entryPtr->scanMarkIndex = entryPtr->leftIndex;
+ } else if ((minorCmd[0] == 'd')
+ && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) {
+ EntryScanTo(entryPtr, x);
+ } else {
+ Tcl_AppendResult(interp, "bad scan option \"",
+ Tcl_GetString(objv[2]), "\": must be mark or dragto",
+ (char *) NULL);
+ goto error;
+ }
+ break;
}
- } else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) {
- int index, type, count, charsPerPage;
- double fraction, first, last;
-
- if (argc == 2) {
- EntryVisibleRange(entryPtr, &first, &last);
- sprintf(interp->result, "%g %g", first, last);
- goto done;
- } else if (argc == 3) {
- if (GetEntryIndex(interp, entryPtr, argv[2], &index) != TCL_OK) {
+
+ case COMMAND_SELECTION: {
+ int index, index2;
+
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option ?index?");
goto error;
}
- } else {
- type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
- index = entryPtr->leftIndex;
- switch (type) {
- case TK_SCROLL_ERROR:
- goto error;
- case TK_SCROLL_MOVETO:
- index = (int) ((fraction * entryPtr->numChars) + 0.5);
+
+ /*
+ * Parse the selection sub-command, using the command
+ * table "selCommandNames" defined above.
+ */
+
+ result = Tcl_GetIndexFromObj(interp, objv[2], selCommandNames,
+ "selection option", 0, &selIndex);
+ if (result != TCL_OK) {
+ goto error;
+ }
+
+ switch(selIndex) {
+ case SELECTION_ADJUST: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ if (entryPtr->selectFirst >= 0) {
+ int half1, half2;
+
+ half1 = (entryPtr->selectFirst
+ + entryPtr->selectLast)/2;
+ half2 = (entryPtr->selectFirst
+ + entryPtr->selectLast + 1)/2;
+ if (index < half1) {
+ entryPtr->selectAnchor = entryPtr->selectLast;
+ } else if (index > half2) {
+ entryPtr->selectAnchor = entryPtr->selectFirst;
+ } else {
+ /*
+ * We're at about the halfway point in the
+ * selection; just keep the existing anchor.
+ */
+ }
+ }
+ EntrySelectTo(entryPtr, index);
break;
- case TK_SCROLL_PAGES:
- charsPerPage = ((Tk_Width(entryPtr->tkwin)
- - 2*entryPtr->inset) / entryPtr->avgWidth) - 2;
- if (charsPerPage < 1) {
- charsPerPage = 1;
+ }
+
+ case SELECTION_CLEAR: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL);
+ goto error;
}
- index += charsPerPage*count;
+ if (entryPtr->selectFirst >= 0) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ EventuallyRedraw(entryPtr);
+ }
+ goto done;
+ }
+
+ case SELECTION_FROM: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ entryPtr->selectAnchor = index;
break;
- case TK_SCROLL_UNITS:
- index += count;
+ }
+
+ case SELECTION_PRESENT: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL);
+ goto error;
+ }
+ if (entryPtr->selectFirst < 0) {
+ Tcl_SetResult(interp, "0", TCL_STATIC);
+ } else {
+ Tcl_SetResult(interp, "1", TCL_STATIC);
+ }
+ goto done;
+ }
+
+ case SELECTION_RANGE: {
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 3, objv, "start end");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[4]),& index2) != TCL_OK) {
+ goto error;
+ }
+ if (index >= index2) {
+ entryPtr->selectFirst = -1;
+ entryPtr->selectLast = -1;
+ } else {
+ entryPtr->selectFirst = index;
+ entryPtr->selectLast = index2;
+ }
+ if (!(entryPtr->flags & GOT_SELECTION)
+ && (entryPtr->exportSelection)) {
+ Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,
+ EntryLostSelection, (ClientData) entryPtr);
+ entryPtr->flags |= GOT_SELECTION;
+ }
+ EventuallyRedraw(entryPtr);
break;
+ }
+
+ case SELECTION_TO: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ goto error;
+ }
+ if (GetEntryIndex(interp, entryPtr,
+ Tcl_GetString(objv[3]), &index) != TCL_OK) {
+ goto error;
+ }
+ EntrySelectTo(entryPtr, index);
+ break;
+ }
}
+ break;
}
- if (index >= entryPtr->numChars) {
- index = entryPtr->numChars-1;
- }
- if (index < 0) {
- index = 0;
+
+ case COMMAND_VALIDATE: {
+ int code;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
+ goto error;
+ }
+ selIndex = entryPtr->validate;
+ entryPtr->validate = VALIDATE_ALL;
+ code = EntryValidateChange(entryPtr, (char *) NULL,
+ entryPtr->string, -1, VALIDATE_FORCED);
+ if (entryPtr->validate != VALIDATE_NONE) {
+ entryPtr->validate = selIndex;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj((code == TCL_OK)));
+ break;
+ }
+
+ case COMMAND_XVIEW: {
+ int index;
+
+ if (objc == 2) {
+ double first, last;
+ char buf[TCL_DOUBLE_SPACE * 2];
+
+ EntryVisibleRange(entryPtr, &first, &last);
+ sprintf(buf, "%g %g", first, last);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ goto done;
+ } else if (objc == 3) {
+ if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
+ &index) != TCL_OK) {
+ goto error;
+ }
+ } else {
+ double fraction;
+ int count;
+
+ index = entryPtr->leftIndex;
+ switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,
+ &count)) {
+ case TK_SCROLL_ERROR: {
+ goto error;
+ }
+ case TK_SCROLL_MOVETO: {
+ index = (int) ((fraction * entryPtr->numChars) + 0.5);
+ break;
+ }
+ case TK_SCROLL_PAGES: {
+ int charsPerPage;
+
+ charsPerPage = ((Tk_Width(entryPtr->tkwin)
+ - 2 * entryPtr->inset)
+ / entryPtr->avgWidth) - 2;
+ if (charsPerPage < 1) {
+ charsPerPage = 1;
+ }
+ index += count * charsPerPage;
+ break;
+ }
+ case TK_SCROLL_UNITS: {
+ index += count;
+ break;
+ }
+ }
+ }
+ if (index >= entryPtr->numChars) {
+ index = entryPtr->numChars - 1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ entryPtr->leftIndex = index;
+ entryPtr->flags |= UPDATE_SCROLLBAR;
+ EntryComputeGeometry(entryPtr);
+ EventuallyRedraw(entryPtr);
+ break;
}
- entryPtr->leftIndex = index;
- entryPtr->flags |= UPDATE_SCROLLBAR;
- EntryComputeGeometry(entryPtr);
- EventuallyRedraw(entryPtr);
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be bbox, cget, configure, delete, get, ",
- "icursor, index, insert, scan, selection, or xview",
- (char *) NULL);
- goto error;
}
+
done:
Tcl_Release((ClientData) entryPtr);
return result;
@@ -818,7 +1042,13 @@ static void
DestroyEntry(memPtr)
char *memPtr; /* Info about entry widget. */
{
- register Entry *entryPtr = (Entry *) memPtr;
+ Entry *entryPtr = (Entry *) memPtr;
+ entryPtr->flags |= ENTRY_DELETED;
+
+ Tcl_DeleteCommandFromToken(entryPtr->interp, entryPtr->widgetCmd);
+ if (entryPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayEntry, (ClientData) entryPtr);
+ }
/*
* Free up all the stuff that requires special handling, then
@@ -839,11 +1069,13 @@ 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);
- Tk_FreeOptions(configSpecs, (char *) entryPtr, entryPtr->display, 0);
+ Tk_FreeConfigOptions((char *) entryPtr, entryPtr->optionTable,
+ entryPtr->tkwin);
+ entryPtr->tkwin = NULL;
ckfree((char *) entryPtr);
}
@@ -858,7 +1090,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,
@@ -869,14 +1101,17 @@ DestroyEntry(memPtr)
*/
static int
-ConfigureEntry(interp, entryPtr, argc, argv, flags)
+ConfigureEntry(interp, entryPtr, objc, objv, flags)
Tcl_Interp *interp; /* Used for error reporting. */
- register 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. */
+ Entry *entryPtr; /* Information about widget; may or may not
+ * already have values for some fields. */
+ int objc; /* Number of valid entries in argv. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *errorResult = NULL;
+ int error;
int oldExport;
/*
@@ -890,9 +1125,83 @@ ConfigureEntry(interp, entryPtr, argc, argv, flags)
}
oldExport = entryPtr->exportSelection;
- if (Tk_ConfigureWidget(interp, entryPtr->tkwin, configSpecs,
- argc, argv, (char *) entryPtr, flags) != TCL_OK) {
- return TCL_ERROR;
+
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) entryPtr,
+ entryPtr->optionTable, objc, objv,
+ entryPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ /*
+ * A few other options also need special processing, such as parsing
+ * the geometry and setting the background from a 3-D border.
+ */
+
+ Tk_SetBackgroundFromBorder(entryPtr->tkwin, entryPtr->normalBorder);
+
+ if (entryPtr->insertWidth <= 0) {
+ entryPtr->insertWidth = 2;
+ }
+ if (entryPtr->insertBorderWidth > entryPtr->insertWidth/2) {
+ entryPtr->insertBorderWidth = entryPtr->insertWidth/2;
+ }
+
+ /*
+ * Restart the cursor timing sequence in case the on-time or
+ * off-time just changed. Set validate temporarily to none,
+ * so the configure doesn't cause it to be triggered.
+ */
+
+ if (entryPtr->flags & GOT_FOCUS) {
+ int validate = entryPtr->validate;
+ entryPtr->validate = VALIDATE_NONE;
+ EntryFocusProc(entryPtr, 1);
+ entryPtr->validate = validate;
+ }
+
+ /*
+ * Claim the selection if we've suddenly started exporting it.
+ */
+
+ if (entryPtr->exportSelection && (!oldExport)
+ && (entryPtr->selectFirst != -1)
+ && !(entryPtr->flags & GOT_SELECTION)) {
+ Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
+ (ClientData) entryPtr);
+ entryPtr->flags |= GOT_SELECTION;
+ }
+
+ /*
+ * Recompute the window's geometry and arrange for it to be
+ * redisplayed.
+ */
+
+ Tk_SetInternalBorder(entryPtr->tkwin,
+ entryPtr->borderWidth + entryPtr->highlightWidth);
+ if (entryPtr->highlightWidth <= 0) {
+ entryPtr->highlightWidth = 0;
+ }
+ entryPtr->inset = entryPtr->highlightWidth
+ + entryPtr->borderWidth + XPAD;
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
}
/*
@@ -915,63 +1224,14 @@ ConfigureEntry(interp, entryPtr, argc, argv, flags)
EntryTextVarProc, (ClientData) entryPtr);
}
- /*
- * A few other options also need special processing, such as parsing
- * the geometry and setting the background from a 3-D border.
- */
-
- if ((entryPtr->state != tkNormalUid)
- && (entryPtr->state != tkDisabledUid)) {
- Tcl_AppendResult(interp, "bad state value \"", entryPtr->state,
- "\": must be normal or disabled", (char *) NULL);
- entryPtr->state = tkNormalUid;
+ EntryWorldChanged((ClientData) entryPtr);
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
return TCL_ERROR;
+ } else {
+ return TCL_OK;
}
-
- Tk_SetBackgroundFromBorder(entryPtr->tkwin, entryPtr->normalBorder);
-
- if (entryPtr->insertWidth <= 0) {
- entryPtr->insertWidth = 2;
- }
- if (entryPtr->insertBorderWidth > entryPtr->insertWidth/2) {
- entryPtr->insertBorderWidth = entryPtr->insertWidth/2;
- }
-
- /*
- * Restart the cursor timing sequence in case the on-time or off-time
- * just changed.
- */
-
- if (entryPtr->flags & GOT_FOCUS) {
- EntryFocusProc(entryPtr, 1);
- }
-
- /*
- * Claim the selection if we've suddenly started exporting it.
- */
-
- if (entryPtr->exportSelection && (!oldExport)
- && (entryPtr->selectFirst != -1)
- && !(entryPtr->flags & GOT_SELECTION)) {
- Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
- (ClientData) entryPtr);
- entryPtr->flags |= GOT_SELECTION;
- }
-
- /*
- * Recompute the window's geometry and arrange for it to be
- * redisplayed.
- */
-
- Tk_SetInternalBorder(entryPtr->tkwin,
- entryPtr->borderWidth + entryPtr->highlightWidth);
- if (entryPtr->highlightWidth <= 0) {
- entryPtr->highlightWidth = 0;
- }
- entryPtr->inset = entryPtr->highlightWidth + entryPtr->borderWidth + XPAD;
-
- EntryWorldChanged((ClientData) entryPtr);
- return TCL_OK;
}
/*
@@ -997,7 +1257,7 @@ EntryWorldChanged(instanceData)
ClientData instanceData; /* Information about widget. */
{
XGCValues gcValues;
- GC gc;
+ GC gc = None;
unsigned long mask;
Entry *entryPtr;
@@ -1008,12 +1268,15 @@ EntryWorldChanged(instanceData)
entryPtr->avgWidth = 1;
}
+ if (entryPtr->normalBorder != NULL) {
+ Tk_SetBackgroundFromBorder(entryPtr->tkwin, entryPtr->normalBorder);
+ }
+
gcValues.foreground = entryPtr->fgColorPtr->pixel;
gcValues.font = Tk_FontId(entryPtr->tkfont);
gcValues.graphics_exposures = False;
mask = GCForeground | GCFont | GCGraphicsExposures;
- gc = Tk_GetGCColor(entryPtr->tkwin, mask, &gcValues, entryPtr->fgColorPtr,
- NULL);
+ gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
if (entryPtr->textGC != None) {
Tk_FreeGC(entryPtr->display, entryPtr->textGC);
}
@@ -1022,8 +1285,7 @@ EntryWorldChanged(instanceData)
gcValues.foreground = entryPtr->selFgColorPtr->pixel;
gcValues.font = Tk_FontId(entryPtr->tkfont);
mask = GCForeground | GCFont;
- gc = Tk_GetGCColor(entryPtr->tkwin, mask, &gcValues,
- entryPtr->selFgColorPtr, NULL);
+ gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
if (entryPtr->selTextGC != None) {
Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
}
@@ -1059,9 +1321,9 @@ 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;
@@ -1119,19 +1381,21 @@ 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)) {
+ 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+
+ 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;
+ &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;
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->selectLast,
+ &selEndX, NULL, NULL, NULL);
+ selEndX += entryPtr->layoutX;
Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->selBorder,
selStartX - entryPtr->selBorderWidth,
baseY - fm.ascent - entryPtr->selBorderWidth,
@@ -1151,33 +1415,22 @@ DisplayEntry(clientData)
*/
if ((entryPtr->insertPos >= entryPtr->leftIndex)
- && (entryPtr->state == tkNormalUid)
+ && (entryPtr->state == STATE_NORMAL)
&& (entryPtr->flags & GOT_FOCUS)) {
- if (entryPtr->insertPos == 0) {
- cursorX = 0;
- } else if (entryPtr->insertPos >= entryPtr->numChars) {
- int idx = entryPtr->numChars >= 1 ? entryPtr->numChars - 1 : 0;
- Tk_CharBbox(entryPtr->textLayout, idx,
- &x, NULL, &w, NULL);
- cursorX = x + w;
- } else {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos,
- &x, NULL, NULL, NULL);
- cursorX = x;
- }
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &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);
}
}
}
@@ -1191,18 +1444,19 @@ DisplayEntry(clientData)
entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
entryPtr->leftIndex, entryPtr->numChars);
- if (showSelection && (entryPtr->selTextGC != entryPtr->textGC) &&
- (entryPtr->selectFirst < entryPtr->selectLast)) {
- int first;
+ if (showSelection
+ && (entryPtr->selTextGC != entryPtr->textGC)
+ && (entryPtr->selectFirst < entryPtr->selectLast)) {
+ int selFirst;
- if (entryPtr->selectFirst - entryPtr->leftIndex < 0) {
- first = entryPtr->leftIndex;
+ if (entryPtr->selectFirst < entryPtr->leftIndex) {
+ selFirst = entryPtr->leftIndex;
} else {
- first = entryPtr->selectFirst;
+ selFirst = entryPtr->selectFirst;
}
Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,
entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
- first, entryPtr->selectLast);
+ selFirst, entryPtr->selectLast);
}
/*
@@ -1213,19 +1467,22 @@ 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) {
- GC gc;
+ GC fgGC, bgGC;
+ bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, pixmap);
if (entryPtr->flags & GOT_FOCUS) {
- gc = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap);
+ fgGC = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap);
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC,
+ entryPtr->highlightWidth, pixmap);
} else {
- gc = Tk_GCForColor(entryPtr->highlightBgColorPtr, pixmap);
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC,
+ entryPtr->highlightWidth, pixmap);
}
- Tk_DrawFocusHighlight(tkwin, gc, entryPtr->highlightWidth, pixmap);
}
/*
@@ -1262,38 +1519,53 @@ 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;
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];
+ Tcl_UniChar ch;
+ char buf[TCL_UTF_MAX];
+ int size;
+
+ /*
+ * Normalize the special character so we can safely duplicate it
+ * in the display string. If we didn't do this, then two malformed
+ * characters might end up looking like one valid UTF character in
+ * the resulting string.
+ */
+
+ 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;
- displayString = entryPtr->displayString;
- } else {
- displayString = entryPtr->string;
+ *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->numChars, 0,
+ entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);
entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2;
@@ -1328,13 +1600,13 @@ 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);
+ Tk_CharBbox(entryPtr->textLayout, entryPtr->leftIndex, &rightX,
+ NULL, NULL, NULL);
entryPtr->leftX = entryPtr->inset;
entryPtr->layoutX = entryPtr->leftX - rightX;
}
@@ -1371,28 +1643,59 @@ 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);
+
+ if ((entryPtr->validate == VALIDATE_KEY ||
+ entryPtr->validate == VALIDATE_ALL) &&
+ EntryValidateChange(entryPtr, value, new, index,
+ VALIDATE_INSERT) != TCL_OK) {
+ ckfree(new);
+ return;
+ }
+
+ 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 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.
@@ -1403,19 +1706,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);
}
@@ -1439,11 +1743,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, *todelete;
if ((index + count) > entryPtr->numChars) {
count = entryPtr->numChars - index;
@@ -1452,12 +1757,38 @@ 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);
+
+ todelete = (char *) ckalloc((unsigned) (byteCount + 1));
+ memcpy(todelete, string + byteIndex, (size_t) byteCount);
+ todelete[byteCount] = '\0';
+
+ if ((entryPtr->validate == VALIDATE_KEY ||
+ entryPtr->validate == VALIDATE_ALL) &&
+ EntryValidateChange(entryPtr, todelete, new, index,
+ VALIDATE_DELETE) != TCL_OK) {
+ ckfree(new);
+ ckfree(todelete);
+ return;
+ }
+
+ ckfree(todelete);
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
@@ -1466,21 +1797,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)) {
@@ -1490,14 +1822,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;
@@ -1583,24 +1915,74 @@ 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;
+ int code, valueLen, malloced = 0;
+
+ if (strcmp(value, entryPtr->string) == 0) {
+ return;
+ }
+ valueLen = strlen(value);
+
+ if (entryPtr->flags & VALIDATE_VAR) {
+ entryPtr->flags |= VALIDATE_ABORT;
+ } else {
+ /*
+ * If we validate, we create a copy of the value, as it may
+ * point to volatile memory, like the value of the -textvar
+ * which may get freed during validation
+ */
+ oldSource = (char *) ckalloc((unsigned) (valueLen + 1));
+ strcpy(oldSource, value);
+ value = oldSource;
+ malloced = 1;
+
+ entryPtr->flags |= VALIDATE_VAR;
+ code = EntryValidateChange(entryPtr, (char *) NULL, value, -1,
+ VALIDATE_FORCED);
+ entryPtr->flags &= ~VALIDATE_VAR;
+ /*
+ * If VALIDATE_ABORT has been set, then this operation should be
+ * aborted because the validatecommand did something else instead
+ */
+ if (entryPtr->flags & VALIDATE_ABORT) {
+ entryPtr->flags &= ~VALIDATE_ABORT;
+ ckfree(value);
+ return;
+ }
+ }
+
+ oldSource = entryPtr->string;
ckfree(entryPtr->string);
- entryPtr->numChars = strlen(value);
- entryPtr->string = (char *) ckalloc((unsigned) (entryPtr->numChars + 1));
- strcpy(entryPtr->string, value);
- if (entryPtr->selectFirst != -1) {
+
+ if (malloced) {
+ entryPtr->string = value;
+ } else {
+ entryPtr->string = (char *) ckalloc((unsigned) (valueLen + 1));
+ strcpy(entryPtr->string, value);
+ }
+ entryPtr->numBytes = valueLen;
+ entryPtr->numChars = Tcl_NumUtfChars(value, valueLen);
+
+ 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;
}
}
@@ -1641,14 +2023,7 @@ EntryEventProc(clientData, eventPtr)
EventuallyRedraw(entryPtr);
entryPtr->flags |= BORDER_NEEDED;
} else if (eventPtr->type == DestroyNotify) {
- if (entryPtr->tkwin != NULL) {
- entryPtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(entryPtr->interp, entryPtr->widgetCmd);
- }
- if (entryPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(DisplayEntry, (ClientData) entryPtr);
- }
- Tcl_EventuallyFree((ClientData) entryPtr, DestroyEntry);
+ DestroyEntry((char *) clientData);
} else if (eventPtr->type == ConfigureNotify) {
Tcl_Preserve((ClientData) entryPtr);
entryPtr->flags |= UPDATE_SCROLLBAR;
@@ -1689,7 +2064,6 @@ EntryCmdDeletedProc(clientData)
ClientData clientData; /* Pointer to widget record for widget. */
{
Entry *entryPtr = (Entry *) clientData;
- Tk_Window tkwin = entryPtr->tkwin;
/*
* This procedure could be invoked either because the window was
@@ -1698,14 +2072,13 @@ EntryCmdDeletedProc(clientData)
* destroys the widget.
*/
- if (tkwin != NULL) {
- entryPtr->tkwin = NULL;
- Tk_DestroyWindow(tkwin);
+ if (!(entryPtr->flags & ENTRY_DELETED)) {
+ Tk_DestroyWindow(entryPtr->tkwin);
}
}
/*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*
* GetEntryIndex --
*
@@ -1714,15 +2087,15 @@ EntryCmdDeletedProc(clientData)
*
* Results:
* A standard Tcl result. If all went well, then *indexPtr is
- * filled in with the index (into entryPtr) corresponding to
+ * filled in with the character index (into entryPtr) corresponding to
* string. The index value is guaranteed to lie between 0 and
* the number of characters in the string, inclusive. If an
- * error occurs then an error message is left in interp->result.
+ * error occurs then an error message is left in the interp's result.
*
* Side effects:
* None.
*
- *--------------------------------------------------------------
+ *---------------------------------------------------------------------------
*/
static int
@@ -1731,7 +2104,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;
@@ -1744,7 +2118,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.
*/
@@ -1766,8 +2140,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) {
@@ -1783,7 +2157,7 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
} else if (string[0] == '@') {
int x, roundUp;
- if (Tcl_GetInt(interp, string+1, &x) != TCL_OK) {
+ if (Tcl_GetInt(interp, string + 1, &x) != TCL_OK) {
goto badIndex;
}
if (x < entryPtr->inset) {
@@ -1815,7 +2189,7 @@ GetEntryIndex(interp, entryPtr, string, indexPtr)
*indexPtr = 0;
} else if (*indexPtr > entryPtr->numChars) {
*indexPtr = entryPtr->numChars;
- }
+ }
}
if(*indexPtr > entryPtr->numChars)
*indexPtr = entryPtr->numChars;
@@ -1841,9 +2215,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;
@@ -1859,19 +2232,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);
}
}
@@ -1895,10 +2273,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;
@@ -1961,38 +2338,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;
}
/*
@@ -2015,7 +2389,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;
@@ -2028,7 +2402,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);
@@ -2057,7 +2431,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;
@@ -2096,11 +2470,11 @@ EventuallyRedraw(entryPtr)
static void
EntryVisibleRange(entryPtr, firstPtr, lastPtr)
- Entry *entryPtr; /* Information about widget. */
- double *firstPtr; /* Return position of first visible
- * character in widget. */
- double *lastPtr; /* Return position of char just after
- * last 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;
@@ -2110,22 +2484,18 @@ EntryVisibleRange(entryPtr, firstPtr, lastPtr)
} else {
charsInWindow = 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 (charsInWindow < entryPtr->numChars) {
+ charsInWindow++;
}
charsInWindow -= entryPtr->leftIndex;
if (charsInWindow == 0) {
charsInWindow = 1;
}
- *firstPtr = ((double) entryPtr->leftIndex)/entryPtr->numChars;
- *lastPtr = ((double) (entryPtr->leftIndex + charsInWindow))
- /entryPtr->numChars;
+
+ *firstPtr = (double) entryPtr->leftIndex / entryPtr->numChars;
+ *lastPtr = (double) (entryPtr->leftIndex + charsInWindow)
+ / entryPtr->numChars;
}
}
@@ -2153,7 +2523,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;
@@ -2198,9 +2568,10 @@ 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)) {
+ if ((entryPtr->state == STATE_DISABLED) ||
+ !(entryPtr->flags & GOT_FOCUS) || (entryPtr->insertOffTime == 0)) {
return;
}
if (entryPtr->flags & CURSOR_ON) {
@@ -2235,7 +2606,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. */
{
@@ -2247,9 +2618,21 @@ EntryFocusProc(entryPtr, gotFocus)
entryPtr->insertOnTime, EntryBlinkProc,
(ClientData) entryPtr);
}
+ if (entryPtr->validate == VALIDATE_ALL ||
+ entryPtr->validate == VALIDATE_FOCUS ||
+ entryPtr->validate == VALIDATE_FOCUSIN) {
+ EntryValidateChange(entryPtr, (char *) NULL,
+ entryPtr->string, -1, VALIDATE_FOCUSIN);
+ }
} else {
entryPtr->flags &= ~(GOT_FOCUS | CURSOR_ON);
entryPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
+ if (entryPtr->validate == VALIDATE_ALL ||
+ entryPtr->validate == VALIDATE_FOCUS ||
+ entryPtr->validate == VALIDATE_FOCUSOUT) {
+ EntryValidateChange(entryPtr, (char *) NULL,
+ entryPtr->string, -1, VALIDATE_FOCUSOUT);
+ }
}
EventuallyRedraw(entryPtr);
}
@@ -2281,7 +2664,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;
/*
@@ -2311,8 +2694,308 @@ EntryTextVarProc(clientData, interp, name1, name2, flags)
if (value == NULL) {
value = "";
}
- if (strcmp(value, entryPtr->string) != 0) {
- EntrySetValue(entryPtr, value);
- }
+ EntrySetValue(entryPtr, value);
return (char *) NULL;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryValidate --
+ *
+ * This procedure is invoked when any character is added or
+ * removed from the entry widget, or a focus has trigerred validation.
+ *
+ * Results:
+ * TCL_OK if the validatecommand passes the new string.
+ * TCL_BREAK if the vcmd executed OK, but rejects the string.
+ * TCL_ERROR if an error occurred while executing the vcmd
+ * or a valid Tcl_Bool is not returned.
+ *
+ * Side effects:
+ * An error condition may arise
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EntryValidate(entryPtr, cmd)
+ register Entry *entryPtr; /* Entry that needs validation. */
+ register char *cmd; /* Validation command (NULL-terminated
+ * string). */
+{
+ register Tcl_Interp *interp = entryPtr->interp;
+ int code, bool;
+
+ code = Tcl_EvalEx(interp, cmd, -1, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
+
+ if (code != TCL_OK && code != TCL_RETURN) {
+ Tcl_AddErrorInfo(interp,
+ "\n\t(in validation command executed by entry)");
+ Tcl_BackgroundError(interp);
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetBooleanFromObj(interp, Tcl_GetObjResult(interp),
+ &bool) != TCL_OK) {
+ Tcl_AddErrorInfo(interp,
+ "\nvalid boolean not returned by validation command");
+ Tcl_BackgroundError(interp);
+ Tcl_SetResult(interp, NULL, 0);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetResult(interp, NULL, 0);
+ return (bool ? TCL_OK : TCL_BREAK);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EntryValidateChange --
+ *
+ * This procedure is invoked when any character is added or
+ * removed from the entry widget, or a focus has trigerred validation.
+ *
+ * Results:
+ * TCL_OK if the validatecommand accepts the new string,
+ * TCL_ERROR if any problems occured with validatecommand.
+ *
+ * Side effects:
+ * The insertion/deletion may be aborted, and the
+ * validatecommand might turn itself off (if an error
+ * or loop condition arises).
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+EntryValidateChange(entryPtr, change, new, index, type)
+ register Entry *entryPtr; /* Entry that needs validation. */
+ char *change; /* Characters to be added/deleted
+ * (NULL-terminated string). */
+ char *new; /* Potential new value of entry string */
+ int index; /* index of insert/delete, -1 otherwise */
+ int type; /* forced, delete, insert,
+ * focusin or focusout */
+{
+ int code, varValidate = (entryPtr->flags & VALIDATE_VAR);
+ char *p;
+ Tcl_DString script;
+
+ if (entryPtr->validateCmd == NULL ||
+ entryPtr->validate == VALIDATE_NONE) {
+ return (varValidate ? TCL_ERROR : TCL_OK);
+ }
+
+ /*
+ * If we're already validating, then we're hitting a loop condition
+ * Return and set validate to 0 to disallow further validations
+ * and prevent current validation from finishing
+ */
+ if (entryPtr->flags & VALIDATING) {
+ entryPtr->validate = VALIDATE_NONE;
+ return (varValidate ? TCL_ERROR : TCL_OK);
+ }
+
+ entryPtr->flags |= VALIDATING;
+
+ /*
+ * Now form command string and run through the -validatecommand
+ */
+
+ Tcl_DStringInit(&script);
+ ExpandPercents(entryPtr, entryPtr->validateCmd,
+ change, new, index, type, &script);
+ Tcl_DStringAppend(&script, "", 1);
+
+ p = Tcl_DStringValue(&script);
+ code = EntryValidate(entryPtr, p);
+ Tcl_DStringFree(&script);
+
+ /*
+ * If e->validate has become VALIDATE_NONE during the validation, or
+ * we now have VALIDATE_VAR set (from EntrySetValue) and didn't before,
+ * it means that a loop condition almost occured. Do not allow
+ * this validation result to finish.
+ */
+ if (entryPtr->validate == VALIDATE_NONE
+ || (!varValidate && (entryPtr->flags & VALIDATE_VAR))) {
+ code = TCL_ERROR;
+ }
+ /*
+ * If validate will return ERROR, then disallow further validations
+ * Otherwise, if it didn't accept the new string (returned TCL_BREAK)
+ * then eval the invalidCmd (if it's set)
+ */
+ if (code == TCL_ERROR) {
+ entryPtr->validate = VALIDATE_NONE;
+ } else if (code == TCL_BREAK) {
+ /*
+ * If we were doing forced validation (like via a variable
+ * trace) and the command returned 0, the we turn off validation
+ * because we assume that textvariables have precedence in
+ * managing the value. We also don't call the invcmd, as it
+ * may want to do entry manipulation which the setting of the
+ * var will later wipe anyway.
+ */
+ if (varValidate) {
+ entryPtr->validate = VALIDATE_NONE;
+ } else if (entryPtr->invalidCmd != NULL) {
+ Tcl_DStringInit(&script);
+ ExpandPercents(entryPtr, entryPtr->invalidCmd,
+ change, new, index, type, &script);
+ Tcl_DStringAppend(&script, "", 1);
+ p = Tcl_DStringValue(&script);
+ if (Tcl_EvalEx(entryPtr->interp, p, -1,
+ TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT) != TCL_OK) {
+ Tcl_AddErrorInfo(entryPtr->interp,
+ "\n\t(in invalidcommand executed by entry)");
+ Tcl_BackgroundError(entryPtr->interp);
+ code = TCL_ERROR;
+ entryPtr->validate = VALIDATE_NONE;
+ }
+ Tcl_DStringFree(&script);
+ }
+ }
+
+ entryPtr->flags &= ~VALIDATING;
+
+ return code;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ExpandPercents --
+ *
+ * Given a command and an event, produce a new command
+ * by replacing % constructs in the original command
+ * with information from the X event.
+ *
+ * Results:
+ * The new expanded command is appended to the dynamic string
+ * given by dsPtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ExpandPercents(entryPtr, before, change, new, index, type, dsPtr)
+ register Entry *entryPtr; /* Entry that needs validation. */
+ register char *before; /* Command containing percent
+ * expressions to be replaced. */
+ char *change; /* Characters to added/deleted
+ * (NULL-terminated string). */
+ char *new; /* Potential new value of entry string */
+ int index; /* index of insert/delete */
+ int type; /* INSERT or DELETE */
+ Tcl_DString *dsPtr; /* Dynamic string in which to append
+ * new command. */
+{
+ int spaceNeeded, cvtFlags; /* Used to substitute string as proper Tcl
+ * list element. */
+ int number, length;
+ register char *string;
+ Tcl_UniChar ch;
+ char numStorage[2*TCL_INTEGER_SPACE];
+
+ while (1) {
+ if (*before == '\0') {
+ break;
+ }
+ /*
+ * Find everything up to the next % character and append it
+ * to the result string.
+ */
+
+ string = before;
+ /* No need to convert '%', as it is in ascii range */
+ string = Tcl_UtfFindFirst(before, '%');
+ if (string == (char *) NULL) {
+ Tcl_DStringAppend(dsPtr, before, -1);
+ break;
+ } else if (string != before) {
+ Tcl_DStringAppend(dsPtr, before, string-before);
+ before = string;
+ }
+
+ /*
+ * There's a percent sequence here. Process it.
+ */
+
+ before++; /* skip over % */
+ if (*before != '\0') {
+ before += Tcl_UtfToUniChar(before, &ch);
+ } else {
+ ch = '%';
+ }
+ switch (ch) {
+ case 'd': /* Type of call that caused validation */
+ switch (type) {
+ case VALIDATE_INSERT:
+ number = 1;
+ break;
+ case VALIDATE_DELETE:
+ number = 0;
+ break;
+ default:
+ number = -1;
+ break;
+ }
+ sprintf(numStorage, "%d", number);
+ string = numStorage;
+ break;
+ case 'i': /* index of insert/delete */
+ sprintf(numStorage, "%d", index);
+ string = numStorage;
+ break;
+ case 'P': /* 'Peeked' new value of the string */
+ string = new;
+ break;
+ case 's': /* Current string value of entry */
+ string = entryPtr->string;
+ break;
+ case 'S': /* string to be inserted/deleted, if any */
+ string = change;
+ break;
+ case 'v': /* type of validation currently set */
+ string = validateStrings[entryPtr->validate];
+ break;
+ case 'V': /* type of validation in effect */
+ switch (type) {
+ case VALIDATE_INSERT:
+ case VALIDATE_DELETE:
+ string = validateStrings[VALIDATE_KEY];
+ break;
+ case VALIDATE_FORCED:
+ string = "forced";
+ break;
+ default:
+ string = validateStrings[type];
+ break;
+ }
+ break;
+ case 'W': /* widget name */
+ string = Tk_PathName(entryPtr->tkwin);
+ break;
+ default:
+ length = Tcl_UniCharToUtf(ch, numStorage);
+ numStorage[length] = '\0';
+ string = numStorage;
+ break;
+ }
+
+ spaceNeeded = Tcl_ScanCountedElement(string, -1, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertCountedElement(string, -1,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ }
+}
+
diff --git a/tk/generic/tkError.c b/tk/generic/tkError.c
index 77909331a6f..aaf7c10b351 100644
--- a/tk/generic/tkError.c
+++ b/tk/generic/tkError.c
@@ -305,3 +305,4 @@ ErrorProc(display, errEventPtr)
couldntHandle:
return (*defaultHandler)(display, errEventPtr);
}
+
diff --git a/tk/generic/tkEvent.c b/tk/generic/tkEvent.c
index 2d10dccc69c..bd70e881bae 100644
--- a/tk/generic/tkEvent.c
+++ b/tk/generic/tkEvent.c
@@ -39,10 +39,6 @@ typedef struct InProgress {
struct InProgress *nextPtr; /* Next higher nested search. */
} InProgress;
-static InProgress *pendingPtr = NULL;
- /* Topmost search in progress, or
- * NULL if none. */
-
/*
* For each call to Tk_CreateGenericHandler, an instance of the following
* structure will be created. All of the active handlers are linked into a
@@ -58,11 +54,6 @@ typedef struct GenericHandler {
* handlers, or NULL for end of list. */
} GenericHandler;
-static GenericHandler *genericList = NULL;
- /* First handler in the list, or NULL. */
-static GenericHandler *lastGenericPtr = NULL;
- /* Last handler in list. */
-
/*
* There's a potential problem if Tk_HandleEvent is entered recursively.
* A handler cannot be deleted physically until we have returned from
@@ -70,11 +61,8 @@ static GenericHandler *lastGenericPtr = NULL;
* its `next' entry. We deal with the problem by using the `delete flag' and
* deleting handlers only when it's known that there's no handler active.
*
- * The following variable has a non-zero value when a handler is active.
*/
-static int genericHandlersActive = 0;
-
/*
* The following structure is used for queueing X-style events on the
* Tcl event queue.
@@ -134,15 +122,37 @@ static unsigned long eventMasks[TK_LASTEVENT] = {
MouseWheelMask /* MouseWheelEvent */
};
+
/*
- * If someone has called Tk_RestrictEvents, the information below
- * keeps track of it.
+ * The structure below is used to store Data for the Event module that
+ * must be kept thread-local. The "dataKey" is used to fetch the
+ * thread-specific storage for the current thread.
*/
-static Tk_RestrictProc *restrictProc;
+typedef struct ThreadSpecificData {
+
+ int genericHandlersActive;
+ /* The following variable has a non-zero
+ * value when a handler is active. */
+ InProgress *pendingPtr;
+ /* Topmost search in progress, or
+ * NULL if none. */
+ GenericHandler *genericList;
+ /* First handler in the list, or NULL. */
+ GenericHandler *lastGenericPtr;
+ /* Last handler in list. */
+
+ /*
+ * If someone has called Tk_RestrictEvents, the information below
+ * keeps track of it.
+ */
+
+ Tk_RestrictProc *restrictProc;
/* Procedure to call. NULL means no
* restrictProc is currently in effect. */
-static ClientData restrictArg; /* Argument to pass to restrictProc. */
+ ClientData restrictArg; /* Argument to pass to restrictProc. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Prototypes for procedures that are only referenced locally within
@@ -266,6 +276,8 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
register InProgress *ipPtr;
TkEventHandler *prevPtr;
register TkWindow *winPtr = (TkWindow *) token;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Find the event handler to be deleted, or return
@@ -288,7 +300,7 @@ Tk_DeleteEventHandler(token, mask, proc, clientData)
* process the next one instead.
*/
- for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
if (ipPtr->nextHandler == handlerPtr) {
ipPtr->nextHandler = handlerPtr->nextPtr;
}
@@ -337,6 +349,8 @@ Tk_CreateGenericHandler(proc, clientData)
ClientData clientData; /* One-word value to pass to proc. */
{
GenericHandler *handlerPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler));
@@ -344,12 +358,12 @@ Tk_CreateGenericHandler(proc, clientData)
handlerPtr->clientData = clientData;
handlerPtr->deleteFlag = 0;
handlerPtr->nextPtr = NULL;
- if (genericList == NULL) {
- genericList = handlerPtr;
+ if (tsdPtr->genericList == NULL) {
+ tsdPtr->genericList = handlerPtr;
} else {
- lastGenericPtr->nextPtr = handlerPtr;
+ tsdPtr->lastGenericPtr->nextPtr = handlerPtr;
}
- lastGenericPtr = handlerPtr;
+ tsdPtr->lastGenericPtr = handlerPtr;
}
/*
@@ -377,8 +391,10 @@ Tk_DeleteGenericHandler(proc, clientData)
ClientData clientData;
{
GenericHandler * handler;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- for (handler = genericList; handler; handler = handler->nextPtr) {
+ for (handler = tsdPtr->genericList; handler; handler = handler->nextPtr) {
if ((handler->proc == proc) && (handler->clientData == clientData)) {
handler->deleteFlag = 1;
}
@@ -388,6 +404,39 @@ Tk_DeleteGenericHandler(proc, clientData)
/*
*--------------------------------------------------------------
*
+ * TkEventInit --
+ *
+ * This procedures initializes all the event module
+ * structures used by the current thread. It must be
+ * called before any other procedure in this file is
+ * called.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkEventInit _ANSI_ARGS_((void))
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->genericHandlersActive = 0;
+ tsdPtr->pendingPtr = NULL;
+ tsdPtr->genericList = NULL;
+ tsdPtr->lastGenericPtr = NULL;
+ tsdPtr->restrictProc = NULL;
+ tsdPtr->restrictArg = NULL;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* Tk_HandleEvent --
*
* Given an event, invoke all the handlers that have
@@ -415,6 +464,35 @@ Tk_HandleEvent(eventPtr)
Window handlerWindow;
TkDisplay *dispPtr;
Tcl_Interp *interp = (Tcl_Interp *) NULL;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ /*
+ * Hack for simulated X-events: Correct the state field
+ * of the event record to match with the ButtonPress
+ * and ButtonRelease events.
+ */
+
+ if (eventPtr->type==ButtonPress) {
+ dispPtr = TkGetDisplay(eventPtr->xbutton.display);
+ eventPtr->xbutton.state |= dispPtr->mouseButtonState;
+ switch (eventPtr->xbutton.button) {
+ case 1: dispPtr->mouseButtonState |= Button1Mask; break;
+ case 2: dispPtr->mouseButtonState |= Button2Mask; break;
+ case 3: dispPtr->mouseButtonState |= Button3Mask; break;
+ }
+ } else if (eventPtr->type==ButtonRelease) {
+ dispPtr = TkGetDisplay(eventPtr->xbutton.display);
+ switch (eventPtr->xbutton.button) {
+ case 1: dispPtr->mouseButtonState &= ~Button1Mask; break;
+ case 2: dispPtr->mouseButtonState &= ~Button2Mask; break;
+ case 3: dispPtr->mouseButtonState &= ~Button3Mask; break;
+ }
+ eventPtr->xbutton.state |= dispPtr->mouseButtonState;
+ } else if (eventPtr->type==MotionNotify) {
+ dispPtr = TkGetDisplay(eventPtr->xmotion.display);
+ eventPtr->xmotion.state |= dispPtr->mouseButtonState;
+ }
/*
* Next, invoke all the generic event handlers (those that are
@@ -422,9 +500,10 @@ Tk_HandleEvent(eventPtr)
* an event is fully processed, go no further.
*/
- for (genPrevPtr = NULL, genericPtr = genericList; genericPtr != NULL; ) {
+ for (genPrevPtr = NULL, genericPtr = tsdPtr->genericList;
+ genericPtr != NULL; ) {
if (genericPtr->deleteFlag) {
- if (!genericHandlersActive) {
+ if (!tsdPtr->genericHandlersActive) {
GenericHandler *tmpPtr;
/*
@@ -435,12 +514,12 @@ Tk_HandleEvent(eventPtr)
tmpPtr = genericPtr->nextPtr;
if (genPrevPtr == NULL) {
- genericList = tmpPtr;
+ tsdPtr->genericList = tmpPtr;
} else {
genPrevPtr->nextPtr = tmpPtr;
}
if (tmpPtr == NULL) {
- lastGenericPtr = genPrevPtr;
+ tsdPtr->lastGenericPtr = genPrevPtr;
}
(void) ckfree((char *) genericPtr);
genericPtr = tmpPtr;
@@ -449,9 +528,9 @@ Tk_HandleEvent(eventPtr)
} else {
int done;
- genericHandlersActive++;
+ tsdPtr->genericHandlersActive++;
done = (*genericPtr->proc)(genericPtr->clientData, eventPtr);
- genericHandlersActive--;
+ tsdPtr->genericHandlersActive--;
if (done) {
return;
}
@@ -590,19 +669,20 @@ Tk_HandleEvent(eventPtr)
* input context for the window if it hasn't already been done
* (XFilterEvent needs this context).
*/
-
- if (!(winPtr->flags & TK_CHECKED_IC)) {
- if (winPtr->dispPtr->inputMethod != NULL) {
- winPtr->inputContext = XCreateIC(
+ if (winPtr->dispPtr->useInputMethods) {
+ if (!(winPtr->flags & TK_CHECKED_IC)) {
+ if (winPtr->dispPtr->inputMethod != NULL) {
+ winPtr->inputContext = XCreateIC(
winPtr->dispPtr->inputMethod, XNInputStyle,
XIMPreeditNothing|XIMStatusNothing,
XNClientWindow, winPtr->window,
XNFocusWindow, winPtr->window, NULL);
+ }
+ winPtr->flags |= TK_CHECKED_IC;
+ }
+ if (XFilterEvent(eventPtr, None)) {
+ goto done;
}
- winPtr->flags |= TK_CHECKED_IC;
- }
- if (XFilterEvent(eventPtr, None)) {
- goto done;
}
#endif /* TK_USE_INPUT_METHODS */
@@ -623,8 +703,8 @@ Tk_HandleEvent(eventPtr)
ip.eventPtr = eventPtr;
ip.winPtr = winPtr;
ip.nextHandler = NULL;
- ip.nextPtr = pendingPtr;
- pendingPtr = &ip;
+ ip.nextPtr = tsdPtr->pendingPtr;
+ tsdPtr->pendingPtr = &ip;
if (mask == 0) {
if ((eventPtr->type == SelectionClear)
|| (eventPtr->type == SelectionRequest)
@@ -657,7 +737,7 @@ Tk_HandleEvent(eventPtr)
TkBindEventProc(winPtr, eventPtr);
}
}
- pendingPtr = ip.nextPtr;
+ tsdPtr->pendingPtr = ip.nextPtr;
done:
/*
@@ -695,6 +775,8 @@ TkEventDeadWindow(winPtr)
{
register TkEventHandler *handlerPtr;
register InProgress *ipPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* While deleting all the handlers, be careful to check for
@@ -706,7 +788,8 @@ TkEventDeadWindow(winPtr)
while (winPtr->handlerList != NULL) {
handlerPtr = winPtr->handlerList;
winPtr->handlerList = handlerPtr->nextPtr;
- for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
if (ipPtr->nextHandler == handlerPtr) {
ipPtr->nextHandler = NULL;
}
@@ -744,11 +827,13 @@ TkCurrentTime(dispPtr)
TkDisplay *dispPtr; /* Display for which the time is desired. */
{
register XEvent *eventPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (pendingPtr == NULL) {
+ if (tsdPtr->pendingPtr == NULL) {
return dispPtr->lastEventTime;
}
- eventPtr = pendingPtr->eventPtr;
+ eventPtr = tsdPtr->pendingPtr->eventPtr;
switch (eventPtr->type) {
case ButtonPress:
case ButtonRelease:
@@ -798,11 +883,13 @@ Tk_RestrictEvents(proc, arg, prevArgPtr)
* argument. */
{
Tk_RestrictProc *prev;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- prev = restrictProc;
- *prevArgPtr = restrictArg;
- restrictProc = proc;
- restrictArg = arg;
+ prev = tsdPtr->restrictProc;
+ *prevArgPtr = tsdPtr->restrictArg;
+ tsdPtr->restrictProc = proc;
+ tsdPtr->restrictArg = arg;
return prev;
}
@@ -841,7 +928,7 @@ Tk_QueueWindowEvent(eventPtr, position)
* Find our display structure for the event's display.
*/
- for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
if (dispPtr == NULL) {
return;
}
@@ -962,12 +1049,14 @@ WindowEventProc(evPtr, flags)
{
TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr;
Tk_RestrictAction result;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (!(flags & TCL_WINDOW_EVENTS)) {
return 0;
}
- if (restrictProc != NULL) {
- result = (*restrictProc)(restrictArg, &wevPtr->event);
+ if (tsdPtr->restrictProc != NULL) {
+ result = (*tsdPtr->restrictProc)(tsdPtr->restrictArg, &wevPtr->event);
if (result != TK_PROCESS_EVENT) {
if (result == TK_DEFER_EVENT) {
return 0;
@@ -1041,3 +1130,4 @@ Tk_MainLoop()
Tcl_DoOneEvent(0);
}
}
+
diff --git a/tk/generic/tkFileFilter.c b/tk/generic/tkFileFilter.c
index 258f6fdf604..7604746bf9f 100644
--- a/tk/generic/tkFileFilter.c
+++ b/tk/generic/tkFileFilter.c
@@ -10,7 +10,6 @@
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id$
- *
*/
#include "tkInt.h"
@@ -484,3 +483,4 @@ FreeMacFileTypes(clausePtr)
}
clausePtr->macTypes = NULL;
}
+
diff --git a/tk/generic/tkFileFilter.h b/tk/generic/tkFileFilter.h
index 1550d76b45b..ec4d43f9c76 100644
--- a/tk/generic/tkFileFilter.h
+++ b/tk/generic/tkFileFilter.h
@@ -90,3 +90,4 @@ EXTERN int TkGetFileFilters _ANSI_ARGS_ ((Tcl_Interp *interp,
# define TCL_STORAGE_CLASS DLLIMPORT
#endif
+
diff --git a/tk/generic/tkFocus.c b/tk/generic/tkFocus.c
index 4cd35ce9fe2..8ed77cbb309 100644
--- a/tk/generic/tkFocus.c
+++ b/tk/generic/tkFocus.c
@@ -76,12 +76,6 @@ typedef struct TkDisplayFocusInfo {
} DisplayFocusInfo;
/*
- * Global used for debugging.
- */
-
-int tclFocusDebug = 0;
-
-/*
* The following magic value is stored in the "send_event" field of
* FocusIn and FocusOut events that are generated in this file. This
* allows us to separate "real" events coming from the server from
@@ -101,12 +95,11 @@ static void FocusMapProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
static void GenerateFocusEvents _ANSI_ARGS_((TkWindow *sourcePtr,
TkWindow *destPtr));
-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 +114,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,81 +147,94 @@ 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;
}
if (!(newPtr->flags & TK_ALREADY_DEAD)) {
- SetFocus(newPtr, 0);
+ TkSetFocusWin(newPtr, 0);
}
return TCL_OK;
}
}
- 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;
+ }
+ TkSetFocusWin(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;
}
@@ -300,7 +308,7 @@ TkFocusFilterEvent(winPtr, eventPtr)
if ((eventPtr->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
&& (eventPtr->type == FocusIn)) {
- SetFocus(winPtr, eventPtr->xfocus.detail);
+ TkSetFocusWin(winPtr, eventPtr->xfocus.detail);
return 0;
}
@@ -479,7 +487,7 @@ TkFocusFilterEvent(winPtr, eventPtr)
if (eventPtr->xcrossing.focus &&
(displayFocusPtr->focusWinPtr == NULL)
&& !(winPtr->flags & TK_EMBEDDED)) {
- if (tclFocusDebug) {
+ if (dispPtr->focusDebug) {
printf("Focussed implicitly on %s\n",
newFocusPtr->pathName);
}
@@ -504,7 +512,7 @@ TkFocusFilterEvent(winPtr, eventPtr)
if ((dispPtr->implicitWinPtr != NULL)
&& !(winPtr->flags & TK_EMBEDDED)) {
- if (tclFocusDebug) {
+ if (dispPtr->focusDebug) {
printf("Defocussed implicit Async\n");
}
GenerateFocusEvents(displayFocusPtr->focusWinPtr,
@@ -521,7 +529,7 @@ TkFocusFilterEvent(winPtr, eventPtr)
/*
*----------------------------------------------------------------------
*
- * SetFocus --
+ * TkSetFocusWin --
*
* This procedure is invoked to change the focus window for a
* given display in a given application.
@@ -536,8 +544,8 @@ TkFocusFilterEvent(winPtr, eventPtr)
*----------------------------------------------------------------------
*/
-static void
-SetFocus(winPtr, force)
+void
+TkSetFocusWin(winPtr, force)
TkWindow *winPtr; /* Window that is to be the new focus for
* its display and application. */
int force; /* If non-zero, set the X focus to this
@@ -550,8 +558,14 @@ SetFocus(winPtr, force)
int allMapped, serial;
displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr);
- /* CYGNUS LOCAL: We can't just return if force is set. */
- if (winPtr == displayFocusPtr->focusWinPtr && ! force) {
+
+ /*
+ * If force is set, we should make sure we grab the focus regardless
+ * of the current focus window since under Windows, we may need to
+ * take control away from another application.
+ */
+
+ if (winPtr == displayFocusPtr->focusWinPtr && !force) {
return;
}
@@ -814,7 +828,7 @@ TkFocusDeadWindow(winPtr)
*/
if (dispPtr->implicitWinPtr == winPtr) {
- if (tclFocusDebug) {
+ if (dispPtr->focusDebug) {
printf("releasing focus to root after %s died\n",
tlFocusPtr->topLevelPtr->pathName);
}
@@ -842,7 +856,7 @@ TkFocusDeadWindow(winPtr)
tlFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr;
if ((displayFocusPtr->focusWinPtr == winPtr)
&& !(tlFocusPtr->topLevelPtr->flags & TK_ALREADY_DEAD)) {
- if (tclFocusDebug) {
+ if (dispPtr->focusDebug) {
printf("forwarding focus to %s after %s died\n",
tlFocusPtr->topLevelPtr->pathName,
winPtr->pathName);
@@ -937,14 +951,14 @@ FocusMapProc(clientData, eventPtr)
if (eventPtr->type == VisibilityNotify) {
displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr,
winPtr->dispPtr);
- if (tclFocusDebug) {
+ if (winPtr->dispPtr->focusDebug) {
printf("auto-focussing on %s, force %d\n", winPtr->pathName,
displayFocusPtr->forceFocus);
}
Tk_DeleteEventHandler((Tk_Window) winPtr, VisibilityChangeMask,
FocusMapProc, clientData);
displayFocusPtr->focusOnMapPtr = NULL;
- SetFocus(winPtr, displayFocusPtr->forceFocus);
+ TkSetFocusWin(winPtr, displayFocusPtr->forceFocus);
}
}
@@ -997,3 +1011,4 @@ FindDisplayFocusInfo(mainPtr, dispPtr)
mainPtr->displayFocusPtr = displayFocusPtr;
return displayFocusPtr;
}
+
diff --git a/tk/generic/tkFont.c b/tk/generic/tkFont.c
index 018199f6c2b..4ced32a9e59 100644
--- a/tk/generic/tkFont.c
+++ b/tk/generic/tkFont.c
@@ -6,7 +6,7 @@
* 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.
@@ -14,6 +14,7 @@
* RCS: @(#) $Id$
*/
+#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.
@@ -77,6 +71,7 @@ typedef struct LayoutChunk {
CONST char *start; /* Pointer to simple string to be displayed.
* This is a pointer into the TkTextLayout's
* string. */
+ int numBytes; /* The number of bytes in this chunk. */
int numChars; /* The number of characters in this chunk. */
int numDisplayChars; /* The number of characters to display when
* this chunk is displayed. Can be less than
@@ -168,13 +163,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 +184,136 @@ 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. */
+ "bitstream cyberbit", /* Windows popular CJK font */
+ "chicago", /* Mac. */
+ NULL
+};
#define GetFontAttributes(tkfont) \
((CONST TkFontAttributes *) &((TkFont *) (tkfont))->fa)
@@ -208,7 +325,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 +341,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 +374,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 +389,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 +421,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 +517,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 +543,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 +561,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 +569,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 +577,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 +589,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 +602,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 +624,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 +659,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 +670,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 +697,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 +705,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 +733,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 +762,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 +779,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 +799,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 != 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 +843,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 +851,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 +864,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 +878,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 +897,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 +921,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 +939,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 +965,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.
+ */
- fontPtr = (TkFont *) Tcl_GetHashValue(cacheHashPtr);
- fontPtr->refCount++;
- return (Tk_Font) fontPtr;
+ FreeFontObjProc(objPtr);
+ oldFontPtr = NULL;
+ } else if (Tk_Screen(tkwin) == oldFontPtr->screen) {
+ oldFontPtr->resourceRefCount++;
+ return (Tk_Font) oldFontPtr;
+ }
}
- namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, key.string);
+ /*
+ * Next, search the list of fonts that have the name we want, to see
+ * if one of them is for the right screen.
+ */
+
+ new = 0;
+ 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;
+ }
+ }
+
+ /*
+ * 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 +1050,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 +1071,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 +1102,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 +1120,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 +1262,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 +1288,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;
}
- Tcl_DeleteHashEntry(fontPtr->cacheHashPtr);
- TkpDeleteFont(fontPtr);
+ 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;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * 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 +1520,6 @@ Tk_GetFontMetrics(tkfont, fmPtr)
*---------------------------------------------------------------------------
*/
-
int
Tk_PostscriptFontName(tkfont, dsPtr)
Tk_Font tkfont; /* Font in which text will be printed. */
@@ -1154,6 +1561,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 +1574,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 +1663,7 @@ Tk_PostscriptFontName(tkfont, dsPtr)
}
}
- return fontPtr->fa.pointsize;
+ return fontPtr->fa.size;
}
/*
@@ -1273,18 +1685,18 @@ Tk_PostscriptFontName(tkfont, dsPtr)
*/
int
-Tk_TextWidth(tkfont, string, numChars)
+Tk_TextWidth(tkfont, string, numBytes)
Tk_Font tkfont; /* Font in which text will be measured. */
CONST char *string; /* String whose width will be computed. */
- int numChars; /* Number of characters to consider from
+ int numBytes; /* Number of bytes to consider from
* string, or < 0 for strlen(). */
{
int width;
- if (numChars < 0) {
- numChars = strlen(string);
+ if (numBytes < 0) {
+ numBytes = strlen(string);
}
- Tk_MeasureChars(tkfont, string, numChars, 0, 0, &width);
+ Tk_MeasureChars(tkfont, string, numBytes, -1, 0, &width);
return width;
}
@@ -1311,8 +1723,8 @@ Tk_TextWidth(tkfont, string, numChars)
*/
void
-Tk_UnderlineChars(display, drawable, gc, tkfont, string, x, y, firstChar,
- lastChar)
+Tk_UnderlineChars(display, drawable, gc, tkfont, string, x, y, firstByte,
+ lastByte)
Display *display; /* Display on which to draw. */
Drawable drawable; /* Window or pixmap in which to draw. */
GC gc; /* Graphics context for actually drawing
@@ -1324,16 +1736,17 @@ Tk_UnderlineChars(display, drawable, gc, tkfont, string, x, y, firstChar,
* underlined or overstruck. */
int x, y; /* Coordinates at which first character of
* string is drawn. */
- int firstChar; /* Index of first character. */
- int lastChar; /* Index of one after the last character. */
+ int firstByte; /* Index of first byte of first character. */
+ int lastByte; /* Index of first byte after the last
+ * character. */
{
TkFont *fontPtr;
int startX, endX;
fontPtr = (TkFont *) tkfont;
- Tk_MeasureChars(tkfont, string, firstChar, 0, 0, &startX);
- Tk_MeasureChars(tkfont, string, lastChar, 0, 0, &endX);
+ Tk_MeasureChars(tkfont, string, firstByte, -1, 0, &startX);
+ Tk_MeasureChars(tkfont, string, lastByte, -1, 0, &endX);
XFillRectangle(display, drawable, gc, x + startX,
y + fontPtr->underlinePos, (unsigned int) (endX - startX),
@@ -1394,26 +1807,37 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
{
TkFont *fontPtr;
CONST char *start, *end, *special;
- int n, y, charsThisChunk, maxChunks;
+ int n, y, bytesThisChunk, maxChunks;
int baseline, height, curX, newX, maxWidth;
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;
+ if ((fontPtr == NULL) || (string == NULL)) {
+ if (widthPtr != NULL) {
+ *widthPtr = 0;
+ }
+ if (heightPtr != NULL) {
+ *heightPtr = 0;
+ }
+ return NULL;
+ }
+
fmPtr = &fontPtr->fm;
height = fmPtr->ascent + fmPtr->descent;
if (numChars < 0) {
- numChars = strlen(string);
+ numChars = Tcl_NumUtfChars(string, -1);
+ }
+ if (wrapLength == 0) {
+ wrapLength = -1;
}
maxChunks = 1;
@@ -1433,16 +1857,20 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
curX = 0;
- end = string + numChars;
+ end = Tcl_UtfAtIndex(string, numChars);
special = string;
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) {
/*
* Find the next special character in the string.
+ *
+ * INTL: Note that it is safe to increment by byte, because we are
+ * looking for 7-bit characters that will appear unchanged in
+ * UTF-8. At some point we may need to support the full Unicode
+ * whitespace set.
*/
for (special = start; special < end; special++) {
@@ -1466,15 +1894,15 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
chunkPtr = NULL;
if (start < special) {
- charsThisChunk = Tk_MeasureChars(tkfont, start, special - start,
+ bytesThisChunk = Tk_MeasureChars(tkfont, start, special - start,
wrapLength - curX, flags, &newX);
newX += curX;
flags &= ~TK_AT_LEAST_ONE;
- if (charsThisChunk > 0) {
+ if (bytesThisChunk > 0) {
chunkPtr = NewChunk(&layoutPtr, &maxChunks, start,
- charsThisChunk, curX, newX, baseline);
+ bytesThisChunk, curX, newX, baseline);
- start += charsThisChunk;
+ start += bytesThisChunk;
curX = newX;
}
}
@@ -1482,6 +1910,9 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
if ((start == special) && (special < end)) {
/*
* Handle the special character.
+ *
+ * INTL: Special will be pointing at a 7-bit character so we
+ * can safely treat it as a single byte.
*/
chunkPtr = NULL;
@@ -1502,7 +1933,7 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
continue;
}
} else {
- NewChunk(&layoutPtr, &maxChunks, start, 1, curX, 1000000000,
+ NewChunk(&layoutPtr, &maxChunks, start, 1, curX, curX,
baseline)->numDisplayChars = -1;
start++;
goto wrapLine;
@@ -1515,7 +1946,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;
@@ -1529,15 +1960,21 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
start++;
}
if (chunkPtr != NULL) {
+ CONST char *end;
+
/*
* Append all the extra spaces on this line to the end of the
- * last text chunk.
+ * last text chunk. This is a little tricky because we are
+ * switching back and forth between characters and bytes.
*/
- charsThisChunk = start - (chunkPtr->start + chunkPtr->numChars);
- if (charsThisChunk > 0) {
- chunkPtr->numChars += Tk_MeasureChars(tkfont,
- chunkPtr->start + chunkPtr->numChars, charsThisChunk,
- 0, 0, &chunkPtr->totalWidth);
+
+ end = chunkPtr->start + chunkPtr->numBytes;
+ bytesThisChunk = start - end;
+ if (bytesThisChunk > 0) {
+ bytesThisChunk = Tk_MeasureChars(tkfont, end, bytesThisChunk,
+ -1, 0, &chunkPtr->totalWidth);
+ chunkPtr->numBytes += bytesThisChunk;
+ chunkPtr->numChars += Tcl_NumUtfChars(end, bytesThisChunk);
chunkPtr->totalWidth += curX;
}
}
@@ -1559,19 +1996,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;
@@ -1586,36 +2011,13 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
if ((layoutPtr->numChunks > 0) && ((flags & TK_IGNORE_NEWLINES) == 0)) {
if (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\n') {
chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, 0, curX,
- 1000000000, baseline);
+ curX, baseline);
chunkPtr->numDisplayChars = -1;
+ Tcl_DStringAppend(&lineBuffer, (char *) &curX, sizeof(curX));
baseline += height;
}
}
- /*
- * Using maximum line length, shift all the chunks so that the lines are
- * all justified correctly.
- */
-
- curLine = 0;
- chunkPtr = layoutPtr->chunks;
- y = chunkPtr->y;
- for (n = 0; n < layoutPtr->numChunks; n++) {
- int extra;
-
- if (chunkPtr->y != y) {
- curLine++;
- y = chunkPtr->y;
- }
- extra = maxWidth - lineLengths[curLine];
- if (justify == TK_JUSTIFY_CENTER) {
- chunkPtr->x += extra / 2;
- } else if (justify == TK_JUSTIFY_RIGHT) {
- chunkPtr->x += extra;
- }
- chunkPtr++;
- }
-
layoutPtr->width = maxWidth;
layoutHeight = baseline - fmPtr->ascent;
if (layoutPtr->numChunks == 0) {
@@ -1629,12 +2031,38 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
layoutPtr->numChunks = 1;
layoutPtr->chunks[0].start = string;
+ layoutPtr->chunks[0].numBytes = 0;
layoutPtr->chunks[0].numChars = 0;
layoutPtr->chunks[0].numDisplayChars = -1;
layoutPtr->chunks[0].x = 0;
layoutPtr->chunks[0].y = fmPtr->ascent;
layoutPtr->chunks[0].totalWidth = 0;
layoutPtr->chunks[0].displayWidth = 0;
+ } else {
+ /*
+ * Using maximum line length, shift all the chunks so that the lines
+ * are all justified correctly.
+ */
+
+ curLine = 0;
+ chunkPtr = layoutPtr->chunks;
+ y = chunkPtr->y;
+ lineLengths = (int *) Tcl_DStringValue(&lineBuffer);
+ for (n = 0; n < layoutPtr->numChunks; n++) {
+ int extra;
+
+ if (chunkPtr->y != y) {
+ curLine++;
+ y = chunkPtr->y;
+ }
+ extra = maxWidth - lineLengths[curLine];
+ if (justify == TK_JUSTIFY_CENTER) {
+ chunkPtr->x += extra / 2;
+ } else if (justify == TK_JUSTIFY_RIGHT) {
+ chunkPtr->x += extra;
+ }
+ chunkPtr++;
+ }
}
if (widthPtr != NULL) {
@@ -1643,9 +2071,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;
}
@@ -1718,6 +2144,8 @@ Tk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar)
{
TextLayout *layoutPtr;
int i, numDisplayChars, drawX;
+ CONST char *firstByte;
+ CONST char *lastByte;
LayoutChunk *chunkPtr;
layoutPtr = (TextLayout *) layout;
@@ -1735,15 +2163,18 @@ Tk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar)
if (firstChar <= 0) {
drawX = 0;
firstChar = 0;
+ firstByte = chunkPtr->start;
} else {
- Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start, firstChar,
- 0, 0, &drawX);
+ firstByte = Tcl_UtfAtIndex(chunkPtr->start, firstChar);
+ Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start,
+ firstByte - chunkPtr->start, -1, 0, &drawX);
}
if (lastChar < numDisplayChars) {
numDisplayChars = lastChar;
}
+ lastByte = Tcl_UtfAtIndex(chunkPtr->start, numDisplayChars);
Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont,
- chunkPtr->start + firstChar, numDisplayChars - firstChar,
+ firstByte, lastByte - firstByte,
x + chunkPtr->x + drawX, y + chunkPtr->y);
}
firstChar -= chunkPtr->numChars;
@@ -1791,18 +2222,21 @@ Tk_UnderlineTextLayout(display, drawable, gc, layout, x, y, underline)
int underline; /* Index of the single character to
* underline, or -1 for no underline. */
{
- TextLayout *layoutPtr;
+ TextLayout *layoutPtr = (TextLayout *) layout;
TkFont *fontPtr;
- int xx, yy, width, height;
+ int xx, yy, width, height, underlineByte;
- if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0)
- && (width != 0)) {
- layoutPtr = (TextLayout *) layout;
- fontPtr = (TkFont *) layoutPtr->tkfont;
+ if (underline > -1) {
+ underlineByte = Tcl_UtfAtIndex(layoutPtr->string, underline)
+ - layoutPtr->string;
+ if ((Tk_CharBbox(layout, underlineByte, &xx, &yy, &width, &height) != 0)
+ && (width != 0)) {
+ fontPtr = (TkFont *) layoutPtr->tkfont;
- XFillRectangle(display, drawable, gc, x + xx,
- y + yy + fontPtr->fm.ascent + fontPtr->underlinePos,
- (unsigned int) width, (unsigned int) fontPtr->underlineHeight);
+ XFillRectangle(display, drawable, gc, x + xx,
+ y + yy + fontPtr->fm.ascent + fontPtr->underlinePos,
+ (unsigned int) width, (unsigned int) fontPtr->underlineHeight);
+ }
}
}
@@ -1849,7 +2283,7 @@ Tk_PointToChar(layout, x, y)
TextLayout *layoutPtr;
LayoutChunk *chunkPtr, *lastPtr;
TkFont *fontPtr;
- int i, n, dummy, baseline, pos;
+ int i, n, dummy, baseline, pos, numChars;
if (y < 0) {
/*
@@ -1867,6 +2301,7 @@ Tk_PointToChar(layout, x, y)
layoutPtr = (TextLayout *) layout;
fontPtr = (TkFont *) layoutPtr->tkfont;
lastPtr = chunkPtr = layoutPtr->chunks;
+ numChars = 0;
for (i = 0; i < layoutPtr->numChunks; i++) {
baseline = chunkPtr->y;
if (y < baseline + fontPtr->fm.descent) {
@@ -1876,7 +2311,7 @@ Tk_PointToChar(layout, x, y)
* the index of the first character on this line.
*/
- return chunkPtr->start - layoutPtr->string;
+ return numChars;
}
if (x >= layoutPtr->width) {
/*
@@ -1907,13 +2342,14 @@ Tk_PointToChar(layout, x, y)
* tab or newline char.
*/
- return chunkPtr->start - layoutPtr->string;
+ return numChars;
}
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->numBytes, x - chunkPtr->x,
+ 0, &dummy);
+ return numChars + Tcl_NumUtfChars(chunkPtr->start, n);
}
+ numChars += chunkPtr->numChars;
lastPtr = chunkPtr;
chunkPtr++;
i++;
@@ -1925,12 +2361,13 @@ Tk_PointToChar(layout, x, y)
* chunk on this line.
*/
- pos = (lastPtr->start + lastPtr->numChars) - layoutPtr->string;
+ pos = numChars;
if (i < layoutPtr->numChunks) {
pos--;
}
return pos;
}
+ numChars += chunkPtr->numChars;
lastPtr = chunkPtr;
chunkPtr++;
}
@@ -1997,6 +2434,7 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr)
int i, x, w;
Tk_Font tkfont;
TkFont *fontPtr;
+ CONST char *end;
if (index < 0) {
if (xPtr)
@@ -2023,12 +2461,15 @@ Tk_CharBbox(layout, index, xPtr, yPtr, widthPtr, heightPtr)
goto check;
}
} else if (index < chunkPtr->numChars) {
+ end = Tcl_UtfAtIndex(chunkPtr->start, index);
if (xPtr != NULL) {
- Tk_MeasureChars(tkfont, chunkPtr->start, index, 0, 0, &x);
+ Tk_MeasureChars(tkfont, chunkPtr->start,
+ end - chunkPtr->start, -1, 0, &x);
x += chunkPtr->x;
}
if (widthPtr != NULL) {
- Tk_MeasureChars(tkfont, chunkPtr->start + index, 1, 0, 0, &w);
+ Tk_MeasureChars(tkfont, end, Tcl_UtfNext(end) - end,
+ -1, 0, &w);
}
goto check;
}
@@ -2284,7 +2725,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:
@@ -2302,6 +2743,8 @@ Tk_TextLayoutToPostscript(interp, layout)
char buf[MAXUSE+10];
LayoutChunk *chunkPtr;
int i, j, used, c, baseline;
+ Tcl_UniChar ch;
+ CONST char *p;
TextLayout *layoutPtr;
layoutPtr = (TextLayout *) layout;
@@ -2322,8 +2765,16 @@ Tk_TextLayoutToPostscript(interp, layout)
buf[used++] = 't';
}
} else {
+ p = chunkPtr->start;
for (j = 0; j < chunkPtr->numDisplayChars; j++) {
- c = UCHAR(chunkPtr->start[j]);
+ /*
+ * INTL: For now we just treat the characters as binary
+ * data and display the lower byte. Eventually this should
+ * be revised to handle international postscript fonts.
+ */
+
+ p += Tcl_UtfToUniChar(p, &ch);
+ c = UCHAR(ch & 0xff);
if ((c == '(') || (c == ')') || (c == '\\') || (c < 0x20)
|| (c >= UCHAR(0x7f))) {
/*
@@ -2367,36 +2818,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
@@ -2427,68 +2848,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 ((i+2 >= objc) && (objc & 1)) {
+ /*
+ * This test occurs after Tcl_GetIndexFromObj() so that
+ * "font create xyz -xyz" will return the error message
+ * that "-xyz" is a bad option, rather than that the value
+ * for "-xyz" is missing.
+ */
+
+ 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;
@@ -2523,18 +2950,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;
}
@@ -2542,55 +2970,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;
}
@@ -2605,7 +3021,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:
@@ -2622,20 +3038,23 @@ 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;
char *string;
- string = Tcl_GetStringFromObj(objPtr, NULL);
+ TkInitFontAttributes(faPtr);
+
+ string = Tcl_GetString(objPtr);
if (*string == '-') {
/*
* This may be an XLFD or an "-option value" string.
@@ -2648,7 +3067,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;
}
@@ -2661,15 +3081,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;
}
}
@@ -2678,21 +3099,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;
@@ -2703,23 +3122,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;
@@ -2729,9 +3147,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;
@@ -2740,7 +3157,69 @@ 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, numBytes, curX, newX, y)
+ TextLayout **layoutPtrPtr;
+ int *maxPtr;
+ CONST char *start;
+ int numBytes;
+ int curX;
+ int newX;
+ int y;
+{
+ TextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ int maxChunks, numChars;
+ size_t s;
+
+ layoutPtr = *layoutPtrPtr;
+ maxChunks = *maxPtr;
+ if (layoutPtr->numChunks == maxChunks) {
+ maxChunks *= 2;
+ s = sizeof(TextLayout) + ((maxChunks - 1) * sizeof(LayoutChunk));
+ layoutPtr = (TextLayout *) ckrealloc((char *) layoutPtr, s);
+
+ *layoutPtrPtr = layoutPtr;
+ *maxPtr = maxChunks;
+ }
+ numChars = Tcl_NumUtfChars(start, numBytes);
+ chunkPtr = &layoutPtr->chunks[layoutPtr->numChunks];
+ chunkPtr->start = start;
+ chunkPtr->numBytes = numBytes;
+ 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.
*
@@ -2756,18 +3235,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;
@@ -2781,27 +3273,32 @@ TkParseXLFD(string, xaPtr)
field[0] = src;
for (i = 0; *src != '\0'; src++) {
- if (isupper(UCHAR(*src))) {
- *src = tolower(UCHAR(*src));
+ if (!(*src & 0x80)
+ && Tcl_UniCharIsUpper(UCHAR(*src))) {
+ *src = (char) Tcl_UniCharToLower(UCHAR(*src));
}
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]))) {
@@ -2828,19 +3325,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])) {
@@ -2851,9 +3348,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] == '[') {
/*
@@ -2866,10 +3366,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;
}
@@ -2891,14 +3391,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. */
@@ -2908,14 +3408,11 @@ 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_ENCODING])) {
- xaPtr->encoding = atoi(field[XLFD_ENCODING]);
+ if (FieldSpecified(field[XLFD_CHARSET])) {
+ xaPtr->charset = Tk_GetUid(field[XLFD_CHARSET]);
+ } else {
+ xaPtr->charset = Tk_GetUid("iso8859-1");
}
-
Tcl_DStringFree(&ds);
return TCL_OK;
}
@@ -2957,61 +3454,225 @@ 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;
}
/* CYGNUS LOCAL: This routine is called on Windows to update a named
@@ -3033,8 +3694,9 @@ TkUpdateFonts(tkwin, changed)
while (namedHashPtr != NULL) {
nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr);
if ((*changed)(&nfPtr->fa)) {
- UpdateDependantFonts(fiPtr, tkwin, namedHashPtr);
+ UpdateDependentFonts(fiPtr, tkwin, namedHashPtr);
}
namedHashPtr = Tcl_NextHashEntry(&search);
}
}
+
diff --git a/tk/generic/tkFont.h b/tk/generic/tkFont.h
index 7bd9928fbea..5c891e3e8e5 100644
--- a/tk/generic/tkFont.h
+++ b/tk/generic/tkFont.h
@@ -5,7 +5,7 @@
* 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.
@@ -28,8 +28,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. */
@@ -91,13 +92,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
@@ -106,7 +119,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.
*/
@@ -121,6 +134,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;
/*
@@ -130,16 +148,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;
/*
@@ -155,15 +169,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.
*/
@@ -180,28 +185,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));
@@ -218,3 +228,5 @@ EXTERN void TkUpdateFonts _ANSI_ARGS_((Tk_Window tkwin,
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKFONT */
+
+
diff --git a/tk/generic/tkFrame.c b/tk/generic/tkFrame.c
index ded4e4ca4bd..949fb18c226 100644
--- a/tk/generic/tkFrame.c
+++ b/tk/generic/tkFrame.c
@@ -7,7 +7,7 @@
* 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.
@@ -167,22 +167,25 @@ static Tk_ConfigSpec configSpecs[] = {
*/
static int ConfigureFrame _ANSI_ARGS_((Tcl_Interp *interp,
- Frame *framePtr, int argc, char **argv,
+ Frame *framePtr, int objc, Tcl_Obj *CONST objv[],
int flags));
+static int CreateFrame _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST argv[],
+ int toplevel, char *appName));
static void DestroyFrame _ANSI_ARGS_((char *memPtr));
static void DisplayFrame _ANSI_ARGS_((ClientData clientData));
static void FrameCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static void FrameEventProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
-static int FrameWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+static int FrameWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
static void MapFrame _ANSI_ARGS_((ClientData clientData));
/*
*--------------------------------------------------------------
*
- * Tk_FrameCmd, Tk_ToplevelCmd --
+ * Tk_FrameObjCmd, Tk_ToplevelObjCmd --
*
* These procedures are invoked to process the "frame" and
* "toplevel" Tcl commands. See the user documentation for
@@ -199,31 +202,31 @@ static void MapFrame _ANSI_ARGS_((ClientData clientData));
*/
int
-Tk_FrameCmd(clientData, interp, argc, argv)
+Tk_FrameObjCmd(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. */
{
- return TkCreateFrame(clientData, interp, argc, argv, 0, (char *) NULL);
+ return CreateFrame(clientData, interp, objc, objv, 0, (char *) NULL);
}
int
-Tk_ToplevelCmd(clientData, interp, argc, argv)
+Tk_ToplevelObjCmd(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. */
{
- return TkCreateFrame(clientData, interp, argc, argv, 1, (char *) NULL);
+ return CreateFrame(clientData, interp, objc, objv, 1, (char *) NULL);
}
/*
*--------------------------------------------------------------
*
- * TkFrameCreate --
+ * TkCreateFrame --
*
* This procedure is invoked to process the "frame" and "toplevel"
* Tcl commands; it is also invoked directly by Tk_Init to create
@@ -253,18 +256,47 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
* NULL: gives the base name to use for the
* new application. */
{
+ int result, i;
+ Tcl_Obj **objv = (Tcl_Obj **) ckalloc((argc+1) * sizeof(Tcl_Obj **));
+ for (i=0; i<argc; i++) {
+ objv[i] = Tcl_NewStringObj(argv[i], -1);
+ Tcl_IncrRefCount(objv[i]);
+ }
+ objv[argc] = NULL;
+ result = CreateFrame(clientData, interp, argc, objv, toplevel, appName);
+ for (i=0; i<argc; i++) {
+ Tcl_DecrRefCount(objv[i]);
+ }
+ ckfree((char *) objv);
+ return result;
+}
+
+static int
+CreateFrame(clientData, interp, objc, objv, toplevel, appName)
+ ClientData clientData; /* Main window associated with interpreter.
+ * If we're called by Tk_Init to create a
+ * new application, then this is NULL. */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument objects. */
+ int toplevel; /* Non-zero means create a toplevel window,
+ * zero means create a frame. */
+ char *appName; /* Should only be non-NULL if clientData is
+ * NULL: gives the base name to use for the
+ * new application. */
+{
Tk_Window tkwin = (Tk_Window) clientData;
Frame *framePtr;
Tk_Window new;
char *className, *screenName, *visualName, *colormapName, *arg, *useOption;
- int i, c, length, depth;
+ int i, c, depth;
+ size_t length;
unsigned int mask;
Colormap colormap;
Visual *visual;
- 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;
}
@@ -277,28 +309,27 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
className = colormapName = screenName = visualName = useOption = NULL;
colormap = None;
- for (i = 2; i < argc; i += 2) {
- arg = argv[i];
- length = strlen(arg);
+ for (i = 2; i < objc; i += 2) {
+ arg = Tcl_GetStringFromObj(objv[i], (int *) &length);
if (length < 2) {
continue;
}
c = arg[1];
- if ((c == 'c') && (strncmp(arg, "-class", strlen(arg)) == 0)
+ if ((c == 'c') && (strncmp(arg, "-class", length) == 0)
&& (length >= 3)) {
- className = argv[i+1];
+ className = Tcl_GetString(objv[i+1]);
} else if ((c == 'c')
- && (strncmp(arg, "-colormap", strlen(arg)) == 0)) {
- colormapName = argv[i+1];
+ && (strncmp(arg, "-colormap", length) == 0)) {
+ colormapName = Tcl_GetString(objv[i+1]);
} else if ((c == 's') && toplevel
- && (strncmp(arg, "-screen", strlen(arg)) == 0)) {
- screenName = argv[i+1];
+ && (strncmp(arg, "-screen", length) == 0)) {
+ screenName = Tcl_GetString(objv[i+1]);
} else if ((c == 'u') && toplevel
- && (strncmp(arg, "-use", strlen(arg)) == 0)) {
- useOption = argv[i+1];
+ && (strncmp(arg, "-use", length) == 0)) {
+ useOption = Tcl_GetString(objv[i+1]);
} else if ((c == 'v')
- && (strncmp(arg, "-visual", strlen(arg)) == 0)) {
- visualName = argv[i+1];
+ && (strncmp(arg, "-visual", length) == 0)) {
+ visualName = Tcl_GetString(objv[i+1]);
}
}
@@ -321,7 +352,8 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
screenName = (toplevel) ? "" : NULL;
}
if (tkwin != NULL) {
- new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], screenName);
+ new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
+ screenName);
} else {
/*
* We were called from Tk_Init; create a new application.
@@ -392,8 +424,8 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
framePtr->tkwin = new;
framePtr->display = Tk_Display(new);
framePtr->interp = interp;
- framePtr->widgetCmd = Tcl_CreateCommand(interp,
- Tk_PathName(new), FrameWidgetCmd,
+ framePtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(new), FrameWidgetObjCmd,
(ClientData) framePtr, FrameCmdDeletedProc);
framePtr->className = NULL;
framePtr->mask = (toplevel) ? TOPLEVEL : FRAME;
@@ -426,7 +458,7 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
mask |= ActivateMask;
}
Tk_CreateEventHandler(new, mask, FrameEventProc, (ClientData) framePtr);
- if (ConfigureFrame(interp, framePtr, argc-2, argv+2, 0) != TCL_OK) {
+ if (ConfigureFrame(interp, framePtr, objc-2, objv+2, 0) != TCL_OK) {
goto error;
}
if ((framePtr->isContainer)) {
@@ -441,7 +473,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:
@@ -454,7 +486,7 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
/*
*--------------------------------------------------------------
*
- * FrameWidgetCmd --
+ * FrameWidgetObjCmd --
*
* This procedure is invoked to process the Tcl command
* that corresponds to a frame widget. See the user
@@ -470,83 +502,87 @@ TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
*/
static int
-FrameWidgetCmd(clientData, interp, argc, argv)
+FrameWidgetObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about frame 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. */
{
+ static char *frameOptions[] = {
+ "cget", "configure", (char *) NULL
+ };
+ enum options {
+ FRAME_CGET, FRAME_CONFIGURE
+ };
register Frame *framePtr = (Frame *) clientData;
- int result;
+ int result = TCL_OK, index;
size_t length;
int c, i;
- 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], frameOptions, "option", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
Tcl_Preserve((ClientData) framePtr);
- 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);
+ switch ((enum options) index) {
+ case FRAME_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
result = TCL_ERROR;
goto done;
}
result = Tk_ConfigureValue(interp, framePtr->tkwin, configSpecs,
- (char *) framePtr, argv[2], framePtr->mask);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
+ (char *) framePtr, Tcl_GetString(objv[2]), framePtr->mask);
+ break;
+ }
+ case FRAME_CONFIGURE: {
+ if (objc == 2) {
result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
(char *) framePtr, (char *) NULL, framePtr->mask);
- } else if (argc == 3) {
+ } else if (objc == 3) {
result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
- (char *) framePtr, argv[2], framePtr->mask);
+ (char *) framePtr, Tcl_GetString(objv[2]), framePtr->mask);
} else {
/*
* Don't allow the options -class, -colormap, -container,
* -newcmap, -screen, -use, or -visual to be changed.
*/
- for (i = 2; i < argc; i++) {
- length = strlen(argv[i]);
+ for (i = 2; i < objc; i++) {
+ char *arg = Tcl_GetStringFromObj(objv[i], (int *) &length);
if (length < 2) {
continue;
}
- c = argv[i][1];
- if (((c == 'c') && (strncmp(argv[i], "-class", length) == 0)
+ c = arg[1];
+ if (((c == 'c') && (strncmp(arg, "-class", length) == 0)
&& (length >= 2))
|| ((c == 'c') && (framePtr->mask == TOPLEVEL)
- && (strncmp(argv[i], "-colormap", length) == 0)
+ && (strncmp(arg, "-colormap", length) == 0)
&& (length >= 3))
|| ((c == 'c')
- && (strncmp(argv[i], "-container", length) == 0)
+ && (strncmp(arg, "-container", length) == 0)
&& (length >= 3))
|| ((c == 's') && (framePtr->mask == TOPLEVEL)
- && (strncmp(argv[i], "-screen", length) == 0))
+ && (strncmp(arg, "-screen", length) == 0))
|| ((c == 'u') && (framePtr->mask == TOPLEVEL)
- && (strncmp(argv[i], "-use", length) == 0))
+ && (strncmp(arg, "-use", length) == 0))
|| ((c == 'v') && (framePtr->mask == TOPLEVEL)
- && (strncmp(argv[i], "-visual", length) == 0))) {
- Tcl_AppendResult(interp, "can't modify ", argv[i],
+ && (strncmp(arg, "-visual", length) == 0))) {
+ Tcl_AppendResult(interp, "can't modify ", arg,
" option after widget is created", (char *) NULL);
result = TCL_ERROR;
goto done;
}
}
- result = ConfigureFrame(interp, framePtr, argc-2, argv+2,
+ result = ConfigureFrame(interp, framePtr, objc-2, objv+2,
TK_CONFIG_ARGV_ONLY);
}
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be cget or configure", (char *) NULL);
- result = TCL_ERROR;
+ break;
+ }
}
done:
@@ -591,13 +627,13 @@ DestroyFrame(memPtr)
*
* ConfigureFrame --
*
- * This procedure is called to process an argv/argc list, plus
+ * This procedure is called to process an objv/objc list, plus
* the Tk option database, in order to configure (or
* reconfigure) a frame widget.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then 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,
@@ -608,12 +644,12 @@ DestroyFrame(memPtr)
*/
static int
-ConfigureFrame(interp, framePtr, argc, argv, flags)
+ConfigureFrame(interp, framePtr, objc, objv, flags)
Tcl_Interp *interp; /* Used for error reporting. */
register Frame *framePtr; /* 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 objc; /* Number of valid entries in objv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
char *oldMenuName;
@@ -630,7 +666,8 @@ ConfigureFrame(interp, framePtr, argc, argv, flags)
}
if (Tk_ConfigureWidget(interp, framePtr->tkwin, configSpecs,
- argc, argv, (char *) framePtr, flags | framePtr->mask) != TCL_OK) {
+ objc, (char **) objv, (char *) framePtr,
+ flags | framePtr->mask | TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -694,7 +731,8 @@ DisplayFrame(clientData)
{
register Frame *framePtr = (Frame *) clientData;
register Tk_Window tkwin = framePtr->tkwin;
- GC gc;
+ void (* drawFunction) _ANSI_ARGS_((Tk_Window, Drawable, Tk_3DBorder,
+ int, int, int, int, int, int)) = Tk_Fill3DRectangle;
framePtr->flags &= ~REDRAW_PENDING;
if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)
@@ -703,7 +741,7 @@ DisplayFrame(clientData)
}
if (framePtr->border != NULL) {
- Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
+ drawFunction(tkwin, Tk_WindowId(tkwin),
framePtr->border, framePtr->highlightWidth,
framePtr->highlightWidth,
Tk_Width(tkwin) - 2*framePtr->highlightWidth,
@@ -711,15 +749,19 @@ DisplayFrame(clientData)
framePtr->borderWidth, framePtr->relief);
}
if (framePtr->highlightWidth != 0) {
+ GC fgGC, bgGC;
+
+ bgGC = Tk_GCForColor(framePtr->highlightBgColorPtr,
+ Tk_WindowId(tkwin));
if (framePtr->flags & GOT_FOCUS) {
- gc = Tk_GCForColor(framePtr->highlightColorPtr,
+ fgGC = Tk_GCForColor(framePtr->highlightColorPtr,
+ Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC, framePtr->highlightWidth,
Tk_WindowId(tkwin));
} else {
- gc = Tk_GCForColor(framePtr->highlightBgColorPtr,
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC, framePtr->highlightWidth,
Tk_WindowId(tkwin));
}
- Tk_DrawFocusHighlight(tkwin, gc, framePtr->highlightWidth,
- Tk_WindowId(tkwin));
}
}
@@ -933,7 +975,11 @@ TkInstallFrameMenu(tkwin)
if (winPtr->mainPtr != NULL) {
Frame *framePtr;
framePtr = (Frame*) winPtr->instanceData;
+ if (framePtr == NULL) {
+ panic("TkInstallFrameMenu couldn't get frame pointer");
+ }
TkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp,
framePtr->menuName);
}
}
+
diff --git a/tk/generic/tkGC.c b/tk/generic/tkGC.c
index 9d1c6949009..8ddcd391e4c 100644
--- a/tk/generic/tkGC.c
+++ b/tk/generic/tkGC.c
@@ -14,9 +14,6 @@
*/
#include "tkPort.h"
-#include "tk.h"
-
-/* CYGNUS LOCAL, for TkRegisterColorGC. */
#include "tkInt.h"
/*
@@ -32,46 +29,20 @@ typedef struct {
int refCount; /* Number of active uses of gc. */
Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting
* this structure). */
- /* CYGNUS LOCAL. */
- XColor *foreground; /* Foreground color. */
- XColor *background; /* Background color. */
} TkGC;
-/*
- * Hash table to map from a GC's values to a TkGC structure describing
- * a GC with those values (used by Tk_GetGC).
- */
-
-static Tcl_HashTable valueTable;
typedef struct {
XGCValues values; /* Desired values for GC. */
Display *display; /* Display for which GC is valid. */
int screenNum; /* screen number of display */
int depth; /* and depth for which GC is valid. */
- /* CYGNUS LOCAL. */
- XColor *foreground; /* Foreground color. */
- XColor *background; /* Background color. */
} ValueKey;
/*
- * Hash table for <display + GC> -> TkGC mapping. This table is used by
- * Tk_FreeGC.
- */
-
-static Tcl_HashTable idTable;
-typedef struct {
- Display *display; /* Display for which GC was allocated. */
- GC gc; /* X's identifier for GC. */
-} IdKey;
-
-static int initialized = 0; /* 0 means static structures haven't been
- * initialized yet. */
-
-/*
* Forward declarations for procedures defined in this file:
*/
-static void GCInit _ANSI_ARGS_((void));
+static void GCInit _ANSI_ARGS_((TkDisplay *dispPtr));
/*
*----------------------------------------------------------------------
@@ -95,11 +66,8 @@ static void GCInit _ANSI_ARGS_((void));
*----------------------------------------------------------------------
*/
-/* CYGNUS LOCAL: Rename this to Tk_GetGCColor. The new Tk_GetGC is
- below. */
-
GC
-Tk_GetGCColor(tkwin, valueMask, valuePtr, foreground, background)
+Tk_GetGC(tkwin, valueMask, valuePtr)
Tk_Window tkwin; /* Window in which GC will be used. */
register unsigned long valueMask;
/* 1 bits correspond to values specified
@@ -108,31 +76,18 @@ Tk_GetGCColor(tkwin, valueMask, valuePtr, foreground, background)
register XGCValues *valuePtr;
/* Values are specified here for bits set
* in valueMask. */
- /* CYGNUS LOCAL. */
- XColor *foreground; /* Foreground color. */
- XColor *background; /* Background color. */
{
ValueKey valueKey;
- IdKey idKey;
Tcl_HashEntry *valueHashPtr, *idHashPtr;
register TkGC *gcPtr;
int new;
Drawable d, freeDrawable;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- GCInit();
+ if (!dispPtr->gcInit) {
+ GCInit(dispPtr);
}
-#if !defined(__WIN32__) && !defined(_WIN32)
- /* CYGNUS LOCAL. We only care about special foreground and
- background colors on Windows. If we are on some other
- platform, just ignore them. If we don't do this, we may
- allocate an unnecessary GC if we have two colors with different
- names but the same pixel value. */
- foreground = NULL;
- background = NULL;
-#endif
-
/*
* Must zero valueKey at start to clear out pad bytes that may be
* part of structure on some systems.
@@ -263,12 +218,8 @@ Tk_GetGCColor(tkwin, valueMask, valuePtr, foreground, background)
valueKey.display = Tk_Display(tkwin);
valueKey.screenNum = Tk_ScreenNumber(tkwin);
valueKey.depth = Tk_Depth(tkwin);
-
- /* CYGNUS LOCAL. Set colors. */
- valueKey.foreground = foreground;
- valueKey.background = background;
-
- valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new);
+ valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable,
+ (char *) &valueKey, &new);
if (!new) {
gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr);
gcPtr->refCount++;
@@ -305,9 +256,8 @@ Tk_GetGCColor(tkwin, valueMask, valuePtr, foreground, background)
gcPtr->display = valueKey.display;
gcPtr->refCount = 1;
gcPtr->valueHashPtr = valueHashPtr;
- idKey.display = valueKey.display;
- idKey.gc = gcPtr->gc;
- idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new);
+ idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable,
+ (char *) gcPtr->gc, &new);
if (!new) {
panic("GC already registered in Tk_GetGC");
}
@@ -317,36 +267,8 @@ Tk_GetGCColor(tkwin, valueMask, valuePtr, foreground, background)
Tk_FreePixmap(valueKey.display, freeDrawable);
}
- /* CYGNUS LOCAL. Record and register the colors. */
- gcPtr->foreground = foreground;
- gcPtr->background = background;
- if (foreground != NULL) {
- TkRegisterColorGC(foreground, valueKey.display, gcPtr->gc,
- GCForeground);
- }
- if (background != NULL) {
- TkRegisterColorGC(background, valueKey.display, gcPtr->gc,
- GCBackground);
- }
-
return gcPtr->gc;
}
-
-/* CYGNUS LOCAL. Tk_GetGC now just calls Tk_GetGCColor. */
-
-GC
-Tk_GetGC(tkwin, valueMask, valuePtr)
- Tk_Window tkwin; /* Window in which GC will be used. */
- register unsigned long valueMask;
- /* 1 bits correspond to values specified
- * in *valuesPtr; other values are set
- * from defaults. */
- register XGCValues *valuePtr;
- /* Values are specified here for bits set
- * in valueMask. */
-{
- return Tk_GetGCColor(tkwin, valueMask, valuePtr, NULL, NULL);
-}
/*
*----------------------------------------------------------------------
@@ -371,33 +293,21 @@ Tk_FreeGC(display, gc)
Display *display; /* Display for which gc was allocated. */
GC gc; /* Graphics context to be released. */
{
- IdKey idKey;
Tcl_HashEntry *idHashPtr;
register TkGC *gcPtr;
+ TkDisplay *dispPtr = TkGetDisplay(display);
- if (!initialized) {
+ if (!dispPtr->gcInit) {
panic("Tk_FreeGC called before Tk_GetGC");
}
- idKey.display = display;
- idKey.gc = gc;
- idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey);
+ idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc);
if (idHashPtr == NULL) {
panic("Tk_FreeGC received unknown gc argument");
}
gcPtr = (TkGC *) Tcl_GetHashValue(idHashPtr);
gcPtr->refCount--;
if (gcPtr->refCount == 0) {
- /* CYGNUS LOCAL: Deregister the colors. */
- if (gcPtr->foreground != NULL) {
- TkDeregisterColorGC(gcPtr->foreground, gcPtr->gc,
- GCForeground);
- }
- if (gcPtr->background != NULL) {
- TkDeregisterColorGC(gcPtr->background, gcPtr->gc,
- GCBackground);
- }
-
Tk_FreeXId(gcPtr->display, (XID) XGContextFromGC(gcPtr->gc));
XFreeGC(gcPtr->display, gcPtr->gc);
Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
@@ -423,9 +333,10 @@ Tk_FreeGC(display, gc)
*/
static void
-GCInit()
+GCInit(dispPtr)
+ TkDisplay *dispPtr;
{
- initialized = 1;
- Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int));
- Tcl_InitHashTable(&idTable, sizeof(IdKey)/sizeof(int));
+ dispPtr->gcInit = 1;
+ Tcl_InitHashTable(&dispPtr->gcValueTable, sizeof(ValueKey)/sizeof(int));
+ Tcl_InitHashTable(&dispPtr->gcIdTable, TCL_ONE_WORD_KEYS);
}
diff --git a/tk/generic/tkGeometry.c b/tk/generic/tkGeometry.c
index 3545c4b7c4e..fcc33e33d55 100644
--- a/tk/generic/tkGeometry.c
+++ b/tk/generic/tkGeometry.c
@@ -53,19 +53,6 @@ typedef struct MaintainMaster {
} MaintainMaster;
/*
- * Hash table that maps from a master's Tk_Window token to a list of
- * Maintains for that master:
- */
-
-static Tcl_HashTable maintainHashTable;
-
-/*
- * Has maintainHashTable been initialized yet?
- */
-
-static int initialized = 0;
-
-/*
* Prototypes for static procedures in this file:
*/
@@ -261,10 +248,11 @@ Tk_MaintainGeometry(slave, master, x, y, width, height)
register MaintainSlave *slavePtr;
int new, map;
Tk_Window ancestor, parent;
+ TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr;
- if (!initialized) {
- initialized = 1;
- Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS);
+ if (!dispPtr->geomInit) {
+ dispPtr->geomInit = 1;
+ Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
}
/*
@@ -273,7 +261,8 @@ Tk_MaintainGeometry(slave, master, x, y, width, height)
*/
parent = Tk_Parent(slave);
- hPtr = Tcl_CreateHashEntry(&maintainHashTable, (char *) master, &new);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable,
+ (char *) master, &new);
if (!new) {
masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
} else {
@@ -383,16 +372,17 @@ Tk_UnmaintainGeometry(slave, master)
MaintainMaster *masterPtr;
register MaintainSlave *slavePtr, *prevPtr;
Tk_Window ancestor;
+ TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr;
- if (!initialized) {
- initialized = 1;
- Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS);
+ if (!dispPtr->geomInit) {
+ dispPtr->geomInit = 1;
+ Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
}
if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) {
Tk_UnmapWindow(slave);
}
- hPtr = Tcl_FindHashEntry(&maintainHashTable, (char *) master);
+ hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, (char *) master);
if (hPtr == NULL) {
return;
}
@@ -580,3 +570,4 @@ MaintainCheckProc(clientData)
}
}
}
+
diff --git a/tk/generic/tkGet.c b/tk/generic/tkGet.c
index 020a39005ae..f9df1acb1a2 100644
--- a/tk/generic/tkGet.c
+++ b/tk/generic/tkGet.c
@@ -8,7 +8,7 @@
* 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.
@@ -20,12 +20,64 @@
#include "tkPort.h"
/*
- * The hash table below is used to keep track of all the Tk_Uids created
- * so far.
+ * One of these structures is created per thread to store
+ * thread-specific data. In this case, it is used to house the
+ * Tk_Uid structs used by each thread. The "dataKey" below is
+ * used to locate the ThreadSpecificData for the current thread.
*/
-static Tcl_HashTable uidTable;
-static int initialized = 0;
+typedef struct ThreadSpecificData {
+ int initialized;
+ Tcl_HashTable uidTable;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * 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};
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * 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;
+}
/*
*--------------------------------------------------------------
@@ -39,7 +91,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.
@@ -148,14 +200,14 @@ Tk_NameOfAnchor(anchor)
*
* Tk_GetJoinStyle --
*
- * Given a string, return the corresponding Tk_JoinStyle.
+ * Given a string, return the corresponding Tk JoinStyle.
*
* Results:
* The return value is a standard Tcl return result. If
* TCL_OK is returned, then everything went well and the
* justification is stored at *joinPtr; otherwise
* TCL_ERROR is returned and an error message is left in
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -200,7 +252,7 @@ Tk_GetJoinStyle(interp, string, joinPtr)
*
* Tk_NameOfJoinStyle --
*
- * Given a Tk_JoinStyle, return the string that corresponds
+ * Given a Tk JoinStyle, return the string that corresponds
* to it.
*
* Results:
@@ -230,14 +282,14 @@ Tk_NameOfJoinStyle(join)
*
* Tk_GetCapStyle --
*
- * Given a string, return the corresponding Tk_CapStyle.
+ * Given a string, return the corresponding Tk CapStyle.
*
* Results:
* The return value is a standard Tcl return result. If
* TCL_OK is returned, then everything went well and the
* justification is stored at *capPtr; otherwise
* TCL_ERROR is returned and an error message is left in
- * interp->result.
+ * the interp's result.
*
* Side effects:
* None.
@@ -282,7 +334,7 @@ Tk_GetCapStyle(interp, string, capPtr)
*
* Tk_NameOfCapStyle --
*
- * Given a Tk_CapStyle, return the string that corresponds
+ * Given a Tk CapStyle, return the string that corresponds
* to it.
*
* Results:
@@ -308,6 +360,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 +408,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.
@@ -417,13 +506,16 @@ Tk_GetUid(string)
CONST char *string; /* String to convert. */
{
int dummy;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_HashTable *tablePtr = &tsdPtr->uidTable;
- if (!initialized) {
- Tcl_InitHashTable(&uidTable, TCL_STRING_KEYS);
- initialized = 1;
+ if (!tsdPtr->initialized) {
+ Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+ tsdPtr->initialized = 1;
}
- return (Tk_Uid) Tcl_GetHashKey(&uidTable,
- Tcl_CreateHashEntry(&uidTable, string, &dummy));
+ return (Tk_Uid) Tcl_GetHashKey(tablePtr,
+ Tcl_CreateHashEntry(tablePtr, string, &dummy));
}
/*
@@ -439,7 +531,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 +607,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.
@@ -529,13 +621,56 @@ Tk_GetPixels(interp, tkwin, string, intPtr)
Tk_Window tkwin; /* Window whose screen determines conversion
* from centimeters and other absolute
* units. */
- char *string; /* String describing a justification style. */
+ char *string; /* String describing a number of pixels. */
int *intPtr; /* Place to store converted result. */
{
+ double d;
+
+ if (TkGetDoublePixels(interp, tkwin, string, &d) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (d < 0) {
+ *intPtr = (int) (d - 0.5);
+ } else {
+ *intPtr = (int) (d + 0.5);
+ }
+ return TCL_OK;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetDoublePixels --
+ *
+ * Given a string, returns the number of pixels corresponding
+ * to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If
+ * TCL_OK is returned, then everything went well and the
+ * pixel distance is stored at *doublePtr; otherwise
+ * TCL_ERROR is returned and an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkGetDoublePixels(interp, tkwin, string, doublePtr)
+ Tcl_Interp *interp; /* Use this for error reporting. */
+ Tk_Window tkwin; /* Window whose screen determines conversion
+ * from centimeters and other absolute
+ * units. */
+ CONST char *string; /* String describing a number of pixels. */
+ double *doublePtr; /* Place to store converted result. */
+{
char *end;
double d;
- d = strtod(string, &end);
+ d = strtod((char *) string, &end);
if (end == string) {
error:
Tcl_AppendResult(interp, "bad screen distance \"", string,
@@ -577,10 +712,9 @@ Tk_GetPixels(interp, tkwin, string, intPtr)
if (*end != 0) {
goto error;
}
- if (d < 0) {
- *intPtr = (int) (d - 0.5);
- } else {
- *intPtr = (int) (d + 0.5);
- }
+ *doublePtr = d;
return TCL_OK;
}
+
+
+
diff --git a/tk/generic/tkGrab.c b/tk/generic/tkGrab.c
index 8be4b9f24f8..1ff6b8e1bcf 100644
--- a/tk/generic/tkGrab.c
+++ b/tk/generic/tkGrab.c
@@ -4,7 +4,7 @@
* 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.
@@ -15,6 +15,10 @@
#include "tkPort.h"
#include "tkInt.h"
+#if !defined(__WIN32__) && !defined(MAC_TCL)
+#include "tkUnixInt.h"
+#endif
+
/*
* The grab state machine has four states: ungrabbed, button pressed,
* grabbed, and button pressed while grabbed. In addition, there are
@@ -238,10 +242,11 @@ 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;
+ for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
dispPtr = dispPtr->nextPtr) {
if (dispPtr->eventualGrabWinPtr != NULL) {
Tcl_AppendElement(interp,
@@ -303,11 +308,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 +334,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 +371,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 +438,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);
@@ -1533,3 +1542,4 @@ TkGrabState(winPtr)
return TkPositionInTree(winPtr, grabWinPtr);
}
+
diff --git a/tk/generic/tkGrid.c b/tk/generic/tkGrid.c
index e78eb7e3b78..def4a434d49 100644
--- a/tk/generic/tkGrid.c
+++ b/tk/generic/tkGrid.c
@@ -222,14 +222,6 @@ typedef struct Gridder {
#define DONT_PROPAGATE 2
/*
- * Hash table used to map from Tk_Window tokens to corresponding
- * Grid structures:
- */
-
-static Tcl_HashTable gridHashTable;
-static int initialized = 0;
-
-/*
* Prototypes for procedures used only in this file:
*/
@@ -314,6 +306,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 +344,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 +353,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 +399,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],
@@ -440,6 +434,9 @@ Tk_GridCmd(clientData, interp, argc, argv)
slavePtr->padX = slavePtr->padY = 0;
slavePtr->iPadX = slavePtr->iPadY = 0;
slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width;
+ if (slavePtr->flags & REQUESTED_RELAYOUT) {
+ Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr);
+ }
slavePtr->flags = 0;
slavePtr->sticky = 0;
}
@@ -456,7 +453,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 +466,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 +488,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 +510,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;
@@ -524,7 +522,7 @@ Tk_GridCmd(clientData, interp, argc, argv)
*/
while (masterPtr->flags & REQUESTED_RELAYOUT) {
- Tk_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr);
+ Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr);
ArrangeGrid ((ClientData) masterPtr);
}
SetGridSize(masterPtr);
@@ -551,7 +549,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,14 +567,23 @@ 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) {
return TCL_ERROR;
}
+
+ /* Only request a relayout if the propagation bit changes */
+
if ((!propagate) ^ (masterPtr->flags&DONT_PROPAGATE)) {
- masterPtr->flags ^= DONT_PROPAGATE;
+ if (propagate) {
+ masterPtr->flags &= ~DONT_PROPAGATE;
+ } else {
+ masterPtr->flags |= DONT_PROPAGATE;
+ }
/*
* Re-arrange the master to allow new geometry information to
@@ -606,13 +614,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 +765,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 +795,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 +812,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 +832,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);
@@ -1411,7 +1438,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset)
gridCount = MAX(constraintCount,slotCount);
if (gridCount >= TYPICAL_SIZE) {
- layoutPtr = (GridLayout *) Tcl_Alloc(sizeof(GridLayout) * (1+gridCount));
+ layoutPtr = (GridLayout *) ckalloc(sizeof(GridLayout) * (1+gridCount));
} else {
layoutPtr = layoutData;
}
@@ -1714,10 +1741,11 @@ GetGrid(tkwin)
register Gridder *gridPtr;
Tcl_HashEntry *hPtr;
int new;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- initialized = 1;
- Tcl_InitHashTable(&gridHashTable, TCL_ONE_WORD_KEYS);
+ if (!dispPtr->gridInit) {
+ Tcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS);
+ dispPtr->gridInit = 1;
}
/*
@@ -1725,11 +1753,11 @@ GetGrid(tkwin)
* then create a new one.
*/
- hPtr = Tcl_CreateHashEntry(&gridHashTable, (char *) tkwin, &new);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char *) tkwin, &new);
if (!new) {
return (Gridder *) Tcl_GetHashValue(hPtr);
}
- gridPtr = (Gridder *) Tcl_Alloc(sizeof(Gridder));
+ gridPtr = (Gridder *) ckalloc(sizeof(Gridder));
gridPtr->tkwin = tkwin;
gridPtr->masterPtr = NULL;
gridPtr->masterDataPtr = NULL;
@@ -1852,7 +1880,7 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly)
int newNumSlot = slot + PREALLOC ;
size_t oldSize = numSlot * sizeof(SlotInfo) ;
size_t newSize = newNumSlot * sizeof(SlotInfo) ;
- SlotInfo *new = (SlotInfo *) Tcl_Alloc(newSize);
+ SlotInfo *new = (SlotInfo *) ckalloc(newSize);
SlotInfo *old = (slotType == ROW) ?
masterPtr->masterDataPtr->rowPtr :
masterPtr->masterDataPtr->columnPtr;
@@ -1904,19 +1932,19 @@ InitMasterData(masterPtr)
size_t size;
if (masterPtr->masterDataPtr == NULL) {
GridMaster *gridPtr = masterPtr->masterDataPtr =
- (GridMaster *) Tcl_Alloc(sizeof(GridMaster));
+ (GridMaster *) ckalloc(sizeof(GridMaster));
size = sizeof(SlotInfo) * TYPICAL_SIZE;
gridPtr->columnEnd = 0;
gridPtr->columnMax = 0;
- gridPtr->columnPtr = (SlotInfo *) Tcl_Alloc(size);
- gridPtr->columnSpace = 0;
+ gridPtr->columnPtr = (SlotInfo *) ckalloc(size);
gridPtr->columnSpace = TYPICAL_SIZE;
gridPtr->rowEnd = 0;
gridPtr->rowMax = 0;
- gridPtr->rowPtr = (SlotInfo *) Tcl_Alloc(size);
- gridPtr->rowSpace = 0;
+ gridPtr->rowPtr = (SlotInfo *) ckalloc(size);
gridPtr->rowSpace = TYPICAL_SIZE;
+ gridPtr->startX = 0;
+ gridPtr->startY = 0;
memset((VOID *) gridPtr->columnPtr, 0, size);
memset((VOID *) gridPtr->rowPtr, 0, size);
@@ -1986,7 +2014,7 @@ Unlink(slavePtr)
*
* DestroyGrid --
*
- * This procedure is invoked by Tk_EventuallyFree or Tcl_Release
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
* to clean up the internal structure of a grid at a safe time
* (when no-one is using it anymore). Cleaning up the grid involves
* freeing the main structure for all windows. and the master structure
@@ -2045,6 +2073,7 @@ GridStructureProc(clientData, eventPtr)
XEvent *eventPtr; /* Describes what just happened. */
{
register Gridder *gridPtr = (Gridder *) clientData;
+ TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr;
if (eventPtr->type == ConfigureNotify) {
if (!(gridPtr->flags & REQUESTED_RELAYOUT)) {
@@ -2072,13 +2101,13 @@ GridStructureProc(clientData, eventPtr)
nextPtr = gridPtr2->nextPtr;
gridPtr2->nextPtr = NULL;
}
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&gridHashTable,
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable,
(char *) gridPtr->tkwin));
if (gridPtr->flags & REQUESTED_RELAYOUT) {
- Tk_CancelIdleCall(ArrangeGrid, (ClientData) gridPtr);
+ Tcl_CancelIdleCall(ArrangeGrid, (ClientData) gridPtr);
}
gridPtr->tkwin = NULL;
- Tk_EventuallyFree((ClientData) gridPtr, DestroyGrid);
+ Tcl_EventuallyFree((ClientData) gridPtr, DestroyGrid);
} else if (eventPtr->type == MapNotify) {
if (!(gridPtr->flags & REQUESTED_RELAYOUT)) {
gridPtr->flags |= REQUESTED_RELAYOUT;
@@ -2107,7 +2136,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 +2310,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);
@@ -2482,6 +2512,7 @@ ConfigureSlaves(interp, tkwin, argc, argv)
return TCL_ERROR;
}
+ /* Count the number of consecutive ^'s starting from this position */
for (width=1; width+j < numWindows && *argv[j+width] == REL_VERT;
width++) {
/* Null Body */
@@ -2494,7 +2525,7 @@ ConfigureSlaves(interp, tkwin, argc, argv)
if (lastWindow == NULL) {
if (masterPtr->masterDataPtr != NULL) {
SetGridSize(masterPtr);
- lastRow = masterPtr->masterDataPtr->rowEnd - 1;
+ lastRow = masterPtr->masterDataPtr->rowEnd - 2;
} else {
lastRow = 0;
}
@@ -2502,27 +2533,30 @@ ConfigureSlaves(interp, tkwin, argc, argv)
} else {
other = Tk_NameToWindow(interp, lastWindow, tkwin);
otherPtr = GetGrid(other);
- lastRow = otherPtr->row;
+ lastRow = otherPtr->row + otherPtr->numRows - 2;
lastColumn = otherPtr->column + otherPtr->numCols;
}
for (match=0, slavePtr = masterPtr->slavePtr; slavePtr != NULL;
slavePtr = slavePtr->nextPtr) {
- if (slavePtr->numCols == width
- && slavePtr->column == lastColumn
- && slavePtr->row + slavePtr->numRows == lastRow) {
- slavePtr->numRows++;
- match++;
+ if (slavePtr->column == lastColumn
+ && slavePtr->row + slavePtr->numRows - 1 == lastRow) {
+ if (slavePtr->numCols <= width) {
+ slavePtr->numRows++;
+ match++;
+ j += slavePtr->numCols - 1;
+ lastWindow = Tk_PathName(slavePtr->tkwin);
+ break;
+ }
}
- lastWindow = Tk_PathName(slavePtr->tkwin);
}
if (!match) {
Tcl_AppendResult(interp, "can't find slave to extend with \"^\".",
(char *) NULL);
return TCL_ERROR;
}
- j += width - 1;
+/* j += width - 1; */
}
if (masterPtr == NULL) {
@@ -2613,3 +2647,5 @@ StringToSticky(string)
}
return sticky;
}
+
+
diff --git a/tk/generic/tkImage.c b/tk/generic/tkImage.c
index 74ed3bc91b2..778081002a9 100644
--- a/tk/generic/tkImage.c
+++ b/tk/generic/tkImage.c
@@ -6,7 +6,7 @@
* 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.
@@ -71,12 +71,13 @@ typedef struct ImageMaster {
* derived from this name. */
} ImageMaster;
-/*
- * The following variable points to the first in a list of all known
- * image types.
- */
-
-static Tk_ImageType *imageTypeList = NULL;
+typedef struct ThreadSpecificData {
+ Tk_ImageType *imageTypeList;/* First in a list of all known image
+ * types. */
+ Tk_ImageType *oldImageTypeList;/* First in a list of all known old-style image
+ * types. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Prototypes for local procedures:
@@ -87,7 +88,7 @@ static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
/*
*----------------------------------------------------------------------
*
- * Tk_CreateImageType --
+ * Tk_CreateOldImageType, Tk_CreateImageType --
*
* This procedure is invoked by an image manager to tell Tk about
* a new kind of image and the procedures that manage the new type.
@@ -104,20 +105,37 @@ static void DeleteImage _ANSI_ARGS_((ImageMaster *masterPtr));
*/
void
+Tk_CreateOldImageType(typePtr)
+ Tk_ImageType *typePtr; /* Structure describing the type. All of
+ * the fields except "nextPtr" must be filled
+ * in by caller. Must not have been passed
+ * to Tk_CreateImageType previously. */
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ typePtr->nextPtr = tsdPtr->oldImageTypeList;
+ tsdPtr->oldImageTypeList = typePtr;
+}
+
+void
Tk_CreateImageType(typePtr)
Tk_ImageType *typePtr; /* Structure describing the type. All of
* the fields except "nextPtr" must be filled
* in by caller. Must not have been passed
* to Tk_CreateImageType previously. */
{
- typePtr->nextPtr = imageTypeList;
- imageTypeList = typePtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ typePtr->nextPtr = tsdPtr->imageTypeList;
+ tsdPtr->imageTypeList = typePtr;
}
/*
*----------------------------------------------------------------------
*
- * Tk_ImageCmd --
+ * Tk_ImageObjCmd --
*
* This procedure is invoked to process the "image" Tcl command.
* See the user documentation for details on what it does.
@@ -132,210 +150,263 @@ Tk_CreateImageType(typePtr)
*/
int
-Tk_ImageCmd(clientData, interp, argc, objv)
+Tk_ImageObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
+ int objc; /* Number of arguments. */
Tcl_Obj *CONST objv[]; /* Argument strings. */
{
+ static char *imageOptions[] = {
+ "create", "delete", "height", "names", "type", "types", "width",
+ (char *) NULL
+ };
+ enum options {
+ IMAGE_CREATE, IMAGE_DELETE, IMAGE_HEIGHT, IMAGE_NAMES,
+ IMAGE_TYPE, IMAGE_TYPES, IMAGE_WIDTH
+ };
TkWindow *winPtr = (TkWindow *) clientData;
- int c, i, new, firstOption;
- size_t length;
+ int i, new, firstOption, index;
Tk_ImageType *typePtr;
ImageMaster *masterPtr;
Image *imagePtr;
Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- char idString[30], *name;
- static int id = 0;
-
- static char **argv = NULL;
- if (argv) ckfree((char *) argv);
- argv = (char **) ckalloc(argc * sizeof(char *));
- for (i = 0; i < argc; i++) {
- argv[i]=Tcl_GetStringFromObj(objv[i], (int *) NULL);
+ char idString[16 + TCL_INTEGER_SPACE], *name;
+ TkDisplay *dispPtr = winPtr->dispPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?args?");
+ return TCL_ERROR;
}
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " option ?args?\"", (char *) NULL);
+
+ if (Tcl_GetIndexFromObj(interp, objv[1], imageOptions, "option", 0,
+ &index) != TCL_OK) {
return TCL_ERROR;
}
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 'c') && (strncmp(argv[1], "create", length) == 0)) {
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " create type ?name? ?options?\"", (char *) NULL);
- return TCL_ERROR;
- }
- c = argv[2][0];
+ switch ((enum options) index) {
+ case IMAGE_CREATE: {
+ char *arg;
+ Tcl_Obj **args;
+ int oldimage = 0;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?");
+ return TCL_ERROR;
+ }
- /*
- * Look up the image type.
- */
+ /*
+ * Look up the image type.
+ */
- for (typePtr = imageTypeList; typePtr != NULL;
- typePtr = typePtr->nextPtr) {
- if ((c == typePtr->name[0])
- && (strcmp(argv[2], typePtr->name) == 0)) {
- break;
+ arg = Tcl_GetString(objv[2]);
+ for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ if ((*arg == typePtr->name[0])
+ && (strcmp(arg, typePtr->name) == 0)) {
+ break;
+ }
+ }
+ if (typePtr == NULL) {
+ oldimage = 1;
+ for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ if ((*arg == typePtr->name[0])
+ && (strcmp(arg, typePtr->name) == 0)) {
+ break;
+ }
+ }
+ }
+ if (typePtr == NULL) {
+ Tcl_AppendResult(interp, "image type \"", arg,
+ "\" doesn't exist", (char *) NULL);
+ return TCL_ERROR;
}
- }
- if (typePtr == NULL) {
- Tcl_AppendResult(interp, "image type \"", argv[2],
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Figure out a name to use for the new image.
- */
- if ((argc == 3) || (argv[3][0] == '-')) {
- id++;
- sprintf(idString, "image%d", id);
- name = idString;
- firstOption = 3;
- } else {
- name = argv[3];
- firstOption = 4;
- }
+ /*
+ * Figure out a name to use for the new image.
+ */
- /*
- * Create the data structure for the new image.
- */
+ if ((objc == 3) || (*(arg = Tcl_GetString(objv[3])) == '-')) {
+ dispPtr->imageId++;
+ sprintf(idString, "image%d", dispPtr->imageId);
+ name = idString;
+ firstOption = 3;
+ } else {
+ name = arg;
+ firstOption = 4;
+ }
- hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable, name, &new);
- if (new) {
- masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
- masterPtr->typePtr = NULL;
- masterPtr->masterData = NULL;
- masterPtr->width = masterPtr->height = 1;
- masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
- masterPtr->hPtr = hPtr;
- masterPtr->instancePtr = NULL;
- Tcl_SetHashValue(hPtr, masterPtr);
- } else {
/*
- * An image already exists by this name. Disconnect the
- * instances from the master.
+ * Create the data structure for the new image.
*/
- masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- if (masterPtr->typePtr != NULL) {
- for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
- imagePtr = imagePtr->nextPtr) {
- (*masterPtr->typePtr->freeProc)(
- imagePtr->instanceData, imagePtr->display);
- (*imagePtr->changeProc)(imagePtr->widgetClientData, 0, 0,
- masterPtr->width, masterPtr->height, masterPtr->width,
- masterPtr->height);
- }
- (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
+ hPtr = Tcl_CreateHashEntry(&winPtr->mainPtr->imageTable,
+ name, &new);
+ if (new) {
+ masterPtr = (ImageMaster *) ckalloc(sizeof(ImageMaster));
masterPtr->typePtr = NULL;
+ masterPtr->masterData = NULL;
+ masterPtr->width = masterPtr->height = 1;
+ masterPtr->tablePtr = &winPtr->mainPtr->imageTable;
+ masterPtr->hPtr = hPtr;
+ masterPtr->instancePtr = NULL;
+ Tcl_SetHashValue(hPtr, masterPtr);
+ } else {
+ /*
+ * An image already exists by this name. Disconnect the
+ * instances from the master.
+ */
+
+ masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
+ if (masterPtr->typePtr != NULL) {
+ for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
+ imagePtr = imagePtr->nextPtr) {
+ (*masterPtr->typePtr->freeProc)(
+ imagePtr->instanceData, imagePtr->display);
+ (*imagePtr->changeProc)(imagePtr->widgetClientData,
+ 0, 0, masterPtr->width, masterPtr->height,
+ masterPtr->width, masterPtr->height);
+ }
+ (*masterPtr->typePtr->deleteProc)(masterPtr->masterData);
+ masterPtr->typePtr = NULL;
+ }
}
- }
- /*
- * Call the image type manager so that it can perform its own
- * initialization, then re-"get" for any existing instances of
- * the image.
- */
+ /*
+ * Call the image type manager so that it can perform its own
+ * initialization, then re-"get" for any existing instances of
+ * the image.
+ */
- if ((*typePtr->createProc)(interp, name, argc-firstOption,
- objv+firstOption, typePtr, (Tk_ImageMaster) masterPtr,
- &masterPtr->masterData) != TCL_OK) {
- DeleteImage(masterPtr);
- return TCL_ERROR;
+ objv += firstOption;
+ objc -= firstOption;
+ args = (Tcl_Obj **) objv;
+ if (oldimage) {
+ int i;
+ args = (Tcl_Obj **) ckalloc((objc+1) * sizeof(char *));
+ for (i = 0; i < objc; i++) {
+ args[i] = (Tcl_Obj *) Tcl_GetString(objv[i]);
+ }
+ args[objc] = NULL;
+ }
+ if ((*typePtr->createProc)(interp, name, objc,
+ args, typePtr, (Tk_ImageMaster) masterPtr,
+ &masterPtr->masterData) != TCL_OK) {
+ DeleteImage(masterPtr);
+ if (oldimage) {
+ ckfree((char *) args);
+ }
+ return TCL_ERROR;
+ }
+ if (oldimage) {
+ ckfree((char *) args);
+ }
+ masterPtr->typePtr = typePtr;
+ for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
+ imagePtr = imagePtr->nextPtr) {
+ imagePtr->instanceData = (*typePtr->getProc)(
+ imagePtr->tkwin, masterPtr->masterData);
+ }
+ Tcl_SetResult(interp,
+ Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),
+ TCL_STATIC);
+ break;
}
- masterPtr->typePtr = typePtr;
- for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
- imagePtr = imagePtr->nextPtr) {
- imagePtr->instanceData = (*typePtr->getProc)(
- imagePtr->tkwin, masterPtr->masterData);
+ case IMAGE_DELETE: {
+ for (i = 2; i < objc; i++) {
+ char *arg = Tcl_GetString(objv[i]);
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "image \"", arg,
+ "\" doesn't exist", (char *) NULL);
+ return TCL_ERROR;
+ }
+ masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
+ DeleteImage(masterPtr);
+ }
+ break;
}
- Tcl_AppendResult(interp, Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr), (char *) NULL);
- } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
- for (i = 2; i < argc; i++) {
- hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[i]);
+ case IMAGE_HEIGHT: {
+ char *arg;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
+ }
+ arg = Tcl_GetString(objv[2]);
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
if (hPtr == NULL) {
- Tcl_AppendResult(interp, "image \"", argv[i],
- "\" doesn't exist", (char *) NULL);
+ Tcl_AppendResult(interp, "image \"", arg,
+ "\" doesn't exist", (char *) NULL);
return TCL_ERROR;
}
masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- DeleteImage(masterPtr);
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
+ break;
}
- } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " height name\"", (char *) NULL);
- return TCL_ERROR;
- }
- hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "image \"", argv[2],
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
- masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
- } else if ((c == 'n') && (strncmp(argv[1], "names", length) == 0)) {
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " names\"", (char *) NULL);
- return TCL_ERROR;
- }
- for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
- Tcl_AppendElement(interp, Tcl_GetHashKey(
+ case IMAGE_NAMES: {
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ for (hPtr = Tcl_FirstHashEntry(&winPtr->mainPtr->imageTable, &search);
+ hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
+ Tcl_AppendElement(interp, Tcl_GetHashKey(
&winPtr->mainPtr->imageTable, hPtr));
+ }
+ break;
}
- } else if ((c == 't') && (strcmp(argv[1], "type") == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " type name\"", (char *) NULL);
- return TCL_ERROR;
- }
- hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "image \"", argv[2],
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
- masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- if (masterPtr->typePtr != NULL) {
- Tcl_AppendResult(interp, masterPtr->typePtr->name, (char *) NULL);
- }
- } else if ((c == 't') && (strcmp(argv[1], "types") == 0)) {
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " types\"", (char *) NULL);
- return TCL_ERROR;
- }
- for (typePtr = imageTypeList; typePtr != NULL;
- typePtr = typePtr->nextPtr) {
- Tcl_AppendElement(interp, typePtr->name);
+ case IMAGE_TYPE: {
+ char *arg;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
+ }
+ arg = Tcl_GetString(objv[2]);
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "image \"", arg,
+ "\" doesn't exist", (char *) NULL);
+ return TCL_ERROR;
+ }
+ masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
+ if (masterPtr->typePtr != NULL) {
+ Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);
+ }
+ break;
}
- } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " width name\"", (char *) NULL);
- return TCL_ERROR;
+ case IMAGE_TYPES: {
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ return TCL_ERROR;
+ }
+ for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ Tcl_AppendElement(interp, typePtr->name);
+ }
+ for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
+ typePtr = typePtr->nextPtr) {
+ Tcl_AppendElement(interp, typePtr->name);
+ }
+ break;
}
- hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, argv[2]);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "image \"", argv[2],
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
+ case IMAGE_WIDTH: {
+ char *arg;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "name");
+ return TCL_ERROR;
+ }
+ arg = Tcl_GetString(objv[2]);
+ hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "image \"", arg,
+ "\" doesn't exist", (char *) NULL);
+ return TCL_ERROR;
+ }
+ masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width);
+ break;
}
- masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->width);
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be create, delete, height, names, type, types,",
- " or width", (char *) NULL);
- return TCL_ERROR;
}
return TCL_OK;
}
@@ -379,9 +450,9 @@ Tk_ImageChanged(imageMaster, x, y, width, height, imageWidth,
masterPtr->width = imageWidth;
masterPtr->height = imageHeight;
for (imagePtr = masterPtr->instancePtr; imagePtr != NULL;
- imagePtr = imagePtr->nextPtr) {
+ imagePtr = imagePtr->nextPtr) {
(*imagePtr->changeProc)(imagePtr->widgetClientData, x, y,
- width, height, imageWidth, imageHeight);
+ width, height, imageWidth, imageHeight);
}
}
@@ -422,7 +493,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
@@ -537,6 +608,101 @@ Tk_FreeImage(image)
/*
*----------------------------------------------------------------------
*
+ * Tk_PostscriptImage --
+ *
+ * This procedure is called by widgets that contain images in order
+ * to redisplay an image on the screen or an off-screen pixmap.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The image's manager is notified, and it redraws the desired
+ * portion of the image before returning.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_PostscriptImage(image, interp, tkwin, psinfo, x, y, width, height, prepass)
+ Tk_Image image; /* Token for image to redisplay. */
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+ Tk_PostscriptInfo psinfo; /* postscript info */
+ int x, y; /* Upper-left pixel of region in image that
+ * needs to be redisplayed. */
+ int width, height; /* Dimensions of region to redraw. */
+ int prepass;
+{
+ Image *imagePtr = (Image *) image;
+ int result;
+ XImage *ximage;
+ Pixmap pmap;
+ GC newGC;
+ XGCValues gcValues;
+
+ if (imagePtr->masterPtr->typePtr == NULL) {
+ /*
+ * No master for image, so nothing to display on postscript.
+ */
+ return TCL_OK;
+ }
+
+ /*
+ * Check if an image specific postscript-generation function
+ * exists; otherwise go on with generic code.
+ */
+
+ if (imagePtr->masterPtr->typePtr->postscriptProc != NULL) {
+ return (*imagePtr->masterPtr->typePtr->postscriptProc)(
+ imagePtr->masterPtr->masterData, interp, tkwin, psinfo,
+ x, y, width, height, prepass);
+ }
+
+ if (prepass) {
+ return TCL_OK;
+ }
+
+ /*
+ * Create a Pixmap, tell the image to redraw itself there, and then
+ * generate an XImage from the Pixmap. We can then read pixel
+ * values out of the XImage.
+ */
+
+ pmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
+ width, height, Tk_Depth(tkwin));
+
+ gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
+ newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
+ if (newGC != None) {
+ XFillRectangle(Tk_Display(tkwin), pmap, newGC,
+ 0, 0, (unsigned int)width, (unsigned int)height);
+ Tk_FreeGC(Tk_Display(tkwin), newGC);
+ }
+
+ Tk_RedrawImage(image, x, y, width, height, pmap, 0, 0);
+
+ ximage = XGetImage(Tk_Display(tkwin), pmap, 0, 0,
+ (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
+
+ Tk_FreePixmap(Tk_Display(tkwin), pmap);
+
+ if (ximage == NULL) {
+ /* The XGetImage() function is apparently not
+ * implemented on this system. Just ignore it.
+ */
+ return TCL_OK;
+ }
+ result = TkPostscriptImage(interp, tkwin, psinfo, ximage, x, y,
+ width, height);
+
+ XDestroyImage(ximage);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_RedrawImage --
*
* This procedure is called by widgets that contain images in order
@@ -793,3 +959,41 @@ Tk_GetImageMasterData(interp, name, typePtrPtr)
*typePtrPtr = masterPtr->typePtr;
return masterPtr->masterData;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_SetTSOrigin --
+ *
+ * Set the pattern origin of the tile to a common point (i.e. the
+ * origin (0,0) of the top level window) so that tiles from two
+ * different widgets will match up. This done by setting the
+ * GCTileStipOrigin field is set to the translated origin of the
+ * toplevel window in the hierarchy.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The GCTileStipOrigin is reset in the GC. This will cause the
+ * tile origin to change when the GC is used for drawing.
+ *
+ *----------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+void
+Tk_SetTSOrigin(tkwin, gc, x, y)
+ Tk_Window tkwin;
+ GC gc;
+ int x, y;
+{
+ while (!Tk_IsTopLevel(tkwin)) {
+ x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
+ y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
+ tkwin = Tk_Parent(tkwin);
+ }
+ XSetTSOrigin(Tk_Display(tkwin), gc, x, y);
+}
+
+
+
diff --git a/tk/generic/tkImgBmap.c b/tk/generic/tkImgBmap.c
index fcdc990ed82..47eacf2f560 100644
--- a/tk/generic/tkImgBmap.c
+++ b/tk/generic/tkImgBmap.c
@@ -5,6 +5,7 @@
*
* Copyright (c) 1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -91,6 +92,10 @@ static void ImgBmapDisplay _ANSI_ARGS_((ClientData clientData,
static void ImgBmapFree _ANSI_ARGS_((ClientData clientData,
Display *display));
static void ImgBmapDelete _ANSI_ARGS_((ClientData clientData));
+static int ImgBmapPostscript _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psinfo, int x, int y,
+ int width, int height, int prepass));
Tk_ImageType tkBitmapImageType = {
"bitmap", /* name */
@@ -99,6 +104,7 @@ Tk_ImageType tkBitmapImageType = {
ImgBmapDisplay, /* displayProc */
ImgBmapFree, /* freeProc */
ImgBmapDelete, /* deleteProc */
+ ImgBmapPostscript, /* postscriptProc */
(Tk_ImageType *) NULL /* nextPtr */
};
@@ -149,13 +155,13 @@ typedef struct ParseInfo {
*/
static int ImgBmapCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+ Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
static void ImgBmapCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static void ImgBmapConfigureInstance _ANSI_ARGS_((
BitmapInstance *instancePtr));
static int ImgBmapConfigureMaster _ANSI_ARGS_((
- BitmapMaster *masterPtr, int argc, char **argv,
+ BitmapMaster *masterPtr, int argc, Tcl_Obj *CONST objv[],
int flags));
static int NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr));
@@ -178,12 +184,12 @@ static int NextBitmapWord _ANSI_ARGS_((ParseInfo *parseInfoPtr));
/* ARGSUSED */
static int
-ImgBmapCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
+ImgBmapCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)
Tcl_Interp *interp; /* Interpreter for application containing
* image. */
char *name; /* Name to use for image. */
int argc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects for options (doesn't
+ Tcl_Obj *CONST argv[]; /* Argument objects for options (doesn't
* include image name or type). */
Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
Tk_ImageMaster master; /* Token for image, to be used by us in
@@ -192,13 +198,11 @@ ImgBmapCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
* it will be returned in later callbacks. */
{
BitmapMaster *masterPtr;
- char **argv;
- int i;
masterPtr = (BitmapMaster *) ckalloc(sizeof(BitmapMaster));
masterPtr->tkMaster = master;
masterPtr->interp = interp;
- masterPtr->imageCmd = Tcl_CreateCommand(interp, name, ImgBmapCmd,
+ masterPtr->imageCmd = Tcl_CreateObjCommand(interp, name, ImgBmapCmd,
(ClientData) masterPtr, ImgBmapCmdDeletedProc);
masterPtr->width = masterPtr->height = 0;
masterPtr->data = NULL;
@@ -211,20 +215,10 @@ ImgBmapCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
masterPtr->maskDataString = NULL;
masterPtr->instancePtr = NULL;
- /*
- * Convert the objv arguments into string equivalent.
- * A proper conversion to object format will need to be done in the future
- */
- argv = (char **) ckalloc(argc * sizeof(char *));
- for (i = 0; i < argc; i++) {
- argv[i] = Tcl_GetStringFromObj(objv[i], NULL);
- }
if (ImgBmapConfigureMaster(masterPtr, argc, argv, 0) != TCL_OK) {
ImgBmapDelete((ClientData) masterPtr);
- ckfree((char *) argv);
return TCL_ERROR;
}
- ckfree((char *) argv);
*clientDataPtr = (ClientData) masterPtr;
return TCL_OK;
}
@@ -240,7 +234,7 @@ ImgBmapCreate(interp, name, argc, objv, 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
@@ -250,22 +244,30 @@ ImgBmapCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
*/
static int
-ImgBmapConfigureMaster(masterPtr, argc, argv, flags)
+ImgBmapConfigureMaster(masterPtr, objc, objv, flags)
BitmapMaster *masterPtr; /* Pointer to data structure describing
* overall bitmap image to (reconfigure). */
- int argc; /* Number of entries in argv. */
- char **argv; /* Pairs of configuration options for image. */
+ int objc; /* Number of entries in objv. */
+ Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */
int flags; /* Flags to pass to Tk_ConfigureWidget,
* such as TK_CONFIG_ARGV_ONLY. */
{
BitmapInstance *instancePtr;
int maskWidth, maskHeight, dummy1, dummy2;
+ char **argv = (char **) ckalloc((objc+1) * sizeof(char *));
+ for (dummy1 = 0; dummy1 < objc; dummy1++) {
+ argv[dummy1]=Tcl_GetString(objv[dummy1]);
+ }
+ argv[objc] = NULL;
+
if (Tk_ConfigureWidget(masterPtr->interp, Tk_MainWindow(masterPtr->interp),
- configSpecs, argc, argv, (char *) masterPtr, flags)
+ configSpecs, objc, argv, (char *) masterPtr, flags)
!= TCL_OK) {
+ ckfree((char *) argv);
return TCL_ERROR;
}
+ ckfree((char *) argv);
/*
* Parse the bitmap and/or mask to create binary data. Make sure that
@@ -291,7 +293,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,
@@ -304,7 +307,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;
}
}
@@ -353,6 +357,7 @@ ImgBmapConfigureInstance(instancePtr)
XGCValues gcValues;
GC gc;
unsigned int mask;
+ Pixmap oldMask;
/*
* For each of the options in masterPtr, translate the string
@@ -395,10 +400,14 @@ ImgBmapConfigureInstance(instancePtr)
(unsigned) masterPtr->height);
}
- if (instancePtr->mask != None) {
- Tk_FreePixmap(Tk_Display(instancePtr->tkwin), instancePtr->mask);
- instancePtr->mask = None;
- }
+ /*
+ * Careful: We have to allocate a new mask Pixmap before deleting
+ * the old one. Otherwise, The XID allocator will always return
+ * the same XID for the new Pixmap as was used for the old Pixmap.
+ * And that will prevent the mask from changing in the GC below.
+ */
+ oldMask = instancePtr->mask;
+ instancePtr->mask = None;
if (masterPtr->maskData != NULL) {
instancePtr->mask = XCreateBitmapFromData(
Tk_Display(instancePtr->tkwin),
@@ -406,6 +415,9 @@ ImgBmapConfigureInstance(instancePtr)
masterPtr->maskData, (unsigned) masterPtr->width,
(unsigned) masterPtr->height);
}
+ if (oldMask != None) {
+ Tk_FreePixmap(Tk_Display(instancePtr->tkwin), oldMask);
+ }
if (masterPtr->data != NULL) {
gcValues.foreground = instancePtr->fg->pixel;
@@ -422,8 +434,7 @@ ImgBmapConfigureInstance(instancePtr)
gcValues.clip_mask = instancePtr->bitmap;
mask |= GCClipMask;
}
- gc = Tk_GetGCColor(instancePtr->tkwin, mask, &gcValues,
- instancePtr->fg, instancePtr->bg);
+ gc = Tk_GetGC(instancePtr->tkwin, mask, &gcValues);
} else {
gc = None;
}
@@ -465,7 +476,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.
@@ -515,6 +526,15 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr,
}
return NULL;
}
+
+ if (Tcl_SetChannelOption(interp, pi.chan, "-translation", "binary")
+ != TCL_OK) {
+ return NULL;
+ }
+ if (Tcl_SetChannelOption(interp, pi.chan, "-encoding", "binary")
+ != TCL_OK) {
+ return NULL;
+ }
} else {
pi.chan = NULL;
}
@@ -635,8 +655,9 @@ TkGetBitmapData(interp, string, fileName, widthPtr, heightPtr,
error:
if (interp != NULL) {
- interp->result = "format error in bitmap data";
+ Tcl_SetResult(interp, "format error in bitmap data", TCL_STATIC);
}
+
errorCleanup:
if (data != NULL) {
ckfree(data);
@@ -735,52 +756,52 @@ NextBitmapWord(parseInfoPtr)
*/
static int
-ImgBmapCmd(clientData, interp, argc, argv)
+ImgBmapCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about the image master. */
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 *bmapOptions[] = {"cget", "configure", (char *) NULL};
BitmapMaster *masterPtr = (BitmapMaster *) clientData;
- int c, code;
- size_t length;
+ int code, index;
- if (argc < 2) {
- sprintf(interp->result,
- "wrong # args: should be \"%.50s option ?arg arg ...?\"",
- argv[0]);
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
return TCL_ERROR;
}
- 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);
+ if (Tcl_GetIndexFromObj(interp, objv[1], bmapOptions, "option", 0,
+ &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (index) {
+ case 0: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
return TCL_ERROR;
}
return Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
- (char *) masterPtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
+ (char *) masterPtr, Tcl_GetString(objv[2]), 0);
+ }
+ case 1: {
+ if (objc == 2) {
code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
configSpecs, (char *) masterPtr, (char *) NULL, 0);
- } else if (argc == 3) {
+ } else if (objc == 3) {
code = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
- configSpecs, (char *) masterPtr, argv[2], 0);
+ configSpecs, (char *) masterPtr,
+ Tcl_GetString(objv[2]), 0);
} else {
- code = ImgBmapConfigureMaster(masterPtr, argc-2, argv+2,
+ code = ImgBmapConfigureMaster(masterPtr, objc-2, objv+2,
TK_CONFIG_ARGV_ONLY);
}
return code;
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be cget or configure", (char *) NULL);
- return TCL_ERROR;
+ }
+ default: {
+ panic("bad const entries to bmapOptions in ImgBmapCmd");
+ }
}
+ return TCL_OK;
}
/*
@@ -1080,3 +1101,104 @@ GetByte(chan)
return buffer;
}
}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ImgBmapPostscript --
+ *
+ * This procedure is called by the image code to create
+ * postscript output for an image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height,
+ prepass)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+ Tk_PostscriptInfo psinfo;
+ int x, y, width, height, prepass;
+{
+ BitmapMaster *masterPtr = (BitmapMaster *) clientData;
+ int rowsAtOnce, rowsThisTime;
+ int curRow, yy;
+ char buffer[200];
+
+ if (prepass) {
+ return TCL_OK;
+ }
+ /*
+ * Color the background, if there is one.
+ */
+
+ if (masterPtr->bgUid != NULL) {
+ XColor color;
+ XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid,
+ &color);
+ sprintf(buffer,
+ "%d %d moveto %d 0 rlineto 0 %d rlineto %d %s\n",
+ x, y, width, height, -width,"0 rlineto closepath");
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(interp, "fill\n", (char *) NULL);
+ }
+
+ /*
+ * Draw the bitmap, if there is a foreground color. If the bitmap
+ * is very large, then chop it up into multiple bitmaps, each
+ * consisting of one or more rows. This is needed because Postscript
+ * can't handle single strings longer than 64 KBytes long.
+ */
+
+ if (masterPtr->fgUid != NULL) {
+ XColor color;
+ XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid,
+ &color);
+ if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (width > 60000) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "can't generate Postscript",
+ " for bitmaps more than 60000 pixels wide",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ rowsAtOnce = 60000/width;
+ if (rowsAtOnce < 1) {
+ rowsAtOnce = 1;
+ }
+ sprintf(buffer, "%d %d translate\n", x, y);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ for (curRow = y+height-1; curRow >= y; curRow -= rowsAtOnce) {
+ rowsThisTime = rowsAtOnce;
+ if (rowsThisTime > (curRow + 1 - y)) {
+ rowsThisTime = curRow + 1 - y;
+ }
+ sprintf(buffer, "%d %d", width, rowsThisTime);
+ Tcl_AppendResult(interp, buffer, " true matrix {\n<",
+ (char *) NULL);
+ for (yy = curRow; yy >= (curRow - rowsThisTime + 1); yy--) {
+ sprintf(buffer, "row %d\n", yy);
+ Tcl_AppendResult(interp, buffer, (char *) NULL);
+ }
+ sprintf(buffer, "0 %.15g", (double) rowsThisTime);
+ Tcl_AppendResult(interp, ">\n} imagemask\n", buffer,
+ " translate\n", (char *) NULL);
+ }
+ }
+ return TCL_OK;
+}
+
diff --git a/tk/generic/tkImgGIF.c b/tk/generic/tkImgGIF.c
index 98bb23af4e4..f9588892b4a 100644
--- a/tk/generic/tkImgGIF.c
+++ b/tk/generic/tkImgGIF.c
@@ -2,8 +2,8 @@
* tkImgGIF.c --
*
* A photo image file handler for GIF files. Reads 87a and 89a GIF
- * files. At present there is no write function. GIF images may be
- * read using the -data option of the photo image. The data may be
+ * files. At present, there only is a file write function. GIF images
+ * may be read using the -data option of the photo image. The data may be
* given as a binary string in a Tcl_Obj or by representing
* the data as BASE64 encoded ascii. Derived from the giftoppm code
* found in the pbmplus package and tkImgFmtPPM.c in the tk4.0b2
@@ -63,29 +63,67 @@ typedef struct mFile {
#include "tkPort.h"
/*
+ * Non-ASCII encoding support:
+ * Most data in a GIF image is binary and is treated as such. However,
+ * a few key bits are stashed in ASCII. If we try to compare those pieces
+ * to the char they represent, it will fail on any non-ASCII (eg, EBCDIC)
+ * system. To accomodate these systems, we test against the numeric value
+ * of the ASCII characters instead of the characters themselves. This is
+ * encoding independant.
+ */
+
+static CONST char GIF87a[] =
+ { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x00 }; /* ASCII GIF87a */
+static CONST char GIF89a[] =
+ { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x00 }; /* ASCII GIF89a */
+# define GIF_TERMINATOR 0x3b /* ASCII ; */
+# define GIF_EXTENSION 0x21 /* ASCII ! */
+# define GIF_START 0x2c /* ASCII , */
+
+/*
+ * HACK ALERT!! HACK ALERT!! HACK ALERT!!
+ * This code is hard-wired for reading from files. In order to read
+ * from a data stream, we'll trick fread so we can reuse the same code.
+ * 0==from file; 1==from base64 encoded data; 2==from binary data
+ */
+
+typedef struct ThreadSpecificData {
+ int fromData;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
* The format record for the GIF file format:
*/
-static int FileMatchGIF _ANSI_ARGS_((Tcl_Channel chan, char *fileName,
- char *formatString, int *widthPtr, int *heightPtr));
+static int FileMatchGIF _ANSI_ARGS_((Tcl_Channel chan, CONST char *fileName,
+ Tcl_Obj *format, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp));
static int FileReadGIF _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Channel chan, char *fileName, char *formatString,
+ Tcl_Channel chan, CONST char *fileName, Tcl_Obj *format,
Tk_PhotoHandle imageHandle, int destX, int destY,
int width, int height, int srcX, int srcY));
static int StringMatchGIF _ANSI_ARGS_(( Tcl_Obj *dataObj,
- char *formatString, int *widthPtr, int *heightPtr));
+ Tcl_Obj *format, int *widthPtr, int *heightPtr,
+ Tcl_Interp *interp));
static int StringReadGIF _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *dataObj,
- char *formatString, Tk_PhotoHandle imageHandle,
+ Tcl_Obj *format, Tk_PhotoHandle imageHandle,
int destX, int destY, int width, int height,
int srcX, int srcY));
+static int FileWriteGIF _ANSI_ARGS_((Tcl_Interp *interp,
+ CONST char *filename, Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr));
+static int CommonWriteGIF _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Channel handle, Tcl_Obj *format,
+ Tk_PhotoImageBlock *blockPtr));
Tk_PhotoImageFormat tkImgFmtGIF = {
- "GIF", /* name */
+ "gif", /* name */
FileMatchGIF, /* fileMatchProc */
StringMatchGIF, /* stringMatchProc */
FileReadGIF, /* fileReadProc */
StringReadGIF, /* stringReadProc */
- NULL, /* fileWriteProc */
+ FileWriteGIF, /* fileWriteProc */
NULL, /* stringWriteProc */
};
@@ -102,15 +140,6 @@ Tk_PhotoImageFormat tkImgFmtGIF = {
#define ReadOK(file,buffer,len) (Fread(buffer, len, 1, file) != 0)
/*
- * HACK ALERT!! HACK ALERT!! HACK ALERT!!
- * This code is hard-wired for reading from files. In order to read
- * from a data stream, we'll trick fread so we can reuse the same code.
- * 0==from file; 1==from base64 encoded data; 2==from binary data
- */
-
-static int fromData=0;
-
-/*
* Prototypes for local procedures defined in this file:
*/
@@ -120,8 +149,6 @@ static int GetCode _ANSI_ARGS_((Tcl_Channel chan, int code_size,
int flag));
static int GetDataBlock _ANSI_ARGS_((Tcl_Channel chan,
unsigned char *buf));
-static int LWZReadByte _ANSI_ARGS_((Tcl_Channel chan, int flag,
- int input_code_size));
static int ReadColorMap _ANSI_ARGS_((Tcl_Channel chan, int number,
unsigned char buffer[MAXCOLORMAPSIZE][4]));
static int ReadGIFHeader _ANSI_ARGS_((Tcl_Channel chan,
@@ -145,6 +172,7 @@ static int Mgetc _ANSI_ARGS_((MFile *handle));
static int char64 _ANSI_ARGS_((int c));
static void mInit _ANSI_ARGS_((unsigned char *string,
MFile *handle));
+
/*
*----------------------------------------------------------------------
@@ -165,13 +193,14 @@ static void mInit _ANSI_ARGS_((unsigned char *string,
*/
static int
-FileMatchGIF(chan, fileName, formatString, widthPtr, heightPtr)
+FileMatchGIF(chan, fileName, format, widthPtr, heightPtr, interp)
Tcl_Channel chan; /* The image file, open for reading. */
- char *fileName; /* The name of the image file. */
- char *formatString; /* User-specified format string, or NULL. */
+ CONST char *fileName; /* The name of the image file. */
+ Tcl_Obj *format; /* User-specified format object, or NULL. */
int *widthPtr, *heightPtr; /* The dimensions of the image are
* returned here if the file is a valid
* raw GIF file. */
+ Tcl_Interp *interp; /* not used */
{
return ReadGIFHeader(chan, widthPtr, heightPtr);
}
@@ -197,12 +226,12 @@ FileMatchGIF(chan, fileName, formatString, widthPtr, heightPtr)
*/
static int
-FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
+FileReadGIF(interp, chan, fileName, format, imageHandle, destX, destY,
width, height, srcX, srcY)
Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
Tcl_Channel chan; /* The image file, open for reading. */
- char *fileName; /* The name of the image file. */
- char *formatString; /* User-specified format string, or NULL. */
+ CONST char *fileName; /* The name of the image file. */
+ Tcl_Obj *format; /* User-specified format object, or NULL. */
Tk_PhotoHandle imageHandle; /* The photo image to write into. */
int destX, destY; /* Coordinates of top-left pixel in
* photo image to be written to. */
@@ -212,15 +241,39 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
* in image being read. */
{
int fileWidth, fileHeight;
- int nBytes;
+ int nBytes, index = 0, argc = 0, i;
+ Tcl_Obj **objv;
Tk_PhotoImageBlock block;
unsigned char buf[100];
+ unsigned char *trashBuffer = NULL;
int bitPixel;
unsigned char colorMap[MAXCOLORMAPSIZE][4];
int transparent = -1;
+ static char *optionStrings[] = {
+ "-index", NULL
+ };
+ if (format && Tcl_ListObjGetElements(interp, format,
+ &argc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 1; i < argc; i++) {
+ if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option name", 0,
+ &nBytes) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (i == (argc-1)) {
+ Tcl_AppendResult(interp, "no value given for \"",
+ Tcl_GetStringFromObj(objv[i], NULL),
+ "\" option", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[++i], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
if (!ReadGIFHeader(chan, &fileWidth, &fileHeight)) {
- Tcl_AppendResult(interp, "couldn't read GIF header from file \"",
+ Tcl_AppendResult(interp, "couldn't read GIF header from file \"",
fileName, "\"", NULL);
return TCL_ERROR;
}
@@ -263,8 +316,8 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
block.offset[0] = 0;
block.offset[1] = 1;
block.offset[2] = 2;
- nBytes = height * block.pitch;
- block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
+ block.offset[3] = 3;
+ block.pixelPtr = NULL;
while (1) {
if (Fread(buf, 1, 1, chan) != 1) {
@@ -276,15 +329,17 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
break;
}
- if (buf[0] == ';') {
+ if (buf[0] == GIF_TERMINATOR) {
/*
* GIF terminator.
*/
- break;
+ Tcl_AppendResult(interp,"no image data for this index",
+ (char *) NULL);
+ goto error;
}
- if (buf[0] == '!') {
+ if (buf[0] == GIF_EXTENSION) {
/*
* This is a GIF extension.
*/
@@ -301,7 +356,7 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
continue;
}
- if (buf[0] != ',') {
+ if (buf[0] != GIF_START) {
/*
* Not a valid start character; ignore it.
*/
@@ -313,8 +368,55 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
goto error;
}
+ fileWidth = LM_to_uint(buf[4],buf[5]);
+ fileHeight = LM_to_uint(buf[6],buf[7]);
+
bitPixel = 1<<((buf[8]&0x07)+1);
+ if (index--) {
+ /* this is not the image we want to read: skip it. */
+ if (BitSet(buf[8], LOCALCOLORMAP)) {
+ if (!ReadColorMap(chan, bitPixel, colorMap)) {
+ Tcl_AppendResult(interp,
+ "error reading color map", (char *) NULL);
+ goto error;
+ }
+ }
+
+ /* If we've not yet allocated a trash buffer, do so now */
+ if (trashBuffer == NULL) {
+ nBytes = fileWidth * fileHeight * 3;
+ trashBuffer =
+ (unsigned char *) ckalloc((unsigned int) nBytes);
+ }
+
+ /*
+ * Slurp! Process the data for this image and stuff it in a
+ * trash buffer.
+ *
+ * Yes, it might be more efficient here to *not* store the data
+ * (we're just going to throw it away later). However, I elected
+ * to implement it this way for good reasons. First, I wanted to
+ * avoid duplicating the (fairly complex) LWZ decoder in ReadImage.
+ * Fine, you say, why didn't you just modify it to allow the use of
+ * a NULL specifier for the output buffer? I tried that, but it
+ * negatively impacted the performance of what I think will be the
+ * common case: reading the first image in the file. Rather than
+ * marginally improve the speed of the less frequent case, I chose
+ * to maintain high performance for the common case.
+ */
+ if (ReadImage(interp, (char *) trashBuffer, chan, fileWidth,
+ fileHeight, colorMap, 0, 0, 0, 0, 0, -1) != TCL_OK) {
+ goto error;
+ }
+ continue;
+ }
+
+ /* If a trash buffer has been allocated, free it now */
+ if (trashBuffer != NULL) {
+ ckfree((char *)trashBuffer);
+ trashBuffer = NULL;
+ }
if (BitSet(buf[8], LOCALCOLORMAP)) {
if (!ReadColorMap(chan, bitPixel, colorMap)) {
Tcl_AppendResult(interp, "error reading color map",
@@ -322,50 +424,62 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
goto error;
}
}
+
+ index = LM_to_uint(buf[0],buf[1]);
+ srcX -= index;
+ if (srcX<0) {
+ destX -= srcX; width += srcX;
+ srcX = 0;
+ }
+
+ if (width > fileWidth) {
+ width = fileWidth;
+ }
+
+ index = LM_to_uint(buf[2],buf[3]);
+ srcY -= index;
+ if (index > srcY) {
+ destY -= srcY; height += srcY;
+ srcY = 0;
+ }
+ if (height > fileHeight) {
+ height = fileHeight;
+ }
+
+ if ((width <= 0) || (height <= 0)) {
+ block.pixelPtr = 0;
+ goto noerror;
+ }
+
+ block.width = width;
+ block.height = height;
+ block.pixelSize = (transparent>=0) ? 4 : 3;
+ block.offset[3] = (transparent>=0) ? 3 : 0;
+ block.pitch = block.pixelSize * width;
+ nBytes = block.pitch * height;
+ block.pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
+
if (ReadImage(interp, (char *) block.pixelPtr, chan, width,
height, colorMap, fileWidth, fileHeight, srcX, srcY,
BitSet(buf[8], INTERLACE), transparent) != TCL_OK) {
goto error;
}
break;
- }
+ }
- if (transparent == -1) {
- Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height);
- } else {
- int x, y, end;
- unsigned char *imagePtr, *rowPtr, *pixelPtr;
-
- imagePtr = rowPtr = block.pixelPtr;
- for (y = 0; y < height; y++) {
- x = 0;
- pixelPtr = rowPtr;
- while(x < width) {
- /* search for first non-transparent pixel */
- while ((x < width) && !(pixelPtr[CM_ALPHA])) {
- x++; pixelPtr += 4;
- }
- end = x;
- /* search for first transparent pixel */
- while ((end < width) && pixelPtr[CM_ALPHA]) {
- end++; pixelPtr += 4;
- }
- if (end > x) {
- block.pixelPtr = rowPtr + 4 * x;
- Tk_PhotoPutBlock(imageHandle, &block, destX+x,
- destY+y, end-x, 1);
- }
- x = end;
- }
- rowPtr += block.pitch;
- }
- block.pixelPtr = imagePtr;
+ Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, height);
+
+ noerror:
+ if (block.pixelPtr) {
+ ckfree((char *) block.pixelPtr);
}
- ckfree((char *) block.pixelPtr);
+ Tcl_AppendResult(interp, tkImgFmtGIF.name, (char *) NULL);
return TCL_OK;
error:
- ckfree((char *) block.pixelPtr);
+ if (block.pixelPtr) {
+ ckfree((char *) block.pixelPtr);
+ }
return TCL_ERROR;
}
@@ -389,17 +503,18 @@ FileReadGIF(interp, chan, fileName, formatString, imageHandle, destX, destY,
*/
static int
-StringMatchGIF(dataObj, formatString, widthPtr, heightPtr)
+StringMatchGIF(dataObj, format, widthPtr, heightPtr, interp)
Tcl_Obj *dataObj; /* the object containing the image data */
- char *formatString; /* the image format string */
+ Tcl_Obj *format; /* the image format object, or NULL */
int *widthPtr; /* where to put the string width */
int *heightPtr; /* where to put the string height */
+ Tcl_Interp *interp; /* not used */
{
unsigned char *data, header[10];
int got, length;
MFile handle;
- data = Tcl_GetStringFromObj(dataObj, &length);
+ data = Tcl_GetByteArrayFromObj(dataObj, &length);
/* Header is a minimum of 10 bytes */
if (length < 10) {
@@ -408,14 +523,14 @@ StringMatchGIF(dataObj, formatString, widthPtr, heightPtr)
/* Check whether the data is Base64 encoded */
- if ((strncmp("GIF87a", data, 6) != 0) &&
- (strncmp("GIF89a", data, 6) != 0)) {
+ if ((strncmp(GIF87a, (char *) data, 6) != 0) &&
+ (strncmp(GIF89a, (char *) data, 6) != 0)) {
/* Try interpreting the data as Base64 encoded */
mInit((unsigned char *) data, &handle);
got = Mread(header, 10, 1, &handle);
if (got != 10
- || ((strncmp("GIF87a", (char *) header, 6) != 0)
- && (strncmp("GIF89a", (char *) header, 6) != 0))) {
+ || ((strncmp(GIF87a, (char *) header, 6) != 0)
+ && (strncmp(GIF89a, (char *) header, 6) != 0))) {
return 0;
}
} else {
@@ -448,37 +563,41 @@ StringMatchGIF(dataObj, formatString, widthPtr, heightPtr)
*/
static int
-StringReadGIF(interp,dataObj,formatString,imageHandle,
+StringReadGIF(interp, dataObj, format, imageHandle,
destX, destY, width, height, srcX, srcY)
Tcl_Interp *interp; /* interpreter for reporting errors in */
Tcl_Obj *dataObj; /* object containing the image */
- char *formatString; /* format string if any */
+ Tcl_Obj *format; /* format object, or NULL */
Tk_PhotoHandle imageHandle; /* the image to write this data into */
int destX, destY; /* The rectangular region of the */
int width, height; /* image to copy */
int srcX, srcY;
{
- int result;
- MFile handle;
- Tcl_Channel dataSrc;
- char *data;
- /* Check whether the data is Base64 encoded */
- data = Tcl_GetStringFromObj(dataObj, NULL);
- if ((strncmp("GIF87a", data, 6) != 0) &&
- (strncmp("GIF89a", data, 6) != 0)) {
- mInit((unsigned char *)data,&handle);
- fromData = 1;
- dataSrc = (Tcl_Channel) &handle;
- } else {
- fromData = 2;
- mInit((unsigned char *)data,&handle);
- dataSrc = (Tcl_Channel) &handle;
- }
- result = FileReadGIF(interp, dataSrc, "inline data",
- formatString, imageHandle, destX, destY, width, height,
- srcX, srcY);
- fromData = 0;
- return(result);
+ int result;
+ MFile handle;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_Channel dataSrc;
+ char *data;
+
+ /*
+ * Check whether the data is Base64 encoded
+ */
+ data = (char *) Tcl_GetByteArrayFromObj(dataObj, NULL);
+ if ((strncmp(GIF87a, data, 6) != 0) &&
+ (strncmp(GIF89a, data, 6) != 0)) {
+ mInit((unsigned char *)data, &handle);
+ tsdPtr->fromData = 1;
+ dataSrc = (Tcl_Channel) &handle;
+ } else {
+ tsdPtr->fromData = 2;
+ mInit((unsigned char *)data, &handle);
+ dataSrc = (Tcl_Channel) &handle;
+ }
+ result = FileReadGIF(interp, dataSrc, "inline data",
+ format, imageHandle, destX, destY, width, height, srcX, srcY);
+ tsdPtr->fromData = 0;
+ return(result);
}
/*
@@ -510,8 +629,8 @@ ReadGIFHeader(chan, widthPtr, heightPtr)
unsigned char buf[7];
if ((Fread(buf, 1, 6, chan) != 6)
- || ((strncmp("GIF87a", (char *) buf, 6) != 0)
- && (strncmp("GIF89a", (char *) buf, 6) != 0))) {
+ || ((strncmp(GIF87a, (char *) buf, 6) != 0)
+ && (strncmp(GIF89a, (char *) buf, 6) != 0))) {
return 0;
}
@@ -545,10 +664,12 @@ ReadColorMap(chan, number, buffer)
return 0;
}
- buffer[i][CM_RED] = rgb[0] ;
- buffer[i][CM_GREEN] = rgb[1] ;
- buffer[i][CM_BLUE] = rgb[2] ;
- buffer[i][CM_ALPHA] = 255 ;
+ if (buffer) {
+ buffer[i][CM_RED] = rgb[0] ;
+ buffer[i][CM_GREEN] = rgb[1] ;
+ buffer[i][CM_BLUE] = rgb[2] ;
+ buffer[i][CM_ALPHA] = 255 ;
+ }
}
return 1;
}
@@ -621,6 +742,34 @@ GetDataBlock(chan, buf)
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ReadImage --
+ *
+ * Process a GIF image from a given source, with a given height,
+ * width, transparency, etc.
+ *
+ * This code is based on the code found in the ImageMagick GIF decoder,
+ * which is (c) 2000 ImageMagick Studio.
+ *
+ * Some thoughts on our implementation:
+ * It sure would be nice if ReadImage didn't take 11 parameters! I think
+ * that if we were smarter, we could avoid doing that.
+ *
+ * Possible further optimizations: we could pull the GetCode function
+ * directly into ReadImage, which would improve our speed.
+ *
+ * Results:
+ * Processes a GIF image and loads the pixel data into a memory array.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
static int
ReadImage(interp, imagePtr, chan, len, rows, cmap,
width, height, srcX, srcY, interlace, transparent)
@@ -634,26 +783,27 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
int interlace;
int transparent;
{
- unsigned char c;
+ unsigned char initialCodeSize;
int v;
- int xpos = 0, ypos = 0, pass = 0;
- char *pixelPtr;
-
-
+ int xpos = 0, ypos = 0, pass = 0, i;
+ register char *pixelPtr;
+ CONST static int interlaceStep[] = { 8, 8, 4, 2 };
+ CONST static int interlaceStart[] = { 0, 4, 2, 1 };
+ unsigned short prefix[(1 << MAX_LWZ_BITS)];
+ unsigned char append[(1 << MAX_LWZ_BITS)];
+ unsigned char stack[(1 << MAX_LWZ_BITS)*2];
+ register unsigned char *top;
+ int codeSize, clearCode, inCode, endCode, oldCode, maxCode,
+ code, firstCode;
+
/*
- * Initialize the Compression routines
+ * Initialize the decoder
*/
- if (! ReadOK(chan, &c, 1)) {
+ if (! ReadOK(chan, &initialCodeSize, 1)) {
Tcl_AppendResult(interp, "error reading GIF image: ",
Tcl_PosixError(interp), (char *) NULL);
return TCL_ERROR;
}
-
- if (LWZReadByte(chan, 1, c) < 0) {
- interp->result = "format error in GIF image";
- return TCL_ERROR;
- }
-
if (transparent!=-1) {
cmap[transparent][CM_RED] = 0;
cmap[transparent][CM_GREEN] = 0;
@@ -662,180 +812,194 @@ ReadImage(interp, imagePtr, chan, len, rows, cmap,
}
pixelPtr = imagePtr;
- while ((v = LWZReadByte(chan, 0, c)) >= 0 ) {
- if ((xpos>=srcX) && (xpos<srcX+len) &&
- (ypos>=srcY) && (ypos<srcY+rows)) {
- *pixelPtr++ = cmap[v][CM_RED];
- *pixelPtr++ = cmap[v][CM_GREEN];
- *pixelPtr++ = cmap[v][CM_BLUE];
- *pixelPtr++ = cmap[v][CM_ALPHA];
- }
-
- ++xpos;
- if (xpos == width) {
- xpos = 0;
- if (interlace) {
- switch (pass) {
- case 0:
- case 1:
- ypos += 8; break;
- case 2:
- ypos += 4; break;
- case 3:
- ypos += 2; break;
- }
-
- while (ypos >= height) {
- ++pass;
- switch (pass) {
- case 1:
- ypos = 4; break;
- case 2:
- ypos = 2; break;
- case 3:
- ypos = 1; break;
- default:
- return TCL_OK;
- }
- }
- } else {
- ++ypos;
- }
- pixelPtr = imagePtr + (ypos-srcY) * len * 4;
- }
- if (ypos >= height)
- break;
+ /* Initialize the decoder */
+ /* Set values for "special" numbers:
+ * clear code reset the decoder
+ * end code stop decoding
+ * code size size of the next code to retrieve
+ * max code next available table position
+ */
+ clearCode = 1 << (int) initialCodeSize;
+ endCode = clearCode + 1;
+ codeSize = (int) initialCodeSize + 1;
+ maxCode = clearCode + 2;
+ oldCode = -1;
+ firstCode = -1;
+
+ memset((void *)prefix, 0, (1 << MAX_LWZ_BITS) * sizeof(short));
+ memset((void *)append, 0, (1 << MAX_LWZ_BITS) * sizeof(char));
+ for (i = 0; i < clearCode; i++) {
+ append[i] = i;
}
- return TCL_OK;
-}
-
-static int
-LWZReadByte(chan, flag, input_code_size)
- Tcl_Channel chan;
- int flag;
- int input_code_size;
-{
- static int fresh = 0;
- int code, incode;
- static int code_size, set_code_size;
- static int max_code, max_code_size;
- static int firstcode, oldcode;
- static int clear_code, end_code;
- static int table[2][(1<< MAX_LWZ_BITS)];
- static int stack[(1<<(MAX_LWZ_BITS))*2], *sp;
- register int i;
-
- if (flag) {
- set_code_size = input_code_size;
- code_size = set_code_size+1;
- clear_code = 1 << set_code_size ;
- end_code = clear_code + 1;
- max_code_size = 2*clear_code;
- max_code = clear_code+2;
+ top = stack;
- GetCode(chan, 0, 1);
+ GetCode(chan, 0, 1);
- fresh = 1;
+ /* Read until we finish the image */
+ for (i = 0, ypos = 0; i < rows; i++) {
+ for (xpos = 0; xpos < len; ) {
- for (i = 0; i < clear_code; ++i) {
- table[0][i] = 0;
- table[1][i] = i;
- }
- for (; i < (1<<MAX_LWZ_BITS); ++i) {
- table[0][i] = table[1][0] = 0;
- }
+ if (top == stack) {
+ /* Bummer -- our stack is empty. Now we have to work! */
+ code = GetCode(chan, codeSize, 0);
+ if (code < 0) {
+ return TCL_OK;
+ }
- sp = stack;
+ if (code > maxCode || code == endCode) {
+ /*
+ * If we're doing things right, we should never
+ * receive a code that is greater than our current
+ * maximum code. If we do, bail, because our decoder
+ * does not yet have that code set up.
+ *
+ * If the code is the magic endCode value, quit.
+ */
+ return TCL_OK;
+ }
- return 0;
- } else if (fresh) {
- fresh = 0;
- do {
- firstcode = oldcode = GetCode(chan, code_size, 0);
- } while (firstcode == clear_code);
- return firstcode;
- }
+ if (code == clearCode) {
+ /* Reset the decoder */
+ codeSize = initialCodeSize + 1;
+ maxCode = clearCode + 2;
+ oldCode = -1;
+ continue;
+ }
+
+ if (oldCode == -1) {
+ /*
+ * Last pass reset the decoder, so the first code we
+ * see must be a singleton. Seed the stack with it,
+ * and set up the old/first code pointers for
+ * insertion into the string table. We can't just
+ * roll this into the clearCode test above, because
+ * at that point we have not yet read the next code.
+ */
+ *top++=append[code];
+ oldCode = code;
+ firstCode = code;
+ continue;
+ }
+
+ inCode = code;
+
+ if (code == maxCode) {
+ /*
+ * maxCode is always one bigger than our highest assigned
+ * code. If the code we see is equal to maxCode, then
+ * we are about to add a new string to the table. ???
+ */
+ *top++ = firstCode;
+ code = oldCode;
+ }
- if (sp > stack) {
- return *--sp;
- }
+ while (code > clearCode) {
+ /*
+ * Populate the stack by tracing the string in the
+ * string table from its tail to its head
+ */
+ *top++ = append[code];
+ code = prefix[code];
+ }
+ firstCode = append[code];
- while ((code = GetCode(chan, code_size, 0)) >= 0) {
- if (code == clear_code) {
- for (i = 0; i < clear_code; ++i) {
- table[0][i] = 0;
- table[1][i] = i;
- }
-
- for (; i < (1<<MAX_LWZ_BITS); ++i) {
- table[0][i] = table[1][i] = 0;
- }
+ /*
+ * If there's no more room in our string table, quit.
+ * Otherwise, add a new string to the table
+ */
+ if (maxCode >= (1 << MAX_LWZ_BITS)) {
+ return TCL_OK;
+ }
- code_size = set_code_size+1;
- max_code_size = 2*clear_code;
- max_code = clear_code+2;
- sp = stack;
- firstcode = oldcode = GetCode(chan, code_size, 0);
- return firstcode;
+ /* Push the head of the string onto the stack */
+ *top++ = firstCode;
- } else if (code == end_code) {
- int count;
- unsigned char buf[260];
+ /* Add a new string to the string table */
+ prefix[maxCode] = oldCode;
+ append[maxCode] = firstCode;
+ maxCode++;
- if (ZeroDataBlock) {
- return -2;
+ /* maxCode tells us the maximum code value we can accept.
+ * If we see that we need more bits to represent it than
+ * we are requesting from the unpacker, we need to increase
+ * the number we ask for.
+ */
+ if ((maxCode >= (1 << codeSize))
+ && (maxCode < (1<<MAX_LWZ_BITS))) {
+ codeSize++;
+ }
+ oldCode = inCode;
}
-
- while ((count = GetDataBlock(chan, buf)) > 0)
- /* Empty body */;
- if (count != 0) {
- return -2;
+ /* Pop the next color index off the stack */
+ v = *(--top);
+ if (v < 0) {
+ return TCL_OK;
}
- }
-
- incode = code;
-
- if (code >= max_code) {
- *sp++ = firstcode;
- code = oldcode;
- }
- while (code >= clear_code) {
- *sp++ = table[1][code];
- if (code == table[0][code]) {
- return -2;
-
- /*
- * Used to be this instead, Steve Ball suggested
- * the change to just return.
- printf("circular table entry BIG ERROR\n");
- */
+ /*
+ * If pixelPtr is null, we're skipping this image (presumably
+ * there are more in the file and we will be called to read
+ * one of them later)
+ */
+ *pixelPtr++ = cmap[v][CM_RED];
+ *pixelPtr++ = cmap[v][CM_GREEN];
+ *pixelPtr++ = cmap[v][CM_BLUE];
+ if (transparent >= 0) {
+ *pixelPtr++ = cmap[v][CM_ALPHA];
}
- code = table[0][code];
- }
-
- *sp++ = firstcode = table[1][code];
+ xpos++;
- if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
- table[0][code] = oldcode;
- table[1][code] = firstcode;
- ++max_code;
- if ((max_code>=max_code_size) && (max_code_size < (1<<MAX_LWZ_BITS))) {
- max_code_size *= 2;
- ++code_size;
- }
}
- oldcode = incode;
-
- if (sp > stack)
- return *--sp;
+ /* If interlacing, the next ypos is not just +1 */
+ if (interlace) {
+ ypos += interlaceStep[pass];
+ while (ypos >= height) {
+ pass++;
+ if (pass > 3) {
+ return TCL_OK;
+ }
+ ypos = interlaceStart[pass];
+ }
+ } else {
+ ypos++;
}
- return code;
+ pixelPtr = imagePtr + (ypos) * len * ((transparent>=0)?4:3);
+ }
+ return TCL_OK;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCode --
+ *
+ * Extract the next compression code from the file. In GIF's, the
+ * compression codes are between 3 and 12 bits long and are then
+ * packed into 8 bit bytes, left to right, for example:
+ * bbbaaaaa
+ * dcccccbb
+ * eeeedddd
+ * ...
+ * We use a byte buffer read from the file and a sliding window
+ * to unpack the bytes. Thanks to ImageMagick for the sliding window
+ * idea.
+ * args: chan the channel to read from
+ * code_size size of the code to extract
+ * flag boolean indicating whether the extractor
+ * should be reset or not
+ *
+ * Results:
+ * code the next compression code
+ *
+ * Side effects:
+ * May consume more input from chan.
+ *
+ *----------------------------------------------------------------------
+ */
static int
GetCode(chan, code_size, flag)
@@ -844,46 +1008,50 @@ GetCode(chan, code_size, flag)
int flag;
{
static unsigned char buf[280];
- static int curbit, lastbit, done, last_byte;
- int i, j, ret;
- unsigned char count;
+ static int bytes = 0, done;
+ static unsigned char *c;
+ static unsigned int window;
+ static int bitsInWindow = 0;
+ int ret;
+
if (flag) {
- curbit = 0;
- lastbit = 0;
+ /* Initialize the decoder */
+ bitsInWindow = 0;
+ bytes = 0;
+ window = 0;
done = 0;
+ c = NULL;
return 0;
}
-
- if ( (curbit+code_size) >= lastbit) {
+ while (bitsInWindow < code_size) {
+ /* Not enough bits in our window to cover the request */
if (done) {
- /* ran off the end of my bits */
return -1;
}
- if (last_byte >= 2) {
- buf[0] = buf[last_byte-2];
- }
- if (last_byte >= 1) {
- buf[1] = buf[last_byte-1];
- }
-
- if ((count = GetDataBlock(chan, &buf[2])) == 0) {
- done = 1;
+ if (bytes == 0) {
+ /* Not enough bytes in our buffer to add to the window */
+ bytes = GetDataBlock(chan, buf);
+ c = buf;
+ if (bytes <= 0) {
+ done = 1;
+ break;
+ }
}
-
- last_byte = 2 + count;
- curbit = (curbit - lastbit) + 16;
- lastbit = (2+count)*8 ;
+ /* Tack another byte onto the window, see if that's enough */
+ window += (*c) << bitsInWindow;
+ c++;
+ bitsInWindow += 8;
+ bytes--;
}
- ret = 0;
- for (i = curbit, j = 0; j < code_size; ++i, ++j) {
- ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
- }
-
- curbit += code_size;
-
+ /* The next code will always be the last code_size bits of the window */
+ ret = window & ((1 << code_size) - 1);
+
+ /* Shift data in the window to put the next code at the end */
+ window >>= code_size;
+ bitsInWindow -= code_size;
return ret;
}
@@ -1083,16 +1251,761 @@ Fread(dst, hunk, count, chan)
size_t hunk,count; /* how many */
Tcl_Channel chan;
{
- MFile *handle;
- switch (fromData) {
- case 0:
- return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ MFile *handle;
+
+ switch (tsdPtr->fromData) {
case 1:
return(Mread(dst, hunk, count, (MFile *) chan));
case 2:
handle = (MFile *) chan;
- memcpy((VOID *)dst, (VOID *) handle->data, (int) (hunk * count));
+ memcpy((VOID *)dst, (VOID *) handle->data, (size_t) (hunk * count));
handle->data += hunk * count;
return((int) (hunk * count));
+ default:
+ return Tcl_Read(chan, (char *) dst, (int) (hunk * count));
}
}
+
+
+/*
+ * ChanWriteGIF - writes a image in GIF format.
+ *-------------------------------------------------------------------------
+ * Author: Lolo
+ * Engeneering Projects Area
+ * Department of Mining
+ * University of Oviedo
+ * e-mail zz11425958@zeus.etsimo.uniovi.es
+ * lolo@pcsig22.etsimo.uniovi.es
+ * Date: Fri September 20 1996
+ *
+ * Modified for transparency handling (gif89a) and miGIF compression
+ * by Jan Nijtmans <j.nijtmans@chello.nl>
+ *
+ *----------------------------------------------------------------------
+ * FileWriteGIF-
+ *
+ * This procedure is called by the photo image type to write
+ * GIF format data from a photo image into a given file
+ *
+ * Results:
+ * A standard TCL completion code. If TCL_ERROR is returned
+ * then an error message is left in interp->result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /*
+ * Types, defines and variables needed to write and compress a GIF.
+ */
+
+typedef int (* ifunptr) _ANSI_ARGS_((void));
+
+#define LSB(a) ((unsigned char) (((short)(a)) & 0x00FF))
+#define MSB(a) ((unsigned char) (((short)(a)) >> 8))
+
+#define GIFBITS 12
+#define HSIZE 5003 /* 80% occupancy */
+
+static int ssize;
+static int csize;
+static int rsize;
+static unsigned char *pixelo;
+static int pixelSize;
+static int pixelPitch;
+static int greenOffset;
+static int blueOffset;
+static int alphaOffset;
+static int num;
+static unsigned char mapa[MAXCOLORMAPSIZE][3];
+
+/*
+ * Definition of new functions to write GIFs
+ */
+
+static int color _ANSI_ARGS_((int red,int green, int blue,
+ unsigned char mapa[MAXCOLORMAPSIZE][3]));
+static void compress _ANSI_ARGS_((int init_bits, Tcl_Channel handle,
+ ifunptr readValue));
+static int nuevo _ANSI_ARGS_((int red, int green ,int blue,
+ unsigned char mapa[MAXCOLORMAPSIZE][3]));
+static void savemap _ANSI_ARGS_((Tk_PhotoImageBlock *blockPtr,
+ unsigned char mapa[MAXCOLORMAPSIZE][3]));
+static int ReadValue _ANSI_ARGS_((void));
+
+static int
+FileWriteGIF (interp, filename, format, blockPtr)
+ Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
+ CONST char *filename;
+ Tcl_Obj *format;
+ Tk_PhotoImageBlock *blockPtr;
+{
+ Tcl_Channel chan = NULL;
+ int result;
+
+ chan = Tcl_OpenFileChannel(interp, (char *) filename, "w", 0644);
+ if (!chan) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ result = CommonWriteGIF(interp, chan, format, blockPtr);
+ if (Tcl_Close(interp, chan) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ return result;
+}
+
+#define Mputc(c,handle) Tcl_Write(handle,(char *) &c,1)
+
+static int
+CommonWriteGIF(interp, handle, format, blockPtr)
+ Tcl_Interp *interp;
+ Tcl_Channel handle;
+ Tcl_Obj *format;
+ Tk_PhotoImageBlock *blockPtr;
+{
+ int resolution;
+
+ long width,height,x;
+ unsigned char c;
+ unsigned int top,left;
+
+ top = 0;
+ left = 0;
+
+ pixelSize=blockPtr->pixelSize;
+ greenOffset=blockPtr->offset[1]-blockPtr->offset[0];
+ blueOffset=blockPtr->offset[2]-blockPtr->offset[0];
+ alphaOffset = blockPtr->offset[0];
+ if (alphaOffset < blockPtr->offset[2]) {
+ alphaOffset = blockPtr->offset[2];
+ }
+ if (++alphaOffset < pixelSize) {
+ alphaOffset -= blockPtr->offset[0];
+ } else {
+ alphaOffset = 0;
+ }
+
+ Tcl_Write(handle, (char *) (alphaOffset ? GIF89a : GIF87a), 6);
+
+ for (x=0;x<MAXCOLORMAPSIZE;x++) {
+ mapa[x][CM_RED] = 255;
+ mapa[x][CM_GREEN] = 255;
+ mapa[x][CM_BLUE] = 255;
+ }
+
+
+ width=blockPtr->width;
+ height=blockPtr->height;
+ pixelo=blockPtr->pixelPtr + blockPtr->offset[0];
+ pixelPitch=blockPtr->pitch;
+ savemap(blockPtr,mapa);
+ if (num>=MAXCOLORMAPSIZE) {
+ Tcl_AppendResult(interp, "too many colors", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (num<2) num=2;
+ c=LSB(width);
+ Mputc(c,handle);
+ c=MSB(width);
+ Mputc(c,handle);
+ c=LSB(height);
+ Mputc(c,handle);
+ c=MSB(height);
+ Mputc(c,handle);
+
+ resolution = 0;
+ while (num >> resolution) {
+ resolution++;
+ }
+ c = 111 + resolution * 17;
+ Mputc(c,handle);
+
+ num = 1 << resolution;
+
+ /* background color */
+
+ c = 0;
+ Mputc(c,handle);
+
+ /* zero for future expansion */
+
+ Mputc(c,handle);
+
+ for (x=0; x<num ;x++) {
+ c = mapa[x][CM_RED];
+ Mputc(c,handle);
+ c = mapa[x][CM_GREEN];
+ Mputc(c,handle);
+ c = mapa[x][CM_BLUE];
+ Mputc(c,handle);
+ }
+
+ /*
+ * Write out extension for transparent colour index, if necessary.
+ */
+
+ if (alphaOffset) {
+ c = GIF_EXTENSION;
+ Mputc(c, handle);
+ Tcl_Write(handle, "\371\4\1\0\0\0", 7);
+ }
+
+ c = GIF_START;
+ Mputc(c,handle);
+ c=LSB(top);
+ Mputc(c,handle);
+ c=MSB(top);
+ Mputc(c,handle);
+ c=LSB(left);
+ Mputc(c,handle);
+ c=MSB(left);
+ Mputc(c,handle);
+
+ c=LSB(width);
+ Mputc(c,handle);
+ c=MSB(width);
+ Mputc(c,handle);
+
+ c=LSB(height);
+ Mputc(c,handle);
+ c=MSB(height);
+ Mputc(c,handle);
+
+ c=0;
+ Mputc(c,handle);
+ c=resolution;
+ Mputc(c,handle);
+
+ ssize = rsize = blockPtr->width;
+ csize = blockPtr->height;
+ compress(resolution+1, handle, ReadValue);
+
+ c = 0;
+ Mputc(c,handle);
+ c = GIF_TERMINATOR;
+ Mputc(c,handle);
+
+ return TCL_OK;
+}
+
+static int
+color(red, green, blue, mapa)
+ int red;
+ int green;
+ int blue;
+ unsigned char mapa[MAXCOLORMAPSIZE][3];
+{
+ int x;
+ for (x=(alphaOffset != 0);x<=MAXCOLORMAPSIZE;x++) {
+ if ((mapa[x][CM_RED]==red) && (mapa[x][CM_GREEN]==green) &&
+ (mapa[x][CM_BLUE]==blue)) {
+ return x;
+ }
+ }
+ return -1;
+}
+
+
+static int
+nuevo(red, green, blue, mapa)
+ int red,green,blue;
+ unsigned char mapa[MAXCOLORMAPSIZE][3];
+{
+ int x;
+ for (x=(alphaOffset != 0);x<=num;x++) {
+ if ((mapa[x][CM_RED]==red) && (mapa[x][CM_GREEN]==green) &&
+ (mapa[x][CM_BLUE]==blue)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void
+savemap(blockPtr,mapa)
+ Tk_PhotoImageBlock *blockPtr;
+ unsigned char mapa[MAXCOLORMAPSIZE][3];
+{
+ unsigned char *colores;
+ int x,y;
+ unsigned char red,green,blue;
+
+ if (alphaOffset) {
+ num = 0;
+ mapa[0][CM_RED] = 0xd9;
+ mapa[0][CM_GREEN] = 0xd9;
+ mapa[0][CM_BLUE] = 0xd9;
+ } else {
+ num = -1;
+ }
+
+ for(y=0;y<blockPtr->height;y++) {
+ colores=blockPtr->pixelPtr + blockPtr->offset[0]
+ + y * blockPtr->pitch;
+ for(x=0;x<blockPtr->width;x++) {
+ if (!alphaOffset || (colores[alphaOffset] != 0)) {
+ red = colores[0];
+ green = colores[greenOffset];
+ blue = colores[blueOffset];
+ if (nuevo(red,green,blue,mapa)) {
+ num++;
+ if (num>=MAXCOLORMAPSIZE) {
+ return;
+ }
+ mapa[num][CM_RED]=red;
+ mapa[num][CM_GREEN]=green;
+ mapa[num][CM_BLUE]=blue;
+ }
+ }
+ colores += pixelSize;
+ }
+ }
+ return;
+}
+
+static int
+ReadValue()
+{
+ unsigned int col;
+
+ if (csize == 0) {
+ return EOF;
+ }
+ if (alphaOffset && (pixelo[alphaOffset]==0)) {
+ col = 0;
+ } else {
+ col = color(pixelo[0],pixelo[greenOffset],pixelo[blueOffset], mapa);
+ }
+ pixelo += pixelSize;
+ if (--ssize <= 0) {
+ ssize = rsize;
+ csize--;
+ pixelo += pixelPitch - (rsize * pixelSize);
+ }
+
+ return col;
+}
+
+
+
+/*-----------------------------------------------------------------------
+ *
+ * miGIF Compression - mouse and ivo's GIF-compatible compression
+ *
+ * -run length encoding compression routines-
+ *
+ * Copyright (C) 1998 Hutchison Avenue Software Corporation
+ * http://www.hasc.com
+ * info@hasc.com
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "AS IS." The Hutchison Avenue
+ * Software Corporation disclaims all warranties, either express or implied,
+ * including but not limited to implied warranties of merchantability and
+ * fitness for a particular purpose, with respect to this code and accompanying
+ * documentation.
+ *
+ * The miGIF compression routines do not, strictly speaking, generate files
+ * conforming to the GIF spec, since the image data is not LZW-compressed
+ * (this is the point: in order to avoid transgression of the Unisys patent
+ * on the LZW algorithm.) However, miGIF generates data streams that any
+ * reasonably sane LZW decompresser will decompress to what we want.
+ *
+ * miGIF compression uses run length encoding. It compresses horizontal runs
+ * of pixels of the same color. This type of compression gives good results
+ * on images with many runs, for example images with lines, text and solid
+ * shapes on a solid-colored background. It gives little or no compression
+ * on images with few runs, for example digital or scanned photos.
+ *
+ * der Mouse
+ * mouse@rodents.montreal.qc.ca
+ * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
+ *
+ * ivo@hasc.com
+ *
+ * The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated.
+ *
+ */
+
+static int rl_pixel;
+static int rl_basecode;
+static int rl_count;
+static int rl_table_pixel;
+static int rl_table_max;
+static int just_cleared;
+static int out_bits;
+static int out_bits_init;
+static int out_count;
+static int out_bump;
+static int out_bump_init;
+static int out_clear;
+static int out_clear_init;
+static int max_ocodes;
+static int code_clear;
+static int code_eof;
+static unsigned int obuf;
+static int obits;
+static Tcl_Channel ofile;
+static unsigned char oblock[256];
+static int oblen;
+
+/* Used only when debugging GIF compression code */
+/* #define DEBUGGING_ENVARS */
+
+#ifdef DEBUGGING_ENVARS
+
+static int verbose_set = 0;
+static int verbose;
+#define VERBOSE (verbose_set?verbose:set_verbose())
+
+static int set_verbose(void)
+{
+ verbose = !!getenv("GIF_VERBOSE");
+ verbose_set = 1;
+ return(verbose);
+}
+
+#else
+
+#define VERBOSE 0
+
+#endif
+
+
+static CONST char *
+binformat(v, nbits)
+ unsigned int v;
+ int nbits;
+{
+ static char bufs[8][64];
+ static int bhand = 0;
+ unsigned int bit;
+ int bno;
+ char *bp;
+
+ bhand --;
+ if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
+ bp = &bufs[bhand][0];
+ for (bno=nbits-1,bit=((unsigned int)1)<<bno;bno>=0;bno--,bit>>=1)
+ { *bp++ = (v & bit) ? '1' : '0';
+ if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
+ }
+ *bp = '\0';
+ return(&bufs[bhand][0]);
+}
+
+static void write_block()
+{
+ int i;
+ unsigned char c;
+
+ if (VERBOSE)
+ { printf("write_block %d:",oblen);
+ for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
+ printf("\n");
+ }
+ c = oblen;
+ Tcl_Write(ofile, (char *) &c, 1);
+ Tcl_Write(ofile, (char *) &oblock[0], oblen);
+ oblen = 0;
+}
+
+static void
+block_out(c)
+ unsigned char c;
+{
+ if (VERBOSE) printf("block_out %s\n",binformat(c,8));
+ oblock[oblen++] = c;
+ if (oblen >= 255) write_block();
+}
+
+static void block_flush()
+{
+ if (VERBOSE) printf("block_flush\n");
+ if (oblen > 0) write_block();
+}
+
+static void output(val)
+ int val;
+{
+ if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
+ obuf |= val << obits;
+ obits += out_bits;
+ while (obits >= 8)
+ { block_out(obuf&0xff);
+ obuf >>= 8;
+ obits -= 8;
+ }
+ if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
+}
+
+static void output_flush()
+{
+ if (VERBOSE) printf("output_flush\n");
+ if (obits > 0) block_out(obuf);
+ block_flush();
+}
+
+static void did_clear()
+{
+ if (VERBOSE) printf("did_clear\n");
+ out_bits = out_bits_init;
+ out_bump = out_bump_init;
+ out_clear = out_clear_init;
+ out_count = 0;
+ rl_table_max = 0;
+ just_cleared = 1;
+}
+
+static void
+output_plain(c)
+ int c;
+{
+ if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
+ just_cleared = 0;
+ output(c);
+ out_count ++;
+ if (out_count >= out_bump)
+ { out_bits ++;
+ out_bump += 1 << (out_bits - 1);
+ }
+ if (out_count >= out_clear)
+ { output(code_clear);
+ did_clear();
+ }
+}
+
+static unsigned int isqrt(x)
+ unsigned int x;
+{
+ unsigned int r;
+ unsigned int v;
+
+ if (x < 2) return(x);
+ for (v=x,r=1;v;v>>=2,r<<=1) ;
+ while (1)
+ { v = ((x / r) + r) / 2;
+ if ((v == r) || (v == r+1)) return(r);
+ r = v;
+ }
+}
+
+static unsigned int
+compute_triangle_count(count, nrepcodes)
+ unsigned int count;
+ unsigned int nrepcodes;
+{
+ unsigned int perrep;
+ unsigned int cost;
+
+ cost = 0;
+ perrep = (nrepcodes * (nrepcodes+1)) / 2;
+ while (count >= perrep)
+ { cost += nrepcodes;
+ count -= perrep;
+ }
+ if (count > 0)
+ { unsigned int n;
+ n = isqrt(count);
+ while ((n*(n+1)) >= 2*count) n --;
+ while ((n*(n+1)) < 2*count) n ++;
+ cost += n;
+ }
+ return(cost);
+}
+
+static void max_out_clear()
+{
+ out_clear = max_ocodes;
+}
+
+static void reset_out_clear()
+{
+ out_clear = out_clear_init;
+ if (out_count >= out_clear)
+ { output(code_clear);
+ did_clear();
+ }
+}
+
+static void
+rl_flush_fromclear(count)
+ int count;
+{
+ int n;
+
+ if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
+ max_out_clear();
+ rl_table_pixel = rl_pixel;
+ n = 1;
+ while (count > 0)
+ { if (n == 1)
+ { rl_table_max = 1;
+ output_plain(rl_pixel);
+ count --;
+ }
+ else if (count >= n)
+ { rl_table_max = n;
+ output_plain(rl_basecode+n-2);
+ count -= n;
+ }
+ else if (count == 1)
+ { rl_table_max ++;
+ output_plain(rl_pixel);
+ count = 0;
+ }
+ else
+ { rl_table_max ++;
+ output_plain(rl_basecode+count-2);
+ count = 0;
+ }
+ if (out_count == 0) n = 1; else n ++;
+ }
+ reset_out_clear();
+ if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
+}
+
+static void rl_flush_clearorrep(count)
+ int count;
+{
+ int withclr;
+
+ if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
+ withclr = 1 + compute_triangle_count(count,max_ocodes);
+ if (withclr < count)
+ { output(code_clear);
+ did_clear();
+ rl_flush_fromclear(count);
+ }
+ else
+ { for (;count>0;count--) output_plain(rl_pixel);
+ }
+}
+
+static void rl_flush_withtable(count)
+ int count;
+{
+ int repmax;
+ int repleft;
+ int leftover;
+
+ if (VERBOSE) printf("rl_flush_withtable %d\n",count);
+ repmax = count / rl_table_max;
+ leftover = count % rl_table_max;
+ repleft = (leftover ? 1 : 0);
+ if (out_count+repmax+repleft > max_ocodes)
+ { repmax = max_ocodes - out_count;
+ leftover = count - (repmax * rl_table_max);
+ repleft = 1 + compute_triangle_count(leftover,max_ocodes);
+ }
+ if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
+ if (1+(int)compute_triangle_count(count,max_ocodes) < repmax+repleft)
+ { output(code_clear);
+ did_clear();
+ rl_flush_fromclear(count);
+ return;
+ }
+ max_out_clear();
+ for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
+ if (leftover)
+ { if (just_cleared)
+ { rl_flush_fromclear(leftover);
+ }
+ else if (leftover == 1)
+ { output_plain(rl_pixel);
+ }
+ else
+ { output_plain(rl_basecode+leftover-2);
+ }
+ }
+ reset_out_clear();
+}
+
+static void rl_flush()
+{
+ if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
+ if (rl_count == 1)
+ { output_plain(rl_pixel);
+ rl_count = 0;
+ if (VERBOSE) printf("rl_flush ]\n");
+ return;
+ }
+ if (just_cleared)
+ { rl_flush_fromclear(rl_count);
+ }
+ else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
+ { rl_flush_clearorrep(rl_count);
+ }
+ else
+ { rl_flush_withtable(rl_count);
+ }
+ if (VERBOSE) printf("rl_flush ]\n");
+ rl_count = 0;
+}
+
+
+static void compress( init_bits, handle, readValue )
+ int init_bits;
+ Tcl_Channel handle;
+ ifunptr readValue;
+{
+ int c;
+
+ ofile = handle;
+ obuf = 0;
+ obits = 0;
+ oblen = 0;
+ code_clear = 1 << (init_bits - 1);
+ code_eof = code_clear + 1;
+ rl_basecode = code_eof + 1;
+ out_bump_init = (1 << (init_bits - 1)) - 1;
+ /* for images with a lot of runs, making out_clear_init larger will
+ give better compression. */
+ out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
+#ifdef DEBUGGING_ENVARS
+ { const char *ocienv;
+ ocienv = getenv("GIF_OUT_CLEAR_INIT");
+ if (ocienv)
+ { out_clear_init = atoi(ocienv);
+ if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
+ }
+ }
+#endif
+ out_bits_init = init_bits;
+ max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
+ did_clear();
+ output(code_clear);
+ rl_count = 0;
+ while (1)
+ { c = readValue();
+ if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
+ if (c == EOF) break;
+ if (rl_pixel == c)
+ { rl_count ++;
+ }
+ else
+ { rl_pixel = c;
+ rl_count = 1;
+ }
+ }
+ output(code_eof);
+ output_flush();
+}
+
+/*-----------------------------------------------------------------------
+ *
+ * End of miGIF section - See copyright notice at start of section.
+ *
+ *-----------------------------------------------------------------------*/
+
+
diff --git a/tk/generic/tkImgPPM.c b/tk/generic/tkImgPPM.c
index 02309eb6588..8e5d17aee2b 100644
--- a/tk/generic/tkImgPPM.c
+++ b/tk/generic/tkImgPPM.c
@@ -16,6 +16,8 @@
* RCS: @(#) $Id$
*/
+#define USE_OLD_IMAGE
+
#include "tkInt.h"
#include "tkPort.h"
@@ -110,7 +112,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 +153,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,
@@ -183,6 +185,7 @@ FileReadPPM(interp, chan, fileName, formatString, imageHandle, destX, destY,
block.offset[1] = 1;
block.offset[2] = 2;
}
+ block.offset[3] = 0;
block.width = width;
block.pitch = block.pixelSize * fileWidth;
@@ -243,7 +246,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,13 +265,22 @@ 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) {
return TCL_ERROR;
}
+ if (Tcl_SetChannelOption(interp, chan, "-translation", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
sprintf(header, "P6\n%d %d\n255\n", blockPtr->width, blockPtr->height);
Tcl_Write(chan, header, -1);
@@ -343,7 +355,7 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
{
#define BUFFER_SIZE 1000
char buffer[BUFFER_SIZE];
- int i, numFields, firstInLine;
+ int i, numFields;
int type = 0;
char c;
@@ -355,7 +367,6 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
if (Tcl_Read(chan, &c, 1) != 1) {
return 0;
}
- firstInLine = 1;
i = 0;
for (numFields = 0; numFields < 4; numFields++) {
/*
@@ -364,7 +375,6 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
while (1) {
while (isspace(UCHAR(c))) {
- firstInLine = (c == '\n');
if (Tcl_Read(chan, &c, 1) != 1) {
return 0;
}
@@ -377,7 +387,6 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
return 0;
}
} while (c != '\n');
- firstInLine = 1;
}
/*
@@ -397,7 +406,6 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
buffer[i] = ' ';
i++;
}
- firstInLine = 0;
}
done:
buffer[i] = 0;
@@ -419,3 +427,4 @@ ReadPPMFileHeader(chan, widthPtr, heightPtr, maxIntensityPtr)
}
return type;
}
+
diff --git a/tk/generic/tkImgPhoto.c b/tk/generic/tkImgPhoto.c
index 72fddfe1478..7416771041b 100644
--- a/tk/generic/tkImgPhoto.c
+++ b/tk/generic/tkImgPhoto.c
@@ -2,7 +2,7 @@
* tkImgPhoto.c --
*
* Implements images of type "photo" for Tk. Photo images are
- * stored in full color (24 bits per pixel) and displayed using
+ * stored in full color (32 bits per pixel) and displayed using
* dithering if necessary.
*
* Copyright (c) 1994 The Australian National University.
@@ -11,6 +11,10 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
+ * Author: Paul Mackerras (paulus@cs.anu.edu.au),
+ * Department of Computer Science,
+ * Australian National University.
+ *
* RCS: @(#) $Id$
*/
@@ -19,11 +23,15 @@
#include "tclMath.h"
#include <ctype.h>
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+
/*
* Declaration for internal Xlib function used here:
*/
-extern _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image));
+extern int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image));
/*
* A signed 8-bit integral type. If chars are unsigned and the compiler
@@ -121,6 +129,9 @@ typedef struct ColorTable {
* MAP_COLORS: 1 means pixel values should be mapped
* through pixelMap.
*/
+#ifdef COLOR_WINDOW
+#undef COLOR_WINDOW
+#endif
#define BLACK_AND_WHITE 1
#define COLOR_WINDOW 2
@@ -147,8 +158,8 @@ typedef struct PhotoMaster {
* instances of this image. */
double gamma; /* Display gamma value to correct for. */
char *fileString; /* Name of file to read into image. */
- Tcl_Obj *dataObj; /* Object to use as contents of image. */
- char *format; /* User-specified format of data in image
+ Tcl_Obj *dataString; /* Object to use as contents of image. */
+ Tcl_Obj *format; /* User-specified format of data in image
* file or string value. */
unsigned char *pix24; /* Local storage for 24-bit image. */
int ditherX, ditherY; /* Location of first incorrectly
@@ -211,14 +222,14 @@ typedef struct PhotoInstance {
struct SubcommandOptions {
int options; /* Individual bits indicate which
* options were specified - see below. */
- char *name; /* Name specified without an option. */
+ Tcl_Obj *name; /* Name specified without an option. */
int fromX, fromY; /* Values specified for -from option. */
int fromX2, fromY2; /* Second coordinate pair for -from option. */
int toX, toY; /* Values specified for -to option. */
int toX2, toY2; /* Second coordinate pair for -to option. */
int zoomX, zoomY; /* Values specified for -zoom option. */
int subsampleX, subsampleY; /* Values specified for -subsample option. */
- char *format; /* Value specified for -format option. */
+ Tcl_Obj *format; /* Value specified for -format option. */
XColor *background; /* Value specified for -background option. */
};
@@ -270,7 +281,7 @@ static char *optionNames[] = {
*/
static int ImgPhotoCreate _ANSI_ARGS_((Tcl_Interp *interp,
- char *name, int argc, Tcl_Obj *CONST objv[],
+ char *name, int objc, Tcl_Obj *CONST objv[],
Tk_ImageType *typePtr, Tk_ImageMaster master,
ClientData *clientDataPtr));
static ClientData ImgPhotoGet _ANSI_ARGS_((Tk_Window tkwin,
@@ -282,6 +293,10 @@ static void ImgPhotoDisplay _ANSI_ARGS_((ClientData clientData,
static void ImgPhotoFree _ANSI_ARGS_((ClientData clientData,
Display *display));
static void ImgPhotoDelete _ANSI_ARGS_((ClientData clientData));
+static int ImgPhotoPostscript _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ Tk_PostscriptInfo psInfo, int x, int y, int width,
+ int height, int prepass));
Tk_ImageType tkPhotoImageType = {
"photo", /* name */
@@ -290,9 +305,18 @@ Tk_ImageType tkPhotoImageType = {
ImgPhotoDisplay, /* displayProc */
ImgPhotoFree, /* freeProc */
ImgPhotoDelete, /* deleteProc */
+ ImgPhotoPostscript, /* postscriptProc */
(Tk_ImageType *) NULL /* nextPtr */
};
+typedef struct ThreadSpecificData {
+ Tk_PhotoImageFormat *formatList; /* Pointer to the first in the
+ * list of known photo image formats.*/
+ Tk_PhotoImageFormat *oldFormatList; /* Pointer to the first in the
+ * list of known photo image formats.*/
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
/*
* Default configuration
*/
@@ -306,8 +330,6 @@ Tk_ImageType tkPhotoImageType = {
* Information used for parsing configuration specifications:
*/
static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_STRING, "-format", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(PhotoMaster, format), TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(PhotoMaster, fileString), TK_CONFIG_NULL_OK},
{TK_CONFIG_DOUBLE, "-gamma", (char *) NULL, (char *) NULL,
@@ -332,26 +354,20 @@ static int imgPhotoColorHashInitialized;
#define N_COLOR_HASH (sizeof(ColorTableId) / sizeof(int))
/*
- * Pointer to the first in the list of known photo image formats.
- */
-
-static Tk_PhotoImageFormat *formatList = NULL;
-
-/*
* Forward declarations
*/
static int ImgPhotoCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
static int ParseSubcommandOptions _ANSI_ARGS_((
struct SubcommandOptions *optPtr,
Tcl_Interp *interp, int allowedOptions,
- int *indexPtr, int argc, char **argv));
+ int *indexPtr, int objc, Tcl_Obj *CONST objv[]));
static void ImgPhotoCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static int ImgPhotoConfigureMaster _ANSI_ARGS_((
Tcl_Interp *interp, PhotoMaster *masterPtr,
- int argc, Tcl_Obj *CONST objv[], int flags));
+ int objc, Tcl_Obj *CONST objv[], int flags));
static void ImgPhotoConfigureInstance _ANSI_ARGS_((
PhotoInstance *instancePtr));
static void ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr,
@@ -359,7 +375,7 @@ static void ImgPhotoSetSize _ANSI_ARGS_((PhotoMaster *masterPtr,
static void ImgPhotoInstanceSetSize _ANSI_ARGS_((
PhotoInstance *instancePtr));
static int ImgStringWrite _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_DString *dataPtr, char *formatString,
+ Tcl_Obj *formatString,
Tk_PhotoImageBlock *blockPtr));
static char * ImgGetPhoto _ANSI_ARGS_((PhotoMaster *masterPtr,
Tk_PhotoImageBlock *blockPtr,
@@ -376,18 +392,19 @@ static void DisposeInstance _ANSI_ARGS_((ClientData clientData));
static int ReclaimColors _ANSI_ARGS_((ColorTableId *id,
int numColors));
static int MatchFileFormat _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Channel chan, char *fileName,
- char *formatString,
+ Tcl_Channel chan, char *fileName, Tcl_Obj *formatString,
Tk_PhotoImageFormat **imageFormatPtr,
- int *widthPtr, int *heightPtr));
+ int *widthPtr, int *heightPtr, int *oldformat));
static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *dataObj, char *formatString,
+ Tcl_Obj *data, Tcl_Obj *formatString,
Tk_PhotoImageFormat **imageFormatPtr,
- int *widthPtr, int *heightPtr));
-static void Dither _ANSI_ARGS_((PhotoMaster *masterPtr,
- int x, int y, int width, int height));
+ int *widthPtr, int *heightPtr, int *oldformat));
+static Tcl_ObjCmdProc * PhotoOptionFind _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_Obj *obj));
static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr,
int x, int y, int width, int height));
+static void PhotoOptionCleanupProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp));
#undef MIN
#define MIN(a, b) ((a) < (b)? (a): (b))
@@ -397,7 +414,7 @@ static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr,
/*
*----------------------------------------------------------------------
*
- * Tk_CreatePhotoImageFormat --
+ * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat --
*
* This procedure is invoked by an image file handler to register
* a new photo image format and the procedures that handle the
@@ -413,6 +430,25 @@ static void DitherInstance _ANSI_ARGS_((PhotoInstance *instancePtr,
*
*----------------------------------------------------------------------
*/
+void
+Tk_CreateOldPhotoImageFormat(formatPtr)
+ Tk_PhotoImageFormat *formatPtr;
+ /* Structure describing the format. All of
+ * the fields except "nextPtr" must be filled
+ * in by caller. Must not have been passed
+ * to Tk_CreatePhotoImageFormat previously. */
+{
+ Tk_PhotoImageFormat *copyPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat));
+ *copyPtr = *formatPtr;
+ copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1));
+ strcpy(copyPtr->name, formatPtr->name);
+ copyPtr->nextPtr = tsdPtr->oldFormatList;
+ tsdPtr->oldFormatList = copyPtr;
+}
void
Tk_CreatePhotoImageFormat(formatPtr)
@@ -423,13 +459,20 @@ Tk_CreatePhotoImageFormat(formatPtr)
* to Tk_CreatePhotoImageFormat previously. */
{
Tk_PhotoImageFormat *copyPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat));
*copyPtr = *formatPtr;
copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1));
strcpy(copyPtr->name, formatPtr->name);
- copyPtr->nextPtr = formatList;
- formatList = copyPtr;
+ if (isupper((unsigned char) *formatPtr->name)) {
+ copyPtr->nextPtr = tsdPtr->oldFormatList;
+ tsdPtr->oldFormatList = copyPtr;
+ } else {
+ copyPtr->nextPtr = tsdPtr->formatList;
+ tsdPtr->formatList = copyPtr;
+ }
}
/*
@@ -451,11 +494,11 @@ Tk_CreatePhotoImageFormat(formatPtr)
*/
static int
-ImgPhotoCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
+ImgPhotoCreate(interp, name, objc, objv, typePtr, master, clientDataPtr)
Tcl_Interp *interp; /* Interpreter for application containing
* image. */
char *name; /* Name to use for image. */
- int argc; /* Number of arguments. */
+ int objc; /* Number of arguments. */
Tcl_Obj *CONST objv[]; /* Argument objects for options (doesn't
* include image name or type). */
Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
@@ -485,7 +528,7 @@ ImgPhotoCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
* Process configuration options given in the image create command.
*/
- if (ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, 0) != TCL_OK) {
+ if (ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, 0) != TCL_OK) {
ImgPhotoDelete((ClientData) masterPtr);
return TCL_ERROR;
}
@@ -513,14 +556,24 @@ ImgPhotoCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
*/
static int
-ImgPhotoCmd(clientData, interp, argc, objv)
+ImgPhotoCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about photo master. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
+ int objc; /* Number of arguments. */
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
+ int oldformat = 0;
+ static char *photoOptions[] = {
+ "blank", "cget", "configure", "copy", "data", "get", "put",
+ "read", "redither", "write", (char *) NULL
+ };
+ enum options {
+ PHOTO_BLANK, PHOTO_CGET, PHOTO_CONFIGURE, PHOTO_COPY, PHOTO_DATA,
+ PHOTO_GET, PHOTO_PUT, PHOTO_READ, PHOTO_REDITHER, PHOTO_WRITE
+ };
+
PhotoMaster *masterPtr = (PhotoMaster *) clientData;
- int c, result, index;
+ int result, index;
int x, y, width, height;
int dataWidth, dataHeight;
struct SubcommandOptions options;
@@ -530,7 +583,6 @@ ImgPhotoCmd(clientData, interp, argc, objv)
unsigned char *pixelPtr;
Tk_PhotoImageBlock block;
Tk_Window tkwin;
- char string[16];
XColor color;
Tk_PhotoImageFormat *imageFormat;
int imageWidth, imageHeight;
@@ -538,96 +590,126 @@ ImgPhotoCmd(clientData, interp, argc, objv)
Tcl_Channel chan;
Tk_PhotoHandle srcHandle;
size_t length;
- static char **argv = NULL;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- 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 (argv) {
- ckfree((char *) argv);
- }
- argv = (char **) ckalloc((argc+1) * sizeof(char *));
- argv[argc] = NULL;
- for (index = 0; index < argc; index++) {
- argv[index] = Tcl_GetStringFromObj(objv[index], (int *) NULL);
+ if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0,
+ &index) != TCL_OK) {
+ Tcl_ObjCmdProc *proc;
+ proc = PhotoOptionFind(interp, objv[1]);
+ if (proc == (Tcl_ObjCmdProc *) NULL) {
+ return TCL_ERROR;
+ }
+ return proc(clientData, interp, objc, objv);
}
- c = argv[1][0];
- length = strlen(argv[1]);
-
- if ((c == 'b') && (strncmp(argv[1], "blank", length) == 0)) {
+ switch ((enum options) index) {
+ case PHOTO_BLANK: {
/*
* photo blank command - just call Tk_PhotoBlank.
*/
- if (argc == 2) {
+ if (objc == 2) {
Tk_PhotoBlank(masterPtr);
} else {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " blank\"", (char *) NULL);
+ Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
return TCL_ERROR;
}
- } else if ((c == 'c') && (length >= 2)
- && (strncmp(argv[1], "cget", length) == 0)) {
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " cget option\"",
- (char *) NULL);
+ break;
+ }
+ case PHOTO_CGET: {
+ char *arg;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
return TCL_ERROR;
}
- if (strncmp(argv[2],"-data", length) == 0) {
- if (masterPtr->dataObj) {
- Tcl_SetObjResult(interp, masterPtr->dataObj);
+ arg = Tcl_GetStringFromObj(objv[2], (int *) &length);
+ if (strncmp(arg,"-data", length) == 0) {
+ if (masterPtr->dataString) {
+ Tcl_SetObjResult(interp, masterPtr->dataString);
+ }
+ return TCL_OK;
+ }
+ if (strncmp(arg,"-format", length) == 0) {
+ if (masterPtr->format) {
+ Tcl_SetObjResult(interp, masterPtr->format);
}
return TCL_OK;
}
Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs,
- (char *) masterPtr, argv[2], 0);
- } else if ((c == 'c') && (length >= 3)
- && (strncmp(argv[1], "configure", length) == 0)) {
+ (char *) masterPtr, Tcl_GetString(objv[2]), 0);
+ break;
+ }
+ case PHOTO_CONFIGURE: {
/*
* photo configure command - handle this in the standard way.
*/
char *opt, *arg;
- if (argc == 2) {
+ if (objc == 2) {
+ Tcl_Obj *obj, *subobj;
result = Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
configSpecs, (char *) masterPtr, (char *) NULL, 0);
if (result != TCL_OK) {
return result;
}
- opt = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &length);
- arg = (char *) ckalloc(length + 1);
- strcpy(arg, opt);
- Tcl_ResetResult(interp);
- Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "{-data {} {} {} {}} ", arg, (char*) NULL);
- ckfree(arg);
+ obj = Tcl_NewObj();
+ subobj = Tcl_NewStringObj("-data {} {} {}", 14);
+ if (masterPtr->dataString) {
+ Tcl_ListObjAppendElement(interp, subobj, masterPtr->dataString);
+ } else {
+ Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL);
+ }
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewStringObj("-format {} {} {}", 16);
+ if (masterPtr->format) {
+ Tcl_ListObjAppendElement(interp, subobj, masterPtr->format);
+ } else {
+ Tcl_AppendStringsToObj(subobj, " {}", (char *) NULL);
+ }
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp));
+ Tcl_SetObjResult(interp, obj);
return TCL_OK;
}
- if (argc == 3) {
- if (strncmp(argv[2], "-data", length)) {
- return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
- configSpecs, (char *) masterPtr, argv[2], 0);
- } else {
+ if (objc == 3) {
+ char *arg = Tcl_GetStringFromObj(objv[2], (int *) &length);
+ if (!strncmp(arg, "-data", length)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "-data {} {} {}", (char *) NULL);
+ if (masterPtr->dataString) {
+ Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
+ masterPtr->dataString);
+ } else {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ " {}", (char *) NULL);
+ }
+ return TCL_OK;
+ } else if (!strncmp(arg, "-format", length)) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "-data {} {} {} ", (char *) NULL);
- if (masterPtr->dataObj) {
+ "-format {} {} {}", (char *) NULL);
+ if (masterPtr->format) {
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
- masterPtr->dataObj);
+ masterPtr->format);
} else {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
- "{}", (char *) NULL);
+ " {}", (char *) NULL);
}
return TCL_OK;
+ } else {
+ return Tk_ConfigureInfo(interp, Tk_MainWindow(interp),
+ configSpecs, (char *) masterPtr, arg, 0);
}
}
- return ImgPhotoConfigureMaster(interp, masterPtr, argc-2, objv+2,
+ return ImgPhotoConfigureMaster(interp, masterPtr, objc-2, objv+2,
TK_CONFIG_ARGV_ONLY);
- } else if ((c == 'c') && (length >= 3)
- && (strncmp(argv[1], "copy", length) == 0)) {
+ break;
+ }
+ case PHOTO_COPY: {
/*
* photo copy command - first parse options.
*/
@@ -639,14 +721,12 @@ ImgPhotoCmd(clientData, interp, argc, objv)
options.name = NULL;
if (ParseSubcommandOptions(&options, interp,
OPT_FROM | OPT_TO | OPT_ZOOM | OPT_SUBSAMPLE | OPT_SHRINK,
- &index, argc, argv) != TCL_OK) {
+ &index, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- if (options.name == NULL || index < argc) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " copy source-image ?-from x1 y1 x2 y2?",
- " ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?",
- "\"", (char *) NULL);
+ if (options.name == NULL || index < objc) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "source-image ?-from x1 y1 x2 y2? ?-to x1 y1 x2 y2? ?-zoom x y? ?-subsample x y?");
return TCL_ERROR;
}
@@ -655,8 +735,9 @@ ImgPhotoCmd(clientData, interp, argc, objv)
* Check the values given for the -from option.
*/
- if ((srcHandle = Tk_FindPhoto(interp, options.name)) == NULL) {
- Tcl_AppendResult(interp, "image \"", argv[2], "\" doesn't",
+ if ((srcHandle = Tk_FindPhoto(interp, Tcl_GetString(options.name))) == NULL) {
+ Tcl_AppendResult(interp, "image \"",
+ Tcl_GetString(options.name), "\" doesn't",
" exist or is not a photo image", (char *) NULL);
return TCL_ERROR;
}
@@ -722,8 +803,9 @@ ImgPhotoCmd(clientData, interp, argc, objv)
options.toY2 - options.toY, options.zoomX, options.zoomY,
options.subsampleX, options.subsampleY);
- } else if ((c == 'd') && (strncmp(argv[1], "data", length) == 0)) {
- Tcl_DString buffer;
+ break;
+ }
+ case PHOTO_DATA: {
char *data;
/*
@@ -739,13 +821,11 @@ ImgPhotoCmd(clientData, interp, argc, objv)
options.fromY = 0;
if (ParseSubcommandOptions(&options, interp,
OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
- &index, argc, argv) != TCL_OK) {
+ &index, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- if ((options.name != NULL) || (index < argc)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " data ?-format format-name?",
- "?-from x1 y1 x2 y2?\"", (char *) NULL);
+ if ((options.name != NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "?options?");
return TCL_ERROR;
}
if ((options.fromX > masterPtr->width)
@@ -771,10 +851,10 @@ ImgPhotoCmd(clientData, interp, argc, objv)
*/
if (options.options & OPT_FORMAT) {
- for (imageFormat = formatList; imageFormat != NULL;
+ for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
imageFormat = imageFormat->nextPtr) {
- if ((strncasecmp(options.format, imageFormat->name,
- strlen(imageFormat->name)) == 0)) {
+ if ((strncasecmp(Tcl_GetString(options.format),
+ imageFormat->name, strlen(imageFormat->name)) == 0)) {
if (imageFormat->stringWriteProc != NULL) {
stringWriteProc = imageFormat->stringWriteProc;
break;
@@ -782,7 +862,8 @@ ImgPhotoCmd(clientData, interp, argc, objv)
}
}
if (stringWriteProc == NULL) {
- Tcl_AppendResult(interp, "image string format \"", options.format,
+ Tcl_AppendResult(interp, "image string format \"",
+ Tcl_GetString(options.format),
"\" is not supported", (char *) NULL);
return TCL_ERROR;
}
@@ -796,39 +877,37 @@ ImgPhotoCmd(clientData, interp, argc, objv)
*/
data = ImgGetPhoto(masterPtr, &block, &options);
- Tcl_DStringInit(&buffer);
- result = stringWriteProc(interp, &buffer,
- options.format, &block);
+ result = ((int (*) _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *formatString,
+ Tk_PhotoImageBlock *blockPtr, VOID *dummy))) stringWriteProc)
+ (interp, options.format, &block, (VOID *) NULL);
if (options.background) {
Tk_FreeColor(options.background);
}
if (data) {
ckfree(data);
}
- if (result == TCL_OK) {
- Tcl_DStringResult(interp, &buffer);
- } else {
- Tcl_DStringFree(&buffer);
- }
return result;
- } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
+ break;
+ }
+ case PHOTO_GET: {
/*
* photo get command - first parse and check parameters.
*/
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " get x y\"", (char *) NULL);
+ char string[TCL_INTEGER_SPACE * 3];
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "x y");
return TCL_ERROR;
}
- if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
return TCL_ERROR;
}
if ((x < 0) || (x >= masterPtr->width)
|| (y < 0) || (y >= masterPtr->height)) {
- Tcl_AppendResult(interp, argv[0], " get: ",
+ Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " get: ",
"coordinates out of range", (char *) NULL);
return TCL_ERROR;
}
@@ -841,7 +920,9 @@ ImgPhotoCmd(clientData, interp, argc, objv)
sprintf(string, "%d %d %d", pixelPtr[0], pixelPtr[1],
pixelPtr[2]);
Tcl_AppendResult(interp, string, (char *) NULL);
- } else if ((c == 'p') && (strncmp(argv[1], "put", length) == 0)) {
+ break;
+ }
+ case PHOTO_PUT: {
/*
* photo put command - first parse the options and colors specified.
*/
@@ -850,19 +931,19 @@ ImgPhotoCmd(clientData, interp, argc, objv)
memset((VOID *) &options, 0, sizeof(options));
options.name = NULL;
if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT,
- &index, argc, argv) != TCL_OK) {
+ &index, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- if ((options.name == NULL) || (index < argc)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " put data ?-format format? ?-to x1 y1 x2 y2?\"",
- (char *) NULL);
+ if ((options.name == NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "data ?options?");
return TCL_ERROR;
}
if (MatchStringFormat(interp, options.name ? objv[2]:NULL,
options.format, &imageFormat, &imageWidth,
- &imageHeight) == TCL_OK) {
+ &imageHeight, &oldformat) == TCL_OK) {
+ Tcl_Obj *format;
+ Tcl_Obj *data;
if (((options.options & OPT_TO) == 0) || (options.toX2 < 0)) {
options.toX2 = options.toX + imageWidth;
options.toY2 = options.toY + imageHeight;
@@ -873,8 +954,16 @@ ImgPhotoCmd(clientData, interp, argc, objv)
if (imageHeight > options.toY2 - options.toY) {
imageHeight = options.toY2 - options.toY;
}
- if ((*imageFormat->stringReadProc)(interp, objv[2],
- options.format, (Tk_PhotoHandle) masterPtr,
+ format = options.format;
+ data = objv[2];
+ if (oldformat) {
+ if (format) {
+ format = (Tcl_Obj *) Tcl_GetString(format);
+ }
+ data = (Tcl_Obj *) Tcl_GetString(data);
+ }
+ if ((*imageFormat->stringReadProc)(interp, data,
+ format, (Tk_PhotoHandle) masterPtr,
0, 0, imageWidth, imageHeight, options.toX, options.toY)
!= TCL_OK) {
return TCL_ERROR;
@@ -886,7 +975,8 @@ ImgPhotoCmd(clientData, interp, argc, objv)
return TCL_ERROR;
}
Tcl_ResetResult(interp);
- if (Tcl_SplitList(interp, options.name, &dataHeight, &srcArgv)
+ if (Tcl_SplitList(interp, Tcl_GetString(options.name),
+ &dataHeight, &srcArgv)
!= TCL_OK) {
return TCL_ERROR;
}
@@ -955,30 +1045,31 @@ ImgPhotoCmd(clientData, interp, argc, objv)
block.offset[0] = 0;
block.offset[1] = 1;
block.offset[2] = 2;
+ block.offset[3] = 0;
Tk_PhotoPutBlock((ClientData)masterPtr, &block,
options.toX, options.toY, options.toX2 - options.toX,
options.toY2 - options.toY);
ckfree((char *) block.pixelPtr);
- } else if ((c == 'r') && (length >= 3)
- && (strncmp(argv[1], "read", length) == 0)) {
+ break;
+ }
+ case PHOTO_READ: {
/*
* photo read command - first parse the options specified.
*/
+ Tcl_Obj *format;
index = 2;
memset((VOID *) &options, 0, sizeof(options));
options.name = NULL;
options.format = NULL;
if (ParseSubcommandOptions(&options, interp,
OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK,
- &index, argc, argv) != TCL_OK) {
+ &index, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- if ((options.name == NULL) || (index < argc)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " read fileName ?-format format-name?",
- " ?-from x1 y1 x2 y2? ?-to x y? ?-shrink?\"",
- (char *) NULL);
+ if ((options.name == NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "fileName ?options?");
return TCL_ERROR;
}
@@ -996,7 +1087,8 @@ ImgPhotoCmd(clientData, interp, argc, objv)
* Open the image file and look for a handler for it.
*/
- chan = Tcl_OpenFileChannel(interp, options.name, "r", 0);
+ chan = Tcl_OpenFileChannel(interp,
+ Tcl_GetString(options.name), "r", 0);
if (chan == NULL) {
return TCL_ERROR;
}
@@ -1004,8 +1096,14 @@ ImgPhotoCmd(clientData, interp, argc, objv)
!= TCL_OK) {
return TCL_ERROR;
}
- if (MatchFileFormat(interp, chan, options.name, options.format,
- &imageFormat, &imageWidth, &imageHeight) != TCL_OK) {
+ if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (MatchFileFormat(interp, chan,
+ Tcl_GetString(options.name), options.format,
+ &imageFormat, &imageWidth, &imageHeight, &oldformat) != TCL_OK) {
Tcl_Close(NULL, chan);
return TCL_ERROR;
}
@@ -1044,17 +1142,22 @@ ImgPhotoCmd(clientData, interp, argc, objv)
* into the image.
*/
- result = (*imageFormat->fileReadProc)(interp, chan, options.name,
- options.format, (Tk_PhotoHandle) masterPtr, options.toX,
+ format = options.format;
+ if (oldformat && format) {
+ format = (Tcl_Obj *) Tcl_GetString(format);
+ }
+ result = (*imageFormat->fileReadProc)(interp, chan,
+ Tcl_GetString(options.name),
+ format, (Tk_PhotoHandle) masterPtr, options.toX,
options.toY, width, height, options.fromX, options.fromY);
if (chan != NULL) {
Tcl_Close(NULL, chan);
}
return result;
- } else if ((c == 'r') && (length >= 3)
- && (strncmp(argv[1], "redither", length) == 0)) {
-
- if (argc == 2) {
+ break;
+ }
+ case PHOTO_REDITHER: {
+ if (objc == 2) {
/*
* Call Dither if any part of the image is not correctly
* dithered at present.
@@ -1063,11 +1166,11 @@ ImgPhotoCmd(clientData, interp, argc, objv)
x = masterPtr->ditherX;
y = masterPtr->ditherY;
if (masterPtr->ditherX != 0) {
- Dither(masterPtr, x, y, masterPtr->width - x, 1);
+ Tk_DitherPhoto((Tk_PhotoHandle) masterPtr, x, y, masterPtr->width - x, 1);
}
if (masterPtr->ditherY < masterPtr->height) {
x = 0;
- Dither(masterPtr, 0, masterPtr->ditherY, masterPtr->width,
+ Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, 0, masterPtr->ditherY, masterPtr->width,
masterPtr->height - masterPtr->ditherY);
}
@@ -1082,12 +1185,15 @@ ImgPhotoCmd(clientData, interp, argc, objv)
}
} else {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " redither\"", (char *) NULL);
+ Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
return TCL_ERROR;
}
- } else if ((c == 'w') && (strncmp(argv[1], "write", length) == 0)) {
+ break;
+ }
+ case PHOTO_WRITE: {
char *data;
+ Tcl_Obj *format;
+
/*
* Prevent file system access in safe interpreters.
*/
@@ -1108,13 +1214,11 @@ ImgPhotoCmd(clientData, interp, argc, objv)
options.format = NULL;
if (ParseSubcommandOptions(&options, interp,
OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND,
- &index, argc, argv) != TCL_OK) {
+ &index, objc, objv) != TCL_OK) {
return TCL_ERROR;
}
- if ((options.name == NULL) || (index < argc)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " write fileName ?-format format-name?",
- "?-from x1 y1 x2 y2?\"", (char *) NULL);
+ if ((options.name == NULL) || (index < objc)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fileName ?options?");
return TCL_ERROR;
}
if ((options.fromX > masterPtr->width)
@@ -1141,16 +1245,30 @@ ImgPhotoCmd(clientData, interp, argc, objv)
*/
matched = 0;
- for (imageFormat = formatList; imageFormat != NULL;
+ for (imageFormat = tsdPtr->formatList; imageFormat != NULL;
+ imageFormat = imageFormat->nextPtr) {
+ if ((options.format == NULL)
+ || (strncasecmp(Tcl_GetString(options.format),
+ imageFormat->name, strlen(imageFormat->name)) == 0)) {
+ matched = 1;
+ if (imageFormat->fileWriteProc != NULL) {
+ break;
+ }
+ }
+ }
+ if (imageFormat == NULL) {
+ oldformat = 1;
+ for (imageFormat = tsdPtr->oldFormatList; imageFormat != NULL;
imageFormat = imageFormat->nextPtr) {
if ((options.format == NULL)
- || (strncasecmp(options.format, imageFormat->name,
- strlen(imageFormat->name)) == 0)) {
+ || (strncasecmp(Tcl_GetString(options.format),
+ imageFormat->name, strlen(imageFormat->name)) == 0)) {
matched = 1;
if (imageFormat->fileWriteProc != NULL) {
break;
}
}
+ }
}
if (imageFormat == NULL) {
if (options.format == NULL) {
@@ -1158,10 +1276,12 @@ ImgPhotoCmd(clientData, interp, argc, objv)
"has file writing capability", (char *) NULL);
} else if (!matched) {
Tcl_AppendResult(interp, "image file format \"",
- options.format, "\" is unknown", (char *) NULL);
+ Tcl_GetString(options.format),
+ "\" is unknown", (char *) NULL);
} else {
Tcl_AppendResult(interp, "image file format \"",
- options.format, "\" has no file writing capability",
+ Tcl_GetString(options.format),
+ "\" has no file writing capability",
(char *) NULL);
}
return TCL_ERROR;
@@ -1173,8 +1293,13 @@ ImgPhotoCmd(clientData, interp, argc, objv)
*/
data = ImgGetPhoto(masterPtr, &block, &options);
- result = (*imageFormat->fileWriteProc)(interp, options.name,
- options.format, &block);
+ format = options.format;
+ if (oldformat && format) {
+ format = (Tcl_Obj *) Tcl_GetString(options.format);
+ }
+ result = (*imageFormat->fileWriteProc)(interp,
+ Tcl_GetString(options.name),
+ format, &block);
if (options.background) {
Tk_FreeColor(options.background);
}
@@ -1182,11 +1307,8 @@ ImgPhotoCmd(clientData, interp, argc, objv)
ckfree(data);
}
return result;
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be blank, cget, configure, copy, get, put,",
- " read, redither, or write", (char *) NULL);
- return TCL_ERROR;
+ break;
+ }
}
return TCL_OK;
@@ -1211,7 +1333,7 @@ ImgPhotoCmd(clientData, interp, argc, objv)
*/
static int
-ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
+ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv)
struct SubcommandOptions *optPtr;
/* Information about the options specified
* and the values given is returned here. */
@@ -1219,27 +1341,27 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
int allowedOptions; /* Indicates which options are valid for
* the current command. */
int *optIndexPtr; /* Points to a variable containing the
- * current index in argv; this variable is
+ * current index in objv; this variable is
* updated by this procedure. */
- int argc; /* Number of arguments in argv[]. */
- char **argv; /* Arguments to be parsed. */
+ int objc; /* Number of arguments in objv[]. */
+ Tcl_Obj *CONST objv[]; /* Arguments to be parsed. */
{
int index, c, bit, currentBit;
- size_t length;
+ int length;
char *option, **listPtr;
int values[4];
int numValues, maxValues, argIndex;
- for (index = *optIndexPtr; index < argc; *optIndexPtr = ++index) {
+ for (index = *optIndexPtr; index < objc; *optIndexPtr = ++index) {
/*
* We can have one value specified without an option;
* it goes into optPtr->name.
*/
- option = argv[index];
+ option = Tcl_GetStringFromObj(objv[index], &length);
if (option[0] != '-') {
if (optPtr->name == NULL) {
- optPtr->name = option;
+ optPtr->name = objv[index];
continue;
}
break;
@@ -1249,13 +1371,12 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
* Work out which option this is.
*/
- length = strlen(option);
c = option[0];
bit = 0;
currentBit = 1;
for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
if ((c == *listPtr[0])
- && (strncmp(option, *listPtr, length) == 0)) {
+ && (strncmp(option, *listPtr, (size_t) length) == 0)) {
if (bit != 0) {
bit = 0; /* An ambiguous option. */
break;
@@ -1271,7 +1392,8 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
*/
if ((allowedOptions & bit) == 0) {
- Tcl_AppendResult(interp, "unrecognized option \"", argv[index],
+ Tcl_AppendResult(interp, "unrecognized option \"",
+ Tcl_GetString(objv[index]),
"\": must be ", (char *)NULL);
bit = 1;
for (listPtr = optionNames; *listPtr != NULL; ++listPtr) {
@@ -1300,10 +1422,10 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
* The -background option takes a single XColor value.
*/
- if (index + 1 < argc) {
+ if (index + 1 < objc) {
*optIndexPtr = ++index;
optPtr->background = Tk_GetColor(interp, Tk_MainWindow(interp),
- Tk_GetUid(argv[index]));
+ Tk_GetUid(Tcl_GetString(objv[index])));
if (!optPtr->background) {
return TCL_ERROR;
}
@@ -1317,22 +1439,26 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
* The -format option takes a single string value.
*/
- if (index + 1 < argc) {
+ if (index + 1 < objc) {
*optIndexPtr = ++index;
- optPtr->format = argv[index];
+ optPtr->format = objv[index];
} else {
Tcl_AppendResult(interp, "the \"-format\" option ",
"requires a value", (char *) NULL);
return TCL_ERROR;
}
} else if ((bit != OPT_SHRINK) && (bit != OPT_GRAYSCALE)) {
+ char *val;
maxValues = ((bit == OPT_FROM) || (bit == OPT_TO))? 4: 2;
argIndex = index + 1;
for (numValues = 0; numValues < maxValues; ++numValues) {
- if ((argIndex < argc) && (isdigit(UCHAR(argv[argIndex][0]))
- || ((argv[argIndex][0] == '-')
- && (isdigit(UCHAR(argv[argIndex][1])))))) {
- if (Tcl_GetInt(interp, argv[argIndex], &values[numValues])
+ if (argIndex >= objc) {
+ break;
+ }
+ val = Tcl_GetString(objv[argIndex]);
+ if ((argIndex < objc) && (isdigit(UCHAR(val[0]))
+ || ((val[0] == '-') && isdigit(UCHAR(val[1]))))) {
+ if (Tcl_GetInt(interp, val, &values[numValues])
!= TCL_OK) {
return TCL_ERROR;
}
@@ -1343,7 +1469,7 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
}
if (numValues == 0) {
- Tcl_AppendResult(interp, "the \"", argv[index], "\" option ",
+ Tcl_AppendResult(interp, "the \"", option, "\" option ",
"requires one ", maxValues == 2? "or two": "to four",
" integer values", (char *) NULL);
return TCL_ERROR;
@@ -1442,7 +1568,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
@@ -1452,38 +1578,48 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, argc, argv)
*/
static int
-ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, flags)
+ImgPhotoConfigureMaster(interp, masterPtr, objc, objv, flags)
Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
PhotoMaster *masterPtr; /* Pointer to data structure describing
* overall photo image to (re)configure. */
- int argc; /* Number of entries in argv. */
+ int objc; /* Number of entries in objv. */
Tcl_Obj *CONST objv[]; /* Pairs of configuration options for image. */
int flags; /* Flags to pass to Tk_ConfigureWidget,
* such as TK_CONFIG_ARGV_ONLY. */
{
PhotoInstance *instancePtr;
- char *oldFileString, *oldPaletteString, *oldFormat;
- Tcl_Obj *oldDataObj, *dataObj = NULL;
+ char *oldFileString, *oldPaletteString;
+ Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL;
int length, i, j;
double oldGamma;
int result;
Tcl_Channel chan;
Tk_PhotoImageFormat *imageFormat;
int imageWidth, imageHeight;
- static char **argv = NULL;
-
- if (argv) ckfree((char *) argv);
- argv = (char **) ckalloc((argc + 1) * sizeof(char *));
- for (i = 0, j = 0; i < argc; i++,j++) {
- argv[j] = Tcl_GetStringFromObj(objv[i], &length);
- if (argv[j][0] == '-' && argv[j][1] == 'd' &&
- strncmp(argv[j],"-data", length) == 0) {
- if (i < argc) {
- dataObj = objv[++i];
- j--;
+ char **args;
+ int oldformat;
+ Tcl_Obj *tempdata, *tempformat;
+
+ args = (char **) ckalloc((objc + 1) * sizeof(char *));
+ for (i = 0, j = 0; i < objc; i++,j++) {
+ args[j] = Tcl_GetStringFromObj(objv[i], &length);
+ if ((length > 1) && (args[j][0] == '-')) {
+ if ((args[j][1] == 'd') &&
+ !strncmp(args[j],"-data", (size_t) length)) {
+ if (i < objc) {
+ data = objv[++i];
+ j--;
+ }
+ } else if ((args[j][1] == 'f') &&
+ !strncmp(args[j],"-format", (size_t) length)) {
+ if (i < objc) {
+ format = objv[++i];
+ j--;
+ }
}
}
}
+
/*
* Save the current values for fileString and dataString, so we
* can tell if the user specifies them anew.
@@ -1494,7 +1630,7 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, flags)
*/
oldFileString = masterPtr->fileString;
- oldDataObj = (oldFileString == NULL) ? masterPtr->dataObj: NULL;
+ oldData = (oldFileString == NULL) ? masterPtr->dataString: NULL;
oldFormat = masterPtr->format;
oldPaletteString = masterPtr->palette;
oldGamma = masterPtr->gamma;
@@ -1504,9 +1640,11 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, flags)
*/
if (Tk_ConfigureWidget(interp, Tk_MainWindow(interp), configSpecs,
- j, argv, (char *) masterPtr, flags) != TCL_OK) {
+ j, args, (char *) masterPtr, flags) != TCL_OK) {
+ ckfree((char *) args);
return TCL_ERROR;
}
+ ckfree((char *) args);
/*
* Regard the empty string for -file, -data or -format as the null
@@ -1517,22 +1655,30 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, flags)
ckfree(masterPtr->fileString);
masterPtr->fileString = NULL;
}
- if (dataObj) {
- if (dataObj->length) {
- Tcl_IncrRefCount(dataObj);
+ if (data) {
+ if (data->length
+ || (data->typePtr == Tcl_GetObjType("bytearray")
+ && data->internalRep.otherValuePtr != NULL)) {
+ Tcl_IncrRefCount(data);
} else {
- dataObj = NULL;
+ data = NULL;
}
- if (masterPtr->dataObj) {
- Tcl_DecrRefCount(masterPtr->dataObj);
+ if (masterPtr->dataString) {
+ Tcl_DecrRefCount(masterPtr->dataString);
}
- masterPtr->dataObj = dataObj;
+ masterPtr->dataString = data;
}
- if ((masterPtr->format != NULL) && (masterPtr->format[0] == 0)) {
- ckfree(masterPtr->format);
- masterPtr->format = NULL;
+ if (format) {
+ if (format->length) {
+ Tcl_IncrRefCount(format);
+ } else {
+ format = NULL;
+ }
+ if (masterPtr->format) {
+ Tcl_DecrRefCount(masterPtr->format);
+ }
+ masterPtr->format = format;
}
-
/*
* Set the image to the user-requested size, if any,
* and make sure storage is correctly allocated for this image.
@@ -1567,15 +1713,23 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, flags)
!= TCL_OK) {
return TCL_ERROR;
}
+ if (Tcl_SetChannelOption(interp, chan, "-encoding", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
if (MatchFileFormat(interp, chan, masterPtr->fileString,
masterPtr->format, &imageFormat, &imageWidth,
- &imageHeight) != TCL_OK) {
+ &imageHeight, &oldformat) != TCL_OK) {
Tcl_Close(NULL, chan);
return TCL_ERROR;
}
ImgPhotoSetSize(masterPtr, imageWidth, imageHeight);
+ tempformat = masterPtr->format;
+ if (oldformat && tempformat) {
+ tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
+ }
result = (*imageFormat->fileReadProc)(interp, chan,
- masterPtr->fileString, masterPtr->format,
+ masterPtr->fileString, tempformat,
(Tk_PhotoHandle) masterPtr, 0, 0,
imageWidth, imageHeight, 0, 0);
Tcl_Close(NULL, chan);
@@ -1583,25 +1737,35 @@ ImgPhotoConfigureMaster(interp, masterPtr, argc, objv, flags)
return TCL_ERROR;
}
+ Tcl_ResetResult(interp);
masterPtr->flags |= IMAGE_CHANGED;
}
- if ((masterPtr->fileString == NULL) && (masterPtr->dataObj != NULL)
- && ((masterPtr->dataObj != oldDataObj)
+ if ((masterPtr->fileString == NULL) && (masterPtr->dataString != NULL)
+ && ((masterPtr->dataString != oldData)
|| (masterPtr->format != oldFormat))) {
- if (MatchStringFormat(interp, masterPtr->dataObj,
+ if (MatchStringFormat(interp, masterPtr->dataString,
masterPtr->format, &imageFormat, &imageWidth,
- &imageHeight) != TCL_OK) {
+ &imageHeight, &oldformat) != TCL_OK) {
return TCL_ERROR;
}
ImgPhotoSetSize(masterPtr, imageWidth, imageHeight);
- if ((*imageFormat->stringReadProc)(interp, masterPtr->dataObj,
- masterPtr->format, (Tk_PhotoHandle) masterPtr,
+ tempformat = masterPtr->format;
+ tempdata = masterPtr->dataString;
+ if (oldformat) {
+ if (tempformat) {
+ tempformat = (Tcl_Obj *) Tcl_GetString(tempformat);
+ }
+ tempdata = (Tcl_Obj *) Tcl_GetString(tempdata);
+ }
+ if ((*imageFormat->stringReadProc)(interp, tempdata,
+ tempformat, (Tk_PhotoHandle) masterPtr,
0, 0, imageWidth, imageHeight, 0, 0) != TCL_OK) {
return TCL_ERROR;
}
+ Tcl_ResetResult(interp);
masterPtr->flags |= IMAGE_CHANGED;
}
@@ -1814,7 +1978,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;
@@ -1955,9 +2119,8 @@ ImgPhotoGet(tkwin, masterData)
gcValues.background = (black != NULL)? black->pixel:
BlackPixelOfScreen(Tk_Screen(tkwin));
gcValues.graphics_exposures = False;
- instancePtr->gc = Tk_GetGCColor(tkwin,
- GCForeground|GCBackground|GCGraphicsExposures, &gcValues,
- white, black);
+ instancePtr->gc = Tk_GetGC(tkwin,
+ GCForeground|GCBackground|GCGraphicsExposures, &gcValues);
/*
* Set configuration options and finish the initialization of the instance.
*/
@@ -2133,8 +2296,11 @@ ImgPhotoDelete(masterData)
if (masterPtr->validRegion != NULL) {
TkDestroyRegion(masterPtr->validRegion);
}
- if (masterPtr->dataObj != NULL) {
- Tcl_DecrRefCount(masterPtr->dataObj);
+ if (masterPtr->dataString != NULL) {
+ Tcl_DecrRefCount(masterPtr->dataString);
+ }
+ if (masterPtr->format != NULL) {
+ Tcl_DecrRefCount(masterPtr->format);
}
Tk_FreeOptions(configSpecs, (char *) masterPtr, (Display *) NULL, 0);
ckfree((char *) masterPtr);
@@ -3225,20 +3391,29 @@ DisposeInstance(clientData)
*/
static int
-MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr,
- widthPtr, heightPtr)
+MatchFileFormat(interp, chan, fileName, formatObj, imageFormatPtr,
+ widthPtr, heightPtr, oldformat)
Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
Tcl_Channel chan; /* The image file, open for reading. */
char *fileName; /* The name of the image file. */
- char *formatString; /* User-specified format string, or NULL. */
+ Tcl_Obj *formatObj; /* User-specified format string, or NULL. */
Tk_PhotoImageFormat **imageFormatPtr;
/* A pointer to the photo image format
* record is returned here. */
int *widthPtr, *heightPtr; /* The dimensions of the image are
* returned here. */
+ int *oldformat;
{
int matched;
+ int useoldformat = 0;
Tk_PhotoImageFormat *formatPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ char *formatString = NULL;
+
+ if (formatObj) {
+ formatString = Tcl_GetString(formatObj);
+ }
/*
* Scan through the table of file format handlers to find
@@ -3246,11 +3421,11 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr,
*/
matched = 0;
- for (formatPtr = formatList; formatPtr != NULL;
+ for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
formatPtr = formatPtr->nextPtr) {
- if (formatString != NULL) {
- if (strncasecmp(formatString, formatPtr->name,
- strlen(formatPtr->name)) != 0) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
continue;
}
matched = 1;
@@ -3263,8 +3438,8 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr,
if (formatPtr->fileMatchProc != NULL) {
(void) Tcl_Seek(chan, 0L, SEEK_SET);
- if ((*formatPtr->fileMatchProc)(chan, fileName, formatString,
- widthPtr, heightPtr)) {
+ if ((*formatPtr->fileMatchProc)(chan, fileName, formatObj,
+ widthPtr, heightPtr, interp)) {
if (*widthPtr < 1) {
*widthPtr = 1;
}
@@ -3275,10 +3450,42 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr,
}
}
}
+ if (formatPtr == NULL) {
+ useoldformat = 1;
+ for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatString != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->fileMatchProc == NULL) {
+ Tcl_AppendResult(interp, "-file option isn't supported for ",
+ formatString, " images", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (formatPtr->fileMatchProc != NULL) {
+ (void) Tcl_Seek(chan, 0L, SEEK_SET);
+ if ((*formatPtr->fileMatchProc)(chan, fileName, (Tcl_Obj *) formatString,
+ widthPtr, heightPtr, interp)) {
+ if (*widthPtr < 1) {
+ *widthPtr = 1;
+ }
+ if (*heightPtr < 1) {
+ *heightPtr = 1;
+ }
+ break;
+ }
+ }
+ }
+ }
if (formatPtr == NULL) {
- if ((formatString != NULL) && !matched) {
- Tcl_AppendResult(interp, "image file format \"", formatString,
+ if ((formatObj != NULL) && !matched) {
+ Tcl_AppendResult(interp, "image file format \"",
+ formatString,
"\" is not supported", (char *) NULL);
} else {
Tcl_AppendResult(interp,
@@ -3289,6 +3496,7 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr,
}
*imageFormatPtr = formatPtr;
+ *oldformat = useoldformat;
(void) Tcl_Seek(chan, 0L, SEEK_SET);
return TCL_OK;
}
@@ -3316,19 +3524,28 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr,
*/
static int
-MatchStringFormat(interp, dataObj, formatString, imageFormatPtr,
- widthPtr, heightPtr)
+MatchStringFormat(interp, data, formatObj, imageFormatPtr,
+ widthPtr, heightPtr, oldformat)
Tcl_Interp *interp; /* Interpreter to use for reporting errors. */
- Tcl_Obj *dataObj; /* Object containing the image data. */
- char *formatString; /* User-specified format string, or NULL. */
+ Tcl_Obj *data; /* Object containing the image data. */
+ Tcl_Obj *formatObj; /* User-specified format string, or NULL. */
Tk_PhotoImageFormat **imageFormatPtr;
/* A pointer to the photo image format
* record is returned here. */
int *widthPtr, *heightPtr; /* The dimensions of the image are
* returned here. */
+ int *oldformat; /* returns 1 if the old image API is used */
{
int matched;
+ int useoldformat = 0;
Tk_PhotoImageFormat *formatPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ char *formatString = NULL;
+
+ if (formatObj) {
+ formatString = Tcl_GetString(formatObj);
+ }
/*
* Scan through the table of file format handlers to find
@@ -3336,11 +3553,11 @@ MatchStringFormat(interp, dataObj, formatString, imageFormatPtr,
*/
matched = 0;
- for (formatPtr = formatList; formatPtr != NULL;
+ for (formatPtr = tsdPtr->formatList; formatPtr != NULL;
formatPtr = formatPtr->nextPtr) {
- if (formatString != NULL) {
- if (strncasecmp(formatString, formatPtr->name,
- strlen(formatPtr->name)) != 0) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
continue;
}
matched = 1;
@@ -3352,15 +3569,41 @@ MatchStringFormat(interp, dataObj, formatString, imageFormatPtr,
}
if ((formatPtr->stringMatchProc != NULL)
&& (formatPtr->stringReadProc != NULL)
- && (*formatPtr->stringMatchProc)(dataObj, formatString,
- widthPtr, heightPtr)) {
+ && (*formatPtr->stringMatchProc)(data, formatObj,
+ widthPtr, heightPtr, interp)) {
break;
}
}
if (formatPtr == NULL) {
- if ((formatString != NULL) && !matched) {
- Tcl_AppendResult(interp, "image format \"", formatString,
+ useoldformat = 1;
+ for (formatPtr = tsdPtr->oldFormatList; formatPtr != NULL;
+ formatPtr = formatPtr->nextPtr) {
+ if (formatObj != NULL) {
+ if (strncasecmp(formatString,
+ formatPtr->name, strlen(formatPtr->name)) != 0) {
+ continue;
+ }
+ matched = 1;
+ if (formatPtr->stringMatchProc == NULL) {
+ Tcl_AppendResult(interp, "-data option isn't supported for ",
+ formatString, " images", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((formatPtr->stringMatchProc != NULL)
+ && (formatPtr->stringReadProc != NULL)
+ && (*formatPtr->stringMatchProc)((Tcl_Obj *) Tcl_GetString(data),
+ (Tcl_Obj *) formatString,
+ widthPtr, heightPtr, interp)) {
+ break;
+ }
+ }
+ }
+ if (formatPtr == NULL) {
+ if ((formatObj != NULL) && !matched) {
+ Tcl_AppendResult(interp, "image format \"",
+ formatString,
"\" is not supported", (char *) NULL);
} else {
Tcl_AppendResult(interp, "couldn't recognize image data",
@@ -3370,6 +3613,7 @@ MatchStringFormat(interp, dataObj, formatString, imageFormatPtr,
}
*imageFormatPtr = formatPtr;
+ *oldformat = useoldformat;
return TCL_OK;
}
@@ -3482,13 +3726,8 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
- alphaOffset = 0;
- while ((alphaOffset != blockPtr->offset[0]) &&
- (alphaOffset != blockPtr->offset[1]) &&
- (alphaOffset != blockPtr->offset[2])) {
- alphaOffset++;
- }
- if (alphaOffset >= blockPtr->pixelSize) {
+ alphaOffset = blockPtr->offset[3];
+ if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) {
alphaOffset = 0;
} else {
alphaOffset -= blockPtr->offset[0];
@@ -3505,7 +3744,13 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4;
pitch = masterPtr->width * 4;
- if ((blockPtr->pixelSize == 4) && (greenOffset == 1) && (blueOffset == 2)
+ /*
+ * This test is probably too restrictive. We should also be able to
+ * do a memcpy if pixelSize == 3 and alphaOffset == 0. Maybe other cases
+ * too.
+ */
+ if ((blockPtr->pixelSize == 4)
+ && (greenOffset == 1) && (blueOffset == 2) && (alphaOffset == 3)
&& (width <= blockPtr->width) && (height <= blockPtr->height)
&& ((height == 1) || ((x == 0) && (width == masterPtr->width)
&& (blockPtr->pitch == pitch)))) {
@@ -3524,11 +3769,24 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
wLeft -= wCopy;
srcPtr = srcLinePtr;
for (; wCopy > 0; --wCopy) {
+ if (!destPtr[3]) {
+ destPtr[0] = destPtr[1] = destPtr[2] = 0xd9;
+ }
+ if (!alphaOffset || (srcPtr[alphaOffset] == 255)) {
*destPtr++ = srcPtr[0];
*destPtr++ = srcPtr[greenOffset];
*destPtr++ = srcPtr[blueOffset];
- *destPtr++ = alphaOffset ? srcPtr[alphaOffset] : 255;
- srcPtr += blockPtr->pixelSize;
+ *destPtr++ = 255;
+ } else {
+ if (srcPtr[alphaOffset]) {
+ destPtr[0] += (srcPtr[0] - destPtr[0]) * srcPtr[alphaOffset] / 255;
+ destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * srcPtr[alphaOffset] / 255;
+ destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * srcPtr[alphaOffset] / 255;
+ destPtr[3] += (255 - destPtr[3]) * srcPtr[alphaOffset] / 255;
+ }
+ destPtr+=4;
+ }
+ srcPtr += blockPtr->pixelSize;
}
}
srcLinePtr += blockPtr->pitch;
@@ -3541,18 +3799,67 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
* Add this new block to the region which specifies which data is valid.
*/
+ if (alphaOffset) {
+ int x1, y1, end;
+
+ /*
+ * This block is grossly inefficient. For each row in the image, it
+ * finds each continguous string of transparent pixels, then marks those
+ * areas as invalid in the validRegion mask. This makes drawing very
+ * efficient, because of the way we use X: we just say, here's your
+ * mask, and here's your data. We need not worry about the current
+ * background color, etc. But this costs us a lot on the image setup.
+ * Still, image setup only happens once, whereas the drawing happens
+ * many times, so this might be the best way to go.
+ *
+ * An alternative might be to not set up this mask, and instead, at
+ * drawing time, for each transparent pixel, set its color to the
+ * color of the background behind that pixel. This is what I suspect
+ * most of programs do. However, they don't have to deal with the canvas,
+ * which could have many different background colors. Determining the
+ * correct bg color for a given pixel might be expensive.
+ */
+
+ destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4 + 3;
+ for (y1 = 0; y1 < height; y1++) {
+ x1 = 0;
+ destPtr = destLinePtr;
+ while (x1 < width) {
+ /* search for first non-transparent pixel */
+ while ((x1 < width) && !*destPtr) {
+ x1++; destPtr += 4;
+ }
+ end = x1;
+ /* search for first transparent pixel */
+ while ((end < width) && *destPtr) {
+ end++; destPtr += 4;
+ }
+ if (end > x1) {
+ rect.x = x + x1;
+ rect.y = y + y1;
+ rect.width = end - x1;
+ rect.height = 1;
+ TkUnionRectWithRegion(&rect, masterPtr->validRegion,
+ masterPtr->validRegion);
+ }
+ x1 = end;
+ }
+ destLinePtr += masterPtr->width * 4;
+ }
+ } else {
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
TkUnionRectWithRegion(&rect, masterPtr->validRegion,
masterPtr->validRegion);
+ }
/*
* Update each instance.
*/
- Dither(masterPtr, x, y, width, height);
+ Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height);
/*
* Tell the core image code that this image has changed.
@@ -3656,13 +3963,8 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
- alphaOffset = 0;
- while ((alphaOffset != blockPtr->offset[0]) &&
- (alphaOffset != blockPtr->offset[1]) &&
- (alphaOffset != blockPtr->offset[2])) {
- alphaOffset++;
- }
- if (alphaOffset >= blockPtr->pixelSize) {
+ alphaOffset = blockPtr->offset[3];
+ if ((alphaOffset >= blockPtr->pixelSize) || (alphaOffset < 0)) {
alphaOffset = 0;
} else {
alphaOffset -= blockPtr->offset[0];
@@ -3718,10 +4020,23 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
srcPtr = srcLinePtr;
for (; wCopy > 0; wCopy -= zoomX) {
for (xRepeat = MIN(wCopy, zoomX); xRepeat > 0; xRepeat--) {
+ if (!destPtr[3]) {
+ destPtr[0] = destPtr[1] = destPtr[2] = 0xd9;
+ }
+ if (!alphaOffset || (srcPtr[alphaOffset] == 255)) {
*destPtr++ = srcPtr[0];
*destPtr++ = srcPtr[greenOffset];
*destPtr++ = srcPtr[blueOffset];
- *destPtr++ = alphaOffset ? srcPtr[alphaOffset] : 255;
+ *destPtr++ = 255;
+ } else {
+ if (srcPtr[alphaOffset]) {
+ destPtr[0] += (srcPtr[0] - destPtr[0]) * srcPtr[alphaOffset] / 255;
+ destPtr[1] += (srcPtr[greenOffset] - destPtr[1]) * srcPtr[alphaOffset] / 255;
+ destPtr[2] += (srcPtr[blueOffset] - destPtr[2]) * srcPtr[alphaOffset] / 255;
+ destPtr[3] += (255 - destPtr[3]) * srcPtr[alphaOffset] / 255;
+ }
+ destPtr+=4;
+ }
}
srcPtr += blockXSkip;
}
@@ -3739,18 +4054,49 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
* Add this new block to the region that specifies which data is valid.
*/
+ if (alphaOffset) {
+ int x1, y1, end;
+
+ destLinePtr = masterPtr->pix24 + (y * masterPtr->width + x) * 4 + 3;
+ for (y1 = 0; y1 < height; y1++) {
+ x1 = 0;
+ destPtr = destLinePtr;
+ while (x1 < width) {
+ /* search for first non-transparent pixel */
+ while ((x1 < width) && !*destPtr) {
+ x1++; destPtr += 4;
+ }
+ end = x1;
+ /* search for first transparent pixel */
+ while ((end < width) && *destPtr) {
+ end++; destPtr += 4;
+ }
+ if (end > x1) {
+ rect.x = x + x1;
+ rect.y = y + y1;
+ rect.width = end - x1;
+ rect.height = 1;
+ TkUnionRectWithRegion(&rect, masterPtr->validRegion,
+ masterPtr->validRegion);
+ }
+ x1 = end;
+ }
+ destLinePtr += masterPtr->width * 4;
+ }
+ } else {
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
TkUnionRectWithRegion(&rect, masterPtr->validRegion,
masterPtr->validRegion);
+ }
/*
* Update each instance.
*/
- Dither(masterPtr, x, y, width, height);
+ Tk_DitherPhoto((Tk_PhotoHandle)masterPtr, x, y, width, height);
/*
* Tell the core image code that this image has changed.
@@ -3763,7 +4109,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
/*
*----------------------------------------------------------------------
*
- * Dither --
+ * Tk_DitherPhoto --
*
* This procedure is called to update an area of each instance's
* pixmap by dithering the corresponding area of the image master.
@@ -3779,14 +4125,15 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
*----------------------------------------------------------------------
*/
-static void
-Dither(masterPtr, x, y, width, height)
- PhotoMaster *masterPtr; /* Image master whose instances are
+void
+Tk_DitherPhoto(photo, x, y, width, height)
+ Tk_PhotoHandle photo; /* Image master whose instances are
* to be updated. */
int x, y; /* Coordinates of the top-left pixel
* in the area to be dithered. */
int width, height; /* Dimensions of the area to be dithered. */
{
+ PhotoMaster *masterPtr = (PhotoMaster *) photo;
PhotoInstance *instancePtr;
if ((width <= 0) || (height <= 0)) {
@@ -4431,7 +4778,8 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr)
if ((greenOffset || blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {
newPixelSize += 2;
}
- data = ckalloc(newPixelSize * blockPtr->width * blockPtr->height);
+ data = ckalloc((unsigned int) (newPixelSize *
+ blockPtr->width * blockPtr->height));
srcPtr = blockPtr->pixelPtr + blockPtr->offset[0];
destPtr = (unsigned char *) data;
if (!greenOffset && !blueOffset) {
@@ -4546,22 +4894,23 @@ ImgGetPhoto(masterPtr, blockPtr, optPtr)
*/
static int
-ImgStringWrite (interp, dataPtr, formatString, blockPtr)
+ImgStringWrite(interp, formatString, blockPtr)
Tcl_Interp *interp;
- Tcl_DString *dataPtr;
- char *formatString;
+ Tcl_Obj *formatString;
Tk_PhotoImageBlock *blockPtr;
{
int row,col;
char *line, *linePtr;
unsigned char *pixelPtr;
int greenOffset, blueOffset;
+ Tcl_DString data;
greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
+ Tcl_DStringInit(&data);
if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
- line = (char *) ckalloc(8 * blockPtr->width + 2);
+ line = (char *) ckalloc((unsigned int) ((8 * blockPtr->width) + 2));
for (row=0; row<blockPtr->height; row++) {
pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0] +
row * blockPtr->pitch;
@@ -4572,10 +4921,11 @@ ImgStringWrite (interp, dataPtr, formatString, blockPtr)
pixelPtr += blockPtr->pixelSize;
linePtr += 8;
}
- Tcl_DStringAppendElement(dataPtr, line+1);
+ Tcl_DStringAppendElement(&data, line+1);
}
ckfree (line);
}
+ Tcl_DStringResult(interp, &data);
return TCL_OK;
}
@@ -4618,5 +4968,189 @@ Tk_PhotoGetImage(handle, blockPtr)
blockPtr->offset[0] = 0;
blockPtr->offset[1] = 1;
blockPtr->offset[2] = 2;
+ blockPtr->offset[3] = 3;
return 1;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PhotoOptionFind --
+ *
+ * Finds a specific Photo option.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * After commands are removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+typedef struct OptionAssocData {
+ struct OptionAssocData *nextPtr; /* pointer to next OptionAssocData */
+ Tcl_ObjCmdProc *command; /* command associated with this
+ * option */
+ char name[1]; /* name of option (remaining chars) */
+} OptionAssocData;
+
+static Tcl_ObjCmdProc *
+PhotoOptionFind(interp, obj)
+ Tcl_Interp *interp; /* Interpreter that is being deleted. */
+ Tcl_Obj *obj; /* Name of option to be found. */
+{
+ size_t length;
+ char *name = Tcl_GetStringFromObj(obj, (int *) &length);
+ OptionAssocData *list;
+ char *prevname = NULL;
+ Tcl_ObjCmdProc *proc = (Tcl_ObjCmdProc *) NULL;
+ list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption",
+ (Tcl_InterpDeleteProc **) NULL);
+ while (list != (OptionAssocData *) NULL) {
+ if (strncmp(name, list->name, length) == 0) {
+ if (proc != (Tcl_ObjCmdProc *) NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "ambiguous option \"", name,
+ "\": must be ", prevname, (char *) NULL);
+ while (list->nextPtr != (OptionAssocData *) NULL) {
+ Tcl_AppendResult(interp, prevname, ", ",(char *) NULL);
+ list = list->nextPtr;
+ prevname = list->name;
+ }
+ Tcl_AppendResult(interp, ", or", prevname, (char *) NULL);
+ return (Tcl_ObjCmdProc *) NULL;
+ }
+ proc = list->command;
+ prevname = list->name;
+ }
+ list = list->nextPtr;
+ }
+ if (proc != (Tcl_ObjCmdProc *) NULL) {
+ Tcl_ResetResult(interp);
+ }
+ return proc;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * PhotoOptionCleanupProc --
+ *
+ * This procedure is invoked whenever an interpreter is deleted
+ * to cleanup the AssocData for "photoVisitor".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Photo Visitor options are removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+PhotoOptionCleanupProc(clientData, interp)
+ ClientData clientData; /* Points to "photoVisitor" AssocData
+ * for the interpreter. */
+ Tcl_Interp *interp; /* Interpreter that is being deleted. */
+{
+ OptionAssocData *list = (OptionAssocData *) clientData;
+ OptionAssocData *ptr;
+
+ while (list != NULL) {
+ list = (ptr = list)->nextPtr;
+ ckfree((char *) ptr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreatePhotoOption --
+ *
+ * This procedure may be invoked to add a new kind of photo
+ * option to the core photo command supported by Tk.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * From now on, the new option will be useable by the
+ * photo command.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+Tk_CreatePhotoOption(interp, name, proc)
+ Tcl_Interp *interp; /* interpreter */
+ CONST char *name; /* option name */
+ Tcl_ObjCmdProc *proc; /* proc to execute command */
+{
+ OptionAssocData *typePtr2, *prevPtr, *ptr;
+ OptionAssocData *list;
+
+ list = (OptionAssocData *) Tcl_GetAssocData(interp, "photoOption",
+ (Tcl_InterpDeleteProc **) NULL);
+
+ /*
+ * If there's already a photo option with the given name, remove it.
+ */
+
+ for (typePtr2 = list, prevPtr = NULL; typePtr2 != NULL;
+ prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
+ if (strcmp(typePtr2->name, name) == 0) {
+ if (prevPtr == NULL) {
+ list = typePtr2->nextPtr;
+ } else {
+ prevPtr->nextPtr = typePtr2->nextPtr;
+ }
+ ckfree((char *) typePtr2);
+ break;
+ }
+ }
+ ptr = (OptionAssocData *) ckalloc(sizeof(OptionAssocData) + strlen(name));
+ strcpy(&(ptr->name[0]), name);
+ ptr->command = proc;
+ ptr->nextPtr = list;
+ Tcl_SetAssocData(interp, "photoOption", PhotoOptionCleanupProc,
+ (ClientData) ptr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkPostscriptPhoto --
+ *
+ * This procedure is called to output the contents of a
+ * photo image in Postscript by calling the Tk_PostscriptPhoto
+ * function.
+ *
+ * Results:
+ * Returns a standard Tcl return value.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+static int
+ImgPhotoPostscript(clientData, interp, tkwin, psInfo,
+ x, y, width, height, prepass)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+ Tk_PostscriptInfo psInfo; /* postscript info */
+ int x, y; /* First pixel to output */
+ int width, height; /* Width and height of area */
+ int prepass;
+{
+ Tk_PhotoImageBlock block;
+
+ Tk_PhotoGetImage((Tk_PhotoHandle) clientData, &block);
+ block.pixelPtr += y * block.pitch + x * block.pixelSize;
+
+ return Tk_PostscriptPhoto(interp, &block, psInfo, width, height);
+}
+
diff --git a/tk/generic/tkImgUtil.c b/tk/generic/tkImgUtil.c
index b865c9ca18f..810611ddded 100644
--- a/tk/generic/tkImgUtil.c
+++ b/tk/generic/tkImgUtil.c
@@ -76,3 +76,4 @@ TkAlignImageData(image, alignment, bitOrder)
}
return data;
}
+
diff --git a/tk/generic/tkInitScript.h b/tk/generic/tkInitScript.h
index 959ebea448d..0ff30077918 100644
--- a/tk/generic/tkInitScript.h
+++ b/tk/generic/tkInitScript.h
@@ -12,6 +12,8 @@
* RCS: @(#) $Id$
*/
+
+
/*
* In order to find tk.tcl during initialization, the following script
* is invoked by Tk_Init(). It looks in several different directories:
@@ -46,11 +48,12 @@
*/
static char initScript[] = "if {[info proc tkInit]==\"\"} {\n\
- proc tkInit {} {\n\
- global tk_library tk_version tk_patchLevel\n\
- rename tkInit {}\n\
- tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\
- }\n\
+ proc tkInit {} {\n\
+ global tk_library tk_version tk_patchLevel\n\
+ rename tkInit {}\n\
+ tcl_findLibrary tk $tk_version $tk_patchLevel tk.tcl TK_LIBRARY tk_library\n\
+}\n\
}\n\
tkInit";
+
diff --git a/tk/generic/tkInt.decls b/tk/generic/tkInt.decls
new file mode 100644
index 00000000000..b4d3d470477
--- /dev/null
+++ b/tk/generic/tkInt.decls
@@ -0,0 +1,1932 @@
+ # tkInt.decls --
+#
+# This file contains the declarations for all unsupported
+# functions that are exported by the Tk library. This file
+# is used to generate the tkIntDecls.h, tkIntPlatDecls.h,
+# tkIntStub.c, and tkPlatStub.c files.
+#
+# Copyright (c) 1998-1999 by Scriptics Corporation.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+# RCS: @(#) $Id$
+
+library tk
+
+# Define the unsupported generic interfaces.
+
+interface tkInt
+
+# Declare each of the functions in the unsupported internal Tcl
+# interface. These interfaces are allowed to changed between versions.
+# Use at your own risk. Note that the position of functions should not
+# be changed between versions to avoid gratuitous incompatibilities.
+
+declare 0 generic {
+ TkWindow * TkAllocWindow (TkDisplay *dispPtr, int screenNum, \
+ TkWindow *parentPtr)
+}
+
+declare 1 generic {
+ void TkBezierPoints (double control[], int numSteps, double *coordPtr)
+}
+
+declare 2 generic {
+ void TkBezierScreenPoints (Tk_Canvas canvas, double control[], \
+ int numSteps, XPoint *xPointPtr)
+}
+
+declare 3 generic {
+ void TkBindDeadWindow (TkWindow *winPtr)
+}
+
+declare 4 generic {
+ void TkBindEventProc (TkWindow *winPtr, XEvent *eventPtr)
+}
+
+declare 5 generic {
+ void TkBindFree (TkMainInfo *mainPtr)
+}
+
+declare 6 generic {
+ void TkBindInit (TkMainInfo *mainPtr)
+}
+
+declare 7 generic {
+ void TkChangeEventWindow (XEvent *eventPtr, TkWindow *winPtr)
+}
+
+declare 8 generic {
+ int TkClipInit (Tcl_Interp *interp, TkDisplay *dispPtr)
+}
+
+declare 9 generic {
+ void TkComputeAnchor (Tk_Anchor anchor, Tk_Window tkwin, \
+ int padX, int padY, int innerWidth, int innerHeight, \
+ int *xPtr, int *yPtr)
+}
+
+declare 10 generic {
+ int TkCopyAndGlobalEval (Tcl_Interp *interp, char *script)
+}
+
+declare 11 generic {
+ unsigned long TkCreateBindingProcedure (Tcl_Interp *interp, \
+ Tk_BindingTable bindingTable, \
+ ClientData object, char *eventString, \
+ TkBindEvalProc *evalProc, TkBindFreeProc *freeProc, \
+ ClientData clientData)
+}
+
+declare 12 generic {
+ TkCursor * TkCreateCursorFromData (Tk_Window tkwin, \
+ char *source, char *mask, int width, int height, \
+ int xHot, int yHot, XColor fg, XColor bg)
+}
+
+declare 13 generic {
+ int TkCreateFrame (ClientData clientData, \
+ Tcl_Interp *interp, int argc, char **argv, \
+ int toplevel, char *appName)
+}
+
+declare 14 generic {
+ Tk_Window TkCreateMainWindow (Tcl_Interp *interp, \
+ char *screenName, char *baseName)
+}
+
+declare 15 generic {
+ Time TkCurrentTime (TkDisplay *dispPtr)
+}
+
+declare 16 generic {
+ void TkDeleteAllImages (TkMainInfo *mainPtr)
+}
+
+declare 17 generic {
+ void TkDoConfigureNotify (TkWindow *winPtr)
+}
+
+declare 18 generic {
+ void TkDrawInsetFocusHighlight (Tk_Window tkwin, GC gc, int width, \
+ Drawable drawable, int padding)
+}
+
+declare 19 generic {
+ void TkEventDeadWindow (TkWindow *winPtr)
+}
+
+declare 20 generic {
+ void TkFillPolygon (Tk_Canvas canvas, \
+ double *coordPtr, int numPoints, Display *display, \
+ Drawable drawable, GC gc, GC outlineGC)
+}
+
+declare 21 generic {
+ int TkFindStateNum (Tcl_Interp *interp, \
+ CONST char *option, CONST TkStateMap *mapPtr, \
+ CONST char *strKey)
+}
+
+declare 22 generic {
+ char * TkFindStateString (CONST TkStateMap *mapPtr, int numKey)
+}
+
+declare 23 generic {
+ void TkFocusDeadWindow (TkWindow *winPtr)
+}
+
+declare 24 generic {
+ int TkFocusFilterEvent (TkWindow *winPtr, XEvent *eventPtr)
+}
+
+declare 25 generic {
+ TkWindow * TkFocusKeyEvent (TkWindow *winPtr, XEvent *eventPtr)
+}
+
+declare 26 generic {
+ void TkFontPkgInit (TkMainInfo *mainPtr)
+}
+
+declare 27 generic {
+ void TkFontPkgFree (TkMainInfo *mainPtr)
+}
+
+declare 28 generic {
+ void TkFreeBindingTags (TkWindow *winPtr)
+}
+
+# Name change only, TkFreeCursor in Tcl 8.0.x now TkpFreeCursor
+declare 29 generic {
+ void TkpFreeCursor (TkCursor *cursorPtr)
+}
+
+declare 30 generic {
+ char * TkGetBitmapData (Tcl_Interp *interp, \
+ char *string, char *fileName, int *widthPtr, \
+ int *heightPtr, int *hotXPtr, int *hotYPtr)
+}
+
+declare 31 generic {
+ void TkGetButtPoints (double p1[], double p2[], \
+ double width, int project, double m1[], double m2[])
+}
+
+declare 32 generic {
+ TkCursor * TkGetCursorByName (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tk_Uid string)
+}
+
+declare 33 generic {
+ char * TkGetDefaultScreenName (Tcl_Interp *interp, char *screenName)
+}
+
+declare 34 generic {
+ TkDisplay * TkGetDisplay (Display *display)
+}
+
+declare 35 generic {
+ int TkGetDisplayOf (Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], \
+ Tk_Window *tkwinPtr)
+}
+
+declare 36 generic {
+ TkWindow * TkGetFocusWin (TkWindow *winPtr)
+}
+
+declare 37 generic {
+ int TkGetInterpNames (Tcl_Interp *interp, Tk_Window tkwin)
+}
+
+declare 38 generic {
+ int TkGetMiterPoints (double p1[], double p2[], double p3[], \
+ double width, double m1[],double m2[])
+}
+
+declare 39 generic {
+ void TkGetPointerCoords (Tk_Window tkwin, int *xPtr, int *yPtr)
+}
+
+declare 40 generic {
+ void TkGetServerInfo (Tcl_Interp *interp, Tk_Window tkwin)
+}
+
+declare 41 generic {
+ void TkGrabDeadWindow (TkWindow *winPtr)
+}
+
+declare 42 generic {
+ int TkGrabState (TkWindow *winPtr)
+}
+
+declare 43 generic {
+ void TkIncludePoint (Tk_Item *itemPtr, double *pointPtr)
+}
+
+declare 44 generic {
+ void TkInOutEvents (XEvent *eventPtr, TkWindow *sourcePtr, \
+ TkWindow *destPtr, int leaveType, int enterType, \
+ Tcl_QueuePosition position)
+}
+
+declare 45 generic {
+ void TkInstallFrameMenu (Tk_Window tkwin)
+}
+
+declare 46 generic {
+ char * TkKeysymToString (KeySym keysym)
+}
+
+declare 47 generic {
+ int TkLineToArea (double end1Ptr[], double end2Ptr[], double rectPtr[])
+}
+
+declare 48 generic {
+ double TkLineToPoint (double end1Ptr[], \
+ double end2Ptr[], double pointPtr[])
+}
+
+declare 49 generic {
+ int TkMakeBezierCurve (Tk_Canvas canvas, \
+ double *pointPtr, int numPoints, int numSteps, \
+ XPoint xPoints[], double dblPoints[])
+}
+
+declare 50 generic {
+ void TkMakeBezierPostscript (Tcl_Interp *interp, \
+ Tk_Canvas canvas, double *pointPtr, int numPoints)
+}
+
+declare 51 generic {
+ void TkOptionClassChanged (TkWindow *winPtr)
+}
+
+declare 52 generic {
+ void TkOptionDeadWindow (TkWindow *winPtr)
+}
+
+declare 53 generic {
+ int TkOvalToArea (double *ovalPtr, double *rectPtr)
+}
+
+declare 54 generic {
+ double TkOvalToPoint (double ovalPtr[], \
+ double width, int filled, double pointPtr[])
+}
+
+declare 55 generic {
+ int TkpChangeFocus (TkWindow *winPtr, int force)
+}
+
+declare 56 generic {
+ void TkpCloseDisplay (TkDisplay *dispPtr)
+}
+
+declare 57 generic {
+ void TkpClaimFocus (TkWindow *topLevelPtr, int force)
+}
+
+declare 58 generic {
+ void TkpDisplayWarning (char *msg, char *title)
+}
+
+declare 59 generic {
+ void TkpGetAppName (Tcl_Interp *interp, Tcl_DString *name)
+}
+
+declare 60 generic {
+ TkWindow * TkpGetOtherWindow (TkWindow *winPtr)
+}
+
+declare 61 generic {
+ TkWindow * TkpGetWrapperWindow (TkWindow *winPtr)
+}
+
+declare 62 generic {
+ int TkpInit (Tcl_Interp *interp)
+}
+
+declare 63 generic {
+ void TkpInitializeMenuBindings (Tcl_Interp *interp, \
+ Tk_BindingTable bindingTable)
+}
+
+declare 64 generic {
+ void TkpMakeContainer (Tk_Window tkwin)
+}
+
+declare 65 generic {
+ void TkpMakeMenuWindow (Tk_Window tkwin, int transient)
+}
+
+declare 66 generic {
+ Window TkpMakeWindow (TkWindow *winPtr, Window parent)
+}
+
+declare 67 generic {
+ void TkpMenuNotifyToplevelCreate (Tcl_Interp *interp1, char *menuName)
+}
+
+declare 68 generic {
+ TkDisplay * TkpOpenDisplay (char *display_name)
+}
+
+declare 69 generic {
+ int TkPointerEvent (XEvent *eventPtr, TkWindow *winPtr)
+}
+
+declare 70 generic {
+ int TkPolygonToArea (double *polyPtr, int numPoints, double *rectPtr)
+}
+
+declare 71 generic {
+ double TkPolygonToPoint (double *polyPtr, int numPoints, double *pointPtr)
+}
+
+declare 72 generic {
+ int TkPositionInTree (TkWindow *winPtr, TkWindow *treePtr)
+}
+
+declare 73 generic {
+ void TkpRedirectKeyEvent (TkWindow *winPtr, XEvent *eventPtr)
+}
+
+declare 74 generic {
+ void TkpSetMainMenubar (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *menuName)
+}
+
+declare 75 generic {
+ int TkpUseWindow (Tcl_Interp *interp, Tk_Window tkwin, char *string)
+}
+
+declare 76 generic {
+ int TkpWindowWasRecentlyDeleted (Window win, TkDisplay *dispPtr)
+}
+
+declare 77 generic {
+ void TkQueueEventForAllChildren (TkWindow *winPtr, XEvent *eventPtr)
+}
+
+declare 78 generic {
+ int TkReadBitmapFile (Display* display, Drawable d, CONST char* filename, \
+ unsigned int* width_return, unsigned int* height_return, \
+ Pixmap* bitmap_return, int* x_hot_return, int* y_hot_return)
+}
+
+declare 79 generic {
+ int TkScrollWindow (Tk_Window tkwin, GC gc, \
+ int x, int y, int width, int height, int dx, \
+ int dy, TkRegion damageRgn)
+}
+
+declare 80 generic {
+ void TkSelDeadWindow (TkWindow *winPtr)
+}
+
+declare 81 generic {
+ void TkSelEventProc (Tk_Window tkwin, XEvent *eventPtr)
+}
+
+declare 82 generic {
+ void TkSelInit (Tk_Window tkwin)
+}
+
+declare 83 generic {
+ void TkSelPropProc (XEvent *eventPtr)
+}
+
+declare 84 generic {
+ void TkSetClassProcs (Tk_Window tkwin, \
+ TkClassProcs *procs, ClientData instanceData)
+}
+
+declare 85 generic {
+ void TkSetWindowMenuBar (Tcl_Interp *interp, \
+ Tk_Window tkwin, char *oldMenuName, char *menuName)
+}
+
+declare 86 generic {
+ KeySym TkStringToKeysym (char *name)
+}
+
+declare 87 generic {
+ int TkThickPolyLineToArea (double *coordPtr, \
+ int numPoints, double width, int capStyle, \
+ int joinStyle, double *rectPtr)
+}
+
+declare 88 generic {
+ void TkWmAddToColormapWindows (TkWindow *winPtr)
+}
+
+declare 89 generic {
+ void TkWmDeadWindow (TkWindow *winPtr)
+}
+
+declare 90 generic {
+ TkWindow * TkWmFocusToplevel (TkWindow *winPtr)
+}
+
+declare 91 generic {
+ void TkWmMapWindow (TkWindow *winPtr)
+}
+
+declare 92 generic {
+ void TkWmNewWindow (TkWindow *winPtr)
+}
+
+declare 93 generic {
+ void TkWmProtocolEventProc (TkWindow *winPtr, XEvent *evenvPtr)
+}
+
+declare 94 generic {
+ void TkWmRemoveFromColormapWindows (TkWindow *winPtr)
+}
+
+declare 95 generic {
+ void TkWmRestackToplevel (TkWindow *winPtr, int aboveBelow, \
+ TkWindow *otherPtr)
+}
+
+declare 96 generic {
+ void TkWmSetClass (TkWindow *winPtr)
+}
+
+declare 97 generic {
+ void TkWmUnmapWindow (TkWindow *winPtr)
+}
+
+# new for 8.1
+
+declare 98 generic {
+ Tcl_Obj * TkDebugBitmap ( Tk_Window tkwin, char *name)
+}
+
+declare 99 generic {
+ Tcl_Obj * TkDebugBorder ( Tk_Window tkwin, char *name)
+}
+
+declare 100 generic {
+ Tcl_Obj * TkDebugCursor ( Tk_Window tkwin, char *name)
+}
+
+declare 101 generic {
+ Tcl_Obj * TkDebugColor ( Tk_Window tkwin, char *name)
+}
+
+declare 102 generic {
+ Tcl_Obj * TkDebugConfig (Tcl_Interp *interp, Tk_OptionTable table)
+}
+
+declare 103 generic {
+ Tcl_Obj * TkDebugFont ( Tk_Window tkwin, char *name)
+}
+
+declare 104 generic {
+ int TkFindStateNumObj (Tcl_Interp *interp, \
+ Tcl_Obj *optionPtr, CONST TkStateMap *mapPtr, \
+ Tcl_Obj *keyPtr)
+}
+
+declare 105 generic {
+ Tcl_HashTable * TkGetBitmapPredefTable (void)
+}
+
+declare 106 generic {
+ TkDisplay * TkGetDisplayList (void)
+}
+
+declare 107 generic {
+ TkMainInfo * TkGetMainInfoList (void)
+}
+
+declare 108 generic {
+ int TkGetWindowFromObj (Tcl_Interp *interp, \
+ Tk_Window tkwin, Tcl_Obj *objPtr, \
+ Tk_Window *windowPtr)
+}
+
+declare 109 generic {
+ char * TkpGetString (TkWindow *winPtr, \
+ XEvent *eventPtr, Tcl_DString *dsPtr)
+}
+
+declare 110 generic {
+ void TkpGetSubFonts (Tcl_Interp *interp, Tk_Font tkfont)
+}
+
+declare 111 generic {
+ Tcl_Obj * TkpGetSystemDefault (Tk_Window tkwin, \
+ char *dbName, char *className)
+}
+
+declare 112 generic {
+ void TkpMenuThreadInit (void)
+}
+
+declare 113 win {
+ void TkClipBox (TkRegion rgn, XRectangle* rect_return)
+}
+
+declare 113 mac {
+ void TkClipBox (TkRegion rgn, XRectangle* rect_return)
+}
+
+declare 114 win {
+ TkRegion TkCreateRegion (void)
+}
+
+declare 114 mac {
+ TkRegion TkCreateRegion (void)
+}
+
+declare 115 win {
+ void TkDestroyRegion (TkRegion rgn)
+}
+
+declare 115 mac {
+ void TkDestroyRegion (TkRegion rgn)
+}
+
+declare 116 win {
+ void TkIntersectRegion (TkRegion sra, TkRegion srcb, TkRegion dr_return)
+}
+
+declare 116 mac {
+ void TkIntersectRegion (TkRegion sra, TkRegion srcb, TkRegion dr_return)
+}
+
+declare 117 win {
+ int TkRectInRegion (TkRegion rgn, int x, int y, unsigned int width, \
+ unsigned int height)
+}
+
+declare 117 mac {
+ int TkRectInRegion (TkRegion rgn, int x, int y, unsigned int width, \
+ unsigned int height)
+}
+
+declare 118 win {
+ void TkSetRegion (Display* display, GC gc, TkRegion rgn)
+}
+
+declare 118 mac {
+ void TkSetRegion (Display* display, GC gc, TkRegion rgn)
+}
+
+declare 119 win {
+ void TkUnionRectWithRegion (XRectangle* rect, \
+ TkRegion src, TkRegion dr_return)
+}
+
+declare 119 mac {
+ void TkUnionRectWithRegion (XRectangle* rect, \
+ TkRegion src, TkRegion dr_return)
+}
+
+declare 130 mac {
+ Window TkGetTransientMaster (TkWindow *winPtr)
+}
+
+declare 131 mac {
+ int TkGenerateButtonEvent (int x, int y, \
+ Window window, unsigned int state)
+}
+
+declare 133 mac {
+ void TkGenWMDestroyEvent (Tk_Window tkwin)
+}
+
+declare 134 mac {
+ void TkGenWMConfigureEvent (Tk_Window tkwin, int x, int y, \
+ int width, int height, int flags)
+}
+
+declare 135 generic {
+ void TkpDrawHighlightBorder (Tk_Window tkwin, GC fgGC, GC bgGC, \
+ int highlightWidth, Drawable drawable)
+}
+
+declare 136 generic {
+ void TkSetFocusWin (TkWindow *winPtr, int force)
+}
+
+declare 137 generic {
+ void TkpSetKeycodeAndState (Tk_Window tkwin, KeySym keySym, \
+ XEvent *eventPtr)
+}
+
+declare 138 generic {
+ KeySym TkpGetKeySym (TkDisplay *dispPtr, XEvent *eventPtr)
+}
+
+declare 139 generic {
+ void TkpInitKeymapInfo (TkDisplay *dispPtr)
+}
+
+##############################################################################
+
+# Define the platform specific internal Tcl interface. These functions are
+# only available on the designated platform.
+
+interface tkIntPlat
+
+#########################
+# Unix specific functions
+
+declare 0 unix {
+ void TkCreateXEventSource (void)
+}
+
+declare 1 unix {
+ void TkFreeWindowId (TkDisplay *dispPtr, Window w)
+}
+
+declare 2 unix {
+ void TkInitXId (TkDisplay *dispPtr)
+}
+
+declare 3 unix {
+ int TkpCmapStressed (Tk_Window tkwin, Colormap colormap)
+}
+
+declare 4 unix {
+ void TkpSync (Display *display)
+}
+
+declare 5 unix {
+ Window TkUnixContainerId (TkWindow *winPtr)
+}
+
+declare 6 unix {
+ int TkUnixDoOneXEvent (Tcl_Time *timePtr)
+}
+
+declare 7 unix {
+ void TkUnixSetMenubar (Tk_Window tkwin, Tk_Window menubar)
+}
+
+
+
+############################
+# Windows specific functions
+
+declare 0 win {
+ char * TkAlignImageData (XImage *image, int alignment, int bitOrder)
+}
+
+declare 2 win {
+ void TkGenerateActivateEvents (TkWindow *winPtr, int active)
+}
+
+declare 3 win {
+ unsigned long TkpGetMS (void)
+}
+
+declare 4 win {
+ void TkPointerDeadWindow (TkWindow *winPtr)
+}
+
+declare 5 win {
+ void TkpPrintWindowId (char *buf, Window window)
+}
+
+declare 6 win {
+ int TkpScanWindowId (Tcl_Interp *interp, char *string, int *idPtr)
+}
+
+declare 7 win {
+ void TkpSetCapture (TkWindow *winPtr)
+}
+
+declare 8 win {
+ void TkpSetCursor (TkpCursor cursor)
+}
+
+declare 9 win {
+ void TkpWmSetState (TkWindow *winPtr, int state)
+}
+
+declare 10 win {
+ void TkSetPixmapColormap (Pixmap pixmap, Colormap colormap)
+}
+
+declare 11 win {
+ void TkWinCancelMouseTimer (void)
+}
+
+declare 12 win {
+ void TkWinClipboardRender (TkDisplay *dispPtr, UINT format)
+}
+
+declare 13 win {
+ LRESULT TkWinEmbeddedEventProc (HWND hwnd, UINT message, \
+ WPARAM wParam, LPARAM lParam)
+}
+
+declare 14 win {
+ void TkWinFillRect (HDC dc, int x, int y, int width, int height, \
+ int pixel)
+}
+
+declare 15 win {
+ COLORREF TkWinGetBorderPixels (Tk_Window tkwin, Tk_3DBorder border, \
+ int which)
+}
+
+declare 16 win {
+ HDC TkWinGetDrawableDC (Display *display, Drawable d, TkWinDCState* state)
+}
+
+declare 17 win {
+ int TkWinGetModifierState (void)
+}
+
+declare 18 win {
+ HPALETTE TkWinGetSystemPalette (void)
+}
+
+declare 19 win {
+ HWND TkWinGetWrapperWindow (Tk_Window tkwin)
+}
+
+declare 20 win {
+ int TkWinHandleMenuEvent (HWND *phwnd, \
+ UINT *pMessage, WPARAM *pwParam, LPARAM *plParam, \
+ LRESULT *plResult)
+}
+
+declare 21 win {
+ int TkWinIndexOfColor (XColor *colorPtr)
+}
+
+declare 22 win {
+ void TkWinReleaseDrawableDC (Drawable d, HDC hdc, TkWinDCState* state)
+}
+
+declare 23 win {
+ LRESULT TkWinResendEvent (WNDPROC wndproc, HWND hwnd, XEvent *eventPtr)
+}
+
+declare 24 win {
+ HPALETTE TkWinSelectPalette (HDC dc, Colormap colormap)
+}
+
+declare 25 win {
+ void TkWinSetMenu (Tk_Window tkwin, HMENU hMenu)
+}
+
+declare 26 win {
+ void TkWinSetWindowPos (HWND hwnd, HWND siblingHwnd, int pos)
+}
+
+declare 27 win {
+ void TkWinWmCleanup (HINSTANCE hInstance)
+}
+
+declare 28 win {
+ void TkWinXCleanup (HINSTANCE hInstance)
+}
+
+declare 29 win {
+ void TkWinXInit (HINSTANCE hInstance)
+}
+
+# new for 8.1
+
+declare 30 win {
+ void TkWinSetForegroundWindow (TkWindow *winPtr)
+}
+
+declare 31 win {
+ void TkWinDialogDebug (int debug)
+}
+
+declare 32 win {
+ Tcl_Obj * TkWinGetMenuSystemDefault (Tk_Window tkwin, \
+ char *dbName, char *className)
+}
+
+declare 33 win {
+ int TkWinGetPlatformId(void)
+}
+
+########################
+# Mac specific functions
+
+declare 0 mac {
+ void TkGenerateActivateEvents (TkWindow *winPtr, int active)
+}
+
+declare 1 mac {
+ Pixmap TkpCreateNativeBitmap (Display *display, char * source)
+}
+
+declare 2 mac {
+ void TkpDefineNativeBitmaps (void)
+}
+
+declare 3 mac {
+ unsigned long TkpGetMS (void)
+}
+
+declare 4 mac {
+ Pixmap TkpGetNativeAppBitmap (Display *display, \
+ char *name, int *width, int *height)
+}
+
+declare 5 mac {
+ void TkPointerDeadWindow (TkWindow *winPtr)
+}
+
+declare 6 mac {
+ void TkpSetCapture (TkWindow *winPtr)
+}
+
+declare 7 mac {
+ void TkpSetCursor (TkpCursor cursor)
+}
+
+declare 8 mac {
+ void TkpWmSetState (TkWindow *winPtr, int state)
+}
+
+declare 9 mac {
+ int HandleWMEvent (EventRecord *theEvent)
+}
+
+declare 10 mac {
+ void TkAboutDlg (void)
+}
+
+declare 11 mac {
+ void TkCreateMacEventSource (void)
+}
+
+declare 12 mac {
+ void TkFontList (Tcl_Interp *interp, Display *display)
+}
+
+declare 13 mac {
+ Window TkGetTransientMaster (TkWindow *winPtr)
+}
+
+declare 14 mac {
+ int TkGenerateButtonEvent (int x, int y, \
+ Window window, unsigned int state)
+}
+
+declare 15 mac {
+ int TkGetCharPositions (XFontStruct *font_struct, char *string, \
+ int count, short *buffer)
+}
+
+declare 16 mac {
+ void TkGenWMDestroyEvent (Tk_Window tkwin)
+}
+
+declare 17 mac {
+ void TkGenWMConfigureEvent (Tk_Window tkwin, int x, int y, \
+ int width, int height, int flags)
+}
+
+declare 18 mac {
+ unsigned int TkMacButtonKeyState (void)
+}
+
+declare 19 mac {
+ void TkMacClearMenubarActive (void)
+}
+
+declare 20 mac {
+ int TkMacConvertEvent (EventRecord *eventPtr)
+}
+
+declare 21 mac {
+ int TkMacDispatchMenuEvent (int menuID, int index)
+}
+
+declare 22 mac {
+ void TkMacInstallCursor (int resizeOverride)
+}
+
+declare 23 mac {
+ int TkMacConvertTkEvent (EventRecord *eventPtr, Window window)
+}
+
+declare 24 mac {
+ void TkMacHandleTearoffMenu (void)
+}
+
+declare 25 mac {
+ void tkMacInstallMWConsole (Tcl_Interp *interp)
+}
+
+declare 26 mac {
+ void TkMacInvalClipRgns (TkWindow *winPtr)
+}
+
+declare 27 mac {
+ void TkMacDoHLEvent (EventRecord *theEvent)
+}
+
+declare 28 mac {
+ void TkMacFontInfo (Font fontId, short *family, \
+ short *style, short *size)
+}
+
+declare 29 mac {
+ Time TkMacGenerateTime (void)
+}
+
+declare 30 mac {
+ GWorldPtr TkMacGetDrawablePort (Drawable drawable)
+}
+
+declare 31 mac {
+ TkWindow * TkMacGetScrollbarGrowWindow (TkWindow *winPtr)
+}
+
+declare 32 mac {
+ Window TkMacGetXWindow (WindowRef macWinPtr)
+}
+
+declare 33 mac {
+ int TkMacGrowToplevel (WindowRef whichWindow, Point start)
+}
+
+declare 34 mac {
+ void TkMacHandleMenuSelect (long mResult, int optionKeyPressed)
+}
+
+declare 35 mac {
+ int TkMacHaveAppearance (void)
+}
+
+declare 36 mac {
+ void TkMacInitAppleEvents (Tcl_Interp *interp)
+}
+
+declare 37 mac {
+ void TkMacInitMenus (Tcl_Interp *interp)
+}
+
+declare 38 mac {
+ void TkMacInvalidateWindow (MacDrawable *macWin, int flag)
+}
+
+declare 39 mac {
+ int TkMacIsCharacterMissing (Tk_Font tkfont, unsigned int searchChar)
+}
+
+declare 40 mac {
+ void TkMacMakeRealWindowExist (TkWindow *winPtr)
+}
+
+declare 41 mac {
+ BitMapPtr TkMacMakeStippleMap(Drawable d1, Drawable d2)
+}
+
+declare 42 mac {
+ void TkMacMenuClick (void)
+}
+
+declare 43 mac {
+ void TkMacRegisterOffScreenWindow (Window window, GWorldPtr portPtr)
+}
+
+declare 44 mac {
+ int TkMacResizable (TkWindow *winPtr)
+}
+
+declare 45 mac {
+ void TkMacSetEmbedRgn (TkWindow *winPtr, RgnHandle rgn)
+}
+
+declare 46 mac {
+ void TkMacSetHelpMenuItemCount (void)
+}
+
+declare 47 mac {
+ void TkMacSetScrollbarGrow (TkWindow *winPtr, int flag)
+}
+
+declare 48 mac {
+ void TkMacSetUpClippingRgn (Drawable drawable)
+}
+
+declare 49 mac {
+ void TkMacSetUpGraphicsPort (GC gc)
+}
+
+declare 50 mac {
+ void TkMacUpdateClipRgn (TkWindow *winPtr)
+}
+
+declare 51 mac {
+ void TkMacUnregisterMacWindow (GWorldPtr portPtr)
+}
+
+declare 52 mac {
+ int TkMacUseMenuID (short macID)
+}
+
+declare 53 mac {
+ RgnHandle TkMacVisableClipRgn (TkWindow *winPtr)
+}
+
+declare 54 mac {
+ void TkMacWinBounds (TkWindow *winPtr, Rect *geometry)
+}
+
+declare 55 mac {
+ void TkMacWindowOffset (WindowRef wRef, int *xOffset, int *yOffset)
+}
+
+declare 56 mac {
+ void TkResumeClipboard (void)
+}
+
+declare 57 mac {
+ int TkSetMacColor (unsigned long pixel, RGBColor *macColor)
+}
+
+declare 58 mac {
+ void TkSetWMName (TkWindow *winPtr, Tk_Uid titleUid)
+}
+
+declare 59 mac {
+ void TkSuspendClipboard (void)
+}
+
+declare 60 mac {
+ int TkWMGrowToplevel (WindowRef whichWindow, Point start)
+}
+
+declare 61 mac {
+ int TkMacZoomToplevel (WindowPtr whichWindow, Point where, short zoomPart)
+}
+
+declare 62 mac {
+ Tk_Window Tk_TopCoordsToWindow (Tk_Window tkwin, \
+ int rootX, int rootY, int *newX, int *newY)
+}
+
+declare 63 mac {
+ MacDrawable * TkMacContainerId (TkWindow *winPtr)
+}
+
+declare 64 mac {
+ MacDrawable * TkMacGetHostToplevel (TkWindow *winPtr)
+}
+
+
+##############################################################################
+
+# Define the platform specific internal Xlib interfaces. These functions are
+# only available on the designated platform.
+
+interface tkIntXlib
+
+# X functions for Windows
+
+# This slot is reserved for use by the dash patch:
+# declare 0 win {
+# XSetDashes
+# }
+declare 1 win {
+ XModifierKeymap* XGetModifierMapping (Display* d)
+}
+
+declare 2 win {
+ XImage * XCreateImage (Display* d, Visual* v, unsigned int ui1, int i1, \
+ int i2, char* cp, unsigned int ui2, unsigned int ui3, int i3, \
+ int i4)
+
+}
+
+declare 3 win {
+ XImage *XGetImage (Display* d, Drawable dr, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)
+}
+
+declare 4 win {
+ char *XGetAtomName (Display* d,Atom a)
+
+}
+
+declare 5 win {
+ char *XKeysymToString (KeySym k)
+}
+
+declare 6 win {
+ Colormap XCreateColormap (Display* d, Window w, Visual* v, int i)
+
+}
+
+declare 7 win {
+ Cursor XCreatePixmapCursor (Display* d, Pixmap p1, Pixmap p2, \
+ XColor* x1, XColor* x2, \
+ unsigned int ui1, unsigned int ui2)
+}
+
+declare 8 win {
+ Cursor XCreateGlyphCursor (Display* d, Font f1, Font f2, \
+ unsigned int ui1, unsigned int ui2, XColor* x1, XColor* x2)
+}
+
+declare 9 win {
+ GContext XGContextFromGC (GC g)
+}
+
+declare 10 win {
+ XHostAddress *XListHosts (Display* d, int* i, Bool* b)
+}
+
+# second parameter was of type KeyCode
+declare 11 win {
+ KeySym XKeycodeToKeysym (Display* d, unsigned int k, int i)
+}
+
+declare 12 win {
+ KeySym XStringToKeysym (_Xconst char* c)
+}
+
+declare 13 win {
+ Window XRootWindow (Display* d, int i)
+}
+
+declare 14 win {
+ XErrorHandler XSetErrorHandler (XErrorHandler x)
+}
+
+declare 15 win {
+ Status XIconifyWindow (Display* d, Window w, int i)
+}
+
+declare 16 win {
+ Status XWithdrawWindow (Display* d, Window w, int i)
+}
+
+declare 17 win {
+ Status XGetWMColormapWindows (Display* d, Window w, Window** wpp, int* ip)
+}
+
+declare 18 win {
+ Status XAllocColor (Display* d, Colormap c, XColor* xp)
+}
+
+declare 19 win {
+ void XBell (Display* d, int i)
+}
+
+declare 20 win {
+ void XChangeProperty (Display* d, Window w, Atom a1, Atom a2, int i1, \
+ int i2, _Xconst unsigned char* c, int i3)
+}
+
+declare 21 win {
+ void XChangeWindowAttributes (Display* d, Window w, unsigned long ul, \
+ XSetWindowAttributes* x)
+}
+
+declare 22 win {
+ void XClearWindow (Display* d, Window w)
+}
+
+declare 23 win {
+ void XConfigureWindow (Display* d, Window w, unsigned int i, \
+ XWindowChanges* x)
+}
+
+declare 24 win {
+ void XCopyArea (Display* d, Drawable dr1, Drawable dr2, GC g, int i1, \
+ int i2, unsigned int ui1, \
+ unsigned int ui2, int i3, int i4)
+}
+
+declare 25 win {
+ void XCopyPlane (Display* d, Drawable dr1, Drawable dr2, GC g, int i1, \
+ int i2, unsigned int ui1, \
+ unsigned int ui2, int i3, int i4, unsigned long ul)
+}
+
+declare 26 win {
+ Pixmap XCreateBitmapFromData(Display* display, Drawable d, \
+ _Xconst char* data, unsigned int width,unsigned int height)
+}
+
+declare 27 win {
+ void XDefineCursor (Display* d, Window w, Cursor c)
+}
+
+declare 28 win {
+ void XDeleteProperty (Display* d, Window w, Atom a)
+}
+
+declare 29 win {
+ void XDestroyWindow (Display* d, Window w)
+}
+
+declare 30 win {
+ void XDrawArc (Display* d, Drawable dr, GC g, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+
+declare 31 win {
+ void XDrawLines (Display* d, Drawable dr, GC g, XPoint* x, int i1, int i2)
+}
+
+declare 32 win {
+ void XDrawRectangle (Display* d, Drawable dr, GC g, int i1, int i2,\
+ unsigned int ui1, unsigned int ui2)
+}
+
+declare 33 win {
+ void XFillArc (Display* d, Drawable dr, GC g, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+
+declare 34 win {
+ void XFillPolygon (Display* d, Drawable dr, GC g, XPoint* x, \
+ int i1, int i2, int i3)
+}
+
+declare 35 win {
+ void XFillRectangles (Display* d, Drawable dr, GC g, XRectangle* x, int i)
+}
+
+declare 36 win {
+ void XForceScreenSaver (Display* d, int i)
+}
+
+declare 37 win {
+ void XFreeColormap (Display* d, Colormap c)
+}
+
+declare 38 win {
+ void XFreeColors (Display* d, Colormap c, \
+ unsigned long* ulp, int i, unsigned long ul)
+}
+
+declare 39 win {
+ void XFreeCursor (Display* d, Cursor c)
+}
+
+declare 40 win {
+ void XFreeModifiermap (XModifierKeymap* x)
+}
+
+declare 41 win {
+ Status XGetGeometry (Display* d, Drawable dr, Window* w, int* i1, \
+ int* i2, unsigned int* ui1, unsigned int* ui2, unsigned int* ui3, \
+ unsigned int* ui4)
+}
+
+declare 42 win {
+ void XGetInputFocus (Display* d, Window* w, int* i)
+}
+
+declare 43 win {
+ int XGetWindowProperty (Display* d, Window w, Atom a1, long l1, long l2, \
+ Bool b, Atom a2, Atom* ap, int* ip, unsigned long* ulp1, \
+ unsigned long* ulp2, unsigned char** cpp)
+}
+
+declare 44 win {
+ Status XGetWindowAttributes (Display* d, Window w, XWindowAttributes* x)
+}
+
+declare 45 win {
+ int XGrabKeyboard (Display* d, Window w, Bool b, int i1, int i2, Time t)
+}
+
+declare 46 win {
+ int XGrabPointer (Display* d, Window w1, Bool b, unsigned int ui, \
+ int i1, int i2, Window w2, Cursor c, Time t)
+}
+
+declare 47 win {
+ KeyCode XKeysymToKeycode (Display* d, KeySym k)
+}
+
+declare 48 win {
+ Status XLookupColor (Display* d, Colormap c1, _Xconst char* c2, \
+ XColor* x1, XColor* x2)
+}
+
+declare 49 win {
+ void XMapWindow (Display* d, Window w)
+}
+
+declare 50 win {
+ void XMoveResizeWindow (Display* d, Window w, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2)
+}
+
+declare 51 win {
+ void XMoveWindow (Display* d, Window w, int i1, int i2)
+}
+
+declare 52 win {
+ void XNextEvent (Display* d, XEvent* x)
+}
+
+declare 53 win {
+ void XPutBackEvent (Display* d, XEvent* x)
+}
+
+declare 54 win {
+ void XQueryColors (Display* d, Colormap c, XColor* x, int i)
+}
+
+declare 55 win {
+ Bool XQueryPointer (Display* d, Window w1, Window* w2, Window* w3, \
+ int* i1, int* i2, int* i3, int* i4, unsigned int* ui)
+}
+
+declare 56 win {
+ Status XQueryTree (Display* d, Window w1, Window* w2, Window* w3, \
+ Window** w4, unsigned int* ui)
+}
+
+declare 57 win {
+ void XRaiseWindow (Display* d, Window w)
+}
+
+declare 58 win {
+ void XRefreshKeyboardMapping (XMappingEvent* x)
+}
+
+declare 59 win {
+ void XResizeWindow (Display* d, Window w, unsigned int ui1, \
+ unsigned int ui2)
+}
+
+declare 60 win {
+ void XSelectInput (Display* d, Window w, long l)
+}
+
+declare 61 win {
+ Status XSendEvent (Display* d, Window w, Bool b, long l, XEvent* x)
+}
+
+declare 62 win {
+ void XSetCommand (Display* d, Window w, char** c, int i)
+}
+
+declare 63 win {
+ void XSetIconName (Display* d, Window w, _Xconst char* c)
+}
+
+declare 64 win {
+ void XSetInputFocus (Display* d, Window w, int i, Time t)
+}
+
+declare 65 win {
+ void XSetSelectionOwner (Display* d, Atom a, Window w, Time t)
+}
+
+declare 66 win {
+ void XSetWindowBackground (Display* d, Window w, unsigned long ul)
+}
+
+declare 67 win {
+ void XSetWindowBackgroundPixmap (Display* d, Window w, Pixmap p)
+}
+
+declare 68 win {
+ void XSetWindowBorder (Display* d, Window w, unsigned long ul)
+}
+
+declare 69 win {
+ void XSetWindowBorderPixmap (Display* d, Window w, Pixmap p)
+}
+
+declare 70 win {
+ void XSetWindowBorderWidth (Display* d, Window w, unsigned int ui)
+}
+
+declare 71 win {
+ void XSetWindowColormap (Display* d, Window w, Colormap c)
+}
+
+declare 72 win {
+ Bool XTranslateCoordinates (Display* d, Window w1, Window w2, int i1,\
+ int i2, int* i3, int* i4, Window* w3)
+}
+
+declare 73 win {
+ void XUngrabKeyboard (Display* d, Time t)
+}
+
+declare 74 win {
+ void XUngrabPointer (Display* d, Time t)
+}
+
+declare 75 win {
+ void XUnmapWindow (Display* d, Window w)
+}
+
+declare 76 win {
+ void XWindowEvent (Display* d, Window w, long l, XEvent* x)
+}
+
+declare 77 win {
+ void XDestroyIC (XIC x)
+}
+
+declare 78 win {
+ Bool XFilterEvent (XEvent* x, Window w)
+}
+
+declare 79 win {
+ int XmbLookupString (XIC xi, XKeyPressedEvent* xk, \
+ char* c, int i, KeySym* k, Status* s)
+}
+
+declare 80 win {
+ void TkPutImage (unsigned long *colors, \
+ int ncolors, Display* display, Drawable d, \
+ GC gc, XImage* image, int src_x, int src_y, \
+ int dest_x, int dest_y, unsigned int width, \
+ unsigned int height)
+}
+# This slot is reserved for use by the clipping rectangle patch:
+# declare 81 win {
+# XSetClipRectangles(Display *display, GC gc, int clip_x_origin, \
+# int clip_y_origin, XRectangle rectangles[], int n, int ordering)
+# }
+
+declare 82 win {
+ Status XParseColor (Display *display, Colormap map, \
+ _Xconst char* spec, XColor *colorPtr)
+}
+
+declare 83 win {
+ GC XCreateGC(Display* display, Drawable d, \
+ unsigned long valuemask, XGCValues* values)
+}
+
+declare 84 win {
+ void XFreeGC(Display* display, GC gc)
+}
+
+declare 85 win {
+ Atom XInternAtom(Display* display,_Xconst char* atom_name, \
+ Bool only_if_exists)
+}
+
+declare 86 win {
+ void XSetBackground(Display* display, GC gc, \
+ unsigned long foreground)
+}
+
+declare 87 win {
+ void XSetForeground(Display* display, GC gc, \
+ unsigned long foreground)
+}
+
+declare 88 win {
+ void XSetClipMask(Display* display, GC gc, Pixmap pixmap)
+}
+
+declare 89 win {
+ void XSetClipOrigin(Display* display, GC gc, \
+ int clip_x_origin, int clip_y_origin)
+}
+
+declare 90 win {
+ void XSetTSOrigin(Display* display, GC gc, \
+ int ts_x_origin, int ts_y_origin)
+}
+
+declare 91 win {
+ void XChangeGC(Display * d, GC gc, unsigned long mask, XGCValues *values)
+}
+
+declare 92 win {
+ void XSetFont(Display *display, GC gc, Font font)
+}
+
+declare 93 win {
+ void XSetArcMode(Display *display, GC gc, int arc_mode)
+}
+
+declare 94 win {
+ void XSetStipple(Display *display, GC gc, Pixmap stipple)
+}
+
+declare 95 win {
+ void XSetFillRule(Display *display, GC gc, int fill_rule)
+}
+
+declare 96 win {
+ void XSetFillStyle(Display *display, GC gc, int fill_style)
+}
+
+declare 97 win {
+ void XSetFunction(Display *display, GC gc, int function)
+}
+
+declare 98 win {
+ void XSetLineAttributes(Display *display, GC gc, \
+ unsigned int line_width, int line_style, \
+ int cap_style, int join_style)
+}
+
+declare 99 win {
+ int _XInitImageFuncPtrs(XImage *image)
+}
+
+declare 100 win {
+ XIC XCreateIC(void)
+}
+
+declare 101 win {
+ XVisualInfo *XGetVisualInfo(Display* display, long vinfo_mask, \
+ XVisualInfo* vinfo_template, int* nitems_return)
+}
+
+declare 102 win {
+ void XSetWMClientMachine(Display* display, Window w, XTextProperty* text_prop)
+}
+
+declare 103 win {
+ Status XStringListToTextProperty(char** list, int count, \
+ XTextProperty* text_prop_return)
+}
+
+# X functions for Mac
+
+# This slot is reserved for use by the dash patch:
+# declare 0 win {
+# XSetDashes
+# }
+
+declare 1 mac {
+ XModifierKeymap* XGetModifierMapping (Display* d)
+}
+
+declare 2 mac {
+ XImage * XCreateImage (Display* d, Visual* v, unsigned int ui1, int i1, \
+ int i2, char* cp, unsigned int ui2, unsigned int ui3, int i3, \
+ int i4)
+
+}
+
+declare 3 mac {
+ XImage *XGetImage (Display* d, Drawable dr, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)
+}
+
+declare 4 mac {
+ char *XGetAtomName (Display* d,Atom a)
+
+}
+
+declare 5 mac {
+ char *XKeysymToString (KeySym k)
+}
+
+declare 6 mac {
+ Colormap XCreateColormap (Display* d, Window w, Visual* v, int i)
+
+}
+
+declare 7 mac {
+ GContext XGContextFromGC (GC g)
+}
+
+declare 8 mac {
+ KeySym XKeycodeToKeysym (Display* d, KeyCode k, int i)
+}
+
+declare 9 mac {
+ KeySym XStringToKeysym (_Xconst char* c)
+}
+
+declare 10 mac {
+ Window XRootWindow (Display* d, int i)
+}
+
+declare 11 mac {
+ XErrorHandler XSetErrorHandler (XErrorHandler x)
+}
+
+declare 12 mac {
+ Status XAllocColor (Display* d, Colormap c, XColor* xp)
+}
+
+declare 13 mac {
+ void XBell (Display* d, int i)
+}
+
+declare 14 mac {
+ void XChangeProperty (Display* d, Window w, Atom a, Atom a, int i1, \
+ int i2, _Xconst unsigned char* c, int i3)
+}
+
+declare 15 mac {
+ void XChangeWindowAttributes (Display* d, Window w, unsigned long ul, \
+ XSetWindowAttributes* x)
+}
+
+declare 16 mac {
+ void XConfigureWindow (Display* d, Window w, unsigned int i, \
+ XWindowChanges* x)
+}
+
+declare 17 mac {
+ void XCopyArea (Display* d, Drawable dr1, Drawable dr2, GC g, int i1, \
+ int i2, unsigned int ui1, \
+ unsigned int ui2, int i3, int i4)
+}
+
+declare 18 mac {
+ void XCopyPlane (Display* d, Drawable dr1, Drawable dr2, GC g, int i1, \
+ int i2, unsigned int ui1, \
+ unsigned int ui2, int i3, int i4, unsigned long ul)
+}
+
+declare 19 mac {
+ Pixmap XCreateBitmapFromData(Display* display, Drawable d, \
+ _Xconst char* data, unsigned int width,unsigned int height)
+}
+
+declare 20 mac {
+ void XDefineCursor (Display* d, Window w, Cursor c)
+}
+
+declare 21 mac {
+ void XDestroyWindow (Display* d, Window w)
+}
+
+declare 22 mac {
+ void XDrawArc (Display* d, Drawable dr, GC g, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+
+declare 23 mac {
+ void XDrawLines (Display* d, Drawable dr, GC g, XPoint* x, int i1, int i2)
+}
+
+declare 24 mac {
+ void XDrawRectangle (Display* d, Drawable dr, GC g, int i1, int i2,\
+ unsigned int ui1, unsigned int ui2)
+}
+
+declare 25 mac {
+ void XFillArc (Display* d, Drawable dr, GC g, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2, int i3, int i4)
+}
+
+declare 26 mac {
+ void XFillPolygon (Display* d, Drawable dr, GC g, XPoint* x, \
+ int i1, int i2, int i3)
+}
+
+declare 27 mac {
+ void XFillRectangles (Display* d, Drawable dr, GC g, XRectangle* x, int i)
+}
+
+declare 28 mac {
+ void XFreeColormap (Display* d, Colormap c)
+}
+
+declare 29 mac {
+ void XFreeColors (Display* d, Colormap c, \
+ unsigned long* ulp, int i, unsigned long ul)
+}
+
+declare 30 mac {
+ void XFreeModifiermap (XModifierKeymap* x)
+}
+
+declare 31 mac {
+ Status XGetGeometry (Display* d, Drawable dr, Window* w, int* i1, \
+ int* i2, unsigned int* ui1, unsigned int* ui2, unsigned int* ui3, \
+ unsigned int* ui4)
+}
+
+declare 32 mac {
+ int XGetWindowProperty (Display* d, Window w, Atom a1, long l1, long l2, \
+ Bool b, Atom a2, Atom* ap, int* ip, unsigned long* ulp1, \
+ unsigned long* ulp2, unsigned char** cpp)
+}
+
+declare 33 mac {
+ int XGrabKeyboard (Display* d, Window w, Bool b, int i1, int i2, Time t)
+}
+
+declare 34 mac {
+ int XGrabPointer (Display* d, Window w1, Bool b, unsigned int ui, \
+ int i1, int i2, Window w2, Cursor c, Time t)
+}
+
+declare 35 mac {
+ KeyCode XKeysymToKeycode (Display* d, KeySym k)
+}
+
+declare 36 mac {
+ void XMapWindow (Display* d, Window w)
+}
+
+declare 37 mac {
+ void XMoveResizeWindow (Display* d, Window w, int i1, int i2, \
+ unsigned int ui1, unsigned int ui2)
+}
+
+declare 38 mac {
+ void XMoveWindow (Display* d, Window w, int i1, int i2)
+}
+
+declare 39 mac {
+ Bool XQueryPointer (Display* d, Window w1, Window* w2, Window* w3, \
+ int* i1, int* i2, int* i3, int* i4, unsigned int* ui)
+}
+
+declare 40 mac {
+ void XRaiseWindow (Display* d, Window w)
+}
+
+declare 41 mac {
+ void XRefreshKeyboardMapping (XMappingEvent* x)
+}
+
+declare 42 mac {
+ void XResizeWindow (Display* d, Window w, unsigned int ui1, \
+ unsigned int ui2)
+}
+
+declare 43 mac {
+ void XSelectInput (Display* d, Window w, long l)
+}
+
+declare 44 mac {
+ Status XSendEvent (Display* d, Window w, Bool b, long l, XEvent* x)
+}
+
+declare 45 mac {
+ void XSetIconName (Display* d, Window w, _Xconst char* c)
+}
+
+declare 46 mac {
+ void XSetInputFocus (Display* d, Window w, int i, Time t)
+}
+
+declare 47 mac {
+ void XSetSelectionOwner (Display* d, Atom a, Window w, Time t)
+}
+
+declare 48 mac {
+ void XSetWindowBackground (Display* d, Window w, unsigned long ul)
+}
+
+declare 49 mac {
+ void XSetWindowBackgroundPixmap (Display* d, Window w, Pixmap p)
+}
+
+declare 50 mac {
+ void XSetWindowBorder (Display* d, Window w, unsigned long ul)
+}
+
+declare 51 mac {
+ void XSetWindowBorderPixmap (Display* d, Window w, Pixmap p)
+}
+
+declare 52 mac {
+ void XSetWindowBorderWidth (Display* d, Window w, unsigned int ui)
+}
+
+declare 53 mac {
+ void XSetWindowColormap (Display* d, Window w, Colormap c)
+}
+
+declare 54 mac {
+ void XUngrabKeyboard (Display* d, Time t)
+}
+
+declare 55 mac {
+ void XUngrabPointer (Display* d, Time t)
+}
+
+declare 56 mac {
+ void XUnmapWindow (Display* d, Window w)
+}
+
+declare 57 mac {
+ void TkPutImage (unsigned long *colors, \
+ int ncolors, Display* display, Drawable d, \
+ GC gc, XImage* image, int src_x, int src_y, \
+ int dest_x, int dest_y, unsigned int width, \
+ unsigned int height)
+}
+declare 58 mac {
+ Status XParseColor (Display *display, Colormap map, \
+ _Xconst char* spec, XColor *colorPtr)
+}
+
+declare 59 mac {
+ GC XCreateGC(Display* display, Drawable d, \
+ unsigned long valuemask, XGCValues* values)
+}
+
+declare 60 mac {
+ void XFreeGC(Display* display, GC gc)
+}
+
+declare 61 mac {
+ Atom XInternAtom(Display* display,_Xconst char* atom_name, \
+ Bool only_if_exists)
+}
+
+declare 62 mac {
+ void XSetBackground(Display* display, GC gc, \
+ unsigned long foreground)
+}
+
+declare 63 mac {
+ void XSetForeground(Display* display, GC gc, \
+ unsigned long foreground)
+}
+
+declare 64 mac {
+ void XSetClipMask(Display* display, GC gc, Pixmap pixmap)
+}
+
+declare 65 mac {
+ void XSetClipOrigin(Display* display, GC gc, \
+ int clip_x_origin, int clip_y_origin)
+}
+
+declare 66 mac {
+ void XSetTSOrigin(Display* display, GC gc, \
+ int ts_x_origin, int ts_y_origin)
+}
+
+declare 67 mac {
+ void XChangeGC(Display * d, GC gc, unsigned long mask, XGCValues *values)
+}
+
+declare 68 mac {
+ void XSetFont(Display *display, GC gc, Font font)
+}
+
+declare 69 mac {
+ void XSetArcMode(Display *display, GC gc, int arc_mode)
+}
+
+declare 70 mac {
+ void XSetStipple(Display *display, GC gc, Pixmap stipple)
+}
+
+declare 71 mac {
+ void XSetFillRule(Display *display, GC gc, int fill_rule)
+}
+
+declare 72 mac {
+ void XSetFillStyle(Display *display, GC gc, int fill_style)
+}
+
+declare 73 mac {
+ void XSetFunction(Display *display, GC gc, int function)
+}
+
+declare 74 mac {
+ void XSetLineAttributes(Display *display, GC gc, \
+ unsigned int line_width, int line_style, \
+ int cap_style, int join_style)
+}
+
+declare 75 mac {
+ int _XInitImageFuncPtrs(XImage *image)
+}
+
+declare 76 mac {
+ XIC XCreateIC(void)
+}
+
+declare 77 mac {
+ XVisualInfo *XGetVisualInfo(Display* display, long vinfo_mask, \
+ XVisualInfo* vinfo_template, int* nitems_return)
+}
+
+declare 78 mac {
+ void XSetWMClientMachine(Display* display, Window w, \
+ XTextProperty* text_prop)
+}
+
+declare 79 mac {
+ Status XStringListToTextProperty(char** list, int count, \
+ XTextProperty* text_prop_return)
+}
+declare 80 mac {
+ void XDrawSegments(Display *display, Drawable d, GC gc, \
+ XSegment *segments, int nsegments)
+}
+declare 81 mac {
+ void XForceScreenSaver(Display* display, int mode)
+}
+
diff --git a/tk/generic/tkInt.h b/tk/generic/tkInt.h
index 359b6c99150..1164edd4b1c 100644
--- a/tk/generic/tkInt.h
+++ b/tk/generic/tkInt.h
@@ -27,18 +27,12 @@
#include <tkPort.h>
#endif
-#ifdef BUILD_tk
-# undef TCL_STORAGE_CLASS
-# define TCL_STORAGE_CLASS DLLEXPORT
-#endif
-
/*
* Opaque type declarations:
*/
typedef struct TkColormap TkColormap;
typedef struct TkGrabEvent TkGrabEvent;
-typedef struct Tk_PostscriptInfo Tk_PostscriptInfo;
typedef struct TkpCursor_ *TkpCursor;
typedef struct TkRegion_ *TkRegion;
typedef struct TkStressedCmap TkStressedCmap;
@@ -87,16 +81,37 @@ 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_Preserve).
+ * If this count is 0, then this structure
+ * is no longer valid and it isn't present
+ * in a hash table: it is being kept around
+ * only because there are objects referring
+ * to it. The structure is freed when
+ * resourceRefCount and objRefCount are
+ * both 0. */
+ int objRefCount; /* Number of Tcl objects that reference
+ * this structure.. */
Tcl_HashTable *otherTable; /* Second table (other than idTable) used
* to index this entry. */
Tcl_HashEntry *hashPtr; /* Entry in otherTable for this structure
* (needed when deleting). */
+ Tcl_HashEntry *idHashPtr; /* Entry in idTable for this structure
+ * (needed when deleting). */
+ 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;
/*
* One of the following structures is maintained for each display
- * containing a window managed by Tk:
+ * containing a window managed by Tk. In part, the structure is
+ * used to store thread-specific data, since each thread will have
+ * its own TkDisplay structure.
*/
typedef struct TkDisplay {
@@ -108,6 +123,23 @@ typedef struct TkDisplay {
* display. */
/*
+ * Information used primarily by tk3d.c:
+ */
+
+ int borderInit; /* 0 means borderTable needs initializing. */
+ Tcl_HashTable borderTable; /* Maps from color name to TkBorder
+ * structure. */
+
+ /*
+ * Information used by tkAtom.c only:
+ */
+
+ int atomInit; /* 0 means stuff below hasn't been
+ * initialized yet. */
+ Tcl_HashTable nameTable; /* Maps from names to Atom's. */
+ Tcl_HashTable atomTable; /* Maps from Atom's back to names. */
+
+ /*
* Information used primarily by tkBind.c:
*/
@@ -133,6 +165,63 @@ typedef struct TkDisplay {
* may be NULL. */
/*
+ * Information used by tkBitmap.c only:
+ */
+
+ int bitmapInit; /* 0 means tables above need initializing. */
+ int bitmapAutoNumber; /* Used to number bitmaps. */
+ Tcl_HashTable bitmapNameTable;
+ /* Maps from name of bitmap to the first
+ * TkBitmap record for that name. */
+ Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap
+ * structure for the bitmap. */
+ Tcl_HashTable bitmapDataTable;
+ /* Used by Tk_GetBitmapFromData to map from
+ * a collection of in-core data about a
+ * bitmap to a reference giving an auto-
+ * matically-generated name for the bitmap. */
+
+ /*
+ * Information used by tkCanvas.c only:
+ */
+
+ int numIdSearches;
+ int numSlowSearches;
+
+ /*
+ * Used by tkColor.c only:
+ */
+
+ int colorInit; /* 0 means color module needs initializing. */
+ TkStressedCmap *stressPtr; /* First in list of colormaps that have
+ * filled up, so we have to pick an
+ * approximate color. */
+ Tcl_HashTable colorNameTable;
+ /* Maps from color name to TkColor structure
+ * for that color. */
+ Tcl_HashTable colorValueTable;
+ /* Maps from integer RGB values to TkColor
+ * structures. */
+
+ /*
+ * Used by tkCursor.c only:
+ */
+
+ int cursorInit; /* 0 means cursor module need initializing. */
+ Tcl_HashTable cursorNameTable;
+ /* Maps from a string name to a cursor to the
+ * TkCursor record for the cursor. */
+ Tcl_HashTable cursorDataTable;
+ /* Maps from a collection of in-core data
+ * about a cursor to a TkCursor structure. */
+ Tcl_HashTable cursorIdTable;
+ /* Maps from a cursor id to the TkCursor
+ * structure for the cursor. */
+ char cursorString[20]; /* Used to store a cursor id string. */
+ Font cursorFont; /* Font to use for standard cursors.
+ * None means font not loaded yet. */
+
+ /*
* Information used by tkError.c only:
*/
@@ -146,68 +235,65 @@ typedef struct TkDisplay {
* gets big, handlers get cleaned up. */
/*
- * Information used by tkSend.c only:
+ * Used by tkEvent.c only:
*/
- Tk_Window commTkwin; /* Window used for communication
- * between interpreters during "send"
- * commands. NULL means send info hasn't
- * been initialized yet. */
- Atom commProperty; /* X's name for comm property. */
- Atom registryProperty; /* X's name for property containing
- * registry of interpreter names. */
- Atom appNameProperty; /* X's name for property used to hold the
- * application name on each comm window. */
+ struct TkWindowEvent *delayedMotionPtr;
+ /* Points to a malloc-ed motion event
+ * whose processing has been delayed in
+ * the hopes that another motion event
+ * will come along right away and we can
+ * merge the two of them together. NULL
+ * means that there is no delayed motion
+ * event. */
/*
- * Information used by tkSelect.c and tkClipboard.c only:
+ * Information used by tkFocus.c only:
*/
- struct TkSelectionInfo *selectionInfoPtr;
- /* First in list of selection information
- * records. Each entry contains information
- * about the current owner of a particular
- * selection on this display. */
- Atom multipleAtom; /* Atom for MULTIPLE. None means
- * selection stuff isn't initialized. */
- Atom incrAtom; /* Atom for INCR. */
- Atom targetsAtom; /* Atom for TARGETS. */
- Atom timestampAtom; /* Atom for TIMESTAMP. */
- Atom textAtom; /* Atom for TEXT. */
- Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */
- Atom applicationAtom; /* Atom for TK_APPLICATION. */
- Atom windowAtom; /* Atom for TK_WINDOW. */
- Atom clipboardAtom; /* Atom for CLIPBOARD. */
+ int focusDebug; /* 1 means collect focus debugging
+ * statistics. */
+ struct TkWindow *implicitWinPtr;
+ /* If the focus arrived at a toplevel window
+ * implicitly via an Enter event (rather
+ * than via a FocusIn event), this points
+ * to the toplevel window. Otherwise it is
+ * NULL. */
+ struct TkWindow *focusPtr; /* Points to the window on this display that
+ * should be receiving keyboard events. When
+ * multiple applications on the display have
+ * the focus, this will refer to the
+ * innermost window in the innermost
+ * application. This information isn't used
+ * under Unix or Windows, but it's needed on
+ * the Macintosh. */
- Tk_Window clipWindow; /* Window used for clipboard ownership and to
- * retrieve selections between processes. NULL
- * means clipboard info hasn't been
- * initialized. */
- int clipboardActive; /* 1 means we currently own the clipboard
- * selection, 0 means we don't. */
- struct TkMainInfo *clipboardAppPtr;
- /* Last application that owned clipboard. */
- struct TkClipboardTarget *clipTargetPtr;
- /* First in list of clipboard type information
- * records. Each entry contains information
- * about the buffers for a given selection
- * target. */
+ /*
+ * Information used by tkGC.c only:
+ */
+
+ Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure
+ * describing a GC with those values. */
+ Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */
+ int gcInit; /* 0 means the tables below need
+ * initializing. */
/*
- * Information used by tkAtom.c only:
+ * Information used by tkGeometry.c only:
*/
- int atomInit; /* 0 means stuff below hasn't been
- * initialized yet. */
- Tcl_HashTable nameTable; /* Maps from names to Atom's. */
- Tcl_HashTable atomTable; /* Maps from Atom's back to names. */
+ Tcl_HashTable maintainHashTable;
+ /* Hash table that maps from a master's
+ * Tk_Window token to a list of slaves
+ * managed by that master. */
+ int geomInit;
/*
- * Information used by tkCursor.c only:
+ * Information used by tkGet.c only:
*/
-
- Font cursorFont; /* Font to use for standard cursors.
- * None means font not loaded yet. */
+
+ Tcl_HashTable uidTable; /* Stores all Tk_Uid used in a thread. */
+ int uidInit; /* 0 means uidTable needs initializing. */
/*
* Information used by tkGrab.c only:
@@ -245,6 +331,100 @@ typedef struct TkDisplay {
* in tkGrab.c. */
/*
+ * Information used by tkGrid.c only:
+ */
+
+ int gridInit; /* 0 means table below needs initializing. */
+ Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to
+ * corresponding Grid structures. */
+
+ /*
+ * Information used by tkImage.c only:
+ */
+
+ int imageId; /* Value used to number image ids. */
+
+ /*
+ * Information used by tkMacWinMenu.c only:
+ */
+
+ int postCommandGeneration;
+
+ /*
+ * Information used by tkOption.c only.
+ */
+
+
+
+ /*
+ * Information used by tkPack.c only.
+ */
+
+ int packInit; /* 0 means table below needs initializing. */
+ Tcl_HashTable packerHashTable;
+ /* Maps from Tk_Window tokens to
+ * corresponding Packer structures. */
+
+
+ /*
+ * Information used by tkPlace.c only.
+ */
+
+ int placeInit; /* 0 means tables below need initializing. */
+ Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master
+ * structure for the window, if it exists. */
+ Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave
+ * structure for the window, if it exists. */
+
+ /*
+ * Information used by tkSelect.c and tkClipboard.c only:
+ */
+
+ struct TkSelectionInfo *selectionInfoPtr;
+ /* First in list of selection information
+ * records. Each entry contains information
+ * about the current owner of a particular
+ * selection on this display. */
+ Atom multipleAtom; /* Atom for MULTIPLE. None means
+ * selection stuff isn't initialized. */
+ Atom incrAtom; /* Atom for INCR. */
+ Atom targetsAtom; /* Atom for TARGETS. */
+ Atom timestampAtom; /* Atom for TIMESTAMP. */
+ Atom textAtom; /* Atom for TEXT. */
+ Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */
+ Atom applicationAtom; /* Atom for TK_APPLICATION. */
+ Atom windowAtom; /* Atom for TK_WINDOW. */
+ Atom clipboardAtom; /* Atom for CLIPBOARD. */
+
+ Tk_Window clipWindow; /* Window used for clipboard ownership and to
+ * retrieve selections between processes. NULL
+ * means clipboard info hasn't been
+ * initialized. */
+ int clipboardActive; /* 1 means we currently own the clipboard
+ * selection, 0 means we don't. */
+ struct TkMainInfo *clipboardAppPtr;
+ /* Last application that owned clipboard. */
+ struct TkClipboardTarget *clipTargetPtr;
+ /* First in list of clipboard type information
+ * records. Each entry contains information
+ * about the buffers for a given selection
+ * target. */
+
+ /*
+ * Information used by tkSend.c only:
+ */
+
+ Tk_Window commTkwin; /* Window used for communication
+ * between interpreters during "send"
+ * commands. NULL means send info hasn't
+ * been initialized yet. */
+ Atom commProperty; /* X's name for comm property. */
+ Atom registryProperty; /* X's name for property containing
+ * registry of interpreter names. */
+ Atom appNameProperty; /* X's name for property used to hold the
+ * application name on each comm window. */
+
+ /*
* Information used by tkXId.c only:
*/
@@ -263,6 +443,19 @@ typedef struct TkDisplay {
* hasn't. */
/*
+ * Information used by tkUnixWm.c and tkWinWm.c only:
+ */
+
+ int wmTracing; /* Used to enable or disable tracing in
+ * this module. If tracing is enabled,
+ * then information is printed on
+ * standard output about interesting
+ * interactions with the window manager. */
+ struct TkWmInfo *firstWmPtr; /* Points to first top-level window. */
+ struct TkWmInfo *foregroundWmPtr;
+ /* Points to the foreground window. */
+
+ /*
* Information maintained by tkWindow.c for use later on by tkXId.c:
*/
@@ -283,46 +476,6 @@ typedef struct TkDisplay {
* allocated for this display. */
/*
- * Information used by tkFocus.c only:
- */
-
- struct TkWindow *implicitWinPtr;
- /* If the focus arrived at a toplevel window
- * implicitly via an Enter event (rather
- * than via a FocusIn event), this points
- * to the toplevel window. Otherwise it is
- * NULL. */
- struct TkWindow *focusPtr; /* Points to the window on this display that
- * should be receiving keyboard events. When
- * multiple applications on the display have
- * the focus, this will refer to the
- * innermost window in the innermost
- * application. This information isn't used
- * under Unix or Windows, but it's needed on
- * the Macintosh. */
-
- /*
- * Used by tkColor.c only:
- */
-
- TkStressedCmap *stressPtr; /* First in list of colormaps that have
- * filled up, so we have to pick an
- * approximate color. */
-
- /*
- * Used by tkEvent.c only:
- */
-
- struct TkWindowEvent *delayedMotionPtr;
- /* Points to a malloc-ed motion event
- * whose processing has been delayed in
- * the hopes that another motion event
- * will come along right away and we can
- * merge the two of them together. NULL
- * means that there is no delayed motion
- * event. */
-
- /*
* Miscellaneous information:
*/
@@ -336,6 +489,16 @@ typedef struct TkDisplay {
* the display when we no longer have any
* Tk applications using it.
*/
+ /*
+ * The following field were all added for Tk8.3
+ */
+ int mouseButtonState; /* current mouse button state for this
+ * display */
+ int warpInProgress;
+ Window warpWindow;
+ int warpX;
+ int warpY;
+ int useInputMethods; /* Whether to use input methods */
} TkDisplay;
/*
@@ -373,6 +536,9 @@ typedef struct TkErrorHandler {
* list. */
} TkErrorHandler;
+
+
+
/*
* One of the following structures exists for each event handler
* created by calling Tk_CreateEventHandler. This information
@@ -393,7 +559,7 @@ typedef struct TkEventHandler {
/*
* Tk keeps one of the following data structures for each main
- * window (created by a call to Tk_CreateMainWindow). It stores
+ * window (created by a call to TkCreateMainWindow). It stores
* information that is shared by all of the windows associated
* with a particular main window.
*/
@@ -415,10 +581,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:
@@ -685,296 +851,239 @@ extern TkDisplay *tkDisplayList;
#define EMBEDDED_APP_WANTS_FOCUS (NotifyNormal + 20)
/*
+ * The following special modifier mask bits are defined, to indicate
+ * logical modifiers such as Meta and Alt that may float among the
+ * actual modifier bits.
+ */
+
+#define META_MASK (AnyModifier<<1)
+#define ALT_MASK (AnyModifier<<2)
+
+/*
* Miscellaneous variables shared among Tk modules but not exported
* to the outside world:
*/
-extern Tk_Uid tkActiveUid;
+extern Tk_SmoothMethod tkBezierSmoothMethod;
extern Tk_ImageType tkBitmapImageType;
-extern Tk_Uid tkDisabledUid;
extern Tk_PhotoImageFormat tkImgFmtGIF;
extern void (*tkHandleEventProc) _ANSI_ARGS_((
XEvent* eventPtr));
extern Tk_PhotoImageFormat tkImgFmtPPM;
extern TkMainInfo *tkMainWindowList;
-extern Tk_Uid tkNormalUid;
extern Tk_ImageType tkPhotoImageType;
extern Tcl_HashTable tkPredefBitmapTable;
extern int tkSendSerial;
+#include "tkIntDecls.h"
+
+#ifdef BUILD_tk
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
/*
* Internal procedures shared among Tk modules but not exported
* to the outside world:
*/
-EXTERN char * TkAlignImageData _ANSI_ARGS_((XImage *image,
- int alignment, int bitOrder));
-EXTERN TkWindow * TkAllocWindow _ANSI_ARGS_((TkDisplay *dispPtr,
- int screenNum, TkWindow *parentPtr));
-EXTERN void TkBezierPoints _ANSI_ARGS_((double control[],
- int numSteps, double *coordPtr));
-EXTERN void TkBezierScreenPoints _ANSI_ARGS_((Tk_Canvas canvas,
- double control[], int numSteps,
- XPoint *xPointPtr));
-EXTERN void TkBindDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkBindEventProc _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
-EXTERN void TkBindFree _ANSI_ARGS_((TkMainInfo *mainPtr));
-EXTERN void TkBindInit _ANSI_ARGS_((TkMainInfo *mainPtr));
-EXTERN void TkChangeEventWindow _ANSI_ARGS_((XEvent *eventPtr,
- TkWindow *winPtr));
-#ifndef TkClipBox
-EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn,
- XRectangle* rect_return));
-#endif
-EXTERN int TkClipInit _ANSI_ARGS_((Tcl_Interp *interp,
- TkDisplay *dispPtr));
-EXTERN void TkComputeAnchor _ANSI_ARGS_((Tk_Anchor anchor,
- Tk_Window tkwin, int padX, int padY,
- int innerWidth, int innerHeight, int *xPtr,
- int *yPtr));
-EXTERN int TkCopyAndGlobalEval _ANSI_ARGS_((Tcl_Interp *interp,
- char *script));
-EXTERN unsigned long TkCreateBindingProcedure _ANSI_ARGS_((
- Tcl_Interp *interp, Tk_BindingTable bindingTable,
- ClientData object, char *eventString,
- TkBindEvalProc *evalProc, TkBindFreeProc *freeProc,
- ClientData clientData));
-EXTERN TkCursor * TkCreateCursorFromData _ANSI_ARGS_((Tk_Window tkwin,
- char *source, char *mask, int width, int height,
- int xHot, int yHot, XColor fg, XColor bg));
-EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv,
- int toplevel, char *appName));
-EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp *interp,
- char *screenName, char *baseName));
-#ifndef TkCreateRegion
-EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void));
-#endif
-EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay *dispPtr));
+EXTERN int Tk_AfterCmd _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_ButtonObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_CanvasObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, Tcl_Obj *CONST objv[]));
+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_ChooseColorObjCmd _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]));
+EXTERN int Tk_ChooseDirectoryObjCmd _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]));
+EXTERN int Tk_ChooseFontObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_DestroyObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_EntryObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_EventObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_FileeventCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_FrameObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_FocusObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_FontObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_GetOpenFileObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_GetSaveFileObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_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_ImageObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_LabelObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_ListboxObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_LowerObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_MenubuttonObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_MessageBoxObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_MessageCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_OptionObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+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_RadiobuttonObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_RaiseObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_ScaleObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_ScrollbarCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+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,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_TkwaitCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_ToplevelObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_UpdateObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_WinfoObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+EXTERN int Tk_WmCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int argc, char **argv));
+
+void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp,
+ int devId, char *buffer, long size));
+
+EXTERN void TkEventInit _ANSI_ARGS_((void));
+
+EXTERN int TkCreateMenuCmd _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo *mainPtr));
-#ifndef TkDestroyRegion
-EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn));
-#endif
-EXTERN void TkDoConfigureNotify _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_((
- Tk_Window tkwin, GC gc, int width,
- Drawable drawable, int padding));
-EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas,
- double *coordPtr, int numPoints, Display *display,
- Drawable drawable, GC gc, GC outlineGC));
-EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp *interp,
- CONST char *option, CONST TkStateMap *mapPtr,
- CONST char *strKey));
-EXTERN char * TkFindStateString _ANSI_ARGS_((
- CONST TkStateMap *mapPtr, int numKey));
-EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN int TkFocusFilterEvent _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
-EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
-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_((
- TkWindow *winPtr, int active));
-EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp *interp,
- char *string, char *fileName, int *widthPtr,
- int *heightPtr, int *hotXPtr, int *hotYPtr));
-EXTERN void TkGetButtPoints _ANSI_ARGS_((double p1[], double p2[],
- double width, int project, double m1[],
- double m2[]));
-EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, Tk_Uid string));
-EXTERN char * TkGetDefaultScreenName _ANSI_ARGS_((Tcl_Interp *interp,
- char *screenName));
-EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display *display));
-EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj *CONST objv[],
- Tk_Window *tkwinPtr));
-EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin));
-EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], double p2[],
- double p3[], double width, double m1[],
- double m2[]));
-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 void TkGrabDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN int TkGrabState _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkIncludePoint _ANSI_ARGS_((Tk_Item *itemPtr,
- double *pointPtr));
-EXTERN void TkInitXId _ANSI_ARGS_((TkDisplay *dispPtr));
-EXTERN void TkInOutEvents _ANSI_ARGS_((XEvent *eventPtr,
- TkWindow *sourcePtr, TkWindow *destPtr,
- int leaveType, int enterType,
- Tcl_QueuePosition position));
-EXTERN void TkInstallFrameMenu _ANSI_ARGS_((Tk_Window tkwin));
-#ifndef TkIntersectRegion
-EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra,
- TkRegion srcb, TkRegion dr_return));
-#endif
-EXTERN char * TkKeysymToString _ANSI_ARGS_((KeySym keysym));
-EXTERN int TkLineToArea _ANSI_ARGS_((double end1Ptr[2],
- double end2Ptr[2], double rectPtr[4]));
-EXTERN double TkLineToPoint _ANSI_ARGS_((double end1Ptr[2],
- double end2Ptr[2], double pointPtr[2]));
-EXTERN int TkMakeBezierCurve _ANSI_ARGS_((Tk_Canvas canvas,
- double *pointPtr, int numPoints, int numSteps,
- XPoint xPoints[], double dblPoints[]));
-EXTERN void TkMakeBezierPostscript _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Canvas canvas, double *pointPtr,
- int numPoints));
-EXTERN void TkOptionClassChanged _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkOptionDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN int TkOvalToArea _ANSI_ARGS_((double *ovalPtr,
- double *rectPtr));
-EXTERN double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[4],
- double width, int filled, double pointPtr[2]));
-EXTERN int TkpChangeFocus _ANSI_ARGS_((TkWindow *winPtr,
- int force));
-EXTERN void TkpCloseDisplay _ANSI_ARGS_((TkDisplay *dispPtr));
-EXTERN void TkpClaimFocus _ANSI_ARGS_((TkWindow *topLevelPtr,
- int force));
-#ifndef TkpCmapStressed
-EXTERN int TkpCmapStressed _ANSI_ARGS_((Tk_Window tkwin,
- Colormap colormap));
-#endif
-#ifndef TkpCreateNativeBitmap
-EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display *display,
- char * source));
-#endif
-#ifndef TkpDefineNativeBitmaps
-EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void));
-#endif
-EXTERN void TkpDisplayWarning _ANSI_ARGS_((char *msg,
- char *title));
-EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_DString *name));
-EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void));
-#ifndef TkpGetNativeAppBitmap
-EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display *display,
- char *name, int *width, int *height));
-#endif
-EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp *interp));
-EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_((
- Tcl_Interp *interp, Tk_BindingTable bindingTable));
-EXTERN void TkpMakeContainer _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void TkpMakeMenuWindow _ANSI_ARGS_((Tk_Window tkwin,
- int transient));
-EXTERN Window TkpMakeWindow _ANSI_ARGS_((TkWindow *winPtr,
- Window parent));
-EXTERN void TkpMenuNotifyToplevelCreate _ANSI_ARGS_((
- Tcl_Interp *, char *menuName));
-EXTERN TkDisplay * TkpOpenDisplay _ANSI_ARGS_((char *display_name));
-EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN int TkPointerEvent _ANSI_ARGS_((XEvent *eventPtr,
- TkWindow *winPtr));
-EXTERN int TkPolygonToArea _ANSI_ARGS_((double *polyPtr,
- int numPoints, double *rectPtr));
-EXTERN double TkPolygonToPoint _ANSI_ARGS_((double *polyPtr,
- int numPoints, double *pointPtr));
-EXTERN int TkPositionInTree _ANSI_ARGS_((TkWindow *winPtr,
- TkWindow *treePtr));
-#ifndef TkpPrintWindowId
-EXTERN void TkpPrintWindowId _ANSI_ARGS_((char *buf,
- Window window));
-#endif
-EXTERN void TkpRedirectKeyEvent _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *eventPtr));
-#ifndef TkpScanWindowId
-EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp *interp,
- char *string, int *idPtr));
-#endif
-EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor));
-EXTERN void TkpSetMainMenubar _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *menuName));
-#ifndef TkpSync
-EXTERN void TkpSync _ANSI_ARGS_((Display *display));
-#endif
+
EXTERN int TkpTestembedCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *string));
-#ifndef TkPutImage
-EXTERN void TkPutImage _ANSI_ARGS_((unsigned long *colors,
- int ncolors, Display* display, Drawable d,
- GC gc, XImage* image, int src_x, int src_y,
- int dest_x, int dest_y, unsigned int width,
- unsigned int height));
-#endif
-EXTERN int TkpWindowWasRecentlyDeleted _ANSI_ARGS_((Window win,
- TkDisplay *dispPtr));
-EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow *winPtr,
- int state));
-EXTERN void TkQueueEventForAllChildren _ANSI_ARGS_((
- TkWindow *winPtr, XEvent *eventPtr));
-EXTERN int TkReadBitmapFile _ANSI_ARGS_((Display* display,
- Drawable d, CONST char* filename,
- unsigned int* width_return,
- unsigned int* height_return,
- Pixmap* bitmap_return,
- int* x_hot_return, int* y_hot_return));
-#ifndef TkRectInRegion
-EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn,
- int x, int y, unsigned int width,
- unsigned int height));
-#endif
-EXTERN int TkScrollWindow _ANSI_ARGS_((Tk_Window tkwin, GC gc,
- int x, int y, int width, int height, int dx,
- int dy, TkRegion damageRgn));
-EXTERN void TkSelDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin,
- XEvent *eventPtr));
-EXTERN void TkSelInit _ANSI_ARGS_((Tk_Window tkwin));
-EXTERN void TkSelPropProc _ANSI_ARGS_((XEvent *eventPtr));
-EXTERN void TkSetClassProcs _ANSI_ARGS_((Tk_Window tkwin,
- TkClassProcs *procs, ClientData instanceData));
-#ifndef TkSetPixmapColormap
-EXTERN void TkSetPixmapColormap _ANSI_ARGS_((Pixmap pixmap,
- Colormap colormap));
-#endif
-#ifndef TkSetRegion
-EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc,
- TkRegion rgn));
-#endif
-EXTERN void TkSetWindowMenuBar _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Window tkwin, char *oldMenuName,
- char *menuName));
-EXTERN KeySym TkStringToKeysym _ANSI_ARGS_((char *name));
-EXTERN int TkThickPolyLineToArea _ANSI_ARGS_((double *coordPtr,
- int numPoints, double width, int capStyle,
- int joinStyle, double *rectPtr));
-#ifndef TkUnionRectWithRegion
-EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect,
- TkRegion src, TkRegion dr_return));
-#endif
-EXTERN void TkWmAddToColormapWindows _ANSI_ARGS_((
- TkWindow *winPtr));
-EXTERN void TkWmDeadWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN TkWindow * TkWmFocusToplevel _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkWmMapWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkWmNewWindow _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow *winPtr,
- XEvent *evenvPtr));
-EXTERN void TkWmRemoveFromColormapWindows _ANSI_ARGS_((
- TkWindow *winPtr));
-EXTERN void TkWmRestackToplevel _ANSI_ARGS_((TkWindow *winPtr,
- int aboveBelow, TkWindow *otherPtr));
-EXTERN void TkWmSetClass _ANSI_ARGS_((TkWindow *winPtr));
-EXTERN void TkWmUnmapWindow _ANSI_ARGS_((TkWindow *winPtr));
+EXTERN int TkCanvasGetCoordObj _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tcl_Obj *obj,
+ double *doublePtr));
+EXTERN int TkCanvasDashParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value, char *widgRec,
+ int offset));
+EXTERN char * TkCanvasDashPrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+EXTERN int TkGetDoublePixels _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *string,
+ double *doublePtr));
+EXTERN int TkOffsetParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value, char *widgRec,
+ int offset));
+EXTERN char * TkOffsetPrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+EXTERN int TkOrientParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value,
+ char *widgRec, int offset));
+EXTERN char * TkOrientPrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+EXTERN int TkPixelParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value, char *widgRec,
+ int offset));
+EXTERN char * TkPixelPrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+EXTERN int TkPostscriptImage _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_PostscriptInfo psInfo,
+ XImage *ximage, int x, int y, int width,
+ int height));
+EXTERN int TkSmoothParseProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST char *value, char *recordPtr, int offset));
+EXTERN char * TkSmoothPrintProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *recordPtr, int offset,
+ Tcl_FreeProc **freeProcPtr));
+EXTERN int TkStateParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value,
+ char *widgRec, int offset));
+EXTERN char * TkStatePrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+EXTERN int TkTileParseProc _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, CONST char *value, char *widgRec,
+ int offset));
+EXTERN char * TkTilePrintProc _ANSI_ARGS_((
+ ClientData clientData, Tk_Window tkwin,
+ char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
/*
* Unsupported commands.
@@ -987,8 +1096,10 @@ EXTERN void TkRegisterColorGC _ANSI_ARGS_((XColor *, Display *,
GC, unsigned long));
EXTERN void TkDeregisterColorGC _ANSI_ARGS_((XColor *, GC,
unsigned long));
+
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLIMPORT
-
#endif /* _TKINT */
+
+
diff --git a/tk/generic/tkIntDecls.h b/tk/generic/tkIntDecls.h
new file mode 100644
index 00000000000..0e37d59f8b1
--- /dev/null
+++ b/tk/generic/tkIntDecls.h
@@ -0,0 +1,1485 @@
+/*
+ * tkIntDecls.h --
+ *
+ * This file contains the declarations for all unsupported
+ * functions that are exported by the Tk library. These
+ * interfaces are not guaranteed to remain the same between
+ * versions. Use at your own risk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifndef _TKINTDECLS
+#define _TKINTDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tkInt.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+EXTERN TkWindow * TkAllocWindow _ANSI_ARGS_((TkDisplay * dispPtr,
+ int screenNum, TkWindow * parentPtr));
+/* 1 */
+EXTERN void TkBezierPoints _ANSI_ARGS_((double control[],
+ int numSteps, double * coordPtr));
+/* 2 */
+EXTERN void TkBezierScreenPoints _ANSI_ARGS_((Tk_Canvas canvas,
+ double control[], int numSteps,
+ XPoint * xPointPtr));
+/* 3 */
+EXTERN void TkBindDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 4 */
+EXTERN void TkBindEventProc _ANSI_ARGS_((TkWindow * winPtr,
+ XEvent * eventPtr));
+/* 5 */
+EXTERN void TkBindFree _ANSI_ARGS_((TkMainInfo * mainPtr));
+/* 6 */
+EXTERN void TkBindInit _ANSI_ARGS_((TkMainInfo * mainPtr));
+/* 7 */
+EXTERN void TkChangeEventWindow _ANSI_ARGS_((XEvent * eventPtr,
+ TkWindow * winPtr));
+/* 8 */
+EXTERN int TkClipInit _ANSI_ARGS_((Tcl_Interp * interp,
+ TkDisplay * dispPtr));
+/* 9 */
+EXTERN void TkComputeAnchor _ANSI_ARGS_((Tk_Anchor anchor,
+ Tk_Window tkwin, int padX, int padY,
+ int innerWidth, int innerHeight, int * xPtr,
+ int * yPtr));
+/* 10 */
+EXTERN int TkCopyAndGlobalEval _ANSI_ARGS_((Tcl_Interp * interp,
+ char * script));
+/* 11 */
+EXTERN unsigned long TkCreateBindingProcedure _ANSI_ARGS_((
+ Tcl_Interp * interp,
+ Tk_BindingTable bindingTable,
+ ClientData object, char * eventString,
+ TkBindEvalProc * evalProc,
+ TkBindFreeProc * freeProc,
+ ClientData clientData));
+/* 12 */
+EXTERN TkCursor * TkCreateCursorFromData _ANSI_ARGS_((Tk_Window tkwin,
+ char * source, char * mask, int width,
+ int height, int xHot, int yHot, XColor fg,
+ XColor bg));
+/* 13 */
+EXTERN int TkCreateFrame _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp * interp, int argc, char ** argv,
+ int toplevel, char * appName));
+/* 14 */
+EXTERN Tk_Window TkCreateMainWindow _ANSI_ARGS_((Tcl_Interp * interp,
+ char * screenName, char * baseName));
+/* 15 */
+EXTERN Time TkCurrentTime _ANSI_ARGS_((TkDisplay * dispPtr));
+/* 16 */
+EXTERN void TkDeleteAllImages _ANSI_ARGS_((TkMainInfo * mainPtr));
+/* 17 */
+EXTERN void TkDoConfigureNotify _ANSI_ARGS_((TkWindow * winPtr));
+/* 18 */
+EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_((
+ Tk_Window tkwin, GC gc, int width,
+ Drawable drawable, int padding));
+/* 19 */
+EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 20 */
+EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas,
+ double * coordPtr, int numPoints,
+ Display * display, Drawable drawable, GC gc,
+ GC outlineGC));
+/* 21 */
+EXTERN int TkFindStateNum _ANSI_ARGS_((Tcl_Interp * interp,
+ CONST char * option,
+ CONST TkStateMap * mapPtr,
+ CONST char * strKey));
+/* 22 */
+EXTERN char * TkFindStateString _ANSI_ARGS_((
+ CONST TkStateMap * mapPtr, int numKey));
+/* 23 */
+EXTERN void TkFocusDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 24 */
+EXTERN int TkFocusFilterEvent _ANSI_ARGS_((TkWindow * winPtr,
+ XEvent * eventPtr));
+/* 25 */
+EXTERN TkWindow * TkFocusKeyEvent _ANSI_ARGS_((TkWindow * winPtr,
+ XEvent * eventPtr));
+/* 26 */
+EXTERN void TkFontPkgInit _ANSI_ARGS_((TkMainInfo * mainPtr));
+/* 27 */
+EXTERN void TkFontPkgFree _ANSI_ARGS_((TkMainInfo * mainPtr));
+/* 28 */
+EXTERN void TkFreeBindingTags _ANSI_ARGS_((TkWindow * winPtr));
+/* 29 */
+EXTERN void TkpFreeCursor _ANSI_ARGS_((TkCursor * cursorPtr));
+/* 30 */
+EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp * interp,
+ char * string, char * fileName,
+ int * widthPtr, int * heightPtr,
+ int * hotXPtr, int * hotYPtr));
+/* 31 */
+EXTERN void TkGetButtPoints _ANSI_ARGS_((double p1[],
+ double p2[], double width, int project,
+ double m1[], double m2[]));
+/* 32 */
+EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tk_Uid string));
+/* 33 */
+EXTERN char * TkGetDefaultScreenName _ANSI_ARGS_((
+ Tcl_Interp * interp, char * screenName));
+/* 34 */
+EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display * display));
+/* 35 */
+EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp * interp,
+ int objc, Tcl_Obj *CONST objv[],
+ Tk_Window * tkwinPtr));
+/* 36 */
+EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow * winPtr));
+/* 37 */
+EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin));
+/* 38 */
+EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[],
+ double p2[], double p3[], double width,
+ double m1[], double m2[]));
+/* 39 */
+EXTERN void TkGetPointerCoords _ANSI_ARGS_((Tk_Window tkwin,
+ int * xPtr, int * yPtr));
+/* 40 */
+EXTERN void TkGetServerInfo _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin));
+/* 41 */
+EXTERN void TkGrabDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 42 */
+EXTERN int TkGrabState _ANSI_ARGS_((TkWindow * winPtr));
+/* 43 */
+EXTERN void TkIncludePoint _ANSI_ARGS_((Tk_Item * itemPtr,
+ double * pointPtr));
+/* 44 */
+EXTERN void TkInOutEvents _ANSI_ARGS_((XEvent * eventPtr,
+ TkWindow * sourcePtr, TkWindow * destPtr,
+ int leaveType, int enterType,
+ Tcl_QueuePosition position));
+/* 45 */
+EXTERN void TkInstallFrameMenu _ANSI_ARGS_((Tk_Window tkwin));
+/* 46 */
+EXTERN char * TkKeysymToString _ANSI_ARGS_((KeySym keysym));
+/* 47 */
+EXTERN int TkLineToArea _ANSI_ARGS_((double end1Ptr[],
+ double end2Ptr[], double rectPtr[]));
+/* 48 */
+EXTERN double TkLineToPoint _ANSI_ARGS_((double end1Ptr[],
+ double end2Ptr[], double pointPtr[]));
+/* 49 */
+EXTERN int TkMakeBezierCurve _ANSI_ARGS_((Tk_Canvas canvas,
+ double * pointPtr, int numPoints,
+ int numSteps, XPoint xPoints[],
+ double dblPoints[]));
+/* 50 */
+EXTERN void TkMakeBezierPostscript _ANSI_ARGS_((
+ Tcl_Interp * interp, Tk_Canvas canvas,
+ double * pointPtr, int numPoints));
+/* 51 */
+EXTERN void TkOptionClassChanged _ANSI_ARGS_((TkWindow * winPtr));
+/* 52 */
+EXTERN void TkOptionDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 53 */
+EXTERN int TkOvalToArea _ANSI_ARGS_((double * ovalPtr,
+ double * rectPtr));
+/* 54 */
+EXTERN double TkOvalToPoint _ANSI_ARGS_((double ovalPtr[],
+ double width, int filled, double pointPtr[]));
+/* 55 */
+EXTERN int TkpChangeFocus _ANSI_ARGS_((TkWindow * winPtr,
+ int force));
+/* 56 */
+EXTERN void TkpCloseDisplay _ANSI_ARGS_((TkDisplay * dispPtr));
+/* 57 */
+EXTERN void TkpClaimFocus _ANSI_ARGS_((TkWindow * topLevelPtr,
+ int force));
+/* 58 */
+EXTERN void TkpDisplayWarning _ANSI_ARGS_((char * msg,
+ char * title));
+/* 59 */
+EXTERN void TkpGetAppName _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_DString * name));
+/* 60 */
+EXTERN TkWindow * TkpGetOtherWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 61 */
+EXTERN TkWindow * TkpGetWrapperWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 62 */
+EXTERN int TkpInit _ANSI_ARGS_((Tcl_Interp * interp));
+/* 63 */
+EXTERN void TkpInitializeMenuBindings _ANSI_ARGS_((
+ Tcl_Interp * interp,
+ Tk_BindingTable bindingTable));
+/* 64 */
+EXTERN void TkpMakeContainer _ANSI_ARGS_((Tk_Window tkwin));
+/* 65 */
+EXTERN void TkpMakeMenuWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int transient));
+/* 66 */
+EXTERN Window TkpMakeWindow _ANSI_ARGS_((TkWindow * winPtr,
+ Window parent));
+/* 67 */
+EXTERN void TkpMenuNotifyToplevelCreate _ANSI_ARGS_((
+ Tcl_Interp * interp1, char * menuName));
+/* 68 */
+EXTERN TkDisplay * TkpOpenDisplay _ANSI_ARGS_((char * display_name));
+/* 69 */
+EXTERN int TkPointerEvent _ANSI_ARGS_((XEvent * eventPtr,
+ TkWindow * winPtr));
+/* 70 */
+EXTERN int TkPolygonToArea _ANSI_ARGS_((double * polyPtr,
+ int numPoints, double * rectPtr));
+/* 71 */
+EXTERN double TkPolygonToPoint _ANSI_ARGS_((double * polyPtr,
+ int numPoints, double * pointPtr));
+/* 72 */
+EXTERN int TkPositionInTree _ANSI_ARGS_((TkWindow * winPtr,
+ TkWindow * treePtr));
+/* 73 */
+EXTERN void TkpRedirectKeyEvent _ANSI_ARGS_((TkWindow * winPtr,
+ XEvent * eventPtr));
+/* 74 */
+EXTERN void TkpSetMainMenubar _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * menuName));
+/* 75 */
+EXTERN int TkpUseWindow _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * string));
+/* 76 */
+EXTERN int TkpWindowWasRecentlyDeleted _ANSI_ARGS_((Window win,
+ TkDisplay * dispPtr));
+/* 77 */
+EXTERN void TkQueueEventForAllChildren _ANSI_ARGS_((
+ TkWindow * winPtr, XEvent * eventPtr));
+/* 78 */
+EXTERN int TkReadBitmapFile _ANSI_ARGS_((Display* display,
+ Drawable d, CONST char* filename,
+ unsigned int* width_return,
+ unsigned int* height_return,
+ Pixmap* bitmap_return, int* x_hot_return,
+ int* y_hot_return));
+/* 79 */
+EXTERN int TkScrollWindow _ANSI_ARGS_((Tk_Window tkwin, GC gc,
+ int x, int y, int width, int height, int dx,
+ int dy, TkRegion damageRgn));
+/* 80 */
+EXTERN void TkSelDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 81 */
+EXTERN void TkSelEventProc _ANSI_ARGS_((Tk_Window tkwin,
+ XEvent * eventPtr));
+/* 82 */
+EXTERN void TkSelInit _ANSI_ARGS_((Tk_Window tkwin));
+/* 83 */
+EXTERN void TkSelPropProc _ANSI_ARGS_((XEvent * eventPtr));
+/* 84 */
+EXTERN void TkSetClassProcs _ANSI_ARGS_((Tk_Window tkwin,
+ TkClassProcs * procs,
+ ClientData instanceData));
+/* 85 */
+EXTERN void TkSetWindowMenuBar _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, char * oldMenuName,
+ char * menuName));
+/* 86 */
+EXTERN KeySym TkStringToKeysym _ANSI_ARGS_((char * name));
+/* 87 */
+EXTERN int TkThickPolyLineToArea _ANSI_ARGS_((double * coordPtr,
+ int numPoints, double width, int capStyle,
+ int joinStyle, double * rectPtr));
+/* 88 */
+EXTERN void TkWmAddToColormapWindows _ANSI_ARGS_((
+ TkWindow * winPtr));
+/* 89 */
+EXTERN void TkWmDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 90 */
+EXTERN TkWindow * TkWmFocusToplevel _ANSI_ARGS_((TkWindow * winPtr));
+/* 91 */
+EXTERN void TkWmMapWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 92 */
+EXTERN void TkWmNewWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 93 */
+EXTERN void TkWmProtocolEventProc _ANSI_ARGS_((TkWindow * winPtr,
+ XEvent * evenvPtr));
+/* 94 */
+EXTERN void TkWmRemoveFromColormapWindows _ANSI_ARGS_((
+ TkWindow * winPtr));
+/* 95 */
+EXTERN void TkWmRestackToplevel _ANSI_ARGS_((TkWindow * winPtr,
+ int aboveBelow, TkWindow * otherPtr));
+/* 96 */
+EXTERN void TkWmSetClass _ANSI_ARGS_((TkWindow * winPtr));
+/* 97 */
+EXTERN void TkWmUnmapWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 98 */
+EXTERN Tcl_Obj * TkDebugBitmap _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 99 */
+EXTERN Tcl_Obj * TkDebugBorder _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 100 */
+EXTERN Tcl_Obj * TkDebugCursor _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 101 */
+EXTERN Tcl_Obj * TkDebugColor _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 102 */
+EXTERN Tcl_Obj * TkDebugConfig _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_OptionTable table));
+/* 103 */
+EXTERN Tcl_Obj * TkDebugFont _ANSI_ARGS_((Tk_Window tkwin,
+ char * name));
+/* 104 */
+EXTERN int TkFindStateNumObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_Obj * optionPtr,
+ CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr));
+/* 105 */
+EXTERN Tcl_HashTable * TkGetBitmapPredefTable _ANSI_ARGS_((void));
+/* 106 */
+EXTERN TkDisplay * TkGetDisplayList _ANSI_ARGS_((void));
+/* 107 */
+EXTERN TkMainInfo * TkGetMainInfoList _ANSI_ARGS_((void));
+/* 108 */
+EXTERN int TkGetWindowFromObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Window tkwin, Tcl_Obj * objPtr,
+ Tk_Window * windowPtr));
+/* 109 */
+EXTERN char * TkpGetString _ANSI_ARGS_((TkWindow * winPtr,
+ XEvent * eventPtr, Tcl_DString * dsPtr));
+/* 110 */
+EXTERN void TkpGetSubFonts _ANSI_ARGS_((Tcl_Interp * interp,
+ Tk_Font tkfont));
+/* 111 */
+EXTERN Tcl_Obj * TkpGetSystemDefault _ANSI_ARGS_((Tk_Window tkwin,
+ char * dbName, char * className));
+/* 112 */
+EXTERN void TkpMenuThreadInit _ANSI_ARGS_((void));
+#ifdef __WIN32__
+/* 113 */
+EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn,
+ XRectangle* rect_return));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 113 */
+EXTERN void TkClipBox _ANSI_ARGS_((TkRegion rgn,
+ XRectangle* rect_return));
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+/* 114 */
+EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 114 */
+EXTERN TkRegion TkCreateRegion _ANSI_ARGS_((void));
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+/* 115 */
+EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 115 */
+EXTERN void TkDestroyRegion _ANSI_ARGS_((TkRegion rgn));
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+/* 116 */
+EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra,
+ TkRegion srcb, TkRegion dr_return));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 116 */
+EXTERN void TkIntersectRegion _ANSI_ARGS_((TkRegion sra,
+ TkRegion srcb, TkRegion dr_return));
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+/* 117 */
+EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x,
+ int y, unsigned int width,
+ unsigned int height));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 117 */
+EXTERN int TkRectInRegion _ANSI_ARGS_((TkRegion rgn, int x,
+ int y, unsigned int width,
+ unsigned int height));
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+/* 118 */
+EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc,
+ TkRegion rgn));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 118 */
+EXTERN void TkSetRegion _ANSI_ARGS_((Display* display, GC gc,
+ TkRegion rgn));
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+/* 119 */
+EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect,
+ TkRegion src, TkRegion dr_return));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 119 */
+EXTERN void TkUnionRectWithRegion _ANSI_ARGS_((XRectangle* rect,
+ TkRegion src, TkRegion dr_return));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 120 */
+EXTERN void TkGenerateActivateEvents _ANSI_ARGS_((
+ TkWindow * winPtr, int active));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 121 */
+EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display,
+ char * source));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 122 */
+EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 123 */
+EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 124 */
+EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display * display,
+ CONST char * name, int * width, int * height));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 125 */
+EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 126 */
+EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 127 */
+EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 128 */
+EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr,
+ int state));
+#endif /* MAC_TCL */
+/* Slot 129 is reserved */
+#ifdef MAC_TCL
+/* 130 */
+EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 131 */
+EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y,
+ Window window, unsigned int state));
+#endif /* MAC_TCL */
+/* Slot 132 is reserved */
+#ifdef MAC_TCL
+/* 133 */
+EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin));
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+/* 134 */
+EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y, int width, int height,
+ int flags));
+#endif /* MAC_TCL */
+/* 135 */
+EXTERN void TkpDrawHighlightBorder _ANSI_ARGS_((Tk_Window tkwin,
+ GC fgGC, GC bgGC, int highlightWidth,
+ Drawable drawable));
+/* 136 */
+EXTERN void TkSetFocusWin _ANSI_ARGS_((TkWindow * winPtr,
+ int force));
+/* 137 */
+EXTERN void TkpSetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin,
+ KeySym keySym, XEvent * eventPtr));
+/* 138 */
+EXTERN KeySym TkpGetKeySym _ANSI_ARGS_((TkDisplay * dispPtr,
+ XEvent * eventPtr));
+/* 139 */
+EXTERN void TkpInitKeymapInfo _ANSI_ARGS_((TkDisplay * dispPtr));
+
+typedef struct TkIntStubs {
+ int magic;
+ struct TkIntStubHooks *hooks;
+
+ TkWindow * (*tkAllocWindow) _ANSI_ARGS_((TkDisplay * dispPtr, int screenNum, TkWindow * parentPtr)); /* 0 */
+ void (*tkBezierPoints) _ANSI_ARGS_((double control[], int numSteps, double * coordPtr)); /* 1 */
+ void (*tkBezierScreenPoints) _ANSI_ARGS_((Tk_Canvas canvas, double control[], int numSteps, XPoint * xPointPtr)); /* 2 */
+ void (*tkBindDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 3 */
+ void (*tkBindEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 4 */
+ void (*tkBindFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 5 */
+ void (*tkBindInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 6 */
+ void (*tkChangeEventWindow) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 7 */
+ int (*tkClipInit) _ANSI_ARGS_((Tcl_Interp * interp, TkDisplay * dispPtr)); /* 8 */
+ void (*tkComputeAnchor) _ANSI_ARGS_((Tk_Anchor anchor, Tk_Window tkwin, int padX, int padY, int innerWidth, int innerHeight, int * xPtr, int * yPtr)); /* 9 */
+ int (*tkCopyAndGlobalEval) _ANSI_ARGS_((Tcl_Interp * interp, char * script)); /* 10 */
+ unsigned long (*tkCreateBindingProcedure) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable, ClientData object, char * eventString, TkBindEvalProc * evalProc, TkBindFreeProc * freeProc, ClientData clientData)); /* 11 */
+ TkCursor * (*tkCreateCursorFromData) _ANSI_ARGS_((Tk_Window tkwin, char * source, char * mask, int width, int height, int xHot, int yHot, XColor fg, XColor bg)); /* 12 */
+ int (*tkCreateFrame) _ANSI_ARGS_((ClientData clientData, Tcl_Interp * interp, int argc, char ** argv, int toplevel, char * appName)); /* 13 */
+ Tk_Window (*tkCreateMainWindow) _ANSI_ARGS_((Tcl_Interp * interp, char * screenName, char * baseName)); /* 14 */
+ Time (*tkCurrentTime) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 15 */
+ void (*tkDeleteAllImages) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 16 */
+ void (*tkDoConfigureNotify) _ANSI_ARGS_((TkWindow * winPtr)); /* 17 */
+ void (*tkDrawInsetFocusHighlight) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int width, Drawable drawable, int padding)); /* 18 */
+ void (*tkEventDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 19 */
+ void (*tkFillPolygon) _ANSI_ARGS_((Tk_Canvas canvas, double * coordPtr, int numPoints, Display * display, Drawable drawable, GC gc, GC outlineGC)); /* 20 */
+ int (*tkFindStateNum) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * option, CONST TkStateMap * mapPtr, CONST char * strKey)); /* 21 */
+ char * (*tkFindStateString) _ANSI_ARGS_((CONST TkStateMap * mapPtr, int numKey)); /* 22 */
+ void (*tkFocusDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 23 */
+ int (*tkFocusFilterEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 24 */
+ TkWindow * (*tkFocusKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 25 */
+ void (*tkFontPkgInit) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 26 */
+ void (*tkFontPkgFree) _ANSI_ARGS_((TkMainInfo * mainPtr)); /* 27 */
+ void (*tkFreeBindingTags) _ANSI_ARGS_((TkWindow * winPtr)); /* 28 */
+ void (*tkpFreeCursor) _ANSI_ARGS_((TkCursor * cursorPtr)); /* 29 */
+ char * (*tkGetBitmapData) _ANSI_ARGS_((Tcl_Interp * interp, char * string, char * fileName, int * widthPtr, int * heightPtr, int * hotXPtr, int * hotYPtr)); /* 30 */
+ void (*tkGetButtPoints) _ANSI_ARGS_((double p1[], double p2[], double width, int project, double m1[], double m2[])); /* 31 */
+ TkCursor * (*tkGetCursorByName) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tk_Uid string)); /* 32 */
+ char * (*tkGetDefaultScreenName) _ANSI_ARGS_((Tcl_Interp * interp, char * screenName)); /* 33 */
+ TkDisplay * (*tkGetDisplay) _ANSI_ARGS_((Display * display)); /* 34 */
+ int (*tkGetDisplayOf) _ANSI_ARGS_((Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[], Tk_Window * tkwinPtr)); /* 35 */
+ TkWindow * (*tkGetFocusWin) _ANSI_ARGS_((TkWindow * winPtr)); /* 36 */
+ int (*tkGetInterpNames) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 37 */
+ int (*tkGetMiterPoints) _ANSI_ARGS_((double p1[], double p2[], double p3[], double width, double m1[], double m2[])); /* 38 */
+ void (*tkGetPointerCoords) _ANSI_ARGS_((Tk_Window tkwin, int * xPtr, int * yPtr)); /* 39 */
+ void (*tkGetServerInfo) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin)); /* 40 */
+ void (*tkGrabDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 41 */
+ int (*tkGrabState) _ANSI_ARGS_((TkWindow * winPtr)); /* 42 */
+ void (*tkIncludePoint) _ANSI_ARGS_((Tk_Item * itemPtr, double * pointPtr)); /* 43 */
+ void (*tkInOutEvents) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * sourcePtr, TkWindow * destPtr, int leaveType, int enterType, Tcl_QueuePosition position)); /* 44 */
+ void (*tkInstallFrameMenu) _ANSI_ARGS_((Tk_Window tkwin)); /* 45 */
+ char * (*tkKeysymToString) _ANSI_ARGS_((KeySym keysym)); /* 46 */
+ int (*tkLineToArea) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double rectPtr[])); /* 47 */
+ double (*tkLineToPoint) _ANSI_ARGS_((double end1Ptr[], double end2Ptr[], double pointPtr[])); /* 48 */
+ int (*tkMakeBezierCurve) _ANSI_ARGS_((Tk_Canvas canvas, double * pointPtr, int numPoints, int numSteps, XPoint xPoints[], double dblPoints[])); /* 49 */
+ void (*tkMakeBezierPostscript) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Canvas canvas, double * pointPtr, int numPoints)); /* 50 */
+ void (*tkOptionClassChanged) _ANSI_ARGS_((TkWindow * winPtr)); /* 51 */
+ void (*tkOptionDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 52 */
+ int (*tkOvalToArea) _ANSI_ARGS_((double * ovalPtr, double * rectPtr)); /* 53 */
+ double (*tkOvalToPoint) _ANSI_ARGS_((double ovalPtr[], double width, int filled, double pointPtr[])); /* 54 */
+ int (*tkpChangeFocus) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 55 */
+ void (*tkpCloseDisplay) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 56 */
+ void (*tkpClaimFocus) _ANSI_ARGS_((TkWindow * topLevelPtr, int force)); /* 57 */
+ void (*tkpDisplayWarning) _ANSI_ARGS_((char * msg, char * title)); /* 58 */
+ void (*tkpGetAppName) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_DString * name)); /* 59 */
+ TkWindow * (*tkpGetOtherWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 60 */
+ TkWindow * (*tkpGetWrapperWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 61 */
+ int (*tkpInit) _ANSI_ARGS_((Tcl_Interp * interp)); /* 62 */
+ void (*tkpInitializeMenuBindings) _ANSI_ARGS_((Tcl_Interp * interp, Tk_BindingTable bindingTable)); /* 63 */
+ void (*tkpMakeContainer) _ANSI_ARGS_((Tk_Window tkwin)); /* 64 */
+ void (*tkpMakeMenuWindow) _ANSI_ARGS_((Tk_Window tkwin, int transient)); /* 65 */
+ Window (*tkpMakeWindow) _ANSI_ARGS_((TkWindow * winPtr, Window parent)); /* 66 */
+ void (*tkpMenuNotifyToplevelCreate) _ANSI_ARGS_((Tcl_Interp * interp1, char * menuName)); /* 67 */
+ TkDisplay * (*tkpOpenDisplay) _ANSI_ARGS_((char * display_name)); /* 68 */
+ int (*tkPointerEvent) _ANSI_ARGS_((XEvent * eventPtr, TkWindow * winPtr)); /* 69 */
+ int (*tkPolygonToArea) _ANSI_ARGS_((double * polyPtr, int numPoints, double * rectPtr)); /* 70 */
+ double (*tkPolygonToPoint) _ANSI_ARGS_((double * polyPtr, int numPoints, double * pointPtr)); /* 71 */
+ int (*tkPositionInTree) _ANSI_ARGS_((TkWindow * winPtr, TkWindow * treePtr)); /* 72 */
+ void (*tkpRedirectKeyEvent) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 73 */
+ void (*tkpSetMainMenubar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * menuName)); /* 74 */
+ int (*tkpUseWindow) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * string)); /* 75 */
+ int (*tkpWindowWasRecentlyDeleted) _ANSI_ARGS_((Window win, TkDisplay * dispPtr)); /* 76 */
+ void (*tkQueueEventForAllChildren) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr)); /* 77 */
+ int (*tkReadBitmapFile) _ANSI_ARGS_((Display* display, Drawable d, CONST char* filename, unsigned int* width_return, unsigned int* height_return, Pixmap* bitmap_return, int* x_hot_return, int* y_hot_return)); /* 78 */
+ int (*tkScrollWindow) _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x, int y, int width, int height, int dx, int dy, TkRegion damageRgn)); /* 79 */
+ void (*tkSelDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 80 */
+ void (*tkSelEventProc) _ANSI_ARGS_((Tk_Window tkwin, XEvent * eventPtr)); /* 81 */
+ void (*tkSelInit) _ANSI_ARGS_((Tk_Window tkwin)); /* 82 */
+ void (*tkSelPropProc) _ANSI_ARGS_((XEvent * eventPtr)); /* 83 */
+ void (*tkSetClassProcs) _ANSI_ARGS_((Tk_Window tkwin, TkClassProcs * procs, ClientData instanceData)); /* 84 */
+ void (*tkSetWindowMenuBar) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, char * oldMenuName, char * menuName)); /* 85 */
+ KeySym (*tkStringToKeysym) _ANSI_ARGS_((char * name)); /* 86 */
+ int (*tkThickPolyLineToArea) _ANSI_ARGS_((double * coordPtr, int numPoints, double width, int capStyle, int joinStyle, double * rectPtr)); /* 87 */
+ void (*tkWmAddToColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 88 */
+ void (*tkWmDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 89 */
+ TkWindow * (*tkWmFocusToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 90 */
+ void (*tkWmMapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 91 */
+ void (*tkWmNewWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 92 */
+ void (*tkWmProtocolEventProc) _ANSI_ARGS_((TkWindow * winPtr, XEvent * evenvPtr)); /* 93 */
+ void (*tkWmRemoveFromColormapWindows) _ANSI_ARGS_((TkWindow * winPtr)); /* 94 */
+ void (*tkWmRestackToplevel) _ANSI_ARGS_((TkWindow * winPtr, int aboveBelow, TkWindow * otherPtr)); /* 95 */
+ void (*tkWmSetClass) _ANSI_ARGS_((TkWindow * winPtr)); /* 96 */
+ void (*tkWmUnmapWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 97 */
+ Tcl_Obj * (*tkDebugBitmap) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 98 */
+ Tcl_Obj * (*tkDebugBorder) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 99 */
+ Tcl_Obj * (*tkDebugCursor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 100 */
+ Tcl_Obj * (*tkDebugColor) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 101 */
+ Tcl_Obj * (*tkDebugConfig) _ANSI_ARGS_((Tcl_Interp * interp, Tk_OptionTable table)); /* 102 */
+ Tcl_Obj * (*tkDebugFont) _ANSI_ARGS_((Tk_Window tkwin, char * name)); /* 103 */
+ int (*tkFindStateNumObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * optionPtr, CONST TkStateMap * mapPtr, Tcl_Obj * keyPtr)); /* 104 */
+ Tcl_HashTable * (*tkGetBitmapPredefTable) _ANSI_ARGS_((void)); /* 105 */
+ TkDisplay * (*tkGetDisplayList) _ANSI_ARGS_((void)); /* 106 */
+ TkMainInfo * (*tkGetMainInfoList) _ANSI_ARGS_((void)); /* 107 */
+ int (*tkGetWindowFromObj) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Window tkwin, Tcl_Obj * objPtr, Tk_Window * windowPtr)); /* 108 */
+ char * (*tkpGetString) _ANSI_ARGS_((TkWindow * winPtr, XEvent * eventPtr, Tcl_DString * dsPtr)); /* 109 */
+ void (*tkpGetSubFonts) _ANSI_ARGS_((Tcl_Interp * interp, Tk_Font tkfont)); /* 110 */
+ Tcl_Obj * (*tkpGetSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, char * dbName, char * className)); /* 111 */
+ void (*tkpMenuThreadInit) _ANSI_ARGS_((void)); /* 112 */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved113;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkClipBox) _ANSI_ARGS_((TkRegion rgn, XRectangle* rect_return)); /* 113 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved114;
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkRegion (*tkCreateRegion) _ANSI_ARGS_((void)); /* 114 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved115;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkDestroyRegion) _ANSI_ARGS_((TkRegion rgn)); /* 115 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved116;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkIntersectRegion) _ANSI_ARGS_((TkRegion sra, TkRegion srcb, TkRegion dr_return)); /* 116 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved117;
+#endif /* UNIX */
+#ifdef __WIN32__
+ int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ int (*tkRectInRegion) _ANSI_ARGS_((TkRegion rgn, int x, int y, unsigned int width, unsigned int height)); /* 117 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved118;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkSetRegion) _ANSI_ARGS_((Display* display, GC gc, TkRegion rgn)); /* 118 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved119;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkUnionRectWithRegion) _ANSI_ARGS_((XRectangle* rect, TkRegion src, TkRegion dr_return)); /* 119 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved120;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved120;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 120 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved121;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved121;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, char * source)); /* 121 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved122;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved122;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 122 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved123;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved123;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 123 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved124;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved124;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display * display, CONST char * name, int * width, int * height)); /* 124 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved125;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved125;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 125 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved126;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved126;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 126 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved127;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved127;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 127 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved128;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved128;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 128 */
+#endif /* MAC_TCL */
+ void *reserved129;
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved130;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved130;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 130 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved131;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved131;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 131 */
+#endif /* MAC_TCL */
+ void *reserved132;
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved133;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved133;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 133 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void *reserved134;
+#endif /* UNIX */
+#ifdef __WIN32__
+ void *reserved134;
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 134 */
+#endif /* MAC_TCL */
+ void (*tkpDrawHighlightBorder) _ANSI_ARGS_((Tk_Window tkwin, GC fgGC, GC bgGC, int highlightWidth, Drawable drawable)); /* 135 */
+ void (*tkSetFocusWin) _ANSI_ARGS_((TkWindow * winPtr, int force)); /* 136 */
+ void (*tkpSetKeycodeAndState) _ANSI_ARGS_((Tk_Window tkwin, KeySym keySym, XEvent * eventPtr)); /* 137 */
+ KeySym (*tkpGetKeySym) _ANSI_ARGS_((TkDisplay * dispPtr, XEvent * eventPtr)); /* 138 */
+ void (*tkpInitKeymapInfo) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 139 */
+} TkIntStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern TkIntStubs *tkIntStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifndef TkAllocWindow
+#define TkAllocWindow \
+ (tkIntStubsPtr->tkAllocWindow) /* 0 */
+#endif
+#ifndef TkBezierPoints
+#define TkBezierPoints \
+ (tkIntStubsPtr->tkBezierPoints) /* 1 */
+#endif
+#ifndef TkBezierScreenPoints
+#define TkBezierScreenPoints \
+ (tkIntStubsPtr->tkBezierScreenPoints) /* 2 */
+#endif
+#ifndef TkBindDeadWindow
+#define TkBindDeadWindow \
+ (tkIntStubsPtr->tkBindDeadWindow) /* 3 */
+#endif
+#ifndef TkBindEventProc
+#define TkBindEventProc \
+ (tkIntStubsPtr->tkBindEventProc) /* 4 */
+#endif
+#ifndef TkBindFree
+#define TkBindFree \
+ (tkIntStubsPtr->tkBindFree) /* 5 */
+#endif
+#ifndef TkBindInit
+#define TkBindInit \
+ (tkIntStubsPtr->tkBindInit) /* 6 */
+#endif
+#ifndef TkChangeEventWindow
+#define TkChangeEventWindow \
+ (tkIntStubsPtr->tkChangeEventWindow) /* 7 */
+#endif
+#ifndef TkClipInit
+#define TkClipInit \
+ (tkIntStubsPtr->tkClipInit) /* 8 */
+#endif
+#ifndef TkComputeAnchor
+#define TkComputeAnchor \
+ (tkIntStubsPtr->tkComputeAnchor) /* 9 */
+#endif
+#ifndef TkCopyAndGlobalEval
+#define TkCopyAndGlobalEval \
+ (tkIntStubsPtr->tkCopyAndGlobalEval) /* 10 */
+#endif
+#ifndef TkCreateBindingProcedure
+#define TkCreateBindingProcedure \
+ (tkIntStubsPtr->tkCreateBindingProcedure) /* 11 */
+#endif
+#ifndef TkCreateCursorFromData
+#define TkCreateCursorFromData \
+ (tkIntStubsPtr->tkCreateCursorFromData) /* 12 */
+#endif
+#ifndef TkCreateFrame
+#define TkCreateFrame \
+ (tkIntStubsPtr->tkCreateFrame) /* 13 */
+#endif
+#ifndef TkCreateMainWindow
+#define TkCreateMainWindow \
+ (tkIntStubsPtr->tkCreateMainWindow) /* 14 */
+#endif
+#ifndef TkCurrentTime
+#define TkCurrentTime \
+ (tkIntStubsPtr->tkCurrentTime) /* 15 */
+#endif
+#ifndef TkDeleteAllImages
+#define TkDeleteAllImages \
+ (tkIntStubsPtr->tkDeleteAllImages) /* 16 */
+#endif
+#ifndef TkDoConfigureNotify
+#define TkDoConfigureNotify \
+ (tkIntStubsPtr->tkDoConfigureNotify) /* 17 */
+#endif
+#ifndef TkDrawInsetFocusHighlight
+#define TkDrawInsetFocusHighlight \
+ (tkIntStubsPtr->tkDrawInsetFocusHighlight) /* 18 */
+#endif
+#ifndef TkEventDeadWindow
+#define TkEventDeadWindow \
+ (tkIntStubsPtr->tkEventDeadWindow) /* 19 */
+#endif
+#ifndef TkFillPolygon
+#define TkFillPolygon \
+ (tkIntStubsPtr->tkFillPolygon) /* 20 */
+#endif
+#ifndef TkFindStateNum
+#define TkFindStateNum \
+ (tkIntStubsPtr->tkFindStateNum) /* 21 */
+#endif
+#ifndef TkFindStateString
+#define TkFindStateString \
+ (tkIntStubsPtr->tkFindStateString) /* 22 */
+#endif
+#ifndef TkFocusDeadWindow
+#define TkFocusDeadWindow \
+ (tkIntStubsPtr->tkFocusDeadWindow) /* 23 */
+#endif
+#ifndef TkFocusFilterEvent
+#define TkFocusFilterEvent \
+ (tkIntStubsPtr->tkFocusFilterEvent) /* 24 */
+#endif
+#ifndef TkFocusKeyEvent
+#define TkFocusKeyEvent \
+ (tkIntStubsPtr->tkFocusKeyEvent) /* 25 */
+#endif
+#ifndef TkFontPkgInit
+#define TkFontPkgInit \
+ (tkIntStubsPtr->tkFontPkgInit) /* 26 */
+#endif
+#ifndef TkFontPkgFree
+#define TkFontPkgFree \
+ (tkIntStubsPtr->tkFontPkgFree) /* 27 */
+#endif
+#ifndef TkFreeBindingTags
+#define TkFreeBindingTags \
+ (tkIntStubsPtr->tkFreeBindingTags) /* 28 */
+#endif
+#ifndef TkpFreeCursor
+#define TkpFreeCursor \
+ (tkIntStubsPtr->tkpFreeCursor) /* 29 */
+#endif
+#ifndef TkGetBitmapData
+#define TkGetBitmapData \
+ (tkIntStubsPtr->tkGetBitmapData) /* 30 */
+#endif
+#ifndef TkGetButtPoints
+#define TkGetButtPoints \
+ (tkIntStubsPtr->tkGetButtPoints) /* 31 */
+#endif
+#ifndef TkGetCursorByName
+#define TkGetCursorByName \
+ (tkIntStubsPtr->tkGetCursorByName) /* 32 */
+#endif
+#ifndef TkGetDefaultScreenName
+#define TkGetDefaultScreenName \
+ (tkIntStubsPtr->tkGetDefaultScreenName) /* 33 */
+#endif
+#ifndef TkGetDisplay
+#define TkGetDisplay \
+ (tkIntStubsPtr->tkGetDisplay) /* 34 */
+#endif
+#ifndef TkGetDisplayOf
+#define TkGetDisplayOf \
+ (tkIntStubsPtr->tkGetDisplayOf) /* 35 */
+#endif
+#ifndef TkGetFocusWin
+#define TkGetFocusWin \
+ (tkIntStubsPtr->tkGetFocusWin) /* 36 */
+#endif
+#ifndef TkGetInterpNames
+#define TkGetInterpNames \
+ (tkIntStubsPtr->tkGetInterpNames) /* 37 */
+#endif
+#ifndef TkGetMiterPoints
+#define TkGetMiterPoints \
+ (tkIntStubsPtr->tkGetMiterPoints) /* 38 */
+#endif
+#ifndef TkGetPointerCoords
+#define TkGetPointerCoords \
+ (tkIntStubsPtr->tkGetPointerCoords) /* 39 */
+#endif
+#ifndef TkGetServerInfo
+#define TkGetServerInfo \
+ (tkIntStubsPtr->tkGetServerInfo) /* 40 */
+#endif
+#ifndef TkGrabDeadWindow
+#define TkGrabDeadWindow \
+ (tkIntStubsPtr->tkGrabDeadWindow) /* 41 */
+#endif
+#ifndef TkGrabState
+#define TkGrabState \
+ (tkIntStubsPtr->tkGrabState) /* 42 */
+#endif
+#ifndef TkIncludePoint
+#define TkIncludePoint \
+ (tkIntStubsPtr->tkIncludePoint) /* 43 */
+#endif
+#ifndef TkInOutEvents
+#define TkInOutEvents \
+ (tkIntStubsPtr->tkInOutEvents) /* 44 */
+#endif
+#ifndef TkInstallFrameMenu
+#define TkInstallFrameMenu \
+ (tkIntStubsPtr->tkInstallFrameMenu) /* 45 */
+#endif
+#ifndef TkKeysymToString
+#define TkKeysymToString \
+ (tkIntStubsPtr->tkKeysymToString) /* 46 */
+#endif
+#ifndef TkLineToArea
+#define TkLineToArea \
+ (tkIntStubsPtr->tkLineToArea) /* 47 */
+#endif
+#ifndef TkLineToPoint
+#define TkLineToPoint \
+ (tkIntStubsPtr->tkLineToPoint) /* 48 */
+#endif
+#ifndef TkMakeBezierCurve
+#define TkMakeBezierCurve \
+ (tkIntStubsPtr->tkMakeBezierCurve) /* 49 */
+#endif
+#ifndef TkMakeBezierPostscript
+#define TkMakeBezierPostscript \
+ (tkIntStubsPtr->tkMakeBezierPostscript) /* 50 */
+#endif
+#ifndef TkOptionClassChanged
+#define TkOptionClassChanged \
+ (tkIntStubsPtr->tkOptionClassChanged) /* 51 */
+#endif
+#ifndef TkOptionDeadWindow
+#define TkOptionDeadWindow \
+ (tkIntStubsPtr->tkOptionDeadWindow) /* 52 */
+#endif
+#ifndef TkOvalToArea
+#define TkOvalToArea \
+ (tkIntStubsPtr->tkOvalToArea) /* 53 */
+#endif
+#ifndef TkOvalToPoint
+#define TkOvalToPoint \
+ (tkIntStubsPtr->tkOvalToPoint) /* 54 */
+#endif
+#ifndef TkpChangeFocus
+#define TkpChangeFocus \
+ (tkIntStubsPtr->tkpChangeFocus) /* 55 */
+#endif
+#ifndef TkpCloseDisplay
+#define TkpCloseDisplay \
+ (tkIntStubsPtr->tkpCloseDisplay) /* 56 */
+#endif
+#ifndef TkpClaimFocus
+#define TkpClaimFocus \
+ (tkIntStubsPtr->tkpClaimFocus) /* 57 */
+#endif
+#ifndef TkpDisplayWarning
+#define TkpDisplayWarning \
+ (tkIntStubsPtr->tkpDisplayWarning) /* 58 */
+#endif
+#ifndef TkpGetAppName
+#define TkpGetAppName \
+ (tkIntStubsPtr->tkpGetAppName) /* 59 */
+#endif
+#ifndef TkpGetOtherWindow
+#define TkpGetOtherWindow \
+ (tkIntStubsPtr->tkpGetOtherWindow) /* 60 */
+#endif
+#ifndef TkpGetWrapperWindow
+#define TkpGetWrapperWindow \
+ (tkIntStubsPtr->tkpGetWrapperWindow) /* 61 */
+#endif
+#ifndef TkpInit
+#define TkpInit \
+ (tkIntStubsPtr->tkpInit) /* 62 */
+#endif
+#ifndef TkpInitializeMenuBindings
+#define TkpInitializeMenuBindings \
+ (tkIntStubsPtr->tkpInitializeMenuBindings) /* 63 */
+#endif
+#ifndef TkpMakeContainer
+#define TkpMakeContainer \
+ (tkIntStubsPtr->tkpMakeContainer) /* 64 */
+#endif
+#ifndef TkpMakeMenuWindow
+#define TkpMakeMenuWindow \
+ (tkIntStubsPtr->tkpMakeMenuWindow) /* 65 */
+#endif
+#ifndef TkpMakeWindow
+#define TkpMakeWindow \
+ (tkIntStubsPtr->tkpMakeWindow) /* 66 */
+#endif
+#ifndef TkpMenuNotifyToplevelCreate
+#define TkpMenuNotifyToplevelCreate \
+ (tkIntStubsPtr->tkpMenuNotifyToplevelCreate) /* 67 */
+#endif
+#ifndef TkpOpenDisplay
+#define TkpOpenDisplay \
+ (tkIntStubsPtr->tkpOpenDisplay) /* 68 */
+#endif
+#ifndef TkPointerEvent
+#define TkPointerEvent \
+ (tkIntStubsPtr->tkPointerEvent) /* 69 */
+#endif
+#ifndef TkPolygonToArea
+#define TkPolygonToArea \
+ (tkIntStubsPtr->tkPolygonToArea) /* 70 */
+#endif
+#ifndef TkPolygonToPoint
+#define TkPolygonToPoint \
+ (tkIntStubsPtr->tkPolygonToPoint) /* 71 */
+#endif
+#ifndef TkPositionInTree
+#define TkPositionInTree \
+ (tkIntStubsPtr->tkPositionInTree) /* 72 */
+#endif
+#ifndef TkpRedirectKeyEvent
+#define TkpRedirectKeyEvent \
+ (tkIntStubsPtr->tkpRedirectKeyEvent) /* 73 */
+#endif
+#ifndef TkpSetMainMenubar
+#define TkpSetMainMenubar \
+ (tkIntStubsPtr->tkpSetMainMenubar) /* 74 */
+#endif
+#ifndef TkpUseWindow
+#define TkpUseWindow \
+ (tkIntStubsPtr->tkpUseWindow) /* 75 */
+#endif
+#ifndef TkpWindowWasRecentlyDeleted
+#define TkpWindowWasRecentlyDeleted \
+ (tkIntStubsPtr->tkpWindowWasRecentlyDeleted) /* 76 */
+#endif
+#ifndef TkQueueEventForAllChildren
+#define TkQueueEventForAllChildren \
+ (tkIntStubsPtr->tkQueueEventForAllChildren) /* 77 */
+#endif
+#ifndef TkReadBitmapFile
+#define TkReadBitmapFile \
+ (tkIntStubsPtr->tkReadBitmapFile) /* 78 */
+#endif
+#ifndef TkScrollWindow
+#define TkScrollWindow \
+ (tkIntStubsPtr->tkScrollWindow) /* 79 */
+#endif
+#ifndef TkSelDeadWindow
+#define TkSelDeadWindow \
+ (tkIntStubsPtr->tkSelDeadWindow) /* 80 */
+#endif
+#ifndef TkSelEventProc
+#define TkSelEventProc \
+ (tkIntStubsPtr->tkSelEventProc) /* 81 */
+#endif
+#ifndef TkSelInit
+#define TkSelInit \
+ (tkIntStubsPtr->tkSelInit) /* 82 */
+#endif
+#ifndef TkSelPropProc
+#define TkSelPropProc \
+ (tkIntStubsPtr->tkSelPropProc) /* 83 */
+#endif
+#ifndef TkSetClassProcs
+#define TkSetClassProcs \
+ (tkIntStubsPtr->tkSetClassProcs) /* 84 */
+#endif
+#ifndef TkSetWindowMenuBar
+#define TkSetWindowMenuBar \
+ (tkIntStubsPtr->tkSetWindowMenuBar) /* 85 */
+#endif
+#ifndef TkStringToKeysym
+#define TkStringToKeysym \
+ (tkIntStubsPtr->tkStringToKeysym) /* 86 */
+#endif
+#ifndef TkThickPolyLineToArea
+#define TkThickPolyLineToArea \
+ (tkIntStubsPtr->tkThickPolyLineToArea) /* 87 */
+#endif
+#ifndef TkWmAddToColormapWindows
+#define TkWmAddToColormapWindows \
+ (tkIntStubsPtr->tkWmAddToColormapWindows) /* 88 */
+#endif
+#ifndef TkWmDeadWindow
+#define TkWmDeadWindow \
+ (tkIntStubsPtr->tkWmDeadWindow) /* 89 */
+#endif
+#ifndef TkWmFocusToplevel
+#define TkWmFocusToplevel \
+ (tkIntStubsPtr->tkWmFocusToplevel) /* 90 */
+#endif
+#ifndef TkWmMapWindow
+#define TkWmMapWindow \
+ (tkIntStubsPtr->tkWmMapWindow) /* 91 */
+#endif
+#ifndef TkWmNewWindow
+#define TkWmNewWindow \
+ (tkIntStubsPtr->tkWmNewWindow) /* 92 */
+#endif
+#ifndef TkWmProtocolEventProc
+#define TkWmProtocolEventProc \
+ (tkIntStubsPtr->tkWmProtocolEventProc) /* 93 */
+#endif
+#ifndef TkWmRemoveFromColormapWindows
+#define TkWmRemoveFromColormapWindows \
+ (tkIntStubsPtr->tkWmRemoveFromColormapWindows) /* 94 */
+#endif
+#ifndef TkWmRestackToplevel
+#define TkWmRestackToplevel \
+ (tkIntStubsPtr->tkWmRestackToplevel) /* 95 */
+#endif
+#ifndef TkWmSetClass
+#define TkWmSetClass \
+ (tkIntStubsPtr->tkWmSetClass) /* 96 */
+#endif
+#ifndef TkWmUnmapWindow
+#define TkWmUnmapWindow \
+ (tkIntStubsPtr->tkWmUnmapWindow) /* 97 */
+#endif
+#ifndef TkDebugBitmap
+#define TkDebugBitmap \
+ (tkIntStubsPtr->tkDebugBitmap) /* 98 */
+#endif
+#ifndef TkDebugBorder
+#define TkDebugBorder \
+ (tkIntStubsPtr->tkDebugBorder) /* 99 */
+#endif
+#ifndef TkDebugCursor
+#define TkDebugCursor \
+ (tkIntStubsPtr->tkDebugCursor) /* 100 */
+#endif
+#ifndef TkDebugColor
+#define TkDebugColor \
+ (tkIntStubsPtr->tkDebugColor) /* 101 */
+#endif
+#ifndef TkDebugConfig
+#define TkDebugConfig \
+ (tkIntStubsPtr->tkDebugConfig) /* 102 */
+#endif
+#ifndef TkDebugFont
+#define TkDebugFont \
+ (tkIntStubsPtr->tkDebugFont) /* 103 */
+#endif
+#ifndef TkFindStateNumObj
+#define TkFindStateNumObj \
+ (tkIntStubsPtr->tkFindStateNumObj) /* 104 */
+#endif
+#ifndef TkGetBitmapPredefTable
+#define TkGetBitmapPredefTable \
+ (tkIntStubsPtr->tkGetBitmapPredefTable) /* 105 */
+#endif
+#ifndef TkGetDisplayList
+#define TkGetDisplayList \
+ (tkIntStubsPtr->tkGetDisplayList) /* 106 */
+#endif
+#ifndef TkGetMainInfoList
+#define TkGetMainInfoList \
+ (tkIntStubsPtr->tkGetMainInfoList) /* 107 */
+#endif
+#ifndef TkGetWindowFromObj
+#define TkGetWindowFromObj \
+ (tkIntStubsPtr->tkGetWindowFromObj) /* 108 */
+#endif
+#ifndef TkpGetString
+#define TkpGetString \
+ (tkIntStubsPtr->tkpGetString) /* 109 */
+#endif
+#ifndef TkpGetSubFonts
+#define TkpGetSubFonts \
+ (tkIntStubsPtr->tkpGetSubFonts) /* 110 */
+#endif
+#ifndef TkpGetSystemDefault
+#define TkpGetSystemDefault \
+ (tkIntStubsPtr->tkpGetSystemDefault) /* 111 */
+#endif
+#ifndef TkpMenuThreadInit
+#define TkpMenuThreadInit \
+ (tkIntStubsPtr->tkpMenuThreadInit) /* 112 */
+#endif
+#ifdef __WIN32__
+#ifndef TkClipBox
+#define TkClipBox \
+ (tkIntStubsPtr->tkClipBox) /* 113 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkClipBox
+#define TkClipBox \
+ (tkIntStubsPtr->tkClipBox) /* 113 */
+#endif
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+#ifndef TkCreateRegion
+#define TkCreateRegion \
+ (tkIntStubsPtr->tkCreateRegion) /* 114 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkCreateRegion
+#define TkCreateRegion \
+ (tkIntStubsPtr->tkCreateRegion) /* 114 */
+#endif
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+#ifndef TkDestroyRegion
+#define TkDestroyRegion \
+ (tkIntStubsPtr->tkDestroyRegion) /* 115 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkDestroyRegion
+#define TkDestroyRegion \
+ (tkIntStubsPtr->tkDestroyRegion) /* 115 */
+#endif
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+#ifndef TkIntersectRegion
+#define TkIntersectRegion \
+ (tkIntStubsPtr->tkIntersectRegion) /* 116 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkIntersectRegion
+#define TkIntersectRegion \
+ (tkIntStubsPtr->tkIntersectRegion) /* 116 */
+#endif
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+#ifndef TkRectInRegion
+#define TkRectInRegion \
+ (tkIntStubsPtr->tkRectInRegion) /* 117 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkRectInRegion
+#define TkRectInRegion \
+ (tkIntStubsPtr->tkRectInRegion) /* 117 */
+#endif
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+#ifndef TkSetRegion
+#define TkSetRegion \
+ (tkIntStubsPtr->tkSetRegion) /* 118 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkSetRegion
+#define TkSetRegion \
+ (tkIntStubsPtr->tkSetRegion) /* 118 */
+#endif
+#endif /* MAC_TCL */
+#ifdef __WIN32__
+#ifndef TkUnionRectWithRegion
+#define TkUnionRectWithRegion \
+ (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkUnionRectWithRegion
+#define TkUnionRectWithRegion \
+ (tkIntStubsPtr->tkUnionRectWithRegion) /* 119 */
+#endif
+#endif /* MAC_TCL */
+
+#ifdef MAC_TCL
+#ifndef TkGenerateActivateEvents
+#define TkGenerateActivateEvents \
+ (tkIntStubsPtr->tkGenerateActivateEvents) /* 120 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpCreateNativeBitmap
+#define TkpCreateNativeBitmap \
+ (tkIntStubsPtr->tkpCreateNativeBitmap) /* 121 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpDefineNativeBitmaps
+#define TkpDefineNativeBitmaps \
+ (tkIntStubsPtr->tkpDefineNativeBitmaps) /* 122 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpGetMS
+#define TkpGetMS \
+ (tkIntStubsPtr->tkpGetMS) /* 123 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpGetNativeAppBitmap
+#define TkpGetNativeAppBitmap \
+ (tkIntStubsPtr->tkpGetNativeAppBitmap) /* 124 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkPointerDeadWindow
+#define TkPointerDeadWindow \
+ (tkIntStubsPtr->tkPointerDeadWindow) /* 125 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpSetCapture
+#define TkpSetCapture \
+ (tkIntStubsPtr->tkpSetCapture) /* 126 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpSetCursor
+#define TkpSetCursor \
+ (tkIntStubsPtr->tkpSetCursor) /* 127 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkpWmSetState
+#define TkpWmSetState \
+ (tkIntStubsPtr->tkpWmSetState) /* 128 */
+#endif
+#endif /* MAC_TCL */
+/* Slot 129 is reserved */
+#ifdef MAC_TCL
+#ifndef TkGetTransientMaster
+#define TkGetTransientMaster \
+ (tkIntStubsPtr->tkGetTransientMaster) /* 130 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkGenerateButtonEvent
+#define TkGenerateButtonEvent \
+ (tkIntStubsPtr->tkGenerateButtonEvent) /* 131 */
+#endif
+#endif /* MAC_TCL */
+/* Slot 132 is reserved */
+#ifdef MAC_TCL
+#ifndef TkGenWMDestroyEvent
+#define TkGenWMDestroyEvent \
+ (tkIntStubsPtr->tkGenWMDestroyEvent) /* 133 */
+#endif
+#endif /* MAC_TCL */
+#ifdef MAC_TCL
+#ifndef TkGenWMConfigureEvent
+#define TkGenWMConfigureEvent \
+ (tkIntStubsPtr->tkGenWMConfigureEvent) /* 134 */
+#endif
+#endif /* MAC_TCL */
+#ifndef TkpDrawHighlightBorder
+#define TkpDrawHighlightBorder \
+ (tkIntStubsPtr->tkpDrawHighlightBorder) /* 135 */
+#endif
+#ifndef TkSetFocusWin
+#define TkSetFocusWin \
+ (tkIntStubsPtr->tkSetFocusWin) /* 136 */
+#endif
+#ifndef TkpSetKeycodeAndState
+#define TkpSetKeycodeAndState \
+ (tkIntStubsPtr->tkpSetKeycodeAndState) /* 137 */
+#endif
+#ifndef TkpGetKeySym
+#define TkpGetKeySym \
+ (tkIntStubsPtr->tkpGetKeySym) /* 138 */
+#endif
+#ifndef TkpInitKeymapInfo
+#define TkpInitKeymapInfo \
+ (tkIntStubsPtr->tkpInitKeymapInfo) /* 139 */
+#endif
+
+#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKINTDECLS */
+
+
diff --git a/tk/generic/tkIntPlatDecls.h b/tk/generic/tkIntPlatDecls.h
new file mode 100644
index 00000000000..d3240233fe8
--- /dev/null
+++ b/tk/generic/tkIntPlatDecls.h
@@ -0,0 +1,885 @@
+/*
+ * tkIntPlatDecls.h --
+ *
+ * This file contains the declarations for all platform dependent
+ * unsupported functions that are exported by the Tk library. These
+ * interfaces are not guaranteed to remain the same between
+ * versions. Use at your own risk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ * All rights reserved.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifndef _TKINTPLATDECLS
+#define _TKINTPLATDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tkInt.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+/*
+ * Exported function declarations:
+ */
+
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+/* 0 */
+EXTERN void TkCreateXEventSource _ANSI_ARGS_((void));
+/* 1 */
+EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay * dispPtr,
+ Window w));
+/* 2 */
+EXTERN void TkInitXId _ANSI_ARGS_((TkDisplay * dispPtr));
+/* 3 */
+EXTERN int TkpCmapStressed _ANSI_ARGS_((Tk_Window tkwin,
+ Colormap colormap));
+/* 4 */
+EXTERN void TkpSync _ANSI_ARGS_((Display * display));
+/* 5 */
+EXTERN Window TkUnixContainerId _ANSI_ARGS_((TkWindow * winPtr));
+/* 6 */
+EXTERN int TkUnixDoOneXEvent _ANSI_ARGS_((Tcl_Time * timePtr));
+/* 7 */
+EXTERN void TkUnixSetMenubar _ANSI_ARGS_((Tk_Window tkwin,
+ Tk_Window menubar));
+#endif /* UNIX */
+#ifdef __WIN32__
+/* 0 */
+EXTERN char * TkAlignImageData _ANSI_ARGS_((XImage * image,
+ int alignment, int bitOrder));
+/* Slot 1 is reserved */
+/* 2 */
+EXTERN void TkGenerateActivateEvents _ANSI_ARGS_((
+ TkWindow * winPtr, int active));
+/* 3 */
+EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void));
+/* 4 */
+EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 5 */
+EXTERN void TkpPrintWindowId _ANSI_ARGS_((char * buf,
+ Window window));
+/* 6 */
+EXTERN int TkpScanWindowId _ANSI_ARGS_((Tcl_Interp * interp,
+ char * string, int * idPtr));
+/* 7 */
+EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr));
+/* 8 */
+EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor));
+/* 9 */
+EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr,
+ int state));
+/* 10 */
+EXTERN void TkSetPixmapColormap _ANSI_ARGS_((Pixmap pixmap,
+ Colormap colormap));
+/* 11 */
+EXTERN void TkWinCancelMouseTimer _ANSI_ARGS_((void));
+/* 12 */
+EXTERN void TkWinClipboardRender _ANSI_ARGS_((
+ TkDisplay * dispPtr, UINT format));
+/* 13 */
+EXTERN LRESULT TkWinEmbeddedEventProc _ANSI_ARGS_((HWND hwnd,
+ UINT message, WPARAM wParam, LPARAM lParam));
+/* 14 */
+EXTERN void TkWinFillRect _ANSI_ARGS_((HDC dc, int x, int y,
+ int width, int height, int pixel));
+/* 15 */
+EXTERN COLORREF TkWinGetBorderPixels _ANSI_ARGS_((Tk_Window tkwin,
+ Tk_3DBorder border, int which));
+/* 16 */
+EXTERN HDC TkWinGetDrawableDC _ANSI_ARGS_((Display * display,
+ Drawable d, TkWinDCState* state));
+/* 17 */
+EXTERN int TkWinGetModifierState _ANSI_ARGS_((void));
+/* 18 */
+EXTERN HPALETTE TkWinGetSystemPalette _ANSI_ARGS_((void));
+/* 19 */
+EXTERN HWND TkWinGetWrapperWindow _ANSI_ARGS_((Tk_Window tkwin));
+/* 20 */
+EXTERN int TkWinHandleMenuEvent _ANSI_ARGS_((HWND * phwnd,
+ UINT * pMessage, WPARAM * pwParam,
+ LPARAM * plParam, LRESULT * plResult));
+/* 21 */
+EXTERN int TkWinIndexOfColor _ANSI_ARGS_((XColor * colorPtr));
+/* 22 */
+EXTERN void TkWinReleaseDrawableDC _ANSI_ARGS_((Drawable d,
+ HDC hdc, TkWinDCState* state));
+/* 23 */
+EXTERN LRESULT TkWinResendEvent _ANSI_ARGS_((WNDPROC wndproc,
+ HWND hwnd, XEvent * eventPtr));
+/* 24 */
+EXTERN HPALETTE TkWinSelectPalette _ANSI_ARGS_((HDC dc,
+ Colormap colormap));
+/* 25 */
+EXTERN void TkWinSetMenu _ANSI_ARGS_((Tk_Window tkwin,
+ HMENU hMenu));
+/* 26 */
+EXTERN void TkWinSetWindowPos _ANSI_ARGS_((HWND hwnd,
+ HWND siblingHwnd, int pos));
+/* 27 */
+EXTERN void TkWinWmCleanup _ANSI_ARGS_((HINSTANCE hInstance));
+/* 28 */
+EXTERN void TkWinXCleanup _ANSI_ARGS_((HINSTANCE hInstance));
+/* 29 */
+EXTERN void TkWinXInit _ANSI_ARGS_((HINSTANCE hInstance));
+/* 30 */
+EXTERN void TkWinSetForegroundWindow _ANSI_ARGS_((
+ TkWindow * winPtr));
+/* 31 */
+EXTERN void TkWinDialogDebug _ANSI_ARGS_((int debug));
+/* 32 */
+EXTERN Tcl_Obj * TkWinGetMenuSystemDefault _ANSI_ARGS_((
+ Tk_Window tkwin, char * dbName,
+ char * className));
+/* 33 */
+EXTERN int TkWinGetPlatformId _ANSI_ARGS_((void));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 0 */
+EXTERN void TkGenerateActivateEvents _ANSI_ARGS_((
+ TkWindow * winPtr, int active));
+/* 1 */
+EXTERN Pixmap TkpCreateNativeBitmap _ANSI_ARGS_((Display * display,
+ char * source));
+/* 2 */
+EXTERN void TkpDefineNativeBitmaps _ANSI_ARGS_((void));
+/* 3 */
+EXTERN unsigned long TkpGetMS _ANSI_ARGS_((void));
+/* 4 */
+EXTERN Pixmap TkpGetNativeAppBitmap _ANSI_ARGS_((Display * display,
+ char * name, int * width, int * height));
+/* 5 */
+EXTERN void TkPointerDeadWindow _ANSI_ARGS_((TkWindow * winPtr));
+/* 6 */
+EXTERN void TkpSetCapture _ANSI_ARGS_((TkWindow * winPtr));
+/* 7 */
+EXTERN void TkpSetCursor _ANSI_ARGS_((TkpCursor cursor));
+/* 8 */
+EXTERN void TkpWmSetState _ANSI_ARGS_((TkWindow * winPtr,
+ int state));
+/* 9 */
+EXTERN int HandleWMEvent _ANSI_ARGS_((EventRecord * theEvent));
+/* 10 */
+EXTERN void TkAboutDlg _ANSI_ARGS_((void));
+/* 11 */
+EXTERN void TkCreateMacEventSource _ANSI_ARGS_((void));
+/* 12 */
+EXTERN void TkFontList _ANSI_ARGS_((Tcl_Interp * interp,
+ Display * display));
+/* 13 */
+EXTERN Window TkGetTransientMaster _ANSI_ARGS_((TkWindow * winPtr));
+/* 14 */
+EXTERN int TkGenerateButtonEvent _ANSI_ARGS_((int x, int y,
+ Window window, unsigned int state));
+/* 15 */
+EXTERN int TkGetCharPositions _ANSI_ARGS_((
+ XFontStruct * font_struct, char * string,
+ int count, short * buffer));
+/* 16 */
+EXTERN void TkGenWMDestroyEvent _ANSI_ARGS_((Tk_Window tkwin));
+/* 17 */
+EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y, int width, int height,
+ int flags));
+/* 18 */
+EXTERN unsigned int TkMacButtonKeyState _ANSI_ARGS_((void));
+/* 19 */
+EXTERN void TkMacClearMenubarActive _ANSI_ARGS_((void));
+/* 20 */
+EXTERN int TkMacConvertEvent _ANSI_ARGS_((
+ EventRecord * eventPtr));
+/* 21 */
+EXTERN int TkMacDispatchMenuEvent _ANSI_ARGS_((int menuID,
+ int index));
+/* 22 */
+EXTERN void TkMacInstallCursor _ANSI_ARGS_((int resizeOverride));
+/* 23 */
+EXTERN int TkMacConvertTkEvent _ANSI_ARGS_((
+ EventRecord * eventPtr, Window window));
+/* 24 */
+EXTERN void TkMacHandleTearoffMenu _ANSI_ARGS_((void));
+/* 25 */
+EXTERN void tkMacInstallMWConsole _ANSI_ARGS_((
+ Tcl_Interp * interp));
+/* 26 */
+EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr));
+/* 27 */
+EXTERN void TkMacDoHLEvent _ANSI_ARGS_((EventRecord * theEvent));
+/* 28 */
+EXTERN void TkMacFontInfo _ANSI_ARGS_((Font fontId,
+ short * family, short * style, short * size));
+/* 29 */
+EXTERN Time TkMacGenerateTime _ANSI_ARGS_((void));
+/* 30 */
+EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable));
+/* 31 */
+EXTERN TkWindow * TkMacGetScrollbarGrowWindow _ANSI_ARGS_((
+ TkWindow * winPtr));
+/* 32 */
+EXTERN Window TkMacGetXWindow _ANSI_ARGS_((WindowRef macWinPtr));
+/* 33 */
+EXTERN int TkMacGrowToplevel _ANSI_ARGS_((WindowRef whichWindow,
+ Point start));
+/* 34 */
+EXTERN void TkMacHandleMenuSelect _ANSI_ARGS_((long mResult,
+ int optionKeyPressed));
+/* 35 */
+EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void));
+/* 36 */
+EXTERN void TkMacInitAppleEvents _ANSI_ARGS_((
+ Tcl_Interp * interp));
+/* 37 */
+EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp));
+/* 38 */
+EXTERN void TkMacInvalidateWindow _ANSI_ARGS_((
+ MacDrawable * macWin, int flag));
+/* 39 */
+EXTERN int TkMacIsCharacterMissing _ANSI_ARGS_((Tk_Font tkfont,
+ unsigned int searchChar));
+/* 40 */
+EXTERN void TkMacMakeRealWindowExist _ANSI_ARGS_((
+ TkWindow * winPtr));
+/* 41 */
+EXTERN BitMapPtr TkMacMakeStippleMap _ANSI_ARGS_((Drawable d1,
+ Drawable d2));
+/* 42 */
+EXTERN void TkMacMenuClick _ANSI_ARGS_((void));
+/* 43 */
+EXTERN void TkMacRegisterOffScreenWindow _ANSI_ARGS_((
+ Window window, GWorldPtr portPtr));
+/* 44 */
+EXTERN int TkMacResizable _ANSI_ARGS_((TkWindow * winPtr));
+/* 45 */
+EXTERN void TkMacSetEmbedRgn _ANSI_ARGS_((TkWindow * winPtr,
+ RgnHandle rgn));
+/* 46 */
+EXTERN void TkMacSetHelpMenuItemCount _ANSI_ARGS_((void));
+/* 47 */
+EXTERN void TkMacSetScrollbarGrow _ANSI_ARGS_((TkWindow * winPtr,
+ int flag));
+/* 48 */
+EXTERN void TkMacSetUpClippingRgn _ANSI_ARGS_((Drawable drawable));
+/* 49 */
+EXTERN void TkMacSetUpGraphicsPort _ANSI_ARGS_((GC gc));
+/* 50 */
+EXTERN void TkMacUpdateClipRgn _ANSI_ARGS_((TkWindow * winPtr));
+/* 51 */
+EXTERN void TkMacUnregisterMacWindow _ANSI_ARGS_((
+ GWorldPtr portPtr));
+/* 52 */
+EXTERN int TkMacUseMenuID _ANSI_ARGS_((short macID));
+/* 53 */
+EXTERN RgnHandle TkMacVisableClipRgn _ANSI_ARGS_((TkWindow * winPtr));
+/* 54 */
+EXTERN void TkMacWinBounds _ANSI_ARGS_((TkWindow * winPtr,
+ Rect * geometry));
+/* 55 */
+EXTERN void TkMacWindowOffset _ANSI_ARGS_((WindowRef wRef,
+ int * xOffset, int * yOffset));
+/* 56 */
+EXTERN void TkResumeClipboard _ANSI_ARGS_((void));
+/* 57 */
+EXTERN int TkSetMacColor _ANSI_ARGS_((unsigned long pixel,
+ RGBColor * macColor));
+/* 58 */
+EXTERN void TkSetWMName _ANSI_ARGS_((TkWindow * winPtr,
+ Tk_Uid titleUid));
+/* 59 */
+EXTERN void TkSuspendClipboard _ANSI_ARGS_((void));
+/* 60 */
+EXTERN int TkWMGrowToplevel _ANSI_ARGS_((WindowRef whichWindow,
+ Point start));
+/* 61 */
+EXTERN int TkMacZoomToplevel _ANSI_ARGS_((WindowPtr whichWindow,
+ Point where, short zoomPart));
+/* 62 */
+EXTERN Tk_Window Tk_TopCoordsToWindow _ANSI_ARGS_((Tk_Window tkwin,
+ int rootX, int rootY, int * newX, int * newY));
+/* 63 */
+EXTERN MacDrawable * TkMacContainerId _ANSI_ARGS_((TkWindow * winPtr));
+/* 64 */
+EXTERN MacDrawable * TkMacGetHostToplevel _ANSI_ARGS_((TkWindow * winPtr));
+#endif /* MAC_TCL */
+
+typedef struct TkIntPlatStubs {
+ int magic;
+ struct TkIntPlatStubHooks *hooks;
+
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ void (*tkCreateXEventSource) _ANSI_ARGS_((void)); /* 0 */
+ void (*tkFreeWindowId) _ANSI_ARGS_((TkDisplay * dispPtr, Window w)); /* 1 */
+ void (*tkInitXId) _ANSI_ARGS_((TkDisplay * dispPtr)); /* 2 */
+ int (*tkpCmapStressed) _ANSI_ARGS_((Tk_Window tkwin, Colormap colormap)); /* 3 */
+ void (*tkpSync) _ANSI_ARGS_((Display * display)); /* 4 */
+ Window (*tkUnixContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */
+ int (*tkUnixDoOneXEvent) _ANSI_ARGS_((Tcl_Time * timePtr)); /* 6 */
+ void (*tkUnixSetMenubar) _ANSI_ARGS_((Tk_Window tkwin, Tk_Window menubar)); /* 7 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ char * (*tkAlignImageData) _ANSI_ARGS_((XImage * image, int alignment, int bitOrder)); /* 0 */
+ void *reserved1;
+ void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 2 */
+ unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */
+ void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 4 */
+ void (*tkpPrintWindowId) _ANSI_ARGS_((char * buf, Window window)); /* 5 */
+ int (*tkpScanWindowId) _ANSI_ARGS_((Tcl_Interp * interp, char * string, int * idPtr)); /* 6 */
+ void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 7 */
+ void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 8 */
+ void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 9 */
+ void (*tkSetPixmapColormap) _ANSI_ARGS_((Pixmap pixmap, Colormap colormap)); /* 10 */
+ void (*tkWinCancelMouseTimer) _ANSI_ARGS_((void)); /* 11 */
+ void (*tkWinClipboardRender) _ANSI_ARGS_((TkDisplay * dispPtr, UINT format)); /* 12 */
+ LRESULT (*tkWinEmbeddedEventProc) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); /* 13 */
+ void (*tkWinFillRect) _ANSI_ARGS_((HDC dc, int x, int y, int width, int height, int pixel)); /* 14 */
+ COLORREF (*tkWinGetBorderPixels) _ANSI_ARGS_((Tk_Window tkwin, Tk_3DBorder border, int which)); /* 15 */
+ HDC (*tkWinGetDrawableDC) _ANSI_ARGS_((Display * display, Drawable d, TkWinDCState* state)); /* 16 */
+ int (*tkWinGetModifierState) _ANSI_ARGS_((void)); /* 17 */
+ HPALETTE (*tkWinGetSystemPalette) _ANSI_ARGS_((void)); /* 18 */
+ HWND (*tkWinGetWrapperWindow) _ANSI_ARGS_((Tk_Window tkwin)); /* 19 */
+ int (*tkWinHandleMenuEvent) _ANSI_ARGS_((HWND * phwnd, UINT * pMessage, WPARAM * pwParam, LPARAM * plParam, LRESULT * plResult)); /* 20 */
+ int (*tkWinIndexOfColor) _ANSI_ARGS_((XColor * colorPtr)); /* 21 */
+ void (*tkWinReleaseDrawableDC) _ANSI_ARGS_((Drawable d, HDC hdc, TkWinDCState* state)); /* 22 */
+ LRESULT (*tkWinResendEvent) _ANSI_ARGS_((WNDPROC wndproc, HWND hwnd, XEvent * eventPtr)); /* 23 */
+ HPALETTE (*tkWinSelectPalette) _ANSI_ARGS_((HDC dc, Colormap colormap)); /* 24 */
+ void (*tkWinSetMenu) _ANSI_ARGS_((Tk_Window tkwin, HMENU hMenu)); /* 25 */
+ void (*tkWinSetWindowPos) _ANSI_ARGS_((HWND hwnd, HWND siblingHwnd, int pos)); /* 26 */
+ void (*tkWinWmCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 27 */
+ void (*tkWinXCleanup) _ANSI_ARGS_((HINSTANCE hInstance)); /* 28 */
+ void (*tkWinXInit) _ANSI_ARGS_((HINSTANCE hInstance)); /* 29 */
+ void (*tkWinSetForegroundWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 30 */
+ void (*tkWinDialogDebug) _ANSI_ARGS_((int debug)); /* 31 */
+ Tcl_Obj * (*tkWinGetMenuSystemDefault) _ANSI_ARGS_((Tk_Window tkwin, char * dbName, char * className)); /* 32 */
+ int (*tkWinGetPlatformId) _ANSI_ARGS_((void)); /* 33 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tkGenerateActivateEvents) _ANSI_ARGS_((TkWindow * winPtr, int active)); /* 0 */
+ Pixmap (*tkpCreateNativeBitmap) _ANSI_ARGS_((Display * display, char * source)); /* 1 */
+ void (*tkpDefineNativeBitmaps) _ANSI_ARGS_((void)); /* 2 */
+ unsigned long (*tkpGetMS) _ANSI_ARGS_((void)); /* 3 */
+ Pixmap (*tkpGetNativeAppBitmap) _ANSI_ARGS_((Display * display, char * name, int * width, int * height)); /* 4 */
+ void (*tkPointerDeadWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 5 */
+ void (*tkpSetCapture) _ANSI_ARGS_((TkWindow * winPtr)); /* 6 */
+ void (*tkpSetCursor) _ANSI_ARGS_((TkpCursor cursor)); /* 7 */
+ void (*tkpWmSetState) _ANSI_ARGS_((TkWindow * winPtr, int state)); /* 8 */
+ int (*handleWMEvent) _ANSI_ARGS_((EventRecord * theEvent)); /* 9 */
+ void (*tkAboutDlg) _ANSI_ARGS_((void)); /* 10 */
+ void (*tkCreateMacEventSource) _ANSI_ARGS_((void)); /* 11 */
+ void (*tkFontList) _ANSI_ARGS_((Tcl_Interp * interp, Display * display)); /* 12 */
+ Window (*tkGetTransientMaster) _ANSI_ARGS_((TkWindow * winPtr)); /* 13 */
+ int (*tkGenerateButtonEvent) _ANSI_ARGS_((int x, int y, Window window, unsigned int state)); /* 14 */
+ int (*tkGetCharPositions) _ANSI_ARGS_((XFontStruct * font_struct, char * string, int count, short * buffer)); /* 15 */
+ void (*tkGenWMDestroyEvent) _ANSI_ARGS_((Tk_Window tkwin)); /* 16 */
+ void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 17 */
+ unsigned int (*tkMacButtonKeyState) _ANSI_ARGS_((void)); /* 18 */
+ void (*tkMacClearMenubarActive) _ANSI_ARGS_((void)); /* 19 */
+ int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 20 */
+ int (*tkMacDispatchMenuEvent) _ANSI_ARGS_((int menuID, int index)); /* 21 */
+ void (*tkMacInstallCursor) _ANSI_ARGS_((int resizeOverride)); /* 22 */
+ int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 23 */
+ void (*tkMacHandleTearoffMenu) _ANSI_ARGS_((void)); /* 24 */
+ void (*tkMacInstallMWConsole) _ANSI_ARGS_((Tcl_Interp * interp)); /* 25 */
+ void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 26 */
+ void (*tkMacDoHLEvent) _ANSI_ARGS_((EventRecord * theEvent)); /* 27 */
+ void (*tkMacFontInfo) _ANSI_ARGS_((Font fontId, short * family, short * style, short * size)); /* 28 */
+ Time (*tkMacGenerateTime) _ANSI_ARGS_((void)); /* 29 */
+ GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 30 */
+ TkWindow * (*tkMacGetScrollbarGrowWindow) _ANSI_ARGS_((TkWindow * winPtr)); /* 31 */
+ Window (*tkMacGetXWindow) _ANSI_ARGS_((WindowRef macWinPtr)); /* 32 */
+ int (*tkMacGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 33 */
+ void (*tkMacHandleMenuSelect) _ANSI_ARGS_((long mResult, int optionKeyPressed)); /* 34 */
+ int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 35 */
+ void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 36 */
+ void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 37 */
+ void (*tkMacInvalidateWindow) _ANSI_ARGS_((MacDrawable * macWin, int flag)); /* 38 */
+ int (*tkMacIsCharacterMissing) _ANSI_ARGS_((Tk_Font tkfont, unsigned int searchChar)); /* 39 */
+ void (*tkMacMakeRealWindowExist) _ANSI_ARGS_((TkWindow * winPtr)); /* 40 */
+ BitMapPtr (*tkMacMakeStippleMap) _ANSI_ARGS_((Drawable d1, Drawable d2)); /* 41 */
+ void (*tkMacMenuClick) _ANSI_ARGS_((void)); /* 42 */
+ void (*tkMacRegisterOffScreenWindow) _ANSI_ARGS_((Window window, GWorldPtr portPtr)); /* 43 */
+ int (*tkMacResizable) _ANSI_ARGS_((TkWindow * winPtr)); /* 44 */
+ void (*tkMacSetEmbedRgn) _ANSI_ARGS_((TkWindow * winPtr, RgnHandle rgn)); /* 45 */
+ void (*tkMacSetHelpMenuItemCount) _ANSI_ARGS_((void)); /* 46 */
+ void (*tkMacSetScrollbarGrow) _ANSI_ARGS_((TkWindow * winPtr, int flag)); /* 47 */
+ void (*tkMacSetUpClippingRgn) _ANSI_ARGS_((Drawable drawable)); /* 48 */
+ void (*tkMacSetUpGraphicsPort) _ANSI_ARGS_((GC gc)); /* 49 */
+ void (*tkMacUpdateClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 50 */
+ void (*tkMacUnregisterMacWindow) _ANSI_ARGS_((GWorldPtr portPtr)); /* 51 */
+ int (*tkMacUseMenuID) _ANSI_ARGS_((short macID)); /* 52 */
+ RgnHandle (*tkMacVisableClipRgn) _ANSI_ARGS_((TkWindow * winPtr)); /* 53 */
+ void (*tkMacWinBounds) _ANSI_ARGS_((TkWindow * winPtr, Rect * geometry)); /* 54 */
+ void (*tkMacWindowOffset) _ANSI_ARGS_((WindowRef wRef, int * xOffset, int * yOffset)); /* 55 */
+ void (*tkResumeClipboard) _ANSI_ARGS_((void)); /* 56 */
+ int (*tkSetMacColor) _ANSI_ARGS_((unsigned long pixel, RGBColor * macColor)); /* 57 */
+ void (*tkSetWMName) _ANSI_ARGS_((TkWindow * winPtr, Tk_Uid titleUid)); /* 58 */
+ void (*tkSuspendClipboard) _ANSI_ARGS_((void)); /* 59 */
+ int (*tkWMGrowToplevel) _ANSI_ARGS_((WindowRef whichWindow, Point start)); /* 60 */
+ int (*tkMacZoomToplevel) _ANSI_ARGS_((WindowPtr whichWindow, Point where, short zoomPart)); /* 61 */
+ Tk_Window (*tk_TopCoordsToWindow) _ANSI_ARGS_((Tk_Window tkwin, int rootX, int rootY, int * newX, int * newY)); /* 62 */
+ MacDrawable * (*tkMacContainerId) _ANSI_ARGS_((TkWindow * winPtr)); /* 63 */
+ MacDrawable * (*tkMacGetHostToplevel) _ANSI_ARGS_((TkWindow * winPtr)); /* 64 */
+#endif /* MAC_TCL */
+} TkIntPlatStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern TkIntPlatStubs *tkIntPlatStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS)
+
+/*
+ * Inline function declarations:
+ */
+
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+#ifndef TkCreateXEventSource
+#define TkCreateXEventSource \
+ (tkIntPlatStubsPtr->tkCreateXEventSource) /* 0 */
+#endif
+#ifndef TkFreeWindowId
+#define TkFreeWindowId \
+ (tkIntPlatStubsPtr->tkFreeWindowId) /* 1 */
+#endif
+#ifndef TkInitXId
+#define TkInitXId \
+ (tkIntPlatStubsPtr->tkInitXId) /* 2 */
+#endif
+#ifndef TkpCmapStressed
+#define TkpCmapStressed \
+ (tkIntPlatStubsPtr->tkpCmapStressed) /* 3 */
+#endif
+#ifndef TkpSync
+#define TkpSync \
+ (tkIntPlatStubsPtr->tkpSync) /* 4 */
+#endif
+#ifndef TkUnixContainerId
+#define TkUnixContainerId \
+ (tkIntPlatStubsPtr->tkUnixContainerId) /* 5 */
+#endif
+#ifndef TkUnixDoOneXEvent
+#define TkUnixDoOneXEvent \
+ (tkIntPlatStubsPtr->tkUnixDoOneXEvent) /* 6 */
+#endif
+#ifndef TkUnixSetMenubar
+#define TkUnixSetMenubar \
+ (tkIntPlatStubsPtr->tkUnixSetMenubar) /* 7 */
+#endif
+#endif /* UNIX */
+#ifdef __WIN32__
+#ifndef TkAlignImageData
+#define TkAlignImageData \
+ (tkIntPlatStubsPtr->tkAlignImageData) /* 0 */
+#endif
+/* Slot 1 is reserved */
+#ifndef TkGenerateActivateEvents
+#define TkGenerateActivateEvents \
+ (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 2 */
+#endif
+#ifndef TkpGetMS
+#define TkpGetMS \
+ (tkIntPlatStubsPtr->tkpGetMS) /* 3 */
+#endif
+#ifndef TkPointerDeadWindow
+#define TkPointerDeadWindow \
+ (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 4 */
+#endif
+#ifndef TkpPrintWindowId
+#define TkpPrintWindowId \
+ (tkIntPlatStubsPtr->tkpPrintWindowId) /* 5 */
+#endif
+#ifndef TkpScanWindowId
+#define TkpScanWindowId \
+ (tkIntPlatStubsPtr->tkpScanWindowId) /* 6 */
+#endif
+#ifndef TkpSetCapture
+#define TkpSetCapture \
+ (tkIntPlatStubsPtr->tkpSetCapture) /* 7 */
+#endif
+#ifndef TkpSetCursor
+#define TkpSetCursor \
+ (tkIntPlatStubsPtr->tkpSetCursor) /* 8 */
+#endif
+#ifndef TkpWmSetState
+#define TkpWmSetState \
+ (tkIntPlatStubsPtr->tkpWmSetState) /* 9 */
+#endif
+#ifndef TkSetPixmapColormap
+#define TkSetPixmapColormap \
+ (tkIntPlatStubsPtr->tkSetPixmapColormap) /* 10 */
+#endif
+#ifndef TkWinCancelMouseTimer
+#define TkWinCancelMouseTimer \
+ (tkIntPlatStubsPtr->tkWinCancelMouseTimer) /* 11 */
+#endif
+#ifndef TkWinClipboardRender
+#define TkWinClipboardRender \
+ (tkIntPlatStubsPtr->tkWinClipboardRender) /* 12 */
+#endif
+#ifndef TkWinEmbeddedEventProc
+#define TkWinEmbeddedEventProc \
+ (tkIntPlatStubsPtr->tkWinEmbeddedEventProc) /* 13 */
+#endif
+#ifndef TkWinFillRect
+#define TkWinFillRect \
+ (tkIntPlatStubsPtr->tkWinFillRect) /* 14 */
+#endif
+#ifndef TkWinGetBorderPixels
+#define TkWinGetBorderPixels \
+ (tkIntPlatStubsPtr->tkWinGetBorderPixels) /* 15 */
+#endif
+#ifndef TkWinGetDrawableDC
+#define TkWinGetDrawableDC \
+ (tkIntPlatStubsPtr->tkWinGetDrawableDC) /* 16 */
+#endif
+#ifndef TkWinGetModifierState
+#define TkWinGetModifierState \
+ (tkIntPlatStubsPtr->tkWinGetModifierState) /* 17 */
+#endif
+#ifndef TkWinGetSystemPalette
+#define TkWinGetSystemPalette \
+ (tkIntPlatStubsPtr->tkWinGetSystemPalette) /* 18 */
+#endif
+#ifndef TkWinGetWrapperWindow
+#define TkWinGetWrapperWindow \
+ (tkIntPlatStubsPtr->tkWinGetWrapperWindow) /* 19 */
+#endif
+#ifndef TkWinHandleMenuEvent
+#define TkWinHandleMenuEvent \
+ (tkIntPlatStubsPtr->tkWinHandleMenuEvent) /* 20 */
+#endif
+#ifndef TkWinIndexOfColor
+#define TkWinIndexOfColor \
+ (tkIntPlatStubsPtr->tkWinIndexOfColor) /* 21 */
+#endif
+#ifndef TkWinReleaseDrawableDC
+#define TkWinReleaseDrawableDC \
+ (tkIntPlatStubsPtr->tkWinReleaseDrawableDC) /* 22 */
+#endif
+#ifndef TkWinResendEvent
+#define TkWinResendEvent \
+ (tkIntPlatStubsPtr->tkWinResendEvent) /* 23 */
+#endif
+#ifndef TkWinSelectPalette
+#define TkWinSelectPalette \
+ (tkIntPlatStubsPtr->tkWinSelectPalette) /* 24 */
+#endif
+#ifndef TkWinSetMenu
+#define TkWinSetMenu \
+ (tkIntPlatStubsPtr->tkWinSetMenu) /* 25 */
+#endif
+#ifndef TkWinSetWindowPos
+#define TkWinSetWindowPos \
+ (tkIntPlatStubsPtr->tkWinSetWindowPos) /* 26 */
+#endif
+#ifndef TkWinWmCleanup
+#define TkWinWmCleanup \
+ (tkIntPlatStubsPtr->tkWinWmCleanup) /* 27 */
+#endif
+#ifndef TkWinXCleanup
+#define TkWinXCleanup \
+ (tkIntPlatStubsPtr->tkWinXCleanup) /* 28 */
+#endif
+#ifndef TkWinXInit
+#define TkWinXInit \
+ (tkIntPlatStubsPtr->tkWinXInit) /* 29 */
+#endif
+#ifndef TkWinSetForegroundWindow
+#define TkWinSetForegroundWindow \
+ (tkIntPlatStubsPtr->tkWinSetForegroundWindow) /* 30 */
+#endif
+#ifndef TkWinDialogDebug
+#define TkWinDialogDebug \
+ (tkIntPlatStubsPtr->tkWinDialogDebug) /* 31 */
+#endif
+#ifndef TkWinGetMenuSystemDefault
+#define TkWinGetMenuSystemDefault \
+ (tkIntPlatStubsPtr->tkWinGetMenuSystemDefault) /* 32 */
+#endif
+#ifndef TkWinGetPlatformId
+#define TkWinGetPlatformId \
+ (tkIntPlatStubsPtr->tkWinGetPlatformId) /* 33 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef TkGenerateActivateEvents
+#define TkGenerateActivateEvents \
+ (tkIntPlatStubsPtr->tkGenerateActivateEvents) /* 0 */
+#endif
+#ifndef TkpCreateNativeBitmap
+#define TkpCreateNativeBitmap \
+ (tkIntPlatStubsPtr->tkpCreateNativeBitmap) /* 1 */
+#endif
+#ifndef TkpDefineNativeBitmaps
+#define TkpDefineNativeBitmaps \
+ (tkIntPlatStubsPtr->tkpDefineNativeBitmaps) /* 2 */
+#endif
+#ifndef TkpGetMS
+#define TkpGetMS \
+ (tkIntPlatStubsPtr->tkpGetMS) /* 3 */
+#endif
+#ifndef TkpGetNativeAppBitmap
+#define TkpGetNativeAppBitmap \
+ (tkIntPlatStubsPtr->tkpGetNativeAppBitmap) /* 4 */
+#endif
+#ifndef TkPointerDeadWindow
+#define TkPointerDeadWindow \
+ (tkIntPlatStubsPtr->tkPointerDeadWindow) /* 5 */
+#endif
+#ifndef TkpSetCapture
+#define TkpSetCapture \
+ (tkIntPlatStubsPtr->tkpSetCapture) /* 6 */
+#endif
+#ifndef TkpSetCursor
+#define TkpSetCursor \
+ (tkIntPlatStubsPtr->tkpSetCursor) /* 7 */
+#endif
+#ifndef TkpWmSetState
+#define TkpWmSetState \
+ (tkIntPlatStubsPtr->tkpWmSetState) /* 8 */
+#endif
+#ifndef HandleWMEvent
+#define HandleWMEvent \
+ (tkIntPlatStubsPtr->handleWMEvent) /* 9 */
+#endif
+#ifndef TkAboutDlg
+#define TkAboutDlg \
+ (tkIntPlatStubsPtr->tkAboutDlg) /* 10 */
+#endif
+#ifndef TkCreateMacEventSource
+#define TkCreateMacEventSource \
+ (tkIntPlatStubsPtr->tkCreateMacEventSource) /* 11 */
+#endif
+#ifndef TkFontList
+#define TkFontList \
+ (tkIntPlatStubsPtr->tkFontList) /* 12 */
+#endif
+#ifndef TkGetTransientMaster
+#define TkGetTransientMaster \
+ (tkIntPlatStubsPtr->tkGetTransientMaster) /* 13 */
+#endif
+#ifndef TkGenerateButtonEvent
+#define TkGenerateButtonEvent \
+ (tkIntPlatStubsPtr->tkGenerateButtonEvent) /* 14 */
+#endif
+#ifndef TkGetCharPositions
+#define TkGetCharPositions \
+ (tkIntPlatStubsPtr->tkGetCharPositions) /* 15 */
+#endif
+#ifndef TkGenWMDestroyEvent
+#define TkGenWMDestroyEvent \
+ (tkIntPlatStubsPtr->tkGenWMDestroyEvent) /* 16 */
+#endif
+#ifndef TkGenWMConfigureEvent
+#define TkGenWMConfigureEvent \
+ (tkIntPlatStubsPtr->tkGenWMConfigureEvent) /* 17 */
+#endif
+#ifndef TkMacButtonKeyState
+#define TkMacButtonKeyState \
+ (tkIntPlatStubsPtr->tkMacButtonKeyState) /* 18 */
+#endif
+#ifndef TkMacClearMenubarActive
+#define TkMacClearMenubarActive \
+ (tkIntPlatStubsPtr->tkMacClearMenubarActive) /* 19 */
+#endif
+#ifndef TkMacConvertEvent
+#define TkMacConvertEvent \
+ (tkIntPlatStubsPtr->tkMacConvertEvent) /* 20 */
+#endif
+#ifndef TkMacDispatchMenuEvent
+#define TkMacDispatchMenuEvent \
+ (tkIntPlatStubsPtr->tkMacDispatchMenuEvent) /* 21 */
+#endif
+#ifndef TkMacInstallCursor
+#define TkMacInstallCursor \
+ (tkIntPlatStubsPtr->tkMacInstallCursor) /* 22 */
+#endif
+#ifndef TkMacConvertTkEvent
+#define TkMacConvertTkEvent \
+ (tkIntPlatStubsPtr->tkMacConvertTkEvent) /* 23 */
+#endif
+#ifndef TkMacHandleTearoffMenu
+#define TkMacHandleTearoffMenu \
+ (tkIntPlatStubsPtr->tkMacHandleTearoffMenu) /* 24 */
+#endif
+#ifndef tkMacInstallMWConsole
+#define tkMacInstallMWConsole \
+ (tkIntPlatStubsPtr->tkMacInstallMWConsole) /* 25 */
+#endif
+#ifndef TkMacInvalClipRgns
+#define TkMacInvalClipRgns \
+ (tkIntPlatStubsPtr->tkMacInvalClipRgns) /* 26 */
+#endif
+#ifndef TkMacDoHLEvent
+#define TkMacDoHLEvent \
+ (tkIntPlatStubsPtr->tkMacDoHLEvent) /* 27 */
+#endif
+#ifndef TkMacFontInfo
+#define TkMacFontInfo \
+ (tkIntPlatStubsPtr->tkMacFontInfo) /* 28 */
+#endif
+#ifndef TkMacGenerateTime
+#define TkMacGenerateTime \
+ (tkIntPlatStubsPtr->tkMacGenerateTime) /* 29 */
+#endif
+#ifndef TkMacGetDrawablePort
+#define TkMacGetDrawablePort \
+ (tkIntPlatStubsPtr->tkMacGetDrawablePort) /* 30 */
+#endif
+#ifndef TkMacGetScrollbarGrowWindow
+#define TkMacGetScrollbarGrowWindow \
+ (tkIntPlatStubsPtr->tkMacGetScrollbarGrowWindow) /* 31 */
+#endif
+#ifndef TkMacGetXWindow
+#define TkMacGetXWindow \
+ (tkIntPlatStubsPtr->tkMacGetXWindow) /* 32 */
+#endif
+#ifndef TkMacGrowToplevel
+#define TkMacGrowToplevel \
+ (tkIntPlatStubsPtr->tkMacGrowToplevel) /* 33 */
+#endif
+#ifndef TkMacHandleMenuSelect
+#define TkMacHandleMenuSelect \
+ (tkIntPlatStubsPtr->tkMacHandleMenuSelect) /* 34 */
+#endif
+#ifndef TkMacHaveAppearance
+#define TkMacHaveAppearance \
+ (tkIntPlatStubsPtr->tkMacHaveAppearance) /* 35 */
+#endif
+#ifndef TkMacInitAppleEvents
+#define TkMacInitAppleEvents \
+ (tkIntPlatStubsPtr->tkMacInitAppleEvents) /* 36 */
+#endif
+#ifndef TkMacInitMenus
+#define TkMacInitMenus \
+ (tkIntPlatStubsPtr->tkMacInitMenus) /* 37 */
+#endif
+#ifndef TkMacInvalidateWindow
+#define TkMacInvalidateWindow \
+ (tkIntPlatStubsPtr->tkMacInvalidateWindow) /* 38 */
+#endif
+#ifndef TkMacIsCharacterMissing
+#define TkMacIsCharacterMissing \
+ (tkIntPlatStubsPtr->tkMacIsCharacterMissing) /* 39 */
+#endif
+#ifndef TkMacMakeRealWindowExist
+#define TkMacMakeRealWindowExist \
+ (tkIntPlatStubsPtr->tkMacMakeRealWindowExist) /* 40 */
+#endif
+#ifndef TkMacMakeStippleMap
+#define TkMacMakeStippleMap \
+ (tkIntPlatStubsPtr->tkMacMakeStippleMap) /* 41 */
+#endif
+#ifndef TkMacMenuClick
+#define TkMacMenuClick \
+ (tkIntPlatStubsPtr->tkMacMenuClick) /* 42 */
+#endif
+#ifndef TkMacRegisterOffScreenWindow
+#define TkMacRegisterOffScreenWindow \
+ (tkIntPlatStubsPtr->tkMacRegisterOffScreenWindow) /* 43 */
+#endif
+#ifndef TkMacResizable
+#define TkMacResizable \
+ (tkIntPlatStubsPtr->tkMacResizable) /* 44 */
+#endif
+#ifndef TkMacSetEmbedRgn
+#define TkMacSetEmbedRgn \
+ (tkIntPlatStubsPtr->tkMacSetEmbedRgn) /* 45 */
+#endif
+#ifndef TkMacSetHelpMenuItemCount
+#define TkMacSetHelpMenuItemCount \
+ (tkIntPlatStubsPtr->tkMacSetHelpMenuItemCount) /* 46 */
+#endif
+#ifndef TkMacSetScrollbarGrow
+#define TkMacSetScrollbarGrow \
+ (tkIntPlatStubsPtr->tkMacSetScrollbarGrow) /* 47 */
+#endif
+#ifndef TkMacSetUpClippingRgn
+#define TkMacSetUpClippingRgn \
+ (tkIntPlatStubsPtr->tkMacSetUpClippingRgn) /* 48 */
+#endif
+#ifndef TkMacSetUpGraphicsPort
+#define TkMacSetUpGraphicsPort \
+ (tkIntPlatStubsPtr->tkMacSetUpGraphicsPort) /* 49 */
+#endif
+#ifndef TkMacUpdateClipRgn
+#define TkMacUpdateClipRgn \
+ (tkIntPlatStubsPtr->tkMacUpdateClipRgn) /* 50 */
+#endif
+#ifndef TkMacUnregisterMacWindow
+#define TkMacUnregisterMacWindow \
+ (tkIntPlatStubsPtr->tkMacUnregisterMacWindow) /* 51 */
+#endif
+#ifndef TkMacUseMenuID
+#define TkMacUseMenuID \
+ (tkIntPlatStubsPtr->tkMacUseMenuID) /* 52 */
+#endif
+#ifndef TkMacVisableClipRgn
+#define TkMacVisableClipRgn \
+ (tkIntPlatStubsPtr->tkMacVisableClipRgn) /* 53 */
+#endif
+#ifndef TkMacWinBounds
+#define TkMacWinBounds \
+ (tkIntPlatStubsPtr->tkMacWinBounds) /* 54 */
+#endif
+#ifndef TkMacWindowOffset
+#define TkMacWindowOffset \
+ (tkIntPlatStubsPtr->tkMacWindowOffset) /* 55 */
+#endif
+#ifndef TkResumeClipboard
+#define TkResumeClipboard \
+ (tkIntPlatStubsPtr->tkResumeClipboard) /* 56 */
+#endif
+#ifndef TkSetMacColor
+#define TkSetMacColor \
+ (tkIntPlatStubsPtr->tkSetMacColor) /* 57 */
+#endif
+#ifndef TkSetWMName
+#define TkSetWMName \
+ (tkIntPlatStubsPtr->tkSetWMName) /* 58 */
+#endif
+#ifndef TkSuspendClipboard
+#define TkSuspendClipboard \
+ (tkIntPlatStubsPtr->tkSuspendClipboard) /* 59 */
+#endif
+#ifndef TkWMGrowToplevel
+#define TkWMGrowToplevel \
+ (tkIntPlatStubsPtr->tkWMGrowToplevel) /* 60 */
+#endif
+#ifndef TkMacZoomToplevel
+#define TkMacZoomToplevel \
+ (tkIntPlatStubsPtr->tkMacZoomToplevel) /* 61 */
+#endif
+#ifndef Tk_TopCoordsToWindow
+#define Tk_TopCoordsToWindow \
+ (tkIntPlatStubsPtr->tk_TopCoordsToWindow) /* 62 */
+#endif
+#ifndef TkMacContainerId
+#define TkMacContainerId \
+ (tkIntPlatStubsPtr->tkMacContainerId) /* 63 */
+#endif
+#ifndef TkMacGetHostToplevel
+#define TkMacGetHostToplevel \
+ (tkIntPlatStubsPtr->tkMacGetHostToplevel) /* 64 */
+#endif
+#endif /* MAC_TCL */
+
+#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKINTPLATDECLS */
diff --git a/tk/generic/tkIntXlibDecls.h b/tk/generic/tkIntXlibDecls.h
new file mode 100644
index 00000000000..7126dd6bcc6
--- /dev/null
+++ b/tk/generic/tkIntXlibDecls.h
@@ -0,0 +1,1674 @@
+/*
+ * tkIntXlibDecls.h --
+ *
+ * This file contains the declarations for all platform dependent
+ * unsupported functions that are exported by the Tk library. These
+ * interfaces are not guaranteed to remain the same between
+ * versions. Use at your own risk.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ * All rights reserved.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifndef _TKINTXLIBDECLS
+#define _TKINTXLIBDECLS
+
+#ifdef MAC_TCL
+#include "Xutil.h"
+#else
+#include "X11/Xutil.h"
+#endif
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tkInt.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+/*
+ * Exported function declarations:
+ */
+
+#ifdef __WIN32__
+/* 0 */
+EXTERN void XSetDashes _ANSI_ARGS_((Display* display, GC gc,
+ int dash_offset, _Xconst char* dash_list,
+ int n));
+/* 1 */
+EXTERN XModifierKeymap* XGetModifierMapping _ANSI_ARGS_((Display* d));
+/* 2 */
+EXTERN XImage * XCreateImage _ANSI_ARGS_((Display* d, Visual* v,
+ unsigned int ui1, int i1, int i2, char* cp,
+ unsigned int ui2, unsigned int ui3, int i3,
+ int i4));
+/* 3 */
+EXTERN XImage * XGetImage _ANSI_ARGS_((Display* d, Drawable dr,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2, unsigned long ul, int i3));
+/* 4 */
+EXTERN char * XGetAtomName _ANSI_ARGS_((Display* d, Atom a));
+/* 5 */
+EXTERN char * XKeysymToString _ANSI_ARGS_((KeySym k));
+/* 6 */
+EXTERN Colormap XCreateColormap _ANSI_ARGS_((Display* d, Window w,
+ Visual* v, int i));
+/* 7 */
+EXTERN Cursor XCreatePixmapCursor _ANSI_ARGS_((Display* d,
+ Pixmap p1, Pixmap p2, XColor* x1, XColor* x2,
+ unsigned int ui1, unsigned int ui2));
+/* 8 */
+EXTERN Cursor XCreateGlyphCursor _ANSI_ARGS_((Display* d, Font f1,
+ Font f2, unsigned int ui1, unsigned int ui2,
+ XColor* x1, XColor* x2));
+/* 9 */
+EXTERN GContext XGContextFromGC _ANSI_ARGS_((GC g));
+/* 10 */
+EXTERN XHostAddress * XListHosts _ANSI_ARGS_((Display* d, int* i, Bool* b));
+/* 11 */
+EXTERN KeySym XKeycodeToKeysym _ANSI_ARGS_((Display* d,
+ unsigned int k, int i));
+/* 12 */
+EXTERN KeySym XStringToKeysym _ANSI_ARGS_((_Xconst char* c));
+/* 13 */
+EXTERN Window XRootWindow _ANSI_ARGS_((Display* d, int i));
+/* 14 */
+EXTERN XErrorHandler XSetErrorHandler _ANSI_ARGS_((XErrorHandler x));
+/* 15 */
+EXTERN Status XIconifyWindow _ANSI_ARGS_((Display* d, Window w,
+ int i));
+/* 16 */
+EXTERN Status XWithdrawWindow _ANSI_ARGS_((Display* d, Window w,
+ int i));
+/* 17 */
+EXTERN Status XGetWMColormapWindows _ANSI_ARGS_((Display* d,
+ Window w, Window** wpp, int* ip));
+/* 18 */
+EXTERN Status XAllocColor _ANSI_ARGS_((Display* d, Colormap c,
+ XColor* xp));
+/* 19 */
+EXTERN void XBell _ANSI_ARGS_((Display* d, int i));
+/* 20 */
+EXTERN void XChangeProperty _ANSI_ARGS_((Display* d, Window w,
+ Atom a1, Atom a2, int i1, int i2,
+ _Xconst unsigned char* c, int i3));
+/* 21 */
+EXTERN void XChangeWindowAttributes _ANSI_ARGS_((Display* d,
+ Window w, unsigned long ul,
+ XSetWindowAttributes* x));
+/* 22 */
+EXTERN void XClearWindow _ANSI_ARGS_((Display* d, Window w));
+/* 23 */
+EXTERN void XConfigureWindow _ANSI_ARGS_((Display* d, Window w,
+ unsigned int i, XWindowChanges* x));
+/* 24 */
+EXTERN void XCopyArea _ANSI_ARGS_((Display* d, Drawable dr1,
+ Drawable dr2, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3,
+ int i4));
+/* 25 */
+EXTERN void XCopyPlane _ANSI_ARGS_((Display* d, Drawable dr1,
+ Drawable dr2, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3,
+ int i4, unsigned long ul));
+/* 26 */
+EXTERN Pixmap XCreateBitmapFromData _ANSI_ARGS_((Display* display,
+ Drawable d, _Xconst char* data,
+ unsigned int width, unsigned int height));
+/* 27 */
+EXTERN void XDefineCursor _ANSI_ARGS_((Display* d, Window w,
+ Cursor c));
+/* 28 */
+EXTERN void XDeleteProperty _ANSI_ARGS_((Display* d, Window w,
+ Atom a));
+/* 29 */
+EXTERN void XDestroyWindow _ANSI_ARGS_((Display* d, Window w));
+/* 30 */
+EXTERN void XDrawArc _ANSI_ARGS_((Display* d, Drawable dr, GC g,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4));
+/* 31 */
+EXTERN void XDrawLines _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, XPoint* x, int i1, int i2));
+/* 32 */
+EXTERN void XDrawRectangle _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, int i1, int i2, unsigned int ui1,
+ unsigned int ui2));
+/* 33 */
+EXTERN void XFillArc _ANSI_ARGS_((Display* d, Drawable dr, GC g,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4));
+/* 34 */
+EXTERN void XFillPolygon _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, XPoint* x, int i1, int i2, int i3));
+/* 35 */
+EXTERN void XFillRectangles _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, XRectangle* x, int i));
+/* 36 */
+EXTERN void XForceScreenSaver _ANSI_ARGS_((Display* d, int i));
+/* 37 */
+EXTERN void XFreeColormap _ANSI_ARGS_((Display* d, Colormap c));
+/* 38 */
+EXTERN void XFreeColors _ANSI_ARGS_((Display* d, Colormap c,
+ unsigned long* ulp, int i, unsigned long ul));
+/* 39 */
+EXTERN void XFreeCursor _ANSI_ARGS_((Display* d, Cursor c));
+/* 40 */
+EXTERN void XFreeModifiermap _ANSI_ARGS_((XModifierKeymap* x));
+/* 41 */
+EXTERN Status XGetGeometry _ANSI_ARGS_((Display* d, Drawable dr,
+ Window* w, int* i1, int* i2,
+ unsigned int* ui1, unsigned int* ui2,
+ unsigned int* ui3, unsigned int* ui4));
+/* 42 */
+EXTERN void XGetInputFocus _ANSI_ARGS_((Display* d, Window* w,
+ int* i));
+/* 43 */
+EXTERN int XGetWindowProperty _ANSI_ARGS_((Display* d, Window w,
+ Atom a1, long l1, long l2, Bool b, Atom a2,
+ Atom* ap, int* ip, unsigned long* ulp1,
+ unsigned long* ulp2, unsigned char** cpp));
+/* 44 */
+EXTERN Status XGetWindowAttributes _ANSI_ARGS_((Display* d,
+ Window w, XWindowAttributes* x));
+/* 45 */
+EXTERN int XGrabKeyboard _ANSI_ARGS_((Display* d, Window w,
+ Bool b, int i1, int i2, Time t));
+/* 46 */
+EXTERN int XGrabPointer _ANSI_ARGS_((Display* d, Window w1,
+ Bool b, unsigned int ui, int i1, int i2,
+ Window w2, Cursor c, Time t));
+/* 47 */
+EXTERN KeyCode XKeysymToKeycode _ANSI_ARGS_((Display* d, KeySym k));
+/* 48 */
+EXTERN Status XLookupColor _ANSI_ARGS_((Display* d, Colormap c1,
+ _Xconst char* c2, XColor* x1, XColor* x2));
+/* 49 */
+EXTERN void XMapWindow _ANSI_ARGS_((Display* d, Window w));
+/* 50 */
+EXTERN void XMoveResizeWindow _ANSI_ARGS_((Display* d, Window w,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2));
+/* 51 */
+EXTERN void XMoveWindow _ANSI_ARGS_((Display* d, Window w,
+ int i1, int i2));
+/* 52 */
+EXTERN void XNextEvent _ANSI_ARGS_((Display* d, XEvent* x));
+/* 53 */
+EXTERN void XPutBackEvent _ANSI_ARGS_((Display* d, XEvent* x));
+/* 54 */
+EXTERN void XQueryColors _ANSI_ARGS_((Display* d, Colormap c,
+ XColor* x, int i));
+/* 55 */
+EXTERN Bool XQueryPointer _ANSI_ARGS_((Display* d, Window w1,
+ Window* w2, Window* w3, int* i1, int* i2,
+ int* i3, int* i4, unsigned int* ui));
+/* 56 */
+EXTERN Status XQueryTree _ANSI_ARGS_((Display* d, Window w1,
+ Window* w2, Window* w3, Window** w4,
+ unsigned int* ui));
+/* 57 */
+EXTERN void XRaiseWindow _ANSI_ARGS_((Display* d, Window w));
+/* 58 */
+EXTERN void XRefreshKeyboardMapping _ANSI_ARGS_((
+ XMappingEvent* x));
+/* 59 */
+EXTERN void XResizeWindow _ANSI_ARGS_((Display* d, Window w,
+ unsigned int ui1, unsigned int ui2));
+/* 60 */
+EXTERN void XSelectInput _ANSI_ARGS_((Display* d, Window w,
+ long l));
+/* 61 */
+EXTERN Status XSendEvent _ANSI_ARGS_((Display* d, Window w, Bool b,
+ long l, XEvent* x));
+/* 62 */
+EXTERN void XSetCommand _ANSI_ARGS_((Display* d, Window w,
+ char** c, int i));
+/* 63 */
+EXTERN void XSetIconName _ANSI_ARGS_((Display* d, Window w,
+ _Xconst char* c));
+/* 64 */
+EXTERN void XSetInputFocus _ANSI_ARGS_((Display* d, Window w,
+ int i, Time t));
+/* 65 */
+EXTERN void XSetSelectionOwner _ANSI_ARGS_((Display* d, Atom a,
+ Window w, Time t));
+/* 66 */
+EXTERN void XSetWindowBackground _ANSI_ARGS_((Display* d,
+ Window w, unsigned long ul));
+/* 67 */
+EXTERN void XSetWindowBackgroundPixmap _ANSI_ARGS_((Display* d,
+ Window w, Pixmap p));
+/* 68 */
+EXTERN void XSetWindowBorder _ANSI_ARGS_((Display* d, Window w,
+ unsigned long ul));
+/* 69 */
+EXTERN void XSetWindowBorderPixmap _ANSI_ARGS_((Display* d,
+ Window w, Pixmap p));
+/* 70 */
+EXTERN void XSetWindowBorderWidth _ANSI_ARGS_((Display* d,
+ Window w, unsigned int ui));
+/* 71 */
+EXTERN void XSetWindowColormap _ANSI_ARGS_((Display* d, Window w,
+ Colormap c));
+/* 72 */
+EXTERN Bool XTranslateCoordinates _ANSI_ARGS_((Display* d,
+ Window w1, Window w2, int i1, int i2,
+ int* i3, int* i4, Window* w3));
+/* 73 */
+EXTERN void XUngrabKeyboard _ANSI_ARGS_((Display* d, Time t));
+/* 74 */
+EXTERN void XUngrabPointer _ANSI_ARGS_((Display* d, Time t));
+/* 75 */
+EXTERN void XUnmapWindow _ANSI_ARGS_((Display* d, Window w));
+/* 76 */
+EXTERN void XWindowEvent _ANSI_ARGS_((Display* d, Window w,
+ long l, XEvent* x));
+/* 77 */
+EXTERN void XDestroyIC _ANSI_ARGS_((XIC x));
+/* 78 */
+EXTERN Bool XFilterEvent _ANSI_ARGS_((XEvent* x, Window w));
+/* 79 */
+EXTERN int XmbLookupString _ANSI_ARGS_((XIC xi,
+ XKeyPressedEvent* xk, char* c, int i,
+ KeySym* k, Status* s));
+/* 80 */
+EXTERN void TkPutImage _ANSI_ARGS_((unsigned long * colors,
+ int ncolors, Display* display, Drawable d,
+ GC gc, XImage* image, int src_x, int src_y,
+ int dest_x, int dest_y, unsigned int width,
+ unsigned int height));
+/* Slot 81 is reserved */
+/* 82 */
+EXTERN Status XParseColor _ANSI_ARGS_((Display * display,
+ Colormap map, _Xconst char* spec,
+ XColor * colorPtr));
+/* 83 */
+EXTERN GC XCreateGC _ANSI_ARGS_((Display* display, Drawable d,
+ unsigned long valuemask, XGCValues* values));
+/* 84 */
+EXTERN void XFreeGC _ANSI_ARGS_((Display* display, GC gc));
+/* 85 */
+EXTERN Atom XInternAtom _ANSI_ARGS_((Display* display,
+ _Xconst char* atom_name, Bool only_if_exists));
+/* 86 */
+EXTERN void XSetBackground _ANSI_ARGS_((Display* display, GC gc,
+ unsigned long foreground));
+/* 87 */
+EXTERN void XSetForeground _ANSI_ARGS_((Display* display, GC gc,
+ unsigned long foreground));
+/* 88 */
+EXTERN void XSetClipMask _ANSI_ARGS_((Display* display, GC gc,
+ Pixmap pixmap));
+/* 89 */
+EXTERN void XSetClipOrigin _ANSI_ARGS_((Display* display, GC gc,
+ int clip_x_origin, int clip_y_origin));
+/* 90 */
+EXTERN void XSetTSOrigin _ANSI_ARGS_((Display* display, GC gc,
+ int ts_x_origin, int ts_y_origin));
+/* 91 */
+EXTERN void XChangeGC _ANSI_ARGS_((Display * d, GC gc,
+ unsigned long mask, XGCValues * values));
+/* 92 */
+EXTERN void XSetFont _ANSI_ARGS_((Display * display, GC gc,
+ Font font));
+/* 93 */
+EXTERN void XSetArcMode _ANSI_ARGS_((Display * display, GC gc,
+ int arc_mode));
+/* 94 */
+EXTERN void XSetStipple _ANSI_ARGS_((Display * display, GC gc,
+ Pixmap stipple));
+/* 95 */
+EXTERN void XSetFillRule _ANSI_ARGS_((Display * display, GC gc,
+ int fill_rule));
+/* 96 */
+EXTERN void XSetFillStyle _ANSI_ARGS_((Display * display, GC gc,
+ int fill_style));
+/* 97 */
+EXTERN void XSetFunction _ANSI_ARGS_((Display * display, GC gc,
+ int function));
+/* 98 */
+EXTERN void XSetLineAttributes _ANSI_ARGS_((Display * display,
+ GC gc, unsigned int line_width,
+ int line_style, int cap_style,
+ int join_style));
+/* 99 */
+EXTERN int _XInitImageFuncPtrs _ANSI_ARGS_((XImage * image));
+/* 100 */
+EXTERN XIC XCreateIC _ANSI_ARGS_((void));
+/* 101 */
+EXTERN XVisualInfo * XGetVisualInfo _ANSI_ARGS_((Display* display,
+ long vinfo_mask, XVisualInfo* vinfo_template,
+ int* nitems_return));
+/* 102 */
+EXTERN void XSetWMClientMachine _ANSI_ARGS_((Display* display,
+ Window w, XTextProperty* text_prop));
+/* 103 */
+EXTERN Status XStringListToTextProperty _ANSI_ARGS_((char** list,
+ int count, XTextProperty* text_prop_return));
+/* 104 */
+EXTERN void XDrawLine _ANSI_ARGS_((Display* d, Drawable dr, GC g,
+ int x1, int y1, int x2, int y2));
+/* 105 */
+EXTERN void XWarpPointer _ANSI_ARGS_((Display* d, Window s,
+ Window dw, int sx, int sy, unsigned int sw,
+ unsigned int sh, int dx, int dy));
+/* 106 */
+EXTERN void XFillRectangle _ANSI_ARGS_((Display* display,
+ Drawable d, GC gc, int x, int y,
+ unsigned int width, unsigned int height));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 0 */
+EXTERN void XSetDashes _ANSI_ARGS_((Display* display, GC gc,
+ int dash_offset, _Xconst char* dash_list,
+ int n));
+/* 1 */
+EXTERN XModifierKeymap* XGetModifierMapping _ANSI_ARGS_((Display* d));
+/* 2 */
+EXTERN XImage * XCreateImage _ANSI_ARGS_((Display* d, Visual* v,
+ unsigned int ui1, int i1, int i2, char* cp,
+ unsigned int ui2, unsigned int ui3, int i3,
+ int i4));
+/* 3 */
+EXTERN XImage * XGetImage _ANSI_ARGS_((Display* d, Drawable dr,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2, unsigned long ul, int i3));
+/* 4 */
+EXTERN char * XGetAtomName _ANSI_ARGS_((Display* d, Atom a));
+/* 5 */
+EXTERN char * XKeysymToString _ANSI_ARGS_((KeySym k));
+/* 6 */
+EXTERN Colormap XCreateColormap _ANSI_ARGS_((Display* d, Window w,
+ Visual* v, int i));
+/* 7 */
+EXTERN GContext XGContextFromGC _ANSI_ARGS_((GC g));
+/* 8 */
+EXTERN KeySym XKeycodeToKeysym _ANSI_ARGS_((Display* d, KeyCode k,
+ int i));
+/* 9 */
+EXTERN KeySym XStringToKeysym _ANSI_ARGS_((_Xconst char* c));
+/* 10 */
+EXTERN Window XRootWindow _ANSI_ARGS_((Display* d, int i));
+/* 11 */
+EXTERN XErrorHandler XSetErrorHandler _ANSI_ARGS_((XErrorHandler x));
+/* 12 */
+EXTERN Status XAllocColor _ANSI_ARGS_((Display* d, Colormap c,
+ XColor* xp));
+/* 13 */
+EXTERN void XBell _ANSI_ARGS_((Display* d, int i));
+/* 14 */
+EXTERN void XChangeProperty _ANSI_ARGS_((Display* d, Window w,
+ Atom a1, Atom a2, int i1, int i2,
+ _Xconst unsigned char* c, int i3));
+/* 15 */
+EXTERN void XChangeWindowAttributes _ANSI_ARGS_((Display* d,
+ Window w, unsigned long ul,
+ XSetWindowAttributes* x));
+/* 16 */
+EXTERN void XConfigureWindow _ANSI_ARGS_((Display* d, Window w,
+ unsigned int i, XWindowChanges* x));
+/* 17 */
+EXTERN void XCopyArea _ANSI_ARGS_((Display* d, Drawable dr1,
+ Drawable dr2, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3,
+ int i4));
+/* 18 */
+EXTERN void XCopyPlane _ANSI_ARGS_((Display* d, Drawable dr1,
+ Drawable dr2, GC g, int i1, int i2,
+ unsigned int ui1, unsigned int ui2, int i3,
+ int i4, unsigned long ul));
+/* 19 */
+EXTERN Pixmap XCreateBitmapFromData _ANSI_ARGS_((Display* display,
+ Drawable d, _Xconst char* data,
+ unsigned int width, unsigned int height));
+/* 20 */
+EXTERN void XDefineCursor _ANSI_ARGS_((Display* d, Window w,
+ Cursor c));
+/* 21 */
+EXTERN void XDestroyWindow _ANSI_ARGS_((Display* d, Window w));
+/* 22 */
+EXTERN void XDrawArc _ANSI_ARGS_((Display* d, Drawable dr, GC g,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4));
+/* 23 */
+EXTERN void XDrawLines _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, XPoint* x, int i1, int i2));
+/* 24 */
+EXTERN void XDrawRectangle _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, int i1, int i2, unsigned int ui1,
+ unsigned int ui2));
+/* 25 */
+EXTERN void XFillArc _ANSI_ARGS_((Display* d, Drawable dr, GC g,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2, int i3, int i4));
+/* 26 */
+EXTERN void XFillPolygon _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, XPoint* x, int i1, int i2, int i3));
+/* 27 */
+EXTERN void XFillRectangles _ANSI_ARGS_((Display* d, Drawable dr,
+ GC g, XRectangle* x, int i));
+/* 28 */
+EXTERN void XFreeColormap _ANSI_ARGS_((Display* d, Colormap c));
+/* 29 */
+EXTERN void XFreeColors _ANSI_ARGS_((Display* d, Colormap c,
+ unsigned long* ulp, int i, unsigned long ul));
+/* 30 */
+EXTERN void XFreeModifiermap _ANSI_ARGS_((XModifierKeymap* x));
+/* 31 */
+EXTERN Status XGetGeometry _ANSI_ARGS_((Display* d, Drawable dr,
+ Window* w, int* i1, int* i2,
+ unsigned int* ui1, unsigned int* ui2,
+ unsigned int* ui3, unsigned int* ui4));
+/* 32 */
+EXTERN int XGetWindowProperty _ANSI_ARGS_((Display* d, Window w,
+ Atom a1, long l1, long l2, Bool b, Atom a2,
+ Atom* ap, int* ip, unsigned long* ulp1,
+ unsigned long* ulp2, unsigned char** cpp));
+/* 33 */
+EXTERN int XGrabKeyboard _ANSI_ARGS_((Display* d, Window w,
+ Bool b, int i1, int i2, Time t));
+/* 34 */
+EXTERN int XGrabPointer _ANSI_ARGS_((Display* d, Window w1,
+ Bool b, unsigned int ui, int i1, int i2,
+ Window w2, Cursor c, Time t));
+/* 35 */
+EXTERN KeyCode XKeysymToKeycode _ANSI_ARGS_((Display* d, KeySym k));
+/* 36 */
+EXTERN void XMapWindow _ANSI_ARGS_((Display* d, Window w));
+/* 37 */
+EXTERN void XMoveResizeWindow _ANSI_ARGS_((Display* d, Window w,
+ int i1, int i2, unsigned int ui1,
+ unsigned int ui2));
+/* 38 */
+EXTERN void XMoveWindow _ANSI_ARGS_((Display* d, Window w,
+ int i1, int i2));
+/* 39 */
+EXTERN Bool XQueryPointer _ANSI_ARGS_((Display* d, Window w1,
+ Window* w2, Window* w3, int* i1, int* i2,
+ int* i3, int* i4, unsigned int* ui));
+/* 40 */
+EXTERN void XRaiseWindow _ANSI_ARGS_((Display* d, Window w));
+/* 41 */
+EXTERN void XRefreshKeyboardMapping _ANSI_ARGS_((
+ XMappingEvent* x));
+/* 42 */
+EXTERN void XResizeWindow _ANSI_ARGS_((Display* d, Window w,
+ unsigned int ui1, unsigned int ui2));
+/* 43 */
+EXTERN void XSelectInput _ANSI_ARGS_((Display* d, Window w,
+ long l));
+/* 44 */
+EXTERN Status XSendEvent _ANSI_ARGS_((Display* d, Window w, Bool b,
+ long l, XEvent* x));
+/* 45 */
+EXTERN void XSetIconName _ANSI_ARGS_((Display* d, Window w,
+ _Xconst char* c));
+/* 46 */
+EXTERN void XSetInputFocus _ANSI_ARGS_((Display* d, Window w,
+ int i, Time t));
+/* 47 */
+EXTERN void XSetSelectionOwner _ANSI_ARGS_((Display* d, Atom a,
+ Window w, Time t));
+/* 48 */
+EXTERN void XSetWindowBackground _ANSI_ARGS_((Display* d,
+ Window w, unsigned long ul));
+/* 49 */
+EXTERN void XSetWindowBackgroundPixmap _ANSI_ARGS_((Display* d,
+ Window w, Pixmap p));
+/* 50 */
+EXTERN void XSetWindowBorder _ANSI_ARGS_((Display* d, Window w,
+ unsigned long ul));
+/* 51 */
+EXTERN void XSetWindowBorderPixmap _ANSI_ARGS_((Display* d,
+ Window w, Pixmap p));
+/* 52 */
+EXTERN void XSetWindowBorderWidth _ANSI_ARGS_((Display* d,
+ Window w, unsigned int ui));
+/* 53 */
+EXTERN void XSetWindowColormap _ANSI_ARGS_((Display* d, Window w,
+ Colormap c));
+/* 54 */
+EXTERN void XUngrabKeyboard _ANSI_ARGS_((Display* d, Time t));
+/* 55 */
+EXTERN void XUngrabPointer _ANSI_ARGS_((Display* d, Time t));
+/* 56 */
+EXTERN void XUnmapWindow _ANSI_ARGS_((Display* d, Window w));
+/* 57 */
+EXTERN void TkPutImage _ANSI_ARGS_((unsigned long * colors,
+ int ncolors, Display* display, Drawable d,
+ GC gc, XImage* image, int src_x, int src_y,
+ int dest_x, int dest_y, unsigned int width,
+ unsigned int height));
+/* 58 */
+EXTERN Status XParseColor _ANSI_ARGS_((Display * display,
+ Colormap map, _Xconst char* spec,
+ XColor * colorPtr));
+/* 59 */
+EXTERN GC XCreateGC _ANSI_ARGS_((Display* display, Drawable d,
+ unsigned long valuemask, XGCValues* values));
+/* 60 */
+EXTERN void XFreeGC _ANSI_ARGS_((Display* display, GC gc));
+/* 61 */
+EXTERN Atom XInternAtom _ANSI_ARGS_((Display* display,
+ _Xconst char* atom_name, Bool only_if_exists));
+/* 62 */
+EXTERN void XSetBackground _ANSI_ARGS_((Display* display, GC gc,
+ unsigned long foreground));
+/* 63 */
+EXTERN void XSetForeground _ANSI_ARGS_((Display* display, GC gc,
+ unsigned long foreground));
+/* 64 */
+EXTERN void XSetClipMask _ANSI_ARGS_((Display* display, GC gc,
+ Pixmap pixmap));
+/* 65 */
+EXTERN void XSetClipOrigin _ANSI_ARGS_((Display* display, GC gc,
+ int clip_x_origin, int clip_y_origin));
+/* 66 */
+EXTERN void XSetTSOrigin _ANSI_ARGS_((Display* display, GC gc,
+ int ts_x_origin, int ts_y_origin));
+/* 67 */
+EXTERN void XChangeGC _ANSI_ARGS_((Display * d, GC gc,
+ unsigned long mask, XGCValues * values));
+/* 68 */
+EXTERN void XSetFont _ANSI_ARGS_((Display * display, GC gc,
+ Font font));
+/* 69 */
+EXTERN void XSetArcMode _ANSI_ARGS_((Display * display, GC gc,
+ int arc_mode));
+/* 70 */
+EXTERN void XSetStipple _ANSI_ARGS_((Display * display, GC gc,
+ Pixmap stipple));
+/* 71 */
+EXTERN void XSetFillRule _ANSI_ARGS_((Display * display, GC gc,
+ int fill_rule));
+/* 72 */
+EXTERN void XSetFillStyle _ANSI_ARGS_((Display * display, GC gc,
+ int fill_style));
+/* 73 */
+EXTERN void XSetFunction _ANSI_ARGS_((Display * display, GC gc,
+ int function));
+/* 74 */
+EXTERN void XSetLineAttributes _ANSI_ARGS_((Display * display,
+ GC gc, unsigned int line_width,
+ int line_style, int cap_style,
+ int join_style));
+/* 75 */
+EXTERN int _XInitImageFuncPtrs _ANSI_ARGS_((XImage * image));
+/* 76 */
+EXTERN XIC XCreateIC _ANSI_ARGS_((void));
+/* 77 */
+EXTERN XVisualInfo * XGetVisualInfo _ANSI_ARGS_((Display* display,
+ long vinfo_mask, XVisualInfo* vinfo_template,
+ int* nitems_return));
+/* 78 */
+EXTERN void XSetWMClientMachine _ANSI_ARGS_((Display* display,
+ Window w, XTextProperty* text_prop));
+/* 79 */
+EXTERN Status XStringListToTextProperty _ANSI_ARGS_((char** list,
+ int count, XTextProperty* text_prop_return));
+/* 80 */
+EXTERN void XDrawSegments _ANSI_ARGS_((Display * display,
+ Drawable d, GC gc, XSegment * segments,
+ int nsegments));
+/* 81 */
+EXTERN void XForceScreenSaver _ANSI_ARGS_((Display* display,
+ int mode));
+/* 82 */
+EXTERN void XDrawLine _ANSI_ARGS_((Display* d, Drawable dr, GC g,
+ int x1, int y1, int x2, int y2));
+/* 83 */
+EXTERN void XFillRectangle _ANSI_ARGS_((Display* display,
+ Drawable d, GC gc, int x, int y,
+ unsigned int width, unsigned int height));
+/* 84 */
+EXTERN void XClearWindow _ANSI_ARGS_((Display* d, Window w));
+/* 85 */
+EXTERN void XDrawPoint _ANSI_ARGS_((Display* display, Drawable d,
+ GC gc, int x, int y));
+/* 86 */
+EXTERN void XDrawPoints _ANSI_ARGS_((Display* display,
+ Drawable d, GC gc, XPoint * points,
+ int npoints, int mode));
+/* 87 */
+EXTERN void XWarpPointer _ANSI_ARGS_((Display* display,
+ Window src_w, Window dest_w, int src_x,
+ int src_y, unsigned int src_width,
+ unsigned int src_height, int dest_x,
+ int dest_y));
+/* 88 */
+EXTERN void XQueryColor _ANSI_ARGS_((Display * display,
+ Colormap colormap, XColor * def_in_out));
+/* 89 */
+EXTERN void XQueryColors _ANSI_ARGS_((Display * display,
+ Colormap colormap, XColor * defs_in_out,
+ int ncolors));
+#endif /* MAC_TCL */
+
+typedef struct TkIntXlibStubs {
+ int magic;
+ struct TkIntXlibStubHooks *hooks;
+
+#ifdef __WIN32__
+ void (*xSetDashes) _ANSI_ARGS_((Display* display, GC gc, int dash_offset, _Xconst char* dash_list, int n)); /* 0 */
+ XModifierKeymap* (*xGetModifierMapping) _ANSI_ARGS_((Display* d)); /* 1 */
+ XImage * (*xCreateImage) _ANSI_ARGS_((Display* d, Visual* v, unsigned int ui1, int i1, int i2, char* cp, unsigned int ui2, unsigned int ui3, int i3, int i4)); /* 2 */
+ XImage * (*xGetImage) _ANSI_ARGS_((Display* d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)); /* 3 */
+ char * (*xGetAtomName) _ANSI_ARGS_((Display* d, Atom a)); /* 4 */
+ char * (*xKeysymToString) _ANSI_ARGS_((KeySym k)); /* 5 */
+ Colormap (*xCreateColormap) _ANSI_ARGS_((Display* d, Window w, Visual* v, int i)); /* 6 */
+ Cursor (*xCreatePixmapCursor) _ANSI_ARGS_((Display* d, Pixmap p1, Pixmap p2, XColor* x1, XColor* x2, unsigned int ui1, unsigned int ui2)); /* 7 */
+ Cursor (*xCreateGlyphCursor) _ANSI_ARGS_((Display* d, Font f1, Font f2, unsigned int ui1, unsigned int ui2, XColor* x1, XColor* x2)); /* 8 */
+ GContext (*xGContextFromGC) _ANSI_ARGS_((GC g)); /* 9 */
+ XHostAddress * (*xListHosts) _ANSI_ARGS_((Display* d, int* i, Bool* b)); /* 10 */
+ KeySym (*xKeycodeToKeysym) _ANSI_ARGS_((Display* d, unsigned int k, int i)); /* 11 */
+ KeySym (*xStringToKeysym) _ANSI_ARGS_((_Xconst char* c)); /* 12 */
+ Window (*xRootWindow) _ANSI_ARGS_((Display* d, int i)); /* 13 */
+ XErrorHandler (*xSetErrorHandler) _ANSI_ARGS_((XErrorHandler x)); /* 14 */
+ Status (*xIconifyWindow) _ANSI_ARGS_((Display* d, Window w, int i)); /* 15 */
+ Status (*xWithdrawWindow) _ANSI_ARGS_((Display* d, Window w, int i)); /* 16 */
+ Status (*xGetWMColormapWindows) _ANSI_ARGS_((Display* d, Window w, Window** wpp, int* ip)); /* 17 */
+ Status (*xAllocColor) _ANSI_ARGS_((Display* d, Colormap c, XColor* xp)); /* 18 */
+ void (*xBell) _ANSI_ARGS_((Display* d, int i)); /* 19 */
+ void (*xChangeProperty) _ANSI_ARGS_((Display* d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char* c, int i3)); /* 20 */
+ void (*xChangeWindowAttributes) _ANSI_ARGS_((Display* d, Window w, unsigned long ul, XSetWindowAttributes* x)); /* 21 */
+ void (*xClearWindow) _ANSI_ARGS_((Display* d, Window w)); /* 22 */
+ void (*xConfigureWindow) _ANSI_ARGS_((Display* d, Window w, unsigned int i, XWindowChanges* x)); /* 23 */
+ void (*xCopyArea) _ANSI_ARGS_((Display* d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 24 */
+ void (*xCopyPlane) _ANSI_ARGS_((Display* d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul)); /* 25 */
+ Pixmap (*xCreateBitmapFromData) _ANSI_ARGS_((Display* display, Drawable d, _Xconst char* data, unsigned int width, unsigned int height)); /* 26 */
+ void (*xDefineCursor) _ANSI_ARGS_((Display* d, Window w, Cursor c)); /* 27 */
+ void (*xDeleteProperty) _ANSI_ARGS_((Display* d, Window w, Atom a)); /* 28 */
+ void (*xDestroyWindow) _ANSI_ARGS_((Display* d, Window w)); /* 29 */
+ void (*xDrawArc) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 30 */
+ void (*xDrawLines) _ANSI_ARGS_((Display* d, Drawable dr, GC g, XPoint* x, int i1, int i2)); /* 31 */
+ void (*xDrawRectangle) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 32 */
+ void (*xFillArc) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 33 */
+ void (*xFillPolygon) _ANSI_ARGS_((Display* d, Drawable dr, GC g, XPoint* x, int i1, int i2, int i3)); /* 34 */
+ void (*xFillRectangles) _ANSI_ARGS_((Display* d, Drawable dr, GC g, XRectangle* x, int i)); /* 35 */
+ void (*xForceScreenSaver) _ANSI_ARGS_((Display* d, int i)); /* 36 */
+ void (*xFreeColormap) _ANSI_ARGS_((Display* d, Colormap c)); /* 37 */
+ void (*xFreeColors) _ANSI_ARGS_((Display* d, Colormap c, unsigned long* ulp, int i, unsigned long ul)); /* 38 */
+ void (*xFreeCursor) _ANSI_ARGS_((Display* d, Cursor c)); /* 39 */
+ void (*xFreeModifiermap) _ANSI_ARGS_((XModifierKeymap* x)); /* 40 */
+ Status (*xGetGeometry) _ANSI_ARGS_((Display* d, Drawable dr, Window* w, int* i1, int* i2, unsigned int* ui1, unsigned int* ui2, unsigned int* ui3, unsigned int* ui4)); /* 41 */
+ void (*xGetInputFocus) _ANSI_ARGS_((Display* d, Window* w, int* i)); /* 42 */
+ int (*xGetWindowProperty) _ANSI_ARGS_((Display* d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom* ap, int* ip, unsigned long* ulp1, unsigned long* ulp2, unsigned char** cpp)); /* 43 */
+ Status (*xGetWindowAttributes) _ANSI_ARGS_((Display* d, Window w, XWindowAttributes* x)); /* 44 */
+ int (*xGrabKeyboard) _ANSI_ARGS_((Display* d, Window w, Bool b, int i1, int i2, Time t)); /* 45 */
+ int (*xGrabPointer) _ANSI_ARGS_((Display* d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t)); /* 46 */
+ KeyCode (*xKeysymToKeycode) _ANSI_ARGS_((Display* d, KeySym k)); /* 47 */
+ Status (*xLookupColor) _ANSI_ARGS_((Display* d, Colormap c1, _Xconst char* c2, XColor* x1, XColor* x2)); /* 48 */
+ void (*xMapWindow) _ANSI_ARGS_((Display* d, Window w)); /* 49 */
+ void (*xMoveResizeWindow) _ANSI_ARGS_((Display* d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 50 */
+ void (*xMoveWindow) _ANSI_ARGS_((Display* d, Window w, int i1, int i2)); /* 51 */
+ void (*xNextEvent) _ANSI_ARGS_((Display* d, XEvent* x)); /* 52 */
+ void (*xPutBackEvent) _ANSI_ARGS_((Display* d, XEvent* x)); /* 53 */
+ void (*xQueryColors) _ANSI_ARGS_((Display* d, Colormap c, XColor* x, int i)); /* 54 */
+ Bool (*xQueryPointer) _ANSI_ARGS_((Display* d, Window w1, Window* w2, Window* w3, int* i1, int* i2, int* i3, int* i4, unsigned int* ui)); /* 55 */
+ Status (*xQueryTree) _ANSI_ARGS_((Display* d, Window w1, Window* w2, Window* w3, Window** w4, unsigned int* ui)); /* 56 */
+ void (*xRaiseWindow) _ANSI_ARGS_((Display* d, Window w)); /* 57 */
+ void (*xRefreshKeyboardMapping) _ANSI_ARGS_((XMappingEvent* x)); /* 58 */
+ void (*xResizeWindow) _ANSI_ARGS_((Display* d, Window w, unsigned int ui1, unsigned int ui2)); /* 59 */
+ void (*xSelectInput) _ANSI_ARGS_((Display* d, Window w, long l)); /* 60 */
+ Status (*xSendEvent) _ANSI_ARGS_((Display* d, Window w, Bool b, long l, XEvent* x)); /* 61 */
+ void (*xSetCommand) _ANSI_ARGS_((Display* d, Window w, char** c, int i)); /* 62 */
+ void (*xSetIconName) _ANSI_ARGS_((Display* d, Window w, _Xconst char* c)); /* 63 */
+ void (*xSetInputFocus) _ANSI_ARGS_((Display* d, Window w, int i, Time t)); /* 64 */
+ void (*xSetSelectionOwner) _ANSI_ARGS_((Display* d, Atom a, Window w, Time t)); /* 65 */
+ void (*xSetWindowBackground) _ANSI_ARGS_((Display* d, Window w, unsigned long ul)); /* 66 */
+ void (*xSetWindowBackgroundPixmap) _ANSI_ARGS_((Display* d, Window w, Pixmap p)); /* 67 */
+ void (*xSetWindowBorder) _ANSI_ARGS_((Display* d, Window w, unsigned long ul)); /* 68 */
+ void (*xSetWindowBorderPixmap) _ANSI_ARGS_((Display* d, Window w, Pixmap p)); /* 69 */
+ void (*xSetWindowBorderWidth) _ANSI_ARGS_((Display* d, Window w, unsigned int ui)); /* 70 */
+ void (*xSetWindowColormap) _ANSI_ARGS_((Display* d, Window w, Colormap c)); /* 71 */
+ Bool (*xTranslateCoordinates) _ANSI_ARGS_((Display* d, Window w1, Window w2, int i1, int i2, int* i3, int* i4, Window* w3)); /* 72 */
+ void (*xUngrabKeyboard) _ANSI_ARGS_((Display* d, Time t)); /* 73 */
+ void (*xUngrabPointer) _ANSI_ARGS_((Display* d, Time t)); /* 74 */
+ void (*xUnmapWindow) _ANSI_ARGS_((Display* d, Window w)); /* 75 */
+ void (*xWindowEvent) _ANSI_ARGS_((Display* d, Window w, long l, XEvent* x)); /* 76 */
+ void (*xDestroyIC) _ANSI_ARGS_((XIC x)); /* 77 */
+ Bool (*xFilterEvent) _ANSI_ARGS_((XEvent* x, Window w)); /* 78 */
+ int (*xmbLookupString) _ANSI_ARGS_((XIC xi, XKeyPressedEvent* xk, char* c, int i, KeySym* k, Status* s)); /* 79 */
+ void (*tkPutImage) _ANSI_ARGS_((unsigned long * colors, int ncolors, Display* display, Drawable d, GC gc, XImage* image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)); /* 80 */
+ void *reserved81;
+ Status (*xParseColor) _ANSI_ARGS_((Display * display, Colormap map, _Xconst char* spec, XColor * colorPtr)); /* 82 */
+ GC (*xCreateGC) _ANSI_ARGS_((Display* display, Drawable d, unsigned long valuemask, XGCValues* values)); /* 83 */
+ void (*xFreeGC) _ANSI_ARGS_((Display* display, GC gc)); /* 84 */
+ Atom (*xInternAtom) _ANSI_ARGS_((Display* display, _Xconst char* atom_name, Bool only_if_exists)); /* 85 */
+ void (*xSetBackground) _ANSI_ARGS_((Display* display, GC gc, unsigned long foreground)); /* 86 */
+ void (*xSetForeground) _ANSI_ARGS_((Display* display, GC gc, unsigned long foreground)); /* 87 */
+ void (*xSetClipMask) _ANSI_ARGS_((Display* display, GC gc, Pixmap pixmap)); /* 88 */
+ void (*xSetClipOrigin) _ANSI_ARGS_((Display* display, GC gc, int clip_x_origin, int clip_y_origin)); /* 89 */
+ void (*xSetTSOrigin) _ANSI_ARGS_((Display* display, GC gc, int ts_x_origin, int ts_y_origin)); /* 90 */
+ void (*xChangeGC) _ANSI_ARGS_((Display * d, GC gc, unsigned long mask, XGCValues * values)); /* 91 */
+ void (*xSetFont) _ANSI_ARGS_((Display * display, GC gc, Font font)); /* 92 */
+ void (*xSetArcMode) _ANSI_ARGS_((Display * display, GC gc, int arc_mode)); /* 93 */
+ void (*xSetStipple) _ANSI_ARGS_((Display * display, GC gc, Pixmap stipple)); /* 94 */
+ void (*xSetFillRule) _ANSI_ARGS_((Display * display, GC gc, int fill_rule)); /* 95 */
+ void (*xSetFillStyle) _ANSI_ARGS_((Display * display, GC gc, int fill_style)); /* 96 */
+ void (*xSetFunction) _ANSI_ARGS_((Display * display, GC gc, int function)); /* 97 */
+ void (*xSetLineAttributes) _ANSI_ARGS_((Display * display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style)); /* 98 */
+ int (*_XInitImageFuncPtrs) _ANSI_ARGS_((XImage * image)); /* 99 */
+ XIC (*xCreateIC) _ANSI_ARGS_((void)); /* 100 */
+ XVisualInfo * (*xGetVisualInfo) _ANSI_ARGS_((Display* display, long vinfo_mask, XVisualInfo* vinfo_template, int* nitems_return)); /* 101 */
+ void (*xSetWMClientMachine) _ANSI_ARGS_((Display* display, Window w, XTextProperty* text_prop)); /* 102 */
+ Status (*xStringListToTextProperty) _ANSI_ARGS_((char** list, int count, XTextProperty* text_prop_return)); /* 103 */
+ void (*xDrawLine) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int x1, int y1, int x2, int y2)); /* 104 */
+ void (*xWarpPointer) _ANSI_ARGS_((Display* d, Window s, Window dw, int sx, int sy, unsigned int sw, unsigned int sh, int dx, int dy)); /* 105 */
+ void (*xFillRectangle) _ANSI_ARGS_((Display* display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height)); /* 106 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*xSetDashes) _ANSI_ARGS_((Display* display, GC gc, int dash_offset, _Xconst char* dash_list, int n)); /* 0 */
+ XModifierKeymap* (*xGetModifierMapping) _ANSI_ARGS_((Display* d)); /* 1 */
+ XImage * (*xCreateImage) _ANSI_ARGS_((Display* d, Visual* v, unsigned int ui1, int i1, int i2, char* cp, unsigned int ui2, unsigned int ui3, int i3, int i4)); /* 2 */
+ XImage * (*xGetImage) _ANSI_ARGS_((Display* d, Drawable dr, int i1, int i2, unsigned int ui1, unsigned int ui2, unsigned long ul, int i3)); /* 3 */
+ char * (*xGetAtomName) _ANSI_ARGS_((Display* d, Atom a)); /* 4 */
+ char * (*xKeysymToString) _ANSI_ARGS_((KeySym k)); /* 5 */
+ Colormap (*xCreateColormap) _ANSI_ARGS_((Display* d, Window w, Visual* v, int i)); /* 6 */
+ GContext (*xGContextFromGC) _ANSI_ARGS_((GC g)); /* 7 */
+ KeySym (*xKeycodeToKeysym) _ANSI_ARGS_((Display* d, KeyCode k, int i)); /* 8 */
+ KeySym (*xStringToKeysym) _ANSI_ARGS_((_Xconst char* c)); /* 9 */
+ Window (*xRootWindow) _ANSI_ARGS_((Display* d, int i)); /* 10 */
+ XErrorHandler (*xSetErrorHandler) _ANSI_ARGS_((XErrorHandler x)); /* 11 */
+ Status (*xAllocColor) _ANSI_ARGS_((Display* d, Colormap c, XColor* xp)); /* 12 */
+ void (*xBell) _ANSI_ARGS_((Display* d, int i)); /* 13 */
+ void (*xChangeProperty) _ANSI_ARGS_((Display* d, Window w, Atom a1, Atom a2, int i1, int i2, _Xconst unsigned char* c, int i3)); /* 14 */
+ void (*xChangeWindowAttributes) _ANSI_ARGS_((Display* d, Window w, unsigned long ul, XSetWindowAttributes* x)); /* 15 */
+ void (*xConfigureWindow) _ANSI_ARGS_((Display* d, Window w, unsigned int i, XWindowChanges* x)); /* 16 */
+ void (*xCopyArea) _ANSI_ARGS_((Display* d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 17 */
+ void (*xCopyPlane) _ANSI_ARGS_((Display* d, Drawable dr1, Drawable dr2, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4, unsigned long ul)); /* 18 */
+ Pixmap (*xCreateBitmapFromData) _ANSI_ARGS_((Display* display, Drawable d, _Xconst char* data, unsigned int width, unsigned int height)); /* 19 */
+ void (*xDefineCursor) _ANSI_ARGS_((Display* d, Window w, Cursor c)); /* 20 */
+ void (*xDestroyWindow) _ANSI_ARGS_((Display* d, Window w)); /* 21 */
+ void (*xDrawArc) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 22 */
+ void (*xDrawLines) _ANSI_ARGS_((Display* d, Drawable dr, GC g, XPoint* x, int i1, int i2)); /* 23 */
+ void (*xDrawRectangle) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 24 */
+ void (*xFillArc) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int i1, int i2, unsigned int ui1, unsigned int ui2, int i3, int i4)); /* 25 */
+ void (*xFillPolygon) _ANSI_ARGS_((Display* d, Drawable dr, GC g, XPoint* x, int i1, int i2, int i3)); /* 26 */
+ void (*xFillRectangles) _ANSI_ARGS_((Display* d, Drawable dr, GC g, XRectangle* x, int i)); /* 27 */
+ void (*xFreeColormap) _ANSI_ARGS_((Display* d, Colormap c)); /* 28 */
+ void (*xFreeColors) _ANSI_ARGS_((Display* d, Colormap c, unsigned long* ulp, int i, unsigned long ul)); /* 29 */
+ void (*xFreeModifiermap) _ANSI_ARGS_((XModifierKeymap* x)); /* 30 */
+ Status (*xGetGeometry) _ANSI_ARGS_((Display* d, Drawable dr, Window* w, int* i1, int* i2, unsigned int* ui1, unsigned int* ui2, unsigned int* ui3, unsigned int* ui4)); /* 31 */
+ int (*xGetWindowProperty) _ANSI_ARGS_((Display* d, Window w, Atom a1, long l1, long l2, Bool b, Atom a2, Atom* ap, int* ip, unsigned long* ulp1, unsigned long* ulp2, unsigned char** cpp)); /* 32 */
+ int (*xGrabKeyboard) _ANSI_ARGS_((Display* d, Window w, Bool b, int i1, int i2, Time t)); /* 33 */
+ int (*xGrabPointer) _ANSI_ARGS_((Display* d, Window w1, Bool b, unsigned int ui, int i1, int i2, Window w2, Cursor c, Time t)); /* 34 */
+ KeyCode (*xKeysymToKeycode) _ANSI_ARGS_((Display* d, KeySym k)); /* 35 */
+ void (*xMapWindow) _ANSI_ARGS_((Display* d, Window w)); /* 36 */
+ void (*xMoveResizeWindow) _ANSI_ARGS_((Display* d, Window w, int i1, int i2, unsigned int ui1, unsigned int ui2)); /* 37 */
+ void (*xMoveWindow) _ANSI_ARGS_((Display* d, Window w, int i1, int i2)); /* 38 */
+ Bool (*xQueryPointer) _ANSI_ARGS_((Display* d, Window w1, Window* w2, Window* w3, int* i1, int* i2, int* i3, int* i4, unsigned int* ui)); /* 39 */
+ void (*xRaiseWindow) _ANSI_ARGS_((Display* d, Window w)); /* 40 */
+ void (*xRefreshKeyboardMapping) _ANSI_ARGS_((XMappingEvent* x)); /* 41 */
+ void (*xResizeWindow) _ANSI_ARGS_((Display* d, Window w, unsigned int ui1, unsigned int ui2)); /* 42 */
+ void (*xSelectInput) _ANSI_ARGS_((Display* d, Window w, long l)); /* 43 */
+ Status (*xSendEvent) _ANSI_ARGS_((Display* d, Window w, Bool b, long l, XEvent* x)); /* 44 */
+ void (*xSetIconName) _ANSI_ARGS_((Display* d, Window w, _Xconst char* c)); /* 45 */
+ void (*xSetInputFocus) _ANSI_ARGS_((Display* d, Window w, int i, Time t)); /* 46 */
+ void (*xSetSelectionOwner) _ANSI_ARGS_((Display* d, Atom a, Window w, Time t)); /* 47 */
+ void (*xSetWindowBackground) _ANSI_ARGS_((Display* d, Window w, unsigned long ul)); /* 48 */
+ void (*xSetWindowBackgroundPixmap) _ANSI_ARGS_((Display* d, Window w, Pixmap p)); /* 49 */
+ void (*xSetWindowBorder) _ANSI_ARGS_((Display* d, Window w, unsigned long ul)); /* 50 */
+ void (*xSetWindowBorderPixmap) _ANSI_ARGS_((Display* d, Window w, Pixmap p)); /* 51 */
+ void (*xSetWindowBorderWidth) _ANSI_ARGS_((Display* d, Window w, unsigned int ui)); /* 52 */
+ void (*xSetWindowColormap) _ANSI_ARGS_((Display* d, Window w, Colormap c)); /* 53 */
+ void (*xUngrabKeyboard) _ANSI_ARGS_((Display* d, Time t)); /* 54 */
+ void (*xUngrabPointer) _ANSI_ARGS_((Display* d, Time t)); /* 55 */
+ void (*xUnmapWindow) _ANSI_ARGS_((Display* d, Window w)); /* 56 */
+ void (*tkPutImage) _ANSI_ARGS_((unsigned long * colors, int ncolors, Display* display, Drawable d, GC gc, XImage* image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)); /* 57 */
+ Status (*xParseColor) _ANSI_ARGS_((Display * display, Colormap map, _Xconst char* spec, XColor * colorPtr)); /* 58 */
+ GC (*xCreateGC) _ANSI_ARGS_((Display* display, Drawable d, unsigned long valuemask, XGCValues* values)); /* 59 */
+ void (*xFreeGC) _ANSI_ARGS_((Display* display, GC gc)); /* 60 */
+ Atom (*xInternAtom) _ANSI_ARGS_((Display* display, _Xconst char* atom_name, Bool only_if_exists)); /* 61 */
+ void (*xSetBackground) _ANSI_ARGS_((Display* display, GC gc, unsigned long foreground)); /* 62 */
+ void (*xSetForeground) _ANSI_ARGS_((Display* display, GC gc, unsigned long foreground)); /* 63 */
+ void (*xSetClipMask) _ANSI_ARGS_((Display* display, GC gc, Pixmap pixmap)); /* 64 */
+ void (*xSetClipOrigin) _ANSI_ARGS_((Display* display, GC gc, int clip_x_origin, int clip_y_origin)); /* 65 */
+ void (*xSetTSOrigin) _ANSI_ARGS_((Display* display, GC gc, int ts_x_origin, int ts_y_origin)); /* 66 */
+ void (*xChangeGC) _ANSI_ARGS_((Display * d, GC gc, unsigned long mask, XGCValues * values)); /* 67 */
+ void (*xSetFont) _ANSI_ARGS_((Display * display, GC gc, Font font)); /* 68 */
+ void (*xSetArcMode) _ANSI_ARGS_((Display * display, GC gc, int arc_mode)); /* 69 */
+ void (*xSetStipple) _ANSI_ARGS_((Display * display, GC gc, Pixmap stipple)); /* 70 */
+ void (*xSetFillRule) _ANSI_ARGS_((Display * display, GC gc, int fill_rule)); /* 71 */
+ void (*xSetFillStyle) _ANSI_ARGS_((Display * display, GC gc, int fill_style)); /* 72 */
+ void (*xSetFunction) _ANSI_ARGS_((Display * display, GC gc, int function)); /* 73 */
+ void (*xSetLineAttributes) _ANSI_ARGS_((Display * display, GC gc, unsigned int line_width, int line_style, int cap_style, int join_style)); /* 74 */
+ int (*_XInitImageFuncPtrs) _ANSI_ARGS_((XImage * image)); /* 75 */
+ XIC (*xCreateIC) _ANSI_ARGS_((void)); /* 76 */
+ XVisualInfo * (*xGetVisualInfo) _ANSI_ARGS_((Display* display, long vinfo_mask, XVisualInfo* vinfo_template, int* nitems_return)); /* 77 */
+ void (*xSetWMClientMachine) _ANSI_ARGS_((Display* display, Window w, XTextProperty* text_prop)); /* 78 */
+ Status (*xStringListToTextProperty) _ANSI_ARGS_((char** list, int count, XTextProperty* text_prop_return)); /* 79 */
+ void (*xDrawSegments) _ANSI_ARGS_((Display * display, Drawable d, GC gc, XSegment * segments, int nsegments)); /* 80 */
+ void (*xForceScreenSaver) _ANSI_ARGS_((Display* display, int mode)); /* 81 */
+ void (*xDrawLine) _ANSI_ARGS_((Display* d, Drawable dr, GC g, int x1, int y1, int x2, int y2)); /* 82 */
+ void (*xFillRectangle) _ANSI_ARGS_((Display* display, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height)); /* 83 */
+ void (*xClearWindow) _ANSI_ARGS_((Display* d, Window w)); /* 84 */
+ void (*xDrawPoint) _ANSI_ARGS_((Display* display, Drawable d, GC gc, int x, int y)); /* 85 */
+ void (*xDrawPoints) _ANSI_ARGS_((Display* display, Drawable d, GC gc, XPoint * points, int npoints, int mode)); /* 86 */
+ void (*xWarpPointer) _ANSI_ARGS_((Display* display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y)); /* 87 */
+ void (*xQueryColor) _ANSI_ARGS_((Display * display, Colormap colormap, XColor * def_in_out)); /* 88 */
+ void (*xQueryColors) _ANSI_ARGS_((Display * display, Colormap colormap, XColor * defs_in_out, int ncolors)); /* 89 */
+#endif /* MAC_TCL */
+} TkIntXlibStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern TkIntXlibStubs *tkIntXlibStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifdef __WIN32__
+#ifndef XSetDashes
+#define XSetDashes \
+ (tkIntXlibStubsPtr->xSetDashes) /* 0 */
+#endif
+#ifndef XGetModifierMapping
+#define XGetModifierMapping \
+ (tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
+#endif
+#ifndef XCreateImage
+#define XCreateImage \
+ (tkIntXlibStubsPtr->xCreateImage) /* 2 */
+#endif
+#ifndef XGetImage
+#define XGetImage \
+ (tkIntXlibStubsPtr->xGetImage) /* 3 */
+#endif
+#ifndef XGetAtomName
+#define XGetAtomName \
+ (tkIntXlibStubsPtr->xGetAtomName) /* 4 */
+#endif
+#ifndef XKeysymToString
+#define XKeysymToString \
+ (tkIntXlibStubsPtr->xKeysymToString) /* 5 */
+#endif
+#ifndef XCreateColormap
+#define XCreateColormap \
+ (tkIntXlibStubsPtr->xCreateColormap) /* 6 */
+#endif
+#ifndef XCreatePixmapCursor
+#define XCreatePixmapCursor \
+ (tkIntXlibStubsPtr->xCreatePixmapCursor) /* 7 */
+#endif
+#ifndef XCreateGlyphCursor
+#define XCreateGlyphCursor \
+ (tkIntXlibStubsPtr->xCreateGlyphCursor) /* 8 */
+#endif
+#ifndef XGContextFromGC
+#define XGContextFromGC \
+ (tkIntXlibStubsPtr->xGContextFromGC) /* 9 */
+#endif
+#ifndef XListHosts
+#define XListHosts \
+ (tkIntXlibStubsPtr->xListHosts) /* 10 */
+#endif
+#ifndef XKeycodeToKeysym
+#define XKeycodeToKeysym \
+ (tkIntXlibStubsPtr->xKeycodeToKeysym) /* 11 */
+#endif
+#ifndef XStringToKeysym
+#define XStringToKeysym \
+ (tkIntXlibStubsPtr->xStringToKeysym) /* 12 */
+#endif
+#ifndef XRootWindow
+#define XRootWindow \
+ (tkIntXlibStubsPtr->xRootWindow) /* 13 */
+#endif
+#ifndef XSetErrorHandler
+#define XSetErrorHandler \
+ (tkIntXlibStubsPtr->xSetErrorHandler) /* 14 */
+#endif
+#ifndef XIconifyWindow
+#define XIconifyWindow \
+ (tkIntXlibStubsPtr->xIconifyWindow) /* 15 */
+#endif
+#ifndef XWithdrawWindow
+#define XWithdrawWindow \
+ (tkIntXlibStubsPtr->xWithdrawWindow) /* 16 */
+#endif
+#ifndef XGetWMColormapWindows
+#define XGetWMColormapWindows \
+ (tkIntXlibStubsPtr->xGetWMColormapWindows) /* 17 */
+#endif
+#ifndef XAllocColor
+#define XAllocColor \
+ (tkIntXlibStubsPtr->xAllocColor) /* 18 */
+#endif
+#ifndef XBell
+#define XBell \
+ (tkIntXlibStubsPtr->xBell) /* 19 */
+#endif
+#ifndef XChangeProperty
+#define XChangeProperty \
+ (tkIntXlibStubsPtr->xChangeProperty) /* 20 */
+#endif
+#ifndef XChangeWindowAttributes
+#define XChangeWindowAttributes \
+ (tkIntXlibStubsPtr->xChangeWindowAttributes) /* 21 */
+#endif
+#ifndef XClearWindow
+#define XClearWindow \
+ (tkIntXlibStubsPtr->xClearWindow) /* 22 */
+#endif
+#ifndef XConfigureWindow
+#define XConfigureWindow \
+ (tkIntXlibStubsPtr->xConfigureWindow) /* 23 */
+#endif
+#ifndef XCopyArea
+#define XCopyArea \
+ (tkIntXlibStubsPtr->xCopyArea) /* 24 */
+#endif
+#ifndef XCopyPlane
+#define XCopyPlane \
+ (tkIntXlibStubsPtr->xCopyPlane) /* 25 */
+#endif
+#ifndef XCreateBitmapFromData
+#define XCreateBitmapFromData \
+ (tkIntXlibStubsPtr->xCreateBitmapFromData) /* 26 */
+#endif
+#ifndef XDefineCursor
+#define XDefineCursor \
+ (tkIntXlibStubsPtr->xDefineCursor) /* 27 */
+#endif
+#ifndef XDeleteProperty
+#define XDeleteProperty \
+ (tkIntXlibStubsPtr->xDeleteProperty) /* 28 */
+#endif
+#ifndef XDestroyWindow
+#define XDestroyWindow \
+ (tkIntXlibStubsPtr->xDestroyWindow) /* 29 */
+#endif
+#ifndef XDrawArc
+#define XDrawArc \
+ (tkIntXlibStubsPtr->xDrawArc) /* 30 */
+#endif
+#ifndef XDrawLines
+#define XDrawLines \
+ (tkIntXlibStubsPtr->xDrawLines) /* 31 */
+#endif
+#ifndef XDrawRectangle
+#define XDrawRectangle \
+ (tkIntXlibStubsPtr->xDrawRectangle) /* 32 */
+#endif
+#ifndef XFillArc
+#define XFillArc \
+ (tkIntXlibStubsPtr->xFillArc) /* 33 */
+#endif
+#ifndef XFillPolygon
+#define XFillPolygon \
+ (tkIntXlibStubsPtr->xFillPolygon) /* 34 */
+#endif
+#ifndef XFillRectangles
+#define XFillRectangles \
+ (tkIntXlibStubsPtr->xFillRectangles) /* 35 */
+#endif
+#ifndef XForceScreenSaver
+#define XForceScreenSaver \
+ (tkIntXlibStubsPtr->xForceScreenSaver) /* 36 */
+#endif
+#ifndef XFreeColormap
+#define XFreeColormap \
+ (tkIntXlibStubsPtr->xFreeColormap) /* 37 */
+#endif
+#ifndef XFreeColors
+#define XFreeColors \
+ (tkIntXlibStubsPtr->xFreeColors) /* 38 */
+#endif
+#ifndef XFreeCursor
+#define XFreeCursor \
+ (tkIntXlibStubsPtr->xFreeCursor) /* 39 */
+#endif
+#ifndef XFreeModifiermap
+#define XFreeModifiermap \
+ (tkIntXlibStubsPtr->xFreeModifiermap) /* 40 */
+#endif
+#ifndef XGetGeometry
+#define XGetGeometry \
+ (tkIntXlibStubsPtr->xGetGeometry) /* 41 */
+#endif
+#ifndef XGetInputFocus
+#define XGetInputFocus \
+ (tkIntXlibStubsPtr->xGetInputFocus) /* 42 */
+#endif
+#ifndef XGetWindowProperty
+#define XGetWindowProperty \
+ (tkIntXlibStubsPtr->xGetWindowProperty) /* 43 */
+#endif
+#ifndef XGetWindowAttributes
+#define XGetWindowAttributes \
+ (tkIntXlibStubsPtr->xGetWindowAttributes) /* 44 */
+#endif
+#ifndef XGrabKeyboard
+#define XGrabKeyboard \
+ (tkIntXlibStubsPtr->xGrabKeyboard) /* 45 */
+#endif
+#ifndef XGrabPointer
+#define XGrabPointer \
+ (tkIntXlibStubsPtr->xGrabPointer) /* 46 */
+#endif
+#ifndef XKeysymToKeycode
+#define XKeysymToKeycode \
+ (tkIntXlibStubsPtr->xKeysymToKeycode) /* 47 */
+#endif
+#ifndef XLookupColor
+#define XLookupColor \
+ (tkIntXlibStubsPtr->xLookupColor) /* 48 */
+#endif
+#ifndef XMapWindow
+#define XMapWindow \
+ (tkIntXlibStubsPtr->xMapWindow) /* 49 */
+#endif
+#ifndef XMoveResizeWindow
+#define XMoveResizeWindow \
+ (tkIntXlibStubsPtr->xMoveResizeWindow) /* 50 */
+#endif
+#ifndef XMoveWindow
+#define XMoveWindow \
+ (tkIntXlibStubsPtr->xMoveWindow) /* 51 */
+#endif
+#ifndef XNextEvent
+#define XNextEvent \
+ (tkIntXlibStubsPtr->xNextEvent) /* 52 */
+#endif
+#ifndef XPutBackEvent
+#define XPutBackEvent \
+ (tkIntXlibStubsPtr->xPutBackEvent) /* 53 */
+#endif
+#ifndef XQueryColors
+#define XQueryColors \
+ (tkIntXlibStubsPtr->xQueryColors) /* 54 */
+#endif
+#ifndef XQueryPointer
+#define XQueryPointer \
+ (tkIntXlibStubsPtr->xQueryPointer) /* 55 */
+#endif
+#ifndef XQueryTree
+#define XQueryTree \
+ (tkIntXlibStubsPtr->xQueryTree) /* 56 */
+#endif
+#ifndef XRaiseWindow
+#define XRaiseWindow \
+ (tkIntXlibStubsPtr->xRaiseWindow) /* 57 */
+#endif
+#ifndef XRefreshKeyboardMapping
+#define XRefreshKeyboardMapping \
+ (tkIntXlibStubsPtr->xRefreshKeyboardMapping) /* 58 */
+#endif
+#ifndef XResizeWindow
+#define XResizeWindow \
+ (tkIntXlibStubsPtr->xResizeWindow) /* 59 */
+#endif
+#ifndef XSelectInput
+#define XSelectInput \
+ (tkIntXlibStubsPtr->xSelectInput) /* 60 */
+#endif
+#ifndef XSendEvent
+#define XSendEvent \
+ (tkIntXlibStubsPtr->xSendEvent) /* 61 */
+#endif
+#ifndef XSetCommand
+#define XSetCommand \
+ (tkIntXlibStubsPtr->xSetCommand) /* 62 */
+#endif
+#ifndef XSetIconName
+#define XSetIconName \
+ (tkIntXlibStubsPtr->xSetIconName) /* 63 */
+#endif
+#ifndef XSetInputFocus
+#define XSetInputFocus \
+ (tkIntXlibStubsPtr->xSetInputFocus) /* 64 */
+#endif
+#ifndef XSetSelectionOwner
+#define XSetSelectionOwner \
+ (tkIntXlibStubsPtr->xSetSelectionOwner) /* 65 */
+#endif
+#ifndef XSetWindowBackground
+#define XSetWindowBackground \
+ (tkIntXlibStubsPtr->xSetWindowBackground) /* 66 */
+#endif
+#ifndef XSetWindowBackgroundPixmap
+#define XSetWindowBackgroundPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBackgroundPixmap) /* 67 */
+#endif
+#ifndef XSetWindowBorder
+#define XSetWindowBorder \
+ (tkIntXlibStubsPtr->xSetWindowBorder) /* 68 */
+#endif
+#ifndef XSetWindowBorderPixmap
+#define XSetWindowBorderPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBorderPixmap) /* 69 */
+#endif
+#ifndef XSetWindowBorderWidth
+#define XSetWindowBorderWidth \
+ (tkIntXlibStubsPtr->xSetWindowBorderWidth) /* 70 */
+#endif
+#ifndef XSetWindowColormap
+#define XSetWindowColormap \
+ (tkIntXlibStubsPtr->xSetWindowColormap) /* 71 */
+#endif
+#ifndef XTranslateCoordinates
+#define XTranslateCoordinates \
+ (tkIntXlibStubsPtr->xTranslateCoordinates) /* 72 */
+#endif
+#ifndef XUngrabKeyboard
+#define XUngrabKeyboard \
+ (tkIntXlibStubsPtr->xUngrabKeyboard) /* 73 */
+#endif
+#ifndef XUngrabPointer
+#define XUngrabPointer \
+ (tkIntXlibStubsPtr->xUngrabPointer) /* 74 */
+#endif
+#ifndef XUnmapWindow
+#define XUnmapWindow \
+ (tkIntXlibStubsPtr->xUnmapWindow) /* 75 */
+#endif
+#ifndef XWindowEvent
+#define XWindowEvent \
+ (tkIntXlibStubsPtr->xWindowEvent) /* 76 */
+#endif
+#ifndef XDestroyIC
+#define XDestroyIC \
+ (tkIntXlibStubsPtr->xDestroyIC) /* 77 */
+#endif
+#ifndef XFilterEvent
+#define XFilterEvent \
+ (tkIntXlibStubsPtr->xFilterEvent) /* 78 */
+#endif
+#ifndef XmbLookupString
+#define XmbLookupString \
+ (tkIntXlibStubsPtr->xmbLookupString) /* 79 */
+#endif
+#ifndef TkPutImage
+#define TkPutImage \
+ (tkIntXlibStubsPtr->tkPutImage) /* 80 */
+#endif
+/* Slot 81 is reserved */
+#ifndef XParseColor
+#define XParseColor \
+ (tkIntXlibStubsPtr->xParseColor) /* 82 */
+#endif
+#ifndef XCreateGC
+#define XCreateGC \
+ (tkIntXlibStubsPtr->xCreateGC) /* 83 */
+#endif
+#ifndef XFreeGC
+#define XFreeGC \
+ (tkIntXlibStubsPtr->xFreeGC) /* 84 */
+#endif
+#ifndef XInternAtom
+#define XInternAtom \
+ (tkIntXlibStubsPtr->xInternAtom) /* 85 */
+#endif
+#ifndef XSetBackground
+#define XSetBackground \
+ (tkIntXlibStubsPtr->xSetBackground) /* 86 */
+#endif
+#ifndef XSetForeground
+#define XSetForeground \
+ (tkIntXlibStubsPtr->xSetForeground) /* 87 */
+#endif
+#ifndef XSetClipMask
+#define XSetClipMask \
+ (tkIntXlibStubsPtr->xSetClipMask) /* 88 */
+#endif
+#ifndef XSetClipOrigin
+#define XSetClipOrigin \
+ (tkIntXlibStubsPtr->xSetClipOrigin) /* 89 */
+#endif
+#ifndef XSetTSOrigin
+#define XSetTSOrigin \
+ (tkIntXlibStubsPtr->xSetTSOrigin) /* 90 */
+#endif
+#ifndef XChangeGC
+#define XChangeGC \
+ (tkIntXlibStubsPtr->xChangeGC) /* 91 */
+#endif
+#ifndef XSetFont
+#define XSetFont \
+ (tkIntXlibStubsPtr->xSetFont) /* 92 */
+#endif
+#ifndef XSetArcMode
+#define XSetArcMode \
+ (tkIntXlibStubsPtr->xSetArcMode) /* 93 */
+#endif
+#ifndef XSetStipple
+#define XSetStipple \
+ (tkIntXlibStubsPtr->xSetStipple) /* 94 */
+#endif
+#ifndef XSetFillRule
+#define XSetFillRule \
+ (tkIntXlibStubsPtr->xSetFillRule) /* 95 */
+#endif
+#ifndef XSetFillStyle
+#define XSetFillStyle \
+ (tkIntXlibStubsPtr->xSetFillStyle) /* 96 */
+#endif
+#ifndef XSetFunction
+#define XSetFunction \
+ (tkIntXlibStubsPtr->xSetFunction) /* 97 */
+#endif
+#ifndef XSetLineAttributes
+#define XSetLineAttributes \
+ (tkIntXlibStubsPtr->xSetLineAttributes) /* 98 */
+#endif
+#ifndef _XInitImageFuncPtrs
+#define _XInitImageFuncPtrs \
+ (tkIntXlibStubsPtr->_XInitImageFuncPtrs) /* 99 */
+#endif
+#ifndef XCreateIC
+#define XCreateIC \
+ (tkIntXlibStubsPtr->xCreateIC) /* 100 */
+#endif
+#ifndef XGetVisualInfo
+#define XGetVisualInfo \
+ (tkIntXlibStubsPtr->xGetVisualInfo) /* 101 */
+#endif
+#ifndef XSetWMClientMachine
+#define XSetWMClientMachine \
+ (tkIntXlibStubsPtr->xSetWMClientMachine) /* 102 */
+#endif
+#ifndef XStringListToTextProperty
+#define XStringListToTextProperty \
+ (tkIntXlibStubsPtr->xStringListToTextProperty) /* 103 */
+#endif
+#ifndef XDrawLine
+#define XDrawLine \
+ (tkIntXlibStubsPtr->xDrawLine) /* 104 */
+#endif
+#ifndef XWarpPointer
+#define XWarpPointer \
+ (tkIntXlibStubsPtr->xWarpPointer) /* 105 */
+#endif
+#ifndef XFillRectangle
+#define XFillRectangle \
+ (tkIntXlibStubsPtr->xFillRectangle) /* 106 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef XSetDashes
+#define XSetDashes \
+ (tkIntXlibStubsPtr->xSetDashes) /* 0 */
+#endif
+#ifndef XGetModifierMapping
+#define XGetModifierMapping \
+ (tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
+#endif
+#ifndef XCreateImage
+#define XCreateImage \
+ (tkIntXlibStubsPtr->xCreateImage) /* 2 */
+#endif
+#ifndef XGetImage
+#define XGetImage \
+ (tkIntXlibStubsPtr->xGetImage) /* 3 */
+#endif
+#ifndef XGetAtomName
+#define XGetAtomName \
+ (tkIntXlibStubsPtr->xGetAtomName) /* 4 */
+#endif
+#ifndef XKeysymToString
+#define XKeysymToString \
+ (tkIntXlibStubsPtr->xKeysymToString) /* 5 */
+#endif
+#ifndef XCreateColormap
+#define XCreateColormap \
+ (tkIntXlibStubsPtr->xCreateColormap) /* 6 */
+#endif
+#ifndef XGContextFromGC
+#define XGContextFromGC \
+ (tkIntXlibStubsPtr->xGContextFromGC) /* 7 */
+#endif
+#ifndef XKeycodeToKeysym
+#define XKeycodeToKeysym \
+ (tkIntXlibStubsPtr->xKeycodeToKeysym) /* 8 */
+#endif
+#ifndef XStringToKeysym
+#define XStringToKeysym \
+ (tkIntXlibStubsPtr->xStringToKeysym) /* 9 */
+#endif
+#ifndef XRootWindow
+#define XRootWindow \
+ (tkIntXlibStubsPtr->xRootWindow) /* 10 */
+#endif
+#ifndef XSetErrorHandler
+#define XSetErrorHandler \
+ (tkIntXlibStubsPtr->xSetErrorHandler) /* 11 */
+#endif
+#ifndef XAllocColor
+#define XAllocColor \
+ (tkIntXlibStubsPtr->xAllocColor) /* 12 */
+#endif
+#ifndef XBell
+#define XBell \
+ (tkIntXlibStubsPtr->xBell) /* 13 */
+#endif
+#ifndef XChangeProperty
+#define XChangeProperty \
+ (tkIntXlibStubsPtr->xChangeProperty) /* 14 */
+#endif
+#ifndef XChangeWindowAttributes
+#define XChangeWindowAttributes \
+ (tkIntXlibStubsPtr->xChangeWindowAttributes) /* 15 */
+#endif
+#ifndef XConfigureWindow
+#define XConfigureWindow \
+ (tkIntXlibStubsPtr->xConfigureWindow) /* 16 */
+#endif
+#ifndef XCopyArea
+#define XCopyArea \
+ (tkIntXlibStubsPtr->xCopyArea) /* 17 */
+#endif
+#ifndef XCopyPlane
+#define XCopyPlane \
+ (tkIntXlibStubsPtr->xCopyPlane) /* 18 */
+#endif
+#ifndef XCreateBitmapFromData
+#define XCreateBitmapFromData \
+ (tkIntXlibStubsPtr->xCreateBitmapFromData) /* 19 */
+#endif
+#ifndef XDefineCursor
+#define XDefineCursor \
+ (tkIntXlibStubsPtr->xDefineCursor) /* 20 */
+#endif
+#ifndef XDestroyWindow
+#define XDestroyWindow \
+ (tkIntXlibStubsPtr->xDestroyWindow) /* 21 */
+#endif
+#ifndef XDrawArc
+#define XDrawArc \
+ (tkIntXlibStubsPtr->xDrawArc) /* 22 */
+#endif
+#ifndef XDrawLines
+#define XDrawLines \
+ (tkIntXlibStubsPtr->xDrawLines) /* 23 */
+#endif
+#ifndef XDrawRectangle
+#define XDrawRectangle \
+ (tkIntXlibStubsPtr->xDrawRectangle) /* 24 */
+#endif
+#ifndef XFillArc
+#define XFillArc \
+ (tkIntXlibStubsPtr->xFillArc) /* 25 */
+#endif
+#ifndef XFillPolygon
+#define XFillPolygon \
+ (tkIntXlibStubsPtr->xFillPolygon) /* 26 */
+#endif
+#ifndef XFillRectangles
+#define XFillRectangles \
+ (tkIntXlibStubsPtr->xFillRectangles) /* 27 */
+#endif
+#ifndef XFreeColormap
+#define XFreeColormap \
+ (tkIntXlibStubsPtr->xFreeColormap) /* 28 */
+#endif
+#ifndef XFreeColors
+#define XFreeColors \
+ (tkIntXlibStubsPtr->xFreeColors) /* 29 */
+#endif
+#ifndef XFreeModifiermap
+#define XFreeModifiermap \
+ (tkIntXlibStubsPtr->xFreeModifiermap) /* 30 */
+#endif
+#ifndef XGetGeometry
+#define XGetGeometry \
+ (tkIntXlibStubsPtr->xGetGeometry) /* 31 */
+#endif
+#ifndef XGetWindowProperty
+#define XGetWindowProperty \
+ (tkIntXlibStubsPtr->xGetWindowProperty) /* 32 */
+#endif
+#ifndef XGrabKeyboard
+#define XGrabKeyboard \
+ (tkIntXlibStubsPtr->xGrabKeyboard) /* 33 */
+#endif
+#ifndef XGrabPointer
+#define XGrabPointer \
+ (tkIntXlibStubsPtr->xGrabPointer) /* 34 */
+#endif
+#ifndef XKeysymToKeycode
+#define XKeysymToKeycode \
+ (tkIntXlibStubsPtr->xKeysymToKeycode) /* 35 */
+#endif
+#ifndef XMapWindow
+#define XMapWindow \
+ (tkIntXlibStubsPtr->xMapWindow) /* 36 */
+#endif
+#ifndef XMoveResizeWindow
+#define XMoveResizeWindow \
+ (tkIntXlibStubsPtr->xMoveResizeWindow) /* 37 */
+#endif
+#ifndef XMoveWindow
+#define XMoveWindow \
+ (tkIntXlibStubsPtr->xMoveWindow) /* 38 */
+#endif
+#ifndef XQueryPointer
+#define XQueryPointer \
+ (tkIntXlibStubsPtr->xQueryPointer) /* 39 */
+#endif
+#ifndef XRaiseWindow
+#define XRaiseWindow \
+ (tkIntXlibStubsPtr->xRaiseWindow) /* 40 */
+#endif
+#ifndef XRefreshKeyboardMapping
+#define XRefreshKeyboardMapping \
+ (tkIntXlibStubsPtr->xRefreshKeyboardMapping) /* 41 */
+#endif
+#ifndef XResizeWindow
+#define XResizeWindow \
+ (tkIntXlibStubsPtr->xResizeWindow) /* 42 */
+#endif
+#ifndef XSelectInput
+#define XSelectInput \
+ (tkIntXlibStubsPtr->xSelectInput) /* 43 */
+#endif
+#ifndef XSendEvent
+#define XSendEvent \
+ (tkIntXlibStubsPtr->xSendEvent) /* 44 */
+#endif
+#ifndef XSetIconName
+#define XSetIconName \
+ (tkIntXlibStubsPtr->xSetIconName) /* 45 */
+#endif
+#ifndef XSetInputFocus
+#define XSetInputFocus \
+ (tkIntXlibStubsPtr->xSetInputFocus) /* 46 */
+#endif
+#ifndef XSetSelectionOwner
+#define XSetSelectionOwner \
+ (tkIntXlibStubsPtr->xSetSelectionOwner) /* 47 */
+#endif
+#ifndef XSetWindowBackground
+#define XSetWindowBackground \
+ (tkIntXlibStubsPtr->xSetWindowBackground) /* 48 */
+#endif
+#ifndef XSetWindowBackgroundPixmap
+#define XSetWindowBackgroundPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBackgroundPixmap) /* 49 */
+#endif
+#ifndef XSetWindowBorder
+#define XSetWindowBorder \
+ (tkIntXlibStubsPtr->xSetWindowBorder) /* 50 */
+#endif
+#ifndef XSetWindowBorderPixmap
+#define XSetWindowBorderPixmap \
+ (tkIntXlibStubsPtr->xSetWindowBorderPixmap) /* 51 */
+#endif
+#ifndef XSetWindowBorderWidth
+#define XSetWindowBorderWidth \
+ (tkIntXlibStubsPtr->xSetWindowBorderWidth) /* 52 */
+#endif
+#ifndef XSetWindowColormap
+#define XSetWindowColormap \
+ (tkIntXlibStubsPtr->xSetWindowColormap) /* 53 */
+#endif
+#ifndef XUngrabKeyboard
+#define XUngrabKeyboard \
+ (tkIntXlibStubsPtr->xUngrabKeyboard) /* 54 */
+#endif
+#ifndef XUngrabPointer
+#define XUngrabPointer \
+ (tkIntXlibStubsPtr->xUngrabPointer) /* 55 */
+#endif
+#ifndef XUnmapWindow
+#define XUnmapWindow \
+ (tkIntXlibStubsPtr->xUnmapWindow) /* 56 */
+#endif
+#ifndef TkPutImage
+#define TkPutImage \
+ (tkIntXlibStubsPtr->tkPutImage) /* 57 */
+#endif
+#ifndef XParseColor
+#define XParseColor \
+ (tkIntXlibStubsPtr->xParseColor) /* 58 */
+#endif
+#ifndef XCreateGC
+#define XCreateGC \
+ (tkIntXlibStubsPtr->xCreateGC) /* 59 */
+#endif
+#ifndef XFreeGC
+#define XFreeGC \
+ (tkIntXlibStubsPtr->xFreeGC) /* 60 */
+#endif
+#ifndef XInternAtom
+#define XInternAtom \
+ (tkIntXlibStubsPtr->xInternAtom) /* 61 */
+#endif
+#ifndef XSetBackground
+#define XSetBackground \
+ (tkIntXlibStubsPtr->xSetBackground) /* 62 */
+#endif
+#ifndef XSetForeground
+#define XSetForeground \
+ (tkIntXlibStubsPtr->xSetForeground) /* 63 */
+#endif
+#ifndef XSetClipMask
+#define XSetClipMask \
+ (tkIntXlibStubsPtr->xSetClipMask) /* 64 */
+#endif
+#ifndef XSetClipOrigin
+#define XSetClipOrigin \
+ (tkIntXlibStubsPtr->xSetClipOrigin) /* 65 */
+#endif
+#ifndef XSetTSOrigin
+#define XSetTSOrigin \
+ (tkIntXlibStubsPtr->xSetTSOrigin) /* 66 */
+#endif
+#ifndef XChangeGC
+#define XChangeGC \
+ (tkIntXlibStubsPtr->xChangeGC) /* 67 */
+#endif
+#ifndef XSetFont
+#define XSetFont \
+ (tkIntXlibStubsPtr->xSetFont) /* 68 */
+#endif
+#ifndef XSetArcMode
+#define XSetArcMode \
+ (tkIntXlibStubsPtr->xSetArcMode) /* 69 */
+#endif
+#ifndef XSetStipple
+#define XSetStipple \
+ (tkIntXlibStubsPtr->xSetStipple) /* 70 */
+#endif
+#ifndef XSetFillRule
+#define XSetFillRule \
+ (tkIntXlibStubsPtr->xSetFillRule) /* 71 */
+#endif
+#ifndef XSetFillStyle
+#define XSetFillStyle \
+ (tkIntXlibStubsPtr->xSetFillStyle) /* 72 */
+#endif
+#ifndef XSetFunction
+#define XSetFunction \
+ (tkIntXlibStubsPtr->xSetFunction) /* 73 */
+#endif
+#ifndef XSetLineAttributes
+#define XSetLineAttributes \
+ (tkIntXlibStubsPtr->xSetLineAttributes) /* 74 */
+#endif
+#ifndef _XInitImageFuncPtrs
+#define _XInitImageFuncPtrs \
+ (tkIntXlibStubsPtr->_XInitImageFuncPtrs) /* 75 */
+#endif
+#ifndef XCreateIC
+#define XCreateIC \
+ (tkIntXlibStubsPtr->xCreateIC) /* 76 */
+#endif
+#ifndef XGetVisualInfo
+#define XGetVisualInfo \
+ (tkIntXlibStubsPtr->xGetVisualInfo) /* 77 */
+#endif
+#ifndef XSetWMClientMachine
+#define XSetWMClientMachine \
+ (tkIntXlibStubsPtr->xSetWMClientMachine) /* 78 */
+#endif
+#ifndef XStringListToTextProperty
+#define XStringListToTextProperty \
+ (tkIntXlibStubsPtr->xStringListToTextProperty) /* 79 */
+#endif
+#ifndef XDrawSegments
+#define XDrawSegments \
+ (tkIntXlibStubsPtr->xDrawSegments) /* 80 */
+#endif
+#ifndef XForceScreenSaver
+#define XForceScreenSaver \
+ (tkIntXlibStubsPtr->xForceScreenSaver) /* 81 */
+#endif
+#ifndef XDrawLine
+#define XDrawLine \
+ (tkIntXlibStubsPtr->xDrawLine) /* 82 */
+#endif
+#ifndef XFillRectangle
+#define XFillRectangle \
+ (tkIntXlibStubsPtr->xFillRectangle) /* 83 */
+#endif
+#ifndef XClearWindow
+#define XClearWindow \
+ (tkIntXlibStubsPtr->xClearWindow) /* 84 */
+#endif
+#ifndef XDrawPoint
+#define XDrawPoint \
+ (tkIntXlibStubsPtr->xDrawPoint) /* 85 */
+#endif
+#ifndef XDrawPoints
+#define XDrawPoints \
+ (tkIntXlibStubsPtr->xDrawPoints) /* 86 */
+#endif
+#ifndef XWarpPointer
+#define XWarpPointer \
+ (tkIntXlibStubsPtr->xWarpPointer) /* 87 */
+#endif
+#ifndef XQueryColor
+#define XQueryColor \
+ (tkIntXlibStubsPtr->xQueryColor) /* 88 */
+#endif
+#ifndef XQueryColors
+#define XQueryColors \
+ (tkIntXlibStubsPtr->xQueryColors) /* 89 */
+#endif
+#endif /* MAC_TCL */
+
+#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKINTXLIBDECLS */
diff --git a/tk/generic/tkListbox.c b/tk/generic/tkListbox.c
index 9e32979956c..f6b0f75f6ca 100644
--- a/tk/generic/tkListbox.c
+++ b/tk/generic/tkListbox.c
@@ -18,30 +18,13 @@
#include "default.h"
#include "tkInt.h"
-/*
- * One record of the following type is kept for each element
- * associated with a listbox widget:
- */
-
-typedef struct Element {
- int textLength; /* # non-NULL characters in text. */
- int lBearing; /* Distance from first character's
- * origin to left edge of character. */
- int pixelWidth; /* Total width of element in pixels (including
- * left bearing and right bearing). */
- int selected; /* 1 means this item is selected, 0 means
- * it isn't. */
- struct Element *nextPtr; /* Next in list of all elements of this
- * listbox, or NULL for last element. */
- char text[4]; /* Characters of this element, NULL-
- * terminated. The actual space allocated
- * here will be as large as needed (> 4,
- * most likely). Must be the last field
- * of the record. */
-} Element;
-
-#define ElementSize(stringLength) \
- ((unsigned) (sizeof(Element) - 3 + stringLength))
+typedef struct {
+ Tk_OptionTable listboxOptionTable; /* Table defining configuration options
+ * available for the listbox */
+ Tk_OptionTable itemAttrOptionTable; /* Table definining configuration
+ * options available for listbox
+ * items */
+} ListboxOptionTables;
/*
* A data structure of the following type is kept for each listbox
@@ -58,11 +41,16 @@ typedef struct {
* freed even after tkwin has gone away. */
Tcl_Interp *interp; /* Interpreter associated with listbox. */
Tcl_Command widgetCmd; /* Token for listbox's widget command. */
- int numElements; /* Total number of elements in this listbox. */
- Element *firstPtr; /* First in list of elements (NULL if no
- * elements). */
- Element *lastPtr; /* Last in list of elements (NULL if no
- * elements). */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ Tk_OptionTable itemAttrOptionTable; /* Table that defines configuration
+ * options available for listbox
+ * items */
+ char *listVarName; /* List variable name */
+ Tcl_Obj *listObj; /* Pointer to the list object being used */
+ int nElements; /* Holds the current count of elements */
+ Tcl_HashTable *selection; /* Tracks selection */
+ Tcl_HashTable *itemAttrTable; /* Tracks item attributes */
/*
* Information used when displaying widget:
@@ -172,6 +160,17 @@ typedef struct {
} Listbox;
/*
+ * ItemAttr structures are used to store item configuration information for
+ * the items in a listbox
+ */
+typedef struct {
+ Tk_3DBorder border; /* Used for drawing background around text */
+ Tk_3DBorder selBorder; /* Used for selected text */
+ XColor *fgColor; /* Text color in normal mode. */
+ XColor *selFgColor; /* Text color in selected mode. */
+} ItemAttr;
+
+/*
* Flag bits for listboxes:
*
* REDRAW_PENDING: Non-zero means a DoWhenIdle handler
@@ -183,106 +182,184 @@ typedef struct {
* to be updated.
* GOT_FOCUS: Non-zero means this widget currently
* has the input focus.
+ * MAXWIDTH_IS_STALE: Stored maxWidth may be out-of-date
+ * LISTBOX_DELETED: This listbox has been effectively destroyed.
*/
#define REDRAW_PENDING 1
#define UPDATE_V_SCROLLBAR 2
#define UPDATE_H_SCROLLBAR 4
#define GOT_FOCUS 8
+#define MAXWIDTH_IS_STALE 16
+#define LISTBOX_DELETED 32
/*
- * Information used for argv parsing:
+ * The optionSpecs table defines the valid configuration options for the
+ * listbox widget
*/
+static Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_LISTBOX_BG_COLOR, -1, Tk_Offset(Listbox, normalBorder),
+ 0, (ClientData) DEF_LISTBOX_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_LISTBOX_BORDER_WIDTH, -1, Tk_Offset(Listbox, borderWidth),
+ 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_LISTBOX_CURSOR, -1, Tk_Offset(Listbox, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, -1,
+ Tk_Offset(Listbox, exportSelection), 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_LISTBOX_FONT, -1, Tk_Offset(Listbox, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_LISTBOX_FG, -1, Tk_Offset(Listbox, fgColorPtr), 0, 0, 0},
+ {TK_OPTION_INT, "-height", "height", "Height",
+ DEF_LISTBOX_HEIGHT, -1, Tk_Offset(Listbox, height), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, -1,
+ Tk_Offset(Listbox, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_LISTBOX_HIGHLIGHT, -1, Tk_Offset(Listbox, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(Listbox, highlightWidth), 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_LISTBOX_RELIEF, -1, Tk_Offset(Listbox, relief), 0, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ DEF_LISTBOX_SELECT_COLOR, -1, Tk_Offset(Listbox, selBorder),
+ 0, (ClientData) DEF_LISTBOX_SELECT_MONO, 0},
+ {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_LISTBOX_SELECT_BD, -1,
+ Tk_Offset(Listbox, selBorderWidth), 0, 0, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ DEF_LISTBOX_SELECT_FG_COLOR, -1, Tk_Offset(Listbox, selFgColorPtr),
+ 0, (ClientData) DEF_LISTBOX_SELECT_FG_MONO, 0},
+ {TK_OPTION_STRING, "-selectmode", "selectMode", "SelectMode",
+ DEF_LISTBOX_SELECT_MODE, -1, Tk_Offset(Listbox, selectMode),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
+ DEF_LISTBOX_SET_GRID, -1, Tk_Offset(Listbox, setGrid), 0, 0, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_LISTBOX_TAKE_FOCUS, -1, Tk_Offset(Listbox, takeFocus),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-width", "width", "Width",
+ DEF_LISTBOX_WIDTH, -1, Tk_Offset(Listbox, width), 0, 0, 0},
+ {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
+ DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, xScrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
+ DEF_LISTBOX_SCROLL_COMMAND, -1, Tk_Offset(Listbox, yScrollCmd),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-listvariable", "listVariable", "Variable",
+ DEF_LISTBOX_LIST_VARIABLE, -1, Tk_Offset(Listbox, listVarName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, 0, 0}
+};
-static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_LISTBOX_BG_COLOR, Tk_Offset(Listbox, normalBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_LISTBOX_BG_MONO, Tk_Offset(Listbox, normalBorder),
- 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_LISTBOX_BORDER_WIDTH, Tk_Offset(Listbox, borderWidth), 0},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_LISTBOX_CURSOR, Tk_Offset(Listbox, cursor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection",
- "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION,
- Tk_Offset(Listbox, exportSelection), 0},
- {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_FONT, "-font", "font", "Font",
- DEF_LISTBOX_FONT, Tk_Offset(Listbox, tkfont), 0},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_LISTBOX_FG, Tk_Offset(Listbox, fgColorPtr), 0},
- {TK_CONFIG_INT, "-height", "height", "Height",
- DEF_LISTBOX_HEIGHT, Tk_Offset(Listbox, height), 0},
- {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG,
- Tk_Offset(Listbox, highlightBgColorPtr), 0},
- {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_LISTBOX_HIGHLIGHT, Tk_Offset(Listbox, highlightColorPtr), 0},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness",
- DEF_LISTBOX_HIGHLIGHT_WIDTH, Tk_Offset(Listbox, highlightWidth), 0},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_LISTBOX_RELIEF, Tk_Offset(Listbox, relief), 0},
- {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_LISTBOX_SELECT_COLOR, Tk_Offset(Listbox, selBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_LISTBOX_SELECT_MONO, Tk_Offset(Listbox, selBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
- DEF_LISTBOX_SELECT_BD, Tk_Offset(Listbox, selBorderWidth), 0},
- {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_LISTBOX_SELECT_FG_COLOR, Tk_Offset(Listbox, selFgColorPtr),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_LISTBOX_SELECT_FG_MONO, Tk_Offset(Listbox, selFgColorPtr),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_UID, "-selectmode", "selectMode", "SelectMode",
- DEF_LISTBOX_SELECT_MODE, Tk_Offset(Listbox, selectMode), 0},
- {TK_CONFIG_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
- DEF_LISTBOX_SET_GRID, Tk_Offset(Listbox, setGrid), 0},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_LISTBOX_TAKE_FOCUS, Tk_Offset(Listbox, takeFocus),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_INT, "-width", "width", "Width",
- DEF_LISTBOX_WIDTH, Tk_Offset(Listbox, width), 0},
- {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- DEF_LISTBOX_SCROLL_COMMAND, Tk_Offset(Listbox, xScrollCmd),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
- DEF_LISTBOX_SCROLL_COMMAND, Tk_Offset(Listbox, yScrollCmd),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+/*
+ * The itemAttrOptionSpecs table defines the valid configuration options for
+ * listbox items
+ */
+static Tk_OptionSpec itemAttrOptionSpecs[] = {
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ (char *)NULL, -1, Tk_Offset(ItemAttr, border),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
+ (ClientData) DEF_LISTBOX_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ (char *) NULL, -1, Tk_Offset(ItemAttr, fgColor),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT, 0, 0},
+ {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
+ (char *) NULL, -1, Tk_Offset(ItemAttr, selBorder),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
+ (ClientData) DEF_LISTBOX_SELECT_MONO, 0},
+ {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
+ (char *) NULL, -1, Tk_Offset(ItemAttr, selFgColor),
+ TK_OPTION_NULL_OK|TK_OPTION_DONT_SET_DEFAULT,
+ (ClientData) DEF_LISTBOX_SELECT_FG_MONO, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, 0, 0}
};
/*
- * Forward declarations for procedures defined later in this file:
+ * The following tables define the listbox widget commands (and sub-
+ * commands) and map the indexes into the string tables into
+ * enumerated types used to dispatch the listbox widget command.
*/
+static char *commandNames[] = {
+ "activate", "bbox", "cget", "configure", "curselection", "delete", "get",
+ "index", "insert", "itemcget", "itemconfigure", "nearest", "scan",
+ "see", "selection", "size", "xview", "yview",
+ (char *) NULL
+};
+enum command {
+ COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE,
+ COMMAND_CURSELECTION, COMMAND_DELETE, COMMAND_GET, COMMAND_INDEX,
+ COMMAND_INSERT, COMMAND_ITEMCGET, COMMAND_ITEMCONFIGURE,
+ COMMAND_NEAREST, COMMAND_SCAN, COMMAND_SEE, COMMAND_SELECTION,
+ COMMAND_SIZE, COMMAND_XVIEW, COMMAND_YVIEW
+};
+
+static char *selCommandNames[] = {
+ "anchor", "clear", "includes", "set", (char *) NULL
+};
+
+enum selcommand {
+ SELECTION_ANCHOR, SELECTION_CLEAR, SELECTION_INCLUDES, SELECTION_SET
+};
+
+static char *scanCommandNames[] = {
+ "mark", "dragto", (char *) NULL
+};
+
+enum scancommand {
+ SCAN_MARK, SCAN_DRAGTO
+};
+
+static char *indexNames[] = {
+ "active", "anchor", "end", (char *)NULL
+};
+
+enum indices {
+ INDEX_ACTIVE, INDEX_ANCHOR, INDEX_END
+};
+
+
+/* Declarations for procedures defined later in this file */
static void ChangeListboxOffset _ANSI_ARGS_((Listbox *listPtr,
int offset));
static void ChangeListboxView _ANSI_ARGS_((Listbox *listPtr,
int index));
static int ConfigureListbox _ANSI_ARGS_((Tcl_Interp *interp,
- Listbox *listPtr, int argc, char **argv,
+ Listbox *listPtr, int objc, Tcl_Obj *CONST objv[],
int flags));
-static void DeleteEls _ANSI_ARGS_((Listbox *listPtr, int first,
- int last));
+static int ConfigureListboxItem _ANSI_ARGS_ ((Tcl_Interp *interp,
+ Listbox *listPtr, ItemAttr *attrs, int objc,
+ Tcl_Obj *CONST objv[]));
+static int ListboxDeleteSubCmd _ANSI_ARGS_((Listbox *listPtr,
+ int first, int last));
static void DestroyListbox _ANSI_ARGS_((char *memPtr));
+static void DestroyListboxOptionTables _ANSI_ARGS_ (
+ (ClientData clientData, Tcl_Interp *interp));
static void DisplayListbox _ANSI_ARGS_((ClientData clientData));
static int GetListboxIndex _ANSI_ARGS_((Tcl_Interp *interp,
- Listbox *listPtr, char *string, int endIsSize,
+ Listbox *listPtr, Tcl_Obj *index, int endIsSize,
int *indexPtr));
-static void InsertEls _ANSI_ARGS_((Listbox *listPtr, int index,
- int argc, char **argv));
+static int ListboxInsertSubCmd _ANSI_ARGS_((Listbox *listPtr,
+ int index, int objc, Tcl_Obj *CONST objv[]));
static void ListboxCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static void ListboxComputeGeometry _ANSI_ARGS_((Listbox *listPtr,
@@ -294,21 +371,41 @@ static int ListboxFetchSelection _ANSI_ARGS_((
int maxBytes));
static void ListboxLostSelection _ANSI_ARGS_((
ClientData clientData));
-static void ListboxRedrawRange _ANSI_ARGS_((Listbox *listPtr,
+static void EventuallyRedrawRange _ANSI_ARGS_((Listbox *listPtr,
int first, int last));
static void ListboxScanTo _ANSI_ARGS_((Listbox *listPtr,
int x, int y));
-static void ListboxSelect _ANSI_ARGS_((Listbox *listPtr,
+static int ListboxSelect _ANSI_ARGS_((Listbox *listPtr,
int first, int last, int select));
-static void ListboxUpdateHScrollbar _ANSI_ARGS_((Listbox *listPtr));
-static void ListboxUpdateVScrollbar _ANSI_ARGS_((Listbox *listPtr));
-static int ListboxWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+static void ListboxUpdateHScrollbar _ANSI_ARGS_(
+ (Listbox *listPtr));
+static void ListboxUpdateVScrollbar _ANSI_ARGS_(
+ (Listbox *listPtr));
+static int ListboxWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
+static int ListboxBboxSubCmd _ANSI_ARGS_ ((Tcl_Interp *interp,
+ Listbox *listPtr, int index));
+static int ListboxSelectionSubCmd _ANSI_ARGS_ (
+ (Tcl_Interp *interp, Listbox *listPtr, int objc,
+ Tcl_Obj *CONST objv[]));
+static int ListboxXviewSubCmd _ANSI_ARGS_ ((Tcl_Interp *interp,
+ Listbox *listPtr, int objc,
+ Tcl_Obj *CONST objv[]));
+static int ListboxYviewSubCmd _ANSI_ARGS_ ((Tcl_Interp *interp,
+ Listbox *listPtr, int objc,
+ Tcl_Obj *CONST objv[]));
+static ItemAttr * ListboxGetItemAttributes _ANSI_ARGS_ (
+ (Tcl_Interp *interp, Listbox *listPtr, int index));
static void ListboxWorldChanged _ANSI_ARGS_((
ClientData instanceData));
static int NearestListboxElement _ANSI_ARGS_((Listbox *listPtr,
int y));
-
+static char * ListboxListVarProc _ANSI_ARGS_ ((ClientData clientData,
+ Tcl_Interp *interp, char *name1, char *name2,
+ int flags));
+static void MigrateHashEntries _ANSI_ARGS_ ((Tcl_HashTable *table,
+ int first, int last, int offset));
/*
* The structure below defines button class behavior by means of procedures
* that can be invoked from generic window code.
@@ -324,7 +421,7 @@ static TkClassProcs listboxClass = {
/*
*--------------------------------------------------------------
*
- * Tk_ListboxCmd --
+ * Tk_ListboxObjCmd --
*
* This procedure is invoked to process the "listbox" Tcl
* command. See the user documentation for details on what
@@ -340,25 +437,53 @@ static TkClassProcs listboxClass = {
*/
int
-Tk_ListboxCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_ListboxObjCmd(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 objects. */
{
register Listbox *listPtr;
- Tk_Window new;
- Tk_Window tkwin = (Tk_Window) clientData;
+ Tk_Window tkwin;
+ ListboxOptionTables *optionTables;
+
+ optionTables = (ListboxOptionTables *)clientData;
+ if (optionTables == NULL) {
+ Tcl_CmdInfo info;
+ char *name;
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " pathName ?options?\"", (char *) NULL);
+ /*
+ * We haven't created the option tables for this widget class yet.
+ * Do it now and save the a pointer to them as the ClientData for
+ * the command, so future invocations will have access to it.
+ */
+ optionTables =
+ (ListboxOptionTables *) ckalloc(sizeof(ListboxOptionTables));
+ /* Set up an exit handler to free the optionTables struct */
+ Tcl_SetAssocData(interp, "ListboxOptionTables",
+ DestroyListboxOptionTables, (ClientData) optionTables);
+
+ /* Create the listbox option table and the listbox item option table */
+ optionTables->listboxOptionTable =
+ Tk_CreateOptionTable(interp, optionSpecs);
+ optionTables->itemAttrOptionTable =
+ Tk_CreateOptionTable(interp, itemAttrOptionSpecs);
+
+ /* Store a pointer to the tables as the ClientData for the command */
+ name = Tcl_GetString(objv[0]);
+ Tcl_GetCommandInfo(interp, name, &info);
+ info.objClientData = (ClientData) optionTables;
+ Tcl_SetCommandInfo(interp, name, &info);
+ }
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
return TCL_ERROR;
}
- 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;
}
@@ -367,55 +492,62 @@ Tk_ListboxCmd(clientData, interp, argc, argv)
* by ConfigureListbox, or that ConfigureListbox requires to be
* initialized already (e.g. resource pointers).
*/
-
- listPtr = (Listbox *) ckalloc(sizeof(Listbox));
- listPtr->tkwin = new;
- listPtr->display = Tk_Display(new);
- listPtr->interp = interp;
- listPtr->widgetCmd = Tcl_CreateCommand(interp,
- Tk_PathName(listPtr->tkwin), ListboxWidgetCmd,
+ listPtr = (Listbox *) ckalloc(sizeof(Listbox));
+ listPtr->tkwin = tkwin;
+ listPtr->display = Tk_Display(tkwin);
+ listPtr->interp = interp;
+ listPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(listPtr->tkwin), ListboxWidgetObjCmd,
(ClientData) listPtr, ListboxCmdDeletedProc);
- listPtr->numElements = 0;
- listPtr->firstPtr = NULL;
- listPtr->lastPtr = NULL;
- listPtr->normalBorder = NULL;
- listPtr->borderWidth = 0;
- listPtr->relief = TK_RELIEF_RAISED;
- listPtr->highlightWidth = 0;
- listPtr->highlightBgColorPtr = NULL;
- listPtr->highlightColorPtr = NULL;
- listPtr->inset = 0;
- listPtr->tkfont = NULL;
- listPtr->fgColorPtr = NULL;
- listPtr->textGC = None;
- listPtr->selBorder = NULL;
- listPtr->selBorderWidth = 0;
- listPtr->selFgColorPtr = None;
- listPtr->selTextGC = None;
- listPtr->width = 0;
- listPtr->height = 0;
- listPtr->lineHeight = 0;
- listPtr->topIndex = 0;
- listPtr->fullLines = 1;
- listPtr->partialLine = 0;
- listPtr->setGrid = 0;
- listPtr->maxWidth = 0;
- listPtr->xScrollUnit = 1;
- listPtr->xOffset = 0;
- listPtr->selectMode = NULL;
- listPtr->numSelected = 0;
- listPtr->selectAnchor = 0;
- listPtr->exportSelection = 1;
- listPtr->active = 0;
- listPtr->scanMarkX = 0;
- listPtr->scanMarkY = 0;
- listPtr->scanMarkXOffset = 0;
- listPtr->scanMarkYIndex = 0;
- listPtr->cursor = None;
- listPtr->takeFocus = NULL;
- listPtr->xScrollCmd = NULL;
- listPtr->yScrollCmd = NULL;
- listPtr->flags = 0;
+ listPtr->optionTable = optionTables->listboxOptionTable;
+ listPtr->itemAttrOptionTable = optionTables->itemAttrOptionTable;
+ listPtr->listVarName = NULL;
+ listPtr->listObj = NULL;
+ listPtr->selection =
+ (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(listPtr->selection, TCL_ONE_WORD_KEYS);
+ listPtr->itemAttrTable =
+ (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(listPtr->itemAttrTable, TCL_ONE_WORD_KEYS);
+ listPtr->nElements = 0;
+ listPtr->normalBorder = NULL;
+ listPtr->borderWidth = 0;
+ listPtr->relief = TK_RELIEF_RAISED;
+ listPtr->highlightWidth = 0;
+ listPtr->highlightBgColorPtr = NULL;
+ listPtr->highlightColorPtr = NULL;
+ listPtr->inset = 0;
+ listPtr->tkfont = NULL;
+ listPtr->fgColorPtr = NULL;
+ listPtr->textGC = None;
+ listPtr->selBorder = NULL;
+ listPtr->selBorderWidth = 0;
+ listPtr->selFgColorPtr = None;
+ listPtr->selTextGC = None;
+ listPtr->width = 0;
+ listPtr->height = 0;
+ listPtr->lineHeight = 0;
+ listPtr->topIndex = 0;
+ listPtr->fullLines = 1;
+ listPtr->partialLine = 0;
+ listPtr->setGrid = 0;
+ listPtr->maxWidth = 0;
+ listPtr->xScrollUnit = 1;
+ listPtr->xOffset = 0;
+ listPtr->selectMode = NULL;
+ listPtr->numSelected = 0;
+ listPtr->selectAnchor = 0;
+ listPtr->exportSelection = 1;
+ listPtr->active = 0;
+ listPtr->scanMarkX = 0;
+ listPtr->scanMarkY = 0;
+ listPtr->scanMarkXOffset = 0;
+ listPtr->scanMarkYIndex = 0;
+ listPtr->cursor = None;
+ listPtr->takeFocus = NULL;
+ listPtr->xScrollCmd = NULL;
+ listPtr->yScrollCmd = NULL;
+ listPtr->flags = 0;
Tk_SetClass(listPtr->tkwin, "Listbox");
TkSetClassProcs(listPtr->tkwin, &listboxClass, (ClientData) listPtr);
@@ -424,26 +556,29 @@ Tk_ListboxCmd(clientData, interp, argc, argv)
ListboxEventProc, (ClientData) listPtr);
Tk_CreateSelHandler(listPtr->tkwin, XA_PRIMARY, XA_STRING,
ListboxFetchSelection, (ClientData) listPtr, XA_STRING);
- if (ConfigureListbox(interp, listPtr, argc-2, argv+2, 0) != TCL_OK) {
- goto error;
+ if (Tk_InitOptions(interp, (char *)listPtr,
+ optionTables->listboxOptionTable, tkwin) != TCL_OK) {
+ Tk_DestroyWindow(listPtr->tkwin);
+ return TCL_ERROR;
}
- interp->result = Tk_PathName(listPtr->tkwin);
- return TCL_OK;
+ if (ConfigureListbox(interp, listPtr, objc-2, objv+2, 0) != TCL_OK) {
+ Tk_DestroyWindow(listPtr->tkwin);
+ return TCL_ERROR;
+ }
- error:
- Tk_DestroyWindow(listPtr->tkwin);
- return TCL_ERROR;
+ Tcl_SetResult(interp, Tk_PathName(listPtr->tkwin), TCL_STATIC);
+ return TCL_OK;
}
/*
- *--------------------------------------------------------------
+ *----------------------------------------------------------------------
*
- * ListboxWidgetCmd --
+ * ListboxWidgetObjCmd --
*
- * This procedure is invoked to process the Tcl command
- * that corresponds to a widget managed by this module.
- * See the user documentation for details on what it does.
+ * This Tcl_Obj based procedure is invoked to process the Tcl command
+ * that corresponds to a widget managed by this module. See the user
+ * documentation for details on what it does.
*
* Results:
* A standard Tcl result.
@@ -451,477 +586,804 @@ Tk_ListboxCmd(clientData, interp, argc, argv)
* Side effects:
* See the user documentation.
*
- *--------------------------------------------------------------
+ *----------------------------------------------------------------------
*/
static int
-ListboxWidgetCmd(clientData, interp, argc, argv)
+ListboxWidgetObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about listbox widget. */
Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- char **argv; /* Argument strings. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Arguments as Tcl_Obj's. */
{
register Listbox *listPtr = (Listbox *) clientData;
+ int cmdIndex, index;
int result = TCL_OK;
- size_t length;
- int c;
- Tk_FontMetrics fm;
-
- 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;
}
- Tcl_Preserve((ClientData) listPtr);
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 'a') && (strncmp(argv[1], "activate", length) == 0)) {
- int index;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " activate index\"",
- (char *) NULL);
- goto error;
- }
- ListboxRedrawRange(listPtr, listPtr->active, listPtr->active);
- if (GetListboxIndex(interp, listPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index >= listPtr->numElements) {
- index = listPtr->numElements-1;
- }
- if (index < 0) {
- index = 0;
- }
- listPtr->active = index;
- ListboxRedrawRange(listPtr, listPtr->active, listPtr->active);
- } else if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) {
- int index, x, y, i;
- Element *elPtr;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " bbox index\"", (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if ((index >= listPtr->numElements) || (index < 0)) {
- goto done;
- }
- for (i = 0, elPtr = listPtr->firstPtr; i < index;
- i++, elPtr = elPtr->nextPtr) {
- /* Empty loop body. */
- }
- if ((index >= listPtr->topIndex) && (index < listPtr->numElements)
- && (index < (listPtr->topIndex + listPtr->fullLines
- + listPtr->partialLine))) {
- 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);
- }
- } 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;
- }
- result = Tk_ConfigureValue(interp, listPtr->tkwin, configSpecs,
- (char *) listPtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, listPtr->tkwin, configSpecs,
- (char *) listPtr, (char *) NULL, 0);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, listPtr->tkwin, configSpecs,
- (char *) listPtr, argv[2], 0);
- } else {
- result = ConfigureListbox(interp, listPtr, argc-2, argv+2,
- TK_CONFIG_ARGV_ONLY);
- }
- } else if ((c == 'c') && (strncmp(argv[1], "curselection", length) == 0)
- && (length >= 2)) {
- int i, count;
- char index[20];
- Element *elPtr;
+ Tcl_Preserve((ClientData)listPtr);
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " curselection\"",
- (char *) NULL);
- goto error;
- }
- count = 0;
- for (i = 0, elPtr = listPtr->firstPtr; elPtr != NULL;
- i++, elPtr = elPtr->nextPtr) {
- if (elPtr->selected) {
- sprintf(index, "%d", i);
- Tcl_AppendElement(interp, index);
- count++;
+ /*
+ * Parse the command by looking up the second argument in the list
+ * of valid subcommand names
+ */
+ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
+ "option", 0, &cmdIndex);
+ if (result != TCL_OK) {
+ Tcl_Release((ClientData)listPtr);
+ return result;
+ }
+
+ /* The subcommand was valid, so continue processing */
+ switch (cmdIndex) {
+ case COMMAND_ACTIVATE: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
}
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (index >= listPtr->nElements) {
+ index = listPtr->nElements-1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ listPtr->active = index;
+ EventuallyRedrawRange(listPtr, listPtr->active, listPtr->active);
+ result = TCL_OK;
+ break;
}
- if (count != listPtr->numSelected) {
- panic("ListboxWidgetCmd: selection count incorrect");
- }
- } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)) {
- int first, last;
- if ((argc < 3) || (argc > 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " delete firstIndex ?lastIndex?\"",
- (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[2], 0, &first) != TCL_OK) {
- goto error;
+ case COMMAND_BBOX: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ result = ListboxBboxSubCmd(interp, listPtr, index);
+ break;
}
- if (first < listPtr->numElements) {
- if (argc == 3) {
- last = first;
+
+ case COMMAND_CGET: {
+ Tcl_Obj *objPtr;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option");
+ result = TCL_ERROR;
+ break;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *)listPtr,
+ listPtr->optionTable, objv[2], listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_CONFIGURE: {
+ Tcl_Obj *objPtr;
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) listPtr,
+ listPtr->optionTable,
+ (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
+ listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ }
} else {
- if (GetListboxIndex(interp, listPtr, argv[3], 0,
- &last) != TCL_OK) {
- goto error;
+ result = ConfigureListbox(interp, listPtr, objc-2, objv+2, 0);
+ }
+ break;
+ }
+
+ case COMMAND_CURSELECTION: {
+ char indexStringRep[TCL_INTEGER_SPACE];
+ int i;
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+ /*
+ * Of course, it would be more efficient to use the Tcl_HashTable
+ * search functions (Tcl_FirstHashEntry, Tcl_NextHashEntry), but
+ * then the result wouldn't be in sorted order. So instead we
+ * loop through the indices in order, adding them to the result
+ * if they are selected
+ */
+ for (i = 0; i < listPtr->nElements; i++) {
+ if (Tcl_FindHashEntry(listPtr->selection, (char *)i) != NULL) {
+ sprintf(indexStringRep, "%d", i);
+ Tcl_AppendElement(interp, indexStringRep);
+ }
+ }
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_DELETE: {
+ int first, last;
+ if ((objc < 3) || (objc > 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "firstIndex ?lastIndex?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &first);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (first < listPtr->nElements) {
+ /*
+ * if a "last index" was given, get it now; otherwise, use the
+ * first index as the last index
+ */
+ if (objc == 4) {
+ result = GetListboxIndex(interp, listPtr,
+ objv[3], 0, &last);
+ if (result != TCL_OK) {
+ break;
+ }
+ } else {
+ last = first;
}
- if (last >= listPtr->numElements) {
- last = listPtr->numElements-1;
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements - 1;
}
+ result = ListboxDeleteSubCmd(listPtr, first, last);
+ } else {
+ result = TCL_OK;
}
- DeleteEls(listPtr, first, last);
+ break;
}
- } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
- int first, last, i;
- Element *elPtr;
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " get first ?last?\"", (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[2], 0, &first) != TCL_OK) {
- goto error;
- }
- if ((argc == 4) && (GetListboxIndex(interp, listPtr, argv[3],
- 0, &last) != TCL_OK)) {
- goto error;
- }
- if (first >= listPtr->numElements) {
- goto done;
- }
- if (last >= listPtr->numElements) {
- last = listPtr->numElements-1;
+ case COMMAND_GET: {
+ int first, last;
+ Tcl_Obj **elemPtrs;
+ int listLen;
+ if (objc != 3 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &first);
+ if (result != TCL_OK) {
+ break;
+ }
+ last = first;
+ if (objc == 4) {
+ result = GetListboxIndex(interp, listPtr, objv[3], 0, &last);
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ if (first >= listPtr->nElements) {
+ result = TCL_OK;
+ break;
+ }
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements - 1;
+ }
+ if (first < 0) {
+ first = 0;
+ }
+ if (first > last) {
+ result = TCL_OK;
+ break;
+ }
+ result = Tcl_ListObjGetElements(interp, listPtr->listObj, &listLen,
+ &elemPtrs);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (objc == 3) {
+ /*
+ * One element request - we return a string
+ */
+ Tcl_SetObjResult(interp, elemPtrs[first]);
+ } else {
+ Tcl_SetListObj(Tcl_GetObjResult(interp), (last - first + 1),
+ &(elemPtrs[first]));
+ }
+ result = TCL_OK;
+ break;
}
- for (elPtr = listPtr->firstPtr, i = 0; i < first;
- i++, elPtr = elPtr->nextPtr) {
- /* Empty loop body. */
+ case COMMAND_INDEX:{
+ char buf[TCL_INTEGER_SPACE];
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[2], 1, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_INSERT: {
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index ?element element ...?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 1, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+ result = ListboxInsertSubCmd(listPtr, index, objc-3, objv+3);
+ break;
}
- if (elPtr != NULL) {
- if (argc == 3) {
- if (first >= 0) {
- interp->result = elPtr->text;
+
+ case COMMAND_ITEMCGET: {
+ Tcl_Obj *objPtr;
+ ItemAttr *attrPtr;
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index option");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (index < 0 || index >= listPtr->nElements) {
+ Tcl_AppendResult(interp, "item number \"",
+ Tcl_GetString(objv[2]), "\" out of range",
+ (char *)NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ attrPtr = ListboxGetItemAttributes(interp, listPtr, index);
+
+ objPtr = Tk_GetOptionValue(interp, (char *)attrPtr,
+ listPtr->itemAttrOptionTable, objv[3], listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_ITEMCONFIGURE: {
+ Tcl_Obj *objPtr;
+ ItemAttr *attrPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 2, objv,
+ "index ?option? ?value? ?option value ...?");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+
+ if (index < 0 || index >= listPtr->nElements) {
+ Tcl_AppendResult(interp, "item number \"",
+ Tcl_GetString(objv[2]), "\" out of range",
+ (char *)NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ attrPtr = ListboxGetItemAttributes(interp, listPtr, index);
+ if (objc <= 4) {
+ objPtr = Tk_GetOptionInfo(interp, (char *)attrPtr,
+ listPtr->itemAttrOptionTable,
+ (objc == 4) ? objv[3] : (Tcl_Obj *) NULL,
+ listPtr->tkwin);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
}
} else {
- for ( ; i <= last; i++, elPtr = elPtr->nextPtr) {
- Tcl_AppendElement(interp, elPtr->text);
+ result = ConfigureListboxItem(interp, listPtr, attrPtr,
+ objc-3, objv+3);
+ }
+ break;
+ }
+
+ case COMMAND_NEAREST: {
+ char buf[TCL_INTEGER_SPACE];
+ int y;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "y");
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = Tcl_GetIntFromObj(interp, objv[2], &y);
+ if (result != TCL_OK) {
+ break;
+ }
+ index = NearestListboxElement(listPtr, y);
+ sprintf(buf, "%d", index);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ result = TCL_OK;
+ break;
+ }
+
+ case COMMAND_SCAN: {
+ int x, y, scanCmdIndex;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y");
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ result = TCL_ERROR;
+ break;
+ }
+
+ result = Tcl_GetIndexFromObj(interp, objv[2], scanCommandNames,
+ "option", 0, &scanCmdIndex);
+ if (result != TCL_OK) {
+ break;
+ }
+ switch (scanCmdIndex) {
+ case SCAN_MARK: {
+ listPtr->scanMarkX = x;
+ listPtr->scanMarkY = y;
+ listPtr->scanMarkXOffset = listPtr->xOffset;
+ listPtr->scanMarkYIndex = listPtr->topIndex;
+ break;
+ }
+ case SCAN_DRAGTO: {
+ ListboxScanTo(listPtr, x, y);
+ break;
}
}
+ result = TCL_OK;
+ break;
}
- } 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 index\"",
- (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[2], 1, &index)
- != TCL_OK) {
- goto error;
- }
- sprintf(interp->result, "%d", index);
- } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
- && (length >= 3)) {
- int index;
-
- if (argc < 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " insert index ?element element ...?\"",
- (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[2], 1, &index)
- != TCL_OK) {
- goto error;
- }
- InsertEls(listPtr, index, argc-3, argv+3);
- } else if ((c == 'n') && (strncmp(argv[1], "nearest", length) == 0)) {
- int index, y;
-
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " nearest y\"", (char *) NULL);
- goto error;
- }
- if (Tcl_GetInt(interp, argv[2], &y) != TCL_OK) {
- goto error;
- }
- index = NearestListboxElement(listPtr, y);
- sprintf(interp->result, "%d", index);
- } else if ((c == 's') && (length >= 2)
- && (strncmp(argv[1], "scan", length) == 0)) {
- int x, y;
-
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " scan mark|dragto x y\"", (char *) NULL);
- goto error;
- }
- if ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)) {
- goto error;
- }
- if ((argv[2][0] == 'm')
- && (strncmp(argv[2], "mark", strlen(argv[2])) == 0)) {
- listPtr->scanMarkX = x;
- listPtr->scanMarkY = y;
- listPtr->scanMarkXOffset = listPtr->xOffset;
- listPtr->scanMarkYIndex = listPtr->topIndex;
- } else if ((argv[2][0] == 'd')
- && (strncmp(argv[2], "dragto", strlen(argv[2])) == 0)) {
- ListboxScanTo(listPtr, x, y);
- } else {
- Tcl_AppendResult(interp, "bad scan option \"", argv[2],
- "\": must be mark or dragto", (char *) NULL);
- goto error;
- }
- } else if ((c == 's') && (strncmp(argv[1], "see", length) == 0)
- && (length >= 3)) {
- int index, diff;
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " see index\"",
- (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[2], 0, &index) != TCL_OK) {
- goto error;
- }
- if (index >= listPtr->numElements) {
- index = listPtr->numElements-1;
- }
- if (index < 0) {
- index = 0;
- }
- diff = listPtr->topIndex-index;
- if (diff > 0) {
- if (diff <= (listPtr->fullLines/3)) {
- ChangeListboxView(listPtr, index);
- } else {
- ChangeListboxView(listPtr, index - (listPtr->fullLines-1)/2);
+
+ case COMMAND_SEE: {
+ int diff;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 2, objv, "index");
+ result = TCL_ERROR;
+ break;
}
- } else {
- diff = index - (listPtr->topIndex + listPtr->fullLines - 1);
+ result = GetListboxIndex(interp, listPtr, objv[2], 0, &index);
+ if (result != TCL_OK) {
+ break;
+ }
+ if (index >= listPtr->nElements) {
+ index = listPtr->nElements - 1;
+ }
+ if (index < 0) {
+ index = 0;
+ }
+ diff = listPtr->topIndex - index;
if (diff > 0) {
if (diff <= (listPtr->fullLines/3)) {
- ChangeListboxView(listPtr, listPtr->topIndex + diff);
+ ChangeListboxView(listPtr, index);
} else {
ChangeListboxView(listPtr,
index - (listPtr->fullLines-1)/2);
}
+ } else {
+ diff = index - (listPtr->topIndex + listPtr->fullLines - 1);
+ if (diff > 0) {
+ if (diff <= (listPtr->fullLines/3)) {
+ ChangeListboxView(listPtr, listPtr->topIndex + diff);
+ } else {
+ ChangeListboxView(listPtr,
+ index - (listPtr->fullLines-1)/2);
+ }
+ }
}
+ result = TCL_OK;
+ break;
}
- } else if ((c == 's') && (length >= 3)
- && (strncmp(argv[1], "selection", length) == 0)) {
- int first, last;
- if ((argc != 4) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection option index ?index?\"",
- (char *) NULL);
- goto error;
- }
- if (GetListboxIndex(interp, listPtr, argv[3], 0, &first) != TCL_OK) {
- goto error;
+ case COMMAND_SELECTION: {
+ result = ListboxSelectionSubCmd(interp, listPtr, objc, objv);
+ break;
}
- if (argc == 5) {
- if (GetListboxIndex(interp, listPtr, argv[4], 0, &last) != TCL_OK) {
- goto error;
+
+ case COMMAND_SIZE: {
+ char buf[TCL_INTEGER_SPACE];
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, NULL);
+ result = TCL_ERROR;
+ break;
}
- } else {
- last = first;
+ sprintf(buf, "%d", listPtr->nElements);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ result = TCL_OK;
+ break;
}
- length = strlen(argv[2]);
- c = argv[2][0];
- if ((c == 'a') && (strncmp(argv[2], "anchor", length) == 0)) {
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection anchor index\"", (char *) NULL);
- goto error;
+
+ case COMMAND_XVIEW: {
+ result = ListboxXviewSubCmd(interp, listPtr, objc, objv);
+ break;
+ }
+
+ case COMMAND_YVIEW: {
+ result = ListboxYviewSubCmd(interp, listPtr, objc, objv);
+ break;
+ }
+ }
+ Tcl_Release((ClientData)listPtr);
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxBboxSubCmd --
+ *
+ * This procedure is invoked to process a listbox bbox request.
+ * See the user documentation for more information.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * For valid indices, places the bbox of the requested element in
+ * the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxBboxSubCmd(interp, listPtr, index)
+ Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr; /* Information about the listbox */
+ int index; /* Index of the element to get bbox info on */
+{
+ int lastVisibleIndex;
+ /* Determine the index of the last visible item in the listbox */
+ lastVisibleIndex = listPtr->topIndex + listPtr->fullLines
+ + listPtr->partialLine;
+ if (listPtr->nElements < lastVisibleIndex) {
+ lastVisibleIndex = listPtr->nElements;
+ }
+
+ /* Only allow bbox requests for indices that are visible */
+ if ((listPtr->topIndex <= index) && (index < lastVisibleIndex)) {
+ char buf[TCL_INTEGER_SPACE * 4];
+ Tcl_Obj *el;
+ char *stringRep;
+ int pixelWidth, stringLen, x, y, result;
+ Tk_FontMetrics fm;
+
+ /* Compute the pixel width of the requested element */
+ result = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ stringRep = Tcl_GetStringFromObj(el, &stringLen);
+ Tk_GetFontMetrics(listPtr->tkfont, &fm);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen);
+
+ x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
+ y = ((index - listPtr->topIndex)*listPtr->lineHeight)
+ + listPtr->inset + listPtr->selBorderWidth;
+ sprintf(buf, "%d %d %d %d", x, y, pixelWidth, fm.linespace);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxSelectionSubCmd --
+ *
+ * This procedure is invoked to process the selection sub command
+ * for listbox widgets.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May set the interpreter's result field.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxSelectionSubCmd(interp, listPtr, objc, objv)
+ Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr; /* Information about the listbox */
+ int objc; /* Number of arguments in the objv array */
+ Tcl_Obj *CONST objv[]; /* Array of arguments to the procedure */
+{
+ int selCmdIndex, first, last;
+ int result = TCL_OK;
+ if (objc != 4 && objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "option index ?index?");
+ return TCL_ERROR;
+ }
+ result = GetListboxIndex(interp, listPtr, objv[3], 0, &first);
+ if (result != TCL_OK) {
+ return result;
+ }
+ last = first;
+ if (objc == 5) {
+ result = GetListboxIndex(interp, listPtr, objv[4], 0, &last);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+ result = Tcl_GetIndexFromObj(interp, objv[2], selCommandNames,
+ "option", 0, &selCmdIndex);
+ if (result != TCL_OK) {
+ return result;
+ }
+ switch (selCmdIndex) {
+ case SELECTION_ANCHOR: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
}
- if (first >= listPtr->numElements) {
- first = listPtr->numElements-1;
+ if (first >= listPtr->nElements) {
+ first = listPtr->nElements - 1;
}
if (first < 0) {
first = 0;
}
listPtr->selectAnchor = first;
- } else if ((c == 'c') && (strncmp(argv[2], "clear", length) == 0)) {
- ListboxSelect(listPtr, first, last, 0);
- } else if ((c == 'i') && (strncmp(argv[2], "includes", length) == 0)) {
- int i;
- Element *elPtr;
-
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " selection includes index\"", (char *) NULL);
- goto error;
- }
- if ((first < 0) || (first >= listPtr->numElements)) {
- interp->result = "0";
- goto done;
- }
- for (elPtr = listPtr->firstPtr, i = 0; i < first;
- i++, elPtr = elPtr->nextPtr) {
- /* Empty loop body. */
+ result = TCL_OK;
+ break;
+ }
+ case SELECTION_CLEAR: {
+ result = ListboxSelect(listPtr, first, last, 0);
+ break;
+ }
+ case SELECTION_INCLUDES: {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 3, objv, "index");
+ return TCL_ERROR;
}
- if (elPtr->selected) {
- interp->result = "1";
+ if (Tcl_FindHashEntry(listPtr->selection, (char *)first)) {
+ 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);
+ result = TCL_OK;
+ break;
+ }
+ case SELECTION_SET: {
+ result = ListboxSelect(listPtr, first, last, 1);
+ break;
+ }
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxXviewSubCmd --
+ *
+ * Process the listbox "xview" subcommand.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May change the listbox viewing area; may set the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ListboxXviewSubCmd(interp, listPtr, objc, objv)
+ Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr; /* Information about the listbox */
+ int objc; /* Number of arguments in the objv array */
+ Tcl_Obj *CONST objv[]; /* Array of arguments to the procedure */
+{
+
+ int index, count, type, windowWidth, windowUnits;
+ int offset = 0; /* Initialized to stop gcc warnings. */
+ double fraction, fraction2;
+
+ windowWidth = Tk_Width(listPtr->tkwin)
+ - 2*(listPtr->inset + listPtr->selBorderWidth);
+ if (objc == 2) {
+ if (listPtr->maxWidth == 0) {
+ Tcl_SetResult(interp, "0 1", TCL_STATIC);
} else {
- Tcl_AppendResult(interp, "bad selection option \"", argv[2],
- "\": must be anchor, clear, includes, or set",
- (char *) NULL);
- goto error;
- }
- } else if ((c == 's') && (length >= 2)
- && (strncmp(argv[1], "size", length) == 0)) {
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " size\"", (char *) NULL);
- goto error;
- }
- sprintf(interp->result, "%d", listPtr->numElements);
- } else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) {
- int index, count, type, windowWidth, windowUnits;
- int offset = 0; /* Initialized to stop gcc warnings. */
- double fraction, fraction2;
-
- windowWidth = Tk_Width(listPtr->tkwin)
- - 2*(listPtr->inset + listPtr->selBorderWidth);
- if (argc == 2) {
- if (listPtr->maxWidth == 0) {
- interp->result = "0 1";
- } else {
- 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);
- }
- } else if (argc == 3) {
- if (Tcl_GetInt(interp, argv[2], &index) != TCL_OK) {
- goto error;
+ 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;
}
- ChangeListboxOffset(listPtr, index*listPtr->xScrollUnit);
- } else {
- type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
- switch (type) {
- case TK_SCROLL_ERROR:
- goto error;
- case TK_SCROLL_MOVETO:
- offset = (int) (fraction*listPtr->maxWidth + 0.5);
- break;
- case TK_SCROLL_PAGES:
- windowUnits = windowWidth/listPtr->xScrollUnit;
- if (windowUnits > 2) {
- offset = listPtr->xOffset
- + count*listPtr->xScrollUnit*(windowUnits-2);
- } else {
- offset = listPtr->xOffset + count*listPtr->xScrollUnit;
- }
- break;
- case TK_SCROLL_UNITS:
+ sprintf(buf, "%g %g", fraction, fraction2);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ }
+ } else if (objc == 3) {
+ if (Tcl_GetIntFromObj(interp, objv[2], &index) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ChangeListboxOffset(listPtr, index*listPtr->xScrollUnit);
+ } else {
+ type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count);
+ switch (type) {
+ case TK_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TK_SCROLL_MOVETO:
+ offset = (int) (fraction*listPtr->maxWidth + 0.5);
+ break;
+ case TK_SCROLL_PAGES:
+ windowUnits = windowWidth/listPtr->xScrollUnit;
+ if (windowUnits > 2) {
+ offset = listPtr->xOffset
+ + count*listPtr->xScrollUnit*(windowUnits-2);
+ } else {
offset = listPtr->xOffset + count*listPtr->xScrollUnit;
- break;
- }
- ChangeListboxOffset(listPtr, offset);
+ }
+ break;
+ case TK_SCROLL_UNITS:
+ offset = listPtr->xOffset + count*listPtr->xScrollUnit;
+ break;
}
- } else if ((c == 'y') && (strncmp(argv[1], "yview", length) == 0)) {
- int index, count, type;
- double fraction, fraction2;
+ ChangeListboxOffset(listPtr, offset);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxYviewSubCmd --
+ *
+ * Process the listbox "yview" subcommand.
+ *
+ * Results:
+ * Standard Tcl result.
+ *
+ * Side effects:
+ * May change the listbox viewing area; may set the interpreter's result.
+ *
+ *----------------------------------------------------------------------
+ */
- if (argc == 2) {
- if (listPtr->numElements == 0) {
- interp->result = "0 1";
- } else {
- 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);
- }
- } else if (argc == 3) {
- if (GetListboxIndex(interp, listPtr, argv[2], 0, &index)
- != TCL_OK) {
- goto error;
- }
- ChangeListboxView(listPtr, index);
+static int
+ListboxYviewSubCmd(interp, listPtr, objc, objv)
+ Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr; /* Information about the listbox */
+ int objc; /* Number of arguments in the objv array */
+ Tcl_Obj *CONST objv[]; /* Array of arguments to the procedure */
+{
+ int index, count, type;
+ double fraction, fraction2;
+
+ if (objc == 2) {
+ if (listPtr->nElements == 0) {
+ Tcl_SetResult(interp, "0 1", TCL_STATIC);
} else {
- type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
- switch (type) {
- case TK_SCROLL_ERROR:
- goto error;
- case TK_SCROLL_MOVETO:
- index = (int) (listPtr->numElements*fraction + 0.5);
- break;
- case TK_SCROLL_PAGES:
- if (listPtr->fullLines > 2) {
- index = listPtr->topIndex
- + count*(listPtr->fullLines-2);
- } else {
- index = listPtr->topIndex + count;
- }
- break;
- case TK_SCROLL_UNITS:
- index = listPtr->topIndex + count;
- break;
+ char buf[TCL_DOUBLE_SPACE * 2];
+
+ fraction = listPtr->topIndex/((double) listPtr->nElements);
+ fraction2 = (listPtr->topIndex+listPtr->fullLines)
+ /((double) listPtr->nElements);
+ if (fraction2 > 1.0) {
+ fraction2 = 1.0;
}
- ChangeListboxView(listPtr, index);
+ sprintf(buf, "%g %g", fraction, fraction2);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ }
+ } else if (objc == 3) {
+ if (GetListboxIndex(interp, listPtr, objv[2], 0, &index) != TCL_OK) {
+ return TCL_ERROR;
}
+ ChangeListboxView(listPtr, index);
} else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be activate, bbox, cget, configure, ",
- "curselection, delete, get, index, insert, nearest, ",
- "scan, see, selection, size, ",
- "xview, or yview", (char *) NULL);
- goto error;
- }
- done:
- Tcl_Release((ClientData) listPtr);
- return result;
+ type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count);
+ switch (type) {
+ case TK_SCROLL_ERROR:
+ return TCL_ERROR;
+ case TK_SCROLL_MOVETO:
+ index = (int) (listPtr->nElements*fraction + 0.5);
+ break;
+ case TK_SCROLL_PAGES:
+ if (listPtr->fullLines > 2) {
+ index = listPtr->topIndex
+ + count*(listPtr->fullLines-2);
+ } else {
+ index = listPtr->topIndex + count;
+ }
+ break;
+ case TK_SCROLL_UNITS:
+ index = listPtr->topIndex + count;
+ break;
+ }
+ ChangeListboxView(listPtr, index);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxGetItemAttributes --
+ *
+ * Returns a pointer to the ItemAttr record for a given index,
+ * creating one if it does not already exist.
+ *
+ * Results:
+ * Pointer to an ItemAttr record.
+ *
+ * Side effects:
+ * Memory may be allocated for the ItemAttr record.
+ *
+ *----------------------------------------------------------------------
+ */
- error:
- Tcl_Release((ClientData) listPtr);
- return TCL_ERROR;
+static ItemAttr *
+ListboxGetItemAttributes(interp, listPtr, index)
+ Tcl_Interp *interp; /* Pointer to the calling Tcl interpreter */
+ Listbox *listPtr; /* Information about the listbox */
+ int index; /* Index of the item to retrieve attributes
+ * for */
+{
+ int new;
+ Tcl_HashEntry *entry;
+ ItemAttr *attrs;
+
+ entry = Tcl_CreateHashEntry(listPtr->itemAttrTable, (char *)index,
+ &new);
+ if (new) {
+ attrs = (ItemAttr *) ckalloc(sizeof(ItemAttr));
+ attrs->border = NULL;
+ attrs->selBorder = NULL;
+ attrs->fgColor = NULL;
+ attrs->selFgColor = NULL;
+ Tk_InitOptions(interp, (char *)attrs, listPtr->itemAttrOptionTable,
+ listPtr->tkwin);
+ Tcl_SetHashValue(entry, (ClientData) attrs);
+ }
+ attrs = (ItemAttr *)Tcl_GetHashValue(entry);
+ return attrs;
}
/*
@@ -947,18 +1409,43 @@ DestroyListbox(memPtr)
char *memPtr; /* Info about listbox widget. */
{
register Listbox *listPtr = (Listbox *) memPtr;
- register Element *elPtr, *nextPtr;
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch search;
- /*
- * Free up all of the list elements.
- */
+ listPtr->flags |= LISTBOX_DELETED;
- for (elPtr = listPtr->firstPtr; elPtr != NULL; ) {
- nextPtr = elPtr->nextPtr;
- ckfree((char *) elPtr);
- elPtr = nextPtr;
+ Tcl_DeleteCommandFromToken(listPtr->interp, listPtr->widgetCmd);
+ if (listPtr->setGrid) {
+ Tk_UnsetGrid(listPtr->tkwin);
+ }
+ if (listPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayListbox, (ClientData) listPtr);
}
+ /* If we have an internal list object, free it */
+ if (listPtr->listObj != NULL) {
+ Tcl_DecrRefCount(listPtr->listObj);
+ listPtr->listObj = NULL;
+ }
+
+ if (listPtr->listVarName != NULL) {
+ Tcl_UntraceVar(listPtr->interp, listPtr->listVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, (ClientData) listPtr);
+ }
+
+ /* Free the selection hash table */
+ Tcl_DeleteHashTable(listPtr->selection);
+ ckfree((char *)listPtr->selection);
+
+ /* Free the item attribute hash table */
+ for (entry = Tcl_FirstHashEntry(listPtr->itemAttrTable, &search);
+ entry != NULL; entry = Tcl_NextHashEntry(&search)) {
+ ckfree((char *)Tcl_GetHashValue(entry));
+ }
+ Tcl_DeleteHashTable(listPtr->itemAttrTable);
+ ckfree((char *)listPtr->itemAttrTable);
+
/*
* Free up all the stuff that requires special handling, then
* let Tk_FreeOptions handle all the standard option-related
@@ -971,22 +1458,51 @@ DestroyListbox(memPtr)
if (listPtr->selTextGC != None) {
Tk_FreeGC(listPtr->display, listPtr->selTextGC);
}
- Tk_FreeOptions(configSpecs, (char *) listPtr, listPtr->display, 0);
+ Tk_FreeConfigOptions((char *)listPtr, listPtr->optionTable,
+ listPtr->tkwin);
+ listPtr->tkwin = NULL;
ckfree((char *) listPtr);
}
/*
*----------------------------------------------------------------------
*
+ * DestroyListboxOptionTables --
+ *
+ * This procedure is registered as an exit callback when the listbox
+ * command is first called. It cleans up the OptionTables structure
+ * allocated by that command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DestroyListboxOptionTables(clientData, interp)
+ ClientData clientData; /* Pointer to the OptionTables struct */
+ Tcl_Interp *interp; /* Pointer to the calling interp */
+{
+ ckfree((char *)clientData);
+ return;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ConfigureListbox --
*
- * This procedure is called to process an argv/argc list, plus
+ * This procedure is called to process an objv/objc list, plus
* the Tk option database, in order to configure (or reconfigure)
* a listbox widget.
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then 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,
@@ -997,22 +1513,32 @@ DestroyListbox(memPtr)
*/
static int
-ConfigureListbox(interp, listPtr, argc, argv, flags)
+ConfigureListbox(interp, listPtr, objc, objv, flags)
Tcl_Interp *interp; /* Used for error reporting. */
register Listbox *listPtr; /* Information about widget; may or may
* not already have values for some fields. */
- int argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
+ int objc; /* Number of valid entries in argv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *oldListObj = NULL;
int oldExport;
oldExport = listPtr->exportSelection;
- if (Tk_ConfigureWidget(interp, listPtr->tkwin, configSpecs,
- argc, argv, (char *) listPtr, flags) != TCL_OK) {
+ if (listPtr->listVarName != NULL) {
+ Tcl_UntraceVar(interp, listPtr->listVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, (ClientData) listPtr);
+ }
+
+ if (Tk_SetOptions(interp, (char *)listPtr,
+ listPtr->optionTable, objc, objv, listPtr->tkwin,
+ &savedOptions, (int *)NULL) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
return TCL_ERROR;
}
-
+
/*
* A few options need special processing, such as setting the
* background from a 3-D border.
@@ -1036,6 +1562,109 @@ ConfigureListbox(interp, listPtr, argc, argv, flags)
(ClientData) listPtr);
}
+
+ /* Verify the current status of the list var.
+ * PREVIOUS STATE | NEW STATE | ACTION
+ * ------------------+---------------+----------------------------------
+ * no listvar | listvar | If listvar does not exist, create
+ * it and copy the internal list obj's
+ * content to the new var. If it does
+ * exist, toss the internal list obj.
+ *
+ * listvar | no listvar | Copy old listvar content to the
+ * internal list obj
+ *
+ * listvar | listvar | no special action
+ *
+ * no listvar | no listvar | no special action
+ */
+ oldListObj = listPtr->listObj;
+ if (listPtr->listVarName != NULL) {
+ Tcl_Obj *listVarObj = Tcl_GetVar2Ex(interp, listPtr->listVarName,
+ (char *)NULL, TCL_GLOBAL_ONLY);
+ int dummy;
+ if (listVarObj == NULL) {
+ if (listPtr->listObj != NULL) {
+ listVarObj = listPtr->listObj;
+ } else {
+ listVarObj = Tcl_NewObj();
+ }
+ if (Tcl_SetVar2Ex(interp, listPtr->listVarName, (char *)NULL,
+ listVarObj, TCL_GLOBAL_ONLY) == NULL) {
+ Tcl_DecrRefCount(listVarObj);
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+ }
+ /* Make sure the object is a good list object */
+ if (Tcl_ListObjLength(listPtr->interp, listVarObj, &dummy) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ Tcl_AppendResult(listPtr->interp, ": invalid listvar value",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ listPtr->listObj = listVarObj;
+ Tcl_TraceVar(listPtr->interp, listPtr->listVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, (ClientData) listPtr);
+ } else {
+ if (listPtr->listObj == NULL) {
+ listPtr->listObj = Tcl_NewObj();
+ }
+ }
+ Tcl_IncrRefCount(listPtr->listObj);
+ if (oldListObj != NULL) {
+ Tcl_DecrRefCount(oldListObj);
+ }
+
+ /* Make sure that the list length is correct */
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+
+ Tk_FreeSavedOptions(&savedOptions);
+ ListboxWorldChanged((ClientData) listPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ConfigureListboxItem --
+ *
+ * This procedure is called to process an objv/objc list, plus
+ * the Tk option database, in order to configure (or reconfigure)
+ * a listbox item.
+ *
+ * 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 colors, border width,
+ * etc. get set for a listbox item; old resources get freed,
+ * if there were any.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ConfigureListboxItem(interp, listPtr, attrs, objc, objv)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ register Listbox *listPtr; /* Information about widget; may or may
+ * not already have values for some fields. */
+ ItemAttr *attrs; /* Information about the item to configure */
+ int objc; /* Number of valid entries in argv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
+{
+ Tk_SavedOptions savedOptions;
+
+ if (Tk_SetOptions(interp, (char *)attrs,
+ listPtr->itemAttrOptionTable, objc, objv, listPtr->tkwin,
+ &savedOptions, (int *)NULL) != TCL_OK) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+ Tk_FreeSavedOptions(&savedOptions);
ListboxWorldChanged((ClientData) listPtr);
return TCL_OK;
}
@@ -1066,15 +1695,14 @@ ListboxWorldChanged(instanceData)
GC gc;
unsigned long mask;
Listbox *listPtr;
-
+
listPtr = (Listbox *) instanceData;
gcValues.foreground = listPtr->fgColorPtr->pixel;
gcValues.font = Tk_FontId(listPtr->tkfont);
gcValues.graphics_exposures = False;
mask = GCForeground | GCFont | GCGraphicsExposures;
- gc = Tk_GetGCColor(listPtr->tkwin, mask, &gcValues, listPtr->fgColorPtr,
- NULL);
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
if (listPtr->textGC != None) {
Tk_FreeGC(listPtr->display, listPtr->textGC);
}
@@ -1083,8 +1711,7 @@ ListboxWorldChanged(instanceData)
gcValues.foreground = listPtr->selFgColorPtr->pixel;
gcValues.font = Tk_FontId(listPtr->tkfont);
mask = GCForeground | GCFont;
- gc = Tk_GetGCColor(listPtr->tkwin, mask, &gcValues, listPtr->selFgColorPtr,
- NULL);
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
if (listPtr->selTextGC != None) {
Tk_FreeGC(listPtr->display, listPtr->selTextGC);
}
@@ -1097,7 +1724,7 @@ ListboxWorldChanged(instanceData)
ListboxComputeGeometry(listPtr, 1, 1, 1);
listPtr->flags |= UPDATE_V_SCROLLBAR|UPDATE_H_SCROLLBAR;
- ListboxRedrawRange(listPtr, 0, listPtr->numElements-1);
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
}
/*
@@ -1122,16 +1749,30 @@ DisplayListbox(clientData)
{
register Listbox *listPtr = (Listbox *) clientData;
register Tk_Window tkwin = listPtr->tkwin;
- register Element *elPtr;
GC gc;
int i, limit, x, y, width, prevSelected;
Tk_FontMetrics fm;
+ Tcl_Obj *curElement;
+ Tcl_HashEntry *entry;
+ char *stringRep;
+ int stringLen;
+ ItemAttr *attrs;
+ Tk_3DBorder selectedBg;
+ XGCValues gcValues;
+ unsigned long mask;
int left, right; /* Non-zero values here indicate
* that the left or right edge of
* the listbox is off-screen. */
Pixmap pixmap;
listPtr->flags &= ~REDRAW_PENDING;
+
+ if (listPtr->flags & MAXWIDTH_IS_STALE) {
+ ListboxComputeGeometry(listPtr, 0, 1, 0);
+ listPtr->flags &= ~MAXWIDTH_IS_STALE;
+ listPtr->flags |= UPDATE_H_SCROLLBAR;
+ }
+
if (listPtr->flags & UPDATE_V_SCROLLBAR) {
ListboxUpdateVScrollbar(listPtr);
}
@@ -1156,15 +1797,10 @@ DisplayListbox(clientData)
Tk_Fill3DRectangle(tkwin, pixmap, listPtr->normalBorder, 0, 0,
Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
- /*
- * Iterate through all of the elements of the listbox, displaying each
- * in turn. Selected elements use a different GC and have a raised
- * background.
- */
-
+ /* Display each item in the listbox */
limit = listPtr->topIndex + listPtr->fullLines + listPtr->partialLine - 1;
- if (limit >= listPtr->numElements) {
- limit = listPtr->numElements-1;
+ if (limit >= listPtr->nElements) {
+ limit = listPtr->nElements-1;
}
left = right = 0;
if (listPtr->xOffset > 0) {
@@ -1175,19 +1811,45 @@ DisplayListbox(clientData)
right = listPtr->selBorderWidth+1;
}
prevSelected = 0;
- for (elPtr = listPtr->firstPtr, i = 0; (elPtr != NULL) && (i <= limit);
- prevSelected = elPtr->selected, elPtr = elPtr->nextPtr, i++) {
- if (i < listPtr->topIndex) {
- continue;
- }
+
+ for (i = listPtr->topIndex; i <= limit; i++) {
x = listPtr->inset;
y = ((i - listPtr->topIndex) * listPtr->lineHeight)
+ listPtr->inset;
gc = listPtr->textGC;
- if (elPtr->selected) {
+ /*
+ * Lookup this item in the item attributes table, to see if it has
+ * special foreground/background colors
+ */
+ entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *)i);
+
+ /* If the item is selected, it is drawn differently */
+ if (Tcl_FindHashEntry(listPtr->selection, (char *)i) != NULL) {
gc = listPtr->selTextGC;
width = Tk_Width(tkwin) - 2*listPtr->inset;
- Tk_Fill3DRectangle(tkwin, pixmap, listPtr->selBorder, x, y,
+ selectedBg = listPtr->selBorder;
+
+ /* If there is attribute information for this item,
+ * adjust the drawing accordingly */
+ if (entry != NULL) {
+ attrs = (ItemAttr *)Tcl_GetHashValue(entry);
+ /* The default GC has the settings from the widget at large */
+ gcValues.foreground = listPtr->selFgColorPtr->pixel;
+ gcValues.font = Tk_FontId(listPtr->tkfont);
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+
+ if (attrs->selBorder != NULL) {
+ selectedBg = attrs->selBorder;
+ }
+
+ if (attrs->selFgColor != NULL) {
+ gcValues.foreground = attrs->selFgColor->pixel;
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
+ }
+ }
+
+ Tk_Fill3DRectangle(tkwin, pixmap, selectedBg, x, y,
width, listPtr->lineHeight, 0, TK_RELIEF_FLAT);
/*
@@ -1205,43 +1867,71 @@ DisplayListbox(clientData)
* corners are off-screen.
*/
+ /* Draw left bevel */
if (left == 0) {
- Tk_3DVerticalBevel(tkwin, pixmap, listPtr->selBorder,
+ Tk_3DVerticalBevel(tkwin, pixmap, selectedBg,
x, y, listPtr->selBorderWidth, listPtr->lineHeight,
1, TK_RELIEF_RAISED);
}
+ /* Draw right bevel */
if (right == 0) {
- Tk_3DVerticalBevel(tkwin, pixmap, listPtr->selBorder,
+ Tk_3DVerticalBevel(tkwin, pixmap, selectedBg,
x + width - listPtr->selBorderWidth, y,
listPtr->selBorderWidth, listPtr->lineHeight,
0, TK_RELIEF_RAISED);
}
+ /* Draw top bevel */
if (!prevSelected) {
- Tk_3DHorizontalBevel(tkwin, pixmap, listPtr->selBorder,
+ Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg,
x-left, y, width+left+right, listPtr->selBorderWidth,
1, 1, 1, TK_RELIEF_RAISED);
}
- if ((elPtr->nextPtr == NULL) || !elPtr->nextPtr->selected) {
- Tk_3DHorizontalBevel(tkwin, pixmap, listPtr->selBorder, x-left,
+ /* Draw bottom bevel */
+ if (i + 1 == listPtr->nElements ||
+ Tcl_FindHashEntry(listPtr->selection,
+ (char *)(i + 1)) == NULL ) {
+ Tk_3DHorizontalBevel(tkwin, pixmap, selectedBg, x-left,
y + listPtr->lineHeight - listPtr->selBorderWidth,
width+left+right, listPtr->selBorderWidth, 0, 0, 0,
TK_RELIEF_RAISED);
}
+ prevSelected = 1;
+ } else {
+ /* If there is an item attributes record for this item,
+ * draw the background box and set the foreground color
+ * accordingly */
+ if (entry != NULL) {
+ attrs = (ItemAttr *)Tcl_GetHashValue(entry);
+ gcValues.foreground = listPtr->fgColorPtr->pixel;
+ gcValues.font = Tk_FontId(listPtr->tkfont);
+ gcValues.graphics_exposures = False;
+ mask = GCForeground | GCFont | GCGraphicsExposures;
+ if (attrs->border != NULL) {
+ width = Tk_Width(tkwin) - 2*listPtr->inset;
+ Tk_Fill3DRectangle(tkwin, pixmap, attrs->border, x, y,
+ width, listPtr->lineHeight, 0, TK_RELIEF_FLAT);
+ }
+ if (attrs->fgColor != NULL) {
+ gcValues.foreground = attrs->fgColor->pixel;
+ gc = Tk_GetGC(listPtr->tkwin, mask, &gcValues);
+ }
+ }
+ prevSelected = 0;
}
+
+ /* Draw the actual text of this item */
Tk_GetFontMetrics(listPtr->tkfont, &fm);
y += fm.ascent + listPtr->selBorderWidth;
- x = listPtr->inset + listPtr->selBorderWidth - elPtr->lBearing
- - listPtr->xOffset;
+ x = listPtr->inset + listPtr->selBorderWidth - listPtr->xOffset;
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
Tk_DrawChars(listPtr->display, pixmap, gc, listPtr->tkfont,
- elPtr->text, elPtr->textLength, x, y);
-
- /*
- * If this is the active element, underline it.
- */
+ stringRep, stringLen, x, y);
+ /* If this is the active element, underline it. */
if ((i == listPtr->active) && (listPtr->flags & GOT_FOCUS)) {
Tk_UnderlineChars(listPtr->display, pixmap, gc, listPtr->tkfont,
- elPtr->text, x, y, 0, elPtr->textLength);
+ stringRep, x, y, 0, stringLen);
}
}
@@ -1256,14 +1946,17 @@ DisplayListbox(clientData)
Tk_Height(tkwin) - 2*listPtr->highlightWidth,
listPtr->borderWidth, listPtr->relief);
if (listPtr->highlightWidth > 0) {
- GC gc;
+ GC fgGC, bgGC;
+ bgGC = Tk_GCForColor(listPtr->highlightBgColorPtr, pixmap);
if (listPtr->flags & GOT_FOCUS) {
- gc = Tk_GCForColor(listPtr->highlightColorPtr, pixmap);
+ fgGC = Tk_GCForColor(listPtr->highlightColorPtr, pixmap);
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC,
+ listPtr->highlightWidth, pixmap);
} else {
- gc = Tk_GCForColor(listPtr->highlightBgColorPtr, pixmap);
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC,
+ listPtr->highlightWidth, pixmap);
}
- Tk_DrawFocusHighlight(tkwin, gc, listPtr->highlightWidth, pixmap);
}
XCopyArea(listPtr->display, pixmap, Tk_WindowId(tkwin),
listPtr->textGC, 0, 0, (unsigned) Tk_Width(tkwin),
@@ -1306,24 +1999,31 @@ ListboxComputeGeometry(listPtr, fontChanged, maxIsStale, updateGrid)
* Tk_UnsetGrid to update gridding for
* the window. */
{
- register Element *elPtr;
int width, height, pixelWidth, pixelHeight;
Tk_FontMetrics fm;
-
+ Tcl_Obj *element;
+ int textLength;
+ char *text;
+ int i, result;
+
if (fontChanged || maxIsStale) {
listPtr->xScrollUnit = Tk_TextWidth(listPtr->tkfont, "0", 1);
if (listPtr->xScrollUnit == 0) {
listPtr->xScrollUnit = 1;
}
listPtr->maxWidth = 0;
- for (elPtr = listPtr->firstPtr; elPtr != NULL; elPtr = elPtr->nextPtr) {
- if (fontChanged) {
- elPtr->pixelWidth = Tk_TextWidth(listPtr->tkfont,
- elPtr->text, elPtr->textLength);
- elPtr->lBearing = 0;
+ for (i = 0; i < listPtr->nElements; i++) {
+ /* Compute the pixel width of the current element */
+ result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,
+ &element);
+ if (result != TCL_OK) {
+ continue;
}
- if (elPtr->pixelWidth > listPtr->maxWidth) {
- listPtr->maxWidth = elPtr->pixelWidth;
+ text = Tcl_GetStringFromObj(element, &textLength);
+ Tk_GetFontMetrics(listPtr->tkfont, &fm);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, text, textLength);
+ if (pixelWidth > listPtr->maxWidth) {
+ listPtr->maxWidth = pixelWidth;
}
}
}
@@ -1342,7 +2042,7 @@ ListboxComputeGeometry(listPtr, fontChanged, maxIsStale, updateGrid)
+ 2*listPtr->selBorderWidth;
height = listPtr->height;
if (listPtr->height <= 0) {
- height = listPtr->numElements;
+ height = listPtr->nElements;
if (height < 1) {
height = 1;
}
@@ -1363,100 +2063,104 @@ ListboxComputeGeometry(listPtr, fontChanged, maxIsStale, updateGrid)
/*
*----------------------------------------------------------------------
*
- * InsertEls --
+ * ListboxInsertSubCmd --
*
- * Add new elements to a listbox widget.
+ * This procedure is invoked to handle the listbox "insert"
+ * subcommand.
*
* Results:
- * None.
+ * Standard Tcl result.
*
* Side effects:
- * New information gets added to listPtr; it will be redisplayed
- * soon, but not immediately.
+ * New elements are added to the listbox pointed to by listPtr;
+ * a refresh callback is registered for the listbox.
*
*----------------------------------------------------------------------
*/
-static void
-InsertEls(listPtr, index, argc, argv)
+static int
+ListboxInsertSubCmd(listPtr, index, objc, objv)
register Listbox *listPtr; /* Listbox that is to get the new
* elements. */
int index; /* Add the new elements before this
* element. */
- int argc; /* Number of new elements to add. */
- char **argv; /* New elements (one per entry). */
+ int objc; /* Number of new elements to add. */
+ Tcl_Obj *CONST objv[]; /* New elements (one per entry). */
{
- register Element *prevPtr, *newPtr;
- int length, i, oldMaxWidth;
-
- /*
- * Find the element before which the new ones will be inserted.
- */
-
- if (index <= 0) {
- index = 0;
- }
- if (index > listPtr->numElements) {
- index = listPtr->numElements;
+ int i, oldMaxWidth;
+ Tcl_Obj *newListObj;
+ int pixelWidth;
+ int result;
+ char *stringRep;
+ int length;
+
+ oldMaxWidth = listPtr->maxWidth;
+ for (i = 0; i < objc; i++) {
+ /*
+ * Check if any of the new elements are wider than the current widest;
+ * if so, update our notion of "widest."
+ */
+ stringRep = Tcl_GetStringFromObj(objv[i], &length);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);
+ if (pixelWidth > listPtr->maxWidth) {
+ listPtr->maxWidth = pixelWidth;
+ }
}
- if (index == 0) {
- prevPtr = NULL;
- } else if (index == listPtr->numElements) {
- prevPtr = listPtr->lastPtr;
+
+ /* Adjust selection and attribute information for every index after
+ * the first index */
+ MigrateHashEntries(listPtr->selection, index, listPtr->nElements-1, objc);
+ MigrateHashEntries(listPtr->itemAttrTable, index, listPtr->nElements-1,
+ objc);
+
+ /* If the object is shared, duplicate it before writing to it */
+ if (Tcl_IsShared(listPtr->listObj)) {
+ newListObj = Tcl_DuplicateObj(listPtr->listObj);
} else {
- for (prevPtr = listPtr->firstPtr, i = index - 1; i > 0; i--) {
- prevPtr = prevPtr->nextPtr;
- }
+ newListObj = listPtr->listObj;
+ }
+ result =
+ Tcl_ListObjReplace(listPtr->interp, newListObj, index, 0, objc, objv);
+ if (result != TCL_OK) {
+ return result;
}
- /*
- * For each new element, create a record, initialize it, and link
- * it into the list of elements.
- */
+ Tcl_IncrRefCount(newListObj);
+ /* Clean up the old reference */
+ Tcl_DecrRefCount(listPtr->listObj);
- oldMaxWidth = listPtr->maxWidth;
- for (i = argc ; i > 0; i--, argv++, prevPtr = newPtr) {
- length = strlen(*argv);
- newPtr = (Element *) ckalloc(ElementSize(length));
- newPtr->textLength = length;
- strcpy(newPtr->text, *argv);
- newPtr->pixelWidth = Tk_TextWidth(listPtr->tkfont, newPtr->text,
- newPtr->textLength);
- newPtr->lBearing = 0;
- if (newPtr->pixelWidth > listPtr->maxWidth) {
- listPtr->maxWidth = newPtr->pixelWidth;
- }
- newPtr->selected = 0;
- if (prevPtr == NULL) {
- newPtr->nextPtr = listPtr->firstPtr;
- listPtr->firstPtr = newPtr;
- } else {
- newPtr->nextPtr = prevPtr->nextPtr;
- prevPtr->nextPtr = newPtr;
+ /* Set the internal pointer to the new obj */
+ listPtr->listObj = newListObj;
+
+ /* If there is a listvar, make sure it points at the new object */
+ if (listPtr->listVarName != NULL) {
+ if (Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName,
+ (char *)NULL, newListObj, TCL_GLOBAL_ONLY) == NULL) {
+ Tcl_DecrRefCount(newListObj);
+ return TCL_ERROR;
}
}
- if ((prevPtr != NULL) && (prevPtr->nextPtr == NULL)) {
- listPtr->lastPtr = prevPtr;
- }
- listPtr->numElements += argc;
+ /* Get the new list length */
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+
/*
- * Update the selection and other indexes to account for the
- * renumbering that has just occurred. Then arrange for the new
+ * Update the "special" indices (anchor, topIndex, active) to account
+ * for the renumbering that just occurred. Then arrange for the new
* information to be displayed.
*/
if (index <= listPtr->selectAnchor) {
- listPtr->selectAnchor += argc;
+ listPtr->selectAnchor += objc;
}
if (index < listPtr->topIndex) {
- listPtr->topIndex += argc;
+ listPtr->topIndex += objc;
}
if (index <= listPtr->active) {
- listPtr->active += argc;
- if ((listPtr->active >= listPtr->numElements)
- && (listPtr->numElements > 0)) {
- listPtr->active = listPtr->numElements-1;
+ listPtr->active += objc;
+ if ((listPtr->active >= listPtr->nElements) &&
+ (listPtr->nElements > 0)) {
+ listPtr->active = listPtr->nElements-1;
}
}
listPtr->flags |= UPDATE_V_SCROLLBAR;
@@ -1464,35 +2168,42 @@ InsertEls(listPtr, index, argc, argv)
listPtr->flags |= UPDATE_H_SCROLLBAR;
}
ListboxComputeGeometry(listPtr, 0, 0, 0);
- ListboxRedrawRange(listPtr, index, listPtr->numElements-1);
+ EventuallyRedrawRange(listPtr, index, listPtr->nElements-1);
+ return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
- * DeleteEls --
+ * ListboxDeleteSubCmd --
*
- * Remove one or more elements from a listbox widget.
+ * Process a listbox "delete" subcommand by removing one or more
+ * elements from a listbox widget.
*
* Results:
- * None.
+ * Standard Tcl result.
*
* Side effects:
- * Memory gets freed, the listbox gets modified and (eventually)
- * redisplayed.
+ * The listbox will be modified and (eventually) redisplayed.
*
*----------------------------------------------------------------------
*/
-static void
-DeleteEls(listPtr, first, last)
+static int
+ListboxDeleteSubCmd(listPtr, first, last)
register Listbox *listPtr; /* Listbox widget to modify. */
int first; /* Index of first element to delete. */
int last; /* Index of last element to delete. */
{
- register Element *prevPtr, *elPtr;
int count, i, widthChanged;
-
+ Tcl_Obj *newListObj;
+ Tcl_Obj *element;
+ int length;
+ char *stringRep;
+ int result;
+ int pixelWidth;
+ Tcl_HashEntry *entry;
+
/*
* Adjust the range to fit within the existing elements of the
* listbox, and make sure there's something to delete.
@@ -1501,54 +2212,85 @@ DeleteEls(listPtr, first, last)
if (first < 0) {
first = 0;
}
- if (last >= listPtr->numElements) {
- last = listPtr->numElements-1;
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements-1;
}
count = last + 1 - first;
if (count <= 0) {
- return;
+ return TCL_OK;
}
/*
- * Find the element just before the ones to delete.
+ * Foreach deleted index we must:
+ * a) remove selection information
+ * b) check the width of the element; if it is equal to the max, set
+ * widthChanged to 1, because it may be the only element with that
+ * width
*/
+ widthChanged = 0;
+ for (i = first; i <= last; i++) {
+ /* Remove selection information */
+ entry = Tcl_FindHashEntry(listPtr->selection, (char *)i);
+ if (entry != NULL) {
+ listPtr->numSelected--;
+ Tcl_DeleteHashEntry(entry);
+ }
+
+ entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *)i);
+ if (entry != NULL) {
+ Tcl_DeleteHashEntry(entry);
+ }
+
+ /* Check width of the element. We only have to check if widthChanged
+ * has not already been set to 1, because we only need one maxWidth
+ * element to disappear for us to have to recompute the width
+ */
+ if (widthChanged == 0) {
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element);
+ stringRep = Tcl_GetStringFromObj(element, &length);
+ pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length);
+ if (pixelWidth == listPtr->maxWidth) {
+ widthChanged = 1;
+ }
+ }
+ }
+
+ /* Adjust selection and attribute info for indices after lastIndex */
+ MigrateHashEntries(listPtr->selection, last+1,
+ listPtr->nElements-1, count*-1);
+ MigrateHashEntries(listPtr->itemAttrTable, last+1,
+ listPtr->nElements-1, count*-1);
- if (first == 0) {
- prevPtr = NULL;
+ /* Delete the requested elements */
+ if (Tcl_IsShared(listPtr->listObj)) {
+ newListObj = Tcl_DuplicateObj(listPtr->listObj);
} else {
- for (i = first-1, prevPtr = listPtr->firstPtr; i > 0; i--) {
- prevPtr = prevPtr->nextPtr;
- }
+ newListObj = listPtr->listObj;
+ }
+ result = Tcl_ListObjReplace(listPtr->interp,
+ newListObj, first, count, 0, NULL);
+ if (result != TCL_OK) {
+ return result;
}
- /*
- * Delete the requested number of elements.
- */
+ Tcl_IncrRefCount(newListObj);
+ /* Clean up the old reference */
+ Tcl_DecrRefCount(listPtr->listObj);
- widthChanged = 0;
- for (i = count; i > 0; i--) {
- if (prevPtr == NULL) {
- elPtr = listPtr->firstPtr;
- listPtr->firstPtr = elPtr->nextPtr;
- if (listPtr->firstPtr == NULL) {
- listPtr->lastPtr = NULL;
- }
- } else {
- elPtr = prevPtr->nextPtr;
- prevPtr->nextPtr = elPtr->nextPtr;
- if (prevPtr->nextPtr == NULL) {
- listPtr->lastPtr = prevPtr;
- }
- }
- if (elPtr->pixelWidth == listPtr->maxWidth) {
- widthChanged = 1;
- }
- if (elPtr->selected) {
- listPtr->numSelected -= 1;
+ /* Set the internal pointer to the new obj */
+ listPtr->listObj = newListObj;
+
+ /* Get the new list length */
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+
+ /* If there is a listvar, make sure it points at the new object */
+ if (listPtr->listVarName != NULL) {
+ if (Tcl_SetVar2Ex(listPtr->interp, listPtr->listVarName,
+ (char *)NULL, newListObj, TCL_GLOBAL_ONLY) == NULL) {
+ Tcl_DecrRefCount(newListObj);
+ return TCL_ERROR;
}
- ckfree((char *) elPtr);
}
- listPtr->numElements -= count;
/*
* Update the selection and viewing information to reflect the change
@@ -1568,8 +2310,8 @@ DeleteEls(listPtr, first, last)
listPtr->topIndex = first;
}
}
- if (listPtr->topIndex > (listPtr->numElements - listPtr->fullLines)) {
- listPtr->topIndex = listPtr->numElements - listPtr->fullLines;
+ if (listPtr->topIndex > (listPtr->nElements - listPtr->fullLines)) {
+ listPtr->topIndex = listPtr->nElements - listPtr->fullLines;
if (listPtr->topIndex < 0) {
listPtr->topIndex = 0;
}
@@ -1578,9 +2320,9 @@ DeleteEls(listPtr, first, last)
listPtr->active -= count;
} else if (listPtr->active >= first) {
listPtr->active = first;
- if ((listPtr->active >= listPtr->numElements)
- && (listPtr->numElements > 0)) {
- listPtr->active = listPtr->numElements-1;
+ if ((listPtr->active >= listPtr->nElements) &&
+ (listPtr->nElements > 0)) {
+ listPtr->active = listPtr->nElements-1;
}
}
listPtr->flags |= UPDATE_V_SCROLLBAR;
@@ -1588,7 +2330,8 @@ DeleteEls(listPtr, first, last)
if (widthChanged) {
listPtr->flags |= UPDATE_H_SCROLLBAR;
}
- ListboxRedrawRange(listPtr, first, listPtr->numElements-1);
+ EventuallyRedrawRange(listPtr, first, listPtr->nElements-1);
+ return TCL_OK;
}
/*
@@ -1615,24 +2358,14 @@ ListboxEventProc(clientData, eventPtr)
XEvent *eventPtr; /* Information about event. */
{
Listbox *listPtr = (Listbox *) clientData;
-
+
if (eventPtr->type == Expose) {
- ListboxRedrawRange(listPtr,
+ EventuallyRedrawRange(listPtr,
NearestListboxElement(listPtr, eventPtr->xexpose.y),
NearestListboxElement(listPtr, eventPtr->xexpose.y
+ eventPtr->xexpose.height));
} else if (eventPtr->type == DestroyNotify) {
- if (listPtr->tkwin != NULL) {
- if (listPtr->setGrid) {
- Tk_UnsetGrid(listPtr->tkwin);
- }
- listPtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(listPtr->interp, listPtr->widgetCmd);
- }
- if (listPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(DisplayListbox, (ClientData) listPtr);
- }
- Tcl_EventuallyFree((ClientData) listPtr, DestroyListbox);
+ DestroyListbox((char *) clientData);
} else if (eventPtr->type == ConfigureNotify) {
int vertSpace;
@@ -1654,16 +2387,16 @@ ListboxEventProc(clientData, eventPtr)
* everything for safety.
*/
- ListboxRedrawRange(listPtr, 0, listPtr->numElements-1);
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
} else if (eventPtr->type == FocusIn) {
if (eventPtr->xfocus.detail != NotifyInferior) {
listPtr->flags |= GOT_FOCUS;
- ListboxRedrawRange(listPtr, 0, listPtr->numElements-1);
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
}
} else if (eventPtr->type == FocusOut) {
if (eventPtr->xfocus.detail != NotifyInferior) {
listPtr->flags &= ~GOT_FOCUS;
- ListboxRedrawRange(listPtr, 0, listPtr->numElements-1);
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
}
}
}
@@ -1691,7 +2424,6 @@ ListboxCmdDeletedProc(clientData)
ClientData clientData; /* Pointer to widget record for widget. */
{
Listbox *listPtr = (Listbox *) clientData;
- Tk_Window tkwin = listPtr->tkwin;
/*
* This procedure could be invoked either because the window was
@@ -1700,12 +2432,8 @@ ListboxCmdDeletedProc(clientData)
* destroys the widget.
*/
- if (tkwin != NULL) {
- if (listPtr->setGrid) {
- Tk_UnsetGrid(listPtr->tkwin);
- }
- listPtr->tkwin = NULL;
- Tk_DestroyWindow(tkwin);
+ if (!(listPtr->flags & LISTBOX_DELETED)) {
+ Tk_DestroyWindow(listPtr->tkwin);
}
}
@@ -1720,7 +2448,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.
@@ -1729,61 +2457,86 @@ ListboxCmdDeletedProc(clientData)
*/
static int
-GetListboxIndex(interp, listPtr, string, endIsSize, indexPtr)
+GetListboxIndex(interp, listPtr, indexObj, endIsSize, indexPtr)
Tcl_Interp *interp; /* For error messages. */
Listbox *listPtr; /* Listbox for which the index is being
* specified. */
- char *string; /* Specifies an element in the listbox. */
+ Tcl_Obj *indexObj; /* Specifies an element in the listbox. */
int endIsSize; /* If 1, "end" refers to the number of
* entries in the listbox. If 0, "end"
* refers to 1 less than the number of
* entries. */
int *indexPtr; /* Where to store converted index. */
{
- int c;
- size_t length;
-
- length = strlen(string);
- c = string[0];
- if ((c == 'a') && (strncmp(string, "active", length) == 0)
- && (length >= 2)) {
- *indexPtr = listPtr->active;
- } else if ((c == 'a') && (strncmp(string, "anchor", length) == 0)
- && (length >= 2)) {
- *indexPtr = listPtr->selectAnchor;
- } else if ((c == 'e') && (strncmp(string, "end", length) == 0)) {
- if (endIsSize) {
- *indexPtr = listPtr->numElements;
- } else {
- *indexPtr = listPtr->numElements - 1;
- }
- } else if (c == '@') {
- int y;
- char *p, *end;
+ int result;
+ int index;
+ char *stringRep;
+
+ /* First see if the index is one of the named indices */
+ result = Tcl_GetIndexFromObj(NULL, indexObj, indexNames, "", 0, &index);
+ if (result == TCL_OK) {
+ switch (index) {
+ case INDEX_ACTIVE: {
+ /* "active" index */
+ *indexPtr = listPtr->active;
+ break;
+ }
- p = string+1;
- strtol(p, &end, 0);
- if ((end == p) || (*end != ',')) {
- goto badIndex;
+ case INDEX_ANCHOR: {
+ /* "anchor" index */
+ *indexPtr = listPtr->selectAnchor;
+ break;
+ }
+
+ case INDEX_END: {
+ /* "end" index */
+ if (endIsSize) {
+ *indexPtr = listPtr->nElements;
+ } else {
+ *indexPtr = listPtr->nElements - 1;
+ }
+ break;
+ }
}
- p = end+1;
- y = strtol(p, &end, 0);
- if ((end == p) || (*end != 0)) {
- goto badIndex;
+ return TCL_OK;
+ }
+
+ /* The index didn't match any of the named indices; maybe it's an @x,y */
+ stringRep = Tcl_GetString(indexObj);
+ if (stringRep[0] == '@') {
+ /* @x,y index */
+ int y;
+ char *start, *end;
+ start = stringRep + 1;
+ strtol(start, &end, 0);
+ if ((start == end) || (*end != ',')) {
+ Tcl_AppendResult(interp, "bad listbox index \"", stringRep,
+ "\": must be active, anchor, end, @x,y, or a number",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ start = end+1;
+ y = strtol(start, &end, 0);
+ if ((start == end) || (*end != '\0')) {
+ Tcl_AppendResult(interp, "bad listbox index \"", stringRep,
+ "\": must be active, anchor, end, @x,y, or a number",
+ (char *)NULL);
+ return TCL_ERROR;
}
*indexPtr = NearestListboxElement(listPtr, y);
- } else {
- if (Tcl_GetInt(interp, string, indexPtr) != TCL_OK) {
- Tcl_ResetResult(interp);
- goto badIndex;
- }
+ return TCL_OK;
+ }
+
+ /* Maybe the index is just an integer */
+ if (Tcl_GetIntFromObj(interp, indexObj, indexPtr) == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
- badIndex:
- Tcl_AppendResult(interp, "bad listbox index \"", string,
- "\": must be active, anchor, end, @x,y, or a number",
- (char *) NULL);
+ /* Everything failed, nothing matched. Throw up an error message */
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "bad listbox index \"",
+ Tcl_GetString(indexObj), "\": must be active, anchor, ",
+ "end, @x,y, or a number", (char *) NULL);
return TCL_ERROR;
}
@@ -1813,18 +2566,15 @@ ChangeListboxView(listPtr, index)
* that should now appear at the
* top of the listbox. */
{
- if (index >= (listPtr->numElements - listPtr->fullLines)) {
- index = listPtr->numElements - listPtr->fullLines;
+ if (index >= (listPtr->nElements - listPtr->fullLines)) {
+ index = listPtr->nElements - listPtr->fullLines;
}
if (index < 0) {
index = 0;
}
if (listPtr->topIndex != index) {
listPtr->topIndex = index;
- if (!(listPtr->flags & REDRAW_PENDING)) {
- Tcl_DoWhenIdle(DisplayListbox, (ClientData) listPtr);
- listPtr->flags |= REDRAW_PENDING;
- }
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
listPtr->flags |= UPDATE_V_SCROLLBAR;
}
}
@@ -1853,7 +2603,7 @@ ChangeListboxOffset(listPtr, offset)
* listbox. */
{
int maxOffset;
-
+
/*
* Make sure that the new offset is within the allowable range, and
* round it off to an even multiple of xScrollUnit.
@@ -1872,7 +2622,7 @@ ChangeListboxOffset(listPtr, offset)
if (offset != listPtr->xOffset) {
listPtr->xOffset = offset;
listPtr->flags |= UPDATE_H_SCROLLBAR;
- ListboxRedrawRange(listPtr, 0, listPtr->numElements);
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
}
}
@@ -1902,8 +2652,8 @@ ListboxScanTo(listPtr, x, y)
* operation. */
{
int newTopIndex, newOffset, maxIndex, maxOffset;
-
- maxIndex = listPtr->numElements - listPtr->fullLines;
+
+ maxIndex = listPtr->nElements - listPtr->fullLines;
maxOffset = listPtr->maxWidth + (listPtr->xScrollUnit - 1)
- (Tk_Width(listPtr->tkwin) - 2*listPtr->inset
- 2*listPtr->selBorderWidth - listPtr->xScrollUnit);
@@ -1981,8 +2731,8 @@ NearestListboxElement(listPtr, y)
index = 0;
}
index += listPtr->topIndex;
- if (index >= listPtr->numElements) {
- index = listPtr->numElements-1;
+ if (index >= listPtr->nElements) {
+ index = listPtr->nElements-1;
}
return index;
}
@@ -1995,7 +2745,7 @@ NearestListboxElement(listPtr, y)
* Select or deselect one or more elements in a listbox..
*
* Results:
- * None.
+ * Standard Tcl result.
*
* Side effects:
* All of the elements in the range between first and last are
@@ -2007,7 +2757,7 @@ NearestListboxElement(listPtr, y)
*----------------------------------------------------------------------
*/
-static void
+static int
ListboxSelect(listPtr, first, last, select)
register Listbox *listPtr; /* Information about widget. */
int first; /* Index of first element to
@@ -2018,47 +2768,64 @@ ListboxSelect(listPtr, first, last, select)
* deselect them. */
{
int i, firstRedisplay, increment, oldCount;
- Element *elPtr;
-
+ Tcl_HashEntry *entry;
+ int new;
+
if (last < first) {
i = first;
first = last;
last = i;
}
- if ((last < 0) || (first >= listPtr->numElements)) {
- return;
+ if ((last < 0) || (first >= listPtr->nElements)) {
+ return TCL_OK;
}
if (first < 0) {
first = 0;
}
- if (last >= listPtr->numElements) {
- last = listPtr->numElements - 1;
+ if (last >= listPtr->nElements) {
+ last = listPtr->nElements - 1;
}
oldCount = listPtr->numSelected;
firstRedisplay = -1;
increment = select ? 1 : -1;
- for (i = 0, elPtr = listPtr->firstPtr; i < first;
- i++, elPtr = elPtr->nextPtr) {
- /* Empty loop body. */
- }
- for ( ; i <= last; i++, elPtr = elPtr->nextPtr) {
- if (elPtr->selected == select) {
- continue;
- }
- listPtr->numSelected += increment;
- elPtr->selected = select;
- if (firstRedisplay < 0) {
- firstRedisplay = i;
+
+ /*
+ * For each index in the range, find it in our selection hash table.
+ * If it's not there but should be, add it. If it's there but shouldn't
+ * be, remove it.
+ */
+ for (i = first; i <= last; i++) {
+ entry = Tcl_FindHashEntry(listPtr->selection, (char *)i);
+ if (entry != NULL) {
+ if (!select) {
+ Tcl_DeleteHashEntry(entry);
+ listPtr->numSelected--;
+ if (firstRedisplay < 0) {
+ firstRedisplay = i;
+ }
+ }
+ } else {
+ if (select) {
+ entry = Tcl_CreateHashEntry(listPtr->selection,
+ (char *)i, &new);
+ Tcl_SetHashValue(entry, (ClientData) NULL);
+ listPtr->numSelected++;
+ if (firstRedisplay < 0) {
+ firstRedisplay = i;
+ }
+ }
}
}
+
if (firstRedisplay >= 0) {
- ListboxRedrawRange(listPtr, first, last);
+ EventuallyRedrawRange(listPtr, first, last);
}
if ((oldCount == 0) && (listPtr->numSelected > 0)
&& (listPtr->exportSelection)) {
Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection,
(ClientData) listPtr);
}
+ return TCL_OK;
}
/*
@@ -2096,10 +2863,14 @@ ListboxFetchSelection(clientData, offset, buffer, maxBytes)
* NULL character. */
{
register Listbox *listPtr = (Listbox *) clientData;
- register Element *elPtr;
Tcl_DString selection;
int length, count, needNewline;
-
+ Tcl_Obj *curElement;
+ char *stringRep;
+ int stringLen;
+ Tcl_HashEntry *entry;
+ int i;
+
if (!listPtr->exportSelection) {
return -1;
}
@@ -2110,12 +2881,16 @@ ListboxFetchSelection(clientData, offset, buffer, maxBytes)
needNewline = 0;
Tcl_DStringInit(&selection);
- for (elPtr = listPtr->firstPtr; elPtr != NULL; elPtr = elPtr->nextPtr) {
- if (elPtr->selected) {
+ for (i = 0; i < listPtr->nElements; i++) {
+ entry = Tcl_FindHashEntry(listPtr->selection, (char *)i);
+ if (entry != NULL) {
if (needNewline) {
Tcl_DStringAppend(&selection, "\n", 1);
}
- Tcl_DStringAppend(&selection, elPtr->text, elPtr->textLength);
+ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i,
+ &curElement);
+ stringRep = Tcl_GetStringFromObj(curElement, &stringLen);
+ Tcl_DStringAppend(&selection, stringRep, stringLen);
needNewline = 1;
}
}
@@ -2168,16 +2943,16 @@ ListboxLostSelection(clientData)
ClientData clientData; /* Information about listbox widget. */
{
register Listbox *listPtr = (Listbox *) clientData;
-
- if ((listPtr->exportSelection) && (listPtr->numElements > 0)) {
- ListboxSelect(listPtr, 0, listPtr->numElements-1, 0);
+
+ if ((listPtr->exportSelection) && (listPtr->nElements > 0)) {
+ ListboxSelect(listPtr, 0, listPtr->nElements-1, 0);
}
}
/*
*----------------------------------------------------------------------
*
- * ListboxRedrawRange --
+ * EventuallyRedrawRange --
*
* Ensure that a given range of elements is eventually redrawn on
* the display (if those elements in fact appear on the display).
@@ -2191,9 +2966,8 @@ ListboxLostSelection(clientData)
*----------------------------------------------------------------------
*/
- /* ARGSUSED */
static void
-ListboxRedrawRange(listPtr, first, last)
+EventuallyRedrawRange(listPtr, first, last)
register Listbox *listPtr; /* Information about widget. */
int first; /* Index of first element in list
* that needs to be redrawn. */
@@ -2202,12 +2976,15 @@ ListboxRedrawRange(listPtr, first, last)
* be less than first;
* these just bracket a range. */
{
- if ((listPtr->tkwin == NULL) || !Tk_IsMapped(listPtr->tkwin)
- || (listPtr->flags & REDRAW_PENDING)) {
+ /* We don't have to register a redraw callback if one is already pending,
+ * or if the window doesn't exist, or if the window isn't mapped */
+ if ((listPtr->flags & REDRAW_PENDING)
+ || (listPtr->tkwin == NULL)
+ || !Tk_IsMapped(listPtr->tkwin)) {
return;
}
- Tcl_DoWhenIdle(DisplayListbox, (ClientData) listPtr);
listPtr->flags |= REDRAW_PENDING;
+ Tcl_DoWhenIdle(DisplayListbox, (ClientData) listPtr);
}
/*
@@ -2234,21 +3011,21 @@ static void
ListboxUpdateVScrollbar(listPtr)
register Listbox *listPtr; /* Information about widget. */
{
- char string[100];
+ char string[TCL_DOUBLE_SPACE * 2];
double first, last;
int result;
Tcl_Interp *interp;
-
+
if (listPtr->yScrollCmd == NULL) {
return;
}
- if (listPtr->numElements == 0) {
+ if (listPtr->nElements == 0) {
first = 0.0;
last = 1.0;
} else {
- first = listPtr->topIndex/((double) listPtr->numElements);
+ first = listPtr->topIndex/((double) listPtr->nElements);
last = (listPtr->topIndex+listPtr->fullLines)
- /((double) listPtr->numElements);
+ /((double) listPtr->nElements);
if (last > 1.0) {
last = 1.0;
}
@@ -2296,7 +3073,7 @@ static void
ListboxUpdateHScrollbar(listPtr)
register Listbox *listPtr; /* Information about widget. */
{
- char string[60];
+ char string[TCL_DOUBLE_SPACE * 2];
int result, windowWidth;
double first, last;
Tcl_Interp *interp;
@@ -2335,3 +3112,174 @@ ListboxUpdateHScrollbar(listPtr)
}
Tcl_Release((ClientData) interp);
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListboxListVarProc --
+ *
+ * Called whenever the trace on the listbox list var fires.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static char *
+ListboxListVarProc(clientData, interp, name1, name2, flags)
+ ClientData clientData; /* Information about button. */
+ Tcl_Interp *interp; /* Interpreter containing variable. */
+ char *name1; /* Not used. */
+ char *name2; /* Not used. */
+ int flags; /* Information about what happened. */
+{
+ Listbox *listPtr = (Listbox *)clientData;
+ Tcl_Obj *oldListObj, *varListObj;
+ int oldLength;
+ int i;
+ Tcl_HashEntry *entry;
+
+ /* Bwah hahahaha -- puny mortal, you can't unset a -listvar'd variable! */
+ if (flags & TCL_TRACE_UNSETS) {
+ if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
+ Tcl_SetVar2Ex(interp, listPtr->listVarName,
+ (char *)NULL, listPtr->listObj, TCL_GLOBAL_ONLY);
+ Tcl_TraceVar(interp, listPtr->listVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, clientData);
+ return (char *)NULL;
+ }
+ } else {
+ oldListObj = listPtr->listObj;
+ varListObj = Tcl_GetVar2Ex(listPtr->interp, listPtr->listVarName,
+ (char *)NULL, TCL_GLOBAL_ONLY);
+ /*
+ * Make sure the new value is a good list; if it's not, disallow
+ * the change -- the fact that it is a listvar means that it must
+ * always be a valid list -- and return an error message.
+ */
+ if (Tcl_ListObjLength(listPtr->interp, varListObj, &i) != TCL_OK) {
+ Tcl_SetVar2Ex(interp, listPtr->listVarName, (char *)NULL,
+ oldListObj, TCL_GLOBAL_ONLY);
+ return("invalid listvar value");
+ }
+
+ listPtr->listObj = varListObj;
+ /* Incr the obj ref count so it doesn't vanish if the var is unset */
+ Tcl_IncrRefCount(listPtr->listObj);
+ /* Clean up the ref to our old list obj */
+ Tcl_DecrRefCount(oldListObj);
+ }
+
+ /*
+ * If the list length has decreased, then we should clean up selection and
+ * attributes information for elements past the end of the new list
+ */
+ oldLength = listPtr->nElements;
+ Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
+ if (listPtr->nElements < oldLength) {
+ for (i = listPtr->nElements; i < oldLength; i++) {
+ /* Clean up selection */
+ entry = Tcl_FindHashEntry(listPtr->selection, (char *)i);
+ if (entry != NULL) {
+ listPtr->numSelected--;
+ Tcl_DeleteHashEntry(entry);
+ }
+
+ /* Clean up attributes */
+ entry = Tcl_FindHashEntry(listPtr->itemAttrTable, (char *)i);
+ if (entry != NULL) {
+ Tcl_DeleteHashEntry(entry);
+ }
+ }
+ }
+
+ if (oldLength != listPtr->nElements) {
+ listPtr->flags |= UPDATE_V_SCROLLBAR;
+ if (listPtr->topIndex > (listPtr->nElements - listPtr->fullLines)) {
+ listPtr->topIndex = listPtr->nElements - listPtr->fullLines;
+ if (listPtr->topIndex < 0) {
+ listPtr->topIndex = 0;
+ }
+ }
+ }
+
+ /*
+ * The computed maxWidth may have changed as a result of this operation.
+ * However, we don't want to recompute it every time this trace fires
+ * (imagine the user doing 1000 lappends to the listvar). Therefore, set
+ * the MAXWIDTH_IS_STALE flag, which will cause the width to be recomputed
+ * next time the list is redrawn.
+ */
+ listPtr->flags |= MAXWIDTH_IS_STALE;
+
+ EventuallyRedrawRange(listPtr, 0, listPtr->nElements-1);
+ return (char*)NULL;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MigrateHashEntries --
+ *
+ * Given a hash table with entries keyed by a single integer value,
+ * move all entries in a given range by a fixed amount, so that
+ * if in the original table there was an entry with key n and
+ * the offset was i, in the new table that entry would have key n + i.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Rekeys some hash table entries.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MigrateHashEntries(table, first, last, offset)
+ Tcl_HashTable *table;
+ int first;
+ int last;
+ int offset;
+{
+ int i, new;
+ Tcl_HashEntry *entry;
+ ClientData clientData;
+
+ if (offset == 0) {
+ return;
+ }
+ /* It's more efficient to do one if/else and nest the for loops inside,
+ * although we could avoid some code duplication if we nested the if/else
+ * inside the for loops */
+ if (offset > 0) {
+ for (i = last; i >= first; i--) {
+ entry = Tcl_FindHashEntry(table, (char *)i);
+ if (entry != NULL) {
+ clientData = Tcl_GetHashValue(entry);
+ Tcl_DeleteHashEntry(entry);
+ entry = Tcl_CreateHashEntry(table, (char *)(i + offset), &new);
+ Tcl_SetHashValue(entry, clientData);
+ }
+ }
+ } else {
+ for (i = first; i <= last; i++) {
+ entry = Tcl_FindHashEntry(table, (char *)i);
+ if (entry != NULL) {
+ clientData = Tcl_GetHashValue(entry);
+ Tcl_DeleteHashEntry(entry);
+ entry = Tcl_CreateHashEntry(table, (char *)(i + offset), &new);
+ Tcl_SetHashValue(entry, clientData);
+ }
+ }
+ }
+ return;
+}
+
+
+
diff --git a/tk/generic/tkMacWinMenu.c b/tk/generic/tkMacWinMenu.c
index ed9a3b1f42d..066b96eedce 100644
--- a/tk/generic/tkMacWinMenu.c
+++ b/tk/generic/tkMacWinMenu.c
@@ -14,7 +14,11 @@
#include "tkMenu.h"
-static int postCommandGeneration;
+typedef struct ThreadSpecificData {
+ int postCommandGeneration;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
static int PreprocessMenu _ANSI_ARGS_((TkMenu *menuPtr));
@@ -43,6 +47,8 @@ PreprocessMenu(menuPtr)
{
int index, result, finished;
TkMenu *cascadeMenuPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
Tcl_Preserve((ClientData) menuPtr);
@@ -67,16 +73,16 @@ 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)) {
cascadeMenuPtr =
menuPtr->entries[index]->childMenuRefPtr->menuPtr;
if (cascadeMenuPtr->postCommandGeneration !=
- postCommandGeneration) {
+ tsdPtr->postCommandGeneration) {
cascadeMenuPtr->postCommandGeneration =
- postCommandGeneration;
+ tsdPtr->postCommandGeneration;
result = PreprocessMenu(cascadeMenuPtr);
if (result != TCL_OK) {
goto done;
@@ -128,7 +134,11 @@ int
TkPreprocessMenu(menuPtr)
TkMenu *menuPtr;
{
- postCommandGeneration++;
- menuPtr->postCommandGeneration = postCommandGeneration;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->postCommandGeneration++;
+ menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration;
return PreprocessMenu(menuPtr);
}
+
diff --git a/tk/generic/tkMain.c b/tk/generic/tkMain.c
index 02ef0afd422..9f31a9860a2 100644
--- a/tk/generic/tkMain.c
+++ b/tk/generic/tkMain.c
@@ -16,16 +16,37 @@
* RCS: @(#) $Id$
*/
+#ifdef _WIN32
+# include <windows.h>
+#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <tcl.h>
+#include <tclInt.h>
#include <tk.h>
+#include "tkInt.h"
#ifdef NO_STDLIB_H
# include "../compat/stdlib.h"
#else
# include <stdlib.h>
#endif
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+
+
+typedef struct ThreadSpecificData {
+ Tcl_Interp *interp; /* Interpreter for this thread. */
+ Tcl_DString command; /* Used to assemble lines of terminal input
+ * into Tcl commands. */
+ Tcl_DString line; /* Used to read the next line from the
+ * terminal input. */
+ int tty; /* Non-zero means standard input is a
+ * terminal-like device. Zero means it's
+ * a file. */
+} ThreadSpecificData;
+Tcl_ThreadDataKey dataKey;
/*
* Declarations for various library procedures and variables (don't want
@@ -36,27 +57,14 @@
* some systems.
*/
-extern int isatty _ANSI_ARGS_((int fd));
#if !defined(__WIN32__) && !defined(_WIN32)
+extern int isatty _ANSI_ARGS_((int fd));
extern char * strrchr _ANSI_ARGS_((CONST char *string, int c));
#endif
extern void TkpDisplayWarning _ANSI_ARGS_((char *msg,
char *title));
/*
- * Global variables used by the main program:
- */
-
-static Tcl_Interp *interp; /* Interpreter for this application. */
-static Tcl_DString command; /* Used to assemble lines of terminal input
- * into Tcl commands. */
-static Tcl_DString line; /* Used to read the next line from the
- * terminal input. */
-static int tty; /* Non-zero means standard input is a
- * terminal-like device. Zero means it's
- * a file. */
-
-/*
* Forward declarations for procedures defined later in this file.
*/
@@ -67,7 +75,7 @@ static void StdinProc _ANSI_ARGS_((ClientData clientData,
/*
*----------------------------------------------------------------------
*
- * Tk_Main --
+ * Tk_MainEx --
*
* Main program for Wish and most other Tk-based applications.
*
@@ -82,24 +90,46 @@ static void StdinProc _ANSI_ARGS_((ClientData clientData,
*
*----------------------------------------------------------------------
*/
-
void
-Tk_Main(argc, argv, appInitProc)
+Tk_MainEx(argc, argv, appInitProc, interp)
int argc; /* Number of arguments. */
char **argv; /* Array of argument strings. */
Tcl_AppInitProc *appInitProc; /* Application-specific initialization
* procedure to call after most
* initialization but before starting
* to execute commands. */
+ Tcl_Interp *interp;
{
char *args, *fileName;
- char buf[20];
+ char buf[TCL_INTEGER_SPACE];
int code;
size_t length;
Tcl_Channel inChannel, outChannel;
+ Tcl_DString argString;
+ ThreadSpecificData *tsdPtr;
+#ifdef __WIN32__
+ HANDLE handle;
+#endif
+ /*
+ * Ensure that we are getting the matching version of Tcl. This is
+ * really only an issue when Tk is loaded dynamically.
+ */
+
+ if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ abort();
+ }
+
+ tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
Tcl_FindExecutable(argv[0]);
- interp = Tcl_CreateInterp();
+ tsdPtr->interp = interp;
+
+#if (defined(__WIN32__) || defined(MAC_TCL))
+ Tk_InitConsoleChannels(interp);
+#endif
+
#ifdef TCL_MEM_DEBUG
Tcl_InitMemory(interp);
#endif
@@ -111,7 +141,8 @@ Tk_Main(argc, argv, appInitProc)
* use it as the name of a script file to process.
*/
- fileName = NULL;
+ fileName = TclGetStartupScriptFileName();
+
if (argc > 1) {
length = strlen(argv[1]);
if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) {
@@ -119,24 +150,33 @@ Tk_Main(argc, argv, appInitProc)
argv++;
}
}
- if ((argc > 1) && (argv[1][0] != '-')) {
- fileName = argv[1];
- argc--;
- argv++;
+ if (fileName == NULL) {
+ if ((argc > 1) && (argv[1][0] != '-')) {
+ fileName = argv[1];
+ argc--;
+ argv++;
+ }
}
-
+
/*
* Make command-line arguments available in the Tcl variables "argc"
* and "argv".
*/
args = Tcl_Merge(argc-1, argv+1);
- Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
+ Tcl_ExternalToUtfDString(NULL, args, -1, &argString);
+ Tcl_SetVar(interp, "argv", Tcl_DStringValue(&argString), 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.
@@ -150,12 +190,31 @@ Tk_Main(argc, argv, appInitProc)
*/
#ifdef __WIN32__
- tty = 1;
+ handle = GetStdHandle(STD_INPUT_HANDLE);
+
+ if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)
+ || (GetFileType(handle) == FILE_TYPE_UNKNOWN)) {
+ /*
+ * If it's a bad or closed handle, then it's been connected
+ * to a wish console window.
+ */
+
+ tsdPtr->tty = 1;
+ } else if (GetFileType(handle) == FILE_TYPE_CHAR) {
+ /*
+ * A character file handle is a tty by definition.
+ */
+
+ tsdPtr->tty = 1;
+ } else {
+ tsdPtr->tty = 0;
+ }
+
#else
- tty = isatty(0);
+ tsdPtr->tty = isatty(0);
#endif
Tcl_SetVar(interp, "tcl_interactive",
- ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
+ ((fileName == NULL) && tsdPtr->tty) ? "1" : "0", TCL_GLOBAL_ONLY);
/*
* Invoke application-specific initialization.
@@ -170,6 +229,7 @@ Tk_Main(argc, argv, appInitProc)
*/
if (fileName != NULL) {
+ Tcl_ResetResult(interp);
code = Tcl_EvalFile(interp, fileName);
if (code != TCL_OK) {
/*
@@ -183,7 +243,7 @@ Tk_Main(argc, argv, appInitProc)
Tcl_DeleteInterp(interp);
Tcl_Exit(1);
}
- tty = 0;
+ tsdPtr->tty = 0;
} else {
/*
@@ -201,17 +261,18 @@ Tk_Main(argc, argv, appInitProc)
Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,
(ClientData) inChannel);
}
- if (tty) {
+ if (tsdPtr->tty) {
Prompt(interp, 0);
}
}
+ Tcl_DStringFree(&argString);
outChannel = Tcl_GetStdChannel(TCL_STDOUT);
if (outChannel) {
Tcl_Flush(outChannel);
}
- Tcl_DStringInit(&command);
- Tcl_DStringInit(&line);
+ Tcl_DStringInit(&tsdPtr->command);
+ Tcl_DStringInit(&tsdPtr->line);
Tcl_ResetResult(interp);
/*
@@ -254,12 +315,15 @@ StdinProc(clientData, mask)
char *cmd;
int code, count;
Tcl_Channel chan = (Tcl_Channel) clientData;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_Interp *interp = tsdPtr->interp;
- count = Tcl_Gets(chan, &line);
+ count = Tcl_Gets(chan, &tsdPtr->line);
if (count < 0) {
if (!gotPartial) {
- if (tty) {
+ if (tsdPtr->tty) {
Tcl_Exit(0);
} else {
Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);
@@ -268,9 +332,10 @@ StdinProc(clientData, mask)
}
}
- (void) Tcl_DStringAppend(&command, Tcl_DStringValue(&line), -1);
- cmd = Tcl_DStringAppend(&command, "\n", -1);
- Tcl_DStringFree(&line);
+ (void) Tcl_DStringAppend(&tsdPtr->command, Tcl_DStringValue(
+ &tsdPtr->line), -1);
+ cmd = Tcl_DStringAppend(&tsdPtr->command, "\n", -1);
+ Tcl_DStringFree(&tsdPtr->line);
if (!Tcl_CommandComplete(cmd)) {
gotPartial = 1;
goto prompt;
@@ -293,17 +358,14 @@ StdinProc(clientData, mask)
Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,
(ClientData) chan);
}
- Tcl_DStringFree(&command);
- if (*interp->result != 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);
+ Tcl_DStringFree(&tsdPtr->command);
+ if (Tcl_GetStringResult(interp)[0] != '\0') {
+ if ((code != TCL_OK) || (tsdPtr->tty)) {
+ chan = Tcl_GetStdChannel(TCL_STDOUT);
+ if (chan) {
+ Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
+ Tcl_WriteChars(chan, "\n", 1);
+ }
}
}
@@ -312,7 +374,7 @@ StdinProc(clientData, mask)
*/
prompt:
- if (tty) {
+ if (tsdPtr->tty) {
Prompt(interp, gotPartial);
}
Tcl_ResetResult(interp);
@@ -361,7 +423,7 @@ defaultPrompt:
outChannel = Tcl_GetChannel(interp, "stdout", NULL);
if (outChannel != (Tcl_Channel) NULL) {
- Tcl_Write(outChannel, "% ", 2);
+ Tcl_WriteChars(outChannel, "% ", 2);
}
}
} else {
@@ -377,8 +439,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;
}
@@ -388,3 +450,5 @@ defaultPrompt:
Tcl_Flush(outChannel);
}
}
+
+
diff --git a/tk/generic/tkMenu.c b/tk/generic/tkMenu.c
index 3663d40ecbc..2e84ebb59eb 100644
--- a/tk/generic/tkMenu.c
+++ b/tk/generic/tkMenu.c
@@ -7,7 +7,7 @@
* 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.
@@ -68,174 +68,247 @@
*
*/
+#if 0
+
+/*
+ * used only to test for old config code
+ */
+
+#define __NO_OLD_CONFIG
+#endif
+
#include "tkPort.h"
#include "tkMenu.h"
#define MENU_HASH_KEY "tkMenus"
-static int menusInitialized; /* Whether or not the hash tables, etc., have
- * been setup */
+typedef struct ThreadSpecificData {
+ int menusInitialized; /* Flag indicates whether thread-specific
+ * elements of the Windows Menu module
+ * have been initialized. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
+
+/*
+ * The following flag indicates whether the process-wide state for
+ * the Menu module has been intialized. The Mutex protects access to
+ * that flag.
+ */
+
+static int menusInitialized;
+TCL_DECLARE_MUTEX(menuMutex)
/*
* Configuration specs for individual menu entries. If this changes, be sure
* 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,
+ -1, Tk_Offset(TkMenuEntry, columnBreak)},
+ {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,
+ -1, Tk_Offset(TkMenuEntry, hideMargin)},
+ {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,
+ -1, Tk_Offset(TkMenuEntry, state), 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,
+ -1, Tk_Offset(TkMenuEntry, indicatorOn)},
+ {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,
+ -1, Tk_Offset(TkMenuEntry, indicatorOn)},
+ {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, -1, Tk_Offset(TkMenuEntry, state), 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, -1, Tk_Offset(TkMenu, tearoff)},
+ {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 +316,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 +334,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 +348,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 +367,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 +436,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 +488,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->tearoff = 0;
+ menuPtr->tearoffCommandPtr = NULL;
+ menuPtr->cursorPtr = None;
+ menuPtr->takeFocusPtr = NULL;
+ menuPtr->postCommandPtr = NULL;
menuPtr->postCommandGeneration = 0;
menuPtr->postedCascade = NULL;
menuPtr->nextInstancePtr = NULL;
@@ -394,24 +516,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 +570,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 +590,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 +653,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 +676,353 @@ 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)) {
+
+ switch ((enum options) option) {
+ case MENU_ACTIVATE: {
+ int index;
+ /* patch for menu selection */
+ int state;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "activate index");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &index)
+ != TCL_OK) {
+ goto error;
+ }
+ if (menuPtr->active == index) {
+ goto done;
+ }
+ if ((index >= 0)
+ && ((menuPtr->entries[index]->type == SEPARATOR_ENTRY)
+ || (menuPtr->entries[index]->state
+ == ENTRY_DISABLED))) {
index = -1;
}
+ result = TkActivateMenuEntry(menuPtr, index);
+ break;
}
- 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;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "delete first ?last?");
+ goto error;
+ }
+ if (TkGetMenuIndex(interp, menuPtr, objv[2], 0, &first)
+ != TCL_OK) {
+ goto error;
+ }
+ if (objc == 3) {
+ last = first;
+ } else {
+ if (TkGetMenuIndex(interp, menuPtr, objv[3], 0, &last)
+ != TCL_OK) {
+ goto error;
+ }
+ }
+ if (menuPtr->tearoff && (first == 0)) {
+
+ /*
+ * 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_SetResult(interp, "none", TCL_STATIC);
+ } else {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), 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_SetResult(interp, "tearoff", TCL_STATIC);
+ } else {
+ Tcl_SetResult(interp,
+ menuEntryTypeStrings[menuPtr->entries[index]->type],
+ TCL_STATIC);
+ }
+ 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 +1032,6 @@ MenuWidgetCmd(clientData, interp, argc, argv)
Tcl_Release((ClientData) menuPtr);
return TCL_ERROR;
}
-
/*
*----------------------------------------------------------------------
@@ -888,45 +1065,60 @@ TkInvokeMenu(interp, menuPtr, index)
goto done;
}
mePtr = menuPtr->entries[index];
- if (mePtr->state == tkDisabledUid) {
+ if (mePtr->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_DString ds;
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, "tkTearOffMenu ", -1);
+ Tcl_DStringAppend(&ds, Tk_PathName(menuPtr->tkwin), -1);
+ result = Tcl_Eval(interp, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ } else if ((mePtr->type == CHECK_BUTTON_ENTRY)
+ && (mePtr->namePtr != NULL)) {
+ Tcl_Obj *valuePtr;
+
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;
+ }
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewObj();
+ }
+ Tcl_IncrRefCount(valuePtr);
+ if (Tcl_ObjSetVar2(interp, mePtr->namePtr, 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;
+
+ if (valuePtr == NULL) {
+ valuePtr = Tcl_NewObj();
}
- } else if (mePtr->type == RADIO_BUTTON_ENTRY) {
- if (Tcl_SetVar(interp, mePtr->name, mePtr->onValue,
+ Tcl_IncrRefCount(valuePtr);
+ if (Tcl_ObjSetVar2(interp, mePtr->namePtr, 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_EvalObjEx(interp, commandPtr, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(commandPtr);
}
Tcl_Release((ClientData) mePtr);
done:
return result;
}
-
-
/*
*----------------------------------------------------------------------
@@ -951,13 +1143,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 +1170,29 @@ 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;
+ /*
+ * It is possible that the menu info is out of sync, and
+ * these things point to NULL, so verify existence [Bug: 3402]
+ */
+ if (newObjv[0] && newObjv[1]) {
+ Tcl_IncrRefCount(newObjv[0]);
+ Tcl_IncrRefCount(newObjv[1]);
+ 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 +1212,27 @@ DestroyMenuInstance(menuPtr)
/*
* Free up all the stuff that requires special handling, then
- * let Tk_FreeOptions handle all the standard option-related
+ * let Tk_FreeConfigOptions 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 +1411,7 @@ DestroyMenuEntry(memPtr)
/*
* Free up all the stuff that requires special handling, then
- * let Tk_FreeOptions handle all the standard option-related
+ * let Tk_FreeConfigOptions handle all the standard option-related
* stuff.
*/
@@ -1215,15 +1424,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 +1470,6 @@ MenuWorldChanged(instanceData)
TkpConfigureMenuEntry(menuPtr->entries[i]);
}
}
-
/*
*----------------------------------------------------------------------
@@ -1272,7 +1482,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 +1492,32 @@ 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;
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 +1529,57 @@ 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) {
+ if (menuListPtr->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 +1592,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 +1604,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 +1642,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 +1673,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 +1690,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 +1738,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 +1758,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 +1774,69 @@ 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) {
+ valuePtr = Tcl_ObjGetVar2(menuPtr->interp, mePtr->namePtr, 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) {
+ Tcl_ObjSetVar2(menuPtr->interp, mePtr->namePtr, NULL,
+ (mePtr->type == CHECK_BUTTON_ENTRY)
+ ? mePtr->offValuePtr
+ : Tcl_NewObj(),
+ 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 +1844,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 +1925,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 +1951,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 +2001,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 +2011,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 +2059,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 +2068,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 +2116,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 +2174,6 @@ MenuCmdDeletedProc(clientData)
*/
if (tkwin != NULL) {
- menuPtr->tkwin = NULL;
Tk_DestroyWindow(tkwin);
}
}
@@ -1890,41 +2229,49 @@ 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->state = ENTRY_DISABLED;
+ mePtr->borderPtr = NULL;
+ mePtr->fgPtr = NULL;
+ mePtr->activeBorderPtr = NULL;
+ mePtr->activeFgPtr = NULL;
+ mePtr->fontPtr = NULL;
+ mePtr->indicatorOn = 0;
+ mePtr->indicatorFgPtr = NULL;
mePtr->columnBreak = 0;
mePtr->hideMargin = 0;
- mePtr->command = NULL;
- mePtr->name = NULL;
+ 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 +2293,24 @@ 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;
- 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 +2318,12 @@ 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)) {
+ if (menuPtr->tearoff && (index == 0)) {
index = 1;
}
@@ -1984,30 +2331,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 +2347,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 +2382,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 +2452,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 +2465,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 +2479,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;
}
@@ -2193,15 +2540,15 @@ TkActivateMenuEntry(menuPtr, index)
* might already have been changed to disabled).
*/
- if (mePtr->state == tkActiveUid) {
- mePtr->state = tkNormalUid;
+ if (mePtr->state == ENTRY_ACTIVE) {
+ mePtr->state = ENTRY_NORMAL;
}
TkEventuallyRedrawMenu(menuPtr, menuPtr->entries[menuPtr->active]);
}
menuPtr->active = index;
if (index >= 0) {
mePtr = menuPtr->entries[index];
- mePtr->state = tkActiveUid;
+ mePtr->state = ENTRY_ACTIVE;
TkEventuallyRedrawMenu(menuPtr, mePtr);
}
return result;
@@ -2237,9 +2584,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_EvalObjEx(menuPtr->interp, postCommandPtr,
+ TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(postCommandPtr);
if (result != TCL_OK) {
return result;
}
@@ -2269,64 +2620,53 @@ 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, 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 +2699,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 +2712,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 +2730,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 +2788,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 +2855,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 +2932,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 +3106,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_NewObj();
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 +3311,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
@@ -3013,7 +3405,7 @@ DeleteMenuCloneEntries(menuPtr, first, last)
}
for (i = last + 1; i < menuListPtr->numEntries; i++) {
menuListPtr->entries[i - numDeleted] = menuListPtr->entries[i];
- menuListPtr->entries[i - numDeleted]->index = i;
+ menuListPtr->entries[i - numDeleted]->index = i - numDeleted;
}
menuListPtr->numEntries -= numDeleted;
if (menuListPtr->numEntries == 0) {
@@ -3050,8 +3442,21 @@ DeleteMenuCloneEntries(menuPtr, first, last)
void
TkMenuInit()
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
if (!menusInitialized) {
- TkpMenuInit();
- menusInitialized = 1;
+ Tcl_MutexLock(&menuMutex);
+ if (!menusInitialized) {
+ TkpMenuInit();
+ menusInitialized = 1;
+ }
+ Tcl_MutexUnlock(&menuMutex);
+ }
+ if (!tsdPtr->menusInitialized) {
+ TkpMenuThreadInit();
+ tsdPtr->menusInitialized = 1;
}
}
+
+
diff --git a/tk/generic/tkMenu.h b/tk/generic/tkMenu.h
index 27b9dfa61b3..d1b8e39dd3a 100644
--- a/tk/generic/tkMenu.h
+++ b/tk/generic/tkMenu.h
@@ -3,7 +3,7 @@
*
* 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.
@@ -47,66 +47,72 @@ 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:
+ int state; /* 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
- * don't draw it. */
+ * don't draw it. This field is ignored unless
+ * the entry is a radio or check button. */
/*
* 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
* the item in front of it. If this is
- * 1, this item starts a new column. */
+ * 1, this item starts a new column. This
+ * field is always 0 for tearoff and separator
+ * entries. */
int hideMargin; /* If this is 0, then the item has enough
- * margin to accomodate a standard check
- * mark and a default right margin. If this
- * is 1, then the item has no such margins.
- * and checkbuttons and radiobuttons with
- * this set will have a rectangle drawn
- * in the indicator around the item if
- * the item is checked.
- * This is useful palette menus.*/
+ * margin to accomodate a standard check mark
+ * and a default right margin. If this is 1,
+ * then the item has no such margins. and
+ * checkbuttons and radiobuttons with this set
+ * will have a rectangle drawn in the indicator
+ * around the item if the item is checked. This
+ * is useful for palette menus. This field is
+ * ignored for separators and tearoffs. */
int indicatorSpace; /* The width of the indicator space for this
- * entry.
- */
+ * entry. */
int labelWidth; /* Number of pixels to allow for displaying
* labels in menu entries. */
@@ -114,15 +120,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. */
@@ -179,7 +185,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;
@@ -191,9 +197,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.
@@ -211,25 +217,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
@@ -253,7 +256,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" */
@@ -261,20 +264,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
@@ -305,7 +309,7 @@ typedef struct TkMenu {
* Miscellaneous information:
*/
- int tearOff; /* 1 means this menu can be torn off. On some
+ int tearoff; /* 1 means this menu can be torn off. On some
* platforms, the user can drag an outline
* of the menu by just dragging outside of
* the menu, and the tearoff is created where
@@ -313,17 +317,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. */
@@ -341,6 +345,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.
@@ -360,6 +367,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;
/*
@@ -407,6 +421,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
@@ -453,13 +477,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:
*/
@@ -470,21 +487,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,
@@ -506,8 +528,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));
@@ -521,7 +543,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
@@ -547,3 +570,4 @@ EXTERN void TkpSetWindowMenuBar _ANSI_ARGS_((Tk_Window tkwin,
#endif /* _TKMENU */
+
diff --git a/tk/generic/tkMenuDraw.c b/tk/generic/tkMenuDraw.c
index 6109310bb7a..123795c4801 100644
--- a/tk/generic/tkMenuDraw.c
+++ b/tk/generic/tkMenuDraw.c
@@ -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;
XColor *foreground, *background;
/*
@@ -196,33 +199,40 @@ 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;
- newGC = Tk_GetGCColor(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
- &gcValues, menuPtr->fg, Tk_3DBorderColor(menuPtr->border));
+ 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) {
Tk_FreeGC(menuPtr->display, menuPtr->textGC);
}
menuPtr->textGC = newGC;
- gcValues.font = Tk_FontId(menuPtr->tkfont);
- background = Tk_3DBorderColor(menuPtr->border);
+ gcValues.font = Tk_FontId(tkfont);
+ background = Tk_3DBorderColor(border);
gcValues.background = background->pixel;
- if (menuPtr->disabledFg != NULL) {
- foreground = menuPtr->disabledFg;
+ if (menuPtr->disabledFgPtr != NULL) {
+ XColor *disabledFg;
+
+ disabledFg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->disabledFgPtr);
+ foreground = disabledFg;
gcValues.foreground = foreground->pixel;
mask = GCForeground|GCBackground|GCFont;
} else {
- foreground = background;
+ foreground = background;
background = NULL;
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;
@@ -230,47 +240,47 @@ TkMenuConfigureDrawOptions(menuPtr)
mask = GCForeground|GCFillStyle|GCStipple;
}
}
- newGC = Tk_GetGCColor(menuPtr->tkwin, mask, &gcValues, foreground,
- background);
+ newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
if (menuPtr->disabledGC != None) {
Tk_FreeGC(menuPtr->display, menuPtr->disabledGC);
}
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;
gcValues.stipple = menuPtr->gray;
- newGC = Tk_GetGCColor(menuPtr->tkwin,
- GCForeground|GCFillStyle|GCStipple, &gcValues,
- Tk_3DBorderColor(menuPtr->border), NULL);
+ newGC = Tk_GetGC(menuPtr->tkwin,
+ GCForeground|GCFillStyle|GCStipple, &gcValues);
}
if (menuPtr->disabledImageGC != None) {
Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC);
}
menuPtr->disabledImageGC = newGC;
- gcValues.font = Tk_FontId(menuPtr->tkfont);
- gcValues.foreground = menuPtr->activeFg->pixel;
- gcValues.background =
- Tk_3DBorderColor(menuPtr->activeBorder)->pixel;
- newGC = Tk_GetGCColor(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
- &gcValues, menuPtr->activeFg,
- Tk_3DBorderColor(menuPtr->activeBorder));
+ 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) {
Tk_FreeGC(menuPtr->display, menuPtr->activeGC);
}
menuPtr->activeGC = newGC;
- gcValues.foreground = menuPtr->indicatorFg->pixel;
- gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel;
- newGC = Tk_GetGCColor(menuPtr->tkwin, GCForeground|GCBackground|GCFont,
- &gcValues, menuPtr->indicatorFg,
- Tk_3DBorderColor(menuPtr->border));
+ 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) {
Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC);
}
@@ -306,9 +316,10 @@ TkMenuConfigureEntryDrawOptions(mePtr, index)
Tk_Font tkfont;
TkMenu *menuPtr = mePtr->menuPtr;
- tkfont = (mePtr->tkfont == NULL) ? menuPtr->tkfont : mePtr->tkfont;
+ tkfont = Tk_GetFontFromObj(menuPtr->tkwin,
+ (mePtr->fontPtr != NULL) ? mePtr->fontPtr : menuPtr->fontPtr);
- if (mePtr->state == tkActiveUid) {
+ if (mePtr->state == ENTRY_ACTIVE) {
if (index != menuPtr->active) {
TkActivateMenuEntry(menuPtr, index);
}
@@ -316,34 +327,26 @@ 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)) {
- XColor *foreground, *background;
-
- background = Tk_3DBorderColor(
- (mePtr->border != NULL)
- ? mePtr->border
- : menuPtr->border);
- foreground = (mePtr->fg != NULL)
- ? mePtr->fg
- : menuPtr->fg;
+ if ((mePtr->fontPtr != NULL)
+ || (mePtr->borderPtr != NULL)
+ || (mePtr->fgPtr != NULL)
+ || (mePtr->activeBorderPtr != NULL)
+ || (mePtr->activeFgPtr != NULL)
+ || (mePtr->indicatorFgPtr != NULL)) {
+ XColor *fg, *bg, *indicatorFg, *activeFg;
+ Tk_3DBorder border, activeBorder;
+
+ fg = Tk_GetColorFromObj(menuPtr->tkwin, (mePtr->fgPtr != NULL)
+ ? mePtr->fgPtr : menuPtr->fgPtr);
- gcValues.foreground = foreground->pixel;
- gcValues.background = background->pixel;
+ gcValues.foreground = fg->pixel;
+ border = Tk_Get3DBorderFromObj(menuPtr->tkwin,
+ (mePtr->borderPtr != NULL) ? mePtr->borderPtr
+ : menuPtr->borderPtr);
+ bg = Tk_3DBorderColor(border);
+ gcValues.background = bg->pixel;
gcValues.font = Tk_FontId(tkfont);
@@ -354,48 +357,43 @@ TkMenuConfigureEntryDrawOptions(mePtr, index)
*/
gcValues.graphics_exposures = False;
- newGC = Tk_GetGCColor(menuPtr->tkwin,
+ newGC = Tk_GetGC(menuPtr->tkwin,
GCForeground|GCBackground|GCFont|GCGraphicsExposures,
- &gcValues, foreground, background);
-
- if (mePtr->indicatorFg != NULL) {
- foreground = mePtr->indicatorFg;
- gcValues.foreground = foreground->pixel;
- } else if (menuPtr->indicatorFg != NULL) {
- foreground = menuPtr->indicatorFg;
- gcValues.foreground = foreground->pixel;
- }
- newIndicatorGC = Tk_GetGCColor(menuPtr->tkwin,
+ &gcValues);
+ 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, foreground, background);
-
- if ((menuPtr->disabledFg != NULL) || (mePtr->image != NULL)) {
- foreground = menuPtr->disabledFg;
- gcValues.foreground = foreground->pixel;
+ &gcValues);
+ if ((menuPtr->disabledFgPtr != NULL) || (mePtr->image != NULL)) {
+ fg = Tk_GetColorFromObj(menuPtr->tkwin,
+ menuPtr->disabledFgPtr);
+ gcValues.foreground = fg->pixel;
mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures;
} else {
- foreground = background;
- background = NULL;
+ fg = bg;
gcValues.foreground = gcValues.background;
gcValues.fill_style = FillStippled;
gcValues.stipple = menuPtr->gray;
mask = GCForeground|GCFillStyle|GCStipple;
}
- newDisabledGC = Tk_GetGCColor(menuPtr->tkwin, mask, &gcValues,
- foreground, background);
-
- foreground = (mePtr->activeFg != NULL)
- ? mePtr->activeFg
- : menuPtr->activeFg;
- gcValues.foreground = foreground->pixel;
- background = Tk_3DBorderColor(
- (mePtr->activeBorder != NULL)
- ? mePtr->activeBorder
- : menuPtr->activeBorder);
- gcValues.background = background->pixel;
- newActiveGC = Tk_GetGCColor(menuPtr->tkwin,
+ newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues);
+
+ 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;
+ bg = Tk_3DBorderColor(activeBorder);
+ gcValues.background = bg->pixel;
+ newActiveGC = Tk_GetGC(menuPtr->tkwin,
GCForeground|GCBackground|GCFont|GCGraphicsExposures,
- &gcValues, foreground, background);
+ &gcValues);
} else {
newGC = None;
newActiveGC = None;
@@ -496,7 +494,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;
@@ -637,21 +635,30 @@ 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;
+ 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);
@@ -661,7 +668,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.
@@ -681,22 +689,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)
+ if ((index > 0) && (menuPtr->menuType != MENUBAR)
&& mePtr->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);
}
}
@@ -705,28 +713,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);
}
/*
@@ -760,11 +769,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);
}
@@ -774,7 +784,7 @@ TkMenuEventProc(clientData, eventPtr)
if (menuPtr->menuFlags & RESIZE_PENDING) {
Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr);
}
- TkDestroyMenu(menuPtr);
+ Tcl_EventuallyFree((ClientData) menuPtr, TCL_DYNAMIC);
}
}
@@ -942,7 +952,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) {
@@ -950,6 +959,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
@@ -969,17 +980,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
@@ -988,10 +997,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;
}
@@ -1030,10 +1042,16 @@ 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/tk/generic/tkMenubutton.c b/tk/generic/tkMenubutton.c
index f7f9c6cb7c1..059499a7d24 100644
--- a/tk/generic/tkMenubutton.c
+++ b/tk/generic/tkMenubutton.c
@@ -18,117 +18,140 @@
#include "default.h"
/*
- * Uids internal to menubuttons.
+ * The following table defines the legal values for the -direction
+ * option. It is used together with the "enum direction" declaration
+ * in tkMenubutton.h.
*/
-static Tk_Uid aboveUid = NULL;
-static Tk_Uid belowUid = NULL;
-static Tk_Uid leftUid = NULL;
-static Tk_Uid rightUid = NULL;
-static Tk_Uid flushUid = NULL;
+static char *directionStrings[] = {
+ "above", "below", "flush", "left", "right", (char *) NULL
+};
+
+/*
+ * The following table defines the legal values for the -state option.
+ * It is used together with the "enum state" declaration in tkMenubutton.h.
+ */
+
+static char *stateStrings[] = {
+ "active", "disabled", "normal", (char *) NULL
+};
/*
* Information used for parsing configuration specs:
*/
-static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_MENUBUTTON_ACTIVE_BG_COLOR, Tk_Offset(TkMenuButton, activeBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_MENUBUTTON_ACTIVE_BG_MONO, Tk_Offset(TkMenuButton, activeBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_MENUBUTTON_ACTIVE_FG_COLOR, Tk_Offset(TkMenuButton, activeFg),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-activeforeground", "activeForeground", "Background",
- DEF_MENUBUTTON_ACTIVE_FG_MONO, Tk_Offset(TkMenuButton, activeFg),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor",
- DEF_MENUBUTTON_ANCHOR, Tk_Offset(TkMenuButton, anchor), 0},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_MENUBUTTON_BG_COLOR, Tk_Offset(TkMenuButton, normalBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_MENUBUTTON_BG_MONO, Tk_Offset(TkMenuButton, normalBorder),
- 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_BITMAP, "-bitmap", "bitmap", "Bitmap",
- DEF_MENUBUTTON_BITMAP, Tk_Offset(TkMenuButton, bitmap),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_MENUBUTTON_BORDER_WIDTH, Tk_Offset(TkMenuButton, borderWidth), 0},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_MENUBUTTON_CURSOR, Tk_Offset(TkMenuButton, cursor),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-direction", "direction", "Direction",
- DEF_MENUBUTTON_DIRECTION, Tk_Offset(TkMenuButton, direction),
- 0},
- {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
+static Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_MENUBUTTON_ACTIVE_BG_COLOR, -1,
+ Tk_Offset(TkMenuButton, activeBorder), 0,
+ (ClientData) DEF_MENUBUTTON_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-activeforeground", "activeForeground", "Background",
+ DEF_MENUBUTTON_ACTIVE_FG_COLOR, -1,
+ Tk_Offset(TkMenuButton, activeFg),
+ 0, (ClientData) DEF_MENUBUTTON_ACTIVE_FG_MONO, 0},
+ {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor",
+ DEF_MENUBUTTON_ANCHOR, -1,
+ Tk_Offset(TkMenuButton, anchor), 0, 0, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_MENUBUTTON_BG_COLOR, -1, Tk_Offset(TkMenuButton, normalBorder),
+ 0, (ClientData) DEF_MENUBUTTON_BG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
+ {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap",
+ DEF_MENUBUTTON_BITMAP, -1, Tk_Offset(TkMenuButton, bitmap),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_MENUBUTTON_BORDER_WIDTH, -1,
+ Tk_Offset(TkMenuButton, borderWidth), 0, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_MENUBUTTON_CURSOR, -1, Tk_Offset(TkMenuButton, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-direction", "direction", "Direction",
+ DEF_MENUBUTTON_DIRECTION, -1, Tk_Offset(TkMenuButton, direction),
+ 0, (ClientData) directionStrings, 0},
+ {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
"DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_COLOR,
- Tk_Offset(TkMenuButton, disabledFg),
- TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-disabledforeground", "disabledForeground",
- "DisabledForeground", DEF_MENUBUTTON_DISABLED_FG_MONO,
- Tk_Offset(TkMenuButton, 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_MENUBUTTON_FONT, Tk_Offset(TkMenuButton, tkfont), 0},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_MENUBUTTON_FG, Tk_Offset(TkMenuButton, normalFg), 0},
- {TK_CONFIG_STRING, "-height", "height", "Height",
- DEF_MENUBUTTON_HEIGHT, Tk_Offset(TkMenuButton, heightString), 0},
- {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG,
- Tk_Offset(TkMenuButton, highlightBgColorPtr), 0},
- {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_MENUBUTTON_HIGHLIGHT, Tk_Offset(TkMenuButton, highlightColorPtr),
- 0},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
+ -1, Tk_Offset(TkMenuButton, disabledFg), TK_OPTION_NULL_OK,
+ (ClientData) DEF_MENUBUTTON_DISABLED_FG_MONO, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_MENUBUTTON_FONT, -1, Tk_Offset(TkMenuButton, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_MENUBUTTON_FG, -1, Tk_Offset(TkMenuButton, normalFg), 0, 0, 0},
+ {TK_OPTION_STRING, "-height", "height", "Height",
+ DEF_MENUBUTTON_HEIGHT, -1, Tk_Offset(TkMenuButton, heightString),
+ 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkMenuButton, highlightBgColorPtr), 0, 0, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_MENUBUTTON_HIGHLIGHT, -1,
+ Tk_Offset(TkMenuButton, highlightColorPtr), 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
"HighlightThickness", DEF_MENUBUTTON_HIGHLIGHT_WIDTH,
- Tk_Offset(TkMenuButton, highlightWidth), 0},
- {TK_CONFIG_STRING, "-image", "image", "Image",
- DEF_MENUBUTTON_IMAGE, Tk_Offset(TkMenuButton, imageString),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
- DEF_MENUBUTTON_INDICATOR, Tk_Offset(TkMenuButton, indicatorOn), 0},
- {TK_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
- DEF_MENUBUTTON_JUSTIFY, Tk_Offset(TkMenuButton, justify), 0},
- {TK_CONFIG_STRING, "-menu", "menu", "Menu",
- DEF_MENUBUTTON_MENU, Tk_Offset(TkMenuButton, menuName),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
- DEF_MENUBUTTON_PADX, Tk_Offset(TkMenuButton, padX), 0},
- {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
- DEF_MENUBUTTON_PADY, Tk_Offset(TkMenuButton, padY), 0},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_MENUBUTTON_RELIEF, Tk_Offset(TkMenuButton, relief), 0},
- {TK_CONFIG_UID, "-state", "state", "State",
- DEF_MENUBUTTON_STATE, Tk_Offset(TkMenuButton, state), 0},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_MENUBUTTON_TAKE_FOCUS, Tk_Offset(TkMenuButton, takeFocus),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_STRING, "-text", "text", "Text",
- DEF_MENUBUTTON_TEXT, Tk_Offset(TkMenuButton, text), 0},
- {TK_CONFIG_STRING, "-textvariable", "textVariable", "Variable",
- DEF_MENUBUTTON_TEXT_VARIABLE, Tk_Offset(TkMenuButton, textVarName),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_INT, "-underline", "underline", "Underline",
- DEF_MENUBUTTON_UNDERLINE, Tk_Offset(TkMenuButton, underline), 0},
- {TK_CONFIG_STRING, "-width", "width", "Width",
- DEF_MENUBUTTON_WIDTH, Tk_Offset(TkMenuButton, widthString), 0},
- {TK_CONFIG_PIXELS, "-wraplength", "wrapLength", "WrapLength",
- DEF_MENUBUTTON_WRAP_LENGTH, Tk_Offset(TkMenuButton, wrapLength), 0},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ -1, Tk_Offset(TkMenuButton, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-image", "image", "Image",
+ DEF_MENUBUTTON_IMAGE, -1, Tk_Offset(TkMenuButton, imageString),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-indicatoron", "indicatorOn", "IndicatorOn",
+ DEF_MENUBUTTON_INDICATOR, -1, Tk_Offset(TkMenuButton, indicatorOn),
+ 0, 0, 0},
+ {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_BUTTON_JUSTIFY, -1, Tk_Offset(TkMenuButton, justify), 0, 0, 0},
+ {TK_OPTION_STRING, "-menu", "menu", "Menu",
+ DEF_MENUBUTTON_MENU, -1, Tk_Offset(TkMenuButton, menuName),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
+ DEF_MENUBUTTON_PADX, -1, Tk_Offset(TkMenuButton, padX),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
+ DEF_MENUBUTTON_PADY, -1, Tk_Offset(TkMenuButton, padY),
+ 0, 0, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief),
+ 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state),
+ 0, (ClientData) stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_MENUBUTTON_TAKE_FOCUS, -1,
+ Tk_Offset(TkMenuButton, takeFocus), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_STRING, "-text", "text", "Text",
+ DEF_MENUBUTTON_TEXT, -1, Tk_Offset(TkMenuButton, text), 0, 0, 0},
+ {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
+ DEF_MENUBUTTON_TEXT_VARIABLE, -1,
+ Tk_Offset(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-underline", "underline", "Underline",
+ DEF_MENUBUTTON_UNDERLINE, -1, Tk_Offset(TkMenuButton, underline),
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-width", "width", "Width",
+ DEF_MENUBUTTON_WIDTH, -1, Tk_Offset(TkMenuButton, widthString),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength",
+ DEF_MENUBUTTON_WRAP_LENGTH, -1, Tk_Offset(TkMenuButton, wrapLength),
+ 0, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
/*
+ * The following tables define the menubutton widget commands and map the
+ * indexes into the string tables into a single enumerated type used
+ * to dispatch the scale widget command.
+ */
+
+static char *commandNames[] = {
+ "cget", "configure", (char *) NULL
+};
+
+enum command {
+ COMMAND_CGET, COMMAND_CONFIGURE
+};
+
+/*
* Forward declarations for procedures defined later in this file:
*/
@@ -142,17 +165,18 @@ static void MenuButtonImageProc _ANSI_ARGS_((ClientData clientData,
static char * MenuButtonTextVarProc _ANSI_ARGS_((
ClientData clientData, Tcl_Interp *interp,
char *name1, char *name2, int flags));
-static int MenuButtonWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+static int MenuButtonWidgetObjCmd _ANSI_ARGS_((
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[]));
static int ConfigureMenuButton _ANSI_ARGS_((Tcl_Interp *interp,
- TkMenuButton *mbPtr, int argc, char **argv,
- int flags));
+ TkMenuButton *mbPtr, int objc,
+ Tcl_Obj *CONST objv[]));
static void DestroyMenuButton _ANSI_ARGS_((char *memPtr));
/*
*--------------------------------------------------------------
*
- * Tk_MenubuttonCmd --
+ * Tk_MenubuttonObjCmd --
*
* This procedure is invoked to process the "button", "label",
* "radiobutton", and "checkbutton" Tcl commands. See the
@@ -168,20 +192,38 @@ static void DestroyMenuButton _ANSI_ARGS_((char *memPtr));
*/
int
-Tk_MenubuttonCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_MenubuttonObjCmd(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 objects. */
{
register TkMenuButton *mbPtr;
- Tk_Window tkwin = (Tk_Window) clientData;
- Tk_Window new;
+ Tk_OptionTable optionTable;
+ Tk_Window tkwin;
+
+ optionTable = (Tk_OptionTable) clientData;
+ if (optionTable == NULL) {
+ Tcl_CmdInfo info;
+ char *name;
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " pathName ?options?\"", (char *) NULL);
+ /*
+ * 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.
+ */
+
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+ 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;
}
@@ -189,25 +231,28 @@ Tk_MenubuttonCmd(clientData, interp, argc, argv)
* 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, "Menubutton");
- mbPtr = TkpCreateMenuButton(new);
+ Tk_SetClass(tkwin, "Menubutton");
+ mbPtr = TkpCreateMenuButton(tkwin);
- TkSetClassProcs(new, &tkpMenubuttonClass, (ClientData) mbPtr);
+ TkSetClassProcs(tkwin, &tkpMenubuttonClass, (ClientData) mbPtr);
/*
* Initialize the data structure for the button.
*/
- mbPtr->tkwin = new;
- mbPtr->display = Tk_Display (new);
+ mbPtr->tkwin = tkwin;
+ mbPtr->display = Tk_Display (tkwin);
mbPtr->interp = interp;
- mbPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(mbPtr->tkwin),
- MenuButtonWidgetCmd, (ClientData) mbPtr, MenuButtonCmdDeletedProc);
+ mbPtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd,
+ (ClientData) mbPtr, MenuButtonCmdDeletedProc);
+ mbPtr->optionTable = optionTable;
mbPtr->menuName = NULL;
mbPtr->text = NULL;
mbPtr->underline = -1;
@@ -215,7 +260,7 @@ Tk_MenubuttonCmd(clientData, interp, argc, argv)
mbPtr->bitmap = None;
mbPtr->imageString = NULL;
mbPtr->image = NULL;
- mbPtr->state = tkNormalUid;
+ mbPtr->state = STATE_NORMAL;
mbPtr->normalBorder = NULL;
mbPtr->activeBorder = NULL;
mbPtr->borderWidth = 0;
@@ -247,34 +292,35 @@ Tk_MenubuttonCmd(clientData, interp, argc, argv)
mbPtr->indicatorOn = 0;
mbPtr->indicatorWidth = 0;
mbPtr->indicatorHeight = 0;
+ mbPtr->direction = DIRECTION_FLUSH;
mbPtr->cursor = None;
mbPtr->takeFocus = NULL;
mbPtr->flags = 0;
- if (aboveUid == NULL) {
- aboveUid = Tk_GetUid("above");
- belowUid = Tk_GetUid("below");
- leftUid = Tk_GetUid("left");
- rightUid = Tk_GetUid("right");
- flushUid = Tk_GetUid("flush");
- }
- mbPtr->direction = flushUid;
Tk_CreateEventHandler(mbPtr->tkwin,
ExposureMask|StructureNotifyMask|FocusChangeMask,
MenuButtonEventProc, (ClientData) mbPtr);
- if (ConfigureMenuButton(interp, mbPtr, argc-2, argv+2, 0) != TCL_OK) {
+
+ if (Tk_InitOptions(interp, (char *) mbPtr, optionTable, tkwin)
+ != TCL_OK) {
Tk_DestroyWindow(mbPtr->tkwin);
return TCL_ERROR;
}
- interp->result = Tk_PathName(mbPtr->tkwin);
+ if (ConfigureMenuButton(interp, mbPtr, objc-2, objv+2) != TCL_OK) {
+ Tk_DestroyWindow(mbPtr->tkwin);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(mbPtr->tkwin),
+ -1);
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
- * MenuButtonWidgetCmd --
+ * MenuButtonWidgetObjCmd --
*
* This procedure is invoked to process the Tcl command
* that corresponds to a widget managed by this module.
@@ -290,56 +336,68 @@ Tk_MenubuttonCmd(clientData, interp, argc, argv)
*/
static int
-MenuButtonWidgetCmd(clientData, interp, argc, argv)
+MenuButtonWidgetObjCmd(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 objects. */
{
register TkMenuButton *mbPtr = (TkMenuButton *) clientData;
- int result;
- size_t length;
- int c;
+ int result, index;
+ Tcl_Obj *objPtr;
- 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;
}
+ result = Tcl_GetIndexFromObj(interp, objv[1],
+ commandNames, "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
Tcl_Preserve((ClientData) mbPtr);
- 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);
- result = TCL_ERROR;
- } else {
- result = Tk_ConfigureValue(interp, mbPtr->tkwin, configSpecs,
- (char *) mbPtr, argv[2], 0);
+
+ switch (index) {
+ case COMMAND_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
+ goto error;
+ }
+
+ objPtr = Tk_GetOptionValue(interp, (char *) mbPtr,
+ mbPtr->optionTable, objv[2], mbPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ break;
}
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 2)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, mbPtr->tkwin, configSpecs,
- (char *) mbPtr, (char *) NULL, 0);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, mbPtr->tkwin, configSpecs,
- (char *) mbPtr, argv[2], 0);
- } else {
- result = ConfigureMenuButton(interp, mbPtr, argc-2, argv+2,
- TK_CONFIG_ARGV_ONLY);
+
+ case COMMAND_CONFIGURE: {
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) mbPtr,
+ mbPtr->optionTable,
+ (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
+ mbPtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ } else {
+ result = ConfigureMenuButton(interp, mbPtr, objc-2,
+ objv+2);
+ }
+ break;
}
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be cget or configure",
- (char *) NULL);
- result = TCL_ERROR;
}
Tcl_Release((ClientData) mbPtr);
return result;
+
+ error:
+ Tcl_Release((ClientData) mbPtr);
+ return TCL_ERROR;
}
/*
@@ -348,9 +406,9 @@ MenuButtonWidgetCmd(clientData, interp, argc, argv)
* DestroyMenuButton --
*
* This procedure is invoked to recycle all of the resources
- * associated with a button widget. It is invoked as a
+ * associated with a menubutton widget. It is invoked as a
* when-idle handler in order to make sure that there is no
- * other use of the button pending at the time of the deletion.
+ * other use of the menubutton pending at the time of the deletion.
*
* Results:
* None.
@@ -366,6 +424,11 @@ DestroyMenuButton(memPtr)
char *memPtr; /* Info about button widget. */
{
register TkMenuButton *mbPtr = (TkMenuButton *) memPtr;
+ TkpDestroyMenuButton(mbPtr);
+
+ if (mbPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayMenuButton, (ClientData) mbPtr);
+ }
/*
* Free up all the stuff that requires special handling, then
@@ -373,6 +436,7 @@ DestroyMenuButton(memPtr)
* stuff.
*/
+ Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd);
if (mbPtr->textVarName != NULL) {
Tcl_UntraceVar(mbPtr->interp, mbPtr->textVarName,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
@@ -387,15 +451,19 @@ DestroyMenuButton(memPtr)
if (mbPtr->activeTextGC != None) {
Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
}
+ if (mbPtr->disabledGC != None) {
+ Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
+ }
if (mbPtr->gray != None) {
Tk_FreeBitmap(mbPtr->display, mbPtr->gray);
}
- if (mbPtr->disabledGC != None) {
- Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
+ if (mbPtr->textLayout != NULL) {
+ Tk_FreeTextLayout(mbPtr->textLayout);
}
- Tk_FreeTextLayout(mbPtr->textLayout);
- Tk_FreeOptions(configSpecs, (char *) mbPtr, mbPtr->display, 0);
- ckfree((char *) mbPtr);
+ Tk_FreeConfigOptions((char *) mbPtr, mbPtr->optionTable,
+ mbPtr->tkwin);
+ mbPtr->tkwin = NULL;
+ Tcl_EventuallyFree((ClientData) mbPtr, TCL_DYNAMIC);
}
/*
@@ -409,7 +477,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,
@@ -420,147 +488,174 @@ DestroyMenuButton(memPtr)
*/
static int
-ConfigureMenuButton(interp, mbPtr, argc, argv, flags)
+ConfigureMenuButton(interp, mbPtr, objc, objv)
Tcl_Interp *interp; /* Used for error reporting. */
- register TkMenuButton *mbPtr; /* Information about widget; may or may
- * not already have values for some fields. */
- int argc; /* Number of valid entries in argv. */
- char **argv; /* Arguments. */
- int flags; /* Flags to pass to Tk_ConfigureWidget. */
+ register TkMenuButton *mbPtr;
+ /* Information about widget; may or may
+ * not already have values for some
+ * fields. */
+ int objc; /* Number of valid entries in objv. */
+ Tcl_Obj *CONST objv[]; /* Arguments. */
{
- int result;
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *errorResult = NULL;
+ int error;
Tk_Image image;
/*
- * Eliminate any existing trace on variables monitored by the menubutton.
+ * Eliminate any existing trace on variables monitored by the
+ * menubutton.
*/
if (mbPtr->textVarName != NULL) {
- Tcl_UntraceVar(interp, mbPtr->textVarName,
+ Tcl_UntraceVar(interp, mbPtr->textVarName,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
MenuButtonTextVarProc, (ClientData) mbPtr);
}
- result = Tk_ConfigureWidget(interp, mbPtr->tkwin, configSpecs,
- argc, argv, (char *) mbPtr, flags);
- if (result != 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 ((mbPtr->state == tkActiveUid) && !Tk_StrictMotif(mbPtr->tkwin)) {
- Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);
- } else {
- Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);
- if ((mbPtr->state != tkNormalUid) && (mbPtr->state != tkActiveUid)
- && (mbPtr->state != tkDisabledUid)) {
- Tcl_AppendResult(interp, "bad state value \"", mbPtr->state,
- "\": must be normal, active, or disabled", (char *) NULL);
- mbPtr->state = tkNormalUid;
- return TCL_ERROR;
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
+
+ if (Tk_SetOptions(interp, (char *) mbPtr,
+ mbPtr->optionTable, objc, objv,
+ mbPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
+
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
}
- }
- if ((mbPtr->direction != aboveUid) && (mbPtr->direction != belowUid)
- && (mbPtr->direction != leftUid) && (mbPtr->direction != rightUid)
- && (mbPtr->direction != flushUid)) {
- Tcl_AppendResult(interp, "bad direction value \"", mbPtr->direction,
- "\": must be above, below, left, right, or flush",
- (char *) NULL);
- mbPtr->direction = belowUid;
- return TCL_ERROR;
- }
-
- if (mbPtr->highlightWidth < 0) {
- mbPtr->highlightWidth = 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_SetOptions.
+ */
- if (mbPtr->padX < 0) {
- mbPtr->padX = 0;
- }
- if (mbPtr->padY < 0) {
- mbPtr->padY = 0;
- }
+ if ((mbPtr->state == STATE_ACTIVE)
+ && !Tk_StrictMotif(mbPtr->tkwin)) {
+ Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->activeBorder);
+ } else {
+ Tk_SetBackgroundFromBorder(mbPtr->tkwin, mbPtr->normalBorder);
+ }
- /*
- * Get the image for the widget, if there is one. Allocate the
- * new image before freeing the old one, so that the reference
- * count doesn't go to zero and cause image data to be discarded.
- */
+ if (mbPtr->highlightWidth < 0) {
+ mbPtr->highlightWidth = 0;
+ }
- if (mbPtr->imageString != NULL) {
- image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,
- mbPtr->imageString, MenuButtonImageProc, (ClientData) mbPtr);
- if (image == NULL) {
- return TCL_ERROR;
+ if (mbPtr->padX < 0) {
+ mbPtr->padX = 0;
+ }
+ if (mbPtr->padY < 0) {
+ mbPtr->padY = 0;
}
- } else {
- image = NULL;
- }
- if (mbPtr->image != NULL) {
- Tk_FreeImage(mbPtr->image);
- }
- mbPtr->image = image;
- if ((mbPtr->image == NULL) && (mbPtr->bitmap == None)
- && (mbPtr->textVarName != NULL)) {
/*
- * The menubutton displays a variable. Set up a trace to watch
- * for any changes in it.
+ * Get the image for the widget, if there is one. Allocate the
+ * new image before freeing the old one, so that the reference
+ * count doesn't go to zero and cause image data to be discarded.
*/
- char *value;
+ if (mbPtr->imageString != NULL) {
+ image = Tk_GetImage(mbPtr->interp, mbPtr->tkwin,
+ mbPtr->imageString, MenuButtonImageProc,
+ (ClientData) mbPtr);
+ if (image == NULL) {
+ return TCL_ERROR;
+ }
+ } else {
+ image = NULL;
+ }
+ if (mbPtr->image != NULL) {
+ Tk_FreeImage(mbPtr->image);
+ }
+ mbPtr->image = image;
- value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);
- if (value == NULL) {
- Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,
- TCL_GLOBAL_ONLY);
+ /*
+ * Recompute the geometry for the button.
+ */
+
+ if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {
+ if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString,
+ &mbPtr->width) != TCL_OK) {
+ widthError:
+ Tcl_AddErrorInfo(interp, "\n (processing -width option)");
+ continue;
+ }
+ if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString,
+ &mbPtr->height) != TCL_OK) {
+ heightError:
+ Tcl_AddErrorInfo(interp, "\n (processing -height option)");
+ continue;
+ }
} else {
- if (mbPtr->text != NULL) {
- ckfree(mbPtr->text);
+ if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width)
+ != TCL_OK) {
+ goto widthError;
+ }
+ if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height)
+ != TCL_OK) {
+ goto heightError;
}
- mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
- strcpy(mbPtr->text, value);
}
- Tcl_TraceVar(interp, mbPtr->textVarName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- MenuButtonTextVarProc, (ClientData) mbPtr);
+ break;
}
- /*
- * Recompute the geometry for the button.
- */
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
+ }
- if ((mbPtr->bitmap != None) || (mbPtr->image != NULL)) {
- if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->widthString,
- &mbPtr->width) != TCL_OK) {
- widthError:
- Tcl_AddErrorInfo(interp, "\n (processing -width option)");
- return TCL_ERROR;
- }
- if (Tk_GetPixels(interp, mbPtr->tkwin, mbPtr->heightString,
- &mbPtr->height) != TCL_OK) {
- heightError:
- Tcl_AddErrorInfo(interp, "\n (processing -height option)");
- return TCL_ERROR;
- }
- } else {
- if (Tcl_GetInt(interp, mbPtr->widthString, &mbPtr->width)
- != TCL_OK) {
- goto widthError;
- }
- if (Tcl_GetInt(interp, mbPtr->heightString, &mbPtr->height)
- != TCL_OK) {
- goto heightError;
- }
+ if ((mbPtr->image == NULL) && (mbPtr->bitmap == None)
+ && (mbPtr->textVarName != NULL)) {
+
+ /*
+ * The menubutton displays the value of a variable.
+ * Set up a trace to watch for any changes in it, create
+ * the variable if it doesn't exist, and fetch its
+ * current value.
+ */
+
+ char *value;
+
+ value = Tcl_GetVar(interp, mbPtr->textVarName, TCL_GLOBAL_ONLY);
+ if (value == NULL) {
+ Tcl_SetVar(interp, mbPtr->textVarName, mbPtr->text,
+ TCL_GLOBAL_ONLY);
+ } else {
+ if (mbPtr->text != NULL) {
+ ckfree(mbPtr->text);
+ }
+ mbPtr->text = (char *) ckalloc((unsigned) (strlen(value) + 1));
+ strcpy(mbPtr->text, value);
+ }
+ Tcl_TraceVar(interp, mbPtr->textVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ MenuButtonTextVarProc, (ClientData) mbPtr);
}
+
TkMenuButtonWorldChanged((ClientData) mbPtr);
- return TCL_OK;
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
}
/*
@@ -605,8 +700,7 @@ TkMenuButtonWorldChanged(instanceData)
gcValues.graphics_exposures = False;
mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
- gc = Tk_GetGCColor(mbPtr->tkwin, mask, &gcValues, mbPtr->normalFg,
- Tk_3DBorderColor(mbPtr->normalBorder));
+ gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
if (mbPtr->normalTextGC != None) {
Tk_FreeGC(mbPtr->display, mbPtr->normalTextGC);
}
@@ -616,8 +710,7 @@ TkMenuButtonWorldChanged(instanceData)
gcValues.foreground = mbPtr->activeFg->pixel;
gcValues.background = Tk_3DBorderColor(mbPtr->activeBorder)->pixel;
mask = GCForeground | GCBackground | GCFont;
- gc = Tk_GetGCColor(mbPtr->tkwin, mask, &gcValues, mbPtr->activeFg,
- Tk_3DBorderColor(mbPtr->activeBorder));
+ gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
if (mbPtr->activeTextGC != None) {
Tk_FreeGC(mbPtr->display, mbPtr->activeTextGC);
}
@@ -627,11 +720,11 @@ TkMenuButtonWorldChanged(instanceData)
background = Tk_3DBorderColor(mbPtr->normalBorder);
gcValues.background = background->pixel;
if ((mbPtr->disabledFg != NULL) && (mbPtr->imageString == NULL)) {
- foreground = mbPtr->disabledFg;
+ foreground = mbPtr->disabledFg;
gcValues.foreground = foreground->pixel;
mask = GCForeground | GCBackground | GCFont;
} else {
- foreground = background;
+ foreground = background;
background = NULL;
gcValues.foreground = gcValues.background;
mask = GCForeground;
@@ -645,7 +738,7 @@ TkMenuButtonWorldChanged(instanceData)
mask |= GCFillStyle | GCStipple;
}
}
- gc = Tk_GetGCColor(mbPtr->tkwin, mask, &gcValues, foreground, background);
+ gc = Tk_GetGC(mbPtr->tkwin, mask, &gcValues);
if (mbPtr->disabledGC != None) {
Tk_FreeGC(mbPtr->display, mbPtr->disabledGC);
}
@@ -697,15 +790,7 @@ MenuButtonEventProc(clientData, eventPtr)
goto redraw;
} else if (eventPtr->type == DestroyNotify) {
- TkpDestroyMenuButton(mbPtr);
- if (mbPtr->tkwin != NULL) {
- mbPtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(mbPtr->interp, mbPtr->widgetCmd);
- }
- if (mbPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(TkpDisplayMenuButton, (ClientData) mbPtr);
- }
- Tcl_EventuallyFree((ClientData) mbPtr, DestroyMenuButton);
+ DestroyMenuButton((char *) mbPtr);
} else if (eventPtr->type == FocusIn) {
if (eventPtr->xfocus.detail != NotifyInferior) {
mbPtr->flags |= GOT_FOCUS;
@@ -763,7 +848,6 @@ MenuButtonCmdDeletedProc(clientData)
*/
if (tkwin != NULL) {
- mbPtr->tkwin = NULL;
Tk_DestroyWindow(tkwin);
}
}
@@ -870,3 +954,4 @@ MenuButtonImageProc(clientData, x, y, width, height, imgWidth, imgHeight)
}
}
}
+
diff --git a/tk/generic/tkMenubutton.h b/tk/generic/tkMenubutton.h
index b2382c6bde6..2bca6431e73 100644
--- a/tk/generic/tkMenubutton.h
+++ b/tk/generic/tkMenubutton.h
@@ -25,6 +25,23 @@
#endif
/*
+ * Legal values for the "orient" field of TkMenubutton records.
+ */
+
+enum direction {
+ DIRECTION_ABOVE, DIRECTION_BELOW, DIRECTION_FLUSH,
+ DIRECTION_LEFT, DIRECTION_RIGHT
+};
+
+/*
+ * Legal values for the "state" field of TkMenubutton records.
+ */
+
+enum state {
+ STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL
+};
+
+/*
* A data structure of the following type is kept for each
* widget managed by this file:
*/
@@ -39,6 +56,8 @@ typedef struct {
* freed up even after tkwin has gone away. */
Tcl_Interp *interp; /* Interpreter associated with menubutton. */
Tcl_Command widgetCmd; /* Token for menubutton's widget command. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
char *menuName; /* Name of menu associated with widget.
* Malloc-ed. */
@@ -65,7 +84,7 @@ typedef struct {
* Information used when displaying widget:
*/
- Tk_Uid state; /* State of button for display purposes:
+ enum state state; /* State of button for display purposes:
* normal, active, or disabled. */
Tk_3DBorder normalBorder; /* Structure used to draw 3-D
* border and background when window
@@ -143,7 +162,7 @@ typedef struct {
* Miscellaneous information:
*/
- Tk_Uid direction; /* Direction for where to pop the menu.
+ enum direction direction; /* Direction for where to pop the menu.
* Valid directions are "above", "below",
* "left", "right", and "flush". "flush"
* means that the upper left corner of the
@@ -213,3 +232,4 @@ EXTERN void TkMenuButtonWorldChanged _ANSI_ARGS_((
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKMENUBUTTON */
+
diff --git a/tk/generic/tkMessage.c b/tk/generic/tkMessage.c
index e1313bb6bff..eabffe0197c 100644
--- a/tk/generic/tkMessage.c
+++ b/tk/generic/tkMessage.c
@@ -6,7 +6,7 @@
* 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.
@@ -40,7 +40,7 @@ typedef struct {
char *string; /* String displayed in message. */
int numChars; /* Number of characters in string, not
- * including terminating NULL character. */
+ * including terminating NULL. */
char *textVarName; /* Name of variable (malloc'ed) or NULL.
* If non-NULL, message displays the contents
* of this variable. */
@@ -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,
@@ -465,9 +465,7 @@ ConfigureMessage(interp, msgPtr, argc, argv, flags)
* that couldn't be specified to Tk_ConfigureWidget.
*/
- msgPtr->numChars = strlen(msgPtr->string);
-
- Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);
+ msgPtr->numChars = Tcl_NumUtfChars(msgPtr->string, -1);
if (msgPtr->highlightWidth < 0) {
msgPtr->highlightWidth = 0;
@@ -500,16 +498,19 @@ MessageWorldChanged(instanceData)
ClientData instanceData; /* Information about widget. */
{
XGCValues gcValues;
- GC gc;
+ GC gc = None;
Tk_FontMetrics fm;
Message *msgPtr;
msgPtr = (Message *) instanceData;
+ if (msgPtr->border != NULL) {
+ Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);
+ }
+
gcValues.font = Tk_FontId(msgPtr->tkfont);
gcValues.foreground = msgPtr->fgColorPtr->pixel;
- gc = Tk_GetGCColor(msgPtr->tkwin, GCForeground | GCFont, &gcValues,
- msgPtr->fgColorPtr, NULL);
+ gc = Tk_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);
if (msgPtr->textGC != None) {
Tk_FreeGC(msgPtr->display, msgPtr->textGC);
}
@@ -645,13 +646,23 @@ DisplayMessage(clientData)
register Message *msgPtr = (Message *) clientData;
register Tk_Window tkwin = msgPtr->tkwin;
int x, y;
+ int borderWidth = msgPtr->highlightWidth;
msgPtr->flags &= ~REDRAW_PENDING;
if ((msgPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return;
}
- Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border, 0, 0,
- Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+ if (msgPtr->border != NULL) {
+ borderWidth += msgPtr->borderWidth;
+ }
+ if (msgPtr->relief == TK_RELIEF_FLAT) {
+ borderWidth = msgPtr->highlightWidth;
+ }
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,
+ borderWidth, borderWidth,
+ Tk_Width(tkwin) - 2 * borderWidth,
+ Tk_Height(tkwin) - 2 * borderWidth,
+ 0, TK_RELIEF_FLAT);
/*
* Compute starting y-location for message based on message size
@@ -663,7 +674,7 @@ DisplayMessage(clientData)
Tk_DrawTextLayout(Tk_Display(tkwin), Tk_WindowId(tkwin), msgPtr->textGC,
msgPtr->textLayout, x, y, 0, -1);
- if (msgPtr->relief != TK_RELIEF_FLAT) {
+ if (borderWidth > msgPtr->highlightWidth) {
Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), msgPtr->border,
msgPtr->highlightWidth, msgPtr->highlightWidth,
Tk_Width(tkwin) - 2*msgPtr->highlightWidth,
@@ -671,15 +682,17 @@ DisplayMessage(clientData)
msgPtr->borderWidth, msgPtr->relief);
}
if (msgPtr->highlightWidth != 0) {
- GC gc;
+ GC fgGC, bgGC;
+ bgGC = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
if (msgPtr->flags & GOT_FOCUS) {
- gc = Tk_GCForColor(msgPtr->highlightColorPtr, Tk_WindowId(tkwin));
+ fgGC = Tk_GCForColor(msgPtr->highlightColorPtr, Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, fgGC, bgGC, msgPtr->highlightWidth,
+ Tk_WindowId(tkwin));
} else {
- gc = Tk_GCForColor(msgPtr->highlightBgColorPtr, Tk_WindowId(tkwin));
+ TkpDrawHighlightBorder(tkwin, bgGC, bgGC, msgPtr->highlightWidth,
+ Tk_WindowId(tkwin));
}
- Tk_DrawFocusHighlight(tkwin, gc, msgPtr->highlightWidth,
- Tk_WindowId(tkwin));
}
}
@@ -835,8 +848,8 @@ MessageTextVarProc(clientData, interp, name1, name2, flags)
if (msgPtr->string != NULL) {
ckfree(msgPtr->string);
}
- msgPtr->numChars = strlen(value);
- msgPtr->string = (char *) ckalloc((unsigned) (msgPtr->numChars + 1));
+ msgPtr->numChars = Tcl_NumUtfChars(value, -1);
+ msgPtr->string = (char *) ckalloc((unsigned) (strlen(value) + 1));
strcpy(msgPtr->string, value);
ComputeMessageGeometry(msgPtr);
@@ -847,3 +860,4 @@ MessageTextVarProc(clientData, interp, name1, name2, flags)
}
return (char *) NULL;
}
+
diff --git a/tk/generic/tkObj.c b/tk/generic/tkObj.c
new file mode 100644
index 00000000000..071cb383f43
--- /dev/null
+++ b/tk/generic/tkObj.c
@@ -0,0 +1,660 @@
+/*
+ * 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.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#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/tk/generic/tkOldConfig.c b/tk/generic/tkOldConfig.c
new file mode 100644
index 00000000000..18b22e451ee
--- /dev/null
+++ b/tk/generic/tkOldConfig.c
@@ -0,0 +1,1023 @@
+/*
+ * 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.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#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. */
+
+ if (tkwin == NULL) {
+ /*
+ * Either we're not really in Tk, or the main window was destroyed and
+ * we're on our way out of the application
+ */
+ Tcl_AppendResult(interp, "NULL main window", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ 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_Uid structs (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) {
+ char *arg;
+
+ if (flags & TK_CONFIG_OBJS) {
+ arg = Tcl_GetStringFromObj((Tcl_Obj *) *argv, NULL);
+ } else {
+ arg = *argv;
+ }
+ specPtr = FindConfigSpec(interp, specs, arg, needFlags, hateFlags);
+ if (specPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Process the entry.
+ */
+
+ if (argc < 2) {
+ Tcl_AppendResult(interp, "value for \"", arg,
+ "\" missing", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if (flags & TK_CONFIG_OBJS) {
+ arg = Tcl_GetString((Tcl_Obj *) argv[1]);
+ } else {
+ arg = argv[1];
+ }
+ if (DoConfig(interp, tkwin, specPtr, arg, 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 {
+ if (specPtr->defValue != NULL) {
+ value = Tk_GetUid(specPtr->defValue);
+ } else {
+ value = NULL;
+ }
+ 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/tk/generic/tkOption.c b/tk/generic/tkOption.c
index f3807167edb..54e1f27d75e 100644
--- a/tk/generic/tkOption.c
+++ b/tk/generic/tkOption.c
@@ -6,7 +6,7 @@
* 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.
@@ -141,13 +141,6 @@ typedef struct ElArray {
*/
#define NUM_STACKS 8
-static ElArray *stacks[NUM_STACKS];
-static TkWindow *cachedWindow = NULL; /* Lowest-level window currently
- * loaded in stacks at present.
- * NULL means stacks have never
- * been used, or have been
- * invalidated because of a change
- * to the database. */
/*
* One of the following structures is used to keep track of each
@@ -163,33 +156,41 @@ typedef struct StackLevel {
* fields when popping out of a level. */
} StackLevel;
-/*
- * Information about all of the stack levels that are currently
- * active. This array grows dynamically to become as large as needed.
- */
+typedef struct ThreadSpecificData {
+ int initialized; /* 0 means the ThreadSpecific Data structure
+ * for the current thread needs to be
+ * initialized. */
+ ElArray *stacks[NUM_STACKS];
+ TkWindow *cachedWindow;
+ /* Lowest-level window currently
+ * loaded in stacks at present.
+ * NULL means stacks have never
+ * been used, or have been
+ * invalidated because of a change
+ * to the database. */
+ /*
+ * Information about all of the stack levels that are currently
+ * active. This array grows dynamically to become as large as needed.
+ */
-static StackLevel *levels = NULL;
- /* Array describing current stack. */
-static int numLevels = 0; /* Total space allocated. */
-static int curLevel = -1; /* Highest level currently in use. Note:
+ StackLevel *levels; /* Array describing current stack. */
+ int numLevels; /* Total space allocated. */
+ int curLevel; /* Highest level currently in use. Note:
* curLevel is never 0! (I don't remember
* why anymore...) */
+ /*
+ * The variable below is a serial number for all options entered into
+ * the database so far. It increments on each addition to the option
+ * database. It is used in computing option priorities, so that the
+ * most recent entry wins when choosing between options at the same
+ * priority level.
+ */
-/*
- * The variable below is a serial number for all options entered into
- * the database so far. It increments on each addition to the option
- * database. It is used in computing option priorities, so that the
- * most recent entry wins when choosing between options at the same
- * priority level.
- */
-
-static int serial = 0;
-
-/*
- * Special "no match" Element to use as default for searches.
- */
-
-static Element defaultMatch;
+ int serial;
+ Element defaultMatch; /* Special "no match" Element to use as
+ * default for searches.*/
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations for procedures defined in this file:
@@ -248,11 +249,13 @@ Tk_AddOption(tkwin, name, value, priority)
int count, firstField, length;
#define TMP_SIZE 100
char tmp[TMP_SIZE+1];
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (winPtr->mainPtr->optionRootPtr == NULL) {
OptionInit(winPtr->mainPtr);
}
- cachedWindow = NULL; /* Invalidate the cache. */
+ tsdPtr->cachedWindow = NULL; /* Invalidate the cache. */
/*
* Compute the priority for the new element, including both the
@@ -265,8 +268,8 @@ Tk_AddOption(tkwin, name, value, priority)
} else if (priority > TK_MAX_PRIO) {
priority = TK_MAX_PRIO;
}
- newEl.priority = (priority << 24) + serial;
- serial++;
+ newEl.priority = (priority << 24) + tsdPtr->serial;
+ tsdPtr->serial++;
/*
* Parse the option one field at a time.
@@ -396,28 +399,30 @@ Tk_GetOption(tkwin, name, className)
Tk_Uid nameId, classId;
register Element *elPtr, *bestPtr;
register int count;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Note: no need to call OptionInit here: it will be done by
* the SetupStacks call below (squeeze out those nanoseconds).
*/
- if (tkwin != (Tk_Window) cachedWindow) {
+ if (tkwin != (Tk_Window) tsdPtr->cachedWindow) {
SetupStacks((TkWindow *) tkwin, 1);
}
nameId = Tk_GetUid(name);
- bestPtr = &defaultMatch;
- for (elPtr = stacks[EXACT_LEAF_NAME]->els,
- count = stacks[EXACT_LEAF_NAME]->numUsed; count > 0;
+ bestPtr = &tsdPtr->defaultMatch;
+ for (elPtr = tsdPtr->stacks[EXACT_LEAF_NAME]->els,
+ count = tsdPtr->stacks[EXACT_LEAF_NAME]->numUsed; count > 0;
elPtr++, count--) {
if ((elPtr->nameUid == nameId)
&& (elPtr->priority > bestPtr->priority)) {
bestPtr = elPtr;
}
}
- for (elPtr = stacks[WILDCARD_LEAF_NAME]->els,
- count = stacks[WILDCARD_LEAF_NAME]->numUsed; count > 0;
+ for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_NAME]->els,
+ count = tsdPtr->stacks[WILDCARD_LEAF_NAME]->numUsed; count > 0;
elPtr++, count--) {
if ((elPtr->nameUid == nameId)
&& (elPtr->priority > bestPtr->priority)) {
@@ -426,17 +431,17 @@ Tk_GetOption(tkwin, name, className)
}
if (className != NULL) {
classId = Tk_GetUid(className);
- for (elPtr = stacks[EXACT_LEAF_CLASS]->els,
- count = stacks[EXACT_LEAF_CLASS]->numUsed; count > 0;
+ for (elPtr = tsdPtr->stacks[EXACT_LEAF_CLASS]->els,
+ count = tsdPtr->stacks[EXACT_LEAF_CLASS]->numUsed; count > 0;
elPtr++, count--) {
if ((elPtr->nameUid == classId)
&& (elPtr->priority > bestPtr->priority)) {
bestPtr = elPtr;
}
}
- for (elPtr = stacks[WILDCARD_LEAF_CLASS]->els,
- count = stacks[WILDCARD_LEAF_CLASS]->numUsed; count > 0;
- elPtr++, count--) {
+ for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->els,
+ count = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->numUsed;
+ count > 0; elPtr++, count--) {
if ((elPtr->nameUid == classId)
&& (elPtr->priority > bestPtr->priority)) {
bestPtr = elPtr;
@@ -449,7 +454,7 @@ Tk_GetOption(tkwin, name, className)
/*
*--------------------------------------------------------------
*
- * Tk_OptionCmd --
+ * Tk_OptionObjCmd --
*
* This procedure is invoked to process the "option" Tcl command.
* See the user documentation for details on what it does.
@@ -464,98 +469,117 @@ Tk_GetOption(tkwin, name, className)
*/
int
-Tk_OptionCmd(clientData, interp, argc, argv)
+Tk_OptionObjCmd(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 Tcl_Obj arguments. */
+ Tcl_Obj *CONST objv[]; /* Tcl_Obj arguments. */
{
Tk_Window tkwin = (Tk_Window) clientData;
- size_t length;
- char c;
+ int index, result;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ static char *optionCmds[] = {
+ "add", "clear", "get", "readfile", NULL
+ };
- if (argc < 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " cmd arg ?arg ...?\"", (char *) NULL);
+ enum optionVals {
+ OPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE
+ };
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cmd arg ?arg ...?");
return TCL_ERROR;
}
- c = argv[1][0];
- length = strlen(argv[1]);
- if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)) {
- int priority;
-
- if ((argc != 4) && (argc != 5)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " add pattern value ?priority?\"", (char *) NULL);
- return TCL_ERROR;
- }
- if (argc == 4) {
- priority = TK_INTERACTIVE_PRIO;
- } else {
- priority = ParsePriority(interp, argv[4]);
- if (priority < 0) {
+
+ result = Tcl_GetIndexFromObj(interp, objv[1], optionCmds, "option", 0,
+ &index);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ result = TCL_OK;
+ switch ((enum optionVals) index) {
+ case OPTION_ADD: {
+ int priority;
+ if ((objc != 4) && (objc != 5)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?");
return TCL_ERROR;
}
+
+ if (objc == 4) {
+ priority = TK_INTERACTIVE_PRIO;
+ } else {
+ priority = ParsePriority(interp, Tcl_GetString(objv[4]));
+ if (priority < 0) {
+ return TCL_ERROR;
+ }
+ }
+ Tk_AddOption(tkwin, Tcl_GetString(objv[2]),
+ Tcl_GetString(objv[3]), priority);
+ break;
}
- Tk_AddOption(tkwin, argv[2], argv[3], priority);
- return TCL_OK;
- } else if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) {
- TkMainInfo *mainPtr;
-
- if (argc != 2) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " clear\"", (char *) NULL);
- return TCL_ERROR;
- }
- mainPtr = ((TkWindow *) tkwin)->mainPtr;
- if (mainPtr->optionRootPtr != NULL) {
- ClearOptionTree(mainPtr->optionRootPtr);
- mainPtr->optionRootPtr = NULL;
- }
- cachedWindow = NULL;
- return TCL_OK;
- } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
- Tk_Window window;
- Tk_Uid value;
-
- if (argc != 5) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " get window name class\"", (char *) NULL);
- return TCL_ERROR;
- }
- window = Tk_NameToWindow(interp, argv[2], tkwin);
- if (window == NULL) {
- return TCL_ERROR;
- }
- value = Tk_GetOption(window, argv[3], argv[4]);
- if (value != NULL) {
- interp->result = value;
+
+ case OPTION_CLEAR: {
+ TkMainInfo *mainPtr;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+ mainPtr = ((TkWindow *) tkwin)->mainPtr;
+ if (mainPtr->optionRootPtr != NULL) {
+ ClearOptionTree(mainPtr->optionRootPtr);
+ mainPtr->optionRootPtr = NULL;
+ }
+ tsdPtr->cachedWindow = NULL;
+ break;
}
- return TCL_OK;
- } else if ((c == 'r') && (strncmp(argv[1], "readfile", length) == 0)) {
- int priority;
- if ((argc != 3) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " readfile fileName ?priority?\"",
- (char *) NULL);
- return TCL_ERROR;
+ case OPTION_GET: {
+ Tk_Window window;
+ Tk_Uid value;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "window name class");
+ return TCL_ERROR;
+ }
+ window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
+ if (window == NULL) {
+ return TCL_ERROR;
+ }
+ value = Tk_GetOption(window, Tcl_GetString(objv[3]),
+ Tcl_GetString(objv[4]));
+ if (value != NULL) {
+ Tcl_SetResult(interp, value, TCL_STATIC);
+ }
+ break;
}
- if (argc == 4) {
- priority = ParsePriority(interp, argv[3]);
- if (priority < 0) {
+
+ case OPTION_READFILE: {
+ int priority;
+
+ if ((objc != 3) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?");
return TCL_ERROR;
}
- } else {
- priority = TK_INTERACTIVE_PRIO;
+
+ if (objc == 4) {
+ priority = ParsePriority(interp, Tcl_GetString(objv[3]));
+ if (priority < 0) {
+ return TCL_ERROR;
+ }
+ } else {
+ priority = TK_INTERACTIVE_PRIO;
+ }
+ result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]),
+ priority);
+ break;
}
- return ReadOptionFile(interp, tkwin, argv[2], priority);
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be add, clear, get, or readfile", (char *) NULL);
- return TCL_ERROR;
}
+ return result;
}
/*
@@ -581,6 +605,9 @@ void
TkOptionDeadWindow(winPtr)
register TkWindow *winPtr; /* Window to be cleaned up. */
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
/*
* If this window is in the option stacks, then clear the stacks.
*/
@@ -588,11 +615,11 @@ TkOptionDeadWindow(winPtr)
if (winPtr->optionLevel != -1) {
int i;
- for (i = 1; i <= curLevel; i++) {
- levels[i].winPtr->optionLevel = -1;
+ for (i = 1; i <= tsdPtr->curLevel; i++) {
+ tsdPtr->levels[i].winPtr->optionLevel = -1;
}
- curLevel = -1;
- cachedWindow = NULL;
+ tsdPtr->curLevel = -1;
+ tsdPtr->cachedWindow = NULL;
}
/*
@@ -632,6 +659,8 @@ TkOptionClassChanged(winPtr)
{
int i, j, *basePtr;
ElArray *arrayPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (winPtr->optionLevel == -1) {
return;
@@ -642,22 +671,22 @@ TkOptionClassChanged(winPtr)
* flush all of the levels above the matching one.
*/
- for (i = 1; i <= curLevel; i++) {
- if (levels[i].winPtr == winPtr) {
- for (j = i; j <= curLevel; j++) {
- levels[j].winPtr->optionLevel = -1;
+ for (i = 1; i <= tsdPtr->curLevel; i++) {
+ if (tsdPtr->levels[i].winPtr == winPtr) {
+ for (j = i; j <= tsdPtr->curLevel; j++) {
+ tsdPtr->levels[j].winPtr->optionLevel = -1;
}
- curLevel = i-1;
- basePtr = levels[i].bases;
+ tsdPtr->curLevel = i-1;
+ basePtr = tsdPtr->levels[i].bases;
for (j = 0; j < NUM_STACKS; j++) {
- arrayPtr = stacks[j];
+ arrayPtr = tsdPtr->stacks[j];
arrayPtr->numUsed = basePtr[j];
arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
}
- if (curLevel <= 0) {
- cachedWindow = NULL;
+ if (tsdPtr->curLevel <= 0) {
+ tsdPtr->cachedWindow = NULL;
} else {
- cachedWindow = levels[curLevel].winPtr;
+ tsdPtr->cachedWindow = tsdPtr->levels[tsdPtr->curLevel].winPtr;
}
break;
}
@@ -674,7 +703,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 +763,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 +826,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 +861,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 +876,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 +915,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.
@@ -1062,6 +1098,8 @@ SetupStacks(winPtr, leaf)
int level, i, *iPtr;
register StackLevel *levelPtr;
register ElArray *arrayPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* The following array defines the order in which the current
@@ -1086,7 +1124,7 @@ SetupStacks(winPtr, leaf)
if (winPtr->parentPtr != NULL) {
level = winPtr->parentPtr->optionLevel;
- if ((level == -1) || (cachedWindow == NULL)) {
+ if ((level == -1) || (tsdPtr->cachedWindow == NULL)) {
SetupStacks(winPtr->parentPtr, 0);
level = winPtr->parentPtr->optionLevel;
}
@@ -1100,19 +1138,19 @@ SetupStacks(winPtr, leaf)
* mark those windows as no longer having cached information.
*/
- if (curLevel >= level) {
- while (curLevel >= level) {
- levels[curLevel].winPtr->optionLevel = -1;
- curLevel--;
+ if (tsdPtr->curLevel >= level) {
+ while (tsdPtr->curLevel >= level) {
+ tsdPtr->levels[tsdPtr->curLevel].winPtr->optionLevel = -1;
+ tsdPtr->curLevel--;
}
- levelPtr = &levels[level];
+ levelPtr = &tsdPtr->levels[level];
for (i = 0; i < NUM_STACKS; i++) {
- arrayPtr = stacks[i];
+ arrayPtr = tsdPtr->stacks[i];
arrayPtr->numUsed = levelPtr->bases[i];
arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed];
}
}
- curLevel = winPtr->optionLevel = level;
+ tsdPtr->curLevel = winPtr->optionLevel = level;
/*
* Step 3: if the root database information isn't loaded or
@@ -1120,11 +1158,11 @@ SetupStacks(winPtr, leaf)
* database root (this only happens if winPtr is a main window).
*/
- if ((curLevel == 1)
- && ((cachedWindow == NULL)
- || (cachedWindow->mainPtr != winPtr->mainPtr))) {
+ if ((tsdPtr->curLevel == 1)
+ && ((tsdPtr->cachedWindow == NULL)
+ || (tsdPtr->cachedWindow->mainPtr != winPtr->mainPtr))) {
for (i = 0; i < NUM_STACKS; i++) {
- arrayPtr = stacks[i];
+ arrayPtr = tsdPtr->stacks[i];
arrayPtr->numUsed = 0;
arrayPtr->nextToUse = arrayPtr->els;
}
@@ -1138,33 +1176,41 @@ SetupStacks(winPtr, leaf)
* any more).
*/
- if (curLevel >= numLevels) {
+ if (tsdPtr->curLevel >= tsdPtr->numLevels) {
StackLevel *newLevels;
newLevels = (StackLevel *) ckalloc((unsigned)
- (numLevels*2*sizeof(StackLevel)));
- memcpy((VOID *) newLevels, (VOID *) levels,
- (numLevels*sizeof(StackLevel)));
- ckfree((char *) levels);
- numLevels *= 2;
- levels = newLevels;
+ (tsdPtr->numLevels*2*sizeof(StackLevel)));
+ memcpy((VOID *) newLevels, (VOID *) tsdPtr->levels,
+ (tsdPtr->numLevels*sizeof(StackLevel)));
+ ckfree((char *) tsdPtr->levels);
+ tsdPtr->numLevels *= 2;
+ tsdPtr->levels = newLevels;
}
- levelPtr = &levels[curLevel];
+ levelPtr = &tsdPtr->levels[tsdPtr->curLevel];
levelPtr->winPtr = winPtr;
- arrayPtr = stacks[EXACT_LEAF_NAME];
+ arrayPtr = tsdPtr->stacks[EXACT_LEAF_NAME];
arrayPtr->numUsed = 0;
arrayPtr->nextToUse = arrayPtr->els;
- arrayPtr = stacks[EXACT_LEAF_CLASS];
+ arrayPtr = tsdPtr->stacks[EXACT_LEAF_CLASS];
arrayPtr->numUsed = 0;
arrayPtr->nextToUse = arrayPtr->els;
- levelPtr->bases[EXACT_LEAF_NAME] = stacks[EXACT_LEAF_NAME]->numUsed;
- levelPtr->bases[EXACT_LEAF_CLASS] = stacks[EXACT_LEAF_CLASS]->numUsed;
- levelPtr->bases[EXACT_NODE_NAME] = stacks[EXACT_NODE_NAME]->numUsed;
- levelPtr->bases[EXACT_NODE_CLASS] = stacks[EXACT_NODE_CLASS]->numUsed;
- levelPtr->bases[WILDCARD_LEAF_NAME] = stacks[WILDCARD_LEAF_NAME]->numUsed;
- levelPtr->bases[WILDCARD_LEAF_CLASS] = stacks[WILDCARD_LEAF_CLASS]->numUsed;
- levelPtr->bases[WILDCARD_NODE_NAME] = stacks[WILDCARD_NODE_NAME]->numUsed;
- levelPtr->bases[WILDCARD_NODE_CLASS] = stacks[WILDCARD_NODE_CLASS]->numUsed;
+ levelPtr->bases[EXACT_LEAF_NAME] = tsdPtr->stacks[EXACT_LEAF_NAME]
+ ->numUsed;
+ levelPtr->bases[EXACT_LEAF_CLASS] = tsdPtr->stacks[EXACT_LEAF_CLASS]
+ ->numUsed;
+ levelPtr->bases[EXACT_NODE_NAME] = tsdPtr->stacks[EXACT_NODE_NAME]
+ ->numUsed;
+ levelPtr->bases[EXACT_NODE_CLASS] = tsdPtr->stacks[EXACT_NODE_CLASS]
+ ->numUsed;
+ levelPtr->bases[WILDCARD_LEAF_NAME] = tsdPtr->stacks[WILDCARD_LEAF_NAME]
+ ->numUsed;
+ levelPtr->bases[WILDCARD_LEAF_CLASS] = tsdPtr->stacks[WILDCARD_LEAF_CLASS]
+ ->numUsed;
+ levelPtr->bases[WILDCARD_NODE_NAME] = tsdPtr->stacks[WILDCARD_NODE_NAME]
+ ->numUsed;
+ levelPtr->bases[WILDCARD_NODE_CLASS] = tsdPtr->stacks[WILDCARD_NODE_CLASS]
+ ->numUsed;
/*
@@ -1184,7 +1230,7 @@ SetupStacks(winPtr, leaf)
} else {
id = winPtr->nameUid;
}
- elPtr = stacks[i]->els;
+ elPtr = tsdPtr->stacks[i]->els;
count = levelPtr->bases[i];
/*
@@ -1203,7 +1249,7 @@ SetupStacks(winPtr, leaf)
ExtendStacks(elPtr->child.arrayPtr, leaf);
}
}
- cachedWindow = winPtr;
+ tsdPtr->cachedWindow = winPtr;
}
/*
@@ -1232,13 +1278,16 @@ ExtendStacks(arrayPtr, leaf)
{
register int count;
register Element *elPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
for (elPtr = arrayPtr->els, count = arrayPtr->numUsed;
count > 0; elPtr++, count--) {
if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) {
continue;
}
- stacks[elPtr->flags] = ExtendArray(stacks[elPtr->flags], elPtr);
+ tsdPtr->stacks[elPtr->flags] = ExtendArray(
+ tsdPtr->stacks[elPtr->flags], elPtr);
}
}
@@ -1266,24 +1315,32 @@ OptionInit(mainPtr)
{
int i;
Tcl_Interp *interp;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Element *defaultMatchPtr = &tsdPtr->defaultMatch;
/*
* First, once-only initialization.
*/
-
- if (numLevels == 0) {
-
- numLevels = 5;
- levels = (StackLevel *) ckalloc((unsigned) (5*sizeof(StackLevel)));
+
+ if (tsdPtr->initialized == 0) {
+ tsdPtr->initialized = 1;
+ tsdPtr->cachedWindow = NULL;
+ tsdPtr->numLevels = 5;
+ tsdPtr->curLevel = -1;
+ tsdPtr->serial = 0;
+
+ tsdPtr->levels = (StackLevel *) ckalloc((unsigned)
+ (5*sizeof(StackLevel)));
for (i = 0; i < NUM_STACKS; i++) {
- stacks[i] = NewArray(10);
- levels[0].bases[i] = 0;
+ tsdPtr->stacks[i] = NewArray(10);
+ tsdPtr->levels[0].bases[i] = 0;
}
- defaultMatch.nameUid = NULL;
- defaultMatch.child.valueUid = NULL;
- defaultMatch.priority = -1;
- defaultMatch.flags = 0;
+ defaultMatchPtr->nameUid = NULL;
+ defaultMatchPtr->child.valueUid = NULL;
+ defaultMatchPtr->priority = -1;
+ defaultMatchPtr->flags = 0;
}
/*
diff --git a/tk/generic/tkPack.c b/tk/generic/tkPack.c
index 9e5d2421fdf..d10d86782b9 100644
--- a/tk/generic/tkPack.c
+++ b/tk/generic/tkPack.c
@@ -5,7 +5,7 @@
* 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.
@@ -24,7 +24,7 @@ typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side;
* structure of the following type:
*/
-typedef struct Packer {
+typedef struct /* Green Bay */ Packer {
Tk_Window tkwin; /* Tk token for window. NULL means that
* the window has been deleted, but the
* packet hasn't had a chance to clean up
@@ -96,19 +96,6 @@ typedef struct Packer {
#define DONT_PROPAGATE 32
/*
- * Hash table used to map from Tk_Window tokens to corresponding
- * Packer structures:
- */
-
-static Tcl_HashTable packerHashTable;
-
-/*
- * Have statics in this module been initialized?
- */
-
-static int initialized = 0;
-
-/*
* The following structure is the official type record for the
* packer:
*/
@@ -281,7 +268,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 +329,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;
}
@@ -957,10 +944,11 @@ GetPacker(tkwin)
register Packer *packPtr;
Tcl_HashEntry *hPtr;
int new;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
- if (!initialized) {
- initialized = 1;
- Tcl_InitHashTable(&packerHashTable, TCL_ONE_WORD_KEYS);
+ if (!dispPtr->packInit) {
+ dispPtr->packInit = 1;
+ Tcl_InitHashTable(&dispPtr->packerHashTable, TCL_ONE_WORD_KEYS);
}
/*
@@ -968,7 +956,8 @@ GetPacker(tkwin)
* then create a new one.
*/
- hPtr = Tcl_CreateHashEntry(&packerHashTable, (char *) tkwin, &new);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin,
+ &new);
if (!new) {
return (Packer *) Tcl_GetHashValue(hPtr);
}
@@ -1324,6 +1313,7 @@ PackStructureProc(clientData, eventPtr)
XEvent *eventPtr; /* Describes what just happened. */
{
register Packer *packPtr = (Packer *) clientData;
+
if (eventPtr->type == ConfigureNotify) {
if ((packPtr->slavePtr != NULL)
&& !(packPtr->flags & REQUESTED_REPACK)) {
@@ -1353,8 +1343,11 @@ PackStructureProc(clientData, eventPtr)
nextPtr = slavePtr->nextPtr;
slavePtr->nextPtr = NULL;
}
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&packerHashTable,
- (char *) packPtr->tkwin));
+ if (packPtr->tkwin != NULL) {
+ TkDisplay *dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr;
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable,
+ (char *) packPtr->tkwin));
+ }
if (packPtr->flags & REQUESTED_REPACK) {
Tcl_CancelIdleCall(ArrangePacking, (ClientData) packPtr);
}
@@ -1372,16 +1365,15 @@ PackStructureProc(clientData, eventPtr)
Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr);
}
} else if (eventPtr->type == UnmapNotify) {
- Packer *packPtr2;
+ register Packer *packPtr2;
/*
* Unmap all of the slaves when the master gets unmapped,
* so that they don't bother to keep redisplaying
* themselves.
*/
-
for (packPtr2 = packPtr->slavePtr; packPtr2 != NULL;
- packPtr2 = packPtr2->nextPtr) {
+ packPtr2 = packPtr2->nextPtr) {
Tk_UnmapWindow(packPtr2->tkwin);
}
}
@@ -1398,7 +1390,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.
@@ -1725,3 +1717,5 @@ ConfigureSlaves(interp, tkwin, argc, argv)
}
return TCL_OK;
}
+
+
diff --git a/tk/generic/tkPatch.h b/tk/generic/tkPatch.h
new file mode 100644
index 00000000000..c36ed20a17a
--- /dev/null
+++ b/tk/generic/tkPatch.h
@@ -0,0 +1,23 @@
+/*
+ * tkPatch.h --
+ *
+ * This file does nothing except define a "patch level" for Tk.
+ * The patch level has the form "X.YpZ" where X.Y is the base
+ * release, and Z is a serial number that is used to sequence
+ * patches for a given release. Thus 4.0p1 is the first patch
+ * to release 4.0, 4.0p2 is the patch that follows 4.0p1, and
+ * so on. The "pZ" is omitted in an original new release, and
+ * it is replaced with "bZ" for beta releases or "aZ" for alpha
+ * releases (e.g. 4.0b1 is the first beta release of Tk 4.0).
+ * The patch level ensures that patches are applied in the
+ * correct order and only to appropriate sources.
+ *
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkPatch.h 1.22 96/10/02 14:36:36
+ */
+
+#define TK_PATCH_LEVEL "4.2"
diff --git a/tk/generic/tkPlace.c b/tk/generic/tkPlace.c
index 2102b506117..d48895b2d41 100644
--- a/tk/generic/tkPlace.c
+++ b/tk/generic/tkPlace.c
@@ -5,7 +5,7 @@
* 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.
@@ -99,15 +99,6 @@ typedef struct Master {
#define PARENT_RECONFIG_PENDING 1
/*
- * The hash tables below both use Tk_Window tokens as keys. They map
- * from Tk_Windows to Slave and Master structures for windows, if they
- * exist.
- */
-
-static int initialized = 0;
-static Tcl_HashTable masterTable;
-static Tcl_HashTable slaveTable;
-/*
* The following structure is the official type record for the
* placer:
*/
@@ -168,16 +159,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv)
Tcl_HashEntry *hPtr;
size_t length;
int c;
-
- /*
- * Initialize, if that hasn't been done yet.
- */
-
- if (!initialized) {
- Tcl_InitHashTable(&masterTable, TCL_ONE_WORD_KEYS);
- Tcl_InitHashTable(&slaveTable, TCL_ONE_WORD_KEYS);
- initialized = 1;
- }
+ TkDisplay *dispPtr;
if (argc < 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -196,6 +178,18 @@ Tk_PlaceCmd(clientData, interp, argc, argv)
if (tkwin == NULL) {
return TCL_ERROR;
}
+
+ /*
+ * Initialize, if that hasn't been done yet.
+ */
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (!dispPtr->placeInit) {
+ Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
+ dispPtr->placeInit = 1;
+ }
+
slavePtr = FindSlave(tkwin);
return ConfigureSlave(interp, slavePtr, argc-2, argv+2);
}
@@ -209,6 +203,18 @@ Tk_PlaceCmd(clientData, interp, argc, argv)
if (tkwin == NULL) {
return TCL_ERROR;
}
+
+ /*
+ * Initialize, if that hasn't been done yet.
+ */
+
+ dispPtr = ((TkWindow *) tkwin)->dispPtr;
+ if (!dispPtr->placeInit) {
+ Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
+ dispPtr->placeInit = 1;
+ }
+
if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) {
if (argc < 5) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
@@ -225,7 +231,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv)
argv[0], " forget pathName\"", (char *) NULL);
return TCL_ERROR;
}
- hPtr = Tcl_FindHashEntry(&slaveTable, (char *) tkwin);
+ hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin);
if (hPtr == NULL) {
return TCL_OK;
}
@@ -243,14 +249,14 @@ 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 \"",
argv[0], " info pathName\"", (char *) NULL);
return TCL_ERROR;
}
- hPtr = Tcl_FindHashEntry(&slaveTable, (char *) tkwin);
+ hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin);
if (hPtr == NULL) {
return TCL_OK;
}
@@ -306,7 +312,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv)
argv[0], " slaves pathName\"", (char *) NULL);
return TCL_ERROR;
}
- hPtr = Tcl_FindHashEntry(&masterTable, (char *) tkwin);
+ hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, (char *) tkwin);
if (hPtr != NULL) {
Master *masterPtr;
masterPtr = (Master *) Tcl_GetHashValue(hPtr);
@@ -348,8 +354,9 @@ FindSlave(tkwin)
Tcl_HashEntry *hPtr;
register Slave *slavePtr;
int new;
+ TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr;
- hPtr = Tcl_CreateHashEntry(&slaveTable, (char *) tkwin, &new);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->slaveTable, (char *) tkwin, &new);
if (new) {
slavePtr = (Slave *) ckalloc(sizeof(Slave));
slavePtr->tkwin = tkwin;
@@ -441,8 +448,9 @@ FindMaster(tkwin)
Tcl_HashEntry *hPtr;
register Master *masterPtr;
int new;
+ TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr;
- hPtr = Tcl_CreateHashEntry(&masterTable, (char *) tkwin, &new);
+ hPtr = Tcl_CreateHashEntry(&dispPtr->masterTable, (char *) tkwin, &new);
if (new) {
masterPtr = (Master *) ckalloc(sizeof(Master));
masterPtr->tkwin = tkwin;
@@ -467,7 +475,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
@@ -843,7 +851,7 @@ RecomputePlacement(clientData)
/*
* Step 5: reconfigure the window and map it if needed. If the
* slave is a child of the master, we do this ourselves. If the
- * slave isn't a child of the master, let Tk_MaintainWindow do
+ * slave isn't a child of the master, let Tk_MaintainGeometry do
* the work (it will re-adjust things as relevant windows map,
* unmap, and move).
*/
@@ -902,6 +910,7 @@ MasterStructureProc(clientData, eventPtr)
{
register Master *masterPtr = (Master *) clientData;
register Slave *slavePtr, *nextPtr;
+ TkDisplay *dispPtr = ((TkWindow *) masterPtr->tkwin)->dispPtr;
if (eventPtr->type == ConfigureNotify) {
if ((masterPtr->slavePtr != NULL)
@@ -916,7 +925,7 @@ MasterStructureProc(clientData, eventPtr)
nextPtr = slavePtr->nextPtr;
slavePtr->nextPtr = NULL;
}
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&masterTable,
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->masterTable,
(char *) masterPtr->tkwin));
if (masterPtr->flags & PARENT_RECONFIG_PENDING) {
Tcl_CancelIdleCall(RecomputePlacement, (ClientData) masterPtr);
@@ -971,10 +980,11 @@ SlaveStructureProc(clientData, eventPtr)
XEvent *eventPtr; /* Describes what just happened. */
{
register Slave *slavePtr = (Slave *) clientData;
+ TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
if (eventPtr->type == DestroyNotify) {
UnlinkSlave(slavePtr);
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&slaveTable,
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
(char *) slavePtr->tkwin));
ckfree((char *) slavePtr);
}
@@ -1047,14 +1057,18 @@ PlaceLostSlaveProc(clientData, tkwin)
Tk_Window tkwin; /* Tk's handle for the slave window. */
{
register Slave *slavePtr = (Slave *) clientData;
+ TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;
if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
}
Tk_UnmapWindow(tkwin);
UnlinkSlave(slavePtr);
- Tcl_DeleteHashEntry(Tcl_FindHashEntry(&slaveTable, (char *) tkwin));
+ Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
+ (char *) tkwin));
Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
(ClientData) slavePtr);
ckfree((char *) slavePtr);
}
+
+
diff --git a/tk/generic/tkPlatDecls.h b/tk/generic/tkPlatDecls.h
new file mode 100644
index 00000000000..f2c31235b2a
--- /dev/null
+++ b/tk/generic/tkPlatDecls.h
@@ -0,0 +1,208 @@
+/*
+ * tkPlatDecls.h --
+ *
+ * Declarations of functions in the platform-specific public Tcl API.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#ifndef _TKPLATDECLS
+#define _TKPLATDECLS
+
+#ifdef BUILD_tk
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * WARNING: This file is automatically generated by the tools/genStubs.tcl
+ * script. Any modifications to the function declarations below should be made
+ * in the generic/tk.decls script.
+ */
+
+
+/* !BEGIN!: Do not edit below this line. */
+
+/*
+ * Exported function declarations:
+ */
+
+#ifdef __WIN32__
+/* 0 */
+EXTERN Window Tk_AttachHWND _ANSI_ARGS_((Tk_Window tkwin,
+ HWND hwnd));
+/* 1 */
+EXTERN HINSTANCE Tk_GetHINSTANCE _ANSI_ARGS_((void));
+/* 2 */
+EXTERN HWND Tk_GetHWND _ANSI_ARGS_((Window window));
+/* 3 */
+EXTERN Tk_Window Tk_HWNDToWindow _ANSI_ARGS_((HWND hwnd));
+/* 4 */
+EXTERN void Tk_PointerEvent _ANSI_ARGS_((HWND hwnd, int x, int y));
+/* 5 */
+EXTERN int Tk_TranslateWinEvent _ANSI_ARGS_((HWND hwnd,
+ UINT message, WPARAM wParam, LPARAM lParam,
+ LRESULT * result));
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+/* 0 */
+EXTERN void Tk_MacSetEmbedHandler _ANSI_ARGS_((
+ Tk_MacEmbedRegisterWinProc * registerWinProcPtr,
+ Tk_MacEmbedGetGrafPortProc * getPortProcPtr,
+ Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr,
+ Tk_MacEmbedGetClipProc * getClipProc,
+ Tk_MacEmbedGetOffsetInParentProc * getOffsetProc));
+/* 1 */
+EXTERN void Tk_MacTurnOffMenus _ANSI_ARGS_((void));
+/* 2 */
+EXTERN void Tk_MacTkOwnsCursor _ANSI_ARGS_((int tkOwnsIt));
+/* 3 */
+EXTERN void TkMacInitMenus _ANSI_ARGS_((Tcl_Interp * interp));
+/* 4 */
+EXTERN void TkMacInitAppleEvents _ANSI_ARGS_((
+ Tcl_Interp * interp));
+/* 5 */
+EXTERN int TkMacConvertEvent _ANSI_ARGS_((
+ EventRecord * eventPtr));
+/* 6 */
+EXTERN int TkMacConvertTkEvent _ANSI_ARGS_((
+ EventRecord * eventPtr, Window window));
+/* 7 */
+EXTERN void TkGenWMConfigureEvent _ANSI_ARGS_((Tk_Window tkwin,
+ int x, int y, int width, int height,
+ int flags));
+/* 8 */
+EXTERN void TkMacInvalClipRgns _ANSI_ARGS_((TkWindow * winPtr));
+/* 9 */
+EXTERN int TkMacHaveAppearance _ANSI_ARGS_((void));
+/* 10 */
+EXTERN GWorldPtr TkMacGetDrawablePort _ANSI_ARGS_((Drawable drawable));
+#endif /* MAC_TCL */
+
+typedef struct TkPlatStubs {
+ int magic;
+ struct TkPlatStubHooks *hooks;
+
+#ifdef __WIN32__
+ Window (*tk_AttachHWND) _ANSI_ARGS_((Tk_Window tkwin, HWND hwnd)); /* 0 */
+ HINSTANCE (*tk_GetHINSTANCE) _ANSI_ARGS_((void)); /* 1 */
+ HWND (*tk_GetHWND) _ANSI_ARGS_((Window window)); /* 2 */
+ Tk_Window (*tk_HWNDToWindow) _ANSI_ARGS_((HWND hwnd)); /* 3 */
+ void (*tk_PointerEvent) _ANSI_ARGS_((HWND hwnd, int x, int y)); /* 4 */
+ int (*tk_TranslateWinEvent) _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT * result)); /* 5 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ void (*tk_MacSetEmbedHandler) _ANSI_ARGS_((Tk_MacEmbedRegisterWinProc * registerWinProcPtr, Tk_MacEmbedGetGrafPortProc * getPortProcPtr, Tk_MacEmbedMakeContainerExistProc * containerExistProcPtr, Tk_MacEmbedGetClipProc * getClipProc, Tk_MacEmbedGetOffsetInParentProc * getOffsetProc)); /* 0 */
+ void (*tk_MacTurnOffMenus) _ANSI_ARGS_((void)); /* 1 */
+ void (*tk_MacTkOwnsCursor) _ANSI_ARGS_((int tkOwnsIt)); /* 2 */
+ void (*tkMacInitMenus) _ANSI_ARGS_((Tcl_Interp * interp)); /* 3 */
+ void (*tkMacInitAppleEvents) _ANSI_ARGS_((Tcl_Interp * interp)); /* 4 */
+ int (*tkMacConvertEvent) _ANSI_ARGS_((EventRecord * eventPtr)); /* 5 */
+ int (*tkMacConvertTkEvent) _ANSI_ARGS_((EventRecord * eventPtr, Window window)); /* 6 */
+ void (*tkGenWMConfigureEvent) _ANSI_ARGS_((Tk_Window tkwin, int x, int y, int width, int height, int flags)); /* 7 */
+ void (*tkMacInvalClipRgns) _ANSI_ARGS_((TkWindow * winPtr)); /* 8 */
+ int (*tkMacHaveAppearance) _ANSI_ARGS_((void)); /* 9 */
+ GWorldPtr (*tkMacGetDrawablePort) _ANSI_ARGS_((Drawable drawable)); /* 10 */
+#endif /* MAC_TCL */
+} TkPlatStubs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern TkPlatStubs *tkPlatStubsPtr;
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS)
+
+/*
+ * Inline function declarations:
+ */
+
+#ifdef __WIN32__
+#ifndef Tk_AttachHWND
+#define Tk_AttachHWND \
+ (tkPlatStubsPtr->tk_AttachHWND) /* 0 */
+#endif
+#ifndef Tk_GetHINSTANCE
+#define Tk_GetHINSTANCE \
+ (tkPlatStubsPtr->tk_GetHINSTANCE) /* 1 */
+#endif
+#ifndef Tk_GetHWND
+#define Tk_GetHWND \
+ (tkPlatStubsPtr->tk_GetHWND) /* 2 */
+#endif
+#ifndef Tk_HWNDToWindow
+#define Tk_HWNDToWindow \
+ (tkPlatStubsPtr->tk_HWNDToWindow) /* 3 */
+#endif
+#ifndef Tk_PointerEvent
+#define Tk_PointerEvent \
+ (tkPlatStubsPtr->tk_PointerEvent) /* 4 */
+#endif
+#ifndef Tk_TranslateWinEvent
+#define Tk_TranslateWinEvent \
+ (tkPlatStubsPtr->tk_TranslateWinEvent) /* 5 */
+#endif
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+#ifndef Tk_MacSetEmbedHandler
+#define Tk_MacSetEmbedHandler \
+ (tkPlatStubsPtr->tk_MacSetEmbedHandler) /* 0 */
+#endif
+#ifndef Tk_MacTurnOffMenus
+#define Tk_MacTurnOffMenus \
+ (tkPlatStubsPtr->tk_MacTurnOffMenus) /* 1 */
+#endif
+#ifndef Tk_MacTkOwnsCursor
+#define Tk_MacTkOwnsCursor \
+ (tkPlatStubsPtr->tk_MacTkOwnsCursor) /* 2 */
+#endif
+#ifndef TkMacInitMenus
+#define TkMacInitMenus \
+ (tkPlatStubsPtr->tkMacInitMenus) /* 3 */
+#endif
+#ifndef TkMacInitAppleEvents
+#define TkMacInitAppleEvents \
+ (tkPlatStubsPtr->tkMacInitAppleEvents) /* 4 */
+#endif
+#ifndef TkMacConvertEvent
+#define TkMacConvertEvent \
+ (tkPlatStubsPtr->tkMacConvertEvent) /* 5 */
+#endif
+#ifndef TkMacConvertTkEvent
+#define TkMacConvertTkEvent \
+ (tkPlatStubsPtr->tkMacConvertTkEvent) /* 6 */
+#endif
+#ifndef TkGenWMConfigureEvent
+#define TkGenWMConfigureEvent \
+ (tkPlatStubsPtr->tkGenWMConfigureEvent) /* 7 */
+#endif
+#ifndef TkMacInvalClipRgns
+#define TkMacInvalClipRgns \
+ (tkPlatStubsPtr->tkMacInvalClipRgns) /* 8 */
+#endif
+#ifndef TkMacHaveAppearance
+#define TkMacHaveAppearance \
+ (tkPlatStubsPtr->tkMacHaveAppearance) /* 9 */
+#endif
+#ifndef TkMacGetDrawablePort
+#define TkMacGetDrawablePort \
+ (tkPlatStubsPtr->tkMacGetDrawablePort) /* 10 */
+#endif
+#endif /* MAC_TCL */
+
+#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
+
+/* !END!: Do not edit above this line. */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* _TKPLATDECLS */
diff --git a/tk/generic/tkPointer.c b/tk/generic/tkPointer.c
index 85a6af87811..f51e82b7506 100644
--- a/tk/generic/tkPointer.c
+++ b/tk/generic/tkPointer.c
@@ -16,6 +16,10 @@
#include "tkInt.h"
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+
#ifdef MAC_TCL
#define Cursor XCursor
#endif
@@ -32,19 +36,18 @@ static unsigned int buttonMasks[] = {
};
#define ButtonMask(b) (buttonMasks[(b)-Button1])
-/*
- * Declarations of static variables used in the pointer module.
- */
-
-static TkWindow *cursorWinPtr = NULL; /* Window that is currently
- * controlling the global cursor. */
-static TkWindow *grabWinPtr = NULL; /* Window that defines the top of the
+typedef struct ThreadSpecificData {
+ TkWindow *grabWinPtr; /* Window that defines the top of the
* grab tree in a global grab. */
-static XPoint lastPos = { 0, 0}; /* Last reported mouse position. */
-static int lastState = 0; /* Last known state flags. */
-static TkWindow *lastWinPtr = NULL; /* Last reported mouse window. */
-static TkWindow *restrictWinPtr = NULL; /* Window to which all mouse events
+ int lastState; /* Last known state flags. */
+ XPoint lastPos; /* Last reported mouse position. */
+ TkWindow *lastWinPtr; /* Last reported mouse window. */
+ TkWindow *restrictWinPtr; /* Window to which all mouse events
* will be reported. */
+ TkWindow *cursorWinPtr; /* Window that is currently
+ * controlling the global cursor. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations of procedures used in this file.
@@ -137,8 +140,12 @@ GenerateEnterLeave(winPtr, x, y, state)
int state; /* State flags. */
{
int crossed = 0; /* 1 if mouse crossed a window boundary */
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ TkWindow *restrictWinPtr = tsdPtr->restrictWinPtr;
+ TkWindow *lastWinPtr = tsdPtr->lastWinPtr;
- if (winPtr != lastWinPtr) {
+ if (winPtr != tsdPtr->lastWinPtr) {
if (restrictWinPtr) {
int newPos, oldPos;
@@ -196,7 +203,7 @@ GenerateEnterLeave(winPtr, x, y, state)
crossed = 1;
}
}
- lastWinPtr = winPtr;
+ tsdPtr->lastWinPtr = winPtr;
}
return crossed;
@@ -226,11 +233,13 @@ Tk_UpdatePointer(tkwin, x, y, state)
int x, y; /* Pointer location in root coords. */
int state; /* Modifier state mask. */
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
TkWindow *winPtr = (TkWindow *)tkwin;
TkWindow *targetWinPtr;
XPoint pos;
XEvent event;
- int changes = (state ^ lastState) & ALL_BUTTONS;
+ int changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS;
int type, b, mask;
pos.x = x;
@@ -241,7 +250,8 @@ Tk_UpdatePointer(tkwin, x, y, state)
* state since we haven't generated the button events yet.
*/
- lastState = (state & ~ALL_BUTTONS) | (lastState & ALL_BUTTONS);
+ tsdPtr->lastState = (state & ~ALL_BUTTONS) | (tsdPtr->lastState
+ & ALL_BUTTONS);
/*
* Generate Enter/Leave events. If the pointer has crossed window
@@ -249,8 +259,8 @@ Tk_UpdatePointer(tkwin, x, y, state)
* redundant motion events.
*/
- if (GenerateEnterLeave(winPtr, x, y, lastState)) {
- lastPos = pos;
+ if (GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState)) {
+ tsdPtr->lastPos = pos;
}
/*
@@ -269,30 +279,30 @@ Tk_UpdatePointer(tkwin, x, y, state)
* if this is the first button down.
*/
- if (!restrictWinPtr) {
- if (!grabWinPtr) {
+ if (!tsdPtr->restrictWinPtr) {
+ if (!tsdPtr->grabWinPtr) {
/*
* Mouse is not grabbed, so set a button grab.
*/
- restrictWinPtr = winPtr;
- TkpSetCapture(restrictWinPtr);
+ tsdPtr->restrictWinPtr = winPtr;
+ TkpSetCapture(tsdPtr->restrictWinPtr);
- } else if ((lastState & ALL_BUTTONS) == 0) {
+ } else if ((tsdPtr->lastState & ALL_BUTTONS) == 0) {
/*
* Mouse is in a non-button grab, so ensure
* the button grab is inside the grab tree.
*/
- if (TkPositionInTree(winPtr, grabWinPtr)
+ if (TkPositionInTree(winPtr, tsdPtr->grabWinPtr)
== TK_GRAB_IN_TREE) {
- restrictWinPtr = winPtr;
+ tsdPtr->restrictWinPtr = winPtr;
} else {
- restrictWinPtr = grabWinPtr;
+ tsdPtr->restrictWinPtr = tsdPtr->grabWinPtr;
}
- TkpSetCapture(restrictWinPtr);
+ TkpSetCapture(tsdPtr->restrictWinPtr);
}
}
@@ -305,8 +315,8 @@ Tk_UpdatePointer(tkwin, x, y, state)
* aren't in a global grab.
*/
- if ((lastState & ALL_BUTTONS) == mask) {
- if (!grabWinPtr) {
+ if ((tsdPtr->lastState & ALL_BUTTONS) == mask) {
+ if (!tsdPtr->grabWinPtr) {
TkpSetCapture(NULL);
}
}
@@ -317,16 +327,16 @@ Tk_UpdatePointer(tkwin, x, y, state)
* the restrict window to the current mouse position.
*/
- if (restrictWinPtr) {
- InitializeEvent(&event, restrictWinPtr, type, x, y,
- lastState, b);
+ if (tsdPtr->restrictWinPtr) {
+ InitializeEvent(&event, tsdPtr->restrictWinPtr, type, x, y,
+ tsdPtr->lastState, b);
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- lastState &= ~mask;
- lastWinPtr = restrictWinPtr;
- restrictWinPtr = NULL;
+ tsdPtr->lastState &= ~mask;
+ tsdPtr->lastWinPtr = tsdPtr->restrictWinPtr;
+ tsdPtr->restrictWinPtr = NULL;
- GenerateEnterLeave(winPtr, x, y, lastState);
- lastPos = pos;
+ GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState);
+ tsdPtr->lastPos = pos;
continue;
}
}
@@ -338,10 +348,10 @@ Tk_UpdatePointer(tkwin, x, y, state)
* managed by Tk should be reported to the grab window.
*/
- if (restrictWinPtr) {
- targetWinPtr = restrictWinPtr;
- } else if (grabWinPtr && !winPtr) {
- targetWinPtr = grabWinPtr;
+ if (tsdPtr->restrictWinPtr) {
+ targetWinPtr = tsdPtr->restrictWinPtr;
+ } else if (tsdPtr->grabWinPtr && !winPtr) {
+ targetWinPtr = tsdPtr->grabWinPtr;
} else {
targetWinPtr = winPtr;
}
@@ -352,7 +362,7 @@ Tk_UpdatePointer(tkwin, x, y, state)
if (winPtr != NULL) {
InitializeEvent(&event, targetWinPtr, type, x, y,
- lastState, b);
+ tsdPtr->lastState, b);
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
}
@@ -360,9 +370,9 @@ Tk_UpdatePointer(tkwin, x, y, state)
* Update the state for the next iteration.
*/
- lastState = (type == ButtonPress)
- ? (lastState | mask) : (lastState & ~mask);
- lastPos = pos;
+ tsdPtr->lastState = (type == ButtonPress)
+ ? (tsdPtr->lastState | mask) : (tsdPtr->lastState & ~mask);
+ tsdPtr->lastPos = pos;
}
}
@@ -370,11 +380,11 @@ Tk_UpdatePointer(tkwin, x, y, state)
* Make sure the cursor window is up to date.
*/
- if (restrictWinPtr) {
- targetWinPtr = restrictWinPtr;
- } else if (grabWinPtr) {
- targetWinPtr = (TkPositionInTree(winPtr, grabWinPtr)
- == TK_GRAB_IN_TREE) ? winPtr : grabWinPtr;
+ if (tsdPtr->restrictWinPtr) {
+ targetWinPtr = tsdPtr->restrictWinPtr;
+ } else if (tsdPtr->grabWinPtr) {
+ targetWinPtr = (TkPositionInTree(winPtr, tsdPtr->grabWinPtr)
+ == TK_GRAB_IN_TREE) ? winPtr : tsdPtr->grabWinPtr;
} else {
targetWinPtr = winPtr;
}
@@ -385,19 +395,19 @@ Tk_UpdatePointer(tkwin, x, y, state)
* generate a motion event.
*/
- if (lastPos.x != pos.x || lastPos.y != pos.y) {
- if (restrictWinPtr) {
- targetWinPtr = restrictWinPtr;
- } else if (grabWinPtr && !winPtr) {
- targetWinPtr = grabWinPtr;
+ if (tsdPtr->lastPos.x != pos.x || tsdPtr->lastPos.y != pos.y) {
+ if (tsdPtr->restrictWinPtr) {
+ targetWinPtr = tsdPtr->restrictWinPtr;
+ } else if (tsdPtr->grabWinPtr && !winPtr) {
+ targetWinPtr = tsdPtr->grabWinPtr;
}
if (targetWinPtr != NULL) {
InitializeEvent(&event, targetWinPtr, MotionNotify, x, y,
- lastState, NotifyNormal);
+ tsdPtr->lastState, NotifyNormal);
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
}
- lastPos = pos;
+ tsdPtr->lastPos = pos;
}
}
@@ -433,12 +443,16 @@ XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode,
Cursor cursor;
Time time;
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
display->request++;
- grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window);
- restrictWinPtr = NULL;
- TkpSetCapture(grabWinPtr);
- if (TkPositionInTree(lastWinPtr, grabWinPtr) != TK_GRAB_IN_TREE) {
- UpdateCursor(grabWinPtr);
+ tsdPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window);
+ tsdPtr->restrictWinPtr = NULL;
+ TkpSetCapture(tsdPtr->grabWinPtr);
+ if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr)
+ != TK_GRAB_IN_TREE) {
+ UpdateCursor(tsdPtr->grabWinPtr);
}
return GrabSuccess;
}
@@ -464,11 +478,14 @@ XUngrabPointer(display, time)
Display* display;
Time time;
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
display->request++;
- grabWinPtr = NULL;
- restrictWinPtr = NULL;
+ tsdPtr->grabWinPtr = NULL;
+ tsdPtr->restrictWinPtr = NULL;
TkpSetCapture(NULL);
- UpdateCursor(lastWinPtr);
+ UpdateCursor(tsdPtr->lastWinPtr);
}
/*
@@ -491,16 +508,19 @@ void
TkPointerDeadWindow(winPtr)
TkWindow *winPtr;
{
- if (winPtr == lastWinPtr) {
- lastWinPtr = NULL;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ if (winPtr == tsdPtr->lastWinPtr) {
+ tsdPtr->lastWinPtr = NULL;
}
- if (winPtr == grabWinPtr) {
- grabWinPtr = NULL;
+ if (winPtr == tsdPtr->grabWinPtr) {
+ tsdPtr->grabWinPtr = NULL;
}
- if (winPtr == restrictWinPtr) {
- restrictWinPtr = NULL;
+ if (winPtr == tsdPtr->restrictWinPtr) {
+ tsdPtr->restrictWinPtr = NULL;
}
- if (!(restrictWinPtr || grabWinPtr)) {
+ if (!(tsdPtr->restrictWinPtr || tsdPtr->grabWinPtr)) {
TkpSetCapture(NULL);
}
}
@@ -527,6 +547,8 @@ UpdateCursor(winPtr)
TkWindow *winPtr;
{
Cursor cursor = None;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* A window inherits its cursor from its parent if it doesn't
@@ -534,7 +556,7 @@ UpdateCursor(winPtr)
* cursor.
*/
- cursorWinPtr = winPtr;
+ tsdPtr->cursorWinPtr = winPtr;
while (winPtr != NULL) {
if (winPtr->atts.cursor != None) {
cursor = winPtr->atts.cursor;
@@ -573,8 +595,10 @@ XDefineCursor(display, w, cursor)
Cursor cursor;
{
TkWindow *winPtr = (TkWindow *)Tk_IdToWindow(display, w);
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (cursorWinPtr == winPtr) {
+ if (tsdPtr->cursorWinPtr == winPtr) {
UpdateCursor(winPtr);
}
display->request++;
@@ -621,3 +645,4 @@ TkGenerateActivateEvents(winPtr, active)
TkQueueEventForAllChildren(winPtr, &event);
}
+
diff --git a/tk/generic/tkPort.h b/tk/generic/tkPort.h
index ab9f28b15f8..aef9026bcc6 100644
--- a/tk/generic/tkPort.h
+++ b/tk/generic/tkPort.h
@@ -34,3 +34,4 @@
#endif
#endif /* _TKPORT */
+
diff --git a/tk/generic/tkRectOval.c b/tk/generic/tkRectOval.c
index daa39dafbdf..0bb54885371 100644
--- a/tk/generic/tkRectOval.c
+++ b/tk/generic/tkRectOval.c
@@ -5,7 +5,7 @@
* 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.
@@ -17,6 +17,7 @@
#include "tk.h"
#include "tkInt.h"
#include "tkPort.h"
+#include "tkCanvas.h"
/*
* The structure below defines the record for each rectangle/oval item.
@@ -25,14 +26,17 @@
typedef struct RectOvalItem {
Tk_Item header; /* Generic stuff that's the same for all
* types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
double bbox[4]; /* Coordinates of bounding box for rectangle
* or oval (x1, y1, x2, y2). Item includes
* x1 and x2 but not y1 and y2. */
- int width; /* Width of outline. */
- XColor *outlineColor; /* Color for outline. */
+ Tk_TSOffset tsoffset;
XColor *fillColor; /* Color for filling rectangle/oval. */
+ XColor *activeFillColor; /* Color for filling rectangle/oval if state is active. */
+ XColor *disabledFillColor; /* Color for filling rectangle/oval if state is disabled. */
Pixmap fillStipple; /* Stipple bitmap for filling item. */
- GC outlineGC; /* Graphics context for outline. */
+ Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is active. */
+ Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is disabled. */
GC fillGC; /* Graphics context for filling item. */
} RectOvalItem;
@@ -40,21 +44,93 @@ typedef struct RectOvalItem {
* Information used for parsing configuration specs:
*/
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
+static Tk_CustomOption dashOption = {
+ (Tk_OptionParseProc *) TkCanvasDashParseProc,
+ TkCanvasDashPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc, (ClientData) TK_OFFSET_RELATIVE
+};
+static Tk_CustomOption pixelOption = {
+ (Tk_OptionParseProc *) TkPixelParseProc,
+ TkPixelPrintProc, (ClientData) NULL
+};
static Tk_ConfigSpec configSpecs[] = {
+ {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, activeFillColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.activeColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, activeFillStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(RectOvalItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(RectOvalItem, outline.offset),
+ TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, disabledFillColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, disabledFillStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_PIXELS, "-disabledwidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(RectOvalItem, tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
{TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
- "black", Tk_Offset(RectOvalItem, outlineColor), TK_CONFIG_NULL_OK},
+ "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(RectOvalItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(RectOvalItem, outline.stipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
- {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
- "1", Tk_Offset(RectOvalItem, width), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
+ "1.0", Tk_Offset(RectOvalItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
@@ -67,10 +143,10 @@ static void ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas canvas,
RectOvalItem *rectOvalPtr));
static int ConfigureRectOval _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int CreateRectOval _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteRectOval _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayRectOval _ANSI_ARGS_((Tk_Canvas canvas,
@@ -82,7 +158,7 @@ static double OvalToPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *pointPtr));
static int RectOvalCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv));
+ Tcl_Obj *CONST argv[]));
static int RectOvalToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
static int RectToArea _ANSI_ARGS_((Tk_Canvas canvas,
@@ -109,7 +185,7 @@ Tk_ItemType tkRectangleType = {
RectOvalCoords, /* coordProc */
DeleteRectOval, /* deleteProc */
DisplayRectOval, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
RectToPoint, /* pointProc */
RectToArea, /* areaProc */
RectOvalToPostscript, /* postscriptProc */
@@ -120,7 +196,7 @@ Tk_ItemType tkRectangleType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
Tk_ItemType tkOvalType = {
@@ -132,7 +208,7 @@ Tk_ItemType tkOvalType = {
RectOvalCoords, /* coordProc */
DeleteRectOval, /* deleteProc */
DisplayRectOval, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
OvalToPoint, /* pointProc */
OvalToArea, /* areaProc */
RectOvalToPostscript, /* postscriptProc */
@@ -143,7 +219,7 @@ Tk_ItemType tkOvalType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -157,7 +233,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:
@@ -173,11 +249,25 @@ CreateRectOval(interp, canvas, itemPtr, argc, argv)
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_Obj *CONST argv[]; /* Arguments describing rectangle. */
{
RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
+ int i;
+
+
+ if (argc==1) {
+ i = 1;
+ } else {
+ char *arg = Tcl_GetStringFromObj(argv[1], NULL);
+ if ((argc>1) && (arg[0] == '-')
+ && (arg[1] >= 'a') && (arg[1] <= 'z')) {
+ i = 1;
+ } else {
+ i = 4;
+ }
+ }
- if (argc < 4) {
+ if (argc < i) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",
@@ -190,34 +280,33 @@ CreateRectOval(interp, canvas, itemPtr, argc, argv)
* up after errors during the the remainder of this procedure.
*/
- rectOvalPtr->width = 1;
- rectOvalPtr->outlineColor = NULL;
+ Tk_CreateOutline(&(rectOvalPtr->outline));
+ rectOvalPtr->tsoffset.flags = 0;
+ rectOvalPtr->tsoffset.xoffset = 0;
+ rectOvalPtr->tsoffset.yoffset = 0;
rectOvalPtr->fillColor = NULL;
+ rectOvalPtr->activeFillColor = NULL;
+ rectOvalPtr->disabledFillColor = NULL;
rectOvalPtr->fillStipple = None;
- rectOvalPtr->outlineGC = None;
+ rectOvalPtr->activeFillStipple = None;
+ rectOvalPtr->disabledFillStipple = None;
rectOvalPtr->fillGC = None;
/*
* Process the arguments to fill in the item record.
*/
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0],
- &rectOvalPtr->bbox[0]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
- &rectOvalPtr->bbox[1]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[2],
- &rectOvalPtr->bbox[2]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[3],
- &rectOvalPtr->bbox[3]) != TCL_OK)) {
- return TCL_ERROR;
+ if ((RectOvalCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
+ goto error;
}
-
- if (ConfigureRectOval(interp, canvas, itemPtr, argc-4, argv+4, 0)
- != TCL_OK) {
- DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
- return TCL_ERROR;
+ if (ConfigureRectOval(interp, canvas, itemPtr, argc-i, argv+i, 0)
+ == TCL_OK) {
+ return TCL_OK;
}
- return TCL_OK;
+
+ error:
+ DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
+ return TCL_ERROR;
}
/*
@@ -230,7 +319,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.
@@ -246,36 +335,51 @@ RectOvalCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
- char c0[TCL_DOUBLE_SPACE], c1[TCL_DOUBLE_SPACE];
- char c2[TCL_DOUBLE_SPACE], c3[TCL_DOUBLE_SPACE];
if (argc == 0) {
- Tcl_PrintDouble(interp, rectOvalPtr->bbox[0], c0);
- Tcl_PrintDouble(interp, rectOvalPtr->bbox[1], c1);
- Tcl_PrintDouble(interp, rectOvalPtr->bbox[2], c2);
- Tcl_PrintDouble(interp, rectOvalPtr->bbox[3], c3);
- Tcl_AppendResult(interp, c0, " ", c1, " ", c2, " ", c3,
- (char *) NULL);
- } else if (argc == 4) {
- if ((Tk_CanvasGetCoord(interp, canvas, argv[0],
- &rectOvalPtr->bbox[0]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[1],
+ Tcl_Obj *obj = Tcl_NewObj();
+ Tcl_Obj *subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
+ Tcl_SetObjResult(interp, obj);
+ } else if ((argc == 1)||(argc == 4)) {
+ if (argc==1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ } else if (argc != 4) {
+ 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;
+ }
+ }
+ if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0],
+ &rectOvalPtr->bbox[0]) != TCL_OK)
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
&rectOvalPtr->bbox[1]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[2],
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[2],
&rectOvalPtr->bbox[2]) != TCL_OK)
- || (Tk_CanvasGetCoord(interp, canvas, argv[3],
+ || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[3],
&rectOvalPtr->bbox[3]) != TCL_OK)) {
return TCL_ERROR;
}
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 +396,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
@@ -307,7 +411,7 @@ ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Rectangle item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
@@ -315,54 +419,136 @@ ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)
GC newGC;
unsigned long mask;
Tk_Window tkwin;
+ Tk_TSOffset *tsoffset;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) rectOvalPtr, flags) != TCL_OK) {
+
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) rectOvalPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
+ state = itemPtr->state;
/*
* A few of the options require additional processing, such as
* graphics contexts.
*/
- if (rectOvalPtr->width < 1) {
- rectOvalPtr->width = 1;
- }
- if (rectOvalPtr->outlineColor == NULL) {
- newGC = None;
+ if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width ||
+ rectOvalPtr->outline.activeDash.number != 0 ||
+ rectOvalPtr->outline.activeColor != NULL ||
+ rectOvalPtr->outline.activeStipple != None ||
+ rectOvalPtr->activeFillColor != NULL ||
+ rectOvalPtr->activeFillStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
} else {
- gcValues.foreground = rectOvalPtr->outlineColor->pixel;
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+
+ tsoffset = &rectOvalPtr->outline.tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
+ }
+
+ /*
+ * Configure the outline graphics context. If mask is non-zero,
+ * the gc has changed and must be reallocated, provided that the
+ * new settings specify a valid outline (non-zero width and non-NULL
+ * color)
+ */
+
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(rectOvalPtr->outline));
+ if (mask && \
+ rectOvalPtr->outline.width != 0 && \
+ rectOvalPtr->outline.color != NULL) {
gcValues.cap_style = CapProjecting;
- gcValues.line_width = rectOvalPtr->width;
- mask = GCForeground|GCCapStyle|GCLineWidth;
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues,
- rectOvalPtr->outlineColor, NULL);
+ mask |= GCCapStyle;
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = None;
+ }
+ if (rectOvalPtr->outline.gc != None) {
+ Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);
}
- if (rectOvalPtr->outlineGC != None) {
- Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outlineGC);
+ rectOvalPtr->outline.gc = newGC;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ ComputeRectOvalBbox(canvas, rectOvalPtr);
+ return TCL_OK;
}
- rectOvalPtr->outlineGC = newGC;
- if (rectOvalPtr->fillColor == NULL) {
+ color = rectOvalPtr->fillColor;
+ stipple = rectOvalPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (rectOvalPtr->activeFillColor!=NULL) {
+ color = rectOvalPtr->activeFillColor;
+ }
+ if (rectOvalPtr->activeFillStipple!=None) {
+ stipple = rectOvalPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (rectOvalPtr->disabledFillColor!=NULL) {
+ color = rectOvalPtr->disabledFillColor;
+ }
+ if (rectOvalPtr->disabledFillStipple!=None) {
+ stipple = rectOvalPtr->disabledFillStipple;
+ }
+ }
+
+ if (color == NULL) {
newGC = None;
} else {
- gcValues.foreground = rectOvalPtr->fillColor->pixel;
- if (rectOvalPtr->fillStipple != None) {
- gcValues.stipple = rectOvalPtr->fillStipple;
+ gcValues.foreground = color->pixel;
+ if (stipple != None) {
+ gcValues.stipple = stipple;
gcValues.fill_style = FillStippled;
mask = GCForeground|GCStipple|GCFillStyle;
} else {
mask = GCForeground;
}
- newGC = Tk_GetGCColor(tkwin, mask, &gcValues, rectOvalPtr->fillColor,
- NULL);
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
}
if (rectOvalPtr->fillGC != None) {
Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);
}
rectOvalPtr->fillGC = newGC;
+
+ tsoffset = &rectOvalPtr->tsoffset;
+ flags = tsoffset->flags;
+ if (flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
+ } else if (flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
+ } else if (flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
+ }
+ if (flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
+ } else if (flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
+ } else if (flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5);
+ }
+
ComputeRectOvalBbox(canvas, rectOvalPtr);
return TCL_OK;
@@ -394,17 +580,24 @@ DeleteRectOval(canvas, itemPtr, display)
{
RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
- if (rectOvalPtr->outlineColor != NULL) {
- Tk_FreeColor(rectOvalPtr->outlineColor);
- }
+ Tk_DeleteOutline(display, &(rectOvalPtr->outline));
if (rectOvalPtr->fillColor != NULL) {
Tk_FreeColor(rectOvalPtr->fillColor);
}
+ if (rectOvalPtr->activeFillColor != NULL) {
+ Tk_FreeColor(rectOvalPtr->activeFillColor);
+ }
+ if (rectOvalPtr->disabledFillColor != NULL) {
+ Tk_FreeColor(rectOvalPtr->disabledFillColor);
+ }
if (rectOvalPtr->fillStipple != None) {
Tk_FreeBitmap(display, rectOvalPtr->fillStipple);
}
- if (rectOvalPtr->outlineGC != None) {
- Tk_FreeGC(display, rectOvalPtr->outlineGC);
+ if (rectOvalPtr->activeFillStipple != None) {
+ Tk_FreeBitmap(display, rectOvalPtr->activeFillStipple);
+ }
+ if (rectOvalPtr->disabledFillStipple != None) {
+ Tk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);
}
if (rectOvalPtr->fillGC != None) {
Tk_FreeGC(display, rectOvalPtr->fillGC);
@@ -438,7 +631,28 @@ ComputeRectOvalBbox(canvas, rectOvalPtr)
* recomputed. */
{
int bloat, tmp;
- double dtmp;
+ double dtmp, width;
+ Tk_State state = rectOvalPtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = rectOvalPtr->outline.width;
+ if (state==TK_STATE_HIDDEN) {
+ rectOvalPtr->header.x1 = rectOvalPtr->header.y1 =
+ rectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1;
+ return;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {
+ if (rectOvalPtr->outline.activeWidth>width) {
+ width = rectOvalPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (rectOvalPtr->outline.disabledWidth>0) {
+ width = rectOvalPtr->outline.disabledWidth;
+ }
+ }
/*
* Make sure that the first coordinates are the lowest ones.
@@ -457,10 +671,19 @@ ComputeRectOvalBbox(canvas, rectOvalPtr)
rectOvalPtr->bbox[0] = tmp;
}
- if (rectOvalPtr->outlineColor == NULL) {
+ if (rectOvalPtr->outline.gc == None) {
+ /*
+ * The Win32 switch was added for 8.3 to solve a problem
+ * with ovals leaving traces on bottom and right of 1 pixel.
+ * This may not be the correct place to solve it, but it works.
+ */
+#ifdef __WIN32__
+ bloat = 1;
+#else
bloat = 0;
+#endif
} else {
- bloat = (rectOvalPtr->width+1)/2;
+ bloat = (int) (width+1)/2;
}
/*
@@ -519,6 +742,8 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)
{
RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
short x1, y1, x2, y2;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
/*
* Compute the screen coordinates of the bounding box for the item.
@@ -544,9 +769,48 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)
* read-only.
*/
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ fillStipple = rectOvalPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {
+ if (rectOvalPtr->activeFillStipple!=None) {
+ fillStipple = rectOvalPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (rectOvalPtr->disabledFillStipple!=None) {
+ fillStipple = rectOvalPtr->disabledFillStipple;
+ }
+ }
+
if (rectOvalPtr->fillGC != None) {
- if (rectOvalPtr->fillStipple != None) {
- Tk_CanvasSetStippleOrigin(canvas, rectOvalPtr->fillGC);
+ if (fillStipple != None) {
+ Tk_TSOffset *tsoffset;
+ int w=0; int h=0;
+ tsoffset = &rectOvalPtr->tsoffset;
+ if (tsoffset) {
+ int flags = tsoffset->flags;
+ if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
+ Tk_SizeOfBitmap(display, fillStipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ }
+ Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);
+ if (tsoffset) {
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ }
}
if (rectOvalPtr->header.typePtr == &tkRectangleType) {
XFillRectangle(display, drawable, rectOvalPtr->fillGC,
@@ -556,18 +820,20 @@ DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)
x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),
0, 360*64);
}
- if (rectOvalPtr->fillStipple != None) {
+ if (fillStipple != None) {
XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);
}
}
- if (rectOvalPtr->outlineGC != None) {
+ if (rectOvalPtr->outline.gc != None) {
+ Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
if (rectOvalPtr->header.typePtr == &tkRectangleType) {
- XDrawRectangle(display, drawable, rectOvalPtr->outlineGC,
+ XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,
x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));
} else {
- XDrawArc(display, drawable, rectOvalPtr->outlineGC,
+ XDrawArc(display, drawable, rectOvalPtr->outline.gc,
x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);
}
+ Tk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
}
}
@@ -603,6 +869,23 @@ RectToPoint(canvas, itemPtr, pointPtr)
{
RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = rectPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (rectPtr->outline.activeWidth>width) {
+ width = rectPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (rectPtr->outline.disabledWidth>0) {
+ width = rectPtr->outline.disabledWidth;
+ }
+ }
/*
* Generate a new larger rectangle that includes the border
@@ -613,8 +896,8 @@ RectToPoint(canvas, itemPtr, pointPtr)
y1 = rectPtr->bbox[1];
x2 = rectPtr->bbox[2];
y2 = rectPtr->bbox[3];
- if (rectPtr->outlineGC != None) {
- inc = rectPtr->width/2.0;
+ if (rectPtr->outline.gc != None) {
+ inc = width/2.0;
x1 -= inc;
y1 -= inc;
x2 += inc;
@@ -630,7 +913,7 @@ RectToPoint(canvas, itemPtr, pointPtr)
if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
&& (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
- if ((rectPtr->fillGC != None) || (rectPtr->outlineGC == None)) {
+ if ((rectPtr->fillGC != None) || (rectPtr->outline.gc == None)) {
return 0.0;
}
xDiff = pointPtr[0] - x1;
@@ -646,7 +929,7 @@ RectToPoint(canvas, itemPtr, pointPtr)
if (yDiff < xDiff) {
xDiff = yDiff;
}
- xDiff -= rectPtr->width;
+ xDiff -= width;
if (xDiff < 0.0) {
return 0.0;
}
@@ -709,10 +992,26 @@ OvalToPoint(canvas, itemPtr, pointPtr)
RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
double width;
int filled;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = (double) ovalPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (ovalPtr->outline.activeWidth>width) {
+ width = (double) ovalPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (ovalPtr->outline.disabledWidth>0) {
+ width = (double) ovalPtr->outline.disabledWidth;
+ }
+ }
+
- width = ovalPtr->width;
filled = ovalPtr->fillGC != None;
- if (ovalPtr->outlineGC == None) {
+ if (ovalPtr->outline.gc == None) {
width = 0.0;
filled = 1;
}
@@ -750,9 +1049,26 @@ RectToArea(canvas, itemPtr, areaPtr)
{
RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
double halfWidth;
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
- halfWidth = rectPtr->width/2.0;
- if (rectPtr->outlineGC == None) {
+ width = rectPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (rectPtr->outline.activeWidth>width) {
+ width = rectPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (rectPtr->outline.disabledWidth>0) {
+ width = rectPtr->outline.disabledWidth;
+ }
+ }
+
+ halfWidth = width/2.0;
+ if (rectPtr->outline.gc == None) {
halfWidth = 0.0;
}
@@ -762,7 +1078,7 @@ RectToArea(canvas, itemPtr, areaPtr)
|| (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
return -1;
}
- if ((rectPtr->fillGC == None) && (rectPtr->outlineGC != None)
+ if ((rectPtr->fillGC == None) && (rectPtr->outline.gc != None)
&& (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
&& (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
&& (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
@@ -810,13 +1126,30 @@ OvalToArea(canvas, itemPtr, areaPtr)
RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
double oval[4], halfWidth;
int result;
+ double width;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = ovalPtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (ovalPtr->outline.activeWidth>width) {
+ width = ovalPtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (ovalPtr->outline.disabledWidth>0) {
+ width = ovalPtr->outline.disabledWidth;
+ }
+ }
/*
* Expand the oval to include the width of the outline, if any.
*/
- halfWidth = ovalPtr->width/2.0;
- if (ovalPtr->outlineGC == None) {
+ halfWidth = width/2.0;
+ if (ovalPtr->outline.gc == None) {
halfWidth = 0.0;
}
oval[0] = ovalPtr->bbox[0] - halfWidth;
@@ -833,9 +1166,9 @@ OvalToArea(canvas, itemPtr, areaPtr)
* unfilled center, in which case we should return "outside".
*/
- if ((result == 0) && (ovalPtr->outlineGC != None)
+ if ((result == 0) && (ovalPtr->outline.gc != None)
&& (ovalPtr->fillGC == None)) {
- double centerX, centerY, width, height;
+ double centerX, centerY, height;
double xDelta1, yDelta1, xDelta2, yDelta2;
centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
@@ -944,7 +1277,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.
*
@@ -964,9 +1297,13 @@ 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;
+ XColor *color;
+ XColor *fillColor;
+ Pixmap fillStipple;
+ Tk_State state = itemPtr->state;
y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);
y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);
@@ -989,23 +1326,51 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass)
(rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);
}
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ color = rectOvalPtr->outline.color;
+ fillColor = rectOvalPtr->fillColor;
+ fillStipple = rectOvalPtr->fillStipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (rectOvalPtr->outline.activeColor!=NULL) {
+ color = rectOvalPtr->outline.activeColor;
+ }
+ if (rectOvalPtr->activeFillColor!=NULL) {
+ fillColor = rectOvalPtr->activeFillColor;
+ }
+ if (rectOvalPtr->activeFillStipple!=None) {
+ fillStipple = rectOvalPtr->activeFillStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (rectOvalPtr->outline.disabledColor!=NULL) {
+ color = rectOvalPtr->outline.disabledColor;
+ }
+ if (rectOvalPtr->disabledFillColor!=NULL) {
+ fillColor = rectOvalPtr->disabledFillColor;
+ }
+ if (rectOvalPtr->disabledFillStipple!=None) {
+ fillStipple = rectOvalPtr->disabledFillStipple;
+ }
+ }
+
/*
* First draw the filled area of the rectangle.
*/
- if (rectOvalPtr->fillColor != NULL) {
+ if (fillColor != NULL) {
Tcl_AppendResult(interp, pathCmd, (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, rectOvalPtr->fillColor)
+ if (Tk_CanvasPsColor(interp, canvas, fillColor)
!= TCL_OK) {
return TCL_ERROR;
}
- if (rectOvalPtr->fillStipple != None) {
+ if (fillStipple != None) {
Tcl_AppendResult(interp, "clip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, rectOvalPtr->fillStipple)
+ if (Tk_CanvasPsStipple(interp, canvas, fillStipple)
!= TCL_OK) {
return TCL_ERROR;
}
- if (rectOvalPtr->outlineColor != NULL) {
+ if (color != NULL) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
}
} else {
@@ -1017,16 +1382,15 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass)
* Now draw the outline, if there is one.
*/
- if (rectOvalPtr->outlineColor != NULL) {
- Tcl_AppendResult(interp, pathCmd, (char *) NULL);
- sprintf(string, "%d setlinewidth", rectOvalPtr->width);
- Tcl_AppendResult(interp, string,
- " 0 setlinejoin 2 setlinecap\n", (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, rectOvalPtr->outlineColor)
- != TCL_OK) {
+ if (color != NULL) {
+ Tcl_AppendResult(interp, pathCmd, "0 setlinejoin 2 setlinecap\n",
+ (char *) NULL);
+ if (Tk_CanvasPsOutline(canvas, itemPtr,
+ &(rectOvalPtr->outline))!= TCL_OK) {
return TCL_ERROR;
}
- Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
}
return TCL_OK;
}
+
+
diff --git a/tk/generic/tkScale.c b/tk/generic/tkScale.c
index ea579f587d3..fb88fc3da7f 100644
--- a/tk/generic/tkScale.c
+++ b/tk/generic/tkScale.c
@@ -12,7 +12,8 @@
* 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.
+ * Copyright (c) 1998-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -26,96 +27,133 @@
#include "tclMath.h"
#include "tkScale.h"
-static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_SCALE_ACTIVE_BG_COLOR, Tk_Offset(TkScale, activeBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-activebackground", "activeBackground", "Foreground",
- DEF_SCALE_ACTIVE_BG_MONO, Tk_Offset(TkScale, activeBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_SCALE_BG_COLOR, Tk_Offset(TkScale, bgBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_SCALE_BG_MONO, Tk_Offset(TkScale, bgBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
- DEF_SCALE_BIG_INCREMENT, Tk_Offset(TkScale, bigIncrement), 0},
- {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_SCALE_BORDER_WIDTH, Tk_Offset(TkScale, borderWidth), 0},
- {TK_CONFIG_STRING, "-command", "command", "Command",
- DEF_SCALE_COMMAND, Tk_Offset(TkScale, command), TK_CONFIG_NULL_OK},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_SCALE_CURSOR, Tk_Offset(TkScale, cursor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_INT, "-digits", "digits", "Digits",
- DEF_SCALE_DIGITS, Tk_Offset(TkScale, digits), 0},
- {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_FONT, "-font", "font", "Font",
- DEF_SCALE_FONT, Tk_Offset(TkScale, tkfont),
- 0},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_SCALE_FG_COLOR, Tk_Offset(TkScale, textColorPtr),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- DEF_SCALE_FG_MONO, Tk_Offset(TkScale, textColorPtr),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_DOUBLE, "-from", "from", "From",
- DEF_SCALE_FROM, Tk_Offset(TkScale, fromValue), 0},
- {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG,
- Tk_Offset(TkScale, highlightBgColorPtr), 0},
- {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_SCALE_HIGHLIGHT, Tk_Offset(TkScale, highlightColorPtr), 0},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness",
- DEF_SCALE_HIGHLIGHT_WIDTH, Tk_Offset(TkScale, highlightWidth), 0},
- {TK_CONFIG_STRING, "-label", "label", "Label",
- DEF_SCALE_LABEL, Tk_Offset(TkScale, label), TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-length", "length", "Length",
- DEF_SCALE_LENGTH, Tk_Offset(TkScale, length), 0},
- {TK_CONFIG_UID, "-orient", "orient", "Orient",
- DEF_SCALE_ORIENT, Tk_Offset(TkScale, orientUid), 0},
- {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
- DEF_SCALE_RELIEF, Tk_Offset(TkScale, relief), 0},
- {TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
- DEF_SCALE_REPEAT_DELAY, Tk_Offset(TkScale, repeatDelay), 0},
- {TK_CONFIG_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
- DEF_SCALE_REPEAT_INTERVAL, Tk_Offset(TkScale, repeatInterval), 0},
- {TK_CONFIG_DOUBLE, "-resolution", "resolution", "Resolution",
- DEF_SCALE_RESOLUTION, Tk_Offset(TkScale, resolution), 0},
- {TK_CONFIG_BOOLEAN, "-showvalue", "showValue", "ShowValue",
- DEF_SCALE_SHOW_VALUE, Tk_Offset(TkScale, showValue), 0},
- {TK_CONFIG_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
- DEF_SCALE_SLIDER_LENGTH, Tk_Offset(TkScale, sliderLength), 0},
- {TK_CONFIG_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
- DEF_SCALE_SLIDER_RELIEF, Tk_Offset(TkScale, sliderRelief),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_UID, "-state", "state", "State",
- DEF_SCALE_STATE, Tk_Offset(TkScale, state), 0},
- {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocus),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
- DEF_SCALE_TICK_INTERVAL, Tk_Offset(TkScale, tickInterval), 0},
- {TK_CONFIG_DOUBLE, "-to", "to", "To",
- DEF_SCALE_TO, Tk_Offset(TkScale, toValue), 0},
- {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
- DEF_SCALE_TROUGH_COLOR, Tk_Offset(TkScale, troughColorPtr),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-troughcolor", "troughColor", "Background",
- DEF_SCALE_TROUGH_MONO, Tk_Offset(TkScale, troughColorPtr),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_STRING, "-variable", "variable", "Variable",
- DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varName), TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-width", "width", "Width",
- DEF_SCALE_WIDTH, Tk_Offset(TkScale, width), 0},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
+/*
+ * The following table defines the legal values for the -orient option.
+ * It is used together with the "enum orient" declaration in tkScale.h.
+ */
+
+static char *orientStrings[] = {
+ "horizontal", "vertical", (char *) NULL
+};
+
+/*
+ * The following table defines the legal values for the -state option.
+ * It is used together with the "enum state" declaration in tkScale.h.
+ */
+
+static char *stateStrings[] = {
+ "active", "disabled", "normal", (char *) NULL
+};
+
+static Tk_OptionSpec optionSpecs[] = {
+ {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Foreground",
+ DEF_SCALE_ACTIVE_BG_COLOR, -1, Tk_Offset(TkScale, activeBorder),
+ 0, (ClientData) DEF_SCALE_ACTIVE_BG_MONO, 0},
+ {TK_OPTION_BORDER, "-background", "background", "Background",
+ DEF_SCALE_BG_COLOR, -1, Tk_Offset(TkScale, bgBorder),
+ 0, (ClientData) DEF_SCALE_BG_MONO, 0},
+ {TK_OPTION_DOUBLE, "-bigincrement", "bigIncrement", "BigIncrement",
+ DEF_SCALE_BIG_INCREMENT, -1, Tk_Offset(TkScale, bigIncrement),
+ 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
+ {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_SCALE_BORDER_WIDTH, -1, Tk_Offset(TkScale, borderWidth),
+ 0, 0, 0},
+ {TK_OPTION_STRING, "-command", "command", "Command",
+ DEF_SCALE_COMMAND, -1, Tk_Offset(TkScale, command),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_SCALE_CURSOR, -1, Tk_Offset(TkScale, cursor),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_INT, "-digits", "digits", "Digits",
+ DEF_SCALE_DIGITS, -1, Tk_Offset(TkScale, digits),
+ 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
+ {TK_OPTION_FONT, "-font", "font", "Font",
+ DEF_SCALE_FONT, -1, Tk_Offset(TkScale, tkfont), 0, 0, 0},
+ {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_SCALE_FG_COLOR, -1, Tk_Offset(TkScale, textColorPtr), 0,
+ (ClientData) DEF_SCALE_FG_MONO, 0},
+ {TK_OPTION_DOUBLE, "-from", "from", "From", DEF_SCALE_FROM, -1,
+ Tk_Offset(TkScale, fromValue), 0, 0, 0},
+ {TK_OPTION_BORDER, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_SCALE_HIGHLIGHT_BG_COLOR,
+ -1, Tk_Offset(TkScale, highlightBorder),
+ 0, (ClientData) DEF_SCALE_HIGHLIGHT_BG_MONO, 0},
+ {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_SCALE_HIGHLIGHT, -1, Tk_Offset(TkScale, highlightColorPtr),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_SCALE_HIGHLIGHT_WIDTH, -1,
+ Tk_Offset(TkScale, highlightWidth), 0, 0, 0},
+ {TK_OPTION_STRING, "-label", "label", "Label",
+ DEF_SCALE_LABEL, -1, Tk_Offset(TkScale, label),
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-length", "length", "Length",
+ DEF_SCALE_LENGTH, -1, Tk_Offset(TkScale, length), 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient",
+ DEF_SCALE_ORIENT, -1, Tk_Offset(TkScale, orient),
+ 0, (ClientData) orientStrings, 0},
+ {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
+ DEF_SCALE_RELIEF, -1, Tk_Offset(TkScale, relief), 0, 0, 0},
+ {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
+ DEF_SCALE_REPEAT_DELAY, -1, Tk_Offset(TkScale, repeatDelay),
+ 0, 0, 0},
+ {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
+ DEF_SCALE_REPEAT_INTERVAL, -1, Tk_Offset(TkScale, repeatInterval),
+ 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-resolution", "resolution", "Resolution",
+ DEF_SCALE_RESOLUTION, -1, Tk_Offset(TkScale, resolution),
+ 0, 0, 0},
+ {TK_OPTION_BOOLEAN, "-showvalue", "showValue", "ShowValue",
+ DEF_SCALE_SHOW_VALUE, -1, Tk_Offset(TkScale, showValue),
+ 0, 0, 0},
+ {TK_OPTION_PIXELS, "-sliderlength", "sliderLength", "SliderLength",
+ DEF_SCALE_SLIDER_LENGTH, -1, Tk_Offset(TkScale, sliderLength),
+ 0, 0, 0},
+ {TK_OPTION_RELIEF, "-sliderrelief", "sliderRelief", "SliderRelief",
+ DEF_SCALE_SLIDER_RELIEF, -1, Tk_Offset(TkScale, sliderRelief),
+ 0, 0, 0},
+ {TK_OPTION_STRING_TABLE, "-state", "state", "State",
+ DEF_SCALE_STATE, -1, Tk_Offset(TkScale, state),
+ 0, (ClientData) stateStrings, 0},
+ {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_SCALE_TAKE_FOCUS, Tk_Offset(TkScale, takeFocusPtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_DOUBLE, "-tickinterval", "tickInterval", "TickInterval",
+ DEF_SCALE_TICK_INTERVAL, -1, Tk_Offset(TkScale, tickInterval),
+ 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-to", "to", "To",
+ DEF_SCALE_TO, -1, Tk_Offset(TkScale, toValue), 0, 0, 0},
+ {TK_OPTION_COLOR, "-troughcolor", "troughColor", "Background",
+ DEF_SCALE_TROUGH_COLOR, -1, Tk_Offset(TkScale, troughColorPtr),
+ 0, (ClientData) DEF_SCALE_TROUGH_MONO, 0},
+ {TK_OPTION_STRING, "-variable", "variable", "Variable",
+ DEF_SCALE_VARIABLE, Tk_Offset(TkScale, varNamePtr), -1,
+ TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_PIXELS, "-width", "width", "Width",
+ DEF_SCALE_WIDTH, -1, Tk_Offset(TkScale, width), 0, 0, 0},
+ {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, 0, 0}
+};
+
+/*
+ * The following tables define the scale widget commands and map the
+ * indexes into the string tables into a single enumerated type used
+ * to dispatch the scale widget command.
+ */
+
+static char *commandNames[] = {
+ "cget", "configure", "coords", "get", "identify", "set", (char *) NULL
+};
+
+enum command {
+ COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_GET,
+ COMMAND_IDENTIFY, COMMAND_SET
};
/*
@@ -125,8 +163,8 @@ static Tk_ConfigSpec configSpecs[] = {
static void ComputeFormat _ANSI_ARGS_((TkScale *scalePtr));
static void ComputeScaleGeometry _ANSI_ARGS_((TkScale *scalePtr));
static int ConfigureScale _ANSI_ARGS_((Tcl_Interp *interp,
- TkScale *scalePtr, int argc, char **argv,
- int flags));
+ TkScale *scalePtr, int objc,
+ Tcl_Obj *CONST objv[]));
static void DestroyScale _ANSI_ARGS_((char *memPtr));
static void ScaleCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
@@ -135,10 +173,12 @@ static void ScaleEventProc _ANSI_ARGS_((ClientData clientData,
static char * ScaleVarProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, char *name1, char *name2,
int flags));
-static int ScaleWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+static int ScaleWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *CONST objv[]));
static void ScaleWorldChanged _ANSI_ARGS_((
ClientData instanceData));
+static void ScaleSetVariable _ANSI_ARGS_((TkScale *scalePtr));
/*
* The structure below defines scale class behavior by means of procedures
@@ -155,7 +195,7 @@ static TkClassProcs scaleClass = {
/*
*--------------------------------------------------------------
*
- * Tk_ScaleCmd --
+ * Tk_ScaleObjCmd --
*
* This procedure is invoked to process the "scale" Tcl
* command. See the user documentation for details on what
@@ -171,28 +211,48 @@ static TkClassProcs scaleClass = {
*/
int
-Tk_ScaleCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
+Tk_ScaleObjCmd(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. */
{
- Tk_Window tkwin = (Tk_Window) clientData;
register TkScale *scalePtr;
- Tk_Window new;
+ 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);
+ optionTable = Tk_CreateOptionTable(interp, optionSpecs);
+ 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;
}
- 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;
}
- scalePtr = TkpCreateScale(new);
+
+ Tk_SetClass(tkwin, "Scale");
+ scalePtr = TkpCreateScale(tkwin);
/*
* Initialize fields that won't be initialized by ConfigureScale,
@@ -200,79 +260,80 @@ Tk_ScaleCmd(clientData, interp, argc, argv)
* (e.g. resource pointers).
*/
- scalePtr->tkwin = new;
- scalePtr->display = Tk_Display(new);
- scalePtr->interp = interp;
- scalePtr->widgetCmd = Tcl_CreateCommand(interp,
- Tk_PathName(scalePtr->tkwin), ScaleWidgetCmd,
+ scalePtr->tkwin = tkwin;
+ scalePtr->display = Tk_Display(tkwin);
+ scalePtr->interp = interp;
+ scalePtr->widgetCmd = Tcl_CreateObjCommand(interp,
+ Tk_PathName(scalePtr->tkwin), ScaleWidgetObjCmd,
(ClientData) scalePtr, ScaleCmdDeletedProc);
- scalePtr->orientUid = NULL;
- scalePtr->vertical = 0;
- scalePtr->width = 0;
- scalePtr->length = 0;
- scalePtr->value = 0;
- scalePtr->varName = NULL;
- scalePtr->fromValue = 0;
- scalePtr->toValue = 0;
- scalePtr->tickInterval = 0;
- scalePtr->resolution = 1;
- scalePtr->bigIncrement = 0.0;
- scalePtr->command = NULL;
- scalePtr->repeatDelay = 0;
- scalePtr->repeatInterval = 0;
- scalePtr->label = NULL;
- scalePtr->labelLength = 0;
- scalePtr->state = tkNormalUid;
- scalePtr->borderWidth = 0;
- scalePtr->bgBorder = NULL;
- scalePtr->activeBorder = NULL;
- scalePtr->sliderRelief = TK_RELIEF_RAISED;
- scalePtr->troughColorPtr = NULL;
- scalePtr->troughGC = None;
- scalePtr->copyGC = None;
- scalePtr->tkfont = NULL;
- scalePtr->textColorPtr = NULL;
- scalePtr->textGC = None;
- scalePtr->relief = TK_RELIEF_FLAT;
- scalePtr->highlightWidth = 0;
- scalePtr->highlightBgColorPtr = NULL;
- scalePtr->highlightColorPtr = NULL;
- scalePtr->inset = 0;
- scalePtr->sliderLength = 0;
- scalePtr->showValue = 0;
- scalePtr->horizLabelY = 0;
- scalePtr->horizValueY = 0;
- scalePtr->horizTroughY = 0;
- scalePtr->horizTickY = 0;
- scalePtr->vertTickRightX = 0;
- scalePtr->vertValueRightX = 0;
- scalePtr->vertTroughX = 0;
- scalePtr->vertLabelX = 0;
- scalePtr->cursor = None;
- scalePtr->takeFocus = NULL;
- scalePtr->flags = NEVER_SET;
-
- Tk_SetClass(scalePtr->tkwin, "Scale");
+ scalePtr->optionTable = optionTable;
+ scalePtr->orient = ORIENT_VERTICAL;
+ scalePtr->width = 0;
+ scalePtr->length = 0;
+ scalePtr->value = 0.0;
+ scalePtr->varNamePtr = NULL;
+ scalePtr->fromValue = 0.0;
+ scalePtr->toValue = 0.0;
+ scalePtr->tickInterval = 0.0;
+ scalePtr->resolution = 1.0;
+ scalePtr->digits = 0;
+ scalePtr->bigIncrement = 0.0;
+ scalePtr->command = NULL;
+ scalePtr->repeatDelay = 0;
+ scalePtr->repeatInterval = 0;
+ scalePtr->label = NULL;
+ scalePtr->labelLength = 0;
+ scalePtr->state = STATE_NORMAL;
+ scalePtr->borderWidth = 0;
+ scalePtr->bgBorder = NULL;
+ scalePtr->activeBorder = NULL;
+ scalePtr->sliderRelief = TK_RELIEF_RAISED;
+ scalePtr->troughColorPtr = NULL;
+ scalePtr->troughGC = None;
+ scalePtr->copyGC = None;
+ scalePtr->tkfont = NULL;
+ scalePtr->textColorPtr = NULL;
+ scalePtr->textGC = None;
+ scalePtr->relief = TK_RELIEF_FLAT;
+ scalePtr->highlightWidth = 0;
+ scalePtr->highlightBorder = NULL;
+ scalePtr->highlightColorPtr = NULL;
+ scalePtr->inset = 0;
+ scalePtr->sliderLength = 0;
+ scalePtr->showValue = 0;
+ scalePtr->horizLabelY = 0;
+ scalePtr->horizValueY = 0;
+ scalePtr->horizTroughY = 0;
+ scalePtr->horizTickY = 0;
+ scalePtr->vertTickRightX = 0;
+ scalePtr->vertValueRightX = 0;
+ scalePtr->vertTroughX = 0;
+ scalePtr->vertLabelX = 0;
+ scalePtr->fontHeight = 0;
+ scalePtr->cursor = None;
+ scalePtr->takeFocusPtr = NULL;
+ scalePtr->flags = NEVER_SET;
+
TkSetClassProcs(scalePtr->tkwin, &scaleClass, (ClientData) scalePtr);
Tk_CreateEventHandler(scalePtr->tkwin,
ExposureMask|StructureNotifyMask|FocusChangeMask,
ScaleEventProc, (ClientData) scalePtr);
- if (ConfigureScale(interp, scalePtr, argc-2, argv+2, 0) != TCL_OK) {
- goto error;
+
+ if ((Tk_InitOptions(interp, (char *) scalePtr, optionTable, tkwin)
+ != TCL_OK) ||
+ (ConfigureScale(interp, scalePtr, objc - 2, objv + 2) != TCL_OK)) {
+ Tk_DestroyWindow(scalePtr->tkwin);
+ return TCL_ERROR;
}
- interp->result = Tk_PathName(scalePtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(scalePtr->tkwin), TCL_STATIC);
return TCL_OK;
-
- error:
- Tk_DestroyWindow(scalePtr->tkwin);
- return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
- * ScaleWidgetCmd --
+ * ScaleWidgetObjCmd --
*
* This procedure is invoked to process the Tcl command
* that corresponds to a widget managed by this module.
@@ -288,131 +349,152 @@ Tk_ScaleCmd(clientData, interp, argc, argv)
*/
static int
-ScaleWidgetCmd(clientData, interp, argc, argv)
+ScaleWidgetObjCmd(clientData, interp, objc, objv)
ClientData clientData; /* Information about scale
* 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 TkScale *scalePtr = (TkScale *) clientData;
- int result = TCL_OK;
- size_t length;
- int c;
+ TkScale *scalePtr = (TkScale *) clientData;
+ Tcl_Obj *objPtr;
+ int index, result;
- 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;
}
+ result = Tcl_GetIndexFromObj(interp, objv[1], commandNames,
+ "option", 0, &index);
+ if (result != TCL_OK) {
+ return result;
+ }
Tcl_Preserve((ClientData) scalePtr);
- 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, scalePtr->tkwin, configSpecs,
- (char *) scalePtr, argv[2], 0);
- } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
- && (length >= 3)) {
- if (argc == 2) {
- result = Tk_ConfigureInfo(interp, scalePtr->tkwin, configSpecs,
- (char *) scalePtr, (char *) NULL, 0);
- } else if (argc == 3) {
- result = Tk_ConfigureInfo(interp, scalePtr->tkwin, configSpecs,
- (char *) scalePtr, argv[2], 0);
- } else {
- result = ConfigureScale(interp, scalePtr, argc-2, argv+2,
- TK_CONFIG_ARGV_ONLY);
- }
- } else if ((c == 'c') && (strncmp(argv[1], "coords", length) == 0)
- && (length >= 3)) {
- int x, y ;
- double value;
-
- if ((argc != 2) && (argc != 3)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " coords ?value?\"", (char *) NULL);
- goto error;
- }
- if (argc == 3) {
- if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) {
+
+ switch (index) {
+ case COMMAND_CGET: {
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "cget option");
goto error;
}
- } else {
- value = scalePtr->value;
- }
- if (scalePtr->vertical) {
- x = scalePtr->vertTroughX + scalePtr->width/2
- + scalePtr->borderWidth;
- y = TkpValueToPixel(scalePtr, value);
- } else {
- x = TkpValueToPixel(scalePtr, value);
- y = scalePtr->horizTroughY + scalePtr->width/2
- + scalePtr->borderWidth;
+ objPtr = Tk_GetOptionValue(interp, (char *) scalePtr,
+ scalePtr->optionTable, objv[2], scalePtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ break;
}
- sprintf(interp->result, "%d %d", x, y);
- } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
- double value;
- int x, y;
-
- if ((argc != 2) && (argc != 4)) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " get ?x y?\"", (char *) NULL);
- goto error;
+ case COMMAND_CONFIGURE: {
+ if (objc <= 3) {
+ objPtr = Tk_GetOptionInfo(interp, (char *) scalePtr,
+ scalePtr->optionTable,
+ (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
+ scalePtr->tkwin);
+ if (objPtr == NULL) {
+ goto error;
+ } else {
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ } else {
+ result = ConfigureScale(interp, scalePtr, objc-2, objv+2);
+ }
+ break;
}
- if (argc == 2) {
- value = scalePtr->value;
- } else {
- if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
+ case COMMAND_COORDS: {
+ int x, y ;
+ double value;
+ char buf[TCL_INTEGER_SPACE * 2];
+
+ if ((objc != 2) && (objc != 3)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");
goto error;
}
- value = TkpPixelToValue(scalePtr, x, y);
- }
- sprintf(interp->result, scalePtr->format, value);
- } else if ((c == 'i') && (strncmp(argv[1], "identify", length) == 0)) {
- int x, y, thing;
-
- if (argc != 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " identify 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;
- }
- 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;
- }
- } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) {
- double value;
+ if (objc == 3) {
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &value)
+ != TCL_OK) {
+ goto error;
+ }
+ } else {
+ value = scalePtr->value;
+ }
+ if (scalePtr->orient == ORIENT_VERTICAL) {
+ x = scalePtr->vertTroughX + scalePtr->width/2
+ + scalePtr->borderWidth;
+ y = TkScaleValueToPixel(scalePtr, value);
+ } else {
+ x = TkScaleValueToPixel(scalePtr, value);
+ y = scalePtr->horizTroughY + scalePtr->width/2
+ + scalePtr->borderWidth;
+ }
+ sprintf(buf, "%d %d", x, y);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ case COMMAND_GET: {
+ double value;
+ int x, y;
+ char buf[TCL_DOUBLE_SPACE];
+
+ if ((objc != 2) && (objc != 4)) {
+ Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");
+ goto error;
+ }
+ if (objc == 2) {
+ value = scalePtr->value;
+ } else {
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y)
+ != TCL_OK)) {
+ goto error;
+ }
+ value = TkScalePixelToValue(scalePtr, x, y);
+ }
+ sprintf(buf, scalePtr->format, value);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
+ break;
+ }
+ case COMMAND_IDENTIFY: {
+ int x, y, thing;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "identify x y");
+ goto error;
+ }
+ if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
+ || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)) {
+ goto error;
+ }
+ thing = TkpScaleElement(scalePtr, x,y);
+ switch (thing) {
+ case TROUGH1:
+ Tcl_SetResult(interp, "trough1", TCL_STATIC);
+ break;
+ case SLIDER:
+ Tcl_SetResult(interp, "slider", TCL_STATIC);
+ break;
+ case TROUGH2:
+ Tcl_SetResult(interp, "trough2", TCL_STATIC);
+ break;
+ }
+ break;
+ }
+ case COMMAND_SET: {
+ double value;
- if (argc != 3) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " set value\"", (char *) NULL);
- goto error;
- }
- if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) {
- goto error;
- }
- if (scalePtr->state != tkDisabledUid) {
- TkpSetScaleValue(scalePtr, value, 1, 1);
- }
- } else {
- Tcl_AppendResult(interp, "bad option \"", argv[1],
- "\": must be cget, configure, coords, get, identify, or set",
- (char *) NULL);
- goto error;
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "set value");
+ goto error;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &value) != TCL_OK) {
+ goto error;
+ }
+ if (scalePtr->state != STATE_DISABLED) {
+ TkScaleSetValue(scalePtr, value, 1, 1);
+ }
+ break;
+ }
}
Tcl_Release((ClientData) scalePtr);
return result;
@@ -446,14 +528,21 @@ DestroyScale(memPtr)
{
register TkScale *scalePtr = (TkScale *) memPtr;
+ scalePtr->flags |= SCALE_DELETED;
+
+ Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
+ if (scalePtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(TkpDisplayScale, (ClientData) scalePtr);
+ }
+
/*
* Free up all the stuff that requires special handling, then
* let Tk_FreeOptions handle all the standard option-related
* stuff.
*/
- if (scalePtr->varName != NULL) {
- Tcl_UntraceVar(scalePtr->interp, scalePtr->varName,
+ if (scalePtr->varNamePtr != NULL) {
+ Tcl_UntraceVar(scalePtr->interp, Tcl_GetString(scalePtr->varNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ScaleVarProc, (ClientData) scalePtr);
}
@@ -466,7 +555,9 @@ DestroyScale(memPtr)
if (scalePtr->textGC != None) {
Tk_FreeGC(scalePtr->display, scalePtr->textGC);
}
- Tk_FreeOptions(configSpecs, (char *) scalePtr, scalePtr->display, 0);
+ Tk_FreeConfigOptions((char *) scalePtr, scalePtr->optionTable,
+ scalePtr->tkwin);
+ scalePtr->tkwin = NULL;
TkpDestroyScale(scalePtr);
}
@@ -481,7 +572,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,
@@ -492,118 +583,144 @@ DestroyScale(memPtr)
*/
static int
-ConfigureScale(interp, scalePtr, argc, argv, flags)
+ConfigureScale(interp, scalePtr, objc, objv)
Tcl_Interp *interp; /* Used for error reporting. */
register TkScale *scalePtr; /* Information about widget; may or may
* not already have values for some fields. */
- int 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 objv. */
+ Tcl_Obj *CONST objv[]; /* Argument values. */
{
- size_t length;
+ Tk_SavedOptions savedOptions;
+ Tcl_Obj *errorResult = NULL;
+ int error;
+ double oldValue = scalePtr->value;
/*
* Eliminate any existing trace on a variable monitored by the scale.
*/
- if (scalePtr->varName != NULL) {
- Tcl_UntraceVar(interp, scalePtr->varName,
+ if (scalePtr->varNamePtr != NULL) {
+ Tcl_UntraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ScaleVarProc, (ClientData) scalePtr);
}
- if (Tk_ConfigureWidget(interp, scalePtr->tkwin, configSpecs,
- argc, argv, (char *) scalePtr, flags) != TCL_OK) {
- return TCL_ERROR;
- }
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
- /*
- * If the scale is tied to the value of a variable, then set up
- * a trace on the variable's value and set the scale's value from
- * the value of the variable, if it exists.
- */
+ if (Tk_SetOptions(interp, (char *) scalePtr,
+ scalePtr->optionTable, objc, objv,
+ scalePtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
- if (scalePtr->varName != NULL) {
- char *stringValue, *end;
- double value;
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
+
+ /*
+ * If the scale is tied to the value of a variable, then set
+ * the scale's value from the value of the variable, if it exists
+ * and it holds a valid double value.
+ */
- stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY);
- if (stringValue != NULL) {
- value = strtod(stringValue, &end);
- if ((end != stringValue) && (*end == 0)) {
+ if (scalePtr->varNamePtr != NULL) {
+ double value;
+ Tcl_Obj *valuePtr;
+
+ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ if ((valuePtr != NULL) &&
+ (Tcl_GetDoubleFromObj(NULL, valuePtr, &value) == TCL_OK)) {
scalePtr->value = TkRoundToResolution(scalePtr, value);
}
}
- Tcl_TraceVar(interp, scalePtr->varName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- ScaleVarProc, (ClientData) scalePtr);
- }
- /*
- * Several options need special processing, such as parsing the
- * orientation and creating GCs.
- */
+ /*
+ * Several options need special processing, such as parsing the
+ * orientation and creating GCs.
+ */
- length = strlen(scalePtr->orientUid);
- if (strncmp(scalePtr->orientUid, "vertical", length) == 0) {
- scalePtr->vertical = 1;
- } else if (strncmp(scalePtr->orientUid, "horizontal", length) == 0) {
- scalePtr->vertical = 0;
- } else {
- Tcl_AppendResult(interp, "bad orientation \"", scalePtr->orientUid,
- "\": must be vertical or horizontal", (char *) NULL);
- return TCL_ERROR;
- }
+ scalePtr->fromValue = TkRoundToResolution(scalePtr,
+ scalePtr->fromValue);
+ scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
+ scalePtr->tickInterval = TkRoundToResolution(scalePtr,
+ scalePtr->tickInterval);
- scalePtr->fromValue = TkRoundToResolution(scalePtr, scalePtr->fromValue);
- scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue);
- scalePtr->tickInterval = TkRoundToResolution(scalePtr,
- scalePtr->tickInterval);
+ /*
+ * Make sure that the tick interval has the right sign so that
+ * addition moves from fromValue to toValue.
+ */
- /*
- * Make sure that the tick interval has the right sign so that
- * addition moves from fromValue to toValue.
- */
+ if ((scalePtr->tickInterval < 0)
+ ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) {
+ scalePtr->tickInterval = -scalePtr->tickInterval;
+ }
+
+ ComputeFormat(scalePtr);
- if ((scalePtr->tickInterval < 0)
- ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) {
- scalePtr->tickInterval = -scalePtr->tickInterval;
+ scalePtr->labelLength = scalePtr->label ? strlen(scalePtr->label) : 0;
+
+ Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);
+
+ if (scalePtr->highlightWidth < 0) {
+ scalePtr->highlightWidth = 0;
+ }
+ scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
+ break;
+ }
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
}
/*
* Set the scale value to itself; all this does is to make sure
* that the scale's value is within the new acceptable range for
- * the scale and reflect the value in the associated variable,
- * if any.
+ * the scale. We don't set the var here because we need to make
+ * special checks for possibly changed varNamePtr.
*/
- ComputeFormat(scalePtr);
- TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
-
- if (scalePtr->label != NULL) {
- scalePtr->labelLength = strlen(scalePtr->label);
- } else {
- scalePtr->labelLength = 0;
- }
+ TkScaleSetValue(scalePtr, scalePtr->value, 0, 1);
- if ((scalePtr->state != tkNormalUid)
- && (scalePtr->state != tkDisabledUid)
- && (scalePtr->state != tkActiveUid)) {
- Tcl_AppendResult(interp, "bad state value \"", scalePtr->state,
- "\": must be normal, active, or disabled", (char *) NULL);
- scalePtr->state = tkNormalUid;
- return TCL_ERROR;
- }
+ /*
+ * Reestablish the variable trace, if it is needed.
+ */
- Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder);
+ if (scalePtr->varNamePtr != NULL) {
+ Tcl_Obj *valuePtr;
- if (scalePtr->highlightWidth < 0) {
- scalePtr->highlightWidth = 0;
+ /*
+ * Set the associated variable only when the new value differs
+ * from the current value, or the variable doesn't yet exist
+ */
+ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ if ((valuePtr == NULL) || (scalePtr->value != oldValue)
+ || (Tcl_GetDoubleFromObj(NULL, valuePtr, &oldValue) != TCL_OK)
+ || (scalePtr->value != oldValue)) {
+ ScaleSetVariable(scalePtr);
+ }
+ Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ScaleVarProc, (ClientData) scalePtr);
}
- scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth;
ScaleWorldChanged((ClientData) scalePtr);
- return TCL_OK;
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
}
/*
@@ -635,8 +752,7 @@ ScaleWorldChanged(instanceData)
scalePtr = (TkScale *) instanceData;
gcValues.foreground = scalePtr->troughColorPtr->pixel;
- gc = Tk_GetGCColor(scalePtr->tkwin, GCForeground, &gcValues,
- scalePtr->troughColorPtr, NULL);
+ gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues);
if (scalePtr->troughGC != None) {
Tk_FreeGC(scalePtr->display, scalePtr->troughGC);
}
@@ -644,8 +760,7 @@ ScaleWorldChanged(instanceData)
gcValues.font = Tk_FontId(scalePtr->tkfont);
gcValues.foreground = scalePtr->textColorPtr->pixel;
- gc = Tk_GetGCColor(scalePtr->tkwin, GCForeground | GCFont, &gcValues,
- scalePtr->textColorPtr, NULL);
+ gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues);
if (scalePtr->textGC != None) {
Tk_FreeGC(scalePtr->display, scalePtr->textGC);
}
@@ -804,24 +919,26 @@ ComputeScaleGeometry(scalePtr)
int tmp, valuePixels, x, y, extraSpace;
Tk_FontMetrics fm;
+ Tk_GetFontMetrics(scalePtr->tkfont, &fm);
+ scalePtr->fontHeight = fm.linespace + SPACING;
+
/*
* Horizontal scales are simpler than vertical ones because
* all sizes are the same (the height of a line of text);
* handle them first and then quit.
*/
- Tk_GetFontMetrics(scalePtr->tkfont, &fm);
- if (!scalePtr->vertical) {
+ if (scalePtr->orient == ORIENT_HORIZONTAL) {
y = scalePtr->inset;
extraSpace = 0;
if (scalePtr->labelLength != 0) {
scalePtr->horizLabelY = y + SPACING;
- y += fm.linespace + SPACING;
+ y += scalePtr->fontHeight;
extraSpace = SPACING;
}
if (scalePtr->showValue) {
scalePtr->horizValueY = y + SPACING;
- y += fm.linespace + SPACING;
+ y += scalePtr->fontHeight;
extraSpace = SPACING;
} else {
scalePtr->horizValueY = y;
@@ -831,7 +948,7 @@ ComputeScaleGeometry(scalePtr)
y += scalePtr->width + 2*scalePtr->borderWidth;
if (scalePtr->tickInterval != 0) {
scalePtr->horizTickY = y + SPACING;
- y += fm.linespace + 2*SPACING;
+ y += scalePtr->fontHeight + SPACING;
}
Tk_GeometryRequest(scalePtr->tkwin,
scalePtr->length + 2*scalePtr->inset, y + scalePtr->inset);
@@ -884,8 +1001,8 @@ ComputeScaleGeometry(scalePtr)
} else {
scalePtr->vertLabelX = x + fm.ascent/2;
x = scalePtr->vertLabelX + fm.ascent/2
- + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,
- scalePtr->labelLength);
+ + Tk_TextWidth(scalePtr->tkfont, scalePtr->label,
+ scalePtr->labelLength);
}
Tk_GeometryRequest(scalePtr->tkwin, x + scalePtr->inset,
scalePtr->length + 2*scalePtr->inset);
@@ -920,14 +1037,7 @@ ScaleEventProc(clientData, eventPtr)
if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
} else if (eventPtr->type == DestroyNotify) {
- if (scalePtr->tkwin != NULL) {
- scalePtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(scalePtr->interp, scalePtr->widgetCmd);
- }
- if (scalePtr->flags & REDRAW_ALL) {
- Tcl_CancelIdleCall(TkpDisplayScale, (ClientData) scalePtr);
- }
- Tcl_EventuallyFree((ClientData) scalePtr, DestroyScale);
+ DestroyScale((char *) clientData);
} else if (eventPtr->type == ConfigureNotify) {
ComputeScaleGeometry(scalePtr);
TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
@@ -980,8 +1090,8 @@ ScaleCmdDeletedProc(clientData)
* destroys the widget.
*/
- if (tkwin != NULL) {
- scalePtr->tkwin = NULL;
+ if (!(scalePtr->flags & SCALE_DELETED)) {
+ scalePtr->flags |= SCALE_DELETED;
Tk_DestroyWindow(tkwin);
}
}
@@ -1015,7 +1125,8 @@ TkEventuallyRedrawScale(scalePtr, what)
|| !Tk_IsMapped(scalePtr->tkwin)) {
return;
}
- if ((scalePtr->flags & REDRAW_ALL) == 0) {
+ if (!(scalePtr->flags & REDRAW_PENDING)) {
+ scalePtr->flags |= REDRAW_PENDING;
Tcl_DoWhenIdle(TkpDisplayScale, (ClientData) scalePtr);
}
scalePtr->flags |= what;
@@ -1043,20 +1154,21 @@ TkRoundToResolution(scalePtr, value)
TkScale *scalePtr; /* Information about scale widget. */
double value; /* Value to round. */
{
- double rem, new;
+ double rem, new, tick;
if (scalePtr->resolution <= 0) {
return value;
}
- new = scalePtr->resolution * floor(value/scalePtr->resolution);
+ tick = floor(value/scalePtr->resolution);
+ new = scalePtr->resolution * tick;
rem = value - new;
if (rem < 0) {
if (rem <= -scalePtr->resolution/2) {
- new -= scalePtr->resolution;
+ new = (tick - 1.0) * scalePtr->resolution;
}
} else {
if (rem >= scalePtr->resolution/2) {
- new += scalePtr->resolution;
+ new = (tick + 1.0) * scalePtr->resolution;
}
}
return new;
@@ -1091,8 +1203,10 @@ ScaleVarProc(clientData, interp, name1, name2, flags)
int flags; /* Information about what happened. */
{
register TkScale *scalePtr = (TkScale *) clientData;
- char *stringValue, *end, *result;
+ char *resultStr;
double value;
+ Tcl_Obj *valuePtr;
+ int result;
/*
* If the variable is unset, then immediately recreate it unless
@@ -1101,17 +1215,17 @@ ScaleVarProc(clientData, interp, name1, name2, flags)
if (flags & TCL_TRACE_UNSETS) {
if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
- Tcl_TraceVar(interp, scalePtr->varName,
+ Tcl_TraceVar(interp, Tcl_GetString(scalePtr->varNamePtr),
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ScaleVarProc, clientData);
scalePtr->flags |= NEVER_SET;
- TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
+ TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);
}
return (char *) NULL;
}
/*
- * If we came here because we updated the variable (in TkpSetScaleValue),
+ * If we came here because we updated the variable (in TkScaleSetValue),
* then ignore the trace. Otherwise update the scale with the value
* of the variable.
*/
@@ -1119,27 +1233,216 @@ ScaleVarProc(clientData, interp, name1, name2, flags)
if (scalePtr->flags & SETTING_VAR) {
return (char *) NULL;
}
- result = NULL;
- stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY);
- if (stringValue != NULL) {
- value = strtod(stringValue, &end);
- if ((end == stringValue) || (*end != 0)) {
- result = "can't assign non-numeric value to scale variable";
- } else {
- scalePtr->value = TkRoundToResolution(scalePtr, value);
- }
+ resultStr = NULL;
+ valuePtr = Tcl_ObjGetVar2(interp, scalePtr->varNamePtr, NULL,
+ TCL_GLOBAL_ONLY);
+ result = Tcl_GetDoubleFromObj(interp, valuePtr, &value);
+ if (result != TCL_OK) {
+ resultStr = "can't assign non-numeric value to scale variable";
+ ScaleSetVariable(scalePtr);
+ } else {
+ scalePtr->value = TkRoundToResolution(scalePtr, value);
/*
* This code is a bit tricky because it sets the scale's value before
- * calling TkpSetScaleValue. This way, TkpSetScaleValue won't bother
+ * calling TkScaleSetValue. This way, TkScaleSetValue won't bother
* to set the variable again or to invoke the -command. However, it
* also won't redisplay the scale, so we have to ask for that
* explicitly.
*/
- TkpSetScaleValue(scalePtr, scalePtr->value, 1, 0);
- TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
+ TkScaleSetValue(scalePtr, scalePtr->value, 1, 0);
}
+ TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
- return result;
+ return resultStr;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkScaleSetValue --
+ *
+ * This procedure changes the value of a scale and invokes
+ * a Tcl command to reflect the current position of a scale
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A Tcl command is invoked, and an additional error-processing
+ * command may also be invoked. The scale's slider is redrawn.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkScaleSetValue(scalePtr, value, setVar, invokeCommand)
+ register TkScale *scalePtr; /* Info about widget. */
+ double value; /* New value for scale. Gets adjusted
+ * if it's off the scale. */
+ int setVar; /* Non-zero means reflect new value through
+ * to associated variable, if any. */
+ int invokeCommand; /* Non-zero means invoked -command option
+ * to notify of new value, 0 means don't. */
+{
+ value = TkRoundToResolution(scalePtr, value);
+ if ((value < scalePtr->fromValue)
+ ^ (scalePtr->toValue < scalePtr->fromValue)) {
+ value = scalePtr->fromValue;
+ }
+ if ((value > scalePtr->toValue)
+ ^ (scalePtr->toValue < scalePtr->fromValue)) {
+ value = scalePtr->toValue;
+ }
+ if (scalePtr->flags & NEVER_SET) {
+ scalePtr->flags &= ~NEVER_SET;
+ } else if (scalePtr->value == value) {
+ return;
+ }
+ scalePtr->value = value;
+ if (invokeCommand) {
+ scalePtr->flags |= INVOKE_COMMAND;
+ }
+ TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
+
+ if (setVar && scalePtr->varNamePtr) {
+ ScaleSetVariable(scalePtr);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ScaleSetVariable --
+ *
+ * This procedure sets the variable associated with a scale, if any.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Other write traces on the variable will trigger.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+ScaleSetVariable(scalePtr)
+ register TkScale *scalePtr; /* Info about widget. */
+{
+ if (scalePtr->varNamePtr != NULL) {
+ char string[PRINT_CHARS];
+ sprintf(string, scalePtr->format, scalePtr->value);
+ scalePtr->flags |= SETTING_VAR;
+ Tcl_ObjSetVar2(scalePtr->interp, scalePtr->varNamePtr, NULL,
+ Tcl_NewStringObj(string, -1), TCL_GLOBAL_ONLY);
+ scalePtr->flags &= ~SETTING_VAR;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScalePixelToValue --
+ *
+ * Given a pixel within a scale window, return the scale
+ * reading corresponding to that pixel.
+ *
+ * Results:
+ * A double-precision scale reading. If the value is outside
+ * the legal range for the scale then it's rounded to the nearest
+ * end of the scale.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+TkScalePixelToValue(scalePtr, x, y)
+ register TkScale *scalePtr; /* Information about widget. */
+ int x, y; /* Coordinates of point within
+ * window. */
+{
+ double value, pixelRange;
+
+ if (scalePtr->orient == ORIENT_VERTICAL) {
+ pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ value = y;
+ } else {
+ pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength
+ - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ value = x;
+ }
+
+ if (pixelRange <= 0) {
+ /*
+ * Not enough room for the slider to actually slide: just return
+ * the scale's current value.
+ */
+
+ return scalePtr->value;
+ }
+ value -= scalePtr->sliderLength/2 + scalePtr->inset
+ + scalePtr->borderWidth;
+ value /= pixelRange;
+ if (value < 0) {
+ value = 0;
+ }
+ if (value > 1) {
+ value = 1;
+ }
+ value = scalePtr->fromValue +
+ value * (scalePtr->toValue - scalePtr->fromValue);
+ return TkRoundToResolution(scalePtr, value);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScaleValueToPixel --
+ *
+ * Given a reading of the scale, return the x-coordinate or
+ * y-coordinate corresponding to that reading, depending on
+ * whether the scale is vertical or horizontal, respectively.
+ *
+ * Results:
+ * An integer value giving the pixel location corresponding
+ * to reading. The value is restricted to lie within the
+ * defined range for the scale.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkScaleValueToPixel(scalePtr, value)
+ register TkScale *scalePtr; /* Information about widget. */
+ double value; /* Reading of the widget. */
+{
+ int y, pixelRange;
+ double valueRange;
+
+ valueRange = scalePtr->toValue - scalePtr->fromValue;
+ pixelRange = ((scalePtr->orient == ORIENT_VERTICAL)
+ ? Tk_Height(scalePtr->tkwin) : Tk_Width(scalePtr->tkwin))
+ - scalePtr->sliderLength - 2*scalePtr->inset - 2*scalePtr->borderWidth;
+ if (valueRange == 0) {
+ y = 0;
+ } else {
+ y = (int) ((value - scalePtr->fromValue) * pixelRange
+ / valueRange + 0.5);
+ if (y < 0) {
+ y = 0;
+ } else if (y > pixelRange) {
+ y = pixelRange;
+ }
+ }
+ y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;
+ return y;
}
diff --git a/tk/generic/tkScale.h b/tk/generic/tkScale.h
index ee676f3a903..8168aa7171f 100644
--- a/tk/generic/tkScale.h
+++ b/tk/generic/tkScale.h
@@ -5,6 +5,7 @@
* the scale widget.
*
* Copyright (c) 1996 by Sun Microsystems, Inc.
+ * Copyright (c) 1999-2000 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -25,6 +26,22 @@
#endif
/*
+ * Legal values for the "orient" field of TkScale records.
+ */
+
+enum orient {
+ ORIENT_HORIZONTAL, ORIENT_VERTICAL
+};
+
+/*
+ * Legal values for the "state" field of TkScale records.
+ */
+
+enum state {
+ STATE_ACTIVE, STATE_DISABLED, STATE_NORMAL
+};
+
+/*
* A data structure of the following type is kept for each scale
* widget managed by this file:
*/
@@ -39,16 +56,16 @@ typedef struct TkScale {
* freed even after tkwin has gone away. */
Tcl_Interp *interp; /* Interpreter associated with scale. */
Tcl_Command widgetCmd; /* Token for scale's widget command. */
- Tk_Uid orientUid; /* Orientation for window ("vertical" or
- * "horizontal"). */
- int vertical; /* Non-zero means vertical orientation,
- * zero means horizontal. */
+ Tk_OptionTable optionTable; /* Table that defines configuration options
+ * available for this widget. */
+ enum orient orient; /* Orientation for window (vertical or
+ * horizontal). */
int width; /* Desired narrow dimension of scale,
* in pixels. */
int length; /* Desired long dimension of scale,
* in pixels. */
double value; /* Current value of scale. */
- char *varName; /* Name of variable (malloc'ed) or NULL.
+ Tcl_Obj *varNamePtr; /* Name of variable or NULL.
* If non-NULL, scale's value tracks
* the contents of this variable and
* vice versa. */
@@ -56,8 +73,8 @@ typedef struct TkScale {
* scale. */
double toValue; /* Value corresponding to right or bottom
* of scale. */
- double tickInterval; /* Distance between tick marks; 0 means
- * don't display any tick marks. */
+ double tickInterval; /* Distance between tick marks;
+ * 0 means don't display any tick marks. */
double resolution; /* If > 0, all values are rounded to an
* even multiple of this value. */
int digits; /* Number of significant digits to print
@@ -67,20 +84,19 @@ typedef struct TkScale {
char format[10]; /* Sprintf conversion specifier computed from
* digits and other information. */
double bigIncrement; /* Amount to use for large increments to
- * scale value. (0 means we pick a value). */
+ * scale value. (0 means we pick a value). */
char *command; /* Command prefix to use when invoking Tcl
* commands because the scale value changed.
- * NULL means don't invoke commands.
- * Malloc'ed. */
+ * NULL means don't invoke commands. */
int repeatDelay; /* How long to wait before auto-repeating
* on scrolling actions (in ms). */
int repeatInterval; /* Interval between autorepeats (in ms). */
char *label; /* Label to display above or to right of
- * scale; NULL means don't display a
- * label. Malloc'ed. */
+ * scale; NULL means don't display a label. */
int labelLength; /* Number of non-NULL chars. in label. */
- Tk_Uid state; /* Normal or disabled. Value cannot be
- * changed when scale is disabled. */
+ enum state state; /* Values are active, normal, or disabled.
+ * Value of scale cannot be changed when
+ * disabled. */
/*
* Information used when displaying widget:
@@ -90,7 +106,8 @@ typedef struct TkScale {
Tk_3DBorder bgBorder; /* Used for drawing slider and other
* background areas. */
Tk_3DBorder activeBorder; /* For drawing the slider when active. */
- int sliderRelief; /* Is slider to be drawn raised, sunken, etc. */
+ int sliderRelief; /* Is slider to be drawn raised, sunken,
+ * etc. */
XColor *troughColorPtr; /* Color for drawing trough. */
GC troughGC; /* For drawing trough. */
GC copyGC; /* Used for copying from pixmap onto screen. */
@@ -102,9 +119,10 @@ typedef struct TkScale {
int highlightWidth; /* Width in pixels of highlight to draw
* around widget when it has the focus.
* <= 0 means don't draw a highlight. */
- XColor *highlightBgColorPtr;
- /* Color for drawing traversal highlight
- * area when highlight is off. */
+ 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; /* Color for drawing traversal highlight. */
int inset; /* Total width of all borders, including
* traversal highlight and 3-D border.
@@ -114,7 +132,7 @@ typedef struct TkScale {
int sliderLength; /* Length of slider, measured in pixels along
* long dimension of scale. */
int showValue; /* Non-zero means to display the scale value
- * below or to the left of the slider; zero
+ * below or to the left of the slider; zero
* means don't display the value. */
/*
@@ -140,10 +158,11 @@ typedef struct TkScale {
* Miscellaneous information:
*/
+ int fontHeight; /* Height of scale font. */
Tk_Cursor cursor; /* Current cursor for window, or None. */
- 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. */
+ * scripts. May be NULL. */
int flags; /* Various flags; see below for
* definitions. */
} TkScale;
@@ -156,6 +175,7 @@ typedef struct TkScale {
* REDRAW_OTHER - 1 means other stuff besides slider and value
* need to be redrawn.
* REDRAW_ALL - 1 means the entire widget needs to be redrawn.
+ * REDRAW_PENDING - 1 means any sort of redraw is pending
* ACTIVE - 1 means the widget is active (the mouse is
* in its window).
* INVOKE_COMMAND - 1 means the scale's command needs to be
@@ -171,16 +191,19 @@ typedef struct TkScale {
* doesn't appear to have changed).
* GOT_FOCUS - 1 means that the focus is currently in
* this widget.
+ * SCALE_DELETED - 1 means the scale widget is being deleted
*/
-#define REDRAW_SLIDER 1
-#define REDRAW_OTHER 2
-#define REDRAW_ALL 3
-#define ACTIVE 4
-#define INVOKE_COMMAND 0x10
-#define SETTING_VAR 0x20
-#define NEVER_SET 0x40
-#define GOT_FOCUS 0x80
+#define REDRAW_SLIDER (1<<0)
+#define REDRAW_OTHER (1<<1)
+#define REDRAW_ALL (REDRAW_OTHER|REDRAW_SLIDER)
+#define REDRAW_PENDING (1<<2)
+#define ACTIVE (1<<3)
+#define INVOKE_COMMAND (1<<4)
+#define SETTING_VAR (1<<5)
+#define NEVER_SET (1<<6)
+#define GOT_FOCUS (1<<7)
+#define SCALE_DELETED (1<<8)
/*
* Symbolic values for the active parts of a slider. These are
@@ -207,7 +230,7 @@ typedef struct TkScale {
#define PRINT_CHARS 150
/*
- * Declaration of procedures used in the implementation of the scrollbar
+ * Declaration of procedures used in the implementation of the scale
* widget.
*/
@@ -218,16 +241,18 @@ EXTERN double TkRoundToResolution _ANSI_ARGS_((TkScale *scalePtr,
EXTERN TkScale * TkpCreateScale _ANSI_ARGS_((Tk_Window tkwin));
EXTERN void TkpDestroyScale _ANSI_ARGS_((TkScale *scalePtr));
EXTERN void TkpDisplayScale _ANSI_ARGS_((ClientData clientData));
-EXTERN double TkpPixelToValue _ANSI_ARGS_((TkScale *scalePtr,
- int x, int y));
EXTERN int TkpScaleElement _ANSI_ARGS_((TkScale *scalePtr,
int x, int y));
-EXTERN void TkpSetScaleValue _ANSI_ARGS_((TkScale *scalePtr,
+EXTERN void TkScaleSetValue _ANSI_ARGS_((TkScale *scalePtr,
double value, int setVar, int invokeCommand));
-EXTERN int TkpValueToPixel _ANSI_ARGS_((TkScale *scalePtr,
+EXTERN double TkScalePixelToValue _ANSI_ARGS_((TkScale *scalePtr,
+ int x, int y));
+EXTERN int TkScaleValueToPixel _ANSI_ARGS_((TkScale *scalePtr,
double value));
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKSCALE */
+
+
diff --git a/tk/generic/tkScrollbar.c b/tk/generic/tkScrollbar.c
index b49069a0a8a..d0f07c59000 100644
--- a/tk/generic/tkScrollbar.c
+++ b/tk/generic/tkScrollbar.c
@@ -20,6 +20,16 @@
#include "default.h"
/*
+ * Custom option for handling "-orient"
+ */
+
+static Tk_CustomOption orientOption = {
+ (Tk_OptionParseProc *) TkOrientParseProc,
+ TkOrientPrintProc,
+ (ClientData) NULL
+};
+
+/*
* Information used for argv parsing.
*/
@@ -63,8 +73,9 @@ Tk_ConfigSpec tkpScrollbarConfigSpecs[] = {
DEF_SCROLLBAR_HIGHLIGHT_WIDTH, Tk_Offset(TkScrollbar, highlightWidth), 0},
{TK_CONFIG_BOOLEAN, "-jump", "jump", "Jump",
DEF_SCROLLBAR_JUMP, Tk_Offset(TkScrollbar, jump), 0},
- {TK_CONFIG_UID, "-orient", "orient", "Orient",
- DEF_SCROLLBAR_ORIENT, Tk_Offset(TkScrollbar, orientUid), 0},
+ {TK_CONFIG_CUSTOM, "-orient", "orient", "Orient",
+ DEF_SCROLLBAR_ORIENT, Tk_Offset(TkScrollbar, vertical), 0,
+ &orientOption},
{TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
DEF_SCROLLBAR_RELIEF, Tk_Offset(TkScrollbar, relief), 0},
{TK_CONFIG_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
@@ -156,7 +167,6 @@ Tk_ScrollbarCmd(clientData, interp, argc, argv)
scrollPtr->widgetCmd = Tcl_CreateCommand(interp,
Tk_PathName(scrollPtr->tkwin), ScrollbarWidgetCmd,
(ClientData) scrollPtr, ScrollbarCmdDeletedProc);
- scrollPtr->orientUid = NULL;
scrollPtr->vertical = 0;
scrollPtr->width = 0;
scrollPtr->command = NULL;
@@ -193,7 +203,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 +250,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 +308,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 +333,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 +368,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 +383,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 +404,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 +521,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,
@@ -509,29 +542,16 @@ ConfigureScrollbar(interp, scrollPtr, argc, argv, flags)
int flags; /* Flags to pass to
* Tk_ConfigureWidget. */
{
- size_t length;
-
if (Tk_ConfigureWidget(interp, scrollPtr->tkwin, tkpScrollbarConfigSpecs,
argc, argv, (char *) scrollPtr, flags) != TCL_OK) {
return TCL_ERROR;
}
/*
- * A few options need special processing, such as parsing the
- * orientation or setting the background from a 3-D border.
+ * A few options need special processing, such as setting the
+ * background from a 3-D border.
*/
- length = strlen(scrollPtr->orientUid);
- if (strncmp(scrollPtr->orientUid, "vertical", length) == 0) {
- scrollPtr->vertical = 1;
- } else if (strncmp(scrollPtr->orientUid, "horizontal", length) == 0) {
- scrollPtr->vertical = 0;
- } else {
- Tcl_AppendResult(interp, "bad orientation \"", scrollPtr->orientUid,
- "\": must be vertical or horizontal", (char *) NULL);
- return TCL_ERROR;
- }
-
if (scrollPtr->command != NULL) {
scrollPtr->commandSize = strlen(scrollPtr->command);
} else {
@@ -689,3 +709,4 @@ TkScrollbarEventuallyRedraw(scrollPtr)
scrollPtr->flags |= REDRAW_PENDING;
}
}
+
diff --git a/tk/generic/tkScrollbar.h b/tk/generic/tkScrollbar.h
index fea8ea6b093..c6580640434 100644
--- a/tk/generic/tkScrollbar.h
+++ b/tk/generic/tkScrollbar.h
@@ -39,8 +39,6 @@ typedef struct TkScrollbar {
* freed even after tkwin has gone away. */
Tcl_Interp *interp; /* Interpreter associated with scrollbar. */
Tcl_Command widgetCmd; /* Token for scrollbar's widget command. */
- Tk_Uid orientUid; /* Orientation for window ("vertical" or
- * "horizontal"). */
int vertical; /* Non-zero means vertical orientation
* requested, zero means horizontal. */
int width; /* Desired narrow dimension of scrollbar,
@@ -206,3 +204,4 @@ EXTERN int TkpScrollbarPosition _ANSI_ARGS_((
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TKSCROLLBAR */
+
diff --git a/tk/generic/tkSelect.c b/tk/generic/tkSelect.c
index f97d5e411fe..45821e1e3b4 100644
--- a/tk/generic/tkSelect.c
+++ b/tk/generic/tkSelect.c
@@ -6,7 +6,7 @@
* 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.
@@ -26,6 +26,11 @@
typedef struct {
Tcl_Interp *interp; /* Interpreter in which to invoke command. */
int cmdLength; /* # of non-NULL bytes in command. */
+ int charOffset; /* The offset of the next char to retrieve. */
+ int byteOffset; /* The expected byte offset of the next
+ * chunk. */
+ char buffer[TCL_UTF_MAX]; /* A buffer to hold part of a UTF character
+ * that is split across chunks.*/
char command[4]; /* Command to invoke. Actual space is
* allocated as large as necessary. This
* must be the last entry in the structure. */
@@ -45,12 +50,16 @@ typedef struct LostCommand {
} LostCommand;
/*
- * Shared variables:
+ * The structure below is used to keep each thread's pending list
+ * separate.
*/
-TkSelInProgress *pendingPtr = NULL;
+typedef struct ThreadSpecificData {
+ TkSelInProgress *pendingPtr;
/* Topmost search in progress, or
* NULL if none. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
/*
* Forward declarations for procedures defined in this file:
@@ -199,6 +208,8 @@ Tk_DeleteSelHandler(tkwin, selection, target)
TkWindow *winPtr = (TkWindow *) tkwin;
register TkSelHandler *selPtr, *prevPtr;
register TkSelInProgress *ipPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Find the selection handler to be deleted, or return if it doesn't
@@ -220,7 +231,8 @@ Tk_DeleteSelHandler(tkwin, selection, target)
* handler is dead.
*/
- for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
if (ipPtr->selPtr == selPtr) {
ipPtr->selPtr = NULL;
}
@@ -236,7 +248,12 @@ Tk_DeleteSelHandler(tkwin, selection, target)
prevPtr->nextPtr = selPtr->nextPtr;
}
if (selPtr->proc == HandleTclCommand) {
- ckfree((char *) selPtr->clientData);
+ /*
+ * Mark the CommandInfo as deleted and free it if we can.
+ */
+
+ ((CommandInfo*)selPtr->clientData)->interp = NULL;
+ Tcl_EventuallyFree(selPtr->clientData, Tcl_Free);
}
ckfree((char *) selPtr);
}
@@ -431,7 +448,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 +474,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.
*
*--------------------------------------------------------------
@@ -480,6 +497,8 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData)
TkWindow *winPtr = (TkWindow *) tkwin;
TkDisplay *dispPtr = winPtr->dispPtr;
TkSelectionInfo *infoPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (dispPtr->multipleAtom == None) {
TkSelInit(tkwin);
@@ -528,13 +547,13 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData)
offset = 0;
result = TCL_OK;
ip.selPtr = selPtr;
- ip.nextPtr = pendingPtr;
- pendingPtr = &ip;
+ ip.nextPtr = tsdPtr->pendingPtr;
+ tsdPtr->pendingPtr = &ip;
while (1) {
count = (selPtr->proc)(selPtr->clientData, offset, buffer,
TK_SEL_BYTES_AT_ONCE);
if ((count < 0) || (ip.selPtr == NULL)) {
- pendingPtr = ip.nextPtr;
+ tsdPtr->pendingPtr = ip.nextPtr;
goto cantget;
}
if (count > TK_SEL_BYTES_AT_ONCE) {
@@ -548,7 +567,7 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData)
}
offset += count;
}
- pendingPtr = ip.nextPtr;
+ tsdPtr->pendingPtr = ip.nextPtr;
}
return result;
}
@@ -602,9 +621,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];
@@ -785,6 +803,9 @@ Tk_SelectionCmd(clientData, interp, argc, argv)
cmdInfoPtr = (CommandInfo *) ckalloc((unsigned) (
sizeof(CommandInfo) - 3 + cmdLength));
cmdInfoPtr->interp = interp;
+ cmdInfoPtr->charOffset = 0;
+ cmdInfoPtr->byteOffset = 0;
+ cmdInfoPtr->buffer[0] = '\0';
cmdInfoPtr->cmdLength = cmdLength;
strcpy(cmdInfoPtr->command, args[1]);
Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand,
@@ -854,7 +875,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 +899,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;
}
}
@@ -888,6 +908,60 @@ Tk_SelectionCmd(clientData, interp, argc, argv)
/*
*----------------------------------------------------------------------
*
+ * TkSelGetInProgress --
+ *
+ * This procedure returns a pointer to the thread-local
+ * list of pending searches.
+ *
+ * Results:
+ * The return value is a pointer to the first search in progress,
+ * or NULL if there are none.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkSelInProgress *
+TkSelGetInProgress _ANSI_ARGS_((void))
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->pendingPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkSelSetInProgress --
+ *
+ * This procedure is used to set the thread-local list of pending
+ * searches. It is required because the pending list is kept
+ * in thread local storage.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TkSelSetInProgress(pendingPtr)
+ TkSelInProgress *pendingPtr;
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->pendingPtr = pendingPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TkSelDeadWindow --
*
* This procedure is invoked just before a TkWindow is deleted.
@@ -909,6 +983,8 @@ TkSelDeadWindow(winPtr)
register TkSelHandler *selPtr;
register TkSelInProgress *ipPtr;
TkSelectionInfo *infoPtr, *prevPtr, *nextPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* While deleting all the handlers, be careful to check whether
@@ -919,13 +995,19 @@ TkSelDeadWindow(winPtr)
while (winPtr->selHandlerList != NULL) {
selPtr = winPtr->selHandlerList;
winPtr->selHandlerList = selPtr->nextPtr;
- for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
+ for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL;
+ ipPtr = ipPtr->nextPtr) {
if (ipPtr->selPtr == selPtr) {
ipPtr->selPtr = NULL;
}
}
if (selPtr->proc == HandleTclCommand) {
- ckfree((char *) selPtr->clientData);
+ /*
+ * Mark the CommandInfo as deleted and free it if we can.
+ */
+
+ ((CommandInfo*)selPtr->clientData)->interp = NULL;
+ Tcl_EventuallyFree(selPtr->clientData, Tcl_Free);
}
ckfree((char *) selPtr);
}
@@ -1120,21 +1202,42 @@ HandleTclCommand(clientData, offset, buffer, maxBytes)
int spaceNeeded, length;
#define MAX_STATIC_SIZE 100
char staticSpace[MAX_STATIC_SIZE];
- char *command;
- Tcl_Interp *interp;
+ char *command, *string;
+ Tcl_Interp *interp = cmdInfoPtr->interp;
Tcl_DString oldResult;
+ Tcl_Obj *objPtr;
+ int extraBytes, charOffset, count, numChars;
+ char *p;
/*
- * We must copy the interpreter pointer from CommandInfo because the
- * command could delete the handler, freeing the CommandInfo data before we
- * are done using it. We must also protect the interpreter from being
- * deleted too soo.
+ * We must also protect the interpreter and the command from being
+ * deleted too soon.
*/
- interp = cmdInfoPtr->interp;
+ Tcl_Preserve(clientData);
Tcl_Preserve((ClientData) interp);
/*
+ * Compute the proper byte offset in the case where the last chunk
+ * split a character.
+ */
+
+ if (offset == cmdInfoPtr->byteOffset) {
+ charOffset = cmdInfoPtr->charOffset;
+ extraBytes = strlen(cmdInfoPtr->buffer);
+ if (extraBytes > 0) {
+ strcpy(buffer, cmdInfoPtr->buffer);
+ maxBytes -= extraBytes;
+ buffer += extraBytes;
+ }
+ } else {
+ cmdInfoPtr->byteOffset = 0;
+ cmdInfoPtr->charOffset = 0;
+ extraBytes = 0;
+ charOffset = 0;
+ }
+
+ /*
* First, generate a command by taking the command string
* and appending the offset and maximum # of bytes.
*/
@@ -1145,7 +1248,7 @@ HandleTclCommand(clientData, offset, buffer, maxBytes)
} else {
command = (char *) ckalloc((unsigned) spaceNeeded);
}
- sprintf(command, "%s %d %d", cmdInfoPtr->command, offset, maxBytes);
+ sprintf(command, "%s %d %d", cmdInfoPtr->command, charOffset, maxBytes);
/*
* Execute the command. Be sure to restore the state of the
@@ -1155,14 +1258,41 @@ HandleTclCommand(clientData, offset, buffer, maxBytes)
Tcl_DStringInit(&oldResult);
Tcl_DStringGetResult(interp, &oldResult);
if (TkCopyAndGlobalEval(interp, command) == TCL_OK) {
- length = strlen(interp->result);
- if (length > maxBytes) {
- length = maxBytes;
+ objPtr = Tcl_GetObjResult(interp);
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ count = (length > maxBytes) ? maxBytes : length;
+ memcpy((VOID *) buffer, (VOID *) string, (size_t) count);
+ buffer[count] = '\0';
+
+ /*
+ * Update the partial character information for the next
+ * retrieval if the command has not been deleted.
+ */
+
+ if (cmdInfoPtr->interp != NULL) {
+ if (length <= maxBytes) {
+ cmdInfoPtr->charOffset += Tcl_NumUtfChars(string, -1);
+ cmdInfoPtr->buffer[0] = '\0';
+ } else {
+ p = string;
+ string += count;
+ numChars = 0;
+ while (p < string) {
+ p = Tcl_UtfNext(p);
+ numChars++;
+ }
+ cmdInfoPtr->charOffset += numChars;
+ length = p - string;
+ if (length > 0) {
+ strncpy(cmdInfoPtr->buffer, string, (size_t) length);
+ }
+ cmdInfoPtr->buffer[length] = '\0';
+ }
+ cmdInfoPtr->byteOffset += count + extraBytes;
}
- memcpy((VOID *) buffer, (VOID *) interp->result, (size_t) length);
- buffer[length] = '\0';
+ count += extraBytes;
} else {
- length = -1;
+ count = -1;
}
Tcl_DStringResult(interp, &oldResult);
@@ -1170,8 +1300,10 @@ HandleTclCommand(clientData, offset, buffer, maxBytes)
ckfree(command);
}
+
+ Tcl_Release(clientData);
Tcl_Release((ClientData) interp);
- return length;
+ return count;
}
/*
@@ -1299,11 +1431,10 @@ TkSelDefaultSelection(infoPtr, target, buffer, maxBytes, typePtr)
static void
LostSelection(clientData)
- ClientData clientData; /* Pointer to CommandInfo structure. */
+ ClientData clientData; /* Pointer to LostCommand structure. */
{
LostCommand *lostPtr = (LostCommand *) clientData;
- char *oldResultString;
- Tcl_FreeProc *oldFreeProc;
+ Tcl_Obj *objPtr;
Tcl_Interp *interp;
interp = lostPtr->interp;
@@ -1314,22 +1445,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);
@@ -1339,3 +1464,4 @@ LostSelection(clientData)
ckfree((char *) lostPtr);
}
+
diff --git a/tk/generic/tkSelect.h b/tk/generic/tkSelect.h
index 6065aa4b07d..7cce9bbc290 100644
--- a/tk/generic/tkSelect.h
+++ b/tk/generic/tkSelect.h
@@ -95,6 +95,10 @@ typedef struct TkSelRetrievalInfo {
int idleTime; /* Number of seconds that have gone by
* without hearing anything from the
* selection owner. */
+ Tcl_EncodingState encState; /* Holds intermediate state during translations
+ * of data that cross buffer boundaries. */
+ int encFlags; /* Encoding translation state flags. */
+ Tcl_DString buf; /* Buffer to hold translation data. */
struct TkSelRetrievalInfo *nextPtr;
/* Next in list of all pending
* selection retrievals. NULL means
@@ -146,14 +150,6 @@ typedef struct TkSelInProgress {
} TkSelInProgress;
/*
- * Declarations for variables shared among the selection-related files:
- */
-
-extern TkSelInProgress *pendingPtr;
- /* Topmost search in progress, or
- * NULL if none. */
-
-/*
* Chunk size for retrieving selection. It's defined both in
* words and in bytes; the word size is used to allocate
* buffer space that's guaranteed to be word-aligned and that
@@ -168,6 +164,11 @@ extern TkSelInProgress *pendingPtr;
* but shouldn't be used anywhere else in Tk (or by Tk clients):
*/
+extern TkSelInProgress *
+ TkSelGetInProgress _ANSI_ARGS_((void));
+extern void TkSelSetInProgress _ANSI_ARGS_((
+ TkSelInProgress *pendingPtr));
+
extern void TkSelClearSelection _ANSI_ARGS_((Tk_Window tkwin,
XEvent *eventPtr));
extern int TkSelDefaultSelection _ANSI_ARGS_((
@@ -182,3 +183,4 @@ extern void TkSelUpdateClipboard _ANSI_ARGS_((TkWindow *winPtr,
#endif
#endif /* _TKSELECT */
+
diff --git a/tk/generic/tkSend.c b/tk/generic/tkSend.c
new file mode 100644
index 00000000000..074ce5a33d7
--- /dev/null
+++ b/tk/generic/tkSend.c
@@ -0,0 +1,1867 @@
+/*
+ * tkSend.c --
+ *
+ * This file provides procedures that implement the "send"
+ * command, allowing commands to be passed from interpreter
+ * to interpreter.
+ *
+ * Copyright (c) 1989-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkSend.c 1.64 96/07/20 17:38:32
+ */
+
+#include "tkPort.h"
+#include "tkInt.h"
+
+/*
+ * The following structure is used to keep track of the interpreters
+ * registered by this process.
+ */
+
+typedef struct RegisteredInterp {
+ char *name; /* Interpreter's name (malloc-ed). */
+ Tcl_Interp *interp; /* Interpreter associated with name. NULL
+ * means that the application was unregistered
+ * or deleted while a send was in progress
+ * to it. */
+ TkDisplay *dispPtr; /* Display for the application. Needed
+ * because we may need to unregister the
+ * interpreter after its main window has
+ * been deleted. */
+ struct RegisteredInterp *nextPtr;
+ /* Next in list of names associated
+ * with interps in this process.
+ * NULL means end of list. */
+} RegisteredInterp;
+
+static RegisteredInterp *registry = NULL;
+ /* List of all interpreters
+ * registered by this process. */
+
+/*
+ * A registry of all interpreters for a display is kept in a
+ * property "InterpRegistry" on the root window of the display.
+ * It is organized as a series of zero or more concatenated strings
+ * (in no particular order), each of the form
+ * window space name '\0'
+ * where "window" is the hex id of the comm. window to use to talk
+ * to an interpreter named "name".
+ *
+ * When the registry is being manipulated by an application (e.g. to
+ * add or remove an entry), it is loaded into memory using a structure
+ * of the following type:
+ */
+
+typedef struct NameRegistry {
+ TkDisplay *dispPtr; /* Display from which the registry was
+ * read. */
+ int locked; /* Non-zero means that the display was
+ * locked when the property was read in. */
+ int modified; /* Non-zero means that the property has
+ * been modified, so it needs to be written
+ * out when the NameRegistry is closed. */
+ unsigned long propLength; /* Length of the property, in bytes. */
+ char *property; /* The contents of the property, or NULL
+ * if none. See format description above;
+ * this is *not* terminated by the first
+ * null character. Dynamically allocated. */
+ int allocedByX; /* Non-zero means must free property with
+ * XFree; zero means use ckfree. */
+} NameRegistry;
+
+/*
+ * When a result is being awaited from a sent command, one of
+ * the following structures is present on a list of all outstanding
+ * sent commands. The information in the structure is used to
+ * process the result when it arrives. You're probably wondering
+ * how there could ever be multiple outstanding sent commands.
+ * This could happen if interpreters invoke each other recursively.
+ * It's unlikely, but possible.
+ */
+
+typedef struct PendingCommand {
+ int serial; /* Serial number expected in
+ * result. */
+ TkDisplay *dispPtr; /* Display being used for communication. */
+ char *target; /* Name of interpreter command is
+ * being sent to. */
+ Window commWindow; /* Target's communication window. */
+ Tcl_Interp *interp; /* Interpreter from which the send
+ * was invoked. */
+ int code; /* Tcl return code for command
+ * will be stored here. */
+ char *result; /* String result for command (malloc'ed),
+ * or NULL. */
+ char *errorInfo; /* Information for "errorInfo" variable,
+ * or NULL (malloc'ed). */
+ char *errorCode; /* Information for "errorCode" variable,
+ * or NULL (malloc'ed). */
+ int gotResponse; /* 1 means a response has been received,
+ * 0 means the command is still outstanding. */
+ struct PendingCommand *nextPtr;
+ /* Next in list of all outstanding
+ * commands. NULL means end of
+ * list. */
+} PendingCommand;
+
+static PendingCommand *pendingCommands = NULL;
+ /* List of all commands currently
+ * being waited for. */
+
+/*
+ * The information below is used for communication between processes
+ * during "send" commands. Each process keeps a private window, never
+ * even mapped, with one property, "Comm". When a command is sent to
+ * an interpreter, the command is appended to the comm property of the
+ * communication window associated with the interp's process. Similarly,
+ * when a result is returned from a sent command, it is also appended
+ * to the comm property.
+ *
+ * Each command and each result takes the form of ASCII text. For a
+ * command, the text consists of a zero character followed by several
+ * null-terminated ASCII strings. The first string consists of the
+ * single letter "c". Subsequent strings have the form "option value"
+ * where the following options are supported:
+ *
+ * -r commWindow serial
+ *
+ * This option means that a response should be sent to the window
+ * whose X identifier is "commWindow" (in hex), and the response should
+ * be identified with the serial number given by "serial" (in decimal).
+ * If this option isn't specified then the send is asynchronous and
+ * no response is sent.
+ *
+ * -n name
+ * "Name" gives the name of the application for which the command is
+ * intended. This option must be present.
+ *
+ * -s script
+ *
+ * "Script" is the script to be executed. This option must be present.
+ *
+ * The options may appear in any order. The -n and -s options must be
+ * present, but -r may be omitted for asynchronous RPCs. For compatibility
+ * with future releases that may add new features, there may be additional
+ * options present; as long as they start with a "-" character, they will
+ * be ignored.
+ *
+ * A result also consists of a zero character followed by several null-
+ * terminated ASCII strings. The first string consists of the single
+ * letter "r". Subsequent strings have the form "option value" where
+ * the following options are supported:
+ *
+ * -s serial
+ *
+ * Identifies the command for which this is the result. It is the
+ * same as the "serial" field from the -s option in the command. This
+ * option must be present.
+ *
+ * -c code
+ *
+ * "Code" is the completion code for the script, in decimal. If the
+ * code is omitted it defaults to TCL_OK.
+ *
+ * -r result
+ *
+ * "Result" is the result string for the script, which may be either
+ * a result or an error message. If this field is omitted then it
+ * defaults to an empty string.
+ *
+ * -i errorInfo
+ *
+ * "ErrorInfo" gives a string with which to initialize the errorInfo
+ * variable. This option may be omitted; it is ignored unless the
+ * completion code is TCL_ERROR.
+ *
+ * -e errorCode
+ *
+ * "ErrorCode" gives a string with with to initialize the errorCode
+ * variable. This option may be omitted; it is ignored unless the
+ * completion code is TCL_ERROR.
+ *
+ * Options may appear in any order, and only the -s option must be
+ * present. As with commands, there may be additional options besides
+ * these; unknown options are ignored.
+ */
+
+/*
+ * The following variable is the serial number that was used in the
+ * last "send" command. It is exported only for testing purposes.
+ */
+
+int tkSendSerial = 0;
+
+/*
+ * Maximum size property that can be read at one time by
+ * this module:
+ */
+
+#define MAX_PROP_WORDS 100000
+
+/*
+ * The following variable can be set while debugging to do things like
+ * skip locking the server.
+ */
+
+static int sendDebug = 0;
+
+/*
+ * Forward declarations for procedures defined later in this file:
+ */
+
+static int AppendErrorProc _ANSI_ARGS_((ClientData clientData,
+ XErrorEvent *errorPtr));
+static void AppendPropCarefully _ANSI_ARGS_((Display *display,
+ Window window, Atom property, char *value,
+ int length, PendingCommand *pendingPtr));
+static void DeleteProc _ANSI_ARGS_((ClientData clientData));
+static void RegAddName _ANSI_ARGS_((NameRegistry *regPtr,
+ char *name, Window commWindow));
+static void RegClose _ANSI_ARGS_((NameRegistry *regPtr));
+static void RegDeleteName _ANSI_ARGS_((NameRegistry *regPtr,
+ char *name));
+static Window RegFindName _ANSI_ARGS_((NameRegistry *regPtr,
+ char *name));
+static NameRegistry * RegOpen _ANSI_ARGS_((Tcl_Interp *interp,
+ TkDisplay *dispPtr, int lock));
+static void SendEventProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static int SendInit _ANSI_ARGS_((Tcl_Interp *interp,
+ TkDisplay *dispPtr));
+static Tk_RestrictAction SendRestrictProc _ANSI_ARGS_((ClientData clientData,
+ XEvent *eventPtr));
+static int ServerSecure _ANSI_ARGS_((TkDisplay *dispPtr));
+static void TimeoutProc _ANSI_ARGS_((ClientData clientData));
+static void UpdateCommWindow _ANSI_ARGS_((TkDisplay *dispPtr));
+static int ValidateName _ANSI_ARGS_((TkDisplay *dispPtr,
+ char *name, Window commWindow, int oldOK));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RegOpen --
+ *
+ * This procedure loads the name registry for a display into
+ * memory so that it can be manipulated.
+ *
+ * Results:
+ * The return value is a pointer to the loaded registry.
+ *
+ * Side effects:
+ * If "lock" is set then the server will be locked. It is the
+ * caller's responsibility to call RegClose when finished with
+ * the registry, so that we can write back the registry if
+ * neeeded, unlock the server if needed, and free memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static NameRegistry *
+RegOpen(interp, dispPtr, lock)
+ Tcl_Interp *interp; /* Interpreter to use for error reporting
+ * (errors cause a panic so in fact no
+ * error is ever returned, but the interpreter
+ * is needed anyway). */
+ TkDisplay *dispPtr; /* Display whose name registry is to be
+ * opened. */
+ int lock; /* Non-zero means lock the window server
+ * when opening the registry, so no-one
+ * else can use the registry until we
+ * close it. */
+{
+ NameRegistry *regPtr;
+ int result, actualFormat;
+ unsigned long bytesAfter;
+ Atom actualType;
+
+ if (dispPtr->commTkwin == NULL) {
+ SendInit(interp, dispPtr);
+ }
+
+ regPtr = (NameRegistry *) ckalloc(sizeof(NameRegistry));
+ regPtr->dispPtr = dispPtr;
+ regPtr->locked = 0;
+ regPtr->modified = 0;
+ regPtr->allocedByX = 1;
+
+ if (lock && !sendDebug) {
+ XGrabServer(dispPtr->display);
+ regPtr->locked = 1;
+ }
+
+ /*
+ * Read the registry property.
+ */
+
+ result = XGetWindowProperty(dispPtr->display,
+ RootWindow(dispPtr->display, 0),
+ dispPtr->registryProperty, 0, MAX_PROP_WORDS,
+ False, XA_STRING, &actualType, &actualFormat,
+ &regPtr->propLength, &bytesAfter,
+ (unsigned char **) &regPtr->property);
+
+ if (actualType == None) {
+ regPtr->propLength = 0;
+ regPtr->property = NULL;
+ } else if ((result != Success) || (actualFormat != 8)
+ || (actualType != XA_STRING)) {
+ /*
+ * The property is improperly formed; delete it.
+ */
+
+ if (regPtr->property != NULL) {
+ XFree(regPtr->property);
+ regPtr->propLength = 0;
+ regPtr->property = NULL;
+ }
+ XDeleteProperty(dispPtr->display,
+ RootWindow(dispPtr->display, 0),
+ dispPtr->registryProperty);
+ }
+
+ /*
+ * Xlib placed an extra null byte after the end of the property, just
+ * to make sure that it is always NULL-terminated. Be sure to include
+ * this byte in our count if it's needed to ensure null termination
+ * (note: as of 8/95 I'm no longer sure why this code is needed; seems
+ * like it shouldn't be).
+ */
+
+ if ((regPtr->propLength > 0)
+ && (regPtr->property[regPtr->propLength-1] != 0)) {
+ regPtr->propLength++;
+ }
+ return regPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RegFindName --
+ *
+ * Given an open name registry, this procedure finds an entry
+ * with a given name, if there is one, and returns information
+ * about that entry.
+ *
+ * Results:
+ * The return value is the X identifier for the comm window for
+ * the application named "name", or None if there is no such
+ * entry in the registry.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Window
+RegFindName(regPtr, name)
+ NameRegistry *regPtr; /* Pointer to a registry opened with a
+ * previous call to RegOpen. */
+ char *name; /* Name of an application. */
+{
+ char *p, *entry;
+ Window commWindow;
+
+ commWindow = None;
+ for (p = regPtr->property; (p-regPtr->property) < regPtr->propLength; ) {
+ entry = p;
+ while ((*p != 0) && (!isspace(UCHAR(*p)))) {
+ p++;
+ }
+ if ((*p != 0) && (strcmp(name, p+1) == 0)) {
+ if (sscanf(entry, "%x", (unsigned int *) &commWindow) == 1) {
+ return commWindow;
+ }
+ }
+ while (*p != 0) {
+ p++;
+ }
+ p++;
+ }
+ return None;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RegDeleteName --
+ *
+ * This procedure deletes the entry for a given name from
+ * an open registry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there used to be an entry named "name" in the registry,
+ * then it is deleted and the registry is marked as modified
+ * so it will be written back when closed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RegDeleteName(regPtr, name)
+ NameRegistry *regPtr; /* Pointer to a registry opened with a
+ * previous call to RegOpen. */
+ char *name; /* Name of an application. */
+{
+ char *p, *entry, *entryName;
+ int count;
+
+ for (p = regPtr->property; (p-regPtr->property) < regPtr->propLength; ) {
+ entry = p;
+ while ((*p != 0) && (!isspace(UCHAR(*p)))) {
+ p++;
+ }
+ if (*p != 0) {
+ p++;
+ }
+ entryName = p;
+ while (*p != 0) {
+ p++;
+ }
+ p++;
+ if ((strcmp(name, entryName) == 0)) {
+ /*
+ * Found the matching entry. Copy everything after it
+ * down on top of it.
+ */
+
+ count = regPtr->propLength - (p - regPtr->property);
+ if (count > 0) {
+ memmove((VOID *) entry, (VOID *) p, (size_t) count);
+ }
+ regPtr->propLength -= p - entry;
+ regPtr->modified = 1;
+ return;
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RegAddName --
+ *
+ * Add a new entry to an open registry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The open registry is expanded; it is marked as modified so that
+ * it will be written back when closed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RegAddName(regPtr, name, commWindow)
+ NameRegistry *regPtr; /* Pointer to a registry opened with a
+ * previous call to RegOpen. */
+ char *name; /* Name of an application. The caller
+ * must ensure that this name isn't
+ * already registered. */
+ Window commWindow; /* X identifier for comm. window of
+ * application. */
+{
+ char id[30];
+ char *newProp;
+ int idLength, newBytes;
+
+ sprintf(id, "%x ", (unsigned int) commWindow);
+ idLength = strlen(id);
+ newBytes = idLength + strlen(name) + 1;
+ newProp = (char *) ckalloc((unsigned) (regPtr->propLength + newBytes));
+ strcpy(newProp, id);
+ strcpy(newProp+idLength, name);
+ if (regPtr->property != NULL) {
+ memcpy((VOID *) (newProp + newBytes), (VOID *) regPtr->property,
+ regPtr->propLength);
+ if (regPtr->allocedByX) {
+ XFree(regPtr->property);
+ } else {
+ ckfree(regPtr->property);
+ }
+ }
+ regPtr->modified = 1;
+ regPtr->propLength += newBytes;
+ regPtr->property = newProp;
+ regPtr->allocedByX = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * RegClose --
+ *
+ * This procedure is called to end a series of operations on
+ * a name registry.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The registry is written back if it has been modified, and the
+ * X server is unlocked if it was locked. Memory for the
+ * registry is freed, so the caller should never use regPtr
+ * again.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+RegClose(regPtr)
+ NameRegistry *regPtr; /* Pointer to a registry opened with a
+ * previous call to RegOpen. */
+{
+ if (regPtr->modified) {
+ if (!regPtr->locked && !sendDebug) {
+ panic("The name registry was modified without being locked!");
+ }
+ XChangeProperty(regPtr->dispPtr->display,
+ RootWindow(regPtr->dispPtr->display, 0),
+ regPtr->dispPtr->registryProperty, XA_STRING, 8,
+ PropModeReplace, (unsigned char *) regPtr->property,
+ (int) regPtr->propLength);
+ }
+
+ if (regPtr->locked) {
+ XUngrabServer(regPtr->dispPtr->display);
+ }
+ XFlush(regPtr->dispPtr->display);
+
+ if (regPtr->property != NULL) {
+ if (regPtr->allocedByX) {
+ XFree(regPtr->property);
+ } else {
+ ckfree(regPtr->property);
+ }
+ }
+ ckfree((char *) regPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ValidateName --
+ *
+ * This procedure checks to see if an entry in the registry
+ * is still valid.
+ *
+ * Results:
+ * The return value is 1 if the given commWindow exists and its
+ * name is "name". Otherwise 0 is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ValidateName(dispPtr, name, commWindow, oldOK)
+ TkDisplay *dispPtr; /* Display for which to perform the
+ * validation. */
+ char *name; /* The name of an application. */
+ Window commWindow; /* X identifier for the application's
+ * comm. window. */
+ int oldOK; /* Non-zero means that we should consider
+ * an application to be valid even if it
+ * looks like an old-style (pre-4.0) one;
+ * 0 means consider these invalid. */
+{
+ int result, actualFormat, argc, i;
+ unsigned long length, bytesAfter;
+ Atom actualType;
+ char *property;
+ Tk_ErrorHandler handler;
+ char **argv;
+
+ property = NULL;
+
+ /*
+ * Ignore X errors when reading the property (e.g., the window
+ * might not exist). If an error occurs, result will be some
+ * value other than Success.
+ */
+
+ handler = Tk_CreateErrorHandler(dispPtr->display, -1, -1, -1,
+ (Tk_ErrorProc *) NULL, (ClientData) NULL);
+ result = XGetWindowProperty(dispPtr->display, commWindow,
+ dispPtr->appNameProperty, 0, MAX_PROP_WORDS,
+ False, XA_STRING, &actualType, &actualFormat,
+ &length, &bytesAfter, (unsigned char **) &property);
+
+ if ((result == Success) && (actualType == None)) {
+ XWindowAttributes atts;
+
+ /*
+ * The comm. window exists but the property we're looking for
+ * doesn't exist. This probably means that the application
+ * comes from an older version of Tk (< 4.0) that didn't set the
+ * property; if this is the case, then assume for compatibility's
+ * sake that everything's OK. However, it's also possible that
+ * some random application has re-used the window id for something
+ * totally unrelated. Check a few characteristics of the window,
+ * such as its dimensions and mapped state, to be sure that it
+ * still "smells" like a commWindow.
+ */
+
+ if (!oldOK
+ || !XGetWindowAttributes(dispPtr->display, commWindow, &atts)
+ || (atts.width != 1) || (atts.height != 1)
+ || (atts.map_state != IsUnmapped)) {
+ result = 0;
+ } else {
+ result = 1;
+ }
+ } else if ((result == Success) && (actualFormat == 8)
+ && (actualType == XA_STRING)) {
+ result = 0;
+ if (Tcl_SplitList((Tcl_Interp *) NULL, property, &argc, &argv)
+ == TCL_OK) {
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], name) == 0) {
+ result = 1;
+ break;
+ }
+ }
+ ckfree((char *) argv);
+ }
+ } else {
+ result = 0;
+ }
+ Tk_DeleteErrorHandler(handler);
+ if (property != NULL) {
+ XFree(property);
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ServerSecure --
+ *
+ * Check whether a server is secure enough for us to trust
+ * Tcl scripts arriving via that server.
+ *
+ * Results:
+ * The return value is 1 if the server is secure, which means
+ * that host-style authentication is turned on but there are
+ * no hosts in the enabled list. This means that some other
+ * form of authorization (presumably more secure, such as xauth)
+ * is in use.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ServerSecure(dispPtr)
+ TkDisplay *dispPtr; /* Display to check. */
+{
+#ifdef TK_NO_SECURITY
+ return 1;
+#else
+ XHostAddress *addrPtr;
+ int numHosts, secure;
+ Bool enabled;
+
+ secure = 0;
+ addrPtr = XListHosts(dispPtr->display, &numHosts, &enabled);
+ if (enabled && (numHosts == 0)) {
+ secure = 1;
+ }
+ if (addrPtr != NULL) {
+ XFree((char *) addrPtr);
+ }
+ return secure;
+#endif /* TK_NO_SECURITY */
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SetAppName --
+ *
+ * This procedure is called to associate an ASCII name with a Tk
+ * application. If the application has already been named, the
+ * name replaces the old one.
+ *
+ * Results:
+ * The return value is the name actually given to the application.
+ * This will normally be the same as name, but if name was already
+ * in use for an application then a name of the form "name #2" will
+ * be chosen, with a high enough number to make the name unique.
+ *
+ * Side effects:
+ * Registration info is saved, thereby allowing the "send" command
+ * to be used later to invoke commands in the application. In
+ * addition, the "send" command is created in the application's
+ * interpreter. The registration will be removed automatically
+ * if the interpreter is deleted or the "send" command is removed.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+Tk_SetAppName(tkwin, name)
+ Tk_Window tkwin; /* Token for any window in the application
+ * to be named: it is just used to identify
+ * the application and the display. */
+ char *name; /* The name that will be used to
+ * refer to the interpreter in later
+ * "send" commands. Must be globally
+ * unique. */
+{
+ RegisteredInterp *riPtr, *riPtr2;
+ Window w;
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ TkDisplay *dispPtr;
+ NameRegistry *regPtr;
+ Tcl_Interp *interp;
+ char *actualName;
+ Tcl_DString dString;
+ int offset, i;
+
+#ifdef __WIN32__
+ return name;
+#endif /* __WIN32__ */
+
+ dispPtr = winPtr->dispPtr;
+ interp = winPtr->mainPtr->interp;
+ if (dispPtr->commTkwin == NULL) {
+ SendInit(interp, winPtr->dispPtr);
+ }
+
+ /*
+ * See if the application is already registered; if so, remove its
+ * current name from the registry.
+ */
+
+ regPtr = RegOpen(interp, winPtr->dispPtr, 1);
+ for (riPtr = registry; ; riPtr = riPtr->nextPtr) {
+ if (riPtr == NULL) {
+ /*
+ * This interpreter isn't currently registered; create
+ * the data structure that will be used to register it locally,
+ * plus add the "send" command to the interpreter.
+ */
+
+ riPtr = (RegisteredInterp *) ckalloc(sizeof(RegisteredInterp));
+ riPtr->interp = interp;
+ riPtr->dispPtr = winPtr->dispPtr;
+ riPtr->nextPtr = registry;
+ registry = riPtr;
+ Tcl_CreateCommand(interp, "send", Tk_SendCmd, (ClientData) riPtr,
+ DeleteProc);
+ break;
+ }
+ if (riPtr->interp == interp) {
+ /*
+ * The interpreter is currently registered; remove it from
+ * the name registry.
+ */
+
+ RegDeleteName(regPtr, riPtr->name);
+ ckfree(riPtr->name);
+ break;
+ }
+ }
+
+ /*
+ * Pick a name to use for the application. Use "name" if it's not
+ * already in use. Otherwise add a suffix such as " #2", trying
+ * larger and larger numbers until we eventually find one that is
+ * unique.
+ */
+
+ actualName = name;
+ offset = 0; /* Needed only to avoid "used before
+ * set" compiler warnings. */
+ for (i = 1; ; i++) {
+ if (i > 1) {
+ if (i == 2) {
+ Tcl_DStringInit(&dString);
+ Tcl_DStringAppend(&dString, name, -1);
+ Tcl_DStringAppend(&dString, " #", 2);
+ offset = Tcl_DStringLength(&dString);
+ Tcl_DStringSetLength(&dString, offset+10);
+ actualName = Tcl_DStringValue(&dString);
+ }
+ sprintf(actualName + offset, "%d", i);
+ }
+ w = RegFindName(regPtr, actualName);
+ if (w == None) {
+ break;
+ }
+
+ /*
+ * The name appears to be in use already, but double-check to
+ * be sure (perhaps the application died without removing its
+ * name from the registry?).
+ */
+
+ if (w == Tk_WindowId(dispPtr->commTkwin)) {
+ for (riPtr2 = registry; riPtr2 != NULL; riPtr2 = riPtr2->nextPtr) {
+ if ((riPtr2->interp != interp) &&
+ (strcmp(riPtr2->name, actualName) == 0)) {
+ goto nextSuffix;
+ }
+ }
+ RegDeleteName(regPtr, actualName);
+ break;
+ } else if (!ValidateName(winPtr->dispPtr, actualName, w, 1)) {
+ RegDeleteName(regPtr, actualName);
+ break;
+ }
+ nextSuffix:
+ continue;
+ }
+
+ /*
+ * We've now got a name to use. Store it in the name registry and
+ * in the local entry for this application, plus put it in a property
+ * on the commWindow.
+ */
+
+ RegAddName(regPtr, actualName, Tk_WindowId(dispPtr->commTkwin));
+ RegClose(regPtr);
+ riPtr->name = (char *) ckalloc((unsigned) (strlen(actualName) + 1));
+ strcpy(riPtr->name, actualName);
+ if (actualName != name) {
+ Tcl_DStringFree(&dString);
+ }
+ UpdateCommWindow(dispPtr);
+
+ return riPtr->name;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_SendCmd --
+ *
+ * This procedure is invoked to process the "send" Tcl command.
+ * See the user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_SendCmd(clientData, interp, argc, argv)
+ ClientData clientData; /* Information about sender (only
+ * dispPtr field is used). */
+ Tcl_Interp *interp; /* Current interpreter. */
+ int argc; /* Number of arguments. */
+ char **argv; /* Argument strings. */
+{
+ TkWindow *winPtr;
+ Window commWindow;
+ PendingCommand pending;
+ register RegisteredInterp *riPtr;
+ char *destName, buffer[30];
+ int result, c, async, i, firstArg;
+ size_t length;
+ Tk_RestrictProc *prevRestrictProc;
+ ClientData prevArg;
+ TkDisplay *dispPtr;
+ NameRegistry *regPtr;
+ Tcl_DString request;
+ Tcl_Interp *localInterp; /* Used when the interpreter to
+ * send the command to is within
+ * the same process. */
+
+ /*
+ * Process options, if any.
+ */
+
+ async = 0;
+ winPtr = (TkWindow *) Tk_MainWindow(interp);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ for (i = 1; i < (argc-1); ) {
+ if (argv[i][0] != '-') {
+ break;
+ }
+ c = argv[i][1];
+ length = strlen(argv[i]);
+ if ((c == 'a') && (strncmp(argv[i], "-async", length) == 0)) {
+ async = 1;
+ i++;
+ } else if ((c == 'd') && (strncmp(argv[i], "-displayof",
+ length) == 0)) {
+ winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[i+1],
+ (Tk_Window) winPtr);
+ if (winPtr == NULL) {
+ return TCL_ERROR;
+ }
+ i += 2;
+ } else if (strcmp(argv[i], "--") == 0) {
+ i++;
+ break;
+ } else {
+ Tcl_AppendResult(interp, "bad option \"", argv[i],
+ "\": must be -async, -displayof, or --", (char *) NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (argc < (i+2)) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
+ " ?options? interpName arg ?arg ...?\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ destName = argv[i];
+ firstArg = i+1;
+
+ dispPtr = winPtr->dispPtr;
+ if (dispPtr->commTkwin == NULL) {
+ SendInit(interp, winPtr->dispPtr);
+ }
+
+ /*
+ * See if the target interpreter is local. If so, execute
+ * the command directly without going through the X server.
+ * The only tricky thing is passing the result from the target
+ * interpreter to the invoking interpreter. Watch out: they
+ * could be the same!
+ */
+
+ for (riPtr = registry; riPtr != NULL; riPtr = riPtr->nextPtr) {
+ if ((riPtr->dispPtr != dispPtr)
+ || (strcmp(riPtr->name, destName) != 0)) {
+ continue;
+ }
+ Tcl_Preserve((ClientData) riPtr);
+ localInterp = riPtr->interp;
+ Tcl_Preserve((ClientData) localInterp);
+ if (firstArg == (argc-1)) {
+ result = Tcl_GlobalEval(localInterp, argv[firstArg]);
+ } else {
+ Tcl_DStringInit(&request);
+ Tcl_DStringAppend(&request, argv[firstArg], -1);
+ for (i = firstArg+1; i < argc; i++) {
+ Tcl_DStringAppend(&request, " ", 1);
+ Tcl_DStringAppend(&request, argv[i], -1);
+ }
+ result = Tcl_GlobalEval(localInterp, Tcl_DStringValue(&request));
+ Tcl_DStringFree(&request);
+ }
+ if (interp != localInterp) {
+ if (result == TCL_ERROR) {
+
+ /*
+ * An error occurred, so transfer error information from the
+ * destination interpreter back to our interpreter. Must clear
+ * interp's result before calling Tcl_AddErrorInfo, since
+ * Tcl_AddErrorInfo will store the interp's result in errorInfo
+ * before appending riPtr's $errorInfo; we've already got
+ * everything we need in riPtr's $errorInfo.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AddErrorInfo(interp, Tcl_GetVar2(localInterp,
+ "errorInfo", (char *) NULL, TCL_GLOBAL_ONLY));
+ Tcl_SetVar2(interp, "errorCode", (char *) NULL,
+ Tcl_GetVar2(localInterp, "errorCode", (char *) NULL,
+ TCL_GLOBAL_ONLY), TCL_GLOBAL_ONLY);
+ }
+ if (localInterp->freeProc != TCL_STATIC) {
+ interp->result = localInterp->result;
+ interp->freeProc = localInterp->freeProc;
+ localInterp->freeProc = TCL_STATIC;
+ } else {
+ Tcl_SetResult(interp, localInterp->result, TCL_VOLATILE);
+ }
+ Tcl_ResetResult(localInterp);
+ }
+ Tcl_Release((ClientData) riPtr);
+ Tcl_Release((ClientData) localInterp);
+ return result;
+ }
+
+ /*
+ * Bind the interpreter name to a communication window.
+ */
+
+ regPtr = RegOpen(interp, winPtr->dispPtr, 0);
+ commWindow = RegFindName(regPtr, destName);
+ RegClose(regPtr);
+ if (commWindow == None) {
+ Tcl_AppendResult(interp, "no application named \"",
+ destName, "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Send the command to the target interpreter by appending it to the
+ * comm window in the communication window.
+ */
+
+ tkSendSerial++;
+ Tcl_DStringInit(&request);
+ Tcl_DStringAppend(&request, "\0c\0-n ", 6);
+ Tcl_DStringAppend(&request, destName, -1);
+ if (!async) {
+ sprintf(buffer, "%x %d",
+ (unsigned int) Tk_WindowId(dispPtr->commTkwin),
+ tkSendSerial);
+ Tcl_DStringAppend(&request, "\0-r ", 4);
+ Tcl_DStringAppend(&request, buffer, -1);
+ }
+ Tcl_DStringAppend(&request, "\0-s ", 4);
+ Tcl_DStringAppend(&request, argv[firstArg], -1);
+ for (i = firstArg+1; i < argc; i++) {
+ Tcl_DStringAppend(&request, " ", 1);
+ Tcl_DStringAppend(&request, argv[i], -1);
+ }
+ (void) AppendPropCarefully(dispPtr->display, commWindow,
+ dispPtr->commProperty, Tcl_DStringValue(&request),
+ Tcl_DStringLength(&request) + 1,
+ (async) ? (PendingCommand *) NULL : &pending);
+ Tcl_DStringFree(&request);
+ if (async) {
+ /*
+ * This is an asynchronous send: return immediately without
+ * waiting for a response.
+ */
+
+ return TCL_OK;
+ }
+
+ /*
+ * Register the fact that we're waiting for a command to complete
+ * (this is needed by SendEventProc and by AppendErrorProc to pass
+ * back the command's results). Set up a timeout handler so that
+ * we can check during long sends to make sure that the destination
+ * application is still alive.
+ */
+
+ pending.serial = tkSendSerial;
+ pending.dispPtr = dispPtr;
+ pending.target = destName;
+ pending.commWindow = commWindow;
+ pending.interp = interp;
+ pending.result = NULL;
+ pending.errorInfo = NULL;
+ pending.errorCode = NULL;
+ pending.gotResponse = 0;
+ pending.nextPtr = pendingCommands;
+ pendingCommands = &pending;
+
+ /*
+ * Enter a loop processing X events until the result comes
+ * in or the target is declared to be dead. While waiting
+ * for a result, look only at send-related events so that
+ * the send is synchronous with respect to other events in
+ * the application.
+ */
+
+ prevRestrictProc = Tk_RestrictEvents(SendRestrictProc,
+ (ClientData) NULL, &prevArg);
+ Tcl_CreateModalTimeout(1000, TimeoutProc, (ClientData) &pending);
+ while (!pending.gotResponse) {
+ Tcl_DoOneEvent(TCL_WINDOW_EVENTS);
+ }
+ Tcl_DeleteModalTimeout(TimeoutProc, (ClientData) &pending);
+ (void) Tk_RestrictEvents(prevRestrictProc, prevArg, &prevArg);
+
+ /*
+ * Unregister the information about the pending command
+ * and return the result.
+ */
+
+ if (pendingCommands == &pending) {
+ pendingCommands = pending.nextPtr;
+ } else {
+ PendingCommand *pcPtr;
+
+ for (pcPtr = pendingCommands; pcPtr != NULL;
+ pcPtr = pcPtr->nextPtr) {
+ if (pcPtr->nextPtr == &pending) {
+ pcPtr->nextPtr = pending.nextPtr;
+ break;
+ }
+ }
+ }
+ if (pending.errorInfo != NULL) {
+ /*
+ * Special trick: must clear the interp's result before calling
+ * Tcl_AddErrorInfo, since Tcl_AddErrorInfo will store the interp's
+ * result in errorInfo before appending pending.errorInfo; we've
+ * already got everything we need in pending.errorInfo.
+ */
+
+ Tcl_ResetResult(interp);
+ Tcl_AddErrorInfo(interp, pending.errorInfo);
+ ckfree(pending.errorInfo);
+ }
+ if (pending.errorCode != NULL) {
+ Tcl_SetVar2(interp, "errorCode", (char *) NULL, pending.errorCode,
+ TCL_GLOBAL_ONLY);
+ ckfree(pending.errorCode);
+ }
+ Tcl_SetResult(interp, pending.result, TCL_DYNAMIC);
+ return pending.code;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkGetInterpNames --
+ *
+ * This procedure is invoked to fetch a list of all the
+ * interpreter names currently registered for the display
+ * of a particular window.
+ *
+ * Results:
+ * A standard Tcl return value. Interp->result will be set
+ * to hold a list of all the interpreter names defined for
+ * tkwin's display. If an error occurs, then TCL_ERROR
+ * is returned and interp->result will hold an error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkGetInterpNames(interp, tkwin)
+ Tcl_Interp *interp; /* Interpreter for returning a result. */
+ Tk_Window tkwin; /* Window whose display is to be used
+ * for the lookup. */
+{
+ TkWindow *winPtr = (TkWindow *) tkwin;
+ char *p, *entry, *entryName;
+ NameRegistry *regPtr;
+ Window commWindow;
+ int count;
+
+ /*
+ * Read the registry property, then scan through all of its entries.
+ * Validate each entry to be sure that its application still exists.
+ */
+
+ regPtr = RegOpen(interp, winPtr->dispPtr, 1);
+ for (p = regPtr->property; (p-regPtr->property) < regPtr->propLength; ) {
+ entry = p;
+ if (sscanf(p, "%x",(unsigned int *) &commWindow) != 1) {
+ commWindow = None;
+ }
+ while ((*p != 0) && (!isspace(UCHAR(*p)))) {
+ p++;
+ }
+ if (*p != 0) {
+ p++;
+ }
+ entryName = p;
+ while (*p != 0) {
+ p++;
+ }
+ p++;
+ if (ValidateName(winPtr->dispPtr, entryName, commWindow, 1)) {
+ /*
+ * The application still exists; add its name to the result.
+ */
+
+ Tcl_AppendElement(interp, entryName);
+ } else {
+ /*
+ * This name is bogus (perhaps the application died without
+ * cleaning up its entry in the registry?). Delete the name.
+ */
+
+ count = regPtr->propLength - (p - regPtr->property);
+ if (count > 0) {
+ memmove((VOID *) entry, (VOID *) p, (size_t) count);
+ }
+ regPtr->propLength -= p - entry;
+ regPtr->modified = 1;
+ p = entry;
+ }
+ }
+ RegClose(regPtr);
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SendInit --
+ *
+ * This procedure is called to initialize the
+ * communication channels for sending commands and
+ * receiving results.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets up various data structures and windows.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+SendInit(interp, dispPtr)
+ Tcl_Interp *interp; /* Interpreter to use for error reporting
+ * (no errors are ever returned, but the
+ * interpreter is needed anyway). */
+ TkDisplay *dispPtr; /* Display to initialize. */
+{
+ XSetWindowAttributes atts;
+
+ /*
+ * Create the window used for communication, and set up an
+ * event handler for it.
+ */
+
+ dispPtr->commTkwin = Tk_CreateWindow(interp, (Tk_Window) NULL,
+ "_comm", DisplayString(dispPtr->display));
+ if (dispPtr->commTkwin == NULL) {
+ panic("Tk_CreateWindow failed in SendInit!");
+ }
+ atts.override_redirect = True;
+ Tk_ChangeWindowAttributes(dispPtr->commTkwin,
+ CWOverrideRedirect, &atts);
+ Tk_CreateEventHandler(dispPtr->commTkwin, PropertyChangeMask,
+ SendEventProc, (ClientData) dispPtr);
+ Tk_MakeWindowExist(dispPtr->commTkwin);
+
+ /*
+ * Get atoms used as property names.
+ */
+
+ dispPtr->commProperty = Tk_InternAtom(dispPtr->commTkwin, "Comm");
+ dispPtr->registryProperty = Tk_InternAtom(dispPtr->commTkwin,
+ "InterpRegistry");
+ dispPtr->appNameProperty = Tk_InternAtom(dispPtr->commTkwin,
+ "TK_APPLICATION");
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SendEventProc --
+ *
+ * This procedure is invoked automatically by the toolkit
+ * event manager when a property changes on the communication
+ * window. This procedure reads the property and handles
+ * command requests and responses.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If there are command requests in the property, they
+ * are executed. If there are responses in the property,
+ * their information is saved for the (ostensibly waiting)
+ * "send" commands. The property is deleted.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+SendEventProc(clientData, eventPtr)
+ ClientData clientData; /* Display information. */
+ XEvent *eventPtr; /* Information about event. */
+{
+ TkDisplay *dispPtr = (TkDisplay *) clientData;
+ char *propInfo;
+ register char *p;
+ int result, actualFormat;
+ unsigned long numItems, bytesAfter;
+ Atom actualType;
+ Tcl_Interp *remoteInterp; /* Interp in which to execute the command. */
+
+ if ((eventPtr->xproperty.atom != dispPtr->commProperty)
+ || (eventPtr->xproperty.state != PropertyNewValue)) {
+ return;
+ }
+
+ /*
+ * Read the comm property and delete it.
+ */
+
+ propInfo = NULL;
+ result = XGetWindowProperty(dispPtr->display,
+ Tk_WindowId(dispPtr->commTkwin),
+ dispPtr->commProperty, 0, MAX_PROP_WORDS, True,
+ XA_STRING, &actualType, &actualFormat,
+ &numItems, &bytesAfter, (unsigned char **) &propInfo);
+
+ /*
+ * If the property doesn't exist or is improperly formed
+ * then ignore it.
+ */
+
+ if ((result != Success) || (actualType != XA_STRING)
+ || (actualFormat != 8)) {
+ if (propInfo != NULL) {
+ XFree(propInfo);
+ }
+ return;
+ }
+
+ /*
+ * Several commands and results could arrive in the property at
+ * one time; each iteration through the outer loop handles a
+ * single command or result.
+ */
+
+ for (p = propInfo; (p-propInfo) < numItems; ) {
+ /*
+ * Ignore leading NULLs; each command or result starts with a
+ * NULL so that no matter how badly formed a preceding command
+ * is, we'll be able to tell that a new command/result is
+ * starting.
+ */
+
+ if (*p == 0) {
+ p++;
+ continue;
+ }
+
+ if ((*p == 'c') && (p[1] == 0)) {
+ Window commWindow;
+ char *interpName, *script, *serial, *end;
+ Tcl_DString reply;
+ RegisteredInterp *riPtr;
+
+ /*
+ *----------------------------------------------------------
+ * This is an incoming command from some other application.
+ * Iterate over all of its options. Stop when we reach
+ * the end of the property or something that doesn't look
+ * like an option.
+ *----------------------------------------------------------
+ */
+
+ p += 2;
+ interpName = NULL;
+ commWindow = None;
+ serial = "";
+ script = NULL;
+ while (((p-propInfo) < numItems) && (*p == '-')) {
+ switch (p[1]) {
+ case 'r':
+ commWindow = (Window) strtoul(p+2, &end, 16);
+ if ((end == p+2) || (*end != ' ')) {
+ commWindow = None;
+ } else {
+ p = serial = end+1;
+ }
+ break;
+ case 'n':
+ if (p[2] == ' ') {
+ interpName = p+3;
+ }
+ break;
+ case 's':
+ if (p[2] == ' ') {
+ script = p+3;
+ }
+ break;
+ }
+ while (*p != 0) {
+ p++;
+ }
+ p++;
+ }
+
+ if ((script == NULL) || (interpName == NULL)) {
+ continue;
+ }
+
+ /*
+ * Initialize the result property, so that we're ready at any
+ * time if we need to return an error.
+ */
+
+ if (commWindow != None) {
+ Tcl_DStringInit(&reply);
+ Tcl_DStringAppend(&reply, "\0r\0-s ", 6);
+ Tcl_DStringAppend(&reply, serial, -1);
+ Tcl_DStringAppend(&reply, "\0-r ", 4);
+ }
+
+ if (!ServerSecure(dispPtr)) {
+ if (commWindow != None) {
+ Tcl_DStringAppend(&reply, "X server insecure (must use xauth-style authorization); command ignored", -1);
+ }
+ result = TCL_ERROR;
+ goto returnResult;
+ }
+
+ /*
+ * Locate the application, then execute the script.
+ */
+
+ for (riPtr = registry; ; riPtr = riPtr->nextPtr) {
+ if (riPtr == NULL) {
+ if (commWindow != None) {
+ Tcl_DStringAppend(&reply,
+ "receiver never heard of interpreter \"", -1);
+ Tcl_DStringAppend(&reply, interpName, -1);
+ Tcl_DStringAppend(&reply, "\"", 1);
+ }
+ result = TCL_ERROR;
+ goto returnResult;
+ }
+ if (strcmp(riPtr->name, interpName) == 0) {
+ break;
+ }
+ }
+ Tcl_Preserve((ClientData) riPtr);
+
+ /*
+ * We must protect the interpreter because the script may
+ * enter another event loop, which might call Tcl_DeleteInterp.
+ */
+
+ remoteInterp = riPtr->interp;
+ Tcl_Preserve((ClientData) remoteInterp);
+
+ result = Tcl_GlobalEval(remoteInterp, script);
+
+ /*
+ * The call to Tcl_Release may have released the interpreter
+ * which will cause the "send" command for that interpreter
+ * to be deleted. The command deletion callback will set the
+ * riPtr->interp field to NULL, hence the check below for NULL.
+ */
+
+ if (commWindow != None) {
+ Tcl_DStringAppend(&reply, remoteInterp->result, -1);
+ if (result == TCL_ERROR) {
+ char *varValue;
+
+ varValue = Tcl_GetVar2(remoteInterp, "errorInfo",
+ (char *) NULL, TCL_GLOBAL_ONLY);
+ if (varValue != NULL) {
+ Tcl_DStringAppend(&reply, "\0-i ", 4);
+ Tcl_DStringAppend(&reply, varValue, -1);
+ }
+ varValue = Tcl_GetVar2(remoteInterp, "errorCode",
+ (char *) NULL, TCL_GLOBAL_ONLY);
+ if (varValue != NULL) {
+ Tcl_DStringAppend(&reply, "\0-e ", 4);
+ Tcl_DStringAppend(&reply, varValue, -1);
+ }
+ }
+ }
+ Tcl_Release((ClientData) remoteInterp);
+ Tcl_Release((ClientData) riPtr);
+
+ /*
+ * Return the result to the sender if a commWindow was
+ * specified (if none was specified then this is an asynchronous
+ * call). Right now reply has everything but the completion
+ * code, but it needs the NULL to terminate the current option.
+ */
+
+ returnResult:
+ if (commWindow != None) {
+ if (result != TCL_OK) {
+ char buffer[20];
+
+ sprintf(buffer, "%d", result);
+ Tcl_DStringAppend(&reply, "\0-c ", 4);
+ Tcl_DStringAppend(&reply, buffer, -1);
+ }
+ (void) AppendPropCarefully(dispPtr->display, commWindow,
+ dispPtr->commProperty, Tcl_DStringValue(&reply),
+ Tcl_DStringLength(&reply) + 1,
+ (PendingCommand *) NULL);
+ XFlush(dispPtr->display);
+ Tcl_DStringFree(&reply);
+ }
+ } else if ((*p == 'r') && (p[1] == 0)) {
+ int serial, code, gotSerial;
+ char *errorInfo, *errorCode, *resultString;
+ PendingCommand *pcPtr;
+
+ /*
+ *----------------------------------------------------------
+ * This is a reply to some command that we sent out. Iterate
+ * over all of its options. Stop when we reach the end of the
+ * property or something that doesn't look like an option.
+ *----------------------------------------------------------
+ */
+
+ p += 2;
+ code = TCL_OK;
+ gotSerial = 0;
+ errorInfo = NULL;
+ errorCode = NULL;
+ resultString = "";
+ while (((p-propInfo) < numItems) && (*p == '-')) {
+ switch (p[1]) {
+ case 'c':
+ if (sscanf(p+2, " %d", &code) != 1) {
+ code = TCL_OK;
+ }
+ break;
+ case 'e':
+ if (p[2] == ' ') {
+ errorCode = p+3;
+ }
+ break;
+ case 'i':
+ if (p[2] == ' ') {
+ errorInfo = p+3;
+ }
+ break;
+ case 'r':
+ if (p[2] == ' ') {
+ resultString = p+3;
+ }
+ break;
+ case 's':
+ if (sscanf(p+2, " %d", &serial) == 1) {
+ gotSerial = 1;
+ }
+ break;
+ }
+ while (*p != 0) {
+ p++;
+ }
+ p++;
+ }
+
+ if (!gotSerial) {
+ continue;
+ }
+
+ /*
+ * Give the result information to anyone who's
+ * waiting for it.
+ */
+
+ for (pcPtr = pendingCommands; pcPtr != NULL;
+ pcPtr = pcPtr->nextPtr) {
+ if ((serial != pcPtr->serial) || (pcPtr->result != NULL)) {
+ continue;
+ }
+ pcPtr->code = code;
+ if (resultString != NULL) {
+ pcPtr->result = (char *) ckalloc((unsigned)
+ (strlen(resultString) + 1));
+ strcpy(pcPtr->result, resultString);
+ }
+ if (code == TCL_ERROR) {
+ if (errorInfo != NULL) {
+ pcPtr->errorInfo = (char *) ckalloc((unsigned)
+ (strlen(errorInfo) + 1));
+ strcpy(pcPtr->errorInfo, errorInfo);
+ }
+ if (errorCode != NULL) {
+ pcPtr->errorCode = (char *) ckalloc((unsigned)
+ (strlen(errorCode) + 1));
+ strcpy(pcPtr->errorCode, errorCode);
+ }
+ }
+ pcPtr->gotResponse = 1;
+ break;
+ }
+ } else {
+ /*
+ * Didn't recognize this thing. Just skip through the next
+ * null character and try again.
+ */
+
+ while (*p != 0) {
+ p++;
+ }
+ p++;
+ }
+ }
+ XFree(propInfo);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * AppendPropCarefully --
+ *
+ * Append a given property to a given window, but set up
+ * an X error handler so that if the append fails this
+ * procedure can return an error code rather than having
+ * Xlib panic.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The given property on the given window is appended to.
+ * If this operation fails and if pendingPtr is non-NULL,
+ * then the pending operation is marked as complete with
+ * an error.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+AppendPropCarefully(display, window, property, value, length, pendingPtr)
+ Display *display; /* Display on which to operate. */
+ Window window; /* Window whose property is to
+ * be modified. */
+ Atom property; /* Name of property. */
+ char *value; /* Characters to append to property. */
+ int length; /* Number of bytes to append. */
+ PendingCommand *pendingPtr; /* Pending command to mark complete
+ * if an error occurs during the
+ * property op. NULL means just
+ * ignore the error. */
+{
+ Tk_ErrorHandler handler;
+
+ handler = Tk_CreateErrorHandler(display, -1, -1, -1, AppendErrorProc,
+ (ClientData) pendingPtr);
+ XChangeProperty(display, window, property, XA_STRING, 8,
+ PropModeAppend, (unsigned char *) value, length);
+ Tk_DeleteErrorHandler(handler);
+}
+
+/*
+ * The procedure below is invoked if an error occurs during
+ * the XChangeProperty operation above.
+ */
+
+ /* ARGSUSED */
+static int
+AppendErrorProc(clientData, errorPtr)
+ ClientData clientData; /* Command to mark complete, or NULL. */
+ XErrorEvent *errorPtr; /* Information about error. */
+{
+ PendingCommand *pendingPtr = (PendingCommand *) clientData;
+ register PendingCommand *pcPtr;
+
+ if (pendingPtr == NULL) {
+ return 0;
+ }
+
+ /*
+ * Make sure this command is still pending.
+ */
+
+ for (pcPtr = pendingCommands; pcPtr != NULL;
+ pcPtr = pcPtr->nextPtr) {
+ if ((pcPtr == pendingPtr) && (pcPtr->result == NULL)) {
+ pcPtr->result = (char *) ckalloc((unsigned)
+ (strlen(pcPtr->target) + 50));
+ sprintf(pcPtr->result, "no application named \"%s\"",
+ pcPtr->target);
+ pcPtr->code = TCL_ERROR;
+ pcPtr->gotResponse = 1;
+ break;
+ }
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TimeoutProc --
+ *
+ * This procedure is invoked when an unusually long amout of
+ * time has elapsed during the processing of a sent command.
+ * It checks to make sure that the target application still
+ * exists, and reschedules itself to check again later.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If the target application has gone away abort the send
+ * operation with an error.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+TimeoutProc(clientData)
+ ClientData clientData; /* Information about command that
+ * has been sent but not yet
+ * responded to. */
+{
+ PendingCommand *pcPtr = (PendingCommand *) clientData;
+ register PendingCommand *pcPtr2;
+
+ /*
+ * Make sure that the command is still in the pending list
+ * and that it hasn't already completed. Then validate the
+ * existence of the target application.
+ */
+
+ for (pcPtr2 = pendingCommands; pcPtr2 != NULL;
+ pcPtr2 = pcPtr2->nextPtr) {
+ char *msg;
+ if ((pcPtr2 != pcPtr) || (pcPtr2->result != NULL)) {
+ continue;
+ }
+ if (!ValidateName(pcPtr2->dispPtr, pcPtr2->target,
+ pcPtr2->commWindow, 0)) {
+ if (ValidateName(pcPtr2->dispPtr, pcPtr2->target,
+ pcPtr2->commWindow, 1)) {
+ msg =
+ "target application died or uses a Tk version before 4.0";
+ } else {
+ msg = "target application died";
+ }
+ pcPtr2->code = TCL_ERROR;
+ pcPtr2->result = (char *) ckalloc((unsigned) (strlen(msg) + 1));
+ strcpy(pcPtr2->result, msg);
+ pcPtr2->gotResponse = 1;
+ } else {
+ Tcl_DeleteModalTimeout(TimeoutProc, clientData);
+ Tcl_CreateModalTimeout(2000, TimeoutProc, clientData);
+ }
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DeleteProc --
+ *
+ * This procedure is invoked by Tcl when the "send" command
+ * is deleted in an interpreter. It unregisters the interpreter.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The interpreter given by riPtr is unregistered.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+DeleteProc(clientData)
+ ClientData clientData; /* Info about registration, passed
+ * as ClientData. */
+{
+ RegisteredInterp *riPtr = (RegisteredInterp *) clientData;
+ register RegisteredInterp *riPtr2;
+ NameRegistry *regPtr;
+
+ regPtr = RegOpen(riPtr->interp, riPtr->dispPtr, 1);
+ RegDeleteName(regPtr, riPtr->name);
+ RegClose(regPtr);
+
+ if (registry == riPtr) {
+ registry = riPtr->nextPtr;
+ } else {
+ for (riPtr2 = registry; riPtr2 != NULL;
+ riPtr2 = riPtr2->nextPtr) {
+ if (riPtr2->nextPtr == riPtr) {
+ riPtr2->nextPtr = riPtr->nextPtr;
+ break;
+ }
+ }
+ }
+ ckfree((char *) riPtr->name);
+ riPtr->interp = NULL;
+ UpdateCommWindow(riPtr->dispPtr);
+ Tcl_EventuallyFree((ClientData) riPtr, TCL_DYNAMIC);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SendRestrictProc --
+ *
+ * This procedure filters incoming events when a "send" command
+ * is outstanding. It defers all events except those containing
+ * send commands and results.
+ *
+ * Results:
+ * False is returned except for property-change events on a
+ * commWindow.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+static Tk_RestrictAction
+SendRestrictProc(clientData, eventPtr)
+ ClientData clientData; /* Not used. */
+ register XEvent *eventPtr; /* Event that just arrived. */
+{
+ TkDisplay *dispPtr;
+
+ if (eventPtr->type != PropertyNotify) {
+ return TK_DEFER_EVENT;
+ }
+ for (dispPtr = tkDisplayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) {
+ if ((eventPtr->xany.display == dispPtr->display)
+ && (eventPtr->xproperty.window
+ == Tk_WindowId(dispPtr->commTkwin))) {
+ return TK_PROCESS_EVENT;
+ }
+ }
+ return TK_DEFER_EVENT;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateCommWindow --
+ *
+ * This procedure updates the list of application names stored
+ * on our commWindow. It is typically called when interpreters
+ * are registered and unregistered.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The TK_APPLICATION property on the comm window is updated.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateCommWindow(dispPtr)
+ TkDisplay *dispPtr; /* Display whose commWindow is to be
+ * updated. */
+{
+ Tcl_DString names;
+ RegisteredInterp *riPtr;
+
+ Tcl_DStringInit(&names);
+ for (riPtr = registry; riPtr != NULL; riPtr = riPtr->nextPtr) {
+ Tcl_DStringAppendElement(&names, riPtr->name);
+ }
+ XChangeProperty(dispPtr->display, Tk_WindowId(dispPtr->commTkwin),
+ dispPtr->appNameProperty, XA_STRING, 8, PropModeReplace,
+ (unsigned char *) Tcl_DStringValue(&names),
+ Tcl_DStringLength(&names));
+ Tcl_DStringFree(&names);
+}
diff --git a/tk/generic/tkSquare.c b/tk/generic/tkSquare.c
index 50484528d30..983969c1f4d 100644
--- a/tk/generic/tkSquare.c
+++ b/tk/generic/tkSquare.c
@@ -1,14 +1,13 @@
/*
* 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.
@@ -17,7 +16,9 @@
*/
#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;
}
@@ -585,3 +635,4 @@ KeepInWindow(squarePtr)
squarePtr->y = bd;
}
}
+
diff --git a/tk/generic/tkStubImg.c b/tk/generic/tkStubImg.c
new file mode 100644
index 00000000000..024e581c578
--- /dev/null
+++ b/tk/generic/tkStubImg.c
@@ -0,0 +1,75 @@
+/*
+ * tkStubImg.c --
+ *
+ * Stub object that will be statically linked into extensions that wish
+ * to access Tk.
+ *
+ * Copyright (c) 1999 Jan Nijtmans.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "tcl.h"
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_InitImageArgs --
+ *
+ * Performs the necessary conversion from Tcl_Obj's to strings
+ * in the createProc for Tcl_CreateImageType. If running under
+ * Tk 8.2 or earlier without the Img-patch, this function has
+ * no effect.
+ *
+ * Results:
+ * argvPtr will point to an argument list which is guaranteed to
+ * contain strings, no matter what Tk version is running.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------
+ */
+
+#ifdef Tk_InitImageArgs
+#undef Tk_InitImageArgs
+#endif
+
+void
+Tk_InitImageArgs(interp, argc, argvPtr)
+ Tcl_Interp *interp;
+ int argc;
+ char ***argvPtr;
+{
+ static useNewImage = -1;
+ static char **argv = NULL;
+
+ if (argv) {
+ tclStubsPtr->tcl_Free((char *) argv);
+ argv = NULL;
+ }
+
+ if (useNewImage < 0) {
+ Tcl_CmdInfo cmdInfo;
+ if (!tclStubsPtr->tcl_GetCommandInfo(interp,"image", &cmdInfo)) {
+ tclStubsPtr->tcl_Panic("cannot find the \"image\" command");
+ }
+ if (cmdInfo.isNativeObjectProc == 1) {
+ useNewImage = 1; /* Tk uses the new image interface */
+ }
+ }
+ if (useNewImage && (argc > 0)) {
+ int i;
+ argv = (char **) tclStubsPtr->tcl_Alloc(argc * sizeof(char *));
+ for (i = 0; i < argc; i++) {
+ argv[i] = tclStubsPtr->tcl_GetString((Tcl_Obj *)(*argvPtr)[i]);
+ }
+ *argvPtr = (char **) argv;
+ }
+}
+
diff --git a/tk/generic/tkStubInit.c b/tk/generic/tkStubInit.c
new file mode 100644
index 00000000000..5dc7b43920a
--- /dev/null
+++ b/tk/generic/tkStubInit.c
@@ -0,0 +1,954 @@
+/*
+ * tkStubInit.c --
+ *
+ * This file contains the initializers for the Tk stub vectors.
+ *
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "tkInt.h"
+#include "tkPort.h"
+
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+#ifdef MAC_TCL
+#include "tkMacInt.h"
+#endif
+
+#include "tkDecls.h"
+#include "tkPlatDecls.h"
+#include "tkIntDecls.h"
+#include "tkIntPlatDecls.h"
+#include "tkIntXlibDecls.h"
+
+/*
+ * Remove macros that will interfere with the definitions below.
+ */
+
+#define Tk_CreateCanvasVisitor ((void (*) _ANSI_ARGS_((Tcl_Interp * interp, \
+ VOID * typePtr))) NULL)
+#define Tk_GetCanvasVisitor ((VOID * (*) _ANSI_ARGS_((Tcl_Interp * interp, \
+ CONST char * name))) NULL)
+
+/*
+ * WARNING: The contents of this file is automatically generated by the
+ * tools/genStubs.tcl script. Any modifications to the function declarations
+ * below should be made in the generic/tk.decls script.
+ */
+
+/* !BEGIN!: Do not edit below this line. */
+
+TkIntStubs tkIntStubs = {
+ TCL_STUB_MAGIC,
+ NULL,
+ TkAllocWindow, /* 0 */
+ TkBezierPoints, /* 1 */
+ TkBezierScreenPoints, /* 2 */
+ TkBindDeadWindow, /* 3 */
+ TkBindEventProc, /* 4 */
+ TkBindFree, /* 5 */
+ TkBindInit, /* 6 */
+ TkChangeEventWindow, /* 7 */
+ TkClipInit, /* 8 */
+ TkComputeAnchor, /* 9 */
+ TkCopyAndGlobalEval, /* 10 */
+ TkCreateBindingProcedure, /* 11 */
+ TkCreateCursorFromData, /* 12 */
+ TkCreateFrame, /* 13 */
+ TkCreateMainWindow, /* 14 */
+ TkCurrentTime, /* 15 */
+ TkDeleteAllImages, /* 16 */
+ TkDoConfigureNotify, /* 17 */
+ TkDrawInsetFocusHighlight, /* 18 */
+ TkEventDeadWindow, /* 19 */
+ TkFillPolygon, /* 20 */
+ TkFindStateNum, /* 21 */
+ TkFindStateString, /* 22 */
+ TkFocusDeadWindow, /* 23 */
+ TkFocusFilterEvent, /* 24 */
+ TkFocusKeyEvent, /* 25 */
+ TkFontPkgInit, /* 26 */
+ TkFontPkgFree, /* 27 */
+ TkFreeBindingTags, /* 28 */
+ TkpFreeCursor, /* 29 */
+ TkGetBitmapData, /* 30 */
+ TkGetButtPoints, /* 31 */
+ TkGetCursorByName, /* 32 */
+ TkGetDefaultScreenName, /* 33 */
+ TkGetDisplay, /* 34 */
+ TkGetDisplayOf, /* 35 */
+ TkGetFocusWin, /* 36 */
+ TkGetInterpNames, /* 37 */
+ TkGetMiterPoints, /* 38 */
+ TkGetPointerCoords, /* 39 */
+ TkGetServerInfo, /* 40 */
+ TkGrabDeadWindow, /* 41 */
+ TkGrabState, /* 42 */
+ TkIncludePoint, /* 43 */
+ TkInOutEvents, /* 44 */
+ TkInstallFrameMenu, /* 45 */
+ TkKeysymToString, /* 46 */
+ TkLineToArea, /* 47 */
+ TkLineToPoint, /* 48 */
+ TkMakeBezierCurve, /* 49 */
+ TkMakeBezierPostscript, /* 50 */
+ TkOptionClassChanged, /* 51 */
+ TkOptionDeadWindow, /* 52 */
+ TkOvalToArea, /* 53 */
+ TkOvalToPoint, /* 54 */
+ TkpChangeFocus, /* 55 */
+ TkpCloseDisplay, /* 56 */
+ TkpClaimFocus, /* 57 */
+ TkpDisplayWarning, /* 58 */
+ TkpGetAppName, /* 59 */
+ TkpGetOtherWindow, /* 60 */
+ TkpGetWrapperWindow, /* 61 */
+ TkpInit, /* 62 */
+ TkpInitializeMenuBindings, /* 63 */
+ TkpMakeContainer, /* 64 */
+ TkpMakeMenuWindow, /* 65 */
+ TkpMakeWindow, /* 66 */
+ TkpMenuNotifyToplevelCreate, /* 67 */
+ TkpOpenDisplay, /* 68 */
+ TkPointerEvent, /* 69 */
+ TkPolygonToArea, /* 70 */
+ TkPolygonToPoint, /* 71 */
+ TkPositionInTree, /* 72 */
+ TkpRedirectKeyEvent, /* 73 */
+ TkpSetMainMenubar, /* 74 */
+ TkpUseWindow, /* 75 */
+ TkpWindowWasRecentlyDeleted, /* 76 */
+ TkQueueEventForAllChildren, /* 77 */
+ TkReadBitmapFile, /* 78 */
+ TkScrollWindow, /* 79 */
+ TkSelDeadWindow, /* 80 */
+ TkSelEventProc, /* 81 */
+ TkSelInit, /* 82 */
+ TkSelPropProc, /* 83 */
+ TkSetClassProcs, /* 84 */
+ TkSetWindowMenuBar, /* 85 */
+ TkStringToKeysym, /* 86 */
+ TkThickPolyLineToArea, /* 87 */
+ TkWmAddToColormapWindows, /* 88 */
+ TkWmDeadWindow, /* 89 */
+ TkWmFocusToplevel, /* 90 */
+ TkWmMapWindow, /* 91 */
+ TkWmNewWindow, /* 92 */
+ TkWmProtocolEventProc, /* 93 */
+ TkWmRemoveFromColormapWindows, /* 94 */
+ TkWmRestackToplevel, /* 95 */
+ TkWmSetClass, /* 96 */
+ TkWmUnmapWindow, /* 97 */
+ TkDebugBitmap, /* 98 */
+ TkDebugBorder, /* 99 */
+ TkDebugCursor, /* 100 */
+ TkDebugColor, /* 101 */
+ TkDebugConfig, /* 102 */
+ TkDebugFont, /* 103 */
+ TkFindStateNumObj, /* 104 */
+ TkGetBitmapPredefTable, /* 105 */
+ TkGetDisplayList, /* 106 */
+ TkGetMainInfoList, /* 107 */
+ TkGetWindowFromObj, /* 108 */
+ TkpGetString, /* 109 */
+ TkpGetSubFonts, /* 110 */
+ TkpGetSystemDefault, /* 111 */
+ TkpMenuThreadInit, /* 112 */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 113 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkClipBox, /* 113 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkClipBox, /* 113 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 114 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkCreateRegion, /* 114 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkCreateRegion, /* 114 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 115 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkDestroyRegion, /* 115 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkDestroyRegion, /* 115 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 116 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkIntersectRegion, /* 116 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkIntersectRegion, /* 116 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 117 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkRectInRegion, /* 117 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkRectInRegion, /* 117 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 118 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkSetRegion, /* 118 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkSetRegion, /* 118 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 119 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkUnionRectWithRegion, /* 119 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkUnionRectWithRegion, /* 119 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 120 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 120 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkGenerateActivateEvents, /* 120 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 121 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 121 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpCreateNativeBitmap, /* 121 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 122 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 122 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpDefineNativeBitmaps, /* 122 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 123 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 123 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpGetMS, /* 123 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 124 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 124 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpGetNativeAppBitmap, /* 124 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 125 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 125 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkPointerDeadWindow, /* 125 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 126 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 126 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpSetCapture, /* 126 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 127 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 127 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpSetCursor, /* 127 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 128 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 128 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkpWmSetState, /* 128 */
+#endif /* MAC_TCL */
+ NULL, /* 129 */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 130 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 130 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkGetTransientMaster, /* 130 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 131 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 131 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkGenerateButtonEvent, /* 131 */
+#endif /* MAC_TCL */
+ NULL, /* 132 */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 133 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 133 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkGenWMDestroyEvent, /* 133 */
+#endif /* MAC_TCL */
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ NULL, /* 134 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ NULL, /* 134 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkGenWMConfigureEvent, /* 134 */
+#endif /* MAC_TCL */
+ TkpDrawHighlightBorder, /* 135 */
+ TkSetFocusWin, /* 136 */
+ TkpSetKeycodeAndState, /* 137 */
+ TkpGetKeySym, /* 138 */
+ TkpInitKeymapInfo, /* 139 */
+};
+
+TkIntPlatStubs tkIntPlatStubs = {
+ TCL_STUB_MAGIC,
+ NULL,
+#if !defined(__WIN32__) && !defined(MAC_TCL) /* UNIX */
+ TkCreateXEventSource, /* 0 */
+ TkFreeWindowId, /* 1 */
+ TkInitXId, /* 2 */
+ TkpCmapStressed, /* 3 */
+ TkpSync, /* 4 */
+ TkUnixContainerId, /* 5 */
+ TkUnixDoOneXEvent, /* 6 */
+ TkUnixSetMenubar, /* 7 */
+#endif /* UNIX */
+#ifdef __WIN32__
+ TkAlignImageData, /* 0 */
+ NULL, /* 1 */
+ TkGenerateActivateEvents, /* 2 */
+ TkpGetMS, /* 3 */
+ TkPointerDeadWindow, /* 4 */
+ TkpPrintWindowId, /* 5 */
+ TkpScanWindowId, /* 6 */
+ TkpSetCapture, /* 7 */
+ TkpSetCursor, /* 8 */
+ TkpWmSetState, /* 9 */
+ TkSetPixmapColormap, /* 10 */
+ TkWinCancelMouseTimer, /* 11 */
+ TkWinClipboardRender, /* 12 */
+ TkWinEmbeddedEventProc, /* 13 */
+ TkWinFillRect, /* 14 */
+ TkWinGetBorderPixels, /* 15 */
+ TkWinGetDrawableDC, /* 16 */
+ TkWinGetModifierState, /* 17 */
+ TkWinGetSystemPalette, /* 18 */
+ TkWinGetWrapperWindow, /* 19 */
+ TkWinHandleMenuEvent, /* 20 */
+ TkWinIndexOfColor, /* 21 */
+ TkWinReleaseDrawableDC, /* 22 */
+ TkWinResendEvent, /* 23 */
+ TkWinSelectPalette, /* 24 */
+ TkWinSetMenu, /* 25 */
+ TkWinSetWindowPos, /* 26 */
+ TkWinWmCleanup, /* 27 */
+ TkWinXCleanup, /* 28 */
+ TkWinXInit, /* 29 */
+ TkWinSetForegroundWindow, /* 30 */
+ TkWinDialogDebug, /* 31 */
+ TkWinGetMenuSystemDefault, /* 32 */
+ TkWinGetPlatformId, /* 33 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ TkGenerateActivateEvents, /* 0 */
+ TkpCreateNativeBitmap, /* 1 */
+ TkpDefineNativeBitmaps, /* 2 */
+ TkpGetMS, /* 3 */
+ NULL, /* 4 */
+ TkPointerDeadWindow, /* 5 */
+ TkpSetCapture, /* 6 */
+ TkpSetCursor, /* 7 */
+ TkpWmSetState, /* 8 */
+ NULL, /* 9 */
+ TkAboutDlg, /* 10 */
+ NULL, /* 11 */
+ NULL, /* 12 */
+ TkGetTransientMaster, /* 13 */
+ TkGenerateButtonEvent, /* 14 */
+ NULL, /* 15 */
+ TkGenWMDestroyEvent, /* 16 */
+ TkGenWMConfigureEvent, /* 17 */
+ TkMacButtonKeyState, /* 18 */
+ TkMacClearMenubarActive, /* 19 */
+ TkMacConvertEvent, /* 20 */
+ TkMacDispatchMenuEvent, /* 21 */
+ TkMacInstallCursor, /* 22 */
+ TkMacConvertTkEvent, /* 23 */
+ TkMacHandleTearoffMenu, /* 24 */
+ NULL, /* 25 */
+ TkMacInvalClipRgns, /* 26 */
+ TkMacDoHLEvent, /* 27 */
+ NULL, /* 28 */
+ TkMacGenerateTime, /* 29 */
+ TkMacGetDrawablePort, /* 30 */
+ TkMacGetScrollbarGrowWindow, /* 31 */
+ TkMacGetXWindow, /* 32 */
+ TkMacGrowToplevel, /* 33 */
+ TkMacHandleMenuSelect, /* 34 */
+ TkMacHaveAppearance, /* 35 */
+ TkMacInitAppleEvents, /* 36 */
+ TkMacInitMenus, /* 37 */
+ TkMacInvalidateWindow, /* 38 */
+ TkMacIsCharacterMissing, /* 39 */
+ TkMacMakeRealWindowExist, /* 40 */
+ TkMacMakeStippleMap, /* 41 */
+ TkMacMenuClick, /* 42 */
+ TkMacRegisterOffScreenWindow, /* 43 */
+ TkMacResizable, /* 44 */
+ NULL, /* 45 */
+ TkMacSetHelpMenuItemCount, /* 46 */
+ TkMacSetScrollbarGrow, /* 47 */
+ TkMacSetUpClippingRgn, /* 48 */
+ TkMacSetUpGraphicsPort, /* 49 */
+ TkMacUpdateClipRgn, /* 50 */
+ TkMacUnregisterMacWindow, /* 51 */
+ TkMacUseMenuID, /* 52 */
+ TkMacVisableClipRgn, /* 53 */
+ TkMacWinBounds, /* 54 */
+ TkMacWindowOffset, /* 55 */
+ NULL, /* 56 */
+ TkSetMacColor, /* 57 */
+ TkSetWMName, /* 58 */
+ TkSuspendClipboard, /* 59 */
+ NULL, /* 60 */
+ TkMacZoomToplevel, /* 61 */
+ Tk_TopCoordsToWindow, /* 62 */
+ TkMacContainerId, /* 63 */
+ TkMacGetHostToplevel, /* 64 */
+ TkMacPreprocessMenu, /* 65 */
+#endif /* MAC_TCL */
+};
+
+TkIntXlibStubs tkIntXlibStubs = {
+ TCL_STUB_MAGIC,
+ NULL,
+#ifdef __WIN32__
+ XSetDashes, /* 0 */
+ XGetModifierMapping, /* 1 */
+ XCreateImage, /* 2 */
+ XGetImage, /* 3 */
+ XGetAtomName, /* 4 */
+ XKeysymToString, /* 5 */
+ XCreateColormap, /* 6 */
+ XCreatePixmapCursor, /* 7 */
+ XCreateGlyphCursor, /* 8 */
+ XGContextFromGC, /* 9 */
+ XListHosts, /* 10 */
+ XKeycodeToKeysym, /* 11 */
+ XStringToKeysym, /* 12 */
+ XRootWindow, /* 13 */
+ XSetErrorHandler, /* 14 */
+ XIconifyWindow, /* 15 */
+ XWithdrawWindow, /* 16 */
+ XGetWMColormapWindows, /* 17 */
+ XAllocColor, /* 18 */
+ XBell, /* 19 */
+ XChangeProperty, /* 20 */
+ XChangeWindowAttributes, /* 21 */
+ XClearWindow, /* 22 */
+ XConfigureWindow, /* 23 */
+ XCopyArea, /* 24 */
+ XCopyPlane, /* 25 */
+ XCreateBitmapFromData, /* 26 */
+ XDefineCursor, /* 27 */
+ XDeleteProperty, /* 28 */
+ XDestroyWindow, /* 29 */
+ XDrawArc, /* 30 */
+ XDrawLines, /* 31 */
+ XDrawRectangle, /* 32 */
+ XFillArc, /* 33 */
+ XFillPolygon, /* 34 */
+ XFillRectangles, /* 35 */
+ XForceScreenSaver, /* 36 */
+ XFreeColormap, /* 37 */
+ XFreeColors, /* 38 */
+ XFreeCursor, /* 39 */
+ XFreeModifiermap, /* 40 */
+ XGetGeometry, /* 41 */
+ XGetInputFocus, /* 42 */
+ XGetWindowProperty, /* 43 */
+ XGetWindowAttributes, /* 44 */
+ XGrabKeyboard, /* 45 */
+ XGrabPointer, /* 46 */
+ XKeysymToKeycode, /* 47 */
+ XLookupColor, /* 48 */
+ XMapWindow, /* 49 */
+ XMoveResizeWindow, /* 50 */
+ XMoveWindow, /* 51 */
+ XNextEvent, /* 52 */
+ XPutBackEvent, /* 53 */
+ XQueryColors, /* 54 */
+ XQueryPointer, /* 55 */
+ XQueryTree, /* 56 */
+ XRaiseWindow, /* 57 */
+ XRefreshKeyboardMapping, /* 58 */
+ XResizeWindow, /* 59 */
+ XSelectInput, /* 60 */
+ XSendEvent, /* 61 */
+ XSetCommand, /* 62 */
+ XSetIconName, /* 63 */
+ XSetInputFocus, /* 64 */
+ XSetSelectionOwner, /* 65 */
+ XSetWindowBackground, /* 66 */
+ XSetWindowBackgroundPixmap, /* 67 */
+ XSetWindowBorder, /* 68 */
+ XSetWindowBorderPixmap, /* 69 */
+ XSetWindowBorderWidth, /* 70 */
+ XSetWindowColormap, /* 71 */
+ XTranslateCoordinates, /* 72 */
+ XUngrabKeyboard, /* 73 */
+ XUngrabPointer, /* 74 */
+ XUnmapWindow, /* 75 */
+ XWindowEvent, /* 76 */
+ XDestroyIC, /* 77 */
+ XFilterEvent, /* 78 */
+ XmbLookupString, /* 79 */
+ TkPutImage, /* 80 */
+ NULL, /* 81 */
+ XParseColor, /* 82 */
+ XCreateGC, /* 83 */
+ XFreeGC, /* 84 */
+ XInternAtom, /* 85 */
+ XSetBackground, /* 86 */
+ XSetForeground, /* 87 */
+ XSetClipMask, /* 88 */
+ XSetClipOrigin, /* 89 */
+ XSetTSOrigin, /* 90 */
+ XChangeGC, /* 91 */
+ XSetFont, /* 92 */
+ XSetArcMode, /* 93 */
+ XSetStipple, /* 94 */
+ XSetFillRule, /* 95 */
+ XSetFillStyle, /* 96 */
+ XSetFunction, /* 97 */
+ XSetLineAttributes, /* 98 */
+ _XInitImageFuncPtrs, /* 99 */
+ XCreateIC, /* 100 */
+ XGetVisualInfo, /* 101 */
+ XSetWMClientMachine, /* 102 */
+ XStringListToTextProperty, /* 103 */
+ XDrawLine, /* 104 */
+ XWarpPointer, /* 105 */
+ XFillRectangle, /* 106 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ XSetDashes, /* 0 */
+ XGetModifierMapping, /* 1 */
+ XCreateImage, /* 2 */
+ XGetImage, /* 3 */
+ XGetAtomName, /* 4 */
+ XKeysymToString, /* 5 */
+ XCreateColormap, /* 6 */
+ XGContextFromGC, /* 7 */
+ XKeycodeToKeysym, /* 8 */
+ XStringToKeysym, /* 9 */
+ XRootWindow, /* 10 */
+ XSetErrorHandler, /* 11 */
+ XAllocColor, /* 12 */
+ XBell, /* 13 */
+ XChangeProperty, /* 14 */
+ XChangeWindowAttributes, /* 15 */
+ XConfigureWindow, /* 16 */
+ XCopyArea, /* 17 */
+ XCopyPlane, /* 18 */
+ XCreateBitmapFromData, /* 19 */
+ XDefineCursor, /* 20 */
+ XDestroyWindow, /* 21 */
+ XDrawArc, /* 22 */
+ XDrawLines, /* 23 */
+ XDrawRectangle, /* 24 */
+ XFillArc, /* 25 */
+ XFillPolygon, /* 26 */
+ XFillRectangles, /* 27 */
+ XFreeColormap, /* 28 */
+ XFreeColors, /* 29 */
+ XFreeModifiermap, /* 30 */
+ XGetGeometry, /* 31 */
+ XGetWindowProperty, /* 32 */
+ XGrabKeyboard, /* 33 */
+ XGrabPointer, /* 34 */
+ XKeysymToKeycode, /* 35 */
+ XMapWindow, /* 36 */
+ XMoveResizeWindow, /* 37 */
+ XMoveWindow, /* 38 */
+ XQueryPointer, /* 39 */
+ XRaiseWindow, /* 40 */
+ XRefreshKeyboardMapping, /* 41 */
+ XResizeWindow, /* 42 */
+ XSelectInput, /* 43 */
+ XSendEvent, /* 44 */
+ XSetIconName, /* 45 */
+ XSetInputFocus, /* 46 */
+ XSetSelectionOwner, /* 47 */
+ XSetWindowBackground, /* 48 */
+ XSetWindowBackgroundPixmap, /* 49 */
+ XSetWindowBorder, /* 50 */
+ XSetWindowBorderPixmap, /* 51 */
+ XSetWindowBorderWidth, /* 52 */
+ XSetWindowColormap, /* 53 */
+ XUngrabKeyboard, /* 54 */
+ XUngrabPointer, /* 55 */
+ XUnmapWindow, /* 56 */
+ TkPutImage, /* 57 */
+ XParseColor, /* 58 */
+ XCreateGC, /* 59 */
+ XFreeGC, /* 60 */
+ XInternAtom, /* 61 */
+ XSetBackground, /* 62 */
+ XSetForeground, /* 63 */
+ XSetClipMask, /* 64 */
+ XSetClipOrigin, /* 65 */
+ XSetTSOrigin, /* 66 */
+ XChangeGC, /* 67 */
+ XSetFont, /* 68 */
+ XSetArcMode, /* 69 */
+ XSetStipple, /* 70 */
+ XSetFillRule, /* 71 */
+ XSetFillStyle, /* 72 */
+ XSetFunction, /* 73 */
+ XSetLineAttributes, /* 74 */
+ _XInitImageFuncPtrs, /* 75 */
+ XCreateIC, /* 76 */
+ XGetVisualInfo, /* 77 */
+ XSetWMClientMachine, /* 78 */
+ XStringListToTextProperty, /* 79 */
+ XDrawSegments, /* 80 */
+ XForceScreenSaver, /* 81 */
+ XDrawLine, /* 82 */
+ XFillRectangle, /* 83 */
+ XClearWindow, /* 84 */
+ XDrawPoint, /* 85 */
+ XDrawPoints, /* 86 */
+ XWarpPointer, /* 87 */
+ XQueryColor, /* 88 */
+ XQueryColors, /* 89 */
+#endif /* MAC_TCL */
+};
+
+TkPlatStubs tkPlatStubs = {
+ TCL_STUB_MAGIC,
+ NULL,
+#ifdef __WIN32__
+ Tk_AttachHWND, /* 0 */
+ Tk_GetHINSTANCE, /* 1 */
+ Tk_GetHWND, /* 2 */
+ Tk_HWNDToWindow, /* 3 */
+ Tk_PointerEvent, /* 4 */
+ Tk_TranslateWinEvent, /* 5 */
+#endif /* __WIN32__ */
+#ifdef MAC_TCL
+ Tk_MacSetEmbedHandler, /* 0 */
+ Tk_MacTurnOffMenus, /* 1 */
+ Tk_MacTkOwnsCursor, /* 2 */
+ TkMacInitMenus, /* 3 */
+ TkMacInitAppleEvents, /* 4 */
+ TkMacConvertEvent, /* 5 */
+ TkMacConvertTkEvent, /* 6 */
+ TkGenWMConfigureEvent, /* 7 */
+ TkMacInvalClipRgns, /* 8 */
+ TkMacHaveAppearance, /* 9 */
+ TkMacGetDrawablePort, /* 10 */
+#endif /* MAC_TCL */
+};
+
+static TkStubHooks tkStubHooks = {
+ &tkPlatStubs,
+ &tkIntStubs,
+ &tkIntPlatStubs,
+ &tkIntXlibStubs
+};
+
+TkStubs tkStubs = {
+ TCL_STUB_MAGIC,
+ &tkStubHooks,
+ Tk_MainLoop, /* 0 */
+ Tk_3DBorderColor, /* 1 */
+ Tk_3DBorderGC, /* 2 */
+ Tk_3DHorizontalBevel, /* 3 */
+ Tk_3DVerticalBevel, /* 4 */
+ Tk_AddOption, /* 5 */
+ Tk_BindEvent, /* 6 */
+ Tk_CanvasDrawableCoords, /* 7 */
+ Tk_CanvasEventuallyRedraw, /* 8 */
+ Tk_CanvasGetCoord, /* 9 */
+ Tk_CanvasGetTextInfo, /* 10 */
+ Tk_CanvasPsBitmap, /* 11 */
+ Tk_CanvasPsColor, /* 12 */
+ Tk_CanvasPsFont, /* 13 */
+ Tk_CanvasPsPath, /* 14 */
+ Tk_CanvasPsStipple, /* 15 */
+ Tk_CanvasPsY, /* 16 */
+ Tk_CanvasSetStippleOrigin, /* 17 */
+ Tk_CanvasTagsParseProc, /* 18 */
+ Tk_CanvasTagsPrintProc, /* 19 */
+ Tk_CanvasTkwin, /* 20 */
+ Tk_CanvasWindowCoords, /* 21 */
+ Tk_ChangeWindowAttributes, /* 22 */
+ Tk_CharBbox, /* 23 */
+ Tk_ClearSelection, /* 24 */
+ Tk_ClipboardAppend, /* 25 */
+ Tk_ClipboardClear, /* 26 */
+ Tk_ConfigureInfo, /* 27 */
+ Tk_ConfigureValue, /* 28 */
+ Tk_ConfigureWidget, /* 29 */
+ Tk_ConfigureWindow, /* 30 */
+ Tk_ComputeTextLayout, /* 31 */
+ Tk_CoordsToWindow, /* 32 */
+ Tk_CreateBinding, /* 33 */
+ Tk_CreateBindingTable, /* 34 */
+ Tk_CreateErrorHandler, /* 35 */
+ Tk_CreateEventHandler, /* 36 */
+ Tk_CreateGenericHandler, /* 37 */
+ Tk_CreateImageType, /* 38 */
+ Tk_CreateItemType, /* 39 */
+ Tk_CreatePhotoImageFormat, /* 40 */
+ Tk_CreateSelHandler, /* 41 */
+ Tk_CreateWindow, /* 42 */
+ Tk_CreateWindowFromPath, /* 43 */
+ Tk_DefineBitmap, /* 44 */
+ Tk_DefineCursor, /* 45 */
+ Tk_DeleteAllBindings, /* 46 */
+ Tk_DeleteBinding, /* 47 */
+ Tk_DeleteBindingTable, /* 48 */
+ Tk_DeleteErrorHandler, /* 49 */
+ Tk_DeleteEventHandler, /* 50 */
+ Tk_DeleteGenericHandler, /* 51 */
+ Tk_DeleteImage, /* 52 */
+ Tk_DeleteSelHandler, /* 53 */
+ Tk_DestroyWindow, /* 54 */
+ Tk_DisplayName, /* 55 */
+ Tk_DistanceToTextLayout, /* 56 */
+ Tk_Draw3DPolygon, /* 57 */
+ Tk_Draw3DRectangle, /* 58 */
+ Tk_DrawChars, /* 59 */
+ Tk_DrawFocusHighlight, /* 60 */
+ Tk_DrawTextLayout, /* 61 */
+ Tk_Fill3DPolygon, /* 62 */
+ Tk_Fill3DRectangle, /* 63 */
+ Tk_FindPhoto, /* 64 */
+ Tk_FontId, /* 65 */
+ Tk_Free3DBorder, /* 66 */
+ Tk_FreeBitmap, /* 67 */
+ Tk_FreeColor, /* 68 */
+ Tk_FreeColormap, /* 69 */
+ Tk_FreeCursor, /* 70 */
+ Tk_FreeFont, /* 71 */
+ Tk_FreeGC, /* 72 */
+ Tk_FreeImage, /* 73 */
+ Tk_FreeOptions, /* 74 */
+ Tk_FreePixmap, /* 75 */
+ Tk_FreeTextLayout, /* 76 */
+ Tk_FreeXId, /* 77 */
+ Tk_GCForColor, /* 78 */
+ Tk_GeometryRequest, /* 79 */
+ Tk_Get3DBorder, /* 80 */
+ Tk_GetAllBindings, /* 81 */
+ Tk_GetAnchor, /* 82 */
+ Tk_GetAtomName, /* 83 */
+ Tk_GetBinding, /* 84 */
+ Tk_GetBitmap, /* 85 */
+ Tk_GetBitmapFromData, /* 86 */
+ Tk_GetCapStyle, /* 87 */
+ Tk_GetColor, /* 88 */
+ Tk_GetColorByValue, /* 89 */
+ Tk_GetColormap, /* 90 */
+ Tk_GetCursor, /* 91 */
+ Tk_GetCursorFromData, /* 92 */
+ Tk_GetFont, /* 93 */
+ Tk_GetFontFromObj, /* 94 */
+ Tk_GetFontMetrics, /* 95 */
+ Tk_GetGC, /* 96 */
+ Tk_GetImage, /* 97 */
+ Tk_GetImageMasterData, /* 98 */
+ Tk_GetItemTypes, /* 99 */
+ Tk_GetJoinStyle, /* 100 */
+ Tk_GetJustify, /* 101 */
+ Tk_GetNumMainWindows, /* 102 */
+ Tk_GetOption, /* 103 */
+ Tk_GetPixels, /* 104 */
+ Tk_GetPixmap, /* 105 */
+ Tk_GetRelief, /* 106 */
+ Tk_GetRootCoords, /* 107 */
+ Tk_GetScrollInfo, /* 108 */
+ Tk_GetScreenMM, /* 109 */
+ Tk_GetSelection, /* 110 */
+ Tk_GetUid, /* 111 */
+ Tk_GetVisual, /* 112 */
+ Tk_GetVRootGeometry, /* 113 */
+ Tk_Grab, /* 114 */
+ Tk_HandleEvent, /* 115 */
+ Tk_IdToWindow, /* 116 */
+ Tk_ImageChanged, /* 117 */
+ Tk_Init, /* 118 */
+ Tk_InternAtom, /* 119 */
+ Tk_IntersectTextLayout, /* 120 */
+ Tk_MaintainGeometry, /* 121 */
+ Tk_MainWindow, /* 122 */
+ Tk_MakeWindowExist, /* 123 */
+ Tk_ManageGeometry, /* 124 */
+ Tk_MapWindow, /* 125 */
+ Tk_MeasureChars, /* 126 */
+ Tk_MoveResizeWindow, /* 127 */
+ Tk_MoveWindow, /* 128 */
+ Tk_MoveToplevelWindow, /* 129 */
+ Tk_NameOf3DBorder, /* 130 */
+ Tk_NameOfAnchor, /* 131 */
+ Tk_NameOfBitmap, /* 132 */
+ Tk_NameOfCapStyle, /* 133 */
+ Tk_NameOfColor, /* 134 */
+ Tk_NameOfCursor, /* 135 */
+ Tk_NameOfFont, /* 136 */
+ Tk_NameOfImage, /* 137 */
+ Tk_NameOfJoinStyle, /* 138 */
+ Tk_NameOfJustify, /* 139 */
+ Tk_NameOfRelief, /* 140 */
+ Tk_NameToWindow, /* 141 */
+ Tk_OwnSelection, /* 142 */
+ Tk_ParseArgv, /* 143 */
+ Tk_PhotoPutBlock, /* 144 */
+ Tk_PhotoPutZoomedBlock, /* 145 */
+ Tk_PhotoGetImage, /* 146 */
+ Tk_PhotoBlank, /* 147 */
+ Tk_PhotoExpand, /* 148 */
+ Tk_PhotoGetSize, /* 149 */
+ Tk_PhotoSetSize, /* 150 */
+ Tk_PointToChar, /* 151 */
+ Tk_PostscriptFontName, /* 152 */
+ Tk_PreserveColormap, /* 153 */
+ Tk_QueueWindowEvent, /* 154 */
+ Tk_RedrawImage, /* 155 */
+ Tk_ResizeWindow, /* 156 */
+ Tk_RestackWindow, /* 157 */
+ Tk_RestrictEvents, /* 158 */
+ Tk_SafeInit, /* 159 */
+ Tk_SetAppName, /* 160 */
+ Tk_SetBackgroundFromBorder, /* 161 */
+ Tk_SetClass, /* 162 */
+ Tk_SetGrid, /* 163 */
+ Tk_SetInternalBorder, /* 164 */
+ Tk_SetWindowBackground, /* 165 */
+ Tk_SetWindowBackgroundPixmap, /* 166 */
+ Tk_SetWindowBorder, /* 167 */
+ Tk_SetWindowBorderWidth, /* 168 */
+ Tk_SetWindowBorderPixmap, /* 169 */
+ Tk_SetWindowColormap, /* 170 */
+ Tk_SetWindowVisual, /* 171 */
+ Tk_SizeOfBitmap, /* 172 */
+ Tk_SizeOfImage, /* 173 */
+ Tk_StrictMotif, /* 174 */
+ Tk_TextLayoutToPostscript, /* 175 */
+ Tk_TextWidth, /* 176 */
+ Tk_UndefineCursor, /* 177 */
+ Tk_UnderlineChars, /* 178 */
+ Tk_UnderlineTextLayout, /* 179 */
+ Tk_Ungrab, /* 180 */
+ Tk_UnmaintainGeometry, /* 181 */
+ Tk_UnmapWindow, /* 182 */
+ Tk_UnsetGrid, /* 183 */
+ Tk_UpdatePointer, /* 184 */
+ Tk_AllocBitmapFromObj, /* 185 */
+ Tk_Alloc3DBorderFromObj, /* 186 */
+ Tk_AllocColorFromObj, /* 187 */
+ Tk_AllocCursorFromObj, /* 188 */
+ Tk_AllocFontFromObj, /* 189 */
+ Tk_CreateOptionTable, /* 190 */
+ Tk_DeleteOptionTable, /* 191 */
+ Tk_Free3DBorderFromObj, /* 192 */
+ Tk_FreeBitmapFromObj, /* 193 */
+ Tk_FreeColorFromObj, /* 194 */
+ Tk_FreeConfigOptions, /* 195 */
+ Tk_FreeSavedOptions, /* 196 */
+ Tk_FreeCursorFromObj, /* 197 */
+ Tk_FreeFontFromObj, /* 198 */
+ Tk_Get3DBorderFromObj, /* 199 */
+ Tk_GetAnchorFromObj, /* 200 */
+ Tk_GetBitmapFromObj, /* 201 */
+ Tk_GetColorFromObj, /* 202 */
+ Tk_GetCursorFromObj, /* 203 */
+ Tk_GetOptionInfo, /* 204 */
+ Tk_GetOptionValue, /* 205 */
+ Tk_GetJustifyFromObj, /* 206 */
+ Tk_GetMMFromObj, /* 207 */
+ Tk_GetPixelsFromObj, /* 208 */
+ Tk_GetReliefFromObj, /* 209 */
+ Tk_GetScrollInfoObj, /* 210 */
+ Tk_InitOptions, /* 211 */
+ Tk_MainEx, /* 212 */
+ Tk_RestoreSavedOptions, /* 213 */
+ Tk_SetOptions, /* 214 */
+ Tk_InitConsoleChannels, /* 215 */
+ Tk_CreateConsoleWindow, /* 216 */
+ Tk_CreateSmoothMethod, /* 217 */
+ NULL, /* 218 */
+ NULL, /* 219 */
+ Tk_GetDash, /* 220 */
+ Tk_CreateOutline, /* 221 */
+ Tk_DeleteOutline, /* 222 */
+ Tk_ConfigOutlineGC, /* 223 */
+ Tk_ChangeOutlineGC, /* 224 */
+ Tk_ResetOutlineGC, /* 225 */
+ Tk_CanvasPsOutline, /* 226 */
+ Tk_SetTSOrigin, /* 227 */
+ Tk_CanvasGetCoordFromObj, /* 228 */
+ Tk_CanvasSetOffset, /* 229 */
+ Tk_DitherPhoto, /* 230 */
+ Tk_PostscriptBitmap, /* 231 */
+ Tk_PostscriptColor, /* 232 */
+ Tk_PostscriptFont, /* 233 */
+ Tk_PostscriptImage, /* 234 */
+ Tk_PostscriptPath, /* 235 */
+ Tk_PostscriptStipple, /* 236 */
+ Tk_PostscriptY, /* 237 */
+ Tk_PostscriptPhoto, /* 238 */
+};
+
+/* !END!: Do not edit above this line. */
diff --git a/tk/generic/tkStubLib.c b/tk/generic/tkStubLib.c
new file mode 100644
index 00000000000..7a9e7bd0d53
--- /dev/null
+++ b/tk/generic/tkStubLib.c
@@ -0,0 +1,110 @@
+/*
+ * tkStubLib.c --
+ *
+ * Stub object that will be statically linked into extensions that wish
+ * to access Tk.
+ *
+ * Copyright (c) 1998 Paul Duffin.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+/*
+ * We need to ensure that we use the stub macros so that this file contains
+ * no references to any of the stub functions. This will make it possible
+ * to build an extension that references Tk_InitStubs but doesn't end up
+ * including the rest of the stub functions.
+ */
+
+
+#ifndef USE_TCL_STUBS
+#define USE_TCL_STUBS
+#endif
+#undef USE_TCL_STUB_PROCS
+
+#ifndef USE_TK_STUBS
+#define USE_TK_STUBS
+#endif
+#undef USE_TK_STUB_PROCS
+
+#include "tkPort.h"
+#include "tkInt.h"
+
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+#ifdef MAC_TCL
+#include "tkMacInt.h"
+#endif
+
+#include "tkDecls.h"
+#include "tkIntDecls.h"
+#include "tkPlatDecls.h"
+#include "tkIntPlatDecls.h"
+#include "tkIntXlibDecls.h"
+
+/*
+ * Ensure that Tk_InitStubs is built as an exported symbol. The other stub
+ * functions should be built as non-exported symbols.
+ */
+
+#undef TCL_STORAGE_CLASS
+#define TCL_STORAGE_CLASS DLLEXPORT
+
+TkStubs *tkStubsPtr;
+TkPlatStubs *tkPlatStubsPtr;
+TkIntStubs *tkIntStubsPtr;
+TkIntPlatStubs *tkIntPlatStubsPtr;
+TkIntXlibStubs *tkIntXlibStubsPtr;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_InitStubs --
+ *
+ * Checks that the correct version of Tk is loaded and that it
+ * supports stubs. It then initialises the stub table pointers.
+ *
+ * Results:
+ * The actual version of Tk that satisfies the request, or
+ * NULL to indicate that an error occurred.
+ *
+ * Side effects:
+ * Sets the stub table pointers.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+Tk_InitStubs(interp, version, exact)
+ Tcl_Interp *interp;
+ char *version;
+ int exact;
+{
+ char *actualVersion;
+
+ actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, exact,
+ (ClientData *) &tkStubsPtr);
+ if (!actualVersion) {
+ return NULL;
+ }
+
+ if (!tkStubsPtr) {
+ Tcl_SetResult(interp,
+ "This implementation of Tk does not support stubs",
+ TCL_STATIC);
+ return NULL;
+ }
+
+ tkPlatStubsPtr = tkStubsPtr->hooks->tkPlatStubs;
+ tkIntStubsPtr = tkStubsPtr->hooks->tkIntStubs;
+ tkIntPlatStubsPtr = tkStubsPtr->hooks->tkIntPlatStubs;
+ tkIntXlibStubsPtr = tkStubsPtr->hooks->tkIntXlibStubs;
+
+ return actualVersion;
+}
diff --git a/tk/generic/tkTest.c b/tk/generic/tkTest.c
index e33d6b62853..7fd0d5125b4 100644
--- a/tk/generic/tkTest.c
+++ b/tk/generic/tkTest.c
@@ -8,6 +8,7 @@
*
* Copyright (c) 1993-1994 The Regents of the University of California.
* Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1998-1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -16,7 +17,8 @@
*/
#include "tkInt.h"
-#include "tkPort.h"
+#include "tkPort.h"
+#include "tkText.h"
#ifdef __WIN32__
#include "tkWinInt.h"
@@ -59,10 +61,17 @@ typedef struct TImageInstance {
* The type record for test images:
*/
+#ifdef USE_OLD_IMAGE
+static int ImageCreate _ANSI_ARGS_((Tcl_Interp *interp,
+ char *name, int argc, char **argv,
+ Tk_ImageType *typePtr, Tk_ImageMaster master,
+ ClientData *clientDataPtr));
+#else
static int ImageCreate _ANSI_ARGS_((Tcl_Interp *interp,
char *name, int argc, Tcl_Obj *CONST objv[],
Tk_ImageType *typePtr, Tk_ImageMaster master,
ClientData *clientDataPtr));
+#endif
static ClientData ImageGet _ANSI_ARGS_((Tk_Window tkwin,
ClientData clientData));
static void ImageDisplay _ANSI_ARGS_((ClientData clientData,
@@ -76,11 +85,12 @@ static void ImageDelete _ANSI_ARGS_((ClientData clientData));
static Tk_ImageType imageType = {
"test", /* name */
- ImageCreate, /* createProc */
+ (Tk_ImageCreateProc *) ImageCreate, /* createProc */
ImageGet, /* getProc */
ImageDisplay, /* displayProc */
ImageFree, /* freeProc */
ImageDelete, /* deleteProc */
+ (Tk_ImagePostscriptProc *) NULL,/* postscriptPtr */
(Tk_ImageType *) NULL /* nextPtr */
};
@@ -102,8 +112,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 +122,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 +160,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,22 +185,35 @@ 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:
*/
-EXTERN int TkplatformtestInit _ANSI_ARGS_((
- Tcl_Interp *interp));
-#ifndef MAC_TCL
+extern int TkplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
+extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp));
+
+#if !(defined(__WIN32__) || defined(MAC_TCL))
#define TkplatformtestInit(x) TCL_OK
#endif
@@ -167,7 +227,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 +249,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,12 +281,20 @@ 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);
#endif
-/*
+#ifdef TCL_THREADS
+ if (TclThread_Init(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+#endif
+
+ /*
* Create test image type.
*/
@@ -237,48 +313,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 +420,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 +598,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"
@@ -439,6 +1563,7 @@ TestdeleteappsCmd(clientData, interp, argc, argv)
*/
/* ARGSUSED */
+#ifdef USE_OLD_IMAGE
static int
ImageCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
Tcl_Interp *interp; /* Interpreter for application containing
@@ -457,21 +1582,55 @@ ImageCreate(interp, name, argc, objv, typePtr, master, clientDataPtr)
char *varName;
int i;
+ Tk_InitImageArgs(interp, argc, &argv);
varName = "log";
for (i = 0; i < argc; i += 2) {
- char *arg = Tcl_GetStringFromObj(objv[i], NULL);
- if (strcmp(arg, "-variable") != 0) {
- Tcl_AppendResult(interp, "bad option name \"", arg,
- "\"", (char *) NULL);
+ if (strcmp(argv[i], "-variable") != 0) {
+ Tcl_AppendResult(interp, "bad option name \"",
+ argv[i], "\"", (char *) NULL);
return TCL_ERROR;
}
if ((i+1) == argc) {
- Tcl_AppendResult(interp, "no value given for \"", arg,
- "\" option", (char *) NULL);
+ Tcl_AppendResult(interp, "no value given for \"",
+ argv[i], "\" option", (char *) NULL);
return TCL_ERROR;
}
varName = Tcl_GetStringFromObj(objv[i+1], NULL);
}
+#else
+static int
+ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr)
+ Tcl_Interp *interp; /* Interpreter for application containing
+ * image. */
+ char *name; /* Name to use for image. */
+ int objc; /* Number of arguments. */
+ Tcl_Obj *CONST objv[]; /* Argument strings for options (doesn't
+ * include image name or type). */
+ Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
+ Tk_ImageMaster master; /* Token for image, to be used by us in
+ * later callbacks. */
+ ClientData *clientDataPtr; /* Store manager's token for image here;
+ * it will be returned in later callbacks. */
+{
+ TImageMaster *timPtr;
+ char *varName;
+ int i;
+
+ varName = "log";
+ for (i = 0; i < objc; i += 2) {
+ if (strcmp(Tcl_GetString(objv[i]), "-variable") != 0) {
+ Tcl_AppendResult(interp, "bad option name \"",
+ Tcl_GetString(objv[i]), "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ if ((i+1) == objc) {
+ Tcl_AppendResult(interp, "no value given for \"",
+ Tcl_GetString(objv[i]), "\" option", (char *) NULL);
+ return TCL_ERROR;
+ }
+ varName = Tcl_GetString(objv[i+1]);
+ }
+#endif
timPtr = (TImageMaster *) ckalloc(sizeof(TImageMaster));
timPtr->master = master;
timPtr->interp = interp;
@@ -524,7 +1683,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;
}
@@ -618,7 +1778,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,
@@ -735,12 +1895,12 @@ TestmakeexistCmd(clientData, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- Tk_Window mainwin = (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], mainwin);
+ tkwin = Tk_NameToWindow(interp, argv[i], mainWin);
if (tkwin == NULL) {
return TCL_ERROR;
}
@@ -777,7 +1937,7 @@ TestmenubarCmd(clientData, interp, argc, argv)
char **argv; /* Argument strings. */
{
#ifdef __UNIX__
- Tk_Window mainwin = (Tk_Window) clientData;
+ Tk_Window mainWin = (Tk_Window) clientData;
Tk_Window tkwin, menubar;
if (argc < 2) {
@@ -792,14 +1952,14 @@ TestmenubarCmd(clientData, interp, argc, argv)
"window toplevel menubar\"", (char *) NULL);
return TCL_ERROR;
}
- tkwin = Tk_NameToWindow(interp, argv[2], mainwin);
+ 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], mainwin);
+ menubar = Tk_NameToWindow(interp, argv[3], mainWin);
if (menubar == NULL) {
return TCL_ERROR;
}
@@ -813,7 +1973,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
}
@@ -843,7 +2004,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],
@@ -875,7 +2036,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],
@@ -928,7 +2089,7 @@ TestpropCmd(clientData, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- Tk_Window mainwin = (Tk_Window) clientData;
+ Tk_Window mainWin = (Tk_Window) clientData;
int result, actualFormat;
unsigned long bytesAfter, length, value;
Atom actualType, propName;
@@ -943,9 +2104,9 @@ TestpropCmd(clientData, interp, argc, argv)
}
w = strtoul(argv[1], &end, 0);
- propName = Tk_InternAtom(mainwin, argv[2]);
+ propName = Tk_InternAtom(mainWin, argv[2]);
property = NULL;
- result = XGetWindowProperty(Tk_Display(mainwin),
+ result = XGetWindowProperty(Tk_Display(mainWin),
w, propName, 0, 100000, False, AnyPropertyType,
&actualType, &actualFormat, &length,
&bytesAfter, (unsigned char **) &property);
@@ -1006,7 +2167,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],
@@ -1074,7 +2237,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);
@@ -1084,6 +2250,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))
/*
*----------------------------------------------------------------------
@@ -1128,8 +2373,13 @@ 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;
}
#endif
+
+
diff --git a/tk/generic/tkText.c b/tk/generic/tkText.c
index d9ff1cc9165..560c0260d9c 100644
--- a/tk/generic/tkText.c
+++ b/tk/generic/tkText.c
@@ -9,6 +9,7 @@
*
* Copyright (c) 1992-1994 The Regents of the University of California.
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -28,6 +29,15 @@
#include "tkText.h"
/*
+ * Custom options for handling "-state"
+ */
+
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) NULL /* only "normal" and "disabled" */
+};
+
+/*
* Information used to parse text configuration options:
*/
@@ -112,8 +122,8 @@ static Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_PIXELS, "-spacing3", "spacing3", "Spacing",
DEF_TEXT_SPACING3, Tk_Offset(TkText, spacing3),
TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_UID, "-state", "state", "State",
- DEF_TEXT_STATE, Tk_Offset(TkText, state), 0},
+ {TK_CONFIG_CUSTOM, "-state", "state", "State",
+ DEF_TEXT_STATE, Tk_Offset(TkText, state), 0, &stateOption},
{TK_CONFIG_STRING, "-tabs", "tabs", "Tabs",
DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionString), TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
@@ -121,8 +131,8 @@ static Tk_ConfigSpec configSpecs[] = {
TK_CONFIG_NULL_OK},
{TK_CONFIG_INT, "-width", "width", "Width",
DEF_TEXT_WIDTH, Tk_Offset(TkText, width), 0},
- {TK_CONFIG_UID, "-wrap", "wrap", "Wrap",
- DEF_TEXT_WRAP, Tk_Offset(TkText, wrapMode), 0},
+ {TK_CONFIG_CUSTOM, "-wrap", "wrap", "Wrap",
+ DEF_TEXT_WRAP, Tk_Offset(TkText, wrapMode), 0, &textWrapModeOption},
{TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
DEF_TEXT_XSCROLL_COMMAND, Tk_Offset(TkText, xScrollCmd),
TK_CONFIG_NULL_OK},
@@ -143,21 +153,133 @@ static Tk_ConfigSpec configSpecs[] = {
};
/*
- * Tk_Uid's used to represent text states:
+ * Boolean variable indicating whether or not special debugging code
+ * should be executed.
*/
-Tk_Uid tkTextCharUid = NULL;
-Tk_Uid tkTextDisabledUid = NULL;
-Tk_Uid tkTextNoneUid = NULL;
-Tk_Uid tkTextNormalUid = NULL;
-Tk_Uid tkTextWordUid = NULL;
+int tkTextDebug = 0;
/*
- * Boolean variable indicating whether or not special debugging code
- * should be executed.
+ * Custom options for handling "-wrap":
*/
-int tkTextDebug = 0;
+static int WrapModeParseProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, char *value,
+ char *widgRec, int offset));
+static char * WrapModePrintProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+
+Tk_CustomOption textWrapModeOption = {
+ WrapModeParseProc,
+ WrapModePrintProc,
+ (ClientData) NULL
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WrapModeParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * "-wrap" options for text widgets.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The wrap mode for a given item gets replaced by the wrap mode
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+WrapModeParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *value; /* Value of option (list of tag
+ * names). */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register TkWrapMode *wrapPtr = (TkWrapMode *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *wrapPtr = TEXT_WRAPMODE_NULL;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'c') && (strncmp(value, "char", length) == 0)) {
+ *wrapPtr = TEXT_WRAPMODE_CHAR;
+ return TCL_OK;
+ }
+ if ((c == 'n') && (strncmp(value, "none", length) == 0)) {
+ *wrapPtr = TEXT_WRAPMODE_NONE;
+ return TCL_OK;
+ }
+ if ((c == 'w') && (strncmp(value, "word", length) == 0)) {
+ *wrapPtr = TEXT_WRAPMODE_WORD;
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "bad wrap mode \"", value,
+ "\": must be char, none, or word",
+ (char *) NULL);
+ *wrapPtr = TEXT_WRAPMODE_CHAR;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WrapModePrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-wrap" configuration
+ * option for canvas items.
+ *
+ * Results:
+ * The return value is a string describing the state for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static char *
+WrapModePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Ignored. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register TkWrapMode *wrapPtr = (TkWrapMode *) (widgRec + offset);
+
+ if (*wrapPtr==TEXT_WRAPMODE_CHAR) {
+ return "char";
+ } else if (*wrapPtr==TEXT_WRAPMODE_NONE) {
+ return "none";
+ } else if (*wrapPtr==TEXT_WRAPMODE_WORD) {
+ return "word";
+ } else {
+ return "";
+ }
+}
/*
* Forward declarations for procedures defined later in this file:
@@ -189,7 +311,7 @@ static void DumpLine _ANSI_ARGS_((Tcl_Interp *interp,
TkText *textPtr, int what, TkTextLine *linePtr,
int start, int end, int lineno, char *command));
static int DumpSegment _ANSI_ARGS_((Tcl_Interp *interp, char *key,
- char *value, char * command, int lineno, int offset,
+ char *value, char * command, TkTextIndex *index,
int what));
/*
@@ -241,18 +363,6 @@ Tk_TextCmd(clientData, interp, argc, argv)
}
/*
- * Perform once-only initialization:
- */
-
- if (tkTextNormalUid == NULL) {
- tkTextCharUid = Tk_GetUid("char");
- tkTextDisabledUid = Tk_GetUid("disabled");
- tkTextNoneUid = Tk_GetUid("none");
- tkTextNormalUid = Tk_GetUid("normal");
- tkTextWordUid = Tk_GetUid("word");
- }
-
- /*
* Create the window.
*/
@@ -274,7 +384,7 @@ Tk_TextCmd(clientData, interp, argc, argv)
Tcl_InitHashTable(&textPtr->markTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&textPtr->windowTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&textPtr->imageTable, TCL_STRING_KEYS);
- textPtr->state = tkTextNormalUid;
+ textPtr->state = TK_STATE_NORMAL;
textPtr->border = NULL;
textPtr->borderWidth = 0;
textPtr->padX = 0;
@@ -293,14 +403,14 @@ Tk_TextCmd(clientData, interp, argc, argv)
textPtr->tabOptionString = NULL;
textPtr->tabsize = 8;
textPtr->tabArrayPtr = NULL;
- textPtr->wrapMode = tkTextCharUid;
+ textPtr->wrapMode = TEXT_WRAPMODE_CHAR;
textPtr->width = 0;
textPtr->height = 0;
textPtr->setGrid = 0;
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;
@@ -336,7 +446,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);
@@ -357,7 +468,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;
}
@@ -474,7 +585,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)) {
@@ -532,7 +646,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) {
@@ -554,7 +668,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;
@@ -573,18 +687,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- if (textPtr->state == tkTextNormalUid) {
- /*
- * KHAMIS
- * Call synchronize command
- * BEFORE INSERTING INTO THE EDITOR
- ***********************************/
- if (textPtr->SyncCmd && *textPtr->SyncCmd) {
- result = ExecSyncCmd (interp, textPtr, argc, argv);
- if (result == TCL_ERROR) {
- goto done;
- }
- }
+ if (textPtr->state == TK_STATE_NORMAL) {
result = DeleteChars(textPtr, argv[2],
(argc == 4) ? argv[3] : (char *) NULL);
}
@@ -604,8 +707,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)) {
@@ -638,10 +743,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;
}
@@ -653,10 +758,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\"",
@@ -668,7 +775,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;
@@ -689,22 +797,11 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- if (textPtr->state == tkTextNormalUid) {
- /*
- * KHAMIS
- * Call synchronize command
- * BEFORE INSERTING INTO THE EDITOR
- ***********************************/
- if (textPtr->SyncCmd && *textPtr->SyncCmd) {
- result = ExecSyncCmd (interp, textPtr, argc, argv);
- if (result == TCL_ERROR) {
- goto done;
- }
- }
+ if (textPtr->state == TK_STATE_NORMAL) {
for (j = 3; j < argc; j += 2) {
InsertChars(textPtr, &index1, argv[j]);
if (argc > (j+1)) {
- TkTextIndexForwChars(&index1, (int) strlen(argv[j]),
+ TkTextIndexForwBytes(&index1, (int) strlen(argv[j]),
&index2);
oldTagArrayPtr = TkBTreeGetTags(&index1, &numTags);
if (oldTagArrayPtr != NULL) {
@@ -752,8 +849,8 @@ TextWidgetCmd(clientData, interp, argc, argv)
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be bbox, cget, compare, configure, debug, delete, ",
- "dlineinfo, get, image, index, insert, mark, scan, search, see, ",
- "tag, window, xview, or yview",
+ "dlineinfo, dump, get, image, index, insert, mark, scan, ",
+ "search, see, tag, window, xview, or yview",
(char *) NULL);
result = TCL_ERROR;
}
@@ -845,7 +942,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,
@@ -876,23 +973,6 @@ ConfigureText(interp, textPtr, argc, argv, flags)
* the geometry and setting the background from a 3-D border.
*/
- if ((textPtr->state != tkTextNormalUid)
- && (textPtr->state != tkTextDisabledUid)) {
- Tcl_AppendResult(interp, "bad state value \"", textPtr->state,
- "\": must be normal or disabled", (char *) NULL);
- textPtr->state = tkTextNormalUid;
- return TCL_ERROR;
- }
-
- if ((textPtr->wrapMode != tkTextCharUid)
- && (textPtr->wrapMode != tkTextNoneUid)
- && (textPtr->wrapMode != tkTextWordUid)) {
- Tcl_AppendResult(interp, "bad wrap mode \"", textPtr->wrapMode,
- "\": must be char, none, or word", (char *) NULL);
- textPtr->wrapMode = tkTextCharUid;
- return TCL_ERROR;
- }
-
Tk_SetBackgroundFromBorder(textPtr->tkwin, textPtr->border);
/*
@@ -967,7 +1047,8 @@ ConfigureText(interp, textPtr, argc, argv, flags)
|| (textPtr->selTagPtr->spacing3String != NULL)
|| (textPtr->selTagPtr->tabString != NULL)
|| (textPtr->selTagPtr->underlineString != NULL)
- || (textPtr->selTagPtr->wrapMode != NULL)) {
+ || (textPtr->selTagPtr->elideString != NULL)
+ || (textPtr->selTagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
textPtr->selTagPtr->affectsDisplay = 1;
}
TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
@@ -982,8 +1063,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)
@@ -1214,7 +1295,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);
}
/*
@@ -1227,16 +1308,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);
}
@@ -1275,7 +1356,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;
/*
@@ -1326,7 +1407,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--;
}
@@ -1349,7 +1430,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) {
/*
@@ -1359,7 +1442,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.
@@ -1368,7 +1451,7 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line1;
- charIndex = textPtr->topIndex.charIndex;
+ byteIndex = textPtr->topIndex.byteIndex;
}
} else if (index2.linePtr == textPtr->topIndex.linePtr) {
/*
@@ -1379,16 +1462,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);
}
@@ -1452,12 +1535,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)) {
@@ -1504,8 +1587,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) {
@@ -1513,14 +1596,15 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
}
}
}
- if (segPtr->typePtr == &tkTextCharType) {
+ if ((segPtr->typePtr == &tkTextCharType)
+ && !TkTextIsElided(textPtr, &textPtr->selIndex)) {
memcpy((VOID *) buffer, (VOID *) (segPtr->body.chars
+ offsetInSeg), (size_t) chunkSize);
buffer += chunkSize;
maxBytes -= chunkSize;
count += chunkSize;
}
- TkTextIndexForwChars(&textPtr->selIndex, chunkSize,
+ TkTextIndexForwBytes(&textPtr->selIndex, chunkSize,
&textPtr->selIndex);
}
@@ -1577,8 +1661,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
@@ -1611,7 +1695,8 @@ TextBlinkProc(clientData)
TkTextIndex index;
int x, y, w, h;
- if (!(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {
+ if ((textPtr->state == TK_STATE_DISABLED) ||
+ !(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {
return;
}
if (textPtr->flags & INSERT_ON) {
@@ -1654,10 +1739,10 @@ TextSearchCmd(textPtr, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- int backwards, exact, c, i, argsLeft, noCase, leftToScan;
+ int backwards, exact, searchElide, 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];
@@ -1665,6 +1750,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
Tcl_DString line, patDString;
TkTextSegment *segPtr;
TkTextLine *linePtr;
+ TkTextIndex curIndex;
+ Tcl_Obj *patObj = NULL;
Tcl_RegExp regexp = NULL; /* Initialization needed only to
* prevent compiler warning. */
@@ -1673,6 +1760,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
exact = 1;
+ searchElide = 0;
+ curIndex.tree = textPtr->tree;
backwards = 0;
noCase = 0;
varName = NULL;
@@ -1685,8 +1774,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
if (length < 2) {
badSwitch:
Tcl_AppendResult(interp, "bad switch \"", arg,
- "\": must be -forward, -backward, -exact, -regexp, ",
- "-nocase, -count, or --", (char *) NULL);
+ "\": must be --, -backward, -count, -elide, -exact, ",
+ "-forward, -nocase, or -regexp", (char *) NULL);
return TCL_ERROR;
}
c = arg[1];
@@ -1694,13 +1783,24 @@ 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++;
varName = argv[i];
- } else if ((c == 'e') && (strncmp(argv[i], "-exact", length) == 0)) {
+ } else if ((c == 'e') && (length > 2)
+ && (strncmp(argv[i], "-exact", length) == 0)) {
exact = 1;
+ } else if ((c == 'e') && (length > 2)
+ && (strncmp(argv[i], "-elide", length) == 0)) {
+ searchElide = 1;
+ } else if ((c == 'h') && (strncmp(argv[i], "-hidden", length) == 0)) {
+ /*
+ * -hidden is kept around for backwards compatibility with
+ * the dash patch, but -elide is the official option
+ */
+ searchElide = 1;
} else if ((c == 'f') && (strncmp(argv[i], "-forwards", length) == 0)) {
backwards = 0;
} else if ((c == 'n') && (strncmp(argv[i], "-nocase", length) == 0)) {
@@ -1717,7 +1817,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
argsLeft = argc - (i+2);
if ((argsLeft != 0) && (argsLeft != 1)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " search ?switches? pattern index ?stopIndex?",
+ argv[0], " search ?switches? pattern index ?stopIndex?\"",
(char *) NULL);
return TCL_ERROR;
}
@@ -1727,36 +1827,35 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Convert the pattern to lower-case if we're supposed to ignore case.
*/
- if (noCase) {
+ if (noCase && exact) {
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);
}
+ Tcl_DStringInit(&line);
if (TkTextGetIndex(interp, textPtr, argv[i+1], &index) != TCL_OK) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
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) {
if (TkTextGetIndex(interp, textPtr, argv[i+2], &stopIndex) != TCL_OK) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
stopLine = TkBTreeLineIndex(stopIndex.linePtr);
if (!backwards && (stopLine == numLines)) {
@@ -1778,14 +1877,17 @@ TextSearchCmd(textPtr, interp, argc, argv)
if (exact) {
patLength = strlen(pattern);
} else {
- regexp = Tcl_RegExpCompile(interp, pattern);
+ patObj = Tcl_NewStringObj(pattern, -1);
+ Tcl_IncrRefCount(patObj);
+ regexp = Tcl_GetRegExpFromObj(interp, patObj,
+ (noCase ? TCL_REG_NOCASE : 0) | TCL_REG_ADVANCED);
if (regexp == NULL) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
}
lineNum = startingLine;
code = TCL_OK;
- Tcl_DStringInit(&line);
for (passes = 0; passes < 2; ) {
if (lineNum >= numLines) {
/*
@@ -1802,9 +1904,11 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
+ curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
for (segPtr = linePtr->segPtr; segPtr != NULL;
- segPtr = segPtr->nextPtr) {
- if (segPtr->typePtr != &tkTextCharType) {
+ curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr != &tkTextCharType)
+ || (!searchElide && TkTextIsElided(textPtr, &curIndex))) {
continue;
}
Tcl_DStringAppend(&line, segPtr->body.chars, segPtr->size);
@@ -1819,22 +1923,20 @@ 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)));
}
/*
* Check for matches within the current line. If so, and if we're
* searching backwards, repeat the search to find the last match
- * in the line.
+ * in the line. (Note: The lastByte should include the NULL char
+ * so we can handle searching for end of line easier.)
*/
- matchChar = -1;
- firstChar = 0;
- lastChar = INT_MAX;
+ matchByte = -1;
+ firstByte = 0;
+ lastByte = Tcl_DStringLength(&line) + 1;
if (lineNum == startingLine) {
int indexInDString;
@@ -1848,8 +1950,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;
@@ -1863,8 +1965,9 @@ 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))
+ && !((Tcl_DStringLength(&line) == 0) && !exact)) {
goto nextLine;
}
} else {
@@ -1872,13 +1975,16 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Use only the first part of the line.
*/
- lastChar = indexInDString;
+ lastByte = indexInDString;
}
}
do {
int thisLength;
+ Tcl_UniChar ch;
+
if (exact) {
- p = strstr(startOfLine + firstChar, pattern);
+ p = strstr(startOfLine + firstByte, /* INTL: Native. */
+ pattern);
if (p == NULL) {
break;
}
@@ -1889,7 +1995,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;
@@ -1901,12 +2007,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 = i + Tcl_UtfToUniChar(startOfLine + matchByte, &ch);
} while (backwards);
/*
@@ -1915,32 +2021,49 @@ TextSearchCmd(textPtr, interp, argc, argv)
* specified.
*/
- if (matchChar >= 0) {
+ if (matchByte >= 0) {
+ int numChars;
+
+ /*
+ * Convert the byte length to a character count.
+ */
+
+ numChars = Tcl_NumUtfChars(startOfLine + matchByte,
+ matchLength);
+
/*
* The index information returned by the regular expression
* parser only considers textual information: it doesn't
- * account for embedded windows or any other non-textual info.
+ * account for embedded windows, elided text (when we are not
+ * searching elided text) or any other non-textual info.
* Scan through the line's segments again to adjust both
* matchChar and matchCount.
+ *
+ * We will walk through the segments of this line until we have
+ * either reached the end of the match or we have reached the end
+ * of the line.
*/
- for (segPtr = linePtr->segPtr, leftToScan = matchChar;
- leftToScan >= 0; segPtr = segPtr->nextPtr) {
- if (segPtr->typePtr != &tkTextCharType) {
- matchChar += segPtr->size;
- continue;
+ curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
+ for (segPtr = linePtr->segPtr, leftToScan = matchByte;
+ leftToScan >= 0 && segPtr; segPtr = segPtr->nextPtr) {
+ if (segPtr->typePtr != &tkTextCharType || \
+ (!searchElide && TkTextIsElided(textPtr, &curIndex))) {
+ matchByte += segPtr->size;
+ } else {
+ leftToScan -= segPtr->size;
}
- leftToScan -= segPtr->size;
+ curIndex.byteIndex += segPtr->size;
}
for (leftToScan += matchLength; leftToScan > 0;
segPtr = segPtr->nextPtr) {
if (segPtr->typePtr != &tkTextCharType) {
- matchLength += segPtr->size;
+ numChars += segPtr->size;
continue;
}
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;
@@ -1950,14 +2073,15 @@ TextSearchCmd(textPtr, interp, argc, argv)
}
}
if (varName != NULL) {
- sprintf(buffer, "%d", matchLength);
+ sprintf(buffer, "%d", numChars);
if (Tcl_SetVar(interp, varName, buffer, TCL_LEAVE_ERR_MSG)
== NULL) {
code = TCL_ERROR;
goto done;
}
}
- TkTextPrintIndex(&index, interp->result);
+ TkTextPrintIndex(&index, buffer);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
goto done;
}
@@ -1989,9 +2113,12 @@ TextSearchCmd(textPtr, interp, argc, argv)
}
done:
Tcl_DStringFree(&line);
- if (noCase) {
+ if (noCase && exact) {
Tcl_DStringFree(&patDString);
}
+ if (patObj != NULL) {
+ Tcl_DecrRefCount(patObj);
+ }
return code;
}
@@ -2006,7 +2133,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
@@ -2028,6 +2155,7 @@ TkTextGetTabs(interp, tkwin, string)
char **argv;
TkTextTabArray *tabArrayPtr;
TkTextTab *tabPtr;
+ Tcl_UniChar ch;
if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
return NULL;
@@ -2070,11 +2198,12 @@ TkTextGetTabs(interp, tkwin, string)
if ((i+1) == argc) {
continue;
}
- c = UCHAR(argv[i+1][0]);
- if (!isalpha(c)) {
+ Tcl_UtfToUniChar(argv[i+1], &ch);
+ if (!Tcl_UniCharIsAlpha(ch)) {
continue;
}
i += 1;
+ c = argv[i][0];
if ((c == 'l') && (strncmp(argv[i], "left",
strlen(argv[i])) == 0)) {
tabPtr->alignment = LEFT;
@@ -2186,7 +2315,7 @@ TextDumpCmd(textPtr, interp, argc, argv)
if (TkTextGetIndex(interp, textPtr, argv[arg], &index1) != TCL_OK) {
return TCL_ERROR;
}
- lineno = TkBTreeLineIndex(index1.linePtr) + 1;
+ lineno = TkBTreeLineIndex(index1.linePtr);
arg++;
atEnd = 0;
if (argc == arg) {
@@ -2204,10 +2333,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++;
@@ -2218,14 +2347,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;
@@ -2243,17 +2372,18 @@ 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 */
{
int offset;
TkTextSegment *segPtr;
+ TkTextIndex index;
/*
* Must loop through line looking at its segments.
* character
@@ -2262,47 +2392,54 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
* image
* 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';
+
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset + first, &index);
DumpSegment(interp, "text", segPtr->body.chars + first,
- command, lineno, offset + first, what);
+ command, &index, 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);
- DumpSegment(interp, "mark", name,
- command, lineno, offset, what);
+
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
+ DumpSegment(interp, "mark", name, command, &index, what);
} else if ((what & TK_DUMP_TAG) &&
(segPtr->typePtr == &tkTextToggleOnType)) {
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "tagon",
segPtr->body.toggle.tagPtr->name,
- command, lineno, offset, what);
+ command, &index, what);
} else if ((what & TK_DUMP_TAG) &&
(segPtr->typePtr == &tkTextToggleOffType)) {
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "tagoff",
segPtr->body.toggle.tagPtr->name,
- command, lineno, offset, what);
+ command, &index, what);
} else if ((what & TK_DUMP_IMG) &&
(segPtr->typePtr->name[0] == 'i')) {
TkTextEmbImage *eiPtr = (TkTextEmbImage *)&segPtr->body;
char *name = (eiPtr->name == NULL) ? "" : eiPtr->name;
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "image", name,
- command, lineno, offset, what);
+ command, &index, what);
} else if ((what & TK_DUMP_WIN) &&
(segPtr->typePtr->name[0] == 'w')) {
TkTextEmbWindow *ewPtr = (TkTextEmbWindow *)&segPtr->body;
@@ -2312,8 +2449,9 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
} else {
pathname = Tk_PathName(ewPtr->tkwin);
}
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "window", pathname,
- command, lineno, offset, what);
+ command, &index, what);
}
}
}
@@ -2331,17 +2469,16 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
* Either evals the callback or appends elements to the result string.
*/
static int
-DumpSegment(interp, key, value, command, lineno, offset, what)
+DumpSegment(interp, key, value, command, index, what)
Tcl_Interp *interp;
char *key; /* Segment type key */
char *value; /* Segment value */
char *command; /* Script callback */
- int lineno; /* Line number for indices dump */
- int offset; /* Character position */
+ TkTextIndex *index; /* index with line/byte position info */
int what; /* Look for TK_DUMP_INDEX bit */
{
- char buffer[30];
- sprintf(buffer, "%d.%d", lineno, offset);
+ char buffer[TCL_INTEGER_SPACE*2];
+ TkTextPrintIndex(index, buffer);
if (command == (char *) NULL) {
Tcl_AppendElement(interp, key);
Tcl_AppendElement(interp, value);
@@ -2362,3 +2499,5 @@ DumpSegment(interp, key, value, command, lineno, offset, what)
}
}
+
+
diff --git a/tk/generic/tkText.h b/tk/generic/tkText.h
index e8c0ab2440e..9152e2c7264 100644
--- a/tk/generic/tkText.h
+++ b/tk/generic/tkText.h
@@ -20,6 +20,11 @@
#include "tk.h"
#endif
+#ifdef BUILD_tk
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
/*
* Opaque types for structures whose guts are only needed by a single
* file:
@@ -176,7 +181,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 +246,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 +261,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
@@ -269,6 +274,12 @@ struct TkTextDispChunk {
* referred to in other structures.
*/
+typedef enum { TEXT_WRAPMODE_NULL, TEXT_WRAPMODE_NONE,
+ TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_WORD
+} TkWrapMode;
+
+EXTERN Tk_CustomOption textWrapModeOption;
+
typedef struct TkTextTag {
char *name; /* Name of this tag. This field is actually
* a pointer to the key from the entry in
@@ -366,10 +377,15 @@ typedef struct TkTextTag {
int underline; /* Non-zero means draw underline underneath
* text. Only valid if underlineString is
* non-NULL. */
- Tk_Uid wrapMode; /* How to handle wrap-around for this tag.
- * Must be tkTextCharUid, tkTextNoneUid,
- * tkTextWordUid, or NULL to use wrapMode
- * for whole widget. */
+ TkWrapMode wrapMode; /* How to handle wrap-around for this tag.
+ * Must be TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE, TEXT_WRAPMODE_WORD,
+ * or TEXT_WRAPMODE_NULL to use wrapmode for
+ * whole widget. */
+ char *elideString; /* -elide option string (malloc-ed).
+ * NULL means option not specified. */
+ int elide; /* Non-zero means that data under this tag
+ * should not be displayed. */
int affectsDisplay; /* Non-zero means that this tag affects the
* way information is displayed on the screen
* (so need to redisplay if tag changes). */
@@ -470,8 +486,8 @@ typedef struct TkText {
* image segment doesn't yet have an
* associated image, there is no entry for
* it here. */
- Tk_Uid state; /* Normal or disabled. Text is read-only
- * when disabled. */
+ int state; /* Either STATE_NORMAL or STATE_DISABLED. A
+ * text widget is read-only when disabled. */
/*
* Default information for displaying (may be overridden by tags
@@ -518,9 +534,9 @@ typedef struct TkText {
* Additional information used for displaying:
*/
- Tk_Uid wrapMode; /* How to handle wrap-around. Must be
- * tkTextCharUid, tkTextNoneUid, or
- * tkTextWordUid. */
+ TkWrapMode wrapMode; /* How to handle wrap-around. Must be
+ * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
+ * TEXT_WRAPMODE_WORD. */
int width, height; /* Desired dimensions for window, measured
* in characters. */
int setGrid; /* Non-zero means pass gridding information
@@ -661,7 +677,7 @@ typedef void Tk_SegLineChangeProc _ANSI_ARGS_((
typedef int Tk_SegLayoutProc _ANSI_ARGS_((struct TkText *textPtr,
struct TkTextIndex *indexPtr, TkTextSegment *segPtr,
int offset, int maxX, int maxChars,
- int noCharsYet, Tk_Uid wrapMode,
+ int noCharsYet, TkWrapMode wrapMode,
struct TkTextDispChunk *chunkPtr));
typedef void Tk_SegCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,
TkTextLine *linePtr));
@@ -717,141 +733,156 @@ typedef struct Tk_SegType {
* Declarations for variables shared among the text-related files:
*/
-extern int tkBTreeDebug;
-extern int tkTextDebug;
-extern Tk_SegType tkTextCharType;
-extern Tk_Uid tkTextCharUid;
-extern Tk_Uid tkTextDisabledUid;
-extern Tk_SegType tkTextLeftMarkType;
-extern Tk_Uid tkTextNoneUid;
-extern Tk_Uid tkTextNormalUid;
-extern Tk_SegType tkTextRightMarkType;
-extern Tk_SegType tkTextToggleOnType;
-extern Tk_SegType tkTextToggleOffType;
-extern Tk_Uid tkTextWordUid;
+EXTERN int tkBTreeDebug;
+EXTERN int tkTextDebug;
+EXTERN Tk_SegType tkTextCharType;
+EXTERN Tk_SegType tkTextLeftMarkType;
+EXTERN Tk_SegType tkTextRightMarkType;
+EXTERN Tk_SegType tkTextToggleOnType;
+EXTERN Tk_SegType tkTextToggleOffType;
/*
* Declarations for procedures that are used by the text-related files
* but shouldn't be used anywhere else in Tk (or by Tk clients):
*/
-extern int TkBTreeCharTagged _ANSI_ARGS_((TkTextIndex *indexPtr,
+EXTERN int TkBTreeCharTagged _ANSI_ARGS_((TkTextIndex *indexPtr,
TkTextTag *tagPtr));
-extern void TkBTreeCheck _ANSI_ARGS_((TkTextBTree tree));
-extern int TkBTreeCharsInLine _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,
+EXTERN void TkBTreeCheck _ANSI_ARGS_((TkTextBTree tree));
+EXTERN int TkBTreeCharsInLine _ANSI_ARGS_((TkTextLine *linePtr));
+EXTERN int TkBTreeBytesInLine _ANSI_ARGS_((TkTextLine *linePtr));
+EXTERN TkTextBTree TkBTreeCreate _ANSI_ARGS_((TkText *textPtr));
+EXTERN void TkBTreeDestroy _ANSI_ARGS_((TkTextBTree tree));
+EXTERN void TkBTreeDeleteChars _ANSI_ARGS_((TkTextIndex *index1Ptr,
TkTextIndex *index2Ptr));
-extern TkTextLine * TkBTreeFindLine _ANSI_ARGS_((TkTextBTree tree,
+EXTERN TkTextLine * TkBTreeFindLine _ANSI_ARGS_((TkTextBTree tree,
int line));
-extern TkTextTag ** TkBTreeGetTags _ANSI_ARGS_((TkTextIndex *indexPtr,
+EXTERN TkTextTag ** TkBTreeGetTags _ANSI_ARGS_((TkTextIndex *indexPtr,
int *numTagsPtr));
-extern void TkBTreeInsertChars _ANSI_ARGS_((TkTextIndex *indexPtr,
+EXTERN void TkBTreeInsertChars _ANSI_ARGS_((TkTextIndex *indexPtr,
char *string));
-extern int TkBTreeLineIndex _ANSI_ARGS_((TkTextLine *linePtr));
-extern void TkBTreeLinkSegment _ANSI_ARGS_((TkTextSegment *segPtr,
+EXTERN int TkBTreeLineIndex _ANSI_ARGS_((TkTextLine *linePtr));
+EXTERN void TkBTreeLinkSegment _ANSI_ARGS_((TkTextSegment *segPtr,
TkTextIndex *indexPtr));
-extern TkTextLine * TkBTreeNextLine _ANSI_ARGS_((TkTextLine *linePtr));
-extern int TkBTreeNextTag _ANSI_ARGS_((TkTextSearch *searchPtr));
-extern int TkBTreeNumLines _ANSI_ARGS_((TkTextBTree tree));
-extern TkTextLine * TkBTreePreviousLine _ANSI_ARGS_((TkTextLine *linePtr));
-extern int TkBTreePrevTag _ANSI_ARGS_((TkTextSearch *searchPtr));
-extern void TkBTreeStartSearch _ANSI_ARGS_((TkTextIndex *index1Ptr,
+EXTERN TkTextLine * TkBTreeNextLine _ANSI_ARGS_((TkTextLine *linePtr));
+EXTERN int TkBTreeNextTag _ANSI_ARGS_((TkTextSearch *searchPtr));
+EXTERN int TkBTreeNumLines _ANSI_ARGS_((TkTextBTree tree));
+EXTERN TkTextLine * TkBTreePreviousLine _ANSI_ARGS_((TkTextLine *linePtr));
+EXTERN int TkBTreePrevTag _ANSI_ARGS_((TkTextSearch *searchPtr));
+EXTERN void TkBTreeStartSearch _ANSI_ARGS_((TkTextIndex *index1Ptr,
TkTextIndex *index2Ptr, TkTextTag *tagPtr,
TkTextSearch *searchPtr));
-extern void TkBTreeStartSearchBack _ANSI_ARGS_((TkTextIndex *index1Ptr,
+EXTERN void TkBTreeStartSearchBack _ANSI_ARGS_((TkTextIndex *index1Ptr,
TkTextIndex *index2Ptr, TkTextTag *tagPtr,
TkTextSearch *searchPtr));
-extern void TkBTreeTag _ANSI_ARGS_((TkTextIndex *index1Ptr,
+EXTERN void TkBTreeTag _ANSI_ARGS_((TkTextIndex *index1Ptr,
TkTextIndex *index2Ptr, TkTextTag *tagPtr,
int add));
-extern void TkBTreeUnlinkSegment _ANSI_ARGS_((TkTextBTree tree,
+EXTERN void TkBTreeUnlinkSegment _ANSI_ARGS_((TkTextBTree tree,
TkTextSegment *segPtr, TkTextLine *linePtr));
-extern void TkTextBindProc _ANSI_ARGS_((ClientData clientData,
+EXTERN void TkTextBindProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
-extern void TkTextChanged _ANSI_ARGS_((TkText *textPtr,
+EXTERN void TkTextChanged _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *index1Ptr, TkTextIndex *index2Ptr));
-extern int TkTextCharBbox _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextCharBbox _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, int *xPtr, int *yPtr,
int *widthPtr, int *heightPtr));
-extern int TkTextCharLayoutProc _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextCharLayoutProc _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, TkTextSegment *segPtr,
int offset, int maxX, int maxChars, int noBreakYet,
- Tk_Uid wrapMode, TkTextDispChunk *chunkPtr));
-extern void TkTextCreateDInfo _ANSI_ARGS_((TkText *textPtr));
-extern int TkTextDLineInfo _ANSI_ARGS_((TkText *textPtr,
+ TkWrapMode wrapMode, TkTextDispChunk *chunkPtr));
+EXTERN void TkTextCreateDInfo _ANSI_ARGS_((TkText *textPtr));
+EXTERN int TkTextDLineInfo _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, int *xPtr, int *yPtr,
int *widthPtr, int *heightPtr, int *basePtr));
-extern TkTextTag * TkTextCreateTag _ANSI_ARGS_((TkText *textPtr,
+EXTERN TkTextTag * TkTextCreateTag _ANSI_ARGS_((TkText *textPtr,
char *tagName));
-extern void TkTextFreeDInfo _ANSI_ARGS_((TkText *textPtr));
-extern void TkTextFreeTag _ANSI_ARGS_((TkText *textPtr,
+EXTERN void TkTextFreeDInfo _ANSI_ARGS_((TkText *textPtr));
+EXTERN void TkTextFreeTag _ANSI_ARGS_((TkText *textPtr,
TkTextTag *tagPtr));
-extern int TkTextGetIndex _ANSI_ARGS_((Tcl_Interp *interp,
+EXTERN int TkTextGetIndex _ANSI_ARGS_((Tcl_Interp *interp,
TkText *textPtr, char *string,
TkTextIndex *indexPtr));
-extern TkTextTabArray * TkTextGetTabs _ANSI_ARGS_((Tcl_Interp *interp,
+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 TkTextInsertDisplayProc _ANSI_ARGS_((
+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_((
+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 int TkTextMarkCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextIsElided _ANSI_ARGS_((TkText *textPtr,
+ TkTextIndex *indexPtr));
+EXTERN TkTextIndex * TkTextMakeByteIndex _ANSI_ARGS_((TkTextBTree tree,
+ int lineIndex, int byteIndex,
+ TkTextIndex *indexPtr));
+EXTERN int TkTextMarkCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextMarkNameToIndex _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextMarkNameToIndex _ANSI_ARGS_((TkText *textPtr,
char *name, TkTextIndex *indexPtr));
-extern void TkTextMarkSegToIndex _ANSI_ARGS_((TkText *textPtr,
+EXTERN void TkTextMarkSegToIndex _ANSI_ARGS_((TkText *textPtr,
TkTextSegment *markPtr, TkTextIndex *indexPtr));
-extern void TkTextEventuallyRepick _ANSI_ARGS_((TkText *textPtr));
-extern void TkTextPickCurrent _ANSI_ARGS_((TkText *textPtr,
+EXTERN void TkTextEventuallyRepick _ANSI_ARGS_((TkText *textPtr));
+EXTERN void TkTextPickCurrent _ANSI_ARGS_((TkText *textPtr,
XEvent *eventPtr));
-extern void TkTextPixelIndex _ANSI_ARGS_((TkText *textPtr,
+EXTERN void TkTextPixelIndex _ANSI_ARGS_((TkText *textPtr,
int x, int y, TkTextIndex *indexPtr));
-extern void TkTextPrintIndex _ANSI_ARGS_((TkTextIndex *indexPtr,
- char *string));
-extern void TkTextRedrawRegion _ANSI_ARGS_((TkText *textPtr,
+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,
+EXTERN void TkTextRedrawTag _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *index1Ptr, TkTextIndex *index2Ptr,
TkTextTag *tagPtr, int withTag));
-extern void TkTextRelayoutWindow _ANSI_ARGS_((TkText *textPtr));
-extern int TkTextScanCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN void TkTextRelayoutWindow _ANSI_ARGS_((TkText *textPtr));
+EXTERN int TkTextScanCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextSeeCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextSeeCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextSegToOffset _ANSI_ARGS_((TkTextSegment *segPtr,
- TkTextLine *linePtr));
-extern TkTextSegment * TkTextSetMark _ANSI_ARGS_((TkText *textPtr, char *name,
+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,
+EXTERN void TkTextSetYView _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, int pickPlace));
-extern int TkTextTagCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextTagCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextImageCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextImageCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextImageIndex _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextImageIndex _ANSI_ARGS_((TkText *textPtr,
char *name, TkTextIndex *indexPtr));
-extern int TkTextWindowCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextWindowCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextWindowIndex _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextWindowIndex _ANSI_ARGS_((TkText *textPtr,
char *name, TkTextIndex *indexPtr));
-extern int TkTextXviewCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextXviewCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
-extern int TkTextYviewCmd _ANSI_ARGS_((TkText *textPtr,
+EXTERN int TkTextYviewCmd _ANSI_ARGS_((TkText *textPtr,
Tcl_Interp *interp, int argc, char **argv));
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLIMPORT
+
#endif /* _TKTEXT */
+
diff --git a/tk/generic/tkTextBTree.c b/tk/generic/tkTextBTree.c
index 128edd29550..42fa1b2cba4 100644
--- a/tk/generic/tkTextBTree.c
+++ b/tk/generic/tkTextBTree.c
@@ -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)) {
@@ -2431,6 +2431,148 @@ TkBTreeGetTags(indexPtr, numTagsPtr)
/*
*----------------------------------------------------------------------
*
+ * TkTextIsElided --
+ *
+ * Special case to just return information about elided attribute.
+ * Specialized from TkBTreeGetTags(indexPtr, numTagsPtr)
+ * and GetStyle(textPtr, indexPtr).
+ * Just need to keep track of invisibility settings for each priority,
+ * pick highest one active at end
+ *
+ * Results:
+ * Returns whether this text should be elided or not.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ /* ARGSUSED */
+int
+TkTextIsElided(textPtr, indexPtr)
+ TkText *textPtr; /* Overall information about text widget. */
+ TkTextIndex *indexPtr; /* The character in the text for which
+ * display information is wanted. */
+{
+#define LOTSA_TAGS 1000
+ int elide = 0; /* if nobody says otherwise, it's visible */
+
+ int deftagCnts[LOTSA_TAGS];
+ int *tagCnts = deftagCnts;
+ TkTextTag *deftagPtrs[LOTSA_TAGS];
+ TkTextTag **tagPtrs = deftagPtrs;
+ int numTags = textPtr->numTags;
+ register Node *nodePtr;
+ register TkTextLine *siblingLinePtr;
+ register TkTextSegment *segPtr;
+ register TkTextTag *tagPtr;
+ register int i, index;
+
+ /* almost always avoid malloc, so stay out of system calls */
+ if (LOTSA_TAGS < numTags) {
+ tagCnts = (int *)ckalloc((unsigned)sizeof(int) * numTags);
+ tagPtrs = (TkTextTag **)ckalloc((unsigned)sizeof(TkTextTag *) * numTags);
+ }
+
+ for (i=0; i<numTags; i++) {
+ tagCnts[i] = 0;
+ }
+
+ /*
+ * Record tag toggles within the line of indexPtr but preceding
+ * indexPtr.
+ */
+
+ for (index = 0, segPtr = indexPtr->linePtr->segPtr;
+ (index + segPtr->size) <= indexPtr->byteIndex;
+ index += segPtr->size, segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType)) {
+ tagPtr = segPtr->body.toggle.tagPtr;
+ if (tagPtr->elideString != NULL) {
+ tagPtrs[tagPtr->priority] = tagPtr;
+ tagCnts[tagPtr->priority]++;
+ }
+ }
+ }
+
+ /*
+ * Record toggles for tags in lines that are predecessors of
+ * indexPtr->linePtr but under the same level-0 node.
+ */
+
+ for (siblingLinePtr = indexPtr->linePtr->parentPtr->children.linePtr;
+ siblingLinePtr != indexPtr->linePtr;
+ siblingLinePtr = siblingLinePtr->nextPtr) {
+ for (segPtr = siblingLinePtr->segPtr; segPtr != NULL;
+ segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr == &tkTextToggleOnType)
+ || (segPtr->typePtr == &tkTextToggleOffType)) {
+ tagPtr = segPtr->body.toggle.tagPtr;
+ if (tagPtr->elideString != NULL) {
+ tagPtrs[tagPtr->priority] = tagPtr;
+ tagCnts[tagPtr->priority]++;
+ }
+ }
+ }
+ }
+
+ /*
+ * For each node in the ancestry of this line, record tag toggles
+ * for all siblings that precede that node.
+ */
+
+ for (nodePtr = indexPtr->linePtr->parentPtr; nodePtr->parentPtr != NULL;
+ nodePtr = nodePtr->parentPtr) {
+ register Node *siblingPtr;
+ register Summary *summaryPtr;
+
+ for (siblingPtr = nodePtr->parentPtr->children.nodePtr;
+ siblingPtr != nodePtr; siblingPtr = siblingPtr->nextPtr) {
+ for (summaryPtr = siblingPtr->summaryPtr; summaryPtr != NULL;
+ summaryPtr = summaryPtr->nextPtr) {
+ if (summaryPtr->toggleCount & 1) {
+ tagPtr = summaryPtr->tagPtr;
+ if (tagPtr->elideString != NULL) {
+ tagPtrs[tagPtr->priority] = tagPtr;
+ tagCnts[tagPtr->priority] += summaryPtr->toggleCount;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Now traverse from highest priority to lowest,
+ * take elided value from first odd count (= on)
+ */
+
+ for (i = numTags-1; i >=0; i--) {
+ if (tagCnts[i] & 1) {
+#ifndef ALWAYS_SHOW_SELECTION
+ /* who would make the selection elided? */
+ if ((tagPtr == textPtr->selTagPtr)
+ && !(textPtr->flags & GOT_FOCUS)) {
+ continue;
+ }
+#endif
+ elide = tagPtrs[i]->elide;
+ break;
+ }
+ }
+
+ if (LOTSA_TAGS < numTags) {
+ ckfree((char *) tagCnts);
+ ckfree((char *) tagPtrs);
+ }
+
+ return elide;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* IncCount --
*
* This is a utility procedure used by TkBTreeGetTags. It
@@ -3588,7 +3730,27 @@ 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/tk/generic/tkTextDisp.c b/tk/generic/tkTextDisp.c
index 9d0afc19727..36906b8caba 100644
--- a/tk/generic/tkTextDisp.c
+++ b/tk/generic/tkTextDisp.c
@@ -18,6 +18,10 @@
#include "tkInt.h"
#include "tkText.h"
+#ifdef __WIN32__
+#include "tkWinInt.h"
+#endif
+
/*
* The following structure describes how to display a range of characters.
* The information is generated by scanning all of the tags associated
@@ -55,9 +59,10 @@ typedef struct StyleValues {
* be NULL). */
int underline; /* Non-zero means draw underline underneath
* text. */
- Tk_Uid wrapMode; /* How to handle wrap-around for this tag.
- * One of tkTextCharUid, tkTextNoneUid,
- * or tkTextWordUid. */
+ int elide; /* Non-zero means draw text */
+ TkWrapMode wrapMode; /* How to handle wrap-around for this tag.
+ * One of TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE or TEXT_WRAPMODE_WORD.*/
} StyleValues;
/*
@@ -98,7 +103,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
@@ -156,12 +161,14 @@ typedef struct DLine {
* BOTTOM_LINE - Non-zero means that this was the bottom line
* in the window the last time that the window
* was laid out.
+ * IS_DISABLED - This Dline cannot be edited.
*/
#define HAS_3D_BORDER 1
#define NEW_LAYOUT 2
#define TOP_LINE 4
#define BOTTOM_LINE 8
+#define IS_DISABLED 16
/*
* Overall display information for a text widget:
@@ -199,7 +206,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 +229,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 +262,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;
@@ -311,6 +319,21 @@ static int CharMeasureProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
int x));
static void CharUndisplayProc _ANSI_ARGS_((TkText *textPtr,
TkTextDispChunk *chunkPtr));
+
+/*
+ Definitions of elided procs.
+ Compiler can't inline these since we use pointers to these functions.
+ ElideDisplayProc, ElideUndisplayProc special-cased for speed,
+ as potentially many elided DLine chunks if large, tag toggle-filled
+ elided region.
+*/
+static void ElideBboxProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
+ int index, int y, int lineHeight, int baseline,
+ int *xPtr, int *yPtr, int *widthPtr,
+ int *heightPtr));
+static int ElideMeasureProc _ANSI_ARGS_((TkTextDispChunk *chunkPtr,
+ int x));
+
static void DisplayDLine _ANSI_ARGS_((TkText *textPtr,
DLine *dlPtr, DLine *prevPtr, Pixmap pixmap));
static void DisplayLineBackground _ANSI_ARGS_((TkText *textPtr,
@@ -331,7 +354,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 +404,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;
@@ -479,7 +502,7 @@ GetStyle(textPtr, indexPtr)
int borderPrio, borderWidthPrio, reliefPrio, bgStipplePrio;
int fgPrio, fontPrio, fgStipplePrio;
- int underlinePrio, justifyPrio, offsetPrio;
+ int underlinePrio, elidePrio, justifyPrio, offsetPrio;
int lMargin1Prio, lMargin2Prio, rMarginPrio;
int spacing1Prio, spacing2Prio, spacing3Prio;
int overstrikePrio, tabPrio, wrapPrio;
@@ -494,7 +517,7 @@ GetStyle(textPtr, indexPtr)
tagPtrs = TkBTreeGetTags(indexPtr, &numTags);
borderPrio = borderWidthPrio = reliefPrio = bgStipplePrio = -1;
fgPrio = fontPrio = fgStipplePrio = -1;
- underlinePrio = justifyPrio = offsetPrio = -1;
+ underlinePrio = elidePrio = justifyPrio = offsetPrio = -1;
lMargin1Prio = lMargin2Prio = rMarginPrio = -1;
spacing1Prio = spacing2Prio = spacing3Prio = -1;
overstrikePrio = tabPrio = wrapPrio = -1;
@@ -508,6 +531,7 @@ GetStyle(textPtr, indexPtr)
styleValues.spacing3 = textPtr->spacing3;
styleValues.tabArrayPtr = textPtr->tabArrayPtr;
styleValues.wrapMode = textPtr->wrapMode;
+ styleValues.elide = 0;
for (i = 0 ; i < numTags; i++) {
tagPtr = tagPtrs[i];
@@ -612,7 +636,12 @@ GetStyle(textPtr, indexPtr)
styleValues.underline = tagPtr->underline;
underlinePrio = tagPtr->priority;
}
- if ((tagPtr->wrapMode != NULL)
+ if ((tagPtr->elideString != NULL)
+ && (tagPtr->priority > elidePrio)) {
+ styleValues.elide = tagPtr->elide;
+ elidePrio = tagPtr->priority;
+ }
+ if ((tagPtr->wrapMode != TEXT_WRAPMODE_NULL)
&& (tagPtr->priority > wrapPrio)) {
styleValues.wrapMode = tagPtr->wrapMode;
wrapPrio = tagPtr->priority;
@@ -648,22 +677,20 @@ GetStyle(textPtr, indexPtr)
gcValues.fill_style = FillStippled;
mask |= GCStipple|GCFillStyle;
}
- stylePtr->bgGC = Tk_GetGCColor(textPtr->tkwin, mask, &gcValues,
- Tk_3DBorderColor(styleValues.border),
- NULL);
+ stylePtr->bgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
} else {
stylePtr->bgGC = None;
}
- mask = GCForeground|GCFont;
- gcValues.foreground = styleValues.fgColor->pixel;
+ mask = GCFont;
gcValues.font = Tk_FontId(styleValues.tkfont);
+ mask |= GCForeground;
+ gcValues.foreground = styleValues.fgColor->pixel;
if (styleValues.fgStipple != None) {
gcValues.stipple = styleValues.fgStipple;
gcValues.fill_style = FillStippled;
mask |= GCStipple|GCFillStyle;
}
- stylePtr->fgGC = Tk_GetGCColor(textPtr->tkwin, mask, &gcValues,
- styleValues.fgColor, NULL);
+ stylePtr->fgGC = Tk_GetGC(textPtr->tkwin, mask, &gcValues);
stylePtr->sValuePtr = (StyleValues *)
Tcl_GetHashKey(&textPtr->dInfoPtr->styleTable, hPtr);
stylePtr->hPtr = hPtr;
@@ -701,7 +728,9 @@ FreeStyle(textPtr, stylePtr)
if (stylePtr->bgGC != None) {
Tk_FreeGC(textPtr->display, stylePtr->bgGC);
}
- Tk_FreeGC(textPtr->display, stylePtr->fgGC);
+ if (stylePtr->fgGC != None) {
+ Tk_FreeGC(textPtr->display, stylePtr->fgGC);
+ }
Tcl_DeleteHashEntry(stylePtr->hPtr);
ckfree((char *) stylePtr);
}
@@ -742,16 +771,18 @@ 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. */
- Tk_Uid wrapMode; /* Wrap mode to use for this line. */
+ TkWrapMode wrapMode; /* Wrap mode to use for this line. */
int x = 0, maxX = 0; /* Initializations needed only to
* stop compiler warnings. */
int wholeLine; /* Non-zero means this display line
@@ -761,17 +792,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, elide, elidesize;
StyleValues *sValuePtr;
/*
@@ -780,7 +812,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;
@@ -790,6 +822,37 @@ LayoutDLine(textPtr, indexPtr)
dlPtr->flags = NEW_LAYOUT;
/*
+ * Special case entirely elide line as there may be 1000s or more
+ */
+ elide = TkTextIsElided(textPtr, indexPtr); /* save a malloc */
+ if (elide && indexPtr->byteIndex==0) {
+ maxBytes = 0;
+ for (segPtr = indexPtr->linePtr->segPtr;
+ elide && (segPtr != NULL);
+ segPtr = segPtr->nextPtr) {
+ if ((elidesize = segPtr->size) > 0) {
+ maxBytes += elidesize;
+ /*
+ * If have we have a tag toggle, there is a chance
+ * that invisibility state changed, so bail out
+ */
+ } else if ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType)) {
+ if (segPtr->body.toggle.tagPtr->elideString != NULL) {
+ elide = (segPtr->typePtr == &tkTextToggleOffType)
+ ^ segPtr->body.toggle.tagPtr->elide;
+ }
+ }
+ }
+
+ if (elide) {
+ dlPtr->byteCount = maxBytes;
+ dlPtr->spaceAbove = dlPtr->spaceBelow = dlPtr->length = 0;
+ return dlPtr;
+ }
+ }
+
+ /*
* Each iteration of the loop below creates one TkTextDispChunk for
* the new display line. The line will always have at least one
* chunk (for the newline character at the end, if there's nothing
@@ -800,14 +863,15 @@ LayoutDLine(textPtr, indexPtr)
lastChunkPtr = NULL;
chunkPtr = NULL;
noCharsYet = 1;
+ elide = 0;
breakChunkPtr = NULL;
- breakCharOffset = 0;
+ breakByteOffset = 0;
justify = TK_JUSTIFY_LEFT;
tabIndex = -1;
tabChunkPtr = NULL;
tabArrayPtr = NULL;
rMargin = 0;
- wrapMode = tkTextCharUid;
+ wrapMode = TEXT_WRAPMODE_CHAR;
tabSize = 0;
lastCharChunkPtr = NULL;
@@ -817,16 +881,48 @@ 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) {
+ /*
+ * Every line still gets at least one chunk due to expectations
+ * in the rest of the code, but we are able to skip elided portions
+ * of the line quickly.
+ * If current chunk is elided and last chunk was too, coalese
+ */
+ if (elide && (lastChunkPtr != NULL)
+ && (lastChunkPtr->displayProc == NULL /*ElideDisplayProc*/)) {
+ if ((elidesize = segPtr->size - byteOffset) > 0) {
+ curIndex.byteIndex += elidesize;
+ lastChunkPtr->numBytes += elidesize;
+ breakByteOffset = lastChunkPtr->breakIndex = lastChunkPtr->numBytes;
+ /*
+ * If have we have a tag toggle, there is a chance
+ * that invisibility state changed, so bail out
+ */
+ } else if ((segPtr->typePtr == &tkTextToggleOffType)
+ || (segPtr->typePtr == &tkTextToggleOnType)) {
+ if (segPtr->body.toggle.tagPtr->elideString != NULL) {
+ elide = (segPtr->typePtr == &tkTextToggleOffType)
+ ^ segPtr->body.toggle.tagPtr->elide;
+ }
+ }
+
+ byteOffset = 0;
+ segPtr = segPtr->nextPtr;
+ if (segPtr == NULL && chunkPtr != NULL) {
+ ckfree((char *) chunkPtr);
+ }
+ continue;
+ }
+
if (segPtr->typePtr->layoutProc == NULL) {
segPtr = segPtr->nextPtr;
- offset = 0;
+ byteOffset = 0;
continue;
}
if (chunkPtr == NULL) {
@@ -834,6 +930,7 @@ LayoutDLine(textPtr, indexPtr)
chunkPtr->nextPtr = NULL;
}
chunkPtr->stylePtr = GetStyle(textPtr, &curIndex);
+ elide = chunkPtr->stylePtr->sValuePtr->elide;
/*
* Save style information such as justification and indentation,
@@ -846,11 +943,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;
+ if (wrapMode == TEXT_WRAPMODE_NONE) {
+ maxX = -1;
} else {
maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x
- rMargin;
@@ -866,24 +963,37 @@ LayoutDLine(textPtr, indexPtr)
*/
gotTab = 0;
- maxChars = segPtr->size - offset;
- if (justify == TK_JUSTIFY_LEFT) {
+ maxBytes = segPtr->size - byteOffset;
+ if (!elide && 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;
}
}
}
}
-
chunkPtr->x = x;
+ if (elide && maxBytes) {
+ /* don't free style here, as other code expects to be able to do that */
+ /*breakByteOffset =*/ chunkPtr->breakIndex = chunkPtr->numBytes = maxBytes;
+ chunkPtr->width = 0;
+ chunkPtr->minAscent = chunkPtr->minDescent = chunkPtr->minHeight = 0;
+
+ /* would just like to point to canonical empty chunk */
+ chunkPtr->displayProc = (Tk_ChunkDisplayProc *) NULL;
+ chunkPtr->undisplayProc = (Tk_ChunkUndisplayProc *) NULL;
+ chunkPtr->measureProc = ElideMeasureProc;
+ chunkPtr->bboxProc = ElideBboxProc;
+
+ code = 1;
+ } else
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);
@@ -894,7 +1004,7 @@ LayoutDLine(textPtr, indexPtr)
*/
segPtr = segPtr->nextPtr;
- offset = 0;
+ byteOffset = 0;
continue;
}
@@ -908,7 +1018,7 @@ LayoutDLine(textPtr, indexPtr)
}
break;
}
- if (chunkPtr->numChars > 0) {
+ if (chunkPtr->numBytes > 0) {
noCharsYet = 0;
lastCharChunkPtr = chunkPtr;
}
@@ -920,11 +1030,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;
}
@@ -943,16 +1053,17 @@ 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;
}
if (noCharsYet) {
@@ -976,10 +1087,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) {
@@ -990,17 +1101,18 @@ 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;
wholeLine = 0;
}
+
/*
* Make tab adjustments for the last tab stop, if there is one.
*/
@@ -1011,7 +1123,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,
@@ -1022,7 +1134,7 @@ LayoutDLine(textPtr, indexPtr)
* what is implemented below.
*/
- if (wrapMode == tkTextNoneUid) {
+ if (wrapMode == TEXT_WRAPMODE_NONE) {
maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x - rMargin;
}
dlPtr->length = lastChunkPtr->x + lastChunkPtr->width;
@@ -1037,7 +1149,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;
}
@@ -1060,7 +1172,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;
@@ -1213,7 +1325,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.
*/
@@ -1224,7 +1336,7 @@ UpdateDisplayInfo(textPtr)
}
goto lineOK;
}
- if (index.charIndex < dlPtr->index.charIndex) {
+ if (index.byteIndex < dlPtr->index.byteIndex) {
goto makeNewDLine;
}
@@ -1251,7 +1363,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;
@@ -1302,7 +1414,7 @@ UpdateDisplayInfo(textPtr)
*/
if (y < maxY) {
- int lineNum, spaceLeft, charsToCount;
+ int lineNum, spaceLeft, bytesToCount;
DLine *lowestPtr;
/*
@@ -1315,22 +1427,24 @@ 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)
+ if (dlPtr->length == 0 && dlPtr->height == 0) { bytesToCount--; break; } /* elide */
+ TkTextIndexForwBytes(&index, dlPtr->byteCount, &index);
+ bytesToCount -= dlPtr->byteCount;
+ } while ((bytesToCount > 0)
&& (index.linePtr == lowestPtr->index.linePtr));
/*
@@ -1357,7 +1471,7 @@ UpdateDisplayInfo(textPtr)
}
}
FreeDLines(textPtr, lowestPtr, (DLine *) NULL, 0);
- charsToCount = INT_MAX;
+ bytesToCount = INT_MAX;
}
/*
@@ -1444,13 +1558,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;
@@ -1557,6 +1671,8 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap)
Display *display;
int height, x;
+ if (dlPtr->chunkPtr == NULL) return;
+
/*
* First, clear the area of the line to the background color for the
* text widget.
@@ -1580,11 +1696,7 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap)
* to its left.
*/
-#ifndef __WIN32__
- /* CYGNUS LOCAL: On Windows, display the cursor even for disabled
- text widgets. */
- if (textPtr->state == tkNormalUid) {
-#endif /* __WIN32__ */
+ if (textPtr->state == TK_STATE_NORMAL) {
for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
chunkPtr = chunkPtr->nextPtr) {
x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curPixelOffset;
@@ -1595,9 +1707,7 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap)
dlPtr->y + dlPtr->spaceAbove);
}
}
-#ifndef __WIN32__
}
-#endif /* __WIN32__ */
/*
* Make yet another pass through all of the chunks to redraw all of
@@ -1629,12 +1739,16 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap)
* something is off to the right).
*/
+ if (chunkPtr->displayProc != NULL)
(*chunkPtr->displayProc)(chunkPtr, -chunkPtr->width,
dlPtr->spaceAbove,
dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
dlPtr->baseline - dlPtr->spaceAbove, display, pixmap,
dlPtr->y + dlPtr->spaceAbove);
} else {
+ /* don't call if elide. This tax ok since not very many visible DLine's in
+ an area, but potentially many elide ones */
+ if (chunkPtr->displayProc != NULL)
(*chunkPtr->displayProc)(chunkPtr, x, dlPtr->spaceAbove,
dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
dlPtr->baseline - dlPtr->spaceAbove, display, pixmap,
@@ -1723,6 +1837,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap)
StyleValues *sValuePtr;
Display *display;
+
/*
* Pass 1: scan through dlPtr from left to right. For each range of
* chunks with the same style, draw the main background for the style
@@ -1796,7 +1911,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap)
rightX = maxX;
}
chunkPtr2 = NULL;
- if (prevPtr != NULL) {
+ if (prevPtr != NULL && prevPtr->chunkPtr != NULL) {
/*
* Find the chunk in the previous line that covers leftX.
*/
@@ -1917,7 +2032,7 @@ DisplayLineBackground(textPtr, dlPtr, prevPtr, pixmap)
rightX = maxX;
}
chunkPtr2 = NULL;
- if (dlPtr->nextPtr != NULL) {
+ if (dlPtr->nextPtr != NULL && dlPtr->nextPtr->chunkPtr != NULL) {
/*
* Find the chunk in the previous line that covers leftX.
*/
@@ -2243,17 +2358,19 @@ DisplayText(clientData)
Tk_Height(textPtr->tkwin) - 2*textPtr->highlightWidth,
textPtr->borderWidth, textPtr->relief);
if (textPtr->highlightWidth != 0) {
- GC gc;
+ GC fgGC, bgGC;
+ bgGC = Tk_GCForColor(textPtr->highlightBgColorPtr,
+ Tk_WindowId(textPtr->tkwin));
if (textPtr->flags & GOT_FOCUS) {
- gc = Tk_GCForColor(textPtr->highlightColorPtr,
+ fgGC = Tk_GCForColor(textPtr->highlightColorPtr,
Tk_WindowId(textPtr->tkwin));
+ TkpDrawHighlightBorder(textPtr->tkwin, fgGC, bgGC,
+ textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin));
} else {
- gc = Tk_GCForColor(textPtr->highlightBgColorPtr,
- Tk_WindowId(textPtr->tkwin));
+ TkpDrawHighlightBorder(textPtr->tkwin, bgGC, bgGC,
+ textPtr->highlightWidth, Tk_WindowId(textPtr->tkwin));
}
- Tk_DrawFocusHighlight(textPtr->tkwin, gc, textPtr->highlightWidth,
- Tk_WindowId(textPtr->tkwin));
}
borders = textPtr->borderWidth + textPtr->highlightWidth;
if (textPtr->padY > 0) {
@@ -2308,6 +2425,7 @@ DisplayText(clientData)
for (prevPtr = NULL, dlPtr = textPtr->dInfoPtr->dLinePtr;
(dlPtr != NULL) && (dlPtr->y < dInfoPtr->maxY);
prevPtr = dlPtr, dlPtr = dlPtr->nextPtr) {
+ if (dlPtr->chunkPtr == NULL) continue;
if (dlPtr->oldY != dlPtr->y) {
if (tkTextDebug) {
char string[TK_POS_CHARS];
@@ -2324,6 +2442,7 @@ DisplayText(clientData)
dlPtr->oldY = dlPtr->y;
dlPtr->flags &= ~NEW_LAYOUT;
}
+ /*prevPtr = dlPtr;*/
}
Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
}
@@ -2600,7 +2719,7 @@ TkTextChanged(textPtr, index1Ptr, index2Ptr)
*/
rounded = *index1Ptr;
- rounded.charIndex = 0;
+ rounded.byteIndex = 0;
firstPtr = FindDLine(dInfoPtr->dLinePtr, &rounded);
if (firstPtr == NULL) {
return;
@@ -2676,7 +2795,7 @@ TkTextRedrawTag(textPtr, index1Ptr, index2Ptr, tagPtr, withTag)
*/
if (index2Ptr == NULL) {
- index2Ptr = TkTextMakeIndex(textPtr->tree,
+ index2Ptr = TkTextMakeByteIndex(textPtr->tree,
TkBTreeNumLines(textPtr->tree), 0, &endOfText);
}
@@ -2730,13 +2849,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) {
@@ -2755,7 +2874,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;
}
@@ -2867,7 +2986,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);
}
@@ -2934,7 +3053,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);
@@ -2962,7 +3081,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;
}
}
@@ -3060,37 +3179,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
@@ -3117,7 +3236,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. */
}
/*
@@ -3125,7 +3244,7 @@ MeasureUp(textPtr, srcPtr, distance, dstPtr)
* in the text.
*/
- TkTextMakeIndex(textPtr->tree, 0, 0, dstPtr);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, dstPtr);
}
/*
@@ -3157,7 +3276,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;
@@ -3166,7 +3285,6 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
argv[0], " see index\"", (char *) NULL);
return TCL_ERROR;
}
-
if (TkTextGetIndex(interp, textPtr, argv[2], &index) != TCL_OK) {
return TCL_ERROR;
}
@@ -3203,27 +3321,12 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
*/
dlPtr = FindDLine(dInfoPtr->dLinePtr, &index);
-
- /*
- * CYGNUS LOCAL: I can sometimes get FindDLine to return a null
- * pointer. I have not been able to find a simple test case,
- * it happens in Gdbtk when you change the font for the debug window.
- * Since you should not have to catch the see command, I have made
- * the error silent...
- */
-
- if (dlPtr == NULL) {
- Tcl_AppendResult(interp, "got a null dlinePtr from FindDLine in the see command.",
- (char *) NULL);
- return TCL_OK;
- }
-
- charCount = index.charIndex - dlPtr->index.charIndex;
- for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) {
- if (charCount < chunkPtr->numChars) {
+ byteCount = index.byteIndex - dlPtr->index.byteIndex;
+ for (chunkPtr = dlPtr->chunkPtr; chunkPtr!=NULL ; chunkPtr = chunkPtr->nextPtr) {
+ if (byteCount < chunkPtr->numBytes) {
break;
}
- charCount -= chunkPtr->numChars;
+ byteCount -= chunkPtr->numBytes;
}
/*
@@ -3231,7 +3334,8 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
* the character within the chunk.
*/
- (*chunkPtr->bboxProc)(chunkPtr, charCount, dlPtr->y + dlPtr->spaceAbove,
+ if (chunkPtr!=NULL) { /* chunkPtr==NULL iff trying to see in elided region */
+ (*chunkPtr->bboxProc)(chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove,
dlPtr->height - dlPtr->spaceAbove - dlPtr->spaceBelow,
dlPtr->baseline - dlPtr->spaceAbove, &x, &y, &width,
&height);
@@ -3239,24 +3343,24 @@ 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 {
return TCL_OK;
}
- }
+ }}
dInfoPtr->flags |= DINFO_OUT_OF_DATE;
if (!(dInfoPtr->flags & REDRAW_PENDING)) {
dInfoPtr->flags |= REDRAW_PENDING;
@@ -3305,7 +3409,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:
@@ -3326,14 +3430,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;
@@ -3369,7 +3473,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;
@@ -3382,21 +3486,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) {
@@ -3406,7 +3510,7 @@ ScrollByLines(textPtr, offset)
break;
}
}
-
+
/*
* Discard the display lines, then either return or prepare
* for the next display line to lay out.
@@ -3416,7 +3520,7 @@ ScrollByLines(textPtr, offset)
if (offset >= 0) {
goto scheduleUpdate;
}
- charsToCount = INT_MAX;
+ bytesToCount = INT_MAX;
}
/*
@@ -3424,7 +3528,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.
@@ -3435,8 +3539,9 @@ ScrollByLines(textPtr, offset)
TkBTreeNumLines(textPtr->tree));
for (i = 0; i < offset; i++) {
dlPtr = LayoutDLine(textPtr, &textPtr->topIndex);
+ if (dlPtr->length == 0 && dlPtr->height == 0) offset++;
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;
@@ -3480,7 +3585,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;
@@ -3518,7 +3623,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;
}
@@ -3553,11 +3658,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;
@@ -3595,7 +3700,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);
@@ -3647,13 +3752,14 @@ 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, gain=10;
Tk_FontMetrics fm;
size_t length;
- if (argc != 5) {
+ if ((argc != 5) && (argc != 6)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " scan mark|dragto x y\"", (char *) NULL);
+ argv[0], " scan mark x y\" or \"",
+ argv[0], " scan dragto x y ?gain?\"", (char *) NULL);
return TCL_ERROR;
}
if (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) {
@@ -3662,6 +3768,8 @@ TkTextScanCmd(textPtr, interp, argc, argv)
if (Tcl_GetInt(interp, argv[4], &y) != TCL_OK) {
return TCL_ERROR;
}
+ if ((argc == 6) && (Tcl_GetInt(interp, argv[5], &gain) != TCL_OK))
+ return TCL_ERROR;
c = argv[2][0];
length = strlen(argv[2]);
if ((c == 'd') && (strncmp(argv[2], "dragto", length) == 0)) {
@@ -3677,33 +3785,35 @@ TkTextScanCmd(textPtr, interp, argc, argv)
* moving again).
*/
- newChar = dInfoPtr->scanMarkChar + (10*(dInfoPtr->scanMarkX - x))
+ newByte = dInfoPtr->scanMarkIndex + (gain*(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;
+ totalScroll = (gain*(dInfoPtr->scanMarkY - y)) / fm.linespace;
if (totalScroll != dInfoPtr->scanTotalScroll) {
index = textPtr->topIndex;
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;
@@ -3730,11 +3840,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).
@@ -3749,13 +3859,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;
@@ -3772,7 +3882,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)) {
@@ -3800,11 +3911,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).
@@ -3819,22 +3930,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) {
@@ -3846,17 +3957,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)) {
@@ -3865,8 +3977,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)");
@@ -3938,7 +4049,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;
@@ -3974,7 +4085,7 @@ TkTextPixelIndex(textPtr, x, y, indexPtr)
* index of the character nearest to (x,y). */
{
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
- register DLine *dlPtr;
+ register DLine *dlPtr, *validdlPtr;
register TkTextDispChunk *chunkPtr;
/*
@@ -4007,8 +4118,9 @@ TkTextPixelIndex(textPtr, x, y, indexPtr)
* Find the display line containing the desired y-coordinate.
*/
- for (dlPtr = dInfoPtr->dLinePtr; y >= (dlPtr->y + dlPtr->height);
+ for (dlPtr = validdlPtr = dInfoPtr->dLinePtr; y >= (dlPtr->y + dlPtr->height);
dlPtr = dlPtr->nextPtr) {
+ if (dlPtr->chunkPtr !=NULL) validdlPtr = dlPtr;
if (dlPtr->nextPtr == NULL) {
/*
* Y-coordinate is off the bottom of the displayed text.
@@ -4019,6 +4131,8 @@ TkTextPixelIndex(textPtr, x, y, indexPtr)
break;
}
}
+ if (dlPtr->chunkPtr == NULL) dlPtr = validdlPtr;
+
/*
* Scan through the line's chunks to find the one that contains
@@ -4030,21 +4144,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);
}
}
@@ -4081,7 +4196,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.
@@ -4105,15 +4220,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;
}
/*
@@ -4124,12 +4239,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.
@@ -4191,6 +4306,7 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr)
{
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
DLine *dlPtr;
+ int dlx;
/*
* Make sure that all of the screen layout information is up to date.
@@ -4209,8 +4325,9 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr)
return -1;
}
- *xPtr = dInfoPtr->x - dInfoPtr->curPixelOffset + dlPtr->chunkPtr->x;
- *widthPtr = dlPtr->length - dlPtr->chunkPtr->x;
+ dlx = (dlPtr->chunkPtr != NULL? dlPtr->chunkPtr->x: 0);
+ *xPtr = dInfoPtr->x - dInfoPtr->curPixelOffset + dlx;
+ *widthPtr = dlPtr->length - dlx;
*yPtr = dlPtr->y;
if ((dlPtr->y + dlPtr->height) > dInfoPtr->maxY) {
*heightPtr = dInfoPtr->maxY - dlPtr->y;
@@ -4221,6 +4338,41 @@ TkTextDLineInfo(textPtr, indexPtr, xPtr, yPtr, widthPtr, heightPtr, basePtr)
return 0;
}
+static void
+ElideBboxProc(chunkPtr, index, y, lineHeight, baseline, xPtr, yPtr,
+ widthPtr, heightPtr)
+ TkTextDispChunk *chunkPtr; /* Chunk containing desired char. */
+ int index; /* Index of desired character within
+ * the chunk. */
+ int y; /* Topmost pixel in area allocated
+ * for this line. */
+ int lineHeight; /* Height of line, in pixels. */
+ int baseline; /* Location of line's baseline, in
+ * pixels measured down from y. */
+ int *xPtr, *yPtr; /* Gets filled in with coords of
+ * character's upper-left pixel.
+ * X-coord is in same coordinate
+ * system as chunkPtr->x. */
+ int *widthPtr; /* Gets filled in with width of
+ * character, in pixels. */
+ int *heightPtr; /* Gets filled in with height of
+ * character, in pixels. */
+{
+ *xPtr = chunkPtr->x;
+ *yPtr = y;
+ *widthPtr = *heightPtr = 0;
+}
+
+
+static int
+ElideMeasureProc(chunkPtr, x)
+ TkTextDispChunk *chunkPtr; /* Chunk containing desired coord. */
+ int x; /* X-coordinate, in same coordinate
+ * system as chunkPtr->x. */
+{
+ return 0 /*chunkPtr->numBytes - 1*/;
+}
+
/*
*--------------------------------------------------------------
*
@@ -4228,7 +4380,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
@@ -4245,29 +4397,29 @@ 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. */
- Tk_Uid wrapMode; /* How to handle line wrapping: tkTextCharUid,
- * tkTextNoneUid, or tkTextWordUid. */
+ TkWrapMode wrapMode; /* How to handle line wrapping: TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */
register TkTextDispChunk *chunkPtr;
/* Structure to fill in with information
* about this chunk. The x field has already
* been set by the caller. */
{
Tk_Font tkfont;
- int nextX, charsThatFit, count;
+ int nextX, bytesThatFit, count;
CharInfo *ciPtr;
char *p;
TkTextSegment *nextPtr;
@@ -4285,17 +4437,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
@@ -4303,17 +4457,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;
}
}
@@ -4330,19 +4484,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--;
}
/*
@@ -4352,22 +4506,22 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
* is not a character segment.
*/
- if (wrapMode != tkTextWordUid) {
- chunkPtr->breakIndex = chunkPtr->numChars;
+ if (wrapMode != TEXT_WRAPMODE_WORD) {
+ 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;
}
@@ -4414,7 +4568,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) {
/*
@@ -4436,30 +4590,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 (!sValuePtr->elide && (ciPtr->numBytes > offsetBytes) && (stylePtr->fgGC != None)) {
+ 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) {
@@ -4467,10 +4620,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);
}
}
}
@@ -4532,7 +4685,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 */
}
/*
@@ -4559,11 +4713,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. */
@@ -4582,10 +4736,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
@@ -4593,8 +4747,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.
@@ -4603,7 +4757,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 {
@@ -4738,7 +4892,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 == ',')) {
@@ -4759,7 +4913,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 {
@@ -4784,7 +4938,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;
}
@@ -4889,7 +5043,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;
}
@@ -4953,7 +5107,7 @@ NextTabStop(textPtr, tkfont, x, tabOrigin)
*
* Determine the number of characters from the string that will fit
* in the given horizontal span. The measurement is done under the
- * assumption that Tk_DisplayChars will be used to actually display
+ * assumption that Tk_DrawTextLayout will be used to actually display
* the characters.
*
* If tabs are encountered in the string, they will be expanded
@@ -4964,7 +5118,7 @@ NextTabStop(textPtr, 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
@@ -4977,11 +5131,11 @@ NextTabStop(textPtr, 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. */
@@ -4998,7 +5152,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) {
/*
@@ -5018,7 +5172,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,
@@ -5043,3 +5197,4 @@ MeasureChars(tkfont, source, maxChars, startX, maxX, tabOrigin, nextXPtr)
*nextXPtr = curX;
return start - source;
}
+
diff --git a/tk/generic/tkTextImage.c b/tk/generic/tkTextImage.c
index 2083d101895..01757b071f8 100644
--- a/tk/generic/tkTextImage.c
+++ b/tk/generic/tkTextImage.c
@@ -5,7 +5,7 @@
* 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.
@@ -62,7 +62,7 @@ static void EmbImageDisplayProc _ANSI_ARGS_((
static int EmbImageLayoutProc _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, TkTextSegment *segPtr,
int offset, int maxX, int maxChars,
- int noCharsYet, Tk_Uid wrapMode,
+ int noCharsYet, TkWrapMode wrapMode,
TkTextDispChunk *chunkPtr));
static void EmbImageProc _ANSI_ARGS_((ClientData clientData,
int x, int y, int width, int height,
@@ -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);
}
@@ -604,8 +604,8 @@ EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars,
* many characters. */
int noCharsYet; /* Non-zero means no characters have been
* assigned to this line yet. */
- Tk_Uid wrapMode; /* Wrap mode to use for line: tkTextCharUid,
- * tkTextNoneUid, or tkTextWordUid. */
+ TkWrapMode wrapMode; /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */
register TkTextDispChunk *chunkPtr;
/* Structure to fill in with information
* about this chunk. The x field has already
@@ -630,7 +630,7 @@ EmbImageLayoutProc(textPtr, indexPtr, eiPtr, offset, maxX, maxChars,
height += 2*eiPtr->body.ei.padY;
}
if ((width > (maxX - chunkPtr->x))
- && !noCharsYet && (textPtr->wrapMode != tkTextNoneUid)) {
+ && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
return 0;
}
@@ -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,7 @@ 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/tk/generic/tkTextIndex.c b/tk/generic/tkTextIndex.c
index f2e9b0316ab..0b59b536c07 100644
--- a/tk/generic/tkTextIndex.c
+++ b/tk/generic/tkTextIndex.c
@@ -5,7 +5,7 @@
* 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.
@@ -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
-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. */
+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
+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,12 +944,128 @@ 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;
+ }
+}
+
+/*
*----------------------------------------------------------------------
*
* StartEnd --
@@ -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);
@@ -838,3 +1184,4 @@ StartEnd(string, indexPtr)
done:
return p;
}
+
diff --git a/tk/generic/tkTextMark.c b/tk/generic/tkTextMark.c
index 87f6079abab..c2e262a4c92 100644
--- a/tk/generic/tkTextMark.c
+++ b/tk/generic/tkTextMark.c
@@ -39,7 +39,7 @@ static void MarkCheckProc _ANSI_ARGS_((TkTextSegment *segPtr,
static int MarkLayoutProc _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, TkTextSegment *segPtr,
int offset, int maxX, int maxChars,
- int noCharsYet, Tk_Uid wrapMode,
+ int noCharsYet, TkWrapMode wrapMode,
TkTextDispChunk *chunkPtr));
static int MarkFindNext _ANSI_ARGS_((Tcl_Interp *interp,
TkText *textPtr, char *markName));
@@ -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;
}
}
@@ -454,7 +454,7 @@ MarkLayoutProc(textPtr, indexPtr, segPtr, offset, maxX, maxChars,
* many characters. */
int noCharsYet; /* Non-zero means no characters have been
* assigned to this line yet. */
- Tk_Uid wrapMode; /* Not used. */
+ TkWrapMode wrapMode; /* Not used. */
register TkTextDispChunk *chunkPtr;
/* Structure to fill in with information
* about this chunk. The x field has already
@@ -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 */ ;
}
@@ -773,3 +773,4 @@ MarkFindPrev(interp, textPtr, string)
segPtr = NULL;
}
}
+
diff --git a/tk/generic/tkTextTag.c b/tk/generic/tkTextTag.c
index e3ae2451683..f623b93026e 100644
--- a/tk/generic/tkTextTag.c
+++ b/tk/generic/tkTextTag.c
@@ -6,7 +6,7 @@
* 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.
@@ -16,13 +16,9 @@
#include "default.h"
#include "tkPort.h"
-#include "tk.h"
+#include "tkInt.h"
#include "tkText.h"
-/*
- * Information used for parsing tag configuration information:
- */
-
static Tk_ConfigSpec tagConfigSpecs[] = {
{TK_CONFIG_BORDER, "-background", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, border), TK_CONFIG_NULL_OK},
@@ -30,7 +26,10 @@ static Tk_ConfigSpec tagConfigSpecs[] = {
(char *) NULL, Tk_Offset(TkTextTag, bgStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-borderwidth", (char *) NULL, (char *) NULL,
"0", Tk_Offset(TkTextTag, bdString),
- TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
+ TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
+ {TK_CONFIG_STRING, "-elide", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(TkTextTag, elideString),
+ TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
{TK_CONFIG_BITMAP, "-fgstipple", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, fgStipple), TK_CONFIG_NULL_OK},
{TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
@@ -63,9 +62,9 @@ static Tk_ConfigSpec tagConfigSpecs[] = {
{TK_CONFIG_STRING, "-underline", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, underlineString),
TK_CONFIG_NULL_OK},
- {TK_CONFIG_UID, "-wrap", (char *) NULL, (char *) NULL,
+ {TK_CONFIG_CUSTOM, "-wrap", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, wrapMode),
- TK_CONFIG_NULL_OK},
+ TK_CONFIG_NULL_OK, &textWrapModeOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
@@ -235,9 +234,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);
@@ -378,14 +390,11 @@ TkTextTagCmd(textPtr, interp, argc, argv)
return TCL_ERROR;
}
}
- if ((tagPtr->wrapMode != NULL)
- && (tagPtr->wrapMode != tkTextCharUid)
- && (tagPtr->wrapMode != tkTextNoneUid)
- && (tagPtr->wrapMode != tkTextWordUid)) {
- Tcl_AppendResult(interp, "bad wrap mode \"", tagPtr->wrapMode,
- "\": must be char, none, or word", (char *) NULL);
- tagPtr->wrapMode = NULL;
- return TCL_ERROR;
+ if (tagPtr->elideString != NULL) {
+ if (Tcl_GetBoolean(interp, tagPtr->elideString,
+ &tagPtr->elide) != TCL_OK) {
+ return TCL_ERROR;
+ }
}
/*
@@ -419,7 +428,8 @@ TkTextTagCmd(textPtr, interp, argc, argv)
|| (tagPtr->spacing3String != NULL)
|| (tagPtr->tabString != NULL)
|| (tagPtr->underlineString != NULL)
- || (tagPtr->wrapMode != NULL)) {
+ || (tagPtr->elideString != NULL)
+ || (tagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
tagPtr->affectsDisplay = 1;
}
TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
@@ -448,10 +458,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 +562,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 +592,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 +641,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 +661,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 +721,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)) {
@@ -811,7 +821,9 @@ TkTextCreateTag(textPtr, tagName)
tagPtr->tabArrayPtr = NULL;
tagPtr->underlineString = NULL;
tagPtr->underline = 0;
- tagPtr->wrapMode = NULL;
+ tagPtr->elideString = NULL;
+ tagPtr->elide = 0;
+ tagPtr->wrapMode = TEXT_WRAPMODE_NULL;
tagPtr->affectsDisplay = 0;
textPtr->numTags++;
Tcl_SetHashValue(hPtr, tagPtr);
@@ -828,7 +840,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:
@@ -1374,3 +1386,4 @@ TkTextPickCurrent(textPtr, eventPtr)
ckfree((char *) copyArrayPtr);
}
}
+
diff --git a/tk/generic/tkTextWind.c b/tk/generic/tkTextWind.c
index cc9f7ba0820..9624403cf2c 100644
--- a/tk/generic/tkTextWind.c
+++ b/tk/generic/tkTextWind.c
@@ -6,7 +6,7 @@
* 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.
@@ -81,7 +81,7 @@ static void EmbWinDisplayProc _ANSI_ARGS_((
static int EmbWinLayoutProc _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, TkTextSegment *segPtr,
int offset, int maxX, int maxChars,
- int noCharsYet, Tk_Uid wrapMode,
+ int noCharsYet, TkWrapMode wrapMode,
TkTextDispChunk *chunkPtr));
static void EmbWinStructureProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
@@ -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);
}
@@ -744,8 +744,8 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
* many characters. */
int noCharsYet; /* Non-zero means no characters have been
* assigned to this line yet. */
- Tk_Uid wrapMode; /* Wrap mode to use for line: tkTextCharUid,
- * tkTextNoneUid, or tkTextWordUid. */
+ TkWrapMode wrapMode; /* Wrap mode to use for line: TEXT_WRAPMODE_CHAR,
+ * TEXT_WRAPMODE_NONE, or TEXT_WRAPMODE_WORD. */
register TkTextDispChunk *chunkPtr;
/* Structure to fill in with information
* about this chunk. The x field has already
@@ -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);
@@ -835,7 +835,7 @@ EmbWinLayoutProc(textPtr, indexPtr, ewPtr, offset, maxX, maxChars,
height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;
}
if ((width > (maxX - chunkPtr->x))
- && !noCharsYet && (textPtr->wrapMode != tkTextNoneUid)) {
+ && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
return 0;
}
@@ -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,7 @@ 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/tk/generic/tkTrig.c b/tk/generic/tkTrig.c
index cf4b8b80c0b..b9f0628242a 100644
--- a/tk/generic/tkTrig.c
+++ b/tk/generic/tkTrig.c
@@ -7,7 +7,7 @@
* 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.
@@ -1066,6 +1066,14 @@ TkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints)
* just put the first point into the output.
*/
+ if (!pointPtr) {
+ /* Of pointPtr == NULL, this function returns an upper limit.
+ * of the array size to store the coordinates. This can be
+ * used to allocate storage, before the actual coordinates
+ * are calculated. */
+ return 1 + numPoints * numSteps;
+ }
+
outputPoints = 0;
if ((pointPtr[0] == pointPtr[numCoords-2])
&& (pointPtr[1] == pointPtr[numCoords-1])) {
@@ -1195,7 +1203,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.
@@ -1465,3 +1473,4 @@ TkGetButtPoints(p1, p2, width, project, m1, m2)
}
}
}
+
diff --git a/tk/generic/tkUtil.c b/tk/generic/tkUtil.c
index 407837438e6..cbb49e6d8bb 100644
--- a/tk/generic/tkUtil.c
+++ b/tk/generic/tkUtil.c
@@ -6,7 +6,7 @@
* 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.
@@ -16,6 +16,501 @@
#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 */
+};
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkStateParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-state" and "-default" options.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The state for a given item gets replaced by the state
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ int c;
+ int flags = (int)clientData;
+ size_t length;
+
+ register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *statePtr = TK_STATE_NULL;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'n') && (strncmp(value, "normal", length) == 0)) {
+ *statePtr = TK_STATE_NORMAL;
+ return TCL_OK;
+ }
+ if ((c == 'd') && (strncmp(value, "disabled", length) == 0)) {
+ *statePtr = TK_STATE_DISABLED;
+ return TCL_OK;
+ }
+ if ((c == 'a') && (flags&1) && (strncmp(value, "active", length) == 0)) {
+ *statePtr = TK_STATE_ACTIVE;
+ return TCL_OK;
+ }
+ if ((c == 'h') && (flags&2) && (strncmp(value, "hidden", length) == 0)) {
+ *statePtr = TK_STATE_HIDDEN;
+ return TCL_OK;
+ }
+
+ Tcl_AppendResult(interp, "bad ", (flags&4)?"-default" : "state",
+ " value \"", value, "\": must be normal",
+ (char *) NULL);
+ if (flags&1) {
+ Tcl_AppendResult(interp, ", active",(char *) NULL);
+ }
+ if (flags&2) {
+ Tcl_AppendResult(interp, ", hidden",(char *) NULL);
+ }
+ if (flags&3) {
+ Tcl_AppendResult(interp, ",",(char *) NULL);
+ }
+ Tcl_AppendResult(interp, " or disabled",(char *) NULL);
+ *statePtr = TK_STATE_NORMAL;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkStatePrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-state"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the state for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TkStatePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
+
+ if (*statePtr==TK_STATE_NORMAL) {
+ return "normal";
+ } else if (*statePtr==TK_STATE_DISABLED) {
+ return "disabled";
+ } else if (*statePtr==TK_STATE_HIDDEN) {
+ return "hidden";
+ } else if (*statePtr==TK_STATE_ACTIVE) {
+ return "active";
+ } else {
+ return "";
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOrientParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-orient" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The orientation for a given item gets replaced by the orientation
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ int c;
+ size_t length;
+
+ register int *orientPtr = (int *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *orientPtr = 0;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'h') && (strncmp(value, "horizontal", length) == 0)) {
+ *orientPtr = 0;
+ return TCL_OK;
+ }
+ if ((c == 'v') && (strncmp(value, "vertical", length) == 0)) {
+ *orientPtr = 1;
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "bad orientation \"", value,
+ "\": must be vertical or horizontal",
+ (char *) NULL);
+ *orientPtr = 0;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkOrientPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-orient"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the orientation for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TkOrientPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register int *statePtr = (int *) (widgRec + offset);
+
+ if (*statePtr) {
+ return "vertical";
+ } else {
+ return "horizontal";
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkOffsetParseProc --
+ *
+ * Converts the offset of a stipple or tile into the Tk_TSOffset structure.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkOffsetParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* not used */
+ Tcl_Interp *interp; /* Interpreter to send results back to */
+ Tk_Window tkwin; /* Window on same display as tile */
+ CONST char *value; /* Name of image */
+ char *widgRec; /* Widget structure record */
+ int offset; /* Offset of tile in record */
+{
+ Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset);
+ Tk_TSOffset tsoffset;
+ CONST char *q, *p;
+ int result;
+
+ if ((value == NULL) || (*value == 0)) {
+ tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ }
+ tsoffset.flags = 0;
+ p = value;
+
+ switch(value[0]) {
+ case '#':
+ if (((int)clientData) & TK_OFFSET_RELATIVE) {
+ tsoffset.flags = TK_OFFSET_RELATIVE;
+ p++; break;
+ }
+ goto badTSOffset;
+ case 'e':
+ switch(value[1]) {
+ case '\0':
+ tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ case 'n':
+ if (value[2]!='d' || value[3]!='\0') {goto badTSOffset;}
+ tsoffset.flags = INT_MAX;
+ goto goodTSOffset;
+ }
+ case 'w':
+ if (value[1] != '\0') {goto badTSOffset;}
+ tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ case 'n':
+ if ((value[1] != '\0') && (value[2] != '\0')) {
+ goto badTSOffset;
+ }
+ switch(value[1]) {
+ case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP;
+ goto goodTSOffset;
+ case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP;
+ goto goodTSOffset;
+ case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP;
+ goto goodTSOffset;
+ }
+ goto badTSOffset;
+ case 's':
+ if ((value[1] != '\0') && (value[2] != '\0')) {
+ goto badTSOffset;
+ }
+ switch(value[1]) {
+ case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM;
+ goto goodTSOffset;
+ case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM;
+ goto goodTSOffset;
+ case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM;
+ goto goodTSOffset;
+ }
+ goto badTSOffset;
+ case 'c':
+ if (strncmp(value, "center", strlen(value)) != 0) {
+ goto badTSOffset;
+ }
+ tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;
+ goto goodTSOffset;
+ }
+ if ((q = strchr(p,',')) == NULL) {
+ if (((int)clientData) & TK_OFFSET_INDEX) {
+ if (Tcl_GetInt(interp, (char *) p, &tsoffset.flags) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ goto badTSOffset;
+ }
+ tsoffset.flags |= TK_OFFSET_INDEX;
+ goto goodTSOffset;
+ }
+ goto badTSOffset;
+ }
+ *((char *) q) = 0;
+ result = Tk_GetPixels(interp, tkwin, (char *) p, &tsoffset.xoffset);
+ *((char *) q) = ',';
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tk_GetPixels(interp, tkwin, (char *) q+1, &tsoffset.yoffset) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+
+goodTSOffset:
+ /* below is a hack to allow the stipple/tile offset to be stored
+ * in the internal tile structure. Most of the times, offsetPtr
+ * is a pointer to an already existing tile structure. However
+ * if this structure is not already created, we must do it
+ * with Tk_GetTile()!!!!;
+ */
+
+ memcpy(offsetPtr,&tsoffset, sizeof(Tk_TSOffset));
+ return TCL_OK;
+
+badTSOffset:
+ Tcl_AppendResult(interp, "bad offset \"", value,
+ "\": expected \"x,y\"", (char *) NULL);
+ if (((int) clientData) & TK_OFFSET_RELATIVE) {
+ Tcl_AppendResult(interp, ", \"#x,y\"", (char *) NULL);
+ }
+ if (((int) clientData) & TK_OFFSET_INDEX) {
+ Tcl_AppendResult(interp, ", <index>", (char *) NULL);
+ }
+ Tcl_AppendResult(interp, ", n, ne, e, se, s, sw, w, nw, or center",
+ (char *) NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkOffsetPrintProc --
+ *
+ * Returns the offset of the tile.
+ *
+ * Results:
+ * The offset of the tile is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TkOffsetPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* not used */
+ Tk_Window tkwin; /* not used */
+ char *widgRec; /* Widget structure record */
+ int offset; /* Offset of tile in record */
+ Tcl_FreeProc **freeProcPtr; /* not used */
+{
+ Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset);
+ char *p, *q;
+
+ if ((offsetPtr->flags) & TK_OFFSET_INDEX) {
+ if ((offsetPtr->flags) >= INT_MAX) {
+ return "end";
+ }
+ p = (char *) ckalloc(32);
+ sprintf(p, "%d",(offsetPtr->flags & (~TK_OFFSET_INDEX)));
+ *freeProcPtr = TCL_DYNAMIC;
+ return p;
+ }
+ if ((offsetPtr->flags) & TK_OFFSET_TOP) {
+ if ((offsetPtr->flags) & TK_OFFSET_LEFT) {
+ return "nw";
+ } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) {
+ return "n";
+ } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) {
+ return "ne";
+ }
+ } else if ((offsetPtr->flags) & TK_OFFSET_MIDDLE) {
+ if ((offsetPtr->flags) & TK_OFFSET_LEFT) {
+ return "w";
+ } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) {
+ return "center";
+ } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) {
+ return "e";
+ }
+ } else if ((offsetPtr->flags) & TK_OFFSET_BOTTOM) {
+ if ((offsetPtr->flags) & TK_OFFSET_LEFT) {
+ return "sw";
+ } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) {
+ return "s";
+ } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) {
+ return "se";
+ }
+ }
+ q = p = (char *) ckalloc(32);
+ if ((offsetPtr->flags) & TK_OFFSET_RELATIVE) {
+ *q++ = '#';
+ }
+ sprintf(q, "%d,%d",offsetPtr->xoffset, offsetPtr->yoffset);
+ *freeProcPtr = TCL_DYNAMIC;
+ return p;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPixelParseProc --
+ *
+ * Converts the name of an image into a tile.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkPixelParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* if non-NULL, negative values are
+ * allowed as well */
+ Tcl_Interp *interp; /* Interpreter to send results back to */
+ Tk_Window tkwin; /* Window on same display as tile */
+ CONST char *value; /* Name of image */
+ char *widgRec; /* Widget structure record */
+ int offset; /* Offset of tile in record */
+{
+ double *doublePtr = (double *)(widgRec + offset);
+ int result;
+
+ result = TkGetDoublePixels(interp, tkwin, value, doublePtr);
+
+ if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) {
+ Tcl_AppendResult(interp, "bad screen distance \"", value,
+ "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPixelPrintProc --
+ *
+ * Returns the name of the tile.
+ *
+ * Results:
+ * The name of the tile is returned.
+ *
+ *----------------------------------------------------------------------
+ */
+
+char *
+TkPixelPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* not used */
+ Tk_Window tkwin; /* not used */
+ char *widgRec; /* Widget structure record */
+ int offset; /* Offset of tile in record */
+ Tcl_FreeProc **freeProcPtr; /* not used */
+{
+ double *doublePtr = (double *)(widgRec + offset);
+ char *p;
+
+ p = (char *) ckalloc(24);
+ Tcl_PrintDouble((Tcl_Interp *) NULL, *doublePtr, p);
+ *freeProcPtr = TCL_DYNAMIC;
+ return p;
+}
/*
*----------------------------------------------------------------------
@@ -50,22 +545,6 @@ TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding)
{
XRectangle rects[4];
- /*
- * On the Macintosh the highlight ring needs to be "padded"
- * out by one pixel. Unfortunantly, none of the Tk widgets
- * had a notion of padding between the focus ring and the
- * widget. So we add this padding here. This introduces
- * two things to worry about:
- *
- * 1) The widget must draw the background color covering
- * the focus ring area before calling Tk_DrawFocus.
- * 2) It is impossible to draw a focus ring of width 1.
- * (For the Macintosh Look & Feel use width of 3)
- */
-#ifdef MAC_TCL
- width--;
-#endif
-
rects[0].x = padding;
rects[0].y = padding;
rects[0].width = Tk_Width(tkwin) - (2 * padding);
@@ -93,6 +572,12 @@ TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding)
* This procedure draws a rectangular ring around the outside of
* a widget to indicate that it has received the input focus.
*
+ * This function is now deprecated. Use TkpDrawHighlightBorder instead,
+ * since this function does not handle drawing the Focus ring properly
+ * on the Macintosh - you need to know the background GC as well
+ * as the foreground since the Mac focus ring separated from the widget
+ * by a 1 pixel border.
+ *
* Results:
* None.
*
@@ -132,7 +617,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:
@@ -197,6 +682,85 @@ Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr)
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetScrollInfoObj --
+ *
+ * This procedure is invoked to parse "xview" and "yview"
+ * scrolling commands for widgets using the new scrolling
+ * command syntax ("moveto" or "scroll" options).
+ *
+ * Results:
+ * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,
+ * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether
+ * the command was successfully parsed and what form the command
+ * took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the
+ * desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS,
+ * *intPtr is filled in with the number of lines to move (may be
+ * negative); if TK_SCROLL_ERROR, the interp's result contains an
+ * error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ int objc; /* # arguments for command. */
+ Tcl_Obj *CONST objv[]; /* Arguments for command. */
+ double *dblPtr; /* Filled in with argument "moveto"
+ * option, if any. */
+ int *intPtr; /* Filled in with number of pages
+ * or lines to scroll, if any. */
+{
+ int c;
+ size_t length;
+ char *arg2, *arg4;
+
+ arg2 = Tcl_GetString(objv[2]);
+ length = strlen(arg2);
+ c = arg2[0];
+ if ((c == 'm') && (strncmp(arg2, "moveto", length) == 0)) {
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 2, objv, "moveto fraction");
+ return TK_SCROLL_ERROR;
+ }
+ if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {
+ return TK_SCROLL_ERROR;
+ }
+ return TK_SCROLL_MOVETO;
+ } else if ((c == 's')
+ && (strncmp(arg2, "scroll", length) == 0)) {
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages");
+ return TK_SCROLL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
+ return TK_SCROLL_ERROR;
+ }
+ arg4 = Tcl_GetString(objv[4]);
+ length = (strlen(arg4));
+ c = arg4[0];
+ if ((c == 'p') && (strncmp(arg4, "pages", length) == 0)) {
+ return TK_SCROLL_PAGES;
+ } else if ((c == 'u')
+ && (strncmp(arg4, "units", length) == 0)) {
+ return TK_SCROLL_UNITS;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", arg4,
+ "\": must be units or pages", (char *) NULL);
+ return TK_SCROLL_ERROR;
+ }
+ }
+ Tcl_AppendResult(interp, "unknown option \"", arg2,
+ "\": must be moveto or scroll", (char *) NULL);
+ return TK_SCROLL_ERROR;
+}
+
+/*
*---------------------------------------------------------------------------
*
* TkComputeAnchor --
@@ -310,7 +874,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,30 +883,73 @@ 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/tk/generic/tkVisual.c b/tk/generic/tkVisual.c
index 4b9457814a2..a2d717a119d 100644
--- a/tk/generic/tkVisual.c
+++ b/tk/generic/tkVisual.c
@@ -6,7 +6,7 @@
* 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.
@@ -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
@@ -538,3 +539,4 @@ Tk_PreserveColormap(display, colormap)
}
}
}
+
diff --git a/tk/generic/tkWindow.c b/tk/generic/tkWindow.c
index 2da31fd6e2d..5f3a8a0c517 100644
--- a/tk/generic/tkWindow.c
+++ b/tk/generic/tkWindow.c
@@ -18,38 +18,30 @@
#include "tkPort.h"
#include "tkInt.h"
-/*
- * Count of number of main windows currently open in this process.
- */
-
-static int numMainWindows;
-
-/*
- * First in list of all main windows managed by this process.
- */
-
-TkMainInfo *tkMainWindowList = NULL;
-
-/*
- * List of all displays currently in use.
- */
-
-TkDisplay *tkDisplayList = NULL;
+#if !defined(__WIN32__) && !defined(MAC_TCL)
+#include "tkUnixInt.h"
+#endif
-/*
- * Have statics in this module been initialized?
- */
-static int initialized = 0;
+typedef struct ThreadSpecificData {
+ int numMainWindows; /* Count of numver of main windows currently
+ * open in this thread. */
+ TkMainInfo *mainWindowList;
+ /* First in list of all main windows managed
+ * by this thread. */
+ TkDisplay *displayList;
+ /* List of all displays currently in use by
+ * the current thread. */
+ int initialized; /* 0 means the structures above need
+ * initializing. */
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
-/*
- * The variables below hold several uid's that are used in many places
- * in the toolkit.
+/*
+ * The Mutex below is used to lock access to the Tk_Uid structs above.
*/
-Tk_Uid tkDisabledUid = NULL;
-Tk_Uid tkActiveUid = NULL;
-Tk_Uid tkNormalUid = NULL;
+TCL_DECLARE_MUTEX(windowMutex)
/*
* Default values for "changes" and "atts" fields of TkWindows. Note
@@ -94,6 +86,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 +97,67 @@ static TkCmd commands[] = {
* Commands that are part of the intrinsics:
*/
- {"bell", NULL, Tk_BellObjCmd, 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", NULL, Tk_ImageCmd, 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", NULL, Tk_DestroyObjCmd, 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", NULL, Tk_ImageObjCmd, 1, 1},
+ {"lower", NULL, Tk_LowerObjCmd, 1, 1},
+ {"option", NULL, Tk_OptionObjCmd, 1, 1},
+ {"pack", Tk_PackCmd, NULL, 1, 1},
+ {"place", Tk_PlaceCmd, NULL, 1, 1},
+ {"raise", NULL, Tk_RaiseObjCmd, 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", NULL, Tk_CanvasObjCmd, 1, 1},
+ {"checkbutton", NULL, Tk_CheckbuttonObjCmd, 1, 0},
+ {"entry", NULL, Tk_EntryObjCmd, 1, 0},
+ {"frame", NULL, Tk_FrameObjCmd, 1, 1},
+ {"label", NULL, Tk_LabelObjCmd, 1, 0},
+ {"listbox", NULL, Tk_ListboxObjCmd, 1, 0},
+ {"menubutton", NULL, Tk_MenubuttonObjCmd, 1, 0},
+ {"message", Tk_MessageCmd, NULL, 1, 1},
+ {"radiobutton", NULL, Tk_RadiobuttonObjCmd, 1, 0},
+ {"scale", NULL, Tk_ScaleObjCmd, 1, 0},
+ {"scrollbar", Tk_ScrollbarCmd, NULL, 1, 1},
+ {"text", Tk_TextCmd, NULL, 1, 1},
+ {"toplevel", NULL, Tk_ToplevelObjCmd, 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 +222,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
@@ -249,12 +250,11 @@ CreateTopLevelWindow(interp, parent, name, screenName)
register TkWindow *winPtr;
register TkDisplay *dispPtr;
int screenId;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- if (!initialized) {
- initialized = 1;
- tkActiveUid = Tk_GetUid("active");
- tkDisabledUid = Tk_GetUid("disabled");
- tkNormalUid = Tk_GetUid("normal");
+ if (!tsdPtr->initialized) {
+ tsdPtr->initialized = 1;
/*
* Create built-in image types.
@@ -268,7 +268,7 @@ CreateTopLevelWindow(interp, parent, name, screenName)
*/
Tk_CreatePhotoImageFormat(&tkImgFmtGIF);
- Tk_CreatePhotoImageFormat(&tkImgFmtPPM);
+ Tk_CreateOldPhotoImageFormat(&tkImgFmtPPM);
/*
* Create exit handler to delete all windows when the application
@@ -331,7 +331,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.
*
@@ -354,6 +354,8 @@ GetScreen(interp, screenName, screenPtr)
char *p;
int screenId;
size_t length;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Separate the screen number from the rest of the display
@@ -364,8 +366,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);
@@ -384,7 +387,7 @@ GetScreen(interp, screenName, screenPtr)
* then open a new connection.
*/
- for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
if (dispPtr == NULL) {
dispPtr = TkpOpenDisplay(screenName);
if (dispPtr == NULL) {
@@ -392,29 +395,35 @@ GetScreen(interp, screenName, screenPtr)
screenName, "\"", (char *) NULL);
return (TkDisplay *) NULL;
}
- dispPtr->nextPtr = tkDisplayList;
+ dispPtr->nextPtr = TkGetDisplayList();
dispPtr->name = (char *) ckalloc((unsigned) (length+1));
dispPtr->lastEventTime = CurrentTime;
- strncpy(dispPtr->name, screenName, length);
- dispPtr->name[length] = '\0';
+ dispPtr->borderInit = 0;
+ dispPtr->atomInit = 0;
dispPtr->bindInfoStale = 1;
dispPtr->modeModMask = 0;
dispPtr->metaModMask = 0;
dispPtr->altModMask = 0;
dispPtr->numModKeyCodes = 0;
dispPtr->modKeyCodes = NULL;
- OpenIM(dispPtr);
+ dispPtr->bitmapInit = 0;
+ dispPtr->bitmapAutoNumber = 0;
+ dispPtr->numIdSearches = 0;
+ dispPtr->numSlowSearches = 0;
+ dispPtr->colorInit = 0;
+ dispPtr->stressPtr = NULL;
+ dispPtr->cursorInit = 0;
+ dispPtr->cursorString[0] = '\0';
+ dispPtr->cursorFont = None;
dispPtr->errorPtr = NULL;
dispPtr->deleteCount = 0;
- dispPtr->commTkwin = NULL;
- dispPtr->selectionInfoPtr = NULL;
- dispPtr->multipleAtom = None;
- dispPtr->clipWindow = NULL;
- dispPtr->clipboardActive = 0;
- dispPtr->clipboardAppPtr = NULL;
- dispPtr->clipTargetPtr = NULL;
- dispPtr->atomInit = 0;
- dispPtr->cursorFont = None;
+ dispPtr->delayedMotionPtr = NULL;
+ dispPtr->focusDebug = 0;
+ dispPtr->implicitWinPtr = NULL;
+ dispPtr->focusPtr = NULL;
+ dispPtr->gcInit = 0;
+ dispPtr->geomInit = 0;
+ dispPtr->uidInit = 0;
dispPtr->grabWinPtr = NULL;
dispPtr->eventualGrabWinPtr = NULL;
dispPtr->buttonWinPtr = NULL;
@@ -422,18 +431,38 @@ GetScreen(interp, screenName, screenPtr)
dispPtr->firstGrabEventPtr = NULL;
dispPtr->lastGrabEventPtr = NULL;
dispPtr->grabFlags = 0;
- TkInitXId(dispPtr);
+ dispPtr->mouseButtonState = 0;
+ dispPtr->warpInProgress = 0;
+ dispPtr->warpWindow = None;
+ dispPtr->warpX = 0;
+ dispPtr->warpY = 0;
+ dispPtr->gridInit = 0;
+ dispPtr->imageId = 0;
+ dispPtr->packInit = 0;
+ dispPtr->placeInit = 0;
+ dispPtr->selectionInfoPtr = NULL;
+ dispPtr->multipleAtom = None;
+ dispPtr->clipWindow = NULL;
+ dispPtr->clipboardActive = 0;
+ dispPtr->clipboardAppPtr = NULL;
+ dispPtr->clipTargetPtr = NULL;
+ dispPtr->commTkwin = NULL;
+ dispPtr->wmTracing = 0;
+ dispPtr->firstWmPtr = NULL;
+ dispPtr->foregroundWmPtr = NULL;
dispPtr->destroyCount = 0;
dispPtr->lastDestroyRequest = 0;
dispPtr->cmapPtr = NULL;
- dispPtr->implicitWinPtr = NULL;
- dispPtr->focusPtr = NULL;
- dispPtr->stressPtr = NULL;
- dispPtr->delayedMotionPtr = NULL;
Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS);
+
dispPtr->refCount = 0;
-
- tkDisplayList = dispPtr;
+ strncpy(dispPtr->name, screenName, length);
+ dispPtr->name[length] = '\0';
+ dispPtr->useInputMethods = 0;
+ OpenIM(dispPtr);
+ TkInitXId(dispPtr);
+
+ tsdPtr->displayList = dispPtr;
break;
}
if ((strncmp(dispPtr->name, screenName, length) == 0)
@@ -442,7 +471,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;
@@ -472,8 +504,10 @@ TkGetDisplay(display)
Display *display; /* X's display pointer */
{
TkDisplay *dispPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- for (dispPtr = tkDisplayList; dispPtr != NULL;
+ for (dispPtr = tsdPtr->displayList; dispPtr != NULL;
dispPtr = dispPtr->nextPtr) {
if (dispPtr->display == display) {
break;
@@ -485,6 +519,58 @@ TkGetDisplay(display)
/*
*--------------------------------------------------------------
*
+ * TkGetDisplayList --
+ *
+ * This procedure returns a pointer to the thread-local
+ * list of TkDisplays corresponding to the open displays.
+ *
+ * Results:
+ * The return value is a pointer to the first TkDisplay
+ * structure in thread-local-storage.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+TkDisplay *
+TkGetDisplayList()
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->displayList;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkGetMainInfoList --
+ *
+ * This procedure returns a pointer to the list of structures
+ * containing information about all main windows for the
+ * current thread.
+ *
+ * Results:
+ * The return value is a pointer to the first TkMainInfo
+ * structure in thread local storage.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+TkMainInfo *
+TkGetMainInfoList()
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->mainWindowList;
+}
+/*
+ *--------------------------------------------------------------
+ *
* TkAllocWindow --
*
* This procedure creates and initializes a TkWindow structure.
@@ -675,7 +761,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 +789,9 @@ TkCreateMainWindow(interp, screenName, baseName)
register TkMainInfo *mainPtr;
register TkWindow *winPtr;
register TkCmd *cmdPtr;
+ ClientData clientData;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Panic if someone updated the TkWindow structure without
@@ -734,6 +823,7 @@ TkCreateMainWindow(interp, screenName, baseName)
mainPtr->refCount = 1;
mainPtr->interp = interp;
Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
+ TkEventInit();
TkBindInit(mainPtr);
TkFontPkgInit(mainPtr);
mainPtr->tlFocusPtr = NULL;
@@ -745,8 +835,8 @@ TkCreateMainWindow(interp, screenName, baseName)
TCL_LINK_BOOLEAN) != TCL_OK) {
Tcl_ResetResult(interp);
}
- mainPtr->nextPtr = tkMainWindowList;
- tkMainWindowList = mainPtr;
+ mainPtr->nextPtr = tsdPtr->mainWindowList;
+ tsdPtr->mainWindowList = mainPtr;
winPtr->mainPtr = mainPtr;
hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
Tcl_SetHashValue(hPtr, winPtr);
@@ -774,12 +864,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 +883,8 @@ TkCreateMainWindow(interp, screenName, baseName)
}
}
+ TkCreateMenuCmd(interp);
+
/*
* Set variables for the intepreter.
*/
@@ -795,7 +892,7 @@ TkCreateMainWindow(interp, screenName, baseName)
Tcl_SetVar(interp, "tk_patchLevel", TK_PATCH_LEVEL, TCL_GLOBAL_ONLY);
Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);
- numMainWindows++;
+ tsdPtr->numMainWindows++;
return tkwin;
}
@@ -811,7 +908,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 +922,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 +975,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 +989,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. */
@@ -1011,6 +1108,8 @@ Tk_DestroyWindow(tkwin)
TkWindow *winPtr = (TkWindow *) tkwin;
TkDisplay *dispPtr = winPtr->dispPtr;
XEvent event;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (winPtr->flags & TK_ALREADY_DEAD) {
/*
@@ -1054,19 +1153,19 @@ Tk_DestroyWindow(tkwin)
if (winPtr->mainPtr->winPtr == winPtr) {
dispPtr->refCount--;
- if (tkMainWindowList == winPtr->mainPtr) {
- tkMainWindowList = winPtr->mainPtr->nextPtr;
+ if (tsdPtr->mainWindowList == winPtr->mainPtr) {
+ tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr;
} else {
TkMainInfo *prevPtr;
- for (prevPtr = tkMainWindowList;
+ for (prevPtr = tsdPtr->mainWindowList;
prevPtr->nextPtr != winPtr->mainPtr;
prevPtr = prevPtr->nextPtr) {
/* Empty loop body. */
}
prevPtr->nextPtr = winPtr->mainPtr->nextPtr;
}
- numMainWindows--;
+ tsdPtr->numMainWindows--;
}
/*
@@ -1222,8 +1321,8 @@ Tk_DestroyWindow(tkwin)
Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
TkBindFree(winPtr->mainPtr);
- TkFontPkgFree(winPtr->mainPtr);
TkDeleteAllImages(winPtr->mainPtr);
+ TkFontPkgFree(winPtr->mainPtr);
/*
* When embedding Tk into other applications, make sure
@@ -1257,7 +1356,7 @@ Tk_DestroyWindow(tkwin)
* Splice this display out of the list of displays.
*/
- for (theDispPtr = tkDisplayList, backDispPtr = NULL;
+ for (theDispPtr = displayList, backDispPtr = NULL;
(theDispPtr != winPtr->dispPtr) &&
(theDispPtr != NULL);
theDispPtr = theDispPtr->nextPtr) {
@@ -1267,7 +1366,7 @@ Tk_DestroyWindow(tkwin)
panic("could not find display to close!");
}
if (backDispPtr == NULL) {
- tkDisplayList = theDispPtr->nextPtr;
+ displayList = theDispPtr->nextPtr;
} else {
backDispPtr->nextPtr = theDispPtr->nextPtr;
}
@@ -1993,7 +2092,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.
@@ -2010,6 +2109,15 @@ Tk_NameToWindow(interp, pathName, tkwin)
{
Tcl_HashEntry *hPtr;
+ if (tkwin == NULL) {
+ /*
+ * Either we're not really in Tk, or the main window was destroyed and
+ * we're on our way out of the application
+ */
+ Tcl_AppendResult(interp, "NULL main window", (char *)NULL);
+ return NULL;
+ }
+
hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
pathName);
if (hPtr == NULL) {
@@ -2048,7 +2156,7 @@ Tk_IdToWindow(display, window)
TkDisplay *dispPtr;
Tcl_HashEntry *hPtr;
- for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
+ for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) {
if (dispPtr == NULL) {
return NULL;
}
@@ -2165,9 +2273,6 @@ Tk_RestackWindow(tkwin, aboveBelow, other)
{
TkWindow *winPtr = (TkWindow *) tkwin;
TkWindow *otherPtr = (TkWindow *) other;
- XWindowChanges changes;
- unsigned int mask;
-
/*
* Special case: if winPtr is a top-level window then just find
@@ -2175,8 +2280,6 @@ Tk_RestackWindow(tkwin, aboveBelow, other)
* otherPtr without changing any of Tk's childLists.
*/
- changes.stack_mode = aboveBelow;
- mask = CWStackMode;
if (winPtr->flags & TK_TOP_LEVEL) {
while ((otherPtr != NULL) && !(otherPtr->flags & TK_TOP_LEVEL)) {
otherPtr = otherPtr->parentPtr;
@@ -2248,6 +2351,10 @@ Tk_RestackWindow(tkwin, aboveBelow, other)
*/
if (winPtr->window != None) {
+ XWindowChanges changes;
+ unsigned int mask;
+
+ mask = CWStackMode;
changes.stack_mode = Above;
for (otherPtr = winPtr->nextPtr; otherPtr != NULL;
otherPtr = otherPtr->nextPtr) {
@@ -2274,7 +2381,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.
@@ -2289,14 +2396,16 @@ Tk_MainWindow(interp)
* reporting also. */
{
TkMainInfo *mainPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- for (mainPtr = tkMainWindowList; mainPtr != NULL;
+ for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL;
mainPtr = mainPtr->nextPtr) {
if (mainPtr->interp == 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;
}
@@ -2407,7 +2516,10 @@ OpenIM(dispPtr)
int
Tk_GetNumMainWindows()
{
- return numMainWindows;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ return tsdPtr->numMainWindows;
}
/*
@@ -2433,8 +2545,10 @@ DeleteWindowsExitProc(clientData)
{
TkDisplay *displayPtr, *nextPtr;
Tcl_Interp *interp;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- while (tkMainWindowList != NULL) {
+ while (tsdPtr->mainWindowList != NULL) {
/*
* We must protect the interpreter while deleting the window,
* because of <Destroy> bindings which could destroy the interpreter
@@ -2442,14 +2556,14 @@ DeleteWindowsExitProc(clientData)
* the call stack pointing at deleted memory, causing core dumps.
*/
- interp = tkMainWindowList->winPtr->mainPtr->interp;
+ interp = tsdPtr->mainWindowList->winPtr->mainPtr->interp;
Tcl_Preserve((ClientData) interp);
- Tk_DestroyWindow((Tk_Window) tkMainWindowList->winPtr);
+ Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr);
Tcl_Release((ClientData) interp);
}
- displayPtr = tkDisplayList;
- tkDisplayList = NULL;
+ displayPtr = tsdPtr->displayList;
+ tsdPtr->displayList = NULL;
/*
* Iterate destroying the displays until no more displays remain.
@@ -2458,9 +2572,9 @@ DeleteWindowsExitProc(clientData)
* as well as the old ones.
*/
- for (displayPtr = tkDisplayList;
+ for (displayPtr = tsdPtr->displayList;
displayPtr != NULL;
- displayPtr = tkDisplayList) {
+ displayPtr = tsdPtr->displayList) {
/*
* Now iterate over the current list of open displays, and first
@@ -2471,7 +2585,8 @@ DeleteWindowsExitProc(clientData)
* if it needs to dispatch a message.
*/
- for (tkDisplayList = NULL; displayPtr != NULL; displayPtr = nextPtr) {
+ for (tsdPtr->displayList = NULL; displayPtr != NULL;
+ displayPtr = nextPtr) {
nextPtr = displayPtr->nextPtr;
if (displayPtr->name != (char *) NULL) {
ckfree(displayPtr->name);
@@ -2481,12 +2596,9 @@ DeleteWindowsExitProc(clientData)
}
}
- numMainWindows = 0;
- tkMainWindowList = NULL;
- initialized = 0;
- tkDisabledUid = NULL;
- tkActiveUid = NULL;
- tkNormalUid = NULL;
+ tsdPtr->numMainWindows = 0;
+ tsdPtr->mainWindowList = NULL;
+ tsdPtr->initialized = 0;
}
/*
@@ -2504,7 +2616,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 +2641,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:
@@ -2582,6 +2694,9 @@ Tk_SafeInit(interp)
return Initialize(interp);
}
+
+extern TkStubs tkStubs;
+
/*
*----------------------------------------------------------------------
*
@@ -2589,8 +2704,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 +2721,19 @@ Initialize(interp)
int argc, code;
char **argv, *args[20];
Tcl_DString class;
- char buffer[30];
+ ThreadSpecificData *tsdPtr;
+
+ /*
+ * Ensure that we are getting the matching version of Tcl. This is
+ * really only an issue when Tk is loaded dynamically.
+ */
+
+ if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
+ return TCL_ERROR;
+ }
+
+ tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
/*
* Start by initializing all the static variables to default acceptable
@@ -2614,6 +2741,7 @@ Initialize(interp)
* code.
*/
+ Tcl_MutexLock(&windowMutex);
synchronize = 0;
name = NULL;
display = NULL;
@@ -2648,6 +2776,7 @@ Initialize(interp)
if (master == NULL) {
Tcl_DStringFree(&ds);
Tcl_AppendResult(interp, "NULL master", (char *) NULL);
+ Tcl_MutexUnlock(&windowMutex);
return TCL_ERROR;
}
if (!Tcl_IsSafe(master)) {
@@ -2661,6 +2790,7 @@ Initialize(interp)
if (Tcl_GetInterpPath(master, interp) != TCL_OK) {
Tcl_AppendResult(interp, "error in Tcl_GetInterpPath",
(char *) NULL);
+ Tcl_MutexUnlock(&windowMutex);
return TCL_ERROR;
}
/*
@@ -2684,6 +2814,7 @@ Initialize(interp)
Tcl_AppendResult(interp,
"not allowed to start Tk by master's safe::TkInit",
(char *) NULL);
+ Tcl_MutexUnlock(&windowMutex);
return TCL_ERROR;
}
Tcl_DStringFree(&ds);
@@ -2705,10 +2836,13 @@ Initialize(interp)
}
argv = NULL;
if (p != NULL) {
+ char buffer[TCL_INTEGER_SPACE];
+
if (Tcl_SplitList(interp, p, &argc, &argv) != TCL_OK) {
argError:
Tcl_AddErrorInfo(interp,
"\n (processing arguments in argv variable)");
+ Tcl_MutexUnlock(&windowMutex);
return TCL_ERROR;
}
if (Tk_ParseArgv(interp, (Tk_Window) NULL, &argc, argv,
@@ -2741,8 +2875,8 @@ Initialize(interp)
}
p = Tcl_DStringValue(&class);
- if (islower(UCHAR(*p))) {
- *p = toupper(UCHAR(*p));
+ if (*p) {
+ Tcl_UtfToTitle(p);
}
/*
@@ -2766,7 +2900,7 @@ Initialize(interp)
* that it will be available to subprocesses created by us.
*/
- if (numMainWindows == 0) {
+ if (tsdPtr->numMainWindows == 0) {
Tcl_SetVar2(interp, "env", "DISPLAY", display, TCL_GLOBAL_ONLY);
}
}
@@ -2813,15 +2947,28 @@ Initialize(interp)
}
geometry = NULL;
}
+ Tcl_MutexUnlock(&windowMutex);
+
if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) {
code = TCL_ERROR;
goto done;
}
- code = Tcl_PkgProvide(interp, "Tk", TK_VERSION);
+
+ /*
+ * Provide Tk and its stub table.
+ */
+
+ code = Tcl_PkgProvideEx(interp, "Tk", TK_VERSION, (ClientData) &tkStubs);
if (code != TCL_OK) {
goto done;
}
+#ifdef Tk_InitStubs
+#undef Tk_InitStubs
+#endif
+
+ Tk_InitStubs(interp, TK_VERSION, 1);
+
/*
* Invoke platform-specific initialization.
*/
@@ -2834,3 +2981,5 @@ Initialize(interp)
}
return code;
}
+
+
diff --git a/tk/generic/tkXId.c b/tk/generic/tkXId.c
new file mode 100644
index 00000000000..8cf397d9dd4
--- /dev/null
+++ b/tk/generic/tkXId.c
@@ -0,0 +1,495 @@
+/*
+ * tkXId.c --
+ *
+ * This file provides a replacement function for the default X
+ * resource allocator (_XAllocID). The problem with the default
+ * allocator is that it never re-uses ids, which causes long-lived
+ * applications to crash when X resource identifiers wrap around.
+ * The replacement functions in this file re-use old identifiers
+ * to prevent this problem.
+ *
+ * The code in this file is based on similar implementations by
+ * George C. Kaplan and Michael Hoegeman.
+ *
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1994-1995 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * SCCS: @(#) tkXId.c 1.16 96/02/28 21:56:40
+ */
+
+/*
+ * The definition below is needed on some systems so that we can access
+ * the resource_alloc field of Display structures in order to replace
+ * the resource allocator.
+ */
+
+#define XLIB_ILLEGAL_ACCESS 1
+
+#include "tkInt.h"
+#include "tkPort.h"
+
+/*
+ * A structure of the following type is used to hold one or more
+ * available resource identifiers. There is a list of these structures
+ * for each display.
+ */
+
+#define IDS_PER_STACK 10
+typedef struct TkIdStack {
+ XID ids[IDS_PER_STACK]; /* Array of free identifiers. */
+ int numUsed; /* Indicates how many of the entries
+ * in ids are currently in use. */
+ TkDisplay *dispPtr; /* Display to which ids belong. */
+ struct TkIdStack *nextPtr; /* Next bunch of free identifiers
+ * for the same display. */
+} TkIdStack;
+
+/*
+ * Forward declarations for procedures defined in this file:
+ */
+
+static XID AllocXId _ANSI_ARGS_((Display *display));
+static Tk_RestrictAction CheckRestrictProc _ANSI_ARGS_((
+ ClientData clientData, XEvent *eventPtr));
+static void WindowIdCleanup _ANSI_ARGS_((ClientData clientData));
+static void WindowIdCleanup2 _ANSI_ARGS_((ClientData clientData));
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkInitXId --
+ *
+ * This procedure is called to initialize the id allocator for
+ * a given display.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The official allocator for the display is set up to be Tk_AllocXID.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkInitXId(dispPtr)
+ TkDisplay *dispPtr; /* Tk's information about the
+ * display. */
+{
+ dispPtr->idStackPtr = NULL;
+ dispPtr->defaultAllocProc = dispPtr->display->resource_alloc;
+ dispPtr->display->resource_alloc = AllocXId;
+ dispPtr->windowStackPtr = NULL;
+ dispPtr->idCleanupScheduled = 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AllocXId --
+ *
+ * This procedure is invoked by Xlib as the resource allocator
+ * for a display.
+ *
+ * Results:
+ * The return value is an X resource identifier that isn't currently
+ * in use.
+ *
+ * Side effects:
+ * The identifier is removed from the stack of free identifiers,
+ * if it was previously on the stack.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static XID
+AllocXId(display)
+ Display *display; /* Display for which to allocate. */
+{
+ TkDisplay *dispPtr;
+ TkIdStack *stackPtr;
+
+ /*
+ * Find Tk's information about the display.
+ */
+
+ dispPtr = TkGetDisplay(display);
+
+ /*
+ * If the topmost chunk on the stack is empty then free it. Then
+ * check for a free id on the stack and return it if it exists.
+ */
+
+ stackPtr = dispPtr->idStackPtr;
+ if (stackPtr != NULL) {
+ while (stackPtr->numUsed == 0) {
+ dispPtr->idStackPtr = stackPtr->nextPtr;
+ ckfree((char *) stackPtr);
+ stackPtr = dispPtr->idStackPtr;
+ if (stackPtr == NULL) {
+ goto defAlloc;
+ }
+ }
+ stackPtr->numUsed--;
+ return stackPtr->ids[stackPtr->numUsed];
+ }
+
+ /*
+ * No free ids in the stack: just get one from the default
+ * allocator.
+ */
+
+ defAlloc:
+ return (*dispPtr->defaultAllocProc)(display);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreeXId --
+ *
+ * This procedure is called to indicate that an X resource identifier
+ * is now free.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The identifier is added to the stack of free identifiers for its
+ * display, so that it can be re-used.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreeXId(display, xid)
+ Display *display; /* Display for which xid was
+ * allocated. */
+ XID xid; /* Identifier that is no longer
+ * in use. */
+{
+ TkDisplay *dispPtr;
+ TkIdStack *stackPtr;
+
+ /*
+ * Find Tk's information about the display.
+ */
+
+ dispPtr = TkGetDisplay(display);
+
+ /*
+ * Add a new chunk to the stack if the current chunk is full.
+ */
+
+ stackPtr = dispPtr->idStackPtr;
+ if ((stackPtr == NULL) || (stackPtr->numUsed >= IDS_PER_STACK)) {
+ stackPtr = (TkIdStack *) ckalloc(sizeof(TkIdStack));
+ stackPtr->numUsed = 0;
+ stackPtr->dispPtr = dispPtr;
+ stackPtr->nextPtr = dispPtr->idStackPtr;
+ dispPtr->idStackPtr = stackPtr;
+ }
+
+ /*
+ * Add the id to the current chunk.
+ */
+
+ stackPtr->ids[stackPtr->numUsed] = xid;
+ stackPtr->numUsed++;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkFreeWindowId --
+ *
+ * This procedure is invoked instead of TkFreeXId for window ids.
+ * See below for the reason why.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The id given by w will eventually be freed, so that it can be
+ * reused for other resources.
+ *
+ * Design:
+ * Freeing window ids is very tricky because there could still be
+ * events pending for a window in the event queue (or even in the
+ * server) at the time the window is destroyed. If the window
+ * id were to get reused immediately for another window, old
+ * events could "drop in" on the new window, causing unexpected
+ * behavior.
+ *
+ * Thus we have to wait to re-use a window id until we know that
+ * there are no events left for it. Right now this is done in
+ * two steps. First, we wait until we know that the server
+ * has seen the XDestroyWindow request, so we can be sure that
+ * it won't generate more events for the window and that any
+ * existing events are in our queue. Second, we make sure that
+ * there are no events whatsoever in our queue (this is conservative
+ * but safe).
+ *
+ * The first step is done by remembering the request id of the
+ * XDestroyWindow request and using LastKnownRequestProcessed to
+ * see what events the server has processed. If multiple windows
+ * get destroyed at about the same time, we just remember the
+ * most recent request number for any of them (again, conservative
+ * but safe).
+ *
+ * There are a few other complications as well. When Tk destroys a
+ * sub-tree of windows, it only issues a single XDestroyWindow call,
+ * at the very end for the root of the subtree. We can't free any of
+ * the window ids until the final XDestroyWindow call. To make sure
+ * that this happens, we have to keep track of deletions in progress,
+ * hence the need for the "destroyCount" field of the display.
+ *
+ * One final problem. Some servers, like Sun X11/News servers still
+ * seem to have problems with ids getting reused too quickly. I'm
+ * not completely sure why this is a problem, but delaying the
+ * recycling of ids appears to eliminate it. Therefore, we wait
+ * an additional few seconds, even after "the coast is clear"
+ * before reusing the ids.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkFreeWindowId(dispPtr, w)
+ TkDisplay *dispPtr; /* Display that w belongs to. */
+ Window w; /* X identifier for window on dispPtr. */
+{
+ TkIdStack *stackPtr;
+
+ /*
+ * Put the window id on a separate stack of window ids, rather
+ * than the main stack, so it won't get reused right away. Add
+ * a new chunk to the stack if the current chunk is full.
+ */
+
+ stackPtr = dispPtr->windowStackPtr;
+ if ((stackPtr == NULL) || (stackPtr->numUsed >= IDS_PER_STACK)) {
+ stackPtr = (TkIdStack *) ckalloc(sizeof(TkIdStack));
+ stackPtr->numUsed = 0;
+ stackPtr->dispPtr = dispPtr;
+ stackPtr->nextPtr = dispPtr->windowStackPtr;
+ dispPtr->windowStackPtr = stackPtr;
+ }
+
+ /*
+ * Add the id to the current chunk.
+ */
+
+ stackPtr->ids[stackPtr->numUsed] = w;
+ stackPtr->numUsed++;
+
+ /*
+ * Schedule a call to WindowIdCleanup if one isn't already
+ * scheduled.
+ */
+
+ if (!dispPtr->idCleanupScheduled) {
+ dispPtr->idCleanupScheduled = 1;
+ Tcl_CreateTimerHandler(100, WindowIdCleanup, (ClientData *) dispPtr);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WindowIdCleanup --
+ *
+ * See if we can now free up all the accumulated ids of
+ * deleted windows.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If it's safe to move the window ids back to the main free
+ * list, we schedule this to happen after a few mores seconds
+ * of delay. If it's not safe to move them yet, a timer handler
+ * gets invoked to try again later.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+WindowIdCleanup(clientData)
+ ClientData clientData; /* Pointer to TkDisplay for display */
+{
+ TkDisplay *dispPtr = (TkDisplay *) clientData;
+ int anyEvents, delta;
+ Tk_RestrictProc *oldProc;
+ ClientData oldData;
+
+ dispPtr->idCleanupScheduled = 0;
+
+ /*
+ * See if it's safe to recycle the window ids. It's safe if:
+ * (a) no deletions are in progress.
+ * (b) the server has seen all of the requests up to the last
+ * XDestroyWindow request.
+ * (c) there are no events in the event queue; the only way to
+ * test for this right now is to create a restrict proc that
+ * will filter the events, then call Tcl_DoOneEvent to see if
+ * the procedure gets invoked.
+ */
+
+ if (dispPtr->destroyCount > 0) {
+ goto tryAgain;
+ }
+ delta = LastKnownRequestProcessed(dispPtr->display)
+ - dispPtr->lastDestroyRequest;
+ if (delta < 0) {
+ XSync(dispPtr->display, False);
+ }
+ anyEvents = 0;
+ oldProc = Tk_RestrictEvents(CheckRestrictProc, (ClientData) &anyEvents,
+ &oldData);
+ Tcl_DoOneEvent(TCL_DONT_WAIT|TCL_WINDOW_EVENTS);
+ Tk_RestrictEvents(oldProc, oldData, &oldData);
+ if (anyEvents) {
+ goto tryAgain;
+ }
+
+ /*
+ * These ids look safe to recycle, but we still need to delay a bit
+ * more (see comments for TkFreeWindowId). Schedule the final freeing.
+ */
+
+ if (dispPtr->windowStackPtr != NULL) {
+ Tcl_CreateTimerHandler(5000, WindowIdCleanup2,
+ (ClientData) dispPtr->windowStackPtr);
+ dispPtr->windowStackPtr = NULL;
+ }
+ return;
+
+ /*
+ * It's still not safe to free up the ids. Try again a bit later.
+ */
+
+ tryAgain:
+ dispPtr->idCleanupScheduled = 1;
+ Tcl_CreateTimerHandler(500, WindowIdCleanup, (ClientData *) dispPtr);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * WindowIdCleanup2 --
+ *
+ * This procedure is the last one in the chain that recycles
+ * window ids. It takes all of the ids indicated by its
+ * argument and adds them back to the main id free list.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Window ids get added to the main free list for their display.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+WindowIdCleanup2(clientData)
+ ClientData clientData; /* Pointer to TkIdStack list. */
+{
+ TkIdStack *stackPtr = (TkIdStack *) clientData;
+ TkIdStack *lastPtr;
+
+ lastPtr = stackPtr;
+ while (lastPtr->nextPtr != NULL) {
+ lastPtr = lastPtr->nextPtr;
+ }
+ lastPtr->nextPtr = stackPtr->dispPtr->idStackPtr;
+ stackPtr->dispPtr->idStackPtr = stackPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CheckRestrictProc --
+ *
+ * This procedure is a restrict procedure, called by Tcl_DoOneEvent
+ * to filter X events. All it does is to set a flag to indicate
+ * that there are X events present.
+ *
+ * Results:
+ * Sets the integer pointed to by the argument, then returns
+ * TK_DEFER_EVENT.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tk_RestrictAction
+CheckRestrictProc(clientData, eventPtr)
+ ClientData clientData; /* Pointer to flag to set. */
+ XEvent *eventPtr; /* Event to filter; not used. */
+{
+ int *flag = (int *) clientData;
+ *flag = 1;
+ return TK_DEFER_EVENT;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_GetPixmap --
+ *
+ * Same as the XCreatePixmap procedure except that it manages
+ * resource identifiers better.
+ *
+ * Results:
+ * Returns a new pixmap.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Pixmap
+Tk_GetPixmap(display, d, width, height, depth)
+ Display *display; /* Display for new pixmap. */
+ Drawable d; /* Drawable where pixmap will be used. */
+ int width, height; /* Dimensions of pixmap. */
+ int depth; /* Bits per pixel for pixmap. */
+{
+ return XCreatePixmap(display, d, (unsigned) width, (unsigned) height,
+ (unsigned) depth);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tk_FreePixmap --
+ *
+ * Same as the XFreePixmap procedure except that it also marks
+ * the resource identifier as free.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The pixmap is freed in the X server and its resource identifier
+ * is saved for re-use.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_FreePixmap(display, pixmap)
+ Display *display; /* Display for which pixmap was allocated. */
+ Pixmap pixmap; /* Identifier for pixmap. */
+{
+ XFreePixmap(display, pixmap);
+ Tk_FreeXId(display, (XID) pixmap);
+}