xref: /aosp_15_r20/external/coreboot/payloads/libpayload/curses/PDCurses/x11/ScrollBox.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /*
2  * Copyright 1989 O'Reilly and Associates, Inc.
3 
4      The X Consortium, and any party obtaining a copy of these files from
5      the X Consortium, directly or indirectly, is granted, free of charge, a
6      full and unrestricted irrevocable, world-wide, paid up, royalty-free,
7      nonexclusive right and license to deal in this software and
8      documentation files (the "Software"), including without limitation the
9      rights to use, copy, modify, merge, publish, distribute, sublicense,
10      and/or sell copies of the Software, and to permit persons who receive
11      copies from any such party to do so.  This license includes without
12      limitation a license to do the foregoing actions under any patents of
13      the party supplying this software to the X Consortium.
14 
15      $Id: ScrollBox.c,v 1.15 2008/07/14 04:24:52 wmcbrine Exp $
16  */
17 
18 /* ScrollBox.c - scrollBox composite widget */
19 
20 #include <X11/IntrinsicP.h>
21 #include <X11/StringDefs.h>
22 #include <X11/Shell.h>
23 
24 #include "x11/ScrollBoxP.h"
25 
26 #include <stdio.h>
27 
28 #define INITIAL_WIDTH 300
29 #define INITIAL_HEIGHT 300
30 
31 /************************************************************************
32  *                                                                      *
33  * scrollBox Resources                                                  *
34  *                                                                      *
35  ************************************************************************/
36 
37 static XtResource resources[] =
38 {
39     { XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension),
40         XtOffset(ScrollBoxWidget, scrollBox.h_space),
41         XtRImmediate, (XtPointer)4 },
42     { XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension),
43         XtOffset(ScrollBoxWidget, scrollBox.v_space),
44         XtRImmediate, (XtPointer)4 },
45     { XtNheightInc, XtCHeightInc, XtRDimension, sizeof(Dimension),
46         XtOffset(ScrollBoxWidget, scrollBox.increment_height),
47         XtRImmediate, (XtPointer)13 },
48     { XtNwidthInc, XtCWidthInc, XtRDimension, sizeof(Dimension),
49         XtOffset(ScrollBoxWidget, scrollBox.increment_width),
50         XtRImmediate, (XtPointer)7 },
51 };
52 
53 /************************************************************************
54  *                                                                      *
55  * Full class record constant                                           *
56  *                                                                      *
57  ************************************************************************/
58 
59 static void Initialize(Widget, Widget, ArgList, Cardinal *);
60 static void Resize(Widget);
61 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
62 static void ChangeManaged(Widget);
63 static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
64                                       XtWidgetGeometry *);
65 static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *,
66                                         XtWidgetGeometry *);
67 static void RefigureLocations(Widget);
68 
69 ScrollBoxClassRec scrollBoxClassRec = {
70   {
71     /* core_class fields        */
72         /* superclass           */  (WidgetClass) &compositeClassRec,
73         /* class_name           */  "scrollBox",
74         /* widget_size          */  sizeof(ScrollBoxRec),
75         /* class_initialize     */  NULL,
76         /* class_part_init      */  NULL,
77         /* class_inited         */  FALSE,
78         /* initialize           */  Initialize,
79         /* initialize_hook      */  NULL,
80         /* realize              */  XtInheritRealize,
81         /* actions              */  NULL,
82         /* num_actions          */  0,
83         /* resources            */  resources,
84         /* num_resources        */  XtNumber(resources),
85         /* xrm_class            */  NULLQUARK,
86         /* compress_motion      */  TRUE,
87         /* compress_exposure    */  TRUE,
88         /* compress_enterleave  */  TRUE,
89         /* visible_interest     */  FALSE,
90         /* destroy              */  NULL,
91         /* resize               */  Resize,
92         /* expose               */  NULL,
93         /* set_values           */  SetValues,
94         /* set_values_hook      */  NULL,
95         /* set_values_almost    */  XtInheritSetValuesAlmost,
96         /* get_values_hook      */  NULL,
97         /* accept_focus         */  NULL,
98         /* version              */  XtVersion,
99         /* callback_private     */  NULL,
100         /* tm_table             */  NULL,
101         /* query_geometry       */  QueryGeometry,
102         /* display_accelerator  */  XtInheritDisplayAccelerator,
103         /* extension            */  NULL
104   },{
105     /* composite_class fields   */
106         /* geometry_manager     */  GeometryManager,
107         /* change_managed       */  ChangeManaged,
108         /* insert_child         */  XtInheritInsertChild,
109         /* delete_child         */  XtInheritDeleteChild,
110         /* extension            */  NULL
111   },{
112     /* scrollBox class fields   */
113         /* empty                */  0,
114   }
115 };
116 
117 WidgetClass scrollBoxWidgetClass = (WidgetClass)&scrollBoxClassRec;
118 
119 /************************************************************************
120  *                                                                      *
121  * Private Routines                                                     *
122  *                                                                      *
123  ************************************************************************/
124 
125 /* Do a layout, either actually assigning positions, or just
126    calculating size. */
127 
DoLayout(Widget w,Boolean doit)128 static void DoLayout(Widget w, Boolean doit)
129 {
130     ScrollBoxWidget sbw = (ScrollBoxWidget)w;
131     Widget wmain, vscroll, hscroll, child;
132     Dimension mw, mh;   /* main window */
133     Dimension vh;   /* vertical scrollbar length (height) */
134     Dimension hw;   /* horizontal scrollbar length (width) */
135     Position vx;
136     Position hy;
137     Cardinal i;
138 
139     if (sbw->composite.num_children != 3)
140         XtAppError(XtWidgetToApplicationContext(w),
141             "ScrollBox: must manage exactly three widgets.");
142 
143     for (i = 0; i < sbw->composite.num_children; i++)
144     {
145         child = sbw->composite.children[i];
146 
147         if (!XtIsManaged(child))
148             XtAppError(XtWidgetToApplicationContext(w),
149                 "ScrollBox: all three widgets must be managed.");
150     }
151 
152     /* Child one is the main window, two is the vertical scrollbar,
153        and three is the horizontal scrollbar. */
154 
155     wmain = sbw->composite.children[0];
156     vscroll = sbw->composite.children[1];
157     hscroll = sbw->composite.children[2];
158 
159     /* Size all three widgets so that space is fully utilized. */
160 
161     mw = sbw->core.width - (2 * sbw->scrollBox.h_space) -
162         vscroll->core.width - (2 * vscroll->core.border_width) -
163         (2 * wmain->core.border_width);
164 
165     mh = sbw->core.height - (2 * sbw->scrollBox.v_space) -
166         hscroll->core.height - (2 * hscroll->core.border_width) -
167         (2 * wmain->core.border_width);
168 
169     /* Force the main window to be sized to the appropriate increment. */
170 
171     mw = (mw / sbw->scrollBox.increment_width) *
172         sbw->scrollBox.increment_width;
173 
174     mh = ((mh / sbw->scrollBox.increment_height) *
175         sbw->scrollBox.increment_height) +
176         sbw->scrollBox.increment_height;
177 
178     vx = wmain->core.x + mw + sbw->scrollBox.h_space +
179         wmain->core.border_width + vscroll->core.border_width;
180 
181     hy = wmain->core.y + mh + sbw->scrollBox.v_space +
182         wmain->core.border_width + hscroll->core.border_width;
183 
184     vh = mh;   /* scrollbars are always same length as main window */
185     hw = mw;
186 
187     if (doit)
188     {
189         XtResizeWidget(wmain, mw, mh, 1);
190 
191         XtResizeWidget(vscroll, vscroll->core.width, vh, 1);
192         XtMoveWidget(vscroll, vx, vscroll->core.y);
193 
194         XtResizeWidget(hscroll, hw, hscroll->core.height, 1);
195         XtMoveWidget(hscroll, hscroll->core.x, hy);
196     }
197 }
198 
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)199 static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request,
200                                         XtWidgetGeometry *reply)
201 {
202     XtWidgetGeometry allowed;
203 
204     if (request->request_mode & ~(XtCWQueryOnly | CWWidth | CWHeight))
205         return XtGeometryNo;
206 
207     if (request->request_mode & CWWidth)
208         allowed.width = request->width;
209     else
210         allowed.width = w->core.width;
211 
212     if (request->request_mode & CWHeight)
213         allowed.height = request->height;
214     else
215         allowed.height = w->core.height;
216 
217     if (allowed.width == w->core.width && allowed.height == w->core.height)
218         return XtGeometryNo;
219 
220     if (!(request->request_mode & XtCWQueryOnly))
221         RefigureLocations(w);
222 
223     return XtGeometryYes;
224 }
225 
RefigureLocations(Widget w)226 static void RefigureLocations(Widget w)
227 {
228     DoLayout(w, False);
229 }
230 
231 /* Calculate preferred size.  We can't just use the current sizes
232    of the children, because that calculation would always end up with
233    our current size.  Could query each child, and use that size to
234    recalculate a size for us, then if it ends up being larger than width
235    and height passed in, accept bounding box. However, we know our
236    children and they don't have any particular preferred geometry,
237    except the bigger the better. Therefore, if the parent suggested a
238    size, we'll take it. */
239 
QueryGeometry(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply_return)240 static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request,
241                                       XtWidgetGeometry *reply_return)
242 {
243     XtGeometryResult result=XtGeometryNo;
244 
245     request->request_mode &= CWWidth | CWHeight;
246 
247     /* parent isn't going to change w or h, so nothing to re-compute */
248 
249     if (request->request_mode == 0)
250         return XtGeometryYes;
251 
252     /* if proposed size is large enough, accept it.  Otherwise, suggest
253        our arbitrary initial size. */
254 
255     if (request->request_mode & CWHeight)
256     {
257         if (request->height < INITIAL_HEIGHT)
258         {
259             result = XtGeometryAlmost;
260             reply_return->height = INITIAL_HEIGHT;
261             reply_return->request_mode &= CWHeight;
262         }
263         else
264             result = XtGeometryYes;
265     }
266 
267     if (request->request_mode & CWWidth)
268     {
269         if (request->width < INITIAL_WIDTH)
270         {
271             result = XtGeometryAlmost;
272             reply_return->width = INITIAL_WIDTH;
273             reply_return->request_mode &= CWWidth;
274         }
275         else
276             result = XtGeometryYes;
277     }
278 
279     return result;
280 }
281 
282 /* Actually layout the scrollBox  */
283 
Resize(Widget w)284 static void Resize(Widget w)
285 {
286     DoLayout(w, True);
287 }
288 
ChangeManaged(Widget w)289 static void ChangeManaged(Widget w)
290 {
291     DoLayout(w, True);
292 }
293 
Initialize(Widget request,Widget new,ArgList args,Cardinal * num_args)294 static void Initialize(Widget request, Widget new,
295                        ArgList args, Cardinal *num_args)
296 {
297     ScrollBoxWidget newsbw = (ScrollBoxWidget)new;
298 
299     if (newsbw->core.width == 0)
300         newsbw->core.width = INITIAL_WIDTH;
301 
302     if (newsbw->core.height == 0)
303         newsbw->core.height = INITIAL_HEIGHT;
304 
305 }
306 
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)307 static Boolean SetValues(Widget current, Widget request, Widget new,
308                          ArgList args, Cardinal *num_args)
309 {
310     ScrollBoxWidget sbwcurrent = (ScrollBoxWidget)current;
311     ScrollBoxWidget sbwnew = (ScrollBoxWidget)new;
312 
313     /* need to relayout if h_space or v_space change */
314 
315     if ((sbwnew->scrollBox.h_space != sbwcurrent->scrollBox.h_space) ||
316         (sbwnew->scrollBox.v_space != sbwcurrent->scrollBox.v_space))
317         DoLayout(new, True);
318 
319     return False;
320 }
321