Change-Id: If881ec130833c7e7e62caa3d31e350a531f5bc8e Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Reviewed-on: http://review.coreboot.org/12398 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
		
			
				
	
	
		
			322 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright 1989 O'Reilly and Associates, Inc.
 | |
| 
 | |
|      The X Consortium, and any party obtaining a copy of these files from
 | |
|      the X Consortium, directly or indirectly, is granted, free of charge, a
 | |
|      full and unrestricted irrevocable, world-wide, paid up, royalty-free,
 | |
|      nonexclusive right and license to deal in this software and
 | |
|      documentation files (the "Software"), including without limitation the
 | |
|      rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|      and/or sell copies of the Software, and to permit persons who receive
 | |
|      copies from any such party to do so.  This license includes without
 | |
|      limitation a license to do the foregoing actions under any patents of
 | |
|      the party supplying this software to the X Consortium.
 | |
| 
 | |
|      $Id: ScrollBox.c,v 1.15 2008/07/14 04:24:52 wmcbrine Exp $
 | |
|  */
 | |
| 
 | |
| /* ScrollBox.c - scrollBox composite widget */
 | |
| 
 | |
| #include <X11/IntrinsicP.h>
 | |
| #include <X11/StringDefs.h>
 | |
| #include <X11/Shell.h>
 | |
| 
 | |
| #include "x11/ScrollBoxP.h"
 | |
| 
 | |
| #include <stdio.h>
 | |
| 
 | |
| #define INITIAL_WIDTH 300
 | |
| #define INITIAL_HEIGHT 300
 | |
| 
 | |
| /************************************************************************
 | |
|  *                                                                      *
 | |
|  * scrollBox Resources                                                  *
 | |
|  *                                                                      *
 | |
|  ************************************************************************/
 | |
| 
 | |
| static XtResource resources[] =
 | |
| {
 | |
|     { XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension),
 | |
|         XtOffset(ScrollBoxWidget, scrollBox.h_space),
 | |
|         XtRImmediate, (XtPointer)4 },
 | |
|     { XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension),
 | |
|         XtOffset(ScrollBoxWidget, scrollBox.v_space),
 | |
|         XtRImmediate, (XtPointer)4 },
 | |
|     { XtNheightInc, XtCHeightInc, XtRDimension, sizeof(Dimension),
 | |
|         XtOffset(ScrollBoxWidget, scrollBox.increment_height),
 | |
|         XtRImmediate, (XtPointer)13 },
 | |
|     { XtNwidthInc, XtCWidthInc, XtRDimension, sizeof(Dimension),
 | |
|         XtOffset(ScrollBoxWidget, scrollBox.increment_width),
 | |
|         XtRImmediate, (XtPointer)7 },
 | |
| };
 | |
| 
 | |
| /************************************************************************
 | |
|  *                                                                      *
 | |
|  * Full class record constant                                           *
 | |
|  *                                                                      *
 | |
|  ************************************************************************/
 | |
| 
 | |
| static void Initialize(Widget, Widget, ArgList, Cardinal *);
 | |
| static void Resize(Widget);
 | |
| static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
 | |
| static void ChangeManaged(Widget);
 | |
| static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
 | |
|                                       XtWidgetGeometry *);
 | |
| static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *,
 | |
|                                         XtWidgetGeometry *);
 | |
| static void RefigureLocations(Widget);
 | |
| 
 | |
| ScrollBoxClassRec scrollBoxClassRec = {
 | |
|   {
 | |
|     /* core_class fields        */
 | |
|         /* superclass           */  (WidgetClass) &compositeClassRec,
 | |
|         /* class_name           */  "scrollBox",
 | |
|         /* widget_size          */  sizeof(ScrollBoxRec),
 | |
|         /* class_initialize     */  NULL,
 | |
|         /* class_part_init      */  NULL,
 | |
|         /* class_inited         */  FALSE,
 | |
|         /* initialize           */  Initialize,
 | |
|         /* initialize_hook      */  NULL,
 | |
|         /* realize              */  XtInheritRealize,
 | |
|         /* actions              */  NULL,
 | |
|         /* num_actions          */  0,
 | |
|         /* resources            */  resources,
 | |
|         /* num_resources        */  XtNumber(resources),
 | |
|         /* xrm_class            */  NULLQUARK,
 | |
|         /* compress_motion      */  TRUE,
 | |
|         /* compress_exposure    */  TRUE,
 | |
|         /* compress_enterleave  */  TRUE,
 | |
|         /* visible_interest     */  FALSE,
 | |
|         /* destroy              */  NULL,
 | |
|         /* resize               */  Resize,
 | |
|         /* expose               */  NULL,
 | |
|         /* set_values           */  SetValues,
 | |
|         /* set_values_hook      */  NULL,
 | |
|         /* set_values_almost    */  XtInheritSetValuesAlmost,
 | |
|         /* get_values_hook      */  NULL,
 | |
|         /* accept_focus         */  NULL,
 | |
|         /* version              */  XtVersion,
 | |
|         /* callback_private     */  NULL,
 | |
|         /* tm_table             */  NULL,
 | |
|         /* query_geometry       */  QueryGeometry,
 | |
|         /* display_accelerator  */  XtInheritDisplayAccelerator,
 | |
|         /* extension            */  NULL
 | |
|   },{
 | |
|     /* composite_class fields   */
 | |
|         /* geometry_manager     */  GeometryManager,
 | |
|         /* change_managed       */  ChangeManaged,
 | |
|         /* insert_child         */  XtInheritInsertChild,
 | |
|         /* delete_child         */  XtInheritDeleteChild,
 | |
|         /* extension            */  NULL
 | |
|   },{
 | |
|     /* scrollBox class fields   */
 | |
|         /* empty                */  0,
 | |
|   }
 | |
| };
 | |
