]> andersk Git - moira.git/blob - clients/cluster/MList.c
Diane Delgado's changes for a fixed table-locking order
[moira.git] / clients / cluster / MList.c
1 #if ( !defined(lint) && !defined(SABER))
2   static char Xrcs_id[] = "$XConsortium: MList.c,v 1.29 90/05/08 15:16:32 converse Exp $";
3 #endif
4
5 /*
6  * Copyright 1989 Massachusetts Institute of Technology
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and its
9  * documentation for any purpose is hereby granted without fee, provided that
10  * the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the name of M.I.T. not be used in advertising or
13  * publicity pertaining to distribution of the software without specific,
14  * written prior permission.  M.I.T. makes no representations about the
15  * suitability of this software for any purpose.  It is provided "as is"
16  * without express or implied warranty.
17  *
18  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
20  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
23  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  */
26
27 /*
28  * MList.c - MList widget
29  *
30  * This is the MList widget, it is useful to display a list, without the
31  * overhead of having a widget for each item in the list.  It allows 
32  * the user to select an item in a list and notifies the application through
33  * a callback function.
34  *
35  *      Created:        8/13/88
36  *      By:             Chris D. Peterson
37  *                      MIT X Consortium
38  */
39
40 #include <stdio.h>
41 #include <ctype.h>
42
43 #include <X11/IntrinsicP.h>
44 #include <X11/StringDefs.h>
45
46 #include <X11/Xmu/Drawing.h>
47
48 #include <X11/Xaw/XawInit.h>
49 #include "MListP.h"
50
51
52 /* 
53  * Default Translation table.
54  */
55
56 static char defaultTranslations[] =  
57   "<Btn1Down>:   Set()\n\
58    <Btn1Up>:     Notify()";
59
60 /****************************************************************
61  *
62  * Full class record constant
63  *
64  ****************************************************************/
65
66 /* Private Data */
67
68 #define offset(field) XtOffset(MListWidget, field)
69
70 static XtResource resources[] = {
71     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
72         offset(list.foreground), XtRString, "XtDefaultForeground"},
73     {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
74        offset(simple.cursor), XtRString, "left_ptr"},
75     {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
76         offset(list.font),XtRString, "XtDefaultFont"},
77     {XtNlist, XtCMList, XtRPointer, sizeof(char **),
78        offset(list.list), XtRString, NULL},
79     {XtNdefaultColumns, XtCColumns, XtRInt,  sizeof(int),
80         offset(list.default_cols), XtRImmediate, (caddr_t)2},
81     {XtNlongest, XtCLongest, XtRInt,  sizeof(int),
82         offset(list.longest), XtRImmediate, (caddr_t)0},
83     {XtNnumberStrings, XtCNumberStrings, XtRInt,  sizeof(int),
84         offset(list.nitems), XtRImmediate, (caddr_t)0},
85     {XtNpasteBuffer, XtCBoolean, XtRBoolean,  sizeof(Boolean),
86         offset(list.paste), XtRString, (caddr_t) "False"},
87     {XtNforceColumns, XtCColumns, XtRBoolean,  sizeof(Boolean),
88         offset(list.force_cols), XtRString, (caddr_t) "False"},
89     {XtNverticalList, XtCBoolean, XtRBoolean,  sizeof(Boolean),
90         offset(list.vertical_cols), XtRString, (caddr_t) "False"},
91     {XtNinternalWidth, XtCWidth, XtRDimension,  sizeof(Dimension),
92         offset(list.internal_width), XtRImmediate, (caddr_t)4},
93     {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
94         offset(list.internal_height), XtRImmediate, (caddr_t)2},
95     {XtNcolumnSpacing, XtCSpacing, XtRDimension,  sizeof(Dimension),
96         offset(list.column_space), XtRImmediate, (caddr_t)6},
97     {XtNrowSpacing, XtCSpacing, XtRDimension,  sizeof(Dimension),
98         offset(list.row_space), XtRImmediate, (caddr_t)2},
99     {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t),
100         offset(list.callback), XtRCallback, NULL},
101 };
102
103 static void Initialize();
104 static void ChangeSize();
105 static void Resize();
106 static void Redisplay();
107 static Boolean Layout();
108 static XtGeometryResult PreferredGeom();
109 static Boolean SetValues();
110 static void Notify(), Set(), Unset();
111
112 static XtActionsRec actions[] = {
113       {"Notify",         Notify},
114       {"Set",            Set},
115       {"Unset",          Unset},
116 };
117
118 MListClassRec mlistClassRec = {
119   {
120 /* core_class fields */ 
121 #define superclass              (&simpleClassRec)
122     /* superclass               */      (WidgetClass) superclass,
123     /* class_name               */      "MList",
124     /* widget_size              */      sizeof(MListRec),
125     /* class_initialize         */      XawInitializeWidgetSet,
126     /* class_part_initialize    */      NULL,
127     /* class_inited             */      FALSE,
128     /* initialize               */      Initialize,
129     /* initialize_hook          */      NULL,
130     /* realize                  */      XtInheritRealize,
131     /* actions                  */      actions,
132     /* num_actions              */      XtNumber(actions),
133     /* resources                */      resources,
134     /* num_resources            */      XtNumber(resources),
135     /* xrm_class                */      NULLQUARK,
136     /* compress_motion          */      TRUE,
137     /* compress_exposure        */      FALSE,
138     /* compress_enterleave      */      TRUE,
139     /* visible_interest         */      FALSE,
140     /* destroy                  */      NULL,
141     /* resize                   */      Resize,
142     /* expose                   */      Redisplay,
143     /* set_values               */      SetValues,
144     /* set_values_hook          */      NULL,
145     /* set_values_almost        */      XtInheritSetValuesAlmost,
146     /* get_values_hook          */      NULL,
147     /* accept_focus             */      NULL,
148     /* version                  */      XtVersion,
149     /* callback_private         */      NULL,
150     /* tm_table                 */      defaultTranslations,
151    /* query_geometry            */      PreferredGeom,
152   },
153 /* Simple class fields initialization */
154   {
155     /* change_sensitive         */      XtInheritChangeSensitive
156   }
157 };
158
159 WidgetClass mlistWidgetClass = (WidgetClass)&mlistClassRec;
160
161 /****************************************************************
162  *
163  * Private Procedures
164  *
165  ****************************************************************/
166
167 static void GetGCs(w)
168 Widget w;
169 {
170     XGCValues   values;
171     MListWidget lw = (MListWidget) w;    
172
173     values.foreground   = lw->list.foreground;
174     values.font         = lw->list.font->fid;
175     lw->list.normgc = XtGetGC(w, (unsigned) GCForeground | GCFont,
176                                  &values);
177
178     values.foreground   = lw->core.background_pixel;
179     lw->list.revgc = XtGetGC(w, (unsigned) GCForeground | GCFont,
180                                  &values);
181
182     values.tile       = XmuCreateStippledPixmap(XtScreen(w), 
183                                                 lw->list.foreground,
184                                                 lw->core.background_pixel,
185                                                 lw->core.depth);
186     values.fill_style = FillTiled;
187
188     lw->list.graygc = XtGetGC(w, (unsigned) GCFont | GCTile | GCFillStyle,
189                               &values);
190 }
191
192 /*      Function Name: ResetMList
193  *      Description: Resets the new list when important things change.
194  *      Arguments: w - the widget.
195  *                 changex, changey - allow the height or width to change?
196  *      Returns: none.
197  */
198
199 static void
200 ResetMList(w, changex, changey)
201 Widget w;
202 Boolean changex, changey;
203 {
204     MListWidget lw = (MListWidget) w;
205     Dimension width = w->core.width;
206     Dimension height = w->core.height;
207     register int i, len;
208
209 /*
210  * If list is NULL then the list will just be the name of the widget.
211  */
212
213     if (lw->list.list == NULL) {
214       lw->list.list = &(lw->core.name);
215       lw->list.nitems = 1;
216     }
217
218     if (lw->list.nitems == 0)       /* Get number of items. */
219         for ( ; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++);
220
221     if (lw->list.longest == 0) /* Get column width. */
222         for ( i = 0 ; i < lw->list.nitems; i++) {
223             len = XTextWidth(lw->list.font, lw->list.list[i],
224                              strlen(lw->list.list[i]));
225             if (len > lw->list.longest)
226                 lw->list.longest = len;
227         }
228
229     lw->list.col_width = lw->list.longest + lw->list.column_space;
230
231     if (Layout(w, changex, changey, &width, &height))
232       ChangeSize(w, width, height);
233 }
234
235 /*      Function Name: ChangeSize.
236  *      Description: Laysout the widget.
237  *      Arguments: w - the widget to try change the size of.
238  *      Returns: none.
239  */
240
241 static void
242 ChangeSize(w, width, height)
243 Widget w;
244 Dimension width, height;
245 {
246     XtWidgetGeometry request, reply;
247
248     request.request_mode = CWWidth | CWHeight;
249     request.width = width;
250     request.height = height;
251     
252     switch ( XtMakeGeometryRequest(w, &request, &reply) ) {
253     case XtGeometryYes:
254     case XtGeometryNo:
255         break;
256     case XtGeometryAlmost:
257         Layout(w, (request.height != reply.height),
258                   (request.width != reply.width),
259                &(reply.width), &(reply.height));
260         request = reply;
261         switch (XtMakeGeometryRequest(w, &request, &reply) ) {
262         case XtGeometryYes:
263         case XtGeometryNo:
264             break;
265         case XtGeometryAlmost:
266             request = reply;
267             if (Layout(w, FALSE, FALSE,
268                        &(request.width), &(request.height))) {
269               char buf[BUFSIZ];
270               sprintf(buf, "MList Widget: %s %s",
271                       "Size Changed when it shouldn't have",
272                       "when computing layout");
273               XtAppWarning(XtWidgetToApplicationContext(w), buf);
274             }
275             request.request_mode = CWWidth | CWHeight;
276             XtMakeGeometryRequest(w, &request, &reply);
277             break;
278         default:
279           XtAppWarning(XtWidgetToApplicationContext(w),
280                        "MList Widget: Unknown geometry return.");
281           break;
282         }
283         break;
284     default:
285         XtAppWarning(XtWidgetToApplicationContext(w),
286                      "MList Widget: Unknown geometry return.");
287         break;
288     }
289 }
290
291 /*      Function Name: Initialize
292  *      Description: Function that initilizes the widget instance.
293  *      Arguments: junk - NOT USED.
294  *                 new  - the new widget.
295  *      Returns: none
296  */
297
298 /* ARGSUSED */
299 static void 
300 Initialize(junk, new)
301 Widget junk, new;
302 {
303     MListWidget lw = (MListWidget) new;
304
305 /* 
306  * Initialize all private resources.
307  */
308
309     GetGCs(new);
310
311     /* Set row height. */
312     lw->list.row_height = lw->list.font->max_bounds.ascent
313                         + lw->list.font->max_bounds.descent
314                         + lw->list.row_space;
315
316     ResetMList(new, (new->core.width == 0), (new->core.height == 0));
317
318     lw->list.highlight = NO_HIGHLIGHT;
319     lw->list.nhighlighted = 0;
320     lw->list.is_highlighted = (int *) malloc(0);
321
322 } /* Initialize */
323
324
325
326 /*
327  * Determine if the specified item is selected
328  */
329
330 static Boolean
331 IsHighlit(lw, item)
332 MListWidget lw;
333 int item;
334 {
335     int i;
336
337     for (i = 0; i < lw->list.nhighlighted; i++) {
338         if (lw->list.is_highlighted[i] == item)
339           return True;
340     }
341     return False;
342 }
343
344
345 /*      Function Name: CvtToItem
346  *      Description: Converts Xcoord to item number of item containing that
347  *                   point.
348  *      Arguments: w - the list widget.
349  *                 xloc, yloc - x location, and y location.
350  *      Returns: the item number.
351  */
352
353 static int
354 CvtToItem(w, xloc, yloc, item)
355 Widget w;
356 int xloc, yloc;
357 int *item;
358 {
359     int one, another;
360     MListWidget lw = (MListWidget) w;
361     int ret_val = OKAY;
362
363     if (lw->list.vertical_cols) {
364         one = lw->list.nrows * ((xloc - (int) lw->list.internal_width)
365             / lw->list.col_width);
366         another = (yloc - (int) lw->list.internal_height) 
367                 / lw->list.row_height;
368          /* If out of range, return minimum possible value. */
369         if (another >= lw->list.nrows) {
370             another = lw->list.nrows - 1;
371             ret_val = OUT_OF_RANGE;
372         }
373     }
374     else {
375         one = (lw->list.ncols * ((yloc - (int) lw->list.internal_height) 
376               / lw->list.row_height)) ;
377         /* If in right margin handle things right. */
378         another = (xloc - (int) lw->list.internal_width) / lw->list.col_width;
379         if (another >= lw->list.ncols) {
380             another = lw->list.ncols - 1; 
381             ret_val = OUT_OF_RANGE;
382         }
383     }  
384     if ((xloc < 0) || (yloc < 0))
385         ret_val = OUT_OF_RANGE;
386     if (one < 0) one = 0;
387     if (another < 0) another = 0;
388     *item = one + another;
389     if (*item >= lw->list.nitems) return(OUT_OF_RANGE);
390     return(ret_val);
391 }
392
393 /*      Function Name: FindCornerItems.
394  *      Description: Find the corners of the rectangle in item space.
395  *      Arguments: w - the list widget.
396  *                 event - the event structure that has the rectangle it it.
397  *                 ul_ret, lr_ret - the corners ** RETURNED **.
398  *      Returns: none.
399  */
400
401 static FindCornerItems(w, event, ul_ret, lr_ret)
402 Widget w;
403 XEvent * event;
404 int *ul_ret, *lr_ret;
405 {
406     int xloc, yloc;
407
408     xloc = event->xexpose.x;
409     yloc = event->xexpose.y;
410     CvtToItem(w, xloc, yloc, ul_ret);
411     xloc += event->xexpose.width;
412     yloc += event->xexpose.height;
413     CvtToItem(w, xloc, yloc, lr_ret);
414 }
415
416 /*      Function Name: ItemInRectangle
417  *      Description: returns TRUE if the item passed is in the given rectangle.
418  *      Arguments: w - the list widget.
419  *                 ul, lr - corners of the rectangle in item space.
420  *                 item - item to check.
421  *      Returns: TRUE if the item passed is in the given rectangle.
422  */
423     
424 static ItemInRectangle(w, ul, lr, item)
425 Widget w;
426 int ul, lr, item;
427 {
428     MListWidget lw = (MListWidget) w;
429     register int mod_item;
430     int things;
431     
432     if (item < ul || item > lr) 
433         return(FALSE);
434     if (lw->list.vertical_cols)
435         things = lw->list.nrows;
436     else
437         things = lw->list.ncols;
438
439     mod_item = item % things;
440     if ( (mod_item >= ul % things) && (mod_item <= lr % things ) )
441         return(TRUE);
442     return(FALSE);
443 }
444
445 /*      Function Name: HighlightBackground
446  *      Description: paints the color of the background for the given item.
447  *      Arguments: w - the widget.
448  *                 x, y - ul corner of the area item occupies.
449  *                 item - the item we are dealing with.
450  *                 gc - the gc that is used to paint this rectangle
451  *      Returns: 
452  */
453
454 static HighlightBackground(w, x, y, item, gc)
455 Widget w;
456 int x, y, item;
457 GC gc;
458 {
459     MListWidget lw = (MListWidget) w;
460     int hl_x, hl_y, width, height;
461
462     hl_x = x - lw->list.column_space/2;
463     width = XTextWidth(lw->list.font, lw->list.list[item],
464                          strlen(lw->list.list[item])) + lw->list.column_space;
465     hl_y = y - lw->list.row_space/2;
466     height = lw->list.row_height + lw->list.row_space;
467
468     XFillRectangle(XtDisplay(w), XtWindow(w), gc, hl_x, hl_y, width, height);
469 }
470
471 /*      Function Name: PaintItemName
472  *      Description: paints the name of the item in the appropriate location.
473  *      Arguments: w - the list widget.
474  *                 item - the item to draw.
475  *      Returns: none.
476  *
477  *      NOTE: no action taken on an unrealized widget.
478  */
479
480 static PaintItemName(w, item)
481 Widget w;
482 int item;
483 {
484     char * str;
485     GC gc;
486     int x, y, str_y;
487     MListWidget lw = (MListWidget) w;
488
489     if (!XtIsRealized(w)) return; /* Just in case... */
490    
491     if (lw->list.vertical_cols) {
492         x = lw->list.col_width * (item / lw->list.nrows)
493           + lw->list.internal_width;
494         y = lw->list.row_height * (item % lw->list.nrows)
495           + lw->list.internal_height;
496     }
497     else {
498         x = lw->list.col_width * (item % lw->list.ncols)
499           + lw->list.internal_width;
500         y = lw->list.row_height * (item / lw->list.ncols)
501           + lw->list.internal_height;
502     }
503
504     str_y = y + lw->list.font->max_bounds.ascent;
505
506     if (IsHighlit(lw, item)) {
507         gc = lw->list.revgc;
508         HighlightBackground(w, x, y, item, lw->list.normgc);
509     }
510     else {
511         if (XtIsSensitive(w)) 
512           gc = lw->list.normgc;
513         else
514           gc = lw->list.graygc;
515         HighlightBackground(w, x, y, item, lw->list.revgc);
516     }
517
518     str =  lw->list.list[item]; /* draw it */
519     XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, strlen(str));
520 }
521     
522 /*      Function Name: Redisplay
523  *      Description: Repaints the widget window on expose events.
524  *      Arguments: w - the list widget.
525  *                 event - the expose event for this repaint.
526  *                 junk - NOT USED.
527  *      Returns: 
528  */
529
530 /* ARGSUSED */
531 static void 
532 Redisplay(w, event, junk)
533 Widget w;
534 XEvent *event;
535 Region junk;
536 {
537     int item;                   /* an item to work with. */
538     int ul_item, lr_item;       /* corners of items we need to paint. */
539     MListWidget lw = (MListWidget) w;
540
541     if (event == NULL) {        /* repaint all. */
542         ul_item = 0;
543         lr_item = lw->list.nrows * lw->list.ncols - 1;
544         XClearWindow(XtDisplay(w), XtWindow(w));
545     }
546     else
547         FindCornerItems(w, event, &ul_item, &lr_item);
548     
549     for (item = ul_item; (item <= lr_item && item < lw->list.nitems) ; item++)
550       if (ItemInRectangle(w, ul_item, lr_item, item))
551         PaintItemName(w, item);
552 }
553
554 /*      Function Name: PreferredGeom
555  *      Description: This tells the parent what size we would like to be
556  *                   given certain constraints.
557  *      Arguments: w - the widget.
558  *                 intended - what the parent intends to do with us.
559  *                 requested - what we want to happen.
560  *      Returns: none.
561  */
562
563 static XtGeometryResult 
564 PreferredGeom(w, intended, requested)
565 Widget w;
566 XtWidgetGeometry *intended, *requested;
567 {
568     Dimension new_width, new_height;
569     Boolean change, width_req, height_req;
570     
571     width_req = intended->request_mode & CWWidth;
572     height_req = intended->request_mode & CWHeight;
573
574     if (width_req)
575       new_width = intended->width;
576     else
577       new_width = w->core.width;
578
579     if (height_req)
580       new_height = intended->height;
581     else
582       new_height = w->core.height;
583
584     requested->request_mode = 0;
585     
586 /*
587  * We only care about our height and width.
588  */
589
590     if ( !width_req && !height_req)
591       return(XtGeometryYes);
592     
593     change = Layout(w, !width_req, !height_req, &new_width, &new_height);
594
595     requested->request_mode |= CWWidth;
596     requested->width = new_width;
597     requested->request_mode |= CWHeight;
598     requested->height = new_height;
599
600     if (change)
601         return(XtGeometryAlmost);
602     return(XtGeometryYes);
603 }
604
605 /*      Function Name: Resize
606  *      Description: resizes the widget, by changing the number of rows and
607  *                   columns.
608  *      Arguments: w - the widget.
609  *      Returns: none.
610  */
611
612 static void
613 Resize(w)
614 Widget w;
615 {
616   Dimension width, height;
617
618   width = w->core.width;
619   height = w->core.height;
620
621   if (Layout(w, FALSE, FALSE, &width, &height))
622     XtAppWarning(XtWidgetToApplicationContext(w),
623             "MList Widget: Size changed when it shouldn't have when resising.");
624 }
625
626 /*      Function Name: Layout
627  *      Description: lays out the item in the list.
628  *      Arguments: w - the widget.
629  *                 xfree, yfree - TRUE if we are free to resize the widget in
630  *                                this direction.
631  *                 width, height - the is the current width and height that 
632  *                                 we are going to layout the list widget to,
633  *                                 depending on xfree and yfree of course.
634  *                               
635  *      Returns: TRUE if width or height have been changed.
636  */
637
638 static Boolean
639 Layout(w, xfree, yfree, width, height)
640 Widget w;
641 Boolean xfree, yfree;
642 Dimension *width, *height;
643 {
644     MListWidget lw = (MListWidget) w;
645     Boolean change = FALSE;
646     
647 /* 
648  * If force columns is set then always use number of columns specified
649  * by default_cols.
650  */
651
652     if (lw->list.force_cols) {
653         lw->list.ncols = lw->list.default_cols;
654         if (lw->list.ncols <= 0) lw->list.ncols = 1;
655         /* 12/3 = 4 and 10/3 = 4, but 9/3 = 3 */
656         lw->list.nrows = ( ( lw->list.nitems - 1) / lw->list.ncols) + 1 ;
657         if (xfree) {            /* If allowed resize width. */
658             *width = lw->list.ncols * lw->list.col_width 
659                    + 2 * lw->list.internal_width;
660             change = TRUE;
661         }
662         if (yfree) {            /* If allowed resize height. */
663             *height = (lw->list.nrows * lw->list.row_height)
664                     + 2 * lw->list.internal_height;
665             change = TRUE;
666         }
667         return(change);
668     }
669
670 /*
671  * If both width and height are free to change the use default_cols
672  * to determine the number columns and set new width and height to
673  * just fit the window.
674  */
675
676     if (xfree && yfree) {
677         lw->list.ncols = lw->list.default_cols;
678         if (lw->list.ncols <= 0) lw->list.ncols = 1;
679         lw->list.nrows = ( ( lw->list.nitems - 1) / lw->list.ncols) + 1 ;
680         *width = lw->list.ncols * lw->list.col_width
681                + 2 * lw->list.internal_width;
682         *height = (lw->list.nrows * lw->list.row_height)
683                 + 2 * lw->list.internal_height;
684         change = TRUE;
685     }
686 /* 
687  * If the width is fixed then use it to determine the number of columns.
688  * If the height is free to move (width still fixed) then resize the height
689  * of the widget to fit the current list exactly.
690  */
691     else if (!xfree) {
692         lw->list.ncols = ( (*width - 2 * lw->list.internal_width)
693                             / lw->list.col_width);
694         if (lw->list.ncols <= 0) lw->list.ncols = 1;
695         lw->list.nrows = ( ( lw->list.nitems - 1) / lw->list.ncols) + 1 ;
696         if ( yfree ) {
697             *height = (lw->list.nrows * lw->list.row_height)
698                     + 2 * lw->list.internal_height;
699             change = TRUE;
700         }
701     }
702 /* 
703  * The last case is xfree and !yfree we use the height to determine
704  * the number of rows and then set the width to just fit the resulting
705  * number of columns.
706  */
707     else if (!yfree) {          /* xfree must be TRUE. */
708         lw->list.nrows = (*height - 2 * lw->list.internal_height) 
709                        / lw->list.row_height;
710         if (lw->list.nrows <= 0) lw->list.nrows = 1;
711         lw->list.ncols = (( lw->list.nitems - 1 ) / lw->list.nrows) + 1;
712         *width = lw->list.ncols * lw->list.col_width 
713                + 2 * lw->list.internal_width;
714         change = TRUE;
715     }      
716     return(change);
717 }
718
719 /*      Function Name: Notify
720  *      Description: Notifies the user that a button has been pressed, and
721  *                   calles the callback, if the XtNpasteBuffer resource
722  *                   is true then the name of the item is also put in the
723  *                   X cut buffer ( buf (0) ).
724  *      Arguments: w - the widget that the notify occured in.
725  *                 event - event that caused this notification.
726  *                 params, num_params - not used.
727  *      Returns: none.
728  */
729
730 /* ARGSUSED */
731 static void
732 Notify(w, event, params, num_params)
733 Widget w;
734 XEvent * event;
735 String * params;
736 Cardinal *num_params;
737 {
738     MListWidget lw = ( MListWidget ) w;
739     int item, item_len;
740     XawMListReturnStruct ret_value;
741
742 /* 
743  * Find item and if out of range then unhighlight and return. 
744  * 
745  * If the current item is unhighlighted then the user has aborted the
746  * notify, so unhighlight and return.
747  */
748
749     if ( ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item))
750           == OUT_OF_RANGE) || (lw->list.highlight != item) ) {
751         XawMListUnhighlight(w, lw->list.highlight);
752         lw->list.highlight = NO_HIGHLIGHT;
753         return;
754     }
755     lw->list.highlight = NO_HIGHLIGHT;
756
757     item_len = strlen(lw->list.list[item]);
758
759     if ( lw->list.paste )       /* if XtNpasteBuffer set then paste it. */
760         XStoreBytes(XtDisplay(w), lw->list.list[item], item_len);
761
762 /* 
763  * Call Callback function.
764  */
765
766     ret_value.string = lw->list.list[item];
767     ret_value.list_index = item;
768     
769     XtCallCallbacks( w, XtNcallback, (caddr_t) &ret_value);
770 }
771
772 /*      Function Name: Unset
773  *      Description: unhighlights the current element.
774  *      Arguments: w - the widget that the event occured in.
775  *                 event - not used.
776  *                 params, num_params - not used.
777  *      Returns: none.
778  */
779
780 /* ARGSUSED */
781 static void
782 Unset(w, event, params, num_params)
783 Widget w;
784 XEvent * event;
785 String * params;
786 Cardinal *num_params;
787 {
788   MListWidget lw = (MListWidget) w;
789
790   XawMListUnhighlight(w, lw->list.highlight);
791 }
792
793 /*      Function Name: Set
794  *      Description: Highlights the current element.
795  *      Arguments: w - the widget that the event occured in.
796  *                 event - event that caused this notification.
797  *                 params, num_params - not used.
798  *      Returns: none.
799  */
800
801 /* ARGSUSED */
802 static void
803 Set(w, event, params, num_params)
804 Widget w;
805 XEvent * event;
806 String * params;
807 Cardinal *num_params;
808 {
809   int item;
810   MListWidget lw = (MListWidget) w;
811
812   if ( (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item))
813       == OUT_OF_RANGE)
814     return;
815
816   if (IsHighlit(lw, item))
817     (void) XawMListUnhighlight(w, item);
818   else {
819       (void) XawMListHighlight(w, item);
820       lw->list.highlight = item;
821   }
822 }
823
824 /*
825  * Set specified arguments into widget
826  */
827
828 static Boolean 
829 SetValues(current, request, new)
830 Widget current, request, new;
831 {
832     MListWidget cl = (MListWidget) current;
833     MListWidget rl = (MListWidget) request;
834     MListWidget nl = (MListWidget) new;
835     Boolean redraw = FALSE;
836
837     if ((cl->list.foreground != rl->list.foreground) ||
838         (cl->core.background_pixel != rl->core.background_pixel) ||
839         (cl->list.font != rl->list.font) ) {
840         XtDestroyGC(cl->list.normgc);
841         XtDestroyGC(cl->list.graygc);
842         XtDestroyGC(cl->list.revgc);
843         GetGCs(new);
844         redraw = TRUE;
845     }
846
847     /* Reset row height. */
848
849     if ((cl->list.row_space != rl->list.row_space) ||
850         (cl->list.font != rl->list.font)) 
851         nl->list.row_height = nl->list.font->max_bounds.ascent
852                             + nl->list.font->max_bounds.descent
853                             + nl->list.row_space;
854     
855     if ((cl->core.width != rl->core.width)                     ||
856         (cl->core.height != rl->core.height)                   ||
857         (cl->list.internal_width != rl->list.internal_width)   ||
858         (cl->list.internal_height != rl->list.internal_height) ||
859         (cl->list.column_space != rl->list.column_space)       ||
860         (cl->list.row_space != rl->list.row_space)             ||
861         (cl->list.default_cols != rl->list.default_cols)       ||
862         (  (cl->list.force_cols != rl->list.force_cols) &&
863            (rl->list.force_cols != rl->list.ncols) )           ||
864         (cl->list.vertical_cols != rl->list.vertical_cols)     ||
865         (cl->list.longest != rl->list.longest)                 ||
866         (cl->list.nitems != rl->list.nitems)                   ||
867         (cl->list.font != rl->list.font)                       ||
868         (cl->list.list != rl->list.list)                        ) {
869
870       ResetMList(new, TRUE, TRUE);
871       redraw = TRUE;
872     }
873
874     if (cl->list.list != rl->list.list)
875       nl->list.highlight = NO_HIGHLIGHT;
876
877     if ((cl->core.sensitive != rl->core.sensitive) ||
878         (cl->core.ancestor_sensitive != rl->core.ancestor_sensitive)) {
879         nl->list.highlight = NO_HIGHLIGHT;
880         redraw = TRUE;
881     }
882     
883     if (!XtIsRealized(current))
884       return(FALSE);
885       
886     return(redraw);
887 }
888
889 /* Exported Functions */
890
891 /*      Function Name: XawMListChange.
892  *      Description: Changes the list being used and shown.
893  *      Arguments: w - the list widget.
894  *                 list - the new list.
895  *                 nitems - the number of items in the list.
896  *                 longest - the length (in Pixels) of the longest element
897  *                           in the list.
898  *                 resize - if TRUE the the list widget will
899  *                          try to resize itself.
900  *      Returns: none.
901  *      NOTE:      If nitems of longest are <= 0 then they will be calculated.
902  *                 If nitems is <= 0 then the list needs to be NULL terminated.
903  */
904
905 void
906 #if NeedFunctionPrototypes
907 XawMListChange(Widget w, char ** list, int nitems, int longest,
908 #if NeedWidePrototypes
909               int resize_it)
910 #else
911               Boolean resize_it)
912 #endif
913 #else
914 XawMListChange(w, list, nitems, longest, resize_it)
915 Widget w;
916 char ** list;
917 int nitems, longest;
918 Boolean resize_it;
919 #endif
920 {
921     MListWidget lw = (MListWidget) w;
922
923     lw->list.list = list;
924
925     if (nitems <= 0) nitems = 0;
926     lw->list.nitems = nitems;
927     if (longest <= 0) longest = 0;
928     lw->list.longest = longest;
929
930     ResetMList(w, resize_it, resize_it);
931 /*    lw->list.is_highlighted = */
932     lw->list.highlight = NO_HIGHLIGHT;
933     if ( XtIsRealized(w) )
934       Redisplay(w, NULL, NULL);
935 }
936
937 /*      Function Name: XawMListUnhighlight
938  *      Description: unlights the current highlighted element.
939  *      Arguments: w - the widget, item - the element to unhighlight
940  *      Returns: none.
941  */
942
943 void
944 #if NeedFunctionPrototypes
945 XawMListUnhighlight(Widget w, int item)
946 #else
947 XawMListUnhighlight(w, item)
948 Widget w;
949 int item;
950 #endif
951 {
952     int i;
953     MListWidget lw = (MListWidget) w;
954
955     if (IsHighlit(w, item)) {
956         for (i = 0; i < lw->list.nhighlighted; i++)
957           if (lw->list.is_highlighted[i] == item) break;
958         lw->list.nhighlighted--;
959         lw->list.is_highlighted[i] =
960                 lw->list.is_highlighted[lw->list.nhighlighted];
961         lw->list.is_highlighted = (int *)
962                 realloc((char *)lw->list.is_highlighted,
963                         sizeof(int) * lw->list.nhighlighted);
964         PaintItemName(w, item); /* unhighlight this one. */
965     }
966 }
967
968 /*      Function Name: XawMListHighlight
969  *      Description: Highlights the given item.
970  *      Arguments: w - the list widget.
971  *                 item - the item to hightlight.
972  *      Returns: none.
973  */
974
975 void
976 #if NeedFunctionPrototypes
977 XawMListHighlight(Widget w, int item)
978 #else
979 XawMListHighlight(w, item)
980 Widget w;
981 int item;
982 #endif
983 {
984     MListWidget lw = ( MListWidget ) w;
985     
986     if (XtIsSensitive(w)) {
987         if (!IsHighlit(lw, item)) {
988             lw->list.is_highlighted = (int *)
989                 realloc((char *)lw->list.is_highlighted,
990                         sizeof(int) * (lw->list.nhighlighted + 1));
991             lw->list.is_highlighted[lw->list.nhighlighted] = item;
992             lw->list.nhighlighted++;
993         }
994         PaintItemName(w, item); /* HIGHLIGHT this one. */ 
995     }
996 }
997
998 /*      Function Name: XawMListShowCurrent
999  *      Description: returns the currently highlighted object.
1000  *      Arguments: w - the list widget.
1001  *      Returns: the info about the currently highlighted object.
1002  */
1003
1004 XawMListReturnStruct *
1005 #if NeedFunctionPrototypes
1006 XawMListShowCurrent(Widget w, int *numselected)
1007 #else
1008 XawMListShowCurrent(w, numselected)
1009 Widget w;
1010 int *numselected;
1011 #endif
1012 {
1013     MListWidget lw = ( MListWidget ) w;
1014     XawMListReturnStruct * ret_val;
1015     int i;
1016
1017     *numselected = lw->list.nhighlighted;
1018     ret_val = (XawMListReturnStruct *)
1019         XtMalloc (sizeof(XawMListReturnStruct) * lw->list.nhighlighted);
1020     
1021     for (i = 0; i < lw->list.nhighlighted; i++) {
1022         ret_val[i].list_index = lw->list.is_highlighted[i];
1023         ret_val[i].string = lw->list.list[ ret_val->list_index ];
1024     }
1025
1026     return(ret_val);
1027 }
1028
This page took 0.1223 seconds and 5 git commands to generate.