summaryrefslogtreecommitdiffstats
path: root/generic/tkCanvas.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkCanvas.c')
-rw-r--r--generic/tkCanvas.c2787
1 files changed, 2325 insertions, 462 deletions
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);
+}