This is MyList.c in view mode; [Download] [Up]
#if ( !defined(lint) && !defined(SABER)) static char PCN_rcsid[] = "$Header: /ufs/comp/mei/PROJ_PCN/onprofile/IFModel/Xsw/RCS/MyList.c,v 1.1 1992/04/17 18:26:10 mei Exp $"; #endif /****************************************************************************** * * * Copyright (C) The Aerospace Corporation 1991 * * * * This software was developed by The Aerospace Corporation as a * * research endeavor for the United States Air Force * * Space Systems Division. The current version of the Gauge * * computer program is available for release to you for * * educational and research purposes only. It is not * * to be used for commercial purposes. * * * * In addition, the following conditions shall apply. * * * * 1) The computer software and documentation were designed to * * satisfy internal Aerospace requirements only. * * The software is provided ``as is,'' and The Aerospace Corporation * * makes no warranty, expressed or implied, as to it accuracy, * * functioning, or fitness for a particular purpose. * * * * 2) The Aerospace Corporation and its personnel are not * * responsible for providing technical support or general assistance * * with respect to the software. * * * * 3) Neither The Aerospace Corporation nor its personnel shall be * * liable for claims, losses, or damages arising out of or connected * * with the use of this software. * * Your sole and exclusive remedy shall be to request a replacement * * copy of the program. * * * ******************************************************************************/ #include <X11/IntrinsicP.h> #include "Xsw.h" #include "MyListP.h" #include "Patterns.h" #define DIMENSION(widget) ( (widget->myList.vertical) ? (widget->core.height) : (widget->core.width) ) #define FONTWIDTH(font) ((font)->max_bounds.rbearing-(font)->max_bounds.lbearing) static XtResource resources[] = { #define offset(field) XtOffset(MyListWidget, myList.field) { XtNcallback, XtCCallback, XtRCallback, sizeof(XPointer), offset(callback), XtRCallback, NULL }, { XtNlongest, XtCLongest, XtRInt, sizeof(int), offset(longest), XtRString, "0" }, { XtNmaxChars, XtCMaxChars, XtRInt, sizeof(int), offset(max_chars), XtRString, "0" }, { XtNnumberStrings, XtCNumberStrings, XtRInt, sizeof(int), offset(nitems), XtRString, "0" }, { XtNfont, XtCFont, XtRFontStruct, sizeof(XtPointer), offset(font), XtRString, XtDefaultFont }, { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), offset(foreground), XtRString, XtDefaultForeground }, { XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel), offset(highlight), XtRString, XtDefaultForeground }, { XtNlist, XtCList, XtRPointer, sizeof(XtPointer), offset(list), XtRString, NULL }, { XtNspacing, XtCSpacing, XtRDimension, sizeof(Dimension), offset(space), XtRString, "1" }, { XtNtopItem, XtCItem, XtRInt, sizeof(int), offset(top_item), XtRString, "0" }, { XtNvertical, XtCVertical, XtRBoolean, sizeof(Boolean), offset(vertical), XtRString, "True" }, { XtNrotate, XtCRotate, XtRBoolean, sizeof(Boolean), offset(rotate), XtRString, "False" }, { XtNrigidZoom, XtCRigidZoom, XtRBoolean, sizeof(Boolean), offset(rigid_zoom), XtRString, "False" }, { XtNzoom, XtCZoom, XtRBoolean, sizeof(Boolean), offset(zoom), XtRString, "True" }, #undef offset }; static void Initialize(); static void Redisplay(); static void Resize(); static void Destroy(); static Boolean SetValues(); static void DrawItem(); static void SelectItem(); static void ManyItems(); void SetItem(); static XtActionsRec actions[] = { {"SelectItem", SelectItem}, {"ManyItems", ManyItems}, }; static char translations[] = "<Btn1Down>: SelectItem() \n\ <Btn1Motion>: ManyItems() \n\ "; /* definition in MyList.h */ static MyListItemInfo info; MyListClassRec myListClassRec = { { /* core fields */ /* superclass */ (WidgetClass) &coreClassRec, /* class_name */ "MyList", /* widget_size */ sizeof(MyListRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ translations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* template fields */ /* empty */ 0 } }; WidgetClass myListWidgetClass = (WidgetClass)&myListClassRec; static void GetAllGC(cw) MyListWidget cw; { XGCValues values; XtGCMask mask = GCForeground | GCBackground | GCFont | GCFillStyle; values.foreground = cw->core.background_pixel; values.background = cw->core.background_pixel; values.font = cw->myList.font->fid; values.fill_style = FillSolid; cw->myList.cleargc = XtGetGC((Widget) cw, mask, &values); if ((cw->myList.highlight == cw->myList.foreground) || (cw->myList.highlight == cw->core.background_pixel)) { values.background = cw->myList.foreground; values.foreground = cw->core.background_pixel; values.fill_style = FillOpaqueStippled; mask = mask | GCStipple; values.stipple = XCreateBitmapFromData(XtDisplay(cw), RootWindow(XtDisplay(cw), DefaultScreen(XtDisplay(cw))), zero, PAT_WIDTH, PAT_HEIGHT); } else { values.foreground = cw->myList.highlight; } cw->myList.revgc = XtGetGC((Widget) cw, mask, &values); values.foreground = cw->myList.foreground; values.background = cw->core.background_pixel; cw->myList.normgc = XtGetGC((Widget) cw, mask, &values); } static void FillSlot(cw, gc, i, pos) MyListWidget cw; GC gc; int i, pos; { int x, y; unsigned int w, h; Boolean text; if (cw->myList.vertical) { if (cw->myList.space >= FONTHEIGHT(cw->myList.font)) { y = pos; x = 0; text = True; } else { y = pos-cw->myList.space; x = 0; h = cw->myList.space-1; w = cw->core.width; text = False; } } else { if (cw->myList.space >= ((cw->myList.rotate) ? FONTWIDTH(cw->myList.font) : cw->myList.longest)) { y = cw->myList.font->max_bounds.ascent; x = pos; text = True; } else { y = 0; x = pos-cw->myList.space; h = cw->core.height; w = cw->myList.space-1; text = False; } } if (!text) XFillRectangle(XtDisplay(cw), XtWindow(cw), gc, x, y, w, h); else if (cw->myList.rotate) { char buff[2]; char *sPtr = cw->myList.list[i].label; char *cPtr = sPtr + strlen(cw->myList.list[i].label); y += (cw->myList.max_chars - 1) * FONTHEIGHT(cw->myList.font); buff[1] = '\0'; while ( --cPtr >= sPtr) { buff[0] = *cPtr; XDrawImageString(XtDisplay(cw), XtWindow(cw), gc, x, y, buff, 1); y -= cw->myList.font->max_bounds.ascent; } } else XDrawImageString(XtDisplay(cw), XtWindow(cw), gc, x, y, cw->myList.list[i].label, strlen(cw->myList.list[i].label)); } static Boolean IsVisible(w, pos) MyListWidget w; int pos; { Boolean result = True; if (!w->myList.zoom) if (w->myList.vertical) { if (pos >= w->core.height/w->myList.space+w->myList.top_item) result = False; } else { if (pos >= w->core.width/w->myList.space+w->myList.top_item) result = False; } if ((pos < w->myList.top_item) || (pos >= w->myList.nitems)) result = False; return result; } static void ShowList(cw) MyListWidget cw; { int i; if ((XtWindow(cw) != (Window) NULL) && (cw->myList.list != (ListElement *)NULL)) { i = cw->myList.top_item; while (IsVisible(cw, i)) { DrawItem(cw, i); i++; } } /* This is the efficient but inelegant method boundary = DIMENSION(cw); if (cw->myList.vertical) { if (cw->myList.space >= FONTHEIGHT(cw->myList.font)) offset = cw->myList.font->max_bounds.descent + ((cw->myList.space - FONTHEIGHT(cw->myList.font))/2); } while ((cw->myList.list[i].label != (String)NULL) && ((int)coord <= boundary)) { if (!(cw->myList.vertical)) { if (cw->myList.space >= cw->myList.longest) { offset = (cw->myList.space + XTextWidth(cw->myList.font, cw->myList.list[i].label, strlen(cw->myList.list[i].label)))/2; if (offset > cw->myList.space) offset = cw->myList.space; } else offset = 0; } if (cw->myList.list[i].state) FillSlot(cw, cw->myList.revgc, i, (int)coord - offset); else FillSlot(cw, cw->myList.normgc, i, (int)coord - offset); i++; coord += space; } } */ } /* ARGSUSED */ static void Initialize(request, new) MyListWidget request, new; { GetAllGC(new); if (new->myList.list[0].label == NULL) new->myList.list[0].label = new->core.name; new->myList.save_space = new->myList.space; if (new->myList.vertical) new->myList.rotate = 0; if ((new->myList.longest == 0) || (new->myList.nitems == 0) || (new->myList.max_chars == 0)) { int longest = 0; int max_chars = 0; int nitems = 0; int length; while (new->myList.list[nitems].label != (String)NULL) { length = XTextWidth(new->myList.font, new->myList.list[nitems].label, strlen(new->myList.list[nitems].label)); if (length > longest) longest = length; length = strlen(new->myList.list[nitems].label); if (length > max_chars) max_chars = length; nitems++; } if (new->myList.longest == 0) new->myList.longest = longest; if (new->myList.max_chars == 0) new->myList.max_chars = max_chars; if (new->myList.nitems == 0) new->myList.nitems = nitems; } if (new->myList.vertical) { new->core.width = new->myList.longest; new->core.height = new->myList.nitems*new->myList.space; } else if (new->myList.rotate) { new->core.width = FONTWIDTH(new->myList.font)*new->myList.nitems; new->core.height = new->myList.max_chars * FONTHEIGHT(new->myList.font); } else { new->core.width = new->myList.longest*new->myList.nitems; new->core.height = FONTHEIGHT(new->myList.font); } if ((new->myList.vertical) && (new->myList.space < FONTHEIGHT(new->myList.font))) { new->core.width = new->myList.space; } if (!(new->myList.vertical) && !(new->myList.rotate) && (new->myList.space < new->myList.longest)) { new->core.height = new->myList.space; } if (!(new->myList.vertical) && new->myList.rotate && (new->myList.space < FONTWIDTH(new->myList.font))) { new->core.height = new->myList.space; } new->myList.tog_state = True; new->myList.save_top = new->myList.top_item; } void XswListRedisplay(w) MyListWidget w; { if (!XtIsRealized((Widget) w)) return; else ShowList(w); } static void Redisplay(cw, event) MyListWidget cw; XExposeEvent *event; { int pos, max; if (!XtIsRealized((Widget) cw)) return; if (event) { /* called from btn-event or expose */ if (cw->myList.zoom && (!cw->myList.rigid_zoom)) { pos = (cw->myList.vertical ? event->y : event->x) / ((double)DIMENSION(cw)/(double)cw->myList.nitems); max = (cw->myList.vertical ? event->y+event->height : event->x+event->width) / ((double)DIMENSION(cw)/(double)cw->myList.nitems); } else { if (cw->myList.vertical) { pos = cw->myList.top_item + event->y / cw->myList.space; max = cw->myList.top_item + (event->height+event->y)/cw->myList.space + 1; } else { pos = cw->myList.top_item + event->x / cw->myList.space; max = cw->myList.top_item + (event->width+event->x)/cw->myList.space + 1; } } if (max > cw->myList.nitems) max = cw->myList.nitems; max = MIN(max, ((double)DIMENSION(cw)/(double)cw->myList.space) + cw->myList.top_item); if (pos < 0) pos = 0; if ((max == cw->myList.nitems) && (pos == 0)) ShowList(cw); else for( ; pos<max; pos++) DrawItem(cw, pos); } else { /* called because complete redraw */ ShowList(cw); } } static void ScrollList(cw, p0, p1) MyListWidget cw; int p0, p1; { int pos; unsigned int size, cover, excess; XExposeEvent fake_event; pos = (p1 - p0) * cw->myList.space; if (cw->myList.zoom && !cw->myList.rigid_zoom) { excess = 0; } else { excess = DIMENSION(cw) % cw->myList.space; } if (pos > 0) { p0 = pos; p1 = 0; size = DIMENSION(cw) - pos - excess; pos = size; cover = p0; fake_event.y = fake_event.x = size; fake_event.height = fake_event.width = p0; } else { p0 = 0; p1 = -pos; size = DIMENSION(cw) + pos - excess; pos = 0; cover = p1; fake_event.y = fake_event.x = 0; fake_event.height = fake_event.width = p1; } if (size > DIMENSION(cw)) { XFillRectangle(XtDisplay(cw), XtWindow(cw), cw->myList.cleargc, 0, 0, cw->core.width, cw->core.height); ShowList(cw); } else { if (cw->myList.vertical) { XCopyArea(XtDisplay(cw), XtWindow(cw), XtWindow(cw), cw->myList.normgc, 0, p0, cw->core.width, size, 0, p1); XFillRectangle(XtDisplay(cw), XtWindow(cw), cw->myList.cleargc, 0, pos, cw->core.width, cover); } else { XCopyArea(XtDisplay(cw), XtWindow(cw), XtWindow(cw), cw->myList.normgc, p0, 0, size, cw->core.height, p1, 0); XFillRectangle(XtDisplay(cw), XtWindow(cw), cw->myList.cleargc, pos, 0, cover, cw->core.height); } Redisplay(cw, &fake_event); } } /* ARGSUSED */ static Boolean SetValues(current, request, new) Widget current, request, new; { MyListWidget curcw = (MyListWidget) current; MyListWidget newcw = (MyListWidget) new; Boolean redisplay = False; Boolean change_stats = False; Arg arg[2]; if ((curcw->myList.foreground != newcw->myList.foreground) || (curcw->myList.highlight != newcw->myList.highlight)) { if (newcw->myList.normgc) XtReleaseGC((Widget) newcw, newcw->myList.normgc); if (newcw->myList.revgc) XtReleaseGC((Widget) newcw, newcw->myList.revgc); if (newcw->myList.cleargc) XtReleaseGC((Widget) newcw, newcw->myList.cleargc); GetAllGC(newcw); redisplay = True; } if (curcw->myList.zoom != newcw->myList.zoom) { if (newcw->myList.zoom) { newcw->myList.save_top = newcw->myList.top_item; newcw->myList.top_item = 0; } else { newcw->myList.top_item = newcw->myList.save_top; } } if ((curcw->myList.space != newcw->myList.space) || (curcw->myList.zoom != newcw->myList.zoom)) { newcw->myList.space = newcw->myList.save_space; Resize(newcw, NULL); redisplay = True; } if ((curcw->myList.list != newcw->myList.list) || (curcw->myList.nitems != newcw->myList.nitems) || (curcw->myList.longest != newcw->myList.longest)) { change_stats = True; redisplay = True; } if ((curcw->myList.rotate != newcw->myList.rotate)) { XtSetArg(arg[0], XtNheight, (Dimension) (newcw->myList.rotate ? newcw->myList.longest : newcw->myList.max_chars * FONTHEIGHT(newcw->myList.font))); XtSetValues((Widget) newcw, arg, 1); } if (curcw->myList.top_item != newcw->myList.top_item) { while ((newcw->myList.top_item > 0) && (newcw->myList.space * (newcw->myList.nitems-newcw->myList.top_item) < DIMENSION(newcw) - (DIMENSION(newcw) % newcw->myList.space))) newcw->myList.top_item--; if (newcw->myList.top_item < 0) newcw->myList.top_item = 0; ScrollList(newcw, curcw->myList.top_item, newcw->myList.top_item); } if (change_stats) { if ((newcw->myList.longest == 0) || (newcw->myList.nitems == 0) || (newcw->myList.max_chars)) { int longest = 0; int max_chars = 0; int nitems = 0; int length; while (newcw->myList.list[nitems].label != (String)NULL) { length = XTextWidth(newcw->myList.font, newcw->myList.list[nitems].label, strlen(newcw->myList.list[nitems].label)); if (length > longest) longest = length; length = strlen(newcw->myList.list[nitems].label); if (length > max_chars) max_chars = length; nitems++; } if (newcw->myList.longest == 0) newcw->myList.longest = longest; if (newcw->myList.max_chars == 0) newcw->myList.max_chars = max_chars; if (newcw->myList.nitems == 0) newcw->myList.nitems = nitems; Resize(newcw, NULL); } if (newcw->myList.vertical) XtVaSetValues((Widget)newcw, XtNwidth, (Dimension)newcw->myList.longest,NULL); } return redisplay; } /* ARGSUSED */ static void Resize(cw, event) MyListWidget cw; XExposeEvent *event; { if (cw->myList.zoom) { /* * Calculate the maximum spacing that will allow the * entire list to be displayed. */ cw->myList.space = DIMENSION(cw) / cw->myList.nitems; } else { while ((cw->myList.top_item > 0) && (cw->myList.space * (cw->myList.nitems-cw->myList.top_item) < cw->core.height - (cw->core.height % cw->myList.space))) cw->myList.top_item--; } } static void Destroy(cw) MyListWidget cw; { if (cw->myList.normgc) XtReleaseGC((Widget) cw, cw->myList.normgc); if (cw->myList.revgc) XtReleaseGC((Widget) cw, cw->myList.revgc); if (cw->myList.cleargc) XtReleaseGC((Widget) cw, cw->myList.cleargc); } void XswListSetItem(w, pos, state) MyListWidget w; int pos; Boolean state; { if (w->myList.list[pos].state != state) { w->myList.list[pos].state = state; if (IsVisible(w, pos)) DrawItem(w, pos); } } static Boolean GetCoord(w, event, nPtr) MyListWidget w; XButtonEvent *event; int * nPtr; { if ((w->myList.zoom) && (!w->myList.rigid_zoom)) { *nPtr = (w->myList.vertical ? event->y : event->x) / ((double)DIMENSION(w)/(double)w->myList.nitems); } else { if (w->myList.vertical) { *nPtr = w->myList.top_item + event->y / w->myList.space; } else { *nPtr = w->myList.top_item + event->x / w->myList.space; } } if (!IsVisible(w, *nPtr)) return False; else return True; } static void SelectItem(w, event) MyListWidget w; XButtonEvent *event; { int new; if (!GetCoord(w, event, &new)) return; w->myList.list[new].state = !w->myList.list[new].state; w->myList.tog_state = w->myList.list[new].state; DrawItem(w, new); info.item = new; info.state = w->myList.tog_state; XtCallCallbacks((Widget) w, XtNcallback, &info); } static void ManyItems(w, event) MyListWidget w; XButtonEvent *event; { int new; if (!GetCoord(w, event, &new)) return; if (w->myList.list[new].state != w->myList.tog_state) { w->myList.list[new].state = w->myList.tog_state; DrawItem(w, new); info.item = new; info.state = w->myList.tog_state; XtCallCallbacks((Widget) w, XtNcallback, &info); } } static void DrawItem(cw, i) MyListWidget cw; int i; { int y; int offset = 0; if (cw->myList.zoom && (!cw->myList.rigid_zoom)) y = (double)(i + 1) * (double)((double)DIMENSION(cw)/(double)cw->myList.nitems); else y = (i - cw->myList.top_item + 1) * cw->myList.space; if (cw->myList.vertical) { if (cw->myList.space >= FONTHEIGHT(cw->myList.font)) offset = cw->myList.font->max_bounds.descent + ((cw->myList.space - FONTHEIGHT(cw->myList.font))/2); } else if (cw->myList.rotate) { if (cw->myList.space >= FONTWIDTH(cw->myList.font)) { /* Fprototyping .. hui 4/15, very odd offset = (cw->myList.space + XTextWidth(cw->myList.font, cw->myList.list[i].label + strlen(cw->myList.list[i]) - 1, 1))/2; maybe like the following */ offset = (cw->myList.space + XTextWidth(cw->myList.font, cw->myList.list[i].label,strlen(cw->myList.list[i].label)) - 1)/2; } } else { if (cw->myList.space >= cw->myList.longest) { offset = (cw->myList.space + XTextWidth(cw->myList.font, cw->myList.list[i].label, strlen(cw->myList.list[i].label)))/2; if (offset > cw->myList.space) offset = cw->myList.space; } } if (cw->myList.list[i].state) FillSlot(cw, cw->myList.revgc, i, y-offset); else FillSlot(cw, cw->myList.normgc, i, y-offset); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.