tkCanvWind.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:32k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkCanvWind.c --
  3.  *
  4.  * This file implements window items for canvas widgets.
  5.  *
  6.  * Copyright (c) 1992-1994 The Regents of the University of California.
  7.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkCanvWind.c,v 1.9.2.2 2006/05/12 18:17:55 das Exp $
  13.  */
  14. #include <stdio.h>
  15. #include "tkInt.h"
  16. #include "tkPort.h"
  17. #include "tkCanvas.h"
  18. /*
  19.  * The structure below defines the record for each window item.
  20.  */
  21. typedef struct WindowItem  {
  22.     Tk_Item header; /* Generic stuff that's the same for all
  23.  * types.  MUST BE FIRST IN STRUCTURE. */
  24.     double x, y; /* Coordinates of positioning point for
  25.  * window. */
  26.     Tk_Window tkwin; /* Window associated with item.  NULL means
  27.  * window has been destroyed. */
  28.     int width; /* Width to use for window (<= 0 means use
  29.  * window's requested width). */
  30.     int height; /* Width to use for window (<= 0 means use
  31.  * window's requested width). */
  32.     Tk_Anchor anchor; /* Where to anchor window relative to
  33.  * (x,y). */
  34.     Tk_Canvas canvas; /* Canvas containing this item. */
  35. } WindowItem;
  36. /*
  37.  * Information used for parsing configuration specs:
  38.  */
  39. static Tk_CustomOption stateOption = {
  40.     (Tk_OptionParseProc *) TkStateParseProc,
  41.     TkStatePrintProc, (ClientData) 2
  42. };
  43. static Tk_CustomOption tagsOption = {
  44.     (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
  45.     Tk_CanvasTagsPrintProc, (ClientData) NULL
  46. };
  47. static Tk_ConfigSpec configSpecs[] = {
  48.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  49. "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  50.     {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
  51. "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT},
  52.     {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
  53. (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
  54. &stateOption},
  55.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  56. (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
  57.     {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
  58. "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT},
  59.     {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
  60. (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK},
  61.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  62. (char *) NULL, 0, 0}
  63. };
  64. /*
  65.  * Prototypes for procedures defined in this file:
  66.  */
  67. static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas,
  68.     WindowItem *winItemPtr));
  69. static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp,
  70.     Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
  71.     Tcl_Obj *CONST objv[], int flags));
  72. static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp,
  73.     Tk_Canvas canvas, struct Tk_Item *itemPtr,
  74.     int objc, Tcl_Obj *CONST objv[]));
  75. static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas,
  76.     Tk_Item *itemPtr, Display *display));
  77. static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas,
  78.     Tk_Item *itemPtr, Display *display, Drawable dst,
  79.     int x, int y, int width, int height));
  80. static void ScaleWinItem _ANSI_ARGS_((Tk_Canvas canvas,
  81.     Tk_Item *itemPtr, double originX, double originY,
  82.     double scaleX, double scaleY));
  83. static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas,
  84.     Tk_Item *itemPtr, double deltaX, double deltaY));
  85. static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp,
  86.     Tk_Canvas canvas, Tk_Item *itemPtr, int objc,
  87.     Tcl_Obj *CONST objv[]));
  88. static void WinItemLostSlaveProc _ANSI_ARGS_((
  89.     ClientData clientData, Tk_Window tkwin));
  90. static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData,
  91.     Tk_Window tkwin));
  92. static void WinItemStructureProc _ANSI_ARGS_((
  93.     ClientData clientData, XEvent *eventPtr));
  94. static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas,
  95.     Tk_Item *itemPtr, double *rectPtr));
  96. static int WinItemToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
  97.     Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
  98. static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  99.     Tk_Item *itemPtr, double *pointPtr));
  100. #ifdef X_GetImage
  101. static int xerrorhandler _ANSI_ARGS_((ClientData clientData,
  102.     XErrorEvent *e));
  103. #endif
  104. static int CanvasPsWindow _ANSI_ARGS_((Tcl_Interp *interp,
  105.     Tk_Window tkwin, Tk_Canvas canvas, double x,
  106.     double y, int width, int height));
  107. /*
  108.  * The structure below defines the window item type by means of procedures
  109.  * that can be invoked by generic item code.
  110.  */
  111. Tk_ItemType tkWindowType = {
  112.     "window", /* name */
  113.     sizeof(WindowItem), /* itemSize */
  114.     CreateWinItem, /* createProc */
  115.     configSpecs, /* configSpecs */
  116.     ConfigureWinItem, /* configureProc */
  117.     WinItemCoords, /* coordProc */
  118.     DeleteWinItem, /* deleteProc */
  119.     DisplayWinItem, /* displayProc */
  120.     1|TK_CONFIG_OBJS, /* flags */
  121.     WinItemToPoint, /* pointProc */
  122.     WinItemToArea, /* areaProc */
  123.     WinItemToPostscript,         /* postscriptProc */
  124.     ScaleWinItem, /* scaleProc */
  125.     TranslateWinItem, /* translateProc */
  126.     (Tk_ItemIndexProc *) NULL, /* indexProc */
  127.     (Tk_ItemCursorProc *) NULL, /* cursorProc */
  128.     (Tk_ItemSelectionProc *) NULL, /* selectionProc */
  129.     (Tk_ItemInsertProc *) NULL, /* insertProc */
  130.     (Tk_ItemDCharsProc *) NULL, /* dTextProc */
  131.     (Tk_ItemType *) NULL, /* nextPtr */
  132. };
  133. /*
  134.  * The structure below defines the official type record for the
  135.  * placer:
  136.  */
  137. static Tk_GeomMgr canvasGeomType = {
  138.     "canvas", /* name */
  139.     WinItemRequestProc, /* requestProc */
  140.     WinItemLostSlaveProc, /* lostSlaveProc */
  141. };
  142. /*
  143.  *--------------------------------------------------------------
  144.  *
  145.  * CreateWinItem --
  146.  *
  147.  * This procedure is invoked to create a new window
  148.  * item in a canvas.
  149.  *
  150.  * Results:
  151.  * A standard Tcl return value.  If an error occurred in
  152.  * creating the item, then an error message is left in
  153.  * the interp's result;  in this case itemPtr is
  154.  * left uninitialized, so it can be safely freed by the
  155.  * caller.
  156.  *
  157.  * Side effects:
  158.  * A new window item is created.
  159.  *
  160.  *--------------------------------------------------------------
  161.  */
  162. static int
  163. CreateWinItem(interp, canvas, itemPtr, objc, objv)
  164.     Tcl_Interp *interp; /* Interpreter for error reporting. */
  165.     Tk_Canvas canvas; /* Canvas to hold new item. */
  166.     Tk_Item *itemPtr; /* Record to hold new item;  header
  167.  * has been initialized by caller. */
  168.     int objc; /* Number of arguments in objv. */
  169.     Tcl_Obj *CONST objv[]; /* Arguments describing window. */
  170. {
  171.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  172.     int i;
  173.     if (objc == 0) {
  174. panic("canvas did not pass any coordsn");
  175.     }
  176.     /*
  177.      * Initialize item's record.
  178.      */
  179.     winItemPtr->tkwin = NULL;
  180.     winItemPtr->width = 0;
  181.     winItemPtr->height = 0;
  182.     winItemPtr->anchor = TK_ANCHOR_CENTER;
  183.     winItemPtr->canvas = canvas;
  184.     /*
  185.      * Process the arguments to fill in the item record.
  186.      * Only 1 (list) or 2 (x y) coords are allowed.
  187.      */
  188.     if (objc == 1) {
  189. i = 1;
  190.     } else {
  191. char *arg = Tcl_GetString(objv[1]);
  192. i = 2;
  193. if ((arg[0] == '-') && (arg[1] >= 'a') && (arg[1] <= 'z')) {
  194.     i = 1;
  195. }
  196.     }
  197.     if (WinItemCoords(interp, canvas, itemPtr, i, objv) != TCL_OK) {
  198. goto error;
  199.     }
  200.     if (ConfigureWinItem(interp, canvas, itemPtr, objc-i, objv+i, 0)
  201.     == TCL_OK) {
  202. return TCL_OK;
  203.     }
  204.     error:
  205.     DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  206.     return TCL_ERROR;
  207. }
  208. /*
  209.  *--------------------------------------------------------------
  210.  *
  211.  * WinItemCoords --
  212.  *
  213.  * This procedure is invoked to process the "coords" widget
  214.  * command on window items.  See the user documentation for
  215.  * details on what it does.
  216.  *
  217.  * Results:
  218.  * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
  219.  *
  220.  * Side effects:
  221.  * The coordinates for the given item may be changed.
  222.  *
  223.  *--------------------------------------------------------------
  224.  */
  225. static int
  226. WinItemCoords(interp, canvas, itemPtr, objc, objv)
  227.     Tcl_Interp *interp; /* Used for error reporting. */
  228.     Tk_Canvas canvas; /* Canvas containing item. */
  229.     Tk_Item *itemPtr; /* Item whose coordinates are to be
  230.  * read or modified. */
  231.     int objc; /* Number of coordinates supplied in
  232.  * objv. */
  233.     Tcl_Obj *CONST objv[]; /* Array of coordinates: x1, y1,
  234.  * x2, y2, ... */
  235. {
  236.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  237.     if (objc == 0) {
  238. Tcl_Obj *obj = Tcl_NewObj();
  239. Tcl_Obj *subobj = Tcl_NewDoubleObj(winItemPtr->x);
  240. Tcl_ListObjAppendElement(interp, obj, subobj);
  241. subobj = Tcl_NewDoubleObj(winItemPtr->y);
  242. Tcl_ListObjAppendElement(interp, obj, subobj);
  243. Tcl_SetObjResult(interp, obj);
  244.     } else if (objc < 3) {
  245. if (objc==1) {
  246.     if (Tcl_ListObjGetElements(interp, objv[0], &objc,
  247.     (Tcl_Obj ***) &objv) != TCL_OK) {
  248. return TCL_ERROR;
  249.     } else if (objc != 2) {
  250. char buf[64 + TCL_INTEGER_SPACE];
  251. sprintf(buf, "wrong # coordinates: expected 2, got %d", objc);
  252. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  253. return TCL_ERROR;
  254.     }
  255. }
  256. if ((Tk_CanvasGetCoordFromObj(interp, canvas, objv[0], &winItemPtr->x)
  257. != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
  258. &winItemPtr->y) != TCL_OK)) {
  259.     return TCL_ERROR;
  260. }
  261. ComputeWindowBbox(canvas, winItemPtr);
  262.     } else {
  263. char buf[64 + TCL_INTEGER_SPACE];
  264. sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", objc);
  265. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  266. return TCL_ERROR;
  267.     }
  268.     return TCL_OK;
  269. }
  270. /*
  271.  *--------------------------------------------------------------
  272.  *
  273.  * ConfigureWinItem --
  274.  *
  275.  * This procedure is invoked to configure various aspects
  276.  * of a window item, such as its anchor position.
  277.  *
  278.  * Results:
  279.  * A standard Tcl result code.  If an error occurs, then
  280.  * an error message is left in the interp's result.
  281.  *
  282.  * Side effects:
  283.  * Configuration information may be set for itemPtr.
  284.  *
  285.  *--------------------------------------------------------------
  286.  */
  287. static int
  288. ConfigureWinItem(interp, canvas, itemPtr, objc, objv, flags)
  289.     Tcl_Interp *interp; /* Used for error reporting. */
  290.     Tk_Canvas canvas; /* Canvas containing itemPtr. */
  291.     Tk_Item *itemPtr; /* Window item to reconfigure. */
  292.     int objc; /* Number of elements in objv.  */
  293.     Tcl_Obj *CONST objv[]; /* Arguments describing things to configure. */
  294.     int flags; /* Flags to pass to Tk_ConfigureWidget. */
  295. {
  296.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  297.     Tk_Window oldWindow;
  298.     Tk_Window canvasTkwin;
  299.     oldWindow = winItemPtr->tkwin;
  300.     canvasTkwin = Tk_CanvasTkwin(canvas);
  301.     if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc,
  302.     (CONST char **) objv, (char *) winItemPtr, flags|TK_CONFIG_OBJS)) {
  303. return TCL_ERROR;
  304.     }
  305.     /*
  306.      * A few of the options require additional processing.
  307.      */
  308.     if (oldWindow != winItemPtr->tkwin) {
  309. if (oldWindow != NULL) {
  310.     Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
  311.     WinItemStructureProc, (ClientData) winItemPtr);
  312.     Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
  313.     (ClientData) NULL);
  314.     Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
  315.     Tk_UnmapWindow(oldWindow);
  316. }
  317. if (winItemPtr->tkwin != NULL) {
  318.     Tk_Window ancestor, parent;
  319.     /*
  320.      * Make sure that the canvas is either the parent of the
  321.      * window associated with the item or a descendant of that
  322.      * parent.  Also, don't allow a top-of-hierarchy window to be
  323.      * managed inside a canvas.
  324.      */
  325.     parent = Tk_Parent(winItemPtr->tkwin);
  326.     for (ancestor = canvasTkwin; ;
  327.     ancestor = Tk_Parent(ancestor)) {
  328. if (ancestor == parent) {
  329.     break;
  330. }
  331. if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_HIERARCHY) {
  332.     badWindow:
  333.     Tcl_AppendResult(interp, "can't use ",
  334.     Tk_PathName(winItemPtr->tkwin),
  335.     " in a window item of this canvas", (char *) NULL);
  336.     winItemPtr->tkwin = NULL;
  337.     return TCL_ERROR;
  338. }
  339.     }
  340.     if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_HIERARCHY) {
  341. goto badWindow;
  342.     }
  343.     if (winItemPtr->tkwin == canvasTkwin) {
  344. goto badWindow;
  345.     }
  346.     Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
  347.     WinItemStructureProc, (ClientData) winItemPtr);
  348.     Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType,
  349.     (ClientData) winItemPtr);
  350. }
  351.     }
  352.     if ((winItemPtr->tkwin != NULL)
  353.     && (itemPtr->state == TK_STATE_HIDDEN)) {
  354. if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
  355.     Tk_UnmapWindow(winItemPtr->tkwin);
  356. } else {
  357.     Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  358. }
  359.     }
  360.     ComputeWindowBbox(canvas, winItemPtr);
  361.     return TCL_OK;
  362. }
  363. /*
  364.  *--------------------------------------------------------------
  365.  *
  366.  * DeleteWinItem --
  367.  *
  368.  * This procedure is called to clean up the data structure
  369.  * associated with a window item.
  370.  *
  371.  * Results:
  372.  * None.
  373.  *
  374.  * Side effects:
  375.  * Resources associated with itemPtr are released.
  376.  *
  377.  *--------------------------------------------------------------
  378.  */
  379. static void
  380. DeleteWinItem(canvas, itemPtr, display)
  381.     Tk_Canvas canvas; /* Overall info about widget. */
  382.     Tk_Item *itemPtr; /* Item that is being deleted. */
  383.     Display *display; /* Display containing window for
  384.  * canvas. */
  385. {
  386.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  387.     Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
  388.     if (winItemPtr->tkwin != NULL) {
  389. Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
  390. WinItemStructureProc, (ClientData) winItemPtr);
  391. Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL,
  392. (ClientData) NULL);
  393. if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
  394.     Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  395. }
  396. Tk_UnmapWindow(winItemPtr->tkwin);
  397.     }
  398. }
  399. /*
  400.  *--------------------------------------------------------------
  401.  *
  402.  * ComputeWindowBbox --
  403.  *
  404.  * This procedure is invoked to compute the bounding box of
  405.  * all the pixels that may be drawn as part of a window item.
  406.  * This procedure is where the child window's placement is
  407.  * computed.
  408.  *
  409.  * Results:
  410.  * None.
  411.  *
  412.  * Side effects:
  413.  * The fields x1, y1, x2, and y2 are updated in the header
  414.  * for itemPtr.
  415.  *
  416.  *--------------------------------------------------------------
  417.  */
  418. static void
  419. ComputeWindowBbox(canvas, winItemPtr)
  420.     Tk_Canvas canvas; /* Canvas that contains item. */
  421.     WindowItem *winItemPtr; /* Item whose bbox is to be
  422.  * recomputed. */
  423. {
  424.     int width, height, x, y;
  425.     Tk_State state = winItemPtr->header.state;
  426.     x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));
  427.     y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));
  428.     if (state == TK_STATE_NULL) {
  429. state = ((TkCanvas *)canvas)->canvas_state;
  430.     }
  431.     if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) {
  432. /*
  433.  * There is no window for this item yet.  Just give it a 1x1
  434.  * bounding box.  Don't give it a 0x0 bounding box; there are
  435.  * strange cases where this bounding box might be used as the
  436.  * dimensions of the window, and 0x0 causes problems under X.
  437.  */
  438. winItemPtr->header.x1 = x;
  439. winItemPtr->header.x2 = winItemPtr->header.x1 + 1;
  440. winItemPtr->header.y1 = y;
  441. winItemPtr->header.y2 = winItemPtr->header.y1 + 1;
  442. return;
  443.     }
  444.     /*
  445.      * Compute dimensions of window.
  446.      */
  447.     width = winItemPtr->width;
  448.     if (width <= 0) {
  449. width = Tk_ReqWidth(winItemPtr->tkwin);
  450. if (width <= 0) {
  451.     width = 1;
  452. }
  453.     }
  454.     height = winItemPtr->height;
  455.     if (height <= 0) {
  456. height = Tk_ReqHeight(winItemPtr->tkwin);
  457. if (height <= 0) {
  458.     height = 1;
  459. }
  460.     }
  461.     /*
  462.      * Compute location of window, using anchor information.
  463.      */
  464.     switch (winItemPtr->anchor) {
  465. case TK_ANCHOR_N:
  466.     x -= width/2;
  467.     break;
  468. case TK_ANCHOR_NE:
  469.     x -= width;
  470.     break;
  471. case TK_ANCHOR_E:
  472.     x -= width;
  473.     y -= height/2;
  474.     break;
  475. case TK_ANCHOR_SE:
  476.     x -= width;
  477.     y -= height;
  478.     break;
  479. case TK_ANCHOR_S:
  480.     x -= width/2;
  481.     y -= height;
  482.     break;
  483. case TK_ANCHOR_SW:
  484.     y -= height;
  485.     break;
  486. case TK_ANCHOR_W:
  487.     y -= height/2;
  488.     break;
  489. case TK_ANCHOR_NW:
  490.     break;
  491. case TK_ANCHOR_CENTER:
  492.     x -= width/2;
  493.     y -= height/2;
  494.     break;
  495.     }
  496.     /*
  497.      * Store the information in the item header.
  498.      */
  499.     winItemPtr->header.x1 = x;
  500.     winItemPtr->header.y1 = y;
  501.     winItemPtr->header.x2 = x + width;
  502.     winItemPtr->header.y2 = y + height;
  503. }
  504. /*
  505.  *--------------------------------------------------------------
  506.  *
  507.  * DisplayWinItem --
  508.  *
  509.  * This procedure is invoked to "draw" a window item in a given
  510.  * drawable.  Since the window draws itself, we needn't do any
  511.  * actual redisplay here.  However, this procedure takes care
  512.  * of actually repositioning the child window so that it occupies
  513.  * the correct screen position.
  514.  *
  515.  * Results:
  516.  * None.
  517.  *
  518.  * Side effects:
  519.  * The child window's position may get changed.  Note: this
  520.  * procedure gets called both when a window needs to be displayed
  521.  * and when it ceases to be visible on the screen (e.g. it was
  522.  * scrolled or moved off-screen or the enclosing canvas is
  523.  * unmapped).
  524.  *
  525.  *--------------------------------------------------------------
  526.  */
  527. static void
  528. DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY,
  529. regionWidth, regionHeight)
  530.     Tk_Canvas canvas; /* Canvas that contains item. */
  531.     Tk_Item *itemPtr; /* Item to be displayed. */
  532.     Display *display; /* Display on which to draw item. */
  533.     Drawable drawable; /* Pixmap or window in which to draw
  534.  * item. */
  535.     int regionX, regionY, regionWidth, regionHeight;
  536. /* Describes region of canvas that
  537.  * must be redisplayed (not used). */
  538. {
  539.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  540.     int width, height;
  541.     short x, y;
  542.     Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
  543.     Tk_State state = itemPtr->state;
  544.     if (winItemPtr->tkwin == NULL) {
  545. return;
  546.     }
  547.     if (state == TK_STATE_NULL) {
  548. state = ((TkCanvas *)canvas)->canvas_state;
  549.     }
  550.     /*
  551.      * A drawable of None is used by the canvas UnmapNotify handler
  552.      * to indicate that we should no longer display ourselves.
  553.      */
  554.     if (state == TK_STATE_HIDDEN || drawable == None) {
  555. if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
  556.     Tk_UnmapWindow(winItemPtr->tkwin);
  557. } else {
  558.     Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  559. }
  560. return;
  561.     }
  562.     Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
  563.     (double) winItemPtr->header.y1, &x, &y);
  564.     width = winItemPtr->header.x2 - winItemPtr->header.x1;
  565.     height = winItemPtr->header.y2 - winItemPtr->header.y1;
  566.     /*
  567.      * If the window is completely out of the visible area of the canvas
  568.      * then unmap it.  This code used not to be present (why unmap the
  569.      * window if it isn't visible anyway?) but this could cause the
  570.      * window to suddenly reappear if the canvas window got resized.
  571.      */
  572.     if (((x + width) <= 0) || ((y + height) <= 0)
  573.     || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {
  574. if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
  575.     Tk_UnmapWindow(winItemPtr->tkwin); 
  576. } else {
  577.     Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  578. }
  579. return;
  580.     }
  581.     /*
  582.      * Reposition and map the window (but in different ways depending
  583.      * on whether the canvas is the window's parent).
  584.      */
  585.     if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
  586. if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
  587. || (width != Tk_Width(winItemPtr->tkwin))
  588. || (height != Tk_Height(winItemPtr->tkwin))) {
  589.     Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
  590. }
  591. Tk_MapWindow(winItemPtr->tkwin);
  592.     } else {
  593. Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
  594. width, height);
  595.     }
  596. }
  597. /*
  598.  *--------------------------------------------------------------
  599.  *
  600.  * WinItemToPoint --
  601.  *
  602.  * Computes the distance from a given point to a given
  603.  * window, in canvas units.
  604.  *
  605.  * Results:
  606.  * The return value is 0 if the point whose x and y coordinates
  607.  * are coordPtr[0] and coordPtr[1] is inside the window.  If the
  608.  * point isn't inside the window then the return value is the
  609.  * distance from the point to the window.
  610.  *
  611.  * Side effects:
  612.  * None.
  613.  *
  614.  *--------------------------------------------------------------
  615.  */
  616. static double
  617. WinItemToPoint(canvas, itemPtr, pointPtr)
  618.     Tk_Canvas canvas; /* Canvas containing item. */
  619.     Tk_Item *itemPtr; /* Item to check against point. */
  620.     double *pointPtr; /* Pointer to x and y coordinates. */
  621. {
  622.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  623.     double x1, x2, y1, y2, xDiff, yDiff;
  624.     x1 = winItemPtr->header.x1;
  625.     y1 = winItemPtr->header.y1;
  626.     x2 = winItemPtr->header.x2;
  627.     y2 = winItemPtr->header.y2;
  628.     /*
  629.      * Point is outside window.
  630.      */
  631.     if (pointPtr[0] < x1) {
  632. xDiff = x1 - pointPtr[0];
  633.     } else if (pointPtr[0] >= x2)  {
  634. xDiff = pointPtr[0] + 1 - x2;
  635.     } else {
  636. xDiff = 0;
  637.     }
  638.     if (pointPtr[1] < y1) {
  639. yDiff = y1 - pointPtr[1];
  640.     } else if (pointPtr[1] >= y2)  {
  641. yDiff = pointPtr[1] + 1 - y2;
  642.     } else {
  643. yDiff = 0;
  644.     }
  645.     return hypot(xDiff, yDiff);
  646. }
  647. /*
  648.  *--------------------------------------------------------------
  649.  *
  650.  * WinItemToArea --
  651.  *
  652.  * This procedure is called to determine whether an item
  653.  * lies entirely inside, entirely outside, or overlapping
  654.  * a given rectangle.
  655.  *
  656.  * Results:
  657.  * -1 is returned if the item is entirely outside the area
  658.  * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  659.  * inside the given area.
  660.  *
  661.  * Side effects:
  662.  * None.
  663.  *
  664.  *--------------------------------------------------------------
  665.  */
  666. static int
  667. WinItemToArea(canvas, itemPtr, rectPtr)
  668.     Tk_Canvas canvas; /* Canvas containing item. */
  669.     Tk_Item *itemPtr; /* Item to check against rectangle. */
  670.     double *rectPtr; /* Pointer to array of four coordinates
  671.  * (x1, y1, x2, y2) describing rectangular
  672.  * area.  */
  673. {
  674.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  675.     if ((rectPtr[2] <= winItemPtr->header.x1)
  676.     || (rectPtr[0] >= winItemPtr->header.x2)
  677.     || (rectPtr[3] <= winItemPtr->header.y1)
  678.     || (rectPtr[1] >= winItemPtr->header.y2)) {
  679. return -1;
  680.     }
  681.     if ((rectPtr[0] <= winItemPtr->header.x1)
  682.     && (rectPtr[1] <= winItemPtr->header.y1)
  683.     && (rectPtr[2] >= winItemPtr->header.x2)
  684.     && (rectPtr[3] >= winItemPtr->header.y2)) {
  685. return 1;
  686.     }
  687.     return 0;
  688. }
  689. /*
  690.  *--------------------------------------------------------------
  691.  *
  692.  * xerrorhandler --
  693.  *
  694.  * This is a dummy function to catch X11 errors during an
  695.  * attempt to print a canvas window.
  696.  *
  697.  * Results:
  698.  * None.
  699.  *
  700.  * Side effects:
  701.  * None.
  702.  *
  703.  *--------------------------------------------------------------
  704.  */
  705. #ifdef X_GetImage
  706. static int
  707. xerrorhandler(clientData, e)
  708.     ClientData clientData;
  709.     XErrorEvent *e;
  710. {
  711. return 0;
  712. }
  713. #endif
  714. /*
  715.  *--------------------------------------------------------------
  716.  *
  717.  * WinItemToPostscript --
  718.  *
  719.  * This procedure is called to generate Postscript for
  720.  * window items.
  721.  *
  722.  * Results:
  723.  * The return value is a standard Tcl result.  If an error
  724.  * occurs in generating Postscript then an error message is
  725.  * left in interp->result, replacing whatever used to be there.
  726.  * If no error occurs, then Postscript for the item is appended
  727.  * to the result.
  728.  *
  729.  * Side effects:
  730.  * None.
  731.  *
  732.  *--------------------------------------------------------------
  733.  */
  734. static int
  735. WinItemToPostscript(interp, canvas, itemPtr, prepass)
  736.     Tcl_Interp *interp; /* Leave Postscript or error message
  737.  * here. */
  738.     Tk_Canvas canvas; /* Information about overall canvas. */
  739.     Tk_Item *itemPtr; /* Item for which Postscript is
  740.  * wanted. */
  741.     int prepass; /* 1 means this is a prepass to
  742.  * collect font information;  0 means
  743.  * final Postscript is being created.*/
  744. {
  745.     WindowItem *winItemPtr = (WindowItem *)itemPtr;
  746.     double x, y;
  747.     int width, height;
  748.     Tk_Window tkwin = winItemPtr->tkwin;
  749.     if (prepass || winItemPtr->tkwin == NULL) {
  750.         return TCL_OK;
  751.     }
  752.     
  753.     width = Tk_Width(tkwin);
  754.     height = Tk_Height(tkwin);
  755.     /*
  756.      * Compute the coordinates of the lower-left corner of the window,
  757.      * taking into account the anchor position for the window.
  758.      */
  759.     x = winItemPtr->x;
  760.     y = Tk_CanvasPsY(canvas, winItemPtr->y);
  761.     
  762.     switch (winItemPtr->anchor) {
  763. case TK_ANCHOR_NW: y -= height; break;
  764. case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
  765. case TK_ANCHOR_NE: x -= width; y -= height; break;
  766. case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
  767. case TK_ANCHOR_SE: x -= width; break;
  768. case TK_ANCHOR_S: x -= width/2.0; break;
  769. case TK_ANCHOR_SW: break;
  770. case TK_ANCHOR_W: y -= height/2.0; break;
  771. case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
  772.     }
  773.     return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height);
  774. }
  775. static int
  776. CanvasPsWindow(interp, tkwin, canvas, x, y, width, height)
  777.     Tcl_Interp *interp; /* Leave Postscript or error message
  778.  * here. */
  779.     Tk_Window tkwin; /* window to be printed */
  780.     Tk_Canvas canvas; /* Information about overall canvas. */
  781.     double x, y; /* origin of window. */
  782.     int width, height; /* width/height of window. */
  783. {
  784.     char buffer[256];
  785.     XImage *ximage;
  786.     int result;
  787.     Tcl_DString buffer1, buffer2;
  788. #ifdef X_GetImage
  789.     Tk_ErrorHandler handle;
  790. #endif
  791.     sprintf(buffer, "n%%%% %s item (%s, %d x %d)n%.15g %.15g translaten",
  792.     Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y);
  793.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  794.     /* first try if the widget has its own "postscript" command. If it
  795.      * exists, this will produce much better postscript than
  796.      * when a pixmap is used.
  797.      */
  798.     Tcl_DStringInit(&buffer1);
  799.     Tcl_DStringInit(&buffer2);
  800.     Tcl_DStringGetResult(interp, &buffer2);
  801.     sprintf (buffer, "%s postscript -prolog 0n", Tk_PathName(tkwin));
  802.     result = Tcl_Eval(interp, buffer);
  803.     Tcl_DStringGetResult(interp, &buffer1);
  804.     Tcl_DStringResult(interp, &buffer2);
  805.     Tcl_DStringFree(&buffer2);
  806.     if (result == TCL_OK) {
  807. Tcl_AppendResult(interp,
  808. "50 dict beginnsavengsaven",
  809. (char *) NULL);
  810. sprintf (buffer,
  811. "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
  812. height, width, height, width);
  813. Tcl_AppendResult(interp, buffer, (char *) NULL);
  814. Tcl_AppendResult(interp, " 0 rlineto closepathn",
  815. "1.000 1.000 1.000 setrgbcolor AdjustColornfillngrestoren",
  816. Tcl_DStringValue(&buffer1), "nrestorenendnnn",
  817. (char *) NULL);
  818. Tcl_DStringFree(&buffer1);
  819. return result;
  820.     }
  821.     Tcl_DStringFree(&buffer1);
  822.     /*
  823.      * If the window is off the screen it will generate an BadMatch/XError
  824.      * We catch any BadMatch errors here
  825.      */
  826. #ifdef X_GetImage
  827.     handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch,
  828.     X_GetImage, -1, xerrorhandler, (ClientData) tkwin);
  829. #endif
  830.     /*
  831.      * Generate an XImage from the window.  We can then read pixel 
  832.      * values out of the XImage.
  833.      */
  834.     ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0,
  835.     (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
  836. #ifdef X_GetImage
  837.     Tk_DeleteErrorHandler(handle);
  838. #endif
  839.     if (ximage == (XImage*) NULL) { 
  840. return TCL_OK;
  841.     }
  842.     result = TkPostscriptImage(interp, tkwin,
  843.     ((TkCanvas *)canvas)->psInfo, ximage, 0, 0, width, height);
  844.     XDestroyImage(ximage);
  845.     return result;
  846. }
  847. /*
  848.  *--------------------------------------------------------------
  849.  *
  850.  * ScaleWinItem --
  851.  *
  852.  * This procedure is invoked to rescale a window item.
  853.  *
  854.  * Results:
  855.  * None.
  856.  *
  857.  * Side effects:
  858.  * The window referred to by itemPtr is rescaled
  859.  * so that the following transformation is applied to all
  860.  * point coordinates:
  861.  * x' = originX + scaleX*(x-originX)
  862.  * y' = originY + scaleY*(y-originY)
  863.  *
  864.  *--------------------------------------------------------------
  865.  */
  866. static void
  867. ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY)
  868.     Tk_Canvas canvas; /* Canvas containing window. */
  869.     Tk_Item *itemPtr; /* Window to be scaled. */
  870.     double originX, originY; /* Origin about which to scale window. */
  871.     double scaleX; /* Amount to scale in X direction. */
  872.     double scaleY; /* Amount to scale in Y direction. */
  873. {
  874.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  875.     winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);
  876.     winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);
  877.     if (winItemPtr->width > 0) {
  878. winItemPtr->width = (int) (scaleX*winItemPtr->width);
  879.     }
  880.     if (winItemPtr->height > 0) {
  881. winItemPtr->height = (int) (scaleY*winItemPtr->height);
  882.     }
  883.     ComputeWindowBbox(canvas, winItemPtr);
  884. }
  885. /*
  886.  *--------------------------------------------------------------
  887.  *
  888.  * TranslateWinItem --
  889.  *
  890.  * This procedure is called to move a window by a given amount.
  891.  *
  892.  * Results:
  893.  * None.
  894.  *
  895.  * Side effects:
  896.  * The position of the window is offset by (xDelta, yDelta),
  897.  * and the bounding box is updated in the generic part of the
  898.  * item structure.
  899.  *
  900.  *--------------------------------------------------------------
  901.  */
  902. static void
  903. TranslateWinItem(canvas, itemPtr, deltaX, deltaY)
  904.     Tk_Canvas canvas; /* Canvas containing item. */
  905.     Tk_Item *itemPtr; /* Item that is being moved. */
  906.     double deltaX, deltaY; /* Amount by which item is to be
  907.  * moved. */
  908. {
  909.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  910.     winItemPtr->x += deltaX;
  911.     winItemPtr->y += deltaY;
  912.     ComputeWindowBbox(canvas, winItemPtr);
  913. }
  914. /*
  915.  *--------------------------------------------------------------
  916.  *
  917.  * WinItemStructureProc --
  918.  *
  919.  * This procedure is invoked whenever StructureNotify events
  920.  * occur for a window that's managed as part of a canvas window
  921.  * item.  This procudure's only purpose is to clean up when
  922.  * windows are deleted.
  923.  *
  924.  * Results:
  925.  * None.
  926.  *
  927.  * Side effects:
  928.  * The window is disassociated from the window item when it is
  929.  * deleted.
  930.  *
  931.  *--------------------------------------------------------------
  932.  */
  933. static void
  934. WinItemStructureProc(clientData, eventPtr)
  935.     ClientData clientData; /* Pointer to record describing window item. */
  936.     XEvent *eventPtr; /* Describes what just happened. */
  937. {
  938.     WindowItem *winItemPtr = (WindowItem *) clientData;
  939.     if (eventPtr->type == DestroyNotify) {
  940. winItemPtr->tkwin = NULL;
  941.     }
  942. }
  943. /*
  944.  *--------------------------------------------------------------
  945.  *
  946.  * WinItemRequestProc --
  947.  *
  948.  * This procedure is invoked whenever a window that's associated
  949.  * with a window canvas item changes its requested dimensions.
  950.  *
  951.  * Results:
  952.  * None.
  953.  *
  954.  * Side effects:
  955.  * The size and location on the screen of the window may change,
  956.  * depending on the options specified for the window item.
  957.  *
  958.  *--------------------------------------------------------------
  959.  */
  960. static void
  961. WinItemRequestProc(clientData, tkwin)
  962.     ClientData clientData; /* Pointer to record for window item. */
  963.     Tk_Window tkwin; /* Window that changed its desired
  964.  * size. */
  965. {
  966.     WindowItem *winItemPtr = (WindowItem *) clientData;
  967.     ComputeWindowBbox(winItemPtr->canvas, winItemPtr);
  968.     /*
  969.      * A drawable argument of None to DisplayWinItem is used by the canvas
  970.      * UnmapNotify handler to indicate that we should no longer display
  971.      * ourselves, so need to pass a (bogus) non-zero drawable value here.
  972.      */
  973.     DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr, NULL,
  974.     (Drawable) -1, 0, 0, 0, 0);
  975. }
  976. /*
  977.  *--------------------------------------------------------------
  978.  *
  979.  * WinItemLostSlaveProc --
  980.  *
  981.  * This procedure is invoked by Tk whenever some other geometry
  982.  * claims control over a slave that used to be managed by us.
  983.  *
  984.  * Results:
  985.  * None.
  986.  *
  987.  * Side effects:
  988.  * Forgets all canvas-related information about the slave.
  989.  *
  990.  *--------------------------------------------------------------
  991.  */
  992. /* ARGSUSED */
  993. static void
  994. WinItemLostSlaveProc(clientData, tkwin)
  995.     ClientData clientData; /* WindowItem structure for slave window that
  996.  * was stolen away. */
  997.     Tk_Window tkwin; /* Tk's handle for the slave window. */
  998. {
  999.     WindowItem *winItemPtr = (WindowItem *) clientData;
  1000.     Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
  1001.     Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
  1002.     WinItemStructureProc, (ClientData) winItemPtr);
  1003.     if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
  1004. Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  1005.     }
  1006.     Tk_UnmapWindow(winItemPtr->tkwin);
  1007.     winItemPtr->tkwin = NULL;
  1008. }