📄 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-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkCanvas.c 1.126 97/07/31 09:05:52 */#include "default.h"#include "tkInt.h"#include "tkPort.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 { TkCanvas *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(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_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_COLOR, "-selectforeground", "selectForeground", "Background", DEF_CANVAS_SELECT_FG_MONO, Tk_Offset(TkCanvas, textInfo.selFgColorPtr), TK_CONFIG_MONO_ONLY}, {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: */static Tk_ItemType *typeList = NULL; /* NULL means initialization hasn't * been done yet. *//* * Standard item types provided by Tk: */extern Tk_ItemType tkArcType, tkBitmapType, tkImageType, tkLineType;extern Tk_ItemType tkOvalType, tkPolygonType;extern Tk_ItemType tkRectangleType, tkTextType, tkWindowType;/* * Various Tk_Uid's used by this module (set up during initialization): */static Tk_Uid allUid = NULL;static Tk_Uid currentUid = NULL;/* * 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 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, char **argv));static void CanvasWorldChanged _ANSI_ARGS_(( ClientData instanceData));static int ConfigureCanvas _ANSI_ARGS_((Tcl_Interp *interp, TkCanvas *canvasPtr, int argc, char **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 int FindItems _ANSI_ARGS_((Tcl_Interp *interp, TkCanvas *canvasPtr, int argc, char **argv, char *newTag, char *cmdName, char *option));static int FindArea _ANSI_ARGS_((Tcl_Interp *interp, TkCanvas *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_((TkCanvas *canvasPtr, XEvent *eventPtr));static void PrintScrollFractions _ANSI_ARGS_((int screen1, int screen2, int object1, int object2, char *string));static void RelinkItems _ANSI_ARGS_((TkCanvas *canvasPtr, char *tag, Tk_Item *prevPtr));static Tk_Item * StartTagSearch _ANSI_ARGS_((TkCanvas *canvasPtr, char *tag, TagSearch *searchPtr));/* * The structure below defines canvas class behavior by means of procedures * that can be invoked from generic window code. */static TkClassProcs canvasClass = { NULL, /* createProc. */ CanvasWorldChanged, /* geometryProc. */ NULL /* modalProc. */};/* *-------------------------------------------------------------- * * 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; TkCanvas *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 = (TkCanvas *) ckalloc(sizeof(TkCanvas)); canvasPtr->tkwin = new; canvasPtr->display = Tk_Display(new); canvasPtr->interp = interp; canvasPtr->widgetCmd = Tcl_CreateCommand(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->psInfoPtr = NULL; Tk_SetClass(canvasPtr->tkwin, "Canvas"); TkSetClassProcs(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; } 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. */{ TkCanvas *canvasPtr = (TkCanvas *) clientData; size_t length; int c, result; Tk_Item *itemPtr = NULL; /* Initialization needed only to * prevent compiler warning. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -