static int TkcCreateBitmap( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tk_Canvas canvas, /* Canvas to hold new item. */ Tk_Item *itemPtr, /* Record to hold new item; header has been * initialized by caller. */ int objc, /* Number of arguments in objv. */ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; int i; if (objc == 0) { Tcl_Panic("canvas did not pass any coords"); } /* * Initialize item's record. */ bmapPtr->anchor = TK_ANCHOR_CENTER; bmapPtr->bitmap = None; bmapPtr->activeBitmap = None; bmapPtr->disabledBitmap = None; bmapPtr->fgColor = NULL; bmapPtr->activeFgColor = NULL; bmapPtr->disabledFgColor = NULL; bmapPtr->bgColor = NULL; bmapPtr->activeBgColor = NULL; bmapPtr->disabledBgColor = NULL; bmapPtr->gc = None; /* * Process the arguments to fill in the item record. Only 1 (list) or 2 (x * y) coords are allowed. */ if (objc == 1) { i = 1; } else { const char *arg = Tcl_GetString(objv[1]); i = 2; if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { i = 1; } } if (BitmapCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) { goto error; } if (ConfigureBitmap(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) { return TCL_OK; } error: DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; }
static int CreateRectOval( Tcl_Interp *interp, /* For error reporting. */ Tk_Canvas canvas, /* Canvas to hold new item. */ Tk_Item *itemPtr, /* Record to hold new item; header has been * initialized by caller. */ int objc, /* Number of arguments in objv. */ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; int i; if (objc == 0) { Tcl_Panic("canvas did not pass any coords"); } /* * Carry out initialization that is needed in order to clean up after * errors during the the remainder of this function. */ Tk_CreateOutline(&(rectOvalPtr->outline)); rectOvalPtr->tsoffset.flags = 0; rectOvalPtr->tsoffset.xoffset = 0; rectOvalPtr->tsoffset.yoffset = 0; rectOvalPtr->fillColor = NULL; rectOvalPtr->activeFillColor = NULL; rectOvalPtr->disabledFillColor = NULL; rectOvalPtr->fillStipple = None; rectOvalPtr->activeFillStipple = None; rectOvalPtr->disabledFillStipple = None; rectOvalPtr->fillGC = None; /* * Process the arguments to fill in the item record. */ for (i = 1; i < objc; i++) { const char *arg = Tcl_GetString(objv[i]); if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { break; } } if ((RectOvalCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) { goto error; } if (ConfigureRectOval(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) { return TCL_OK; } error: DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; }
static int CreateWinItem( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tk_Canvas canvas, /* Canvas to hold new item. */ Tk_Item *itemPtr, /* Record to hold new item; header has been * initialized by caller. */ int objc, /* Number of arguments in objv. */ Tcl_Obj *const objv[]) /* Arguments describing window. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; int i; if (objc == 0) { Tcl_Panic("canvas did not pass any coords"); } /* * Initialize item's record. */ winItemPtr->tkwin = NULL; winItemPtr->width = 0; winItemPtr->height = 0; winItemPtr->anchor = TK_ANCHOR_CENTER; winItemPtr->canvas = canvas; /* * Process the arguments to fill in the item record. Only 1 (list) or 2 (x * y) coords are allowed. */ if (objc == 1) { i = 1; } else { const char *arg = Tcl_GetString(objv[1]); i = 2; if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { i = 1; } } if (WinItemCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) { goto error; } if (ConfigureWinItem(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) { return TCL_OK; } error: DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; }
/* ARGSUSED */ static void WinItemLostSlaveProc( ClientData clientData, /* WindowItem structure for slave window that * was stolen away. */ Tk_Window tkwin) /* Tk's handle for the slave window. */ { WindowItem *winItemPtr = clientData; Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas); Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, winItemPtr); if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } Tk_UnmapWindow(winItemPtr->tkwin); winItemPtr->tkwin = NULL; }
static void DeleteWinItem( Tk_Canvas canvas, /* Overall info about widget. */ Tk_Item *itemPtr, /* Item that is being deleted. */ Display *display) /* Display containing window for canvas. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas); if (winItemPtr->tkwin != NULL) { Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, winItemPtr); Tk_ManageGeometry(winItemPtr->tkwin, NULL, NULL); if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } Tk_UnmapWindow(winItemPtr->tkwin); } }
static int ConfigureBLine(Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, CONST84 char** argv, int flags) { register BLineItem *linePtr = (BLineItem *) itemPtr; Tk_Window tkwin; tkwin = Tk_CanvasTkwin(canvas); if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv, (char *) linePtr, flags) != TCL_OK) { return TCL_ERROR; } /* * Recompute bounding box for line. */ ComputeBLineBbox(canvas, linePtr); return TCL_OK; }
static int BitmapToPostscript( Tcl_Interp *interp, /* Leave Postscript or error message here. */ Tk_Canvas canvas, /* Information about overall canvas. */ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ int prepass) /* 1 means this is a prepass to collect font * information; 0 means final Postscript is * being created. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; double x, y; int width, height, rowsAtOnce, rowsThisTime; int curRow; char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4]; XColor *fgColor; XColor *bgColor; Pixmap bitmap; Tk_State state = itemPtr->state; if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } fgColor = bmapPtr->fgColor; bgColor = bmapPtr->bgColor; bitmap = bmapPtr->bitmap; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (bmapPtr->activeFgColor!=NULL) { fgColor = bmapPtr->activeFgColor; } if (bmapPtr->activeBgColor!=NULL) { bgColor = bmapPtr->activeBgColor; } if (bmapPtr->activeBitmap!=None) { bitmap = bmapPtr->activeBitmap; } } else if (state == TK_STATE_DISABLED) { if (bmapPtr->disabledFgColor!=NULL) { fgColor = bmapPtr->disabledFgColor; } if (bmapPtr->disabledBgColor!=NULL) { bgColor = bmapPtr->disabledBgColor; } if (bmapPtr->disabledBitmap!=None) { bitmap = bmapPtr->disabledBitmap; } } if (bitmap == None) { return TCL_OK; } /* * Compute the coordinates of the lower-left corner of the bitmap, taking * into account the anchor position for the bitmp. */ x = bmapPtr->x; y = Tk_CanvasPsY(canvas, bmapPtr->y); Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &width, &height); switch (bmapPtr->anchor) { case TK_ANCHOR_NW: y -= height; break; case TK_ANCHOR_N: x -= width/2.0; y -= height; break; case TK_ANCHOR_NE: x -= width; y -= height; break; case TK_ANCHOR_E: x -= width; y -= height/2.0; break; case TK_ANCHOR_SE: x -= width; break; case TK_ANCHOR_S: x -= width/2.0; break; case TK_ANCHOR_SW: break; case TK_ANCHOR_W: y -= height/2.0; break; case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; } /* * Color the background, if there is one. */ if (bgColor != NULL) { sprintf(buffer, "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %s\n", x, y, width, height, -width, "0 rlineto closepath"); Tcl_AppendResult(interp, buffer, NULL); if (Tk_CanvasPsColor(interp, canvas, bgColor) != TCL_OK) { return TCL_ERROR; } Tcl_AppendResult(interp, "fill\n", NULL); } /* * Draw the bitmap, if there is a foreground color. If the bitmap is very * large, then chop it up into multiple bitmaps, each consisting of one or * more rows. This is needed because Postscript can't handle single * strings longer than 64 KBytes long. */ if (fgColor != NULL) { if (Tk_CanvasPsColor(interp, canvas, fgColor) != TCL_OK) { return TCL_ERROR; } if (width > 60000) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "can't generate Postscript", " for bitmaps more than 60000 pixels wide", NULL); return TCL_ERROR; } rowsAtOnce = 60000/width; if (rowsAtOnce < 1) { rowsAtOnce = 1; } sprintf(buffer, "%.15g %.15g translate\n", x, y+height); Tcl_AppendResult(interp, buffer, NULL); for (curRow = 0; curRow < height; curRow += rowsAtOnce) { rowsThisTime = rowsAtOnce; if (rowsThisTime > (height - curRow)) { rowsThisTime = height - curRow; } sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n", (double) rowsThisTime, width, rowsThisTime); Tcl_AppendResult(interp, buffer, NULL); if (Tk_CanvasPsBitmap(interp, canvas, bitmap, 0, curRow, width, rowsThisTime) != TCL_OK) { return TCL_ERROR; } Tcl_AppendResult(interp, "\n} imagemask\n", NULL); } } return TCL_OK; }
/* ARGSUSED */ static void ComputeBitmapBbox( Tk_Canvas canvas, /* Canvas that contains item. */ BitmapItem *bmapPtr) /* Item whose bbox is to be recomputed. */ { int width, height; int x, y; Pixmap bitmap; Tk_State state = bmapPtr->header.state; if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } bitmap = bmapPtr->bitmap; if (Canvas(canvas)->currentItemPtr == (Tk_Item *)bmapPtr) { if (bmapPtr->activeBitmap!=None) { bitmap = bmapPtr->activeBitmap; } } else if (state==TK_STATE_DISABLED) { if (bmapPtr->disabledBitmap!=None) { bitmap = bmapPtr->disabledBitmap; } } x = (int) (bmapPtr->x + ((bmapPtr->x >= 0) ? 0.5 : - 0.5)); y = (int) (bmapPtr->y + ((bmapPtr->y >= 0) ? 0.5 : - 0.5)); if (state==TK_STATE_HIDDEN || bitmap == None) { bmapPtr->header.x1 = bmapPtr->header.x2 = x; bmapPtr->header.y1 = bmapPtr->header.y2 = y; return; } /* * Compute location and size of bitmap, using anchor information. */ Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bitmap, &width, &height); switch (bmapPtr->anchor) { case TK_ANCHOR_N: x -= width/2; break; case TK_ANCHOR_NE: x -= width; break; case TK_ANCHOR_E: x -= width; y -= height/2; break; case TK_ANCHOR_SE: x -= width; y -= height; break; case TK_ANCHOR_S: x -= width/2; y -= height; break; case TK_ANCHOR_SW: y -= height; break; case TK_ANCHOR_W: y -= height/2; break; case TK_ANCHOR_NW: break; case TK_ANCHOR_CENTER: x -= width/2; y -= height/2; break; } /* * Store the information in the item header. */ bmapPtr->header.x1 = x; bmapPtr->header.y1 = y; bmapPtr->header.x2 = x + width; bmapPtr->header.y2 = y + height; }
static int ConfigureBitmap( Tcl_Interp *interp, /* Used for error reporting. */ Tk_Canvas canvas, /* Canvas containing itemPtr. */ Tk_Item *itemPtr, /* Bitmap item to reconfigure. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[], /* Arguments describing things to configure. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { BitmapItem *bmapPtr = (BitmapItem *) itemPtr; XGCValues gcValues; GC newGC; Tk_Window tkwin; unsigned long mask; XColor *fgColor; XColor *bgColor; Pixmap bitmap; Tk_State state; tkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc, (const char **) objv, (char *) bmapPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } /* * A few of the options require additional processing, such as those that * determine the graphics context. */ state = itemPtr->state; if (bmapPtr->activeFgColor!=NULL || bmapPtr->activeBgColor!=NULL || bmapPtr->activeBitmap!=None) { itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; } else { itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; } if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } if (state == TK_STATE_HIDDEN) { ComputeBitmapBbox(canvas, bmapPtr); return TCL_OK; } fgColor = bmapPtr->fgColor; bgColor = bmapPtr->bgColor; bitmap = bmapPtr->bitmap; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (bmapPtr->activeFgColor!=NULL) { fgColor = bmapPtr->activeFgColor; } if (bmapPtr->activeBgColor!=NULL) { bgColor = bmapPtr->activeBgColor; } if (bmapPtr->activeBitmap!=None) { bitmap = bmapPtr->activeBitmap; } } else if (state == TK_STATE_DISABLED) { if (bmapPtr->disabledFgColor!=NULL) { fgColor = bmapPtr->disabledFgColor; } if (bmapPtr->disabledBgColor!=NULL) { bgColor = bmapPtr->disabledBgColor; } if (bmapPtr->disabledBitmap!=None) { bitmap = bmapPtr->disabledBitmap; } } if (bitmap == None) { newGC = None; } else { gcValues.foreground = fgColor->pixel; mask = GCForeground; if (bgColor != NULL) { gcValues.background = bgColor->pixel; mask |= GCBackground; } else { gcValues.clip_mask = bitmap; mask |= GCClipMask; } newGC = Tk_GetGC(tkwin, mask, &gcValues); } if (bmapPtr->gc != None) { Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc); } bmapPtr->gc = newGC; ComputeBitmapBbox(canvas, bmapPtr); return TCL_OK; }
static int CreateBLine(Tcl_Interp* interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, CONST84 char** argv) { BLineItem *linePtr = (BLineItem *) itemPtr; int i; tagsOption.parseProc = Tk_CanvasTagsParseProc; tagsOption.printProc = Tk_CanvasTagsPrintProc; if (argc < 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", Tk_PathName(Tk_CanvasTkwin(canvas)), "\" create ", itemPtr->typePtr->name, " x1 y1 x2 y2 ?x3 y3 ...? ?options?", (char *) NULL); return TCL_ERROR; } /* * Carry out initialization that is needed to set defaults and to * allow proper cleanup after errors during the the remainder of * this procedure. */ linePtr->numPoints = 0; linePtr->coordPtr = NULL; linePtr->width = 1; linePtr->capStyle = CapButt; linePtr->joinStyle = JoinRound; linePtr->borderWidth = 2; linePtr->relief = TK_RELIEF_RAISED; linePtr->border = NULL; /* * Count the number of points and then parse them into a point * array. Leading arguments are assumed to be points if they * start with a digit or a minus sign followed by a digit. */ for (i = 4; i < (argc-1); i+=2) { if ((!isdigit(UCHAR(argv[i][0]))) && ((argv[i][0] != '-') || (!isdigit(UCHAR(argv[i][1]))))) { break; } } if (BLineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK) { goto error; } if (ConfigureBLine(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) { return TCL_OK; } error: DeleteBLine(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; }
static int ConfigureText( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tk_Canvas canvas, /* Canvas containing itemPtr. */ Tk_Item *itemPtr, /* Rectangle item to reconfigure. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[], /* Arguments describing things to configure. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { TextItem *textPtr = (TextItem *) itemPtr; XGCValues gcValues; GC newGC, newSelGC; unsigned long mask; Tk_Window tkwin; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; XColor *selBgColorPtr; XColor *color; Pixmap stipple; Tk_State state; tkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc, (const char **) objv, (char *) textPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } /* * A few of the options require additional processing, such as graphics * contexts. */ state = itemPtr->state; if (textPtr->activeColor != NULL || textPtr->activeStipple != None) { itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; } else { itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; } if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } color = textPtr->color; stipple = textPtr->stipple; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (textPtr->activeColor != NULL) { color = textPtr->activeColor; } if (textPtr->activeStipple != None) { stipple = textPtr->activeStipple; } } else if (state == TK_STATE_DISABLED) { if (textPtr->disabledColor != NULL) { color = textPtr->disabledColor; } if (textPtr->disabledStipple != None) { stipple = textPtr->disabledStipple; } } newGC = newSelGC = NULL; if (textPtr->tkfont != NULL) { gcValues.font = Tk_FontId(textPtr->tkfont); mask = GCFont; if (color != NULL) { gcValues.foreground = color->pixel; mask |= GCForeground; if (stipple != None) { gcValues.stipple = stipple; gcValues.fill_style = FillStippled; mask |= GCStipple|GCFillStyle; } newGC = Tk_GetGC(tkwin, mask, &gcValues); } mask &= ~(GCTile|GCFillStyle|GCStipple); if (stipple != None) { gcValues.stipple = stipple; gcValues.fill_style = FillStippled; mask |= GCStipple|GCFillStyle; } if (textInfoPtr->selFgColorPtr != NULL) { gcValues.foreground = textInfoPtr->selFgColorPtr->pixel; } newSelGC = Tk_GetGC(tkwin, mask|GCForeground, &gcValues); } if (textPtr->gc != NULL) { Tk_FreeGC(Tk_Display(tkwin), textPtr->gc); } textPtr->gc = newGC; if (textPtr->selTextGC != NULL) { Tk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC); } textPtr->selTextGC = newSelGC; selBgColorPtr = Tk_3DBorderColor(textInfoPtr->selBorder); if (Tk_3DBorderColor(textInfoPtr->insertBorder)->pixel == selBgColorPtr->pixel) { if (selBgColorPtr->pixel == BlackPixelOfScreen(Tk_Screen(tkwin))) { gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin)); } else { gcValues.foreground = BlackPixelOfScreen(Tk_Screen(tkwin)); } newGC = Tk_GetGC(tkwin, GCForeground, &gcValues); } else { newGC = NULL; } if (textPtr->cursorOffGC != NULL) { Tk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC); } textPtr->cursorOffGC = newGC; /* * If the text was changed, move the selection and insertion indices to * keep them inside the item. */ textPtr->numBytes = strlen(textPtr->text); textPtr->numChars = Tcl_NumUtfChars(textPtr->text, textPtr->numBytes); if (textInfoPtr->selItemPtr == itemPtr) { if (textInfoPtr->selectFirst >= textPtr->numChars) { textInfoPtr->selItemPtr = NULL; } else { if (textInfoPtr->selectLast >= textPtr->numChars) { textInfoPtr->selectLast = textPtr->numChars - 1; } if ((textInfoPtr->anchorItemPtr == itemPtr) && (textInfoPtr->selectAnchor >= textPtr->numChars)) { textInfoPtr->selectAnchor = textPtr->numChars - 1; } } } if (textPtr->insertPos >= textPtr->numChars) { textPtr->insertPos = textPtr->numChars; } /* * Restrict so that 0.0 <= angle < 360.0, and then recompute the cached * sine and cosine of the angle. Note that fmod() can produce negative * results, and we try to avoid negative zero as well. */ textPtr->angle = fmod(textPtr->angle, 360.0); if (textPtr->angle < 0.0) { textPtr->angle += 360.0; } if (textPtr->angle == 0.0) { textPtr->angle = 0.0; } textPtr->sine = sin(textPtr->angle * PI/180.0); textPtr->cosine = cos(textPtr->angle * PI/180.0); ComputeTextBbox(canvas, textPtr); return TCL_OK; }
static int ConfigureImage( Tcl_Interp *interp, /* Used for error reporting. */ Tk_Canvas canvas, /* Canvas containing itemPtr. */ Tk_Item *itemPtr, /* Image item to reconfigure. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[], /* Arguments describing things to configure. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { ImageItem *imgPtr = (ImageItem *) itemPtr; Tk_Window tkwin; Tk_Image image; tkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc, (const char **) objv, (char *) imgPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } /* * Create the image. Save the old image around and don't free it until * after the new one is allocated. This keeps the reference count from * going to zero so the image doesn't have to be recreated if it hasn't * changed. */ if (imgPtr->activeImageString != NULL) { itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; } else { itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; } if (imgPtr->imageString != NULL) { image = Tk_GetImage(interp, tkwin, imgPtr->imageString, ImageChangedProc, imgPtr); if (image == NULL) { return TCL_ERROR; } } else { image = NULL; } if (imgPtr->image != NULL) { Tk_FreeImage(imgPtr->image); } imgPtr->image = image; if (imgPtr->activeImageString != NULL) { image = Tk_GetImage(interp, tkwin, imgPtr->activeImageString, ImageChangedProc, imgPtr); if (image == NULL) { return TCL_ERROR; } } else { image = NULL; } if (imgPtr->activeImage != NULL) { Tk_FreeImage(imgPtr->activeImage); } imgPtr->activeImage = image; if (imgPtr->disabledImageString != NULL) { image = Tk_GetImage(interp, tkwin, imgPtr->disabledImageString, ImageChangedProc, imgPtr); if (image == NULL) { return TCL_ERROR; } } else { image = NULL; } if (imgPtr->disabledImage != NULL) { Tk_FreeImage(imgPtr->disabledImage); } imgPtr->disabledImage = image; ComputeImageBbox(canvas, imgPtr); return TCL_OK; }
static void DisplayWinItem( Tk_Canvas canvas, /* Canvas that contains item. */ Tk_Item *itemPtr, /* Item to be displayed. */ Display *display, /* Display on which to draw item. */ Drawable drawable, /* Pixmap or window in which to draw item. */ int regionX, int regionY, int regionWidth, int regionHeight) /* Describes region of canvas that must be * redisplayed (not used). */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; int width, height; short x, y; Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas); Tk_State state = itemPtr->state; if (winItemPtr->tkwin == NULL) { return; } if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } /* * A drawable of None is used by the canvas UnmapNotify handler * to indicate that we should no longer display ourselves. */ if (state == TK_STATE_HIDDEN || drawable == None) { if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { Tk_UnmapWindow(winItemPtr->tkwin); } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } return; } Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1, (double) winItemPtr->header.y1, &x, &y); width = winItemPtr->header.x2 - winItemPtr->header.x1; height = winItemPtr->header.y2 - winItemPtr->header.y1; /* * If the window is completely out of the visible area of the canvas then * unmap it. This code used not to be present (why unmap the window if it * isn't visible anyway?) but this could cause the window to suddenly * reappear if the canvas window got resized. */ if (((x + width) <= 0) || ((y + height) <= 0) || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) { if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { Tk_UnmapWindow(winItemPtr->tkwin); } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } return; } /* * Reposition and map the window (but in different ways depending on * whether the canvas is the window's parent). */ if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin)) || (width != Tk_Width(winItemPtr->tkwin)) || (height != Tk_Height(winItemPtr->tkwin))) { Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height); } Tk_MapWindow(winItemPtr->tkwin); } else { Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y, width, height); } }
static int ConfigureWinItem( Tcl_Interp *interp, /* Used for error reporting. */ Tk_Canvas canvas, /* Canvas containing itemPtr. */ Tk_Item *itemPtr, /* Window item to reconfigure. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[], /* Arguments describing things to configure. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window oldWindow; Tk_Window canvasTkwin; oldWindow = winItemPtr->tkwin; canvasTkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc, (const char **) objv, (char *) winItemPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } /* * A few of the options require additional processing. */ if (oldWindow != winItemPtr->tkwin) { if (oldWindow != NULL) { Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, WinItemStructureProc, winItemPtr); Tk_ManageGeometry(oldWindow, NULL, NULL); Tk_UnmaintainGeometry(oldWindow, canvasTkwin); Tk_UnmapWindow(oldWindow); } if (winItemPtr->tkwin != NULL) { Tk_Window ancestor, parent; /* * Make sure that the canvas is either the parent of the window * associated with the item or a descendant of that parent. Also, * don't allow a top-of-hierarchy window to be managed inside a * canvas. */ parent = Tk_Parent(winItemPtr->tkwin); for (ancestor = canvasTkwin ;; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (((Tk_FakeWin *) ancestor)->flags & TK_TOP_HIERARCHY) { goto badWindow; } } if (((Tk_FakeWin *) winItemPtr->tkwin)->flags & TK_TOP_HIERARCHY){ goto badWindow; } if (winItemPtr->tkwin == canvasTkwin) { goto badWindow; } Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, winItemPtr); Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType, winItemPtr); } } if ((winItemPtr->tkwin != NULL) && (itemPtr->state == TK_STATE_HIDDEN)) { if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { Tk_UnmapWindow(winItemPtr->tkwin); } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } } ComputeWindowBbox(canvas, winItemPtr); return TCL_OK; badWindow: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use %s in a window item of this canvas", Tk_PathName(winItemPtr->tkwin))); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL); winItemPtr->tkwin = NULL; return TCL_ERROR; }
static void DisplayCanvText( Tk_Canvas canvas, /* Canvas that contains item. */ Tk_Item *itemPtr, /* Item to be displayed. */ Display *display, /* Display on which to draw item. */ Drawable drawable, /* Pixmap or window in which to draw item. */ int x, int y, int width, int height) /* Describes region of canvas that must be * redisplayed (not used). */ { TextItem *textPtr; Tk_CanvasTextInfo *textInfoPtr; int selFirstChar, selLastChar; short drawableX, drawableY; Pixmap stipple; Tk_State state = itemPtr->state; textPtr = (TextItem *) itemPtr; textInfoPtr = textPtr->textInfoPtr; if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } stipple = textPtr->stipple; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (textPtr->activeStipple != None) { stipple = textPtr->activeStipple; } } else if (state == TK_STATE_DISABLED) { if (textPtr->disabledStipple != None) { stipple = textPtr->disabledStipple; } } if (textPtr->gc == NULL) { return; } /* * If we're stippling, then modify the stipple offset in the GC. Be sure * to reset the offset when done, since the GC is supposed to be * read-only. */ if (stipple != None) { Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset); } selFirstChar = -1; selLastChar = 0; /* lint. */ Tk_CanvasDrawableCoords(canvas, textPtr->drawOrigin[0], textPtr->drawOrigin[1], &drawableX, &drawableY); if (textInfoPtr->selItemPtr == itemPtr) { selFirstChar = textInfoPtr->selectFirst; selLastChar = textInfoPtr->selectLast; if (selLastChar > textPtr->numChars) { selLastChar = textPtr->numChars - 1; } if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) { int xFirst, yFirst, hFirst; int xLast, yLast, wLast; /* * Draw a special background under the selection. */ Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst, NULL, &hFirst); Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast, &wLast, NULL); /* * If the selection spans the end of this line, then display * selection background all the way to the end of the line. * However, for the last line we only want to display up to the * last character, not the end of the line. */ x = xFirst; height = hFirst; for (y = yFirst ; y <= yLast; y += height) { int dx1, dy1, dx2, dy2; double s = textPtr->sine, c = textPtr->cosine; XPoint points[4]; if (y == yLast) { width = xLast + wLast - x; } else { width = textPtr->actualWidth - x; } dx1 = x - textInfoPtr->selBorderWidth; dy1 = y; dx2 = width + 2 * textInfoPtr->selBorderWidth; dy2 = height; points[0].x = (short)(drawableX + dx1*c + dy1*s); points[0].y = (short)(drawableY + dy1*c - dx1*s); points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s); points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s); points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s); points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s); points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s); points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s); Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable, textInfoPtr->selBorder, points, 4, textInfoPtr->selBorderWidth, TK_RELIEF_RAISED); x = 0; } } } /* * If the insertion point should be displayed, then draw a special * background for the cursor before drawing the text. Note: if we're the * cursor item but the cursor is turned off, then redraw background over * the area of the cursor. This guarantees that the selection won't make * the cursor invisible on mono displays, where both are drawn in the same * color. */ if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) { if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos, &x, &y, NULL, &height)) { int dx1, dy1, dx2, dy2; double s = textPtr->sine, c = textPtr->cosine; XPoint points[4]; dx1 = x - (textInfoPtr->insertWidth / 2); dy1 = y; dx2 = textInfoPtr->insertWidth; dy2 = height; points[0].x = (short)(drawableX + dx1*c + dy1*s); points[0].y = (short)(drawableY + dy1*c - dx1*s); points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s); points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s); points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s); points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s); points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s); points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s); Tk_SetCaretPos(Tk_CanvasTkwin(canvas), points[0].x, points[0].y, height); if (textInfoPtr->cursorOn) { Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable, textInfoPtr->insertBorder, points, 4, textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED); } else if (textPtr->cursorOffGC != NULL) { /* * Redraw the background over the area of the cursor, even * though the cursor is turned off. This guarantees that the * selection won't make the cursor invisible on mono displays, * where both may be drawn in the same color. */ XFillPolygon(display, drawable, textPtr->cursorOffGC, points, 4, Convex, CoordModeOrigin); } } } /* * If there is no selected text or the selected text foreground is the * same as the regular text foreground, then draw one text string. If * there is selected text and the foregrounds differ, draw the regular * text up to the selection, draw the selection, then draw the rest of the * regular text. Drawing the regular text and then the selected text over * it would causes problems with anti-aliased text because the two * anti-aliasing colors would blend together. */ if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) { TkDrawAngledTextLayout(display, drawable, textPtr->gc, textPtr->textLayout, drawableX, drawableY, textPtr->angle, 0, selFirstChar); TkDrawAngledTextLayout(display, drawable, textPtr->selTextGC, textPtr->textLayout, drawableX, drawableY, textPtr->angle, selFirstChar, selLastChar + 1); TkDrawAngledTextLayout(display, drawable, textPtr->gc, textPtr->textLayout, drawableX, drawableY, textPtr->angle, selLastChar + 1, -1); } else { TkDrawAngledTextLayout(display, drawable, textPtr->gc, textPtr->textLayout, drawableX, drawableY, textPtr->angle, 0, -1); } TkUnderlineAngledTextLayout(display, drawable, textPtr->gc, textPtr->textLayout, drawableX, drawableY, textPtr->angle, textPtr->underline); if (stipple != None) { XSetTSOrigin(display, textPtr->gc, 0, 0); } }
static int ImageToPostscript( Tcl_Interp *interp, /* Leave Postscript or error message here. */ Tk_Canvas canvas, /* Information about overall canvas. */ Tk_Item *itemPtr, /* Item for which Postscript is wanted. */ int prepass) /* 1 means this is a prepass to collect font * information; 0 means final Postscript is * being created.*/ { ImageItem *imgPtr = (ImageItem *) itemPtr; Tk_Window canvasWin = Tk_CanvasTkwin(canvas); double x, y; int width, height; Tk_Image image; Tk_State state = itemPtr->state; if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } image = imgPtr->image; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (imgPtr->activeImage != NULL) { image = imgPtr->activeImage; } } else if (state == TK_STATE_DISABLED) { if (imgPtr->disabledImage != NULL) { image = imgPtr->disabledImage; } } if (image == NULL) { /* * Image item without actual image specified. */ return TCL_OK; } Tk_SizeOfImage(image, &width, &height); /* * Compute the coordinates of the lower-left corner of the image, taking * into account the anchor position for the image. */ x = imgPtr->x; y = Tk_CanvasPsY(canvas, imgPtr->y); switch (imgPtr->anchor) { case TK_ANCHOR_NW: y -= height; break; case TK_ANCHOR_N: x -= width/2.0; y -= height; break; case TK_ANCHOR_NE: x -= width; y -= height; break; case TK_ANCHOR_E: x -= width; y -= height/2.0; break; case TK_ANCHOR_SE: x -= width; break; case TK_ANCHOR_S: x -= width/2.0; break; case TK_ANCHOR_SW: break; case TK_ANCHOR_W: y -= height/2.0; break; case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break; } if (!prepass) { Tcl_Obj *psObj = Tcl_GetObjResult(interp); if (Tcl_IsShared(psObj)) { psObj = Tcl_DuplicateObj(psObj); Tcl_SetObjResult(interp, psObj); } Tcl_AppendPrintfToObj(psObj, "%.15g %.15g translate\n", x, y); } return Tk_PostscriptImage(image, interp, canvasWin, ((TkCanvas *) canvas)->psInfo, 0, 0, width, height, prepass); }
static int ConfigureRectOval( Tcl_Interp *interp, /* Used for error reporting. */ Tk_Canvas canvas, /* Canvas containing itemPtr. */ Tk_Item *itemPtr, /* Rectangle item to reconfigure. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[], /* Arguments describing things to configure. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr; XGCValues gcValues; GC newGC; unsigned long mask; Tk_Window tkwin; Tk_TSOffset *tsoffset; XColor *color; Pixmap stipple; Tk_State state; tkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, tkwin, configSpecs, objc, (const char **)objv, (char *) rectOvalPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } state = itemPtr->state; /* * A few of the options require additional processing, such as graphics * contexts. */ if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width || rectOvalPtr->outline.activeDash.number != 0 || rectOvalPtr->outline.activeColor != NULL || rectOvalPtr->outline.activeStipple != None || rectOvalPtr->activeFillColor != NULL || rectOvalPtr->activeFillStipple != None) { itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT; } else { itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT; } tsoffset = &rectOvalPtr->outline.tsoffset; flags = tsoffset->flags; if (flags & TK_OFFSET_LEFT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5); } else if (flags & TK_OFFSET_CENTER) { tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2); } else if (flags & TK_OFFSET_RIGHT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5); } if (flags & TK_OFFSET_TOP) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5); } else if (flags & TK_OFFSET_MIDDLE) { tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2); } else if (flags & TK_OFFSET_BOTTOM) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5); } /* * Configure the outline graphics context. If mask is non-zero, the gc has * changed and must be reallocated, provided that the new settings specify * a valid outline (non-zero width and non-NULL color) */ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(rectOvalPtr->outline)); if (mask && \ rectOvalPtr->outline.width != 0 && \ rectOvalPtr->outline.color != NULL) { gcValues.cap_style = CapProjecting; mask |= GCCapStyle; newGC = Tk_GetGC(tkwin, mask, &gcValues); } else { newGC = None; } if (rectOvalPtr->outline.gc != None) { Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc); } rectOvalPtr->outline.gc = newGC; if (state == TK_STATE_NULL) { state = Canvas(canvas)->canvas_state; } if (state == TK_STATE_HIDDEN) { ComputeRectOvalBbox(canvas, rectOvalPtr); return TCL_OK; } color = rectOvalPtr->fillColor; stipple = rectOvalPtr->fillStipple; if (Canvas(canvas)->currentItemPtr == itemPtr) { if (rectOvalPtr->activeFillColor!=NULL) { color = rectOvalPtr->activeFillColor; } if (rectOvalPtr->activeFillStipple!=None) { stipple = rectOvalPtr->activeFillStipple; } } else if (state == TK_STATE_DISABLED) { if (rectOvalPtr->disabledFillColor!=NULL) { color = rectOvalPtr->disabledFillColor; } if (rectOvalPtr->disabledFillStipple!=None) { stipple = rectOvalPtr->disabledFillStipple; } } if (color == NULL) { newGC = None; } else { gcValues.foreground = color->pixel; if (stipple != None) { gcValues.stipple = stipple; gcValues.fill_style = FillStippled; mask = GCForeground|GCStipple|GCFillStyle; } else { mask = GCForeground; } #ifdef MAC_OSX_TK /* * Mac OS X CG drawing needs access to the outline linewidth even for * fills (as linewidth controls antialiasing). */ gcValues.line_width = rectOvalPtr->outline.gc != None ? rectOvalPtr->outline.gc->line_width : 0; mask |= GCLineWidth; #endif newGC = Tk_GetGC(tkwin, mask, &gcValues); } if (rectOvalPtr->fillGC != None) { Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC); } rectOvalPtr->fillGC = newGC; tsoffset = &rectOvalPtr->tsoffset; flags = tsoffset->flags; if (flags & TK_OFFSET_LEFT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5); } else if (flags & TK_OFFSET_CENTER) { tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2); } else if (flags & TK_OFFSET_RIGHT) { tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5); } if (flags & TK_OFFSET_TOP) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5); } else if (flags & TK_OFFSET_MIDDLE) { tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2); } else if (flags & TK_OFFSET_BOTTOM) { tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5); } ComputeRectOvalBbox(canvas, rectOvalPtr); return TCL_OK; }
static int CreateText( Tcl_Interp *interp, /* Interpreter for error reporting. */ Tk_Canvas canvas, /* Canvas to hold new item. */ Tk_Item *itemPtr, /* Record to hold new item; header has been * initialized by caller. */ int objc, /* Number of arguments in objv. */ Tcl_Obj *const objv[]) /* Arguments describing rectangle. */ { TextItem *textPtr = (TextItem *) itemPtr; int i; if (objc == 0) { Tcl_Panic("canvas did not pass any coords"); } /* * Carry out initialization that is needed in order to clean up after * errors during the the remainder of this function. */ textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas); textPtr->insertPos = 0; textPtr->anchor = TK_ANCHOR_CENTER; textPtr->tsoffset.flags = 0; textPtr->tsoffset.xoffset = 0; textPtr->tsoffset.yoffset = 0; textPtr->color = NULL; textPtr->activeColor = NULL; textPtr->disabledColor = NULL; textPtr->tkfont = NULL; textPtr->justify = TK_JUSTIFY_LEFT; textPtr->stipple = None; textPtr->activeStipple = None; textPtr->disabledStipple = None; textPtr->text = NULL; textPtr->width = 0; textPtr->underline = -1; textPtr->angle = 0.0; textPtr->numChars = 0; textPtr->numBytes = 0; textPtr->textLayout = NULL; textPtr->actualWidth = 0; textPtr->drawOrigin[0] = textPtr->drawOrigin[1] = 0.0; textPtr->gc = NULL; textPtr->selTextGC = NULL; textPtr->cursorOffGC = NULL; textPtr->sine = 0.0; textPtr->cosine = 1.0; /* * Process the arguments to fill in the item record. Only 1 (list) or 2 (x * y) coords are allowed. */ if (objc == 1) { i = 1; } else { const char *arg = Tcl_GetString(objv[1]); i = 2; if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) { i = 1; } } if ((TextCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) { goto error; } if (ConfigureText(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) { return TCL_OK; } error: DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); return TCL_ERROR; }