Bug Summary

File:Box.c
Location:line 327, column 29
Description:Assigned value is garbage or undefined

Annotated Source Code

1/***********************************************************
2
3Copyright (c) 1987, 1988, 1994 X Consortium
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the X Consortium shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from the X Consortium.
25
26
27Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29 All Rights Reserved
30
31Permission to use, copy, modify, and distribute this software and its
32documentation for any purpose and without fee is hereby granted,
33provided that the above copyright notice appear in all copies and that
34both that copyright notice and this permission notice appear in
35supporting documentation, and that the name of Digital not be
36used in advertising or publicity pertaining to distribution of the
37software without specific, written prior permission.
38
39DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45SOFTWARE.
46
47******************************************************************/
48
49#ifdef HAVE_CONFIG_H1
50#include "config.h"
51#endif
52
53/*
54 * Box.c - Box composite widget
55 *
56 */
57
58#include <X11/IntrinsicP.h>
59#include <X11/StringDefs.h>
60#include <X11/Xmu/Misc.h>
61#include <X11/Xaw3d/XawInit.h>
62#include <X11/Xaw3d/BoxP.h>
63
64/****************************************************************
65 *
66 * Box Resources
67 *
68 ****************************************************************/
69
70static XtResource resources[] = {
71 { XtNhSpace((char*)&XtStrings[251]), XtCHSpace((char*)&XtStrings[1058]), XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension),
72 XtOffsetOf(BoxRec, box.h_space)__builtin_offsetof(BoxRec, box.h_space),
73 XtRImmediate((char*)&XtStrings[1695]), (XtPointer)4 },
74 { XtNvSpace((char*)&XtStrings[865]), XtCVSpace((char*)&XtStrings[1503]), XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension),
75 XtOffsetOf(BoxRec, box.v_space)__builtin_offsetof(BoxRec, box.v_space),
76 XtRImmediate((char*)&XtStrings[1695]), (XtPointer)4 },
77 { XtNorientation((char*)&XtStrings[505]), XtCOrientation((char*)&XtStrings[1206]), XtROrientation((char*)&XtStrings[1742]), sizeof(XtOrientation),
78 XtOffsetOf(BoxRec, box.orientation)__builtin_offsetof(BoxRec, box.orientation),
79 XtRImmediate((char*)&XtStrings[1695]), (XtPointer)XtorientVertical },
80};
81
82/****************************************************************
83 *
84 * Full class record constant
85 *
86 ****************************************************************/
87
88static void ClassInitialize(void);
89static void Initialize(Widget, Widget, ArgList, Cardinal *);
90static void Realize(Widget, Mask *, XSetWindowAttributes *);
91static void Resize(Widget);
92static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
93static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *, XtWidgetGeometry *);
94static void ChangeManaged(Widget);
95static XtGeometryResult PreferredSize(Widget, XtWidgetGeometry *, XtWidgetGeometry *);
96
97BoxClassRec boxClassRec = {
98 {
99/* core_class fields */
100 /* superclass */ (WidgetClass) &compositeClassRec,
101 /* class_name */ "Box",
102 /* widget_size */ sizeof(BoxRec),
103 /* class_initialize */ ClassInitialize,
104 /* class_part_init */ NULL((void*)0),
105 /* class_inited */ FALSE0,
106 /* initialize */ Initialize,
107 /* initialize_hook */ NULL((void*)0),
108 /* realize */ Realize,
109 /* actions */ NULL((void*)0),
110 /* num_actions */ 0,
111 /* resources */ resources,
112 /* num_resources */ XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))),
113 /* xrm_class */ NULLQUARK((XrmQuark) 0),
114 /* compress_motion */ TRUE1,
115 /* compress_exposure */ TRUE1,
116 /* compress_enterleave*/ TRUE1,
117 /* visible_interest */ FALSE0,
118 /* destroy */ NULL((void*)0),
119 /* resize */ Resize,
120 /* expose */ NULL((void*)0),
121 /* set_values */ SetValues,
122 /* set_values_hook */ NULL((void*)0),
123 /* set_values_almost */ XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit),
124 /* get_values_hook */ NULL((void*)0),
125 /* accept_focus */ NULL((void*)0),
126 /* version */ XtVersion(11 * 1000 + 6),
127 /* callback_private */ NULL((void*)0),
128 /* tm_table */ NULL((void*)0),
129 /* query_geometry */ PreferredSize,
130 /* display_accelerator*/ XtInheritDisplayAccelerator((XtStringProc) _XtInherit),
131 /* extension */ NULL((void*)0)
132 },{
133/* composite_class fields */
134 /* geometry_manager */ GeometryManager,
135 /* change_managed */ ChangeManaged,
136 /* insert_child */ XtInheritInsertChild((XtWidgetProc) _XtInherit),
137 /* delete_child */ XtInheritDeleteChild((XtWidgetProc) _XtInherit),
138 /* extension */ NULL((void*)0)
139 },{
140/* Box class fields */
141 /* empty */ 0,
142 }
143};
144
145WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec;
146
147
148/****************************************************************
149 *
150 * Private Routines
151 *
152 ****************************************************************/
153
154/*
155 *
156 * Do a layout, either actually assigning positions, or just calculating size.
157 * Returns minimum width and height that will preserve the same layout.
158 *
159 */
160
161static void
162DoLayout(BoxWidget bbw, Dimension width, Dimension height,
163 Dimension *reply_width, Dimension *reply_height, Boolean position)
164{
165 Boolean vbox = (bbw->box.orientation == XtorientVertical);
166 Cardinal i;
167 Dimension w, h; /* Width and height needed for box */
168 Dimension lw, lh; /* Width and height needed for current line */
169 Dimension bw, bh; /* Width and height needed for current widget */
170 Dimension h_space; /* Local copy of bbw->box.h_space */
171 Widget widget; /* Current widget */
172 int num_mapped_children = 0;
173
174 /* Box width and height */
175 h_space = bbw->box.h_space;
176
177 w = 0;
178 for (i = 0; i < bbw->composite.num_children; i++) {
179 if ( bbw->composite.children[i]->core.width > w )
180 w = bbw->composite.children[i]->core.width;
181 }
182 w += h_space;
183 if ( w > width ) width = w;
184 h = bbw->box.v_space;
185
186 /* Line width and height */
187 lh = 0;
188 lw = h_space;
189
190 for (i = 0; i < bbw->composite.num_children; i++) {
191 widget = bbw->composite.children[i];
192 if (widget->core.managed) {
193 if (widget->core.mapped_when_managed) num_mapped_children++;
194 /* Compute widget width */
195 bw = widget->core.width + 2*widget->core.border_width + h_space;
196 if ((Dimension)(lw + bw) > width) {
197 if (lw > h_space) {
198 /* At least one widget on this line, and
199 * can't fit any more. Start new line if vbox.
200 */
201 AssignMax(w, lw){if ((lw) > (w)) w = (lw);};
202 if (vbox) {
203 h += lh + bbw->box.v_space;
204 lh = 0;
205 lw = h_space;
206 }
207 }
208 else if (!position) {
209 /* too narrow for this widget; we'll assume we can grow */
210 DoLayout(bbw, lw + bw, height, reply_width,
211 reply_height, position);
212 return;
213 }
214 }
215 if (position && (lw != (Dimension)widget->core.x || h != (Dimension)widget->core.y)) {
216 /* It would be nice to use window gravity, but there isn't
217 * sufficient fine-grain control to nicely handle all
218 * situations (e.g. when only the height changes --
219 * a common case). Explicit unmapping is a cheap hack
220 * to speed things up & avoid the visual jitter as
221 * things slide around.
222 *
223 * %%% perhaps there should be a client resource to
224 * control this. If so, we'll have to optimize to
225 * perform the moves from the correct end so we don't
226 * force extra exposures as children occlude each other.
227 */
228 if (XtIsRealized(widget)(XtWindowOfObject(widget) != 0L) && widget->core.mapped_when_managed)
229 XUnmapWindow( XtDisplay(widget)(((widget)->core.screen)->display), XtWindow(widget)((widget)->core.window) );
230 XtMoveWidget(widget, (int)lw, (int)h);
231 }
232 lw += bw;
233 bh = widget->core.height + 2*widget->core.border_width;
234 AssignMax(lh, bh){if ((bh) > (lh)) lh = (bh);};
235 } /* if managed */
236 } /* for */
237
238 if (!vbox && width && lw > width && lh < height) {
239 /* reduce width if too wide and height not filled */
240 Dimension sw = lw, sh = lh;
241 Dimension width_needed = 0;
242 XtOrientation orientation = bbw->box.orientation;
243 bbw->box.orientation = XtorientVertical;
244 while (sh < height && sw > width) {
245 width_needed = sw;
246 DoLayout(bbw, sw-1, height, &sw, &sh, False0);
247 }
248 if (sh < height) width_needed = sw;
249 if (width_needed != lw) {
250 DoLayout(bbw,width_needed,height,reply_width,reply_height,position);
251 bbw->box.orientation = orientation;
252 return;
253 }
254 bbw->box.orientation = orientation;
255 }
256 if ( vbox && ( ( width < w ) || ( width < lw ) ) ) {
257 AssignMax(w, lw){if ((lw) > (w)) w = (lw);};
258 DoLayout( bbw, w, height, reply_width, reply_height, position );
259 return;
260 }
261 if (position && XtIsRealized((Widget)bbw)(XtWindowOfObject((Widget)bbw) != 0L)) {
262 if (bbw->composite.num_children == num_mapped_children)
263 XMapSubwindows( XtDisplay((Widget)bbw)((((Widget)bbw)->core.screen)->display), XtWindow((Widget)bbw)(((Widget)bbw)->core.window) );
264 else {
265 int j = bbw->composite.num_children;
266 Widget *childP = bbw->composite.children;
267 for (; j > 0; childP++, j--)
268 if (XtIsRealized(*childP)(XtWindowOfObject(*childP) != 0L) && XtIsManaged(*childP) &&
269 (*childP)->core.mapped_when_managed)
270 XtMapWidget(*childP)XMapWindow((((*childP)->core.screen)->display), ((*childP
)->core.window))
;
271 }
272 }
273
274 /* Finish off last line */
275 if (lw > h_space) {
276 AssignMax(w, lw){if ((lw) > (w)) w = (lw);};
277 h += lh + bbw->box.v_space;
278 }
279
280 *reply_width = Max(w, 1)(((w) > (1)) ? (w) : (1));
281 *reply_height = Max(h, 1)(((h) > (1)) ? (h) : (1));
282}
283
284/*
285 *
286 * Calculate preferred size, given constraining box, caching it in the widget.
287 *
288 */
289
290static XtGeometryResult
291PreferredSize(Widget widget, XtWidgetGeometry *constraint, XtWidgetGeometry *preferred)
292{
293 BoxWidget w = (BoxWidget)widget;
294 Dimension width /*, height */;
295 Dimension preferred_width = w->box.preferred_width;
296 Dimension preferred_height = w->box.preferred_height;
297
298 constraint->request_mode &= CWWidth(1<<2) | CWHeight(1<<3);
299
300 if (constraint->request_mode == 0)
5
Taking false branch
301 /* parent isn't going to change w or h, so nothing to re-compute */
302 return XtGeometryYes;
303
304 if (constraint->request_mode == w->box.last_query_mode &&
305 (!(constraint->request_mode & CWWidth(1<<2)) ||
306 constraint->width == w->box.last_query_width) &&
307 (!(constraint->request_mode & CWHeight(1<<3)) ||
308 constraint->height == w->box.last_query_height)) {
309 /* same query; current preferences are still valid */
310 preferred->request_mode = CWWidth(1<<2) | CWHeight(1<<3);
311 preferred->width = preferred_width;
312 preferred->height = preferred_height;
313 if (constraint->request_mode == (CWWidth(1<<2) | CWHeight(1<<3)) &&
314 constraint->width == preferred_width &&
315 constraint->height == preferred_height)
316 return XtGeometryYes;
317 else
318 return XtGeometryAlmost;
319 }
320
321 /* else gotta do it the long way...
322 I have a preference for tall and narrow, so if my width is
323 constrained, I'll accept it; otherwise, I'll compute the minimum
324 width that will fit me within the height constraint */
325
326 w->box.last_query_mode = constraint->request_mode;
327 w->box.last_query_width = constraint->width;
6
Assigned value is garbage or undefined
328 w->box.last_query_height= constraint->height;
329
330 if (constraint->request_mode & CWWidth(1<<2))
331 width = constraint->width;
332 else /* if (constraint->request_mode & CWHeight) */ {
333 /* let's see if I can become any narrower */
334 width = 0;
335 constraint->width = 65535;
336 }
337
338 /* height is currently ignored by DoLayout.
339 height = (constraint->request_mode & CWHeight) ? constraint->height
340 : *preferred_height;
341 */
342 DoLayout(w, width, (Dimension)0,
343 &preferred_width, &preferred_height, FALSE0);
344
345 if (constraint->request_mode & CWHeight(1<<3) &&
346 preferred_height > constraint->height) {
347 /* find minimum width for this height */
348 if (preferred_width > constraint->width) {
349 /* punt; over-constrained */
350 }
351 else {
352 width = preferred_width;
353 do { /* find some width big enough to stay within this height */
354 if (width > (constraint->width >> 1)) /* avoid short int overflow */
355 width = constraint->width;
356 else
357 width <<= 1;
358 DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE0);
359 } while (preferred_height > constraint->height
360 && width < constraint->width);
361 if (width != constraint->width) {
362 do { /* find minimum width */
363 width = preferred_width;
364 DoLayout(w, preferred_width-1, 0,
365 &preferred_width, &preferred_height, FALSE0);
366 } while (preferred_height < constraint->height);
367 /* one last time */
368 DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE0);
369 }
370 }
371 }
372
373 preferred->request_mode = CWWidth(1<<2) | CWHeight(1<<3);
374 preferred->width = w->box.preferred_width = preferred_width;
375 preferred->height = w->box.preferred_height = preferred_height;
376
377 if (constraint->request_mode == (CWWidth(1<<2)|CWHeight(1<<3))
378 && constraint->width == preferred_width
379 && constraint->height == preferred_height)
380 return XtGeometryYes;
381 else
382 return XtGeometryAlmost;
383
384}
385
386/*
387 *
388 * Actually layout the box
389 *
390 */
391
392static void
393Resize(Widget w)
394{
395 Dimension junk;
396
397 DoLayout((BoxWidget)w, w->core.width, w->core.height, &junk, &junk, TRUE1);
398
399} /* Resize */
400
401/*
402 *
403 * Try to do a new layout within the current width and height;
404 * if that fails try to resize and do it within the box returne
405 * by PreferredSize.
406 *
407 * TryNewLayout just says if it's possible, and doesn't actually move the kids
408 */
409
410static Boolean
411TryNewLayout(BoxWidget bbw)
412{
413 Dimension preferred_width, preferred_height;
414 Dimension proposed_width, proposed_height;
415 int iterations;
416
417 DoLayout( bbw, bbw->core.width, bbw->core.height,
418 &preferred_width, &preferred_height, FALSE0 );
419
420 /* at this point, preferred_width is guaranteed to not be greater
421 than bbw->core.width unless some child is larger, so there's no
422 point in re-computing another layout */
423
424 if ((bbw->core.width == preferred_width) &&
425 (bbw->core.height == preferred_height)) {
426 /* Same size */
427 return (TRUE1);
428 }
429
430 /* let's see if our parent will go for a new size. */
431 iterations = 0;
432 proposed_width = preferred_width;
433 proposed_height = preferred_height;
434 do {
435 switch (XtMakeResizeRequest((Widget)bbw,proposed_width,proposed_height,
2
Control jumps to 'case XtGeometryAlmost:' at line 452
436 &proposed_width, &proposed_height))
437 {
438 case XtGeometryYes:
439 return (TRUE1);
440
441 case XtGeometryNo:
442 if (iterations > 0)
443 /* protect from malicious parents who change their minds */
444 DoLayout( bbw, bbw->core.width, bbw->core.height,
445 &preferred_width, &preferred_height, FALSE0 );
446 if ((preferred_width <= bbw->core.width) &&
447 (preferred_height <= bbw->core.height))
448 return (TRUE1);
449 else
450 return (FALSE0);
451
452 case XtGeometryAlmost:
453 if (proposed_height >= preferred_height &&
454 proposed_width >= preferred_width) {
455
456 /*
457 * Take it, and assume the parent knows what it is doing.
458 *
459 * The parent must accept this since it was returned in
460 * almost.
461 *
462 */
463 (void) XtMakeResizeRequest( (Widget)bbw,
464 proposed_width, proposed_height,
465 &proposed_width, &proposed_height);
466 return(TRUE1);
467 }
468 else if (proposed_width != preferred_width) {
3
Taking false branch
469 /* recalc bounding box; height might change */
470 DoLayout(bbw, proposed_width, 0,
471 &preferred_width, &preferred_height, FALSE0);
472 proposed_height = preferred_height;
473 }
474 else { /* proposed_height != preferred_height */
475 XtWidgetGeometry constraints, reply;
476 constraints.request_mode = CWHeight(1<<3);
477 constraints.height = proposed_height;
478 (void)PreferredSize((Widget)bbw, &constraints, &reply);
4
Calling 'PreferredSize'
479 proposed_width = preferred_width;
480 }
481 break;
482
483 case XtGeometryDone: /* ??? */
484 default:
485 break;
486 }
487 iterations++;
488 } while (iterations < 10);
489 return (FALSE0);
490}
491
492/*
493 *
494 * Geometry Manager
495 *
496 * 'reply' is unused; we say only yeay or nay, never almost.
497 *
498 */
499
500/*ARGSUSED*/
501static XtGeometryResult
502GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply)
503{
504 Dimension width, height, borderWidth;
505 BoxWidget bbw;
506
507 /* Position request always denied */
508 if ((request->request_mode & CWX(1<<0) && request->x != w->core.x) ||
509 (request->request_mode & CWY(1<<1) && request->y != w->core.y))
510 return (XtGeometryNo);
511
512 /* Size changes must see if the new size can be accomodated */
513 if (request->request_mode & (CWWidth(1<<2) | CWHeight(1<<3) | CWBorderWidth(1<<4))) {
514
515 /* Make all three fields in the request valid */
516 if ((request->request_mode & CWWidth(1<<2)) == 0)
517 request->width = w->core.width;
518 if ((request->request_mode & CWHeight(1<<3)) == 0)
519 request->height = w->core.height;
520 if ((request->request_mode & CWBorderWidth(1<<4)) == 0)
521 request->border_width = w->core.border_width;
522
523 /* Save current size and set to new size */
524 width = w->core.width;
525 height = w->core.height;
526 borderWidth = w->core.border_width;
527 w->core.width = request->width;
528 w->core.height = request->height;
529 w->core.border_width = request->border_width;
530
531 /* Decide if new layout works: (1) new widget is smaller,
532 (2) new widget fits in existing Box, (3) Box can be
533 expanded to allow new widget to fit */
534
535 bbw = (BoxWidget) w->core.parent;
536
537/* whenever a child changes his geometry, we attempt to
538 * change ours to be the minimum enclosing size...
539 if (((request->width + request->border_width <= width + borderWidth) &&
540 (request->height + request->border_width <= height + borderWidth))
541 || bbw->box.preferred_width < bbw->core.width
542 || bbw->box.preferred_height < bbw->core.height
543 || TryNewLayout(bbw)) {
544 */
545 if (TryNewLayout(bbw)) {
546 /* Fits in existing or new space, relayout */
547 (*XtClass((Widget)bbw)(((Widget)bbw)->core.widget_class)->core_class.resize)((Widget)bbw);
548 return (XtGeometryYes);
549 } else {
550 /* Cannot satisfy request, change back to original geometry */
551 w->core.width = width;
552 w->core.height = height;
553 w->core.border_width = borderWidth;
554 return (XtGeometryNo);
555 }
556 }; /* if any size changes requested */
557
558 /* Any stacking changes don't make a difference, so allow if that's all */
559 return (XtGeometryYes);
560}
561
562static void
563ChangeManaged(Widget w)
564{
565 /* Reconfigure the box */
566 (void) TryNewLayout((BoxWidget)w);
1
Calling 'TryNewLayout'
567 Resize(w);
568}
569
570static void
571ClassInitialize(void)
572{
573 XawInitializeWidgetSet();
574 XtAddConverter( XtRString((char*)&XtStrings[1797]), XtROrientation((char*)&XtStrings[1742]), XmuCvtStringToOrientation,
575 (XtConvertArgList)NULL((void*)0), (Cardinal)0 );
576}
577
578/* ARGSUSED */
579static void
580Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
581{
582 BoxWidget newbbw = (BoxWidget)new;
583
584 newbbw->box.last_query_mode = CWWidth(1<<2) | CWHeight(1<<3);
585 newbbw->box.last_query_width = newbbw->box.last_query_height = 0;
586 newbbw->box.preferred_width = Max(newbbw->box.h_space, 1)(((newbbw->box.h_space) > (1)) ? (newbbw->box.h_space
) : (1))
;
587 newbbw->box.preferred_height = Max(newbbw->box.v_space, 1)(((newbbw->box.v_space) > (1)) ? (newbbw->box.v_space
) : (1))
;
588
589 if (newbbw->core.width == 0)
590 newbbw->core.width = newbbw->box.preferred_width;
591
592 if (newbbw->core.height == 0)
593 newbbw->core.height = newbbw->box.preferred_height;
594
595} /* Initialize */
596
597static void
598Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
599{
600 attributes->bit_gravity = NorthWestGravity1;
601 *valueMask |= CWBitGravity(1L<<4);
602
603 XtCreateWindow( w, (unsigned)InputOutput1, (Visual *)CopyFromParent0L,
604 *valueMask, attributes);
605} /* Realize */
606
607/* ARGSUSED */
608static Boolean
609SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args)
610{
611 /* need to relayout if h_space or v_space change */
612
613 return False0;
614}