List.c revision 5b16253f
17a84e134Smrg/* 27a84e134SmrgCopyright 1989, 1994, 1998 The Open Group 37a84e134Smrg 47a84e134SmrgPermission to use, copy, modify, distribute, and sell this software and its 57a84e134Smrgdocumentation for any purpose is hereby granted without fee, provided that 67a84e134Smrgthe above copyright notice appear in all copies and that both that 77a84e134Smrgcopyright notice and this permission notice appear in supporting 87a84e134Smrgdocumentation. 97a84e134Smrg 107a84e134SmrgThe above copyright notice and this permission notice shall be included in 117a84e134Smrgall copies or substantial portions of the Software. 127a84e134Smrg 137a84e134SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 147a84e134SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 157a84e134SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 167a84e134SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 177a84e134SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 187a84e134SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 197a84e134Smrg 207a84e134SmrgExcept as contained in this notice, the name of The Open Group shall not be 217a84e134Smrgused in advertising or otherwise to promote the sale, use or other dealings 227a84e134Smrgin this Software without prior written authorization from The Open Group. 237a84e134Smrg*/ 247a84e134Smrg 257a84e134Smrg/* 267a84e134Smrg * List.c - List widget 277a84e134Smrg * 287a84e134Smrg * This is a List widget. It allows the user to select an item in a list and 297a84e134Smrg * notifies the application through a callback function. 307a84e134Smrg * 31421c997bSmrg * Created: 8/13/88 327a84e134Smrg * By: Chris D. Peterson 337a84e134Smrg * MIT X Consortium 347a84e134Smrg */ 357a84e134Smrg 367a84e134Smrg#ifdef HAVE_CONFIG_H 377a84e134Smrg#include <config.h> 387a84e134Smrg#endif 397a84e134Smrg#include <stdio.h> 407a84e134Smrg#include <ctype.h> 417a84e134Smrg#include <X11/IntrinsicP.h> 427a84e134Smrg#include <X11/StringDefs.h> 437a84e134Smrg#include <X11/Xmu/Drawing.h> 447a84e134Smrg#include <X11/Xaw/ListP.h> 457a84e134Smrg#include <X11/Xaw/XawInit.h> 467a84e134Smrg#include "Private.h" 477a84e134Smrg 487a84e134Smrg#define HeightLock 1 497a84e134Smrg#define WidthLock 2 507a84e134Smrg#define LongestLock 4 517a84e134Smrg 527a84e134Smrg#define HeightFree(w) !(((ListWidget)(w))->list.freedoms & HeightLock) 537a84e134Smrg#define WidthFree(w) !(((ListWidget)(w))->list.freedoms & WidthLock) 547a84e134Smrg#define LongestFree(w) !(((ListWidget)(w))->list.freedoms & LongestLock) 557a84e134Smrg 567a84e134Smrg#define MaxSize 32767 577a84e134Smrg 587a84e134Smrg/* 597a84e134Smrg * Class Methods 607a84e134Smrg */ 617a84e134Smrgstatic void XawListDestroy(Widget); 627a84e134Smrgstatic void XawListInitialize(Widget, Widget, ArgList, Cardinal*); 637a84e134Smrgstatic XtGeometryResult XawListQueryGeometry(Widget, XtWidgetGeometry*, 647a84e134Smrg XtWidgetGeometry*); 657a84e134Smrgstatic void XawListRedisplay(Widget, XEvent*, Region); 667a84e134Smrgstatic void XawListResize(Widget); 677a84e134Smrgstatic Boolean XawListSetValues(Widget, Widget, Widget, ArgList, Cardinal*); 687a84e134Smrg 697a84e134Smrg/* 707a84e134Smrg * Prototypes 717a84e134Smrg */ 727a84e134Smrgstatic void CalculatedValues(Widget); 737a84e134Smrgstatic void ChangeSize(Widget, unsigned int, unsigned int); 747a84e134Smrgstatic void ClipToShadowInteriorAndLongest(ListWidget, GC*, unsigned int); 757a84e134Smrgstatic int CvtToItem(Widget, int, int, int*); 767a84e134Smrgstatic void FindCornerItems(Widget, XEvent*, int*, int*); 777a84e134Smrgstatic void GetGCs(Widget); 787a84e134Smrgstatic void HighlightBackground(Widget, int, int, GC); 797a84e134Smrgstatic Bool ItemInRectangle(Widget, int, int, int); 807a84e134Smrgstatic Bool Layout(Widget, Bool, Bool, Dimension*, Dimension*); 817a84e134Smrgstatic void PaintItemName(Widget, int); 827a84e134Smrgstatic void ResetList(Widget, Bool, Bool); 837a84e134Smrg 84421c997bSmrg/* 857a84e134Smrg * Actions 867a84e134Smrg */ 877a84e134Smrgstatic void Notify(Widget, XEvent*, String*, Cardinal*); 887a84e134Smrgstatic void Set(Widget, XEvent*, String*, Cardinal*); 897a84e134Smrgstatic void Unset(Widget, XEvent*, String*, Cardinal*); 907a84e134Smrg 917a84e134Smrg/* 927a84e134Smrg * Initialization 937a84e134Smrg */ 94421c997bSmrgstatic char defaultTranslations[] = 957a84e134Smrg"<Btn1Down>:" "Set()\n" 967a84e134Smrg"<Btn1Up>:" "Notify()\n" 977a84e134Smrg; 987a84e134Smrg 997a84e134Smrg#define offset(field) XtOffsetOf(ListRec, field) 1007a84e134Smrgstatic XtResource resources[] = { 1017a84e134Smrg { 1027a84e134Smrg XtNforeground, 1037a84e134Smrg XtCForeground, 1047a84e134Smrg XtRPixel, 1057a84e134Smrg sizeof(Pixel), 1067a84e134Smrg offset(list.foreground), 1077a84e134Smrg XtRString, 1085ec34c4cSmrg (XtPointer)XtDefaultForeground 1097a84e134Smrg }, 1107a84e134Smrg { 1117a84e134Smrg XtNcursor, 1127a84e134Smrg XtCCursor, 1137a84e134Smrg XtRCursor, 1147a84e134Smrg sizeof(Cursor), 1157a84e134Smrg offset(simple.cursor), 1167a84e134Smrg XtRString, 1175ec34c4cSmrg (XtPointer)"left_ptr" 1187a84e134Smrg }, 1197a84e134Smrg { 1207a84e134Smrg XtNfont, 1217a84e134Smrg XtCFont, 1227a84e134Smrg XtRFontStruct, 1237a84e134Smrg sizeof(XFontStruct*), 1247a84e134Smrg offset(list.font), 1257a84e134Smrg XtRString, 1265ec34c4cSmrg (XtPointer)XtDefaultFont 1277a84e134Smrg }, 1287a84e134Smrg { 1297a84e134Smrg XtNfontSet, 1307a84e134Smrg XtCFontSet, 1317a84e134Smrg XtRFontSet, 1327a84e134Smrg sizeof(XFontSet), 1337a84e134Smrg offset(list.fontset), 1347a84e134Smrg XtRString, 1355ec34c4cSmrg (XtPointer)XtDefaultFontSet 1367a84e134Smrg }, 1377a84e134Smrg { 1387a84e134Smrg XtNlist, 1397a84e134Smrg XtCList, 1407a84e134Smrg XtRPointer, 1417a84e134Smrg sizeof(char**), 1427a84e134Smrg offset(list.list), 1437a84e134Smrg#ifdef notyet 1447a84e134Smrg XtRStringArray, 1457a84e134Smrg#else 1467a84e134Smrg XtRString, 1477a84e134Smrg#endif 1487a84e134Smrg NULL 1497a84e134Smrg }, 1507a84e134Smrg { 1517a84e134Smrg XtNdefaultColumns, 1527a84e134Smrg XtCColumns, 1537a84e134Smrg XtRInt, 1547a84e134Smrg sizeof(int), 1557a84e134Smrg offset(list.default_cols), 1567a84e134Smrg XtRImmediate, 1577a84e134Smrg (XtPointer)2 1587a84e134Smrg }, 1597a84e134Smrg { 1607a84e134Smrg XtNlongest, 1617a84e134Smrg XtCLongest, 1627a84e134Smrg XtRInt, 1637a84e134Smrg sizeof(int), 1647a84e134Smrg offset(list.longest), 1657a84e134Smrg XtRImmediate, 1667a84e134Smrg (XtPointer)0 1677a84e134Smrg }, 1687a84e134Smrg { 1697a84e134Smrg XtNnumberStrings, 1707a84e134Smrg XtCNumberStrings, 1717a84e134Smrg XtRInt, 1727a84e134Smrg sizeof(int), 1737a84e134Smrg offset(list.nitems), 1747a84e134Smrg XtRImmediate, 1757a84e134Smrg (XtPointer)0 1767a84e134Smrg }, 1777a84e134Smrg { 1787a84e134Smrg XtNpasteBuffer, 1797a84e134Smrg XtCBoolean, 1807a84e134Smrg XtRBoolean, 1817a84e134Smrg sizeof(Boolean), 1827a84e134Smrg offset(list.paste), 1837a84e134Smrg XtRImmediate, 1847a84e134Smrg (XtPointer)False 1857a84e134Smrg }, 1867a84e134Smrg { 1877a84e134Smrg XtNforceColumns, 1887a84e134Smrg XtCColumns, 1897a84e134Smrg XtRBoolean, 1907a84e134Smrg sizeof(Boolean), 1917a84e134Smrg offset(list.force_cols), 1927a84e134Smrg XtRImmediate, 1937a84e134Smrg (XtPointer)False 1947a84e134Smrg }, 1957a84e134Smrg { 1967a84e134Smrg XtNverticalList, 1977a84e134Smrg XtCBoolean, 1987a84e134Smrg XtRBoolean, 1997a84e134Smrg sizeof(Boolean), 2007a84e134Smrg offset(list.vertical_cols), 2017a84e134Smrg XtRImmediate, 2027a84e134Smrg (XtPointer)False 2037a84e134Smrg }, 2047a84e134Smrg { 2057a84e134Smrg XtNinternalWidth, 2067a84e134Smrg XtCWidth, 2077a84e134Smrg XtRDimension, 2087a84e134Smrg sizeof(Dimension), 2097a84e134Smrg offset(list.internal_width), 2107a84e134Smrg XtRImmediate, 2117a84e134Smrg (XtPointer)2 2127a84e134Smrg }, 2137a84e134Smrg { 2147a84e134Smrg XtNinternalHeight, 2157a84e134Smrg XtCHeight, 2167a84e134Smrg XtRDimension, 2177a84e134Smrg sizeof(Dimension), 2187a84e134Smrg offset(list.internal_height), 2197a84e134Smrg XtRImmediate, 2207a84e134Smrg (XtPointer)2 2217a84e134Smrg }, 2227a84e134Smrg { 2237a84e134Smrg XtNcolumnSpacing, 2247a84e134Smrg XtCSpacing, 2257a84e134Smrg XtRDimension, 2267a84e134Smrg sizeof(Dimension), 2277a84e134Smrg offset(list.column_space), 2287a84e134Smrg XtRImmediate, 2297a84e134Smrg (XtPointer)6 2307a84e134Smrg }, 2317a84e134Smrg { 2327a84e134Smrg XtNrowSpacing, 2337a84e134Smrg XtCSpacing, 2347a84e134Smrg XtRDimension, 2357a84e134Smrg sizeof(Dimension), 2367a84e134Smrg offset(list.row_space), 2377a84e134Smrg XtRImmediate, 2387a84e134Smrg (XtPointer)2 2397a84e134Smrg }, 2407a84e134Smrg { 2417a84e134Smrg XtNcallback, 2427a84e134Smrg XtCCallback, 2437a84e134Smrg XtRCallback, 2447a84e134Smrg sizeof(XtPointer), 2457a84e134Smrg offset(list.callback), 2467a84e134Smrg XtRCallback, 2477a84e134Smrg NULL 2487a84e134Smrg }, 2497a84e134Smrg#ifndef OLDXAW 2507a84e134Smrg { 2517a84e134Smrg XtNshowCurrent, 2527a84e134Smrg XtCBoolean, 2537a84e134Smrg XtRBoolean, 2547a84e134Smrg sizeof(Boolean), 2557a84e134Smrg offset(list.show_current), 2567a84e134Smrg XtRImmediate, 2577a84e134Smrg (XtPointer)False 2587a84e134Smrg }, 2597a84e134Smrg#endif 2607a84e134Smrg}; 2617a84e134Smrg#undef offset 2627a84e134Smrg 2637a84e134Smrgstatic XtActionsRec actions[] = { 2647a84e134Smrg {"Notify", Notify}, 2657a84e134Smrg {"Set", Set}, 2667a84e134Smrg {"Unset", Unset}, 2677a84e134Smrg}; 2687a84e134Smrg 2697a84e134Smrg#define Superclass (&simpleClassRec) 2707a84e134SmrgListClassRec listClassRec = { 2717a84e134Smrg /* core */ 2727a84e134Smrg { 2737a84e134Smrg (WidgetClass)Superclass, /* superclass */ 2747a84e134Smrg "List", /* class_name */ 2757a84e134Smrg sizeof(ListRec), /* widget_size */ 2767a84e134Smrg XawInitializeWidgetSet, /* class_initialize */ 2777a84e134Smrg NULL, /* class_part_initialize */ 2787a84e134Smrg False, /* class_inited */ 2797a84e134Smrg XawListInitialize, /* initialize */ 2807a84e134Smrg NULL, /* initialize_hook */ 2817a84e134Smrg XtInheritRealize, /* realize */ 2827a84e134Smrg actions, /* actions */ 2837a84e134Smrg XtNumber(actions), /* num_actions */ 2847a84e134Smrg resources, /* resources */ 2857a84e134Smrg XtNumber(resources), /* num_resources */ 2867a84e134Smrg NULLQUARK, /* xrm_class */ 2877a84e134Smrg True, /* compress_motion */ 2887a84e134Smrg False, /* compress_exposure */ 2897a84e134Smrg True, /* compress_enterleave */ 2907a84e134Smrg False, /* visible_interest */ 2917a84e134Smrg XawListDestroy, /* destroy */ 2927a84e134Smrg XawListResize, /* resize */ 2937a84e134Smrg XawListRedisplay, /* expose */ 2947a84e134Smrg XawListSetValues, /* set_values */ 2957a84e134Smrg NULL, /* set_values_hook */ 2967a84e134Smrg XtInheritSetValuesAlmost, /* set_values_almost */ 2977a84e134Smrg NULL, /* get_values_hook */ 2987a84e134Smrg NULL, /* accept_focus */ 2997a84e134Smrg XtVersion, /* version */ 3007a84e134Smrg NULL, /* callback_private */ 3017a84e134Smrg defaultTranslations, /* tm_table */ 3027a84e134Smrg XawListQueryGeometry, /* query_geometry */ 3037a84e134Smrg }, 3047a84e134Smrg /* simple */ 3057a84e134Smrg { 3067a84e134Smrg XtInheritChangeSensitive, /* change_sensitive */ 3077a84e134Smrg }, 3087a84e134Smrg /* list */ 3097a84e134Smrg { 3107a84e134Smrg NULL, /* extension */ 3117a84e134Smrg }, 3127a84e134Smrg}; 3137a84e134Smrg 3147a84e134SmrgWidgetClass listWidgetClass = (WidgetClass)&listClassRec; 3157a84e134Smrg 3167a84e134Smrg/* 3177a84e134Smrg * Implementation 3187a84e134Smrg */ 3197a84e134Smrgstatic void 3207a84e134SmrgGetGCs(Widget w) 3217a84e134Smrg{ 3227a84e134Smrg XGCValues values; 3237a84e134Smrg ListWidget lw = (ListWidget)w; 3247a84e134Smrg 3257a84e134Smrg values.foreground = lw->list.foreground; 3267a84e134Smrg values.font = lw->list.font->fid; 3277a84e134Smrg 3287a84e134Smrg if (lw->simple.international == True) 3297a84e134Smrg lw->list.normgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0); 3307a84e134Smrg else 3317a84e134Smrg lw->list.normgc = XtGetGC(w, GCForeground | GCFont, &values); 3327a84e134Smrg 3337a84e134Smrg values.foreground = lw->core.background_pixel; 3347a84e134Smrg 3357a84e134Smrg if (lw->simple.international == True) 3367a84e134Smrg lw->list.revgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0); 3377a84e134Smrg else 3387a84e134Smrg lw->list.revgc = XtGetGC(w, GCForeground | GCFont, &values); 3397a84e134Smrg 340421c997bSmrg values.tile = XmuCreateStippledPixmap(XtScreen(w), 3417a84e134Smrg lw->list.foreground, 3427a84e134Smrg lw->core.background_pixel, 3437a84e134Smrg lw->core.depth); 3447a84e134Smrg values.fill_style = FillTiled; 3457a84e134Smrg 3467a84e134Smrg if (lw->simple.international == True) 3477a84e134Smrg lw->list.graygc = XtAllocateGC(w, 0, GCTile | GCFillStyle, 3487a84e134Smrg &values, GCFont, 0); 3497a84e134Smrg else 3507a84e134Smrg lw->list.graygc = XtGetGC(w, GCFont | GCTile | GCFillStyle, &values); 3517a84e134Smrg} 3527a84e134Smrg 3537a84e134Smrgstatic void 3547a84e134SmrgCalculatedValues(Widget w) 3557a84e134Smrg{ 3567a84e134Smrg int i, len; 3577a84e134Smrg ListWidget lw = (ListWidget)w; 3587a84e134Smrg 3597a84e134Smrg /* If list is NULL then the list will just be the name of the widget */ 3607a84e134Smrg if (lw->list.list == NULL) { 3617a84e134Smrg lw->list.list = &lw->core.name; 3627a84e134Smrg lw->list.nitems = 1; 3637a84e134Smrg } 3647a84e134Smrg 3657a84e134Smrg /* Get number of items */ 3667a84e134Smrg if (lw->list.nitems == 0) 3677a84e134Smrg for (; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++) 3687a84e134Smrg ; 3697a84e134Smrg 3707a84e134Smrg /* Get column width */ 3717a84e134Smrg if (LongestFree(lw)) { 3727a84e134Smrg lw->list.longest = 0; /* so it will accumulate real longest below */ 3737a84e134Smrg 3747a84e134Smrg for (i = 0 ; i < lw->list.nitems; i++) { 3757a84e134Smrg if (lw->simple.international == True) 3767a84e134Smrg len = XmbTextEscapement(lw->list.fontset, lw->list.list[i], 3775ec34c4cSmrg (int)strlen(lw->list.list[i])); 3787a84e134Smrg else 3797a84e134Smrg len = XTextWidth(lw->list.font, lw->list.list[i], 3805ec34c4cSmrg (int)strlen(lw->list.list[i])); 3817a84e134Smrg if (len > lw->list.longest) 3827a84e134Smrg lw->list.longest = len; 3837a84e134Smrg } 3847a84e134Smrg } 3857a84e134Smrg 3867a84e134Smrg lw->list.col_width = lw->list.longest + lw->list.column_space; 3877a84e134Smrg} 3887a84e134Smrg 3897a84e134Smrg/* 3907a84e134Smrg * Function: 3917a84e134Smrg * ResetList 3927a84e134Smrg * 3937a84e134Smrg * Parameters: 3947a84e134Smrg * w - list widget 3957a84e134Smrg * changex - allow the height or width to change? 3967a84e134Smrg * changey - "" 3977a84e134Smrg * 3987a84e134Smrg * Description: 3997a84e134Smrg * Resets the new list when important things change. 4007a84e134Smrg * 4017a84e134Smrg * Returns: 4027a84e134Smrg * True if width or height have been changed 4037a84e134Smrg */ 4047a84e134Smrgstatic void 4057a84e134SmrgResetList(Widget w, Bool changex, Bool changey) 4067a84e134Smrg{ 4077a84e134Smrg Dimension width = XtWidth(w); 4087a84e134Smrg Dimension height = XtHeight(w); 4097a84e134Smrg 4107a84e134Smrg CalculatedValues(w); 4117a84e134Smrg 4127a84e134Smrg if (Layout(w, changex, changey, &width, &height)) { 4137a84e134Smrg if (XtIsComposite(XtParent(w))) 4147a84e134Smrg ChangeSize(w, width, height); 4157a84e134Smrg else { 4167a84e134Smrg XtWidth(w) = width; 4177a84e134Smrg XtHeight(w) = height; 4187a84e134Smrg } 4197a84e134Smrg } 4207a84e134Smrg} 4217a84e134Smrg 4227a84e134Smrg/* 4237a84e134Smrg * Function: 4247a84e134Smrg * ChangeSize 4257a84e134Smrg * 4267a84e134Smrg * Parameters: 4277a84e134Smrg * w - widget to try change the size of 4287a84e134Smrg * 4297a84e134Smrg * Description: 4307a84e134Smrg * Laysout the widget. 4317a84e134Smrg */ 4327a84e134Smrgstatic void 4337a84e134SmrgChangeSize(Widget w, unsigned int width, unsigned int height) 4347a84e134Smrg{ 4357a84e134Smrg XtWidgetGeometry request, reply; 4367a84e134Smrg 4377a84e134Smrg request.request_mode = CWWidth | CWHeight; 4385ec34c4cSmrg request.width = (Dimension)width; 4395ec34c4cSmrg request.height = (Dimension)height; 4407a84e134Smrg 4417a84e134Smrg switch (XtMakeGeometryRequest(w, &request, &reply)) { 4427a84e134Smrg case XtGeometryYes: 4437a84e134Smrg case XtGeometryNo: 4447a84e134Smrg break; 4457a84e134Smrg case XtGeometryAlmost: 4467a84e134Smrg Layout(w, request.height != reply.height, 4477a84e134Smrg request.width != reply.width, &reply.width, &reply.height); 4487a84e134Smrg request = reply; 4497a84e134Smrg switch (XtMakeGeometryRequest(w, &request, &reply)) { 4507a84e134Smrg case XtGeometryYes: 4517a84e134Smrg case XtGeometryNo: 4527a84e134Smrg break; 4537a84e134Smrg case XtGeometryAlmost: 4547a84e134Smrg request = reply; 4557a84e134Smrg Layout(w, False, False, &request.width, &request.height); 4567a84e134Smrg request.request_mode = CWWidth | CWHeight; 4577a84e134Smrg XtMakeGeometryRequest(w, &request, &reply); 4585b16253fSmrg /*FALLTHROUGH*/ 4597a84e134Smrg default: 4607a84e134Smrg break; 4617a84e134Smrg } 4625b16253fSmrg /*FALLTHROUGH*/ 4637a84e134Smrg default: 4647a84e134Smrg break; 4657a84e134Smrg } 4667a84e134Smrg} 4677a84e134Smrg 4687a84e134Smrg/*ARGSUSED*/ 469421c997bSmrgstatic void 4705ec34c4cSmrgXawListInitialize(Widget temp1 _X_UNUSED, Widget cnew, ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 4717a84e134Smrg{ 4727a84e134Smrg ListWidget lw = (ListWidget)cnew; 4737a84e134Smrg 4747a84e134Smrg if (!lw->list.font) XtError("Aborting: no font found\n"); 475421c997bSmrg if (lw->simple.international && !lw->list.fontset) 4767a84e134Smrg XtError("Aborting: no fontset found\n"); 477421c997bSmrg 4787a84e134Smrg /* 4797a84e134Smrg * Initialize all private resources 4807a84e134Smrg */ 4817a84e134Smrg /* record for posterity if we are free */ 4827a84e134Smrg lw->list.freedoms = ((XtWidth(lw) != 0) * WidthLock + 4837a84e134Smrg (XtHeight(lw) != 0) * HeightLock + 4847a84e134Smrg (lw->list.longest != 0) * LongestLock); 4857a84e134Smrg 4867a84e134Smrg GetGCs(cnew); 4877a84e134Smrg 4887a84e134Smrg /* Set row height, based on font or fontset */ 4897a84e134Smrg if (lw->simple.international == True) 4907a84e134Smrg lw->list.row_height = 4917a84e134Smrg XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height + 4927a84e134Smrg lw->list.row_space; 4937a84e134Smrg else 4947a84e134Smrg lw->list.row_height = lw->list.font->max_bounds.ascent + 4957a84e134Smrg lw->list.font->max_bounds.descent + 4967a84e134Smrg lw->list.row_space; 4977a84e134Smrg 4987a84e134Smrg ResetList(cnew, WidthFree(lw), HeightFree(lw)); 4997a84e134Smrg 5007a84e134Smrg lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT; 5017a84e134Smrg} 5027a84e134Smrg 5037a84e134Smrg/* 5047a84e134Smrg * Function: 5057a84e134Smrg * CvtToItem 5067a84e134Smrg * 5077a84e134Smrg * Parameters: 5087a84e134Smrg * w - list widget 5097a84e134Smrg * xloc - x location 5107a84e134Smrg * yloc - y location 5117a84e134Smrg * 5127a84e134Smrg * Description: 5137a84e134Smrg * Converts Xcoord to item number of item containing that point. 5147a84e134Smrg * 5157a84e134Smrg * Returns: 5167a84e134Smrg * Item number 5177a84e134Smrg */ 5187a84e134Smrgstatic int 5197a84e134SmrgCvtToItem(Widget w, int xloc, int yloc, int *item) 5207a84e134Smrg{ 5217a84e134Smrg int one, another; 5227a84e134Smrg ListWidget lw = (ListWidget)w; 5237a84e134Smrg int ret_val = OKAY; 5247a84e134Smrg 5257a84e134Smrg if (lw->list.vertical_cols) { 5267a84e134Smrg one = lw->list.nrows * ((xloc - (int)lw->list.internal_width) 5277a84e134Smrg / lw->list.col_width); 5287a84e134Smrg another = (yloc - (int)lw->list.internal_height) / lw->list.row_height; 5297a84e134Smrg /* If out of range, return minimum possible value */ 5307a84e134Smrg if (another >= lw->list.nrows) { 5317a84e134Smrg another = lw->list.nrows - 1; 5327a84e134Smrg ret_val = OUT_OF_RANGE; 5337a84e134Smrg } 5347a84e134Smrg } 5357a84e134Smrg else { 5367a84e134Smrg one = (lw->list.ncols * ((yloc - (int)lw->list.internal_height) 5377a84e134Smrg / lw->list.row_height)); 5387a84e134Smrg /* If in right margin handle things right */ 5397a84e134Smrg another = (xloc - (int)lw->list.internal_width) / lw->list.col_width; 5407a84e134Smrg if (another >= lw->list.ncols) { 541421c997bSmrg another = lw->list.ncols - 1; 5427a84e134Smrg ret_val = OUT_OF_RANGE; 5437a84e134Smrg } 544421c997bSmrg } 5457a84e134Smrg if (xloc < 0 || yloc < 0) 5467a84e134Smrg ret_val = OUT_OF_RANGE; 5477a84e134Smrg if (one < 0) 5487a84e134Smrg one = 0; 5497a84e134Smrg if (another < 0) 5507a84e134Smrg another = 0; 5517a84e134Smrg *item = one + another; 5527a84e134Smrg if (*item >= lw->list.nitems) 5537a84e134Smrg return (OUT_OF_RANGE); 5547a84e134Smrg 5557a84e134Smrg return (ret_val); 5567a84e134Smrg} 5577a84e134Smrg 5587a84e134Smrg/* 5597a84e134Smrg * Function: 5607a84e134Smrg * FindCornerItems 5617a84e134Smrg * 5627a84e134Smrg * Arguments: 5637a84e134Smrg * w - list widget 5647a84e134Smrg * event - event structure that has the rectangle it it 5657a84e134Smrg * ul_ret - the corners (return) 5667a84e134Smrg * lr_ret - "" 5677a84e134Smrg * 5687a84e134Smrg * Description: 5697a84e134Smrg * Find the corners of the rectangle in item space. 5707a84e134Smrg */ 5717a84e134Smrgstatic void 5727a84e134SmrgFindCornerItems(Widget w, XEvent *event, int *ul_ret, int *lr_ret) 5737a84e134Smrg{ 5747a84e134Smrg int xloc, yloc; 5757a84e134Smrg 5767a84e134Smrg xloc = event->xexpose.x; 5777a84e134Smrg yloc = event->xexpose.y; 5787a84e134Smrg CvtToItem(w, xloc, yloc, ul_ret); 5797a84e134Smrg xloc += event->xexpose.width; 5807a84e134Smrg yloc += event->xexpose.height; 5817a84e134Smrg CvtToItem(w, xloc, yloc, lr_ret); 5827a84e134Smrg} 5837a84e134Smrg 5847a84e134Smrg/* 5857a84e134Smrg * Function: 5867a84e134Smrg * ItemInRectangle 5877a84e134Smrg * 5887a84e134Smrg * Parameters: 5897a84e134Smrg * w - list widget 5907a84e134Smrg * ul - corners of the rectangle in item space 5917a84e134Smrg * lr - "" 5927a84e134Smrg * item - item to check 5937a84e134Smrg * 5947a84e134Smrg * Returns: 5957a84e134Smrg * True if the item passed is in the given rectangle 5967a84e134Smrg */ 5977a84e134Smrgstatic Bool 5987a84e134SmrgItemInRectangle(Widget w, int ul, int lr, int item) 5997a84e134Smrg{ 6007a84e134Smrg ListWidget lw = (ListWidget)w; 6017a84e134Smrg int mod_item; 6027a84e134Smrg int things; 603421c997bSmrg 604421c997bSmrg if (item < ul || item > lr) 6057a84e134Smrg return (False); 6067a84e134Smrg if (lw->list.vertical_cols) 6077a84e134Smrg things = lw->list.nrows; 6087a84e134Smrg else 6097a84e134Smrg things = lw->list.ncols; 6107a84e134Smrg 6117a84e134Smrg mod_item = item % things; 6127a84e134Smrg if ((mod_item >= ul % things) && (mod_item <= lr % things)) 6137a84e134Smrg return (True); 6147a84e134Smrg 6157a84e134Smrg return (False); 6167a84e134Smrg} 6177a84e134Smrg 6187a84e134Smrg/* HighlightBackground() 6197a84e134Smrg * 6207a84e134Smrg * Paints the color of the background for the given item. It performs 6217a84e134Smrg * clipping to the interior of internal_width/height by hand, as its a 6227a84e134Smrg * simple calculation and probably much faster than using Xlib and a clip mask. 6237a84e134Smrg * 6247a84e134Smrg * x, y - ul corner of the area item occupies. 6257a84e134Smrg * gc - the gc to use to paint this rectangle 6267a84e134Smrg */ 6277a84e134Smrgstatic void 6287a84e134SmrgHighlightBackground(Widget w, int x, int y, GC gc) 6297a84e134Smrg{ 6307a84e134Smrg ListWidget lw = (ListWidget)w; 6315ec34c4cSmrg Dimension width = (Dimension)lw->list.col_width; 6325ec34c4cSmrg Dimension height = (Dimension)lw->list.row_height; 6335ec34c4cSmrg Dimension frame_limited_width = (Dimension)(XtWidth(w) - lw->list.internal_width - x); 6345ec34c4cSmrg Dimension frame_limited_height= (Dimension)(XtHeight(w) - lw->list.internal_height - y); 6357a84e134Smrg 6367a84e134Smrg /* Clip the rectangle width and height to the edge of the drawable area */ 6377a84e134Smrg if (width > frame_limited_width) 6387a84e134Smrg width = frame_limited_width; 6397a84e134Smrg if (height > frame_limited_height) 6407a84e134Smrg height = frame_limited_height; 6417a84e134Smrg 6427a84e134Smrg /* Clip the rectangle x and y to the edge of the drawable area */ 6437a84e134Smrg if (x < lw->list.internal_width) { 6445ec34c4cSmrg width = (Dimension)(width - (lw->list.internal_width - x)); 6457a84e134Smrg x = lw->list.internal_width; 6467a84e134Smrg } 6477a84e134Smrg if (y < lw->list.internal_height) { 6485ec34c4cSmrg height = (Dimension)(height - (lw->list.internal_height - y)); 6497a84e134Smrg y = lw->list.internal_height; 6507a84e134Smrg } 6517a84e134Smrg 6527a84e134Smrg if (gc == lw->list.revgc && lw->core.background_pixmap != XtUnspecifiedPixmap) 6537a84e134Smrg XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False); 6547a84e134Smrg else 6557a84e134Smrg XFillRectangle(XtDisplay(w), XtWindow(w), gc, x, y, width, height); 6567a84e134Smrg} 6577a84e134Smrg 6587a84e134Smrg 6597a84e134Smrg/* ClipToShadowInteriorAndLongest() 6607a84e134Smrg * 6617a84e134Smrg * Converts the passed gc so that any drawing done with that GC will not 6627a84e134Smrg * write in the empty margin (specified by internal_width/height) (which also 6637a84e134Smrg * prevents erasing the shadow. It also clips against the value longest. 6647a84e134Smrg * If the user doesn't set longest, this has no effect (as longest is the 6657a84e134Smrg * maximum of all item lengths). If the user does specify, say, 80 pixel 6667a84e134Smrg * columns, though, this prevents items from overwriting other items. 6677a84e134Smrg */ 6687a84e134Smrgstatic void 6697a84e134SmrgClipToShadowInteriorAndLongest(ListWidget lw, GC *gc_p, unsigned int x) 6707a84e134Smrg{ 6717a84e134Smrg XRectangle rect; 6727a84e134Smrg 6735ec34c4cSmrg rect.x = (short)x; 6745ec34c4cSmrg rect.y = (short)lw->list.internal_height; 6755ec34c4cSmrg rect.height = (unsigned short)(XtHeight(lw) - (lw->list.internal_height << 1)); 6765ec34c4cSmrg rect.width = (unsigned short)(XtWidth(lw) - (unsigned)lw->list.internal_width - x); 6777a84e134Smrg if (rect.width > lw->list.longest) 6785ec34c4cSmrg rect.width = (unsigned short)lw->list.longest; 6797a84e134Smrg 6807a84e134Smrg XSetClipRectangles(XtDisplay((Widget)lw), *gc_p, 0, 0, &rect, 1, YXBanded); 6817a84e134Smrg} 6827a84e134Smrg 6837a84e134Smrgstatic void 6847a84e134SmrgPaintItemName(Widget w, int item) 6857a84e134Smrg{ 6865ec34c4cSmrg _Xconst char *str; 6877a84e134Smrg GC gc; 6887a84e134Smrg int x, y, str_y; 6897a84e134Smrg ListWidget lw = (ListWidget)w; 6907a84e134Smrg XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset); 6917a84e134Smrg 6927a84e134Smrg if (!XtIsRealized(w) || item > lw->list.nitems) 6937a84e134Smrg return; 6947a84e134Smrg 6957a84e134Smrg if (lw->list.vertical_cols) { 6967a84e134Smrg x = lw->list.col_width * (item / lw->list.nrows) 6977a84e134Smrg + lw->list.internal_width; 6987a84e134Smrg y = lw->list.row_height * (item % lw->list.nrows) 6997a84e134Smrg + lw->list.internal_height; 7007a84e134Smrg } 7017a84e134Smrg else { 7027a84e134Smrg x = lw->list.col_width * (item % lw->list.ncols) 7037a84e134Smrg + lw->list.internal_width; 7047a84e134Smrg y = lw->list.row_height * (item / lw->list.ncols) 7057a84e134Smrg + lw->list.internal_height; 7067a84e134Smrg } 7077a84e134Smrg 7087a84e134Smrg if ( lw->simple.international == True ) 7097a84e134Smrg str_y = y + XawAbs(ext->max_ink_extent.y); 7107a84e134Smrg else 7117a84e134Smrg str_y = y + lw->list.font->max_bounds.ascent; 7127a84e134Smrg 7137a84e134Smrg if (item == lw->list.is_highlighted) { 7147a84e134Smrg if (item == lw->list.highlight) { 7157a84e134Smrg gc = lw->list.revgc; 7167a84e134Smrg HighlightBackground(w, x, y, lw->list.normgc); 7177a84e134Smrg } 7187a84e134Smrg else { 719421c997bSmrg if (XtIsSensitive(w)) 7207a84e134Smrg gc = lw->list.normgc; 7217a84e134Smrg else 7227a84e134Smrg gc = lw->list.graygc; 7237a84e134Smrg HighlightBackground(w, x, y, lw->list.revgc); 7247a84e134Smrg lw->list.is_highlighted = NO_HIGHLIGHT; 7257a84e134Smrg } 7267a84e134Smrg } 7277a84e134Smrg else { 7287a84e134Smrg if (item == lw->list.highlight) { 7297a84e134Smrg gc = lw->list.revgc; 7307a84e134Smrg HighlightBackground(w, x, y, lw->list.normgc); 7317a84e134Smrg lw->list.is_highlighted = item; 7327a84e134Smrg } 7337a84e134Smrg else { 734421c997bSmrg if (XtIsSensitive(w)) 7357a84e134Smrg gc = lw->list.normgc; 7367a84e134Smrg else 7377a84e134Smrg gc = lw->list.graygc; 7387a84e134Smrg } 7397a84e134Smrg } 7407a84e134Smrg 7417a84e134Smrg /* List's overall width contains the same number of inter-column 7427a84e134Smrg column_space's as columns. There should thus be a half 7437a84e134Smrg column_width margin on each side of each column. 7447a84e134Smrg The row case is symmetric */ 7457a84e134Smrg 7467a84e134Smrg x += lw->list.column_space >> 1; 7477a84e134Smrg str_y += lw->list.row_space >> 1; 7487a84e134Smrg 7497a84e134Smrg str = lw->list.list[item]; /* draw it */ 7507a84e134Smrg 7515ec34c4cSmrg ClipToShadowInteriorAndLongest(lw, &gc, (unsigned)x); 7527a84e134Smrg 7537a84e134Smrg if (lw->simple.international == True) 7547a84e134Smrg XmbDrawString(XtDisplay(w), XtWindow(w), lw->list.fontset, 7555ec34c4cSmrg gc, x, str_y, str, (int)strlen(str)); 7567a84e134Smrg else 7575ec34c4cSmrg XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, (int)strlen(str)); 7587a84e134Smrg 7597a84e134Smrg XSetClipMask(XtDisplay(w), gc, None); 7607a84e134Smrg} 7617a84e134Smrg 762421c997bSmrgstatic void 7637a84e134SmrgXawListRedisplay(Widget w, XEvent *event, Region region) 7647a84e134Smrg{ 7657a84e134Smrg int item; /* an item to work with */ 7667a84e134Smrg int ul_item, lr_item; /* corners of items we need to paint */ 7677a84e134Smrg ListWidget lw = (ListWidget)w; 7687a84e134Smrg 7697a84e134Smrg if (event == NULL) { 7707a84e134Smrg ul_item = 0; 7717a84e134Smrg lr_item = lw->list.nrows * lw->list.ncols - 1; 7727a84e134Smrg XClearWindow(XtDisplay(w), XtWindow(w)); 7737a84e134Smrg } 7747a84e134Smrg else 7757a84e134Smrg FindCornerItems(w, event, &ul_item, &lr_item); 7767a84e134Smrg 7777a84e134Smrg if (Superclass->core_class.expose) 7787a84e134Smrg (Superclass->core_class.expose)(w, event, region); 779421c997bSmrg 7807a84e134Smrg for (item = ul_item; item <= lr_item && item < lw->list.nitems; item++) 7817a84e134Smrg if (ItemInRectangle(w, ul_item, lr_item, item)) 7827a84e134Smrg PaintItemName(w, item); 7837a84e134Smrg} 7847a84e134Smrg 7857a84e134Smrg/* XawListQueryGeometry() 7867a84e134Smrg * 7877a84e134Smrg * This tells the parent what size we would like to be 7887a84e134Smrg * given certain constraints. 7897a84e134Smrg * w - the widget. 7907a84e134Smrg * intended - what the parent intends to do with us. 7917a84e134Smrg * requested - what we want to happen */ 792421c997bSmrgstatic XtGeometryResult 7937a84e134SmrgXawListQueryGeometry(Widget w, XtWidgetGeometry *intended, 7947a84e134Smrg XtWidgetGeometry *requested) 7957a84e134Smrg{ 7967a84e134Smrg Dimension new_width, new_height; 7977a84e134Smrg Bool change, width_req, height_req; 798421c997bSmrg 7997a84e134Smrg width_req = intended->request_mode & CWWidth; 8007a84e134Smrg height_req = intended->request_mode & CWHeight; 8017a84e134Smrg 8027a84e134Smrg if (width_req) 8037a84e134Smrg new_width = intended->width; 8047a84e134Smrg else 8057a84e134Smrg new_width = XtWidth(w); 8067a84e134Smrg 8077a84e134Smrg if (height_req) 8087a84e134Smrg new_height = intended->height; 8097a84e134Smrg else 8107a84e134Smrg new_height = XtHeight(w); 8117a84e134Smrg 8127a84e134Smrg requested->request_mode = 0; 813421c997bSmrg 8147a84e134Smrg /* 8157a84e134Smrg * We only care about our height and width 8167a84e134Smrg */ 8177a84e134Smrg if (!width_req && !height_req) 8187a84e134Smrg return (XtGeometryYes); 819421c997bSmrg 8207a84e134Smrg change = Layout(w, !width_req, !height_req, &new_width, &new_height); 8217a84e134Smrg 8227a84e134Smrg requested->request_mode |= CWWidth; 8237a84e134Smrg requested->width = new_width; 8247a84e134Smrg requested->request_mode |= CWHeight; 8257a84e134Smrg requested->height = new_height; 8267a84e134Smrg 8277a84e134Smrg if (change) 8287a84e134Smrg return (XtGeometryAlmost); 8297a84e134Smrg 8307a84e134Smrg return (XtGeometryYes); 8317a84e134Smrg} 8327a84e134Smrg 8337a84e134Smrgstatic void 8347a84e134SmrgXawListResize(Widget w) 8357a84e134Smrg{ 8367a84e134Smrg Dimension width, height; 8377a84e134Smrg 8387a84e134Smrg width = XtWidth(w); 8397a84e134Smrg height = XtHeight(w); 8407a84e134Smrg 8417a84e134Smrg if (Layout(w, False, False, &width, &height)) 8427a84e134Smrg XtAppWarning(XtWidgetToApplicationContext(w), 8437a84e134Smrg "List Widget: Size changed when it shouldn't " 8447a84e134Smrg "have when resising."); 8457a84e134Smrg} 8467a84e134Smrg 8477a84e134Smrg/* Layout() 8487a84e134Smrg * 8497a84e134Smrg * lays out the item in the list. 8507a84e134Smrg * w - the widget. 8517a84e134Smrg * xfree, yfree - True if we are free to resize the widget in 8527a84e134Smrg * this direction. 8537a84e134Smrg * width, height- the is the current width and height that we are going 8547a84e134Smrg * we are going to layout the list widget to, 8557a84e134Smrg * depending on xfree and yfree of course. 856421c997bSmrg * 8577a84e134Smrg * Return: 8587a84e134Smrg * True if width or height have been changed */ 8597a84e134Smrgstatic Bool 8607a84e134SmrgLayout(Widget w, Bool xfree, Bool yfree, Dimension *width, Dimension *height) 8617a84e134Smrg{ 8627a84e134Smrg ListWidget lw = (ListWidget)w; 8637a84e134Smrg Bool change = False; 8647a84e134Smrg unsigned long width2 = 0, height2 = 0; 8657a84e134Smrg 8667a84e134Smrg /* 8677a84e134Smrg * If force columns is set then always use number of columns specified 8687a84e134Smrg * by default_cols 8697a84e134Smrg */ 8707a84e134Smrg if (lw->list.force_cols) { 8717a84e134Smrg lw->list.ncols = lw->list.default_cols; 8727a84e134Smrg if (lw->list.ncols <= 0) 8737a84e134Smrg lw->list.ncols = 1; 8747a84e134Smrg lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; 8757a84e134Smrg if (xfree) { 8767a84e134Smrg /* this counts the same number 8777a84e134Smrg of inter-column column_space 's as columns. There should thus 8787a84e134Smrg be a half column_space margin on each side of each column...*/ 8795ec34c4cSmrg width2 = (unsigned long)(lw->list.ncols * lw->list.col_width + 8805ec34c4cSmrg (lw->list.internal_width << 1)); 8817a84e134Smrg change = True; 8827a84e134Smrg } 8837a84e134Smrg if (yfree) { 8845ec34c4cSmrg height2 = (unsigned long)(lw->list.nrows * lw->list.row_height + 8855ec34c4cSmrg (lw->list.internal_height << 1)); 8867a84e134Smrg change = True; 8877a84e134Smrg } 8887a84e134Smrg } 8897a84e134Smrg 8907a84e134Smrg /* 8917a84e134Smrg * If both width and height are free to change the use default_cols 8927a84e134Smrg * to determine the number columns and set new width and height to 8937a84e134Smrg * just fit the window 8947a84e134Smrg */ 8957a84e134Smrg else if (xfree && yfree) { 8967a84e134Smrg lw->list.ncols = lw->list.default_cols; 8977a84e134Smrg if (lw->list.ncols <= 0) { 8987a84e134Smrg int wid = (int)XtWidth(lw) - (int)(lw->list.internal_width << 1) 8997a84e134Smrg + (int)lw->list.column_space; 9007a84e134Smrg 9017a84e134Smrg if (wid <= 0 || lw->list.col_width <= 0 9027a84e134Smrg || (lw->list.ncols = wid / lw->list.col_width) <= 0) 9037a84e134Smrg lw->list.ncols = 1; 9047a84e134Smrg } 9055ec34c4cSmrg width2 = (unsigned long)((lw->list.ncols * lw->list.col_width) 9065ec34c4cSmrg + (lw->list.internal_width << 1)); 9075ec34c4cSmrg height2 = (unsigned long)((lw->list.nrows * lw->list.row_height) 9085ec34c4cSmrg + (lw->list.internal_height << 1)); 9097a84e134Smrg change = True; 9107a84e134Smrg } 9117a84e134Smrg 9127a84e134Smrg /* 9137a84e134Smrg * If the width is fixed then use it to determine the number of columns. 9147a84e134Smrg * If the height is free to move (width still fixed) then resize the height 9157a84e134Smrg * of the widget to fit the current list exactly 9167a84e134Smrg */ 9177a84e134Smrg else if (!xfree) { 9187a84e134Smrg lw->list.ncols = ((int)(*width - (lw->list.internal_width << 1)) 9197a84e134Smrg / (int)lw->list.col_width); 9207a84e134Smrg if (lw->list.ncols <= 0) 9217a84e134Smrg lw->list.ncols = 1; 9227a84e134Smrg lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; 9237a84e134Smrg if (yfree) { 9245ec34c4cSmrg height2 = (unsigned long)((lw->list.nrows * lw->list.row_height) + 9255ec34c4cSmrg (lw->list.internal_height << 1)); 9267a84e134Smrg change = True; 9277a84e134Smrg } 9287a84e134Smrg } 9297a84e134Smrg 9307a84e134Smrg /* 9317a84e134Smrg * The last case is xfree and !yfree we use the height to determine 9327a84e134Smrg * the number of rows and then set the width to just fit the resulting 9337a84e134Smrg * number of columns 9347a84e134Smrg */ 9357a84e134Smrg else if (!yfree) { 9367a84e134Smrg lw->list.nrows = ((int)(*height - (lw->list.internal_height << 1)) 9377a84e134Smrg / (int)lw->list.row_height); 9387a84e134Smrg if (lw->list.nrows <= 0) 9397a84e134Smrg lw->list.nrows = 1; 9407a84e134Smrg lw->list.ncols = ((lw->list.nitems - 1) / lw->list.nrows) + 1; 9415ec34c4cSmrg width2 = (unsigned long)((lw->list.ncols * lw->list.col_width) + 9425ec34c4cSmrg (lw->list.internal_width << 1)); 9437a84e134Smrg change = True; 9447a84e134Smrg } 9457a84e134Smrg 9467a84e134Smrg if (!lw->list.force_cols && lw->list.nrows) { 9477a84e134Smrg /*CONSTCOND*/ 9487a84e134Smrg while (1) { 9497a84e134Smrg lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; 9505ec34c4cSmrg width2 = (unsigned long)((lw->list.ncols * lw->list.col_width) + 9515ec34c4cSmrg (lw->list.internal_width << 1)); 9525ec34c4cSmrg height2 = (unsigned long)((lw->list.nrows * lw->list.row_height) + 9535ec34c4cSmrg (lw->list.internal_height << 1)); 9547a84e134Smrg if (width2 >= MaxSize && height2 >= MaxSize) 9557a84e134Smrg break; 9567a84e134Smrg if (height2 > MaxSize) 9577a84e134Smrg ++lw->list.ncols; 9587a84e134Smrg else if (width2 > MaxSize && lw->list.ncols > 1) 9597a84e134Smrg --lw->list.ncols; 9607a84e134Smrg else 9617a84e134Smrg break; 9627a84e134Smrg } 9637a84e134Smrg } 9647a84e134Smrg if (width2) 9655ec34c4cSmrg *width = (Dimension)width2; 9667a84e134Smrg if (height2) 9675ec34c4cSmrg *height = (Dimension)height2; 9687a84e134Smrg 9697a84e134Smrg return (change); 9707a84e134Smrg} 9717a84e134Smrg 9727a84e134Smrg/* Notify() - Action 9737a84e134Smrg * 9747a84e134Smrg * Notifies the user that a button has been pressed, and 9757a84e134Smrg * calls the callback; if the XtNpasteBuffer resource is true 9767a84e134Smrg * then the name of the item is also put in CUT_BUFFER0 */ 9777a84e134Smrg/*ARGSUSED*/ 9787a84e134Smrgstatic void 9795ec34c4cSmrgNotify(Widget w, XEvent *event, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 9807a84e134Smrg{ 9817a84e134Smrg ListWidget lw = (ListWidget)w; 9827a84e134Smrg int item, item_len; 9837a84e134Smrg XawListReturnStruct ret_value; 9847a84e134Smrg 9857a84e134Smrg /* 9867a84e134Smrg * Find item and if out of range then unhighlight and return 987421c997bSmrg * 9887a84e134Smrg * If the current item is unhighlighted then the user has aborted the 9897a84e134Smrg * notify, so unhighlight and return 9907a84e134Smrg */ 9917a84e134Smrg if ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE) 9927a84e134Smrg || lw->list.highlight != item) { 9937a84e134Smrg#ifndef OLDXAW 9947a84e134Smrg if (!lw->list.show_current || lw->list.selected == NO_HIGHLIGHT) 9957a84e134Smrg XawListUnhighlight(w); 9967a84e134Smrg else 9977a84e134Smrg XawListHighlight(w, lw->list.selected); 9987a84e134Smrg#else 9997a84e134Smrg XawListUnhighlight(w); 10007a84e134Smrg#endif 10017a84e134Smrg return; 10027a84e134Smrg } 10037a84e134Smrg 10045ec34c4cSmrg item_len = (int)strlen(lw->list.list[item]); 10057a84e134Smrg 10067a84e134Smrg if (lw->list.paste) /* if XtNpasteBuffer set then paste it */ 10077a84e134Smrg XStoreBytes(XtDisplay(w), lw->list.list[item], item_len); 10087a84e134Smrg 10097a84e134Smrg#ifndef OLDXAW 10107a84e134Smrg lw->list.selected = item; 10117a84e134Smrg#endif 10127a84e134Smrg /* 10137a84e134Smrg * Call Callback function 10147a84e134Smrg */ 10157a84e134Smrg ret_value.string = lw->list.list[item]; 10167a84e134Smrg ret_value.list_index = item; 1017421c997bSmrg 10187a84e134Smrg XtCallCallbacks(w, XtNcallback, (XtPointer)&ret_value); 10197a84e134Smrg} 10207a84e134Smrg 10217a84e134Smrg/* Unset() - Action 10227a84e134Smrg * 10237a84e134Smrg * unhighlights the current element */ 10247a84e134Smrg/*ARGSUSED*/ 10257a84e134Smrgstatic void 10265ec34c4cSmrgUnset(Widget w, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 10277a84e134Smrg{ 10287a84e134Smrg XawListUnhighlight(w); 10297a84e134Smrg} 10307a84e134Smrg 10317a84e134Smrg/* Set() - Action 10327a84e134Smrg * 10337a84e134Smrg * Highlights the current element */ 10347a84e134Smrg/*ARGSUSED*/ 10357a84e134Smrgstatic void 10365ec34c4cSmrgSet(Widget w, XEvent *event, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 10377a84e134Smrg{ 10387a84e134Smrg int item; 10397a84e134Smrg ListWidget lw = (ListWidget)w; 10407a84e134Smrg 10417a84e134Smrg#ifndef OLDXAW 10427a84e134Smrg lw->list.selected = lw->list.highlight; 10437a84e134Smrg#endif 10447a84e134Smrg if (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE) 10457a84e134Smrg XawListUnhighlight(w); /* Unhighlight current item */ 10467a84e134Smrg else if (lw->list.is_highlighted != item) /* If this item is not */ 10477a84e134Smrg XawListHighlight(w, item); /* highlighted then do it */ 10487a84e134Smrg} 10497a84e134Smrg 10507a84e134Smrg/* 10517a84e134Smrg * Set specified arguments into widget 10527a84e134Smrg */ 10537a84e134Smrg/*ARGSUSED*/ 1054421c997bSmrgstatic Boolean 10557a84e134SmrgXawListSetValues(Widget current, Widget request, Widget cnew, 10565ec34c4cSmrg ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 10577a84e134Smrg{ 10587a84e134Smrg ListWidget cl = (ListWidget)current; 10597a84e134Smrg ListWidget rl = (ListWidget)request; 10607a84e134Smrg ListWidget nl = (ListWidget)cnew; 10617a84e134Smrg Bool redraw = False; 10627a84e134Smrg XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset); 10637a84e134Smrg 10647a84e134Smrg /* If the request height/width is different, lock it. Unless its 0. If 10657a84e134Smrg neither new nor 0, leave it as it was. Not in R5 */ 10667a84e134Smrg if (XtWidth(nl) != XtWidth(cl)) 10677a84e134Smrg nl->list.freedoms |= WidthLock; 10687a84e134Smrg if (XtWidth(nl) == 0) 10697a84e134Smrg nl->list.freedoms &= ~WidthLock; 10707a84e134Smrg 10717a84e134Smrg if (XtHeight(nl) != XtHeight(cl)) 10727a84e134Smrg nl->list.freedoms |= HeightLock; 10737a84e134Smrg if (XtHeight(nl) == 0) 10747a84e134Smrg nl->list.freedoms &= ~HeightLock; 10757a84e134Smrg 10767a84e134Smrg if (nl->list.longest != cl->list.longest) 10777a84e134Smrg nl->list.freedoms |= LongestLock; 10787a84e134Smrg if (nl->list.longest == 0) 10797a84e134Smrg nl->list.freedoms &= ~LongestLock; 10807a84e134Smrg 10817a84e134Smrg if (cl->list.foreground != nl->list.foreground || 10827a84e134Smrg cl->core.background_pixel != nl->core.background_pixel || 10837a84e134Smrg cl->list.font != nl->list.font) { 10847a84e134Smrg XGCValues values; 10857a84e134Smrg 10867a84e134Smrg XGetGCValues(XtDisplay(current), cl->list.graygc, GCTile, &values); 10877a84e134Smrg XmuReleaseStippledPixmap(XtScreen(current), values.tile); 10887a84e134Smrg XtReleaseGC(current, cl->list.graygc); 10897a84e134Smrg XtReleaseGC(current, cl->list.revgc); 10907a84e134Smrg XtReleaseGC(current, cl->list.normgc); 10917a84e134Smrg GetGCs(cnew); 10927a84e134Smrg redraw = True; 10937a84e134Smrg } 10947a84e134Smrg 10957a84e134Smrg if (cl->list.font != nl->list.font && cl->simple.international == False) 10967a84e134Smrg nl->list.row_height = nl->list.font->max_bounds.ascent 10977a84e134Smrg + nl->list.font->max_bounds.descent 10987a84e134Smrg + nl->list.row_space; 10997a84e134Smrg else if (cl->list.fontset != nl->list.fontset 11007a84e134Smrg && cl->simple.international == True) 11017a84e134Smrg nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; 11027a84e134Smrg 11037a84e134Smrg /* ...If the above two font(set) change checkers above both failed, check 11047a84e134Smrg if row_space was altered. If one of the above passed, row_height will 11057a84e134Smrg already have been re-calculated */ 11067a84e134Smrg else if (cl->list.row_space != nl->list.row_space) { 11077a84e134Smrg if (cl->simple.international == True) 11087a84e134Smrg nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; 11097a84e134Smrg else 11107a84e134Smrg nl->list.row_height = nl->list.font->max_bounds.ascent 11117a84e134Smrg + nl->list.font->max_bounds.descent 11127a84e134Smrg + nl->list.row_space; 11137a84e134Smrg } 11147a84e134Smrg 11157a84e134Smrg if (XtWidth(cl) != XtWidth(nl) || XtHeight(cl) != XtHeight(nl) 11167a84e134Smrg || cl->list.internal_width != nl->list.internal_width 11177a84e134Smrg || cl->list.internal_height != nl->list.internal_height 11187a84e134Smrg || cl->list.column_space != nl->list.column_space 11197a84e134Smrg || cl->list.row_space != nl->list.row_space 11207a84e134Smrg || cl->list.default_cols != nl->list.default_cols 11217a84e134Smrg || (cl->list.force_cols != nl->list.force_cols 11227a84e134Smrg && rl->list.force_cols != nl->list.ncols) 11237a84e134Smrg || cl->list.vertical_cols != nl->list.vertical_cols 11247a84e134Smrg || cl->list.longest != nl->list.longest 11257a84e134Smrg || cl->list.nitems != nl->list.nitems 11267a84e134Smrg || cl->list.font != nl->list.font 11277a84e134Smrg /* Equiv. fontsets might have different values, but the same fonts, 11287a84e134Smrg so the next comparison is sloppy but not dangerous */ 11297a84e134Smrg || cl->list.fontset != nl->list.fontset 11307a84e134Smrg || cl->list.list != nl->list.list) { 11317a84e134Smrg CalculatedValues(cnew); 11327a84e134Smrg Layout(cnew, WidthFree(nl), HeightFree(nl), 11337a84e134Smrg &nl->core.width, &nl->core.height); 11347a84e134Smrg redraw = True; 11357a84e134Smrg } 11367a84e134Smrg 11377a84e134Smrg if (cl->list.list != nl->list.list || cl->list.nitems != nl->list.nitems) 11387a84e134Smrg nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT; 11397a84e134Smrg 11407a84e134Smrg if (cl->core.sensitive != nl->core.sensitive 11417a84e134Smrg || cl->core.ancestor_sensitive != nl->core.ancestor_sensitive) { 11427a84e134Smrg nl->list.highlight = NO_HIGHLIGHT; 11437a84e134Smrg redraw = True; 11447a84e134Smrg } 1145421c997bSmrg 11465ec34c4cSmrg return (Boolean)(redraw); 11477a84e134Smrg} 11487a84e134Smrg 11497a84e134Smrgstatic void 11507a84e134SmrgXawListDestroy(Widget w) 11517a84e134Smrg{ 11527a84e134Smrg ListWidget lw = (ListWidget)w; 11537a84e134Smrg XGCValues values; 1154421c997bSmrg 11557a84e134Smrg XGetGCValues(XtDisplay(w), lw->list.graygc, GCTile, &values); 11567a84e134Smrg XmuReleaseStippledPixmap(XtScreen(w), values.tile); 11577a84e134Smrg XtReleaseGC(w, lw->list.graygc); 11587a84e134Smrg XtReleaseGC(w, lw->list.revgc); 11597a84e134Smrg XtReleaseGC(w, lw->list.normgc); 11607a84e134Smrg} 11617a84e134Smrg 11627a84e134Smrg/* 11637a84e134Smrg * Function: 11647a84e134Smrg * XawListChange 11657a84e134Smrg * 11667a84e134Smrg * Parameters: 11677a84e134Smrg * w - list widget 11687a84e134Smrg * list - new list 11697a84e134Smrg * nitems - number of items in the list 11707a84e134Smrg * longest - length (in Pixels) of the longest element in the list 11717a84e134Smrg * resize - if True the the list widget will try to resize itself 11727a84e134Smrg * 11737a84e134Smrg * Description: 11747a84e134Smrg * Changes the list being used and shown. 11757a84e134Smrg * 11767a84e134Smrg * Note: 11777a84e134Smrg * If nitems of longest are <= 0 then they will be calculated 11787a84e134Smrg * If nitems is <= 0 then the list needs to be NULL terminated 11797a84e134Smrg */ 11807a84e134Smrgvoid 11815ec34c4cSmrgXawListChange(Widget w, _Xconst char **list, int nitems, int longest, 11827a84e134Smrg#if NeedWidePrototypes 11837a84e134Smrg int resize_it 11847a84e134Smrg#else 11857a84e134Smrg Boolean resize_it 11867a84e134Smrg#endif 11877a84e134Smrg) 11887a84e134Smrg{ 11897a84e134Smrg ListWidget lw = (ListWidget)w; 11907a84e134Smrg Dimension new_width = XtWidth(w); 11917a84e134Smrg Dimension new_height = XtHeight(w); 11927a84e134Smrg 11937a84e134Smrg lw->list.list = list; 11947a84e134Smrg 11957a84e134Smrg if (nitems <= 0) 11967a84e134Smrg nitems = 0; 11977a84e134Smrg lw->list.nitems = nitems; 11987a84e134Smrg if (longest <= 0) 11997a84e134Smrg longest = 0; 12007a84e134Smrg 12017a84e134Smrg /* If the user passes 0 meaning "calculate it", it must be free */ 12027a84e134Smrg if (longest != 0) 12037a84e134Smrg lw->list.freedoms |= LongestLock; 12047a84e134Smrg else 12057a84e134Smrg lw->list.freedoms &= ~LongestLock; 12067a84e134Smrg 12077a84e134Smrg if (resize_it) 12087a84e134Smrg lw->list.freedoms &= ~WidthLock & ~HeightLock; 12097a84e134Smrg 12107a84e134Smrg lw->list.longest = longest; 12117a84e134Smrg 12127a84e134Smrg CalculatedValues(w); 12137a84e134Smrg 12147a84e134Smrg if (Layout(w, WidthFree(w), HeightFree(w), &new_width, &new_height)) 12157a84e134Smrg ChangeSize(w, new_width, new_height); 12167a84e134Smrg 12177a84e134Smrg lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT; 12187a84e134Smrg if (XtIsRealized(w)) 12197a84e134Smrg XawListRedisplay(w, NULL, NULL); 12207a84e134Smrg} 12217a84e134Smrg 12227a84e134Smrgvoid 12237a84e134SmrgXawListUnhighlight(Widget w) 12247a84e134Smrg{ 12257a84e134Smrg ListWidget lw = (ListWidget)w; 12267a84e134Smrg 12277a84e134Smrg lw->list.highlight = NO_HIGHLIGHT; 12287a84e134Smrg if (lw->list.is_highlighted != NO_HIGHLIGHT) 12297a84e134Smrg PaintItemName(w, lw->list.is_highlighted); 12307a84e134Smrg} 12317a84e134Smrg 12327a84e134Smrgvoid 12337a84e134SmrgXawListHighlight(Widget w, int item) 12347a84e134Smrg{ 12357a84e134Smrg ListWidget lw = (ListWidget)w; 1236421c997bSmrg 12377a84e134Smrg if (XtIsSensitive(w)) { 12387a84e134Smrg lw->list.highlight = item; 12397a84e134Smrg if (lw->list.is_highlighted != NO_HIGHLIGHT) 12407a84e134Smrg PaintItemName(w, lw->list.is_highlighted); 12417a84e134Smrg PaintItemName(w, item); 12427a84e134Smrg } 12437a84e134Smrg} 12447a84e134Smrg 12457a84e134Smrg/* 12467a84e134Smrg * Function: 12477a84e134Smrg * XawListShowCurrent 12487a84e134Smrg * 12497a84e134Smrg * Parameters: 12507a84e134Smrg * w - list widget 12517a84e134Smrg * 12527a84e134Smrg * Returns: 12537a84e134Smrg * Info about the currently highlighted object 12547a84e134Smrg */ 12557a84e134SmrgXawListReturnStruct * 12567a84e134SmrgXawListShowCurrent(Widget w) 12577a84e134Smrg{ 12587a84e134Smrg ListWidget lw = (ListWidget)w; 12597a84e134Smrg XawListReturnStruct *ret_val; 12607a84e134Smrg 12617a84e134Smrg ret_val = (XawListReturnStruct *)XtMalloc(sizeof(XawListReturnStruct)); 1262421c997bSmrg 12637a84e134Smrg ret_val->list_index = lw->list.highlight; 12647a84e134Smrg if (ret_val->list_index == XAW_LIST_NONE) 12657a84e134Smrg ret_val->string = ""; 12667a84e134Smrg else 12677a84e134Smrg ret_val->string = lw->list.list[ret_val->list_index]; 12687a84e134Smrg 12697a84e134Smrg return (ret_val); 12707a84e134Smrg} 1271