home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / generic / tkCanvWind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  24.1 KB  |  846 lines  |  [TEXT/CWIE]

  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-1995 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.  * SCCS: @(#) tkCanvWind.c 1.28 97/06/16 15:31:39
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include "tkInt.h"
  17. #include "tkPort.h"
  18. #include "tkCanvas.h"
  19.  
  20. /*
  21.  * The structure below defines the record for each window item.
  22.  */
  23.  
  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
  28.                  * window. */
  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
  36.                  * (x,y). */
  37.     Tk_Canvas canvas;        /* Canvas containing this item. */
  38. } WindowItem;
  39.  
  40. /*
  41.  * Information used for parsing configuration specs:
  42.  */
  43.  
  44. static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
  45.     Tk_CanvasTagsPrintProc, (ClientData) NULL
  46. };
  47.  
  48. static Tk_ConfigSpec configSpecs[] = {
  49.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  50.     "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  51.     {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
  52.     "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT},
  53.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  54.     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
  55.     {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
  56.     "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT},
  57.     {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
  58.     (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK},
  59.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  60.     (char *) NULL, 0, 0}
  61. };
  62.  
  63. /*
  64.  * Prototypes for procedures defined in this file:
  65.  */
  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 argc,
  71.                 char **argv, int flags));
  72. static int        CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp,
  73.                 Tk_Canvas canvas, struct Tk_Item *itemPtr,
  74.                 int argc, char **argv));
  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 argc,
  87.                 char **argv));
  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 double        WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  97.                 Tk_Item *itemPtr, double *pointPtr));
  98.  
  99. /*
  100.  * The structure below defines the window item type by means of procedures
  101.  * that can be invoked by generic item code.
  102.  */
  103.  
  104. Tk_ItemType tkWindowType = {
  105.     "window",                /* name */
  106.     sizeof(WindowItem),            /* itemSize */
  107.     CreateWinItem,            /* createProc */
  108.     configSpecs,            /* configSpecs */
  109.     ConfigureWinItem,            /* configureProc */
  110.     WinItemCoords,            /* coordProc */
  111.     DeleteWinItem,            /* deleteProc */
  112.     DisplayWinItem,            /* displayProc */
  113.     1,                    /* alwaysRedraw */
  114.     WinItemToPoint,            /* pointProc */
  115.     WinItemToArea,            /* areaProc */
  116.     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
  117.     ScaleWinItem,            /* scaleProc */
  118.     TranslateWinItem,            /* translateProc */
  119.     (Tk_ItemIndexProc *) NULL,        /* indexProc */
  120.     (Tk_ItemCursorProc *) NULL,        /* cursorProc */
  121.     (Tk_ItemSelectionProc *) NULL,    /* selectionProc */
  122.     (Tk_ItemInsertProc *) NULL,        /* insertProc */
  123.     (Tk_ItemDCharsProc *) NULL,        /* dTextProc */
  124.     (Tk_ItemType *) NULL        /* nextPtr */
  125. };
  126.  
  127.  
  128. /*
  129.  * The structure below defines the official type record for the
  130.  * placer:
  131.  */
  132.  
  133. static Tk_GeomMgr canvasGeomType = {
  134.     "canvas",                /* name */
  135.     WinItemRequestProc,            /* requestProc */
  136.     WinItemLostSlaveProc,        /* lostSlaveProc */
  137. };
  138.  
  139. /*
  140.  *--------------------------------------------------------------
  141.  *
  142.  * CreateWinItem --
  143.  *
  144.  *    This procedure is invoked to create a new window
  145.  *    item in a canvas.
  146.  *
  147.  * Results:
  148.  *    A standard Tcl return value.  If an error occurred in
  149.  *    creating the item, then an error message is left in
  150.  *    interp->result;  in this case itemPtr is
  151.  *    left uninitialized, so it can be safely freed by the
  152.  *    caller.
  153.  *
  154.  * Side effects:
  155.  *    A new window item is created.
  156.  *
  157.  *--------------------------------------------------------------
  158.  */
  159.  
  160. static int
  161. CreateWinItem(interp, canvas, itemPtr, argc, argv)
  162.     Tcl_Interp *interp;            /* Interpreter for error reporting. */
  163.     Tk_Canvas canvas;            /* Canvas to hold new item. */
  164.     Tk_Item *itemPtr;            /* Record to hold new item;  header
  165.                      * has been initialized by caller. */
  166.     int argc;                /* Number of arguments in argv. */
  167.     char **argv;            /* Arguments describing rectangle. */
  168. {
  169.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  170.  
  171.     if (argc < 2) {
  172.     Tcl_AppendResult(interp, "wrong # args: should be \"",
  173.         Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
  174.         itemPtr->typePtr->name, " x y ?options?\"",
  175.         (char *) NULL);
  176.     return TCL_ERROR;
  177.     }
  178.  
  179.     /*
  180.      * Initialize item's record.
  181.      */
  182.  
  183.     winItemPtr->tkwin = NULL;
  184.     winItemPtr->width = 0;
  185.     winItemPtr->height = 0;
  186.     winItemPtr->anchor = TK_ANCHOR_CENTER;
  187.     winItemPtr->canvas = canvas;
  188.  
  189.     /*
  190.      * Process the arguments to fill in the item record.
  191.      */
  192.  
  193.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) != TCL_OK)
  194.         || (Tk_CanvasGetCoord(interp, canvas, argv[1],
  195.         &winItemPtr->y) != TCL_OK)) {
  196.     return TCL_ERROR;
  197.     }
  198.  
  199.     if (ConfigureWinItem(interp, canvas, itemPtr, argc-2, argv+2, 0)
  200.         != TCL_OK) {
  201.     DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  202.     return TCL_ERROR;
  203.     }
  204.     return TCL_OK;
  205. }
  206.  
  207. /*
  208.  *--------------------------------------------------------------
  209.  *
  210.  * WinItemCoords --
  211.  *
  212.  *    This procedure is invoked to process the "coords" widget
  213.  *    command on window items.  See the user documentation for
  214.  *    details on what it does.
  215.  *
  216.  * Results:
  217.  *    Returns TCL_OK or TCL_ERROR, and sets interp->result.
  218.  *
  219.  * Side effects:
  220.  *    The coordinates for the given item may be changed.
  221.  *
  222.  *--------------------------------------------------------------
  223.  */
  224.  
  225. static int
  226. WinItemCoords(interp, canvas, itemPtr, argc, argv)
  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 argc;                /* Number of coordinates supplied in
  232.                      * argv. */
  233.     char **argv;            /* Array of coordinates: x1, y1,
  234.                      * x2, y2, ... */
  235. {
  236.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  237.     char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
  238.  
  239.     if (argc == 0) {
  240.     Tcl_PrintDouble(interp, winItemPtr->x, x);
  241.     Tcl_PrintDouble(interp, winItemPtr->y, y);
  242.     Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
  243.     } else if (argc == 2) {
  244.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x)
  245.         != TCL_OK) || (Tk_CanvasGetCoord(interp, canvas, argv[1],
  246.         &winItemPtr->y) != TCL_OK)) {
  247.         return TCL_ERROR;
  248.     }
  249.     ComputeWindowBbox(canvas, winItemPtr);
  250.     } else {
  251.     sprintf(interp->result,
  252.         "wrong # coordinates: expected 0 or 2, got %d", argc);
  253.     return TCL_ERROR;
  254.     }
  255.     return TCL_OK;
  256. }
  257.  
  258. /*
  259.  *--------------------------------------------------------------
  260.  *
  261.  * ConfigureWinItem --
  262.  *
  263.  *    This procedure is invoked to configure various aspects
  264.  *    of a window item, such as its anchor position.
  265.  *
  266.  * Results:
  267.  *    A standard Tcl result code.  If an error occurs, then
  268.  *    an error message is left in interp->result.
  269.  *
  270.  * Side effects:
  271.  *    Configuration information may be set for itemPtr.
  272.  *
  273.  *--------------------------------------------------------------
  274.  */
  275.  
  276. static int
  277. ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags)
  278.     Tcl_Interp *interp;        /* Used for error reporting. */
  279.     Tk_Canvas canvas;        /* Canvas containing itemPtr. */
  280.     Tk_Item *itemPtr;        /* Window item to reconfigure. */
  281.     int argc;            /* Number of elements in argv.  */
  282.     char **argv;        /* Arguments describing things to configure. */
  283.     int flags;            /* Flags to pass to Tk_ConfigureWidget. */
  284. {
  285.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  286.     Tk_Window oldWindow;
  287.     Tk_Window canvasTkwin;
  288.  
  289.     oldWindow = winItemPtr->tkwin;
  290.     canvasTkwin = Tk_CanvasTkwin(canvas);
  291.     if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, argv,
  292.         (char *) winItemPtr, flags) != TCL_OK) {
  293.     return TCL_ERROR;
  294.     }
  295.  
  296.     /*
  297.      * A few of the options require additional processing.
  298.      */
  299.  
  300.     if (oldWindow != winItemPtr->tkwin) {
  301.     if (oldWindow != NULL) {
  302.         Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
  303.             WinItemStructureProc, (ClientData) winItemPtr);
  304.         Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
  305.             (ClientData) NULL);
  306.         Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
  307.         Tk_UnmapWindow(oldWindow);
  308.     }
  309.     if (winItemPtr->tkwin != NULL) {
  310.         Tk_Window ancestor, parent;
  311.  
  312.         /*
  313.          * Make sure that the canvas is either the parent of the
  314.          * window associated with the item or a descendant of that
  315.          * parent.  Also, don't allow a top-level window to be
  316.          * managed inside a canvas.
  317.          */
  318.  
  319.         parent = Tk_Parent(winItemPtr->tkwin);
  320.         for (ancestor = canvasTkwin; ;
  321.             ancestor = Tk_Parent(ancestor)) {
  322.         if (ancestor == parent) {
  323.             break;
  324.         }
  325.         if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) {
  326.             badWindow:
  327.             Tcl_AppendResult(interp, "can't use ",
  328.                 Tk_PathName(winItemPtr->tkwin),
  329.                 " in a window item of this canvas", (char *) NULL);
  330.             winItemPtr->tkwin = NULL;
  331.             return TCL_ERROR;
  332.         }
  333.         }
  334.         if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_LEVEL) {
  335.         goto badWindow;
  336.         }
  337.         if (winItemPtr->tkwin == canvasTkwin) {
  338.         goto badWindow;
  339.         }
  340.         Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
  341.             WinItemStructureProc, (ClientData) winItemPtr);
  342.         Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType,
  343.             (ClientData) winItemPtr);
  344.     }
  345.     }
  346.  
  347.     ComputeWindowBbox(canvas, winItemPtr);
  348.  
  349.     return TCL_OK;
  350. }
  351.  
  352. /*
  353.  *--------------------------------------------------------------
  354.  *
  355.  * DeleteWinItem --
  356.  *
  357.  *    This procedure is called to clean up the data structure
  358.  *    associated with a window item.
  359.  *
  360.  * Results:
  361.  *    None.
  362.  *
  363.  * Side effects:
  364.  *    Resources associated with itemPtr are released.
  365.  *
  366.  *--------------------------------------------------------------
  367.  */
  368.  
  369. static void
  370. DeleteWinItem(canvas, itemPtr, display)
  371.     Tk_Canvas canvas;            /* Overall info about widget. */
  372.     Tk_Item *itemPtr;            /* Item that is being deleted. */
  373.     Display *display;            /* Display containing window for
  374.                      * canvas. */
  375. {
  376.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  377.     Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
  378.  
  379.     if (winItemPtr->tkwin != NULL) {
  380.     Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
  381.         WinItemStructureProc, (ClientData) winItemPtr);
  382.     Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL,
  383.         (ClientData) NULL);
  384.     if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
  385.         Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  386.     }
  387.     Tk_UnmapWindow(winItemPtr->tkwin);
  388.     }
  389. }
  390.  
  391. /*
  392.  *--------------------------------------------------------------
  393.  *
  394.  * ComputeWindowBbox --
  395.  *
  396.  *    This procedure is invoked to compute the bounding box of
  397.  *    all the pixels that may be drawn as part of a window item.
  398.  *    This procedure is where the child window's placement is
  399.  *    computed.
  400.  *
  401.  * Results:
  402.  *    None.
  403.  *
  404.  * Side effects:
  405.  *    The fields x1, y1, x2, and y2 are updated in the header
  406.  *    for itemPtr.
  407.  *
  408.  *--------------------------------------------------------------
  409.  */
  410.  
  411. static void
  412. ComputeWindowBbox(canvas, winItemPtr)
  413.     Tk_Canvas canvas;            /* Canvas that contains item. */
  414.     WindowItem *winItemPtr;        /* Item whose bbox is to be
  415.                      * recomputed. */
  416. {
  417.     int width, height, x, y;
  418.  
  419.     x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));
  420.     y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));
  421.  
  422.     if (winItemPtr->tkwin == NULL) {
  423.     /*
  424.      * There is no window for this item yet.  Just give it a 1x1
  425.      * bounding box.  Don't give it a 0x0 bounding box; there are
  426.      * strange cases where this bounding box might be used as the
  427.      * dimensions of the window, and 0x0 causes problems under X.
  428.      */
  429.  
  430.     winItemPtr->header.x1 = x;
  431.     winItemPtr->header.x2 = winItemPtr->header.x1 + 1;
  432.     winItemPtr->header.y1 = y;
  433.     winItemPtr->header.y2 = winItemPtr->header.y1 + 1;
  434.     return;
  435.     }
  436.  
  437.     /*
  438.      * Compute dimensions of window.
  439.      */
  440.  
  441.     width = winItemPtr->width;
  442.     if (width <= 0) {
  443.     width = Tk_ReqWidth(winItemPtr->tkwin);
  444.     if (width <= 0) {
  445.         width = 1;
  446.     }
  447.     }
  448.     height = winItemPtr->height;
  449.     if (height <= 0) {
  450.     height = Tk_ReqHeight(winItemPtr->tkwin);
  451.     if (height <= 0) {
  452.         height = 1;
  453.     }
  454.     }
  455.  
  456.     /*
  457.      * Compute location of window, using anchor information.
  458.      */
  459.  
  460.     switch (winItemPtr->anchor) {
  461.     case TK_ANCHOR_N:
  462.         x -= width/2;
  463.         break;
  464.     case TK_ANCHOR_NE:
  465.         x -= width;
  466.         break;
  467.     case TK_ANCHOR_E:
  468.         x -= width;
  469.         y -= height/2;
  470.         break;
  471.     case TK_ANCHOR_SE:
  472.         x -= width;
  473.         y -= height;
  474.         break;
  475.     case TK_ANCHOR_S:
  476.         x -= width/2;
  477.         y -= height;
  478.         break;
  479.     case TK_ANCHOR_SW:
  480.         y -= height;
  481.         break;
  482.     case TK_ANCHOR_W:
  483.         y -= height/2;
  484.         break;
  485.     case TK_ANCHOR_NW:
  486.         break;
  487.     case TK_ANCHOR_CENTER:
  488.         x -= width/2;
  489.         y -= height/2;
  490.         break;
  491.     }
  492.  
  493.     /*
  494.      * Store the information in the item header.
  495.      */
  496.  
  497.     winItemPtr->header.x1 = x;
  498.     winItemPtr->header.y1 = y;
  499.     winItemPtr->header.x2 = x + width;
  500.     winItemPtr->header.y2 = y + height;
  501. }
  502.  
  503. /*
  504.  *--------------------------------------------------------------
  505.  *
  506.  * DisplayWinItem --
  507.  *
  508.  *    This procedure is invoked to "draw" a window item in a given
  509.  *    drawable.  Since the window draws itself, we needn't do any
  510.  *    actual redisplay here.  However, this procedure takes care
  511.  *    of actually repositioning the child window so that it occupies
  512.  *    the correct screen position.
  513.  *
  514.  * Results:
  515.  *    None.
  516.  *
  517.  * Side effects:
  518.  *    The child window's position may get changed.  Note: this
  519.  *    procedure gets called both when a window needs to be displayed
  520.  *    and when it ceases to be visible on the screen (e.g. it was
  521.  *    scrolled or moved off-screen or the enclosing canvas is
  522.  *    unmapped).
  523.  *
  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.  
  544.     if (winItemPtr->tkwin == NULL) {
  545.     return;
  546.     }
  547.  
  548.     Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
  549.         (double) winItemPtr->header.y1, &x, &y);
  550.     width = winItemPtr->header.x2 - winItemPtr->header.x1;
  551.     height = winItemPtr->header.y2 - winItemPtr->header.y1;
  552.  
  553.     /*
  554.      * Reposition and map the window (but in different ways depending
  555.      * on whether the canvas is the window's parent).
  556.      */
  557.  
  558.     if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
  559.     if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
  560.         || (width != Tk_Width(winItemPtr->tkwin))
  561.         || (height != Tk_Height(winItemPtr->tkwin))) {
  562.         Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
  563.     }
  564.     Tk_MapWindow(winItemPtr->tkwin);
  565.     } else {
  566.     Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
  567.         width, height);
  568.     }
  569. }
  570.  
  571. /*
  572.  *--------------------------------------------------------------
  573.  *
  574.  * WinItemToPoint --
  575.  *
  576.  *    Computes the distance from a given point to a given
  577.  *    rectangle, in canvas units.
  578.  *
  579.  * Results:
  580.  *    The return value is 0 if the point whose x and y coordinates
  581.  *    are coordPtr[0] and coordPtr[1] is inside the window.  If the
  582.  *    point isn't inside the window then the return value is the
  583.  *    distance from the point to the window.
  584.  *
  585.  * Side effects:
  586.  *    None.
  587.  *
  588.  *--------------------------------------------------------------
  589.  */
  590.  
  591. static double
  592. WinItemToPoint(canvas, itemPtr, pointPtr)
  593.     Tk_Canvas canvas;        /* Canvas containing item. */
  594.     Tk_Item *itemPtr;        /* Item to check against point. */
  595.     double *pointPtr;        /* Pointer to x and y coordinates. */
  596. {
  597.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  598.     double x1, x2, y1, y2, xDiff, yDiff;
  599.  
  600.     x1 = winItemPtr->header.x1;
  601.     y1 = winItemPtr->header.y1;
  602.     x2 = winItemPtr->header.x2;
  603.     y2 = winItemPtr->header.y2;
  604.  
  605.     /*
  606.      * Point is outside rectangle.
  607.      */
  608.  
  609.     if (pointPtr[0] < x1) {
  610.     xDiff = x1 - pointPtr[0];
  611.     } else if (pointPtr[0] >= x2)  {
  612.     xDiff = pointPtr[0] + 1 - x2;
  613.     } else {
  614.     xDiff = 0;
  615.     }
  616.  
  617.     if (pointPtr[1] < y1) {
  618.     yDiff = y1 - pointPtr[1];
  619.     } else if (pointPtr[1] >= y2)  {
  620.     yDiff = pointPtr[1] + 1 - y2;
  621.     } else {
  622.     yDiff = 0;
  623.     }
  624.  
  625.     return hypot(xDiff, yDiff);
  626. }
  627.  
  628. /*
  629.  *--------------------------------------------------------------
  630.  *
  631.  * WinItemToArea --
  632.  *
  633.  *    This procedure is called to determine whether an item
  634.  *    lies entirely inside, entirely outside, or overlapping
  635.  *    a given rectangle.
  636.  *
  637.  * Results:
  638.  *    -1 is returned if the item is entirely outside the area
  639.  *    given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  640.  *    inside the given area.
  641.  *
  642.  * Side effects:
  643.  *    None.
  644.  *
  645.  *--------------------------------------------------------------
  646.  */
  647.  
  648. static int
  649. WinItemToArea(canvas, itemPtr, rectPtr)
  650.     Tk_Canvas canvas;        /* Canvas containing item. */
  651.     Tk_Item *itemPtr;        /* Item to check against rectangle. */
  652.     double *rectPtr;        /* Pointer to array of four coordinates
  653.                  * (x1, y1, x2, y2) describing rectangular
  654.                  * area.  */
  655. {
  656.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  657.  
  658.     if ((rectPtr[2] <= winItemPtr->header.x1)
  659.         || (rectPtr[0] >= winItemPtr->header.x2)
  660.         || (rectPtr[3] <= winItemPtr->header.y1)
  661.         || (rectPtr[1] >= winItemPtr->header.y2)) {
  662.     return -1;
  663.     }
  664.     if ((rectPtr[0] <= winItemPtr->header.x1)
  665.         && (rectPtr[1] <= winItemPtr->header.y1)
  666.         && (rectPtr[2] >= winItemPtr->header.x2)
  667.         && (rectPtr[3] >= winItemPtr->header.y2)) {
  668.     return 1;
  669.     }
  670.     return 0;
  671. }
  672.  
  673. /*
  674.  *--------------------------------------------------------------
  675.  *
  676.  * ScaleWinItem --
  677.  *
  678.  *    This procedure is invoked to rescale a rectangle or oval
  679.  *    item.
  680.  *
  681.  * Results:
  682.  *    None.
  683.  *
  684.  * Side effects:
  685.  *    The rectangle or oval referred to by itemPtr is rescaled
  686.  *    so that the following transformation is applied to all
  687.  *    point coordinates:
  688.  *        x' = originX + scaleX*(x-originX)
  689.  *        y' = originY + scaleY*(y-originY)
  690.  *
  691.  *--------------------------------------------------------------
  692.  */
  693.  
  694. static void
  695. ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY)
  696.     Tk_Canvas canvas;            /* Canvas containing rectangle. */
  697.     Tk_Item *itemPtr;            /* Rectangle to be scaled. */
  698.     double originX, originY;        /* Origin about which to scale rect. */
  699.     double scaleX;            /* Amount to scale in X direction. */
  700.     double scaleY;            /* Amount to scale in Y direction. */
  701. {
  702.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  703.  
  704.     winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);
  705.     winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);
  706.     if (winItemPtr->width > 0) {
  707.     winItemPtr->width = (int) (scaleX*winItemPtr->width);
  708.     }
  709.     if (winItemPtr->height > 0) {
  710.     winItemPtr->height = (int) (scaleY*winItemPtr->height);
  711.     }
  712.     ComputeWindowBbox(canvas, winItemPtr);
  713. }
  714.  
  715. /*
  716.  *--------------------------------------------------------------
  717.  *
  718.  * TranslateWinItem --
  719.  *
  720.  *    This procedure is called to move a rectangle or oval by a
  721.  *    given amount.
  722.  *
  723.  * Results:
  724.  *    None.
  725.  *
  726.  * Side effects:
  727.  *    The position of the rectangle or oval is offset by
  728.  *    (xDelta, yDelta), and the bounding box is updated in the
  729.  *    generic part of the item structure.
  730.  *
  731.  *--------------------------------------------------------------
  732.  */
  733.  
  734. static void
  735. TranslateWinItem(canvas, itemPtr, deltaX, deltaY)
  736.     Tk_Canvas canvas;            /* Canvas containing item. */
  737.     Tk_Item *itemPtr;            /* Item that is being moved. */
  738.     double deltaX, deltaY;        /* Amount by which item is to be
  739.                      * moved. */
  740. {
  741.     WindowItem *winItemPtr = (WindowItem *) itemPtr;
  742.  
  743.     winItemPtr->x += deltaX;
  744.     winItemPtr->y += deltaY;
  745.     ComputeWindowBbox(canvas, winItemPtr);
  746. }
  747.  
  748. /*
  749.  *--------------------------------------------------------------
  750.  *
  751.  * WinItemStructureProc --
  752.  *
  753.  *    This procedure is invoked whenever StructureNotify events
  754.  *    occur for a window that's managed as part of a canvas window
  755.  *    item.  This procudure's only purpose is to clean up when
  756.  *    windows are deleted.
  757.  *
  758.  * Results:
  759.  *    None.
  760.  *
  761.  * Side effects:
  762.  *    The window is disassociated from the window item when it is
  763.  *    deleted.
  764.  *
  765.  *--------------------------------------------------------------
  766.  */
  767.  
  768. static void
  769. WinItemStructureProc(clientData, eventPtr)
  770.     ClientData clientData;    /* Pointer to record describing window item. */
  771.     XEvent *eventPtr;        /* Describes what just happened. */
  772. {
  773.     WindowItem *winItemPtr = (WindowItem *) clientData;
  774.  
  775.     if (eventPtr->type == DestroyNotify) {
  776.     winItemPtr->tkwin = NULL;
  777.     }
  778. }
  779.  
  780. /*
  781.  *--------------------------------------------------------------
  782.  *
  783.  * WinItemRequestProc --
  784.  *
  785.  *    This procedure is invoked whenever a window that's associated
  786.  *    with a window canvas item changes its requested dimensions.
  787.  *
  788.  * Results:
  789.  *    None.
  790.  *
  791.  * Side effects:
  792.  *    The size and location on the screen of the window may change,
  793.  *    depending on the options specified for the window item.
  794.  *
  795.  *--------------------------------------------------------------
  796.  */
  797.  
  798. static void
  799. WinItemRequestProc(clientData, tkwin)
  800.     ClientData clientData;        /* Pointer to record for window item. */
  801.     Tk_Window tkwin;            /* Window that changed its desired
  802.                      * size. */
  803. {
  804.     WindowItem *winItemPtr = (WindowItem *) clientData;
  805.  
  806.     ComputeWindowBbox(winItemPtr->canvas, winItemPtr);
  807.     DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr,
  808.         (Display *) NULL, (Drawable) None, 0, 0, 0, 0);
  809. }
  810.  
  811. /*
  812.  *--------------------------------------------------------------
  813.  *
  814.  * WinItemLostSlaveProc --
  815.  *
  816.  *    This procedure is invoked by Tk whenever some other geometry
  817.  *    claims control over a slave that used to be managed by us.
  818.  *
  819.  * Results:
  820.  *    None.
  821.  *
  822.  * Side effects:
  823.  *    Forgets all canvas-related information about the slave.
  824.  *
  825.  *--------------------------------------------------------------
  826.  */
  827.  
  828.     /* ARGSUSED */
  829. static void
  830. WinItemLostSlaveProc(clientData, tkwin)
  831.     ClientData clientData;    /* WindowItem structure for slave window that
  832.                  * was stolen away. */
  833.     Tk_Window tkwin;        /* Tk's handle for the slave window. */
  834. {
  835.     WindowItem *winItemPtr = (WindowItem *) clientData;
  836.     Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
  837.  
  838.     Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
  839.         WinItemStructureProc, (ClientData) winItemPtr);
  840.     if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
  841.     Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
  842.     }
  843.     Tk_UnmapWindow(winItemPtr->tkwin);
  844.     winItemPtr->tkwin = NULL;
  845. }
  846.