4 * This file implements window items for canvas widgets.
6 * Copyright (c) 1992-1994 The Regents of the University of California.
7 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
21 * The structure below defines the record for each window item.
24 typedef struct WindowItem {
25 Tk_Item header; /* Generic stuff that's the same for all
26 * types. MUST BE FIRST IN STRUCTURE. */
27 double x, y; /* Coordinates of positioning point for
29 Tk_Window tkwin; /* Window associated with item. NULL means
30 * window has been destroyed. */
31 int width; /* Width to use for window (<= 0 means use
32 * window's requested width). */
33 int height; /* Width to use for window (<= 0 means use
34 * window's requested width). */
35 Tk_Anchor anchor; /* Where to anchor window relative to
37 Tk_Canvas canvas; /* Canvas containing this item. */
41 * Information used for parsing configuration specs:
44 static Tk_CustomOption stateOption = {
45 (Tk_OptionParseProc *) TkStateParseProc,
46 TkStatePrintProc, (ClientData) 2
48 static Tk_CustomOption tagsOption = {
49 (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
50 Tk_CanvasTagsPrintProc, (ClientData) NULL
53 static Tk_ConfigSpec configSpecs[] = {
54 {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
55 "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
56 {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
57 "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT},
58 {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
59 (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
61 {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
62 (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
63 {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
64 "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT},
65 {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
66 (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK},
67 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
72 * Prototypes for procedures defined in this file:
75 static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas,
76 WindowItem *winItemPtr));
77 static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp,
78 Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
79 Tcl_Obj *CONST objv[], int flags));
80 static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp,
81 Tk_Canvas canvas, struct Tk_Item *itemPtr,
82 int objc, Tcl_Obj *CONST objv[]));
83 static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas,
84 Tk_Item *itemPtr, Display *display));
85 static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas,
86 Tk_Item *itemPtr, Display *display, Drawable dst,
87 int x, int y, int width, int height));
88 static void ScaleWinItem _ANSI_ARGS_((Tk_Canvas canvas,
89 Tk_Item *itemPtr, double originX, double originY,
90 double scaleX, double scaleY));
91 static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas,
92 Tk_Item *itemPtr, double deltaX, double deltaY));
93 static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp,
94 Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
95 Tcl_Obj *CONST objv[]));
96 static void WinItemLostSlaveProc _ANSI_ARGS_((
97 ClientData clientData, Tk_Window tkwin));
98 static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData,
100 static void WinItemStructureProc _ANSI_ARGS_((
101 ClientData clientData, XEvent *eventPtr));
102 static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas,
103 Tk_Item *itemPtr, double *rectPtr));
104 static int WinItemToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
105 Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
106 static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas,
107 Tk_Item *itemPtr, double *pointPtr));
109 static int xerrorhandler _ANSI_ARGS_((ClientData clientData,
112 static int CanvasPsWindow _ANSI_ARGS_((Tcl_Interp *interp,
113 Tk_Window tkwin, Tk_Canvas canvas, double x,
114 double y, int width, int height));
117 * The structure below defines the window item type by means of procedures
118 * that can be invoked by generic item code.
121 Tk_ItemType tkWindowType = {
123 sizeof(WindowItem), /* itemSize */
124 CreateWinItem, /* createProc */
125 configSpecs, /* configSpecs */
126 ConfigureWinItem, /* configureProc */
127 WinItemCoords, /* coordProc */
128 DeleteWinItem, /* deleteProc */
129 DisplayWinItem, /* displayProc */
130 1|TK_CONFIG_OBJS, /* flags */
131 WinItemToPoint, /* pointProc */
132 WinItemToArea, /* areaProc */
133 WinItemToPostscript, /* postscriptProc */
134 ScaleWinItem, /* scaleProc */
135 TranslateWinItem, /* translateProc */
136 (Tk_ItemIndexProc *) NULL, /* indexProc */
137 (Tk_ItemCursorProc *) NULL, /* cursorProc */
138 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
139 (Tk_ItemInsertProc *) NULL, /* insertProc */
140 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
141 (Tk_ItemType *) NULL, /* nextPtr */
146 * The structure below defines the official type record for the
150 static Tk_GeomMgr canvasGeomType = {
152 WinItemRequestProc, /* requestProc */
153 WinItemLostSlaveProc, /* lostSlaveProc */
157 *--------------------------------------------------------------
161 * This procedure is invoked to create a new window
165 * A standard Tcl return value. If an error occurred in
166 * creating the item, then an error message is left in
167 * the interp's result; in this case itemPtr is
168 * left uninitialized, so it can be safely freed by the
172 * A new window item is created.
174 *--------------------------------------------------------------
178 CreateWinItem(interp, canvas, itemPtr, objc, objv)
179 Tcl_Interp *interp; /* Interpreter for error reporting. */
180 Tk_Canvas canvas; /* Canvas to hold new item. */
181 Tk_Item *itemPtr; /* Record to hold new item; header
182 * has been initialized by caller. */
183 int objc; /* Number of arguments in objv. */
184 Tcl_Obj *CONST objv[]; /* Arguments describing window. */
186 WindowItem *winItemPtr = (WindowItem *) itemPtr;
191 } else if (objc > 1) {
192 char *arg = Tcl_GetString(objv[1]);
193 if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
199 Tcl_AppendResult(interp, "wrong # args: should be \"",
200 Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
201 itemPtr->typePtr->name, " x y ?options?\"",
207 * Initialize item's record.
210 winItemPtr->tkwin = NULL;
211 winItemPtr->width = 0;
212 winItemPtr->height = 0;
213 winItemPtr->anchor = TK_ANCHOR_CENTER;
214 winItemPtr->canvas = canvas;
217 * Process the arguments to fill in the item record.
220 if ((WinItemCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {
223 if (ConfigureWinItem(interp, canvas, itemPtr, objc-i, objv+i, 0) == TCL_OK) {
228 DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
233 *--------------------------------------------------------------
237 * This procedure is invoked to process the "coords" widget
238 * command on window items. See the user documentation for
239 * details on what it does.
242 * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
245 * The coordinates for the given item may be changed.
247 *--------------------------------------------------------------
251 WinItemCoords(interp, canvas, itemPtr, objc, objv)
252 Tcl_Interp *interp; /* Used for error reporting. */
253 Tk_Canvas canvas; /* Canvas containing item. */
254 Tk_Item *itemPtr; /* Item whose coordinates are to be
255 * read or modified. */
256 int objc; /* Number of coordinates supplied in
258 Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1,
261 WindowItem *winItemPtr = (WindowItem *) itemPtr;
264 Tcl_Obj *obj = Tcl_NewObj();
265 Tcl_Obj *subobj = Tcl_NewDoubleObj(winItemPtr->x);
266 Tcl_ListObjAppendElement(interp, obj, subobj);
267 subobj = Tcl_NewDoubleObj(winItemPtr->y);
268 Tcl_ListObjAppendElement(interp, obj, subobj);
269 Tcl_SetObjResult(interp, obj);
270 } else if (objc < 3) {
272 if (Tcl_ListObjGetElements(interp, objv[0], &objc,
273 (Tcl_Obj ***) &objv) != TCL_OK) {
275 } else if (objc != 2) {
276 char buf[64 + TCL_INTEGER_SPACE];
278 sprintf(buf, "wrong # coordinates: expected 2, got %d", objc);
279 Tcl_SetResult(interp, buf, TCL_VOLATILE);
283 if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], &winItemPtr->x)
284 != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
285 &winItemPtr->y) != TCL_OK)) {
288 ComputeWindowBbox(canvas, winItemPtr);
290 char buf[64 + TCL_INTEGER_SPACE];
292 sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", objc);
293 Tcl_SetResult(interp, buf, TCL_VOLATILE);
300 *--------------------------------------------------------------
302 * ConfigureWinItem --
304 * This procedure is invoked to configure various aspects
305 * of a window item, such as its anchor position.
308 * A standard Tcl result code. If an error occurs, then
309 * an error message is left in the interp's result.
312 * Configuration information may be set for itemPtr.
314 *--------------------------------------------------------------
318 ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags)
319 Tcl_Interp *interp; /* Used for error reporting. */
320 Tk_Canvas canvas; /* Canvas containing itemPtr. */
321 Tk_Item *itemPtr; /* Window item to reconfigure. */
322 int objc; /* Number of elements in objv. */
323 Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */
324 int flags; /* Flags to pass to Tk_ConfigureWidget. */
326 WindowItem *winItemPtr = (WindowItem *) itemPtr;
328 Tk_Window canvasTkwin;
330 oldWindow = winItemPtr->tkwin;
331 canvasTkwin = Tk_CanvasTkwin(canvas);
332 if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc,
333 (CONST char **) objv, (char *) winItemPtr, flags|TK_CONFIG_OBJS)) {
338 * A few of the options require additional processing.
341 if (oldWindow != winItemPtr->tkwin) {
342 if (oldWindow != NULL) {
343 Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
344 WinItemStructureProc, (ClientData) winItemPtr);
345 Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
347 Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
348 Tk_UnmapWindow(oldWindow);
350 if (winItemPtr->tkwin != NULL) {
351 Tk_Window ancestor, parent;
354 * Make sure that the canvas is either the parent of the
355 * window associated with the item or a descendant of that
356 * parent. Also, don't allow a top-of-hierarchy window to be
357 * managed inside a canvas.
360 parent = Tk_Parent(winItemPtr->tkwin);
361 for (ancestor = canvasTkwin; ;
362 ancestor = Tk_Parent(ancestor)) {
363 if (ancestor == parent) {
366 if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) {
368 Tcl_AppendResult(interp, "can't use ",
369 Tk_PathName(winItemPtr->tkwin),
370 " in a window item of this canvas", (char *) NULL);
371 winItemPtr->tkwin = NULL;
375 if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_HIERARCHY) {
378 if (winItemPtr->tkwin == canvasTkwin) {
381 Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
382 WinItemStructureProc, (ClientData) winItemPtr);
383 Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType,
384 (ClientData) winItemPtr);
388 ComputeWindowBbox(canvas, winItemPtr);
394 *--------------------------------------------------------------
398 * This procedure is called to clean up the data structure
399 * associated with a window item.
405 * Resources associated with itemPtr are released.
407 *--------------------------------------------------------------
411 DeleteWinItem(canvas, itemPtr, display)
412 Tk_Canvas canvas; /* Overall info about widget. */
413 Tk_Item *itemPtr; /* Item that is being deleted. */
414 Display *display; /* Display containing window for
417 WindowItem *winItemPtr = (WindowItem *) itemPtr;
418 Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
420 if (winItemPtr->tkwin != NULL) {
421 Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
422 WinItemStructureProc, (ClientData) winItemPtr);
423 Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL,
425 if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
426 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
428 Tk_UnmapWindow(winItemPtr->tkwin);
433 *--------------------------------------------------------------
435 * ComputeWindowBbox --
437 * This procedure is invoked to compute the bounding box of
438 * all the pixels that may be drawn as part of a window item.
439 * This procedure is where the child window's placement is
446 * The fields x1, y1, x2, and y2 are updated in the header
449 *--------------------------------------------------------------
453 ComputeWindowBbox(canvas, winItemPtr)
454 Tk_Canvas canvas; /* Canvas that contains item. */
455 WindowItem *winItemPtr; /* Item whose bbox is to be
458 int width, height, x, y;
459 Tk_State state = winItemPtr->header.state;
461 x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));
462 y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));
464 if (state == TK_STATE_NULL) {
465 state = ((TkCanvas *)canvas)->canvas_state;
467 if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) {
469 * There is no window for this item yet. Just give it a 1x1
470 * bounding box. Don't give it a 0x0 bounding box; there are
471 * strange cases where this bounding box might be used as the
472 * dimensions of the window, and 0x0 causes problems under X.
475 winItemPtr->header.x1 = x;
476 winItemPtr->header.x2 = winItemPtr->header.x1 + 1;
477 winItemPtr->header.y1 = y;
478 winItemPtr->header.y2 = winItemPtr->header.y1 + 1;
483 * Compute dimensions of window.
486 width = winItemPtr->width;
488 width = Tk_ReqWidth(winItemPtr->tkwin);
493 height = winItemPtr->height;
495 height = Tk_ReqHeight(winItemPtr->tkwin);
502 * Compute location of window, using anchor information.
505 switch (winItemPtr->anchor) {
532 case TK_ANCHOR_CENTER:
539 * Store the information in the item header.
542 winItemPtr->header.x1 = x;
543 winItemPtr->header.y1 = y;
544 winItemPtr->header.x2 = x + width;
545 winItemPtr->header.y2 = y + height;
549 *--------------------------------------------------------------
553 * This procedure is invoked to "draw" a window item in a given
554 * drawable. Since the window draws itself, we needn't do any
555 * actual redisplay here. However, this procedure takes care
556 * of actually repositioning the child window so that it occupies
557 * the correct screen position.
563 * The child window's position may get changed. Note: this
564 * procedure gets called both when a window needs to be displayed
565 * and when it ceases to be visible on the screen (e.g. it was
566 * scrolled or moved off-screen or the enclosing canvas is
569 *--------------------------------------------------------------
573 DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY,
574 regionWidth, regionHeight)
575 Tk_Canvas canvas; /* Canvas that contains item. */
576 Tk_Item *itemPtr; /* Item to be displayed. */
577 Display *display; /* Display on which to draw item. */
578 Drawable drawable; /* Pixmap or window in which to draw
580 int regionX, regionY, regionWidth, regionHeight;
581 /* Describes region of canvas that
582 * must be redisplayed (not used). */
584 WindowItem *winItemPtr = (WindowItem *) itemPtr;
587 Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
588 Tk_State state = itemPtr->state;
590 if (winItemPtr->tkwin == NULL) {
593 if(state == TK_STATE_NULL) {
594 state = ((TkCanvas *)canvas)->canvas_state;
596 if (state == TK_STATE_HIDDEN) {
597 Tk_UnmapWindow(winItemPtr->tkwin);
600 Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
601 (double) winItemPtr->header.y1, &x, &y);
602 width = winItemPtr->header.x2 - winItemPtr->header.x1;
603 height = winItemPtr->header.y2 - winItemPtr->header.y1;
606 * If the window is completely out of the visible area of the canvas
607 * then unmap it. This code used not to be present (why unmap the
608 * window if it isn't visible anyway?) but this could cause the
609 * window to suddenly reappear if the canvas window got resized.
612 if (((x + width) <= 0) || ((y + height) <= 0)
613 || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {
614 if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
615 Tk_UnmapWindow(winItemPtr->tkwin);
617 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
623 * Reposition and map the window (but in different ways depending
624 * on whether the canvas is the window's parent).
627 if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
628 if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
629 || (width != Tk_Width(winItemPtr->tkwin))
630 || (height != Tk_Height(winItemPtr->tkwin))) {
631 Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
633 Tk_MapWindow(winItemPtr->tkwin);
635 Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
641 *--------------------------------------------------------------
645 * Computes the distance from a given point to a given
646 * window, in canvas units.
649 * The return value is 0 if the point whose x and y coordinates
650 * are coordPtr[0] and coordPtr[1] is inside the window. If the
651 * point isn't inside the window then the return value is the
652 * distance from the point to the window.
657 *--------------------------------------------------------------
661 WinItemToPoint(canvas, itemPtr, pointPtr)
662 Tk_Canvas canvas; /* Canvas containing item. */
663 Tk_Item *itemPtr; /* Item to check against point. */
664 double *pointPtr; /* Pointer to x and y coordinates. */
666 WindowItem *winItemPtr = (WindowItem *) itemPtr;
667 double x1, x2, y1, y2, xDiff, yDiff;
669 x1 = winItemPtr->header.x1;
670 y1 = winItemPtr->header.y1;
671 x2 = winItemPtr->header.x2;
672 y2 = winItemPtr->header.y2;
675 * Point is outside window.
678 if (pointPtr[0] < x1) {
679 xDiff = x1 - pointPtr[0];
680 } else if (pointPtr[0] >= x2) {
681 xDiff = pointPtr[0] + 1 - x2;
686 if (pointPtr[1] < y1) {
687 yDiff = y1 - pointPtr[1];
688 } else if (pointPtr[1] >= y2) {
689 yDiff = pointPtr[1] + 1 - y2;
694 return hypot(xDiff, yDiff);
698 *--------------------------------------------------------------
702 * This procedure is called to determine whether an item
703 * lies entirely inside, entirely outside, or overlapping
707 * -1 is returned if the item is entirely outside the area
708 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
709 * inside the given area.
714 *--------------------------------------------------------------
718 WinItemToArea(canvas, itemPtr, rectPtr)
719 Tk_Canvas canvas; /* Canvas containing item. */
720 Tk_Item *itemPtr; /* Item to check against rectangle. */
721 double *rectPtr; /* Pointer to array of four coordinates
722 * (x1, y1, x2, y2) describing rectangular
725 WindowItem *winItemPtr = (WindowItem *) itemPtr;
727 if ((rectPtr[2] <= winItemPtr->header.x1)
728 || (rectPtr[0] >= winItemPtr->header.x2)
729 || (rectPtr[3] <= winItemPtr->header.y1)
730 || (rectPtr[1] >= winItemPtr->header.y2)) {
733 if ((rectPtr[0] <= winItemPtr->header.x1)
734 && (rectPtr[1] <= winItemPtr->header.y1)
735 && (rectPtr[2] >= winItemPtr->header.x2)
736 && (rectPtr[3] >= winItemPtr->header.y2)) {
743 *--------------------------------------------------------------
747 * This is a dummy function to catch X11 errors during an
748 * attempt to print a canvas window.
756 *--------------------------------------------------------------
761 xerrorhandler(clientData, e)
762 ClientData clientData;
771 *--------------------------------------------------------------
773 * WinItemToPostscript --
775 * This procedure is called to generate Postscript for
779 * The return value is a standard Tcl result. If an error
780 * occurs in generating Postscript then an error message is
781 * left in interp->result, replacing whatever used to be there.
782 * If no error occurs, then Postscript for the item is appended
788 *--------------------------------------------------------------
792 WinItemToPostscript(interp, canvas, itemPtr, prepass)
793 Tcl_Interp *interp; /* Leave Postscript or error message
795 Tk_Canvas canvas; /* Information about overall canvas. */
796 Tk_Item *itemPtr; /* Item for which Postscript is
798 int prepass; /* 1 means this is a prepass to
799 * collect font information; 0 means
800 * final Postscript is being created.*/
802 WindowItem *winItemPtr = (WindowItem *)itemPtr;
806 Tk_Window tkwin = winItemPtr->tkwin;
808 if (prepass || winItemPtr->tkwin == NULL) {
812 width = Tk_Width(tkwin);
813 height = Tk_Height(tkwin);
816 * Compute the coordinates of the lower-left corner of the window,
817 * taking into account the anchor position for the window.
821 y = Tk_CanvasPsY(canvas, winItemPtr->y);
823 switch (winItemPtr->anchor) {
824 case TK_ANCHOR_NW: y -= height; break;
825 case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
826 case TK_ANCHOR_NE: x -= width; y -= height; break;
827 case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
828 case TK_ANCHOR_SE: x -= width; break;
829 case TK_ANCHOR_S: x -= width/2.0; break;
830 case TK_ANCHOR_SW: break;
831 case TK_ANCHOR_W: y -= height/2.0; break;
832 case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
835 return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height);
839 CanvasPsWindow(interp, tkwin, canvas, x, y, width, height)
840 Tcl_Interp *interp; /* Leave Postscript or error message
842 Tk_Window tkwin; /* window to be printed */
843 Tk_Canvas canvas; /* Information about overall canvas. */
844 double x, y; /* origin of window. */
845 int width, height; /* width/height of window. */
850 Tcl_DString buffer1, buffer2;
852 Tk_ErrorHandler handle;
855 sprintf(buffer, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n",
856 Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y);
857 Tcl_AppendResult(interp, buffer, (char *) NULL);
859 /* first try if the widget has its own "postscript" command. If it
860 * exists, this will produce much better postscript than
861 * when a pixmap is used.
864 Tcl_DStringInit(&buffer1);
865 Tcl_DStringInit(&buffer2);
866 Tcl_DStringGetResult(interp, &buffer2);
867 sprintf (buffer, "%s postscript -prolog 0\n", Tk_PathName(tkwin));
868 result = Tcl_Eval(interp, buffer);
869 Tcl_DStringGetResult(interp, &buffer1);
870 Tcl_DStringResult(interp, &buffer2);
871 Tcl_DStringFree(&buffer2);
873 if (result == TCL_OK) {
874 Tcl_AppendResult(interp,
875 "50 dict begin\nsave\ngsave\n",
878 "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
879 height, width, height, width);
880 Tcl_AppendResult(interp, buffer, (char *) NULL);
881 Tcl_AppendResult(interp, " 0 rlineto closepath\n",
882 "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
883 Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n",
885 Tcl_DStringFree(&buffer1);
889 Tcl_DStringFree(&buffer1);
892 * If the window is off the screen it will generate an BadMatch/XError
893 * We catch any BadMatch errors here
896 handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch,
897 X_GetImage, -1, xerrorhandler, (ClientData) tkwin);
901 * Generate an XImage from the window. We can then read pixel
902 * values out of the XImage.
905 ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0,
906 (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
909 Tk_DeleteErrorHandler(handle);
912 if (ximage == (XImage*) NULL) {
916 result = TkPostscriptImage(interp, tkwin,
917 ((TkCanvas *)canvas)->psInfo, ximage, 0, 0, width, height);
919 XDestroyImage(ximage);
924 *--------------------------------------------------------------
928 * This procedure is invoked to rescale a window item.
934 * The window referred to by itemPtr is rescaled
935 * so that the following transformation is applied to all
937 * x' = originX + scaleX*(x-originX)
938 * y' = originY + scaleY*(y-originY)
940 *--------------------------------------------------------------
944 ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY)
945 Tk_Canvas canvas; /* Canvas containing window. */
946 Tk_Item *itemPtr; /* Window to be scaled. */
947 double originX, originY; /* Origin about which to scale window. */
948 double scaleX; /* Amount to scale in X direction. */
949 double scaleY; /* Amount to scale in Y direction. */
951 WindowItem *winItemPtr = (WindowItem *) itemPtr;
953 winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);
954 winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);
955 if (winItemPtr->width > 0) {
956 winItemPtr->width = (int) (scaleX*winItemPtr->width);
958 if (winItemPtr->height > 0) {
959 winItemPtr->height = (int) (scaleY*winItemPtr->height);
961 ComputeWindowBbox(canvas, winItemPtr);
965 *--------------------------------------------------------------
967 * TranslateWinItem --
969 * This procedure is called to move a window by a given amount.
975 * The position of the window is offset by (xDelta, yDelta),
976 * and the bounding box is updated in the generic part of the
979 *--------------------------------------------------------------
983 TranslateWinItem(canvas, itemPtr, deltaX, deltaY)
984 Tk_Canvas canvas; /* Canvas containing item. */
985 Tk_Item *itemPtr; /* Item that is being moved. */
986 double deltaX, deltaY; /* Amount by which item is to be
989 WindowItem *winItemPtr = (WindowItem *) itemPtr;
991 winItemPtr->x += deltaX;
992 winItemPtr->y += deltaY;
993 ComputeWindowBbox(canvas, winItemPtr);
997 *--------------------------------------------------------------
999 * WinItemStructureProc --
1001 * This procedure is invoked whenever StructureNotify events
1002 * occur for a window that's managed as part of a canvas window
1003 * item. This procudure's only purpose is to clean up when
1004 * windows are deleted.
1010 * The window is disassociated from the window item when it is
1013 *--------------------------------------------------------------
1017 WinItemStructureProc(clientData, eventPtr)
1018 ClientData clientData; /* Pointer to record describing window item. */
1019 XEvent *eventPtr; /* Describes what just happened. */
1021 WindowItem *winItemPtr = (WindowItem *) clientData;
1023 if (eventPtr->type == DestroyNotify) {
1024 winItemPtr->tkwin = NULL;
1029 *--------------------------------------------------------------
1031 * WinItemRequestProc --
1033 * This procedure is invoked whenever a window that's associated
1034 * with a window canvas item changes its requested dimensions.
1040 * The size and location on the screen of the window may change,
1041 * depending on the options specified for the window item.
1043 *--------------------------------------------------------------
1047 WinItemRequestProc(clientData, tkwin)
1048 ClientData clientData; /* Pointer to record for window item. */
1049 Tk_Window tkwin; /* Window that changed its desired
1052 WindowItem *winItemPtr = (WindowItem *) clientData;
1054 ComputeWindowBbox(winItemPtr->canvas, winItemPtr);
1055 DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr,
1056 (Display *) NULL, (Drawable) None, 0, 0, 0, 0);
1060 *--------------------------------------------------------------
1062 * WinItemLostSlaveProc --
1064 * This procedure is invoked by Tk whenever some other geometry
1065 * claims control over a slave that used to be managed by us.
1071 * Forgets all canvas-related information about the slave.
1073 *--------------------------------------------------------------
1078 WinItemLostSlaveProc(clientData, tkwin)
1079 ClientData clientData; /* WindowItem structure for slave window that
1080 * was stolen away. */
1081 Tk_Window tkwin; /* Tk's handle for the slave window. */
1083 WindowItem *winItemPtr = (WindowItem *) clientData;
1084 Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
1086 Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
1087 WinItemStructureProc, (ClientData) winItemPtr);
1088 if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
1089 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
1091 Tk_UnmapWindow(winItemPtr->tkwin);
1092 winItemPtr->tkwin = NULL;