/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include /* */ #ifdef sgi #include #endif #ifdef OS2 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "NumericList.h" #include "NumericListP.h" /*#include "uiustring.h" */ #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #define superclass (&widgetClassRec) #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif static void Initialize( XmNumericListWidget request, XmNumericListWidget new ); static Boolean SetValues( XmNumericListWidget current, XmNumericListWidget request, XmNumericListWidget new ); static void Realize( register XmNumericListWidget w, Mask *p_valueMask, XSetWindowAttributes *attributes ); static void Redisplay(XmNumericListWidget nlw, XEvent *event); static void Destroy(XmNumericListWidget nlw); static void print_vector(XmNumericListWidget nlw, int vector_number, Boolean inverse, Boolean clear); static void do_layout(XmNumericListWidget nlw); static void MakeGC ( XmNumericListWidget w); static void copy_vectors(XmNumericListWidget nlw, int old_n_vectors); static void Arm(); static void Activate(); static void decrement_if_possible(); static void increment_if_possible(); static void jump_to_end(XmNumericListWidget nlw); static void set_decimal_places(XmNumericListWidget nlw); static void BtnMotion(); #define STRCMP(a,b) ((a) ? ((b) ? strcmp(a,b) : strcmp(a,"")) : \ ((b) ? strcmp("",b) : 0)) #define STRLEN(s) ((s) ? strlen(s) : 0) /* Default translation table and action list */ static char defaultTranslations[] = ": Arm()\n\ : Activate()\n\ : BtnMotion()\n\ : Enter() \n\ : FocusIn()"; extern void _XmManagerEnter(); extern void _XmManagerFocusIn(); static XtActionsRec actionsList[] = { { "Arm", (XtActionProc) Arm }, { "Activate", (XtActionProc) Activate }, { "BtnMotion",(XtActionProc) BtnMotion }, { "Enter", (XtActionProc) _XmManagerEnter }, { "FocusIn", (XtActionProc) _XmManagerFocusIn }, }; static XtResource resources[] = { { XmNtuples,XmCValue,XmRInt,sizeof(int), XtOffset(XmNumericListWidget,numeric_list.tuples), XmRImmediate, (caddr_t)3 }, { /* This should be a readonly resource */ XmNreadonlyVectors,XmCVector,XmRVectorList,sizeof(VectorList), XtOffset(XmNumericListWidget,numeric_list.local_vectors), XmRImmediate, (caddr_t)-1 }, { XmNvectors,XmCVector,XmRVectorList,sizeof(VectorList), XtOffset(XmNumericListWidget,numeric_list.vectors), XmRImmediate, (caddr_t)-1 }, { XmNvectorCount,XmCValue,XmRInt,sizeof(int), XtOffset(XmNumericListWidget,numeric_list.vector_count), XmRImmediate, (caddr_t)1 }, { XmNvectorSpacing,XmCValue,XmRDimension,sizeof(Dimension), XtOffset(XmNumericListWidget,numeric_list.vector_spacing), XmRImmediate, (caddr_t)10 }, { XmNdecimalPlaces,XmCValue,XmRPointer,sizeof(int *), XtOffset(XmNumericListWidget,numeric_list.decimal_places), XmRImmediate, (caddr_t)NULL }, { XmNselectCallback,XmCCallback,XmRCallback,sizeof(caddr_t), XtOffset(XmNumericListWidget,numeric_list.select_callback), XmRCallback,(caddr_t)NULL }, { XmNminColumnWidth,XmCMinColumnWidth,XmRDimension,sizeof(Dimension), XtOffset(XmNumericListWidget,numeric_list.min_column_width), XmRImmediate, (caddr_t)20 }, }; /**************************************************************** * * Full class record constant * ****************************************************************/ XmNumericListClassRec xmNumericListClassRec = { { /* core_class fields */ (WidgetClass) &xmBulletinBoardClassRec, /* superclass */ "XmNumericList", /* class_name */ sizeof(XmNumericListRec), /* widget_size */ NULL, /* class_initialize */ NULL, /* class_part_init */ FALSE, /* class_inited */ (XtInitProc) Initialize, /* initialize */ NULL, /* initialize_hook */ (XtRealizeProc)Realize, /* realize */ (XtActionList)actionsList, /* actions */ XtNumber(actionsList), /* num_actions */ resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterlv */ FALSE, /* visible_interest */ (XtWidgetProc)Destroy, /* destroy */ (XtWidgetProc)_XtInherit, /* resize */ (XtExposeProc)Redisplay, /* expose */ (XtSetValuesFunc) SetValues, /* set_values */ NULL, /* set_values_hook */ (XtAlmostProc)_XtInherit, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback_private */ defaultTranslations, /* tm_table */ XtInheritQueryGeometry, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ }, { /* composite_class fields */ XtInheritGeometryManager, /* geometry_manager */ (XtWidgetProc)_XtInherit, /* change_managed */ (XtWidgetProc)_XtInherit, /* insert_child */ (XtWidgetProc)_XtInherit, /* delete_child */ NULL, /* extension */ }, { /* constraint_class fields */ NULL, /* resource list */ 0, /* num resources */ sizeof (XmManagerConstraintRec), /* constraint size */ NULL, /* init proc */ NULL, /* destroy proc */ NULL, /* set values proc */ NULL, /* extension */ }, { /* manager_class fields */ #if (XmVersion >= 1001) XtInheritTranslations, /* translations */ #else (XtTranslations)_XtInherit, /* translations */ #endif NULL, /* get resources */ 0, /* num get_resources */ NULL, /* get_cont_resources */ 0, /* num_get_cont_resources */ (XmParentProcessProc)NULL, /* parent_process */ NULL, /* extension */ }, { /* bulletin board class - none */ 0, /* mumble */ }, { /* numeric_list class - none */ 0 /* mumble */ } }; WidgetClass xmNumericListWidgetClass = (WidgetClass) &xmNumericListClassRec; /* Subroutine: Initialize * Effect: Create and initialize the component widgets */ static void Initialize( XmNumericListWidget request, XmNumericListWidget new ) { XmFontList font_list; int n; int i; int j; Widget label; Arg wargs[100]; unsigned long space; #if (XmVersion >= 1001) XmFontContext context; XmStringCharSet charset; #endif /* * Create a label widget in order to extract the current font list. */ label = (Widget)XmCreateLabel((Widget)(new), "Label", wargs, 0); XtSetArg(wargs[0], XmNfontList, &font_list); XtGetValues(label, wargs, 1); #if (XmVersion < 1001) new->numeric_list.font = font_list->font; #else XmFontListInitFontContext(&context, font_list); XmFontListGetNextFont(context, &charset, &new->numeric_list.font); XmFontListFreeFontContext(context); #endif /* * Check to see if there is a XA_NORM_SPACE font property defined * for this font. If there is, save it. */ if (XGetFontProperty(new->numeric_list.font, XA_NORM_SPACE, &space)) { new->numeric_list.norm_space = space; } else { new->numeric_list.norm_space = 0; } /* * Move the vector pointer to a private variable and reset the resource * variable to NULL so we can detect a SetValues on this resource; */ copy_vectors(new, 0); /* * Setting up the decimal places MUST happen before do_layout. */ new->numeric_list.local_decimal_places = NULL; set_decimal_places(new); new->numeric_list.decimal_places = NULL; /* * Start with none of the vectors selected */ new->numeric_list.selected = -1; new->numeric_list.first_selected = -1; if ( XtClass(XtParent(new)) == xmScrolledWindowWidgetClass) { XtSetArg(wargs[0], XmNverticalScrollBar, &new->numeric_list.vsb); XtGetValues(XtParent(new), wargs, 1); XtSetArg(wargs[0], XmNhorizontalScrollBar, &new->numeric_list.hsb); XtGetValues(XtParent(new), wargs, 1); } else { new->numeric_list.hsb = NULL; new->numeric_list.vsb = NULL; } new->numeric_list.tid = NULL; new->numeric_list.scrolled_window = False; new->numeric_list.sw = NULL; new->numeric_list.decrementing = False; new->numeric_list.incrementing = False; new->numeric_list.vectors = NULL; new->numeric_list.normal_gc = (GC)NULL; new->numeric_list.inverse_gc = (GC)NULL; new->numeric_list.vector_width_left = NULL; new->numeric_list.vector_width_right = NULL; } /* Subroutine: SetValues * Effect: Handles requests to change things from the application */ static Boolean SetValues( XmNumericListWidget current, XmNumericListWidget request, XmNumericListWidget new ) { Boolean dolayout = False; Boolean redraw = False; XSetWindowAttributes attributes; if (new->numeric_list.decimal_places != current->numeric_list.decimal_places) { set_decimal_places(new); dolayout = True; redraw = True; new->numeric_list.decimal_places = NULL; } if(new->numeric_list.vectors != current->numeric_list.vectors) { copy_vectors(new, current->numeric_list.vector_count); dolayout = True; redraw = True; new->numeric_list.vectors = NULL; } if(new->numeric_list.vector_count < current->numeric_list.vector_count) { new->numeric_list.selected = -1; } if ((new->manager.foreground != current->manager.foreground)|| (new->core.background_pixel != current->core.background_pixel)) { MakeGC (new); redraw = True; } if (dolayout) do_layout(new); return redraw; } /* Subroutine: Realize * Purpose: Create the window with PointerMotion events and None gravity */ static void Realize( register XmNumericListWidget w, Mask *p_valueMask, XSetWindowAttributes *attributes ) { /* * Call the superclass realize method */ (*superclass->core_class.realize)((Widget)w, p_valueMask, attributes); MakeGC (w); do_layout(w); } /* * Recompute the GC's. Moved into a subroutine so that it can be called * from SetValues when the colors change. */ static void MakeGC ( XmNumericListWidget w) { unsigned long valuemask; XGCValues values; if(w->numeric_list.normal_gc) XtReleaseGC((Widget)w, w->numeric_list.normal_gc); if(w->numeric_list.inverse_gc) XtReleaseGC((Widget)w, w->numeric_list.inverse_gc); /* * Create a normal video and inverse video GC. */ valuemask = GCForeground | GCBackground | GCFont; values.foreground = w->manager.foreground; values.background = w->core.background_pixel; values.font = w->numeric_list.font->fid; w->numeric_list.normal_gc = XtGetGC((Widget)w, valuemask, &values); values.foreground = w->core.background_pixel; values.background = w->manager.foreground; values.font = w->numeric_list.font->fid; w->numeric_list.inverse_gc = XtGetGC((Widget)w, valuemask, &values); } static void Destroy( XmNumericListWidget nlw) { int i; if(nlw->numeric_list.normal_gc) XtReleaseGC((Widget)nlw, nlw->numeric_list.normal_gc); if(nlw->numeric_list.inverse_gc) XtReleaseGC((Widget)nlw, nlw->numeric_list.inverse_gc); if (nlw->numeric_list.local_decimal_places) XtFree((char*)nlw->numeric_list.local_decimal_places); if (nlw->numeric_list.vector_width_left) XtFree((char*)nlw->numeric_list.vector_width_left); if (nlw->numeric_list.vector_width_right) XtFree((char*)nlw->numeric_list.vector_width_right); /* * Free the old vectors */ if (nlw->numeric_list.vector_count > 0) { if(nlw->numeric_list.local_vectors) { for (i=0; i < nlw->numeric_list.vector_count; i++) { XtFree((char*)nlw->numeric_list.local_vectors[i]); } XtFree((char*)nlw->numeric_list.local_vectors); } } } /********************************************************************* * print_vector - clears the background (if necessary) and draws the * string. **********************************************************************/ static void print_vector(XmNumericListWidget nlw, int vector_number, Boolean inverse, Boolean clear) { int i; char string[100]; char **e_format; char **f_format; char tmp[100]; GC gc; Dimension x; Dimension y; XCharStruct overall; Dimension width; Boolean fixed_format; int k; y = vector_number * nlw->numeric_list.line_height; if (!inverse) { /* * Draw a deselected item */ if(clear || inverse) { XFillRectangle(XtDisplay(nlw), XtWindow(nlw), nlw->numeric_list.inverse_gc, 0,y, nlw->core.width, nlw->numeric_list.line_height); } gc = nlw->numeric_list.normal_gc; } else { /* * Select the item */ if(clear || inverse) { XFillRectangle(XtDisplay(nlw), XtWindow(nlw), nlw->numeric_list.normal_gc, 0,y, nlw->core.width, nlw->numeric_list.line_height); } gc = nlw->numeric_list.inverse_gc; } e_format = (char **)XtCalloc(nlw->numeric_list.tuples , sizeof(char *)); f_format = (char **)XtCalloc(nlw->numeric_list.tuples , sizeof(char *)); for(i = 0; i < nlw->numeric_list.tuples; i++) { e_format[i] = (char *)XtCalloc(100 , sizeof(char *)); f_format[i] = (char *)XtCalloc(100 , sizeof(char *)); *(e_format[i] + 0) = '%'; *(e_format[i] + 1) = '.'; *(e_format[i] + 2) = '\0'; sprintf(tmp, "%de", nlw->numeric_list.local_decimal_places[i]); strcat(e_format[i], tmp); *(f_format[i] + 0) = '%'; *(f_format[i] + 1) = '.'; *(f_format[i] + 2) = '\0'; sprintf(tmp, "%df", nlw->numeric_list.local_decimal_places[i]); strcat(f_format[i], tmp); } x = nlw->numeric_list.vector_spacing; for(i = 0; i < nlw->numeric_list.tuples; i++) { memset(string, 0, 100); if (((*(nlw->numeric_list.local_vectors[vector_number] + i) > 0.0) && (*(nlw->numeric_list.local_vectors[vector_number] + i) < .001)) || ((*(nlw->numeric_list.local_vectors[vector_number] + i) < 0.0) && (*(nlw->numeric_list.local_vectors[vector_number] + i) > -0.001))) { sprintf(string, e_format[i], *(nlw->numeric_list.local_vectors[vector_number] + i)); fixed_format = False; } else { sprintf(string, f_format[i], *(nlw->numeric_list.local_vectors[vector_number] + i)); fixed_format = True; } if (STRLEN(string) > nlw->numeric_list.local_decimal_places[i] + 7) { sprintf(string, e_format[i], *(nlw->numeric_list.local_vectors[vector_number] + i)); fixed_format = False; } k = 0; while( (string[k] != '\0') && (string[k] != '.') ) k++; width = XTextWidth(nlw->numeric_list.font, string, k+1); width += nlw->numeric_list.norm_space * (k+1); XDrawString(XtDisplay(nlw), XtWindow(nlw), gc, x + (nlw->numeric_list.vector_width_left[i] - width), y + nlw->numeric_list.line_height - nlw->numeric_list.descent, string, STRLEN(string)); /* * Move to the next component of the vector. */ x = x + nlw->numeric_list.vector_spacing + nlw->numeric_list.vector_width_left[i] + nlw->numeric_list.vector_width_right[i]; } for(i = 0; i < nlw->numeric_list.tuples; i++) { XtFree(f_format[i]); XtFree(e_format[i]); } XtFree((char*)f_format); XtFree((char*)e_format); } static void Redisplay(XmNumericListWidget nlw, XEvent *event) { Boolean inverse; int i; for(i = 0; i < nlw->numeric_list.vector_count; i++) { if (nlw->numeric_list.selected == i) { inverse = True; } else { inverse = False; } print_vector(nlw, i, inverse, False); } } static void Arm(XmNumericListWidget nlw, XEvent *event, String *params, Cardinal *num_params) { int vector_number; if (nlw->numeric_list.vector_count == 0) return; vector_number = (event->xbutton.y/nlw->numeric_list.line_height); nlw->numeric_list.first_selected = vector_number; /* * Deselect the item if the user pressed a button on a selected item */ if (nlw->numeric_list.selected == vector_number) { print_vector(nlw, vector_number, False, True); nlw->numeric_list.selected = -1; return; } /* * If an item was selected, deselect it. */ if (nlw->numeric_list.selected != -1) { print_vector(nlw, nlw->numeric_list.selected, False, True); } /* * Select the item */ print_vector(nlw, vector_number, True, True); nlw->numeric_list.selected = vector_number; } static void BtnMotion(XmNumericListWidget nlw, XEvent *event, String *params, Cardinal *num_params) { int vector_number; int sw_x; int sw_y; int sw_height; Window child; Widget clip_window; Arg wargs[10]; if (nlw->numeric_list.vector_count == 0) return; /* * Get the coords relative to the scrolled window. */ if (nlw->numeric_list.scrolled_window) { XtSetArg(wargs[0], XmNclipWindow, &clip_window); XtGetValues((Widget)nlw->numeric_list.sw, wargs, 1); XtSetArg(wargs[0], XmNheight, &sw_height); XtGetValues(clip_window, wargs, 1); XTranslateCoordinates( XtDisplay(nlw), XtWindow(nlw), XtWindow(clip_window), event->xbutton.x, event->xbutton.y, &sw_x, &sw_y, &child); /* * Turn off Timer if we have moved back in between the top & bottom. */ if ( (nlw->numeric_list.tid != NULL) && (sw_y > 0) && (sw_y < sw_height) ) { XtRemoveTimeOut(nlw->numeric_list.tid); nlw->numeric_list.tid = NULL; nlw->numeric_list.decrementing = False; nlw->numeric_list.incrementing = False; } /* * Turn on decrement timer. */ if( (sw_y < 0) && (nlw->numeric_list.tid == NULL) ) { nlw->numeric_list.tid = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)nlw), 100, decrement_if_possible, nlw); nlw->numeric_list.decrementing = True; return; } /* * Turn on increment timer. */ if ( (sw_y > sw_height) && (nlw->numeric_list.tid == NULL) ) { nlw->numeric_list.tid = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)nlw), 100, increment_if_possible, nlw); nlw->numeric_list.incrementing = True; return; } /* * Turn off increment time and turn on decrement timer. */ if ( (sw_y < 0) && (nlw->numeric_list.incrementing) ) { XtRemoveTimeOut(nlw->numeric_list.tid); nlw->numeric_list.tid = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)nlw), 100, decrement_if_possible, nlw); nlw->numeric_list.incrementing = False; nlw->numeric_list.decrementing = True; return; } /* * Turn off decrement time and turn on increment timer. */ if ( (sw_y > sw_height) && (nlw->numeric_list.decrementing) ) { XtRemoveTimeOut(nlw->numeric_list.tid); nlw->numeric_list.tid = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)nlw), 100, increment_if_possible, nlw); nlw->numeric_list.decrementing = False; nlw->numeric_list.incrementing = True; return; } } vector_number = (event->xbutton.y/nlw->numeric_list.line_height); if(vector_number < 0) { vector_number = 0; } if(vector_number >= nlw->numeric_list.vector_count) { vector_number = nlw->numeric_list.vector_count - 1; } if (vector_number == nlw->numeric_list.first_selected) { return; } else { nlw->numeric_list.first_selected = -1; } /* * Ignore the item if it was already selected */ if (nlw->numeric_list.selected == vector_number) { return; } /* * If an item was selected, deselect it. */ if (nlw->numeric_list.selected != -1) { print_vector(nlw, nlw->numeric_list.selected, False, True); } /* * Select the item */ print_vector(nlw, vector_number, True, True); nlw->numeric_list.selected = vector_number; } static void Activate(XmNumericListWidget nlw, XEvent *event, String *params, Cardinal *num_params) { XmNumericListCallbackStruct cb; if (nlw->numeric_list.vector_count == 0) return; if (nlw->numeric_list.tid != NULL) { XtRemoveTimeOut(nlw->numeric_list.tid); nlw->numeric_list.tid = NULL; } nlw->numeric_list.first_selected = -1; /* * Invoke the select callback. */ cb.reason = XmCR_SINGLE_SELECT; cb.event = event; cb.position = nlw->numeric_list.selected; cb.vector_list = nlw->numeric_list.local_vectors; XtCallCallbacks((Widget)nlw,XmNselectCallback,&cb); } /********************************************************************* * copy_vectors - allocates an internal buffer and copies the vector * list to the internal buffer * **********************************************************************/ static void copy_vectors(XmNumericListWidget nlw, int old_n_vectors) { int i; int j; /* * Free the old vectors */ if (old_n_vectors > 0) { if(nlw->numeric_list.local_vectors) { for (i=0; i < old_n_vectors; i++) { XtFree((char*)nlw->numeric_list.local_vectors[i]); } XtFree((char*)nlw->numeric_list.local_vectors); } } /* * Alloc the new memory and copy the vector over */ nlw->numeric_list.local_vectors = (VectorList)XtMalloc(sizeof(Vector) * nlw->numeric_list.vector_count); for (i=0; i < nlw->numeric_list.vector_count; i++) { nlw->numeric_list.local_vectors[i] = (Vector)XtCalloc(nlw->numeric_list.tuples , sizeof(double)); /* * It is possible that the user has not provided a VectorList, * so check to see if it exists first. */ if (nlw->numeric_list.vectors) { for (j=0; j < nlw->numeric_list.tuples; j++) { *(nlw->numeric_list.local_vectors[i] + j) = *(nlw->numeric_list.vectors[i] + j); } } } nlw->numeric_list.vectors = NULL; } /********************************************************************* * set_decimal_places - allocates an internal buffer and copies the * decimal places to the internal buffer * **********************************************************************/ static void set_decimal_places(XmNumericListWidget nlw) { int i; if (nlw->numeric_list.local_decimal_places) { XtFree((char*)nlw->numeric_list.local_decimal_places); } nlw->numeric_list.local_decimal_places = (int *)XtCalloc(nlw->numeric_list.tuples, sizeof(int)); for (i = 0; i < nlw->numeric_list.tuples; i++) { if(nlw->numeric_list.decimal_places == NULL) { nlw->numeric_list.local_decimal_places[i] = 2; } else { nlw->numeric_list.local_decimal_places[i] = nlw->numeric_list.decimal_places[i]; } } } /********************************************************************* * do_layout - calculates the overall width and height required for the * widget based on the font information **********************************************************************/ static void do_layout(XmNumericListWidget nlw) { Dimension line_width; int dir; Dimension width; Dimension height; XCharStruct overall; int i; int j; char tmp[100]; char **e_format; char **f_format; char string[100]; int k; Dimension ret_width; Dimension ret_height; Dimension sw_width; Arg wargs[20]; int n; XtGeometryResult status; XtWidgetGeometry request; XtWidgetGeometry reply; Widget clip_window; Boolean fixed_format; /* * Calculate the height required for each line. */ string[0] = '5'; string[1] = '\0'; XTextExtents(nlw->numeric_list.font, string, STRLEN(string), &dir, &nlw->numeric_list.ascent, &nlw->numeric_list.descent, &overall); nlw->numeric_list.line_height = nlw->numeric_list.ascent + nlw->numeric_list.descent; height = MAX(nlw->numeric_list.line_height * nlw->numeric_list.vector_count, 10); /* * Unmanage and re-manage the vertical scrollbar to skirt and *apparent* * bug in the scrolled window widget. */ if(nlw->numeric_list.vsb) XtUnmanageChild(nlw->numeric_list.vsb); request.request_mode = CWHeight; request.height = height; status = XtMakeGeometryRequest((Widget)nlw, &request, &reply); if(nlw->numeric_list.vsb) XtManageChild(nlw->numeric_list.vsb); e_format = (char **)XtCalloc(nlw->numeric_list.tuples, sizeof(char *)); f_format = (char **)XtCalloc(nlw->numeric_list.tuples, sizeof(char *)); if (nlw->numeric_list.vector_width_left) XtFree((char*)nlw->numeric_list.vector_width_left); if (nlw->numeric_list.vector_width_right) XtFree((char*)nlw->numeric_list.vector_width_right); nlw->numeric_list.vector_width_left = (Dimension *)XtCalloc(nlw->numeric_list.tuples, sizeof(Dimension)); nlw->numeric_list.vector_width_right = (Dimension *)XtCalloc(nlw->numeric_list.tuples, sizeof(Dimension)); for(i = 0; i < nlw->numeric_list.tuples; i++) { /* * Create a format string for each column */ e_format[i] = (char *)XtCalloc(100 , sizeof(char *)); f_format[i] = (char *)XtCalloc(100 , sizeof(char *)); *(e_format[i] + 0) = '%'; *(e_format[i] + 1) = '.'; *(e_format[i] + 2) = '\0'; sprintf(tmp, "%de", nlw->numeric_list.local_decimal_places[i]); strcat(e_format[i], tmp); *(f_format[i] + 0) = '%'; *(f_format[i] + 1) = '.'; *(f_format[i] + 2) = '\0'; sprintf(tmp, "%df", nlw->numeric_list.local_decimal_places[i]); strcat(f_format[i], tmp); /* * Init vector width for each column to 0 */ nlw->numeric_list.vector_width_left[i] = nlw->numeric_list.min_column_width; nlw->numeric_list.vector_width_right[i] =nlw->numeric_list.min_column_width; } for(i = 0; i < nlw->numeric_list.vector_count; i++) { for(j = 0; j < nlw->numeric_list.tuples; j++) { memset(string, 0, 100); if (((*(nlw->numeric_list.local_vectors[i] + j) > 0.0) && (*(nlw->numeric_list.local_vectors[i] + j) < .001)) || ((*(nlw->numeric_list.local_vectors[i] + j) < 0.0) && (*(nlw->numeric_list.local_vectors[i] + j) > -0.001))) { sprintf(string, e_format[j], *(nlw->numeric_list.local_vectors[i] + j)); fixed_format = False; } else { sprintf(string, f_format[j], *(nlw->numeric_list.local_vectors[i] + j)); fixed_format = True; } if (STRLEN(string) > nlw->numeric_list.local_decimal_places[j] + 7) { sprintf(string, e_format[j], *(nlw->numeric_list.local_vectors[i] + j)); fixed_format = False; } k = 0; while( (string[k] != '\0') && (string[k] != '.') ) k++; width = XTextWidth(nlw->numeric_list.font, string, k+1); width += nlw->numeric_list.norm_space * (k+1); if(nlw->numeric_list.vector_width_left[j] < width) { nlw->numeric_list.vector_width_left[j] = width; } if(string[k] == '.') { width = XTextWidth(nlw->numeric_list.font, &string[k+1], STRLEN(&string[k+1])); width += nlw->numeric_list.norm_space * STRLEN(&string[k+1]); if(nlw->numeric_list.vector_width_right[j] < width) { nlw->numeric_list.vector_width_right[j] = width; } } } } /* * Calc the overall line width */ line_width = 0; for (i = 0; i < nlw->numeric_list.tuples; i++) { line_width += nlw->numeric_list.vector_width_left[i]; line_width += nlw->numeric_list.vector_width_right[i]; line_width += nlw->numeric_list.vector_spacing; } line_width += nlw->numeric_list.vector_spacing; if ( (XtClass(XtParent(nlw)) == xmScrolledWindowWidgetClass) || (nlw->numeric_list.scrolled_window) ) { if (nlw->numeric_list.hsb && XtIsManaged(nlw->numeric_list.hsb)) { if (nlw->numeric_list.sw) { clip_window = XtParent(nlw); } else { n = 0; XtSetArg(wargs[n], XmNclipWindow, &clip_window); XtGetValues(XtParent(nlw), wargs, n); n++; } n = 0; XtSetArg(wargs[n], XmNwidth, &sw_width); n++; XtGetValues(clip_window, wargs, n); } else { n = 0; XtSetArg(wargs[n], XmNwidth, &sw_width); n++; if (nlw->numeric_list.sw) { XtGetValues((Widget)nlw->numeric_list.sw, wargs, n); } else { XtGetValues(XtParent(nlw), wargs, n); n++; } } if (line_width < sw_width) { line_width = sw_width-2; } } width = MAX(line_width, 10); if(nlw->numeric_list.vsb) XtUnmanageChild(nlw->numeric_list.vsb); request.request_mode = CWWidth; request.width = width; status = XtMakeGeometryRequest((Widget)nlw, &request, &reply); if(nlw->numeric_list.vsb) XtManageChild(nlw->numeric_list.vsb); /* * Free the format strings */ for(i = 0; i < nlw->numeric_list.tuples; i++) { XtFree(e_format[i]); XtFree(f_format[i]); } XtFree((char*)e_format); XtFree((char*)f_format); } /***************************************************************************/ /* Subroutine: decrement_if_possible */ /* */ /* */ /***************************************************************************/ static void decrement_if_possible(XmNumericListWidget nlw, XtIntervalId *id) { Arg wargs[10]; int n; int value; int blank_lines; XmScrolledWindowWidget window; XEvent *event; Boolean inverse; int i; nlw->numeric_list.tid = NULL; if (!nlw->numeric_list.scrolled_window) return; window = (XmScrolledWindowWidget)XtParent(XtParent(nlw)); XtVaGetValues(XtParent(nlw), XmNverticalScrollBar, &nlw->numeric_list.vsb, NULL); if(!nlw->numeric_list.vsb) return; n = 0; XtSetArg(wargs[n], XmNvalue, &value); n++; XtGetValues(nlw->numeric_list.vsb, wargs, n); value = value - nlw->numeric_list.line_height; if (value < 0) value = 0; /* * Align the vectors on a line border */ if (value != 0) { blank_lines = value/nlw->numeric_list.line_height; if (value != blank_lines * nlw->numeric_list.line_height) { value = blank_lines * nlw->numeric_list.line_height; } } else { blank_lines = 0; } /* * Reset the scrolled window's (x,y) origin. */ window->swindow.vOrigin = -value; /* * Move the work window to reflect the new state. */ XtMoveWidget(window->swindow.WorkWindow, (Position)(window->swindow.hOrigin), (Position)(window->swindow.vOrigin)); XtSetArg(wargs[0], XmNvalue, value); XtSetValues(nlw->numeric_list.vsb, wargs, 1); nlw->numeric_list.selected = blank_lines; for(i = 0; i < nlw->numeric_list.vector_count; i++) { if (nlw->numeric_list.selected == i) { inverse = True; } else { inverse = False; } print_vector(nlw, i, inverse, True); } if (value != 0) { nlw->numeric_list.tid = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)nlw), 100, (XtTimerCallbackProc)decrement_if_possible, nlw); } } /***************************************************************************/ /* Subroutine: jump_to_end */ /* */ /* */ /***************************************************************************/ static void jump_to_end(XmNumericListWidget nlw) { Arg wargs[10]; int n; int value; int max; int min; int slider_size; int increment; int page_increment; int blank_lines; XmScrolledWindowWidget window; XEvent *event; Boolean inverse; int i; if (!nlw->numeric_list.scrolled_window) return; window = (XmScrolledWindowWidget)XtParent(XtParent(nlw)); XtVaGetValues(XtParent(nlw), XmNverticalScrollBar, &nlw->numeric_list.vsb, NULL); if(!nlw->numeric_list.vsb) return; n = 0; XtSetArg(wargs[n], XmNmaximum, &max); n++; XtSetArg(wargs[n], XmNsliderSize, &slider_size); n++; XtGetValues(nlw->numeric_list.vsb, wargs, n); XmScrollBarGetValues(nlw->numeric_list.vsb, &value, &slider_size, &increment, &page_increment); value = max - slider_size; XmScrollBarSetValues(nlw->numeric_list.vsb, value, slider_size, increment, page_increment, True); /* * Move the work window to reflect the new state. */ XtMoveWidget(window->swindow.WorkWindow, (Position)(window->swindow.hOrigin), (Position)-value); /* * Reset the scrolled window's (x,y) origin. */ window->swindow.vOrigin = -value; for(i = 0; i < nlw->numeric_list.vector_count; i++) { if (nlw->numeric_list.selected == i) { inverse = True; } else { inverse = False; } print_vector(nlw, i, inverse, True); } } /***************************************************************************/ /* Subroutine: increment_if_possible */ /* */ /* */ /***************************************************************************/ static void increment_if_possible(XmNumericListWidget nlw, XtIntervalId *id) { Arg wargs[10]; int n; int value; int max; int slider_size; int blank_lines; XmScrolledWindowWidget window; XEvent *event; Boolean inverse; int i; nlw->numeric_list.tid = NULL; if (!nlw->numeric_list.scrolled_window) return; window = (XmScrolledWindowWidget)XtParent(XtParent(nlw)); XtVaGetValues(XtParent(nlw), XmNverticalScrollBar, &nlw->numeric_list.vsb, NULL); if(!nlw->numeric_list.vsb) return; n = 0; XtSetArg(wargs[n], XmNvalue, &value); n++; XtSetArg(wargs[n], XmNmaximum, &max); n++; XtSetArg(wargs[n], XmNsliderSize, &slider_size); n++; XtGetValues(nlw->numeric_list.vsb, wargs, n); max = max - slider_size; value = value + nlw->numeric_list.line_height; if (value > max) value = max; /* * Align the vectors on a line border */ if ( (max - value) != 0) { blank_lines = (max - value)/nlw->numeric_list.line_height; if ((max - value) != blank_lines * nlw->numeric_list.line_height) { value = max - blank_lines * nlw->numeric_list.line_height; } } else { blank_lines = 0; } /* * Reset the scrolled window's (x,y) origin. */ window->swindow.vOrigin = -value; /* * Move the work window to reflect the new state. */ XtMoveWidget(window->swindow.WorkWindow, (Position)(window->swindow.hOrigin), (Position)(window->swindow.vOrigin)); XtSetArg(wargs[0], XmNvalue, value); XtSetValues(nlw->numeric_list.vsb, wargs, 1); nlw->numeric_list.selected = nlw->numeric_list.vector_count - (blank_lines + 1); for(i = 0; i < nlw->numeric_list.vector_count; i++) { if (nlw->numeric_list.selected == i) { inverse = True; } else { inverse = False; } print_vector(nlw, i, inverse, True); } if (value != max) { nlw->numeric_list.tid = XtAppAddTimeOut( XtWidgetToApplicationContext((Widget)nlw), 100, (XtTimerCallbackProc)increment_if_possible, nlw); } } /* Subroutine: XmCreateNumericList * Purpose: This function creates and returns a NumericList widget. */ Widget XmCreateNumericList( Widget parent, String name, ArgList args, Cardinal num_args ) { return XtCreateWidget(name, xmNumericListWidgetClass, parent, args, num_args); } /************************************************************************ * * * XmCreateScrolledNumericList - create a list inside of a scrolled window.* * * ************************************************************************/ Widget XmCreateScrolledNumericList(parent, name, args, argCount) Widget parent; char *name; ArgList args; int argCount; { XmNumericListWidget nlw; XmScrolledWindowWidget sw; int n; int i; char *s; Arg wargs[100]; Arg wargs2[100]; s = XtMalloc(STRLEN(name) + 3); /* Name + NULL + "SW" */ strcpy(s, name); strcat(s, "SW"); i = 0; for(n = 0; n < argCount; n++) { wargs[n] = args[n]; if ( (STRCMP(wargs[n].name,XmNwidth) == 0) || (STRCMP(wargs[n].name,XmNheight) == 0) ) { wargs2[i] = args[n]; i++; } } XtSetArg (wargs2[i], XmNscrollingPolicy, XmAUTOMATIC); i++; XtSetArg (wargs2[i], XmNscrollBarDisplayPolicy, (XtArgVal )XmAS_NEEDED);i++; sw = (XmScrolledWindowWidget)XmCreateScrolledWindow(parent, s, wargs2, i); XtManageChild((Widget)sw); XtFree(s); nlw = (XmNumericListWidget)XmCreateNumericList((Widget)sw, name, wargs, n); #if !defined(__cplusplus) && !defined(c_plusplus) /* * The c++ dxui installs its own destroy callbacks for the root of a * widget tree. */ XtAddCallback ((Widget)nlw, XmNdestroyCallback, (XtCallbackProc)_XmDestroyParentCallback, NULL); #endif nlw->numeric_list.scrolled_window = True; nlw->numeric_list.sw = sw; return ((Widget)nlw); } /********************************************************************* * XmNumericListAddVector - Add a vector ABOVE the indicated vector * **********************************************************************/ Boolean XmNumericListAddVector(XmNumericListWidget nlw, Vector vector, int vector_num) { int i; int j; int k; VectorList vlist; XEvent *event; Boolean do_jump = False; /* * Check that the vector_num is in range */ if (vector_num >= nlw->numeric_list.vector_count) { XtWarning("Illegal position value encountered in " "XmNumericListAddVector."); return(0); } /* * Alloc the new memory and copy the vectors over, inserting the new vector */ vlist = (VectorList)XtMalloc(sizeof(Vector) * (nlw->numeric_list.vector_count + 1)); /* * Special Case - when vector_num is -1, add the vector at the end of the * vector list. */ if (vector_num == -1) { for (i=0; i < nlw->numeric_list.vector_count; i++) { vlist[i] = nlw->numeric_list.local_vectors[i]; } vlist[i] = (Vector)XtMalloc(sizeof(double) * nlw->numeric_list.tuples); for (j=0; j < nlw->numeric_list.tuples; j++) { *(vlist[i] + j) = vector[j]; } vector_num = nlw->numeric_list.vector_count; do_jump = True; } else { k = 0; for (i=0; i < nlw->numeric_list.vector_count; i++) { if (i == vector_num) { vlist[k] = (Vector)XtMalloc(sizeof(double) * nlw->numeric_list.tuples); for (j=0; j < nlw->numeric_list.tuples; j++) { *(vlist[k] + j) = vector[j]; } k++; } vlist[k] = nlw->numeric_list.local_vectors[i]; k++; } } /* * Free the old vectors */ XtFree((char*)nlw->numeric_list.local_vectors); /* * Install the new vectors */ nlw->numeric_list.local_vectors = vlist; /* * Bump up the vector count */ nlw->numeric_list.vector_count++; nlw->numeric_list.vectors = NULL; /* * Regenerate the display */ XClearWindow(XtDisplay(nlw), XtWindow(nlw)); do_layout(nlw); Redisplay(nlw, event); if (do_jump) { jump_to_end(nlw); } return(1); } /********************************************************************* * XmNumericListDeleteVector - Delete the indicated vector * **********************************************************************/ Boolean XmNumericListDeleteVector(XmNumericListWidget nlw, int vector_num) { int i; int j; int k; XEvent *event; VectorList vlist; /* * Check that the vector_num is in range */ if (vector_num > nlw->numeric_list.vector_count - 1) { XtWarning("Illegal position value encountered in " "XmNumericListDeleteVector."); return(0); } /* * Special case where #vectors = 1 */ if (nlw->numeric_list.vector_count == 1) { XtFree((char*)nlw->numeric_list.local_vectors[0]); XtFree((char*)nlw->numeric_list.local_vectors); vlist = NULL; } else { /* * Alloc the new memory and copy the vectors over, delete the vector */ vlist = (VectorList)XtMalloc(sizeof(Vector) * (nlw->numeric_list.vector_count - 1)); k = 0; for (i=0; i < nlw->numeric_list.vector_count; i++) { if (i == vector_num) { continue; } vlist[k] = (Vector)XtMalloc(sizeof(double) * nlw->numeric_list.tuples); for (j=0; j < nlw->numeric_list.tuples; j++) { *(vlist[k] + j) = *(nlw->numeric_list.local_vectors[i] + j); } k++; } /* * Free the old vectors */ if(nlw->numeric_list.local_vectors) { for (i=0; i < nlw->numeric_list.vector_count; i++) { XtFree((char*)nlw->numeric_list.local_vectors[i]); } XtFree((char*)nlw->numeric_list.local_vectors); } } /* * Knock down the vector count */ nlw->numeric_list.vector_count--; nlw->numeric_list.local_vectors = vlist; nlw->numeric_list.vectors = NULL; /* * Regenerate the display (good candidate for optimization) */ if (nlw->numeric_list.selected >= nlw->numeric_list.vector_count) { nlw->numeric_list.selected = nlw->numeric_list.vector_count - 1; } XClearWindow(XtDisplay(nlw), XtWindow(nlw)); do_layout(nlw); Redisplay(nlw, event); return(1); } /********************************************************************* * XmNumericListReplaceSelectedVector - Delete the indicated vector * **********************************************************************/ Boolean XmNumericListReplaceSelectedVector(XmNumericListWidget nlw, Vector newvec) { int j, vecnum; XEvent *event; /* * Check that there is a selected item */ vecnum = nlw->numeric_list.selected; if (vecnum == -1) { XtWarning("No selected item in XmNumericListReplaceSelectedVector."); return(0); } for (j=0; j < nlw->numeric_list.tuples; j++) { nlw->numeric_list.local_vectors[vecnum][j] = newvec[j]; } XClearWindow(XtDisplay(nlw), XtWindow(nlw)); do_layout(nlw); Redisplay(nlw, event); return(1); } #if defined(__cplusplus) || defined(c_plusplus) } #endif