home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xaw / Porthole.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-14  |  11.1 KB  |  363 lines

  1. /*
  2.  * $XConsortium: Porthole.c,v 1.14 91/03/14 16:48:01 converse Exp $
  3.  *
  4.  * Copyright 1990 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Jim Fulton, MIT X Consortium
  24.  * 
  25.  * This widget is a trivial clipping widget.  It is typically used with a
  26.  * panner or scrollbar to navigate.
  27.  */
  28.  
  29. #include <X11/IntrinsicP.h>        /* get basic toolkit stuff */
  30. #include <X11/StringDefs.h>        /* get XtN and XtC defines */
  31. #include <X11/Xaw/XawInit.h>        /* get Xaw initialize stuff */
  32. #include <X11/Xaw/PortholeP.h>        /* get porthole structs */
  33. #include <X11/Xmu/Misc.h>        /* for MAX */
  34.  
  35.  
  36. /*
  37.  * resources for the porthole
  38.  */
  39. static XtResource resources[] = {
  40. #define poff(field) XtOffsetOf(PortholeRec, porthole.field)
  41.     { XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer),
  42.     poff(report_callbacks), XtRCallback, (XtPointer) NULL },
  43. #undef poff
  44. };
  45.  
  46.  
  47. /*
  48.  * widget class methods used below
  49.  */
  50. static void Realize();            /* set gravity and upcall */
  51. static void Resize();            /* report new size */
  52. static XtGeometryResult GeometryManager();  /* deal with child requests */
  53. static void ChangeManaged();        /* somebody added a new widget */
  54. static XtGeometryResult QueryGeometry();  /* say how big would like to be */
  55.  
  56. PortholeClassRec portholeClassRec = {
  57.   { /* core fields */
  58.     /* superclass        */    (WidgetClass) &compositeClassRec,
  59.     /* class_name        */    "Porthole",
  60.     /* widget_size        */    sizeof(PortholeRec),
  61.     /* class_initialize        */    XawInitializeWidgetSet,
  62.     /* class_part_initialize    */    NULL,
  63.     /* class_inited        */    FALSE,
  64.     /* initialize        */    NULL,
  65.     /* initialize_hook        */    NULL,
  66.     /* realize            */    Realize,
  67.     /* actions            */    NULL,
  68.     /* num_actions        */    0,
  69.     /* resources        */    resources,
  70.     /* num_resources        */    XtNumber(resources),
  71.     /* xrm_class        */    NULLQUARK,
  72.     /* compress_motion        */    TRUE,
  73.     /* compress_exposure    */    TRUE,
  74.     /* compress_enterleave    */    TRUE,
  75.     /* visible_interest        */    FALSE,
  76.     /* destroy            */    NULL,
  77.     /* resize            */    Resize,
  78.     /* expose            */    NULL,
  79.     /* set_values        */    NULL,
  80.     /* set_values_hook        */    NULL,
  81.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  82.     /* get_values_hook        */    NULL,
  83.     /* accept_focus        */    NULL,
  84.     /* version            */    XtVersion,
  85.     /* callback_private        */    NULL,
  86.     /* tm_table            */    NULL,
  87.     /* query_geometry        */    QueryGeometry,
  88.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  89.     /* extension        */    NULL
  90.   },
  91.   { /* composite fields */
  92.     /* geometry_manager        */    GeometryManager,
  93.     /* change_managed        */    ChangeManaged,
  94.     /* insert_child        */    XtInheritInsertChild,
  95.     /* delete_child        */    XtInheritDeleteChild,
  96.     /* extension        */    NULL
  97.   },
  98.   { /* porthole fields */
  99.     /* ignore                   */    0
  100.   }
  101. };
  102.  
  103. WidgetClass portholeWidgetClass = (WidgetClass) &portholeClassRec;
  104.  
  105.  
  106. /*****************************************************************************
  107.  *                                                                           *
  108.  *                   utility routines                              *
  109.  *                                                                           *
  110.  *****************************************************************************/
  111.  
  112. static Widget find_child (pw)
  113.     register PortholeWidget pw;
  114. {
  115.     register Widget *children;
  116.     register int i;
  117.  
  118.     /*
  119.      * Find the managed child on which we should operate.  Ignore multiple
  120.      * managed children.
  121.      */
  122.     for (i = 0, children = pw->composite.children;
  123.      i < pw->composite.num_children; i++, children++) {
  124.     if (XtIsManaged(*children)) return *children;
  125.     }
  126.  
  127.     return (Widget) NULL;
  128. }
  129.  
  130. static void SendReport (pw, changed)
  131.     PortholeWidget pw;
  132.     unsigned int changed;
  133. {
  134.     Widget child = find_child (pw);
  135.  
  136.     if (pw->porthole.report_callbacks && child) {
  137.     XawPannerReport prep;
  138.  
  139.     prep.changed = changed;
  140.     prep.slider_x = -child->core.x;    /* porthole is "inner" */
  141.     prep.slider_y = -child->core.y;    /* child is outer since it is larger */
  142.     prep.slider_width = pw->core.width;
  143.     prep.slider_height = pw->core.height;
  144.     prep.canvas_width = child->core.width;
  145.     prep.canvas_height = child->core.height;
  146.     XtCallCallbackList ((Widget)pw, pw->porthole.report_callbacks,
  147.                 (XtPointer) &prep);
  148.     }
  149. }
  150.  
  151.  
  152. static void layout_child (pw, child, geomp, xp, yp, widthp, heightp)
  153.     PortholeWidget pw;
  154.     Widget child;
  155.     XtWidgetGeometry *geomp;
  156.     Position *xp, *yp;
  157.     Dimension *widthp, *heightp;
  158. {
  159.     Position minx, miny;
  160.  
  161.     *xp = child->core.x;        /* default to current values */
  162.     *yp = child->core.y;
  163.     *widthp = child->core.width;
  164.     *heightp = child->core.height;
  165.     if (geomp) {            /* mix in any requested changes */
  166.     if (geomp->request_mode & CWX) *xp = geomp->x;
  167.     if (geomp->request_mode & CWY) *yp = geomp->y;
  168.     if (geomp->request_mode & CWWidth) *widthp = geomp->width;
  169.     if (geomp->request_mode & CWHeight) *heightp = geomp->height;
  170.     }
  171.  
  172.     /*
  173.      * Make sure that the child is at least as large as the porthole; there
  174.      * is no maximum size.
  175.      */
  176.     if (*widthp < pw->core.width) *widthp = pw->core.width;
  177.     if (*heightp < pw->core.height) *heightp = pw->core.height;
  178.  
  179.     /*
  180.      * Make sure that the child is still on the screen.  Note that this must
  181.      * be done *after* the size computation so that we know where to put it.
  182.      */
  183.     minx = ((Position) pw->core.width) - ((Position) *widthp);
  184.     miny = ((Position) pw->core.height) - ((Position) *heightp);
  185.  
  186.     if (*xp < minx) *xp = minx;        /* keep at lower right corner */
  187.     if (*yp < miny) *yp = miny;
  188.  
  189.     if (*xp > 0) *xp = 0;        /* keep at upper left corner */
  190.     if (*yp > 0) *yp = 0;
  191. }
  192.  
  193.  
  194.  
  195. /*****************************************************************************
  196.  *                                                                           *
  197.  *             Porthole Widget Class Methods                       *
  198.  *                                                                           *
  199.  *****************************************************************************/
  200.  
  201.  
  202. static void Realize (gw, valueMask, attributes)
  203.     register Widget gw;
  204.     Mask *valueMask;
  205.     XSetWindowAttributes *attributes;
  206. {
  207.     attributes->bit_gravity = NorthWestGravity;
  208.     *valueMask |= CWBitGravity;
  209.  
  210.     if (gw->core.width < 1) gw->core.width = 1;
  211.     if (gw->core.height < 1) gw->core.height = 1;
  212.     (*portholeWidgetClass->core_class.superclass->core_class.realize)
  213.     (gw, valueMask, attributes);
  214. }
  215.  
  216.  
  217. static void Resize (gw)
  218.     Widget gw;
  219. {
  220.     PortholeWidget pw = (PortholeWidget) gw;
  221.     Widget child = find_child (pw);
  222.  
  223.     /*
  224.      * If we have a child, we need to make sure that it is at least as big
  225.      * as we are and in the right place.
  226.      */
  227.     if (child) {
  228.     Position x, y;
  229.     Dimension width, height;
  230.  
  231.     layout_child (pw, child, NULL, &x, &y, &width, &height);
  232.     XtConfigureWidget (child, x, y, width, height, (Dimension) 0);
  233.     }
  234.  
  235.     SendReport (pw, (unsigned int) (XawPRCanvasWidth | XawPRCanvasHeight));
  236. }
  237.  
  238.  
  239. static XtGeometryResult QueryGeometry (gw, intended, preferred)
  240.     Widget gw;
  241.     XtWidgetGeometry *intended, *preferred;
  242. {
  243.     register PortholeWidget pw = (PortholeWidget) gw;
  244.     Widget child = find_child (pw);
  245.  
  246.     if (child) {
  247. #define SIZEONLY (CWWidth | CWHeight)
  248.     preferred->request_mode = SIZEONLY;
  249.     preferred->width = child->core.width;
  250.     preferred->height = child->core.height;
  251.  
  252.     if (((intended->request_mode & SIZEONLY) == SIZEONLY) &&
  253.         intended->width == preferred->width &&
  254.         intended->height == preferred->height)
  255.       return XtGeometryYes;
  256.     else if (preferred->width == pw->core.width &&
  257.          preferred->height == pw->core.height)
  258.       return XtGeometryNo;
  259.     else
  260.       return XtGeometryAlmost;
  261. #undef SIZEONLY
  262.     } 
  263.     return XtGeometryNo;
  264. }
  265.  
  266.  
  267. static XtGeometryResult GeometryManager (w, req, reply)
  268.     Widget w;
  269.     XtWidgetGeometry *req, *reply;
  270. {
  271.     PortholeWidget pw = (PortholeWidget) w->core.parent;
  272.     Widget child = find_child (pw);
  273.     Boolean okay = TRUE;
  274.  
  275.     if (child != w) return XtGeometryNo;  /* unknown child */
  276.  
  277.     *reply = *req;            /* assume we'll grant everything */
  278.  
  279.     if ((req->request_mode & CWBorderWidth) && req->border_width != 0) {
  280.     reply->border_width = 0;    /* require border width of 0 */
  281.     okay = FALSE;
  282.     }
  283.  
  284.     layout_child (pw, child, req, &reply->x, &reply->y,
  285.           &reply->width, &reply->height);
  286.  
  287.     if ((req->request_mode & CWX) && req->x != reply->x) okay = FALSE;
  288.     if ((req->request_mode & CWY) && req->x != reply->x) okay = FALSE;
  289.     if ((req->request_mode & CWWidth) && req->width != reply->width)
  290.       okay = FALSE;
  291.     if ((req->request_mode & CWHeight) && req->height != reply->height)
  292.       okay = FALSE;
  293.  
  294.  
  295.     /*
  296.      * If we failed on anything, simply return without touching widget
  297.      */
  298.     if (!okay) return XtGeometryAlmost;
  299.  
  300.     /*
  301.      * If not just doing a query, update widget and send report.  Note that
  302.      * we will often set fields that weren't requested because we want to keep
  303.      * the child visible.
  304.      */
  305.     if (!(req->request_mode & XtCWQueryOnly)) {
  306.     unsigned int changed = 0;
  307.  
  308.     if (child->core.x != reply->x) {
  309.         changed |= XawPRSliderX;
  310.         child->core.x = reply->x;
  311.     }
  312.     if (child->core.y != reply->y) {
  313.         changed |= XawPRSliderY;
  314.         child->core.y = reply->y;
  315.     }
  316.     if (child->core.width != reply->width) {
  317.         changed |= XawPRSliderWidth;
  318.         child->core.width = reply->width;
  319.     }
  320.     if (child->core.height != reply->height) {
  321.         changed |= XawPRSliderHeight;
  322.         child->core.height = reply->height;
  323.     }
  324.     if (changed) SendReport (pw, changed);
  325.     }
  326.  
  327.     return XtGeometryYes;        /* success! */
  328. }
  329.  
  330.  
  331. static void ChangeManaged (gw)
  332.     Widget gw;
  333. {
  334.     PortholeWidget pw = (PortholeWidget) gw;
  335.     Widget child = find_child (pw);    /* ignore extra children */
  336.  
  337.     if (child) {
  338.     if (!XtIsRealized (gw)) {
  339.         XtWidgetGeometry geom, retgeom;
  340.  
  341.         geom.request_mode = 0;
  342.         if (pw->core.width == 0) {
  343.         geom.width = child->core.width;
  344.         geom.request_mode |= CWWidth;
  345.         }
  346.         if (pw->core.height == 0) {
  347.         geom.height = child->core.height;
  348.         geom.request_mode |= CWHeight;
  349.         }
  350.         if (geom.request_mode &&
  351.         XtMakeGeometryRequest (gw, &geom, &retgeom) ==
  352.         XtGeometryAlmost) {
  353.             (void) XtMakeGeometryRequest (gw, &retgeom, NULL);
  354.         }
  355.     }
  356.     
  357.     XtResizeWidget (child, Max (child->core.width, pw->core.width),
  358.             Max (child->core.height, pw->core.height), 0);
  359.  
  360.     SendReport (pw, (unsigned int) XawPRAll);
  361.     }
  362. }
  363.