📄 tkcanvas.c
字号:
CanvasSetOrigin(canvasPtr, canvasPtr->xOrigin, canvasPtr->yOrigin); EventuallyRedrawArea(canvasPtr, 0, 0, Tk_Width(canvasPtr->tkwin), Tk_Height(canvasPtr->tkwin)); } else if (eventPtr->type == FocusIn) { CanvasFocusProc(canvasPtr, 1); } else if (eventPtr->type == FocusOut) { CanvasFocusProc(canvasPtr, 0); } else if (eventPtr->type == UnmapNotify) { register 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) { (*itemPtr->typePtr->displayProc)(canvasPtr, itemPtr, None); } } }}/* *-------------------------------------------------------------- * * EventuallyRedrawArea -- * * Arrange for part or all of a canvas widget to redrawn at * the next convenient time in the future. * * Results: * None. * * Side effects: * The screen will eventually be refreshed. * *-------------------------------------------------------------- */static voidEventuallyRedrawArea(canvasPtr, x1, y1, x2, y2) register Tk_Canvas *canvasPtr; /* 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. */{ if ((canvasPtr->tkwin == NULL) || !Tk_IsMapped(canvasPtr->tkwin)) { return; } if (canvasPtr->flags & REDRAW_PENDING) { 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; Tk_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. * *-------------------------------------------------------------- */voidTk_CreateItemType(typePtr) Tk_ItemType *typePtr; /* Information about item type; * storage must be statically * allocated (must live forever). */{ if (typeList == NULL) { InitCanvas(); } typePtr->nextPtr = typeList; typeList = typePtr;}/* *-------------------------------------------------------------- * * 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 voidInitCanvas(){ if (typeList != NULL) { return; } typeList = &TkRectangleType; TkRectangleType.nextPtr = &TkTextType; TkTextType.nextPtr = &TkPolygonType; TkPolygonType.nextPtr = &TkOvalType; TkOvalType.nextPtr = &TkLineType; TkLineType.nextPtr = &TkWindowType; TkWindowType.nextPtr = &TkBitmapType; TkBitmapType.nextPtr = &TkArcType; TkArcType.nextPtr = NULL; allUid = Tk_GetUid("all"); currentUid = Tk_GetUid("current");}/* *-------------------------------------------------------------- * * 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, tag, searchPtr) Tk_Canvas *canvasPtr; /* Canvas whose items are to be * searched. */ char *tag; /* String giving tag value. */ TagSearch *searchPtr; /* Record describing tag search; * will be initialized here. */{ int id; register Tk_Item *itemPtr, *prevPtr; register Tk_Uid *tagPtr; register Tk_Uid uid; register int count; /* * 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; numIdSearches++; id = strtoul(tag, &end, 0); if (*end == 0) { itemPtr = canvasPtr->hotPtr; prevPtr = canvasPtr->hotPrevPtr; if ((itemPtr == NULL) || (itemPtr->id != id) || (prevPtr == NULL) || (prevPtr->nextPtr != itemPtr)) { numSlowSearches++; for (prevPtr = NULL, itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; prevPtr = itemPtr, itemPtr = itemPtr->nextPtr) { if (itemPtr->id == id) { break; } } } searchPtr->prevPtr = prevPtr; searchPtr->searchOver = 1; canvasPtr->hotPtr = itemPtr; canvasPtr->hotPrevPtr = prevPtr; return itemPtr; } } searchPtr->tag = uid = Tk_GetUid(tag); if (uid == allUid) { /* * All items match. */ searchPtr->tag = NULL; searchPtr->prevPtr = NULL; searchPtr->currentPtr = canvasPtr->firstItemPtr; return canvasPtr->firstItemPtr; } /* * None of the above. Search for an item with a matching tag. */ for (prevPtr = NULL, itemPtr = canvasPtr->firstItemPtr; itemPtr != NULL; prevPtr = itemPtr, itemPtr = itemPtr->nextPtr) { for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == uid) { searchPtr->prevPtr = prevPtr; searchPtr->currentPtr = itemPtr; return itemPtr; } } } searchPtr->prevPtr = prevPtr; searchPtr->searchOver = 1; return NULL;}/* *-------------------------------------------------------------- * * NextItem -- * * This procedure returns successive items that match a given * tag; it should be called only after StartTagSearch has been * used to begin a search. * * Results: * The return value is a pointer to the next item that matches * the tag specified to StartTagSearch, or NULL if no such * item exists. *SearchPtr is updated so that the next call * to this procedure will return the next item. * * Side effects: * None. * *-------------------------------------------------------------- */static Tk_Item *NextItem(searchPtr) TagSearch *searchPtr; /* Record describing search in * progress. */{ register Tk_Item *itemPtr, *prevPtr; register int count; register Tk_Uid uid; register Tk_Uid *tagPtr; /* * Find next item in list (this may not actually be a suitable * one to return), and return if there are no items left. */ prevPtr = searchPtr->prevPtr; if (prevPtr == NULL) { itemPtr = searchPtr->canvasPtr->firstItemPtr; } else { itemPtr = prevPtr->nextPtr; } if ((itemPtr == NULL) || (searchPtr->searchOver)) { searchPtr->searchOver = 1; return NULL; } if (itemPtr != searchPtr->currentPtr) { /* * The structure of the list has changed. Probably the * previously-returned item was removed from the list. * In this case, don't advance prevPtr; just return * its new successor (i.e. do nothing here). */ } else { prevPtr = itemPtr; itemPtr = prevPtr->nextPtr; } /* * Handle special case of "all" search by returning next item. */ uid = searchPtr->tag; if (uid == NULL) { searchPtr->prevPtr = prevPtr; searchPtr->currentPtr = itemPtr; return itemPtr; } /* * Look for an item with a particular tag. */ for ( ; itemPtr != NULL; prevPtr = itemPtr, itemPtr = itemPtr->nextPtr) { for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; count > 0; tagPtr++, count--) { if (*tagPtr == uid) { searchPtr->prevPtr = prevPtr; searchPtr->currentPtr = itemPtr; return itemPtr; } } } searchPtr->prevPtr = prevPtr; searchPtr->searchOver = 1; return NULL;}/* *-------------------------------------------------------------- * * DoItem -- * * This is a utility procedure called by FindItems. It * either adds itemPtr's id to the result forming in interp, * or it adds a new tag to itemPtr, depending on the value * of tag. * * Results: * None. * * Side effects: * If tag is NULL then itemPtr's id is added as a list element * to interp->result; otherwise tag is added to itemPtr's * list of tags. * *-------------------------------------------------------------- */static voidDoItem(interp, itemPtr, tag) Tcl_Interp *interp; /* Interpreter in which to (possibly) * record item id. */ register Tk_Item *itemPtr; /* Item to (possibly) modify. */ Tk_Uid tag; /* Tag to add to those already * present for item, or NULL. */{ register Tk_Uid *tagPtr; register int count; /* * Handle the "add-to-result" case and return, if appropriate. */ if (tag == NULL) { char msg[30]; sprintf(msg, "%d", itemPtr->id); Tcl_AppendElement(interp, msg); return; } for (tagPtr = itemPtr->tagPtr, count = itemPtr->numTags; count > 0; tagPtr++, count--) { if (tag == *tagPtr) { return; } } /* * Grow the tag space if there's no more room left in the current * block. */ if (itemPtr->tagSpace == itemPtr->numTags) { Tk_Uid *newTagPtr; itemPtr->tagSpace += 5; newTagPtr = (Tk_Uid *) ckalloc((unsigned) (itemPtr->tagSpace * sizeof(Tk_Uid))); memcpy((VOID *) newTagPtr, (VOID *) itemPtr->tagPtr, (itemPtr->numTags * sizeof(Tk_Uid))); if (itemPtr->tagPtr != itemPtr->staticTagSpace) { ckfree((char *) itemPtr->tagPtr); } itemPtr->tagPtr = newTagPtr; tagPtr = &itemPtr->tagPtr[itemPtr->numTags]; } /* * Add in the new tag.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -