2 Copyright 1989, 1994, 1998 The Open Group
4 Permission to use, copy, modify, distribute, and sell this software and its
5 documentation for any purpose is hereby granted without fee, provided that
6 the above copyright notice appear in all copies and that both that
7 copyright notice and this permission notice appear in supporting
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 Except as contained in this notice, the name of The Open Group shall not be
21 used in advertising or otherwise to promote the sale, use or other dealings
22 in this Software without prior written authorization from The Open Group.
26 * List.c - List widget
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.
32 * By: Chris D. Peterson
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>
52 #define HeightFree(w) !(((ListWidget)(w))->list.freedoms & HeightLock)
53 #define WidthFree(w) !(((ListWidget)(w))->list.freedoms & WidthLock)
54 #define LongestFree(w) !(((ListWidget)(w))->list.freedoms & LongestLock)
61 static void XawListDestroy(Widget);
62 static void XawListInitialize(Widget, Widget, ArgList, Cardinal*);
63 static XtGeometryResult XawListQueryGeometry(Widget, XtWidgetGeometry*,
65 static void XawListRedisplay(Widget, XEvent*, Region);
66 static void XawListResize(Widget);
67 static Boolean XawListSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
72 static void CalculatedValues(Widget);
73 static void ChangeSize(Widget, unsigned int, unsigned int);
74 static void ClipToShadowInteriorAndLongest(ListWidget, GC*, unsigned int);
75 static int CvtToItem(Widget, int, int, int*);
76 static void FindCornerItems(Widget, XEvent*, int*, int*);
77 static void GetGCs(Widget);
78 static void HighlightBackground(Widget, int, int, GC);
79 static Bool ItemInRectangle(Widget, int, int, int);
80 static Bool Layout(Widget, Bool, Bool, Dimension*, Dimension*);
81 static void PaintItemName(Widget, int);
82 static void ResetList(Widget, Bool, Bool);
87 static void Notify(Widget, XEvent*, String*, Cardinal*);
88 static void Set(Widget, XEvent*, String*, Cardinal*);
89 static void Unset(Widget, XEvent*, String*, Cardinal*);
94 static char defaultTranslations[] =
95 "<Btn1Down>:" "Set()\n"
96 "<Btn1Up>:" "Notify()\n"
99 #define offset(field) XtOffsetOf(ListRec, field)
100 static XtResource resources[] = {
106 offset(list.foreground),
115 offset(simple.cursor),
123 sizeof(XFontStruct*),
133 offset(list.fontset),
155 offset(list.default_cols),
164 offset(list.longest),
191 offset(list.force_cols),
200 offset(list.vertical_cols),
209 offset(list.internal_width),
218 offset(list.internal_height),
227 offset(list.column_space),
236 offset(list.row_space),
245 offset(list.callback),
255 offset(list.show_current),
263 static XtActionsRec actions[] = {
269 #define Superclass (&simpleClassRec)
270 ListClassRec listClassRec = {
273 (WidgetClass)Superclass, /* superclass */
274 "List", /* class_name */
275 sizeof(ListRec), /* widget_size */
276 XawInitializeWidgetSet, /* class_initialize */
277 NULL, /* class_part_initialize */
278 False, /* class_inited */
279 XawListInitialize, /* initialize */
280 NULL, /* initialize_hook */
281 XtInheritRealize, /* realize */
282 actions, /* actions */
283 XtNumber(actions), /* num_actions */
284 resources, /* resources */
285 XtNumber(resources), /* num_resources */
286 NULLQUARK, /* xrm_class */
287 True, /* compress_motion */
288 False, /* compress_exposure */
289 True, /* compress_enterleave */
290 False, /* visible_interest */
291 XawListDestroy, /* destroy */
292 XawListResize, /* resize */
293 XawListRedisplay, /* expose */
294 XawListSetValues, /* set_values */
295 NULL, /* set_values_hook */
296 XtInheritSetValuesAlmost, /* set_values_almost */
297 NULL, /* get_values_hook */
298 NULL, /* accept_focus */
299 XtVersion, /* version */
300 NULL, /* callback_private */
301 defaultTranslations, /* tm_table */
302 XawListQueryGeometry, /* query_geometry */
306 XtInheritChangeSensitive, /* change_sensitive */
310 NULL, /* extension */
314 WidgetClass listWidgetClass = (WidgetClass)&listClassRec;
323 ListWidget lw = (ListWidget)w;
325 values.foreground = lw->list.foreground;
326 values.font = lw->list.font->fid;
328 if (lw->simple.international == True)
329 lw->list.normgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0);
331 lw->list.normgc = XtGetGC(w, GCForeground | GCFont, &values);
333 values.foreground = lw->core.background_pixel;
335 if (lw->simple.international == True)
336 lw->list.revgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0);
338 lw->list.revgc = XtGetGC(w, GCForeground | GCFont, &values);
340 values.tile = XmuCreateStippledPixmap(XtScreen(w),
342 lw->core.background_pixel,
344 values.fill_style = FillTiled;
346 if (lw->simple.international == True)
347 lw->list.graygc = XtAllocateGC(w, 0, GCTile | GCFillStyle,
350 lw->list.graygc = XtGetGC(w, GCFont | GCTile | GCFillStyle, &values);
354 CalculatedValues(Widget w)
357 ListWidget lw = (ListWidget)w;
359 /* If list is NULL then the list will just be the name of the widget */
360 if (lw->list.list == NULL) {
361 lw->list.list = &lw->core.name;
365 /* Get number of items */
366 if (lw->list.nitems == 0)
367 for (; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++)
370 /* Get column width */
371 if (LongestFree(lw)) {
372 lw->list.longest = 0; /* so it will accumulate real longest below */
374 for (i = 0 ; i < lw->list.nitems; i++) {
375 if (lw->simple.international == True)
376 len = XmbTextEscapement(lw->list.fontset, lw->list.list[i],
377 strlen(lw->list.list[i]));
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;
386 lw->list.col_width = lw->list.longest + lw->list.column_space;
395 * changex - allow the height or width to change?
399 * Resets the new list when important things change.
402 * True if width or height have been changed
405 ResetList(Widget w, Bool changex, Bool changey)
407 Dimension width = XtWidth(w);
408 Dimension height = XtHeight(w);
412 if (Layout(w, changex, changey, &width, &height)) {
413 if (XtIsComposite(XtParent(w)))
414 ChangeSize(w, width, height);
417 XtHeight(w) = height;
427 * w - widget to try change the size of
430 * Laysout the widget.
433 ChangeSize(Widget w, unsigned int width, unsigned int height)
435 XtWidgetGeometry request, reply;
437 request.request_mode = CWWidth | CWHeight;
438 request.width = width;
439 request.height = height;
441 switch (XtMakeGeometryRequest(w, &request, &reply)) {
445 case XtGeometryAlmost:
446 Layout(w, request.height != reply.height,
447 request.width != reply.width, &reply.width, &reply.height);
449 switch (XtMakeGeometryRequest(w, &request, &reply)) {
453 case XtGeometryAlmost:
455 Layout(w, False, False, &request.width, &request.height);
456 request.request_mode = CWWidth | CWHeight;
457 XtMakeGeometryRequest(w, &request, &reply);
470 XawListInitialize(Widget temp1, Widget cnew, ArgList args, Cardinal *num_args)
472 ListWidget lw = (ListWidget)cnew;
474 if (!lw->list.font) XtError("Aborting: no font found\n");
475 if (lw->simple.international && !lw->list.fontset)
476 XtError("Aborting: no fontset found\n");
479 * Initialize all private resources
481 /* record for posterity if we are free */
482 lw->list.freedoms = ((XtWidth(lw) != 0) * WidthLock +
483 (XtHeight(lw) != 0) * HeightLock +
484 (lw->list.longest != 0) * LongestLock);
488 /* Set row height, based on font or fontset */
489 if (lw->simple.international == True)
490 lw->list.row_height =
491 XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height +
494 lw->list.row_height = lw->list.font->max_bounds.ascent +
495 lw->list.font->max_bounds.descent +
498 ResetList(cnew, WidthFree(lw), HeightFree(lw));
500 lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT;
513 * Converts Xcoord to item number of item containing that point.
519 CvtToItem(Widget w, int xloc, int yloc, int *item)
522 ListWidget lw = (ListWidget)w;
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;
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;
545 if (xloc < 0 || yloc < 0)
546 ret_val = OUT_OF_RANGE;
551 *item = one + another;
552 if (*item >= lw->list.nitems)
553 return (OUT_OF_RANGE);
564 * event - event structure that has the rectangle it it
565 * ul_ret - the corners (return)
569 * Find the corners of the rectangle in item space.
572 FindCornerItems(Widget w, XEvent *event, int *ul_ret, int *lr_ret)
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);
590 * ul - corners of the rectangle in item space
592 * item - item to check
595 * True if the item passed is in the given rectangle
598 ItemInRectangle(Widget w, int ul, int lr, int item)
600 ListWidget lw = (ListWidget)w;
604 if (item < ul || item > lr)
606 if (lw->list.vertical_cols)
607 things = lw->list.nrows;
609 things = lw->list.ncols;
611 mod_item = item % things;
612 if ((mod_item >= ul % things) && (mod_item <= lr % things))
618 /* HighlightBackground()
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.
624 * x, y - ul corner of the area item occupies.
625 * gc - the gc to use to paint this rectangle
628 HighlightBackground(Widget w, int x, int y, GC gc)
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) - lw->list.internal_width - x;
634 Dimension frame_limited_height= XtHeight(w) - lw->list.internal_height - y;
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;
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;
647 if (y < lw->list.internal_height) {
648 height = height - (lw->list.internal_height - y);
649 y = lw->list.internal_height;
652 if (gc == lw->list.revgc && lw->core.background_pixmap != XtUnspecifiedPixmap)
653 XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False);
655 XFillRectangle(XtDisplay(w), XtWindow(w), gc, x, y, width, height);
659 /* ClipToShadowInteriorAndLongest()
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.
669 ClipToShadowInteriorAndLongest(ListWidget lw, GC *gc_p, unsigned int x)
674 rect.y = lw->list.internal_height;
675 rect.height = XtHeight(lw) - (lw->list.internal_height << 1);
676 rect.width = XtWidth(lw) - lw->list.internal_width - x;
677 if (rect.width > lw->list.longest)
678 rect.width = lw->list.longest;
680 XSetClipRectangles(XtDisplay((Widget)lw), *gc_p, 0, 0, &rect, 1, YXBanded);
684 PaintItemName(Widget w, int item)
689 ListWidget lw = (ListWidget)w;
690 XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset);
692 if (!XtIsRealized(w) || item > lw->list.nitems)
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;
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;
708 if ( lw->simple.international == True )
709 str_y = y + XawAbs(ext->max_ink_extent.y);
711 str_y = y + lw->list.font->max_bounds.ascent;
713 if (item == lw->list.is_highlighted) {
714 if (item == lw->list.highlight) {
716 HighlightBackground(w, x, y, lw->list.normgc);
719 if (XtIsSensitive(w))
720 gc = lw->list.normgc;
722 gc = lw->list.graygc;
723 HighlightBackground(w, x, y, lw->list.revgc);
724 lw->list.is_highlighted = NO_HIGHLIGHT;
728 if (item == lw->list.highlight) {
730 HighlightBackground(w, x, y, lw->list.normgc);
731 lw->list.is_highlighted = item;
734 if (XtIsSensitive(w))
735 gc = lw->list.normgc;
737 gc = lw->list.graygc;
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 */
746 x += lw->list.column_space >> 1;
747 str_y += lw->list.row_space >> 1;
749 str = lw->list.list[item]; /* draw it */
751 ClipToShadowInteriorAndLongest(lw, &gc, x);
753 if (lw->simple.international == True)
754 XmbDrawString(XtDisplay(w), XtWindow(w), lw->list.fontset,
755 gc, x, str_y, str, strlen(str));
757 XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, strlen(str));
759 XSetClipMask(XtDisplay(w), gc, None);
763 XawListRedisplay(Widget w, XEvent *event, Region region)
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;
771 lr_item = lw->list.nrows * lw->list.ncols - 1;
772 XClearWindow(XtDisplay(w), XtWindow(w));
775 FindCornerItems(w, event, &ul_item, &lr_item);
777 if (Superclass->core_class.expose)
778 (Superclass->core_class.expose)(w, event, region);
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);
785 /* XawListQueryGeometry()
787 * This tells the parent what size we would like to be
788 * given certain constraints.
790 * intended - what the parent intends to do with us.
791 * requested - what we want to happen */
792 static XtGeometryResult
793 XawListQueryGeometry(Widget w, XtWidgetGeometry *intended,
794 XtWidgetGeometry *requested)
796 Dimension new_width, new_height;
797 Bool change, width_req, height_req;
799 width_req = intended->request_mode & CWWidth;
800 height_req = intended->request_mode & CWHeight;
803 new_width = intended->width;
805 new_width = XtWidth(w);
808 new_height = intended->height;
810 new_height = XtHeight(w);
812 requested->request_mode = 0;
815 * We only care about our height and width
817 if (!width_req && !height_req)
818 return (XtGeometryYes);
820 change = Layout(w, !width_req, !height_req, &new_width, &new_height);
822 requested->request_mode |= CWWidth;
823 requested->width = new_width;
824 requested->request_mode |= CWHeight;
825 requested->height = new_height;
828 return (XtGeometryAlmost);
830 return (XtGeometryYes);
834 XawListResize(Widget w)
836 Dimension width, height;
839 height = XtHeight(w);
841 if (Layout(w, False, False, &width, &height))
842 XtAppWarning(XtWidgetToApplicationContext(w),
843 "List Widget: Size changed when it shouldn't "
844 "have when resising.");
849 * lays out the item in the list.
851 * xfree, yfree - True if we are free to resize the widget in
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.
858 * True if width or height have been changed */
860 Layout(Widget w, Bool xfree, Bool yfree, Dimension *width, Dimension *height)
862 ListWidget lw = (ListWidget)w;
864 unsigned long width2 = 0, height2 = 0;
867 * If force columns is set then always use number of columns specified
870 if (lw->list.force_cols) {
871 lw->list.ncols = lw->list.default_cols;
872 if (lw->list.ncols <= 0)
874 lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
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);
884 height2 = lw->list.nrows * lw->list.row_height +
885 (lw->list.internal_height << 1);
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
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) - (int)(lw->list.internal_width << 1)
899 + (int)lw->list.column_space;
901 if (wid <= 0 || lw->list.col_width <= 0
902 || (lw->list.ncols = wid / lw->list.col_width) <= 0)
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);
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
918 lw->list.ncols = ((int)(*width - (lw->list.internal_width << 1))
919 / (int)lw->list.col_width);
920 if (lw->list.ncols <= 0)
922 lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1;
924 height2 = lw->list.nrows * lw->list.row_height +
925 (lw->list.internal_height << 1);
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
936 lw->list.nrows = ((int)(*height - (lw->list.internal_height << 1))
937 / (int)lw->list.row_height);
938 if (lw->list.nrows <= 0)
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);
946 if (!lw->list.force_cols && lw->list.nrows) {
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 >= MaxSize && height2 >= MaxSize)
956 if (height2 > MaxSize)
958 else if (width2 > MaxSize && lw->list.ncols > 1)
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 */
979 Notify(Widget w, XEvent *event, String *params, Cardinal *num_params)
981 ListWidget lw = (ListWidget)w;
983 XawListReturnStruct ret_value;
986 * Find item and if out of range then unhighlight and return
988 * If the current item is unhighlighted then the user has aborted the
989 * notify, so unhighlight and return
991 if ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE)
992 || lw->list.highlight != item) {
994 if (!lw->list.show_current || lw->list.selected == NO_HIGHLIGHT)
995 XawListUnhighlight(w);
997 XawListHighlight(w, lw->list.selected);
999 XawListUnhighlight(w);
1004 item_len = strlen(lw->list.list[item]);
1006 if (lw->list.paste) /* if XtNpasteBuffer set then paste it */
1007 XStoreBytes(XtDisplay(w), lw->list.list[item], item_len);
1010 lw->list.selected = item;
1013 * Call Callback function
1015 ret_value.string = lw->list.list[item];
1016 ret_value.list_index = item;
1018 XtCallCallbacks(w, XtNcallback, (XtPointer)&ret_value);
1023 * unhighlights the current element */
1026 Unset(Widget w, XEvent *event, String *params, Cardinal *num_params)
1028 XawListUnhighlight(w);
1033 * Highlights the current element */
1036 Set(Widget w, XEvent *event, String *params, Cardinal *num_params)
1039 ListWidget lw = (ListWidget)w;
1042 lw->list.selected = lw->list.highlight;
1044 if (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE)
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 */
1051 * Set specified arguments into widget
1055 XawListSetValues(Widget current, Widget request, Widget cnew,
1056 ArgList args, Cardinal *num_args)
1058 ListWidget cl = (ListWidget)current;
1059 ListWidget rl = (ListWidget)request;
1060 ListWidget nl = (ListWidget)cnew;
1061 Bool redraw = False;
1062 XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset);
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) != XtWidth(cl))
1067 nl->list.freedoms |= WidthLock;
1068 if (XtWidth(nl) == 0)
1069 nl->list.freedoms &= ~WidthLock;
1071 if (XtHeight(nl) != XtHeight(cl))
1072 nl->list.freedoms |= HeightLock;
1073 if (XtHeight(nl) == 0)
1074 nl->list.freedoms &= ~HeightLock;
1076 if (nl->list.longest != cl->list.longest)
1077 nl->list.freedoms |= LongestLock;
1078 if (nl->list.longest == 0)
1079 nl->list.freedoms &= ~LongestLock;
1081 if (cl->list.foreground != nl->list.foreground ||
1082 cl->core.background_pixel != nl->core.background_pixel ||
1083 cl->list.font != nl->list.font) {
1086 XGetGCValues(XtDisplay(current), cl->list.graygc, GCTile, &values);
1087 XmuReleaseStippledPixmap(XtScreen(current), values.tile);
1088 XtReleaseGC(current, cl->list.graygc);
1089 XtReleaseGC(current, cl->list.revgc);
1090 XtReleaseGC(current, cl->list.normgc);
1095 if (cl->list.font != nl->list.font && cl->simple.international == False)
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 == True)
1101 nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space;
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 == True)
1108 nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space;
1110 nl->list.row_height = nl->list.font->max_bounds.ascent
1111 + nl->list.font->max_bounds.descent
1112 + nl->list.row_space;
1115 if (XtWidth(cl) != XtWidth(nl) || XtHeight(cl) != XtHeight(nl)
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), HeightFree(nl),
1133 &nl->core.width, &nl->core.height);
1137 if (cl->list.list != nl->list.list || cl->list.nitems != nl->list.nitems)
1138 nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT;
1140 if (cl->core.sensitive != nl->core.sensitive
1141 || cl->core.ancestor_sensitive != nl->core.ancestor_sensitive) {
1142 nl->list.highlight = NO_HIGHLIGHT;
1150 XawListDestroy(Widget w)
1152 ListWidget lw = (ListWidget)w;
1155 XGetGCValues(XtDisplay(w), lw->list.graygc, GCTile, &values);
1156 XmuReleaseStippledPixmap(XtScreen(w), values.tile);
1157 XtReleaseGC(w, lw->list.graygc);
1158 XtReleaseGC(w, lw->list.revgc);
1159 XtReleaseGC(w, lw->list.normgc);
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
1174 * Changes the list being used and shown.
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
1181 XawListChange(Widget w, char **list, int nitems, int longest,
1182 #if NeedWidePrototypes
1189 ListWidget lw = (ListWidget)w;
1190 Dimension new_width = XtWidth(w);
1191 Dimension new_height = XtHeight(w);
1193 lw->list.list = list;
1197 lw->list.nitems = nitems;
1201 /* If the user passes 0 meaning "calculate it", it must be free */
1203 lw->list.freedoms |= LongestLock;
1205 lw->list.freedoms &= ~LongestLock;
1208 lw->list.freedoms &= ~WidthLock & ~HeightLock;
1210 lw->list.longest = longest;
1212 CalculatedValues(w);
1214 if (Layout(w, WidthFree(w), HeightFree(w), &new_width, &new_height))
1215 ChangeSize(w, new_width, new_height);
1217 lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT;
1218 if (XtIsRealized(w))
1219 XawListRedisplay(w, NULL, NULL);
1223 XawListUnhighlight(Widget w)
1225 ListWidget lw = (ListWidget)w;
1227 lw->list.highlight = NO_HIGHLIGHT;
1228 if (lw->list.is_highlighted != NO_HIGHLIGHT)
1229 PaintItemName(w, lw->list.is_highlighted);
1233 XawListHighlight(Widget w, int item)
1235 ListWidget lw = (ListWidget)w;
1237 if (XtIsSensitive(w)) {
1238 lw->list.highlight = item;
1239 if (lw->list.is_highlighted != NO_HIGHLIGHT)
1240 PaintItemName(w, lw->list.is_highlighted);
1241 PaintItemName(w, item);
1247 * XawListShowCurrent
1253 * Info about the currently highlighted object
1255 XawListReturnStruct *
1256 XawListShowCurrent(Widget w)
1258 ListWidget lw = (ListWidget)w;
1259 XawListReturnStruct *ret_val;
1261 ret_val = (XawListReturnStruct *)XtMalloc(sizeof(XawListReturnStruct));
1263 ret_val->list_index = lw->list.highlight;
1264 if (ret_val->list_index == XAW_LIST_NONE)
1265 ret_val->string = "";
1267 ret_val->string = lw->list.list[ret_val->list_index];