summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tk.decls14
-rw-r--r--generic/tk.h170
-rw-r--r--generic/tkBind.c112
-rw-r--r--generic/tkCanvArc.c795
-rw-r--r--generic/tkCanvBmap.c259
-rw-r--r--generic/tkCanvImg.c290
-rw-r--r--generic/tkCanvLine.c1207
-rw-r--r--generic/tkCanvPoly.c1288
-rw-r--r--generic/tkCanvPs.c504
-rw-r--r--generic/tkCanvText.c287
-rw-r--r--generic/tkCanvUtil.c1099
-rw-r--r--generic/tkCanvWind.c331
-rw-r--r--generic/tkCanvas.c2787
-rw-r--r--generic/tkCanvas.h57
-rw-r--r--generic/tkDecls.h27
-rw-r--r--generic/tkEntry.c467
-rw-r--r--generic/tkEvent.c29
-rw-r--r--generic/tkFont.c12
-rw-r--r--generic/tkFrame.c195
-rw-r--r--generic/tkGet.c55
-rw-r--r--generic/tkImage.c491
-rw-r--r--generic/tkImgBmap.c107
-rw-r--r--generic/tkImgPhoto.c187
-rw-r--r--generic/tkInt.decls23
-rw-r--r--generic/tkInt.h91
-rw-r--r--generic/tkIntXlibDecls.h38
-rw-r--r--generic/tkMessage.c26
-rw-r--r--generic/tkOldConfig.c20
-rw-r--r--generic/tkRectOval.c566
-rw-r--r--generic/tkScrollbar.c35
-rw-r--r--generic/tkScrollbar.h4
-rw-r--r--generic/tkStubInit.c16
-rw-r--r--generic/tkTest.c3
-rw-r--r--generic/tkText.c188
-rw-r--r--generic/tkText.h38
-rw-r--r--generic/tkTextBTree.c128
-rw-r--r--generic/tkTextDisp.c225
-rw-r--r--generic/tkTextImage.c10
-rw-r--r--generic/tkTextMark.c6
-rw-r--r--generic/tkTextTag.c137
-rw-r--r--generic/tkTextWind.c10
-rw-r--r--generic/tkTrig.c10
-rw-r--r--generic/tkUtil.c483
-rw-r--r--generic/tkWindow.c13
44 files changed, 10933 insertions, 1907 deletions
diff --git a/generic/tk.decls b/generic/tk.decls
index 6f8eb13..db8314a 100644
--- a/generic/tk.decls
+++ b/generic/tk.decls
@@ -10,7 +10,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tk.decls,v 1.4 1999/04/28 18:18:06 redman Exp $
+# RCS: @(#) $Id: tk.decls,v 1.5 1999/12/14 06:52:24 hobbs Exp $
library tk
@@ -1040,6 +1040,18 @@ 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)
+#}
+
# Define the platform specific public Tk interface. These functions are
# only available on the designated platform.
diff --git a/generic/tk.h b/generic/tk.h
index 552611f..1217e26 100644
--- a/generic/tk.h
+++ b/generic/tk.h
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tk.h,v 1.33 1999/11/23 23:52:13 hobbs Exp $
+ * RCS: @(#) $Id: tk.h,v 1.34 1999/12/14 06:52:25 hobbs Exp $
*/
#ifndef _TK
@@ -110,6 +110,7 @@ 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;
@@ -348,6 +349,7 @@ typedef enum {
*/
#define TK_CONFIG_ARGV_ONLY 1
+#define TK_CONFIG_OBJS 0x80
/*
* Possible flag values for Tk_ConfigSpec structures. Any bits at
@@ -771,6 +773,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
@@ -810,9 +827,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 */
/*
*------------------------------------------------------------------
@@ -825,11 +842,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));
@@ -839,6 +870,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,
@@ -890,7 +932,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,
@@ -971,6 +1013,80 @@ 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;
+
+/*
+ * Some functions handy for Dashing and Outlines (in tkCanvUtil.c).
+ */
+
+EXTERN int Tk_GetDash _ANSI_ARGS_((Tcl_Interp *interp,
+ CONST char *value, Tk_Dash *dash));
+EXTERN void Tk_CreateOutline _ANSI_ARGS_((Tk_Outline *outline));
+EXTERN void Tk_DeleteOutline _ANSI_ARGS_((Display *display,
+ Tk_Outline *outline));
+EXTERN int Tk_ConfigOutlineGC _ANSI_ARGS_((XGCValues *gcValues,
+ Tk_Canvas canvas ,Tk_Item *item,
+ Tk_Outline *outline));
+EXTERN int Tk_ChangeOutlineGC _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *item, Tk_Outline *outline));
+EXTERN int Tk_ResetOutlineGC _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *item, Tk_Outline *outline));
+EXTERN int Tk_CanvasPsOutline _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *item, Tk_Outline *outline));
+EXTERN void Tk_SetTSOrigin _ANSI_ARGS_((Tk_Window tkwin, GC gc, int x,
+ int y));
+
+
+/*
*--------------------------------------------------------------
*
* Procedure prototypes and structures used for managing images:
@@ -999,6 +1115,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
@@ -1028,6 +1147,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
@@ -1240,6 +1362,44 @@ typedef int (Tk_SelectionProc) _ANSI_ARGS_((ClientData clientData,
/*
*--------------------------------------------------------------
*
+ * Exported procedures introduced by dash-patch.
+ *
+ *--------------------------------------------------------------
+ */
+
+EXTERN int Tk_CanvasGetCoordFromObj _ANSI_ARGS_((
+ Tcl_Interp *interp, Tk_Canvas canvas, Tcl_Obj *obj,
+ double *doublePtr));
+EXTERN void Tk_CanvasSetOffset _ANSI_ARGS_((
+ Tk_Canvas canvas, GC gc, Tk_TSOffset *offset));
+EXTERN void Tk_CreatePhotoOption _ANSI_ARGS_((Tcl_Interp *interp,
+ CONST char *name, Tcl_ObjCmdProc *proc));
+EXTERN void Tk_DitherPhoto _ANSI_ARGS_((Tk_PhotoHandle handle,
+ int x, int y, int width, int height));
+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));
+EXTERN int Tk_PostscriptColor _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, XColor *colorPtr));
+EXTERN int Tk_PostscriptFont _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, Tk_Font font));
+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));
+EXTERN void Tk_PostscriptPath _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_PostscriptInfo psInfo, double *coordPtr,
+ int numPoints));
+EXTERN int Tk_PostscriptStipple _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Window tkwin, Tk_PostscriptInfo psInfo,
+ Pixmap bitmap));
+EXTERN double Tk_PostscriptY _ANSI_ARGS_((double y,
+ Tk_PostscriptInfo psInfo));
+
+/*
+ *--------------------------------------------------------------
+ *
* Exported procedures and variables.
*
*--------------------------------------------------------------
diff --git a/generic/tkBind.c b/generic/tkBind.c
index 192ea69..031ded7 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkBind.c,v 1.8 1999/04/21 21:53:23 rjohnson Exp $
+ * RCS: @(#) $Id: tkBind.c,v 1.9 1999/12/14 06:52:25 hobbs Exp $
*/
#include "tkPort.h"
@@ -403,10 +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
+#define QUADRUPLE 4
+#define MULT_CLICKS 7
/*
* The following special modifier mask bits are defined, to indicate
@@ -448,6 +453,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}
};
@@ -685,6 +691,7 @@ static int ParseEventDescription _ANSI_ARGS_((Tcl_Interp *interp,
unsigned long *eventMaskPtr));
static void SetKeycodeAndState _ANSI_ARGS_((Tk_Window tkwin,
KeySym keySym, XEvent *eventPtr));
+static void DoWarp _ANSI_ARGS_((ClientData clientData));
/*
* The following define is used as a short circuit for the callback
@@ -3170,8 +3177,8 @@ HandleEventGenerate(interp, mainWin, objc, objv)
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
XEvent event;
- char *name, *p;
- int count, flags, synch, i, number;
+ char *name, *p, *windowName;
+ int count, flags, synch, i, number, warp;
Tcl_QueuePosition pos;
Pattern pat;
Tk_Window tkwin, tkwin2;
@@ -3184,8 +3191,8 @@ HandleEventGenerate(interp, mainWin, objc, objv)
"-keycode", "-keysym", "-mode", "-override",
"-place", "-root", "-rootx", "-rooty",
"-sendevent", "-serial", "-state", "-subwindow",
- "-time", "-width", "-window", "-x",
- "-y", NULL
+ "-time", "-warp", "-width", "-window",
+ "-x", "-y", NULL
};
enum field {
EVENT_WHEN, EVENT_ABOVE, EVENT_BORDER, EVENT_BUTTON,
@@ -3194,11 +3201,14 @@ HandleEventGenerate(interp, mainWin, objc, objv)
EVENT_KEYCODE, EVENT_KEYSYM, EVENT_MODE, EVENT_OVERRIDE,
EVENT_PLACE, EVENT_ROOT, EVENT_ROOTX, EVENT_ROOTY,
EVENT_SEND, EVENT_SERIAL, EVENT_STATE, EVENT_SUBWINDOW,
- EVENT_TIME, EVENT_WIDTH, EVENT_WINDOW, EVENT_X,
- EVENT_Y
+ EVENT_TIME, EVENT_WARP, EVENT_WIDTH, EVENT_WINDOW,
+ EVENT_X, EVENT_Y
};
- if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) {
+ windowName = Tcl_GetStringFromObj(objv[0], NULL);
+ if (!windowName[0]) {
+ tkwin = mainWin;
+ } else if (NameToWindow(interp, mainWin, objv[0], &tkwin) != TCL_OK) {
return TCL_ERROR;
}
@@ -3236,7 +3246,11 @@ HandleEventGenerate(interp, mainWin, objc, objv)
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];
@@ -3260,6 +3274,7 @@ HandleEventGenerate(interp, mainWin, objc, objv)
*/
synch = 1;
+ warp = 0;
pos = TCL_QUEUE_TAIL;
for (i = 2; i < objc; i += 2) {
Tcl_Obj *optionPtr, *valuePtr;
@@ -3287,6 +3302,15 @@ HandleEventGenerate(interp, mainWin, objc, objv)
}
switch ((enum field) index) {
+ case EVENT_WARP: {
+ if (Tcl_GetBooleanFromObj(interp, valuePtr, &warp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!(flags & (KEY_BUTTON_MOTION_VIRTUAL))) {
+ goto badopt;
+ }
+ break;
+ }
case EVENT_WHEN: {
pos = (Tcl_QueuePosition) TkFindStateNumObj(interp, optionPtr,
queuePosition, valuePtr);
@@ -3667,6 +3691,17 @@ HandleEventGenerate(interp, mainWin, objc, objv)
} else {
Tk_QueueWindowEvent(&event, pos);
}
+ if (warp != 0) {
+ 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;
@@ -3747,6 +3782,33 @@ SetKeycodeAndState(tkwin, keySym, eventPtr)
/*
*-------------------------------------------------------------------------
*
+ * 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;
+}
+
+/*
+ *-------------------------------------------------------------------------
+ *
* GetVirtualEventUid --
*
* Determine if the given string is in the proper format for a
@@ -3886,19 +3948,14 @@ FindSequence(interp, patternTablePtr, object, eventString, create,
}
/*
- * 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++;
- }
}
}
@@ -4117,12 +4174,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++;
@@ -4310,8 +4365,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);
@@ -4324,7 +4379,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);
}
diff --git a/generic/tkCanvArc.c b/generic/tkCanvArc.c
index 1848c88..1d0934e 100644
--- a/generic/tkCanvArc.c
+++ b/generic/tkCanvArc.c
@@ -9,20 +9,25 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvArc.c,v 1.6 1999/04/21 21:53:24 rjohnson Exp $
+ * RCS: @(#) $Id: tkCanvArc.c,v 1.7 1999/12/14 06:52:25 hobbs Exp $
*/
#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,7 +256,7 @@ 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
@@ -197,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?\"",
@@ -214,38 +321,36 @@ CreateArc(interp, canvas, itemPtr, argc, argv)
* 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 = Tk_GetUid("pieslice");
- 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;
}
/*
@@ -274,28 +379,42 @@ 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;
}
@@ -335,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;
@@ -344,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) {
@@ -364,50 +517,60 @@ ConfigureArc(interp, canvas, itemPtr, argc, argv, flags)
i = (int) (arcPtr->extent/360.0);
arcPtr->extent -= i*360.0;
- if ((arcPtr->style != Tk_GetUid("arc"))
- && (arcPtr->style != Tk_GetUid("chord"))
- && (arcPtr->style != Tk_GetUid("pieslice"))) {
- Tcl_AppendResult(interp, "bad -style option \"",
- arcPtr->style, "\": must be arc, chord, or pieslice",
- (char *) NULL);
- arcPtr->style = Tk_GetUid("pieslice");
- return TCL_ERROR;
- }
-
- if (arcPtr->width < 0) {
- arcPtr->width = 1;
- }
- if (arcPtr->outlineColor == NULL) {
- newGC = None;
- } else {
- gcValues.foreground = arcPtr->outlineColor->pixel;
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(arcPtr->outline));
+ if (mask) {
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;
- }
+ mask |= GCCapStyle;
newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = None;
+ }
+ if (arcPtr->outline.gc != None) {
+ Tk_FreeGC(Tk_Display(tkwin), arcPtr->outline.gc);
+ }
+ 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 == Tk_GetUid("arc"))) {
+ 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 == Tk_GetUid("chord")) {
+ 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;
}
@@ -418,6 +581,23 @@ ConfigureArc(interp, canvas, itemPtr, argc, argv, flags)
}
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;
}
@@ -448,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);
@@ -497,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.
@@ -515,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
@@ -529,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 == Tk_GetUid("pieslice")) {
+ if (arcPtr->style == PIESLICE_STYLE) {
TkIncludePoint((Tk_Item *) arcPtr, center);
}
@@ -575,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;
@@ -616,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,
@@ -643,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 == Tk_GetUid("chord")) {
- XDrawLine(display, drawable, arcPtr->outlineGC,
+ if (arcPtr->style == CHORD_STYLE) {
+ XDrawLine(display, drawable, arcPtr->outline.gc,
x1, y1, x2, y2);
- } else if (arcPtr->style == Tk_GetUid("pieslice")) {
+ } 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 == Tk_GetUid("chord")) {
+ if (arcPtr->style == CHORD_STYLE) {
TkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
- display, drawable, arcPtr->outlineGC, None);
- } else if (arcPtr->style == Tk_GetUid("pieslice")) {
+ 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));
}
}
@@ -739,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.
@@ -775,9 +1054,9 @@ ArcToPoint(canvas, itemPtr, pointPtr)
* we're dealing with.
*/
- if (arcPtr->style == Tk_GetUid("arc")) {
+ 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],
@@ -790,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 == Tk_GetUid("pieslice")) {
+ if (arcPtr->style == PIESLICE_STYLE) {
if (width > 1.0) {
dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
pointPtr);
@@ -906,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 ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
+ 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->outline.gc == None)) {
filled = 1;
} else {
filled = 0;
}
- if (arcPtr->outlineGC == None) {
+ if (arcPtr->outline.gc == None) {
width = 0.0;
- } else {
- width = arcPtr->width;
}
/*
@@ -956,7 +1246,7 @@ ArcToArea(canvas, itemPtr, rectPtr)
numPoints = 2;
pointPtr += 4;
- if ((arcPtr->style == Tk_GetUid("pieslice")) && (arcPtr->extent < 180.0)) {
+ if ((arcPtr->style == PIESLICE_STYLE) && (arcPtr->extent < 180.0)) {
pointPtr[0] = 0.0;
pointPtr[1] = 0.0;
numPoints++;
@@ -1030,7 +1320,7 @@ ArcToArea(canvas, itemPtr, rectPtr)
* polygon(s) forming the sides of a chord or pie-slice.
*/
- if (arcPtr->style == Tk_GetUid("pieslice")) {
+ if (arcPtr->style == PIESLICE_STYLE) {
if (width >= 1.0) {
if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
rectPtr) != -1) {
@@ -1046,7 +1336,7 @@ ArcToArea(canvas, itemPtr, rectPtr)
return 0;
}
}
- } else if (arcPtr->style == Tk_GetUid("chord")) {
+ } else if (arcPtr->style == CHORD_STYLE) {
if (width >= 1.0) {
if (TkPolygonToArea(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
rectPtr) != -1) {
@@ -1198,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
@@ -1218,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
@@ -1274,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 {
@@ -1297,11 +1605,11 @@ ComputeArcOutline(arcPtr)
* center point. The second point is the corner point.
*/
- if (arcPtr->style == Tk_GetUid("chord")) {
+ 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]
@@ -1312,7 +1620,7 @@ ComputeArcOutline(arcPtr)
- arcPtr->center1[0];
outlinePtr[9] = arcPtr->center2[1] + outlinePtr[11]
- arcPtr->center1[1];
- } else if (arcPtr->style == Tk_GetUid("pieslice")) {
+ } 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,
@@ -1328,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];
@@ -1357,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))) {
@@ -1588,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]);
@@ -1598,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.
@@ -1608,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 == Tk_GetUid("chord")) {
+ if (arcPtr->style == CHORD_STYLE) {
sprintf(buffer, "0 0 1 %.15g %.15g arc closepath\nsetmatrix\n",
ang1, ang2);
} else {
@@ -1617,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 {
@@ -1638,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 != Tk_GetUid("arc")) {
+ if (arcPtr->style != ARC_STYLE) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
- if (arcPtr->style == Tk_GetUid("chord")) {
+ 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 {
@@ -1686,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 {
@@ -1704,3 +2042,106 @@ 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/generic/tkCanvBmap.c b/generic/tkCanvBmap.c
index dedc4e7..bcef7f3 100644
--- a/generic/tkCanvBmap.c
+++ b/generic/tkCanvBmap.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvBmap.c,v 1.3 1999/04/16 01:51:11 stanton Exp $
+ * RCS: @(#) $Id: tkCanvBmap.c,v 1.4 1999/12/14 06:52:25 hobbs Exp $
*/
#include <stdio.h>
@@ -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));
+ 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,
@@ -104,7 +133,7 @@ Tk_ItemType tkBitmapType = {
BitmapCoords, /* coordProc */
DeleteBitmap, /* deleteProc */
DisplayBitmap, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
BitmapToPoint, /* pointProc */
BitmapToArea, /* areaProc */
BitmapToPostscript, /* postscriptProc */
@@ -115,7 +144,7 @@ Tk_ItemType tkBitmapType = {
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -145,11 +174,24 @@ CreateBitmap(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. */
{
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 @@ CreateBitmap(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;
}
/*
@@ -210,20 +257,34 @@ 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);
@@ -261,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;
@@ -269,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;
}
@@ -281,16 +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_GetGC(tkwin, mask, &gcValues);
+ if (bitmap == None) {
+ newGC = None;
+ } else {
+ newGC = Tk_GetGC(tkwin, mask, &gcValues);
+ }
if (bmapPtr->gc != None) {
Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
}
@@ -330,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);
}
@@ -370,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;
@@ -460,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,
@@ -467,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;
@@ -503,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);
}
}
diff --git a/generic/tkCanvImg.c b/generic/tkCanvImg.c
index cf1106d..144b755 100644
--- a/generic/tkCanvImg.c
+++ b/generic/tkCanvImg.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvImg.c,v 1.3 1999/04/16 01:51:11 stanton Exp $
+ * RCS: @(#) $Id: tkCanvImg.c,v 1.4 1999/12/14 06:52:25 hobbs Exp $
*/
#include <stdio.h>
@@ -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 */
};
/*
@@ -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;
}
/*
@@ -206,20 +246,34 @@ 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);
@@ -257,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;
@@ -265,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;
}
@@ -277,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);
@@ -290,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;
}
@@ -323,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);
+ }
}
/*
@@ -357,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;
@@ -371,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;
@@ -445,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(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
- if (imgPtr->image == NULL) {
+ 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;
}
@@ -456,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);
}
@@ -565,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.
diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c
index 131b73d..328d184 100644
--- a/generic/tkCanvLine.c
+++ b/generic/tkCanvLine.c
@@ -10,23 +10,29 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvLine.c,v 1.4 1999/04/16 01:51:11 stanton Exp $
+ * RCS: @(#) $Id: tkCanvLine.c,v 1.5 1999/12/14 06:52:26 hobbs Exp $
*/
#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
@@ -37,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
@@ -60,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;
@@ -82,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));
@@ -120,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}
};
@@ -166,18 +248,18 @@ 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 */
};
/*
@@ -215,42 +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;
- linePtr->arrow = Tk_GetUid("none");
+ 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;
/*
@@ -259,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) {
@@ -304,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) {
@@ -328,15 +399,19 @@ 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_AppendResult(interp,
- "too few coordinates for line: must have at least 4",
- (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 line",
(char *) NULL);
@@ -344,19 +419,21 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
} 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
@@ -371,7 +448,7 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
ckfree((char *) linePtr->lastArrowPtr);
linePtr->lastArrowPtr = NULL;
}
- if (linePtr->arrow != Tk_GetUid("none")) {
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
ComputeLineBbox(canvas, linePtr);
@@ -404,7 +481,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;
@@ -412,14 +489,11 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
GC newGC, arrowGC;
unsigned long mask;
Tk_Window tkwin;
- Tk_Uid noneUid = Tk_GetUid("none");
- Tk_Uid bothUid = Tk_GetUid("both");
- Tk_Uid firstUid = Tk_GetUid("first");
- Tk_Uid lastUid = Tk_GetUid("last");
+ 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;
}
@@ -428,36 +502,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;
}
+ gcValues.join_style = linePtr->joinStyle;
+ mask |= GCJoinStyle;
newGC = Tk_GetGC(tkwin, mask, &gcValues);
gcValues.line_width = 0;
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;
/*
@@ -470,21 +550,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);
@@ -493,15 +578,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);
}
@@ -540,18 +617,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);
}
@@ -588,7 +657,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;
@@ -608,14 +703,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.
@@ -630,7 +777,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);
}
@@ -642,14 +789,14 @@ ComputeLineBbox(canvas, linePtr)
* Add in the sizes of arrowheads, if any.
*/
- if (linePtr->arrow != Tk_GetUid("none")) {
- if (linePtr->arrow != Tk_GetUid("last")) {
+ 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 != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
@@ -700,13 +847,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;
@@ -715,7 +883,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;
}
@@ -727,7 +897,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 {
@@ -745,12 +915,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);
}
@@ -761,14 +940,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);
}
}
@@ -776,6 +954,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
@@ -800,6 +1297,7 @@ 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];
@@ -817,15 +1315,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 {
@@ -833,11 +1348,19 @@ LineToPoint(canvas, itemPtr, pointPtr)
linePoints = linePtr->coordPtr;
}
- width = (double) linePtr->width;
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
@@ -950,8 +1473,8 @@ LineToPoint(canvas, itemPtr, pointPtr)
* If there are arrowheads, check the distance to the arrowheads.
*/
- if (linePtr->arrow != Tk_GetUid("none")) {
- if (linePtr->arrow != Tk_GetUid("last")) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,
pointPtr);
if (dist <= 0.0) {
@@ -961,7 +1484,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
bestDist = dist;
}
}
- if (linePtr->arrow != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,
pointPtr);
if (dist <= 0.0) {
@@ -1010,8 +1533,36 @@ LineToArea(canvas, itemPtr, rectPtr)
LineItem *linePtr = (LineItem *) itemPtr;
double staticSpace[2*MAX_STATIC_POINTS];
double *linePoints;
- double width;
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
@@ -1019,14 +1570,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 {
@@ -1038,8 +1591,7 @@ LineToArea(canvas, itemPtr, rectPtr)
* Check the segments of the line.
*/
- width = (double) linePtr->width;
- if (width < 1.0) {
+ if (width < 1.0) {
width = 1.0;
}
@@ -1054,15 +1606,15 @@ LineToArea(canvas, itemPtr, rectPtr)
* Check arrowheads, if any.
*/
- if (linePtr->arrow != Tk_GetUid("none")) {
- if (linePtr->arrow != Tk_GetUid("last")) {
+ 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 != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,
rectPtr) != result) {
result = 0;
@@ -1135,7 +1687,7 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)
coordPtr[0] = originX + scaleX*(*coordPtr - originX);
coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
}
- if (linePtr->arrow != Tk_GetUid("none")) {
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
ComputeLineBbox(canvas, linePtr);
@@ -1144,6 +1696,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.
@@ -1217,7 +1859,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
@@ -1232,7 +1874,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,
@@ -1297,6 +1939,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";
+ }
+}
+
/*
*--------------------------------------------------------------
*
@@ -1336,6 +2089,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
@@ -1346,7 +2120,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
@@ -1354,9 +2128,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 != Tk_GetUid("last")) {
+ if (linePtr->arrow != ARROWS_LAST) {
poly = linePtr->firstArrowPtr;
if (poly == NULL) {
poly = (double *) ckalloc((unsigned)
@@ -1401,7 +2175,7 @@ ConfigureArrows(canvas, linePtr)
* Similar arrowhead calculation for the last point of the line.
*/
- if (linePtr->arrow != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);
poly = linePtr->lastArrowPtr;
if (poly == NULL) {
@@ -1475,21 +2249,75 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
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
@@ -1504,13 +2332,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);
@@ -1524,8 +2354,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";
@@ -1540,17 +2368,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);
}
/*
@@ -1558,7 +2379,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);
}
@@ -1568,7 +2389,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,
@@ -1610,10 +2431,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;
}
diff --git a/generic/tkCanvPoly.c b/generic/tkCanvPoly.c
index ad5eb80..f64ccd6 100644
--- a/generic/tkCanvPoly.c
+++ b/generic/tkCanvPoly.c
@@ -9,12 +9,13 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvPoly.c,v 1.3 1999/04/16 01:51:11 stanton Exp $
+ * RCS: @(#) $Id: tkCanvPoly.c,v 1.4 1999/12/14 06:52:26 hobbs Exp $
*/
#include <stdio.h>
#include "tkInt.h"
#include "tkPort.h"
+#include "tkCanvas.h"
/*
* The structure below defines the record for each polygon item.
@@ -23,7 +24,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 +33,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 +53,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 +165,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 +210,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 */
};
/*
@@ -167,34 +260,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 +295,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;
}
@@ -250,11 +342,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 +353,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 +380,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 +389,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];
@@ -342,7 +438,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 +446,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,31 +461,66 @@ 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;
+ 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;
}
@@ -437,20 +571,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);
@@ -483,27 +624,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;
}
/*
@@ -567,7 +840,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);
}
@@ -609,24 +882,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) {
+ 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];
@@ -637,29 +966,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) {
XSetTSOrigin(display, polyPtr->fillGC, 0, 0);
}
}
@@ -667,6 +999,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
@@ -692,41 +1221,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;
}
/*
@@ -759,75 +1416,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 {
- result = 0;
+ 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 {
+ 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;
}
/*
@@ -873,6 +1634,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
@@ -941,29 +1797,103 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass)
* final Postscript is being created. */
{
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 {
@@ -975,25 +1905,29 @@ PolygonToPostscript(interp, canvas, itemPtr, prepass)
* Now draw the outline, if there is one.
*/
- if (polyPtr->outlineColor != NULL) {
- char string[32 + TCL_INTEGER_SPACE];
+ if (color != NULL) {
- if (!polyPtr->smooth) {
+ 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/generic/tkCanvPs.c b/generic/tkCanvPs.c
index 4c99b15..c234320 100644
--- a/generic/tkCanvPs.c
+++ b/generic/tkCanvPs.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvPs.c,v 1.5 1999/04/16 01:51:11 stanton Exp $
+ * RCS: @(#) $Id: tkCanvPs.c,v 1.6 1999/12/14 06:52:26 hobbs Exp $
*/
#include "tkInt.h"
@@ -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,
@@ -124,7 +128,7 @@ static CONST char * CONST prolog[]= {
\n\
% This is a standard prolog for Postscript generated by Tk's canvas\n\
% widget.\n\
-% RCS: @(#) $Id: tkCanvPs.c,v 1.5 1999/04/16 01:51:11 stanton Exp $\n\
+% RCS: @(#) $Id: tkCanvPs.c,v 1.6 1999/12/14 06:52:26 hobbs Exp $\n\
\n\
% The definitions below just define all of the variables used in\n\
% any of the procedures here. This is needed for obscure reasons\n\
@@ -461,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
@@ -487,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;
@@ -510,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) {
@@ -519,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:
@@ -601,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;
@@ -615,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;
@@ -626,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;
@@ -652,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;
@@ -687,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.
@@ -709,21 +716,22 @@ 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);
#ifdef HAVE_PW_GECOS
if (!Tcl_IsSafe(interp)) {
struct passwd *pwPtr = getpwuid(getuid()); /* INTL: Native. */
- Tcl_AppendResult(canvasPtr->interp, "%%For: ",
+ Tcl_AppendResult(interp, "%%For: ",
(pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n",
(char *) NULL);
endpwent();
}
#endif /* HAVE_PW_GECOS */
- Tcl_AppendResult(canvasPtr->interp, "%%Title: Window ",
- Tk_PathName(canvasPtr->tkwin), "\n", (char *) NULL);
+ Tcl_AppendResult(interp, "%%Title: Window ",
+ Tk_PathName(tkwin), "\n", (char *) NULL);
time(&now);
- Tcl_AppendResult(canvasPtr->interp, "%%CreationDate: ",
+ Tcl_AppendResult(interp, "%%CreationDate: ",
ctime(&now), (char *) NULL); /* INTL: Native. */
if (!psInfo.rotate) {
sprintf(string, "%d %d %d %d",
@@ -741,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
@@ -765,7 +773,7 @@ TkCanvPostscriptCmd(canvasPtr, interp, argc, argv)
}
if (psInfo.chan != NULL) {
- Tcl_Write(psInfo.chan, Tcl_GetStringResult(canvasPtr->interp), -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -776,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);
/*
*-----------------------------------------------------------
@@ -793,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, Tcl_GetStringResult(canvasPtr->interp), -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -833,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[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, Tcl_GetStringResult(canvasPtr->interp), -1);
- Tcl_ResetResult(canvasPtr->interp);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
+ Tcl_ResetResult(interp);
}
}
@@ -858,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, Tcl_GetStringResult(canvasPtr->interp), -1);
+ Tcl_Write(psInfo.chan, Tcl_GetStringResult(interp), -1);
Tcl_ResetResult(canvasPtr->interp);
}
@@ -895,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
@@ -928,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];
@@ -989,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
@@ -1010,15 +1026,13 @@ 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[TCL_INTEGER_SPACE];
Tcl_DString ds;
@@ -1083,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
@@ -1103,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;
@@ -1135,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;
@@ -1180,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
@@ -1202,14 +1216,14 @@ 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[TCL_INTEGER_SPACE * 2];
Window dummyRoot;
@@ -1228,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;
}
@@ -1244,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:
@@ -1260,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;
}
@@ -1273,7 +1286,7 @@ Tk_CanvasPsY(canvas, y)
/*
*--------------------------------------------------------------
*
- * Tk_CanvasPsPath --
+ * Tk_PostscriptPath --
*
* Given an array of points for a path, generate Postscript
* commands to create the path.
@@ -1288,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);
}
}
@@ -1385,3 +1397,287 @@ 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;
+}
diff --git a/generic/tkCanvText.c b/generic/tkCanvText.c
index b9b3e2d..4e826e9 100644
--- a/generic/tkCanvText.c
+++ b/generic/tkCanvText.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvText.c,v 1.6 1999/04/21 21:53:24 rjohnson Exp $
+ * RCS: @(#) $Id: tkCanvText.c,v 1.7 1999/12/14 06:52:26 hobbs Exp $
*/
#include <stdio.h>
@@ -44,10 +44,15 @@ typedef struct TextItem {
*/
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. */
@@ -78,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,
@@ -93,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,
@@ -113,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,
@@ -127,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));
@@ -135,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,
@@ -163,18 +191,18 @@ Tk_ItemType tkTextType = {
TextCoords, /* coordProc */
DeleteText, /* deleteProc */
DisplayCanvText, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
TextToPoint, /* pointProc */
TextToArea, /* areaProc */
TextToPostscript, /* postscriptProc */
ScaleText, /* scaleProc */
TranslateText, /* translateProc */
- GetTextIndex, /* indexProc */
+ (Tk_ItemIndexProc *) GetTextIndex,/* indexProc */
SetTextCursor, /* icursorProc */
GetSelText, /* selectionProc */
TextInsert, /* insertProc */
TextDeleteChars, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -204,11 +232,24 @@ CreateText(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. */
{
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);
@@ -225,10 +266,17 @@ 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;
@@ -245,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;
}
/*
@@ -283,19 +330,33 @@ TextCoords(interp, canvas, itemPtr, argc, argv)
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_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);
@@ -334,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;
@@ -344,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;
}
@@ -356,19 +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_GetGC(tkwin, mask, &gcValues);
gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;
- newSelGC = Tk_GetGC(tkwin, mask, &gcValues);
+ newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues);
}
if (textPtr->gc != None) {
Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);
@@ -454,10 +558,22 @@ DeleteText(canvas, itemPtr, display)
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);
}
@@ -502,12 +618,21 @@ ComputeTextBbox(canvas, textPtr)
{
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.
@@ -604,10 +729,26 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
Tk_CanvasTextInfo *textInfoPtr;
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,8 +759,8 @@ 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);
}
selFirstChar = -1;
@@ -735,7 +876,7 @@ DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
selLastChar + 1);
}
- if (textPtr->stipple != None) {
+ if (stipple != None) {
XSetTSOrigin(display, textPtr->gc, 0, 0);
}
}
@@ -771,6 +912,8 @@ TextInsert(canvas, itemPtr, index, string)
char *new, *text;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ string = Tcl_GetStringFromObj((Tcl_Obj *) string, &byteCount);
+
text = textPtr->text;
if (index < 0) {
@@ -942,11 +1085,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;
}
/*
@@ -978,6 +1132,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,
@@ -1074,12 +1233,12 @@ 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 character
* index. */
@@ -1089,6 +1248,7 @@ GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
int c;
TkCanvas *canvasPtr = (TkCanvas *) canvas;
Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
+ char *string = Tcl_GetStringFromObj(obj, (int *) &length);
c = string[0];
length = strlen(string);
@@ -1131,7 +1291,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) {
@@ -1280,9 +1440,32 @@ TextToPostscript(interp, canvas, itemPtr, prepass)
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) {
@@ -1291,13 +1474,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);
}
@@ -1328,7 +1511,7 @@ 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/generic/tkCanvUtil.c b/generic/tkCanvUtil.c
index 7d203ec..3c79861 100644
--- a/generic/tkCanvUtil.c
+++ b/generic/tkCanvUtil.c
@@ -10,10 +10,10 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvUtil.c,v 1.3 1999/04/16 01:51:12 stanton Exp $
+ * RCS: @(#) $Id: tkCanvUtil.c,v 1.4 1999/12/14 06:52:26 hobbs Exp $
*/
-#include "tk.h"
+#include "tkInt.h"
#include "tkCanvas.h"
#include "tkPort.h"
@@ -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,1016 @@ 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 *p;
+ char *s = string;
+ char *l = 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) {
+ s = (char *)ckalloc(1 + 4*(unsigned int)dash->number);
+ } else if (dash->number<-5) {
+ s = (char *)ckalloc(1 - 8*(unsigned int)dash->number);
+ l = (char *)ckalloc(1 - 2*(unsigned int)dash->number);
+ }
+ p = (char *) ((ABS(dash->number) > sizeof(char *)) ) ?
+ dash->pattern.pt : dash->pattern.array;
+ if (dash->number > 0) {
+ sprintf(s,"[%d",*p++ & 0xff);
+ i=dash->number-1;
+ while(i--) {
+ sprintf(s+strlen(s)," %d",*p++ & 0xff);
+ }
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ if (dash->number&1) {
+ Tcl_AppendResult(interp," ",s+1,(char *)NULL);
+ }
+ sprintf(s,"] %d setdash\n",outline->offset);
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ } else if (dash->number < 0) {
+ if ((i = DashConvert(l ,p, -dash->number, width)) != 0) {
+ sprintf(s,"[%d",*l++ & 0xff);
+ while(--i) {
+ sprintf(s+strlen(s)," %d",*l++ & 0xff);
+ }
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ sprintf(s,"] %d setdash\n",outline->offset);
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ } else {
+ Tcl_AppendResult(interp,"[] 0 setdash\n",(char *)NULL);
+ }
+ } else {
+ Tcl_AppendResult(interp,"[] 0 setdash\n",(char *)NULL);
+ }
+ if (s!=string) {
+ ckfree(s);
+ }
+ if (l!=pattern) {
+ ckfree(l);
+ }
+ 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/generic/tkCanvWind.c b/generic/tkCanvWind.c
index 4dd8ee3..fab0015 100644
--- a/generic/tkCanvWind.c
+++ b/generic/tkCanvWind.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvWind.c,v 1.3 1999/04/16 01:51:12 stanton Exp $
+ * RCS: @(#) $Id: tkCanvWind.c,v 1.4 1999/12/14 06:52:26 hobbs Exp $
*/
#include <stdio.h>
@@ -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 */
};
@@ -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;
}
/*
@@ -230,19 +258,33 @@ 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;
}
@@ -281,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;
@@ -290,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;
}
@@ -417,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
@@ -542,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;
@@ -593,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
@@ -622,7 +675,7 @@ WinItemToPoint(canvas, itemPtr, pointPtr)
y2 = winItemPtr->header.y2;
/*
- * Point is outside rectangle.
+ * Point is outside window.
*/
if (pointPtr[0] < x1) {
@@ -692,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)
@@ -712,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. */
{
@@ -736,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.
*
*--------------------------------------------------------------
*/
diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c
index 8183c2b..0446d0c 100644
--- a/generic/tkCanvas.c
+++ b/generic/tkCanvas.c
@@ -12,9 +12,11 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvas.c,v 1.8 1999/09/02 17:02:27 hobbs Exp $
+ * RCS: @(#) $Id: tkCanvas.c,v 1.9 1999/12/14 06:52:26 hobbs Exp $
*/
+/* #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,6 +211,23 @@ static Tk_ConfigSpec configSpecs[] = {
static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't
* been done yet. */
+#ifndef USE_OLD_TAG_SEARCH
+/*
+ * Uids for operands in compiled advanced tag search expressions
+ * Initialization is done by InitCanvas()
+ */
+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 */
+
/*
* Standard item types provided by Tk:
*/
@@ -180,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, char **argv,
- char *newTag, char *cmdName, char *option));
+ TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
+ Tcl_Obj *newTagObj, int first));
+#else /* USE_OLD_TAG_SEARCH */
+static int FindItems _ANSI_ARGS_((Tcl_Interp *interp,
+ TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
+ 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,
+ Tk_Uid uid));
+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
@@ -224,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
@@ -240,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;
@@ -256,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;
}
@@ -276,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;
@@ -340,7 +456,14 @@ 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");
@@ -390,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;
@@ -466,15 +632,15 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
sprintf(buf, "%d %d %d %d", x1, y1, x2, y2);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
- } else if ((c == 'b') && (strncmp(argv[1], "bind", length) == 0)
- && (length >= 2)) {
+ 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;
}
/*
@@ -483,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;
}
@@ -499,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
@@ -520,20 +711,50 @@ 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)) {
+ 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
@@ -541,18 +762,19 @@ 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) {
char *string;
@@ -564,7 +786,8 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
*/
if (string[0] != '\0') {
- goto error;
+ result = TCL_ERROR;
+ goto done;
} else {
Tcl_ResetResult(interp);
}
@@ -574,24 +797,27 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
} 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;
@@ -599,24 +825,27 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
x += canvasPtr->xOrigin;
Tcl_PrintDouble(interp, GridAlign((double) x, grid), buf);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else if ((c == 'c') && (strcmp(argv[1], "canvasy") == 0)) {
+ 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;
@@ -624,76 +853,104 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
y += canvasPtr->yOrigin;
Tcl_PrintDouble(interp, GridAlign((double) y, grid), buf);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
- && (length >= 2)) {
+ 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);
+ for (itemPtr = canvasPtr->firstItemPtr;
+ itemPtr != NULL; itemPtr = itemPtr->nextPtr) {
+ if (itemPtr->state != TK_STATE_NULL) {
+ continue;
+ }
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
+ result = (*itemPtr->typePtr->configProc)(interp,
+ (Tk_Canvas) canvasPtr, itemPtr, 0, (Tcl_Obj **) NULL,
+ TK_CONFIG_ARGV_ONLY);
+ EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
+ canvasPtr->flags |= REPICK_NEEDED;
+ }
}
- } 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;
}
@@ -709,10 +966,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,
@@ -727,36 +995,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(buf, "%d", itemPtr->id);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else if ((c == 'd') && (strncmp(argv[1], "dchars", length) == 0)
- && (length >= 2)) {
+ 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;
@@ -765,26 +1053,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);
@@ -833,24 +1135,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];
@@ -858,23 +1168,27 @@ 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) {
@@ -887,15 +1201,22 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
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;
}
@@ -905,136 +1226,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);
+ }
+ if (result != TCL_OK) {
+ goto done;
}
sprintf(buf, "%d", index);
Tcl_SetResult(interp, buf, TCL_VOLATILE);
- } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
- && (length >= 3)) {
+ 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,
@@ -1042,29 +1441,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;
}
/*
@@ -1075,49 +1481,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;
}
/*
@@ -1129,70 +1561,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)) {
Tcl_SetResult(interp, "scale factor cannot be zero", TCL_STATIC);
- 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->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 ((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 ((Tcl_GetInt(interp, argv[3], &x) != TCL_OK)
- || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)){
- goto error;
+ if ((argc == 6) && (Tcl_GetIntFromObj(interp, argv[5], &gain) != TCL_OK)) {
+ result = TCL_ERROR;
+ goto done;
}
- if ((argv[2][0] == 'm')
- && (strncmp(argv[2], "mark", strlen(argv[2])) == 0)) {
+ 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;
/*
@@ -1200,30 +1668,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;
@@ -1232,24 +1711,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;
}
}
- length = strlen(argv[2]);
- c = argv[2][0];
- if ((c == 'a') && (strncmp(argv[2], "adjust", length) == 0)) {
+ if (Tcl_GetIndexFromObj(interp, argv[2], optionStrings, "select option", 0,
+ &optionindex) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ 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
@@ -1262,36 +1750,37 @@ 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) {
char buf[TCL_INTEGER_SPACE];
@@ -1299,31 +1788,40 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
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) {
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. */
@@ -1335,10 +1833,13 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
- canvasPtr->inset, canvasPtr->scrollX1,
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
@@ -1361,7 +1862,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. */
@@ -1373,10 +1876,13 @@ CanvasWidgetCmd(clientData, interp, argc, argv)
- canvasPtr->inset, canvasPtr->scrollY1,
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
@@ -1400,24 +1906,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;
}
/*
@@ -1470,6 +1967,18 @@ 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);
@@ -1505,14 +2014,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;
}
@@ -1530,10 +2039,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;
+ gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
new = Tk_GetGC(canvasPtr->tkwin,
- GCFunction|GCForeground|GCGraphicsExposures, &gcValues);
+ GCFunction|GCGraphicsExposures|GCForeground, &gcValues);
if (canvasPtr->pixmapGC != None) {
Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
}
@@ -1593,6 +2102,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).
@@ -1683,6 +2208,7 @@ DisplayCanvas(clientData)
if (canvasPtr->tkwin == NULL) {
return;
}
+
if (!Tk_IsMapped(tkwin)) {
goto done;
}
@@ -1704,6 +2230,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.
*/
@@ -1795,7 +2335,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)
@@ -1803,6 +2343,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);
@@ -1856,7 +2401,7 @@ DisplayCanvas(clientData)
}
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) {
@@ -1948,7 +2493,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);
}
@@ -2020,10 +2565,13 @@ Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2)
* Pixels on edge are not redrawn. */
{
TkCanvas *canvasPtr = (TkCanvas *) canvas;
- if ((x1 == x2) || (y1 == y2)) {
+ 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 & REDRAW_PENDING) {
+ if (canvasPtr->flags & BBOX_NOT_EMPTY) {
if (x1 <= canvasPtr->redrawX1) {
canvasPtr->redrawX1 = x1;
}
@@ -2041,6 +2589,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;
}
@@ -2159,8 +2771,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
/*
*--------------------------------------------------------------
*
@@ -2187,10 +2812,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. */
{
@@ -2198,6 +2823,7 @@ 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;
@@ -2249,7 +2875,6 @@ StartTagSearch(canvasPtr, tag, searchPtr)
searchPtr->tag = uid = Tk_GetUid(tag);
if (uid == Tk_GetUid("all")) {
-
/*
* All items match.
*/
@@ -2368,6 +2993,865 @@ 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, uid)
+TagSearchExpr **exprPtrPtr;
+Tk_Uid uid;
+{
+ TagSearchExpr* expr = *exprPtrPtr;
+
+ if (! expr) {
+ expr = (TagSearchExpr *) ckalloc(sizeof(TagSearchExpr));
+ expr->allocated = 0;
+ expr->uids = NULL;
+ expr->next = NULL;
+ }
+ expr->uid = uid;
+ 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 NextItem 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),Tk_GetUid(tag));
+
+ /* short circuit impossible searches for null tags */
+ if ((searchPtr->stringLength = strlen(tag)) == 0) {
+ return TCL_OK;
+ }
+
+ /* Make sure there is enough buffer to hold rewritten tags */
+ if ((unsigned int)searchPtr->stringLength >=
+ searchPtr->rewritebufferAllocated) {
+ searchPtr->rewritebufferAllocated += 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 (isdigit(UCHAR(*tag))) {
+ char *end;
+
+ searchPtr->id = strtoul(tag, &end, 0);
+ if (*end == 0) {
+ searchPtr->type = 1;
+ 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) {
+
+ /* ignore unquoted whitespace */
+ case ' ' :
+ case '\t' :
+ case '\n' :
+ case '\r' :
+ break;
+
+ /* negate next tag or subexpr */
+ case '!' :
+ 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;
+
+ /* scan subexpr (or negated subexpr) recursively */
+ case '(' :
+ 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;
+
+ /* quoted tag string */
+ case '"' :
+ 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;
+
+ /* illegal chars when looking for tag */
+ case '&' :
+ case '|' :
+ case '^' :
+ case ')' :
+ Tcl_AppendResult(interp,
+ "Unexpected operator in tag search expression",
+ (char *) NULL);
+ return TCL_ERROR;
+
+ /* unquoted tag string */
+ default :
+ 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) {
+
+ /* ignore whitespace */
+ case ' ' :
+ case '\t' :
+ case '\n' :
+ case '\r' :
+ break;
+
+ /* AND operator */
+ case '&' :
+ 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;
+
+ /* OR operator */
+ case '|' :
+ 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;
+
+ /* XOR operator */
+ case '^' :
+ expr->uids[expr->index++] = xorUid;
+ looking_for_tag = 1;
+ break;
+
+ /* end subexpression */
+ case ')' :
+ expr->uids[expr->index++] = endparenUid;
+ goto breakwhile;
+
+ /* syntax error */
+ default :
+ 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 */
+
/*
*--------------------------------------------------------------
*
@@ -2473,58 +3957,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 the interp's 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. */
+ 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;
}
@@ -2532,45 +4039,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);
+#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 {
@@ -2582,8 +4097,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;
}
@@ -2598,6 +4120,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;
}
@@ -2635,6 +4161,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;
@@ -2650,36 +4180,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;
}
@@ -2714,7 +4248,7 @@ 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
@@ -2729,13 +4263,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;
}
@@ -2757,6 +4291,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;
@@ -2789,17 +4327,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;
/*
@@ -2809,8 +4357,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
@@ -2841,8 +4397,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;
}
@@ -2852,7 +4407,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) {
@@ -2873,6 +4432,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 */
}
/*
@@ -2990,8 +4552,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.
@@ -3017,6 +4580,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
@@ -3138,7 +4702,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;
@@ -3163,13 +4731,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;
@@ -3183,7 +4771,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
@@ -3213,6 +4802,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;
@@ -3257,6 +4851,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;
@@ -3270,6 +4868,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,
@@ -3279,17 +4878,62 @@ 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;
+ if ((expr->match = TagSearchEvalExpr(expr, itemPtr))) {
+ 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
@@ -3344,11 +4988,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);
}
}
@@ -3391,11 +5032,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;
@@ -3445,11 +5083,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;
@@ -3467,8 +5102,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);
}
}
@@ -3542,11 +5176,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;
}
@@ -3851,3 +5482,235 @@ 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/generic/tkCanvas.h b/generic/tkCanvas.h
index 9dbcd0f..9d2c392 100644
--- a/generic/tkCanvas.h
+++ b/generic/tkCanvas.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvas.h,v 1.3 1998/10/13 18:13:06 rjohnson Exp $
+ * RCS: @(#) $Id: tkCanvas.h,v 1.4 1999/12/14 06:52:27 hobbs Exp $
*/
#ifndef _TKCANVAS
@@ -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,18 @@ 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/generic/tkDecls.h b/generic/tkDecls.h
index c017771..7293542 100644
--- a/generic/tkDecls.h
+++ b/generic/tkDecls.h
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkDecls.h,v 1.5 1999/04/30 22:49:54 stanton Exp $
+ * RCS: @(#) $Id: tkDecls.h,v 1.6 1999/12/14 06:52:27 hobbs Exp $
*/
#ifndef _TKDECLS
@@ -748,6 +748,16 @@ EXTERN void Tk_InitConsoleChannels _ANSI_ARGS_((
/* 216 */
EXTERN int Tk_CreateConsoleWindow _ANSI_ARGS_((
Tcl_Interp * interp));
+/* 217 */
+EXTERN void Tk_CreateSmoothMethod _ANSI_ARGS_((
+ Tcl_Interp * interp,
+ Tk_SmoothMethod * method));
+/* 218 */
+EXTERN void Tk_CreateCanvasVisitor _ANSI_ARGS_((
+ Tcl_Interp * interp, VOID * typePtr));
+/* 219 */
+EXTERN VOID * Tk_GetCanvasVisitor _ANSI_ARGS_((Tcl_Interp * interp,
+ CONST char * name));
typedef struct TkStubHooks {
struct TkPlatStubs *tkPlatStubs;
@@ -977,6 +987,9 @@ typedef struct TkStubs {
int (*tk_SetOptions) _ANSI_ARGS_((Tcl_Interp * interp, char * recordPtr, Tk_OptionTable optionTable, int objc, Tcl_Obj *CONST objv[], Tk_Window tkwin, Tk_SavedOptions * savePtr, int * maskPtr)); /* 214 */
void (*tk_InitConsoleChannels) _ANSI_ARGS_((Tcl_Interp * interp)); /* 215 */
int (*tk_CreateConsoleWindow) _ANSI_ARGS_((Tcl_Interp * interp)); /* 216 */
+ void (*tk_CreateSmoothMethod) _ANSI_ARGS_((Tcl_Interp * interp, Tk_SmoothMethod * method)); /* 217 */
+ void (*tk_CreateCanvasVisitor) _ANSI_ARGS_((Tcl_Interp * interp, VOID * typePtr)); /* 218 */
+ VOID * (*tk_GetCanvasVisitor) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name)); /* 219 */
} TkStubs;
#ifdef __cplusplus
@@ -1861,6 +1874,18 @@ extern TkStubs *tkStubsPtr;
#define Tk_CreateConsoleWindow \
(tkStubsPtr->tk_CreateConsoleWindow) /* 216 */
#endif
+#ifndef Tk_CreateSmoothMethod
+#define Tk_CreateSmoothMethod \
+ (tkStubsPtr->tk_CreateSmoothMethod) /* 217 */
+#endif
+#ifndef Tk_CreateCanvasVisitor
+#define Tk_CreateCanvasVisitor \
+ (tkStubsPtr->tk_CreateCanvasVisitor) /* 218 */
+#endif
+#ifndef Tk_GetCanvasVisitor
+#define Tk_GetCanvasVisitor \
+ (tkStubsPtr->tk_GetCanvasVisitor) /* 219 */
+#endif
#endif /* defined(USE_TK_STUBS) && !defined(USE_TK_STUB_PROCS) */
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 8ae1b06..ac0f288 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -11,12 +11,14 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkEntry.c,v 1.6 1999/11/10 02:56:24 hobbs Exp $
+ * RCS: @(#) $Id: tkEntry.c,v 1.7 1999/12/14 06:52:27 hobbs Exp $
*/
#include "tkInt.h"
#include "default.h"
+#define ENTRY_VALIDATE
+
/*
* A data structure of the following type is kept for each entry
* widget managed by this file:
@@ -151,6 +153,16 @@ typedef struct {
int avgWidth; /* Width of average character. */
int flags; /* Miscellaneous flags; see below for
* definitions. */
+ Tk_TSOffset tsoffset;
+
+#ifdef ENTRY_VALIDATE
+ char *validateCmd; /* Command prefix to use when invoking
+ * validate command. NULL means don't
+ * invoke commands. Malloc'ed. */
+ int validate; /* Non-zero means try to validate */
+ char *invalidCmd; /* Command called when a validation returns 0
+ * (successfully fails), defaults to {}. */
+#endif /* ENTRY_VALIDATE */
} Entry;
/*
@@ -169,6 +181,11 @@ 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.
+ * 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
@@ -178,6 +195,11 @@ typedef struct {
#define UPDATE_SCROLLBAR 0x10
#define GOT_SELECTION 0x20
#define ENTRY_DELETED 0x40
+#ifdef ENTRY_VALIDATE
+#define VALIDATING 0x80
+#define VALIDATE_VAR 0x100
+#define VALIDATE_ABORT 0x200
+#endif /* ENTRY_VALIDATE */
/*
* The following macro defines how many extra pixels to leave on each
@@ -201,6 +223,27 @@ static char *stateStrings[] = {
"disabled", "normal", (char *) NULL
};
+#ifdef ENTRY_VALIDATE
+/*
+ * 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 ""
+
+#endif /* ENTRY_VALIDATE */
+
/*
* Information used for argv parsing.
*/
@@ -256,6 +299,13 @@ static Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth),
0, 0, 0},
+#ifdef ENTRY_VALIDATE
+ {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
+ DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
+ 0, 0, 0},
+ {TK_OPTION_SYNONYM, "-invcmd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0},
+#endif /* ENTRY_VALIDATE */
{TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
@@ -283,6 +333,16 @@ static Tk_OptionSpec optionSpecs[] = {
{TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
TK_CONFIG_NULL_OK, 0, 0},
+#ifdef ENTRY_VALIDATE
+ {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
+ DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
+ 0, (ClientData) validateStrings, 0},
+ {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand",
+ (char *) NULL, -1, Tk_Offset(Entry, validateCmd),
+ TK_CONFIG_NULL_OK, 0, 0},
+ {TK_OPTION_SYNONYM, "-vcmd", (char *) NULL, (char *) NULL,
+ (char *) NULL, 0, -1, 0, (ClientData) "-validatecommand", 0},
+#endif /* ENTRY_VALIDATE */
{TK_OPTION_INT, "-width", "width", "Width",
DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
{TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
@@ -307,13 +367,21 @@ static Tk_OptionSpec optionSpecs[] = {
static char *commandNames[] = {
"bbox", "cget", "configure", "delete", "get", "icursor", "index",
- "insert", "scan", "selection", "xview", (char *) NULL
+ "insert", "scan", "selection",
+#ifdef ENTRY_VALIDATE
+ "validate",
+#endif
+ "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_XVIEW
+ COMMAND_SCAN, COMMAND_SELECTION,
+#ifdef ENTRY_VALIDATE
+ COMMAND_VALIDATE,
+#endif
+ COMMAND_XVIEW
};
static char *selCommandNames[] = {
@@ -358,6 +426,15 @@ static char * EntryTextVarProc _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, char *name1, char *name2,
int flags));
static void EntryUpdateScrollbar _ANSI_ARGS_((Entry *entryPtr));
+#ifdef ENTRY_VALIDATE
+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));
+#endif /* ENTRY_VALIDATE */
static void EntryValueChanged _ANSI_ARGS_((Entry *entryPtr));
static void EntryVisibleRange _ANSI_ARGS_((Entry *entryPtr,
double *firstPtr, double *lastPtr));
@@ -506,6 +583,11 @@ Tk_EntryObjCmd(clientData, interp, objc, objv)
entryPtr->highlightGC = None;
entryPtr->avgWidth = 1;
entryPtr->flags = 0;
+#ifdef ENTRY_VALIDATE
+ entryPtr->validateCmd = NULL;
+ entryPtr->validate = VALIDATE_NONE;
+ entryPtr->invalidCmd = NULL;
+#endif /* ENTRY_VALIDATE */
Tk_SetClass(entryPtr->tkwin, "Entry");
TkSetClassProcs(entryPtr->tkwin, &entryClass, (ClientData) entryPtr);
@@ -888,6 +970,26 @@ EntryWidgetObjCmd(clientData, interp, objc, objv)
break;
}
+#ifdef ENTRY_VALIDATE
+ case COMMAND_VALIDATE: {
+ int code;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "validate");
+ 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;
+ }
+#endif
+
case COMMAND_XVIEW: {
int index;
@@ -1192,7 +1294,7 @@ EntryWorldChanged(instanceData)
ClientData instanceData; /* Information about widget. */
{
XGCValues gcValues;
- GC gc;
+ GC gc = None;
unsigned long mask;
Entry *entryPtr;
@@ -1203,6 +1305,10 @@ 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;
@@ -1313,7 +1419,7 @@ DisplayEntry(clientData)
*/
Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->normalBorder,
- 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
+ 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
string = entryPtr->displayString;
if (showSelection
@@ -1599,6 +1705,16 @@ InsertChars(entryPtr, index, value)
strcpy(new + byteIndex, value);
strcpy(new + byteIndex + byteCount, string + byteIndex);
+#ifdef ENTRY_VALIDATE
+ if ((entryPtr->validate == VALIDATE_KEY ||
+ entryPtr->validate == VALIDATE_ALL) &&
+ EntryValidateChange(entryPtr, value, new, index,
+ VALIDATE_INSERT) != TCL_OK) {
+ ckfree(new);
+ return;
+ }
+#endif /* ENTRY_VALIDATE */
+
ckfree(string);
entryPtr->string = new;
@@ -1674,6 +1790,9 @@ DeleteChars(entryPtr, index, count)
{
int byteIndex, byteCount, newByteCount;
char *new, *string;
+#ifdef ENTRY_VALIDATE
+ char *todelete;
+#endif
if ((index + count) > entryPtr->numChars) {
count = entryPtr->numChars - index;
@@ -1691,6 +1810,23 @@ DeleteChars(entryPtr, index, count)
memcpy(new, string, (size_t) byteIndex);
strcpy(new + byteIndex, string + byteIndex + byteCount);
+#ifdef ENTRY_VALIDATE
+ 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);
+#endif /* ENTRY_VALIDATE */
+
ckfree(entryPtr->string);
entryPtr->string = new;
entryPtr->numChars -= count;
@@ -1830,6 +1966,30 @@ EntrySetValue(entryPtr, value)
char *value; /* New text to display in entry. */
{
char *oldSource;
+#ifdef ENTRY_VALIDATE
+ int code;
+
+ if (strcmp(value, entryPtr->string) == 0) {
+ return;
+ }
+
+ if (entryPtr->flags & VALIDATE_VAR) {
+ entryPtr->flags |= VALIDATE_ABORT;
+ } else {
+ 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;
+ return;
+ }
+ }
+#endif /* ENTRY_VALIDATE */
oldSource = entryPtr->string;
@@ -2489,9 +2649,25 @@ EntryFocusProc(entryPtr, gotFocus)
entryPtr->insertOnTime, EntryBlinkProc,
(ClientData) entryPtr);
}
+#ifdef ENTRY_VALIDATE
+ if (entryPtr->validate == VALIDATE_ALL ||
+ entryPtr->validate == VALIDATE_FOCUS ||
+ entryPtr->validate == VALIDATE_FOCUSIN) {
+ EntryValidateChange(entryPtr, (char *) NULL,
+ entryPtr->string, -1, VALIDATE_FOCUSIN);
+ }
+#endif /* ENTRY_VALIDATE */
} else {
entryPtr->flags &= ~(GOT_FOCUS | CURSOR_ON);
entryPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
+#ifdef ENTRY_VALIDATE
+ if (entryPtr->validate == VALIDATE_ALL ||
+ entryPtr->validate == VALIDATE_FOCUS ||
+ entryPtr->validate == VALIDATE_FOCUSOUT) {
+ EntryValidateChange(entryPtr, (char *) NULL,
+ entryPtr->string, -1, VALIDATE_FOCUSOUT);
+ }
+#endif /* ENTRY_VALIDATE */
}
EventuallyRedraw(entryPtr);
}
@@ -2553,8 +2729,289 @@ EntryTextVarProc(clientData, interp, name1, name2, flags)
if (value == NULL) {
value = "";
}
+#ifdef ENTRY_VALIDATE
+ EntrySetValue(entryPtr, value);
+#else
if (strcmp(value, entryPtr->string) != 0) {
EntrySetValue(entryPtr, value);
}
+#endif /* ENTRY_VALIDATE */
return (char *) NULL;
}
+#ifdef ENTRY_VALIDATE
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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_GlobalEval(interp, cmd);
+
+ 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 Tcl Boolean not returned by validation command");
+ Tcl_BackgroundError(interp);
+ Tcl_SetObjLength(Tcl_GetObjResult(interp), 0);
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjLength(Tcl_GetObjResult(interp), 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;
+ char *p;
+ Tcl_DString script;
+
+ if (entryPtr->validateCmd == NULL ||
+ entryPtr->validate == VALIDATE_NONE) {
+ return (entryPtr->flags & VALIDATE_VAR) ? 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 (entryPtr->flags & VALIDATE_VAR) ? 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,
+ * it means that a loop condition almost occured. Do not allow
+ * this validation result to finish.
+ */
+ if (entryPtr->validate == VALIDATE_NONE ||
+ (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 (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_GlobalEval(entryPtr->interp, p) != 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 */
+ string = validateStrings[entryPtr->validate];
+ 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_ScanElement(string, &cvtFlags);
+ length = Tcl_DStringLength(dsPtr);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ spaceNeeded = Tcl_ConvertElement(string,
+ Tcl_DStringValue(dsPtr) + length,
+ cvtFlags | TCL_DONT_USE_BRACES);
+ Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
+ }
+}
+#endif /* ENTRY_VALIDATE */
diff --git a/generic/tkEvent.c b/generic/tkEvent.c
index 91d4b55..cd3615f 100644
--- a/generic/tkEvent.c
+++ b/generic/tkEvent.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkEvent.c,v 1.5 1999/08/13 17:52:12 redman Exp $
+ * RCS: @(#) $Id: tkEvent.c,v 1.6 1999/12/14 06:52:27 hobbs Exp $
*/
#include "tkPort.h"
@@ -467,6 +467,33 @@ Tk_HandleEvent(eventPtr)
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
* invoked for all events). If a generic event handler reports that
diff --git a/generic/tkFont.c b/generic/tkFont.c
index d63e58d..8fdbcc9 100644
--- a/generic/tkFont.c
+++ b/generic/tkFont.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkFont.c,v 1.6 1999/09/21 06:42:30 hobbs Exp $
+ * RCS: @(#) $Id: tkFont.c,v 1.7 1999/12/14 06:52:28 hobbs Exp $
*/
#include "tkPort.h"
@@ -1818,6 +1818,16 @@ Tk_ComputeTextLayout(tkfont, string, numChars, wrapLength, justify, flags,
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;
diff --git a/generic/tkFrame.c b/generic/tkFrame.c
index 9284deb..4af8d7e 100644
--- a/generic/tkFrame.c
+++ b/generic/tkFrame.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkFrame.c,v 1.4 1999/08/10 05:06:01 jingham Exp $
+ * RCS: @(#) $Id: tkFrame.c,v 1.5 1999/12/14 06:52:28 hobbs Exp $
*/
#include "default.h"
@@ -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)) {
@@ -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,7 +627,7 @@ 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.
*
@@ -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,6 +731,8 @@ DisplayFrame(clientData)
{
register Frame *framePtr = (Frame *) clientData;
register Tk_Window tkwin = framePtr->tkwin;
+ 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)
@@ -702,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,
diff --git a/generic/tkGet.c b/generic/tkGet.c
index b05be71..dd920be 100644
--- a/generic/tkGet.c
+++ b/generic/tkGet.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkGet.c,v 1.5 1999/04/21 21:53:26 rjohnson Exp $
+ * RCS: @(#) $Id: tkGet.c,v 1.6 1999/12/14 06:52:28 hobbs Exp $
*/
#include "tkInt.h"
@@ -621,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,
@@ -669,11 +712,7 @@ 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/generic/tkImage.c b/generic/tkImage.c
index a867594..e54a189 100644
--- a/generic/tkImage.c
+++ b/generic/tkImage.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkImage.c,v 1.4 1999/10/29 03:57:56 hobbs Exp $
+ * RCS: @(#) $Id: tkImage.c,v 1.5 1999/12/14 06:52:28 hobbs Exp $
*/
#include "tkInt.h"
@@ -186,227 +186,227 @@ Tk_ImageObjCmd(clientData, interp, objc, objv)
return TCL_ERROR;
}
switch ((enum options) index) {
- case IMAGE_CREATE: {
- char *arg;
- Tcl_Obj **args;
- int oldimage = 0;
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "type ?name? ?options?");
- return TCL_ERROR;
- }
+ case IMAGE_CREATE: {
+ 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.
+ */
- 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) {
+ 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) {
- Tcl_AppendResult(interp, "image type \"", arg,
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
-
- /*
- * Figure out a name to use for the new image.
- */
+ 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;
+ }
- arg = Tcl_GetString(objv[3]);
- if ((objc == 3) || (arg[0] == '-')) {
- dispPtr->imageId++;
- sprintf(idString, "image%d", dispPtr->imageId);
- name = idString;
- firstOption = 3;
- } else {
- name = arg;
- 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.
+ */
- 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]);
+ 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;
}
- 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_SetResult(interp,
- Tcl_GetHashKey(&winPtr->mainPtr->imageTable, hPtr),
- TCL_STATIC);
- break;
- }
- case IMAGE_DELETE: {
- for (i = 2; i < objc; i++) {
- char *arg = Tcl_GetString(objv[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 \"", arg,
- "\" 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);
- }
- break;
- }
- case IMAGE_HEIGHT: {
- char *arg;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name");
- return TCL_ERROR;
- }
- arg = Tcl_GetString(objv[2]);
- hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "image \"", arg,
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
- masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
- break;
- }
- case IMAGE_NAMES: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), masterPtr->height);
+ break;
}
- 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;
}
- break;
- }
- case IMAGE_TYPE: {
- char *arg;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name");
- return TCL_ERROR;
- }
- arg = Tcl_GetString(objv[2]);
- hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->imageTable, arg);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "image \"", arg,
- "\" doesn't exist", (char *) NULL);
- return TCL_ERROR;
- }
- masterPtr = (ImageMaster *) Tcl_GetHashValue(hPtr);
- if (masterPtr->typePtr != NULL) {
- Tcl_SetResult(interp, masterPtr->typePtr->name, TCL_STATIC);
- }
- break;
- }
- case IMAGE_TYPES: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, NULL);
- return TCL_ERROR;
- }
- for (typePtr = tsdPtr->imageTypeList; typePtr != NULL;
- typePtr = typePtr->nextPtr) {
- Tcl_AppendElement(interp, typePtr->name);
- }
- for (typePtr = tsdPtr->oldImageTypeList; typePtr != NULL;
- typePtr = typePtr->nextPtr) {
- Tcl_AppendElement(interp, typePtr->name);
+ 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;
}
- break;
- }
- case IMAGE_WIDTH: {
- char *arg;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "name");
- 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;
}
- 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;
+ 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);
- break;
- }
}
return TCL_OK;
}
@@ -450,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);
}
}
@@ -608,6 +608,81 @@ 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;
+{
+ int result;
+ XImage *ximage;
+ Pixmap pmap;
+ GC newGC;
+ XGCValues gcValues;
+ 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
@@ -864,3 +939,39 @@ 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/generic/tkImgBmap.c b/generic/tkImgBmap.c
index 60b9f39..6c49129 100644
--- a/generic/tkImgBmap.c
+++ b/generic/tkImgBmap.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkImgBmap.c,v 1.10 1999/10/29 03:57:56 hobbs Exp $
+ * RCS: @(#) $Id: tkImgBmap.c,v 1.11 1999/12/14 06:52:28 hobbs Exp $
*/
#include "tkInt.h"
@@ -92,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 */
@@ -100,6 +104,7 @@ Tk_ImageType tkBitmapImageType = {
ImgBmapDisplay, /* displayProc */
ImgBmapFree, /* freeProc */
ImgBmapDelete, /* deleteProc */
+ ImgBmapPostscript, /* postscriptProc */
(Tk_ImageType *) NULL /* nextPtr */
};
@@ -1095,3 +1100,103 @@ 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/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index 7e3b804..75694c0 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -15,7 +15,7 @@
* Department of Computer Science,
* Australian National University.
*
- * RCS: @(#) $Id: tkImgPhoto.c,v 1.10 1999/10/29 03:57:56 hobbs Exp $
+ * RCS: @(#) $Id: tkImgPhoto.c,v 1.11 1999/12/14 06:52:28 hobbs Exp $
*/
#include "tkInt.h"
@@ -301,6 +301,7 @@ Tk_ImageType tkPhotoImageType = {
ImgPhotoDisplay, /* displayProc */
ImgPhotoFree, /* freeProc */
ImgPhotoDelete, /* deleteProc */
+ (Tk_ImagePostscriptProc *) NULL, /* postscriptProc */
(Tk_ImageType *) NULL /* nextPtr */
};
@@ -394,8 +395,8 @@ static int MatchStringFormat _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *data, Tcl_Obj *formatString,
Tk_PhotoImageFormat **imageFormatPtr,
int *widthPtr, int *heightPtr, int *oldformat));
-static void Dither _ANSI_ARGS_((PhotoMaster *masterPtr,
- int x, int y, int width, int height));
+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));
@@ -588,7 +589,12 @@ ImgPhotoCmd(clientData, interp, objc, objv)
if (Tcl_GetIndexFromObj(interp, objv[1], photoOptions, "option", 0,
&index) != TCL_OK) {
- return TCL_ERROR;
+ Tcl_ObjCmdProc *proc;
+ proc = PhotoOptionFind(interp, objv[1]);
+ if (proc == (Tcl_ObjCmdProc *) NULL) {
+ return TCL_ERROR;
+ }
+ return proc(clientData, interp, objc, objv);
}
switch ((enum options) index) {
case PHOTO_BLANK: {
@@ -610,7 +616,7 @@ ImgPhotoCmd(clientData, interp, objc, objv)
Tcl_WrongNumArgs(interp, 2, objv, "option");
return TCL_ERROR;
}
- arg = Tcl_GetStringFromObj(objv[2],&length);
+ arg = Tcl_GetStringFromObj(objv[2], (int *) &length);
if (strncmp(arg,"-data", length) == 0) {
if (masterPtr->dataString) {
Tcl_SetObjResult(interp, masterPtr->dataString);
@@ -659,7 +665,7 @@ ImgPhotoCmd(clientData, interp, objc, objv)
return TCL_OK;
}
if (objc == 3) {
- char *arg = Tcl_GetStringFromObj(objv[2], &length);
+ char *arg = Tcl_GetStringFromObj(objv[2], (int *) &length);
if (!strncmp(arg, "-data", length)) {
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
"-data {} {} {}", (char *) NULL);
@@ -1172,11 +1178,11 @@ ImgPhotoCmd(clientData, interp, objc, 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);
}
@@ -1454,10 +1460,14 @@ ParseSubcommandOptions(optPtr, interp, allowedOptions, optIndexPtr, objc, objv)
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) {
- char *val = Tcl_GetString(objv[argIndex]);
+ 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])
@@ -3835,7 +3845,7 @@ Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height)
* 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.
@@ -4072,7 +4082,7 @@ Tk_PhotoPutZoomedBlock(handle, blockPtr, x, y, width, height, zoomX, zoomY,
* 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.
@@ -4085,7 +4095,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.
@@ -4101,14 +4111,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)) {
@@ -4944,3 +4955,149 @@ Tk_PhotoGetImage(handle, blockPtr)
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);
+}
diff --git a/generic/tkInt.decls b/generic/tkInt.decls
index 244798f..c45134b 100644
--- a/generic/tkInt.decls
+++ b/generic/tkInt.decls
@@ -9,7 +9,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tkInt.decls,v 1.12 1999/12/07 03:51:05 hobbs Exp $
+# RCS: @(#) $Id: tkInt.decls,v 1.13 1999/12/14 06:52:29 hobbs Exp $
library tk
@@ -1046,10 +1046,11 @@ interface tkIntXlib
# X functions for Windows
-# This slot is reserved for use by the dash patch:
-# declare 0 win {
-# XSetDashes
-# }
+declare 0 win {
+ void XSetDashes (Display* display, GC gc, int dash_offset,
+ _Xconst char* dash_list, int n)
+}
+
declare 1 win {
XModifierKeymap* XGetModifierMapping (Display* d)
}
@@ -1520,13 +1521,17 @@ declare 106 win {
void XFillRectangle (Display* display, Drawable d, GC gc, \
int x, int y, unsigned int width, unsigned int height)
}
+declare 105 win {
+ void XWarpPointer (Display* d, Window s, Window dw, int sx, int sy, \
+ unsigned int sw, unsigned int sh, int dx, int dy)
+}
# X functions for Mac
-# This slot is reserved for use by the dash patch:
-# declare 0 win {
-# XSetDashes
-# }
+declare 0 mac {
+ void XSetDashes (Display* display, GC gc, int dash_offset,
+ _Xconst char* dash_list, int n)
+}
declare 1 mac {
XModifierKeymap* XGetModifierMapping (Display* d)
diff --git a/generic/tkInt.h b/generic/tkInt.h
index c79c55c..6da5416 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: $Id: tkInt.h,v 1.18 1999/12/03 07:14:39 hobbs Exp $
+ * RCS: $Id: tkInt.h,v 1.19 1999/12/14 06:52:29 hobbs Exp $
*/
#ifndef _TKINT
@@ -33,7 +33,6 @@
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;
@@ -490,6 +489,12 @@ typedef struct TkDisplay {
* the display when we no longer have any
* Tk applications using it.
*/
+ int mouseButtonState; /* current mouse button state for this
+ * display */
+ int warpInProgress;
+ Window warpWindow;
+ int warpX;
+ int warpY;
} TkDisplay;
/*
@@ -846,15 +851,13 @@ extern TkDisplay *tkDisplayList;
* 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;
@@ -883,8 +886,8 @@ EXTERN int Tk_BindtagsCmd _ANSI_ARGS_((ClientData clientData,
EXTERN int Tk_ButtonObjCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]));
-EXTERN int Tk_CanvasCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_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[]));
@@ -910,8 +913,9 @@ EXTERN int Tk_EventObjCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Obj *CONST objv[]));
EXTERN int Tk_FileeventCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
-EXTERN int Tk_FrameCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, char **argv));
+EXTERN int Tk_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[]));
@@ -979,8 +983,9 @@ EXTERN int Tk_TkObjCmd _ANSI_ARGS_((ClientData clientData,
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_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[]));
@@ -1001,6 +1006,70 @@ EXTERN int TkDeadAppCmd _ANSI_ARGS_((ClientData clientData,
EXTERN int TkpTestembedCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv));
+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.
diff --git a/generic/tkIntXlibDecls.h b/generic/tkIntXlibDecls.h
index d76165f..5f22fd8 100644
--- a/generic/tkIntXlibDecls.h
+++ b/generic/tkIntXlibDecls.h
@@ -9,7 +9,7 @@
* Copyright (c) 1998-1999 by Scriptics Corporation.
* All rights reserved.
*
- * RCS: @(#) $Id: tkIntXlibDecls.h,v 1.11 1999/07/31 03:36:49 hobbs Exp $
+ * RCS: @(#) $Id: tkIntXlibDecls.h,v 1.12 1999/12/14 06:52:29 hobbs Exp $
*/
#ifndef _TKINTXLIBDECLS
@@ -39,7 +39,10 @@
*/
#ifdef __WIN32__
-/* Slot 0 is reserved */
+/* 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 */
@@ -354,14 +357,20 @@ EXTERN Status XStringListToTextProperty _ANSI_ARGS_((char** list,
/* 104 */
EXTERN void XDrawLine _ANSI_ARGS_((Display* d, Drawable dr, GC g,
int x1, int y1, int x2, int y2));
-/* Slot 105 is reserved */
+/* 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
-/* Slot 0 is reserved */
+/* 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 */
@@ -627,7 +636,7 @@ typedef struct TkIntXlibStubs {
struct TkIntXlibStubHooks *hooks;
#ifdef __WIN32__
- void *reserved0;
+ 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 */
@@ -732,11 +741,11 @@ typedef struct TkIntXlibStubs {
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 *reserved105;
+ 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 *reserved0;
+ 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 */
@@ -838,7 +847,10 @@ extern TkIntXlibStubs *tkIntXlibStubsPtr;
*/
#ifdef __WIN32__
-/* Slot 0 is reserved */
+#ifndef XSetDashes
+#define XSetDashes \
+ (tkIntXlibStubsPtr->xSetDashes) /* 0 */
+#endif
#ifndef XGetModifierMapping
#define XGetModifierMapping \
(tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
@@ -1252,14 +1264,20 @@ extern TkIntXlibStubs *tkIntXlibStubsPtr;
#define XDrawLine \
(tkIntXlibStubsPtr->xDrawLine) /* 104 */
#endif
-/* Slot 105 is reserved */
+#ifndef XWarpPointer
+#define XWarpPointer \
+ (tkIntXlibStubsPtr->xWarpPointer) /* 105 */
+#endif
#ifndef XFillRectangle
#define XFillRectangle \
(tkIntXlibStubsPtr->xFillRectangle) /* 106 */
#endif
#endif /* __WIN32__ */
#ifdef MAC_TCL
-/* Slot 0 is reserved */
+#ifndef XSetDashes
+#define XSetDashes \
+ (tkIntXlibStubsPtr->xSetDashes) /* 0 */
+#endif
#ifndef XGetModifierMapping
#define XGetModifierMapping \
(tkIntXlibStubsPtr->xGetModifierMapping) /* 1 */
diff --git a/generic/tkMessage.c b/generic/tkMessage.c
index 4001ac2..bb3cb00 100644
--- a/generic/tkMessage.c
+++ b/generic/tkMessage.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkMessage.c,v 1.4 1999/08/10 05:06:59 jingham Exp $
+ * RCS: @(#) $Id: tkMessage.c,v 1.5 1999/12/14 06:52:30 hobbs Exp $
*/
#include "tkPort.h"
@@ -467,8 +467,6 @@ ConfigureMessage(interp, msgPtr, argc, argv, flags)
msgPtr->numChars = Tcl_NumUtfChars(msgPtr->string, -1);
- Tk_SetBackgroundFromBorder(msgPtr->tkwin, msgPtr->border);
-
if (msgPtr->highlightWidth < 0) {
msgPtr->highlightWidth = 0;
}
@@ -500,12 +498,16 @@ 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_GetGC(msgPtr->tkwin, GCForeground | GCFont, &gcValues);
@@ -644,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
@@ -662,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,
diff --git a/generic/tkOldConfig.c b/generic/tkOldConfig.c
index 0edf798..70e0152 100644
--- a/generic/tkOldConfig.c
+++ b/generic/tkOldConfig.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkOldConfig.c,v 1.4 1999/04/21 21:53:27 rjohnson Exp $
+ * RCS: @(#) $Id: tkOldConfig.c,v 1.5 1999/12/14 06:52:30 hobbs Exp $
*/
#include "tkPort.h"
@@ -125,7 +125,14 @@ Tk_ConfigureWidget(interp, tkwin, specs, argc, argv, widgRec, flags)
*/
for ( ; argc > 0; argc -= 2, argv += 2) {
- specPtr = FindConfigSpec(interp, specs, *argv, needFlags, hateFlags);
+ 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;
}
@@ -135,11 +142,16 @@ Tk_ConfigureWidget(interp, tkwin, specs, argc, argv, widgRec, flags)
*/
if (argc < 2) {
- Tcl_AppendResult(interp, "value for \"", *argv,
+ Tcl_AppendResult(interp, "value for \"", arg,
"\" missing", (char *) NULL);
return TCL_ERROR;
}
- if (DoConfig(interp, tkwin, specPtr, argv[1], 0, widgRec) != TCL_OK) {
+ 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)",
diff --git a/generic/tkRectOval.c b/generic/tkRectOval.c
index 70556b4..b509c04 100644
--- a/generic/tkRectOval.c
+++ b/generic/tkRectOval.c
@@ -10,13 +10,14 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkRectOval.c,v 1.3 1999/04/16 01:51:21 stanton Exp $
+ * RCS: @(#) $Id: tkRectOval.c,v 1.4 1999/12/14 06:52:30 hobbs Exp $
*/
#include <stdio.h>
#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 */
};
/*
@@ -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;
}
/*
@@ -246,28 +335,42 @@ 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;
}
@@ -308,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;
@@ -316,41 +419,99 @@ 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);
+ }
+
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(rectOvalPtr->outline));
+ if (mask) {
gcValues.cap_style = CapProjecting;
- gcValues.line_width = rectOvalPtr->width;
- mask = GCForeground|GCCapStyle|GCLineWidth;
+ 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;
+ }
+
+ 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;
+ }
}
- rectOvalPtr->outlineGC = newGC;
- if (rectOvalPtr->fillColor == NULL) {
+ 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 {
@@ -362,6 +523,24 @@ ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)
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;
@@ -393,17 +572,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);
@@ -437,7 +623,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.
@@ -456,10 +663,10 @@ ComputeRectOvalBbox(canvas, rectOvalPtr)
rectOvalPtr->bbox[0] = tmp;
}
- if (rectOvalPtr->outlineColor == NULL) {
- bloat = 0;
+ if (rectOvalPtr->outline.gc == None) {
+ bloat = 1;
} else {
- bloat = (rectOvalPtr->width+1)/2;
+ bloat = (int) (width+1)/2;
}
/*
@@ -518,6 +725,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.
@@ -543,9 +752,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,
@@ -555,18 +803,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));
}
}
@@ -602,6 +852,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
@@ -612,8 +879,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;
@@ -629,7 +896,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;
@@ -645,7 +912,7 @@ RectToPoint(canvas, itemPtr, pointPtr)
if (yDiff < xDiff) {
xDiff = yDiff;
}
- xDiff -= rectPtr->width;
+ xDiff -= width;
if (xDiff < 0.0) {
return 0.0;
}
@@ -708,10 +975,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;
}
@@ -749,9 +1032,26 @@ RectToArea(canvas, itemPtr, areaPtr)
{
RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
double halfWidth;
+ double width;
+ Tk_State state = itemPtr->state;
- halfWidth = rectPtr->width/2.0;
- if (rectPtr->outlineGC == None) {
+ 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;
+ }
+ }
+
+ halfWidth = width/2.0;
+ if (rectPtr->outline.gc == None) {
halfWidth = 0.0;
}
@@ -761,7 +1061,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))
@@ -809,13 +1109,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;
@@ -832,9 +1149,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;
@@ -966,6 +1283,10 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass)
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]);
@@ -988,23 +1309,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 {
@@ -1016,18 +1365,13 @@ RectOvalToPostscript(interp, canvas, itemPtr, prepass)
* Now draw the outline, if there is one.
*/
- if (rectOvalPtr->outlineColor != NULL) {
- char string[32 + TCL_INTEGER_SPACE];
-
- Tcl_AppendResult(interp, pathCmd, (char *) NULL);
- sprintf(string, "%d setlinewidth", rectOvalPtr->width);
- Tcl_AppendResult(interp, string,
- " 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/generic/tkScrollbar.c b/generic/tkScrollbar.c
index e00581a..eec060e 100644
--- a/generic/tkScrollbar.c
+++ b/generic/tkScrollbar.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkScrollbar.c,v 1.3 1999/04/16 01:51:21 stanton Exp $
+ * RCS: @(#) $Id: tkScrollbar.c,v 1.4 1999/12/14 06:52:30 hobbs Exp $
*/
#include "tkPort.h"
@@ -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;
@@ -532,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 {
diff --git a/generic/tkScrollbar.h b/generic/tkScrollbar.h
index a1f3d4a..4e119e1 100644
--- a/generic/tkScrollbar.h
+++ b/generic/tkScrollbar.h
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkScrollbar.h,v 1.4 1998/09/14 18:23:17 stanton Exp $
+ * RCS: @(#) $Id: tkScrollbar.h,v 1.5 1999/12/14 06:52:30 hobbs Exp $
*/
#ifndef _TKSCROLLBAR
@@ -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,
diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c
index 06f9e9a..bf2a37d 100644
--- a/generic/tkStubInit.c
+++ b/generic/tkStubInit.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkStubInit.c,v 1.13 1999/12/07 03:51:05 hobbs Exp $
+ * RCS: @(#) $Id: tkStubInit.c,v 1.14 1999/12/14 06:52:31 hobbs Exp $
*/
#include "tkInt.h"
@@ -31,6 +31,11 @@
* 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
@@ -464,7 +469,7 @@ TkIntXlibStubs tkIntXlibStubs = {
TCL_STUB_MAGIC,
NULL,
#ifdef __WIN32__
- NULL, /* 0 */
+ XSetDashes, /* 0 */
XGetModifierMapping, /* 1 */
XCreateImage, /* 2 */
XGetImage, /* 3 */
@@ -569,11 +574,11 @@ TkIntXlibStubs tkIntXlibStubs = {
XSetWMClientMachine, /* 102 */
XStringListToTextProperty, /* 103 */
XDrawLine, /* 104 */
- NULL, /* 105 */
+ XWarpPointer, /* 105 */
XFillRectangle, /* 106 */
#endif /* __WIN32__ */
#ifdef MAC_TCL
- NULL, /* 0 */
+ XSetDashes, /* 0 */
XGetModifierMapping, /* 1 */
XCreateImage, /* 2 */
XGetImage, /* 3 */
@@ -913,6 +918,9 @@ TkStubs tkStubs = {
Tk_SetOptions, /* 214 */
Tk_InitConsoleChannels, /* 215 */
Tk_CreateConsoleWindow, /* 216 */
+ Tk_CreateSmoothMethod, /* 217 */
+ Tk_CreateCanvasVisitor, /* 218 */
+ Tk_GetCanvasVisitor, /* 219 */
};
/* !END!: Do not edit above this line. */
diff --git a/generic/tkTest.c b/generic/tkTest.c
index fd68a32..d1c23bf 100644
--- a/generic/tkTest.c
+++ b/generic/tkTest.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTest.c,v 1.8 1999/12/06 01:54:24 hobbs Exp $
+ * RCS: @(#) $Id: tkTest.c,v 1.9 1999/12/14 06:52:31 hobbs Exp $
*/
#include "tkInt.h"
@@ -83,6 +83,7 @@ static Tk_ImageType imageType = {
ImageDisplay, /* displayProc */
ImageFree, /* freeProc */
ImageDelete, /* deleteProc */
+ (Tk_ImagePostscriptProc *) NULL,/* postscriptPtr */
(Tk_ImageType *) NULL /* nextPtr */
};
diff --git a/generic/tkText.c b/generic/tkText.c
index 65ff1d1..16fb043 100644
--- a/generic/tkText.c
+++ b/generic/tkText.c
@@ -14,7 +14,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkText.c,v 1.8 1999/12/12 22:51:22 hobbs Exp $
+ * RCS: @(#) $Id: tkText.c,v 1.9 1999/12/14 06:52:31 hobbs Exp $
*/
#include "default.h"
@@ -29,6 +29,16 @@
#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:
*/
@@ -113,8 +123,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",
@@ -122,8 +132,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},
@@ -142,6 +152,128 @@ static Tk_ConfigSpec configSpecs[] = {
int tkTextDebug = 0;
/*
+ * Custom options for handling "-wrap":
+ */
+
+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:
*/
@@ -244,7 +376,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 = Tk_GetUid("normal");
+ textPtr->state = TK_STATE_NORMAL;
textPtr->border = NULL;
textPtr->borderWidth = 0;
textPtr->padX = 0;
@@ -262,7 +394,7 @@ Tk_TextCmd(clientData, interp, argc, argv)
textPtr->spacing3 = 0;
textPtr->tabOptionString = NULL;
textPtr->tabArrayPtr = NULL;
- textPtr->wrapMode = Tk_GetUid("char");
+ textPtr->wrapMode = TEXT_WRAPMODE_CHAR;
textPtr->width = 0;
textPtr->height = 0;
textPtr->setGrid = 0;
@@ -480,7 +612,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- if (textPtr->state == Tk_GetUid("normal")) {
+ if (textPtr->state == TK_STATE_NORMAL) {
result = DeleteChars(textPtr, argv[2],
(argc == 4) ? argv[3] : (char *) NULL);
}
@@ -588,7 +720,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- if (textPtr->state == Tk_GetUid("normal")) {
+ if (textPtr->state == TK_STATE_NORMAL) {
for (j = 3; j < argc; j += 2) {
InsertChars(textPtr, &index1, argv[j]);
if (argc > (j+1)) {
@@ -764,23 +896,6 @@ ConfigureText(interp, textPtr, argc, argv, flags)
* the geometry and setting the background from a 3-D border.
*/
- if ((textPtr->state != Tk_GetUid("normal"))
- && (textPtr->state != Tk_GetUid("disabled"))) {
- Tcl_AppendResult(interp, "bad state value \"", textPtr->state,
- "\": must be normal or disabled", (char *) NULL);
- textPtr->state = Tk_GetUid("normal");
- return TCL_ERROR;
- }
-
- if ((textPtr->wrapMode != Tk_GetUid("char"))
- && (textPtr->wrapMode != Tk_GetUid("none"))
- && (textPtr->wrapMode != Tk_GetUid("word"))) {
- Tcl_AppendResult(interp, "bad wrap mode \"", textPtr->wrapMode,
- "\": must be char, none, or word", (char *) NULL);
- textPtr->wrapMode = Tk_GetUid("char");
- return TCL_ERROR;
- }
-
Tk_SetBackgroundFromBorder(textPtr->tkwin, textPtr->border);
/*
@@ -854,8 +969,9 @@ ConfigureText(interp, textPtr, argc, argv, flags)
|| (textPtr->selTagPtr->spacing2String != NULL)
|| (textPtr->selTagPtr->spacing3String != NULL)
|| (textPtr->selTagPtr->tabString != NULL)
+ || (textPtr->selTagPtr->state != TK_STATE_NULL)
|| (textPtr->selTagPtr->underlineString != NULL)
- || (textPtr->selTagPtr->wrapMode != NULL)) {
+ || (textPtr->selTagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
textPtr->selTagPtr->affectsDisplay = 1;
}
TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
@@ -1403,7 +1519,7 @@ 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;
@@ -1544,7 +1660,7 @@ 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, startingByte, lineNum, firstByte, lastByte;
int code, matchLength, matchByte, passes, stopLine, searchWholeText;
@@ -1555,6 +1671,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
Tcl_DString line, patDString;
TkTextSegment *segPtr;
TkTextLine *linePtr;
+ TkTextIndex curIndex;
Tcl_RegExp regexp = NULL; /* Initialization needed only to
* prevent compiler warning. */
@@ -1563,6 +1680,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
exact = 1;
+ searchElide = 0;
+ curIndex.tree = textPtr->tree;
backwards = 0;
noCase = 0;
varName = NULL;
@@ -1576,7 +1695,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
badSwitch:
Tcl_AppendResult(interp, "bad switch \"", arg,
"\": must be -forward, -backward, -exact, -regexp, ",
- "-nocase, -count, or --", (char *) NULL);
+ "-nocase, -count, -hidden, or --", (char *) NULL);
return TCL_ERROR;
}
c = arg[1];
@@ -1592,12 +1711,16 @@ TextSearchCmd(textPtr, interp, argc, argv)
varName = argv[i];
} else if ((c == 'e') && (strncmp(argv[i], "-exact", length) == 0)) {
exact = 1;
+ } else if ((c == 'e') && (strncmp(argv[i], "-elide", length) == 0)) {
+ searchElide = 1;
} else if ((c == 'f') && (strncmp(argv[i], "-forwards", length) == 0)) {
backwards = 0;
} else if ((c == 'n') && (strncmp(argv[i], "-nocase", length) == 0)) {
noCase = 1;
} else if ((c == 'r') && (strncmp(argv[i], "-regexp", length) == 0)) {
exact = 0;
+ } else if ((c == 'h') && (strncmp(argv[i], "-hidden", length) == 0)) {
+ searchElide = 1;
} else if ((c == '-') && (strncmp(argv[i], "--", length) == 0)) {
i++;
break;
@@ -1692,9 +1815,10 @@ 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);
diff --git a/generic/tkText.h b/generic/tkText.h
index 807295b..bec8ef7 100644
--- a/generic/tkText.h
+++ b/generic/tkText.h
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkText.h,v 1.5 1999/06/17 19:58:00 surles Exp $
+ * RCS: @(#) $Id: tkText.h,v 1.6 1999/12/14 06:52:32 hobbs Exp $
*/
#ifndef _TKTEXT
@@ -274,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
@@ -371,13 +377,16 @@ 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. */
int affectsDisplay; /* Non-zero means that this tag affects the
* way information is displayed on the screen
* (so need to redisplay if tag changes). */
+ int state; /* Must be STATE_NULL, STATE_NORMAL,
+ * STATE_HIDDEN or STATE_DISABLED. */
} TkTextTag;
#define TK_TAG_AFFECTS_DISPLAY 0x1
@@ -475,7 +484,7 @@ typedef struct TkText {
* image segment doesn't yet have an
* associated image, there is no entry for
* it here. */
- Tk_Uid state; /* Either normal or disabled. A text
+ int state; /* Either STATE_NORMAL or STATE_DISABLED. A text
* widget is read-only when disabled. */
/*
@@ -518,9 +527,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
@@ -657,7 +666,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));
@@ -716,15 +725,10 @@ typedef struct Tk_SegType {
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;
/*
* Declarations for procedures that are used by the text-related files
@@ -775,7 +779,7 @@ EXTERN int TkTextCharBbox _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));
+ TkWrapMode wrapMode, TkTextDispChunk *chunkPtr));
EXTERN void TkTextCreateDInfo _ANSI_ARGS_((TkText *textPtr));
EXTERN int TkTextDLineInfo _ANSI_ARGS_((TkText *textPtr,
TkTextIndex *indexPtr, int *xPtr, int *yPtr,
@@ -816,6 +820,8 @@ EXTERN void TkTextLostSelection _ANSI_ARGS_((
EXTERN TkTextIndex * TkTextMakeCharIndex _ANSI_ARGS_((TkTextBTree tree,
int lineIndex, int charIndex,
TkTextIndex *indexPtr));
+extern int TkTextIsElided _ANSI_ARGS_((TkText *textPtr,
+ TkTextIndex *indexPtr));
EXTERN TkTextIndex * TkTextMakeByteIndex _ANSI_ARGS_((TkTextBTree tree,
int lineIndex, int byteIndex,
TkTextIndex *indexPtr));
diff --git a/generic/tkTextBTree.c b/generic/tkTextBTree.c
index 6f7beb6..c20a0db 100644
--- a/generic/tkTextBTree.c
+++ b/generic/tkTextBTree.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextBTree.c,v 1.3 1999/04/16 01:51:23 stanton Exp $
+ * RCS: @(#) $Id: tkTextBTree.c,v 1.4 1999/12/14 06:52:32 hobbs Exp $
*/
#include "tkInt.h"
@@ -2427,6 +2427,132 @@ TkBTreeGetTags(indexPtr, numTagsPtr)
}
return tagInfo.tagPtrs;
}
+
+
+/*
+ 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
+*/
+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->state != TK_STATE_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->state != TK_STATE_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->state != TK_STATE_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]->state == TK_STATE_HIDDEN);
+ break;
+ }
+ }
+
+ if (LOTSA_TAGS < numTags) {
+ ckfree((char *) tagCnts);
+ ckfree((char *) tagPtrs);
+ }
+
+ return elide;
+}
/*
*----------------------------------------------------------------------
diff --git a/generic/tkTextDisp.c b/generic/tkTextDisp.c
index 90b1bd2..f9cef40 100644
--- a/generic/tkTextDisp.c
+++ b/generic/tkTextDisp.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextDisp.c,v 1.7 1999/08/10 05:07:36 jingham Exp $
+ * RCS: @(#) $Id: tkTextDisp.c,v 1.8 1999/12/14 06:52:32 hobbs Exp $
*/
#include "tkPort.h"
@@ -59,8 +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 char, none, or text. */
+ 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;
/*
@@ -159,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:
@@ -315,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,
@@ -483,7 +502,7 @@ GetStyle(textPtr, indexPtr)
int borderPrio, borderWidthPrio, reliefPrio, bgStipplePrio;
int fgPrio, fontPrio, fgStipplePrio;
- int underlinePrio, justifyPrio, offsetPrio;
+ int underlinePrio, statePrio, justifyPrio, offsetPrio;
int lMargin1Prio, lMargin2Prio, rMarginPrio;
int spacing1Prio, spacing2Prio, spacing3Prio;
int overstrikePrio, tabPrio, wrapPrio;
@@ -498,7 +517,7 @@ GetStyle(textPtr, indexPtr)
tagPtrs = TkBTreeGetTags(indexPtr, &numTags);
borderPrio = borderWidthPrio = reliefPrio = bgStipplePrio = -1;
fgPrio = fontPrio = fgStipplePrio = -1;
- underlinePrio = justifyPrio = offsetPrio = -1;
+ underlinePrio = statePrio = justifyPrio = offsetPrio = -1;
lMargin1Prio = lMargin2Prio = rMarginPrio = -1;
spacing1Prio = spacing2Prio = spacing3Prio = -1;
overstrikePrio = tabPrio = wrapPrio = -1;
@@ -512,6 +531,7 @@ GetStyle(textPtr, indexPtr)
styleValues.spacing3 = textPtr->spacing3;
styleValues.tabArrayPtr = textPtr->tabArrayPtr;
styleValues.wrapMode = textPtr->wrapMode;
+ styleValues.elide = (textPtr->state == TK_STATE_HIDDEN);
for (i = 0 ; i < numTags; i++) {
tagPtr = tagPtrs[i];
@@ -616,7 +636,12 @@ GetStyle(textPtr, indexPtr)
styleValues.underline = tagPtr->underline;
underlinePrio = tagPtr->priority;
}
- if ((tagPtr->wrapMode != NULL)
+ if ((tagPtr->state != TK_STATE_NULL)
+ && (tagPtr->priority > statePrio)) {
+ styleValues.elide = (tagPtr->state == TK_STATE_HIDDEN);
+ statePrio = tagPtr->priority;
+ }
+ if ((tagPtr->wrapMode != TEXT_WRAPMODE_NULL)
&& (tagPtr->priority > wrapPrio)) {
styleValues.wrapMode = tagPtr->wrapMode;
wrapPrio = tagPtr->priority;
@@ -656,9 +681,10 @@ GetStyle(textPtr, indexPtr)
} 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;
@@ -702,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);
}
@@ -754,7 +782,7 @@ LayoutDLine(textPtr, indexPtr)
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
@@ -775,7 +803,7 @@ LayoutDLine(textPtr, indexPtr)
* lines with numBytes > 0. Used to
* drop 0-sized chunks from the end
* of the line. */
- int byteOffset, ascent, descent, code;
+ int byteOffset, ascent, descent, code, elide, elidesize;
StyleValues *sValuePtr;
/*
@@ -793,6 +821,34 @@ LayoutDLine(textPtr, indexPtr)
dlPtr->nextPtr = NULL;
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 tag toggle, chance that invisibility state changed, so bail out */
+ } else if (segPtr->typePtr == &tkTextToggleOffType || segPtr->typePtr == &tkTextToggleOnType) {
+ if (segPtr->body.toggle.tagPtr->state!=TK_STATE_NULL) {
+ elide = (segPtr->typePtr == &tkTextToggleOffType) ^ (segPtr->body.toggle.tagPtr->state==TK_STATE_HIDDEN);
+ }
+ }
+ }
+
+ 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
@@ -804,6 +860,7 @@ LayoutDLine(textPtr, indexPtr)
lastChunkPtr = NULL;
chunkPtr = NULL;
noCharsYet = 1;
+ elide = 0;
breakChunkPtr = NULL;
breakByteOffset = 0;
justify = TK_JUSTIFY_LEFT;
@@ -811,7 +868,7 @@ LayoutDLine(textPtr, indexPtr)
tabChunkPtr = NULL;
tabArrayPtr = NULL;
rMargin = 0;
- wrapMode = Tk_GetUid("char");
+ wrapMode = TEXT_WRAPMODE_CHAR;
tabSize = 0;
lastCharChunkPtr = NULL;
@@ -828,6 +885,32 @@ LayoutDLine(textPtr, indexPtr)
}
while (segPtr != NULL) {
+
+ /* every line still gets at least one chunk due to expectations in rest of code,
+ but able to skip elided portions of line quickly */
+ /* if current chunk 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 tag toggle, chance that invisibility state changed */
+ } else if (segPtr->typePtr == &tkTextToggleOffType || segPtr->typePtr == &tkTextToggleOnType) {
+ if (segPtr->body.toggle.tagPtr->state!=TK_STATE_NULL) {
+ elide = (segPtr->typePtr == &tkTextToggleOffType) ^
+ (segPtr->body.toggle.tagPtr->state==TK_STATE_HIDDEN);
+ }
+ }
+
+ byteOffset = 0;
+ segPtr = segPtr->nextPtr;
+ if (segPtr == NULL && chunkPtr != NULL) ckfree((char *) chunkPtr);
+
+ continue;
+ }
+
+
if (segPtr->typePtr->layoutProc == NULL) {
segPtr = segPtr->nextPtr;
byteOffset = 0;
@@ -838,6 +921,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,
@@ -853,7 +937,7 @@ LayoutDLine(textPtr, indexPtr)
x = ((curIndex.byteIndex == 0)
? chunkPtr->stylePtr->sValuePtr->lMargin1
: chunkPtr->stylePtr->sValuePtr->lMargin2);
- if (wrapMode == Tk_GetUid("none")) {
+ if (wrapMode == TEXT_WRAPMODE_NONE) {
maxX = -1;
} else {
maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x
@@ -871,7 +955,7 @@ LayoutDLine(textPtr, indexPtr)
gotTab = 0;
maxBytes = segPtr->size - byteOffset;
- if (justify == TK_JUSTIFY_LEFT) {
+ if (!elide && justify == TK_JUSTIFY_LEFT) {
if (segPtr->typePtr == &tkTextCharType) {
char *p;
@@ -884,8 +968,21 @@ LayoutDLine(textPtr, indexPtr)
}
}
}
-
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,
byteOffset, maxX-tabSize, maxBytes, noCharsYet, wrapMode,
chunkPtr);
@@ -957,6 +1054,7 @@ LayoutDLine(textPtr, indexPtr)
byteOffset = 0;
segPtr = segPtr->nextPtr;
}
+
chunkPtr = NULL;
}
if (noCharsYet) {
@@ -1005,6 +1103,7 @@ LayoutDLine(textPtr, indexPtr)
wholeLine = 0;
}
+
/*
* Make tab adjustments for the last tab stop, if there is one.
*/
@@ -1026,7 +1125,7 @@ LayoutDLine(textPtr, indexPtr)
* what is implemented below.
*/
- if (wrapMode == Tk_GetUid("none")) {
+ if (wrapMode == TEXT_WRAPMODE_NONE) {
maxX = textPtr->dInfoPtr->maxX - textPtr->dInfoPtr->x - rMargin;
}
dlPtr->length = lastChunkPtr->x + lastChunkPtr->width;
@@ -1328,10 +1427,12 @@ UpdateDisplayInfo(textPtr)
index.linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
index.byteIndex = 0;
lowestPtr = NULL;
+
do {
dlPtr = LayoutDLine(textPtr, &index);
dlPtr->nextPtr = lowestPtr;
lowestPtr = dlPtr;
+ if (dlPtr->length == 0 && dlPtr->height == 0) { bytesToCount--; break; } /* elide */
TkTextIndexForwBytes(&index, dlPtr->byteCount, &index);
bytesToCount -= dlPtr->byteCount;
} while ((bytesToCount > 0)
@@ -1561,6 +1662,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.
@@ -1584,7 +1687,7 @@ DisplayDLine(textPtr, dlPtr, prevPtr, pixmap)
* to its left.
*/
- if (textPtr->state == Tk_GetUid("normal")) {
+ if (textPtr->state == TK_STATE_NORMAL) {
for (chunkPtr = dlPtr->chunkPtr; (chunkPtr != NULL);
chunkPtr = chunkPtr->nextPtr) {
x = chunkPtr->x + dInfoPtr->x - dInfoPtr->curPixelOffset;
@@ -1627,12 +1730,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,
@@ -1721,6 +1828,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
@@ -1794,7 +1902,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.
*/
@@ -1915,7 +2023,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.
*/
@@ -2308,6 +2416,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 +2433,7 @@ DisplayText(clientData)
dlPtr->oldY = dlPtr->y;
dlPtr->flags &= ~NEW_LAYOUT;
}
+ /*prevPtr = dlPtr;*/
}
Tk_FreePixmap(Tk_Display(textPtr->tkwin), pixmap);
}
@@ -3203,7 +3313,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
dlPtr = FindDLine(dInfoPtr->dLinePtr, &index);
byteCount = index.byteIndex - dlPtr->index.byteIndex;
- for (chunkPtr = dlPtr->chunkPtr; ; chunkPtr = chunkPtr->nextPtr) {
+ for (chunkPtr = dlPtr->chunkPtr; chunkPtr!=NULL ; chunkPtr = chunkPtr->nextPtr) {
if (byteCount < chunkPtr->numBytes) {
break;
}
@@ -3215,6 +3325,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
* the character within the chunk.
*/
+ 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,
@@ -3240,7 +3351,7 @@ TkTextSeeCmd(textPtr, interp, argc, argv)
} else {
return TCL_OK;
}
- }
+ }}
dInfoPtr->flags |= DINFO_OUT_OF_DATE;
if (!(dInfoPtr->flags & REDRAW_PENDING)) {
dInfoPtr->flags |= REDRAW_PENDING;
@@ -3390,7 +3501,7 @@ ScrollByLines(textPtr, offset)
break;
}
}
-
+
/*
* Discard the display lines, then either return or prepare
* for the next display line to lay out.
@@ -3419,6 +3530,7 @@ 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;
TkTextIndexForwBytes(&textPtr->topIndex, dlPtr->byteCount, &new);
FreeDLines(textPtr, dlPtr, (DLine *) NULL, 0);
@@ -3631,13 +3743,14 @@ TkTextScanCmd(textPtr, interp, argc, argv)
{
TextDInfo *dInfoPtr = textPtr->dInfoPtr;
TkTextIndex index;
- int c, x, y, totalScroll, newByte, maxByte;
+ 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) {
@@ -3646,6 +3759,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)) {
@@ -3661,7 +3776,7 @@ TkTextScanCmd(textPtr, interp, argc, argv)
* moving again).
*/
- newByte = dInfoPtr->scanMarkIndex + (10*(dInfoPtr->scanMarkX - x))
+ newByte = dInfoPtr->scanMarkIndex + (gain*(dInfoPtr->scanMarkX - x))
/ (textPtr->charWidth);
maxByte = 1 + (dInfoPtr->maxLength - (dInfoPtr->maxX - dInfoPtr->x)
+ textPtr->charWidth - 1)/textPtr->charWidth;
@@ -3677,7 +3792,7 @@ TkTextScanCmd(textPtr, interp, argc, argv)
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);
@@ -3961,7 +4076,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;
/*
@@ -3994,8 +4109,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.
@@ -4006,6 +4122,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
@@ -4179,6 +4297,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.
@@ -4197,8 +4316,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;
@@ -4209,6 +4329,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*/;
+}
+
/*
*--------------------------------------------------------------
*
@@ -4247,8 +4402,8 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes,
* 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: char,
- * none, or text. */
+ 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
@@ -4342,7 +4497,7 @@ TkTextCharLayoutProc(textPtr, indexPtr, segPtr, byteOffset, maxX, maxBytes,
* is not a character segment.
*/
- if (wrapMode != Tk_GetUid("word")) {
+ if (wrapMode != TEXT_WRAPMODE_WORD) {
chunkPtr->breakIndex = chunkPtr->numBytes;
} else {
for (count = bytesThatFit, p += bytesThatFit - 1; count > 0;
@@ -4436,7 +4591,7 @@ CharDisplayProc(chunkPtr, x, y, height, baseline, display, dst, screenY)
* Draw the text, underline, and overstrike for this chunk.
*/
- if (ciPtr->numBytes > offsetBytes) {
+ if (!sValuePtr->elide && (ciPtr->numBytes > offsetBytes) && (stylePtr->fgGC != None)) {
int numBytes = ciPtr->numBytes - offsetBytes;
char *string = ciPtr->chars + offsetBytes;
diff --git a/generic/tkTextImage.c b/generic/tkTextImage.c
index b2d1923..0708a94 100644
--- a/generic/tkTextImage.c
+++ b/generic/tkTextImage.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextImage.c,v 1.3 1999/04/16 01:51:23 stanton Exp $
+ * RCS: @(#) $Id: tkTextImage.c,v 1.4 1999/12/14 06:52:33 hobbs Exp $
*/
#include "tk.h"
@@ -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,
@@ -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: char,
- * text, or word. */
+ 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 != Tk_GetUid("none"))) {
+ && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
return 0;
}
diff --git a/generic/tkTextMark.c b/generic/tkTextMark.c
index 209a33b..ff3ef44 100644
--- a/generic/tkTextMark.c
+++ b/generic/tkTextMark.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextMark.c,v 1.3 1999/04/16 01:51:24 stanton Exp $
+ * RCS: @(#) $Id: tkTextMark.c,v 1.4 1999/12/14 06:52:33 hobbs Exp $
*/
#include "tkInt.h"
@@ -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));
@@ -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
diff --git a/generic/tkTextTag.c b/generic/tkTextTag.c
index 9827f92..00723ab 100644
--- a/generic/tkTextTag.c
+++ b/generic/tkTextTag.c
@@ -11,18 +11,40 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextTag.c,v 1.3 1999/04/16 01:51:24 stanton Exp $
+ * RCS: @(#) $Id: tkTextTag.c,v 1.4 1999/12/14 06:52:33 hobbs Exp $
*/
#include "default.h"
#include "tkPort.h"
-#include "tk.h"
+#include "tkInt.h"
#include "tkText.h"
/*
* Information used for parsing tag configuration information:
*/
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+
+/* The "-elide" is only provided for compatibility with TkMan 2.0,
+ * but might be removed in the future. The option "-state" provides
+ * the same functionality and is preferred.
+ */
+
+static int ElideParseProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST char *value, char *widgRec, int offset));
+static char * ElidePrintProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *widgRec, int offset,
+ Tcl_FreeProc **freeProcPtr));
+
+static Tk_CustomOption elideOption = {
+ (Tk_OptionParseProc *) ElideParseProc,
+ ElidePrintProc, (ClientData) 0
+};
+
static Tk_ConfigSpec tagConfigSpecs[] = {
{TK_CONFIG_BORDER, "-background", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, border), TK_CONFIG_NULL_OK},
@@ -31,6 +53,9 @@ static Tk_ConfigSpec tagConfigSpecs[] = {
{TK_CONFIG_STRING, "-borderwidth", (char *) NULL, (char *) NULL,
"0", Tk_Offset(TkTextTag, bdString),
TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-elide", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(TkTextTag, state),
+ TK_CONFIG_NULL_OK, &elideOption},
{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,
@@ -58,14 +83,17 @@ static Tk_ConfigSpec tagConfigSpecs[] = {
(char *) NULL, Tk_Offset(TkTextTag, spacing2String), TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-spacing3", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, spacing3String), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(TkTextTag, state),
+ TK_CONFIG_NULL_OK, &stateOption},
{TK_CONFIG_STRING, "-tabs", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, tabString), TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING, "-underline", (char *) NULL, (char *) NULL,
(char *) NULL, Tk_Offset(TkTextTag, underlineString),
TK_CONFIG_NULL_OK},
- {TK_CONFIG_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}
};
@@ -391,15 +419,6 @@ TkTextTagCmd(textPtr, interp, argc, argv)
return TCL_ERROR;
}
}
- if ((tagPtr->wrapMode != NULL)
- && (tagPtr->wrapMode != Tk_GetUid("char"))
- && (tagPtr->wrapMode != Tk_GetUid("none"))
- && (tagPtr->wrapMode != Tk_GetUid("word"))) {
- Tcl_AppendResult(interp, "bad wrap mode \"", tagPtr->wrapMode,
- "\": must be char, none, or word", (char *) NULL);
- tagPtr->wrapMode = NULL;
- return TCL_ERROR;
- }
/*
* If the "sel" tag was changed, be sure to mirror information
@@ -432,7 +451,8 @@ TkTextTagCmd(textPtr, interp, argc, argv)
|| (tagPtr->spacing3String != NULL)
|| (tagPtr->tabString != NULL)
|| (tagPtr->underlineString != NULL)
- || (tagPtr->wrapMode != NULL)) {
+ || (tagPtr->state != TK_STATE_NULL)
+ || (tagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
tagPtr->affectsDisplay = 1;
}
TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
@@ -824,7 +844,8 @@ TkTextCreateTag(textPtr, tagName)
tagPtr->tabArrayPtr = NULL;
tagPtr->underlineString = NULL;
tagPtr->underline = 0;
- tagPtr->wrapMode = NULL;
+ tagPtr->state = TK_STATE_NULL;
+ tagPtr->wrapMode = TEXT_WRAPMODE_NULL;
tagPtr->affectsDisplay = 0;
textPtr->numTags++;
Tcl_SetHashValue(hPtr, tagPtr);
@@ -1387,3 +1408,89 @@ TkTextPickCurrent(textPtr, eventPtr)
ckfree((char *) copyArrayPtr);
}
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ElideParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-elide" option. This option is an obsolete equivalent
+ * of the "-state" option. It is only added for compatibility
+ * with TkMan 2.0, but will be removed in the future.
+ *
+ * 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
+ElideParseProc(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 b;
+ register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *statePtr = TK_STATE_NULL;
+ return TCL_OK;
+ }
+ if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {
+ *statePtr = TK_STATE_NULL;
+ return TCL_ERROR;
+ }
+ *statePtr = b?TK_STATE_HIDDEN:TK_STATE_NORMAL;
+ return TCL_OK;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * ElidePrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-elide"
+ * 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 *
+ElidePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing text 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_HIDDEN) {
+ return "1";
+ } else if (*statePtr==TK_STATE_NULL) {
+ return "";
+ } else {
+ return "0";
+ }
+}
diff --git a/generic/tkTextWind.c b/generic/tkTextWind.c
index ef28b44..c43b8e8 100644
--- a/generic/tkTextWind.c
+++ b/generic/tkTextWind.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTextWind.c,v 1.3 1999/04/16 01:51:24 stanton Exp $
+ * RCS: @(#) $Id: tkTextWind.c,v 1.4 1999/12/14 06:52:33 hobbs Exp $
*/
#include "tk.h"
@@ -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));
@@ -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
@@ -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 != Tk_GetUid("none"))) {
+ && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
return 0;
}
diff --git a/generic/tkTrig.c b/generic/tkTrig.c
index d0afe90..b8a88e7 100644
--- a/generic/tkTrig.c
+++ b/generic/tkTrig.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkTrig.c,v 1.3 1999/04/16 01:51:24 stanton Exp $
+ * RCS: @(#) $Id: tkTrig.c,v 1.4 1999/12/14 06:52:33 hobbs Exp $
*/
#include <stdio.h>
@@ -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])) {
diff --git a/generic/tkUtil.c b/generic/tkUtil.c
index 226fd86..0ba1f96 100644
--- a/generic/tkUtil.c
+++ b/generic/tkUtil.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUtil.c,v 1.6 1999/08/10 05:10:52 jingham Exp $
+ * RCS: @(#) $Id: tkUtil.c,v 1.7 1999/12/14 06:52:34 hobbs Exp $
*/
#include "tkInt.h"
@@ -32,6 +32,487 @@ static Tcl_ObjType stateKeyType = {
/*
+ *--------------------------------------------------------------
+ *
+ * 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;
+}
+
+/*
*----------------------------------------------------------------------
*
* TkDrawInsetFocusHighlight --
diff --git a/generic/tkWindow.c b/generic/tkWindow.c
index 7e4d5fc..4686cb3 100644
--- a/generic/tkWindow.c
+++ b/generic/tkWindow.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWindow.c,v 1.12 1999/12/03 07:14:39 hobbs Exp $
+ * RCS: @(#) $Id: tkWindow.c,v 1.13 1999/12/14 06:52:34 hobbs Exp $
*/
#include "tkPort.h"
@@ -134,10 +134,10 @@ static TkCmd commands[] = {
*/
{"button", NULL, Tk_ButtonObjCmd, 1, 0},
- {"canvas", Tk_CanvasCmd, NULL, 1, 1},
+ {"canvas", NULL, Tk_CanvasObjCmd, 1, 1},
{"checkbutton", NULL, Tk_CheckbuttonObjCmd, 1, 0},
{"entry", NULL, Tk_EntryObjCmd, 1, 0},
- {"frame", Tk_FrameCmd, NULL, 1, 1},
+ {"frame", NULL, Tk_FrameObjCmd, 1, 1},
{"label", NULL, Tk_LabelObjCmd, 1, 0},
{"listbox", NULL, Tk_ListboxObjCmd, 1, 0},
{"menubutton", NULL, Tk_MenubuttonObjCmd, 1, 0},
@@ -146,7 +146,7 @@ static TkCmd commands[] = {
{"scale", NULL, Tk_ScaleObjCmd, 1, 0},
{"scrollbar", Tk_ScrollbarCmd, NULL, 1, 1},
{"text", Tk_TextCmd, NULL, 1, 1},
- {"toplevel", Tk_ToplevelCmd, NULL, 0, 1},
+ {"toplevel", NULL, Tk_ToplevelObjCmd, 0, 1},
/*
* Misc.
@@ -431,6 +431,11 @@ GetScreen(interp, screenName, screenPtr)
dispPtr->firstGrabEventPtr = NULL;
dispPtr->lastGrabEventPtr = NULL;
dispPtr->grabFlags = 0;
+ dispPtr->mouseButtonState = 0;
+ dispPtr->warpInProgress = 0;
+ dispPtr->warpWindow = None;
+ dispPtr->warpX = 0;
+ dispPtr->warpY = 0;
dispPtr->gridInit = 0;
dispPtr->imageId = 0;
dispPtr->packInit = 0;