tkCanvas.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:173k
- /*
- * tkCanvas.c --
- *
- * This module implements canvas widgets for the Tk toolkit.
- * A canvas displays a background and a collection of graphical
- * objects such as rectangles, lines, and texts.
- *
- * Copyright (c) 1991-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
- * Copyright (c) 1998-1999 by Scriptics Corporation.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tkCanvas.c,v 1.21.2.4 2007/04/29 02:24:01 das Exp $
- */
- /* #define USE_OLD_TAG_SEARCH 1 */
- #include "default.h"
- #include "tkInt.h"
- #include "tkPort.h"
- #include "tkCanvas.h"
- #ifdef TK_NO_DOUBLE_BUFFERING
- #ifdef MAC_OSX_TK
- #include "tkMacOSXInt.h"
- #endif
- #endif /* TK_NO_DOUBLE_BUFFERING */
- /*
- * 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
- * StartTagSearch and NextItem.
- */
- typedef struct TagSearch {
- TkCanvas *canvasPtr; /* Canvas widget being searched. */
- Tk_Uid tag; /* Tag to search for. 0 means return
- * all items. */
- Tk_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. */
- } 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.
- */
- static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_CANVAS_BG_COLOR, Tk_Offset(TkCanvas, bgBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-background", "background", "Background",
- DEF_CANVAS_BG_MONO, Tk_Offset(TkCanvas, bgBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
- (char *) NULL, 0, 0},
- {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_CANVAS_BORDER_WIDTH, Tk_Offset(TkCanvas, borderWidth), 0},
- {TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough",
- DEF_CANVAS_CLOSE_ENOUGH, Tk_Offset(TkCanvas, closeEnough), 0},
- {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine",
- DEF_CANVAS_CONFINE, Tk_Offset(TkCanvas, confine), 0},
- {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_CANVAS_CURSOR, Tk_Offset(TkCanvas, cursor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-height", "height", "Height",
- DEF_CANVAS_HEIGHT, Tk_Offset(TkCanvas, height), 0},
- {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_CANVAS_HIGHLIGHT_BG,
- Tk_Offset(TkCanvas, highlightBgColorPtr), 0},
- {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_CANVAS_HIGHLIGHT, Tk_Offset(TkCanvas, highlightColorPtr), 0},
- {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness",
- DEF_CANVAS_HIGHLIGHT_WIDTH, Tk_Offset(TkCanvas, highlightWidth), 0},
- {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground",
- DEF_CANVAS_INSERT_BG, Tk_Offset(TkCanvas, textInfo.insertBorder), 0},
- {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
- DEF_CANVAS_INSERT_BD_COLOR,
- Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
- DEF_CANVAS_INSERT_BD_MONO,
- Tk_Offset(TkCanvas, textInfo.insertBorderWidth), TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
- DEF_CANVAS_INSERT_OFF_TIME, Tk_Offset(TkCanvas, insertOffTime), 0},
- {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
- 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",
- DEF_CANVAS_SCROLL_REGION, Tk_Offset(TkCanvas, regionString),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_CANVAS_SELECT_COLOR, Tk_Offset(TkCanvas, textInfo.selBorder),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_CANVAS_SELECT_MONO, Tk_Offset(TkCanvas, textInfo.selBorder),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
- DEF_CANVAS_SELECT_BD_COLOR,
- Tk_Offset(TkCanvas, textInfo.selBorderWidth), TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
- DEF_CANVAS_SELECT_BD_MONO, Tk_Offset(TkCanvas, textInfo.selBorderWidth),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_CANVAS_SELECT_FG_COLOR, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
- TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(TkCanvas, textInfo.selFgColorPtr),
- TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
- {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},
- {TK_CONFIG_PIXELS, "-width", "width", "Width",
- DEF_CANVAS_WIDTH, Tk_Offset(TkCanvas, width), 0},
- {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- DEF_CANVAS_X_SCROLL_CMD, Tk_Offset(TkCanvas, xScrollCmd),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement",
- "ScrollIncrement",
- DEF_CANVAS_X_SCROLL_INCREMENT, Tk_Offset(TkCanvas, xScrollIncrement),
- 0},
- {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
- DEF_CANVAS_Y_SCROLL_CMD, Tk_Offset(TkCanvas, yScrollCmd),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement",
- "ScrollIncrement",
- DEF_CANVAS_Y_SCROLL_INCREMENT, Tk_Offset(TkCanvas, yScrollIncrement),
- 0},
- {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0}
- };
- /*
- * List of all the item types known at present. This is *global* and
- * is protected by typeListMutex.
- */
- static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't
- * been done yet. */
- TCL_DECLARE_MUTEX(typeListMutex)
- #ifndef USE_OLD_TAG_SEARCH
- /*
- * Uids for operands in compiled advanced tag search expressions
- * Initialization is done by GetStaticUids()
- */
- typedef struct {
- Tk_Uid allUid;
- Tk_Uid currentUid;
- Tk_Uid andUid;
- Tk_Uid orUid;
- Tk_Uid xorUid;
- Tk_Uid parenUid;
- Tk_Uid negparenUid;
- Tk_Uid endparenUid;
- Tk_Uid tagvalUid;
- Tk_Uid negtagvalUid;
- } SearchUids;
- static Tcl_ThreadDataKey dataKey;
- static SearchUids *GetStaticUids _ANSI_ARGS_((void));
- #endif /* USE_OLD_TAG_SEARCH */
- /*
- * Standard item types provided by Tk:
- */
- extern Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType;
- extern Tk_ItemType tkOvalType, tkPolygonType;
- extern Tk_ItemType tkRectangleType, tkTextType, tkWindowType;
- /*
- * Prototypes for procedures defined later in this file:
- */
- static void CanvasBindProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
- static void CanvasBlinkProc _ANSI_ARGS_((ClientData clientData));
- static void CanvasCmdDeletedProc _ANSI_ARGS_((
- ClientData clientData));
- static void CanvasDoEvent _ANSI_ARGS_((TkCanvas *canvasPtr,
- XEvent *eventPtr));
- static void CanvasEventProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
- static int CanvasFetchSelection _ANSI_ARGS_((
- ClientData clientData, int offset,
- char *buffer, int maxBytes));
- static Tk_Item * CanvasFindClosest _ANSI_ARGS_((TkCanvas *canvasPtr,
- double coords[2]));
- static void CanvasFocusProc _ANSI_ARGS_((TkCanvas *canvasPtr,
- int gotFocus));
- static void CanvasLostSelection _ANSI_ARGS_((
- ClientData clientData));
- static void CanvasSelectTo _ANSI_ARGS_((TkCanvas *canvasPtr,
- Tk_Item *itemPtr, int index));
- static void CanvasSetOrigin _ANSI_ARGS_((TkCanvas *canvasPtr,
- int xOrigin, int yOrigin));
- static void CanvasUpdateScrollbars _ANSI_ARGS_((
- TkCanvas *canvasPtr));
- static int CanvasWidgetCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int argc, Tcl_Obj *CONST *argv));
- static void CanvasWorldChanged _ANSI_ARGS_((
- ClientData instanceData));
- static int ConfigureCanvas _ANSI_ARGS_((Tcl_Interp *interp,
- TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
- int flags));
- static void DestroyCanvas _ANSI_ARGS_((char *memPtr));
- static void DisplayCanvas _ANSI_ARGS_((ClientData clientData));
- static void DoItem _ANSI_ARGS_((Tcl_Interp *interp,
- Tk_Item *itemPtr, Tk_Uid tag));
- static void EventuallyRedrawItem _ANSI_ARGS_((Tk_Canvas canvas,
- Tk_Item *itemPtr));
- #ifdef USE_OLD_TAG_SEARCH
- static int FindItems _ANSI_ARGS_((Tcl_Interp *interp,
- TkCanvas *canvasPtr, int argc, Tcl_Obj *CONST *argv,
- Tcl_Obj *newTagObj, int first));
- #else /* USE_OLD_TAG_SEARCH */
- static int FindItems _ANSI_ARGS_((Tcl_Interp *interp,
- TkCanvas *canvasPtr, int argc, 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, Tcl_Obj *CONST *argv, Tk_Uid uid,
- int enclosed));
- static double GridAlign _ANSI_ARGS_((double coord, double spacing));
- static CONST char** GetStringsFromObjs _ANSI_ARGS_((int argc,
- Tcl_Obj *CONST *objv));
- static void InitCanvas _ANSI_ARGS_((void));
- #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 Tcl_Obj * ScrollFractions _ANSI_ARGS_((int screen1,
- int screen2, int object1, int object2));
- #ifdef USE_OLD_TAG_SEARCH
- static void RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr,
- Tcl_Obj *tag, Tk_Item *prevPtr));
- static Tk_Item * StartTagSearch _ANSI_ARGS_((TkCanvas *canvasPtr,
- Tcl_Obj *tag, TagSearch *searchPtr));
- #else /* USE_OLD_TAG_SEARCH */
- static int RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr,
- Tcl_Obj *tag, Tk_Item *prevPtr,
- TagSearch **searchPtrPtr));
- static void TagSearchExprInit _ANSI_ARGS_ ((
- TagSearchExpr **exprPtrPtr));
- static void TagSearchExprDestroy _ANSI_ARGS_((TagSearchExpr *expr));
- static void TagSearchDestroy _ANSI_ARGS_((TagSearch *searchPtr));
- static int TagSearchScan _ANSI_ARGS_((TkCanvas *canvasPtr,
- Tcl_Obj *tag, TagSearch **searchPtrPtr));
- static int TagSearchScanExpr _ANSI_ARGS_((Tcl_Interp *interp,
- TagSearch *searchPtr, TagSearchExpr *expr));
- static int TagSearchEvalExpr _ANSI_ARGS_((TagSearchExpr *expr,
- Tk_Item *itemPtr));
- static Tk_Item * TagSearchFirst _ANSI_ARGS_((TagSearch *searchPtr));
- static Tk_Item * TagSearchNext _ANSI_ARGS_((TagSearch *searchPtr));
- #endif /* USE_OLD_TAG_SEARCH */
- /*
- * The structure below defines canvas class behavior by means of procedures
- * that can be invoked from generic window code.
- */
- static Tk_ClassProcs canvasClass = {
- sizeof(Tk_ClassProcs), /* size */
- CanvasWorldChanged, /* worldChangedProc */
- };
- /*
- *--------------------------------------------------------------
- *
- * Tk_CanvasObjCmd --
- *
- * This procedure is invoked to process the "canvas" Tcl
- * command. See the user documentation for details on what
- * it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
- int
- Tk_CanvasObjCmd(clientData, interp, argc, argv)
- ClientData clientData; /* Main window associated with
- * interpreter. */
- Tcl_Interp *interp; /* Current interpreter. */
- int argc; /* Number of arguments. */
- Tcl_Obj *CONST argv[]; /* Argument objects. */
- {
- Tk_Window tkwin = (Tk_Window) clientData;
- TkCanvas *canvasPtr;
- Tk_Window new;
- if (typeList == NULL) {
- InitCanvas();
- }
- if (argc < 2) {
- Tcl_WrongNumArgs(interp, 1, argv, "pathName ?options?");
- return TCL_ERROR;
- }
- new = Tk_CreateWindowFromPath(interp, tkwin,
- Tcl_GetString(argv[1]), (char *) NULL);
- if (new == NULL) {
- return TCL_ERROR;
- }
- /*
- * Initialize fields that won't be initialized by ConfigureCanvas,
- * or which ConfigureCanvas expects to have reasonable values
- * (e.g. resource pointers).
- */
- canvasPtr = (TkCanvas *) ckalloc(sizeof(TkCanvas));
- canvasPtr->tkwin = new;
- canvasPtr->display = Tk_Display(new);
- canvasPtr->interp = interp;
- canvasPtr->widgetCmd = Tcl_CreateObjCommand(interp,
- Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd,
- (ClientData) canvasPtr, CanvasCmdDeletedProc);
- canvasPtr->firstItemPtr = NULL;
- canvasPtr->lastItemPtr = NULL;
- canvasPtr->borderWidth = 0;
- canvasPtr->bgBorder = NULL;
- canvasPtr->relief = TK_RELIEF_FLAT;
- canvasPtr->highlightWidth = 0;
- canvasPtr->highlightBgColorPtr = NULL;
- canvasPtr->highlightColorPtr = NULL;
- canvasPtr->inset = 0;
- canvasPtr->pixmapGC = None;
- canvasPtr->width = None;
- canvasPtr->height = None;
- canvasPtr->confine = 0;
- canvasPtr->textInfo.selBorder = NULL;
- canvasPtr->textInfo.selBorderWidth = 0;
- canvasPtr->textInfo.selFgColorPtr = NULL;
- canvasPtr->textInfo.selItemPtr = NULL;
- canvasPtr->textInfo.selectFirst = -1;
- canvasPtr->textInfo.selectLast = -1;
- canvasPtr->textInfo.anchorItemPtr = NULL;
- canvasPtr->textInfo.selectAnchor = 0;
- canvasPtr->textInfo.insertBorder = NULL;
- canvasPtr->textInfo.insertWidth = 0;
- canvasPtr->textInfo.insertBorderWidth = 0;
- canvasPtr->textInfo.focusItemPtr = NULL;
- canvasPtr->textInfo.gotFocus = 0;
- canvasPtr->textInfo.cursorOn = 0;
- canvasPtr->insertOnTime = 0;
- canvasPtr->insertOffTime = 0;
- canvasPtr->insertBlinkHandler = (Tcl_TimerToken) NULL;
- canvasPtr->xOrigin = canvasPtr->yOrigin = 0;
- canvasPtr->drawableXOrigin = canvasPtr->drawableYOrigin = 0;
- canvasPtr->bindingTable = NULL;
- canvasPtr->currentItemPtr = NULL;
- canvasPtr->newCurrentPtr = NULL;
- canvasPtr->closeEnough = 0.0;
- canvasPtr->pickEvent.type = LeaveNotify;
- canvasPtr->pickEvent.xcrossing.x = 0;
- canvasPtr->pickEvent.xcrossing.y = 0;
- canvasPtr->state = 0;
- canvasPtr->xScrollCmd = NULL;
- canvasPtr->yScrollCmd = NULL;
- canvasPtr->scrollX1 = 0;
- canvasPtr->scrollY1 = 0;
- canvasPtr->scrollX2 = 0;
- canvasPtr->scrollY2 = 0;
- canvasPtr->regionString = NULL;
- canvasPtr->xScrollIncrement = 0;
- canvasPtr->yScrollIncrement = 0;
- canvasPtr->scanX = 0;
- canvasPtr->scanXOrigin = 0;
- canvasPtr->scanY = 0;
- canvasPtr->scanYOrigin = 0;
- canvasPtr->hotPtr = NULL;
- canvasPtr->hotPrevPtr = NULL;
- canvasPtr->cursor = None;
- canvasPtr->takeFocus = NULL;
- canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(new));
- canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(new));
- canvasPtr->flags = 0;
- canvasPtr->nextId = 1;
- 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");
- Tk_SetClassProcs(canvasPtr->tkwin, &canvasClass, (ClientData) canvasPtr);
- Tk_CreateEventHandler(canvasPtr->tkwin,
- ExposureMask|StructureNotifyMask|FocusChangeMask,
- CanvasEventProc, (ClientData) canvasPtr);
- Tk_CreateEventHandler(canvasPtr->tkwin, KeyPressMask|KeyReleaseMask
- |ButtonPressMask|ButtonReleaseMask|EnterWindowMask
- |LeaveWindowMask|PointerMotionMask|VirtualEventMask,
- CanvasBindProc, (ClientData) canvasPtr);
- Tk_CreateSelHandler(canvasPtr->tkwin, XA_PRIMARY, XA_STRING,
- CanvasFetchSelection, (ClientData) canvasPtr, XA_STRING);
- if (ConfigureCanvas(interp, canvasPtr, argc-2, argv+2, 0) != TCL_OK) {
- goto error;
- }
- Tcl_SetResult(interp, Tk_PathName(canvasPtr->tkwin), TCL_STATIC);
- return TCL_OK;
- error:
- Tk_DestroyWindow(canvasPtr->tkwin);
- return TCL_ERROR;
- }
- /*
- *--------------------------------------------------------------
- *
- * CanvasWidgetCmd --
- *
- * This procedure is invoked to process the Tcl command
- * that corresponds to a widget managed by this module.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
- static int
- CanvasWidgetCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Information about canvas
- * widget. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) clientData;
- int c, length, 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 CONST 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 (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
- return TCL_ERROR;
- }
- if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
- &index) != TCL_OK) {
- return TCL_ERROR;
- }
- Tcl_Preserve((ClientData) canvasPtr);
- result = TCL_OK;
- switch ((enum options) index) {
- case CANV_ADDTAG: {
- if (objc < 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "tag searchCommand ?arg arg ...?");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- result = FindItems(interp, canvasPtr, objc, objv, objv[2], 3);
- #else /* USE_OLD_TAG_SEARCH */
- result = FindItems(interp, canvasPtr, objc, objv, objv[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 (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?tagOrId ...?");
- result = TCL_ERROR;
- goto done;
- }
- gotAny = 0;
- for (i = 2; i < objc; i++) {
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[i], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[i], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if ((itemPtr->x1 >= itemPtr->x2)
- || (itemPtr->y1 >= itemPtr->y2)) {
- continue;
- }
- if (!gotAny) {
- x1 = itemPtr->x1;
- y1 = itemPtr->y1;
- x2 = itemPtr->x2;
- y2 = itemPtr->y2;
- gotAny = 1;
- } else {
- if (itemPtr->x1 < x1) {
- x1 = itemPtr->x1;
- }
- if (itemPtr->y1 < y1) {
- y1 = itemPtr->y1;
- }
- if (itemPtr->x2 > x2) {
- x2 = itemPtr->x2;
- }
- if (itemPtr->y2 > y2) {
- y2 = itemPtr->y2;
- }
- }
- }
- }
- if (gotAny) {
- char buf[TCL_INTEGER_SPACE * 4];
-
- sprintf(buf, "%d %d %d %d", x1, y1, x2, y2);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
- break;
- }
- case CANV_BIND: {
- ClientData object;
- if ((objc < 3) || (objc > 5)) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?sequence? ?command?");
- result = TCL_ERROR;
- goto done;
- }
- /*
- * Figure out what object to use for the binding (individual
- * item vs. tag).
- */
- object = 0;
- #ifdef USE_OLD_TAG_SEARCH
- if (isdigit(UCHAR(Tcl_GetString(objv[2])[0]))) {
- int id;
- char *end;
- Tcl_HashEntry *entryPtr;
- id = strtoul(Tcl_GetString(objv[2]), &end, 0);
- if (*end != 0) {
- goto bindByTag;
- }
- entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id);
- if (entryPtr != NULL) {
- itemPtr = (Tk_Item *) Tcl_GetHashValue(entryPtr);
- object = (ClientData) itemPtr;
- }
- if (object == 0) {
- Tcl_AppendResult(interp, "item "", Tcl_GetString(objv[2]),
- "" doesn't exist", (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- } else {
- bindByTag:
- object = (ClientData) Tk_GetUid(Tcl_GetString(objv[2]));
- }
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[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(objv[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
- * one.
- */
- if (canvasPtr->bindingTable == NULL) {
- canvasPtr->bindingTable = Tk_CreateBindingTable(interp);
- }
- if (objc == 5) {
- int append = 0;
- unsigned long mask;
- char* argv4 = Tcl_GetStringFromObj(objv[4],NULL);
- if (argv4[0] == 0) {
- result = Tk_DeleteBinding(interp, canvasPtr->bindingTable,
- object, Tcl_GetStringFromObj(objv[3], NULL));
- goto done;
- }
- #ifndef USE_OLD_TAG_SEARCH
- if (searchPtr->type == 4) {
- /*
- * if new tag expression, then insert in linked list
- */
- TagSearchExpr *expr, **lastPtr;
- lastPtr = &(canvasPtr->bindTagExprs);
- while ((expr = *lastPtr) != NULL) {
- if (expr->uid == searchPtr->expr->uid) {
- break;
- }
- lastPtr = &(expr->next);
- }
- if (!expr) {
- /*
- * transfer ownership of expr to bindTagExprs list
- */
- *lastPtr = searchPtr->expr;
- searchPtr->expr->next = NULL;
- /*
- * flag in TagSearch that expr has changed ownership
- * so that TagSearchDestroy doesn't try to free it
- */
- searchPtr->expr = NULL;
- }
- }
- #endif /* not USE_OLD_TAG_SEARCH */
- if (argv4[0] == '+') {
- argv4++;
- append = 1;
- }
- mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,
- object, Tcl_GetStringFromObj(objv[3],NULL), argv4, append);
- if (mask == 0) {
- result = TCL_ERROR;
- goto done;
- }
- if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
- |Button2MotionMask|Button3MotionMask|Button4MotionMask
- |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
- |EnterWindowMask|LeaveWindowMask|KeyPressMask
- |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
- Tk_DeleteBinding(interp, canvasPtr->bindingTable,
- object, Tcl_GetStringFromObj(objv[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);
- result = TCL_ERROR;
- goto done;
- }
- } else if (objc == 4) {
- CONST char *command;
-
- command = Tk_GetBinding(interp, canvasPtr->bindingTable,
- object, Tcl_GetStringFromObj(objv[3], NULL));
- if (command == NULL) {
- CONST char *string;
- string = Tcl_GetStringResult(interp);
- /*
- * Ignore missing binding errors. This is a special hack
- * that relies on the error message returned by FindSequence
- * in tkBind.c.
- */
- if (string[0] != ' ') {
- result = TCL_ERROR;
- goto done;
- } else {
- Tcl_ResetResult(interp);
- }
- } else {
- Tcl_SetResult(interp, (char *) command, TCL_STATIC);
- }
- } else {
- Tk_GetAllBindings(interp, canvasPtr->bindingTable, object);
- }
- break;
- }
- case CANV_CANVASX: {
- int x;
- double grid;
- char buf[TCL_DOUBLE_SPACE];
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "screenx ?gridspacing?");
- result = TCL_ERROR;
- goto done;
- }
- if (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, objv[2], &x) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
- if (objc == 4) {
- if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[3],
- &grid) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
- } else {
- grid = 0.0;
- }
- x += canvasPtr->xOrigin;
- Tcl_PrintDouble(interp, GridAlign((double) x, grid), buf);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- break;
- }
- case CANV_CANVASY: {
- int y;
- double grid;
- char buf[TCL_DOUBLE_SPACE];
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "screeny ?gridspacing?");
- result = TCL_ERROR;
- goto done;
- }
- if (Tk_GetPixelsFromObj(interp, canvasPtr->tkwin, objv[2], &y) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
- if (objc == 4) {
- if (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
- objv[3], &grid) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
- } else {
- grid = 0.0;
- }
- y += canvasPtr->yOrigin;
- Tcl_PrintDouble(interp, GridAlign((double) y, grid), buf);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- break;
- }
- case CANV_CGET: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "option");
- result = TCL_ERROR;
- goto done;
- }
- result = Tk_ConfigureValue(interp, canvasPtr->tkwin, configSpecs,
- (char *) canvasPtr, Tcl_GetString(objv[2]), 0);
- break;
- }
- case CANV_CONFIGURE: {
- if (objc == 2) {
- result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,
- (char *) canvasPtr, (char *) NULL, 0);
- } else if (objc == 3) {
- result = Tk_ConfigureInfo(interp, canvasPtr->tkwin, configSpecs,
- (char *) canvasPtr, Tcl_GetString(objv[2]), 0);
- } else {
- result = ConfigureCanvas(interp, canvasPtr, objc-2, objv+2,
- TK_CONFIG_ARGV_ONLY);
- }
- break;
- }
- case CANV_COORDS: {
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?x y x y ...?");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- itemPtr = TagSearchFirst(searchPtr);
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr != NULL) {
- if (objc != 3) {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- }
- if (itemPtr->typePtr->coordProc != NULL) {
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = (*itemPtr->typePtr->coordProc)(interp,
- (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3);
- } else {
- CONST char **args = GetStringsFromObjs(objc-3, objv+3);
- result = (*itemPtr->typePtr->coordProc)(interp,
- (Tk_Canvas) canvasPtr, itemPtr, objc-3, (Tcl_Obj **) args);
- if (args) ckfree((char *) args);
- }
- }
- if (objc != 3) {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- }
- }
- 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 (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg arg ...?");
- result = TCL_ERROR;
- goto done;
- }
- arg = Tcl_GetStringFromObj(objv[2], &length);
- c = arg[0];
- Tcl_MutexLock(&typeListMutex);
- for (typePtr = typeList; typePtr != NULL; typePtr = typePtr->nextPtr) {
- if ((c == typePtr->name[0])
- && (strncmp(arg, typePtr->name, (unsigned) length) == 0)) {
- if (matchPtr != NULL) {
- Tcl_MutexUnlock(&typeListMutex);
- badType:
- Tcl_AppendResult(interp,
- "unknown or ambiguous item type "",
- arg, """, (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- matchPtr = typePtr;
- }
- }
- /*
- * Can unlock now because we no longer look at the fields of
- * the matched item type that are potentially modified by
- * other threads.
- */
- Tcl_MutexUnlock(&typeListMutex);
- if (matchPtr == NULL) {
- goto badType;
- }
- if (objc < 4) {
- /*
- * Allow more specific error return.
- */
- Tcl_WrongNumArgs(interp, 3, objv, "coords ?arg arg ...?");
- result = TCL_ERROR;
- goto done;
- }
- typePtr = matchPtr;
- itemPtr = (Tk_Item *) ckalloc((unsigned) typePtr->itemSize);
- itemPtr->id = canvasPtr->nextId;
- canvasPtr->nextId++;
- itemPtr->tagPtr = itemPtr->staticTagSpace;
- itemPtr->tagSpace = TK_TAG_SPACE;
- itemPtr->numTags = 0;
- itemPtr->typePtr = typePtr;
- itemPtr->state = TK_STATE_NULL;
- itemPtr->redraw_flags = 0;
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = (*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, objc-3, objv+3);
- } else {
- CONST char **args = GetStringsFromObjs(objc-3, objv+3);
- result = (*typePtr->createProc)(interp, (Tk_Canvas) canvasPtr,
- itemPtr, objc-3, (Tcl_Obj **) args);
- if (args) ckfree((char *) args);
- }
- if (result != TCL_OK) {
- ckfree((char *) itemPtr);
- result = TCL_ERROR;
- goto done;
- }
- itemPtr->nextPtr = NULL;
- entryPtr = Tcl_CreateHashEntry(&canvasPtr->idTable,
- (char *) itemPtr->id, &isNew);
- Tcl_SetHashValue(entryPtr, itemPtr);
- itemPtr->prevPtr = canvasPtr->lastItemPtr;
- canvasPtr->hotPtr = itemPtr;
- canvasPtr->hotPrevPtr = canvasPtr->lastItemPtr;
- if (canvasPtr->lastItemPtr == NULL) {
- canvasPtr->firstItemPtr = itemPtr;
- } else {
- canvasPtr->lastItemPtr->nextPtr = itemPtr;
- }
- canvasPtr->lastItemPtr = itemPtr;
- 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);
- break;
- }
- case CANV_DCHARS: {
- int first, last;
- int x1,x2,y1,y2;
- if ((objc != 4) && (objc != 5)) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId first ?last?");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if ((itemPtr->typePtr->indexProc == NULL)
- || (itemPtr->typePtr->dCharsProc == NULL)) {
- continue;
- }
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, (char *) objv[3], &first);
- } else {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, Tcl_GetStringFromObj(objv[3], NULL), &first);
- }
- if (result != TCL_OK) {
- goto done;
- }
- if (objc == 5) {
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, (char *) objv[4], &last);
- } else {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, Tcl_GetStringFromObj(objv[4], NULL), &last);
- }
- if (result != TCL_OK) {
- goto done;
- }
- } else {
- last = first;
- }
- /*
- * Redraw both item's old and new areas: it's possible
- * that a delete could result in a new area larger than
- * the old area. Except if the insertProc sets the
- * TK_ITEM_DONT_REDRAW flag, nothing more needs to be done.
- */
- x1 = itemPtr->x1; y1 = itemPtr->y1;
- x2 = itemPtr->x2; y2 = itemPtr->y2;
- itemPtr->redraw_flags &= ~TK_ITEM_DONT_REDRAW;
- (*itemPtr->typePtr->dCharsProc)((Tk_Canvas) canvasPtr,
- itemPtr, first, last);
- 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;
- }
- break;
- }
- case CANV_DELETE: {
- int i;
- Tcl_HashEntry *entryPtr;
- for (i = 2; i < objc; i++) {
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[i], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[i], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- if (canvasPtr->bindingTable != NULL) {
- Tk_DeleteAllBindings(canvasPtr->bindingTable,
- (ClientData) itemPtr);
- }
- (*itemPtr->typePtr->deleteProc)((Tk_Canvas) canvasPtr, itemPtr,
- canvasPtr->display);
- if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
- ckfree((char *) itemPtr->tagPtr);
- }
- entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable,
- (char *) itemPtr->id);
- Tcl_DeleteHashEntry(entryPtr);
- if (itemPtr->nextPtr != NULL) {
- itemPtr->nextPtr->prevPtr = itemPtr->prevPtr;
- }
- if (itemPtr->prevPtr != NULL) {
- itemPtr->prevPtr->nextPtr = itemPtr->nextPtr;
- }
- if (canvasPtr->firstItemPtr == itemPtr) {
- canvasPtr->firstItemPtr = itemPtr->nextPtr;
- if (canvasPtr->firstItemPtr == NULL) {
- canvasPtr->lastItemPtr = NULL;
- }
- }
- if (canvasPtr->lastItemPtr == itemPtr) {
- canvasPtr->lastItemPtr = itemPtr->prevPtr;
- }
- ckfree((char *) itemPtr);
- if (itemPtr == canvasPtr->currentItemPtr) {
- canvasPtr->currentItemPtr = NULL;
- canvasPtr->flags |= REPICK_NEEDED;
- }
- if (itemPtr == canvasPtr->newCurrentPtr) {
- canvasPtr->newCurrentPtr = NULL;
- canvasPtr->flags |= REPICK_NEEDED;
- }
- if (itemPtr == canvasPtr->textInfo.focusItemPtr) {
- canvasPtr->textInfo.focusItemPtr = NULL;
- }
- if (itemPtr == canvasPtr->textInfo.selItemPtr) {
- canvasPtr->textInfo.selItemPtr = NULL;
- }
- if ((itemPtr == canvasPtr->hotPtr)
- || (itemPtr == canvasPtr->hotPrevPtr)) {
- canvasPtr->hotPtr = NULL;
- }
- }
- }
- break;
- }
- case CANV_DTAG: {
- Tk_Uid tag;
- int i;
- if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?tagToDelete?");
- result = TCL_ERROR;
- goto done;
- }
- if (objc == 4) {
- tag = Tk_GetUid(Tcl_GetStringFromObj(objv[3], NULL));
- } else {
- tag = Tk_GetUid(Tcl_GetStringFromObj(objv[2], NULL));
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- for (i = itemPtr->numTags-1; i >= 0; i--) {
- if (itemPtr->tagPtr[i] == tag) {
- itemPtr->tagPtr[i] = itemPtr->tagPtr[itemPtr->numTags-1];
- itemPtr->numTags--;
- }
- }
- }
- break;
- }
- case CANV_FIND: {
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "searchCommand ?arg arg ...?");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- result = FindItems(interp, canvasPtr, objc, objv, (Tcl_Obj *) NULL, 2);
- #else /* USE_OLD_TAG_SEARCH */
- result = FindItems(interp, canvasPtr, objc, objv,
- (Tcl_Obj *) NULL, 2, &searchPtr);
- #endif /* USE_OLD_TAG_SEARCH */
- break;
- }
- case CANV_FOCUS: {
- if (objc > 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "?tagOrId?");
- result = TCL_ERROR;
- goto done;
- }
- itemPtr = canvasPtr->textInfo.focusItemPtr;
- if (objc == 2) {
- if (itemPtr != NULL) {
- char buf[TCL_INTEGER_SPACE];
-
- sprintf(buf, "%d", itemPtr->id);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
- goto done;
- }
- if ((itemPtr != NULL) && (canvasPtr->textInfo.gotFocus)) {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- }
- if (Tcl_GetStringFromObj(objv[2], NULL)[0] == 0) {
- canvasPtr->textInfo.focusItemPtr = NULL;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr->typePtr->icursorProc != NULL) {
- break;
- }
- }
- if (itemPtr == NULL) {
- goto done;
- }
- canvasPtr->textInfo.focusItemPtr = itemPtr;
- if (canvasPtr->textInfo.gotFocus) {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- }
- break;
- }
- case CANV_GETTAGS: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- itemPtr = TagSearchFirst(searchPtr);
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr != NULL) {
- int i;
- for (i = 0; i < itemPtr->numTags; i++) {
- Tcl_AppendElement(interp, (char *) itemPtr->tagPtr[i]);
- }
- }
- break;
- }
- case CANV_ICURSOR: {
- int index;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if ((itemPtr->typePtr->indexProc == NULL)
- || (itemPtr->typePtr->icursorProc == NULL)) {
- goto done;
- }
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, (char *) objv[3], &index);
- } else {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, Tcl_GetStringFromObj(objv[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)) {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- }
- }
- break;
- }
- case CANV_INDEX: {
- int index;
- char buf[TCL_INTEGER_SPACE];
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId string");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr->typePtr->indexProc != NULL) {
- break;
- }
- }
- if (itemPtr == NULL) {
- Tcl_AppendResult(interp, "can't find an indexable item "",
- Tcl_GetStringFromObj(objv[2], NULL), """, (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, (char *) objv[3], &index);
- } else {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, Tcl_GetStringFromObj(objv[3], NULL), &index);
- }
- if (result != TCL_OK) {
- goto done;
- }
- sprintf(buf, "%d", index);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- break;
- }
- case CANV_INSERT: {
- int beforeThis;
- int x1,x2,y1,y2;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId beforeThis string");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if ((itemPtr->typePtr->indexProc == NULL)
- || (itemPtr->typePtr->insertProc == NULL)) {
- continue;
- }
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, (char *) objv[3], &beforeThis);
- } else {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, Tcl_GetStringFromObj(objv[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. Except if the
- * insertProc sets the TK_ITEM_DONT_REDRAW flag, nothing
- * more needs to be done.
- */
- 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 *) objv[4]);
- } else {
- (*itemPtr->typePtr->insertProc)((Tk_Canvas) canvasPtr,
- itemPtr, beforeThis, Tcl_GetStringFromObj(objv[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;
- }
- break;
- }
- case CANV_ITEMCGET: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId option");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- itemPtr = TagSearchFirst(searchPtr);
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr != NULL) {
- result = Tk_ConfigureValue(canvasPtr->interp, canvasPtr->tkwin,
- itemPtr->typePtr->configSpecs, (char *) itemPtr,
- Tcl_GetStringFromObj(objv[3], NULL), 0);
- }
- break;
- }
- case CANV_ITEMCONFIGURE: {
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?option value ...?");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if (objc == 3) {
- result = Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin,
- itemPtr->typePtr->configSpecs, (char *) itemPtr,
- (char *) NULL, 0);
- } else if (objc == 4) {
- result = Tk_ConfigureInfo(canvasPtr->interp, canvasPtr->tkwin,
- itemPtr->typePtr->configSpecs, (char *) itemPtr,
- Tcl_GetString(objv[3]), 0);
- } else {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = (*itemPtr->typePtr->configProc)(interp,
- (Tk_Canvas) canvasPtr, itemPtr, objc-3, objv+3,
- TK_CONFIG_ARGV_ONLY);
- } else {
- CONST char **args = GetStringsFromObjs(objc-3, objv+3);
- result = (*itemPtr->typePtr->configProc)(interp,
- (Tk_Canvas) canvasPtr, itemPtr, objc-3, (Tcl_Obj **) args,
- TK_CONFIG_ARGV_ONLY);
- if (args) ckfree((char *) args);
- }
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- canvasPtr->flags |= REPICK_NEEDED;
- }
- if ((result != TCL_OK) || (objc < 5)) {
- break;
- }
- }
- break;
- }
- case CANV_LOWER: {
- Tk_Item *itemPtr;
- if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?belowThis?");
- result = TCL_ERROR;
- goto done;
- }
- /*
- * First find the item just after which we'll insert the
- * named items.
- */
- if (objc == 3) {
- itemPtr = NULL;
- } else {
- #ifdef USE_OLD_TAG_SEARCH
- itemPtr = StartTagSearch(canvasPtr, objv[3], &search);
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[3], &searchPtr)) != TCL_OK) {
- goto done;
- }
- itemPtr = TagSearchFirst(searchPtr);
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr == NULL) {
- Tcl_AppendResult(interp, "tag "", Tcl_GetString(objv[3]),
- "" doesn't match any items", (char *) NULL);
- goto done;
- }
- itemPtr = itemPtr->prevPtr;
- }
- #ifdef USE_OLD_TAG_SEARCH
- RelinkItems(canvasPtr, objv[2], itemPtr);
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = RelinkItems(canvasPtr, objv[2], itemPtr, &searchPtr)) != TCL_OK) {
- goto done;
- }
- #endif /* USE_OLD_TAG_SEARCH */
- break;
- }
- case CANV_MOVE: {
- double xAmount, yAmount;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId xAmount yAmount");
- result = TCL_ERROR;
- goto done;
- }
- if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr, objv[3],
- &xAmount) != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp,
- (Tk_Canvas) canvasPtr, objv[4], &yAmount) != TCL_OK)) {
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- (void) (*itemPtr->typePtr->translateProc)((Tk_Canvas) canvasPtr,
- itemPtr, xAmount, yAmount);
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- canvasPtr->flags |= REPICK_NEEDED;
- }
- break;
- }
- case CANV_POSTSCRIPT: {
- CONST char **args = GetStringsFromObjs(objc, objv);
- result = TkCanvPostscriptCmd(canvasPtr, interp, objc, args);
- if (args) ckfree((char *) args);
- break;
- }
- case CANV_RAISE: {
- Tk_Item *prevPtr;
- if ((objc != 3) && (objc != 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId ?aboveThis?");
- result = TCL_ERROR;
- goto done;
- }
- /*
- * First find the item just after which we'll insert the
- * named items.
- */
- if (objc == 3) {
- prevPtr = canvasPtr->lastItemPtr;
- } else {
- prevPtr = NULL;
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[3], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[3], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- prevPtr = itemPtr;
- }
- if (prevPtr == NULL) {
- Tcl_AppendResult(interp, "tagOrId "", Tcl_GetStringFromObj(objv[3], NULL),
- "" doesn't match any items", (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- }
- #ifdef USE_OLD_TAG_SEARCH
- RelinkItems(canvasPtr, objv[2], prevPtr);
- #else /* USE_OLD_TAG_SEARCH */
- result = RelinkItems(canvasPtr, objv[2], prevPtr, &searchPtr);
- if (result != TCL_OK) {
- goto done;
- }
- #endif /* USE_OLD_TAG_SEARCH */
- break;
- }
- case CANV_SCALE: {
- double xOrigin, yOrigin, xScale, yScale;
- if (objc != 7) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId xOrigin yOrigin xScale yScale");
- result = TCL_ERROR;
- goto done;
- }
- if ((Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
- objv[3], &xOrigin) != TCL_OK)
- || (Tk_CanvasGetCoordFromObj(interp, (Tk_Canvas) canvasPtr,
- objv[4], &yOrigin) != TCL_OK)
- || (Tcl_GetDoubleFromObj(interp, objv[5], &xScale) != TCL_OK)
- || (Tcl_GetDoubleFromObj(interp, objv[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);
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- (void) (*itemPtr->typePtr->scaleProc)((Tk_Canvas) canvasPtr,
- itemPtr, xOrigin, yOrigin, xScale, yScale);
- EventuallyRedrawItem((Tk_Canvas) canvasPtr, itemPtr);
- canvasPtr->flags |= REPICK_NEEDED;
- }
- break;
- }
- case CANV_SCAN: {
- int x, y, gain=10;
- static CONST char *optionStrings[] = {
- "mark", "dragto", NULL
- };
- if (objc < 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x y ?dragGain?");
- result = TCL_ERROR;
- } else if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings,
- "scan option", 0, &index) != TCL_OK) {
- result = TCL_ERROR;
- } else if ((objc != 5) && (objc != 5+index)) {
- Tcl_WrongNumArgs(interp, 3, objv, index?"x y ?gain?":"x y");
- result = TCL_ERROR;
- } else if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK)
- || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){
- result = TCL_ERROR;
- } else if ((objc == 6) &&
- (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK)) {
- result = TCL_ERROR;
- } else if (!index) {
- canvasPtr->scanX = x;
- canvasPtr->scanXOrigin = canvasPtr->xOrigin;
- canvasPtr->scanY = y;
- canvasPtr->scanYOrigin = canvasPtr->yOrigin;
- } else {
- int newXOrigin, newYOrigin, tmp;
- /*
- * Compute a new view origin for the canvas, amplifying the
- * mouse motion.
- */
- tmp = canvasPtr->scanXOrigin - gain*(x - canvasPtr->scanX)
- - canvasPtr->scrollX1;
- newXOrigin = canvasPtr->scrollX1 + tmp;
- tmp = canvasPtr->scanYOrigin - gain*(y - canvasPtr->scanY)
- - canvasPtr->scrollY1;
- newYOrigin = canvasPtr->scrollY1 + tmp;
- CanvasSetOrigin(canvasPtr, newXOrigin, newYOrigin);
- }
- break;
- }
- case CANV_SELECT: {
- int index, optionindex;
- static CONST char *optionStrings[] = {
- "adjust", "clear", "from", "item", "to", NULL
- };
- enum options {
- CANV_ADJUST, CANV_CLEAR, CANV_FROM, CANV_ITEM, CANV_TO
- };
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "option ?tagOrId? ?arg?");
- result = TCL_ERROR;
- goto done;
- }
- if (objc >= 4) {
- #ifdef USE_OLD_TAG_SEARCH
- for (itemPtr = StartTagSearch(canvasPtr, objv[3], &search);
- itemPtr != NULL; itemPtr = NextItem(&search)) {
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[3], &searchPtr)) != TCL_OK) {
- goto done;
- }
- for (itemPtr = TagSearchFirst(searchPtr);
- itemPtr != NULL; itemPtr = TagSearchNext(searchPtr)) {
- #endif /* USE_OLD_TAG_SEARCH */
- if ((itemPtr->typePtr->indexProc != NULL)
- && (itemPtr->typePtr->selectionProc != NULL)){
- break;
- }
- }
- if (itemPtr == NULL) {
- Tcl_AppendResult(interp,
- "can't find an indexable and selectable item "",
- Tcl_GetStringFromObj(objv[3], NULL), """, (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- }
- if (objc == 5) {
- if (itemPtr->typePtr->alwaysRedraw & TK_CONFIG_OBJS) {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, (char *) objv[4], &index);
- } else {
- result = itemPtr->typePtr->indexProc(interp, (Tk_Canvas) canvasPtr,
- itemPtr, Tcl_GetStringFromObj(objv[4], NULL), &index);
- }
- if (result != TCL_OK) {
- goto done;
- }
- }
- if (Tcl_GetIndexFromObj(interp, objv[2], optionStrings, "select option", 0,
- &optionindex) != TCL_OK) {
- result = TCL_ERROR;
- goto done;
- }
- switch ((enum options) optionindex) {
- case CANV_ADJUST: {
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index");
- result = TCL_ERROR;
- goto done;
- }
- if (canvasPtr->textInfo.selItemPtr == itemPtr) {
- if (index < (canvasPtr->textInfo.selectFirst
- + canvasPtr->textInfo.selectLast)/2) {
- canvasPtr->textInfo.selectAnchor =
- canvasPtr->textInfo.selectLast + 1;
- } else {
- canvasPtr->textInfo.selectAnchor =
- canvasPtr->textInfo.selectFirst;
- }
- }
- CanvasSelectTo(canvasPtr, itemPtr, index);
- break;
- }
- case CANV_CLEAR: {
- if (objc != 3) {
- Tcl_AppendResult(interp, 3, objv, (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- if (canvasPtr->textInfo.selItemPtr != NULL) {
- EventuallyRedrawItem((Tk_Canvas) canvasPtr,
- canvasPtr->textInfo.selItemPtr);
- canvasPtr->textInfo.selItemPtr = NULL;
- }
- goto done;
- break;
- }
- case CANV_FROM: {
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 3, objv, "tagOrId index");
- result = TCL_ERROR;
- goto done;
- }
- canvasPtr->textInfo.anchorItemPtr = itemPtr;
- canvasPtr->textInfo.selectAnchor = index;
- break;
- }
- case CANV_ITEM: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL);
- result = TCL_ERROR;
- goto done;
- }
- if (canvasPtr->textInfo.selItemPtr != NULL) {
- char buf[TCL_INTEGER_SPACE];
-
- sprintf(buf, "%d", canvasPtr->textInfo.selItemPtr->id);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- }
- break;
- }
- case CANV_TO: {
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 2, objv, "tagOrId index");
- result = TCL_ERROR;
- goto done;
- }
- CanvasSelectTo(canvasPtr, itemPtr, index);
- break;
- }
- }
- break;
- }
- case CANV_TYPE: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "tag");
- result = TCL_ERROR;
- goto done;
- }
- #ifdef USE_OLD_TAG_SEARCH
- itemPtr = StartTagSearch(canvasPtr, objv[2], &search);
- #else /* USE_OLD_TAG_SEARCH */
- if ((result = TagSearchScan(canvasPtr, objv[2], &searchPtr)) != TCL_OK) {
- goto done;
- }
- itemPtr = TagSearchFirst(searchPtr);
- #endif /* USE_OLD_TAG_SEARCH */
- if (itemPtr != NULL) {
- Tcl_SetResult(interp, itemPtr->typePtr->name, TCL_STATIC);
- }
- break;
- }
- case CANV_XVIEW: {
- int count, type;
- int newX = 0; /* Initialization needed only to prevent
- * gcc warnings. */
- double fraction;
- if (objc == 2) {
- Tcl_SetObjResult(interp, ScrollFractions(
- canvasPtr->xOrigin + canvasPtr->inset,
- canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)
- - canvasPtr->inset, canvasPtr->scrollX1,
- canvasPtr->scrollX2));
- } else {
- CONST char **args = GetStringsFromObjs(objc, objv);
- type = Tk_GetScrollInfo(interp, objc, args, &fraction, &count);
- if (args) ckfree((char *) args);
- switch (type) {
- case TK_SCROLL_ERROR:
- result = TCL_ERROR;
- goto done;
- case TK_SCROLL_MOVETO:
- newX = canvasPtr->scrollX1 - canvasPtr->inset
- + (int) (fraction * (canvasPtr->scrollX2
- - canvasPtr->scrollX1) + 0.5);
- break;
- case TK_SCROLL_PAGES:
- newX = (int) (canvasPtr->xOrigin + count * .9
- * (Tk_Width(canvasPtr->tkwin) - 2*canvasPtr->inset));
- break;
- case TK_SCROLL_UNITS:
- if (canvasPtr->xScrollIncrement > 0) {
- newX = canvasPtr->xOrigin
- + count*canvasPtr->xScrollIncrement;
- } else {
- newX = (int) (canvasPtr->xOrigin + count * .1
- * (Tk_Width(canvasPtr->tkwin)
- - 2*canvasPtr->inset));
- }
- break;
- }
- CanvasSetOrigin(canvasPtr, newX, canvasPtr->yOrigin);
- }
- break;
- }
- case CANV_YVIEW: {
- int count, type;
- int newY = 0; /* Initialization needed only to prevent
- * gcc warnings. */
- double fraction;
- if (objc == 2) {
- Tcl_SetObjResult(interp,ScrollFractions(
- canvasPtr->yOrigin + canvasPtr->inset,
- canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin)
- - canvasPtr->inset, canvasPtr->scrollY1,
- canvasPtr->scrollY2));
- } else {
- CONST char **args = GetStringsFromObjs(objc, objv);
- type = Tk_GetScrollInfo(interp, objc, args, &fraction, &count);
- if (args) ckfree((char *) args);
- switch (type) {
- case TK_SCROLL_ERROR:
- result = TCL_ERROR;
- goto done;
- case TK_SCROLL_MOVETO:
- newY = canvasPtr->scrollY1 - canvasPtr->inset
- + (int) (fraction*(canvasPtr->scrollY2
- - canvasPtr->scrollY1) + 0.5);
- break;
- case TK_SCROLL_PAGES:
- newY = (int) (canvasPtr->yOrigin + count * .9
- * (Tk_Height(canvasPtr->tkwin)
- - 2*canvasPtr->inset));
- break;
- case TK_SCROLL_UNITS:
- if (canvasPtr->yScrollIncrement > 0) {
- newY = canvasPtr->yOrigin
- + count*canvasPtr->yScrollIncrement;
- } else {
- newY = (int) (canvasPtr->yOrigin + count * .1
- * (Tk_Height(canvasPtr->tkwin)
- - 2*canvasPtr->inset));
- }
- break;
- }
- CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, newY);
- }
- break;
- }
- }
- done:
- #ifndef USE_OLD_TAG_SEARCH
- TagSearchDestroy(searchPtr);
- #endif /* not USE_OLD_TAG_SEARCH */
- Tcl_Release((ClientData) canvasPtr);
- return result;
- }
- /*
- *----------------------------------------------------------------------
- *
- * DestroyCanvas --
- *
- * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
- * to clean up the internal structure of a canvas at a safe time
- * (when no-one is using it anymore).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Everything associated with the canvas is freed up.
- *
- *----------------------------------------------------------------------
- */
- static void
- DestroyCanvas(memPtr)
- char *memPtr; /* Info about canvas widget. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) memPtr;
- Tk_Item *itemPtr;
- #ifndef USE_OLD_TAG_SEARCH
- TagSearchExpr *expr, *next;
- #endif
- /*
- * Free up all of the items in the canvas.
- */
- for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
- itemPtr = canvasPtr->firstItemPtr) {
- canvasPtr->firstItemPtr = itemPtr->nextPtr;
- (*itemPtr->typePtr->deleteProc)((Tk_Canvas) canvasPtr, itemPtr,
- canvasPtr->display);
- if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
- ckfree((char *) itemPtr->tagPtr);
- }
- ckfree((char *) itemPtr);
- }
- /*
- * Free up all the stuff that requires special handling,
- * then let Tk_FreeOptions handle all the standard option-related
- * stuff.
- */
- Tcl_DeleteHashTable(&canvasPtr->idTable);
- if (canvasPtr->pixmapGC != None) {
- Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
- }
- #ifndef USE_OLD_TAG_SEARCH
- expr = canvasPtr->bindTagExprs;
- while (expr) {
- next = expr->next;
- TagSearchExprDestroy(expr);
- expr = next;
- }
- #endif
- Tcl_DeleteTimerHandler(canvasPtr->insertBlinkHandler);
- if (canvasPtr->bindingTable != NULL) {
- Tk_DeleteBindingTable(canvasPtr->bindingTable);
- }
- Tk_FreeOptions(configSpecs, (char *) canvasPtr, canvasPtr->display, 0);
- canvasPtr->tkwin = NULL;
- ckfree((char *) canvasPtr);
- }
- /*
- *----------------------------------------------------------------------
- *
- * ConfigureCanvas --
- *
- * This procedure is called to process an objv/objc list, plus
- * the Tk option database, in order to configure (or
- * reconfigure) a canvas widget.
- *
- * Results:
- * The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then the interp's result contains an error message.
- *
- * Side effects:
- * Configuration information, such as colors, border width,
- * etc. get set for canvasPtr; old resources get freed,
- * if there were any.
- *
- *----------------------------------------------------------------------
- */
- static int
- ConfigureCanvas(interp, canvasPtr, objc, objv, flags)
- Tcl_Interp *interp; /* Used for error reporting. */
- TkCanvas *canvasPtr; /* Information about widget; may or may
- * not already have values for some fields. */
- int objc; /* Number of valid entries in objv. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- int flags; /* Flags to pass to Tk_ConfigureWidget. */
- {
- XGCValues gcValues;
- GC new;
- if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
- objc, (CONST char **) objv, (char *) canvasPtr,
- flags|TK_CONFIG_OBJS) != TCL_OK) {
- return TCL_ERROR;
- }
- /*
- * A few options need special processing, such as setting the
- * background from a 3-D border and creating a GC for copying
- * bits to the screen.
- */
- Tk_SetBackgroundFromBorder(canvasPtr->tkwin, canvasPtr->bgBorder);
- if (canvasPtr->highlightWidth < 0) {
- canvasPtr->highlightWidth = 0;
- }
- canvasPtr->inset = canvasPtr->borderWidth + canvasPtr->highlightWidth;
- gcValues.function = GXcopy;
- gcValues.graphics_exposures = False;
- gcValues.foreground = Tk_3DBorderColor(canvasPtr->bgBorder)->pixel;
- new = Tk_GetGC(canvasPtr->tkwin,
- GCFunction|GCGraphicsExposures|GCForeground, &gcValues);
- if (canvasPtr->pixmapGC != None) {
- Tk_FreeGC(canvasPtr->display, canvasPtr->pixmapGC);
- }
- canvasPtr->pixmapGC = new;
- /*
- * Reset the desired dimensions for the window.
- */
- Tk_GeometryRequest(canvasPtr->tkwin, canvasPtr->width + 2*canvasPtr->inset,
- canvasPtr->height + 2*canvasPtr->inset);
- /*
- * Restart the cursor timing sequence in case the on-time or off-time
- * just changed.
- */
- if (canvasPtr->textInfo.gotFocus) {
- CanvasFocusProc(canvasPtr, 1);
- }
- /*
- * Recompute the scroll region.
- */
- canvasPtr->scrollX1 = 0;
- canvasPtr->scrollY1 = 0;
- canvasPtr->scrollX2 = 0;
- canvasPtr->scrollY2 = 0;
- if (canvasPtr->regionString != NULL) {
- int argc2;
- CONST char **argv2;
- if (Tcl_SplitList(canvasPtr->interp, canvasPtr->regionString,
- &argc2, &argv2) != TCL_OK) {
- return TCL_ERROR;
- }
- if (argc2 != 4) {
- Tcl_AppendResult(interp, "bad scrollRegion "",
- canvasPtr->regionString, """, (char *) NULL);
- badRegion:
- ckfree(canvasPtr->regionString);
- ckfree((char *) argv2);
- canvasPtr->regionString = NULL;
- return TCL_ERROR;
- }
- if ((Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
- argv2[0], &canvasPtr->scrollX1) != TCL_OK)
- || (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
- argv2[1], &canvasPtr->scrollY1) != TCL_OK)
- || (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
- argv2[2], &canvasPtr->scrollX2) != TCL_OK)
- || (Tk_GetPixels(canvasPtr->interp, canvasPtr->tkwin,
- argv2[3], &canvasPtr->scrollY2) != TCL_OK)) {
- goto badRegion;
- }
- 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).
- */
- CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);
- canvasPtr->flags |= UPDATE_SCROLLBARS|REDRAW_BORDERS;
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->xOrigin, canvasPtr->yOrigin,
- canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
- canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
- return TCL_OK;
- }
- /*
- *---------------------------------------------------------------------------
- *
- * CanvasWorldChanged --
- *
- * This procedure is called when the world has changed in some
- * way and the widget needs to recompute all its graphics contexts
- * and determine its new geometry.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Configures all items in the canvas with a empty argc/argv, for
- * the side effect of causing all the items to recompute their
- * geometry and to be redisplayed.
- *
- *---------------------------------------------------------------------------
- */
-
- static void
- CanvasWorldChanged(instanceData)
- ClientData instanceData; /* Information about widget. */
- {
- TkCanvas *canvasPtr;
- Tk_Item *itemPtr;
- int result;
- canvasPtr = (TkCanvas *) instanceData;
- itemPtr = canvasPtr->firstItemPtr;
- for ( ; itemPtr != NULL; itemPtr = itemPtr->nextPtr) {
- result = (*itemPtr->typePtr->configProc)(canvasPtr->interp,
- (Tk_Canvas) canvasPtr, itemPtr, 0, NULL,
- TK_CONFIG_ARGV_ONLY);
- if (result != TCL_OK) {
- Tcl_ResetResult(canvasPtr->interp);
- }
- }
- canvasPtr->flags |= REPICK_NEEDED;
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr,
- canvasPtr->xOrigin, canvasPtr->yOrigin,
- canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
- canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
- }
- /*
- *--------------------------------------------------------------
- *
- * DisplayCanvas --
- *
- * This procedure redraws the contents of a canvas window.
- * It is invoked as a do-when-idle handler, so it only runs
- * when there's nothing else for the application to do.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Information appears on the screen.
- *
- *--------------------------------------------------------------
- */
- static void
- DisplayCanvas(clientData)
- ClientData clientData; /* Information about widget. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) clientData;
- Tk_Window tkwin = canvasPtr->tkwin;
- Tk_Item *itemPtr;
- Pixmap pixmap;
- int screenX1, screenX2, screenY1, screenY2, width, height;
- if (canvasPtr->tkwin == NULL) {
- return;
- }
- if (!Tk_IsMapped(tkwin)) {
- goto done;
- }
- /*
- * Choose a new current item if that is needed (this could cause
- * event handlers to be invoked).
- */
- while (canvasPtr->flags & REPICK_NEEDED) {
- Tcl_Preserve((ClientData) canvasPtr);
- canvasPtr->flags &= ~REPICK_NEEDED;
- PickCurrentItem(canvasPtr, &canvasPtr->pickEvent);
- tkwin = canvasPtr->tkwin;
- Tcl_Release((ClientData) canvasPtr);
- if (tkwin == NULL) {
- return;
- }
- }
- /*
- * 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.
- */
- if ((canvasPtr->redrawX1 < canvasPtr->redrawX2)
- && (canvasPtr->redrawY1 < canvasPtr->redrawY2)) {
- screenX1 = canvasPtr->xOrigin + canvasPtr->inset;
- screenY1 = canvasPtr->yOrigin + canvasPtr->inset;
- screenX2 = canvasPtr->xOrigin + Tk_Width(tkwin) - canvasPtr->inset;
- screenY2 = canvasPtr->yOrigin + Tk_Height(tkwin) - canvasPtr->inset;
- if (canvasPtr->redrawX1 > screenX1) {
- screenX1 = canvasPtr->redrawX1;
- }
- if (canvasPtr->redrawY1 > screenY1) {
- screenY1 = canvasPtr->redrawY1;
- }
- if (canvasPtr->redrawX2 < screenX2) {
- screenX2 = canvasPtr->redrawX2;
- }
- if (canvasPtr->redrawY2 < screenY2) {
- screenY2 = canvasPtr->redrawY2;
- }
- if ((screenX1 >= screenX2) || (screenY1 >= screenY2)) {
- goto borders;
- }
-
- width = screenX2 - screenX1;
- height = screenY2 - screenY1;
- #ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * Redrawing is done in a temporary pixmap that is allocated
- * here and freed at the end of the procedure. All drawing
- * is done to the pixmap, and the pixmap is copied to the
- * screen at the end of the procedure. The temporary pixmap
- * serves two purposes:
- *
- * 1. It provides a smoother visual effect (no clearing and
- * gradual redraw will be visible to users).
- * 2. It allows us to redraw only the objects that overlap
- * the redraw area. Otherwise incorrect results could
- * occur from redrawing things that stick outside of
- * the redraw area (we'd have to redraw everything in
- * order to make the overlaps look right).
- *
- * Some tricky points about the pixmap:
- *
- * 1. We only allocate a large enough pixmap to hold the
- * area that has to be redisplayed. This saves time in
- * in the X server for large objects that cover much
- * more than the area being redisplayed: only the area
- * of the pixmap will actually have to be redrawn.
- * 2. Some X servers (e.g. the one for DECstations) have troubles
- * with characters that overlap an edge of the pixmap (on the
- * DEC servers, as of 8/18/92, such characters are drawn one
- * pixel too far to the right). To handle this problem,
- * make the pixmap a bit larger than is absolutely needed
- * so that for normal-sized fonts the characters that overlap
- * the edge of the pixmap will be outside the area we care
- * about.
- */
-
- canvasPtr->drawableXOrigin = screenX1 - 30;
- canvasPtr->drawableYOrigin = screenY1 - 30;
- pixmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
- (screenX2 + 30 - canvasPtr->drawableXOrigin),
- (screenY2 + 30 - canvasPtr->drawableYOrigin),
- Tk_Depth(tkwin));
- #else
- canvasPtr->drawableXOrigin = canvasPtr->xOrigin;
- canvasPtr->drawableYOrigin = canvasPtr->yOrigin;
- pixmap = Tk_WindowId(tkwin);
- TkpClipDrawableToRect(Tk_Display(tkwin), pixmap,
- screenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin,
- width, height);
- #endif /* TK_NO_DOUBLE_BUFFERING */
-
- /*
- * Clear the area to be redrawn.
- */
-
- XFillRectangle(Tk_Display(tkwin), pixmap, canvasPtr->pixmapGC,
- screenX1 - canvasPtr->drawableXOrigin,
- screenY1 - canvasPtr->drawableYOrigin, (unsigned int) width,
- (unsigned int) height);
-
- /*
- * Scan through the item list, redrawing those items that need it.
- * An item must be redraw if either (a) it intersects the smaller
- * on-screen area or (b) it intersects the full canvas area and its
- * type requests that it be redrawn always (e.g. so subwindows can
- * be unmapped when they move off-screen).
- */
-
- for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
- itemPtr = itemPtr->nextPtr) {
- if ((itemPtr->x1 >= screenX2)
- || (itemPtr->y1 >= screenY2)
- || (itemPtr->x2 < screenX1)
- || (itemPtr->y2 < screenY1)) {
- if (!(itemPtr->typePtr->alwaysRedraw & 1)
- || (itemPtr->x1 >= canvasPtr->redrawX2)
- || (itemPtr->y1 >= canvasPtr->redrawY2)
- || (itemPtr->x2 < canvasPtr->redrawX1)
- || (itemPtr->y2 < canvasPtr->redrawY1)) {
- 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);
- }
-
- #ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * Copy from the temporary pixmap to the screen, then free up
- * the temporary pixmap.
- */
-
- XCopyArea(Tk_Display(tkwin), pixmap, Tk_WindowId(tkwin),
- canvasPtr->pixmapGC,
- screenX1 - canvasPtr->drawableXOrigin,
- screenY1 - canvasPtr->drawableYOrigin,
- (unsigned int) width, (unsigned int) height,
- screenX1 - canvasPtr->xOrigin, screenY1 - canvasPtr->yOrigin);
- Tk_FreePixmap(Tk_Display(tkwin), pixmap);
- #else
- TkpClipDrawableToRect(Tk_Display(tkwin), pixmap, 0, 0, -1, -1);
- #endif /* TK_NO_DOUBLE_BUFFERING */
- }
- /*
- * Draw the window borders, if needed.
- */
- borders:
- if (canvasPtr->flags & REDRAW_BORDERS) {
- canvasPtr->flags &= ~REDRAW_BORDERS;
- if (canvasPtr->borderWidth > 0) {
- Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin),
- canvasPtr->bgBorder, canvasPtr->highlightWidth,
- canvasPtr->highlightWidth,
- Tk_Width(tkwin) - 2*canvasPtr->highlightWidth,
- Tk_Height(tkwin) - 2*canvasPtr->highlightWidth,
- canvasPtr->borderWidth, canvasPtr->relief);
- }
- if (canvasPtr->highlightWidth != 0) {
- GC fgGC, bgGC;
- bgGC = Tk_GCForColor(canvasPtr->highlightBgColorPtr,
- Tk_WindowId(tkwin));
- if (canvasPtr->textInfo.gotFocus) {
- fgGC = Tk_GCForColor(canvasPtr->highlightColorPtr,
- Tk_WindowId(tkwin));
- TkpDrawHighlightBorder(tkwin, fgGC, bgGC,
- canvasPtr->highlightWidth, Tk_WindowId(tkwin));
- } else {
- TkpDrawHighlightBorder(tkwin, bgGC, bgGC,
- canvasPtr->highlightWidth, Tk_WindowId(tkwin));
- }
- }
- }
- done:
- canvasPtr->flags &= ~(REDRAW_PENDING|BBOX_NOT_EMPTY);
- canvasPtr->redrawX1 = canvasPtr->redrawX2 = 0;
- canvasPtr->redrawY1 = canvasPtr->redrawY2 = 0;
- if (canvasPtr->flags & UPDATE_SCROLLBARS) {
- CanvasUpdateScrollbars(canvasPtr);
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * CanvasEventProc --
- *
- * This procedure is invoked by the Tk dispatcher for various
- * events on canvases.
- *
- * Results:
- * None.
- *
- * Side effects:
- * When the window gets deleted, internal structures get
- * cleaned up. When it gets exposed, it is redisplayed.
- *
- *--------------------------------------------------------------
- */
- static void
- CanvasEventProc(clientData, eventPtr)
- ClientData clientData; /* Information about window. */
- XEvent *eventPtr; /* Information about event. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) clientData;
- if (eventPtr->type == Expose) {
- int x, y;
- x = eventPtr->xexpose.x + canvasPtr->xOrigin;
- y = eventPtr->xexpose.y + canvasPtr->yOrigin;
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, x, y,
- x + eventPtr->xexpose.width,
- y + eventPtr->xexpose.height);
- if ((eventPtr->xexpose.x < canvasPtr->inset)
- || (eventPtr->xexpose.y < canvasPtr->inset)
- || ((eventPtr->xexpose.x + eventPtr->xexpose.width)
- > (Tk_Width(canvasPtr->tkwin) - canvasPtr->inset))
- || ((eventPtr->xexpose.y + eventPtr->xexpose.height)
- > (Tk_Height(canvasPtr->tkwin) - canvasPtr->inset))) {
- canvasPtr->flags |= REDRAW_BORDERS;
- }
- } else if (eventPtr->type == DestroyNotify) {
- if (canvasPtr->tkwin != NULL) {
- canvasPtr->tkwin = NULL;
- Tcl_DeleteCommandFromToken(canvasPtr->interp,
- canvasPtr->widgetCmd);
- }
- if (canvasPtr->flags & REDRAW_PENDING) {
- Tcl_CancelIdleCall(DisplayCanvas, (ClientData) canvasPtr);
- }
- Tcl_EventuallyFree((ClientData) canvasPtr,
- (Tcl_FreeProc *) DestroyCanvas);
- } else if (eventPtr->type == ConfigureNotify) {
- canvasPtr->flags |= UPDATE_SCROLLBARS;
- /*
- * The call below is needed in order to recenter the canvas if
- * it's confined and its scroll region is smaller than the window.
- */
- CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin);
- Tk_CanvasEventuallyRedraw((Tk_Canvas) canvasPtr, canvasPtr->xOrigin,
- canvasPtr->yOrigin,
- canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin),
- canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin));
- canvasPtr->flags |= REDRAW_BORDERS;
- } else if (eventPtr->type == FocusIn) {
- if (eventPtr->xfocus.detail != NotifyInferior) {
- CanvasFocusProc(canvasPtr, 1);
- }
- } else if (eventPtr->type == FocusOut) {
- if (eventPtr->xfocus.detail != NotifyInferior) {
- CanvasFocusProc(canvasPtr, 0);
- }
- } else if (eventPtr->type == UnmapNotify) {
- Tk_Item *itemPtr;
- /*
- * Special hack: if the canvas is unmapped, then must notify
- * all items with "alwaysRedraw" set, so that they know that
- * they are no longer displayed.
- */
- for (itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL;
- itemPtr = itemPtr->nextPtr) {
- if (itemPtr->typePtr->alwaysRedraw & 1) {
- (*itemPtr->typePtr->displayProc)((Tk_Canvas) canvasPtr,
- itemPtr, canvasPtr->display, None, 0, 0, 0, 0);
- }
- }
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * CanvasCmdDeletedProc --
- *
- * This procedure is invoked when a widget command is deleted. If
- * the widget isn't already in the process of being destroyed,
- * this command destroys it.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The widget is destroyed.
- *
- *----------------------------------------------------------------------
- */
- static void
- CanvasCmdDeletedProc(clientData)
- ClientData clientData; /* Pointer to widget record for widget. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) clientData;
- Tk_Window tkwin = canvasPtr->tkwin;
- /*
- * This procedure could be invoked either because the window was
- * destroyed and the command was then deleted (in which case tkwin
- * is NULL) or because the command was deleted, and then this procedure
- * destroys the widget.
- */
- if (tkwin != NULL) {
- canvasPtr->tkwin = NULL;
- Tk_DestroyWindow(tkwin);
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * Tk_CanvasEventuallyRedraw --
- *
- * 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.
- *
- *--------------------------------------------------------------
- */
- void
- Tk_CanvasEventuallyRedraw(canvas, x1, y1, x2, y2)
- Tk_Canvas canvas; /* Information about widget. */
- int x1, y1; /* Upper left corner of area to redraw.
- * Pixels on edge are redrawn. */
- int x2, y2; /* Lower right corner of area to redraw.
- * Pixels on edge are not redrawn. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- /*
- * If tkwin is NULL, the canvas has been destroyed, so we can't really
- * redraw it.
- */
- if (canvasPtr->tkwin == NULL) {
- return;
- }
- if ((x1 >= x2) || (y1 >= y2) ||
- (x2 < canvasPtr->xOrigin) || (y2 < canvasPtr->yOrigin) ||
- (x1 >= canvasPtr->xOrigin + Tk_Width(canvasPtr->tkwin)) ||
- (y1 >= canvasPtr->yOrigin + Tk_Height(canvasPtr->tkwin))) {
- return;
- }
- if (canvasPtr->flags & BBOX_NOT_EMPTY) {
- if (x1 <= canvasPtr->redrawX1) {
- canvasPtr->redrawX1 = x1;
- }
- if (y1 <= canvasPtr->redrawY1) {
- canvasPtr->redrawY1 = y1;
- }
- if (x2 >= canvasPtr->redrawX2) {
- canvasPtr->redrawX2 = x2;
- }
- if (y2 >= canvasPtr->redrawY2) {
- canvasPtr->redrawY2 = y2;
- }
- } else {
- canvasPtr->redrawX1 = x1;
- 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;
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * Tk_CreateItemType --
- *
- * This procedure may be invoked to add a new kind of canvas
- * element to the core item types supported by Tk.
- *
- * Results:
- * None.
- *
- * Side effects:
- * From now on, the new item type will be useable in canvas
- * widgets (e.g. typePtr->name can be used as the item type
- * in "create" widget commands). If there was already a
- * type with the same name as in typePtr, it is replaced with
- * the new type.
- *
- *--------------------------------------------------------------
- */
- void
- Tk_CreateItemType(typePtr)
- Tk_ItemType *typePtr; /* Information about item type;
- * storage must be statically
- * allocated (must live forever). */
- {
- Tk_ItemType *typePtr2, *prevPtr;
- if (typeList == NULL) {
- InitCanvas();
- }
- /*
- * If there's already an item type with the given name, remove it.
- */
- Tcl_MutexLock(&typeListMutex);
- for (typePtr2 = typeList, prevPtr = NULL; typePtr2 != NULL;
- prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
- if (strcmp(typePtr2->name, typePtr->name) == 0) {
- if (prevPtr == NULL) {
- typeList = typePtr2->nextPtr;
- } else {
- prevPtr->nextPtr = typePtr2->nextPtr;
- }
- break;
- }
- }
- typePtr->nextPtr = typeList;
- typeList = typePtr;
- Tcl_MutexUnlock(&typeListMutex);
- }
- /*
- *----------------------------------------------------------------------
- *
- * Tk_GetItemTypes --
- *
- * This procedure returns a pointer to the list of all item
- * types. Note that this is inherently thread-unsafe, but since
- * item types are only ever registered very rarely this is
- * unlikely to be a problem in practice.
- *
- * Results:
- * The return value is a pointer to the first in the list
- * of item types currently supported by canvases.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- Tk_ItemType *
- Tk_GetItemTypes()
- {
- if (typeList == NULL) {
- InitCanvas();
- }
- return typeList;
- }
- /*
- *--------------------------------------------------------------
- *
- * InitCanvas --
- *
- * This procedure is invoked to perform once-only-ever
- * initialization for the module, such as setting up the type
- * table.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
- static void
- InitCanvas()
- {
- Tcl_MutexLock(&typeListMutex);
- if (typeList != NULL) {
- Tcl_MutexUnlock(&typeListMutex);
- return;
- }
- typeList = &tkRectangleType;
- tkRectangleType.nextPtr = &tkTextType;
- tkTextType.nextPtr = &tkLineType;
- tkLineType.nextPtr = &tkPolygonType;
- tkPolygonType.nextPtr = &tkImageType;
- tkImageType.nextPtr = &tkOvalType;
- tkOvalType.nextPtr = &tkBitmapType;
- tkBitmapType.nextPtr = &tkArcType;
- tkArcType.nextPtr = &tkWindowType;
- tkWindowType.nextPtr = NULL;
- Tcl_MutexUnlock(&typeListMutex);
- }
- #ifdef USE_OLD_TAG_SEARCH
- /*
- *--------------------------------------------------------------
- *
- * StartTagSearch --
- *
- * This procedure is called to initiate an enumeration of
- * all items in a given canvas that contain a given tag.
- *
- * Results:
- * The return value is a pointer to the first item in
- * canvasPtr that matches tag, or NULL if there is no
- * such item. The information at *searchPtr is initialized
- * such that successive calls to NextItem will return
- * successive items that match tag.
- *
- * Side effects:
- * SearchPtr is linked into a list of searches in progress
- * on canvasPtr, so that elements can safely be deleted
- * while the search is in progress. EndTagSearch must be
- * called at the end of the search to unlink searchPtr from
- * this list.
- *
- *--------------------------------------------------------------
- */
- static Tk_Item *
- StartTagSearch(canvasPtr, tagObj, searchPtr)
- TkCanvas *canvasPtr; /* Canvas whose items are to be
- * searched. */
- Tcl_Obj *tagObj; /* Object giving tag value. */
- TagSearch *searchPtr; /* Record describing tag search;
- * will be initialized here. */
- {
- int id;
- Tk_Item *itemPtr, *lastPtr;
- Tk_Uid *tagPtr;
- Tk_Uid uid;
- char *tag = Tcl_GetString(tagObj);
- int count;
- TkWindow *tkwin;
- TkDisplay *dispPtr;
- tkwin = (TkWindow *) canvasPtr->tkwin;
- dispPtr = tkwin->dispPtr;
- /*
- * Initialize the search.
- */
- searchPtr->canvasPtr = canvasPtr;
- searchPtr->searchOver = 0;
- /*
- * Find the first matching item in one of several ways. If the tag
- * is a number then it selects the single item with the matching
- * identifier. In this case see if the item being requested is the
- * hot item, in which case the search can be skipped.
- */
- if (isdigit(UCHAR(*tag))) {
- char *end;
- Tcl_HashEntry *entryPtr;
- dispPtr->numIdSearches++;
- id = strtoul(tag, &end, 0);
- if (*end == 0) {
- itemPtr = canvasPtr->hotPtr;
- lastPtr = canvasPtr->hotPrevPtr;
- if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL)
- || (lastPtr->nextPtr != itemPtr)) {
- dispPtr->numSlowSearches++;
- entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id);
- if (entryPtr != NULL) {
- itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr);
- lastPtr = itemPtr->prevPtr;
- } else {
- lastPtr = itemPtr = NULL;
- }