| 
 | |
| WidgetClass scrollBoxWidgetClass = (WidgetClass)&scrollBoxClassRec;
 | |
| 
 | |
| 
 | |
| /************************************************************************
 | |
|  *                                                                      *
 | |
|  * Private Routines                                                     *
 | |
|  *                                                                      *
 | |
|  ************************************************************************/
 | |
| 
 | |
| /* Do a layout, either actually assigning positions, or just
 | |
|    calculating size. */
 | |
| 
 | |
| static void DoLayout(Widget w, Boolean doit)
 | |
| {
 | |
|     ScrollBoxWidget sbw = (ScrollBoxWidget)w;
 | |
|     Widget wmain, vscroll, hscroll, child;
 | |
|     Dimension mw, mh;   /* main window */
 | |
|     Dimension vh;   /* vertical scrollbar length (height) */
 | |
|     Dimension hw;   /* horizontal scrollbar length (width) */
 | |
|     Position vx;
 | |
|     Position hy;
 | |
|     Cardinal i;
 | |
| 
 | |
|     if (sbw->composite.num_children != 3)
 | |
|         XtAppError(XtWidgetToApplicationContext(w),
 | |
|             "ScrollBox: must manage exactly three widgets.");
 | |
| 
 | |
|     for (i = 0; i < sbw->composite.num_children; i++)
 | |
|     {
 | |
|         child = sbw->composite.children[i];
 | |
| 
 | |
|         if (!XtIsManaged(child))
 | |
|             XtAppError(XtWidgetToApplicationContext(w),
 | |
|                 "ScrollBox: all three widgets must be managed.");
 | |
|     }
 | |
| 
 | |
|     /* Child one is the main window, two is the vertical scrollbar,
 | |
|        and three is the horizontal scrollbar. */
 | |
| 
 | |
|     wmain = sbw->composite.children[0];
 | |
|     vscroll = sbw->composite.children[1];
 | |
|     hscroll = sbw->composite.children[2];
 | |
| 
 | |
|     /* Size all three widgets so that space is fully utilized. */
 | |
| 
 | |
|     mw = sbw->core.width - (2 * sbw->scrollBox.h_space) -
 | |
|         vscroll->core.width - (2 * vscroll->core.border_width) -
 | |
|         (2 * wmain->core.border_width);
 | |
| 
 | |
|     mh = sbw->core.height - (2 * sbw->scrollBox.v_space) -
 | |
|         hscroll->core.height - (2 * hscroll->core.border_width) -
 | |
|         (2 * wmain->core.border_width);
 | |
| 
 | |
|     /* Force the main window to be sized to the appropriate increment. */
 | |
| 
 | |
|     mw = (mw / sbw->scrollBox.increment_width) *
 | |
|         sbw->scrollBox.increment_width;
 | |
| 
 | |
|     mh = ((mh / sbw->scrollBox.increment_height) *
 | |
|         sbw->scrollBox.increment_height) +
 | |
|         sbw->scrollBox.increment_height;
 | |
| 
 | |
|     vx = wmain->core.x + mw + sbw->scrollBox.h_space +
 | |
|         wmain->core.border_width + vscroll->core.border_width;
 | |
| 
 | |
|     hy = wmain->core.y + mh + sbw->scrollBox.v_space +
 | |
|         wmain->core.border_width + hscroll->core.border_width;
 | |
| 
 | |
|     vh = mh;   /* scrollbars are always same length as main window */
 | |
|     hw = mw;
 | |
| 
 | |
|     if (doit)
 | |
|     {
 | |
|         XtResizeWidget(wmain, mw, mh, 1);
 | |
| 
 | |
|         XtResizeWidget(vscroll, vscroll->core.width, vh, 1);
 | |
|         XtMoveWidget(vscroll, vx, vscroll->core.y);
 | |
| 
 | |
|         XtResizeWidget(hscroll, hw, hscroll->core.height, 1);
 | |
|         XtMoveWidget(hscroll, hscroll->core.x, hy);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request,
 | |
|                                         XtWidgetGeometry *reply)
 | |
| {
 | |
|     XtWidgetGeometry allowed;
 | |
| 
 | |
|     if (request->request_mode & ~(XtCWQueryOnly | CWWidth | CWHeight))
 | |
|         return XtGeometryNo;
 | |
| 
 | |
|     if (request->request_mode & CWWidth)
 | |
|         allowed.width = request->width;
 | |
|     else
 | |
|         allowed.width = w->core.width;
 | |
| 
 | |
|     if (request->request_mode & CWHeight)
 | |
|         allowed.height = request->height;
 | |
|     else
 | |
|         allowed.height = w->core.height;
 | |
| 
 | |
|     if (allowed.width == w->core.width && allowed.height == w->core.height)
 | |
|         return XtGeometryNo;
 | |
| 
 | |
|     if (!(request->request_mode & XtCWQueryOnly))
 | |
|         RefigureLocations(w);
 | |
| 
 | |
|     return XtGeometryYes;
 | |
| }
 | |
| 
 | |
| static void RefigureLocations(Widget w)
 | |
| {
 | |
|     DoLayout(w, False);
 | |
| }
 | |
| 
 | |
| /* Calculate preferred size.  We can't just use the current sizes
 | |
|    of the children, because that calculation would always end up with
 | |
|    our current size.  Could query each child, and use that size to
 | |
|    recalculate a size for us, then if it ends up being larger than width
 | |
|    and height passed in, accept bounding box. However, we know our
 | |
|    children and they don't have any particular preferred geometry,
 | |
|    except the bigger the better. Therefore, if the parent suggested a
 | |
|    size, we'll take it. */
 | |
| 
 | |
| static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request,
 | |
|                                       XtWidgetGeometry *reply_return)
 | |
