]> andersk Git - moira.git/blame - clients/cluster/MList.c
Diane Delgado's changes for a fixed table-locking order
[moira.git] / clients / cluster / MList.c
CommitLineData
3a3bd871 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
56static 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
70static 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
103static void Initialize();
104static void ChangeSize();
105static void Resize();
106static void Redisplay();
107static Boolean Layout();
108static XtGeometryResult PreferredGeom();
109static Boolean SetValues();
110static void Notify(), Set(), Unset();
111
112static XtActionsRec actions[] = {
113 {"Notify", Notify},
114 {"Set", Set},
115 {"Unset", Unset},
116};
117
118MListClassRec 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
159WidgetClass mlistWidgetClass = (WidgetClass)&mlistClassRec;
160
161/****************************************************************
162 *
163 * Private Procedures
164 *
165 ****************************************************************/
166
167static void GetGCs(w)
168Widget 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
199static void
200ResetMList(w, changex, changey)
201Widget w;
202Boolean 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
241static void
242ChangeSize(w, width, height)
243Widget w;
244Dimension 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 */
299static void
300Initialize(junk, new)
301Widget 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
330static Boolean
331IsHighlit(lw, item)
332MListWidget lw;
333int 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
353static int
354CvtToItem(w, xloc, yloc, item)
355Widget w;
356int xloc, yloc;
357int *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
401static FindCornerItems(w, event, ul_ret, lr_ret)
402Widget w;
403XEvent * event;
404int *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
424static ItemInRectangle(w, ul, lr, item)
425Widget w;
426int 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
454static HighlightBackground(w, x, y, item, gc)
455Widget w;
456int x, y, item;
457GC 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
480static PaintItemName(w, item)
481Widget w;
482int 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 */
531static void
532Redisplay(w, event, junk)
533Widget w;
534XEvent *event;
535Region 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
563static XtGeometryResult
564PreferredGeom(w, intended, requested)
565Widget w;
566XtWidgetGeometry *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
612static void
613Resize(w)
614Widget 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
638static Boolean
639Layout(w, xfree, yfree, width, height)
640Widget w;
641Boolean xfree, yfree;
642Dimension *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 */
731static void
732Notify(w, event, params, num_params)
733Widget w;
734XEvent * event;
735String * params;
736Cardinal *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 */
781static void
782Unset(w, event, params, num_params)
783Widget w;
784XEvent * event;
785String * params;
786Cardinal *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 */
802static void
803Set(w, event, params, num_params)
804Widget w;
805XEvent * event;
806String * params;
807Cardinal *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
828static Boolean
829SetValues(current, request, new)
830Widget 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
905void
906#if NeedFunctionPrototypes
907XawMListChange(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
914XawMListChange(w, list, nitems, longest, resize_it)
915Widget w;
916char ** list;
917int nitems, longest;
918Boolean 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
943void
944#if NeedFunctionPrototypes
945XawMListUnhighlight(Widget w, int item)
946#else
947XawMListUnhighlight(w, item)
948Widget w;
949int 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
975void
976#if NeedFunctionPrototypes
977XawMListHighlight(Widget w, int item)
978#else
979XawMListHighlight(w, item)
980Widget w;
981int 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
1004XawMListReturnStruct *
1005#if NeedFunctionPrototypes
1006XawMListShowCurrent(Widget w, int *numselected)
1007#else
1008XawMListShowCurrent(w, numselected)
1009Widget w;
1010int *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.192615 seconds and 5 git commands to generate.