Bug Summary

File:List.c
Location:line 326, column 20
Description:Access to field 'fid' results in a dereference of a null pointer (loaded from field 'font')

Annotated Source Code

1/*
2Copyright 1989, 1994, 1998 The Open Group
3
4Permission to use, copy, modify, distribute, and sell this software and its
5documentation for any purpose is hereby granted without fee, provided that
6the above copyright notice appear in all copies and that both that
7copyright notice and this permission notice appear in supporting
8documentation.
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20Except as contained in this notice, the name of The Open Group shall not be
21used in advertising or otherwise to promote the sale, use or other dealings
22in this Software without prior written authorization from The Open Group.
23*/
24
25/*
26 * List.c - List widget
27 *
28 * This is a List widget. It allows the user to select an item in a list and
29 * notifies the application through a callback function.
30 *
31 * Created: 8/13/88
32 * By: Chris D. Peterson
33 * MIT X Consortium
34 */
35
36#ifdef HAVE_CONFIG_H1
37#include <config.h>
38#endif
39#include <stdio.h>
40#include <ctype.h>
41#include <X11/IntrinsicP.h>
42#include <X11/StringDefs.h>
43#include <X11/Xmu/Drawing.h>
44#include <X11/Xaw/ListP.h>
45#include <X11/Xaw/XawInit.h>
46#include "Private.h"
47
48#define HeightLock1 1
49#define WidthLock2 2
50#define LongestLock4 4
51
52#define HeightFree(w)!(((ListWidget)(w))->list.freedoms & 1) !(((ListWidget)(w))->list.freedoms & HeightLock1)
53#define WidthFree(w)!(((ListWidget)(w))->list.freedoms & 2) !(((ListWidget)(w))->list.freedoms & WidthLock2)
54#define LongestFree(w)!(((ListWidget)(w))->list.freedoms & 4) !(((ListWidget)(w))->list.freedoms & LongestLock4)
55
56#define MaxSize32767 32767
57
58/*
59 * Class Methods
60 */
61static void XawListDestroy(Widget);
62static void XawListInitialize(Widget, Widget, ArgList, Cardinal*);
63static XtGeometryResult XawListQueryGeometry(Widget, XtWidgetGeometry*,
64 XtWidgetGeometry*);
65static void XawListRedisplay(Widget, XEvent*, Region);
66static void XawListResize(Widget);
67static Boolean XawListSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
68
69/*
70 * Prototypes
71 */
72static void CalculatedValues(Widget);
73static void ChangeSize(Widget, unsigned int, unsigned int);
74static void ClipToShadowInteriorAndLongest(ListWidget, GC*, unsigned int);
75static int CvtToItem(Widget, int, int, int*);
76static void FindCornerItems(Widget, XEvent*, int*, int*);
77static void GetGCs(Widget);
78static void HighlightBackground(Widget, int, int, GC);
79static Boolint ItemInRectangle(Widget, int, int, int);
80static Boolint Layout(Widget, Boolint, Boolint, Dimension*, Dimension*);
81static void PaintItemName(Widget, int);
82static void ResetList(Widget, Boolint, Boolint);
83
84/*
85 * Actions
86 */
87static void Notify(Widget, XEvent*, String*, Cardinal*);
88static void Set(Widget, XEvent*, String*, Cardinal*);
89static void Unset(Widget, XEvent*, String*, Cardinal*);
90
91/*
92 * Initialization
93 */
94static char defaultTranslations[] =
95"<Btn1Down>:" "Set()\n"
96"<Btn1Up>:" "Notify()\n"
97;
98
99#define offset(field) XtOffsetOf(ListRec, field)__builtin_offsetof(ListRec, field)
100static XtResource resources[] = {
101 {
102 XtNforeground((char*)&XtStrings[214]),
103 XtCForeground((char*)&XtStrings[1022]),
104 XtRPixel((char*)&XtStrings[1754]),
105 sizeof(Pixel),
106 offset(list.foreground),
107 XtRString((char*)&XtStrings[1797]),
108 XtDefaultForeground"XtDefaultForeground"
109 },
110 {
111 XtNcursor"cursor",
112 XtCCursor((char*)&XtStrings[976]),
113 XtRCursor((char*)&XtStrings[1611]),
114 sizeof(Cursor),
115 offset(simple.cursor),
116 XtRString((char*)&XtStrings[1797]),
117 "left_ptr"
118 },
119 {
120 XtNfont((char*)&XtStrings[199]),
121 XtCFont((char*)&XtStrings[1017]),
122 XtRFontStruct((char*)&XtStrings[1666]),
123 sizeof(XFontStruct*),
124 offset(list.font),
125 XtRString((char*)&XtStrings[1797]),
126 XtDefaultFont"XtDefaultFont"
127 },
128 {
129 XtNfontSet((char*)&XtStrings[2018]),
130 XtCFontSet((char*)&XtStrings[2034]),
131 XtRFontSet((char*)&XtStrings[2026]),
132 sizeof(XFontSet),
133 offset(list.fontset),
134 XtRString((char*)&XtStrings[1797]),
135 XtDefaultFontSet"XtDefaultFontSet"
136 },
137 {
138 XtNlist"list",
139 XtCList"List",
140 XtRPointer((char*)&XtStrings[1767]),
141 sizeof(char**),
142 offset(list.list),
143#ifdef notyet
144 XtRStringArray((char*)&XtStrings[1804]),
145#else
146 XtRString((char*)&XtStrings[1797]),
147#endif
148 NULL((void*)0)
149 },
150 {
151 XtNdefaultColumns"defaultColumns",
152 XtCColumns"Columns",
153 XtRInt((char*)&XtStrings[1718]),
154 sizeof(int),
155 offset(list.default_cols),
156 XtRImmediate((char*)&XtStrings[1695]),
157 (XtPointer)2
158 },
159 {
160 XtNlongest"longest",
161 XtCLongest"Longest",
162 XtRInt((char*)&XtStrings[1718]),
163 sizeof(int),
164 offset(list.longest),
165 XtRImmediate((char*)&XtStrings[1695]),
166 (XtPointer)0
167 },
168 {
169 XtNnumberStrings"numberStrings",
170 XtCNumberStrings"NumberStrings",
171 XtRInt((char*)&XtStrings[1718]),
172 sizeof(int),
173 offset(list.nitems),
174 XtRImmediate((char*)&XtStrings[1695]),
175 (XtPointer)0
176 },
177 {
178 XtNpasteBuffer"pasteBuffer",
179 XtCBoolean((char*)&XtStrings[920]),
180 XtRBoolean((char*)&XtStrings[1561]),
181 sizeof(Boolean),
182 offset(list.paste),
183 XtRImmediate((char*)&XtStrings[1695]),
184 (XtPointer)False0
185 },
186 {
187 XtNforceColumns"forceColumns",
188 XtCColumns"Columns",
189 XtRBoolean((char*)&XtStrings[1561]),
190 sizeof(Boolean),
191 offset(list.force_cols),
192 XtRImmediate((char*)&XtStrings[1695]),
193 (XtPointer)False0
194 },
195 {
196 XtNverticalList"verticalList",
197 XtCBoolean((char*)&XtStrings[920]),
198 XtRBoolean((char*)&XtStrings[1561]),
199 sizeof(Boolean),
200 offset(list.vertical_cols),
201 XtRImmediate((char*)&XtStrings[1695]),
202 (XtPointer)False0
203 },
204 {
205 XtNinternalWidth((char*)&XtStrings[356]),
206 XtCWidth((char*)&XtStrings[1510]),
207 XtRDimension((char*)&XtStrings[1618]),
208 sizeof(Dimension),
209 offset(list.internal_width),
210 XtRImmediate((char*)&XtStrings[1695]),
211 (XtPointer)2
212 },
213 {
214 XtNinternalHeight((char*)&XtStrings[341]),
215 XtCHeight((char*)&XtStrings[1051]),
216 XtRDimension((char*)&XtStrings[1618]),
217 sizeof(Dimension),
218 offset(list.internal_height),
219 XtRImmediate((char*)&XtStrings[1695]),
220 (XtPointer)2
221 },
222 {
223 XtNcolumnSpacing"columnSpacing",
224 XtCSpacing"Spacing",
225 XtRDimension((char*)&XtStrings[1618]),
226 sizeof(Dimension),
227 offset(list.column_space),
228 XtRImmediate((char*)&XtStrings[1695]),
229 (XtPointer)6
230 },
231 {
232 XtNrowSpacing"rowSpacing",
233 XtCSpacing"Spacing",
234 XtRDimension((char*)&XtStrings[1618]),
235 sizeof(Dimension),
236 offset(list.row_space),
237 XtRImmediate((char*)&XtStrings[1695]),
238 (XtPointer)2
239 },
240 {
241 XtNcallback((char*)&XtStrings[136]),
242 XtCCallback((char*)&XtStrings[952]),
243 XtRCallback((char*)&XtStrings[1569]),
244 sizeof(XtPointer),
245 offset(list.callback),
246 XtRCallback((char*)&XtStrings[1569]),
247 NULL((void*)0)
248 },
249#ifndef OLDXAW
250 {
251 XtNshowCurrent"showCurrent",
252 XtCBoolean((char*)&XtStrings[920]),
253 XtRBoolean((char*)&XtStrings[1561]),
254 sizeof(Boolean),
255 offset(list.show_current),
256 XtRImmediate((char*)&XtStrings[1695]),
257 (XtPointer)False0
258 },
259#endif
260};
261#undef offset
262
263static XtActionsRec actions[] = {
264 {"Notify", Notify},
265 {"Set", Set},
266 {"Unset", Unset},
267};
268
269#define Superclass(&simpleClassRec) (&simpleClassRec)
270ListClassRec listClassRec = {
271 /* core */
272 {
273 (WidgetClass)Superclass(&simpleClassRec), /* superclass */
274 "List", /* class_name */
275 sizeof(ListRec), /* widget_size */
276 XawInitializeWidgetSet, /* class_initialize */
277 NULL((void*)0), /* class_part_initialize */
278 False0, /* class_inited */
279 XawListInitialize, /* initialize */
280 NULL((void*)0), /* initialize_hook */
281 XtInheritRealize((XtRealizeProc) _XtInherit), /* realize */
282 actions, /* actions */
283 XtNumber(actions)((Cardinal) (sizeof(actions) / sizeof(actions[0]))), /* num_actions */
284 resources, /* resources */
285 XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))), /* num_resources */
286 NULLQUARK((XrmQuark) 0), /* xrm_class */
287 True1, /* compress_motion */
288 False0, /* compress_exposure */
289 True1, /* compress_enterleave */
290 False0, /* visible_interest */
291 XawListDestroy, /* destroy */
292 XawListResize, /* resize */
293 XawListRedisplay, /* expose */
294 XawListSetValues, /* set_values */
295 NULL((void*)0), /* set_values_hook */
296 XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit), /* set_values_almost */
297 NULL((void*)0), /* get_values_hook */
298 NULL((void*)0), /* accept_focus */
299 XtVersion(11 * 1000 + 6), /* version */
300 NULL((void*)0), /* callback_private */
301 defaultTranslations, /* tm_table */
302 XawListQueryGeometry, /* query_geometry */
303 },
304 /* simple */
305 {
306 XtInheritChangeSensitive((int (*)(Widget))_XtInherit), /* change_sensitive */
307 },
308 /* list */
309 {
310 NULL((void*)0), /* extension */
311 },
312};
313
314WidgetClass listWidgetClass = (WidgetClass)&listClassRec;
315
316/*
317 * Implementation
318 */
319static void
320GetGCs(Widget w)
321{
322 XGCValues values;
323 ListWidget lw = (ListWidget)w;
324
325 values.foreground = lw->list.foreground;
326 values.font = lw->list.font->fid;
4
Access to field 'fid' results in a dereference of a null pointer (loaded from field 'font')
327
328 if (lw->simple.international == True1)
329 lw->list.normgc = XtAllocateGC(w, 0, GCForeground(1L<<2), &values, GCFont(1L<<14), 0);
330 else
331 lw->list.normgc = XtGetGC(w, GCForeground(1L<<2) | GCFont(1L<<14), &values);
332
333 values.foreground = lw->core.background_pixel;
334
335 if (lw->simple.international == True1)
336 lw->list.revgc = XtAllocateGC(w, 0, GCForeground(1L<<2), &values, GCFont(1L<<14), 0);
337 else
338 lw->list.revgc = XtGetGC(w, GCForeground(1L<<2) | GCFont(1L<<14), &values);
339
340 values.tile = XmuCreateStippledPixmap(XtScreen(w)((w)->core.screen),
341 lw->list.foreground,
342 lw->core.background_pixel,
343 lw->core.depth);
344 values.fill_style = FillTiled1;
345
346 if (lw->simple.international == True1)
347 lw->list.graygc = XtAllocateGC(w, 0, GCTile(1L<<10) | GCFillStyle(1L<<8),
348 &values, GCFont(1L<<14), 0);
349 else
350 lw->list.graygc = XtGetGC(w, GCFont(1L<<14) | GCTile(1L<<10) | GCFillStyle(1L<<8), &values);
351}
352
353static void
354CalculatedValues(Widget w)
355{
356 int i, len;
357 ListWidget lw = (ListWidget)w;
358
359 /* If list is NULL then the list will just be the name of the widget */
360 if (lw->list.list == NULL((void*)0)) {
361 lw->list.list = &lw->core.name;
362 lw->list.nitems = 1;
363 }
364
365 /* Get number of items */
366 if (lw->list.nitems == 0)
367 for (; lw->list.list[lw->list.nitems] != NULL((void*)0) ; lw->list.nitems++)
368 ;
369
370 /* Get column width */
371 if (LongestFree(lw)!(((ListWidget)(lw))->list.freedoms & 4)) {
372 lw->list.longest = 0; /* so it will accumulate real longest below */
373
374 for (i = 0 ; i < lw->list.nitems; i++) {
375 if (lw->simple.international == True1)
376 len = XmbTextEscapement(lw->list.fontset, lw->list.list[i],
377 strlen(lw->list.list[i]));
378 else
379 len = XTextWidth(lw->list.font, lw->list.list[i],
380 strlen(lw->list.list[i]));
381 if (len > lw->list.longest)
382 lw->list.longest = len;
383 }
384 }
385
386 lw->list.col_width = lw->list.longest + lw->list.column_space;
387}
388
389/*
390 * Function:
391 * ResetList
392 *
393 * Parameters:
394 * w - list widget
395 * changex - allow the height or width to change?
396 * changey - ""
397 *
398 * Description:
399 * Resets the new list when important things change.
400 *
401 * Returns:
402 * True if width or height have been changed
403 */
404static void
405ResetList(Widget w, Boolint changex, Boolint changey)
406{
407 Dimension width = XtWidth(w)(((RectObj)w)->rectangle.width);
408 Dimension height = XtHeight(w)(((RectObj)w)->rectangle.height);
409
410 CalculatedValues(w);
411
412 if (Layout(w, changex, changey, &width, &height)) {
413 if (XtIsComposite(XtParent(w))(((Object)(((w)->core.parent)))->object.widget_class->
core_class.class_inited & 0x08)
)
414 ChangeSize(w, width, height);
415 else {
416 XtWidth(w)(((RectObj)w)->rectangle.width) = width;
417 XtHeight(w)(((RectObj)w)->rectangle.height) = height;
418 }
419 }
420}
421
422/*
423 * Function:
424 * ChangeSize
425 *
426 * Parameters:
427 * w - widget to try change the size of
428 *
429 * Description:
430 * Laysout the widget.
431 */
432static void
433ChangeSize(Widget w, unsigned int width, unsigned int height)
434{
435 XtWidgetGeometry request, reply;
436
437 request.request_mode = CWWidth(1<<2) | CWHeight(1<<3);
438 request.width = width;
439 request.height = height;
440
441 switch (XtMakeGeometryRequest(w, &request, &reply)) {
442 case XtGeometryYes:
443 case XtGeometryNo:
444 break;
445 case XtGeometryAlmost:
446 Layout(w, request.height != reply.height,
447 request.width != reply.width, &reply.width, &reply.height);
448 request = reply;
449 switch (XtMakeGeometryRequest(w, &request, &reply)) {
450 case XtGeometryYes:
451 case XtGeometryNo:
452 break;
453 case XtGeometryAlmost:
454 request = reply;
455 Layout(w, False0, False0, &request.width, &request.height);
456 request.request_mode = CWWidth(1<<2) | CWHeight(1<<3);
457 XtMakeGeometryRequest(w, &request, &reply);
458 /*FALLTROUGH*/
459 default:
460 break;
461 }
462 /*FALLTROUGH*/
463 default:
464 break;
465 }
466}
467
468/*ARGSUSED*/
469static void
470XawListInitialize(Widget temp1, Widget cnew, ArgList args, Cardinal *num_args)
471{
472 ListWidget lw = (ListWidget)cnew;
473
474 if (!lw->list.font) XtError("Aborting: no font found\n");
1
Assuming pointer value is null
2
Taking true branch
475 if (lw->simple.international && !lw->list.fontset)
476 XtError("Aborting: no fontset found\n");
477
478 /*
479 * Initialize all private resources
480 */
481 /* record for posterity if we are free */
482 lw->list.freedoms = ((XtWidth(lw)(((RectObj)lw)->rectangle.width) != 0) * WidthLock2 +
483 (XtHeight(lw)(((RectObj)lw)->rectangle.height) != 0) * HeightLock1 +
484 (lw->list.longest != 0) * LongestLock4);
485
486 GetGCs(cnew);
3
Calling 'GetGCs'
487
488 /* Set row height, based on font or fontset */
489 if (lw->simple.international == True1)
490 lw->list.row_height =
491 XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height +
492 lw->list.row_space;
493 else
494 lw->list.row_height = lw->list.font->max_bounds.ascent +
495 lw->list.font->max_bounds.descent +
496 lw->list.row_space;
497
498 ResetList(cnew, WidthFree(lw)!(((ListWidget)(lw))->list.freedoms & 2), HeightFree(lw)!(((ListWidget)(lw))->list.freedoms & 1));
499
500 lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT-1;
501}
502
503/*
504 * Function:
505 * CvtToItem
506 *
507 * Parameters:
508 * w - list widget
509 * xloc - x location
510 * yloc - y location
511 *
512 * Description:
513 * Converts Xcoord to item number of item containing that point.
514 *
515 * Returns:
516 * Item number
517 */
518static int
519CvtToItem(Widget w, int xloc, int yloc, int *item)
520{
521 int one, another;
522 ListWidget lw = (ListWidget)w;
523 int ret_val = OKAY0;
524
525 if (lw->list.vertical_cols) {
526 one = lw->list.nrows * ((xloc - (int)lw->list.internal_width)
527 / lw->list.col_width);
528 another = (yloc - (int)lw->list.internal_height) / lw->list.row_height;
529 /* If out of range, return minimum possible value */
530 if (another >= lw->list.nrows) {
531 another = lw->list.nrows - 1;
532 ret_val = OUT_OF_RANGE-1;
533 }
534 }
535 else {
536 one = (lw->list.ncols * ((yloc - (int)lw->list.internal_height)
537 / lw->list.row_height));
538 /* If in right margin handle things right */
539 another = (xloc - (int)lw->list.internal_width) / lw->list.col_width;
540 if (another >= lw->list.ncols) {
541 another = lw->list.ncols - 1;
542 ret_val = OUT_OF_RANGE-1;
543 }
544 }
545 if (xloc < 0 || yloc < 0)
546 ret_val = OUT_OF_RANGE-1;
547 if (one < 0)
548 one = 0;
549 if (another < 0)
550 another = 0;
551 *item = one + another;
552 if (*item >= lw->list.nitems)
553 return (OUT_OF_RANGE-1);
554
555 return (ret_val);
556}
557
558/*
559 * Function:
560 * FindCornerItems
561 *
562 * Arguments:
563 * w - list widget
564 * event - event structure that has the rectangle it it
565 * ul_ret - the corners (return)
566 * lr_ret - ""
567 *
568 * Description:
569 * Find the corners of the rectangle in item space.
570 */
571static void
572FindCornerItems(Widget w, XEvent *event, int *ul_ret, int *lr_ret)
573{
574 int xloc, yloc;
575
576 xloc = event->xexpose.x;
577 yloc = event->xexpose.y;
578 CvtToItem(w, xloc, yloc, ul_ret);
579 xloc += event->xexpose.width;
580 yloc += event->xexpose.height;
581 CvtToItem(w, xloc, yloc, lr_ret);
582}
583
584/*
585 * Function:
586 * ItemInRectangle
587 *
588 * Parameters:
589 * w - list widget
590 * ul - corners of the rectangle in item space
591 * lr - ""
592 * item - item to check
593 *
594 * Returns:
595 * True if the item passed is in the given rectangle
596 */
597static Boolint
598ItemInRectangle(Widget w, int ul, int lr, int item)
599{
600 ListWidget lw = (ListWidget)w;
601 int mod_item;
602 int things;
603
604 if (item < ul || item > lr)
605 return (False0);
606 if (lw->list.vertical_cols)
607 things = lw->list.nrows;
608 else
609 things = lw->list.ncols;
610
611 mod_item = item % things;
612 if ((mod_item >= ul % things) && (mod_item <= lr % things))
613 return (True1);
614
615 return (False0);
616}
617
618/* HighlightBackground()
619 *
620 * Paints the color of the background for the given item. It performs
621 * clipping to the interior of internal_width/height by hand, as its a
622 * simple calculation and probably much faster than using Xlib and a clip mask.
623 *
624 * x, y - ul corner of the area item occupies.
625 * gc - the gc to use to paint this rectangle
626 */
627static void
628HighlightBackground(Widget w, int x, int y, GC gc)
629{
630 ListWidget lw = (ListWidget)w;
631 Dimension width = lw->list.col_width;
632 Dimension height = lw->list.row_height;
633 Dimension frame_limited_width = XtWidth(w)(((RectObj)w)->rectangle.width) - lw->list.internal_width - x;
634 Dimension frame_limited_height= XtHeight(w)(((RectObj)w)->rectangle.height) - lw->list.internal_height - y;
635
636 /* Clip the rectangle width and height to the edge of the drawable area */
637 if (width > frame_limited_width)
638 width = frame_limited_width;
639 if (height > frame_limited_height)
640 height = frame_limited_height;
641
642 /* Clip the rectangle x and y to the edge of the drawable area */
643 if (x < lw->list.internal_width) {
644 width = width - (lw->list.internal_width - x);
645 x = lw->list.internal_width;
646 }
647 if (y < lw->list.internal_height) {
648 height = height - (lw->list.internal_height - y);
649 y = lw->list.internal_height;
650 }
651
652 if (gc == lw->list.revgc && lw->core.background_pixmap != XtUnspecifiedPixmap((Pixmap)2))
653 XClearArea(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), x, y, width, height, False0);
654 else
655 XFillRectangle(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, x, y, width, height);
656}
657
658
659/* ClipToShadowInteriorAndLongest()
660 *
661 * Converts the passed gc so that any drawing done with that GC will not
662 * write in the empty margin (specified by internal_width/height) (which also
663 * prevents erasing the shadow. It also clips against the value longest.
664 * If the user doesn't set longest, this has no effect (as longest is the
665 * maximum of all item lengths). If the user does specify, say, 80 pixel
666 * columns, though, this prevents items from overwriting other items.
667 */
668static void
669ClipToShadowInteriorAndLongest(ListWidget lw, GC *gc_p, unsigned int x)
670{
671 XRectangle rect;
672
673 rect.x = x;
674 rect.y = lw->list.internal_height;
675 rect.height = XtHeight(lw)(((RectObj)lw)->rectangle.height) - (lw->list.internal_height << 1);
676 rect.width = XtWidth(lw)(((RectObj)lw)->rectangle.width) - lw->list.internal_width - x;
677 if (rect.width > lw->list.longest)
678 rect.width = lw->list.longest;
679
680 XSetClipRectangles(XtDisplay((Widget)lw)((((Widget)lw)->core.screen)->display), *gc_p, 0, 0, &rect, 1, YXBanded3);
681}
682
683static void
684PaintItemName(Widget w, int item)
685{
686 char *str;
687 GC gc;
688 int x, y, str_y;
689 ListWidget lw = (ListWidget)w;
690 XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset);
691
692 if (!XtIsRealized(w)(XtWindowOfObject(w) != 0L) || item > lw->list.nitems)
693 return;
694
695 if (lw->list.vertical_cols) {
696 x = lw->list.col_width * (item / lw->list.nrows)
697 + lw->list.internal_width;
698 y = lw->list.row_height * (item % lw->list.nrows)
699 + lw->list.internal_height;
700 }
701 else {
702 x = lw->list.col_width * (item % lw->list.ncols)
703 + lw->list.internal_width;
704 y = lw->list.row_height * (item / lw->list.ncols)
705 + lw->list.internal_height;
706 }
707
708 if ( lw->simple.international == True1 )
709 str_y = y + XawAbs(ext->max_ink_extent.y)((ext->max_ink_extent.y) < 0 ? -(ext->max_ink_extent
.y) : (ext->max_ink_extent.y))
;
710 else
711 str_y = y + lw->list.font->max_bounds.ascent;
712
713 if (item == lw->list.is_highlighted) {
714 if (item == lw->list.highlight) {
715 gc = lw->list.revgc;
716 HighlightBackground(w, x, y, lw->list.normgc);
717 }
718 else {
719 if (XtIsSensitive(w))
720 gc = lw->list.normgc;
721 else
722 gc = lw->list.graygc;
723 HighlightBackground(w, x, y, lw->list.revgc);
724 lw->list.is_highlighted = NO_HIGHLIGHT-1;
725 }
726 }
727 else {
728 if (item == lw->list.highlight) {
729 gc = lw->list.revgc;
730 HighlightBackground(w, x, y, lw->list.normgc);
731 lw->list.is_highlighted = item;
732 }
733 else {
734 if (XtIsSensitive(w))
735 gc = lw->list.normgc;
736 else
737 gc = lw->list.graygc;
738 }
739 }
740
741 /* List's overall width contains the same number of inter-column
742 column_space's as columns. There should thus be a half
743 column_width margin on each side of each column.
744 The row case is symmetric */
745
746 x += lw->list.column_space >> 1;
747 str_y += lw->list.row_space >> 1;
748
749 str = lw->list.list[item]; /* draw it */
750
751 ClipToShadowInteriorAndLongest(lw, &gc, x);
752
753 if (lw->simple.international == True1)
754 XmbDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), lw->list.fontset,
755 gc, x, str_y, str, strlen(str));
756 else
757 XDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, x, str_y, str, strlen(str));
758
759 XSetClipMask(XtDisplay(w)(((w)->core.screen)->display), gc, None0L);
760}
761
762static void
763XawListRedisplay(Widget w, XEvent *event, Region region)
764{
765 int item; /* an item to work with */
766 int ul_item, lr_item; /* corners of items we need to paint */
767 ListWidget lw = (ListWidget)w;
768
769 if (event == NULL((void*)0)) {
770 ul_item = 0;
771 lr_item = lw->list.nrows * lw->list.ncols - 1;
772 XClearWindow(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window));
773 }
774 else
775 FindCornerItems(w, event, &ul_item, &lr_item);
776
777 if (Superclass(&simpleClassRec)->core_class.expose)
778 (Superclass(&simpleClassRec)->core_class.expose)(w, event, region);
779
780 for (item = ul_item; item <= lr_item && item < lw->list.nitems; item++)
781 if (ItemInRectangle(w, ul_item, lr_item, item))
782 PaintItemName(w, item);
783}
784
785/* XawListQueryGeometry()
786 *
787 * This tells the parent what size we would like to be
788 * given certain constraints.
789 * w - the widget.
790 * intended - what the parent intends to do with us.
791 * requested - what we want to happen */
792static XtGeometryResult
793XawListQueryGeometry(Widget w, XtWidgetGeometry *intended,
794 XtWidgetGeometry *requested)
795{
796 Dimension new_width, new_height;
797 Boolint change, width_req, height_req;
798
799 width_req = intended->request_mode & CWWidth(1<<2);
800 height_req = intended->request_mode & CWHeight(1<<3);
801
802 if (width_req)
803 new_width = intended->width;
804 else
805 new_width = XtWidth(w)(((RectObj)w)->rectangle.width);
806
807 if (height_req)
808 new_height = intended->height;
809 else
810 new_height = XtHeight(w)(((RectObj)w)->rectangle.height);
811
812 requested->request_mode = 0;
813
814 /*
815 * We only care about our height and width
816 */
817 if (!width_req && !height_req)
818 return (XtGeometryYes);
819
820 change = Layout(w, !width_req, !height_req, &new_width, &new_height);
821
822 requested->request_mode |= CWWidth(1<<2);
823 requested->width = new_width;
824 requested->request_mode |= CWHeight(1<<3);
825 requested->height = new_height;
826
827 if (change)
828 return (XtGeometryAlmost);
829
830 return (XtGeometryYes);
831}
832
833static void
834XawListResize(Widget w)
835{
836 Dimension width, height;
837
838 width = XtWidth(w)(((RectObj)w)->rectangle.width);
839 height = XtHeight(w)(((RectObj)w)->rectangle.height);
840
841 if (Layout(w, False0, False0, &width, &height))
842 XtAppWarning(XtWidgetToApplicationContext(w),
843 "List Widget: Size changed when it shouldn't "
844 "have when resising.");
845}
846
847/* Layout()
848 *
849 * lays out the item in the list.
850 * w - the widget.
851 * xfree, yfree - True if we are free to resize the widget in
852 * this direction.
853 * width, height- the is the current width and height that we are going
854 * we are going to layout the list widget to,
855 * depending on xfree and yfree of course.
856 *
857 * Return:
858 * True if width or height have been changed */
859static Boolint
860Layout(Widget w, Boolint xfree, Boolint yfree, Dimension *width, Dimension *height)
861{
862 ListWidget lw = (ListWidget)w;
863 Boolint change = False0;
864 unsigned long width2 = 0, height2 = 0;
865
866 /*
867 * If force columns is set then always use number of columns specified
868 * by default_cols
869 */
870 if (lw->list.force_cols) {
871 lw->list.ncols = lw->list.default_cols;
872 if (lw->list.ncols <= 0)
873 lw->list.ncols = 1;
874 lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
875 if (xfree) {
876 /* this counts the same number
877 of inter-column column_space 's as columns. There should thus
878 be a half column_space margin on each side of each column...*/
879 width2 = lw->list.ncols * lw->list.col_width +
880 (lw->list.internal_width << 1);
881 change = True1;
882 }
883 if (yfree) {
884 height2 = lw->list.nrows * lw->list.row_height +
885 (lw->list.internal_height << 1);
886 change = True1;
887 }
888 }
889
890 /*
891 * If both width and height are free to change the use default_cols
892 * to determine the number columns and set new width and height to
893 * just fit the window
894 */
895 else if (xfree && yfree) {
896 lw->list.ncols = lw->list.default_cols;
897 if (lw->list.ncols <= 0) {
898 int wid = (int)XtWidth(lw)(((RectObj)lw)->rectangle.width) - (int)(lw->list.internal_width << 1)
899 + (int)lw->list.column_space;
900
901 if (wid <= 0 || lw->list.col_width <= 0
902 || (lw->list.ncols = wid / lw->list.col_width) <= 0)
903 lw->list.ncols = 1;
904 }
905 width2 = lw->list.ncols * lw->list.col_width
906 + (lw->list.internal_width << 1);
907 height2 = (lw->list.nrows * lw->list.row_height)
908 + (lw->list.internal_height << 1);
909 change = True1;
910 }
911
912 /*
913 * If the width is fixed then use it to determine the number of columns.
914 * If the height is free to move (width still fixed) then resize the height
915 * of the widget to fit the current list exactly
916 */
917 else if (!xfree) {
918 lw->list.ncols = ((int)(*width - (lw->list.internal_width << 1))
919 / (int)lw->list.col_width);
920 if (lw->list.ncols <= 0)
921 lw->list.ncols = 1;
922 lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
923 if (yfree) {
924 height2 = lw->list.nrows * lw->list.row_height +
925 (lw->list.internal_height << 1);
926 change = True1;
927 }
928 }
929
930 /*
931 * The last case is xfree and !yfree we use the height to determine
932 * the number of rows and then set the width to just fit the resulting
933 * number of columns
934 */
935 else if (!yfree) {
936 lw->list.nrows = ((int)(*height - (lw->list.internal_height << 1))
937 / (int)lw->list.row_height);
938 if (lw->list.nrows <= 0)
939 lw->list.nrows = 1;
940 lw->list.ncols = ((lw->list.nitems - 1) / lw->list.nrows) + 1;
941 width2 = lw->list.ncols * lw->list.col_width +
942 (lw->list.internal_width << 1);
943 change = True1;
944 }
945
946 if (!lw->list.force_cols && lw->list.nrows) {
947 /*CONSTCOND*/
948 while (1) {
949 lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
950 width2 = lw->list.ncols * lw->list.col_width +
951 (lw->list.internal_width << 1);
952 height2 = lw->list.nrows * lw->list.row_height +
953 (lw->list.internal_height << 1);
954 if (width2 >= MaxSize32767 && height2 >= MaxSize32767)
955 break;
956 if (height2 > MaxSize32767)
957 ++lw->list.ncols;
958 else if (width2 > MaxSize32767 && lw->list.ncols > 1)
959 --lw->list.ncols;
960 else
961 break;
962 }
963 }
964 if (width2)
965 *width = width2;
966 if (height2)
967 *height = height2;
968
969 return (change);
970}
971
972/* Notify() - Action
973 *
974 * Notifies the user that a button has been pressed, and
975 * calls the callback; if the XtNpasteBuffer resource is true
976 * then the name of the item is also put in CUT_BUFFER0 */
977/*ARGSUSED*/
978static void
979Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
980{
981 ListWidget lw = (ListWidget)w;
982 int item, item_len;
983 XawListReturnStruct ret_value;
984
985 /*
986 * Find item and if out of range then unhighlight and return
987 *
988 * If the current item is unhighlighted then the user has aborted the
989 * notify, so unhighlight and return
990 */
991 if ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE-1)
992 || lw->list.highlight != item) {
993#ifndef OLDXAW
994 if (!lw->list.show_current || lw->list.selected == NO_HIGHLIGHT-1)
995 XawListUnhighlight(w);
996 else
997 XawListHighlight(w, lw->list.selected);
998#else
999 XawListUnhighlight(w);
1000#endif
1001 return;
1002 }
1003
1004 item_len = strlen(lw->list.list[item]);
1005
1006 if (lw->list.paste) /* if XtNpasteBuffer set then paste it */
1007 XStoreBytes(XtDisplay(w)(((w)->core.screen)->display), lw->list.list[item], item_len);
1008
1009#ifndef OLDXAW
1010 lw->list.selected = item;
1011#endif
1012 /*
1013 * Call Callback function
1014 */
1015 ret_value.string = lw->list.list[item];
1016 ret_value.list_index = item;
1017
1018 XtCallCallbacks(w, XtNcallback((char*)&XtStrings[136]), (XtPointer)&ret_value);
1019}
1020
1021/* Unset() - Action
1022 *
1023 * unhighlights the current element */
1024/*ARGSUSED*/
1025static void
1026Unset(Widget w, XEvent *event, String *params, Cardinal *num_params)
1027{
1028 XawListUnhighlight(w);
1029}
1030
1031/* Set() - Action
1032 *
1033 * Highlights the current element */
1034/*ARGSUSED*/
1035static void
1036Set(Widget w, XEvent *event, String *params, Cardinal *num_params)
1037{
1038 int item;
1039 ListWidget lw = (ListWidget)w;
1040
1041#ifndef OLDXAW
1042 lw->list.selected = lw->list.highlight;
1043#endif
1044 if (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE-1)
1045 XawListUnhighlight(w); /* Unhighlight current item */
1046 else if (lw->list.is_highlighted != item) /* If this item is not */
1047 XawListHighlight(w, item); /* highlighted then do it */
1048}
1049
1050/*
1051 * Set specified arguments into widget
1052 */
1053/*ARGSUSED*/
1054static Boolean
1055XawListSetValues(Widget current, Widget request, Widget cnew,
1056 ArgList args, Cardinal *num_args)
1057{
1058 ListWidget cl = (ListWidget)current;
1059 ListWidget rl = (ListWidget)request;
1060 ListWidget nl = (ListWidget)cnew;
1061 Boolint redraw = False0;
1062 XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset);
1063
1064 /* If the request height/width is different, lock it. Unless its 0. If
1065 neither new nor 0, leave it as it was. Not in R5 */
1066 if (XtWidth(nl)(((RectObj)nl)->rectangle.width) != XtWidth(cl)(((RectObj)cl)->rectangle.width))
1067 nl->list.freedoms |= WidthLock2;
1068 if (XtWidth(nl)(((RectObj)nl)->rectangle.width) == 0)
1069 nl->list.freedoms &= ~WidthLock2;
1070
1071 if (XtHeight(nl)(((RectObj)nl)->rectangle.height) != XtHeight(cl)(((RectObj)cl)->rectangle.height))
1072 nl->list.freedoms |= HeightLock1;
1073 if (XtHeight(nl)(((RectObj)nl)->rectangle.height) == 0)
1074 nl->list.freedoms &= ~HeightLock1;
1075
1076 if (nl->list.longest != cl->list.longest)
1077 nl->list.freedoms |= LongestLock4;
1078 if (nl->list.longest == 0)
1079 nl->list.freedoms &= ~LongestLock4;
1080
1081 if (cl->list.foreground != nl->list.foreground ||
1082 cl->core.background_pixel != nl->core.background_pixel ||
1083 cl->list.font != nl->list.font) {
1084 XGCValues values;
1085
1086 XGetGCValues(XtDisplay(current)(((current)->core.screen)->display), cl->list.graygc, GCTile(1L<<10), &values);
1087 XmuReleaseStippledPixmap(XtScreen(current)((current)->core.screen), values.tile);
1088 XtReleaseGC(current, cl->list.graygc);
1089 XtReleaseGC(current, cl->list.revgc);
1090 XtReleaseGC(current, cl->list.normgc);
1091 GetGCs(cnew);
1092 redraw = True1;
1093 }
1094
1095 if (cl->list.font != nl->list.font && cl->simple.international == False0)
1096 nl->list.row_height = nl->list.font->max_bounds.ascent
1097 + nl->list.font->max_bounds.descent
1098 + nl->list.row_space;
1099 else if (cl->list.fontset != nl->list.fontset
1100 && cl->simple.international == True1)
1101 nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space;
1102
1103 /* ...If the above two font(set) change checkers above both failed, check
1104 if row_space was altered. If one of the above passed, row_height will
1105 already have been re-calculated */
1106 else if (cl->list.row_space != nl->list.row_space) {
1107 if (cl->simple.international == True1)
1108 nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space;
1109 else
1110 nl->list.row_height = nl->list.font->max_bounds.ascent
1111 + nl->list.font->max_bounds.descent
1112 + nl->list.row_space;
1113 }
1114
1115 if (XtWidth(cl)(((RectObj)cl)->rectangle.width) != XtWidth(nl)(((RectObj)nl)->rectangle.width) || XtHeight(cl)(((RectObj)cl)->rectangle.height) != XtHeight(nl)(((RectObj)nl)->rectangle.height)
1116 || cl->list.internal_width != nl->list.internal_width
1117 || cl->list.internal_height != nl->list.internal_height
1118 || cl->list.column_space != nl->list.column_space
1119 || cl->list.row_space != nl->list.row_space
1120 || cl->list.default_cols != nl->list.default_cols
1121 || (cl->list.force_cols != nl->list.force_cols
1122 && rl->list.force_cols != nl->list.ncols)
1123 || cl->list.vertical_cols != nl->list.vertical_cols
1124 || cl->list.longest != nl->list.longest
1125 || cl->list.nitems != nl->list.nitems
1126 || cl->list.font != nl->list.font
1127 /* Equiv. fontsets might have different values, but the same fonts,
1128 so the next comparison is sloppy but not dangerous */
1129 || cl->list.fontset != nl->list.fontset
1130 || cl->list.list != nl->list.list) {
1131 CalculatedValues(cnew);
1132 Layout(cnew, WidthFree(nl)!(((ListWidget)(nl))->list.freedoms & 2), HeightFree(nl)!(((ListWidget)(nl))->list.freedoms & 1),
1133 &nl->core.width, &nl->core.height);
1134 redraw = True1;
1135 }
1136
1137 if (cl->list.list != nl->list.list || cl->list.nitems != nl->list.nitems)
1138 nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT-1;
1139
1140 if (cl->core.sensitive != nl->core.sensitive
1141 || cl->core.ancestor_sensitive != nl->core.ancestor_sensitive) {
1142 nl->list.highlight = NO_HIGHLIGHT-1;
1143 redraw = True1;
1144 }
1145
1146 return (redraw);
1147}
1148
1149static void
1150XawListDestroy(Widget w)
1151{
1152 ListWidget lw = (ListWidget)w;
1153 XGCValues values;
1154
1155 XGetGCValues(XtDisplay(w)(((w)->core.screen)->display), lw->list.graygc, GCTile(1L<<10), &values);
1156 XmuReleaseStippledPixmap(XtScreen(w)((w)->core.screen), values.tile);
1157 XtReleaseGC(w, lw->list.graygc);
1158 XtReleaseGC(w, lw->list.revgc);
1159 XtReleaseGC(w, lw->list.normgc);
1160}
1161
1162/*
1163 * Function:
1164 * XawListChange
1165 *
1166 * Parameters:
1167 * w - list widget
1168 * list - new list
1169 * nitems - number of items in the list
1170 * longest - length (in Pixels) of the longest element in the list
1171 * resize - if True the the list widget will try to resize itself
1172 *
1173 * Description:
1174 * Changes the list being used and shown.
1175 *
1176 * Note:
1177 * If nitems of longest are <= 0 then they will be calculated
1178 * If nitems is <= 0 then the list needs to be NULL terminated
1179 */
1180void
1181XawListChange(Widget w, char **list, int nitems, int longest,
1182#if NeedWidePrototypes1
1183 int resize_it
1184#else
1185 Boolean resize_it
1186#endif
1187)
1188{
1189 ListWidget lw = (ListWidget)w;
1190 Dimension new_width = XtWidth(w)(((RectObj)w)->rectangle.width);
1191 Dimension new_height = XtHeight(w)(((RectObj)w)->rectangle.height);
1192
1193 lw->list.list = list;
1194
1195 if (nitems <= 0)
1196 nitems = 0;
1197 lw->list.nitems = nitems;
1198 if (longest <= 0)
1199 longest = 0;
1200
1201 /* If the user passes 0 meaning "calculate it", it must be free */
1202 if (longest != 0)
1203 lw->list.freedoms |= LongestLock4;
1204 else
1205 lw->list.freedoms &= ~LongestLock4;
1206
1207 if (resize_it)
1208 lw->list.freedoms &= ~WidthLock2 & ~HeightLock1;
1209
1210 lw->list.longest = longest;
1211
1212 CalculatedValues(w);
1213
1214 if (Layout(w, WidthFree(w)!(((ListWidget)(w))->list.freedoms & 2), HeightFree(w)!(((ListWidget)(w))->list.freedoms & 1), &new_width, &new_height))
1215 ChangeSize(w, new_width, new_height);
1216
1217 lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT-1;
1218 if (XtIsRealized(w)(XtWindowOfObject(w) != 0L))
1219 XawListRedisplay(w, NULL((void*)0), NULL((void*)0));
1220}
1221
1222void
1223XawListUnhighlight(Widget w)
1224{
1225 ListWidget lw = (ListWidget)w;
1226
1227 lw->list.highlight = NO_HIGHLIGHT-1;
1228 if (lw->list.is_highlighted != NO_HIGHLIGHT-1)
1229 PaintItemName(w, lw->list.is_highlighted);
1230}
1231
1232void
1233XawListHighlight(Widget w, int item)
1234{
1235 ListWidget lw = (ListWidget)w;
1236
1237 if (XtIsSensitive(w)) {
1238 lw->list.highlight = item;
1239 if (lw->list.is_highlighted != NO_HIGHLIGHT-1)
1240 PaintItemName(w, lw->list.is_highlighted);
1241 PaintItemName(w, item);
1242 }
1243}
1244
1245/*
1246 * Function:
1247 * XawListShowCurrent
1248 *
1249 * Parameters:
1250 * w - list widget
1251 *
1252 * Returns:
1253 * Info about the currently highlighted object
1254 */
1255XawListReturnStruct *
1256XawListShowCurrent(Widget w)
1257{
1258 ListWidget lw = (ListWidget)w;
1259 XawListReturnStruct *ret_val;
1260
1261 ret_val = (XawListReturnStruct *)XtMalloc(sizeof(XawListReturnStruct));
1262
1263 ret_val->list_index = lw->list.highlight;
1264 if (ret_val->list_index == XAW_LIST_NONE-1)
1265 ret_val->string = "";
1266 else
1267 ret_val->string = lw->list.list[ret_val->list_index];
1268
1269 return (ret_val);
1270}