📄 tkcanvas.c
字号:
/* * 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-1993 The Regents of the University of California. * All rights reserved. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */#include "default.h"#include "tkInt.h"#include "tkConfig.h"#include "tkCanvas.h"/* * See tkCanvas.h for key data structures used to implement canvases. *//* * The structure defined below is used to keep track of a tag search * in progress. Only the "prevPtr" field should be accessed by anyone * other than StartTagSearch and NextItem. */typedef struct TagSearch { Tk_Canvas *canvasPtr; /* Canvas widget being searched. */ Tk_Uid tag; /* Tag to search for. 0 means return * all items. */ Tk_Item *prevPtr; /* Item just before last one found (or NULL * if last one found was first in the item * list of canvasPtr). */ Tk_Item *currentPtr; /* Pointer to last item returned. */ int searchOver; /* Non-zero means NextItem should always * return NULL. */} TagSearch;/* * Information used for argv parsing. */static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_CANVAS_BG_COLOR, Tk_Offset(Tk_Canvas, bgBorder), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_CANVAS_BG_MONO, Tk_Offset(Tk_Canvas, 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(Tk_Canvas, borderWidth), 0}, {TK_CONFIG_DOUBLE, "-closeenough", "closeEnough", "CloseEnough", DEF_CANVAS_CLOSE_ENOUGH, Tk_Offset(Tk_Canvas, closeEnough), 0}, {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine", DEF_CANVAS_CONFINE, Tk_Offset(Tk_Canvas, confine), 0}, {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", DEF_CANVAS_CURSOR, Tk_Offset(Tk_Canvas, cursor), TK_CONFIG_NULL_OK}, {TK_CONFIG_PIXELS, "-height", "height", "Height", DEF_CANVAS_HEIGHT, Tk_Offset(Tk_Canvas, height), 0}, {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground", DEF_CANVAS_INSERT_BG, Tk_Offset(Tk_Canvas, insertBorder), 0}, {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_CANVAS_INSERT_BD_COLOR, Tk_Offset(Tk_Canvas, insertBorderWidth), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_CANVAS_INSERT_BD_MONO, Tk_Offset(Tk_Canvas, insertBorderWidth), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", DEF_CANVAS_INSERT_OFF_TIME, Tk_Offset(Tk_Canvas, insertOffTime), 0}, {TK_CONFIG_INT, "-insertontime", "insertOffTime", "OnTime", DEF_CANVAS_INSERT_ON_TIME, Tk_Offset(Tk_Canvas, insertOffTime), 0}, {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", DEF_CANVAS_INSERT_WIDTH, Tk_Offset(Tk_Canvas, insertWidth), 0}, {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_CANVAS_RELIEF, Tk_Offset(Tk_Canvas, relief), 0}, {TK_CONFIG_PIXELS, "-scrollincrement", "scrollIncrement", "ScrollIncrement", DEF_CANVAS_SCROLL_INCREMENT, Tk_Offset(Tk_Canvas, scrollIncrement), 0}, {TK_CONFIG_STRING, "-scrollregion", "scrollRegion", "ScrollRegion", DEF_CANVAS_SCROLL_REGION, Tk_Offset(Tk_Canvas, regionString), TK_CONFIG_NULL_OK}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", DEF_CANVAS_SELECT_COLOR, Tk_Offset(Tk_Canvas, selBorder), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", DEF_CANVAS_SELECT_MONO, Tk_Offset(Tk_Canvas, selBorder), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_CANVAS_SELECT_BD_COLOR, Tk_Offset(Tk_Canvas, selBorderWidth), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_CANVAS_SELECT_BD_MONO, Tk_Offset(Tk_Canvas, selBorderWidth), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", DEF_CANVAS_SELECT_FG_COLOR, Tk_Offset(Tk_Canvas, selFgColorPtr), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(Tk_Canvas, selFgColorPtr), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_PIXELS, "-width", "width", "Width", DEF_CANVAS_WIDTH, Tk_Offset(Tk_Canvas, width), 0}, {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", DEF_CANVAS_X_SCROLL_CMD, Tk_Offset(Tk_Canvas, xScrollCmd), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", DEF_CANVAS_Y_SCROLL_CMD, Tk_Offset(Tk_Canvas, yScrollCmd), TK_CONFIG_NULL_OK}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0}};/* * List of all the item types known at present: */static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't * been done yet. *//* * Standard item types provided by Tk: */extern Tk_ItemType TkArcType, TkBitmapType, TkLineType;extern Tk_ItemType TkOvalType, TkPolygonType;extern Tk_ItemType TkRectangleType, TkTextType, TkWindowType;/* * Various Tk_Uid's used by this module (set up during initialization): */static Tk_Uid allUid = NULL;static Tk_Uid currentUid = NULL;/* * Statistics counters: */static int numIdSearches;static int numSlowSearches;/* * 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 CanvasDoEvent _ANSI_ARGS_((Tk_Canvas *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 void CanvasFocusProc _ANSI_ARGS_((Tk_Canvas *canvasPtr, int gotFocus));static void CanvasLostSelection _ANSI_ARGS_(( ClientData clientData));static void CanvasSelectTo _ANSI_ARGS_((Tk_Canvas *canvasPtr, Tk_Item *itemPtr, int index));static void CanvasSetOrigin _ANSI_ARGS_((Tk_Canvas *canvasPtr, int xOrigin, int yOrigin));static int CanvasTagsParseProc _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, Tk_Window tkwin, char *value, char *widgRec, int offset));static char * CanvasTagsPrintProc _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin, char *widgRec, int offset, Tcl_FreeProc **freeProcPtr));static void CanvasUpdateScrollbars _ANSI_ARGS_(( Tk_Canvas *canvasPtr));static int CanvasWidgetCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv));static int ConfigureCanvas _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas *canvasPtr, int argc, char **argv, int flags));static void DestroyCanvas _ANSI_ARGS_((ClientData clientData));static void DisplayCanvas _ANSI_ARGS_((ClientData clientData));static void DoItem _ANSI_ARGS_((Tcl_Interp *interp, Tk_Item *itemPtr, Tk_Uid tag));static void EventuallyRedrawArea _ANSI_ARGS_((Tk_Canvas *canvasPtr, int x1, int y1, int x2, int y2));static int FindItems _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas *canvasPtr, int argc, char **argv, char *newTag, char *cmdName, char *option));static int FindArea _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas *canvasPtr, char **argv, Tk_Uid uid, int enclosed));static double GridAlign _ANSI_ARGS_((double coord, double spacing));static void InitCanvas _ANSI_ARGS_((void));static Tk_Item * NextItem _ANSI_ARGS_((TagSearch *searchPtr));static void PickCurrentItem _ANSI_ARGS_((Tk_Canvas *canvasPtr, XEvent *eventPtr));static void RelinkItems _ANSI_ARGS_((Tk_Canvas *canvasPtr, char *tag, Tk_Item *prevPtr));static Tk_Item * StartTagSearch _ANSI_ARGS_((Tk_Canvas *canvasPtr, char *tag, TagSearch *searchPtr));/* * Custom option for handling "-tags" options for canvas items: */Tk_CustomOption tkCanvasTagsOption = { CanvasTagsParseProc, CanvasTagsPrintProc, (ClientData) NULL};/* *-------------------------------------------------------------- * * Tk_CanvasCmd -- * * 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. * *-------------------------------------------------------------- */intTk_CanvasCmd(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. */{ Tk_Window tkwin = (Tk_Window) clientData; register Tk_Canvas *canvasPtr; Tk_Window new; if (typeList == NULL) { InitCanvas(); } if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " pathName ?options?\"", (char *) NULL); return TCL_ERROR; } new = Tk_CreateWindowFromPath(interp, tkwin, 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 = (Tk_Canvas *) ckalloc(sizeof(Tk_Canvas)); canvasPtr->tkwin = new; canvasPtr->display = Tk_Display(new); canvasPtr->interp = interp; canvasPtr->firstItemPtr = NULL; canvasPtr->lastItemPtr = NULL; canvasPtr->borderWidth = 0; canvasPtr->bgBorder = NULL; canvasPtr->relief = TK_RELIEF_FLAT; canvasPtr->pixmapGC = None; canvasPtr->width = None; canvasPtr->height = None; canvasPtr->confine = 0; canvasPtr->selBorder = NULL; canvasPtr->selBorderWidth = 0; canvasPtr->selFgColorPtr = NULL; canvasPtr->selItemPtr = NULL; canvasPtr->selectFirst = -1; canvasPtr->selectLast = -1; canvasPtr->anchorItemPtr = NULL; canvasPtr->selectAnchor = 0; canvasPtr->insertBorder = NULL; canvasPtr->insertWidth = 0; canvasPtr->insertBorderWidth = 0; canvasPtr->insertOnTime = 0; canvasPtr->insertOffTime = 0; canvasPtr->insertBlinkHandler = (Tk_TimerToken) NULL; canvasPtr->focusItemPtr = NULL; canvasPtr->xOrigin = canvasPtr->yOrigin = 0; canvasPtr->drawableXOrigin = canvasPtr->drawableYOrigin = 0; canvasPtr->bindingTable = NULL; canvasPtr->currentItemPtr = NULL; canvasPtr->closeEnough = 0.0; canvasPtr->pickEvent.type = LeaveNotify; 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->scrollIncrement = 1; canvasPtr->scanX = 0; canvasPtr->scanXOrigin = 0; canvasPtr->scanY = 0; canvasPtr->scanYOrigin = 0; canvasPtr->hotPtr = NULL; canvasPtr->hotPrevPtr = NULL; canvasPtr->cursor = None; canvasPtr->pixelsPerMM = WidthOfScreen(Tk_Screen(new)); canvasPtr->pixelsPerMM /= WidthMMOfScreen(Tk_Screen(new)); canvasPtr->flags = 0; canvasPtr->nextId = 1; Tk_SetClass(canvasPtr->tkwin, "Canvas"); Tk_CreateEventHandler(canvasPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, CanvasEventProc, (ClientData) canvasPtr); Tk_CreateEventHandler(canvasPtr->tkwin, KeyPressMask|KeyReleaseMask |ButtonPressMask|ButtonReleaseMask|EnterWindowMask |LeaveWindowMask|PointerMotionMask, CanvasBindProc, (ClientData) canvasPtr); Tk_CreateSelHandler(canvasPtr->tkwin, XA_STRING, CanvasFetchSelection, (ClientData) canvasPtr, XA_STRING); Tcl_CreateCommand(interp, Tk_PathName(canvasPtr->tkwin), CanvasWidgetCmd, (ClientData) canvasPtr, (void (*)()) NULL); if (ConfigureCanvas(interp, canvasPtr, argc-2, argv+2, 0) != TCL_OK) { goto error; } interp->result = Tk_PathName(canvasPtr->tkwin); 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 intCanvasWidgetCmd(clientData, interp, argc, argv) ClientData clientData; /* Information about canvas * widget. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ register Tk_Canvas *canvasPtr = (Tk_Canvas *) clientData; int length, result; char c; Tk_Item *itemPtr = NULL; /* Initialization needed only to * prevent compiler warning. */ TagSearch search; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?arg arg ...?\"", (char *) NULL); return TCL_ERROR; } Tk_Preserve((ClientData) canvasPtr); result = TCL_OK; c = argv[1][0]; length = strlen(argv[1]); if ((c == 'a') && (strncmp(argv[1], "addtag", length) == 0)) { 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)) { 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; } gotAny = 0; for (i = 2; i < argc; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -