This is MultiList.c in view mode; [Download] [Up]
#if ( !defined(lint) && !defined(SABER)) static char PCN_rcsid[] = "$Header: /ufs/comp/mei/PROJ_PCN/onprofile/IFModel/Xsw/RCS/MultiList.c,v 1.1 1992/04/17 18:25:49 mei Exp $"; #endif /* * Copyright 1989 Massachusetts Institute of Technology * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ /* * MultiList.c - MultiList widget * * This is the MultiList widget, it is useful to display a multiList, without the * overhead of having a widget for each item in the multiList. It allows * the user to select an item in a multiList and notifies the application through * a callback function. * * Created: 8/13/88 * By: Chris D. Peterson * MIT X Consortium */ #include <stdio.h> #include <ctype.h> #include <X11/IntrinsicP.h> #include <X11/StringDefs.h> #include <X11/Xmu/Drawing.h> #include <X11/Xaw/XawInit.h> #include "MultiListP.h" /* * Default Translation table. */ static char defaultTranslations[] = "<Btn1Down>: Set()Notify()\n\ <Btn1Motion>: Move()\n\ "; /**************************************************************** * * Full class record constant * ****************************************************************/ /* Private Data */ #define offset(field) XtOffset(MultiListWidget, field) static XtResource resources[] = { {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(multiList.foreground), XtRString, "XtDefaultForeground"}, {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), offset(simple.cursor), XtRString, "left_ptr"}, {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), offset(multiList.font),XtRString, "XtDefaultFont"}, {XtNlist, XtCList, XtRPointer, sizeof(char **), offset(multiList.list), XtRString, NULL}, {XtNsingle, XtCSingle, XtRBoolean, sizeof(Boolean), offset(multiList.single), XtRString, "True"}, {XtNdefaultColumns, XtCColumns, XtRInt, sizeof(int), offset(multiList.default_cols), XtRImmediate, (XPointer)2}, {XtNlongest, XtCLongest, XtRInt, sizeof(int), offset(multiList.longest), XtRImmediate, (XPointer)0}, {XtNnumberStrings, XtCNumberStrings, XtRInt, sizeof(int), offset(multiList.nitems), XtRImmediate, (XPointer)0}, {XtNpasteBuffer, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(multiList.paste), XtRString, (XPointer) "False"}, {XtNforceColumns, XtCColumns, XtRBoolean, sizeof(Boolean), offset(multiList.force_cols), XtRString, (XPointer) "False"}, {XtNverticalMultiList, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(multiList.vertical_cols), XtRString, (XPointer) "False"}, {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension), offset(multiList.internal_width), XtRImmediate, (XPointer)4}, {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension), offset(multiList.internal_height), XtRImmediate, (XPointer)2}, {XtNcolumnSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), offset(multiList.column_space), XtRImmediate, (XPointer)6}, {XtNrowSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), offset(multiList.row_space), XtRImmediate, (XPointer)2}, {XtNcallback, XtCCallback, XtRCallback, sizeof(XPointer), offset(multiList.callback), XtRCallback, NULL}, }; static void Initialize(); static void Destroy(); static void ChangeSize(); static void Resize(); static void Redisplay(); static Boolean Layout(); static XtGeometryResult PreferredGeom(); static Boolean SetValues(); static void Notify(), Set(), Unset(), Move(); static XtActionsRec actions[] = { {"Notify", Notify}, {"Set", Set}, {"Unset", Unset}, {"Move", Move}, {NULL,NULL} }; MultiListClassRec multiListClassRec = { { /* core_class fields */ #define superclass (&simpleClassRec) /* superclass */ (WidgetClass) superclass, /* class_name */ "MultiList", /* widget_size */ sizeof(MultiListRec), /* class_initialize */ XawInitializeWidgetSet, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ FALSE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ defaultTranslations, /* query_geometry */ PreferredGeom, }, /* Simple class fields initialization */ { /* change_sensitive */ XtInheritChangeSensitive } }; WidgetClass multiListWidgetClass = (WidgetClass)&multiListClassRec; /**************************************************************** * * Private Procedures * ****************************************************************/ static void GetGCs(w) Widget w; { XGCValues values; MultiListWidget lw = (MultiListWidget) w; values.foreground = lw->multiList.foreground; values.font = lw->multiList.font->fid; lw->multiList.normgc = XtGetGC(w, (unsigned) GCForeground | GCFont, &values); values.foreground = lw->core.background_pixel; lw->multiList.revgc = XtGetGC(w, (unsigned) GCForeground | GCFont, &values); values.tile = XmuCreateStippledPixmap(XtScreen(w), lw->multiList.foreground, lw->core.background_pixel, lw->core.depth); values.fill_style = FillTiled; lw->multiList.graygc = XtGetGC(w, (unsigned) GCFont | GCTile | GCFillStyle, &values); } /* Function Name: ResetMultiList * Description: Resets the new multiList when important things change. * Arguments: w - the widget. * changex, changey - allow the height or width to change? * Returns: none. */ static void ResetMultiList(w, changex, changey) Widget w; Boolean changex, changey; { MultiListWidget lw = (MultiListWidget) w; Dimension width = w->core.width; Dimension height = w->core.height; register int i, len; /* * If multiList is NULL then the multiList will just be the name of the widget. */ if (lw->multiList.list == NULL) { lw->multiList.list = &(lw->core.name); lw->multiList.nitems = 1; } if (lw->multiList.nitems == 0) /* Get number of items. */ for ( ; lw->multiList.list[lw->multiList.nitems] != NULL ; lw->multiList.nitems++); if (lw->multiList.longest == 0) /* Get column width. */ for ( i = 0 ; i < lw->multiList.nitems; i++) { len = XTextWidth(lw->multiList.font, lw->multiList.list[i], strlen(lw->multiList.list[i])); if (len > lw->multiList.longest) lw->multiList.longest = len; } lw->multiList.col_width = lw->multiList.longest + lw->multiList.column_space; if (Layout(w, changex, changey, &width, &height)) ChangeSize(w, width, height); lw->multiList.state = (Boolean *)XtCalloc(lw->multiList.nitems, sizeof(Boolean)); } /* Function Name: ChangeSize. * Description: Laysout the widget. * Arguments: w - the widget to try change the size of. * Returns: none. */ static void ChangeSize(w, width, height) Widget w; Dimension width, height; { XtWidgetGeometry request, reply; request.request_mode = CWWidth | CWHeight; request.width = width; request.height = height; switch ( XtMakeGeometryRequest(w, &request, &reply) ) { case XtGeometryYes: case XtGeometryNo: break; case XtGeometryAlmost: Layout(w, (request.height != reply.height), (request.width != reply.width), &(reply.width), &(reply.height)); request = reply; switch (XtMakeGeometryRequest(w, &request, &reply) ) { case XtGeometryYes: case XtGeometryNo: break; case XtGeometryAlmost: request = reply; if (Layout(w, FALSE, FALSE, &(request.width), &(request.height))) { char buf[BUFSIZ]; sprintf(buf, "MultiList Widget: %s %s", "Size Changed when it shouldn't have", "when computing layout"); XtAppWarning(XtWidgetToApplicationContext(w), buf); } request.request_mode = CWWidth | CWHeight; XtMakeGeometryRequest(w, &request, &reply); break; default: XtAppWarning(XtWidgetToApplicationContext(w), "MultiList Widget: Unknown geometry return."); break; } break; default: XtAppWarning(XtWidgetToApplicationContext(w), "MultiList Widget: Unknown geometry return."); break; } } /* Function Name: Initialize * Description: Function that initilizes the widget instance. * Arguments: junk - NOT USED. * new - the new widget. * Returns: none */ /* ARGSUSED */ static void Initialize(junk, new) Widget junk, new; { MultiListWidget lw = (MultiListWidget) new; /* * Initialize all private resources. */ GetGCs(new); /* Set row height. */ lw->multiList.row_height = lw->multiList.font->max_bounds.ascent + lw->multiList.font->max_bounds.descent + lw->multiList.row_space; ResetMultiList(new, (new->core.width == 0), (new->core.height == 0)); lw->multiList.highlight = lw->multiList.is_highlighted = NO_HIGHLIGHT; } /* Initialize */ /* Function Name: CvtToItem * Description: Converts Xcoord to item number of item containing that * point. * Arguments: w - the multiList widget. * xloc, yloc - x location, and y location. * Returns: the item number. */ static int CvtToItem(w, xloc, yloc, item) Widget w; int xloc, yloc; int *item; { int one, another; MultiListWidget lw = (MultiListWidget) w; int ret_val = OKAY; if (lw->multiList.vertical_cols) { one = lw->multiList.nrows * ((xloc - (int) lw->multiList.internal_width) / lw->multiList.col_width); another = (yloc - (int) lw->multiList.internal_height) / lw->multiList.row_height; /* If out of range, return minimum possible value. */ if (another >= lw->multiList.nrows) { another = lw->multiList.nrows - 1; ret_val = OUT_OF_RANGE; } } else { one = (lw->multiList.ncols * ((yloc - (int) lw->multiList.internal_height) / lw->multiList.row_height)) ; /* If in right margin handle things right. */ another = (xloc - (int) lw->multiList.internal_width) / lw->multiList.col_width; if (another >= lw->multiList.ncols) { another = lw->multiList.ncols - 1; ret_val = OUT_OF_RANGE; } } if ((xloc < 0) || (yloc < 0)) ret_val = OUT_OF_RANGE; if (one < 0) one = 0; if (another < 0) another = 0; *item = one + another; if (*item >= lw->multiList.nitems) return(OUT_OF_RANGE); return(ret_val); } /* Function Name: FindmyCornerItems. * Description: Find the corners of the rectangle in item space. * Arguments: w - the multiList widget. * event - the event structure that has the rectangle it it. * ul_ret, lr_ret - the corners ** RETURNED **. * Returns: none. */ FindmyCornerItems(w, event, ul_ret, lr_ret) Widget w; XEvent * event; int *ul_ret, *lr_ret; { int xloc, yloc; xloc = event->xexpose.x; yloc = event->xexpose.y; CvtToItem(w, xloc, yloc, ul_ret); xloc += event->xexpose.width; yloc += event->xexpose.height; CvtToItem(w, xloc, yloc, lr_ret); } /* Function Name: ItemInmyRectangle * Description: returns TRUE if the item passed is in the given rectangle. * Arguments: w - the multiList widget. * ul, lr - corners of the rectangle in item space. * item - item to check. * Returns: TRUE if the item passed is in the given rectangle. */ ItemInmyRectangle(w, ul, lr, item) Widget w; int ul, lr, item; { MultiListWidget lw = (MultiListWidget) w; register int mod_item; int things; if (item < ul || item > lr) return(FALSE); if (lw->multiList.vertical_cols) things = lw->multiList.nrows; else things = lw->multiList.ncols; mod_item = item % things; if ( (mod_item >= ul % things) && (mod_item <= lr % things ) ) return(TRUE); return(FALSE); } /* Function Name: HighlightmyBackground * Description: paints the color of the background for the given item. * Arguments: w - the widget. * x, y - ul corner of the area item occupies. * item - the item we are dealing with. * gc - the gc that is used to paint this rectangle * Returns: */ HighlightmyBackground(w, x, y, item, gc) Widget w; int x, y, item; GC gc; { MultiListWidget lw = (MultiListWidget) w; int hl_x, hl_y, width, height; hl_x = x - lw->multiList.column_space/2; width = XTextWidth(lw->multiList.font, lw->multiList.list[item], strlen(lw->multiList.list[item])) + lw->multiList.column_space; hl_y = y - lw->multiList.row_space/2; height = lw->multiList.row_height; XFillRectangle(XtDisplay(w), XtWindow(w), gc, hl_x, hl_y, width, height); } /* Function Name: PaintmyItemName * Description: paints the name of the item in the appropriate location. * Arguments: w - the multiList widget. * item - the item to draw. * Returns: none. * * NOTE: no action taken on an unrealized widget. */ PaintmyItemName(w, item) Widget w; int item; { char * str; GC gc; int x, y, str_y; MultiListWidget lw = (MultiListWidget) w; if (!XtIsRealized(w)) return; /* Just in case... */ if (lw->multiList.vertical_cols) { x = lw->multiList.col_width * (item / lw->multiList.nrows) + lw->multiList.internal_width; y = lw->multiList.row_height * (item % lw->multiList.nrows) + lw->multiList.internal_height; } else { x = lw->multiList.col_width * (item % lw->multiList.ncols) + lw->multiList.internal_width; y = lw->multiList.row_height * (item / lw->multiList.ncols) + lw->multiList.internal_height; } str_y = y + lw->multiList.font->max_bounds.ascent; if (lw->multiList.single) { if (item == lw->multiList.is_highlighted) { if (item == lw->multiList.highlight) { gc = lw->multiList.revgc; HighlightmyBackground(w, x, y, item, lw->multiList.normgc); } else { if (XtIsSensitive(w)) gc = lw->multiList.normgc; else gc = lw->multiList.graygc; HighlightmyBackground(w, x, y, item, lw->multiList.revgc); lw->multiList.is_highlighted = NO_HIGHLIGHT; } } else { if (item == lw->multiList.highlight) { gc = lw->multiList.revgc; HighlightmyBackground(w, x, y, item, lw->multiList.normgc); lw->multiList.is_highlighted = item; } else { if (XtIsSensitive(w)) gc = lw->multiList.normgc; else gc = lw->multiList.graygc; } } } else { if (lw->multiList.state[item]) { gc = lw->multiList.revgc; HighlightmyBackground(w, x, y, item, lw->multiList.normgc); } else { if (XtIsSensitive(w)) gc = lw->multiList.normgc; else gc = lw->multiList.graygc; HighlightmyBackground(w, x, y, item, lw->multiList.revgc); } } str = lw->multiList.list[item]; /* draw it */ XDrawString(XtDisplay(w), XtWindow(w), gc, x, str_y, str, strlen(str)); } /* Function Name: Redisplay * Description: Repaints the widget window on expose events. * Arguments: w - the multiList widget. * event - the expose event for this repaint. * junk - NOT USED. * Returns: */ /* ARGSUSED */ static void Redisplay(w, event, junk) Widget w; XEvent *event; Region junk; { int item; /* an item to work with. */ int ul_item, lr_item; /* corners of items we need to paint. */ MultiListWidget lw = (MultiListWidget) w; if (event == NULL) { /* repaint all. */ ul_item = 0; lr_item = lw->multiList.nrows * lw->multiList.ncols - 1; XClearWindow(XtDisplay(w), XtWindow(w)); } else FindmyCornerItems(w, event, &ul_item, &lr_item); for (item = ul_item; (item <= lr_item && item < lw->multiList.nitems) ; item++) if (ItemInmyRectangle(w, ul_item, lr_item, item)) PaintmyItemName(w, item); } /* Function Name: PreferredGeom * Description: This tells the parent what size we would like to be * given certain constraints. * Arguments: w - the widget. * intended - what the parent intends to do with us. * requested - what we want to happen. * Returns: none. */ static XtGeometryResult PreferredGeom(w, intended, requested) Widget w; XtWidgetGeometry *intended, *requested; { Dimension new_width, new_height; Boolean change, width_req, height_req; width_req = intended->request_mode & CWWidth; height_req = intended->request_mode & CWHeight; if (width_req) new_width = intended->width; else new_width = w->core.width; if (height_req) new_height = intended->height; else new_height = w->core.height; requested->request_mode = 0; /* * We only care about our height and width. */ if ( !width_req && !height_req) return(XtGeometryYes); change = Layout(w, !width_req, !height_req, &new_width, &new_height); requested->request_mode |= CWWidth; requested->width = new_width; requested->request_mode |= CWHeight; requested->height = new_height; if (change) return(XtGeometryAlmost); return(XtGeometryYes); } /* Function Name: Resize * Description: resizes the widget, by changing the number of rows and * columns. * Arguments: w - the widget. * Returns: none. */ static void Resize(w) Widget w; { Dimension width, height; width = w->core.width; height = w->core.height; if (Layout(w, FALSE, FALSE, &width, &height)) XtAppWarning(XtWidgetToApplicationContext(w), "MultiList Widget: Size changed when it shouldn't have when resising."); } /* Function Name: Layout * Description: lays out the item in the multiList. * Arguments: w - the widget. * xfree, yfree - TRUE if we are free to resize the widget in * this direction. * width, height - the is the current width and height that * we are going to layout the multiList widget to, * depending on xfree and yfree of course. * * Returns: TRUE if width or height have been changed. */ static Boolean Layout(w, xfree, yfree, width, height) Widget w; Boolean xfree, yfree; Dimension *width, *height; { MultiListWidget lw = (MultiListWidget) w; Boolean change = FALSE; /* * If force columns is set then always use number of columns specified * by default_cols. */ if (lw->multiList.force_cols) { lw->multiList.ncols = lw->multiList.default_cols; if (lw->multiList.ncols <= 0) lw->multiList.ncols = 1; /* 12/3 = 4 and 10/3 = 4, but 9/3 = 3 */ lw->multiList.nrows = ( ( lw->multiList.nitems - 1) / lw->multiList.ncols) + 1 ; if (xfree) { /* If allowed resize width. */ *width = lw->multiList.ncols * lw->multiList.col_width + 2 * lw->multiList.internal_width; change = TRUE; } if (yfree) { /* If allowed resize height. */ *height = (lw->multiList.nrows * lw->multiList.row_height) + 2 * lw->multiList.internal_height; change = TRUE; } return(change); } /* * If both width and height are free to change the use default_cols * to determine the number columns and set new width and height to * just fit the window. */ if (xfree && yfree) { lw->multiList.ncols = lw->multiList.default_cols; if (lw->multiList.ncols <= 0) lw->multiList.ncols = 1; lw->multiList.nrows = ( ( lw->multiList.nitems - 1) / lw->multiList.ncols) + 1 ; *width = lw->multiList.ncols * lw->multiList.col_width + 2 * lw->multiList.internal_width; *height = (lw->multiList.nrows * lw->multiList.row_height) + 2 * lw->multiList.internal_height; change = TRUE; } /* * If the width is fixed then use it to determine the number of columns. * If the height is free to move (width still fixed) then resize the height * of the widget to fit the current multiList exactly. */ else if (!xfree) { lw->multiList.ncols = ( (*width - 2 * lw->multiList.internal_width) / lw->multiList.col_width); if (lw->multiList.ncols <= 0) lw->multiList.ncols = 1; lw->multiList.nrows = ( ( lw->multiList.nitems - 1) / lw->multiList.ncols) + 1 ; if ( yfree ) { *height = (lw->multiList.nrows * lw->multiList.row_height) + 2 * lw->multiList.internal_height; change = TRUE; } } /* * The last case is xfree and !yfree we use the height to determine * the number of rows and then set the width to just fit the resulting * number of columns. */ else if (!yfree) { /* xfree must be TRUE. */ lw->multiList.nrows = (*height - 2 * lw->multiList.internal_height) / lw->multiList.row_height; if (lw->multiList.nrows <= 0) lw->multiList.nrows = 1; lw->multiList.ncols = (( lw->multiList.nitems - 1 ) / lw->multiList.nrows) + 1; *width = lw->multiList.ncols * lw->multiList.col_width + 2 * lw->multiList.internal_width; change = TRUE; } return(change); } /* Function Name: Notify * Description: Notifies the user that a button has been pressed, and * calles the callback, if the XtNpasteBuffer resource * is true then the name of the item is also put in the * X cut buffer ( buf (0) ). * Arguments: w - the widget that the notify occured in. * event - event that caused this notification. * params, num_params - not used. * Returns: none. */ /* ARGSUSED */ static void Notify(w, event, params, num_params) Widget w; XEvent * event; String * params; Cardinal *num_params; { MultiListWidget lw = ( MultiListWidget ) w; int item, item_len; XswMultiListReturnStruct ret_value; /* * Find item and if out of range then unhighlight and return. * * If the current item is unhighlighted then the user has aborted the * notify, so unhighlight and return. */ if ( ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item)) == OUT_OF_RANGE)) { ret_value.string = ""; ret_value.list_index = XSW_LIST_NONE; XtCallCallbacks( w, XtNcallback, (XPointer) &ret_value); return; } if (lw->multiList.single && (lw->multiList.highlight != item) ) { if (lw->multiList.highlight != NO_HIGHLIGHT) XswMultiListUnhighlight(w, lw->multiList.highlight); ret_value.string = ""; ret_value.list_index = XSW_LIST_NONE; XtCallCallbacks( w, XtNcallback, (XPointer) &ret_value); return; } item_len = strlen(lw->multiList.list[item]); if ( lw->multiList.paste ) /* if XtNpasteBuffer set then paste it. */ XStoreBytes(XtDisplay(w), lw->multiList.list[item], item_len); /* * Call Callback function. */ if (lw->multiList.single && (lw->multiList.highlight == NO_HIGHLIGHT)) { ret_value.string = ""; ret_value.list_index = XSW_LIST_NONE; } else { ret_value.string = lw->multiList.list[item]; ret_value.list_index = item; } XtCallCallbacks( w, XtNcallback, (XPointer) &ret_value); } /* Function Name: Unset * Description: unhighlights the current element. * Arguments: w - the widget that the event occured in. * event - not used. * params, num_params - not used. * Returns: none. */ /* ARGSUSED */ static void Unset(w, event, params, num_params) Widget w; XEvent * event; String * params; Cardinal *num_params; { int item; if ( (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item)) != OUT_OF_RANGE) { XswMultiListUnhighlight(w, item); /* highlighted then do it. */ } } /* Function Name: Set * Description: Highlights the current element. * Arguments: w - the widget that the event occured in. * event - event that caused this notification. * params, num_params - not used. * Returns: none. */ /* ARGSUSED */ static void Set(w, event, params, num_params) Widget w; XEvent * event; String * params; Cardinal *num_params; { int item; MultiListWidget lw = (MultiListWidget) w; if ( (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item)) != OUT_OF_RANGE) { if (lw->multiList.single) { XswMultiListHighlight(w, item); } else { if (!lw->multiList.state[item]) XswMultiListHighlight(w, item); else XswMultiListUnhighlight(w, item); lw->multiList.toggle_state = lw->multiList.state[item]; } } else { lw->multiList.toggle_state = False; for(item = 0; item < lw->multiList.nitems; item++) XswMultiListUnhighlight(w, item); } } /* ARGSUSED */ static void Move(w, event, params, num_params) Widget w; XEvent * event; String * params; Cardinal *num_params; { int item; MultiListWidget lw = (MultiListWidget) w; if (!lw->multiList.single) { if ( (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item)) != OUT_OF_RANGE) { if (lw->multiList.toggle_state) XswMultiListHighlight(w, item); else XswMultiListUnhighlight(w, item); } } } /* * Set specified arguments into widget */ static void Destroy(cl) MultiListWidget cl; { XtReleaseGC((Widget) cl, cl->multiList.normgc); XtReleaseGC((Widget) cl, cl->multiList.graygc); XtReleaseGC((Widget) cl, cl->multiList.revgc); XtFree(cl->multiList.state); } static Boolean SetValues(current, request, new) Widget current, request, new; { int i; MultiListWidget cl = (MultiListWidget) current; MultiListWidget rl = (MultiListWidget) request; MultiListWidget nl = (MultiListWidget) new; Boolean redraw = FALSE; if ((cl->multiList.foreground != rl->multiList.foreground) || (cl->core.background_pixel != rl->core.background_pixel) || (cl->multiList.font != rl->multiList.font) ) { XtReleaseGC((Widget) cl, cl->multiList.normgc); XtReleaseGC((Widget) cl, cl->multiList.graygc); XtReleaseGC((Widget) cl, cl->multiList.revgc); GetGCs(new); redraw = TRUE; } /* Reset row height. */ if ((cl->multiList.row_space != rl->multiList.row_space) || (cl->multiList.font != rl->multiList.font)) nl->multiList.row_height = nl->multiList.font->max_bounds.ascent + nl->multiList.font->max_bounds.descent + nl->multiList.row_space; if ((cl->core.width != rl->core.width) || (cl->core.height != rl->core.height) || (cl->multiList.internal_width != rl->multiList.internal_width) || (cl->multiList.internal_height != rl->multiList.internal_height) || (cl->multiList.column_space != rl->multiList.column_space) || (cl->multiList.row_space != rl->multiList.row_space) || (cl->multiList.default_cols != rl->multiList.default_cols) || ( (cl->multiList.force_cols != rl->multiList.force_cols) && (rl->multiList.force_cols != rl->multiList.ncols) ) || (cl->multiList.vertical_cols != rl->multiList.vertical_cols) || (cl->multiList.longest != rl->multiList.longest) || (cl->multiList.nitems != rl->multiList.nitems) || (cl->multiList.font != rl->multiList.font) || (cl->multiList.list != rl->multiList.list) ) { ResetMultiList(new, TRUE, TRUE); redraw = TRUE; } if (cl->multiList.list != rl->multiList.list) for(i = 0; i < rl->multiList.nitems; i++) cl->multiList.state[i] = False; if ((cl->core.sensitive != rl->core.sensitive) || (cl->core.ancestor_sensitive != rl->core.ancestor_sensitive)) { redraw = TRUE; } if (!XtIsRealized(current)) return(FALSE); return(redraw); } /* Exported Functions */ /* Function Name: XswMultiListChange. * Description: Changes the multiList being used and shown. * Arguments: w - the multiList widget. * multiList - the new multiList. * nitems - the number of items in the multiList. * longest - the length (in Pixels) of the longest element * in the multiList. * resize - if TRUE the the multiList widget will * try to resize itself. * Returns: none. * NOTE: If nitems of longest are <= 0 then they will be calculated. * If nitems is <= 0 then the multiList needs to be NULL terminated. */ void XswMultiListChange(w, multiList, nitems, longest, resize_it) Widget w; char ** multiList; int nitems, longest; Boolean resize_it; { MultiListWidget lw = (MultiListWidget) w; lw->multiList.list = multiList; if (nitems <= 0) nitems = 0; lw->multiList.nitems = nitems; if (longest <= 0) longest = 0; lw->multiList.longest = longest; ResetMultiList(w, resize_it, resize_it); if ( XtIsRealized(w) ) Redisplay(w, NULL, NULL); } /* Function Name: XswMultiListUnhighlight * Description: unlights the current highlighted element. * Arguments: w - the widget. * Returns: none. */ void XswMultiListUnhighlight(w, item) Widget w; int item; { MultiListWidget lw = ( MultiListWidget ) w; if (lw->multiList.single) { lw->multiList.highlight = NO_HIGHLIGHT; if (lw->multiList.is_highlighted != NO_HIGHLIGHT) PaintmyItemName(w, lw->multiList.is_highlighted); } else { if (lw->multiList.state[item]) { lw->multiList.state[item] = False; PaintmyItemName(w, item); /* unhighlight this one. */ } } } /* Function Name: XswMultiListHighlight * Description: Highlights the given item. * Arguments: w - the multiList widget. * item - the item to hightlight. * Returns: none. */ void XswMultiListHighlight(w, item) Widget w; int item; { MultiListWidget lw = ( MultiListWidget ) w; if (XtIsSensitive(w)) { if (lw->multiList.single) { lw->multiList.highlight = item; if (lw->multiList.is_highlighted != NO_HIGHLIGHT) PaintmyItemName(w, lw->multiList.is_highlighted); /* Unhighlight. */ PaintmyItemName(w, item); /* HIGHLIGHT this one. */ } else { if (!lw->multiList.state[item]) { lw->multiList.state[item] = True; PaintmyItemName(w, item); /* HIGHLIGHT this one. */ } } } } /* Function Name: XswMultiListShowCurrent * Description: returns the currently highlighted object. * Arguments: w - the multiList widget. * Returns: the info about the currently highlighted object. */ XswMultiListReturnStruct * XswMultiListShowCurrent(w) Widget w; { MultiListWidget lw = ( MultiListWidget ) w; XswMultiListReturnStruct * ret_val; int i, n; ret_val = (XswMultiListReturnStruct *) XtMalloc((lw->multiList.nitems+1) * sizeof(XswMultiListReturnStruct)); if (lw->multiList.single) { ret_val->list_index = lw->multiList.highlight; if (ret_val->list_index == XSW_LIST_NONE) ret_val->string = ""; else ret_val->string = lw->multiList.list[ ret_val->list_index ]; n = 1; } else { n = 0; for(i = 0; i < lw->multiList.nitems; i++) { if (lw->multiList.state[i]) { ret_val[n].string = lw->multiList.list[i]; ret_val[n].list_index = i; n++; } } } ret_val[n].string = ""; ret_val[n].list_index = XSW_LIST_NONE; return(ret_val); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.