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.