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 */ 303efbcb2bfSmrg NULL, /* display_accelerator */ 304efbcb2bfSmrg NULL, /* extension */ 3057a84e134Smrg }, 3067a84e134Smrg /* simple */ 3077a84e134Smrg { 3087a84e134Smrg XtInheritChangeSensitive, /* change_sensitive */ 309efbcb2bfSmrg#ifndef OLDXAW 310efbcb2bfSmrg NULL, 311efbcb2bfSmrg#endif 3127a84e134Smrg }, 3137a84e134Smrg /* list */ 3147a84e134Smrg { 3157a84e134Smrg NULL, /* extension */ 3167a84e134Smrg }, 3177a84e134Smrg}; 3187a84e134Smrg 3197a84e134SmrgWidgetClass listWidgetClass = (WidgetClass)&listClassRec; 3207a84e134Smrg 3217a84e134Smrg/* 3227a84e134Smrg * Implementation 3237a84e134Smrg */ 3247a84e134Smrgstatic void 3257a84e134SmrgGetGCs(Widget w) 3267a84e134Smrg{ 3277a84e134Smrg ListWidget lw = (ListWidget)w; 328efbcb2bfSmrg XGCValues values = { 329efbcb2bfSmrg .foreground = lw->list.foreground, 330efbcb2bfSmrg .font = lw->list.font->fid 331efbcb2bfSmrg }; 3327a84e134Smrg 3337a84e134Smrg if (lw->simple.international == True) 3347a84e134Smrg lw->list.normgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0); 3357a84e134Smrg else 3367a84e134Smrg lw->list.normgc = XtGetGC(w, GCForeground | GCFont, &values); 3377a84e134Smrg 3387a84e134Smrg values.foreground = lw->core.background_pixel; 3397a84e134Smrg 3407a84e134Smrg if (lw->simple.international == True) 3417a84e134Smrg lw->list.revgc = XtAllocateGC(w, 0, GCForeground, &values, GCFont, 0); 3427a84e134Smrg else 3437a84e134Smrg lw->list.revgc = XtGetGC(w, GCForeground | GCFont, &values); 3447a84e134Smrg 345421c997bSmrg values.tile = XmuCreateStippledPixmap(XtScreen(w), 3467a84e134Smrg lw->list.foreground, 3477a84e134Smrg lw->core.background_pixel, 3487a84e134Smrg lw->core.depth); 3497a84e134Smrg values.fill_style = FillTiled; 3507a84e134Smrg 3517a84e134Smrg if (lw->simple.international == True) 3527a84e134Smrg lw->list.graygc = XtAllocateGC(w, 0, GCTile | GCFillStyle, 3537a84e134Smrg &values, GCFont, 0); 3547a84e134Smrg else 3557a84e134Smrg lw->list.graygc = XtGetGC(w, GCFont | GCTile | GCFillStyle, &values); 3567a84e134Smrg} 3577a84e134Smrg 3587a84e134Smrgstatic void 3597a84e134SmrgCalculatedValues(Widget w) 3607a84e134Smrg{ 3617a84e134Smrg ListWidget lw = (ListWidget)w; 3627a84e134Smrg 3637a84e134Smrg /* If list is NULL then the list will just be the name of the widget */ 3647a84e134Smrg if (lw->list.list == NULL) { 3657a84e134Smrg lw->list.list = &lw->core.name; 3667a84e134Smrg lw->list.nitems = 1; 3677a84e134Smrg } 3687a84e134Smrg 3697a84e134Smrg /* Get number of items */ 3707a84e134Smrg if (lw->list.nitems == 0) 3717a84e134Smrg for (; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++) 3727a84e134Smrg ; 3737a84e134Smrg 3747a84e134Smrg /* Get column width */ 3757a84e134Smrg if (LongestFree(lw)) { 376efbcb2bfSmrg int i; 377efbcb2bfSmrg 3787a84e134Smrg lw->list.longest = 0; /* so it will accumulate real longest below */ 3797a84e134Smrg 3807a84e134Smrg for (i = 0 ; i < lw->list.nitems; i++) { 381efbcb2bfSmrg int len; 382efbcb2bfSmrg 3837a84e134Smrg if (lw->simple.international == True) 3847a84e134Smrg len = XmbTextEscapement(lw->list.fontset, lw->list.list[i], 3855ec34c4cSmrg (int)strlen(lw->list.list[i])); 3867a84e134Smrg else 3877a84e134Smrg len = XTextWidth(lw->list.font, lw->list.list[i], 3885ec34c4cSmrg (int)strlen(lw->list.list[i])); 3897a84e134Smrg if (len > lw->list.longest) 3907a84e134Smrg lw->list.longest = len; 3917a84e134Smrg } 3927a84e134Smrg } 3937a84e134Smrg 3947a84e134Smrg lw->list.col_width = lw->list.longest + lw->list.column_space; 3957a84e134Smrg} 3967a84e134Smrg 3977a84e134Smrg/* 3987a84e134Smrg * Function: 3997a84e134Smrg * ResetList 4007a84e134Smrg * 4017a84e134Smrg * Parameters: 4027a84e134Smrg * w - list widget 4037a84e134Smrg * changex - allow the height or width to change? 4047a84e134Smrg * changey - "" 4057a84e134Smrg * 4067a84e134Smrg * Description: 4077a84e134Smrg * Resets the new list when important things change. 4087a84e134Smrg * 4097a84e134Smrg * Returns: 4107a84e134Smrg * True if width or height have been changed 4117a84e134Smrg */ 4127a84e134Smrgstatic void 4137a84e134SmrgResetList(Widget w, Bool changex, Bool changey) 4147a84e134Smrg{ 4157a84e134Smrg Dimension width = XtWidth(w); 4167a84e134Smrg Dimension height = XtHeight(w); 4177a84e134Smrg 4187a84e134Smrg CalculatedValues(w); 4197a84e134Smrg 4207a84e134Smrg if (Layout(w, changex, changey, &width, &height)) { 4217a84e134Smrg if (XtIsComposite(XtParent(w))) 4227a84e134Smrg ChangeSize(w, width, height); 4237a84e134Smrg else { 4247a84e134Smrg XtWidth(w) = width; 4257a84e134Smrg XtHeight(w) = height; 4267a84e134Smrg } 4277a84e134Smrg } 4287a84e134Smrg} 4297a84e134Smrg 4307a84e134Smrg/* 4317a84e134Smrg * Function: 4327a84e134Smrg * ChangeSize 4337a84e134Smrg * 4347a84e134Smrg * Parameters: 4357a84e134Smrg * w - widget to try change the size of 4367a84e134Smrg * 4377a84e134Smrg * Description: 4387a84e134Smrg * Laysout the widget. 4397a84e134Smrg */ 4407a84e134Smrgstatic void 4417a84e134SmrgChangeSize(Widget w, unsigned int width, unsigned int height) 4427a84e134Smrg{ 443efbcb2bfSmrg XtWidgetGeometry request = { 444efbcb2bfSmrg .request_mode = CWWidth | CWHeight, 445efbcb2bfSmrg .width = (Dimension)width, 446efbcb2bfSmrg .height = (Dimension)height 447efbcb2bfSmrg }; 448efbcb2bfSmrg XtWidgetGeometry reply; 4497a84e134Smrg 4507a84e134Smrg switch (XtMakeGeometryRequest(w, &request, &reply)) { 4517a84e134Smrg case XtGeometryYes: 4527a84e134Smrg case XtGeometryNo: 4537a84e134Smrg break; 4547a84e134Smrg case XtGeometryAlmost: 4557a84e134Smrg Layout(w, request.height != reply.height, 4567a84e134Smrg request.width != reply.width, &reply.width, &reply.height); 4577a84e134Smrg request = reply; 4587a84e134Smrg switch (XtMakeGeometryRequest(w, &request, &reply)) { 4597a84e134Smrg case XtGeometryYes: 4607a84e134Smrg case XtGeometryNo: 4617a84e134Smrg break; 4627a84e134Smrg case XtGeometryAlmost: 4637a84e134Smrg request = reply; 4647a84e134Smrg Layout(w, False, False, &request.width, &request.height); 4657a84e134Smrg request.request_mode = CWWidth | CWHeight; 4667a84e134Smrg XtMakeGeometryRequest(w, &request, &reply); 4675b16253fSmrg /*FALLTHROUGH*/ 4687a84e134Smrg default: 4697a84e134Smrg break; 4707a84e134Smrg } 4715b16253fSmrg /*FALLTHROUGH*/ 4727a84e134Smrg default: 4737a84e134Smrg break; 4747a84e134Smrg } 4757a84e134Smrg} 4767a84e134Smrg 4777a84e134Smrg/*ARGSUSED*/ 478421c997bSmrgstatic void 4795ec34c4cSmrgXawListInitialize(Widget temp1 _X_UNUSED, Widget cnew, ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 4807a84e134Smrg{ 4817a84e134Smrg ListWidget lw = (ListWidget)cnew; 4827a84e134Smrg 4837a84e134Smrg if (!lw->list.font) XtError("Aborting: no font found\n"); 484421c997bSmrg if (lw->simple.international && !lw->list.fontset) 4857a84e134Smrg XtError("Aborting: no fontset found\n"); 486421c997bSmrg 4877a84e134Smrg /* 4887a84e134Smrg * Initialize all private resources 4897a84e134Smrg */ 4907a84e134Smrg /* record for posterity if we are free */ 4917a84e134Smrg lw->list.freedoms = ((XtWidth(lw) != 0) * WidthLock + 4927a84e134Smrg (XtHeight(lw) != 0) * HeightLock + 4937a84e134Smrg (lw->list.longest != 0) * LongestLock); 4947a84e134Smrg 4957a84e134Smrg GetGCs(cnew); 4967a84e134Smrg 4977a84e134Smrg /* Set row height, based on font or fontset */ 4987a84e134Smrg if (lw->simple.international == True) 4997a84e134Smrg lw->list.row_height = 5007a84e134Smrg XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height + 5017a84e134Smrg lw->list.row_space; 5027a84e134Smrg else 5037a84e134Smrg lw->list.row_height = lw->list.font->max_bounds.ascent + 5047a84e134Smrg lw->list.font->max_bounds.descent + 5057a84e134Smrg lw->list.row_space; 5067a84e134Smrg 5077a84e134Smrg ResetList(cnew, WidthFree(lw), HeightFree(lw)); 5087a84e134Smrg 5097a84e134Smrg lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT; 5107a84e134Smrg} 5117a84e134Smrg 5127a84e134Smrg/* 5137a84e134Smrg * Function: 5147a84e134Smrg * CvtToItem 5157a84e134Smrg * 5167a84e134Smrg * Parameters: 5177a84e134Smrg * w - list widget 5187a84e134Smrg * xloc - x location 5197a84e134Smrg * yloc - y location 5207a84e134Smrg * 5217a84e134Smrg * Description: 5227a84e134Smrg * Converts Xcoord to item number of item containing that point. 5237a84e134Smrg * 5247a84e134Smrg * Returns: 5257a84e134Smrg * Item number 5267a84e134Smrg */ 5277a84e134Smrgstatic int 5287a84e134SmrgCvtToItem(Widget w, int xloc, int yloc, int *item) 5297a84e134Smrg{ 5307a84e134Smrg int one, another; 5317a84e134Smrg ListWidget lw = (ListWidget)w; 5327a84e134Smrg int ret_val = OKAY; 5337a84e134Smrg 5347a84e134Smrg if (lw->list.vertical_cols) { 5357a84e134Smrg one = lw->list.nrows * ((xloc - (int)lw->list.internal_width) 5367a84e134Smrg / lw->list.col_width); 5377a84e134Smrg another = (yloc - (int)lw->list.internal_height) / lw->list.row_height; 5387a84e134Smrg /* If out of range, return minimum possible value */ 5397a84e134Smrg if (another >= lw->list.nrows) { 5407a84e134Smrg another = lw->list.nrows - 1; 5417a84e134Smrg ret_val = OUT_OF_RANGE; 5427a84e134Smrg } 5437a84e134Smrg } 5447a84e134Smrg else { 5457a84e134Smrg one = (lw->list.ncols * ((yloc - (int)lw->list.internal_height) 5467a84e134Smrg / lw->list.row_height)); 5477a84e134Smrg /* If in right margin handle things right */ 5487a84e134Smrg another = (xloc - (int)lw->list.internal_width) / lw->list.col_width; 5497a84e134Smrg if (another >= lw->list.ncols) { 550421c997bSmrg another = lw->list.ncols - 1; 5517a84e134Smrg ret_val = OUT_OF_RANGE; 5527a84e134Smrg } 553421c997bSmrg } 5547a84e134Smrg if (xloc < 0 || yloc < 0) 5557a84e134Smrg ret_val = OUT_OF_RANGE; 5567a84e134Smrg if (one < 0) 5577a84e134Smrg one = 0; 5587a84e134Smrg if (another < 0) 5597a84e134Smrg another = 0; 5607a84e134Smrg *item = one + another; 5617a84e134Smrg if (*item >= lw->list.nitems) 5627a84e134Smrg return (OUT_OF_RANGE); 5637a84e134Smrg 5647a84e134Smrg return (ret_val); 5657a84e134Smrg} 5667a84e134Smrg 5677a84e134Smrg/* 5687a84e134Smrg * Function: 5697a84e134Smrg * FindCornerItems 5707a84e134Smrg * 5717a84e134Smrg * Arguments: 5727a84e134Smrg * w - list widget 5737a84e134Smrg * event - event structure that has the rectangle it it 5747a84e134Smrg * ul_ret - the corners (return) 5757a84e134Smrg * lr_ret - "" 5767a84e134Smrg * 5777a84e134Smrg * Description: 5787a84e134Smrg * Find the corners of the rectangle in item space. 5797a84e134Smrg */ 5807a84e134Smrgstatic void 5817a84e134SmrgFindCornerItems(Widget w, XEvent *event, int *ul_ret, int *lr_ret) 5827a84e134Smrg{ 5837a84e134Smrg int xloc, yloc; 5847a84e134Smrg 5857a84e134Smrg xloc = event->xexpose.x; 5867a84e134Smrg yloc = event->xexpose.y; 5877a84e134Smrg CvtToItem(w, xloc, yloc, ul_ret); 5887a84e134Smrg xloc += event->xexpose.width; 5897a84e134Smrg yloc += event->xexpose.height; 5907a84e134Smrg CvtToItem(w, xloc, yloc, lr_ret); 5917a84e134Smrg} 5927a84e134Smrg 5937a84e134Smrg/* 5947a84e134Smrg * Function: 5957a84e134Smrg * ItemInRectangle 5967a84e134Smrg * 5977a84e134Smrg * Parameters: 5987a84e134Smrg * w - list widget 5997a84e134Smrg * ul - corners of the rectangle in item space 6007a84e134Smrg * lr - "" 6017a84e134Smrg * item - item to check 6027a84e134Smrg * 6037a84e134Smrg * Returns: 6047a84e134Smrg * True if the item passed is in the given rectangle 6057a84e134Smrg */ 6067a84e134Smrgstatic Bool 6077a84e134SmrgItemInRectangle(Widget w, int ul, int lr, int item) 6087a84e134Smrg{ 6097a84e134Smrg ListWidget lw = (ListWidget)w; 6107a84e134Smrg int mod_item; 6117a84e134Smrg int things; 612421c997bSmrg 613421c997bSmrg if (item < ul || item > lr) 6147a84e134Smrg return (False); 6157a84e134Smrg if (lw->list.vertical_cols) 6167a84e134Smrg things = lw->list.nrows; 6177a84e134Smrg else 6187a84e134Smrg things = lw->list.ncols; 6197a84e134Smrg 6207a84e134Smrg mod_item = item % things; 6217a84e134Smrg if ((mod_item >= ul % things) && (mod_item <= lr % things)) 6227a84e134Smrg return (True); 6237a84e134Smrg 6247a84e134Smrg return (False); 6257a84e134Smrg} 6267a84e134Smrg 6277a84e134Smrg/* HighlightBackground() 6287a84e134Smrg * 6297a84e134Smrg * Paints the color of the background for the given item. It performs 6307a84e134Smrg * clipping to the interior of internal_width/height by hand, as its a 6317a84e134Smrg * simple calculation and probably much faster than using Xlib and a clip mask. 6327a84e134Smrg * 6337a84e134Smrg * x, y - ul corner of the area item occupies. 6347a84e134Smrg * gc - the gc to use to paint this rectangle 6357a84e134Smrg */ 6367a84e134Smrgstatic void 6377a84e134SmrgHighlightBackground(Widget w, int x, int y, GC gc) 6387a84e134Smrg{ 6397a84e134Smrg ListWidget lw = (ListWidget)w; 6405ec34c4cSmrg Dimension width = (Dimension)lw->list.col_width; 6415ec34c4cSmrg Dimension height = (Dimension)lw->list.row_height; 6425ec34c4cSmrg Dimension frame_limited_width = (Dimension)(XtWidth(w) - lw->list.internal_width - x); 6435ec34c4cSmrg Dimension frame_limited_height= (Dimension)(XtHeight(w) - lw->list.internal_height - y); 6447a84e134Smrg 6457a84e134Smrg /* Clip the rectangle width and height to the edge of the drawable area */ 6467a84e134Smrg if (width > frame_limited_width) 6477a84e134Smrg width = frame_limited_width; 6487a84e134Smrg if (height > frame_limited_height) 6497a84e134Smrg height = frame_limited_height; 6507a84e134Smrg 6517a84e134Smrg /* Clip the rectangle x and y to the edge of the drawable area */ 6527a84e134Smrg if (x < lw->list.internal_width) { 6535ec34c4cSmrg width = (Dimension)(width - (lw->list.internal_width - x)); 6547a84e134Smrg x = lw->list.internal_width; 6557a84e134Smrg } 6567a84e134Smrg if (y < lw->list.internal_height) { 6575ec34c4cSmrg height = (Dimension)(height - (lw->list.internal_height - y)); 6587a84e134Smrg y = lw->list.internal_height; 6597a84e134Smrg } 6607a84e134Smrg 6617a84e134Smrg if (gc == lw->list.revgc && lw->core.background_pixmap != XtUnspecifiedPixmap) 6627a84e134Smrg XClearArea(XtDisplay(w), XtWindow(w), x, y, width, height, False); 6637a84e134Smrg else 6647a84e134Smrg XFillRectangle(XtDisplay(w), XtWindow(w), gc, x, y, width, height); 6657a84e134Smrg} 6667a84e134Smrg 6677a84e134Smrg 6687a84e134Smrg/* ClipToShadowInteriorAndLongest() 6697a84e134Smrg * 6707a84e134Smrg * Converts the passed gc so that any drawing done with that GC will not 6717a84e134Smrg * write in the empty margin (specified by internal_width/height) (which also 6727a84e134Smrg * prevents erasing the shadow. It also clips against the value longest. 6737a84e134Smrg * If the user doesn't set longest, this has no effect (as longest is the 6747a84e134Smrg * maximum of all item lengths). If the user does specify, say, 80 pixel 6757a84e134Smrg * columns, though, this prevents items from overwriting other items. 6767a84e134Smrg */ 6777a84e134Smrgstatic void 6787a84e134SmrgClipToShadowInteriorAndLongest(ListWidget lw, GC *gc_p, unsigned int x) 6797a84e134Smrg{ 680efbcb2bfSmrg XRectangle rect = { 681efbcb2bfSmrg .x = (short)x, 682efbcb2bfSmrg .y = (short)lw->list.internal_height, 683efbcb2bfSmrg .height = (unsigned short) 684efbcb2bfSmrg (XtHeight(lw) - (lw->list.internal_height << 1)), 685efbcb2bfSmrg .width = (unsigned short) 686efbcb2bfSmrg (XtWidth(lw) - (unsigned)lw->list.internal_width - x), 687efbcb2bfSmrg }; 6887a84e134Smrg 6897a84e134Smrg if (rect.width > lw->list.longest) 6905ec34c4cSmrg rect.width = (unsigned short)lw->list.longest; 6917a84e134Smrg 6927a84e134Smrg XSetClipRectangles(XtDisplay((Widget)lw), *gc_p, 0, 0, &rect, 1, YXBanded); 6937a84e134Smrg} 6947a84e134Smrg 6957a84e134Smrgstatic void 6967a84e134SmrgPaintItemName(Widget w, int item) 6977a84e134Smrg{ 6985ec34c4cSmrg _Xconst char *str; 6997a84e134Smrg GC gc; 7007a84e134Smrg int x, y, str_y; 7017a84e134Smrg ListWidget lw = (ListWidget)w; 7027a84e134Smrg XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset); 7037a84e134Smrg 7047a84e134Smrg if (!XtIsRealized(w) || item > lw->list.nitems) 7057a84e134Smrg return; 7067a84e134Smrg 7077a84e134Smrg if (lw->list.vertical_cols) { 7087a84e134Smrg x = lw->list.col_width * (item / lw->list.nrows) 7097a84e134Smrg + lw->list.internal_width; 7107a84e134Smrg y = lw->list.row_height * (item % lw->list.nrows) 7117a84e134Smrg + lw->list.internal_height; 7127a84e134Smrg } 7137a84e134Smrg else { 7147a84e134Smrg x = lw->list.col_width * (item % lw->list.ncols) 7157a84e134Smrg + lw->list.internal_width; 7167a84e134Smrg y = lw->list.row_height * (item / lw->list.ncols) 7177a84e134Smrg + lw->list.internal_height; 7187a84e134Smrg } 7197a84e134Smrg 7207a84e134Smrg if ( lw->simple.international == True ) 7217a84e134Smrg str_y = y + XawAbs(ext->max_ink_extent.y); 7227a84e134Smrg else 7237a84e134Smrg str_y = y + lw->list.font->max_bounds.ascent; 7247a84e134Smrg 7257a84e134Smrg if (item == lw->list.is_highlighted) { 7267a84e134Smrg if (item == lw->list.highlight) { 7277a84e134Smrg gc = lw->list.revgc; 7287a84e134Smrg HighlightBackground(w, x, y, lw->list.normgc); 7297a84e134Smrg } 7307a84e134Smrg else { 731421c997bSmrg if (XtIsSensitive(w)) 7327a84e134Smrg gc = lw->list.normgc; 7337a84e134Smrg else 7347a84e134Smrg gc = lw->list.graygc; 7357a84e134Smrg HighlightBackground(w, x, y, lw->list.revgc); 7367a84e134Smrg lw->list.is_highlighted = NO_HIGHLIGHT; 7377a84e134Smrg } 7387a84e134Smrg } 7397a84e134Smrg else { 7407a84e134Smrg if (item == lw->list.highlight) { 7417a84e134Smrg gc = lw->list.revgc; 7427a84e134Smrg HighlightBackground(w, x, y, lw->list.normgc); 7437a84e134Smrg lw->list.is_highlighted = item; 7447a84e134Smrg } 7457a84e134Smrg else { 746421c997bSmrg if (XtIsSensitive(w)) 7477a84e134Smrg gc = lw->list.normgc; 7487a84e134Smrg else 7497a84e134Smrg gc = lw->list.graygc; 7507a84e134Smrg } 7517a84e134Smrg } 7527a84e134Smrg 7537a84e134Smrg /* List's overall width contains the same number of inter-column 7547a84e134Smrg column_space's as columns. There should thus be a half 7557a84e134Smrg column_width margin on each side of each column. 7567a84e134Smrg The row case is symmetric */ 7577a84e134Smrg 7587a84e134Smrg x += lw->list.column_space >> 1; 7597a84e134Smrg str_y += lw->list.row_space >> 1; 7607a84e134Smrg 7617a84e134Smrg str = lw->list.list[item]; /* draw it */ 7627a84e134Smrg 7635ec34c4cSmrg ClipToShadowInteriorAndLongest(lw, &gc, (unsigned)x); 7647a84e134Smrg 7657a84e134Smrg if (lw->simple.international == True) 7667a84e134Smrg XmbDrawString(XtDisplay(w), XtWindow(w), lw->list.fontset, 7675ec34c4cSmrg gc, x, str_y, str, (int)strlen(str)); 7687a84e134Smrg else 7695ec34c4cSmrg XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, (int)strlen(str)); 7707a84e134Smrg 7717a84e134Smrg XSetClipMask(XtDisplay(w), gc, None); 7727a84e134Smrg} 7737a84e134Smrg 774421c997bSmrgstatic void 7757a84e134SmrgXawListRedisplay(Widget w, XEvent *event, Region region) 7767a84e134Smrg{ 7777a84e134Smrg int item; /* an item to work with */ 7787a84e134Smrg int ul_item, lr_item; /* corners of items we need to paint */ 7797a84e134Smrg ListWidget lw = (ListWidget)w; 7807a84e134Smrg 7817a84e134Smrg if (event == NULL) { 7827a84e134Smrg ul_item = 0; 7837a84e134Smrg lr_item = lw->list.nrows * lw->list.ncols - 1; 7847a84e134Smrg XClearWindow(XtDisplay(w), XtWindow(w)); 7857a84e134Smrg } 7867a84e134Smrg else 7877a84e134Smrg FindCornerItems(w, event, &ul_item, &lr_item); 7887a84e134Smrg 7897a84e134Smrg if (Superclass->core_class.expose) 7907a84e134Smrg (Superclass->core_class.expose)(w, event, region); 791421c997bSmrg 7927a84e134Smrg for (item = ul_item; item <= lr_item && item < lw->list.nitems; item++) 7937a84e134Smrg if (ItemInRectangle(w, ul_item, lr_item, item)) 7947a84e134Smrg PaintItemName(w, item); 7957a84e134Smrg} 7967a84e134Smrg 7977a84e134Smrg/* XawListQueryGeometry() 7987a84e134Smrg * 7997a84e134Smrg * This tells the parent what size we would like to be 8007a84e134Smrg * given certain constraints. 8017a84e134Smrg * w - the widget. 8027a84e134Smrg * intended - what the parent intends to do with us. 8037a84e134Smrg * requested - what we want to happen */ 804421c997bSmrgstatic XtGeometryResult 8057a84e134SmrgXawListQueryGeometry(Widget w, XtWidgetGeometry *intended, 8067a84e134Smrg XtWidgetGeometry *requested) 8077a84e134Smrg{ 8087a84e134Smrg Dimension new_width, new_height; 8097a84e134Smrg Bool change, width_req, height_req; 810421c997bSmrg 8117a84e134Smrg width_req = intended->request_mode & CWWidth; 8127a84e134Smrg height_req = intended->request_mode & CWHeight; 8137a84e134Smrg 8147a84e134Smrg if (width_req) 8157a84e134Smrg new_width = intended->width; 8167a84e134Smrg else 8177a84e134Smrg new_width = XtWidth(w); 8187a84e134Smrg 8197a84e134Smrg if (height_req) 8207a84e134Smrg new_height = intended->height; 8217a84e134Smrg else 8227a84e134Smrg new_height = XtHeight(w); 8237a84e134Smrg 8247a84e134Smrg requested->request_mode = 0; 825421c997bSmrg 8267a84e134Smrg /* 8277a84e134Smrg * We only care about our height and width 8287a84e134Smrg */ 8297a84e134Smrg if (!width_req && !height_req) 8307a84e134Smrg return (XtGeometryYes); 831421c997bSmrg 8327a84e134Smrg change = Layout(w, !width_req, !height_req, &new_width, &new_height); 8337a84e134Smrg 8347a84e134Smrg requested->request_mode |= CWWidth; 8357a84e134Smrg requested->width = new_width; 8367a84e134Smrg requested->request_mode |= CWHeight; 8377a84e134Smrg requested->height = new_height; 8387a84e134Smrg 8397a84e134Smrg if (change) 8407a84e134Smrg return (XtGeometryAlmost); 8417a84e134Smrg 8427a84e134Smrg return (XtGeometryYes); 8437a84e134Smrg} 8447a84e134Smrg 8457a84e134Smrgstatic void 8467a84e134SmrgXawListResize(Widget w) 8477a84e134Smrg{ 8487a84e134Smrg Dimension width, height; 8497a84e134Smrg 8507a84e134Smrg width = XtWidth(w); 8517a84e134Smrg height = XtHeight(w); 8527a84e134Smrg 8537a84e134Smrg if (Layout(w, False, False, &width, &height)) 8547a84e134Smrg XtAppWarning(XtWidgetToApplicationContext(w), 8557a84e134Smrg "List Widget: Size changed when it shouldn't " 8567a84e134Smrg "have when resising."); 8577a84e134Smrg} 8587a84e134Smrg 8597a84e134Smrg/* Layout() 8607a84e134Smrg * 8617a84e134Smrg * lays out the item in the list. 8627a84e134Smrg * w - the widget. 8637a84e134Smrg * xfree, yfree - True if we are free to resize the widget in 8647a84e134Smrg * this direction. 8657a84e134Smrg * width, height- the is the current width and height that we are going 8667a84e134Smrg * we are going to layout the list widget to, 8677a84e134Smrg * depending on xfree and yfree of course. 868421c997bSmrg * 8697a84e134Smrg * Return: 8707a84e134Smrg * True if width or height have been changed */ 8717a84e134Smrgstatic Bool 8727a84e134SmrgLayout(Widget w, Bool xfree, Bool yfree, Dimension *width, Dimension *height) 8737a84e134Smrg{ 8747a84e134Smrg ListWidget lw = (ListWidget)w; 8757a84e134Smrg Bool change = False; 8767a84e134Smrg unsigned long width2 = 0, height2 = 0; 8777a84e134Smrg 8787a84e134Smrg /* 8797a84e134Smrg * If force columns is set then always use number of columns specified 8807a84e134Smrg * by default_cols 8817a84e134Smrg */ 8827a84e134Smrg if (lw->list.force_cols) { 8837a84e134Smrg lw->list.ncols = lw->list.default_cols; 8847a84e134Smrg if (lw->list.ncols <= 0) 8857a84e134Smrg lw->list.ncols = 1; 8867a84e134Smrg lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; 8877a84e134Smrg if (xfree) { 8887a84e134Smrg /* this counts the same number 8897a84e134Smrg of inter-column column_space 's as columns. There should thus 8907a84e134Smrg be a half column_space margin on each side of each column...*/ 8915ec34c4cSmrg width2 = (unsigned long)(lw->list.ncols * lw->list.col_width + 8925ec34c4cSmrg (lw->list.internal_width << 1)); 8937a84e134Smrg change = True; 8947a84e134Smrg } 8957a84e134Smrg if (yfree) { 8965ec34c4cSmrg height2 = (unsigned long)(lw->list.nrows * lw->list.row_height + 8975ec34c4cSmrg (lw->list.internal_height << 1)); 8987a84e134Smrg change = True; 8997a84e134Smrg } 9007a84e134Smrg } 9017a84e134Smrg 9027a84e134Smrg /* 9037a84e134Smrg * If both width and height are free to change the use default_cols 9047a84e134Smrg * to determine the number columns and set new width and height to 9057a84e134Smrg * just fit the window 9067a84e134Smrg */ 9077a84e134Smrg else if (xfree && yfree) { 9087a84e134Smrg lw->list.ncols = lw->list.default_cols; 9097a84e134Smrg if (lw->list.ncols <= 0) { 9107a84e134Smrg int wid = (int)XtWidth(lw) - (int)(lw->list.internal_width << 1) 9117a84e134Smrg + (int)lw->list.column_space; 9127a84e134Smrg 9137a84e134Smrg if (wid <= 0 || lw->list.col_width <= 0 9147a84e134Smrg || (lw->list.ncols = wid / lw->list.col_width) <= 0) 9157a84e134Smrg lw->list.ncols = 1; 9167a84e134Smrg } 9175ec34c4cSmrg width2 = (unsigned long)((lw->list.ncols * lw->list.col_width) 9185ec34c4cSmrg + (lw->list.internal_width << 1)); 9195ec34c4cSmrg height2 = (unsigned long)((lw->list.nrows * lw->list.row_height) 9205ec34c4cSmrg + (lw->list.internal_height << 1)); 9217a84e134Smrg change = True; 9227a84e134Smrg } 9237a84e134Smrg 9247a84e134Smrg /* 9257a84e134Smrg * If the width is fixed then use it to determine the number of columns. 9267a84e134Smrg * If the height is free to move (width still fixed) then resize the height 9277a84e134Smrg * of the widget to fit the current list exactly 9287a84e134Smrg */ 9297a84e134Smrg else if (!xfree) { 9307a84e134Smrg lw->list.ncols = ((int)(*width - (lw->list.internal_width << 1)) 9317a84e134Smrg / (int)lw->list.col_width); 9327a84e134Smrg if (lw->list.ncols <= 0) 9337a84e134Smrg lw->list.ncols = 1; 9347a84e134Smrg lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; 9357a84e134Smrg if (yfree) { 9365ec34c4cSmrg height2 = (unsigned long)((lw->list.nrows * lw->list.row_height) + 9375ec34c4cSmrg (lw->list.internal_height << 1)); 9387a84e134Smrg change = True; 9397a84e134Smrg } 9407a84e134Smrg } 9417a84e134Smrg 9427a84e134Smrg /* 9437a84e134Smrg * The last case is xfree and !yfree we use the height to determine 9447a84e134Smrg * the number of rows and then set the width to just fit the resulting 9457a84e134Smrg * number of columns 9467a84e134Smrg */ 9477a84e134Smrg else if (!yfree) { 9487a84e134Smrg lw->list.nrows = ((int)(*height - (lw->list.internal_height << 1)) 9497a84e134Smrg / (int)lw->list.row_height); 9507a84e134Smrg if (lw->list.nrows <= 0) 9517a84e134Smrg lw->list.nrows = 1; 9527a84e134Smrg lw->list.ncols = ((lw->list.nitems - 1) / lw->list.nrows) + 1; 9535ec34c4cSmrg width2 = (unsigned long)((lw->list.ncols * lw->list.col_width) + 9545ec34c4cSmrg (lw->list.internal_width << 1)); 9557a84e134Smrg change = True; 9567a84e134Smrg } 9577a84e134Smrg 9587a84e134Smrg if (!lw->list.force_cols && lw->list.nrows) { 9597a84e134Smrg /*CONSTCOND*/ 9607a84e134Smrg while (1) { 9617a84e134Smrg lw->list.nrows = ((lw->list.nitems - 1) / lw->list.ncols) + 1; 9625ec34c4cSmrg width2 = (unsigned long)((lw->list.ncols * lw->list.col_width) + 9635ec34c4cSmrg (lw->list.internal_width << 1)); 9645ec34c4cSmrg height2 = (unsigned long)((lw->list.nrows * lw->list.row_height) + 9655ec34c4cSmrg (lw->list.internal_height << 1)); 9667a84e134Smrg if (width2 >= MaxSize && height2 >= MaxSize) 9677a84e134Smrg break; 9687a84e134Smrg if (height2 > MaxSize) 9697a84e134Smrg ++lw->list.ncols; 9707a84e134Smrg else if (width2 > MaxSize && lw->list.ncols > 1) 9717a84e134Smrg --lw->list.ncols; 9727a84e134Smrg else 9737a84e134Smrg break; 9747a84e134Smrg } 9757a84e134Smrg } 9767a84e134Smrg if (width2) 9775ec34c4cSmrg *width = (Dimension)width2; 9787a84e134Smrg if (height2) 9795ec34c4cSmrg *height = (Dimension)height2; 9807a84e134Smrg 9817a84e134Smrg return (change); 9827a84e134Smrg} 9837a84e134Smrg 9847a84e134Smrg/* Notify() - Action 9857a84e134Smrg * 9867a84e134Smrg * Notifies the user that a button has been pressed, and 9877a84e134Smrg * calls the callback; if the XtNpasteBuffer resource is true 9887a84e134Smrg * then the name of the item is also put in CUT_BUFFER0 */ 9897a84e134Smrg/*ARGSUSED*/ 9907a84e134Smrgstatic void 9915ec34c4cSmrgNotify(Widget w, XEvent *event, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 9927a84e134Smrg{ 9937a84e134Smrg ListWidget lw = (ListWidget)w; 9947a84e134Smrg int item, item_len; 9957a84e134Smrg 9967a84e134Smrg /* 9977a84e134Smrg * Find item and if out of range then unhighlight and return 998421c997bSmrg * 9997a84e134Smrg * If the current item is unhighlighted then the user has aborted the 10007a84e134Smrg * notify, so unhighlight and return 10017a84e134Smrg */ 10027a84e134Smrg if ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE) 10037a84e134Smrg || lw->list.highlight != item) { 10047a84e134Smrg#ifndef OLDXAW 10057a84e134Smrg if (!lw->list.show_current || lw->list.selected == NO_HIGHLIGHT) 10067a84e134Smrg XawListUnhighlight(w); 10077a84e134Smrg else 10087a84e134Smrg XawListHighlight(w, lw->list.selected); 10097a84e134Smrg#else 10107a84e134Smrg XawListUnhighlight(w); 10117a84e134Smrg#endif 10127a84e134Smrg return; 10137a84e134Smrg } 10147a84e134Smrg 10155ec34c4cSmrg item_len = (int)strlen(lw->list.list[item]); 10167a84e134Smrg 10177a84e134Smrg if (lw->list.paste) /* if XtNpasteBuffer set then paste it */ 10187a84e134Smrg XStoreBytes(XtDisplay(w), lw->list.list[item], item_len); 10197a84e134Smrg 10207a84e134Smrg#ifndef OLDXAW 10217a84e134Smrg lw->list.selected = item; 10227a84e134Smrg#endif 10237a84e134Smrg /* 10247a84e134Smrg * Call Callback function 10257a84e134Smrg */ 1026efbcb2bfSmrg { 1027efbcb2bfSmrg XawListReturnStruct ret_value = { 1028efbcb2bfSmrg .string = lw->list.list[item], 1029efbcb2bfSmrg .list_index = item 1030efbcb2bfSmrg }; 1031421c997bSmrg 1032efbcb2bfSmrg XtCallCallbacks(w, XtNcallback, (XtPointer)&ret_value); 1033efbcb2bfSmrg } 10347a84e134Smrg} 10357a84e134Smrg 10367a84e134Smrg/* Unset() - Action 10377a84e134Smrg * 10387a84e134Smrg * unhighlights the current element */ 10397a84e134Smrg/*ARGSUSED*/ 10407a84e134Smrgstatic void 10415ec34c4cSmrgUnset(Widget w, XEvent *event _X_UNUSED, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 10427a84e134Smrg{ 10437a84e134Smrg XawListUnhighlight(w); 10447a84e134Smrg} 10457a84e134Smrg 10467a84e134Smrg/* Set() - Action 10477a84e134Smrg * 10487a84e134Smrg * Highlights the current element */ 10497a84e134Smrg/*ARGSUSED*/ 10507a84e134Smrgstatic void 10515ec34c4cSmrgSet(Widget w, XEvent *event, String *params _X_UNUSED, Cardinal *num_params _X_UNUSED) 10527a84e134Smrg{ 10537a84e134Smrg int item; 10547a84e134Smrg ListWidget lw = (ListWidget)w; 10557a84e134Smrg 10567a84e134Smrg#ifndef OLDXAW 10577a84e134Smrg lw->list.selected = lw->list.highlight; 10587a84e134Smrg#endif 10597a84e134Smrg if (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item) == OUT_OF_RANGE) 10607a84e134Smrg XawListUnhighlight(w); /* Unhighlight current item */ 10617a84e134Smrg else if (lw->list.is_highlighted != item) /* If this item is not */ 10627a84e134Smrg XawListHighlight(w, item); /* highlighted then do it */ 10637a84e134Smrg} 10647a84e134Smrg 10657a84e134Smrg/* 10667a84e134Smrg * Set specified arguments into widget 10677a84e134Smrg */ 10687a84e134Smrg/*ARGSUSED*/ 1069421c997bSmrgstatic Boolean 10707a84e134SmrgXawListSetValues(Widget current, Widget request, Widget cnew, 10715ec34c4cSmrg ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 10727a84e134Smrg{ 10737a84e134Smrg ListWidget cl = (ListWidget)current; 10747a84e134Smrg ListWidget rl = (ListWidget)request; 10757a84e134Smrg ListWidget nl = (ListWidget)cnew; 10767a84e134Smrg Bool redraw = False; 10777a84e134Smrg XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset); 10787a84e134Smrg 10797a84e134Smrg /* If the request height/width is different, lock it. Unless its 0. If 10807a84e134Smrg neither new nor 0, leave it as it was. Not in R5 */ 10817a84e134Smrg if (XtWidth(nl) != XtWidth(cl)) 10827a84e134Smrg nl->list.freedoms |= WidthLock; 10837a84e134Smrg if (XtWidth(nl) == 0) 10847a84e134Smrg nl->list.freedoms &= ~WidthLock; 10857a84e134Smrg 10867a84e134Smrg if (XtHeight(nl) != XtHeight(cl)) 10877a84e134Smrg nl->list.freedoms |= HeightLock; 10887a84e134Smrg if (XtHeight(nl) == 0) 10897a84e134Smrg nl->list.freedoms &= ~HeightLock; 10907a84e134Smrg 10917a84e134Smrg if (nl->list.longest != cl->list.longest) 10927a84e134Smrg nl->list.freedoms |= LongestLock; 10937a84e134Smrg if (nl->list.longest == 0) 10947a84e134Smrg nl->list.freedoms &= ~LongestLock; 10957a84e134Smrg 10967a84e134Smrg if (cl->list.foreground != nl->list.foreground || 10977a84e134Smrg cl->core.background_pixel != nl->core.background_pixel || 10987a84e134Smrg cl->list.font != nl->list.font) { 10997a84e134Smrg XGCValues values; 11007a84e134Smrg 11017a84e134Smrg XGetGCValues(XtDisplay(current), cl->list.graygc, GCTile, &values); 11027a84e134Smrg XmuReleaseStippledPixmap(XtScreen(current), values.tile); 11037a84e134Smrg XtReleaseGC(current, cl->list.graygc); 11047a84e134Smrg XtReleaseGC(current, cl->list.revgc); 11057a84e134Smrg XtReleaseGC(current, cl->list.normgc); 11067a84e134Smrg GetGCs(cnew); 11077a84e134Smrg redraw = True; 11087a84e134Smrg } 11097a84e134Smrg 11107a84e134Smrg if (cl->list.font != nl->list.font && cl->simple.international == False) 11117a84e134Smrg nl->list.row_height = nl->list.font->max_bounds.ascent 11127a84e134Smrg + nl->list.font->max_bounds.descent 11137a84e134Smrg + nl->list.row_space; 11147a84e134Smrg else if (cl->list.fontset != nl->list.fontset 11157a84e134Smrg && cl->simple.international == True) 11167a84e134Smrg nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; 11177a84e134Smrg 11187a84e134Smrg /* ...If the above two font(set) change checkers above both failed, check 11197a84e134Smrg if row_space was altered. If one of the above passed, row_height will 11207a84e134Smrg already have been re-calculated */ 11217a84e134Smrg else if (cl->list.row_space != nl->list.row_space) { 11227a84e134Smrg if (cl->simple.international == True) 11237a84e134Smrg nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; 11247a84e134Smrg else 11257a84e134Smrg nl->list.row_height = nl->list.font->max_bounds.ascent 11267a84e134Smrg + nl->list.font->max_bounds.descent 11277a84e134Smrg + nl->list.row_space; 11287a84e134Smrg } 11297a84e134Smrg 11307a84e134Smrg if (XtWidth(cl) != XtWidth(nl) || XtHeight(cl) != XtHeight(nl) 11317a84e134Smrg || cl->list.internal_width != nl->list.internal_width 11327a84e134Smrg || cl->list.internal_height != nl->list.internal_height 11337a84e134Smrg || cl->list.column_space != nl->list.column_space 11347a84e134Smrg || cl->list.row_space != nl->list.row_space 11357a84e134Smrg || cl->list.default_cols != nl->list.default_cols 11367a84e134Smrg || (cl->list.force_cols != nl->list.force_cols 11377a84e134Smrg && rl->list.force_cols != nl->list.ncols) 11387a84e134Smrg || cl->list.vertical_cols != nl->list.vertical_cols 11397a84e134Smrg || cl->list.longest != nl->list.longest 11407a84e134Smrg || cl->list.nitems != nl->list.nitems 11417a84e134Smrg || cl->list.font != nl->list.font 11427a84e134Smrg /* Equiv. fontsets might have different values, but the same fonts, 11437a84e134Smrg so the next comparison is sloppy but not dangerous */ 11447a84e134Smrg || cl->list.fontset != nl->list.fontset 11457a84e134Smrg || cl->list.list != nl->list.list) { 11467a84e134Smrg CalculatedValues(cnew); 11477a84e134Smrg Layout(cnew, WidthFree(nl), HeightFree(nl), 11487a84e134Smrg &nl->core.width, &nl->core.height); 11497a84e134Smrg redraw = True; 11507a84e134Smrg } 11517a84e134Smrg 11527a84e134Smrg if (cl->list.list != nl->list.list || cl->list.nitems != nl->list.nitems) 11537a84e134Smrg nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT; 11547a84e134Smrg 11557a84e134Smrg if (cl->core.sensitive != nl->core.sensitive 11567a84e134Smrg || cl->core.ancestor_sensitive != nl->core.ancestor_sensitive) { 11577a84e134Smrg nl->list.highlight = NO_HIGHLIGHT; 11587a84e134Smrg redraw = True; 11597a84e134Smrg } 1160421c997bSmrg 11615ec34c4cSmrg return (Boolean)(redraw); 11627a84e134Smrg} 11637a84e134Smrg 11647a84e134Smrgstatic void 11657a84e134SmrgXawListDestroy(Widget w) 11667a84e134Smrg{ 11677a84e134Smrg ListWidget lw = (ListWidget)w; 11687a84e134Smrg XGCValues values; 1169421c997bSmrg 11707a84e134Smrg XGetGCValues(XtDisplay(w), lw->list.graygc, GCTile, &values); 11717a84e134Smrg XmuReleaseStippledPixmap(XtScreen(w), values.tile); 11727a84e134Smrg XtReleaseGC(w, lw->list.graygc); 11737a84e134Smrg XtReleaseGC(w, lw->list.revgc); 11747a84e134Smrg XtReleaseGC(w, lw->list.normgc); 11757a84e134Smrg} 11767a84e134Smrg 11777a84e134Smrg/* 11787a84e134Smrg * Function: 11797a84e134Smrg * XawListChange 11807a84e134Smrg * 11817a84e134Smrg * Parameters: 11827a84e134Smrg * w - list widget 11837a84e134Smrg * list - new list 11847a84e134Smrg * nitems - number of items in the list 11857a84e134Smrg * longest - length (in Pixels) of the longest element in the list 11867a84e134Smrg * resize - if True the the list widget will try to resize itself 11877a84e134Smrg * 11887a84e134Smrg * Description: 11897a84e134Smrg * Changes the list being used and shown. 11907a84e134Smrg * 11917a84e134Smrg * Note: 11927a84e134Smrg * If nitems of longest are <= 0 then they will be calculated 11937a84e134Smrg * If nitems is <= 0 then the list needs to be NULL terminated 11947a84e134Smrg */ 11957a84e134Smrgvoid 1196efbcb2bfSmrgXawListChange(Widget w, String *list, int nitems, int longest, 11977a84e134Smrg#if NeedWidePrototypes 11987a84e134Smrg int resize_it 11997a84e134Smrg#else 12007a84e134Smrg Boolean resize_it 12017a84e134Smrg#endif 12027a84e134Smrg) 12037a84e134Smrg{ 12047a84e134Smrg ListWidget lw = (ListWidget)w; 12057a84e134Smrg Dimension new_width = XtWidth(w); 12067a84e134Smrg Dimension new_height = XtHeight(w); 12077a84e134Smrg 12087a84e134Smrg lw->list.list = list; 12097a84e134Smrg 12107a84e134Smrg if (nitems <= 0) 12117a84e134Smrg nitems = 0; 12127a84e134Smrg lw->list.nitems = nitems; 12137a84e134Smrg if (longest <= 0) 12147a84e134Smrg longest = 0; 12157a84e134Smrg 12167a84e134Smrg /* If the user passes 0 meaning "calculate it", it must be free */ 12177a84e134Smrg if (longest != 0) 12187a84e134Smrg lw->list.freedoms |= LongestLock; 12197a84e134Smrg else 12207a84e134Smrg lw->list.freedoms &= ~LongestLock; 12217a84e134Smrg 12227a84e134Smrg if (resize_it) 12237a84e134Smrg lw->list.freedoms &= ~WidthLock & ~HeightLock; 12247a84e134Smrg 12257a84e134Smrg lw->list.longest = longest; 12267a84e134Smrg 12277a84e134Smrg CalculatedValues(w); 12287a84e134Smrg 12297a84e134Smrg if (Layout(w, WidthFree(w), HeightFree(w), &new_width, &new_height)) 12307a84e134Smrg ChangeSize(w, new_width, new_height); 12317a84e134Smrg 12327a84e134Smrg lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT; 12337a84e134Smrg if (XtIsRealized(w)) 12347a84e134Smrg XawListRedisplay(w, NULL, NULL); 12357a84e134Smrg} 12367a84e134Smrg 12377a84e134Smrgvoid 12387a84e134SmrgXawListUnhighlight(Widget w) 12397a84e134Smrg{ 12407a84e134Smrg ListWidget lw = (ListWidget)w; 12417a84e134Smrg 12427a84e134Smrg lw->list.highlight = NO_HIGHLIGHT; 12437a84e134Smrg if (lw->list.is_highlighted != NO_HIGHLIGHT) 12447a84e134Smrg PaintItemName(w, lw->list.is_highlighted); 12457a84e134Smrg} 12467a84e134Smrg 12477a84e134Smrgvoid 12487a84e134SmrgXawListHighlight(Widget w, int item) 12497a84e134Smrg{ 12507a84e134Smrg ListWidget lw = (ListWidget)w; 1251421c997bSmrg 12527a84e134Smrg if (XtIsSensitive(w)) { 12537a84e134Smrg lw->list.highlight = item; 12547a84e134Smrg if (lw->list.is_highlighted != NO_HIGHLIGHT) 12557a84e134Smrg PaintItemName(w, lw->list.is_highlighted); 12567a84e134Smrg PaintItemName(w, item); 12577a84e134Smrg } 12587a84e134Smrg} 12597a84e134Smrg 12607a84e134Smrg/* 12617a84e134Smrg * Function: 12627a84e134Smrg * XawListShowCurrent 12637a84e134Smrg * 12647a84e134Smrg * Parameters: 12657a84e134Smrg * w - list widget 12667a84e134Smrg * 12677a84e134Smrg * Returns: 12687a84e134Smrg * Info about the currently highlighted object 12697a84e134Smrg */ 12707a84e134SmrgXawListReturnStruct * 12717a84e134SmrgXawListShowCurrent(Widget w) 12727a84e134Smrg{ 12737a84e134Smrg ListWidget lw = (ListWidget)w; 12747a84e134Smrg XawListReturnStruct *ret_val; 12757a84e134Smrg 12767a84e134Smrg ret_val = (XawListReturnStruct *)XtMalloc(sizeof(XawListReturnStruct)); 1277421c997bSmrg 12787a84e134Smrg ret_val->list_index = lw->list.highlight; 12797a84e134Smrg if (ret_val->list_index == XAW_LIST_NONE) 12807a84e134Smrg ret_val->string = ""; 12817a84e134Smrg else 12827a84e134Smrg ret_val->string = lw->list.list[ret_val->list_index]; 12837a84e134Smrg 12847a84e134Smrg return (ret_val); 12857a84e134Smrg} 1286