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