| {
 | |
|     XtGeometryResult result=XtGeometryNo;
 | |
| 
 | |
|     request->request_mode &= CWWidth | CWHeight;
 | |
| 
 | |
|     /* parent isn't going to change w or h, so nothing to re-compute */
 | |
| 
 | |
|     if (request->request_mode == 0)
 | |
|         return XtGeometryYes;
 | |
| 
 | |
|     /* if proposed size is large enough, accept it.  Otherwise, suggest
 | |
|        our arbitrary initial size. */
 | |
| 
 | |
|     if (request->request_mode & CWHeight)
 | |
|     {
 | |
|         if (request->height < INITIAL_HEIGHT)
 | |
|         {
 | |
|             result = XtGeometryAlmost;
 | |
|             reply_return->height = INITIAL_HEIGHT;
 | |
|             reply_return->request_mode &= CWHeight;
 | |
|         }
 | |
|         else
 | |
|             result = XtGeometryYes;
 | |
|     }
 | |
| 
 | |
|     if (request->request_mode & CWWidth)
 | |
|     {
 | |
|         if (request->width < INITIAL_WIDTH)
 | |
|         {
 | |
|             result = XtGeometryAlmost;
 | |
|             reply_return->width = INITIAL_WIDTH;
 | |
|             reply_return->request_mode &= CWWidth;
 | |
|         }
 | |
|         else
 | |
|             result = XtGeometryYes;
 | |
|     }
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| /* Actually layout the scrollBox  */
 | |
| 
 | |
| static void Resize(Widget w)
 | |
| {
 | |
|     DoLayout(w, True);
 | |
| }
 | |
| 
 | |
| static void ChangeManaged(Widget w)
 | |
| {
 | |
|     DoLayout(w, True);
 | |
| }
 | |
| 
 | |
| static void Initialize(Widget request, Widget new,
 | |
|                        ArgList args, Cardinal *num_args)
 | |
| {
 | |
|     ScrollBoxWidget newsbw = (ScrollBoxWidget)new;
 | |
| 
 | |
|     if (newsbw->core.width == 0)
 | |
|         newsbw->core.width = INITIAL_WIDTH;
 | |
| 
 | |
|     if (newsbw->core.height == 0)
 | |
|         newsbw->core.height = INITIAL_HEIGHT;
 | |
| 
 | |
| }
 | |
| 
 | |
| static Boolean SetValues(Widget current, Widget request, Widget new,
 | |
|                          ArgList args, Cardinal *num_args)
 | |
| {
 | |
|     ScrollBoxWidget sbwcurrent = (ScrollBoxWidget)current;
 | |
|     ScrollBoxWidget sbwnew = (ScrollBoxWidget)new;
 | |
| 
 | |
|     /* need to relayout if h_space or v_space change */
 | |
| 
 | |
|     if ((sbwnew->scrollBox.h_space != sbwcurrent->scrollBox.h_space) ||
 | |
|         (sbwnew->scrollBox.v_space != sbwcurrent->scrollBox.v_space))
 | |
|         DoLayout(new, True);
 | |
| 
 | |
|     return False;
 | |
| }
 |