#ifndef lint static char *rcs="$Header: /mit/hst/src/nl/RCS/NumberLine.c,v 2.4 90/08/28 14:40:11 tldavis Exp $"; #endif /******************************************************* * * Number Line widget for X11R4 Cardiovascular Simulator * Copyright 1989 by Timothy L. Davis * For (probable) X11R3 compatibility, define symbol XAW_BC. * * $Source: /mit/hst/src/nl/RCS/NumberLine.c,v $ * $Log: NumberLine.c,v $ * Revision 2.4 90/08/28 14:40:11 tldavis * Fixed a bug with the text widget, which needs a new string for each change. * * Revision 2.3 90/08/18 18:35:11 tldavis * Removed coloring to do it with a resource file instead. * General cleanup. * * Revision 2.2 90/08/10 16:14:50 tldavis * Fixed asciText text replacement for X11R4. * * Revision 2.1 90/08/10 10:55:49 dot * upgrade to R4; changes to the asciiText widgets * new code ifdef'd under !XAW_BC * * Revision 2.0 90/08/06 17:57:37 tldavis * Final X11R3 version. * * Revision 1.13 90/08/06 17:06:27 tldavis * Fixed problems with color on Suns. * * Revision 1.12 90/05/31 16:57:15 tldavis * Pre-ACIS checkin. * * Revision 1.11 89/10/12 22:15:00 tldavis * Updated fall 1989. * * Revision 1.10 89/09/02 01:03:10 tldavis * Made width dep. on title length work. * * Revision 1.9 89/09/02 00:37:40 tldavis * Made pointer even prettier, made width dep. on label. * * Revision 1.8 89/09/01 23:39:51 tldavis * Made pointer prettier, widget smaller, more compact, added - key activity. * * Revision 1.6 89/06/13 21:24:06 tldavis * R3 fonts fixed. * Revision 1.5 89/02/22 12:26:30 tldavis * X11R3 version. * Revision 1.1 88/10/10 22:30:50 hst * Initial revision -- previous revisions deleted. ********************************************************/ #include #include #include #include #include #include /* necessary for label to redisplay on demand. */ #include #include #ifdef XAW_BC #include /* necessary to get XtTextBlock definition! */ #endif #include #include "NumberLineP.h" #include "InputP.h" #define NL_MAX_TICS 10 #define NL_HDR_HEIGHT 30 extern Display *dpy; extern Window root; extern int screen; /******************************************************** * * Full class record constant * ********************************************************/ /* There is a problem with hc on the RT when compiling the XtOffset macro. * Thought this would work better, but... "illegal initialization" to pcc ... */ #define offset(field) (XtOffset(NumberLineWidget,numberLine.field)) static XtResource resources[] = { {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(foreground), XtRString, "XtDefaultForeground"}, {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), offset(background), XtRString, "XtDefaultBackground"}, {XtNlabel, XtCLabel, XtRString, sizeof(String), offset(title), XtRString, (caddr_t)"Number Line Value Choice"}, {XtNminimum, XtCValue, XtRDouble, sizeof(double), offset(min), XtRString, (caddr_t)"0.0"}, {XtNmaximum, XtCValue, XtRDouble, sizeof(double), offset(max), XtRString, (caddr_t)"100.0"}, {XtNpresent, XtCValue, XtRDouble, sizeof(double), offset(pres), XtRString, (caddr_t)"50.0"}, {XtNdefault, XtCValue, XtRDouble, sizeof(double), offset(def), XtRString, (caddr_t)"30.0"}, {XtNprevious, XtCValue, XtRDouble, sizeof(double), offset(prev), XtRString, (caddr_t)"50.0"}, {XtNdone, XtCValue, XtRInt, sizeof(int), offset(done), XtRString, (String)NULL}, {XtNpercentage, XtCValue, XtRInt, sizeof(int), offset(percentage), XtRString, (caddr_t)"0"}, {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t), offset(callbacks), XtRCallback, (caddr_t)NULL}, }; #undef offset /* * FORWARD defines for the widget activity routines to be put in core struct * These routines follow widget interaction rules. */ static void ClassInitialize(); static void Initialize(); static void Realize(); static void Destroy(); static void Redisplay(); static void GetValuesHook(); static XtGeometryResult GeometryHandler(); NumberLineClassRec numberLineClassRec = { { /* core_class fields */ #define superclass ((WidgetClass) &compositeClassRec) /* superclass */ superclass, /* class_name */ "NumberLine", /* widget_size */ sizeof(NumberLineRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ False, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ True, /* compress_exposure */ True, /* compress_enterleave */ True, /* visible_interest */ False, /* destroy */ Destroy, /* resize */ XtInheritResize, /* expose */ Redisplay, /* set_values */ NULL, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ GetValuesHook, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ XtInheritQueryGeometry, /* NEWR3 */ XtInheritDisplayAccelerator, /* NEWR3 */ NULL, }, { /* composite_class fields */ /* geometry_manager */ GeometryHandler, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* ***NEWR3** extension*/ NULL, }, { /* NumberLine fields */ /* gc */ (GC) NULL, /* big_font */ (XFontStruct *) NULL, /* small_font */ (XFontStruct *) NULL, /* pointer_cursor */ (Cursor) NULL, /* invisible_cursor */ (Cursor) NULL, } }; WidgetClass numberLineWidgetClass = (WidgetClass) &numberLineClassRec; /**************************************************************** * * Private Procedures * ****************************************************************/ /*FORWARD*/static void DefaultCallback(),PreviousCallback(), TargetHandler(), KeyHandler(); /*ARGSUSED*/static void CvtStringToDouble(args, num_args, fromVal, toVal) XrmValue *args; Cardinal *num_args; XrmValue *fromVal, *toVal; { static double i; /* is this dangerous?? can we guarantee that the toolkit will copy * the return value before calling this routine again? (I hope so!) */ if (*num_args != 0) XtWarning("String to Double conversion needs no extra arguments"); if (sscanf ((char *)fromVal->addr,"%lf",&i) == 1) { toVal->size = sizeof(double); toVal->addr = (caddr_t) &i; } } /* * registered private widget initialization and event handling routines: * */ static void ClassInitialize () { XFontStruct *font; static XColor color = { 1, 0, 0, 0, 0, 0}; XGCValues gcv; unsigned long fontmask = 0; if (font = XLoadQueryFont(dpy,"*-new cent*-bold-r-*-*-*-120-*")) numberLineClassRec.numberLine_class.big_font = font; if (numberLineClassRec.numberLine_class.small_font = XLoadQueryFont(dpy,"*-helvetica-medium-r-*-*-*-80-*")) fontmask = GCFont; if (fontmask) gcv.font = numberLineClassRec.numberLine_class.small_font->fid; numberLineClassRec.numberLine_class.gc = XCreateGC(dpy, root, fontmask /*| GCForeground | GCBackground */, &gcv); if (font) numberLineClassRec.numberLine_class.invisible_cursor = XCreateGlyphCursor(dpy, font->fid, font->fid, (unsigned int)' ', (unsigned int)' ', &color, &color); else numberLineClassRec.numberLine_class.invisible_cursor = XCreateFontCursor(dpy, XC_crosshair); numberLineClassRec.numberLine_class.pointer_cursor = XCreateFontCursor(dpy, XC_arrow); XtAddConverter(XtRString, XtRDouble, CvtStringToDouble, (XtConvertArgList)NULL, 0); } /* ClassInitialize() */ /*ARGSUSED*/ static void Initialize(request, new) Widget request, new; { NumberLineWidget nlw = (NumberLineWidget) new; NumberLinePart *nl = & nlw->numberLine; int i; Arg blist[20]; Pixel fore = nl->foreground; Pixel back = nl->background; /* The first 10 elements represent number key presses; the intent of this * translation table is to allow only numeric entry on only 1 line of text. */ static String textEventTable = "0x030: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x031: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x032: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x033: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x034: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x035: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x036: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x037: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x038: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ 0x039: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ .: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ -: kill-to-end-of-line() beginning-of-file() end-of-line() \ insert-char() \n\ CtrlF: forward-character() \n\ 0xff53: forward-character() \n\ CtrlB: backward-character() \n\ 0xff51: backward-character() \n\ CtrlA: beginning-of-line() \n\ CtrlE: end-of-line() \n\ CtrlP: previous-line() \n\ 0xff52: previous-line() \n\ Meta\\<: beginning-of-file() \n\ CtrlZ: scroll-one-line-up() \n\ CtrlD: delete-next-character() \n\ CtrlH: delete-previous-character() \n\ 0xff7f: delete-previous-character() \n\ 0xffff: delete-previous-character() \n\ 0xff08: delete-previous-character() \n\ MetaD: delete-next-word() \n\ MetaH: delete-previous-word() \n\ Shift MetaD: kill-word() \n\ Shift MetaH: backward-kill-word() \n\ CtrlW: kill-selection() \n\ CtrlK: kill-to-end-of-line() \n\ MetaK: kill-to-end-of-paragraph()"; #ifdef DEBUG XSync(dpy, False); fprintf(stderr, "NumberLine.Initialize...\n"); #endif nl->ticsize = 5; if (nl->percentage) { nl->min = 10; nl->max = 200; nl->pres *= 100./nl->def; if (nl->prev) nl->prev *= 100./nl->prev; } XSetState(dpy, numberLineClassRec.numberLine_class.gc, fore, back, GXcopy, AllPlanes); i = 0; XtSetArg(blist[i],XtNborderColor, fore);i++; if (numberLineClassRec.numberLine_class.big_font) XtSetArg(blist[i],XtNfont, numberLineClassRec.numberLine_class.big_font);i++; nl->def_w = XtCreateManagedWidget("Default",commandWidgetClass, (Widget)nlw,blist,i); XtAddCallback(nl->def_w,XtNcallback,DefaultCallback, nlw); i = 0; XtSetArg(blist[i],XtNborderColor, fore);i++; if (numberLineClassRec.numberLine_class.big_font) XtSetArg(blist[i],XtNfont, numberLineClassRec.numberLine_class.big_font);i++; nl->prev_w=XtCreateManagedWidget("Previous",commandWidgetClass, (Widget)nlw,blist, i); XtAddCallback(nl->prev_w,XtNcallback, PreviousCallback, nlw); i = 0; XtSetArg(blist[i], XtNlabel, nl->title);i++; XtSetArg(blist[i],XtNborderWidth, 0);i++; if (numberLineClassRec.numberLine_class.big_font) XtSetArg(blist[i],XtNfont, numberLineClassRec.numberLine_class.big_font);i++; nl->title_w = XtCreateManagedWidget("label",labelWidgetClass, (Widget)nlw, blist, i); i = 0; XtSetArg(blist[i],XtNwidth, 10);i++; XtSetArg(blist[i],XtNheight, 10);i++; nl->target_w = XtCreateManagedWidget("target",inputWidgetClass, (Widget)nlw,blist, i); nl->string = (char *)XtMalloc(32*sizeof(char)); i=0; #ifdef XAW_BC XtSetArg(blist[i],XtNeditType, XttextEdit);i++; #else /* ! XAW_BC */ XtSetArg(blist[i],XtNeditType, XawtextEdit);i++; #endif XtSetArg(blist[i],XtNstring, nl->string);i++; XtSetArg(blist[i],XtNlength, 10);i++; #ifdef XAW_BC XtSetArg(blist[i],XtNtextOptions, editable); i++; #endif XtSetArg(blist[i],XtNwidth, 80);i++; XtSetArg(blist[i],XtNtranslations,XtParseTranslationTable(textEventTable)); i++; if (numberLineClassRec.numberLine_class.big_font) XtSetArg(blist[i],XtNfont, numberLineClassRec.numberLine_class.big_font); i++; #ifdef XAW_BC nl->key_w =XtCreateManagedWidget("text",asciiStringWidgetClass,nlw,blist,i); #else nl->key_w =XtCreateManagedWidget("text",asciiTextWidgetClass, (Widget)nlw,blist,i); #endif XtSetKeyboardFocus((Widget)nlw, nl->key_w); nl->old_hd_x = 0; nl->old_hd_y = 0; nl->head_val = nl->pres; nl->ptr_val = nl->pres; if (numberLineClassRec.numberLine_class.big_font) i = XTextWidth(numberLineClassRec.numberLine_class.big_font, nl->title, strlen(nl->title)) + 50; else i = 10*strlen(nl->title) + 50; if (nlw->core.width == 0) nlw->core.width = (i < 225 ? 225 : i); if (nlw->core.height == 0) nlw->core.height = 110; XtAddEventHandler(nl->target_w, EnterWindowMask | PointerMotionMask | ButtonPressMask | LeaveWindowMask, False, TargetHandler,(caddr_t)nlw); XtAddEventHandler(nl->key_w, KeyPressMask, False, KeyHandler,(caddr_t)nlw); } /* Initialize() */ static void Realize(widget, mask, attributes) Widget widget; Mask *mask; XSetWindowAttributes *attributes; { NumberLinePart *nl = &((NumberLineWidget)widget)->numberLine; int x; (*superclass->core_class.realize)(widget, mask, attributes); x = 5; XtMoveWidget(nl->def_w, x, 5); x += nl->def_w->core.width + 5; XtMoveWidget(nl->prev_w, x, 5); x += nl->prev_w->core.width + 5; XtMoveWidget(nl->key_w, x, 5); XtRealizeWidget(nl->target_w); XDefineCursor(dpy, XtWindow(widget), numberLineClassRec.numberLine_class.pointer_cursor); XDefineCursor(dpy, XtWindow(nl->target_w), numberLineClassRec.numberLine_class.invisible_cursor); } /* Realize() */ static void Destroy(w) Widget w; { NumberLinePart *nl = &((NumberLineWidget)w)->numberLine; NumberLineCancelType(XtParent(w)); XtRemoveEventHandler(nl->key_w,XtAllEvents,True,(XtEventHandler)NULL, (caddr_t)NULL); XtFree((caddr_t) nl->string); } /* Destroy() */ /*FORWARD*/static void set_pointer(), set_pointer_head(), unset_pointer_head(); /*ARGSUSED*/ static void Redisplay(w, event, region) Widget w; XEvent *event; Region region; { Window window = XtWindow(w); NumberLineWidget nlw = (NumberLineWidget) w; NumberLinePart *nl = & nlw->numberLine; CorePart *core = & ((NumberLineRec *) w)->core; XExposeEvent *xev = (XExposeEvent *) event; GC gc = numberLineClassRec.numberLine_class.gc; XFontStruct *smallFont = numberLineClassRec.numberLine_class.small_font; double order, temp; /* used in computing tics */ double next, ticint; int x; int nextnumloc, lastnumloc; char s[20]; if (xev->count) return; /* skip all regions except last (count == 0) */ XClearWindow(dpy, window); /* Compute layout */ nl->minpt = 20; nl->maxpt = nlw->core.width-20; nl->yline = /* (nlw->core.height-NL_HDR_HEIGHT)/2+ */ NL_HDR_HEIGHT + nl->def_w->core.height + 15; nl->ynums = nl->yline+2*nl->ticsize + /*small_font->height ==*/ 10; if (nl->minpt >= nl->maxpt) return; /* give up, window too small (||| should make geometry request) */ /* Configure subwindow target locations */ XtConfigureWidget(nl->target_w, 0, nl->yline-20, core->width, 40, 0); XtConfigureWidget(nl->title_w, 5, nl->ynums+5, core->width-10, nl->title_w->core.height, 0); (labelClassRec.core_class.expose)(nl->title_w, (XEvent *)0, (Region)0); /* Draw the numberLine */ XDrawLine(dpy, window, gc, nl->minpt, nl->yline, nl->maxpt, nl->yline); XDrawLine(dpy, window, gc, nl->minpt, nl->yline-(int)(nl->ticsize*1.5), nl->minpt, nl->yline+(int)(nl->ticsize*1.5)); XDrawLine(dpy, window, gc, nl->maxpt, nl->yline-(int)(nl->ticsize*1.5), nl->maxpt, nl->yline+(int)(nl->ticsize*1.5)); /* print min numbering */ if (nl->min != 0) sprintf(s, "%5f",nl->min); else sprintf(s," %1f ",nl->min); XDrawImageString(dpy,window, gc, nl->minpt - (smallFont ? XTextWidth(smallFont,"000",3) : 18), nl->ynums, s, 5); nextnumloc = nl->minpt + (smallFont ? XTextWidth(smallFont,"00",2) : 9); sprintf(s, "%f ",nl->max); XDrawImageString(dpy,window, gc, nl->maxpt - (smallFont ? XTextWidth(smallFont,"000",3) : 18), nl->ynums, s, 5); lastnumloc = nl->maxpt - 4*(smallFont ? XTextWidth(smallFont,"000",3):18); nl->sf = (nl->maxpt - nl->minpt)/(nl->max - nl->min); ticint = (nl->max - nl->min)/NL_MAX_TICS; /* determine tic interval based on a round number (10, 25, 50...) */ order = pow(10.0, floor(log10(ticint))); temp = ticint/order; if (temp <= 1.0001) temp = 1.; else if (temp <= 2.5001) temp = 2.5; else if (temp <= 5.0001) temp = 5.0; else temp = 10.0; ticint = temp*order; for (next = ticint * ceil(nl->min/ticint); next < nl->max; next += ticint) { x = (next-nl->min)*nl->sf+nl->minpt; XDrawLine(dpy, window, gc, x, nl->yline, x, nl->yline + nl->ticsize); if (smallFont) x -= XTextWidth(smallFont,"00",2); else x -= 9; if (x >= nextnumloc && x <= lastnumloc) { sprintf(s, "%f ", next); XDrawImageString(dpy, window, gc, x, nl->ynums, s, 4); nextnumloc = x + (smallFont ? XTextWidth(smallFont,"00000",5) : 50);; } } ticint *= 0.2; for (next = ticint*ceil(nl->min/ticint); next < nl->max; next += ticint) { x = (next - nl->min)*nl->sf + nl->minpt; XDrawLine(dpy, window, gc, x, nl->yline, x, nl->yline + (int)(nl->ticsize*0.5)); } nl->gran = ticint * 0.125; while (nl->gran * nl->sf < 1.0) nl->gran *= 2.0; nl->old_ptr_x = 0; /* so that old pointer won't be "erased" */ set_pointer(nlw,gc,window,(int)((nl->ptr_val-nl->min) * nl->sf+nl->minpt), nl->yline-1, nl->ptr_val); } /* * a widget get_values_hook procedure to twiddle for retrieval of real * value from a "percent-ized" widget */ static void GetValuesHook (widget, args, argCount) Widget widget; ArgList args; Cardinal *argCount; { NumberLineWidget nlw = (NumberLineWidget)widget; int i = *argCount; double pres = nlw->numberLine.pres; if (nlw->numberLine.percentage) pres = nlw->numberLine.pres*nlw->numberLine.def/100.; while (i > 0) if (args[--i].name == XtNpresent) *((double *)args[i].value) = pres; } /*ARGSUSED*/ static XtGeometryResult GeometryHandler(w, request, geometry_return) Widget w; XtWidgetGeometry *request; XtWidgetGeometry *geometry_return; { return(XtGeometryYes); /* always allow subwidgets to resize themselves */ } static void NewVal(nlw, value) NumberLineWidget nlw; double value; { NumberLinePart *nl = & nlw->numberLine; int pt; nl->ptr_val =(value < nl->min ? nl->min :(value > nl->max ? nl->max :value)); pt = (nl->ptr_val - nl->min)*nl->sf + nl->minpt; unset_pointer_head(nlw); set_pointer(nlw, numberLineClassRec.numberLine_class.gc, XtWindow((Widget)nlw), pt, nl->yline-1, nl->ptr_val); nl->prev = nl->pres; nl->pres = nl->ptr_val; } /*ARGSUSED*/ static void Notify(w, event, params, numParams) Widget w; XEvent *event;/*unused*/ String *params;/*unused*/ Cardinal *numParams;/*unused*/ { XtCallCallbacks(w, XtNcallback, (caddr_t)NULL); } /*ARGSUSED*/ static void KeyHandler(w, client_data, event) Widget w; caddr_t client_data; XKeyEvent *event; { NumberLineWidget nlw = (NumberLineWidget) client_data; char buf[64]; int bytes; double value; bytes = XLookupString(event, buf, 2, (KeySym *)NULL, (XComposeStatus *)NULL); if (bytes >= 1 && (buf[0] == '\n' || buf[0] == '\r')) { #ifdef XAW_BC sscanf(nlw->numberLine.string,"%lf",&value); #else /* !XAW_BC */ { Arg args[5]; int i=0; char *widgetstring; XtSetArg(args[i], XtNstring, &widgetstring); i++; XtGetValues(nlw->numberLine.key_w, args, i); sscanf(widgetstring,"%lf",&value); } #endif NewVal(nlw, value); Notify((Widget) nlw, (XEvent *)event, (String *)NULL, (Cardinal *)NULL); } } /*ARGSUSED*/ static void TargetHandler(w, client_data, event) Widget w; caddr_t client_data; XEvent *event; { NumberLineWidget nlw = (NumberLineWidget) client_data; NumberLinePart *nl = & nlw->numberLine; XPointerMovedEvent *mevent = (XPointerMovedEvent *) event; switch(event->type) { case MotionNotify: { Window root, child; int x, y, win_x, win_y; unsigned int mask; if (XQueryPointer(dpy, mevent->window, &root, &child, &x, &y, &win_x, &win_y, &mask)) { nl->head_val = (win_x - nl->minpt)/nl->sf + nl->min; /*give user-friendly granularity*/ /*want rint() but not on Cray*/ nl->head_val = nl->gran*floor(0.5+nl->head_val/nl->gran); nl->head_val = nl->head_val < nl->min ? nl->min : (nl->head_val > nl->max ? nl->max : nl->head_val); set_pointer_head(nlw,(int)((nl->head_val-nl->min)*nl->sf + nl->minpt), nl->yline-2); return; } break; } case ButtonPress: if (nl->ptr_val != nl->head_val) { NewVal(nlw, nl->head_val); Notify((Widget)nlw, event, (String *)NULL, (Cardinal *)NULL); } break; case LeaveNotify: unset_pointer_head(nlw); return; default: return; } } /*ARGSUSED*/ static void DefaultCallback(widget, client_data, call_data) Widget widget; caddr_t client_data, call_data; { NumberLineWidget nlw = (NumberLineWidget) client_data; if (nlw->numberLine.percentage) NewVal(nlw, (double)100.); else NewVal(nlw, nlw->numberLine.def); Notify((Widget)nlw, (XEvent *)call_data, (String *)NULL, (Cardinal *)NULL); } /*ARGSUSED*/ static void PreviousCallback(widget, client_data, call_data) Widget widget; caddr_t client_data, call_data; { NumberLineWidget nlw = (NumberLineWidget) client_data; NewVal(nlw, nlw->numberLine.prev); Notify((Widget)nlw, (XEvent *)call_data, (String *)NULL, (Cardinal *)NULL); } static void set_pointer(nlw, gc, w, x, y, val) NumberLineWidget nlw; GC gc; Window w; int x, y; double val; { NumberLinePart *nl = & nlw->numberLine; static char s[40]; #ifdef XAW_BC static XtTextBlock textblock = {0, 10, s}; #endif XPoint points[4]; if (nl->old_ptr_x) XClearArea(dpy, w, 0, y-11-10-15, nlw->core.width, 15+10+11+1, False); XSetLineAttributes(dpy, gc, 2, LineSolid, CapButt, JoinMiter); points[0].x = x-5; points[0].y = y-5; points[1].x = x; points[1].y = y; points[2].x = x+5; points[2].y = y-5; points[3].x = x-5; points[3].y = y-5; XFillPolygon(dpy, w, gc, points, 3, Convex, CoordModeOrigin); XDrawLine(dpy, w, gc, x, y-5, x, y-15); XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter); XDrawLine(dpy, w, gc, nl->minpt, (int) (nl->yline-(nl->ticsize*1.5)), nl->minpt, (int) (nl->yline+(nl->ticsize * 1.5))); XDrawLine(dpy, w, gc, nl->maxpt, (int) (nl->yline-(nl->ticsize*1.5)), nl->maxpt, (int) (nl->yline+(nl->ticsize * 1.5))); sprintf(s,"%7.3f",val); XDrawImageString(dpy, w, gc, x-(3*6), y-11-10, s, strlen(s)); #ifdef XAW_BC textblock.length = strlen(s); XtTextSetLastPos(nl->key_w, XtTextTopPosition(nl->key_w)); XtTextSetInsertionPoint(nl->key_w, (XtTextPosition)0); XtTextSetSelection(nl->key_w, (XtTextPosition)0, (XtTextPosition)0); XtTextReplace(nl->key_w, (XtTextPosition)0, (XtTextPosition)0, &textblock); XtTextSetInsertionPoint(nl->key_w, (XtTextPosition)0); #else /* ! XAW_BC */ { Arg args[5]; int i=0; char *news = XtNewString(s); XtSetArg(args[i], XtNstring, news); i++; XtSetValues(nl->key_w, args, i); XtFree(nl->string); nl->string = news; XawTextSetInsertionPoint(nl->key_w, (XawTextPosition)0); } #endif nl->old_ptr_x = x; nl->old_ptr_y = y; } static void set_pointer_head(nlw, x, y) NumberLineWidget nlw; int x, y; { NumberLinePart *nl = &nlw->numberLine; Window w = XtWindow(nlw); GC gc = numberLineClassRec.numberLine_class.gc; XSetFunction(dpy, gc, GXinvert); XSetPlaneMask(dpy, gc, 1); if (nl->old_hd_x) { XDrawLine(dpy, w, gc, nl->old_hd_x, nl->old_hd_y, nl->old_hd_x-5, nl->old_hd_y-5); XDrawLine(dpy, w, gc, nl->old_hd_x, nl->old_hd_y, nl->old_hd_x+5, nl->old_hd_y-5); XDrawPoint(dpy, w, gc, nl->old_hd_x, nl->old_hd_y); } XDrawLine(dpy, w, gc, x, y, x-5, y-5); XDrawLine(dpy, w, gc, x, y, x+5, y-5); XDrawPoint(dpy, w, gc, x, y); nl->old_hd_x = x; nl->old_hd_y = y; XSetFunction(dpy, gc, GXcopy); XSetPlaneMask(dpy, gc, AllPlanes); } static void unset_pointer_head(nlw) NumberLineWidget nlw; { NumberLinePart *nl = &nlw->numberLine; GC gc = numberLineClassRec.numberLine_class.gc; XSetFunction(dpy, gc, GXinvert); XSetPlaneMask(dpy, gc, 1); if (nl->old_hd_x) { XDrawLine(dpy, XtWindow(nlw), gc, nl->old_hd_x, nl->old_hd_y, nl->old_hd_x-5, nl->old_hd_y-5); XDrawLine(dpy, XtWindow(nlw), gc, nl->old_hd_x, nl->old_hd_y, nl->old_hd_x+5, nl->old_hd_y-5); XDrawPoint(dpy, XtWindow(nlw), gc, nl->old_hd_x, nl->old_hd_y); } nl->old_hd_x = 0; nl->old_hd_y = 0; XSetFunction(dpy, gc, GXcopy); XSetPlaneMask(dpy, gc, AllPlanes); } /**************************************************************** * * Public Procedures * ****************************************************************/ /* * * The following keeps track of which number lines are present since * duplicates would have non-intuitive behavior and are hereby disallowed. * */ static Widget nlPresent[10][10] = {(Widget)0, }; static XContext erContext = (XContext)NULL; typedef struct { int place, type; } erRec; /*PUBLIC*/ Boolean NumberLineEnroll(w, place, type) /* returns true if successful */ Widget w; int place, type; { erRec *rec; if (!erContext) erContext = XUniqueContext(); rec = (erRec *) XtMalloc(sizeof(erRec)); rec->place = place; rec->type = type; XSaveContext(dpy, XtWindow(w), erContext, (caddr_t) rec); if (nlPresent[place][type]) return (False); else { nlPresent[place][type] = w; return (True); } } /*PUBLIC*/ void NumberLineCancelType(w) Widget w; { erRec *rec; if (XFindContext(dpy, XtWindow(w), erContext, (caddr_t *)&rec)) return; /* error getting context */ nlPresent[rec->place][rec->type] = (Widget) 0; XDeleteContext(dpy, XtWindow(w), erContext); XtFree((caddr_t) rec); } /*PUBLIC*/ Boolean NumberLineCheckType(place, type) int place, type; { if (nlPresent[place][type]) return(True); else return(False); } /*PUBLIC*/ void NumberLineResetAll() { int i, j; ShellWidget s; for (i = 0; i < 10; i++) for (j = 0; j < 10; j++) if (nlPresent[j][i]) { s = (ShellWidget) nlPresent[j][i]; DefaultCallback(nlPresent[j][i], (caddr_t) *(s->composite.children), (caddr_t)0); } } /*PUBLIC*/ void NumberLineDestroyAll() { int i, j; Widget w; for (i = 0; i < 10; i++) for (j = 0; j < 10; j++) if (w=nlPresent[j][i]) { NumberLineCancelType(w); XtDestroyWidget(w); } } /* * * Get current value * */ /*PUBLIC*/ void NumberLineGetValue (w, value, done) Widget w; double *value; /* RETURN */ int *done; /* RETURN */ { NumberLinePart *nl = &((NumberLineWidget) w)->numberLine; if (nl->percentage) *value = nl->pres*nl->def/100.; else *value = nl->pres; *done = nl->done; }