diff options
author | hobbs <hobbs> | 1999-12-14 06:52:24 (GMT) |
---|---|---|
committer | hobbs <hobbs> | 1999-12-14 06:52:24 (GMT) |
commit | b6b6ff8f0eee42e270a45b019789faa444ed4dad (patch) | |
tree | 5b5ddecf0f3677601c5511eaded466191ef3ba8a /generic/tkCanvWind.c | |
parent | 9b37fa05b11850066aed28ed447109e55708bce0 (diff) | |
download | tk-b6b6ff8f0eee42e270a45b019789faa444ed4dad.zip tk-b6b6ff8f0eee42e270a45b019789faa444ed4dad.tar.gz tk-b6b6ff8f0eee42e270a45b019789faa444ed4dad.tar.bz2 |
* generic/tkStubInit.c:
* generic/tkDecls.h:
* generic/tkIntXlibDecls.h:
* generic/tkInt.decls: added XSetDashes and XWarpPointer
* generic/tk.decls: added Tk_CreateSmoothMethod, and reserved
two spots
* generic/tk.h: added Tk_SmoothMethod struct,
state item to canvas record, #defines for item state,
support for using old char*-based canvas item C creation
procedures with -DUSE_OLD_CANVAS,
Tk_Dash, Tk_TSOffset (-offsets) & Tk_Outline structs and #defs,
decls for dash, outline and postscript routines
* generic/tkBind.c: added support for Quadruple clicks, and added
the -warp option to 'event' with pointer warping routines
* xlib/xgc.c:
* generic/tkRectOval.c:
* generic/tkCanvArc.c:
* generic/tkCanvBmap.c:
* generic/tkCanvImg.c:
* generic/tkCanvLine.c:
* generic/tkCanvPoly.c:
* generic/tkCanvPs.c:
* generic/tkCanvText.c:
* generic/tkCanvUtil.c:
* generic/tkCanvWind.c:
* generic/tkCanvas.c:
* generic/tkCanvas.h: Canvas and items received overhaul to with
the addition of the dash patch (Nijtmans, et al) This includes
objectification of the 'canvas' command, as well as support for
(where appropriate) dashes in items, extended stipple support,
state for all items, and postscript generation of images and
windows. See the new canvas man page for related docs.
* generic/tkEntry.c: added entry widget validation, see entry.n
* generic/tkEvent.c: on simulated events, ButtonPress should
be matched with ButtonRelease to be correct
* generic/tkFont.c: corrected possible null reference
* generic/tkFrame.c: made frame a Tcl_Obj based command
* generic/tkGet.c: added TkGetDoublePixels
* generic/tkImage.c: bug fixes from Img patch and new
Tk_PostscriptImage and Tk_SetTSOrigin functions
* generic/tkImgBmap.c: new ImgBmapPostscript function
* generic/tkImgPhoto.c: new Tk_CreatePhotoOption, Tk_DitherPhoto
* generic/tkInt.h: declarations for some new functions
* generic/tkMessage.c: reworked relief drawing
* generic/tkOldConfig.c: added TK_CONFIG_OBJS so old style
ConfigureWidget calls can pass in Tcl_Obj arrays
* generic/tkScrollbar.c:
* generic/tkScrollbar.h: made -orient use an option table
* generic/tkText.c:
* generic/tkText.h: made -wrap and -state use option tables
* generic/tkTextBTree.c:
* generic/tkTextDisp.c:
* generic/tkTextImage.c:
* generic/tkTextMark.c:
* generic/tkTextTag.c:
* generic/tkTextWind.c: added support for -elide and -state hidden
* generic/tkTrig.c: changed TkMakeBezierCurve to support returning
the upper limit of points needed for spline
* generic/tkUtil.c: new option table parsing routines
* generic/tkWindow.c: init'ing of warp stuff, mouseButtonState
Diffstat (limited to 'generic/tkCanvWind.c')
-rw-r--r-- | generic/tkCanvWind.c | 331 |
1 files changed, 285 insertions, 46 deletions
diff --git a/generic/tkCanvWind.c b/generic/tkCanvWind.c index 4dd8ee3..fab0015 100644 --- a/generic/tkCanvWind.c +++ b/generic/tkCanvWind.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCanvWind.c,v 1.3 1999/04/16 01:51:12 stanton Exp $ + * RCS: @(#) $Id: tkCanvWind.c,v 1.4 1999/12/14 06:52:26 hobbs Exp $ */ #include <stdio.h> @@ -41,7 +41,12 @@ typedef struct WindowItem { * Information used for parsing configuration specs: */ -static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc, +static Tk_CustomOption stateOption = { + (Tk_OptionParseProc *) TkStateParseProc, + TkStatePrintProc, (ClientData) 2 +}; +static Tk_CustomOption tagsOption = { + (Tk_OptionParseProc *) Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, (ClientData) NULL }; @@ -50,6 +55,9 @@ static Tk_ConfigSpec configSpecs[] = { "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT}, {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL, "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT}, + {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL, + (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK, + &stateOption}, {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL, (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL, @@ -68,10 +76,10 @@ static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas, WindowItem *winItemPtr)); static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - char **argv, int flags)); + Tcl_Obj *CONST argv[], int flags)); static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, struct Tk_Item *itemPtr, - int argc, char **argv)); + int argc, Tcl_Obj *CONST argv[])); static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, Display *display)); static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas, @@ -84,7 +92,7 @@ static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double deltaX, double deltaY)); static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas, Tk_Item *itemPtr, int argc, - char **argv)); + Tcl_Obj *CONST argv[])); static void WinItemLostSlaveProc _ANSI_ARGS_(( ClientData clientData, Tk_Window tkwin)); static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData, @@ -93,8 +101,17 @@ static void WinItemStructureProc _ANSI_ARGS_(( ClientData clientData, XEvent *eventPtr)); static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double *rectPtr)); +static int WinItemToPostscript _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Canvas canvas, Tk_Item *itemPtr, int prepass)); static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas, Tk_Item *itemPtr, double *pointPtr)); +#ifdef X_GetImage +static int xerrorhandler _ANSI_ARGS_((ClientData clientData, + XErrorEvent *e)); +#endif +static int CanvasPsWindow _ANSI_ARGS_((Tcl_Interp *interp, + Tk_Window tkwin, Tk_Canvas canvas, double x, + double y, int width, int height)); /* * The structure below defines the window item type by means of procedures @@ -110,10 +127,10 @@ Tk_ItemType tkWindowType = { WinItemCoords, /* coordProc */ DeleteWinItem, /* deleteProc */ DisplayWinItem, /* displayProc */ - 1, /* alwaysRedraw */ + 1|TK_CONFIG_OBJS, /* flags */ WinItemToPoint, /* pointProc */ WinItemToArea, /* areaProc */ - (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */ + WinItemToPostscript, /* postscriptProc */ ScaleWinItem, /* scaleProc */ TranslateWinItem, /* translateProc */ (Tk_ItemIndexProc *) NULL, /* indexProc */ @@ -121,7 +138,7 @@ Tk_ItemType tkWindowType = { (Tk_ItemSelectionProc *) NULL, /* selectionProc */ (Tk_ItemInsertProc *) NULL, /* insertProc */ (Tk_ItemDCharsProc *) NULL, /* dTextProc */ - (Tk_ItemType *) NULL /* nextPtr */ + (Tk_ItemType *) NULL, /* nextPtr */ }; @@ -164,11 +181,24 @@ CreateWinItem(interp, canvas, itemPtr, argc, argv) Tk_Item *itemPtr; /* Record to hold new item; header * has been initialized by caller. */ int argc; /* Number of arguments in argv. */ - char **argv; /* Arguments describing rectangle. */ + Tcl_Obj *CONST argv[]; /* Arguments describing window. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; + int i; + + if (argc==1) { + i = 1; + } else { + char *arg = Tcl_GetStringFromObj(argv[1], NULL); + if (((argc>1) && (arg[0] == '-') + && (arg[1] >= 'a') && (arg[1] <= 'z'))) { + i = 1; + } else { + i = 2; + } + } - if (argc < 2) { + if (argc < i) { Tcl_AppendResult(interp, "wrong # args: should be \"", Tk_PathName(Tk_CanvasTkwin(canvas)), " create ", itemPtr->typePtr->name, " x y ?options?\"", @@ -190,18 +220,16 @@ CreateWinItem(interp, canvas, itemPtr, argc, argv) * Process the arguments to fill in the item record. */ - if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) != TCL_OK) - || (Tk_CanvasGetCoord(interp, canvas, argv[1], - &winItemPtr->y) != TCL_OK)) { - return TCL_ERROR; + if ((WinItemCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) { + goto error; } - - if (ConfigureWinItem(interp, canvas, itemPtr, argc-2, argv+2, 0) - != TCL_OK) { - DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); - return TCL_ERROR; + if (ConfigureWinItem(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) { + return TCL_OK; } - return TCL_OK; + + error: + DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas))); + return TCL_ERROR; } /* @@ -230,19 +258,33 @@ WinItemCoords(interp, canvas, itemPtr, argc, argv) * read or modified. */ int argc; /* Number of coordinates supplied in * argv. */ - char **argv; /* Array of coordinates: x1, y1, + Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1, * x2, y2, ... */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; - char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE]; if (argc == 0) { - Tcl_PrintDouble(interp, winItemPtr->x, x); - Tcl_PrintDouble(interp, winItemPtr->y, y); - Tcl_AppendResult(interp, x, " ", y, (char *) NULL); - } else if (argc == 2) { - if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) - != TCL_OK) || (Tk_CanvasGetCoord(interp, canvas, argv[1], + Tcl_Obj *obj = Tcl_NewObj(); + Tcl_Obj *subobj = Tcl_NewDoubleObj(winItemPtr->x); + Tcl_ListObjAppendElement(interp, obj, subobj); + subobj = Tcl_NewDoubleObj(winItemPtr->y); + Tcl_ListObjAppendElement(interp, obj, subobj); + Tcl_SetObjResult(interp, obj); + } else if (argc < 3) { + if (argc==1) { + if (Tcl_ListObjGetElements(interp, argv[0], &argc, + (Tcl_Obj ***) &argv) != TCL_OK) { + return TCL_ERROR; + } else if (argc != 2) { + char buf[64 + TCL_INTEGER_SPACE]; + + sprintf(buf, "wrong # coordinates: expected 2, got %d", argc); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_ERROR; + } + } + if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &winItemPtr->x) + != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1], &winItemPtr->y) != TCL_OK)) { return TCL_ERROR; } @@ -281,7 +323,7 @@ ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags) Tk_Canvas canvas; /* Canvas containing itemPtr. */ Tk_Item *itemPtr; /* Window item to reconfigure. */ int argc; /* Number of elements in argv. */ - char **argv; /* Arguments describing things to configure. */ + Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; @@ -290,8 +332,8 @@ ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags) oldWindow = winItemPtr->tkwin; canvasTkwin = Tk_CanvasTkwin(canvas); - if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, argv, - (char *) winItemPtr, flags) != TCL_OK) { + if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, (char **) argv, + (char *) winItemPtr, flags|TK_CONFIG_OBJS) != TCL_OK) { return TCL_ERROR; } @@ -417,11 +459,15 @@ ComputeWindowBbox(canvas, winItemPtr) * recomputed. */ { int width, height, x, y; + Tk_State state = winItemPtr->header.state; x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5)); y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5)); - if (winItemPtr->tkwin == NULL) { + if (state == TK_STATE_NULL) { + state = ((TkCanvas *)canvas)->canvas_state; + } + if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) { /* * There is no window for this item yet. Just give it a 1x1 * bounding box. Don't give it a 0x0 bounding box; there are @@ -542,11 +588,18 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, 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 = ((TkCanvas *)canvas)->canvas_state; + } + if (state == TK_STATE_HIDDEN) { + Tk_UnmapWindow(winItemPtr->tkwin); + return; + } Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1, (double) winItemPtr->header.y1, &x, &y); width = winItemPtr->header.x2 - winItemPtr->header.x1; @@ -593,7 +646,7 @@ DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY, * WinItemToPoint -- * * Computes the distance from a given point to a given - * rectangle, in canvas units. + * window, in canvas units. * * Results: * The return value is 0 if the point whose x and y coordinates @@ -622,7 +675,7 @@ WinItemToPoint(canvas, itemPtr, pointPtr) y2 = winItemPtr->header.y2; /* - * Point is outside rectangle. + * Point is outside window. */ if (pointPtr[0] < x1) { @@ -692,16 +745,203 @@ WinItemToArea(canvas, itemPtr, rectPtr) /* *-------------------------------------------------------------- * + * xerrorhandler -- + * + * This is a dummy function to catch X11 errors during an + * attempt to print a canvas window. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +#ifdef X_GetImage +static int +xerrorhandler(clientData, e) + ClientData clientData; + XErrorEvent *e; +{ + return 0; +} +#endif + + +/* + *-------------------------------------------------------------- + * + * WinItemToPostscript -- + * + * This procedure is called to generate Postscript for + * window items. + * + * Results: + * The return value is a standard Tcl result. If an error + * occurs in generating Postscript then an error message is + * left in interp->result, replacing whatever used to be there. + * If no error occurs, then Postscript for the item is appended + * to the result. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static int +WinItemToPostscript(interp, canvas, itemPtr, prepass) + 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.*/ +{ + WindowItem *winItemPtr = (WindowItem *)itemPtr; + + double x, y; + int width, height; + Tk_Window tkwin = winItemPtr->tkwin; + + if (prepass || winItemPtr->tkwin == NULL) { + return TCL_OK; + } + + width = Tk_Width(tkwin); + height = Tk_Height(tkwin); + + /* + * Compute the coordinates of the lower-left corner of the window, + * taking into account the anchor position for the window. + */ + + x = winItemPtr->x; + y = Tk_CanvasPsY(canvas, winItemPtr->y); + + switch (winItemPtr->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; + } + + return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height); +} + +static int +CanvasPsWindow(interp, tkwin, canvas, x, y, width, height) + Tcl_Interp *interp; /* Leave Postscript or error message + * here. */ + Tk_Window tkwin; /* window to be printed */ + Tk_Canvas canvas; /* Information about overall canvas. */ + double x, y; /* origin of window. */ + int width, height; /* width/height of window. */ +{ + char buffer[256]; + TkWindow *winPtr; + XImage *ximage; + int result; + Tcl_DString buffer1, buffer2; +#ifdef X_GetImage + Tk_ErrorHandler handle; +#endif + + sprintf(buffer, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n", + Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y); + Tcl_AppendResult(interp, buffer, (char *) NULL); + + /* first try if the widget has its own "postscript" command. If it + * exists, this will produce much better postscript than + * when a pixmap is used. + */ + + Tcl_DStringInit(&buffer1); + Tcl_DStringInit(&buffer2); + Tcl_DStringGetResult(interp, &buffer2); + sprintf (buffer, "%s postscript -prolog 0\n", Tk_PathName(tkwin)); + result = Tcl_Eval(interp, buffer); + Tcl_DStringGetResult(interp, &buffer1); + Tcl_DStringResult(interp, &buffer2); + Tcl_DStringFree(&buffer2); + + if (result == TCL_OK) { + Tcl_AppendResult(interp, + "50 dict begin\nsave\ngsave\n", + (char *) NULL); + sprintf (buffer, + "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d", + height, width, height, width); + Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, " 0 rlineto closepath\n", + "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n", + Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n", + (char *) NULL); + Tcl_DStringFree(&buffer1); + + for (winPtr = ((TkWindow *) tkwin)->childList; winPtr != NULL; + winPtr = winPtr->nextPtr) { + if (Tk_IsMapped(winPtr)) { +/* printf("child window: %s\n", winPtr->pathName);*/ + } + } + return result; + } + Tcl_DStringFree(&buffer1); + + /* + * If the window is off the screen it will generate an BadMatch/XError + * We catch any BadMatch errors here + */ +#ifdef X_GetImage + handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch, + X_GetImage, -1, xerrorhandler, (ClientData) tkwin); +#endif + + /* + * Generate an XImage from the window. We can then read pixel + * values out of the XImage. + */ + + ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0, + (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap); + +#ifdef X_GetImage + Tk_DeleteErrorHandler(handle); +#endif + + if (ximage == (XImage*) NULL) { + return TCL_OK; + } + + result = TkPostscriptImage(interp, tkwin, + ((TkCanvas *)canvas)->psInfo, ximage, 0, 0, width, height); + + XDestroyImage(ximage); + return result; +} + +/* + *-------------------------------------------------------------- + * * ScaleWinItem -- * - * This procedure is invoked to rescale a rectangle or oval - * item. + * This procedure is invoked to rescale a window item. * * Results: * None. * * Side effects: - * The rectangle or oval referred to by itemPtr is rescaled + * The window referred to by itemPtr is rescaled * so that the following transformation is applied to all * point coordinates: * x' = originX + scaleX*(x-originX) @@ -712,9 +952,9 @@ WinItemToArea(canvas, itemPtr, rectPtr) static void ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY) - Tk_Canvas canvas; /* Canvas containing rectangle. */ - Tk_Item *itemPtr; /* Rectangle to be scaled. */ - double originX, originY; /* Origin about which to scale rect. */ + Tk_Canvas canvas; /* Canvas containing window. */ + Tk_Item *itemPtr; /* Window to be scaled. */ + double originX, originY; /* Origin about which to scale window. */ double scaleX; /* Amount to scale in X direction. */ double scaleY; /* Amount to scale in Y direction. */ { @@ -736,16 +976,15 @@ ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY) * * TranslateWinItem -- * - * This procedure is called to move a rectangle or oval by a - * given amount. + * This procedure is called to move a window by a given amount. * * Results: * None. * * Side effects: - * The position of the rectangle or oval is offset by - * (xDelta, yDelta), and the bounding box is updated in the - * generic part of the item structure. + * The position of the window is offset by (xDelta, yDelta), + * and the bounding box is updated in the generic part of the + * item structure. * *-------------------------------------------------------------- */ |